diff --git a/.gitignore b/.gitignore index e0ee41fdddd04..9153af0c85475 100644 --- a/.gitignore +++ b/.gitignore @@ -7,12 +7,15 @@ /dist /julia +/julia-* /h2j *.exe *.dll *.do *.o +*.dylib +*.dSYM *.out @@ -22,5 +25,7 @@ *.creator *.user *.orig +*.swp +*.kate-swp /usr diff --git a/.gitmodules b/.gitmodules index aa10bcca7173d..69bfeb5dfd124 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "deps/openlibm"] path = deps/openlibm url = git://github.com/JuliaLang/openlibm.git +[submodule "deps/Rmath"] + path = deps/Rmath + url = git://github.com/JuliaLang/Rmath.git diff --git a/.mailmap b/.mailmap index 8cc5f4d9088c0..7700ba1f4aad2 100644 --- a/.mailmap +++ b/.mailmap @@ -59,6 +59,7 @@ Ivan Mantova Keno Fischer Keno Fischer Keno Fischer +Keno Fischer Harlan Harris Harlan Harris @@ -86,3 +87,16 @@ Adam Savitzky David Slate Francois Pepin + +Waldir Pimenta + +Steven G. Johnson + +Isaiah Norton +Isaiah Norton + +Blake Johnson +Blake Johnson + +Marcus Silva +Marcus Silva diff --git a/.travis.yml b/.travis.yml index c8b41709734b6..f72e082f054c6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,14 +5,14 @@ compiler: notifications: email: false before_install: - - BUILDOPTS="LLVM_CONFIG=llvm-config-3.1 USE_QUIET=0"; for lib in LLVM ZLIB SUITESPARSE ARPACK BLAS FFTW LAPACK LIGHTTPD GMP PCRE LIBUNWIND READLINE GLPK; do export BUILDOPTS="$BUILDOPTS USE_SYSTEM_$lib=1"; done + - BUILDOPTS="LLVM_CONFIG=llvm-config-3.2 USE_QUIET=0 USE_LIB64=0"; for lib in LLVM ZLIB SUITESPARSE ARPACK BLAS FFTW LAPACK GMP PCRE LIBUNWIND READLINE GRISU OPENLIBM RMATH; do export BUILDOPTS="$BUILDOPTS USE_SYSTEM_$lib=1"; done - sudo apt-get update -qq -y - sudo apt-get install zlib1g-dev - sudo add-apt-repository ppa:staticfloat/julia-deps -y - sudo apt-get update -qq -y - - sudo apt-get install gfortran llvm-3.1-dev libsuitesparse-dev libncurses5-dev libopenblas-dev libarpack2-dev libfftw3-dev libpcre3-dev libglpk-dev lighttpd libgmp-dev libunwind7-dev libreadline-dev -y -script: make $BUILDOPTS PREFIX=/tmp/julia install -after_script: + - sudo apt-get install patchelf gfortran llvm-3.2-dev libsuitesparse-dev libncurses5-dev libopenblas-dev liblapack-dev libarpack2-dev libfftw3-dev libgmp-dev libpcre3-dev libunwind7-dev libreadline-dev libdouble-conversion-dev libopenlibm-dev librmath-dev -y +script: + - make $BUILDOPTS PREFIX=/tmp/julia install - cd .. && mv julia julia2 - cd /tmp/julia/share/julia/test && /tmp/julia/bin/julia runtests.jl all - cd - && mv julia2 julia diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ab7b30092185c..8fee255a4f634 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,4 @@ -Hi! Thanks for checking out Julia. If you have questions or problems, the [Julia dev list](https://groups.google.com/forum/?fromgroups#!forum/julia-dev) is a good place to post them, but you should check out the [online Julia docs](http://docs.julialang.org/en/latest/) first. If you have changes you'd like to contribute, you'll need a [free GitHub account](https://github.com/signup/free). (If you're reading this on GitHub, you probably already have one.) You'll also want a working copy of Julia, built from source (you can still contribute with a binary install, but it's harder and not really recommended). In list form, here's what to do to become a contributor: +Hi! Thanks for checking out Julia. If you have questions or problems, the [Julia dev list](https://groups.google.com/forum/?fromgroups#!forum/julia-dev) is a good place to post them, but you should check out the [online Julia docs](http://docs.Julialang.org/en/latest/) first. If you have changes you'd like to contribute, you'll need a [free GitHub account](https://github.com/signup/free). (If you're reading this on GitHub, you probably already have one.) You'll also want a working copy of Julia, built from source (you can still contribute with a binary install, but it's harder and not really recommended). In list form, here's what to do to become a contributor: * Join the [dev list](https://groups.google.com/forum/?fromgroups#!forum/julia-dev). @@ -14,36 +14,41 @@ Hi! Thanks for checking out Julia. If you have questions or problems, the [Julia ## Submitting your contributions -Julia now has a [package manager](https://github.com/JuliaLang/METADATA.jl). Most developers writing julia libraries are encouraged to provide them as a julia package. In case you are contributing to the core functionality or the base libraries, the process is as follows. +### Contributing to core functionality or base libraries The Julia team uses [GitHub issues](https://github.com/JuliaLang/julia/issues) to track and discuss problems, feature requests, and pull requests. -You can make pull requests for incomplete features to get code review. The convention is to prefix the pull request title with "WIP:" or "RFC:" as appropriate to indicate that the work is incomplete, so that it is not accidentally merged. +You can make pull requests for incomplete features to get code review. The convention is to prefix the pull request title with "WIP:" for Work In Progress, or "RFC:" for Request for Comments when work is completed and ready for merging. This will prevent accidental merging of work that is in progress. Before submitting, make sure that all tests pass by running `make testall`. Add your own tests for the new functionality in `test/`. If your contribution includes changes to Makefiles or external dependencies, make sure you can build Julia from a clean tree using `git clean -fdx` or equivalent (be careful – this command will delete any files lying around that aren't checked into git). Make sure that [Travis](http://www.travis-ci.org) greenlights the pull request with a `Good to merge` message. *By contributing code to Julia, you are agreeing to release it under the [MIT License](https://github.com/JuliaLang/julia/tree/master/LICENSE.md).* +### Contributing a Julia package + +Julia has a built-in [package manager](https://github.com/JuliaLang/METADATA.jl) based on git. A number of [packages](http://docs.julialang.org/en/latest/packages/packagelist/) across many domains are already available for julia. Developers are encouraged to provide their libraries as a Julia package. The Julia manual provides instructions on [creating julia packages](http://docs.julialang.org/en/latest/manual/packages/). + +For developers who need to wrap C libraries so that they can be called from Julia, the [Clang.jl](https://github.com/ihnorton/Clang.jl) package can help generate the wrappers automatically from the C header files. + ## Getting help -While getting familiar with Julia, remember to check out [the docs](http://docs.julialang.org/en/latest/), keeping in mind that they are [searchable](http://docs.julialang.org/en/latest/search/). (If you use a script blocker then you'll have to unblock that page.) The [source code](https://github.com/JuliaLang/julia) is an excellent source of examples (and it's mostly pretty approachable). If you're still stumped, post something on [the dev list](https://groups.google.com/forum/?fromgroups#!forum/julia-dev), but you may want to search the archives first to see if there's already been a discussion about what you're stuck on. +While getting familiar with Julia, remember to check out [the docs](http://docs.Julialang.org/en/latest/), keeping in mind that they are [searchable](http://docs.Julialang.org/en/latest/search/). (If you use a script blocker then you'll have to unblock that page.) The [source code](https://github.com/JuliaLang/julia) is an excellent source of examples (and it's mostly pretty approachable). If you're still stumped, post something on [the dev list](https://groups.google.com/forum/?fromgroups#!forum/julia-dev), but you may want to search the archives first to see if there's already been a discussion about what you're stuck on. ## Resources * Julia - **Homepage:** - **Mailing lists:** - - **IRC:** + - **IRC:** - **Source code:** - **Git clone URL:** - **Documentation:** + * Design of Julia - [Julia: A Fast Dynamic Language for Technical Computing](http://julialang.org/images/julia-dynamic-2012-tr.pdf) -* Working with Types - - [Some Type Patterns](https://github.com/JuliaLang/julia/wiki/Code-Patterns) - - [The Type Hierarchy](https://github.com/JuliaLang/julia/wiki/Types-Hierarchy) + * Using GitHub - [Using Julia with GitHub (video)](http://www.youtube.com/watch?v=wnFYV3ZKtOg&feature=youtu.be) - - [Using Julia on GitHub (notes for video)](https://gist.github.com/2712118#file_julia_git_pull_request.md) + - [Using Julia on GitHub (notes for video)](https://gist.github.com/2712118#file_Julia_git_pull_request.md) - [General GitHub documentation](http://help.github.com/) - [GitHub pull request documentation](http://help.github.com/send-pull-requests/) diff --git a/LICENSE.md b/LICENSE.md index ce6e540a514d3..7f58931c0a54b 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -51,9 +51,9 @@ External libraries, if used, include their own licenses: - [DOUBLE-CONVERSION](https://code.google.com/p/double-conversion/) - [DSFMT](http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/LICENSE.txt) - [OPENLIBM](https://github.com/JuliaLang/openlibm/blob/master/LICENSE.md) +- [FADDEEVA](http://ab-initio.mit.edu/Faddeeva) - [FEMTOLISP](https://github.com/JeffBezanson/femtolisp) - [FFTW](http://fftw.org/doc/License-and-Copyright.html) -- [GLPK](http://www.gnu.org/software/glpk) - [GMP](http://gmplib.org/manual/Copying.html#Copying) - [LAPACK](http://netlib.org/lapack/LICENSE.txt) - [LIBUNWIND](http://git.savannah.gnu.org/gitweb/?p=libunwind.git;a=blob_plain;f=LICENSE;hb=master) diff --git a/Make.inc b/Make.inc index 57276d5651423..7035176e3aeb6 100644 --- a/Make.inc +++ b/Make.inc @@ -1,33 +1,71 @@ # -*- mode: makefile-gmake -*- +# include twice to pickup user definitions +ifeq (exists, $(shell [ -e $(JULIAHOME)/Make.user ] && echo exists )) +include $(JULIAHOME)/Make.user +endif + +.SUFFIXES: + JULIA_VERSION = $(shell cat $(JULIAHOME)/VERSION) JULIA_COMMIT = $(shell git rev-parse --short=10 HEAD) -USR = $(JULIAHOME)/usr -USRBIN = $(USR)/bin -USRINC = $(USR)/include -LLVMROOT = $(USR) -BUILD = $(USR) - +LLVMROOT = $(BUILD) +BUILD = $(JULIAHOME)/usr # Directories where said libraries get installed to JL_PRIVATE_LIBDIR = lib/julia JL_LIBDIR = lib -# If we're on debian, default to arch-dependent library dirs -ifeq ($(USE_DEBIAN), 1) +# This used for debian packaging, to conform to library layout guidelines +ifeq ($(MULTIARCH_INSTALL), 1) MULTIARCH = $(shell gcc -print-multiarch) JL_PRIVATE_LIBDIR = lib/$(MULTIARCH)/julia JL_LIBDIR = lib/$(MULTIARCH)/ endif -OS = $(shell uname) +# Cross-compile +#XC_HOST = i686-w64-mingw32 +#XC_HOST = x86_64-w64-mingw32 + +ifeq ($(XC_HOST),) +CROSS_COMPILE= +else +ifeq ($(XC_HOST),i686-w64-mingw32) +override OS = WINNT +override ARCH = i686 +override OPENBLAS_DYNAMIC_ARCH = 1 +override CROSS_COMPILE=$(XC_HOST)- +export WINEPATH := '$(BUILD)/lib/julia;$(BUILD)/lib;$(shell $(CROSS_COMPILE)gcc -print-search-dirs | grep programs | sed "s/^programs: =//" | sed "s/:/;/g");C:\\MinGW\\bin;C:\\MinGW\\msys\\1.0\\bin;$(BUILD)/Git/bin' +else ifeq ($(XC_HOST),x86_64-w64-mingw32) +override OS = WINNT +override ARCH = x86_64 +override OPENBLAS_DYNAMIC_ARCH = 1 +override CROSS_COMPILE=$(XC_HOST)- +export WINEPATH := '$(BUILD)/lib/julia;$(BUILD)/lib;$(shell $(CROSS_COMPILE)gcc -print-search-dirs | grep programs | sed "s/^programs: =//" | sed "s/:/;/g");C:\\MinGW\\bin;C:\\MinGW\\msys\\1.0\\bin;$(BUILD)/Git/bin' +else +$(error "unknown XC_HOST variable set") +endif +endif + +# Figure out OS and architecture +BUILD_OS = $(shell uname) +OS = $(BUILD_OS) ARCH = $(shell uname -m) +# Use 64-bit libraries by default on 64-bit architectures +ifeq ($(ARCH), x86_64) +USE_LIB64 = 1 +endif + USE_MKL = 0 MKLLIB = /path/to/mkl/lib/intel64 +# ATLAS must have been previously built with "make -C deps compile-atlas" (without -jN), +# or installed to usr/lib/libatlas from some another source (built as +# a shared library, for your platform, single threaded) USE_ATLAS = 0 -ATLAS_LIBDIR = /path/to/atlas/build/lib +ATLAS_LIBDIR = $(BUILD)/lib +#or ATLAS_LIBDIR = /path/to/system/atlas/lib ifeq ($(OS), MINGW32_NT-6.1) OS=WINNT @@ -35,8 +73,11 @@ endif ifeq ($(OS), WINNT) fPIC = +PATH := ${PATH}:${BUILD}/lib:${BUILD}/lib/julia +EXE = .exe else fPIC = -fPIC +EXE = endif DEFAULT_REPL = readline @@ -45,9 +86,6 @@ USE_COPY_STACKS = 1 # Compiler specific stuff -FC = gfortran -JFFLAGS = -O2 $(fPIC) - ifeq ($(CC), clang) USEGCC = 0 USECLANG = 1 @@ -57,8 +95,9 @@ USECLANG = 0 endif ifeq ($(OS), Darwin) -OSVER = $(shell uname -r | cut -b 1-2) -ifeq ($(OSVER), 10) +DARWINVER = $(shell uname -r | cut -b 1-2) +OSXVER = $(shell sw_vers -productVersion | cut -b 1-4) +ifeq ($(DARWINVER), 10) USEGCC = 1 USECLANG = 0 else @@ -68,11 +107,11 @@ endif endif ifeq ($(USEGCC),1) -CC = gcc -CXX = g++ +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ JCFLAGS = -std=gnu99 -pipe $(fPIC) -fno-strict-aliasing -D_FILE_OFFSET_BITS=64 JCXXFLAGS = -pipe $(fPIC) -fno-rtti -DEBUGFLAGS = -ggdb3 -DDEBUG +DEBUGFLAGS = -ggdb3 -DDEBUG -fstack-protector-all SHIPFLAGS = -O3 -DNDEBUG -falign-functions ifneq ($(ARCH), ppc64) SHIPFLAGS += -momit-leaf-frame-pointer @@ -80,11 +119,11 @@ endif endif ifeq ($(USECLANG),1) -CC = clang -CXX = clang++ +CC = $(CROSS_COMPILE)clang +CXX = $(CROSS_COMPILE)clang++ JCFLAGS = -pipe $(fPIC) -fno-strict-aliasing -D_FILE_OFFSET_BITS=64 JCXXFLAGS = -pipe $(fPIC) -fno-rtti -DEBUGFLAGS = -g -DDEBUG +DEBUGFLAGS = -g -DDEBUG -fstack-protector-all SHIPFLAGS = -O3 -DNDEBUG ifeq ($(OS), Darwin) CC += -mmacosx-version-min=10.6 @@ -93,6 +132,14 @@ JCFLAGS += -D_LARGEFILE_SOURCE -D_DARWIN_USE_64_BIT_INODE=1 endif endif +FC = $(CROSS_COMPILE)gfortran +JFFLAGS = -O2 $(fPIC) +CPP = $(CC) -E +AR := $(CROSS_COMPILE)ar +AS := $(CROSS_COMPILE)as +LD := $(CROSS_COMPILE)ld +RANLIB := $(CROSS_COMPILE)ranlib + # if not absolute, then relative to JULIA_HOME JCFLAGS += '-DJL_SYSTEM_IMAGE_PATH="../$(JL_PRIVATE_LIBDIR)/sys.ji"' @@ -104,48 +151,44 @@ OPENBLAS_TARGET_ARCH= # Use libraries available on the system instead of building them USE_SYSTEM_LLVM=0 -USE_SYSTEM_LIGHTTPD=0 USE_SYSTEM_LIBUNWIND=0 USE_SYSTEM_READLINE=0 USE_SYSTEM_PCRE=0 +USE_SYSTEM_LIBM=0 +USE_SYSTEM_OPENLIBM=0 USE_SYSTEM_BLAS=0 USE_SYSTEM_LAPACK=0 USE_SYSTEM_FFTW=0 USE_SYSTEM_GMP=0 USE_SYSTEM_ARPACK=0 USE_SYSTEM_SUITESPARSE=0 -USE_SYSTEM_GLPK=0 -USE_SYSTEM_NGINX=0 USE_SYSTEM_ZLIB=0 +USE_SYSTEM_GRISU=0 +USE_SYSTEM_RMATH=0 -ifeq ($(USE_DEBIAN), 1) -USE_SYSTEM_LLVM=1 -USE_SYSTEM_LIGHTTPD=1 -USE_SYSTEM_LIBUNWIND=1 -USE_SYSTEM_READLINE=1 -USE_SYSTEM_PCRE=1 -USE_SYSTEM_BLAS=1 -USE_SYSTEM_LAPACK=1 -USE_SYSTEM_FFTW=1 -USE_SYSTEM_GMP=1 -USE_SYSTEM_ARPACK=1 -USE_SYSTEM_SUITESPARSE=1 -USE_SYSTEM_GLPK=1 -USE_SYSTEM_ZLIB=1 +ifeq (exists, $(shell [ -e $(JULIAHOME)/Make.user ] && echo exists )) +include $(JULIAHOME)/Make.user endif --include $(JULIAHOME)/Make.user +# Snow Leopard specific configuration +ifeq ($(OS), Darwin) +ifeq ($(OSXVER), 10.6) +USE_SYSTEM_LIBM = 1 +USE_SYSTEM_BLAS = 1 +USE_SYSTEM_LAPACK = 1 +endif +endif # =========================================================================== ifeq ($(USE_SYSTEM_LIBUNWIND), 1) LIBUNWIND=-lunwind-generic -lunwind else -LIBUNWIND=$(USR)/lib/libunwind-generic.a $(USR)/lib/libunwind.a +LIBUNWIND=$(BUILD)/lib/libunwind-generic.a $(BUILD)/lib/libunwind.a endif ifeq ($(USE_SYSTEM_LLVM), 1) -LLVM_CONFIG=llvm-config +LLVM_CONFIG ?= llvm-config else LLVM_CONFIG=$(LLVMROOT)/bin/llvm-config endif @@ -153,19 +196,19 @@ endif ifeq ($(USE_SYSTEM_READLINE), 1) READLINE = -lreadline else -READLINE = $(USR)/lib/libreadline.a +READLINE = $(BUILD)/lib/libreadline.a endif ifneq ($(OS),WINNT) READLINE += -lncurses else -READLINE += $(USR)/lib/libhistory.a +READLINE += $(BUILD)/lib/libhistory.a endif ifeq ($(USE_SYSTEM_PCRE), 1) PCRE_CONFIG = pcre-config else -PCRE_CONFIG = $(USRBIN)/pcre-config +PCRE_CONFIG = $(BUILD)/bin/pcre-config endif ifeq ($(USE_SYSTEM_BLAS), 1) @@ -177,7 +220,7 @@ LIBBLAS = -lblas LIBBLASNAME = libblas endif else -LIBBLAS = -L$(USR)/lib -lopenblas +LIBBLAS = -L$(BUILD)/lib -lopenblas LIBBLASNAME = libopenblas endif @@ -194,6 +237,18 @@ LIBLAPACK = $(LIBBLAS) LIBLAPACKNAME = $(LIBBLASNAME) endif +ifeq ($(USE_SYSTEM_LIBM), 1) +LIBM = -lm +LIBMNAME = libm +else +LIBM = -lopenlibm +LIBMNAME = libopenlibm +endif + +ifeq ($(USE_MKL), 1) + USE_LIB64 = 0 +endif + # OS specific stuff # install_name_tool @@ -242,7 +297,7 @@ else endif ifeq ($(OS), Linux) -OSLIBS += -ldl -lrt -Wl,--export-dynamic -Wl,--version-script=$(JULIAHOME)/src/julia.expmap -Wl,--no-whole-archive $(LIBUNWIND) +OSLIBS += -ldl -lrt -lpthread -Wl,--export-dynamic -Wl,--version-script=$(JULIAHOME)/src/julia.expmap -Wl,--no-whole-archive $(LIBUNWIND) JLDFLAGS = -Wl,-Bdynamic endif @@ -252,12 +307,25 @@ OSLIBS += -lkvm -lrt -Wl,--export-dynamic -Wl,--version-script=$(JULIAHOME)/src/ endif ifeq ($(OS), Darwin) +INSTALL_NAME_CMD = install_name_tool -id $(INSTALL_NAME_ID_DIR) +INSTALL_NAME_CHANGE_CMD = install_name_tool -change +RPATH = -Wl,-rpath,'@executable_path/../$(JL_LIBDIR)' -Wl,-rpath,'@executable_path/../$(JL_PRIVATE_LIBDIR)' +SHLIB_EXT = dylib OSLIBS += -ldl -Wl,-w -framework CoreFoundation -framework CoreServices +WHOLE_ARCHIVE = -Xlinker -all_load +NO_WHOLE_ARCHIVE = JLDFLAGS = endif ifeq ($(OS), WINNT) -OSLIBS += -Wl,--export-all-symbols -Wl,--version-script=$(JULIAHOME)/src/julia.expmap -lpthread $(NO_WHOLE_ARCHIVE) -lPsapi -lkernel32 -lWs2_32 -lIphlpapi +OSLIBS += -Wl,--export-all-symbols -Wl,--version-script=$(JULIAHOME)/src/julia.expmap $(NO_WHOLE_ARCHIVE) -lpsapi -lkernel32 -lws2_32 -liphlpapi +JCFLAGS += -D_WIN32_WINNT=0x0600 +JCXXFLAGS += -D_WIN32_WINNT=0x0600 +LLVM_CONFIG := WINEPATH="$(WINEPATH)" $(LLVM_CONFIG).exe +JLDFLAGS = -Wl,--stack,8388608 +ifeq ($(ARCH),i686) +JLDFLAGS += -Wl,--large-address-aware +endif endif # MKL @@ -293,7 +361,7 @@ $$(abspath $(1)): @mkdir -p $$@ endef -ifeq ($(OS), WINNT) +ifeq ($(BUILD_OS), WINNT) define mingw_to_dos $(subst /,\\,$(subst $(shell $(2) pwd),$(shell $(2) cmd //C cd),$(abspath $(1)))) endef @@ -316,8 +384,8 @@ $$(abspath $(2)/$(1)): | $$(abspath $(2)) endef endif -JULIA_EXECUTABLE_debug = $(BUILD)/bin/julia-debug-$(DEFAULT_REPL) -JULIA_EXECUTABLE_release = $(BUILD)/bin/julia-release-$(DEFAULT_REPL) +JULIA_EXECUTABLE_debug = $(BUILD)/bin/julia-debug-$(DEFAULT_REPL)$(EXE) +JULIA_EXECUTABLE_release = $(BUILD)/bin/julia-release-$(DEFAULT_REPL)$(EXE) ifeq ($(OS), WINNT) JULIA_EXECUTABLE = $(JULIA_EXECUTABLE_release) @@ -325,7 +393,6 @@ else JULIA_EXECUTABLE = $(JULIAHOME)/julia endif - # Colors for make ifndef USE_QUIET USE_QUIET = 1 diff --git a/Makefile b/Makefile index be10dd385eebe..bbc3b1b63ba1f 100644 --- a/Makefile +++ b/Makefile @@ -1,117 +1,164 @@ JULIAHOME = $(abspath .) include $(JULIAHOME)/Make.inc +# TODO: Code bundled with Julia should be installed into a versioned directory, +# PREFIX/share/julia/VERSDIR, so that in the future one can have multiple +# major versions of Julia installed concurrently. Third-party code that +# is not controlled by Pkg should be installed into +# PREFIX/share/julia/site/VERSDIR (not PREFIX/share/julia/VERSDIR/site ... +# so that PREFIX/share/julia/VERSDIR can be overwritten without touching +# third-party code). +VERSDIR = v`cut -d. -f1-2 < VERSION` + all: default default: release -DIRS = $(BUILD)/bin $(BUILD)/$(JL_LIBDIR) $(BUILD)/$(JL_PRIVATE_LIBDIR) $(BUILD)/share/julia +DIRS = $(BUILD)/bin $(BUILD)/lib $(BUILD)/$(JL_PRIVATE_LIBDIR) $(BUILD)/share/julia $(foreach dir,$(DIRS),$(eval $(call dir_target,$(dir)))) -$(foreach link,extras base test doc examples,$(eval $(call symlink_target,$(link),$(BUILD)/share/julia))) +$(foreach link,extras base test doc examples ui,$(eval $(call symlink_target,$(link),$(BUILD)/share/julia))) -MAKEs = $(MAKE) +QUIET_MAKE = ifeq ($(USE_QUIET), 1) -MAKEs += -s +QUIET_MAKE = -s endif -debug release: | $(DIRS) $(BUILD)/share/julia/extras $(BUILD)/share/julia/base $(BUILD)/share/julia/test $(BUILD)/share/julia/doc $(BUILD)/share/julia/examples - @$(MAKEs) julia-$@ +debug release: | $(DIRS) $(BUILD)/share/julia/extras $(BUILD)/share/julia/base $(BUILD)/share/julia/test $(BUILD)/share/julia/doc $(BUILD)/share/julia/examples $(BUILD)/share/julia/ui + @$(MAKE) $(QUIET_MAKE) julia-$@ @export JL_PRIVATE_LIBDIR=$(JL_PRIVATE_LIBDIR) && \ - $(MAKEs) JULIA_EXECUTABLE=$(JULIA_EXECUTABLE_$@) $(BUILD)/$(JL_PRIVATE_LIBDIR)/sys.ji + $(MAKE) $(QUIET_MAKE) LD_LIBRARY_PATH=$(BUILD)/lib:$(LD_LIBRARY_PATH) JULIA_EXECUTABLE="$(JULIA_EXECUTABLE_$@)" $(BUILD)/$(JL_PRIVATE_LIBDIR)/sys.ji julia-debug julia-release: + @-git submodule init --quiet @-git submodule update - @$(MAKEs) -C deps - @$(MAKEs) -C src lib$@ - @$(MAKEs) -C base - @$(MAKEs) -C extras - @$(MAKEs) -C ui $@ + @$(MAKE) $(QUIET_MAKE) -C deps + @$(MAKE) $(QUIET_MAKE) -C src lib$@ + @$(MAKE) $(QUIET_MAKE) -C base + @$(MAKE) $(QUIET_MAKE) -C ui $@ @ln -sf $(BUILD)/bin/$@-$(DEFAULT_REPL) julia $(BUILD)/share/julia/helpdb.jl: doc/helpdb.jl | $(BUILD)/share/julia @cp $< $@ # use sys.ji if it exists, otherwise run two stages -$(BUILD)/$(JL_PRIVATE_LIBDIR)/sys.ji: VERSION base/*.jl $(BUILD)/share/julia/helpdb.jl +$(BUILD)/$(JL_PRIVATE_LIBDIR)/sys.ji: VERSION base/*.jl base/pkg/*.jl base/linalg/*.jl $(BUILD)/share/julia/helpdb.jl + @#echo `git rev-parse --short HEAD`-$(OS)-$(ARCH) \(`date +"%Y-%m-%d %H:%M:%S"`\) > COMMIT $(QUIET_JULIA) cd base && \ - (test -f $(BUILD)/$(JL_PRIVATE_LIBDIR)/sys.ji || $(JULIA_EXECUTABLE) -bf sysimg.jl) && $(JULIA_EXECUTABLE) -f sysimg.jl || echo "Note: this error is usually fixed by running 'make cleanall'." + (test -f $(BUILD)/$(JL_PRIVATE_LIBDIR)/sys.ji || $(JULIA_EXECUTABLE) -bf sysimg.jl) && $(JULIA_EXECUTABLE) -f sysimg.jl || echo "This error is usually fixed by running 'make clean'. If the error persists, try 'make cleanall'." + +run-julia-debug run-julia-release: run-julia-%: + $(MAKE) $(QUIET_MAKE) run-julia JULIA_EXECUTABLE="$(JULIA_EXECUTABLE_$*)" +run-julia: + #winedbg --gdb + $(JULIA_EXECUTABLE) # public libraries, that are installed in $(PREFIX)/lib JL_LIBS = julia-release julia-debug # private libraries, that are installed in $(PREFIX)/lib/julia JL_PRIVATE_LIBS = amd arpack cholmod colamd fftw3 fftw3f fftw3_threads \ - fftw3f_threads glpk glpk_wrapper gmp gmp_wrapper grisu \ - history openlibm pcre random readline Rmath spqr \ - suitesparse_wrapper tk_wrapper umfpack z openblas + fftw3f_threads gmp grisu \ + openlibm openlibm-extras pcre \ + random Rmath spqr suitesparse_wrapper \ + umfpack z openblas PREFIX ?= julia-$(JULIA_COMMIT) install: release - @$(MAKEs) -C test/unicode - @for subdir in "sbin" "bin" "etc" $(JL_LIBDIR) $(JL_PRIVATE_LIBDIR) "share/julia" ; do \ + @for subdir in "bin" "libexec" $(JL_LIBDIR) $(JL_PRIVATE_LIBDIR) "share/julia" "include/julia" "share/julia/site/"$(VERSDIR) ; do \ mkdir -p $(PREFIX)/$$subdir ; \ done - cp $(BUILD)/bin/*julia* $(PREFIX)/bin - cd $(PREFIX)/bin && ln -s julia-release-$(DEFAULT_REPL) julia +#ifeq ($(OS), Darwin) +# $(MAKE) -C deps install-git +# -cp -a $(BUILD)/libexec $(PREFIX) +# -cp -a $(BUILD)/share $(PREFIX) +#endif + cp -a $(BUILD)/bin $(PREFIX) + cd $(PREFIX)/bin && ln -sf julia-release-$(DEFAULT_REPL) julia -for suffix in $(JL_LIBS) ; do \ - cp -a $(BUILD)/lib/lib$${suffix}.* $(PREFIX)/$(JL_PRIVATE_LIBDIR) ; \ + cp -a $(BUILD)/$(JL_LIBDIR)/lib$${suffix}*.$(SHLIB_EXT)* $(PREFIX)/$(JL_PRIVATE_LIBDIR) ; \ done -for suffix in $(JL_PRIVATE_LIBS) ; do \ - cp -a $(BUILD)/lib/lib$${suffix}.* $(PREFIX)/$(JL_PRIVATE_LIBDIR) ; \ + cp -a $(BUILD)/lib/lib$${suffix}*.$(SHLIB_EXT)* $(PREFIX)/$(JL_PRIVATE_LIBDIR) ; \ done + cp -a $(BUILD)/lib/libuv.a $(PREFIX)/$(JL_PRIVATE_LIBDIR) + cp -a src/julia.h $(BUILD)/include/uv* $(PREFIX)/include/julia # Copy system image cp $(BUILD)/$(JL_PRIVATE_LIBDIR)/sys.ji $(PREFIX)/$(JL_PRIVATE_LIBDIR) # Copy in all .jl sources as well - -cp -R -L $(BUILD)/share/julia $(PREFIX)/share/ + cp -R -L $(BUILD)/share/julia $(PREFIX)/share/ ifeq ($(OS), WINNT) - -cp dist/windows/* $(PREFIX) -ifeq ($(shell uname),MINGW32_NT-6.1) - -for dllname in "libgfortran-3" "libquadmath-0" "libgcc_s_dw2-1" "libstdc++-6,pthreadgc2" ; do \ - cp /mingw/bin/$${dllname}.dll $(PREFIX)/$(JL_LIBDIR) ; \ - done -endif + -cp $(JULIAHOME)/contrib/windows/* $(PREFIX) endif + cp $(JULIAHOME)/VERSION $(PREFIX)/share/julia/VERSION + echo `git rev-parse --short HEAD`-$(OS)-$(ARCH) \(`date +"%Y-%m-%d %H:%M:%S"`\) > $(PREFIX)/share/julia/COMMIT -dist: cleanall +dist: rm -fr julia-*.tar.gz julia-$(JULIA_COMMIT) - -$(MAKE) -C deps clean-openblas +# -$(MAKE) -C deps clean-openblas $(MAKE) install OPENBLAS_DYNAMIC_ARCH=1 ifeq ($(OS), Darwin) - -./contrib/fixup-libgfortran.sh $(PREFIX)/$(JL_PRIVATE_LIBDIR) + -./contrib/mac/fixup-libgfortran.sh $(PREFIX)/$(JL_PRIVATE_LIBDIR) endif +ifeq ($(OS), WINNT) + -[ -e dist-extras/7za.exe ] && cp dist-extras/7za.exe $(PREFIX)/bin/7z.exe + -[ -e dist-extras/PortableGit-1.8.1.2-preview20130201.7z ] && \ + mkdir $(PREFIX)/Git && \ + 7z x dist-extras/PortableGit-1.8.1.2-preview20130201.7z -o"$(PREFIX)/Git" +ifeq ($(shell uname),MINGW32_NT-6.1) + for dllname in "libgfortran-3" "libquadmath-0" "libgcc_s_dw2-1" "libstdc++-6,pthreadgc2" ; do \ + cp /mingw/bin/$${dllname}.dll $(PREFIX)/$(JL_LIBDIR) ; \ + done +else + for dllname in "libgfortran-3" "libquadmath-0" "libgcc_s_sjlj-1" "libstdc++-6" "libssp-0" ; do \ + cp /usr/lib/gcc/i686-w64-mingw32/4.6/$${dllname}.dll $(PREFIX)/$(JL_LIBDIR) ; \ + done +endif + zip -r -9 julia-$(JULIA_COMMIT)-$(OS)-$(ARCH).zip julia-$(JULIA_COMMIT) +else tar zcvf julia-$(JULIA_COMMIT)-$(OS)-$(ARCH).tar.gz julia-$(JULIA_COMMIT) +endif rm -fr julia-$(JULIA_COMMIT) -h2j: $(BUILD)/$(JL_LIBDIR)/libLLVM*.a $(BUILD)/$(JL_LIBDIR)/libclang*.a src/h2j.cpp - $(QUIET_CC) g++ -O2 -fno-rtti -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -Iinclude $^ -o $@ - clean: | $(CLEAN_TARGETS) @$(MAKE) -C base clean - @$(MAKE) -C extras clean @$(MAKE) -C src clean @$(MAKE) -C ui clean - @$(MAKE) -C test/unicode clean @for buildtype in "release" "debug" ; do \ for repltype in "basic" "readline"; do \ rm -f julia-$${buildtype}-$${repltype}; \ done \ done + @rm -f julia @rm -f *~ *# *.tar.gz @rm -fr $(BUILD)/$(JL_PRIVATE_LIBDIR) cleanall: clean @$(MAKE) -C src clean-flisp clean-support @rm -fr $(BUILD)/$(JL_LIBDIR) -# @$(MAKE) -C deps clean-uv + @$(MAKE) -C deps clean-uv + +distclean: cleanall + @$(MAKE) -C deps distclean + @$(MAKE) -C doc distclean + rm -fr usr .PHONY: default debug release julia-debug julia-release \ - test testall test-* clean cleanall + test testall test-* clean distclean cleanall \ + run-julia run-julia-debug run-julia-release test: release - @$(MAKEs) -C test default + @$(MAKE) $(QUIET_MAKE) -C test default testall: release - @$(MAKEs) -C test all + @$(MAKE) $(QUIET_MAKE) -C test all test-%: release - @$(MAKEs) -C test $* + @$(MAKE) $(QUIET_MAKE) -C test $* + +# download target for some hardcoded windows dependencies +.PHONY: win-extras +win-extras: + cd dist-extras && \ + wget -O 7za920.zip http://downloads.sourceforge.net/sevenzip/7za920.zip && \ + wget -O PortableGit-1.8.1.2-preview20130201.7z https://msysgit.googlecode.com/files/PortableGit-1.8.1.2-preview20130201.7z + diff --git a/README.md b/README.md index 1ffc9475e0b18..fddf902cc6324 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,8 @@ |__/ | +[![Build Status](https://api.travis-ci.org/JuliaLang/julia.png?branch=master)](https://travis-ci.org/JuliaLang/julia) + ## The Julia Language @@ -20,9 +22,9 @@ This is the GitHub repository of Julia source code, including instructions for c - **Homepage:** -- **Binaries:** -- **Packages:** -- **Mailing lists:** +- **Binaries:** +- **Packages:** +- **Mailing lists:** - **IRC:** - **Source code:** - **Git clone URL:** @@ -31,7 +33,7 @@ This is the GitHub repository of Julia source code, including instructions for c The mailing list for developer discussion is . All are welcome, but the volume of messages is higher, and the discussions tend to be more esoteric. New -developers may find the notes in [CONTRIBUTING](https://github.com/JuliaLang/julia/blob/master/CONTRIBUTING.md) helpful to start contributing to the julia codebase. +developers may find the notes in [CONTRIBUTING](https://github.com/JuliaLang/julia/blob/master/CONTRIBUTING.md) helpful to start contributing to the Julia codebase. ## Currently Supported Platforms @@ -39,8 +41,9 @@ developers may find the notes in [CONTRIBUTING](https://github.com/JuliaLang/jul - **GNU/Linux** - **Darwin/OS X** - **FreeBSD** +- **Windows** -All systems are supported with both x86/64 (64-bit) and x86 (32-bit) architectures. [Julia has been ported to Windows](https://github.com/loladiro/julia) as well, and Windows support will be merged into the julia mainline once it stabilizes. +All systems are supported with both x86/64 (64-bit) and x86 (32-bit) architectures. ## Source Download & Compilation @@ -49,14 +52,18 @@ First, acquire the source code by cloning the git repository: git clone git://github.com/JuliaLang/julia.git +If you are behind a firewall and you need to use the https protocol instead of the git protocol: + + git config --global url."https://".insteadOf git:// + Next, enter the `julia/` directory and run `make` to build the `julia` executable. To perform a parallel build, use `make -j N` and supply the maximum number of concurrent processes. When compiled the first time, it will automatically download and build its [external dependencies](#Required-Build-Tools-External-Libraries). -This takes a while, but only has to be done once. -Building julia requires 1.5GiB of diskspace and approximately 700MiB of virtual memory. +This takes a while, but only has to be done once. If the defaults in the build do not work for you, and you need to set specific make parameters, you can save them in `Make.user`. The build will automatically check for the existence of `Make.user` and use it if it exists. +Building Julia requires 1.5GiB of diskspace and approximately 700MiB of virtual memory. **Note:** the build process will not work if any of the build directory's parent directories have spaces in their names (this is due to a limitation in GNU make). -Once it is built, you can either run the `julia` executable using its full path in the directory created above, or add that directory to your executable path so that you can run the julia program from anywhere (in the current shell session): +Once it is built, you can either run the `julia` executable using its full path in the directory created above, or add that directory to your executable path so that you can run the Julia program from anywhere (in the current shell session): In bash: @@ -66,7 +73,7 @@ In csh / tcsh: set path= ( $path $cwd ) -Now you should be able to run julia like this: +Now you should be able to run Julia like this: julia @@ -78,32 +85,36 @@ You can read about [getting started](http://julialang.org/manual/getting-started #### Linux -GCC version 4.6 or later is recommended to build julia. +GCC version 4.6 or later is recommended to build Julia. If the build fails trying to compile OpenBLAS, set OPENBLAS_TARGET_ARCH to BARCELONA on AMD, or NEHALEM on Intel CPUs in Make.inc and build again. -On some Linux distributions you may need to change how the readline library is linked. If you get a build error involving readline, try changing the value of `USE_SYSTEM_READLINE` in `Make.inc` to `1`. +On some Linux distributions you may need to change how the readline library is linked. If you get a build error involving readline, set `USE_SYSTEM_READLINE=1` in `Make.user`. On Ubuntu systems, you may also need to install the package `libncurses5-dev`. -On CentOS 5 systems, the default compiler (gcc 4.1) is too old to build julia. +On CentOS 5 systems, the default compiler (gcc 4.1) is too old to build Julia. #### OS X -It is essential to use a 64-bit gfortran. Download and install [gfortran and gcc from hpc.sf.net](http://hpc.sf.net/), if necessary. The HPC gfortran requires gcc to function properly. +It is essential to use a 64-bit gfortran to compile Julia dependencies. The gfortran-4.7 compilers in brew and macports work for building Julia. If you do not use brew or macports, you can download and install [gfortran and gcc from hpc.sf.net](http://hpc.sf.net/). The HPC gfortran requires gcc to function properly. -If you get link errors mentioning `gfortran`, it might help to put `/usr/local/gfortran/lib` at the beginning of the `DYLD_LIBRARY_PATH` environment variable. +Clang is now used by default to build Julia on OS X (10.7 and above). Make sure to update to at least Xcode 4.3.3, and update to the latest command line tools from the Xcode preferences. This will ensure that clang v3.1 is installed, which is the minimum version of clang required to build Julia. On older systems, the Julia build will attempt to use gcc. The build also detects Snow Leopard and sets `USE_SYSTEM_LIBM=1`, `USE_SYSTEM_BLAS=1`, and `USE_SYSTEM_LAPACK=1`. -Clang is now used by default to build julia on OS X (10.7 and above). Make sure to update to at least Xcode 4.3.3, and update to the latest command line tools from the Xcode preferences. This will ensure that clang v3.1 is installed, which is the minimum version of clang required to build julia. +If you have set `LD_LIBRARY_PATH` or `DYLD_LIBRARY_PATH` in your .bashrc or equivalent, Julia may be unable to find various libraries that come bundled with it. These environment variables need to be unset for Julia to work. #### FreeBSD -*Release 9.0:* install the gcc46, git, and gmake packages/ports, and compile julia with the command: +*Release 9.0:* install the gcc46, git, and gmake packages/ports, and compile Julia with the command: $ gmake FC=gfortran46 You must use the gmake command on FreeBSD instead of make. +#### Windows + +In order to build Julia on Windows, see [README.windows](https://github.com/JuliaLang/julia/blob/master/README.windows.md). + #### MKL To use the Intel [MKL] BLAS & LAPACK libraries, edit the following settings in `Make.inc`: @@ -123,7 +134,7 @@ Building Julia requires that the following software be installed: - **[gcc, g++][gcc]** — compiling and linking C, C++ - **[clang][clang]** — clang is the default compiler on OS X (Need at least v3.1, Xcode 4.3.3 on OS X) - **[gfortran][gcc]** — compiling and linking fortran libraries -- **[git]** — contributions and version control. +- **[git]** — version control and package management. - **[perl]** — preprocessing of header files of libraries. - **[wget]**, **[curl]**, or **fetch** (FreeBSD) — to automatically download external libraries. - **[m4]** — needed to build GMP. @@ -131,8 +142,8 @@ Building Julia requires that the following software be installed: Julia uses the following external libraries, which are automatically downloaded (or in a few cases, included in the Julia source repository) and then compiled from source the first time you run `make`: -- **[LLVM]** — compiler infrastructure. Currently, julia requires LLVM 3.1. -- **[FemtoLisp]** — packaged with julia source, and used to implement the compiler front-end. +- **[LLVM]** — compiler infrastructure. +- **[FemtoLisp]** — packaged with Julia source, and used to implement the compiler front-end. - **[readline]** — library allowing shell-like line editing in the terminal, with history and familiar key bindings. - **[libuv]** — portable, high-performance event-based I/O library - **[OpenLibm]** — a portable libm library containing elementary math functions. @@ -146,9 +157,7 @@ Julia uses the following external libraries, which are automatically downloaded - **[FFTW]** — library for computing fast Fourier transforms very quickly and efficiently. - **[PCRE]** — Perl-compatible regular expressions library. - **[GMP]** — the GNU multiple precision arithmetic library, needed for bigint support. -- **[D3]** — JavaScript visualization library. - **[double-conversion]** — efficient number-to-text conversion. -- **[GLPK]** — linear programming. - **[Rmath]** — basic RNGs and distributions. @@ -175,13 +184,11 @@ Julia uses the following external libraries, which are automatically downloaded [FemtoLisp]: https://github.com/JeffBezanson/femtolisp [readline]: http://cnswww.cns.cwru.edu/php/chet/readline/rltop.html [GMP]: http://gmplib.org/ -[D3]: http://mbostock.github.com/d3/ [double-conversion]: http://double-conversion.googlecode.com/ -[GLPK]: http://www.gnu.org/software/glpk/ [Rmath]: http://cran.r-project.org/doc/manuals/R-admin.html#The-standalone-Rmath-library [libuv]: https://github.com/JuliaLang/libuv -If you already have one or more of these packages installed on your system, it is possible to pass `USE_SYSTEM_...=1` to `make` to prevent Julia from compiling duplicates of these libraries. The complete list of possible flags can be found in Make.inc (or pass `USE_DEBIAN=1` to make if you have all build dependencies and want the minimal Julia build). Please be aware that this proceedure is not officially supported, as it introduces additional variablity into the installation and versioning of the dependencies, and is recommended only for system package maintainers. Unexpected compile errors may result, as the build system will do no further checking to ensure the proper packages are installed. +If you already have one or more of these packages installed on your system, it is possible to pass `USE_SYSTEM_...=1` to `make` to prevent Julia from compiling duplicates of these libraries. The complete list of possible flags can be found in Make.inc. Please be aware that this procedure is not officially supported, as it introduces additional variablity into the installation and versioning of the dependencies, and is recommended only for system package maintainers. Unexpected compile errors may result, as the build system will do no further checking to ensure the proper packages are installed. SuiteSparse is a special case, since it is typically only installed as a static library, while `USE_SYSTEM_SUITESPARSE=1` requires that it is a shared library. Running the script `contrib/repackage_system_suitesparse4.make` will copy your static system SuiteSparse installation into the shared library format required by Julia. @@ -189,42 +196,38 @@ SuiteSparse is a special case, since it is typically only installed as a static ## Directories base/ source code for Julia's standard library - contrib/ emacs, vim and textmate support for Julia + contrib/ editor support for Julia source, miscellaneous scripts deps/ external dependencies examples/ example Julia programs extras/ useful optional libraries - lib/ shared libraries loaded by Julia's standard libraries src/ source for Julia language core test/ unit and functional test cases ui/ source for various front ends + usr/ binaries and shared libraries loaded by Julia's standard libraries ## Binary Installation -Because of the rapid pace of development at this point, we recommend installing the latest Julia from source, but platform-specific tarballs with pre-compiled binaries are also [available for download](https://github.com/JuliaLang/julia/downloads). -To install from source, download the appropriate tarball and untar it somewhere. -For example, if you are on an OS X (Darwin) x86/64 system, do the following: +Because of the rapid pace of development at this point, we recommend installing the latest Julia from source, but platform-specific tarballs with pre-compiled binaries are also [available for download](http://code.google.com/p/Julialang/downloads/list). - wget https://github.com/downloads/JuliaLang/julia/julia-c4865bd18d-Darwin-i386.tar.gz - tar zxvf julia-c4865bd18d-Darwin-i386.tar.gz - -You can either run the `julia` executable using its full path in the directory created above, or add that directory to your executable path so that you can run the julia program from anywhere (in the current shell session): +You can either run the `julia` executable using its full path in the directory created above, or add that directory to your executable path so that you can run the Julia program from anywhere (in the current shell session): export PATH="$(pwd)/julia:$PATH" -Now you should be able to run julia like this: +Now you should be able to run Julia like this: julia If everything works correctly, you will see a Julia banner and an interactive prompt into which you can enter expressions for evaluation. You can read about [getting started](http://julialang.org/manual/getting-started) in the manual. -An [Arch Linux package](https://aur.archlinux.org/packages.php?ID=56877) is also available. +An [Arch Linux package](https://aur.archlinux.org/packages.php?ID=56877) is also available. Julia has also been added to [Debian](http://packages.debian.org/sid/julia). On OS X, Julia is available through [homebrew](http://mxcl.github.com/homebrew/). + ## Editor & Terminal Setup -Currently, [julia editing mode](https://github.com/JuliaLang/julia/wiki/Configuring-Editors) support is available for Emacs, Vim, Textmate, Notepad++, and Kate. +Currently, [Julia editing mode](https://github.com/JuliaLang/julia/wiki/Configuring-Editors) support is available for Emacs, Vim, Textmate, Notepad++, and Kate. Adjusting your terminal bindings is optional; everything will work fine without these key bindings. For the best interactive session experience, however, make sure that your terminal emulator (`Terminal`, `iTerm`, `xterm`, etc.) sends the `^H` sequence for `Backspace` (delete key) and that the `Shift-Enter` key combination sends a `\n` newline character to distinguish it from just pressing `Enter`, which sends a `\r` carriage return character. @@ -237,16 +240,6 @@ On Linux systems, the `Shift-Enter` binding can be set by placing the following keysym Return = Return Linefeed - -## Web REPL - -Julia has a web REPL with very preliminary graphics capabilities. The web REPL is currently a showcase to try out new ideas. The web REPL is social - multiple people signing in with a common session name can collaborate within a session. - -1. Do `make -C deps install-lighttpd` to download and build the webserver. -2. Start the web REPL service with `./usr/bin/launch-julia-webserver`. -3. Point your browser to `http://localhost:2000/`. -4. Try `plot(cumsum(randn(1000)))` and other things. - ### Try it Online [Forio.com](http://forio.com/) is generously hosting and maintaining an instance of Julia's web REPL here: [julia.forio.com](http://julia.forio.com). diff --git a/README.windows.md b/README.windows.md new file mode 100644 index 0000000000000..e3ef64920dc00 --- /dev/null +++ b/README.windows.md @@ -0,0 +1,107 @@ +General Information for Windows +=============================== + +Please see the README at https://github.com/JuliaLang/julia/blob/master/README.md for more complete information about Julia. This is intended to only include information specific to using Julia on Windows. + +Julia runs on Windows XP SP2 or later (including Windows Vista, Windows 7, and Windows 8). Both the 32-bit and 64-bit versions are supported. The 32-bit i686 binary will run on either 32-bit and 64-bit operating systems. The 64-bit x86_64 binary will only run on 64-bit Windows. + +Downloading additional libraries (Tk, Cairo, etc) is not necessary. Julia's package manager will acquire them as needed. + +Julia requires that the lib and lib/julia directories be part of your `%PATH%` variable to startup. The `julia.bat` script will attempt to do this for you and is the recommended way of running julia on your system. The julia.bat file can be given arguments (e.g. `julia.bat -p 2 script.jl` for running script.jl on two processors) which will be passed directly to julia.exe. + +___________________________________________________ +Binary Downloads +================ + +Download the latest version of Julia from the downloads page at https://code.google.com/p/julialang/downloads/list + +Unzip the download to a folder. Do not attempt to run Julia without extracting the zip archive first (hint: it won't work). Double-click the file Julia.BAT to launch Julia. + +Explore and have fun! + +Recommended external libraries: + + - msysGit https://code.google.com/p/msysgit/downloads/list + - TortoiseGit https://code.google.com/p/tortoisegit/wiki/Download + +Optional external libraries + + - MinGW/MSYS (as described below) + +___________________________________________________ +Source Compiling +================ + +There are a number of environments you can use to build julia. Making this easy requires getting the right environment. They are ordered below from worst to best. + +Native Compile +-------------- + +On Windows, you can get the mingw/msys environment from http://www.mingw.org/wiki/Getting_Started. I strongly discourage this. However, if you choose to ignore me, you will need to do the following steps (thanks to Pavan): + +1. Download MinGW+ MSYS Innosetup installer from this url +2. Run this installer to choose from options: Destination Directory (Default- C:\MinGW), MinGW compiler suite (selected C, C++, Fortran), MSYS Basic System (selected), MinGW Developer Toolkit packages (selected). Based on your connection speed, it may take a while to download packages. +3. Set path by choosing ControlPanel > System and Security > System > Advanced System Settings > (Advanced) Environment Variables > Path and add to the end of line: C:\MinGW\bin;C:\MinGW\msys\1.0\bin; +4. At command prompt, type - "mingw-get install wget" - to install wget +5. Install 7-zip (http://www.7-zip.org/download.html), if you don't have it already +5. Download Python-2.6.7_msys.7z from [here](https://osspack32.googlecode.com/files/python-2.6.7_msys.7z) and extract files (using 7-Zip) to respective locations in C:\MinGw\msys\1.0 path, i.e., bin, lib, libs, to get Python 2.6.7 +6. Add the following line - _CRTIMP int __cdecl _resetstkoflw (void); - to C:\MinGW\include\malloc.h at Line 76. This helped in tackling _resetstkoflw errors being showed in compiling codegen.cpp + +The recommended way to setup your environment follows: + +1. Download and extract mingw to C:/MinGW (or similar location) from http://sourceforge.net/projects/mingwbuilds/files/external-binary-packages/ +2. Download and extract msys to C:/MinGW/msys/1.0 (or similar location) from http://sourceforge.net/projects/mingwbuilds/files/host-windows/releases/4.7.2/64-bit/threads-win32/sjlj/ +3. Add the line "C:/MinGW /mingw" to C:/MinGW/msys/1.0/etc/fstab (create the file if it doesn't exist) + +These sections assume you are familiar with building code. If you are not, you should stop reading now and go the the section on binaries. Regardless of which set of steps you followed above, you are now ready to compile julia. Open a unix shell by launching C:/MinGW/msys/1.0/msys.bat (or your favorite shortcut to that file). + +Run the following commands in your build directory ($HOME at C:/MinGW/msys/1.0/home/your_name is fine) +1. `git clone https://github.com/JuliaLang/julia.git` +2. `cd julia` +3. `make` +NEVER use the `-j` argument to make. Windows will sometimes corrupt your build files. Additionally, make will probably lock up several times during the process, using 100% cpu, but not show progress. The only solution appears to be to kill make from the Task Manager and rerunning make. It should pickup where it left off. Expect this to take a very long time (dozens of hours is not uncommon). + +Running julia can be done in two ways: +1. `make run-julia[-release|-debug] [DEFAULT_REPL=(basic|readline)]` (e.g. `make run-julia`) +2. Launching the julia.bat script in usr/bin + +Cross-Compile +------------- + +If you prefer to cross-compile (i.e. you are sane), the following steps should get you started: + +First, you will need to ensure your system has the required dependencies. Note that I build on an Ubuntu system, so the `make dist` may not be fully functional on other systems. On Ubuntu 12.04, the following command will install the required build dependencies. + +``` +apt-get install \ + mingw-w64 \ + gfortran-mingw-w64 \ + g++-mingw-w64 \ + gdb-mingw-w64 \ + mingw-w64-tools \ + binutils-mingw-w64 \ + gcc-mingw-w64 \ + wine +``` + +Finally, the build and install process: + +1. `git clone https://github.com/JuliaLang/julia.git julia-win32` +2. `echo override XC_HOST = i686-w64-mingw32 >> Make.user` +3. `echo override DEFAULT_REPL = basic >> Make.user` +4. `make && make install` +5. (optional) `mkdir dist-extras && make win-extras` (actually, you probably want to hand execute these steps) +6. move the julia-* directory to the target machine +7. Ensure your target has the following dependencies "libgfortran-3.dll" "libquadmath-0.dll" "libgcc_s_sjlj-1.dll" "libstdc++-6.dll" "libssp-0.dll" in the PATH (or in installed julia-* lib folder). These can be copied from the your unix system (on my Ubuntu 12.04 system, they are at /usr/lib/gcc/i686-w64-mingw32/4.6/) or, if you followed my advice above to setup MinGW, they are are in C:/MinGW/bin on your Windows system. + +If you are building for 64-bit windows. The steps are pretty much the same. Just replace i686 in XC_HOST with x86_64. + +Important Build Errata +---------------------- + +- Arpack 3.1.2 has an error in the tar file (a symlink from ./depcomp to a nonexistant file) that prevents it from being extracted on windows (cross-build is fine). To resolve this, we need a tar file that doesn't contain this symlink file. I found the easiest way to solve this was to run `make -C deps get-arpack` and then edit the arpack-*.tar.gz in 7zip to delete the depcomp symlink file before running the primary make target. + +- LLVM 3.x has an error on when compiling for 64-bit Windows that causes the build to fail when building the shared library file. Therefore, before building, you will need to change `--enable-shared` to `--disable-shared` in the `LLVM_FLAGS` variable in `deps/Makefile`. + +- The cross-build does not have access to git. If you want your sysimg to contain version information from the commit, remove the `#` from the line in Makefile that begins with @#echo `git rev-parse --short HEAD ...` and ends with `... > COMMIT` + diff --git a/VERSION b/VERSION index 573541ac9702d..3b04cfb60da13 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0 +0.2 diff --git a/base/.gitignore b/base/.gitignore index 57a8e841d7e06..77ecc7d193ca7 100644 --- a/base/.gitignore +++ b/base/.gitignore @@ -1,4 +1,5 @@ /pcre_h.jl /errno_h.jl -os_detect.jl /build_h.jl +/file_constants.jl +/uv_constants.jl diff --git a/base/Makefile b/base/Makefile index 3c76dd98537f1..2129a6cb96ca4 100644 --- a/base/Makefile +++ b/base/Makefile @@ -3,24 +3,36 @@ include ../Make.inc PCRE_CONST = 0x[0-9a-fA-F]+|[-+]?\s*[0-9]+ -all: pcre_h.jl errno_h.jl os_detect.jl build_h.jl +all: pcre_h.jl errno_h.jl build_h.jl file_constants.jl uv_constants.jl pcre_h.jl: - $(QUIET_PERL) $(CC) -E -dM $(shell $(PCRE_CONFIG) --prefix)/include/pcre.h | perl -nle '/^\s*#define\s+PCRE_(\w*)\s*\(?($(PCRE_CONST))\)?\s*$$/ and print "const $$1 = int32($$2)"' | sort > $@ + $(QUIET_PERL) $(CPP) -dM $(shell $(PCRE_CONFIG) --prefix)/include/pcre.h | perl -nle '/^\s*#define\s+PCRE_(\w*)\s*\(?($(PCRE_CONST))\)?\s*$$/ and print "const $$1 = uint32($$2)"' | sort > $@ errno_h.jl: $(QUIET_PERL) echo '#include "errno.h"' | $(CC) -E -dM - | perl -nle 'print "const $$1 = int32($$2)" if /^#define\s+(E\w+)\s+(\d+)\s*$$/' | sort > $@ -os_detect.jl: ../src/os_detect.h - $(QUIET_PERL) $(CC) -E -P -DJULIA ../src/os_detect.h | perl -p -e 's/\\n/\n/g' > $@ +file_constants.jl: ../src/file_constants.h + $(QUIET_PERL) ${CC} -E -P -DJULIA ../src/file_constants.h | perl -nle 'print "$$1 0o$$2" if /^(\s*const\s+[A-z_]+\s+=)\s+(0[0-9]*)\s*$$/; print "$$1" if /^\s*(const\s+[A-z_]+\s+=\s+([1-9]|0x)[0-9A-z]*)\s*$$/' > $@ + +uv_constants.jl: ../src/uv_constants.h + $(QUIET_PERL) ${CC} -E -P -I"../deps/libuv/include" -DJULIA ../src/uv_constants.h | tail -n 5 > $@ + +build_h.jl: ../Make.inc ../src/os_detect.h + $(QUIET_PERL) $(CC) -E -P -DJULIA ../src/os_detect.h | grep OS_NAME > $@ + @echo "const libm_name = \"$(LIBMNAME)\"" >> $@ + @echo "const libblas_name = \"$(LIBBLASNAME)\"" >> $@ + @echo "const liblapack_name = \"$(LIBLAPACKNAME)\"" >> $@ +ifeq ($(USE_LIB64), 1) + @echo "const USE_LIB64 = true" >> $@ +else + @echo "const USE_LIB64 = false" >> $@ +endif -build_h.jl: ../Make.inc - @echo "libblas_name = \"$(LIBBLASNAME)\"" > $@ - @echo "liblapack_name = \"$(LIBLAPACKNAME)\"" >> $@ clean: rm -f *# *~ rm -f pcre_h.jl rm -f errno_h.jl - rm -f os_detect.jl rm -f build_h.jl + rm -f uv_constants.jl + rm -f file_constants.jl diff --git a/base/abstractarray.jl b/base/abstractarray.jl index d3d4420ad6135..64f56bd6c4f72 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -1,18 +1,12 @@ -## abstractarray.jl : Generic array interfaces. - ## Type aliases for convenience ## typealias AbstractVector{T} AbstractArray{T,1} typealias AbstractMatrix{T} AbstractArray{T,2} -typealias Indices{T<:Integer} Union(Integer, AbstractVector{T}) -typealias Dimspec Union(Int,Dims) - -typealias RangeIndex Union(Int, Range{Int}, Range1{Int}) - ## Basic functions ## size{T,n}(t::AbstractArray{T,n}, d) = (d>n ? 1 : size(t)[d]) +eltype(x) = Any eltype{T,n}(::AbstractArray{T,n}) = T eltype{T,n}(::Type{AbstractArray{T,n}}) = T eltype{T<:AbstractArray}(::Type{T}) = eltype(super(T)) @@ -20,6 +14,7 @@ ndims{T,n}(::AbstractArray{T,n}) = n ndims{T,n}(::Type{AbstractArray{T,n}}) = n ndims{T<:AbstractArray}(::Type{T}) = ndims(super(T)) length(t::AbstractArray) = prod(size(t)) +endof(a::AbstractArray) = length(a) first(a::AbstractArray) = a[1] last(a::AbstractArray) = a[end] @@ -53,6 +48,85 @@ function trailingsize(A, n) return s end +## Bounds checking ## +function check_bounds(sz::Int, I::Real) + I = to_index(I) + if I < 1 || I > sz + throw(BoundsError()) + end +end + +function check_bounds(sz::Int, I::AbstractVector{Bool}) + if length(I) > sz + throw(BoundsError()) + end +end + +function check_bounds{T<:Integer}(sz::Int, I::Ranges{T}) + if !isempty(I) && (min(I) < 1 || max(I) > sz) + throw(BoundsError()) + end +end + +function check_bounds{T <: Real}(sz::Int, I::AbstractVector{T}) + for i in I + i = to_index(i) + if i < 1 || i > sz + throw(BoundsError()) + end + end +end + +function check_bounds(A::AbstractArray, I::AbstractArray{Bool}) + if !isequal(size(A), size(I)) throw(BoundsError()) end +end + +check_bounds(A::AbstractArray, I) = check_bounds(length(A), I) + +function check_bounds(A::AbstractMatrix, I, J) + check_bounds(size(A,1), I) + check_bounds(size(A,2), J) +end + +function check_bounds(A::AbstractArray, I, J) + check_bounds(size(A,1), I) + sz = size(A,2) + for i = 3:ndims(A) + sz *= size(A, i) # TODO: sync. with decision on issue #1030 + end + check_bounds(sz, J) +end + +function check_bounds(A::AbstractArray, I::Union(Real,AbstractArray)...) + n = length(I) + if n > 0 + for dim = 1:(n-1) + check_bounds(size(A,dim), I[dim]) + end + sz = size(A,n) + for i = n+1:ndims(A) + sz *= size(A,i) # TODO: sync. with decision on issue #1030 + end + check_bounds(sz, I[n]) + end +end + +## Bounds-checking without errors ## +in_bounds(l::Int, i::Integer) = 1 <= i <= l +function in_bounds(sz::Dims, I::Int...) + n = length(I) + for dim = 1:(n-1) + if !(1 <= I[dim] <= sz[dim]) + return false + end + end + s = sz[n] + for i = n+1:length(sz) + s *= sz[i] + end + 1 <= I[n] <= s +end + ## Constructors ## # default arguments to similar() @@ -63,37 +137,37 @@ similar{T}(a::AbstractArray{T}, dims::Int...) = similar(a, T, dims) similar (a::AbstractArray, T, dims::Int...) = similar(a, T, dims) function reshape(a::AbstractArray, dims::Dims) - if prod(dims) != numel(a) + if prod(dims) != length(a) error("reshape: invalid dimensions") end - b = similar(a, dims) - for i=1:numel(a) - b[i] = a[i] - end - return b + copy!(similar(a, dims), a) end reshape(a::AbstractArray, dims::Int...) = reshape(a, dims) -vec(a::AbstractArray) = reshape(a,max(size(a))) +vec(a::AbstractArray) = reshape(a,length(a)) -function squeeze(A::AbstractArray) +function squeeze(A::AbstractArray, dims) d = () - for i in size(A) - if i != 1 - d = tuple(d..., i) + for i in 1:ndims(A) + if contains(dims,i) + if size(A,i) != 1 + error("squeezed dims must all be size 1") + end + else + d = tuple(d..., size(A,i)) end end reshape(A, d) end function fill!(A::AbstractArray, x) - for i = 1:numel(A) + for i = 1:length(A) A[i] = x end return A end -function copy_to(dest::AbstractArray, src) +function copy!(dest::AbstractArray, src) i = 1 for x in src dest[i] = x @@ -102,7 +176,8 @@ function copy_to(dest::AbstractArray, src) return dest end -copy(a::AbstractArray) = copy_to(similar(a), a) +copy(a::AbstractArray) = copy!(similar(a), a) +copy(a::AbstractArray{None}) = a # cannot be assigned into so is immutable zero{T}(x::AbstractArray{T}) = fill!(similar(x), zero(T)) @@ -110,8 +185,8 @@ zero{T}(x::AbstractArray{T}) = fill!(similar(x), zero(T)) start(a::AbstractArray) = 1 next(a::AbstractArray,i) = (a[i],i+1) -done(a::AbstractArray,i) = (i > numel(a)) -isempty(a::AbstractArray) = (numel(a) == 0) +done(a::AbstractArray,i) = (i > length(a)) +isempty(a::AbstractArray) = (length(a) == 0) ## Conversions ## @@ -130,23 +205,26 @@ for (f,t) in ((:char, Char), (:int16, Int16), (:int32, Int32), (:int64, Int64), + (:int128, Int128), + (:uint, Uint), (:uint8, Uint8), (:uint16, Uint16), (:uint32, Uint32), - (:uint64, Uint64)) + (:uint64, Uint64), + (:uint128,Uint128)) @eval ($f)(x::AbstractArray{$t}) = x @eval ($f)(x::AbstractArray) = iround_to(similar(x,$t), x) end bool(x::AbstractArray{Bool}) = x -bool(x::AbstractArray) = copy_to(similar(x,Bool), x) +bool(x::AbstractArray) = copy!(similar(x,Bool), x) for (f,t) in ((:float32, Float32), (:float64, Float64), (:complex64, Complex64), (:complex128, Complex128)) @eval ($f)(x::AbstractArray{$t}) = x - @eval ($f)(x::AbstractArray) = copy_to(similar(x,$t), x) + @eval ($f)(x::AbstractArray) = copy!(similar(x,$t), x) end integer{T<:Integer}(x::AbstractArray{T}) = x @@ -156,8 +234,8 @@ complex{T<:Complex}(x::AbstractArray{T}) = x integer (x::AbstractArray) = iround_to(similar(x,typeof(integer(one(eltype(x))))), x) unsigned(x::AbstractArray) = iround_to(similar(x,typeof(unsigned(one(eltype(x))))), x) -float (x::AbstractArray) = copy_to(similar(x,typeof(float(one(eltype(x))))), x) -complex (x::AbstractArray) = copy_to(similar(x,typeof(complex(one(eltype(x))))), x) +float (x::AbstractArray) = copy!(similar(x,typeof(float(one(eltype(x))))), x) +complex (x::AbstractArray) = copy!(similar(x,typeof(complex(one(eltype(x))))), x) dense(x::AbstractArray) = x full(x::AbstractArray) = x @@ -383,13 +461,18 @@ end -## Indexing: ref ## +## Indexing: getindex ## -ref(t::AbstractArray, i::Integer) = error("indexing not defined for ", typeof(t)) -ref(t::AbstractArray, i::Real) = ref(t, to_index(i)) -ref(t::AbstractArray, i::Real, j::Real) = ref(t, to_index(i), to_index(j)) -ref(t::AbstractArray, i::Real, j::Real, k::Real) = ref(t, to_index(i), to_index(j), to_index(k)) -ref(t::AbstractArray, r::Real...) = ref(t,map(to_index,r)...) +getindex(t::AbstractArray, i::Real) = error("indexing not defined for ", typeof(t)) + +# linear indexing with a single multi-dimensional index +function getindex(A::AbstractArray, I::AbstractArray) + x = similar(A, size(I)) + for i=1:length(I) + x[i] = A[I[i]] + end + return x +end # index A[:,:,...,i,:,:,...] where "i" is in dimension "d" # TODO: more optimized special cases @@ -436,18 +519,12 @@ function circshift(a, shiftamts) a[I...]::typeof(a) end -## Indexing: assign ## +## Indexing: setindex! ## # 1-d indexing is assumed defined on subtypes -assign(t::AbstractArray, x, i::Integer) = - error("assign not defined for ",typeof(t)) -assign(t::AbstractArray, x) = throw(MethodError(assign, (t, x))) - -assign(t::AbstractArray, x, i::Real) = assign(t, x, to_index(i)) -assign(t::AbstractArray, x, i::Real, j::Real) = assign(t, x, to_index(i),to_index(j)) -assign(t::AbstractArray, x, i::Real, j::Real, k::Real) = - assign(t, x, to_index(i),to_index(j),to_index(k)) -assign(t::AbstractArray, x, r::Real...) = assign(t, x, map(to_index,r)...) +setindex!(t::AbstractArray, x, i::Real) = + error("setindex! not defined for ",typeof(t)) +setindex!(t::AbstractArray, x) = throw(MethodError(setindex!, (t, x))) ## Concatenation ## @@ -503,8 +580,8 @@ function hcat{T}(A::Union(AbstractMatrix{T},AbstractVector{T})...) if dense for k=1:nargs Ak = A[k] - n = numel(Ak) - copy_to(B, pos, Ak, 1, n) + n = length(Ak) + copy!(B, pos, Ak, 1, n) pos += n end else @@ -730,7 +807,7 @@ function hvcat{T<:Number}(rows::(Int...), xs::T...) a end -function _jl_hvcat_fill(a, xs) +function hvcat_fill(a, xs) k = 1 nr, nc = size(a) for i=1:nr @@ -755,7 +832,7 @@ function hvcat(rows::(Int...), xs::Number...) for i=2:length(xs) T = promote_type(T,typeof(xs[i])) end - _jl_hvcat_fill(Array(T, nr, nc), xs) + hvcat_fill(Array(T, nr, nc), xs) end ## Reductions and scans ## @@ -764,7 +841,7 @@ function isequal(A::AbstractArray, B::AbstractArray) if size(A) != size(B) return false end - for i = 1:numel(A) + for i = 1:length(A) if !isequal(A[i], B[i]) return false end @@ -773,7 +850,7 @@ function isequal(A::AbstractArray, B::AbstractArray) end function cmp(A::AbstractArray, B::AbstractArray) - nA, nB = numel(A), numel(B) + nA, nB = length(A), length(B) for i = 1:min(nA, nB) a, b = A[i], B[i] if !isequal(a, b) @@ -789,7 +866,7 @@ function (==)(A::AbstractArray, B::AbstractArray) if size(A) != size(B) return false end - for i = 1:numel(A) + for i = 1:length(A) if !(A[i]==B[i]) return false end @@ -801,7 +878,7 @@ function (!=)(A::AbstractArray, B::AbstractArray) if size(A) != size(B) return true end - for i = 1:numel(A) + for i = 1:length(A) if A[i]!=B[i] return true end @@ -809,17 +886,11 @@ function (!=)(A::AbstractArray, B::AbstractArray) return false end -(<)(A::AbstractArray, B::AbstractArray) = - error("Not defined. To compare arrays, try .< .> .<= .>= or isless.") - -(==)(A::AbstractArray, B) = error("Not defined. Try .== or isequal.") - -(==)(A, B::AbstractArray) = error("Not defined. Try .== or isequal.") - for (f, op) = ((:cumsum, :+), (:cumprod, :*) ) @eval function ($f)(v::AbstractVector) n = length(v) - c = similar(v, n) + c = $(op===:+ ? (:(similar(v,typeof(+zero(eltype(v)))))) : + (:(similar(v)))) if n == 0; return c; end c[1] = v[1] @@ -838,7 +909,50 @@ for (f, op) = ((:cumsum, :+), (:cumprod, :*) ) axis_stride *= size(A,i) end - if axis_size <= 1 + B = $(op===:+ ? (:(similar(A,typeof(+zero(eltype(A)))))) : + (:(similar(A)))) + + if axis_size < 1 + return B + end + + for i = 1:length(A) + if div(i-1, axis_stride) % axis_size == 0 + B[i] = A[i] + else + B[i] = ($op)(A[i], B[i-axis_stride]) + end + end + + return B + end + + @eval ($f)(A::AbstractArray) = ($f)(A, 1) +end + +for (f, op) = ((:cummin, :min), (:cummax, :max)) + @eval function ($f)(v::AbstractVector) + n = length(v) + cur_val = v[1] + res = similar(v, n) + res[1] = cur_val + for i in 2:n + cur_val = ($op)(v[i], cur_val) + res[i] = cur_val + end + return res + end + + @eval function ($f)(A::AbstractArray, axis::Integer) + dimsA = size(A) + ndimsA = ndims(A) + axis_size = dimsA[axis] + axis_stride = 1 + for i = 1:(axis-1) + axis_stride *= size(A,i) + end + + if axis_size < 1 return A end @@ -858,14 +972,14 @@ for (f, op) = ((:cumsum, :+), (:cumprod, :*) ) @eval ($f)(A::AbstractArray) = ($f)(A, 1) end -## ipermute in terms of permute ## +## ipermutedims in terms of permutedims ## -function ipermute(A::AbstractArray,perm) +function ipermutedims(A::AbstractArray,perm) iperm = Array(Int,length(perm)) for i = 1:length(perm) iperm[perm[i]] = i end - return permute(A,iperm) + return permutedims(A,iperm) end ## Other array functions ## @@ -962,9 +1076,9 @@ function ind2sub{T<:Integer}(dims::(Integer,Integer...), ind::AbstractVector{T}) return t end -indices(I::Indices) = I -indices(I::AbstractVector{Bool}) = find(I) -indices(I::(Indices...)) = map(indices, I) +indices(I) = I +indices(I::AbstractArray{Bool,1}) = find(I) +indices(I::Tuple) = map(indices, I) ## iteration utilities ## @@ -1042,9 +1156,9 @@ function bsxfun(f, a::AbstractArray, b::AbstractArray) if isempty(range) return f(a, b) end - if numel(a) == 1 + if length(a) == 1 return f(a[1], b) - elseif numel(b) == 1 + elseif length(b) == 1 return f(a, b[1]) end c = Array(promote_type(eltype(a),eltype(b)), shp...) @@ -1069,12 +1183,12 @@ function bsxfun(f, a::AbstractArray, b::AbstractArray) end end if xb - aa = a[aidxs...]; if numel(aa)==1; aa=aa[1]; end + aa = a[aidxs...]; if length(aa)==1; aa=aa[1]; end else aa = a end if xa - bb = b[bidxs...]; if numel(bb)==1; bb=bb[1]; end + bb = b[bidxs...]; if length(bb)==1; bb=bb[1]; end else bb = b end @@ -1087,3 +1201,313 @@ end bsxfun(f, a, b) = f(a, b) bsxfun(f, a::AbstractArray, b) = f(a, b) bsxfun(f, a, b::AbstractArray) = f(a, b) +bsxfun(f, a, b, c...) = bsxfun(f, bsxfun(f, a, b), c...) + +# Basic AbstractArray functions + +function nnz{T}(a::AbstractArray{T}) + n = 0 + for i = 1:length(a) + n += a[i] != zero(T) ? 1 : 0 + end + return n +end + +# for reductions that expand 0 dims to 1 +reduced_dims(A, region) = ntuple(ndims(A), i->(contains(region, i) ? 1 : + size(A,i))) + +# keep 0 dims in place +reduced_dims0(A, region) = ntuple(ndims(A), i->(size(A,i)==0 ? 0 : + contains(region, i) ? 1 : + size(A,i))) + +reducedim(f::Function, A, region, v0) = + reducedim(f, A, region, v0, similar(A, reduced_dims(A, region))) + +max{T}(A::AbstractArray{T}, b::(), region) = + isempty(A) ? similar(A,reduced_dims0(A,region)) : reducedim(max,A,region,typemin(T)) +min{T}(A::AbstractArray{T}, b::(), region) = + isempty(A) ? similar(A,reduced_dims0(A,region)) : reducedim(min,A,region,typemax(T)) +sum{T}(A::AbstractArray{T}, region) = reducedim(+,A,region,zero(T)) +prod{T}(A::AbstractArray{T}, region) = reducedim(*,A,region,one(T)) + +all(A::AbstractArray{Bool}, region) = reducedim(all,A,region,true) +any(A::AbstractArray{Bool}, region) = reducedim(any,A,region,false) +sum(A::AbstractArray{Bool}, region) = reducedim(+,A,region,0,similar(A,Int,reduced_dims(A,region))) +sum(A::AbstractArray{Bool}) = sum(A, [1:ndims(A)])[1] +prod(A::AbstractArray{Bool}) = + error("use all() instead of prod() for boolean arrays") +prod(A::AbstractArray{Bool}, region) = + error("use all() instead of prod() for boolean arrays") + +function sum{T}(A::AbstractArray{T}) + if isempty(A) + return zero(T) + end + v = A[1] + for i=2:length(A) + v += A[i] + end + v +end + +function sum_kbn{T<:FloatingPoint}(A::AbstractArray{T}) + n = length(A) + if (n == 0) + return zero(T) + end + s = A[1] + c = zero(T) + for i in 2:n + Ai = A[i] + t = s + Ai + if abs(s) >= abs(Ai) + c += ((s-t) + Ai) + else + c += ((Ai-t) + s) + end + s = t + end + + s + c +end + +# Uses K-B-N summation +function cumsum_kbn{T<:FloatingPoint}(v::AbstractVector{T}) + n = length(v) + r = similar(v, n) + if n == 0; return r; end + + s = r[1] = v[1] + c = zero(T) + for i=2:n + vi = v[i] + t = s + vi + if abs(s) >= abs(vi) + c += ((s-t) + vi) + else + c += ((vi-t) + s) + end + s = t + r[i] = s+c + end + return r +end + +# Uses K-B-N summation +function cumsum_kbn{T<:FloatingPoint}(A::AbstractArray{T}, axis::Integer) + dimsA = size(A) + ndimsA = ndims(A) + axis_size = dimsA[axis] + axis_stride = 1 + for i = 1:(axis-1) + axis_stride *= size(A,i) + end + + if axis_size <= 1 + return A + end + + B = similar(A) + C = similar(A) + + for i = 1:length(A) + if div(i-1, axis_stride) % axis_size == 0 + B[i] = A[i] + C[i] = zero(T) + else + s = B[i-axis_stride] + Ai = A[i] + B[i] = t = s + Ai + if abs(s) >= abs(Ai) + C[i] = C[i-axis_stride] + ((s-t) + Ai) + else + C[i] = C[i-axis_stride] + ((Ai-t) + s) + end + end + end + + return B + C +end + +function prod{T}(A::AbstractArray{T}) + if isempty(A) + return one(T) + end + v = A[1] + for i=2:length(A) + v *= A[i] + end + v +end + +function min{T<:Integer}(A::AbstractArray{T}) + if isempty(A); error("min: argument is empty"); end + v = A[1] + for i=2:length(A) + x = A[i] + if x < v + v = x + end + end + v +end + +function max{T<:Integer}(A::AbstractArray{T}) + if isempty(A); error("max: argument is empty"); end + v = A[1] + for i=2:length(A) + x = A[i] + if x > v + v = x + end + end + v +end + +## map over arrays ## + +## along an axis +function amap(f::Function, A::AbstractArray, axis::Integer) + warn_once("amap is deprecated, use mapslices(f, A, dims) instead") + dimsA = size(A) + ndimsA = ndims(A) + axis_size = dimsA[axis] + + if axis_size == 0 + return f(A) + end + + idx = ntuple(ndimsA, j -> j == axis ? 1 : 1:dimsA[j]) + r = f(sub(A, idx)) + R = Array(typeof(r), axis_size) + R[1] = r + + for i = 2:axis_size + idx = ntuple(ndimsA, j -> j == axis ? i : 1:dimsA[j]) + R[i] = f(sub(A, idx)) + end + + return R +end + +## transform any set of dimensions +## dims specifies which dimensions will be transformed. for example +## dims==1:2 will call f on all slices A[:,:,...] +mapslices(f::Function, A::AbstractArray, dims) = mapslices(f, A, [dims...]) +function mapslices(f::Function, A::AbstractArray, dims::AbstractVector) + if isempty(dims) + return A + end + + dimsA = [size(A)...] + ndimsA = ndims(A) + alldims = [1:ndimsA] + + if dims == alldims + return f(A) + end + + otherdims = setdiff(alldims, dims) + + idx = cell(ndimsA) + fill!(idx, 1) + Asliceshape = tuple(dimsA[dims]...) + itershape = tuple(dimsA[otherdims]...) + for d in dims + idx[d] = 1:size(A,d) + end + + r1 = f(reshape(A[idx...], Asliceshape)) + + # determine result size and allocate + Rsize = copy(dimsA) + # TODO: maybe support removing dimensions + if isempty(size(r1)) + r1 = [r1] + end + Rsize[dims] = [size(r1)...] + R = similar(r1, tuple(Rsize...)) + + ridx = cell(ndims(R)) + fill!(ridx, 1) + for d in dims + ridx[d] = 1:size(R,d) + end + + R[ridx...] = r1 + + first = true + cartesian_map(itershape) do idxs... + if first + first = false + else + ia = [idxs...] + idx[otherdims] = ia + ridx[otherdims] = ia + R[ridx...] = f(reshape(A[idx...], Asliceshape)) + end + end + + return R +end + + +## 1 argument +function map_to2(f, first, dest::AbstractArray, A::AbstractArray) + dest[1] = first + for i=2:length(A) + dest[i] = f(A[i]) + end + return dest +end + +function map(f, A::AbstractArray) + if isempty(A); return A; end + first = f(A[1]) + dest = similar(A, typeof(first)) + return map_to2(f, first, dest, A) +end + +## 2 argument +function map_to2(f, first, dest::AbstractArray, A::AbstractArray, B::AbstractArray) + dest[1] = first + for i=2:length(A) + dest[i] = f(A[i], B[i]) + end + return dest +end + +function map(f, A::AbstractArray, B::AbstractArray) + shp = promote_shape(size(A),size(B)) + if isempty(A) + return similar(A, eltype(A), shp) + end + first = f(A[1], B[1]) + dest = similar(A, typeof(first), shp) + return map_to2(f, first, dest, A, B) +end + +## N argument +function map_to2(f, first, dest::AbstractArray, As::AbstractArray...) + n = length(As[1]) + i = 1 + ith = a->a[i] + dest[1] = first + for i=2:n + dest[i] = f(map(ith, As)...) + end + return dest +end + +function map(f, As::AbstractArray...) + shape = mapreduce(size, promote_shape, As) + if prod(shape) == 0 + return similar(As[1], eltype(As[1]), shape) + end + first = f(map(a->a[1], As)...) + dest = similar(As[1], typeof(first), shape) + return map_to2(f, first, dest, As...) +end + diff --git a/base/array.jl b/base/array.jl index 010d6f49e2719..8342b8bf1d317 100644 --- a/base/array.jl +++ b/base/array.jl @@ -15,11 +15,12 @@ size(a::Array) = arraysize(a) size(a::Array, d) = arraysize(a, d) size(a::Matrix) = (arraysize(a,1), arraysize(a,2)) length(a::Array) = arraylen(a) +sizeof(a::Array) = sizeof(eltype(a)) * length(a) function stride(a::Array, i::Integer) s = 1 if i > ndims(a) - return numel(a) + return length(a) end for n=1:(i-1) s *= size(a, n) @@ -34,15 +35,15 @@ isassigned(a::Array, i::Int...) = isdefined(a, i...) ## copy ## -function copy_to{T}(dest::Array{T}, dsto, src::Array{T}, so, N) - if so+N-1 > numel(src) || dsto+N-1 > numel(dest) || dsto < 1 || so < 1 +function copy!{T}(dest::Array{T}, dsto, src::Array{T}, so, N) + if so+N-1 > length(src) || dsto+N-1 > length(dest) || dsto < 1 || so < 1 throw(BoundsError()) end - copy_to_unsafe(dest, dsto, src, so, N) + copy_unsafe!(dest, dsto, src, so, N) end -function copy_to_unsafe{T}(dest::Array{T}, dsto, src::Array{T}, so, N) - if isa(T, BitsKind) +function copy_unsafe!{T}(dest::Array{T}, dsto, src::Array{T}, so, N) + if isbits(T) ccall(:memcpy, Ptr{Void}, (Ptr{Void}, Ptr{Void}, Uint), pointer(dest, dsto), pointer(src, so), N*sizeof(T)) else @@ -53,11 +54,11 @@ function copy_to_unsafe{T}(dest::Array{T}, dsto, src::Array{T}, so, N) return dest end -copy_to{T}(dest::Array{T}, src::Array{T}) = copy_to(dest, 1, src, 1, numel(src)) +copy!{T}(dest::Array{T}, src::Array{T}) = copy!(dest, 1, src, 1, length(src)) -function copy_to{R,S}(B::Matrix{R}, ir_dest::Range1{Int}, jr_dest::Range1{Int}, A::StridedMatrix{S}, ir_src::Range1{Int}, jr_src::Range1{Int}) +function copy!{R,S}(B::Matrix{R}, ir_dest::Range1{Int}, jr_dest::Range1{Int}, A::StridedMatrix{S}, ir_src::Range1{Int}, jr_src::Range1{Int}) if length(ir_dest) != length(ir_src) || length(jr_dest) != length(jr_src) - error("copy_to: size mismatch") + error("copy!: size mismatch") end check_bounds(B, ir_dest, jr_dest) check_bounds(A, ir_src, jr_src) @@ -66,7 +67,7 @@ function copy_to{R,S}(B::Matrix{R}, ir_dest::Range1{Int}, jr_dest::Range1{Int}, Bskip = size(B, 1) if stride(A, 1) == 1 && R == S for jsrc in jr_src - copy_to(B, (jdest-1)*Bskip+first(ir_dest), A, (jsrc-1)*Askip+first(ir_src), length(ir_src)) + copy!(B, (jdest-1)*Bskip+first(ir_dest), A, (jsrc-1)*Askip+first(ir_src), length(ir_src)) jdest += 1 end else @@ -82,9 +83,9 @@ function copy_to{R,S}(B::Matrix{R}, ir_dest::Range1{Int}, jr_dest::Range1{Int}, end end end -function copy_to_transpose{R,S}(B::Matrix{R}, ir_dest::Range1{Int}, jr_dest::Range1{Int}, A::StridedMatrix{S}, ir_src::Range1{Int}, jr_src::Range1{Int}) +function copy_transpose!{R,S}(B::Matrix{R}, ir_dest::Range1{Int}, jr_dest::Range1{Int}, A::StridedMatrix{S}, ir_src::Range1{Int}, jr_src::Range1{Int}) if length(ir_dest) != length(jr_src) || length(jr_dest) != length(ir_src) - error("copy_to: size mismatch") + error("copy_transpose!: size mismatch") end check_bounds(B, ir_dest, jr_dest) check_bounds(A, ir_src, jr_src) @@ -102,8 +103,8 @@ function copy_to_transpose{R,S}(B::Matrix{R}, ir_dest::Range1{Int}, jr_dest::Ran end function reinterpret{T,S}(::Type{T}, a::Array{S,1}) - nel = int(div(numel(a)*sizeof(S),sizeof(T))) - ccall(:jl_reshape_array, Array{T,1}, (Any, Any, Any), Array{T,1}, a, (nel,)) + nel = int(div(length(a)*sizeof(S),sizeof(T))) + return reinterpret(T, a, (nel,)) end function reinterpret{T,S}(::Type{T}, a::Array{S}) @@ -114,7 +115,13 @@ function reinterpret{T,S}(::Type{T}, a::Array{S}) end function reinterpret{T,S,N}(::Type{T}, a::Array{S}, dims::NTuple{N,Int}) - nel = div(numel(a)*sizeof(S),sizeof(T)) + if !isbits(T) + error("cannot reinterpret to type ", T) + end + if !isbits(S) + error("cannot reinterpret Array of type ", S) + end + nel = div(length(a)*sizeof(S),sizeof(T)) if prod(dims) != nel error("reinterpret: invalid dimensions") end @@ -123,7 +130,7 @@ end reinterpret(t::Type,x) = reinterpret(t,[x])[1] function reshape{T,N}(a::Array{T}, dims::NTuple{N,Int}) - if prod(dims) != numel(a) + if prod(dims) != length(a) error("reshape: invalid dimensions") end ccall(:jl_reshape_array, Array{T,N}, (Any, Any, Any), Array{T,N}, a, dims) @@ -142,7 +149,7 @@ similar{T}(a::Array{T,2}, m::Int) = Array(T, m) similar{T}(a::Array{T,2}, S) = Array(S, size(a,1), size(a,2)) # T[x...] constructs Array{T,1} -function ref{T}(::Type{T}, vals...) +function getindex(T::NonTupleType, vals...) a = Array(T,length(vals)) for i = 1:length(vals) a[i] = vals[i] @@ -151,7 +158,7 @@ function ref{T}(::Type{T}, vals...) end # T[a:b] and T[a:s:b] also contruct typed ranges -function ref{T<:Number}(::Type{T}, r::Ranges) +function getindex{T<:Number}(::Type{T}, r::Ranges) a = Array(T,length(r)) i = 1 for x in r @@ -166,10 +173,10 @@ function fill!{T<:Union(Int8,Uint8)}(a::Array{T}, x::Integer) return a end function fill!{T<:Union(Integer,FloatingPoint)}(a::Array{T}, x) - if isa(T,BitsKind) && convert(T,x) == 0 + if isbits(T) && convert(T,x) == 0 ccall(:memset, Ptr{T}, (Ptr{T}, Int32, Int32), a,0,length(a)*sizeof(T)) else - for i = 1:numel(a) + for i = 1:length(a) a[i] = x end end @@ -195,14 +202,15 @@ end eye(m::Int, n::Int) = eye(Float64, m, n) eye(T::Type, n::Int) = eye(T, n, n) eye(n::Int) = eye(Float64, n) -eye{T}(x::StridedMatrix{T}) = eye(T, size(x, 1), size(x, 2)) -function one{T}(x::StridedMatrix{T}) +eye{T}(x::AbstractMatrix{T}) = eye(T, size(x, 1), size(x, 2)) +function one{T}(x::AbstractMatrix{T}) m,n = size(x) if m != n; error("Multiplicative identity only defined for square matrices!"); end; eye(T, m) end - +linspace(start::Integer, stop::Integer, n::Integer) = + linspace(float(start), float(stop), n) function linspace(start::Real, stop::Real, n::Integer) (start, stop) = promote(start, stop) T = typeof(start) @@ -211,19 +219,12 @@ function linspace(start::Real, stop::Real, n::Integer) a[1] = start return a end - step = (stop-start)/(n-1) - if isa(start,Integer) - for i=1:n - a[i] = iround(T,start+(i-1)*step) - end - else - for i=1:n - a[i] = start+(i-1)*step - end + n -= 1 + for i=0:n + a[i+1] = start*((n-i)/n) + stop*(i/n) end a end - linspace(start::Real, stop::Real) = linspace(start, stop, 100) logspace(start::Real, stop::Real, n::Integer) = 10.^linspace(start, stop, n) @@ -234,146 +235,85 @@ logspace(start::Real, stop::Real) = logspace(start, stop, 50) convert{T,n}(::Type{Array{T}}, x::Array{T,n}) = x convert{T,n}(::Type{Array{T,n}}, x::Array{T,n}) = x convert{T,n,S}(::Type{Array{T}}, x::Array{S,n}) = convert(Array{T,n}, x) -convert{T,n,S}(::Type{Array{T,n}}, x::Array{S,n}) = copy_to(similar(x,T), x) +convert{T,n,S}(::Type{Array{T,n}}, x::Array{S,n}) = copy!(similar(x,T), x) -## Bounds checking ## -function check_bounds(sz::Int, I::Integer) - if I < 1 || I > sz - throw(BoundsError()) - end -end +collect(itr) = [x for x in itr] -function check_bounds(sz::Int, I::AbstractVector{Bool}) - if length(I) > sz - throw(BoundsError()) - end -end +## Indexing: getindex ## -function check_bounds{T<:Integer}(sz::Int, I::Ranges{T}) - if min(I) < 1 || max(I) > sz - throw(BoundsError()) - end -end - -function check_bounds{T <: Integer}(sz::Int, I::AbstractVector{T}) - for i in I - if i < 1 || i > sz - throw(BoundsError()) - end - end -end +getindex(a::Array) = arrayref(a,1) -function check_bounds(A::Array, I::Array{Bool}) - if !isequal(size(A), size(I)) - throw(BoundsError()) - end -end - -check_bounds(A::AbstractVector, I::Indices) = check_bounds(length(A), I) +getindex(A::Array, i0::Real) = arrayref(A,to_index(i0)) +getindex(A::Array, i0::Real, i1::Real) = arrayref(A,to_index(i0),to_index(i1)) +getindex(A::Array, i0::Real, i1::Real, i2::Real) = + arrayref(A,to_index(i0),to_index(i1),to_index(i2)) +getindex(A::Array, i0::Real, i1::Real, i2::Real, i3::Real) = + arrayref(A,to_index(i0),to_index(i1),to_index(i2),to_index(i3)) +getindex(A::Array, i0::Real, i1::Real, i2::Real, i3::Real, i4::Real) = + arrayref(A,to_index(i0),to_index(i1),to_index(i2),to_index(i3),to_index(i4)) +getindex(A::Array, i0::Real, i1::Real, i2::Real, i3::Real, i4::Real, i5::Real) = + arrayref(A,to_index(i0),to_index(i1),to_index(i2),to_index(i3),to_index(i4),to_index(i5)) -function check_bounds(A::AbstractMatrix, I::Indices, J::Indices) - check_bounds(size(A,1), I) - check_bounds(size(A,2), J) -end - -function check_bounds(A::AbstractArray, I::Indices, J::Indices) - check_bounds(size(A,1), I) - sz = size(A,2) - for i = 3:ndims(A) - sz *= size(A, i) # TODO: sync. with decision on issue #1030 - end - check_bounds(sz, J) -end +getindex(A::Array, i0::Real, i1::Real, i2::Real, i3::Real, i4::Real, i5::Real, I::Int...) = + arrayref(A,to_index(i0),to_index(i1),to_index(i2),to_index(i3),to_index(i4),to_index(i5),I...) -function check_bounds(A::AbstractArray, I::Indices...) - n = length(I) - if n > 0 - for dim = 1:(n-1) - check_bounds(size(A,dim), I[dim]) - end - sz = size(A,n) - for i = n+1:ndims(A) - sz *= size(A,i) # TODO: sync. with decision on issue #1030 - end - check_bounds(sz, I[n]) +# Fast copy using copy! for Range1 +function getindex(A::Array, I::Range1{Int}) + lI = length(I) + X = similar(A, lI) + if lI > 0 + copy!(X, 1, A, first(I), lI) end -end - -## Indexing: ref ## - -ref(a::Array) = arrayref(a,1) - -ref(A::Array, i0::Integer) = arrayref(A,int(i0)) -ref(A::Array, i0::Integer, i1::Integer) = arrayref(A,int(i0),int(i1)) -ref(A::Array, i0::Integer, i1::Integer, i2::Integer) = - arrayref(A,int(i0),int(i1),int(i2)) -ref(A::Array, i0::Integer, i1::Integer, i2::Integer, i3::Integer) = - arrayref(A,int(i0),int(i1),int(i2),int(i3)) -ref(A::Array, i0::Integer, i1::Integer, i2::Integer, i3::Integer, i4::Integer) = - arrayref(A,int(i0),int(i1),int(i2),int(i3),int(i4)) -ref(A::Array, i0::Integer, i1::Integer, i2::Integer, i3::Integer, i4::Integer, i5::Integer) = - arrayref(A,int(i0),int(i1),int(i2),int(i3),int(i4),int(i5)) - -ref(A::Array, i0::Integer, i1::Integer, i2::Integer, i3::Integer, i4::Integer, i5::Integer, I::Int...) = - arrayref(A,int(i0),int(i1),int(i2),int(i3),int(i4),int(i5),I...) - -# Fast copy using copy_to for Range1 -function ref(A::Array, I::Range1{Int}) - X = similar(A, length(I)) - copy_to(X, 1, A, first(I), length(I)) return X end # note: this is also useful for Ranges -function ref{T<:Integer}(A::Array, I::AbstractVector{T}) - check_bounds(A, I) - return [ A[i] for i=I ] -end -function ref{T<:Integer}(A::AbstractArray, I::AbstractVector{T}) - check_bounds(A, I) - return [ A[i] for i=I ] +function getindex{T<:Real}(A::AbstractArray, I::AbstractVector{T}) + return [ A[i] for i in indices(I) ] end # 2d indexing -function ref(A::Array, I::Range1{Int}, j::Int) +function getindex(A::Array, I::Range1{Int}, j::Real) + j = to_index(j) check_bounds(A, I, j) X = similar(A,length(I)) - copy_to_unsafe(X, 1, A, (j-1)*size(A,1) + first(I), length(I)) + copy_unsafe!(X, 1, A, (j-1)*size(A,1) + first(I), length(I)) return X end -function ref(A::Array, I::Range1{Int}, J::Range1{Int}) +function getindex(A::Array, I::Range1{Int}, J::Range1{Int}) check_bounds(A, I, J) - X = similar(A, ref_shape(I, J)) + X = similar(A, index_shape(I, J)) if length(I) == size(A,1) - copy_to_unsafe(X, 1, A, (first(J)-1)*size(A,1) + 1, size(A,1)*length(J)) + copy_unsafe!(X, 1, A, (first(J)-1)*size(A,1) + 1, size(A,1)*length(J)) else storeoffset = 1 for j = J - copy_to_unsafe(X, storeoffset, A, (j-1)*size(A,1) + first(I), length(I)) + copy_unsafe!(X, storeoffset, A, (j-1)*size(A,1) + first(I), length(I)) storeoffset += length(I) end end return X end -function ref(A::Array, I::Range1{Int}, J::AbstractVector{Int}) +function getindex(A::Array, I::Range1{Int}, J::AbstractVector{Int}) check_bounds(A, I, J) - X = similar(A, ref_shape(I, J)) + X = similar(A, index_shape(I, J)) storeoffset = 1 for j = J - copy_to_unsafe(X, storeoffset, A, (j-1)*size(A,1) + first(I), length(I)) + copy_unsafe!(X, storeoffset, A, (j-1)*size(A,1) + first(I), length(I)) storeoffset += length(I) end return X end -ref{T<:Integer}(A::Array, I::AbstractVector{T}, j::Integer) = [ A[i,j] for i=I ] -ref{T<:Integer}(A::Array, I::Integer, J::AbstractVector{T}) = [ A[i,j] for i=I,j=J ] +getindex{T<:Real}(A::Array, I::AbstractVector{T}, j::Real) = [ A[i,j] for i=indices(I) ] +getindex{T<:Real}(A::Array, I::Real, J::AbstractVector{T}) = [ A[i,j] for i=I,j=indices(J) ] # This next is a 2d specialization of the algorithm used for general # multidimensional indexing -function ref{T<:Integer}(A::Array, I::AbstractVector{T}, J::AbstractVector{T}) +function getindex{T<:Real}(A::Array, I::AbstractVector{T}, J::AbstractVector{T}) check_bounds(A, I, J) - X = similar(A, ref_shape(I, J)) + I = indices(I); J = indices(J) + X = similar(A, index_shape(I, J)) storeind = 1 for j = J offset = (j-1)*size(A,1) @@ -385,17 +325,17 @@ function ref{T<:Integer}(A::Array, I::AbstractVector{T}, J::AbstractVector{T}) return X end # Multidimensional indexing -let ref_cache = nothing -global ref -function ref(A::Array, I::Indices...) +let getindex_cache = nothing +global getindex +function getindex(A::Array, I::Union(Real,AbstractVector)...) check_bounds(A, I...) I = indices(I) - X = similar(A, ref_shape(I...)) + X = similar(A, index_shape(I...)) - if is(ref_cache,nothing) - ref_cache = Dict() + if is(getindex_cache,nothing) + getindex_cache = Dict() end - gen_array_index_map(ref_cache, refind -> quote + gen_array_index_map(getindex_cache, refind -> quote X[storeind] = A[$refind] storeind += 1 end, I, (:A, :X, :storeind), A, X, 1) @@ -406,12 +346,12 @@ end # logical indexing -function _jl_ref_bool_1d(A::Array, I::AbstractArray{Bool}) +function getindex_bool_1d(A::Array, I::AbstractArray{Bool}) check_bounds(A, I) n = sum(I) out = similar(A, n) c = 1 - for i = 1:numel(I) + for i = 1:length(I) if I[i] out[c] = A[i] c += 1 @@ -420,52 +360,52 @@ function _jl_ref_bool_1d(A::Array, I::AbstractArray{Bool}) out end -ref(A::Vector, I::AbstractVector{Bool}) = _jl_ref_bool_1d(A, I) -ref(A::Vector, I::AbstractArray{Bool}) = _jl_ref_bool_1d(A, I) -ref(A::Array, I::AbstractVector{Bool}) = _jl_ref_bool_1d(A, I) -ref(A::Array, I::AbstractArray{Bool}) = _jl_ref_bool_1d(A, I) +getindex(A::Vector, I::AbstractVector{Bool}) = getindex_bool_1d(A, I) +getindex(A::Vector, I::AbstractArray{Bool}) = getindex_bool_1d(A, I) +getindex(A::Array, I::AbstractVector{Bool}) = getindex_bool_1d(A, I) +getindex(A::Array, I::AbstractArray{Bool}) = getindex_bool_1d(A, I) # @Jeff: more efficient is to check the bool vector, and then do # indexing without checking. Turn off checking for the second stage? -ref(A::Matrix, I::Integer, J::AbstractVector{Bool}) = A[I,find(J)] -ref(A::Matrix, I::AbstractVector{Bool}, J::Integer) = A[find(I),J] -ref(A::Matrix, I::AbstractVector{Bool}, J::AbstractVector{Bool}) = A[find(I),find(J)] -ref{T<:Integer}(A::Matrix, I::AbstractVector{T}, J::AbstractVector{Bool}) = A[I,find(J)] -ref{T<:Integer}(A::Matrix, I::AbstractVector{Bool}, J::AbstractVector{T}) = A[find(I),J] - -## Indexing: assign ## -assign{T}(A::Array{T,0}, x) = arrayset(A, convert(T,x), 1) - -assign(A::Array{Any}, x::ANY, i::Integer) = arrayset(A, x, int(i)) - -assign{T}(A::Array{T}, x, i0::Integer) = arrayset(A, convert(T,x), int(i0)) -assign{T}(A::Array{T}, x, i0::Integer, i1::Integer) = - arrayset(A, convert(T,x), int(i0), int(i1)) -assign{T}(A::Array{T}, x, i0::Integer, i1::Integer, i2::Integer) = - arrayset(A, convert(T,x), int(i0), int(i1), int(i2)) -assign{T}(A::Array{T}, x, i0::Integer, i1::Integer, i2::Integer, i3::Integer) = - arrayset(A, convert(T,x), int(i0), int(i1), int(i2), int(i3)) -assign{T}(A::Array{T}, x, i0::Integer, i1::Integer, i2::Integer, i3::Integer, i4::Integer) = - arrayset(A, convert(T,x), int(i0), int(i1), int(i2), int(i3), int(i4)) -assign{T}(A::Array{T}, x, i0::Integer, i1::Integer, i2::Integer, i3::Integer, i4::Integer, i5::Integer) = - arrayset(A, convert(T,x), int(i0), int(i1), int(i2), int(i3), int(i4), int(i5)) -assign{T}(A::Array{T}, x, i0::Integer, i1::Integer, i2::Integer, i3::Integer, i4::Integer, i5::Integer, I::Int...) = - arrayset(A, convert(T,x), int(i0), int(i1), int(i2), int(i3), int(i4), int(i5), I...) - -function assign{T<:Integer}(A::Array, x, I::AbstractVector{T}) +getindex(A::Matrix, I::Real, J::AbstractVector{Bool}) = A[I,find(J)] +getindex(A::Matrix, I::AbstractVector{Bool}, J::Real) = A[find(I),J] +getindex(A::Matrix, I::AbstractVector{Bool}, J::AbstractVector{Bool}) = A[find(I),find(J)] +getindex{T<:Real}(A::Matrix, I::AbstractVector{T}, J::AbstractVector{Bool}) = A[I,find(J)] +getindex{T<:Real}(A::Matrix, I::AbstractVector{Bool}, J::AbstractVector{T}) = A[find(I),J] + +## Indexing: setindex! ## +setindex!{T}(A::Array{T,0}, x) = arrayset(A, convert(T,x), 1) + +setindex!(A::Array{Any}, x::ANY, i::Real) = arrayset(A, x, to_index(i)) + +setindex!{T}(A::Array{T}, x, i0::Real) = arrayset(A, convert(T,x), to_index(i0)) +setindex!{T}(A::Array{T}, x, i0::Real, i1::Real) = + arrayset(A, convert(T,x), to_index(i0), to_index(i1)) +setindex!{T}(A::Array{T}, x, i0::Real, i1::Real, i2::Real) = + arrayset(A, convert(T,x), to_index(i0), to_index(i1), to_index(i2)) +setindex!{T}(A::Array{T}, x, i0::Real, i1::Real, i2::Real, i3::Real) = + arrayset(A, convert(T,x), to_index(i0), to_index(i1), to_index(i2), to_index(i3)) +setindex!{T}(A::Array{T}, x, i0::Real, i1::Real, i2::Real, i3::Real, i4::Real) = + arrayset(A, convert(T,x), to_index(i0), to_index(i1), to_index(i2), to_index(i3), to_index(i4)) +setindex!{T}(A::Array{T}, x, i0::Real, i1::Real, i2::Real, i3::Real, i4::Real, i5::Real) = + arrayset(A, convert(T,x), to_index(i0), to_index(i1), to_index(i2), to_index(i3), to_index(i4), to_index(i5)) +setindex!{T}(A::Array{T}, x, i0::Real, i1::Real, i2::Real, i3::Real, i4::Real, i5::Real, I::Int...) = + arrayset(A, convert(T,x), to_index(i0), to_index(i1), to_index(i2), to_index(i3), to_index(i4), to_index(i5), I...) + +function setindex!{T<:Real}(A::Array, x, I::AbstractVector{T}) for i in I A[i] = x end return A end -function assign{T}(A::Array{T}, X::Array{T}, I::Range1{Int}) +function setindex!{T}(A::Array{T}, X::Array{T}, I::Range1{Int}) if length(X) != length(I); error("argument dimensions must match"); end - copy_to(A, first(I), X, 1, length(I)) + copy!(A, first(I), X, 1, length(I)) return A end -function assign{T<:Integer}(A::Array, X::AbstractArray, I::AbstractVector{T}) +function setindex!{T<:Real}(A::Array, X::AbstractArray, I::AbstractVector{T}) if length(X) != length(I); error("argument dimensions must match"); end count = 1 for i in I @@ -475,7 +415,8 @@ function assign{T<:Integer}(A::Array, X::AbstractArray, I::AbstractVector{T}) return A end -function assign{T<:Integer}(A::Array, x, i::Integer, J::AbstractVector{T}) +function setindex!{T<:Real}(A::Array, x, i::Real, J::AbstractVector{T}) + i = to_index(i) check_bounds(A, i, J) m = size(A, 1) if !isa(x,AbstractArray) @@ -494,7 +435,8 @@ function assign{T<:Integer}(A::Array, x, i::Integer, J::AbstractVector{T}) return A end -function assign{T<:Integer}(A::Array, x, I::AbstractVector{T}, j::Integer) +function setindex!{T<:Real}(A::Array, x, I::AbstractVector{T}, j::Real) + j = to_index(j) check_bounds(A, I, j) m = size(A, 1) offset = (j-1)*m @@ -515,14 +457,15 @@ function assign{T<:Integer}(A::Array, x, I::AbstractVector{T}, j::Integer) return A end -function assign{T}(A::Array{T}, X::Array{T}, I::Range1{Int}, j::Integer) +function setindex!{T}(A::Array{T}, X::Array{T}, I::Range1{Int}, j::Real) + j = to_index(j) check_bounds(A, I, j) if length(X) != length(I); error("argument dimensions must match"); end - copy_to_unsafe(A, first(I) + (j-1)*size(A,1), X, 1, length(I)) + copy_unsafe!(A, first(I) + (j-1)*size(A,1), X, 1, length(I)) return A end -function assign{T}(A::Array{T}, X::Array{T}, I::Range1{Int}, J::Range1{Int}) +function setindex!{T}(A::Array{T}, X::Array{T}, I::Range1{Int}, J::Range1{Int}) check_bounds(A, I, J) nel = length(I)*length(J) if length(X) != nel || @@ -530,18 +473,18 @@ function assign{T}(A::Array{T}, X::Array{T}, I::Range1{Int}, J::Range1{Int}) error("argument dimensions must match") end if length(I) == size(A,1) - copy_to_unsafe(A, first(I) + (first(J)-1)*size(A,1), X, 1, size(A,1)*length(J)) + copy_unsafe!(A, first(I) + (first(J)-1)*size(A,1), X, 1, size(A,1)*length(J)) else refoffset = 1 for j = J - copy_to_unsafe(A, first(I) + (j-1)*size(A,1), X, refoffset, length(I)) + copy_unsafe!(A, first(I) + (j-1)*size(A,1), X, refoffset, length(I)) refoffset += length(I) end end return A end -function assign{T}(A::Array{T}, X::Array{T}, I::Range1{Int}, J::AbstractVector{Int}) +function setindex!{T}(A::Array{T}, X::Array{T}, I::Range1{Int}, J::AbstractVector{Int}) check_bounds(A, I, J) nel = length(I)*length(J) if length(X) != nel || @@ -550,13 +493,13 @@ function assign{T}(A::Array{T}, X::Array{T}, I::Range1{Int}, J::AbstractVector{I end refoffset = 1 for j = J - copy_to_unsafe(A, first(I) + (j-1)*size(A,1), X, refoffset, length(I)) + copy_unsafe!(A, first(I) + (j-1)*size(A,1), X, refoffset, length(I)) refoffset += length(I) end return A end -function assign{T<:Integer}(A::Array, x, I::AbstractVector{T}, J::AbstractVector{T}) +function setindex!{T<:Real}(A::Array, x, I::AbstractVector{T}, J::AbstractVector{T}) check_bounds(A, I, J) m = size(A, 1) if !isa(x,AbstractArray) @@ -586,10 +529,9 @@ function assign{T<:Integer}(A::Array, x, I::AbstractVector{T}, J::AbstractVector end let assign_cache = nothing, assign_scalar_cache = nothing -global assign -function assign(A::Array, x, I0::Indices, I::Indices...) - check_bounds(A, I0, I...) - I0 = indices(I0) +global setindex! +function setindex!(A::Array, x, I::Union(Real,AbstractArray)...) + check_bounds(A, I...) I = indices(I) if !isa(x,AbstractArray) if is(assign_scalar_cache,nothing) @@ -598,7 +540,7 @@ function assign(A::Array, x, I0::Indices, I::Indices...) gen_array_index_map(assign_scalar_cache, storeind -> quote A[$storeind] = x end, - tuple(I0, I...), + I, (:A, :x), A, x) else @@ -606,7 +548,7 @@ function assign(A::Array, x, I0::Indices, I::Indices...) assign_cache = Dict() end X = x - nel = length(I0) + nel = 1 for idx in I nel *= length(idx) end @@ -614,11 +556,8 @@ function assign(A::Array, x, I0::Indices, I::Indices...) error("argument dimensions must match") end if ndims(X) > 1 - if size(X,1) != length(I0) - error("argument dimensions must match") - end for i = 1:length(I) - if size(X,i+1) != length(I[i]) + if size(X,i) != length(I[i]) error("argument dimensions must match") end end @@ -630,7 +569,7 @@ function assign(A::Array, x, I0::Indices, I::Indices...) A[$storeind] = X[refind] refind += 1 end, - tuple(I0, I...), + I, (:A, :X, :refind), A, X, 1) end @@ -640,9 +579,9 @@ end # logical indexing -function _jl_assign_bool_scalar_1d(A::Array, x, I::AbstractArray{Bool}) +function assign_bool_scalar_1d(A::Array, x, I::AbstractArray{Bool}) check_bounds(A, I) - for i = 1:numel(I) + for i = 1:length(I) if I[i] A[i] = x end @@ -650,10 +589,10 @@ function _jl_assign_bool_scalar_1d(A::Array, x, I::AbstractArray{Bool}) A end -function _jl_assign_bool_vector_1d(A::Array, X::AbstractArray, I::AbstractArray{Bool}) +function assign_bool_vector_1d(A::Array, X::AbstractArray, I::AbstractArray{Bool}) check_bounds(A, I) c = 1 - for i = 1:numel(I) + for i = 1:length(I) if I[i] A[i] = X[c] c += 1 @@ -662,24 +601,45 @@ function _jl_assign_bool_vector_1d(A::Array, X::AbstractArray, I::AbstractArray{ A end -assign(A::Array, X::AbstractArray, I::AbstractVector{Bool}) = _jl_assign_bool_vector_1d(A, X, I) -assign(A::Array, X::AbstractArray, I::AbstractArray{Bool}) = _jl_assign_bool_vector_1d(A, X, I) -assign(A::Array, x, I::AbstractVector{Bool}) = _jl_assign_bool_scalar_1d(A, x, I) -assign(A::Array, x, I::AbstractArray{Bool}) = _jl_assign_bool_scalar_1d(A, x, I) +setindex!(A::Array, X::AbstractArray, I::AbstractVector{Bool}) = assign_bool_vector_1d(A, X, I) +setindex!(A::Array, X::AbstractArray, I::AbstractArray{Bool}) = assign_bool_vector_1d(A, X, I) +setindex!(A::Array, x, I::AbstractVector{Bool}) = assign_bool_scalar_1d(A, x, I) +setindex!(A::Array, x, I::AbstractArray{Bool}) = assign_bool_scalar_1d(A, x, I) -assign(A::Array, x, I::Integer, J::AbstractVector{Bool}) = assign(A, x, I,find(J)) +setindex!(A::Array, x, I::Real, J::AbstractVector{Bool}) = setindex!(A, x, I,find(J)) +setindex!(A::Array, x, I::AbstractVector{Bool}, J::Real) = setindex!(A,x,find(I),J) +setindex!(A::Array, x, I::AbstractVector{Bool}, J::AbstractVector{Bool}) = setindex!(A, x, find(I),find(J)) +setindex!{T<:Real}(A::Array, x, I::AbstractVector{T}, J::AbstractVector{Bool}) = setindex!(A, x, I,find(J)) +setindex!{T<:Real}(A::Array, x, I::AbstractVector{Bool}, J::AbstractVector{T}) = setindex!(A, x, find(I),J) -assign(A::Array, x, I::AbstractVector{Bool}, J::Integer) = assign(A,x,find(I),J) +# get (getindex with a default value) -assign(A::Array, x, I::AbstractVector{Bool}, J::AbstractVector{Bool}) = assign(A, x, find(I),find(J)) +get{T}(A::Array, i::Integer, default::T) = in_bounds(length(A), i) ? A[i] : default +get{T}(A::Array, I::(), default::T) = Array(T, 0) +get{T}(A::Array, I::Dims, default::T) = in_bounds(size(A), I...) ? A[I...] : default -assign{T<:Integer}(A::Array, x, I::AbstractVector{T}, J::AbstractVector{Bool}) = assign(A, x, I,find(J)) +function get{T}(X::Array{T}, A::Array, I::Union(Ranges, Vector{Int}), default::T) + ind = findin(I, 1:length(A)) + X[ind] = A[I[ind]] + X[1:first(ind)-1] = default + X[last(ind)+1:length(X)] = default + X +end +get{T}(A::Array, I::Ranges, default::T) = get(Array(T, length(I)), A, I, default) + +RangeVecIntList = Union((Union(Ranges, Vector{Int})...), Vector{Range1{Int}}, Vector{Range{Int}}, Vector{Vector{Int}}) -assign{T<:Integer}(A::Array, x, I::AbstractVector{Bool}, J::AbstractVector{T}) = assign(A, x, find(I),J) +function get{T}(X::Array{T}, A::Array, I::RangeVecIntList, default::T) + fill!(X, default) + dst, src = indcopy(size(A), I) + X[dst...] = A[src...] + X +end +get{T}(A::Array, I::RangeVecIntList, default::T) = get(Array(T, map(length, I)...), A, I, default) ## Dequeue functionality ## -function push{T}(a::Array{T,1}, item) +function push!{T}(a::Array{T,1}, item) if is(T,None) error("[] cannot grow. Instead, initialize the array with \"T[]\".") end @@ -690,7 +650,7 @@ function push{T}(a::Array{T,1}, item) return a end -function push(a::Array{Any,1}, item::ANY) +function push!(a::Array{Any,1}, item::ANY) ccall(:jl_array_grow_end, Void, (Any, Uint), a, 1) arrayset(a, item, length(a)) return a @@ -706,28 +666,44 @@ function append!{T}(a::Array{T,1}, items::Array{T,1}) return a end -function grow(a::Vector, n::Integer) - if n > 0 - ccall(:jl_array_grow_end, Void, (Any, Uint), a, n) +function prepend!{T}(a::Array{T,1}, items::Array{T,1}) + if is(T,None) + error("[] cannot grow. Instead, initialize the array with \"T[]\".") + end + n = length(items) + ccall(:jl_array_grow_beg, Void, (Any, Uint), a, n) + a[1:n] = items + return a +end + +function resize!(a::Vector, nl::Integer) + l = length(a) + if nl > l + ccall(:jl_array_grow_end, Void, (Any, Uint), a, nl-l) else - if n < -length(a) + if nl < 0 throw(BoundsError()) end - ccall(:jl_array_del_end, Void, (Any, Uint), a, -n) + ccall(:jl_array_del_end, Void, (Any, Uint), a, l-nl) end return a end -function pop(a::Vector) +function sizehint(a::Vector, sz::Integer) + ccall(:jl_array_sizehint, Void, (Any, Uint), a, sz) + a +end + +function pop!(a::Vector) if isempty(a) - error("pop: array is empty") + error("pop!: array is empty") end item = a[end] ccall(:jl_array_del_end, Void, (Any, Uint), a, 1) return item end -function enqueue{T}(a::Array{T,1}, item) +function unshift!{T}(a::Array{T,1}, item) if is(T,None) error("[] cannot grow. Instead, initialize the array with \"T[]\".") end @@ -736,18 +712,17 @@ function enqueue{T}(a::Array{T,1}, item) a[1] = item return a end -const unshift = enqueue -function shift(a::Vector) +function shift!(a::Vector) if isempty(a) - error("shift: array is empty") + error("shift!: array is empty") end item = a[1] ccall(:jl_array_del_beg, Void, (Any, Uint), a, 1) return item end -function insert{T}(a::Array{T,1}, i::Integer, item) +function insert!{T}(a::Array{T,1}, i::Integer, item) if i < 1 throw(BoundsError()) end @@ -769,11 +744,12 @@ function insert{T}(a::Array{T,1}, i::Integer, item) a[i] = item end -function del(a::Vector, i::Integer) +function delete!(a::Vector, i::Integer) n = length(a) if !(1 <= i <= n) throw(BoundsError()) end + v = a[i] if i < div(n,2) for k = i:-1:2 a[k] = a[k-1] @@ -785,10 +761,10 @@ function del(a::Vector, i::Integer) end ccall(:jl_array_del_end, Void, (Any, Uint), a, 1) end - return a + return v end -function del{T<:Integer}(a::Vector, r::Range1{T}) +function delete!{T<:Integer}(a::Vector, r::Range1{T}) n = length(a) f = first(r) l = last(r) @@ -796,8 +772,9 @@ function del{T<:Integer}(a::Vector, r::Range1{T}) throw(BoundsError()) end if l < f - return a + return T[] end + v = a[r] d = l-f+1 if f-1 < n-l for k = l:-1:1+d @@ -810,18 +787,18 @@ function del{T<:Integer}(a::Vector, r::Range1{T}) end ccall(:jl_array_del_end, Void, (Any, Uint), a, d) end - return a + return v end -function del_all(a::Vector) +function empty!(a::Vector) ccall(:jl_array_del_end, Void, (Any, Uint), a, length(a)) return a end ## Unary operators ## -function conj!{T<:Number}(A::StridedArray{T}) - for i=1:numel(A) +function conj!{T<:Number}(A::AbstractArray{T}) + for i=1:length(A) A[i] = conj(A[i]) end return A @@ -829,9 +806,9 @@ end for f in (:-, :~, :conj, :sign) @eval begin - function ($f)(A::StridedArray) + function ($f)(A::AbstractArray) F = similar(A) - for i=1:numel(A) + for i=1:length(A) F[i] = ($f)(A[i]) end return F @@ -839,12 +816,14 @@ for f in (:-, :~, :conj, :sign) end end +(-)(A::StridedArray{Bool}) = reshape([ -A[i] for i=1:length(A) ], size(A)) + for f in (:real, :imag) @eval begin - function ($f){T}(A::StridedArray{T}) + function ($f){T}(A::AbstractArray{T}) S = typeof(($f)(zero(T))) F = similar(A, S) - for i=1:numel(A) + for i=1:length(A) F[i] = ($f)(A[i]) end return F @@ -852,9 +831,9 @@ for f in (:real, :imag) end end -function !(A::StridedArray{Bool}) +function !(A::AbstractArray{Bool}) F = similar(A) - for i=1:numel(A) + for i=1:length(A) F[i] = !A[i] end return F @@ -862,82 +841,101 @@ end ## Binary arithmetic operators ## -# ^ is difficult, since negative exponents give a different type - -./(x::Array, y::Array ) = reshape( [ x[i] ./ y[i] for i=1:numel(x) ], size(x) ) -./(x::Number,y::Array ) = reshape( [ x ./ y[i] for i=1:numel(y) ], size(y) ) -./(x::Array, y::Number) = reshape( [ x[i] ./ y for i=1:numel(x) ], size(x) ) - -.^(x::Array, y::Array ) = reshape( [ x[i] ^ y[i] for i=1:numel(x) ], size(x) ) -.^(x::Number,y::Array ) = reshape( [ x ^ y[i] for i=1:numel(y) ], size(y) ) -.^(x::Array, y::Number) = reshape( [ x[i] ^ y for i=1:numel(x) ], size(x) ) +promote_array_type{Scalar, Arry}(::Type{Scalar}, ::Type{Arry}) = promote_type(Scalar, Arry) +promote_array_type{S<:Real, A<:Real}(::Type{S}, ::Type{A}) = A +promote_array_type{S<:Complex, A<:Complex}(::Type{S}, ::Type{A}) = A +promote_array_type{S<:Integer, A<:Integer}(::Type{S}, ::Type{A}) = A +promote_array_type{S<:Real, A<:Integer}(::Type{S}, ::Type{A}) = promote_type(S, A) +promote_array_type{S<:Integer}(::Type{S}, ::Type{Bool}) = S + +./{T<:Integer,S<:Integer}(x::StridedArray{T}, y::StridedArray{S}) = + reshape([ x[i] ./ y[i] for i=1:length(x) ], promote_shape(size(x),size(y))) +./{T<:Integer}(x::Integer, y::StridedArray{T}) = + reshape([ x ./ y[i] for i=1:length(y) ], size(y)) +./{T<:Integer}(x::StridedArray{T}, y::Integer) = + reshape([ x[i] ./ y for i=1:length(x) ], size(x)) + +./{T<:Integer,S<:Integer}(x::StridedArray{ComplexPair{T}}, y::StridedArray{S}) = + reshape([ x[i] ./ y[i] for i=1:length(x) ], promote_shape(size(x),size(y))) +./{T<:Integer,S<:Integer}(x::StridedArray{T}, y::StridedArray{ComplexPair{S}}) = + reshape([ x[i] ./ y[i] for i=1:length(x) ], promote_shape(size(x),size(y))) +./{T<:Integer,S<:Integer}(x::StridedArray{ComplexPair{T}}, y::StridedArray{ComplexPair{S}}) = + reshape([ x[i] ./ y[i] for i=1:length(x) ], promote_shape(size(x),size(y))) +./{T<:Integer}(x::Integer, y::StridedArray{ComplexPair{T}}) = + reshape([ x ./ y[i] for i=1:length(y) ], size(y)) +./{T<:Integer}(x::StridedArray{ComplexPair{T}}, y::Integer) = + reshape([ x[i] ./ y for i=1:length(x) ], size(x)) +./{S<:Integer,T<:Integer}(x::ComplexPair{S}, y::StridedArray{T}) = + reshape([ x ./ y[i] for i=1:length(y) ], size(y)) +./{S<:Integer,T<:Integer}(x::StridedArray{S}, y::ComplexPair{T}) = + reshape([ x[i] ./ y for i=1:length(x) ], size(x)) -function .^{S<:Integer,T<:Integer}(A::Array{S}, B::Array{T}) - F = Array(Float64, promote_shape(size(A), size(B))) - for i=1:numel(A) - F[i] = float64(A[i])^float64(B[i]) - end - return F -end - -function .^{T<:Integer}(A::Integer, B::Array{T}) - F = similar(B, Float64) - for i=1:numel(B) - F[i] = float64(A)^float64(B[i]) - end - return F -end - -function _jl_power_array_int_body{T}(F::Array{T}, A, B) - for i=1:numel(A) - F[i] = A[i]^convert(T,B) - end - return F -end +# ^ is difficult, since negative exponents give a different type -function .^{T<:Integer}(A::Array{T}, B::Integer) - F = similar(A, B < 0 ? Float64 : promote_type(T,typeof(B))) - _jl_power_array_int_body(F, A, B) -end +.^(x::StridedArray, y::StridedArray) = + reshape([ x[i] ^ y[i] for i=1:length(x) ], promote_shape(size(x),size(y))) +.^(x::Number, y::StridedArray) = + reshape([ x ^ y[i] for i=1:length(y) ], size(y)) +.^(x::StridedArray, y::Number ) = + reshape([ x[i] ^ y for i=1:length(x) ], size(x)) -for f in (:+, :-, :.*, :div, :mod, :&, :|, :$) +for f in (:+, :-, :.*, :./, :div, :mod, :&, :|, :$) @eval begin - function ($f){S,T}(A::AbstractArray{S}, B::AbstractArray{T}) + function ($f){S,T}(A::StridedArray{S}, B::StridedArray{T}) F = Array(promote_type(S,T), promote_shape(size(A),size(B))) - for i=1:numel(A) + for i=1:length(A) F[i] = ($f)(A[i], B[i]) end return F end - function ($f){T}(A::Number, B::AbstractArray{T}) - F = similar(B, promote_type(typeof(A),T)) - for i=1:numel(B) + function ($f){T}(A::Number, B::StridedArray{T}) + F = similar(B, promote_array_type(typeof(A),T)) + for i=1:length(B) F[i] = ($f)(A, B[i]) end return F end - function ($f){T}(A::AbstractArray{T}, B::Number) - F = similar(A, promote_type(T,typeof(B))) - for i=1:numel(A) + function ($f){T}(A::StridedArray{T}, B::Number) + F = similar(A, promote_array_type(typeof(B),T)) + for i=1:length(A) F[i] = ($f)(A[i], B) end return F end + # interaction with Ranges + function ($f){S,T<:Real}(A::StridedArray{S}, B::Ranges{T}) + F = Array(promote_type(S,T), promote_shape(size(A),size(B))) + i = 1 + for b in B + F[i] = ($f)(A[i], b) + i += 1 + end + return F + end + function ($f){S<:Real,T}(A::Ranges{S}, B::StridedArray{T}) + F = Array(promote_type(S,T), promote_shape(size(A),size(B))) + i = 1 + for a in A + F[i] = ($f)(a, B[i]) + i += 1 + end + return F + end end end # functions that should give an Int result for Bool arrays -for f in (:+, :-, :div) +for f in (:+, :-) @eval begin - function ($f)(x::Bool, y::Array{Bool}) - reshape([ ($f)(x, y[i]) for i=1:numel(y) ], size(y)) + function ($f)(x::Bool, y::StridedArray{Bool}) + reshape([ ($f)(x, y[i]) for i=1:length(y) ], size(y)) end - function ($f)(x::Array{Bool}, y::Bool) - reshape([ ($f)(x[i], y) for i=1:numel(x) ], size(x)) + function ($f)(x::StridedArray{Bool}, y::Bool) + reshape([ ($f)(x[i], y) for i=1:length(x) ], size(x)) end - function ($f)(x::Array{Bool}, y::Array{Bool}) + function ($f)(x::StridedArray{Bool}, y::StridedArray{Bool}) shp = promote_shape(size(x),size(y)) - reshape([ ($f)(x[i], y[i]) for i=1:numel(x) ], shp) + reshape([ ($f)(x[i], y[i]) for i=1:length(x) ], shp) end end end @@ -946,7 +944,7 @@ end function complex{S<:Real,T<:Real}(A::Array{S}, B::Array{T}) F = similar(A, typeof(complex(zero(S),zero(T)))) - for i=1:numel(A) + for i=1:length(A) F[i] = complex(A[i], B[i]) end return F @@ -954,7 +952,7 @@ end function complex{T<:Real}(A::Real, B::Array{T}) F = similar(B, typeof(complex(A,zero(T)))) - for i=1:numel(B) + for i=1:length(B) F[i] = complex(A, B[i]) end return F @@ -962,7 +960,7 @@ end function complex{T<:Real}(A::Array{T}, B::Real) F = similar(A, typeof(complex(zero(T),B))) - for i=1:numel(A) + for i=1:length(A) F[i] = complex(A[i], B) end return F @@ -983,7 +981,7 @@ function slicedim(A::Array, d::Integer, i::Integer) d_out = tuple(leading..., 1, d_in[(d+1):end]...) M = prod(leading) - N = numel(A) + N = length(A) stride = M * d_in[d] B = similar(A, d_out) @@ -1032,7 +1030,7 @@ function flipdim{T}(A::Array{T}, d::Integer) d_in = size(A) leading = d_in[1:(d-1)] M = prod(leading) - N = numel(A) + N = length(A) stride = M * sd if M==1 @@ -1043,13 +1041,13 @@ function flipdim{T}(A::Array{T}, d::Integer) end end else - if isa(T,BitsKind) && M>200 + if isbits(T) && M>200 for i = 1:sd ri = sd+1-i for j=0:stride:(N-stride) offs = j + 1 + (i-1)*M boffs = j + 1 + (ri-1)*M - copy_to(B, boffs, A, offs, M) + copy!(B, boffs, A, offs, M) end end else @@ -1068,7 +1066,7 @@ function flipdim{T}(A::Array{T}, d::Integer) return B end -function rotl90(A::StridedMatrix) +function rotl90(A::AbstractMatrix) m,n = size(A) B = similar(A,(n,m)) for i=1:m, j=1:n @@ -1076,7 +1074,7 @@ function rotl90(A::StridedMatrix) end return B end -function rotr90(A::StridedMatrix) +function rotr90(A::AbstractMatrix) m,n = size(A) B = similar(A,(n,m)) for i=1:m, j=1:n @@ -1084,7 +1082,7 @@ function rotr90(A::StridedMatrix) end return B end -function rot180(A::StridedMatrix) +function rot180(A::AbstractMatrix) m,n = size(A) B = similar(A) for i=1:m, j=1:n @@ -1100,10 +1098,9 @@ function rotl90(A::AbstractMatrix, k::Integer) end rotr90(A::AbstractMatrix, k::Integer) = rotl90(A,-k) rot180(A::AbstractMatrix, k::Integer) = mod(k, 2) == 1 ? rot180(A) : copy(A) -const rot90 = rotl90 reverse(v::StridedVector) = (n=length(v); [ v[n-i+1] for i=1:n ]) -function reverse!(v::StridedVector) +function reverse!(v::AbstractVector) n = length(v) r = n for i=1:div(n,2) @@ -1121,7 +1118,7 @@ function vcat{T}(arrays::Array{T,1}...) arr = Array(T, n) ptr = pointer(arr) offset = 0 - if isa(T,BitsKind) + if isbits(T) elsz = sizeof(T) else elsz = div(WORD_SIZE,8) @@ -1137,59 +1134,54 @@ end ## find ## -function nnz(a::StridedArray) - n = 0 - for i = 1:numel(a) - n += bool(a[i]) ? 1 : 0 - end - return n -end - -# returns the index of the first non-zero element, or 0 if all zeros -function findfirst(A::StridedArray) - for i = 1:length(A) +# returns the index of the next non-zero element, or 0 if all zeros +function findnext(A, start::Integer) + for i = start:length(A) if A[i] != 0 return i end end return 0 end +findfirst(A) = findnext(A,1) -# returns the index of the first matching element -function findfirst(A::StridedArray, v) - for i = 1:length(A) +# returns the index of the next matching element +function findnext(A, v, start::Integer) + for i = start:length(A) if A[i] == v return i end end return 0 end +findfirst(A,v) = findnext(A,v,1) -# returns the index of the first element for which the function returns true -function findfirst(testf::Function, A::StridedArray) - for i = 1:length(A) +# returns the index of the next element for which the function returns true +function findnext(testf::Function, A, start::Integer) + for i = start:length(A) if testf(A[i]) return i end end return 0 end +findfirst(testf::Function, A) = findnext(testf, A, 1) -function find(testf::Function, A::StridedArray) +function find(testf::Function, A::AbstractArray) # use a dynamic-length array to store the indexes, then copy to a non-padded # array for the return tmpI = Array(Int, 0) for i = 1:length(A) if testf(A[i]) - push(tmpI, i) + push!(tmpI, i) end end I = Array(Int, length(tmpI)) - copy_to(I, tmpI) + copy!(I, tmpI) I end -function find(A::StridedArray) +function find(A::AbstractArray) nnzA = nnz(A) I = Array(Int, nnzA) count = 1 @@ -1202,9 +1194,12 @@ function find(A::StridedArray) return I end -findn(A::StridedVector) = find(A) +find(x::Number) = x == 0 ? Array(Int,0) : [1] +find(testf::Function, x) = find(testf(x)) -function findn(A::StridedMatrix) +findn(A::AbstractVector) = find(A) + +function findn(A::AbstractMatrix) nnzA = nnz(A) I = Array(Int, nnzA) J = Array(Int, nnzA) @@ -1232,7 +1227,7 @@ function findn_one(ivars) end global findn -function findn{T}(A::StridedArray{T}) +function findn{T}(A::AbstractArray{T}) ndimsA = ndims(A) nnzA = nnz(A) I = ntuple(ndimsA, x->Array(Int, nnzA)) @@ -1250,7 +1245,7 @@ function findn{T}(A::StridedArray{T}) end end -function findn_nzs{T}(A::StridedMatrix{T}) +function findnz{T}(A::AbstractMatrix{T}) nnzA = nnz(A) I = zeros(Int, nnzA) J = zeros(Int, nnzA) @@ -1270,7 +1265,7 @@ function findn_nzs{T}(A::StridedMatrix{T}) return (I, J, NZs) end -function nonzeros{T}(A::StridedArray{T}) +function nonzeros{T}(A::AbstractArray{T}) nnzA = nnz(A) V = Array(T, nnzA) count = 1 @@ -1286,10 +1281,15 @@ function nonzeros{T}(A::StridedArray{T}) return V end -function findmax(a::Array) - m = typemin(eltype(a)) - mi = 0 - for i=1:length(a) +nonzeros(x::Number) = x == 0 ? Array(typeof(x),0) : [x] + +function findmax(a) + if isempty(a) + error("findmax: array is empty") + end + m = a[1] + mi = 1 + for i=2:length(a) if a[i] > m m = a[i] mi = i @@ -1298,10 +1298,13 @@ function findmax(a::Array) return (m, mi) end -function findmin(a::Array) - m = typemax(eltype(a)) - mi = 0 - for i=1:length(a) +function findmin(a) + if isempty(a) + error("findmin: array is empty") + end + m = a[1] + mi = 1 + for i=2:length(a) if a[i] < m m = a[i] mi = i @@ -1309,22 +1312,63 @@ function findmin(a::Array) end return (m, mi) end -indmax(a::Array) = findmax(a)[2] -indmin(a::Array) = findmin(a)[2] -## Reductions ## +indmax(a) = findmax(a)[2] +indmin(a) = findmin(a)[2] + +# findin (the index of intersection) +function findin(a, b::Range1) + ind = Array(Int, 0) + f = first(b) + l = last(b) + for i = 1:length(a) + if f <= a[i] <= l + push!(ind, i) + end + end + ind +end + +function findin(a, b) + ind = Array(Int, 0) + bset = Set(b...) + for i = 1:length(a) + if has(bset, a[i]) + push!(ind, i) + end + end + ind +end + +# Copying subregions +function indcopy(sz::Dims, I::RangeVecIntList) + n = length(I) + dst = Array(AbstractVector{Int}, n) + src = Array(AbstractVector{Int}, n) + for dim = 1:(n-1) + tmp = findin(I[dim], 1:sz[dim]) + dst[dim] = tmp + src[dim] = I[dim][tmp] + end + s = sz[n] + for i = n+1:length(sz) + s *= sz[i] + end + tmp = findin(I[n], 1:s) + dst[n] = tmp + src[n] = I[n][tmp] + dst, src +end -reduced_dims(A, region) = ntuple(ndims(A), i->(contains(region, i) ? 1 : size(A,i))) -areduce(f::Function, A, region::Dimspec, v0) = - areduce(f, A, region, v0, similar(A, reduced_dims(A, region))) +## Reductions ## # TODO: # - find out why inner loop with dimsA[i] instead of size(A,i) is way too slow -let areduce_cache = nothing +let reducedim_cache = nothing # generate the body of the N-d loop to compute a reduction -function gen_areduce_func(n, f) +function gen_reducedim_func(n, f) ivars = { symbol(string("i",i)) for i=1:n } # limits and vars for reduction loop lo = { symbol(string("lo",i)) for i=1:n } @@ -1359,12 +1403,12 @@ function gen_areduce_func(n, f) end end -global areduce -function areduce(f::Function, A, region::Dimspec, v0, R) +global reducedim +function reducedim(f::Function, A, region, v0, R) ndimsA = ndims(A) - if is(areduce_cache,nothing) - areduce_cache = Dict() + if is(reducedim_cache,nothing) + reducedim_cache = Dict() end key = ndimsA @@ -1379,12 +1423,12 @@ function areduce(f::Function, A, region::Dimspec, v0, R) key = (fname, ndimsA) end - if !has(areduce_cache,key) - fexpr = gen_areduce_func(ndimsA, fname) + if !has(reducedim_cache,key) + fexpr = gen_reducedim_func(ndimsA, fname) func = eval(fexpr) - areduce_cache[key] = func + reducedim_cache[key] = func else - func = areduce_cache[key] + func = reducedim_cache[key] end func(f, A, region, R, v0) @@ -1393,260 +1437,37 @@ function areduce(f::Function, A, region::Dimspec, v0, R) end end -max{T}(A::AbstractArray{T}, b::(), region::Dimspec) = areduce(max,A,region,typemin(T)) -min{T}(A::AbstractArray{T}, b::(), region::Dimspec) = areduce(min,A,region,typemax(T)) -sum{T}(A::AbstractArray{T}, region::Dimspec) = areduce(+,A,region,zero(T)) -prod{T}(A::AbstractArray{T}, region::Dimspec) = areduce(*,A,region,one(T)) - -all(A::AbstractArray{Bool}, region::Dimspec) = areduce(all,A,region,true) -any(A::AbstractArray{Bool}, region::Dimspec) = areduce(any,A,region,false) -sum(A::AbstractArray{Bool}, region::Dimspec) = areduce(+,A,region,0,similar(A,Int,reduced_dims(A,region))) -sum(A::AbstractArray{Bool}) = count(A) -sum(A::StridedArray{Bool}) = count(A) -prod(A::AbstractArray{Bool}) = - error("use all() instead of prod() for boolean arrays") -prod(A::AbstractArray{Bool}, region::Dimspec) = - error("use all() instead of prod() for boolean arrays") +## Filter ## -function sum{T}(A::StridedArray{T}) - if isempty(A) - return zero(T) - end - v = A[1] - for i=2:numel(A) - v += A[i] - end - v -end +# given a function returning a boolean and an array, return matching elements +filter(f::Function, As::AbstractArray) = As[map(f, As)::AbstractArray{Bool}] -function sum_kbn{T<:FloatingPoint}(A::StridedArray{T}) - n = length(A) - if (n == 0) - return zero(T) - end - s = A[1] - c = zero(T) - for i in 2:n - Ai = A[i] - t = s + Ai - if abs(s) >= abs(Ai) - c += ((s-t) + Ai) - else - c += ((Ai-t) + s) +function filter!(f::Function, a::Vector) + insrt = 1 + for curr = 1:length(a) + if f(a[curr]) + a[insrt] = a[curr] + insrt += 1 end - s = t end - - s + c + delete!(a, insrt:length(a)) + return a end -# Uses K-B-N summation -function cumsum_kbn{T<:FloatingPoint}(v::StridedVector{T}) - n = length(v) - r = similar(v, n) - if n == 0; return r; end - - s = r[1] = v[1] - c = zero(T) - for i=2:n - vi = v[i] - t = s + vi - if abs(s) >= abs(vi) - c += ((s-t) + vi) - else - c += ((vi-t) + s) +function filter(f::Function, a::Vector) + r = Array(eltype(a), 0) + for i = 1:length(a) + if f(a[i]) + push!(r, a[i]) end - s = t - r[i] = s+c end return r end -# Uses K-B-N summation -function cumsum_kbn{T<:FloatingPoint}(A::StridedArray{T}, axis::Integer) - dimsA = size(A) - ndimsA = ndims(A) - axis_size = dimsA[axis] - axis_stride = 1 - for i = 1:(axis-1) - axis_stride *= size(A,i) - end - - if axis_size <= 1 - return A - end - - B = similar(A) - C = similar(A) - - for i = 1:length(A) - if div(i-1, axis_stride) % axis_size == 0 - B[i] = A[i] - C[i] = zero(T) - else - s = B[i-axis_stride] - Ai = A[i] - B[i] = t = s + Ai - if abs(s) >= abs(Ai) - C[i] = C[i-axis_stride] + ((s-t) + Ai) - else - C[i] = C[i-axis_stride] + ((Ai-t) + s) - end - end - end - - return B + C -end - -function prod{T}(A::StridedArray{T}) - if isempty(A) - return one(T) - end - v = A[1] - for i=2:numel(A) - v *= A[i] - end - v -end - -function min{T<:Integer}(A::StridedArray{T}) - v = typemax(T) - for i=1:numel(A) - x = A[i] - if x < v - v = x - end - end - v -end - -function max{T<:Integer}(A::StridedArray{T}) - v = typemin(T) - for i=1:numel(A) - x = A[i] - if x > v - v = x - end - end - v -end - -## map over arrays ## - -## along an axis -function amap(f::Function, A::StridedArray, axis::Integer) - dimsA = size(A) - ndimsA = ndims(A) - axis_size = dimsA[axis] - - if axis_size == 0 - return f(A) - end - - idx = ntuple(ndimsA, j -> j == axis ? 1 : 1:dimsA[j]) - r = f(sub(A, idx)) - R = Array(typeof(r), axis_size) - R[1] = r - - for i = 2:axis_size - idx = ntuple(ndimsA, j -> j == axis ? i : 1:dimsA[j]) - R[i] = f(sub(A, idx)) - end - - return R -end - - -## 1 argument -function map_to(f, dest::StridedArray, A::StridedArray) - for i=1:numel(A) - dest[i] = f(A[i]) - end - return dest -end -function map_to2(f, first, dest::StridedArray, A::StridedArray) - dest[1] = first - for i=2:numel(A) - dest[i] = f(A[i]) - end - return dest -end - -function map(f, A::StridedArray) - if isempty(A); return A; end - first = f(A[1]) - dest = similar(A, typeof(first)) - return map_to2(f, first, dest, A) -end - -## 2 argument -function map_to(f, dest::StridedArray, A::StridedArray, B::StridedArray) - for i=1:numel(A) - dest[i] = f(A[i], B[i]) - end - return dest -end -function map_to2(f, first, dest::StridedArray, A::StridedArray, B::StridedArray) - dest[1] = first - for i=2:numel(A) - dest[i] = f(A[i], B[i]) - end - return dest -end - -function map(f, A::StridedArray, B::StridedArray) - shp = promote_shape(size(A),size(B)) - if isempty(A) - return similar(A, eltype(A), shp) - end - first = f(A[1], B[1]) - dest = similar(A, typeof(first), shp) - return map_to2(f, first, dest, A, B) -end - -## N argument -function map_to(f, dest::StridedArray, As::StridedArray...) - n = numel(As[1]) - i = 1 - ith = a->a[i] - for i=1:n - dest[i] = f(map(ith, As)...) - end - return dest -end -function map_to2(f, first, dest::StridedArray, As::StridedArray...) - n = numel(As[1]) - i = 1 - ith = a->a[i] - dest[1] = first - for i=2:n - dest[i] = f(map(ith, As)...) - end - return dest -end - -function map(f, As::StridedArray...) - shape = mapreduce(promote_shape, size, As) - if prod(shape) == 0 - return similar(As[1], eltype(As[1]), shape) - end - first = f(map(a->a[1], As)...) - dest = similar(As[1], typeof(first), shape) - return map_to2(f, first, dest, As...) -end - -## Filter ## - -# given a function returning a boolean and an array, return matching elements -function filter(f::Function, As::StridedArray) - boolmap::Array{Bool} = map(f, As) - As[boolmap] -end - ## Transpose ## function transpose{T<:Union(Float64,Float32,Complex128,Complex64)}(A::Matrix{T}) - if numel(A) > 50000 + if length(A) > 50000 return FFTW.transpose(reshape(A, size(A, 2), size(A, 1))) else return [ A[j,i] for i=1:size(A,2), j=1:size(A,1) ] @@ -1654,7 +1475,6 @@ function transpose{T<:Union(Float64,Float32,Complex128,Complex64)}(A::Matrix{T}) end ctranspose{T<:Real}(A::StridedVecOrMat{T}) = transpose(A) - ctranspose(x::StridedVecOrMat) = transpose(x) transpose(x::StridedVector) = [ x[j] for i=1, j=1:size(x,1) ] @@ -1663,78 +1483,55 @@ transpose(x::StridedMatrix) = [ x[j,i] for i=1:size(x,2), j=1:size(x,1) ] ctranspose{T<:Number}(x::StridedVector{T}) = [ conj(x[j]) for i=1, j=1:size(x,1) ] ctranspose{T<:Number}(x::StridedMatrix{T}) = [ conj(x[j,i]) for i=1:size(x,2), j=1:size(x,1) ] -## Permute ## - -let permute_cache = nothing, stridenames::Array{Any,1} = {} -global permute -function permute(A::StridedArray, perm) - dimsA = size(A) - ndimsA = length(dimsA) - dimsP = ntuple(ndimsA, i->dimsA[perm[i]]) - P = similar(A, dimsP) - ranges = ntuple(ndimsA, i->(1:dimsP[i])) - while length(stridenames) < ndimsA - push(stridenames, gensym()) - end - - #calculates all the strides - strides = [ stride(A, perm[dim]) for dim = 1:length(perm) ] - - #Creates offset, because indexing starts at 1 - offset = 0 - for i in strides - offset+=i - end - offset = 1-offset - - if isa(A,SubArray) - offset += (A.first_index-1) - A = A.parent - end - - function permute_one(ivars) - len = length(ivars) - counts = { symbol(string("count",i)) for i=1:len} - toReturn = cell(len+1,2) - for i = 1:numel(toReturn) - toReturn[i] = nothing - end - - tmp = counts[end] - toReturn[len+1] = quote - ind = 1 - $tmp = $(stridenames[len]) - end - - #inner most loop - toReturn[1] = quote - P[ind] = A[+($(counts...))+offset] - ind+=1 - $(counts[1]) += $(stridenames[1]) - end - for i = 1:len-1 - tmp = counts[i] - val = i - toReturn[(i+1)] = quote - $tmp = $(stridenames[val]) - end - tmp2 = counts[i+1] - val = i+1 - toReturn[(i+1)+(len+1)] = quote - $tmp2 += $(stridenames[val]) +# set-like operators for vectors +# These are moderately efficient, preserve order, and remove dupes. + +# algorithm: do intersect on sets first, then iterate through the first +# vector and produce only those in the set +function intersect(vs...) + args_type = promote_type([eltype(v) for v in vs]...) + ret = Array(args_type,0) + all_elems = intersect([Set(v...) for v in vs]...) + for v_elem in vs[1] + if has(all_elems, v_elem) + push!(ret, v_elem) + end + end + ret +end +function union(vs...) + args_type = promote_type([eltype(v) for v in vs]...) + ret = Array(args_type,0) + seen = Set() + for v in vs + for v_elem in v + if !has(seen, v_elem) + push!(ret, v_elem) + add!(seen, v_elem) end end - toReturn end - - if is(permute_cache,nothing) - permute_cache = Dict() + ret +end +# setdiff only accepts two args +function setdiff(a, b) + args_type = promote_type(eltype(a), eltype(b)) + bset = Set(b...) + ret = Array(args_type,0) + seen = Set() + for a_elem in a + if !has(seen, a_elem) && !has(bset, a_elem) + push!(ret, a_elem) + add!(seen, a_elem) + end end - - gen_cartesian_map(permute_cache, permute_one, ranges, - tuple(:A, :P, :perm, :offset, stridenames[1:ndimsA]...), - A, P, perm, offset, strides...) - - return P + ret end -end # let +# symdiff is associative, so a relatively clean +# way to implement this is by using setdiff and union, and +# recursing. Has the advantage of keeping order, too, but +# not as fast as other methods that make a single pass and +# store counts with a Dict. +symdiff(a) = a +symdiff(a, b) = union(setdiff(a,b), setdiff(b,a)) +symdiff(a, b, rest...) = symdiff(a, symdiff(b, rest...)) diff --git a/base/ascii.jl b/base/ascii.jl index 7c5d5d126b852..6634fe613fcab 100644 --- a/base/ascii.jl +++ b/base/ascii.jl @@ -1,22 +1,22 @@ ## from base/boot.jl: # -# type ASCIIString <: DirectIndexString +# immutable ASCIIString <: DirectIndexString # data::Array{Uint8,1} # end # ## required core functionality ## -length(s::ASCIIString) = length(s.data) -ref(s::ASCIIString, i::Int) = char(s.data[i]) +endof(s::ASCIIString) = length(s.data) +getindex(s::ASCIIString, i::Int) = (x=s.data[i]; x < 0x80 ? char(x) : '\ufffd') ## overload methods for efficiency ## -ref(s::ASCIIString, r::Vector) = ASCIIString(ref(s.data,r)) -ref(s::ASCIIString, r::Range1{Int}) = ASCIIString(ref(s.data,r)) -ref(s::ASCIIString, indx::AbstractVector{Int}) = ASCIIString(s.data[indx]) -strchr(s::ASCIIString, c::Char, i::Integer) = c < 0x80 ? memchr(s.data,c,i) : 0 -strcat(a::ASCIIString, b::ASCIIString, c::ASCIIString...) = +getindex(s::ASCIIString, r::Vector) = ASCIIString(getindex(s.data,r)) +getindex(s::ASCIIString, r::Range1{Int}) = ASCIIString(getindex(s.data,r)) +getindex(s::ASCIIString, indx::AbstractVector{Int}) = ASCIIString(s.data[indx]) +search(s::ASCIIString, c::Char, i::Integer) = c < 0x80 ? search(s.data,c,i) : 0 +string(a::ASCIIString, b::ASCIIString, c::ASCIIString...) = ASCIIString([a.data,b.data,map(s->s.data,c)...]) function ucfirst(s::ASCIIString) @@ -37,31 +37,31 @@ function lcfirst(s::ASCIIString) end function uppercase(s::ASCIIString) - for i = 1:length(s) - if 'a' <= s[i] <= 'z' - t = ASCIIString(copy(s.data)) - while i <= length(t) - if 'a' <= t[i] <= 'z' - t.data[i] -= 32 + d = s.data + for i = 1:length(d) + if 'a' <= d[i] <= 'z' + td = copy(d) + for j = i:length(td) + if 'a' <= td[j] <= 'z' + td[j] -= 32 end - i += 1 end - return t + return ASCIIString(td) end end return s end function lowercase(s::ASCIIString) - for i = 1:length(s) - if 'A' <= s[i] <= 'Z' - t = ASCIIString(copy(s.data)) - while i <= length(t) - if 'A' <= t[i] <= 'Z' - t.data[i] += 32 + d = s.data + for i = 1:length(d) + if 'A' <= d[i] <= 'Z' + td = copy(d) + for j = i:length(td) + if 'A' <= td[j] <= 'Z' + td[j] += 32 end - i += 1 end - return t + return ASCIIString(td) end end return s @@ -69,7 +69,7 @@ end ## outputing ASCII strings ## -print(io::IO, s::ASCIIString) = (write(io, s.data);nothing) +print(io::IO, s::ASCIIString) = (write(io, s);nothing) write(io::IO, s::ASCIIString) = write(io, s.data) ## transcoding to ASCII ## @@ -77,5 +77,5 @@ write(io::IO, s::ASCIIString) = write(io, s.data) ascii(x) = convert(ASCIIString, x) convert(::Type{ASCIIString}, s::ASCIIString) = s convert(::Type{ASCIIString}, s::UTF8String) = ascii(s.data) -convert(::Type{ASCIIString}, a::Array{Uint8,1}) = check_ascii(ASCIIString(a)) +convert(::Type{ASCIIString}, a::Array{Uint8,1}) = is_valid_ascii(a) ? ASCIIString(a) : error("invalid ASCII sequence") convert(::Type{ASCIIString}, s::String) = ascii(bytestring(s)) diff --git a/base/base.jl b/base/base.jl index f74f32c9c6a6e..e8893ec31f061 100644 --- a/base/base.jl +++ b/base/base.jl @@ -4,17 +4,12 @@ using Core.Intrinsics import Core.Array # to add methods +const NonTupleType = Union(DataType,UnionType,TypeConstructor) + convert(T, x) = convert_default(T, x, convert) convert(T::Tuple, x::Tuple) = convert_tuple(T, x, convert) -ptr_arg_convert{T}(::Type{Ptr{T}}, x) = convert(T, x) - -# conversion used by ccall -cconvert(T, x) = convert(T, x) -# use the code in ccall.cpp to safely allocate temporary pointer arrays -cconvert{T}(::Type{Ptr{Ptr{T}}}, a::Array) = a -# TODO: for some reason this causes a strange type inference problem -#cconvert(::Type{Ptr{Uint8}}, s::String) = bytestring(s) +abstract IO type ErrorException <: Exception msg::String @@ -61,27 +56,12 @@ type MethodError <: Exception args end -type BackTrace <: Exception - e - trace::Array{Any,1} -end - -type ShowError <: Exception - val - err::Exception -end - -show(io, bt::BackTrace) = show(io,bt.e) - -function show(io, se::ShowError) - println("Error showing value of type ", typeof(se.val), ":") - show(io, se.err) -end +type EOFError <: Exception end type WeakRef value WeakRef() = WeakRef(nothing) - WeakRef(v::ANY) = ccall(:jl_gc_new_weakref, WeakRef, (Any,), v) + WeakRef(v::ANY) = ccall(:jl_gc_new_weakref, Any, (Any,), v)::WeakRef end ccall(:jl_get_system_hooks, Void, ()) @@ -96,8 +76,17 @@ uint(x::Uint) = x names(m::Module, all::Bool) = ccall(:jl_module_names, Array{Symbol,1}, (Any,Int32), m, all) names(m::Module) = names(m,false) -module_name(m::Module) = ccall(:jl_module_name, Symbol, (Any,), m) -module_parent(m::Module) = ccall(:jl_module_parent, Module, (Any,), m) +module_name(m::Module) = ccall(:jl_module_name, Any, (Any,), m)::Symbol +module_parent(m::Module) = ccall(:jl_module_parent, Any, (Any,), m)::Module +names(t::DataType) = t.names +function names(v) + t = typeof(v) + if isa(t,DataType) + return names(t) + else + error("cannot call names() on a non-composite type") + end +end # index colon type Colon @@ -109,7 +98,12 @@ isequal(w::WeakRef, v::WeakRef) = isequal(w.value, v.value) isequal(w::WeakRef, v) = isequal(w.value, v) isequal(w, v::WeakRef) = isequal(w, v.value) -finalizer(o, f::Function) = ccall(:jl_gc_add_finalizer, Void, (Any,Any), o, f) +function finalizer(o, f::Function) + if isimmutable(o) + error("objects of type ", typeof(o), " cannot be finalized") + end + ccall(:jl_gc_add_finalizer, Void, (Any,Any), o, f) +end gc() = ccall(:jl_gc_collect, Void, ()) gc_enable() = ccall(:jl_gc_enable, Void, ()) @@ -120,16 +114,12 @@ bytestring(str::ByteString) = str # return an integer such that object_id(x)==object_id(y) if is(x,y) object_id(x::ANY) = ccall(:jl_object_id, Uint, (Any,), x) -const isimmutable = x->(isa(x,Tuple) || isa(x,Symbol) || - isa(typeof(x),BitsKind)) - -dlsym(hnd, s::String) = ccall(:jl_dlsym, Ptr{Void}, (Ptr{Void}, Ptr{Uint8}), hnd, s) -dlsym(hnd, s::Symbol) = ccall(:jl_dlsym, Ptr{Void}, (Ptr{Void}, Ptr{Uint8}), hnd, s) -dlsym_e(hnd, s::Union(Symbol,String)) = ccall(:jl_dlsym_e, Ptr{Void}, (Ptr{Void}, Ptr{Uint8}), hnd, s) -dlopen(s::String) = ccall(:jl_load_dynamic_library, Ptr{Void}, (Ptr{Uint8},), s) - -cfunction(f::Function, r, a) = - ccall(:jl_function_ptr, Ptr{Void}, (Any, Any, Any), f, r, a) +const isimmutable = x->(isa(x,Tuple) || !typeof(x).mutable) +isstructtype(t::DataType) = t.names!=() || (t.size==0 && !t.abstract) +isstructtype(x) = false +isbits(t::DataType) = !t.mutable && t.pointerfree +isbits(t::Type) = false +isbits(x) = isbits(typeof(x)) identity(x) = x @@ -157,7 +147,7 @@ end macro thunk(ex); :(()->$(esc(ex))); end macro L_str(s); s; end -function compile_hint(f, args::Tuple) +function precompile(f, args::Tuple) if isgeneric(f) ccall(:jl_compile_hint, Void, (Any, Any), f, args) end @@ -167,9 +157,6 @@ end Array{T,N}(::Type{T}, d::NTuple{N,Int}) = ccall(:jl_new_array, Array{T,N}, (Any,Any), Array{T,N}, d) -Array{N}(T, d::NTuple{N,Int}) = - (AT = Array{T,N}; - ccall(:jl_new_array, Any, (Any,Any), AT, d)::AT) Array{T}(::Type{T}, m::Int) = ccall(:jl_alloc_array_1d, Array{T,1}, (Any,Int), Array{T,1}, m) @@ -178,8 +165,8 @@ Array{T}(::Type{T}, m::Int,n::Int) = Array{T}(::Type{T}, m::Int,n::Int,o::Int) = ccall(:jl_alloc_array_3d, Array{T,3}, (Any,Int,Int,Int), Array{T,3}, m,n,o) -Array(T, d::Int...) = Array(T, d) -Array(T, d::Integer...) = Array(T, convert((Int...), d)) +Array(T::Type, d::Int...) = Array(T, d) +Array(T::Type, d::Integer...) = Array(T, convert((Int...), d)) Array{T}(::Type{T}, m::Integer) = ccall(:jl_alloc_array_1d, Array{T,1}, (Any,Int), Array{T,1}, m) diff --git a/base/bigfloat.jl b/base/bigfloat.jl new file mode 100644 index 0000000000000..a8031bd488b3a --- /dev/null +++ b/base/bigfloat.jl @@ -0,0 +1,135 @@ +BigFloat_clear(mpf::Vector{Int32}) = ccall((:__gmpf_clear, :libgmp), Void, (Ptr{Void},), mpf) + +immutable BigFloat <: FloatingPoint + mpf::Vector{Int32} + function BigFloat() + z = Array(Int32, 6) + ccall((:__gmpf_init,:libgmp), Void, (Ptr{Void},), z) + b = new(z) + finalizer(b.mpf, BigFloat_clear) + return b + end +end + +function BigFloat(x::BigFloat) + z = BigFloat() + ccall((:__gmpf_set, :libgmp), Void, (Ptr{Void}, Ptr{Void}), z.mpf, x.mpf) + return z +end + +function BigFloat(x::String) + z = BigFloat() + err = ccall((:__gmpf_set_str, :libgmp), Int32, (Ptr{Void}, Ptr{Uint8}, Int32), z.mpf, bytestring(x), 0) + if err != 0; error("Invalid input"); end + return z +end + +function BigFloat(x::Float64) + z = BigFloat() + ccall((:__gmpf_set_d, :libgmp), Void, (Ptr{Void}, Float64), z.mpf, x) + return z +end + +function BigFloat(x::Uint) + z = BigFloat() + ccall((:__gmpf_set_ui, :libgmp), Void, (Ptr{Void}, Uint), z.mpf, x) + return z +end + +function BigFloat(x::Int) + z = BigFloat() + ccall((:__gmpf_set_si, :libgmp), Void, (Ptr{Void}, Int), z.mpf, x) + return z +end + +function BigFloat(x::BigInt) + z = BigFloat() + ccall((:__gmpf_set_z, :libgmp), Void, (Ptr{Void}, Ptr{Void}), z.mpf, x.mpz) + return z +end + +BigFloat(x::Bool) = BigFloat(uint(x)) +BigFloat(x::Signed) = BigFloat(int(x)) +BigFloat(x::Unsigned) = BigFloat(uint(x)) +#BigFloat(x::Int128) = BigFloat(BigInt(x)) +#BigFloat(x::Uint128) = BigFloat(BigInt(x)) +if WORD_SIZE == 32 + BigFloat(x::Int64) = BigFloat(string(x)) + BigFloat(x::Uint64) = BigFloat(BigInt(x)) +end +BigFloat(x::Float32) = BigFloat(float64(x)) +BigFloat(x::Rational) = BigFloat(num(x)) / BigFloat(den(x)) + +convert(::Type{BigFloat}, x::Rational) = BigFloat(x) # to resolve ambiguity +convert(::Type{BigFloat}, x::Real) = BigFloat(x) + +convert(::Type{Float64}, x::BigFloat) = ccall((:__gmpf_get_d,:libgmp), Float64, (Ptr{Void},), x.mpf) +convert(::Type{FloatingPoint}, x::BigInt) = BigFloat(x) + +promote_rule{T<:Union(Integer,FloatingPoint)}(::Type{BigFloat}, ::Type{T}) = BigFloat +promote_rule{T<:FloatingPoint}(::Type{BigInt},::Type{T}) = BigFloat + + +# mpf doesn't have inf or nan +isnan(x::BigFloat) = false +isinf(x::BigFloat) = false + +# Binary ops +for (fJ, fC) in ((:+,:add), (:-,:sub), (:*,:mul), (:/,:div)) + @eval begin + function ($fJ)(x::BigFloat, y::BigFloat) + z = BigFloat() + ccall(($(string(:__gmpf_,fC)),:libgmp), Void, (Ptr{Void}, Ptr{Void}, Ptr{Void}), z.mpf, x.mpf, y.mpf) + return z + end + end +end + +function -(x::BigFloat) + z = BigFloat() + ccall((:__gmpf_neg, :libgmp), Void, (Ptr{Void}, Ptr{Void}), z.mpf, x.mpf) + return z +end + +function cmp(x::BigFloat, y::BigFloat) + ccall((:__gmpf_cmp, :libgmp), Int32, (Ptr{Void}, Ptr{Void}), x.mpf, y.mpf) +end + +for f in (:sqrt, :ceil, :floor, :trunc) + @eval begin + function ($f)(x::BigFloat) + z = BigFloat() + ccall(($(string(:__gmpf_,f)), :libgmp), Void, (Ptr{Void}, Ptr{Void}), z.mpf, x.mpf) + return z + end + end +end + +function ^(x::BigFloat, y::Uint) + z = BigFloat() + ccall((:__gmpf_pow_ui, :libgmp), Void, (Ptr{Void}, Ptr{Void}, Uint), z.mpf, x.mpf, y) + return z +end + +^(x::Float32, y::BigInt) = BigFloat(x)^y +^(x::Float64, y::BigInt) = BigFloat(x)^y + +==(x::BigFloat, y::BigFloat) = cmp(x,y) == 0 +<=(x::BigFloat, y::BigFloat) = cmp(x,y) <= 0 +>=(x::BigFloat, y::BigFloat) = cmp(x,y) >= 0 +<(x::BigFloat, y::BigFloat) = cmp(x,y) < 0 +>(x::BigFloat, y::BigFloat) = cmp(x,y) > 0 + +complex(x::BigFloat, y::BigFloat) = ComplexPair(x, y) + +function string(x::BigFloat) + lng = 128 + for i = 1:2 + z = Array(Uint8, lng) + lng = ccall((:__gmp_snprintf,:libgmp), Int32, (Ptr{Uint8}, Uint, Ptr{Uint8}, Ptr{Void}...), z, lng, "%.Fe", x.mpf) + if lng < 128 || i == 2; return bytestring(convert(Ptr{Uint8}, z[1:lng])); end + end +end + +show(io::IO, b::BigFloat) = print(io, string(b)) +showcompact(io::IO, b::BigFloat) = print(io, string(b)) diff --git a/base/bigint.jl b/base/bigint.jl new file mode 100644 index 0000000000000..206cb2b809bbe --- /dev/null +++ b/base/bigint.jl @@ -0,0 +1,184 @@ +BigInt_clear(mpz::Vector{Int32}) = ccall((:__gmpz_clear, :libgmp), Void, (Ptr{Void},), mpz) + +immutable BigInt <: Integer + mpz::Vector{Int32} + function BigInt() + z = Array(Int32, 4) + ccall((:__gmpz_init,:libgmp), Void, (Ptr{Void},), z) + b = new(z) + finalizer(b.mpz, BigInt_clear) + return b + end +end + +function BigInt(x::BigInt) + z = BigInt() + ccall((:__gmpz_set, :libgmp), Void, (Ptr{Void}, Ptr{Void}), z.mpz, x.mpz) + return z +end + +function BigInt(x::String) + z = BigInt() + err = ccall((:__gmpz_set_str, :libgmp), Int32, (Ptr{Void}, Ptr{Uint8}, Int32), z.mpz, bytestring(x), 0) + if err != 0; error("Invalid input"); end + return z +end + +function BigInt(x::Int) + z = BigInt() + ccall((:__gmpz_set_si, :libgmp), Void, (Ptr{Void}, Int), z.mpz, x) + return z +end + +function BigInt(x::Uint) + z = BigInt() + ccall((:__gmpz_set_ui, :libgmp), Void, + (Ptr{Void}, Uint), z.mpz, x) + return z +end + +BigInt(x::Bool) = BigInt(uint(x)) +BigInt(x::Signed) = BigInt(int(x)) +BigInt(x::Unsigned) = BigInt(uint(x)) +#BigInt(x::Int128) = BigInt(string(x)) +#BigInt(x::Uint128) = BigInt(string(x)) +if WORD_SIZE == 32 + BigInt(x::Int64) = BigInt(string(x)) + BigInt(x::Uint64) = BigInt(string(x)) +end + +convert{T<:Integer}(::Type{BigInt}, x::T) = BigInt(x) + +convert(::Type{Int}, n::BigInt) = + ccall((:__gmpz_get_si, :libgmp), Int, (Ptr{Void},), n.mpz) + +convert(::Type{Uint}, n::BigInt) = + ccall((:__gmpz_get_ui, :libgmp), Uint, (Ptr{Void},), n.mpz) + +promote_rule{T<:Integer}(::Type{BigInt}, ::Type{T}) = BigInt + +# Binary ops +for (fJ, fC) in ((:+, :add), (:-,:sub), (:*, :mul), + (:fld, :fdiv_q), (:div, :tdiv_q), (:mod, :fdiv_r), (:rem, :tdiv_r), + (:gcd, :gcd), (:lcm, :lcm), + (:&, :and), (:|, :ior), (:$, :xor)) + @eval begin + function ($fJ)(x::BigInt, y::BigInt) + z = BigInt() + ccall(($(string(:__gmpz_,fC)), :libgmp), Void, (Ptr{Void}, Ptr{Void}, Ptr{Void}), z.mpz, x.mpz, y.mpz) + return z + end + end +end + +# unary ops +for (fJ, fC) in ((:-, :neg), (:~, :com)) + @eval begin + function ($fJ)(x::BigInt) + z = BigInt() + ccall(($(string(:__gmpz_,fC)), :libgmp), Void, (Ptr{Void}, Ptr{Void}), z.mpz, x.mpz) + return z + end + end +end + +function <<(x::BigInt, c::Uint) + z = BigInt() + ccall((:__gmpz_mul_2exp, :libgmp), Void, (Ptr{Void}, Ptr{Void}, Uint), z.mpz, x.mpz, c) + return z +end +<<(x::BigInt, c::Int32) = c<0 ? throw(DomainError()) : x<>(x::BigInt, c::Uint) + z = BigInt() + ccall((:__gmpz_fdiv_q_2exp, :libgmp), Void, (Ptr{Void}, Ptr{Void}, Uint), z.mpz, x.mpz, c) + return z +end +>>(x::BigInt, c::Int32) = c<0 ? throw(DomainError()) : x>>uint(c) +>>(x::BigInt, c::Integer) = c<0 ? throw(DomainError()) : x>>uint(c) + +function divrem(x::BigInt, y::BigInt) + z1 = BigInt() + z2 = BigInt() + ccall((:__gmpz_tdiv_qr, :libgmp), Void, (Ptr{Void}, Ptr{Void}, Ptr{Void}, Ptr{Void}), z1.mpz, z2.mpz, x.mpz, y.mpz) + z1, z2 +end + +function cmp(x::BigInt, y::BigInt) + ccall((:__gmpz_cmp, :libgmp), Int32, (Ptr{Void}, Ptr{Void}), x.mpz, y.mpz) +end + +function sqrt(x::BigInt) + z = BigInt() + ccall((:__gmpz_sqrt, :libgmp), Void, (Ptr{Void}, Ptr{Void}), z.mpz, x.mpz) + return z +end + +function ^(x::BigInt, y::Uint) + z = BigInt() + ccall((:__gmpz_pow_ui, :libgmp), Void, (Ptr{Void}, Ptr{Void}, Uint), z.mpz, x.mpz, y) + return z +end + +function bigint_pow(x::BigInt, y::Integer) + if y<0; throw(DomainError()); end + if x== 1; return x; end + if x==-1; return isodd(y) ? x : -x; end + if y>typemax(Uint); throw(DomainError()); end + return x^uint(y) +end + +^(x::BigInt , y::BigInt ) = bigint_pow(x, y) +^(x::BigInt , y::Bool ) = y ? x : one(x) +^(x::BigInt , y::Integer) = bigint_pow(x, y) +^(x::Integer, y::BigInt ) = bigint_pow(BigInt(x), y) + +function gcdx(a::BigInt, b::BigInt) + g = BigInt() + s = BigInt() + t = BigInt() + ccall((:__gmpz_gcdext, :libgmp), Void, + (Ptr{Void}, Ptr{Void}, Ptr{Void}, Ptr{Void}, Ptr{Void}), + g, s, t, a.mpz, b.mpz) + BigInt(g), BigInt(s), BigInt(t) +end + +function factorial(bn::BigInt) + if bn<0 + return BigInt(0) + else + n = uint(bn) + end + z = BigInt() + ccall((:__gmpz_fac_ui, :libgmp), Void, + (Ptr{Void}, Uint), z.mpz, n) + return z +end + +function binomial(n::BigInt, k::Uint) + z = BigInt() + ccall((:__gmpz_bin_ui, :libgmp), Void, + (Ptr{Void}, Ptr{Void}, Uint), z.mpz, n.mpz, k) + return z +end +binomial(n::BigInt, k::Integer) = k<0 ? throw(DomainError()) : binomial(n, uint(k)) + +==(x::BigInt, y::BigInt) = cmp(x,y) == 0 +<=(x::BigInt, y::BigInt) = cmp(x,y) <= 0 +>=(x::BigInt, y::BigInt) = cmp(x,y) >= 0 +<(x::BigInt, y::BigInt) = cmp(x,y) < 0 +>(x::BigInt, y::BigInt) = cmp(x,y) > 0 + +function string(x::BigInt) + lng = ndigits(x) + 2 + z = Array(Uint8, lng) + lng = ccall((:__gmp_snprintf,:libgmp), Int32, (Ptr{Uint8}, Uint, Ptr{Uint8}, Ptr{Void}...), z, lng, "%Zd", x.mpz) + return bytestring(convert(Ptr{Uint8}, z[1:lng])) +end + +function show(io::IO, x::BigInt) + print(io, string(x)) +end + +ndigits(x::BigInt) = ccall((:__gmpz_sizeinbase,:libgmp), Uint, (Ptr{Void}, Int32), x.mpz, 10) diff --git a/base/bitarray.jl b/base/bitarray.jl index 9b3ba5493d5be..ea0f83d8f0ed8 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -1,22 +1,17 @@ # prelimnary definitions: constants, macros # and functions used throughout the code const _msk64 = ~uint64(0) -macro _mskr(l) quote _msk64 >>> (64-$(esc(l))) end end -macro _div64(l) quote $(esc(l)) >>> 6 end end -macro _mod64(l) quote $(esc(l)) & 63 end end -macro _msk_end(l) quote @_mskr @_mod64 $(esc(l)) end end -_jl_num_bit_chunks(n::Int) = @_div64 (n+63) -function _jl_check_is_valid_bit{T}(x::T) - if !(isequal(x, zero(T)) || isequal(x, one(T))) - error("invalid BitArray value") - end -end +macro _mskr(l) :(_msk64 >>> (64-$(esc(l)))) end +macro _div64(l) :($(esc(l)) >>> 6) end +macro _mod64(l) :($(esc(l)) & 63) end +macro _msk_end(l) :(@_mskr @_mod64 $(esc(l))) end +num_bit_chunks(n::Int) = @_div64 (n+63) ## BitArray # notes: bits are stored in contiguous chunks # unused bits must always be set to 0 -type BitArray{T<:Integer, N} <: AbstractArray{T, N} +type BitArray{N} <: AbstractArray{Bool, N} chunks::Vector{Uint64} dims::Vector{Int} function BitArray(dims::Int...) @@ -24,7 +19,7 @@ type BitArray{T<:Integer, N} <: AbstractArray{T, N} dims = 0 end n = prod(dims) - nc = _jl_num_bit_chunks(n) + nc = num_bit_chunks(n) chunks = Array(Uint64, nc) if nc > 0 chunks[end] = uint64(0) @@ -33,32 +28,26 @@ type BitArray{T<:Integer, N} <: AbstractArray{T, N} end end -BitArray{T}(::Type{T}) = BitArray{T,1}(0) -BitArray() = BitArray(Bool, 0) -BitArray{T}(::Type{T}, dims::Dims) = BitArray{T, max(length(dims), 1)}(dims...) -BitArray(dims::Dims) = BitArray(Bool, dims) -BitArray{T}(::Type{T}, dims::Int...) = BitArray{T, max(length(dims), 1)}(dims...) -BitArray(dims::Int...) = BitArray(Bool, dims...) +BitArray() = BitArray(0) +BitArray(dims::Dims) = BitArray{max(length(dims), 1)}(dims...) +BitArray(dims::Int...) = BitArray{max(length(dims), 1)}(dims...) -typealias BitVector{T} BitArray{T,1} -typealias BitMatrix{T} BitArray{T,2} +typealias BitVector BitArray{1} +typealias BitMatrix BitArray{2} ## utility functions ## length(B::BitArray) = prod(B.dims) -eltype{T}(B::BitArray{T}) = T -ndims{T,N}(B::BitArray{T,N}) = N -numel(B::BitArray) = prod(B.dims) +eltype(B::BitArray) = Bool +ndims{N}(B::BitArray{N}) = N +length(B::BitArray) = prod(B.dims) size(B::BitArray) = tuple(B.dims...) ## Aux functions ## -function _jl_get_chunks_id(i::Integer) - j = int(i-1) - return (@_div64 j)+1, @_mod64 j -end +get_chunks_id(i::Integer) = @_div64(int(i)-1)+1, @_mod64(int(i)-1) -function _jl_glue_src_bitchunks(src::Vector{Uint64}, k::Int, ks1::Int, msk_s0::Uint64, ls0::Int) +function glue_src_bitchunks(src::Vector{Uint64}, k::Int, ks1::Int, msk_s0::Uint64, ls0::Int) chunk = ((src[k] & msk_s0) >>> ls0) if ks1 > k && ls0 > 0 chunk_n = (src[k + 1] & ~msk_s0) @@ -67,15 +56,15 @@ function _jl_glue_src_bitchunks(src::Vector{Uint64}, k::Int, ks1::Int, msk_s0::U return chunk end -function _jl_copy_chunks(dest::Vector{Uint64}, pos_d::Integer, src::Vector{Uint64}, pos_s::Integer, numbits::Integer) +function copy_chunks(dest::Vector{Uint64}, pos_d::Integer, src::Vector{Uint64}, pos_s::Integer, numbits::Integer) if numbits == 0 return end - kd0, ld0 = _jl_get_chunks_id(pos_d) - kd1, ld1 = _jl_get_chunks_id(pos_d + numbits - 1) - ks0, ls0 = _jl_get_chunks_id(pos_s) - ks1, ls1 = _jl_get_chunks_id(pos_s + numbits - 1) + kd0, ld0 = get_chunks_id(pos_d) + kd1, ld1 = get_chunks_id(pos_d + numbits - 1) + ks0, ls0 = get_chunks_id(pos_s) + ks1, ls1 = get_chunks_id(pos_s + numbits - 1) delta_kd = kd1 - kd0 delta_ks = ks1 - ks0 @@ -93,7 +82,7 @@ function _jl_copy_chunks(dest::Vector{Uint64}, pos_d::Integer, src::Vector{Uint6 msk_s0 = (u << ls0) end - chunk_s0 = _jl_glue_src_bitchunks(src, ks0, ks1, msk_s0, ls0) + chunk_s0 = glue_src_bitchunks(src, ks0, ks1, msk_s0, ls0) dest[kd0] = (dest[kd0] & msk_d0) | ((chunk_s0 << ld0) & ~msk_d0) @@ -102,7 +91,7 @@ function _jl_copy_chunks(dest::Vector{Uint64}, pos_d::Integer, src::Vector{Uint6 end for i = 1 : kd1 - kd0 - 1 - chunk_s1 = _jl_glue_src_bitchunks(src, ks0 + i, ks1, msk_s0, ls0) + chunk_s1 = glue_src_bitchunks(src, ks0 + i, ks1, msk_s0, ls0) chunk_s = (chunk_s0 >>> (63 - ld0) >>> 1) | (chunk_s1 << ld0) @@ -112,7 +101,7 @@ function _jl_copy_chunks(dest::Vector{Uint64}, pos_d::Integer, src::Vector{Uint6 end if ks1 >= ks0 + delta_kd - chunk_s1 = _jl_glue_src_bitchunks(src, ks0 + delta_kd, ks1, msk_s0, ls0) + chunk_s1 = glue_src_bitchunks(src, ks0 + delta_kd, ks1, msk_s0, ls0) else chunk_s1 = uint64(0) end @@ -124,69 +113,49 @@ function _jl_copy_chunks(dest::Vector{Uint64}, pos_d::Integer, src::Vector{Uint6 return end +## similar, fill!, copy! etc ## -## similar, fill, copy_to etc ## - -similar{T}(B::BitArray{T}) = BitArray(T, B.dims...) -similar{T}(B::BitArray{T}, dims::Int...) = BitArray(T, dims) -similar{T}(B::BitArray{T}, dims::Dims) = BitArray(T, dims...) +similar(B::BitArray) = BitArray(B.dims...) +similar(B::BitArray, dims::Int...) = BitArray(dims) +similar(B::BitArray, dims::Dims) = BitArray(dims...) -similar{S<:Integer}(B::BitArray, T::Type{S}, dims::Dims) = BitArray(T, dims) -# changing type to a non-Integer returns an Array +similar(B::BitArray, T::Type{Bool}, dims::Dims) = BitArray(dims) +# changing type to a non-Bool returns an Array # (this triggers conversions like float(bitvector) etc.) similar(B::BitArray, T::Type, dims::Dims) = Array(T, dims) -function fill!{T<:Integer}(B::BitArray{T}, x::Number) - y = convert(T, x) - if isequal(y, zero(T)) - Bc = B.chunks +function fill!(B::BitArray, x) + y = convert(Bool, x) + Bc = B.chunks + if !y for i = 1 : length(B.chunks) Bc[i] = uint64(0) end - elseif isequal(y, one(T)) + else if length(B) == 0 return B end - Bc = B.chunks for i = 1 : length(B.chunks) - 1 Bc[i] = _msk64 end - B.chunks[end] = @_msk_end length(B) - else - error("invalid BitArray value") + Bc[end] = @_msk_end length(B) end return B end -fill!(B::BitArray, x) = fill!(B, int(x)) - -bitzeros{T}(::Type{T}, args...) = fill!(BitArray(T, args...), 0) -bitones{T}(::Type{T}, args...) = fill!(BitArray(T, args...), 1) +falses(args...) = fill!(BitArray(args...), false) +trues(args...) = fill!(BitArray(args...), true) -trues(args...) = bitones(Bool, args...) -falses(args...) = bitzeros(Bool, args...) - -biteye{T}(::Type{T}, n::Integer) = biteye(T, n, n) -function biteye{T}(::Type{T}, m::Integer, n::Integer) - a = bitzeros(T, m, n) - for i = 1:min(m,n) - a[i,i] = one(T) - end - return a -end -biteye(n::Integer) = biteye(Bool, n) -biteye(m::Integer, n::Integer) = biteye(Bool, m, n) - -function one{T}(x::BitMatrix{T}) +function one(x::BitMatrix) m, n = size(x) - a = bitzeros(T,size(x)) + a = falses(size(x)) for i = 1 : min(m,n) - a[i,i] = one(T) + a[i,i] = true end return a end -function copy_to(dest::BitArray, src::BitArray) +function copy!(dest::BitArray, src::BitArray) destc = dest.chunks; srcc = src.chunks nc_d = length(destc) nc_s = length(srcc) @@ -207,28 +176,28 @@ function copy_to(dest::BitArray, src::BitArray) return dest end -function copy_to(dest::BitArray, pos_d::Integer, src::BitArray, pos_s::Integer, numbits::Integer) - if pos_s+numbits-1 > numel(src) || pos_d+numbits-1 > numel(dest) || pos_d < 1 || pos_s < 1 +function copy!(dest::BitArray, pos_d::Integer, src::BitArray, pos_s::Integer, numbits::Integer) + if pos_s+numbits-1 > length(src) || pos_d+numbits-1 > length(dest) || pos_d < 1 || pos_s < 1 throw(BoundsError()) end - _jl_copy_chunks(dest.chunks, pos_d, src.chunks, pos_s, numbits) + copy_chunks(dest.chunks, pos_d, src.chunks, pos_s, numbits) return dest end -function reshape{T,N}(B::BitArray{T}, dims::NTuple{N,Int}) - if prod(dims) != numel(B) +function reshape{N}(B::BitArray, dims::NTuple{N,Int}) + if prod(dims) != length(B) error("reshape: invalid dimensions") end - Br = BitArray{T,N}() + Br = BitArray{N}() Br.chunks = B.chunks - Br.dims = [i::Int for i in dims] + Br.dims = Int[i for i in dims] return Br end ## Conversions ## -convert{T,S,n}(::Type{Array{T}}, B::BitArray{S,n}) = convert(Array{T,n},B) -function convert{T,S,n}(::Type{Array{T,n}}, B::BitArray{S,n}) +convert{T,N}(::Type{Array{T}}, B::BitArray{N}) = convert(Array{T,N},B) +function convert{T,N}(::Type{Array{T,N}}, B::BitArray{N}) A = Array(T, size(B)) for i = 1:length(A) A[i] = B[i] @@ -236,40 +205,31 @@ function convert{T,S,n}(::Type{Array{T,n}}, B::BitArray{S,n}) return A end -convert{T,S,n}(::Type{BitArray{S}}, A::AbstractArray{T,n}) = convert(BitArray{S,n},A) -function convert{T,S,n}(::Type{BitArray{S,n}}, A::AbstractArray{T,n}) - B = BitArray(S, size(A)) +convert{T,N}(::Type{BitArray}, A::AbstractArray{T,N}) = convert(BitArray{N},A) +function convert{T,N}(::Type{BitArray{N}}, A::AbstractArray{T,N}) + B = BitArray(size(A)) for i = 1:length(B) B[i] = A[i] end return B end -convert{T<:Integer,n}(::Type{BitArray{T,n}}, B::BitArray{T,n}) = B -convert{T<:Integer,S<:Integer,n}(::Type{BitArray{T,n}}, B::BitArray{S,n}) = - copy_to(similar(B, T), B) +convert{N}(::Type{BitArray{N}}, B::BitArray{N}) = B -# this version keeps dimensionality -# (it's an extension of Array's behavior, which only does this for Vectors) -function reinterpret{T<:Integer,S<:Integer,N}(::Type{T}, B::BitArray{S,N}) - A = BitArray{T,N}() - A.dims = copy(B.dims) - A.chunks = B.chunks - return A -end -function reinterpret{T<:Integer,S<:Integer,N}(::Type{T}, B::BitArray{S}, dims::NTuple{N,Int}) - if prod(dims) != numel(B) +reinterpret{N}(::Type{Bool}, B::BitArray, dims::NTuple{N,Int}) = reinterpret(B, dims) +function reinterpret{N}(B::BitArray, dims::NTuple{N,Int}) + if prod(dims) != length(B) error("reinterpret: invalid dimensions") end - A = BitArray{T,N}() + A = BitArray{N}() A.dims = [i::Int for i in dims] A.chunks = B.chunks return A end # shorthand forms BitArray <-> Array -bitunpack{T,n}(B::BitArray{T,n}) = convert(Array{T,n}, B) -bitpack{T,n}(A::Array{T,n}) = convert(BitArray{T,n}, A) +bitunpack{N}(B::BitArray{N}) = convert(Array{Bool,N}, B) +bitpack{T,N}(A::AbstractArray{T,N}) = convert(BitArray{N}, A) ## Random ## @@ -278,78 +238,70 @@ function bitarray_rand_fill!(B::BitArray) return B end Bc = B.chunks - for i = 1 : length(B.chunks) - 1 - Bc[i] = randi(Uint64) + for i = 1 : length(Bc) - 1 + Bc[i] = rand(Uint64) end msk = @_msk_end length(B) - B.chunks[end] = msk & randi(Uint64) + Bc[end] = msk & rand(Uint64) return B end -## Bounds checking ## +## Indexing: getindex ## -# @carlo: fixme -function check_bounds(A::Array, B::BitArray) - return nothing +function getindex_unchecked(Bc::Vector{Uint64}, i::Integer) + i1, i2 = get_chunks_id(i) + u = uint64(1) + return (Bc[i1] >>> i2) & u == u end -## Indexing: ref ## - -function ref{T<:Integer}(B::BitArray{T}, i::Integer) +function getindex(B::BitArray, i::Real) + i = to_index(i) if i < 1 || i > length(B) throw(BoundsError()) end - i1, i2 = _jl_get_chunks_id(i) - return (B.chunks[i1] >>> i2) & one(Uint64) == one(Uint64) ? one(T) : zero(T) + getindex_unchecked(B.chunks, i) end # 0d bitarray -ref{T<:Integer}(B::BitArray{T,0}) = B[1] +getindex(B::BitArray{0}) = getindex_unchecked(B.chunks, 1) -ref(B::BitArray, i0::Integer, i1::Integer) = B[i0 + size(B,1)*(i1-1)] -ref(B::BitArray, i0::Integer, i1::Integer, i2::Integer) = - B[i0 + size(B,1)*((i1-1) + size(B,2)*(i2-1))] -ref(B::BitArray, i0::Integer, i1::Integer, i2::Integer, i3::Integer) = - B[i0 + size(B,1)*((i1-1) + size(B,2)*((i2-1) + size(B,3)*(i3-1)))] +getindex(B::BitArray, i0::Real, i1::Real) = B[to_index(i0) + size(B,1)*(to_index(i1)-1)] +getindex(B::BitArray, i0::Real, i1::Real, i2::Real) = + B[to_index(i0) + size(B,1)*((to_index(i1)-1) + size(B,2)*(to_index(i2)-1))] +getindex(B::BitArray, i0::Real, i1::Real, i2::Real, i3::Real) = + B[to_index(i0) + size(B,1)*((to_index(i1)-1) + size(B,2)*((to_index(i2)-1) + size(B,3)*(to_index(i3)-1)))] -# note: although unused, the T here is necessary, otherwhise -# ref(::BitArray, ::Integer) is shadowed (?) -function ref{T<:Integer}(B::BitArray{T}, I::Integer...) +function getindex(B::BitArray, I::Real...) ndims = length(I) - index = I[1] + index = to_index(I[1]) stride = 1 for k=2:ndims stride *= size(B, k - 1) - index += (I[k] - 1) * stride + index += (to_index(I[k]) - 1) * stride end return B[index] end # note: we can gain some performance if the first dimension is a range; -# TODO: extend to I:Indices... (i.e. not necessarily contiguous) -let ref_cache = nothing - global ref - function ref(B::BitArray, I0::Range1{Int}, I::Union(Integer, Range1{Int})...) +# TODO: extend to I:Union(Real,AbstractArray)... (i.e. not necessarily contiguous) +let getindex_cache = nothing + global getindex + function getindex(B::BitArray, I0::Range1{Int}, I::Union(Real,Range1{Int})...) # the < should become a != once # the stricter indexing behaviour is enforced if ndims(B) < 1 + length(I) - error("wrong number of dimensions in ref") + error("wrong number of dimensions in getindex") end - X = similar(B, ref_shape(I0, I...)) - nI = ndims(X) + check_bounds(B, I0, I...) + X = BitArray(index_shape(I0, I...)) + nI = 1 + length(I) - I = map(x->(isa(x,Integer) ? (x:x) : x), I[1:nI-1]) + I = map(x->(isa(x,Real) ? (to_index(x):to_index(x)) : indices(x)), I[1:nI-1]) f0 = first(I0) l0 = length(I0) - if nI == 1 - _jl_copy_chunks(X.chunks, 1, B.chunks, f0, l0) - return X - end - if is(ref_cache,nothing) - ref_cache = Dict() - end - gap_lst = [last(r)-first(r)+1 for r in I] + + gap_lst = Int[last(r)-first(r)+1 for r in I] stride_lst = Array(Int, nI) stride = 1 ind = f0 @@ -363,11 +315,20 @@ let ref_cache = nothing # is dummy (used in bodies[k,2] below) stride_lst[nI] = 0 - gen_cartesian_map(ref_cache, + if ndims(X) == 1 + copy_chunks(X.chunks, 1, B.chunks, ind, l0) + return X + end + + if is(getindex_cache,nothing) + getindex_cache = Dict() + end + + gen_cartesian_map(getindex_cache, ivars->begin bodies = cell(nI, 2) bodies[1] = quote - _jl_copy_chunks(X.chunks, storeind, B.chunks, ind, l0) + copy_chunks(X.chunks, storeind, B.chunks, ind, l0) storeind += l0 ind += stride_lst[loop_ind] end @@ -391,102 +352,115 @@ end # note: the Range1{Int} case is still handled by the version above # (which is fine) -function ref{T<:Integer}(B::BitArray, I::AbstractVector{T}) - X = similar(B, length(I)) +function getindex{T<:Real}(B::BitArray, I::AbstractVector{T}) + X = BitArray(length(I)) + lB = length(B) + Xc = X.chunks + Bc = B.chunks ind = 1 for i in I - X[ind] = B[i] + # faster X[ind] = B[i] + i = to_index(i) + if i < 1 || i > lB + throw(BoundsError()) + end + assign_unchecked(Xc, getindex_unchecked(Bc, i), ind) ind += 1 end return X end -let ref_cache = nothing - global ref - function ref(B::BitArray, I::Indices...) +let getindex_cache = nothing + global getindex + function getindex(B::BitArray, I::Union(Real,AbstractVector)...) I = indices(I) - X = similar(B, ref_shape(I...)) + X = BitArray(index_shape(I...)) + Xc = X.chunks - if is(ref_cache,nothing) - ref_cache = Dict() + if is(getindex_cache,nothing) + getindex_cache = Dict() end - gen_cartesian_map(ref_cache, ivars -> quote - X[storeind] = B[$(ivars...)] - storeind += 1 - end, I, (:B, :X, :storeind), B, X, 1) + gen_cartesian_map(getindex_cache, ivars -> quote + #faster X[storeind] = B[$(ivars...)] + assign_unchecked(Xc, B[$(ivars...)], ind) + ind += 1 + end, I, (:B, :Xc, :ind), B, Xc, 1) return X end end # logical indexing -function _jl_ref_bool_1d(B::BitArray, I::AbstractArray{Bool}) +function getindex_bool_1d(B::BitArray, I::AbstractArray{Bool}) n = sum(I) - out = similar(B, n) - c = 1 - for i = 1:numel(I) + X = BitArray(n) + lI = length(I) + if lI != length(B) + throw(BoundsError()) + end + Xc = X.chunks + Bc = B.chunks + ind = 1 + for i = 1:length(I) if I[i] - out[c] = B[i] - c += 1 + # faster X[ind] = B[i] + assign_unchecked(Xc, getindex_unchecked(Bc, i), ind) + ind += 1 end end - out + return X end -# note : type specifiers needed to gain precedence over ref(::BitArray, ::Indices...) -ref{T<:Integer}(B::BitVector{T}, I::AbstractVector{Bool}) = _jl_ref_bool_1d(B, I) -ref{T<:Integer}(B::BitVector{T}, I::AbstractArray{Bool}) = _jl_ref_bool_1d(B, I) -ref{T<:Integer}(B::BitArray{T}, I::AbstractVector{Bool}) = _jl_ref_bool_1d(B, I) -ref{T<:Integer}(B::BitArray{T}, I::AbstractArray{Bool}) = _jl_ref_bool_1d(B, I) +getindex(B::BitVector, I::AbstractVector{Bool}) = getindex_bool_1d(B, I) +getindex(B::BitVector, I::AbstractArray{Bool}) = getindex_bool_1d(B, I) +getindex(B::BitArray, I::AbstractVector{Bool}) = getindex_bool_1d(B, I) +getindex(B::BitArray, I::AbstractArray{Bool}) = getindex_bool_1d(B, I) -ref{T<:Integer}(B::BitMatrix{T}, I::Integer, J::AbstractVector{Bool}) = B[I, find(J)] -ref{T<:Integer}(B::BitMatrix{T}, I::AbstractVector{Bool}, J::Integer) = B[find(I), J] -ref{T<:Integer}(B::BitMatrix{T}, I::AbstractVector{Bool}, J::AbstractVector{Bool}) = B[find(I), find(J)] -ref{T<:Integer,S<:Integer}(B::BitMatrix{T}, I::AbstractVector{S}, J::AbstractVector{Bool}) = B[I, find(J)] -ref{T<:Integer,S<:Integer}(B::BitMatrix{T}, I::AbstractVector{Bool}, J::AbstractVector{S}) = B[find(I), J] +## Indexing: setindex! ## -## Indexing: assign ## +function assign_unchecked(Bc::Array{Uint64}, x, i::Integer) + x = convert(Bool, x) + i1, i2 = get_chunks_id(i) + u = uint64(1) << i2 + if x + Bc[i1] |= u + else + Bc[i1] &= ~u + end +end -function assign{T<:Integer}(B::BitArray{T}, x::Number, i::Integer) +function setindex!(B::BitArray, x, i::Real) + i = to_index(i) if i < 1 || i > length(B) throw(BoundsError()) end - i1, i2 = _jl_get_chunks_id(i) - u = uint64(1) - y = convert(T, x) - if isequal(y, zero(T)) - B.chunks[i1] &= ~(u << i2) - elseif isequal(y, one(T)) - B.chunks[i1] |= (u << i2) - else - error("invalid BitArray value") - end + assign_unchecked(B.chunks, x, i) return B end -assign(B::BitArray, x::Number, i0::Integer, i1::Integer) = - B[i0 + size(B,1)*(i1-1)] = x +setindex!(B::BitArray, x, i0::Real, i1::Real) = + B[to_index(i0) + size(B,1)*(to_index(i1)-1)] = x -assign(B::BitArray, x::Number, i0::Integer, i1::Integer, i2::Integer) = - B[i0 + size(B,1)*((i1-1) + size(B,2)*(i2-1))] = x +setindex!(B::BitArray, x, i0::Real, i1::Real, i2::Real) = + B[to_index(i0) + size(B,1)*((to_index(i1)-1) + size(B,2)*(to_index(i2)-1))] = x -assign(B::BitArray, x::Number, i0::Integer, i1::Integer, i2::Integer, i3::Integer) = - B[i0 + size(B,1)*((i1-1) + size(B,2)*((i2-1) + size(B,3)*(i3-1)))] = x +setindex!(B::BitArray, x, i0::Real, i1::Real, i2::Real, i3::Real) = + B[to_index(i0) + size(B,1)*((to_index(i1)-1) + size(B,2)*((to_index(i2)-1) + size(B,3)*(to_index(i3)-1)))] = x -function assign(B::BitArray, x::Number, I0::Integer, I::Integer...) - index = I0 +function setindex!(B::BitArray, x, I0::Real, I::Real...) + index = to_index(I0) stride = 1 for k = 1:length(I) stride = stride * size(B, k) - index += (I[k] - 1) * stride + index += (to_index(I[k]) - 1) * stride end B[index] = x return B end let assign_cache = nothing - global _jl_assign_array2bitarray_ranges - function _jl_assign_array2bitarray_ranges(B::BitArray, X::BitArray, I0::Range1{Int}, I::Range1{Int}...) + global assign_array2bitarray_ranges + function assign_array2bitarray_ranges(B::BitArray, X::BitArray, I0::Range1{Int}, I::Range1{Int}...) nI = 1 + length(I) if ndims(B) != nI error("wrong number of dimensions in assigment") @@ -495,7 +469,7 @@ let assign_cache = nothing for r in I lI *= length(r) end - if numel(X) != lI + if length(X) != lI error("array assignment dimensions mismatch") end if lI == 0 @@ -504,7 +478,7 @@ let assign_cache = nothing f0 = first(I0) l0 = length(I0) if nI == 1 - _jl_copy_chunks(B.chunks, f0, X.chunks, 1, l0) + copy_chunks(B.chunks, f0, X.chunks, 1, l0) return B end if is(assign_cache,nothing) @@ -528,7 +502,7 @@ let assign_cache = nothing ivars->begin bodies = cell(nI, 2) bodies[1] = quote - _jl_copy_chunks(B.chunks, ind, X.chunks, refind, l0) + copy_chunks(B.chunks, ind, X.chunks, refind, l0) refind += l0 ind += stride_lst[loop_ind] end @@ -553,52 +527,47 @@ end # note: we can gain some performance if the first dimension is a range; # currently this is mainly indended for the general cat case # TODO: extend to I:Indices... (i.e. not necessarily contiguous) -function assign(B::BitArray, X::BitArray, I0::Range1{Int}, I::Union(Integer, Range1{Int})...) +function setindex!(B::BitArray, X::BitArray, I0::Range1{Int}, I::Union(Integer, Range1{Int})...) I = map(x->(isa(x,Integer) ? (x:x) : x), I) - _jl_assign_array2bitarray_ranges(B, X, I0, I...) + assign_array2bitarray_ranges(B, X, I0, I...) end -function assign{T<:Integer}(B::BitArray, x::Number, I::AbstractVector{T}) +function setindex!{T<:Real}(B::BitArray, X::AbstractArray, I::AbstractVector{T}) + if length(X) != length(I); error("argument dimensions must match"); end + count = 1 for i in I - B[i] = x + B[i] = X[count] + count += 1 end return B end -function assign{T<:Number,S<:Integer}(B::BitArray, X::AbstractArray{T}, I::AbstractVector{S}) - if length(X) != length(I); error("argument dimensions must match"); end - for i = 1:length(I) - B[I[i]] = X[i] +function setindex!(B::BitArray, X::AbstractArray, i0::Real) + if length(X) != 1 + error("argument dimensions must match") end - return B + return setindex!(B, X[1], i0) end -let assign_cache = nothing - global assign - function assign(B::BitArray, x::Number, I0::Indices, I::Indices...) - I0 = indices(I0) - I = indices(I) - if is(assign_cache,nothing) - assign_cache = Dict() - end - gen_cartesian_map(assign_cache, ivars->:(B[$(ivars...)] = x), - tuple(I0, I...), - (:B, :x), - B, x) - return B +function setindex!(B::BitArray, X::AbstractArray, i0::Real, i1::Real) + if length(X) != 1 + error("argument dimensions must match") end + return setindex!(B, X[1], i0, i1) end -# note: use of T<:Integer in the following is to disambiguate -assign{T<:Integer,S<:Number}(B::BitArray{T}, X::AbstractArray{S}, I0::Integer) = - (B[I0] = X[1]) +function setindex!(B::BitArray, X::AbstractArray, I0::Real, I::Real...) + if length(X) != 1 + error("argument dimensions must match") + end + return setindex!(B, X[1], i0, I...) +end let assign_cache = nothing - global assign - function assign{T<:Integer,S<:Number}(B::BitArray{T}, X::AbstractArray{S}, I0::Indices, I::Indices...) - I0 = indices(I0) + global setindex! + function setindex!(B::BitArray, X::AbstractArray, I::Union(Real,AbstractArray)...) I = indices(I) - nel = length(I0) + nel = 1 for idx in I nel *= length(idx) end @@ -606,11 +575,8 @@ let assign_cache = nothing error("argument dimensions must match") end if ndims(X) > 1 - if size(X,1) != length(I0) - error("argument dimensions must match") - end for i = 1:length(I) - if size(X,i+1) != length(I[i]) + if size(X,i) != length(I[i]) error("argument dimensions must match") end end @@ -620,79 +586,107 @@ let assign_cache = nothing end gen_cartesian_map(assign_cache, ivars->:(B[$(ivars...)] = X[refind]; refind += 1), - tuple(I0, I...), + I, (:B, :X, :refind), B, X, 1) return B end end +function setindex!{T<:Real}(B::BitArray, x, I::AbstractVector{T}) + for i in I + B[i] = x + end + return B +end + +let assign_cache = nothing + global setindex! + function setindex!(B::BitArray, x, I::Union(Real,AbstractArray)...) + I = indices(I) + if is(assign_cache,nothing) + assign_cache = Dict() + end + gen_cartesian_map(assign_cache, ivars->:(B[$(ivars...)] = x), + I, + (:B, :x), + B, x) + return B + end +end + # logical indexing -function _jl_assign_bool_scalar_1d(A::BitArray, x::Number, I::AbstractArray{Bool}) - n = sum(I) - for i = 1:numel(I) +function assign_bool_scalar_1d(A::BitArray, x, I::AbstractArray{Bool}) + if length(I) > length(A) + throw(BoundsError()) + end + Ac = A.chunks + for i = 1:length(I) if I[i] - A[i] = x + # faster A[i] = x + assign_unchecked(Ac, x, i) end end A end -function _jl_assign_bool_vector_1d{T<:Number}(A::BitArray, X::AbstractArray{T}, I::AbstractArray{Bool}) - n = sum(I) +function assign_bool_vector_1d(A::BitArray, X::AbstractArray, I::AbstractArray{Bool}) + if length(I) > length(A) + throw(BoundsError()) + end + Ac = A.chunks c = 1 - for i = 1:numel(I) + for i = 1:length(I) if I[i] - A[i] = X[c] + # faster A[i] = X[c] + assign_unchecked(Ac, X[c], i) c += 1 end end A end -assign{T<:Number}(A::BitArray, X::AbstractArray{T}, I::AbstractVector{Bool}) = _jl_assign_bool_vector_1d(A, X, I) -assign{T<:Number}(A::BitArray, X::AbstractArray{T}, I::AbstractArray{Bool}) = _jl_assign_bool_vector_1d(A, X, I) -assign(A::BitArray, x::Number, I::AbstractVector{Bool}) = _jl_assign_bool_scalar_1d(A, x, I) -assign(A::BitArray, x::Number, I::AbstractArray{Bool}) = _jl_assign_bool_scalar_1d(A, x, I) +setindex!(A::BitArray, X::AbstractArray, I::AbstractVector{Bool}) = assign_bool_vector_1d(A, X, I) +setindex!(A::BitArray, X::AbstractArray, I::AbstractArray{Bool}) = assign_bool_vector_1d(A, X, I) +setindex!(A::BitArray, x, I::AbstractVector{Bool}) = assign_bool_scalar_1d(A, x, I) +setindex!(A::BitArray, x, I::AbstractArray{Bool}) = assign_bool_scalar_1d(A, x, I) -# note: use of T<:Integer in the following is to disambiguate -assign{T<:Integer,S<:Number}(A::BitMatrix{T}, x::AbstractArray{S}, I::Integer, J::AbstractVector{Bool}) = +setindex!(A::BitMatrix, x::AbstractArray, I::Real, J::AbstractVector{Bool}) = (A[I,find(J)] = x) -assign{T<:Integer}(A::BitMatrix{T}, x::Number, I::Integer, J::AbstractVector{Bool}) = +setindex!(A::BitMatrix, x, I::Real, J::AbstractVector{Bool}) = (A[I,find(J)] = x) -assign{T<:Integer,S<:Number}(A::BitMatrix{T}, x::AbstractArray{S}, I::AbstractVector{Bool}, J::Integer) = +setindex!(A::BitMatrix, x::AbstractArray, I::AbstractVector{Bool}, J::Real) = (A[find(I),J] = x) -assign{T<:Integer}(A::BitMatrix{T}, x::Number, I::AbstractVector{Bool}, J::Integer) = +setindex!(A::BitMatrix, x, I::AbstractVector{Bool}, J::Real) = (A[find(I),J] = x) -assign{T<:Integer,S<:Number}(A::BitMatrix{T}, x::AbstractArray{S}, I::AbstractVector{Bool}, J::AbstractVector{Bool}) = +setindex!(A::BitMatrix, x::AbstractArray, I::AbstractVector{Bool}, J::AbstractVector{Bool}) = (A[find(I),find(J)] = x) -assign{T<:Integer}(A::BitMatrix{T}, x::Number, I::AbstractVector{Bool}, J::AbstractVector{Bool}) = +setindex!(A::BitMatrix, x, I::AbstractVector{Bool}, J::AbstractVector{Bool}) = (A[find(I),find(J)] = x) -assign{T<:Integer,S<:Number,R<:Integer}(A::BitMatrix{T}, x::AbstractArray{S}, I::AbstractVector{R}, J::AbstractVector{Bool}) = +setindex!{T<:Integer}(A::BitMatrix, x::AbstractArray, I::AbstractVector{T}, J::AbstractVector{Bool}) = (A[I,find(J)] = x) -assign{T<:Integer,R<:Integer}(A::BitMatrix{T}, x::Number, I::AbstractVector{R}, J::AbstractVector{Bool}) = +setindex!{T<:Real}(A::BitMatrix, x, I::AbstractVector{T}, J::AbstractVector{Bool}) = (A[I,find(J)] = x) -assign{T<:Integer,S<:Number,R<:Integer}(A::BitMatrix{T}, x::AbstractArray{S}, I::AbstractVector{Bool}, J::AbstractVector{R}) = +setindex!{T<:Real}(A::BitMatrix, x::AbstractArray, I::AbstractVector{Bool}, J::AbstractVector{T}) = (A[find(I),J] = x) -assign{T<:Integer,R<:Integer}(A::BitMatrix{T}, x::Number, I::AbstractVector{Bool}, J::AbstractVector{R}) = +setindex!{T<:Real}(A::BitMatrix, x, I::AbstractVector{Bool}, J::AbstractVector{T}) = (A[find(I),J] = x) ## Dequeue functionality ## -function push{T<:Integer}(B::BitVector{T}, item) +function push!(B::BitVector, item) # convert first so we don't grow the bitarray if the assignment won't work - item = convert(T, item) - _jl_check_is_valid_bit(item) + item = convert(Bool, item) l = @_mod64 length(B) if l == 0 @@ -700,55 +694,57 @@ function push{T<:Integer}(B::BitVector{T}, item) B.chunks[end] = uint64(0) end B.dims[1] += 1 - B[end] = item + if item + B[end] = true + end return B end -function append!{T<:Integer}(B::BitVector{T}, items::BitVector{T}) +function append!(B::BitVector, items::BitVector) n0 = length(B) n1 = length(items) if n1 == 0 return B end k0 = length(B.chunks) - k1 = _jl_num_bit_chunks(n0 + n1) + k1 = num_bit_chunks(n0 + n1) if k1 > k0 ccall(:jl_array_grow_end, Void, (Any, Uint), B.chunks, k1 - k0) B.chunks[end] = uint64(0) end B.dims[1] += n1 - _jl_copy_chunks(B.chunks, n0+1, items.chunks, 1, n1) + copy_chunks(B.chunks, n0+1, items.chunks, 1, n1) return B end -append!{T<:Integer}(B::BitVector{T}, items::BitVector) = append!(B, reinterpret(T, items)) -append!{T<:Integer}(B::BitVector{T}, items::AbstractVector{T}) = append!(B, bitpack(items)) -append!{T<:Integer}(A::Vector{T}, items::BitVector{T}) = append!(A, bitunpack(items)) +append!(B::BitVector, items::AbstractVector{Bool}) = append!(B, bitpack(items)) +append!(A::Vector{Bool}, items::BitVector) = append!(A, bitunpack(items)) -function grow(B::BitVector, n::Integer) - n0 = length(B) - if n < -n0 +function resize!(B::BitVector, n::Integer) + if n < 0 throw(BoundsError()) end - if n < 0 - return del(B, n0+n+1:n0) + n0 = length(B) + if n <= n0 + delete!(B, n+1:n0) + return B end k0 = length(B.chunks) - k1 = _jl_num_bit_chunks(n0 + int(n)) + k1 = num_bit_chunks(int(n)) if k1 > k0 ccall(:jl_array_grow_end, Void, (Any, Uint), B.chunks, k1 - k0) B.chunks[end] = uint64(0) end - B.dims[1] += n + B.dims[1] = n return B end -function pop(B::BitVector) +function pop!(B::BitVector) if isempty(B) - error("pop: BitArray is empty") + error("pop!: BitArray is empty") end item = B[end] - B[end] = 0 + B[end] = false l = @_mod64 length(B) if l == 1 @@ -759,9 +755,8 @@ function pop(B::BitVector) return item end -function enqueue{T<:Integer}(B::BitVector{T}, item) - item = convert(T, item) - _jl_check_is_valid_bit(item) +function unshift!(B::BitVector, item) + item = convert(Bool, item) l = @_mod64 length(B) if l == 0 @@ -780,9 +775,9 @@ function enqueue{T<:Integer}(B::BitVector{T}, item) return B end -function shift(B::BitVector) +function shift!(B::BitVector) if isempty(B) - error("shift: BitArray is empty") + error("shift!: BitArray is empty") end item = B[1] @@ -801,19 +796,18 @@ function shift(B::BitVector) return item end -function insert{T<:Integer}(B::BitVector{T}, i::Integer, item) +function insert!(B::BitVector, i::Integer, item) if i < 1 throw(BoundsError()) end - item = convert(T, item) - _jl_check_is_valid_bit(item) + item = convert(Bool, item) n = length(B) if i > n - x = bitzeros(T, i - n) + x = falses(i - n) append!(B, x) else - k, j = _jl_get_chunks_id(i) + k, j = get_chunks_id(i) l = @_mod64 length(B) if l == 0 @@ -833,13 +827,14 @@ function insert{T<:Integer}(B::BitVector{T}, i::Integer, item) B[i] = item end -function del(B::BitVector, i::Integer) +function delete!(B::BitVector, i::Integer) n = length(B) if !(1 <= i <= n) throw(BoundsError()) end + v = B[i] - k, j = _jl_get_chunks_id(i) + k, j = get_chunks_id(i) msk_bef = _msk64 >>> (63 - j) msk_aft = ~msk_bef @@ -864,10 +859,10 @@ function del(B::BitVector, i::Integer) B.dims[1] -= 1 - return B + return v end -function del(B::BitVector, r::Range1{Int}) +function delete!(B::BitVector, r::Range1{Int}) n = length(B) i_f = first(r) i_l = last(r) @@ -878,11 +873,11 @@ function del(B::BitVector, r::Range1{Int}) return B end - _jl_copy_chunks(B.chunks, i_f, B.chunks, i_l+1, n-i_l) + copy_chunks(B.chunks, i_f, B.chunks, i_l+1, n-i_l) delta_l = i_l - i_f + 1 new_l = length(B) - delta_l - delta_k = length(B.chunks) - _jl_num_bit_chunks(new_l) + delta_k = length(B.chunks) - num_bit_chunks(new_l) if delta_k > 0 ccall(:jl_array_del_end, Void, (Any, Uint), B.chunks, delta_k) @@ -897,7 +892,7 @@ function del(B::BitVector, r::Range1{Int}) return B end -function del_all(B::BitVector) +function empty!(B::BitVector) ccall(:jl_array_del_end, Void, (Any, Uint), B.chunks, length(B.chunks)) B.dims[1] = 0 return B @@ -911,20 +906,20 @@ end ## Unary operators ## -(~)(B::BitArray) = ~bitunpack(B) - -(-)(B::BitArray) = -bitunpack(B) +function (-)(B::BitArray) + A = zeros(Int, size(B)) + for i = 1:length(B) + if B[i] + A[i] = -1 + end + end + return A +end sign(B::BitArray) = copy(B) -real(B::BitArray) = copy(B) -imag{T}(B::BitArray{T}) = bitzeros(T, size(B)) - -conj!(B::BitArray) = B -conj(B::BitArray) = copy(B) - -function flipbits(B::BitArray) - Bc = B.chunks +function (~)(B::BitArray) C = similar(B) + Bc = B.chunks if !isempty(Bc) Cc = C.chunks for i = 1:length(Bc)-1 @@ -936,77 +931,260 @@ function flipbits(B::BitArray) return C end -# Bools have special treatment -(~)(B::BitArray{Bool}) = flipbits(B) -!(B::BitArray{Bool}) = flipbits(B) -(-)(B::BitArray{Bool}) = copy(B) -sign(B::BitArray{Bool}) = convert(BitArray{Int}, B) +function flipbits!(B::BitArray) + Bc = B.chunks + if !isempty(Bc) + for i = 1:length(B.chunks) - 1 + Bc[i] = ~Bc[i] + end + msk = @_msk_end length(B) + Bc[end] = msk & (~Bc[end]) + end + return B +end + +!(B::BitArray) = ~B ## Binary arithmetic operators ## -for f in (:+, :-, :div, :mod, :./, :.^, :/, :\) +for f in (:+, :-) + @eval begin + function ($f)(A::BitArray, B::BitArray) + shp = promote_shape(size(A),size(B)) + reshape(Int[ ($f)(A[i], B[i]) for i=1:length(A) ], shp) + end + function ($f)(B::BitArray, x::Bool) + reshape([ ($f)(B[i], x) for i = 1:length(B) ], size(B)) + end + function ($f)(B::BitArray, x::Number) + pt = promote_array_type(typeof(x), Bool) + reshape((pt)[ ($f)(B[i], x) for i = 1:length(B) ], size(B)) + end + function ($f)(x::Bool, B::BitArray) + reshape([ ($f)(x, B[i]) for i = 1:length(B) ], size(B)) + end + function ($f)(x::Number, B::BitArray) + pt = promote_array_type(typeof(x), Bool) + reshape((pt)[ ($f)(x, B[i]) for i = 1:length(B) ], size(B)) + end + end +end + +function (./)(A::BitArray, B::BitArray) + shp = promote_shape(size(A),size(B)) + reshape([ A[i] ./ B[i] for i=1:length(A) ], shp) +end +function (./)(B::BitArray, x::Number) + reshape([ B[i] ./ x for i = 1:length(B) ], size(B)) +end +function (./)(x::Number, B::BitArray) + reshape([ x ./ B[i] for i = 1:length(B) ], size(B)) +end + +for f in (:/, :\) @eval begin ($f)(A::BitArray, B::BitArray) = ($f)(bitunpack(A), bitunpack(B)) - ($f)(B::BitArray, x::Number) = ($f)(bitunpack(B), x) - ($f)(x::Number, B::BitArray) = ($f)(x, bitunpack(B)) end end +(/)(B::BitArray, x::Number) = (/)(bitunpack(B), x) +(/)(x::Number, B::BitArray) = (/)(x, bitunpack(B)) -for f in (:&, :|, :$) +function div(A::BitArray, B::BitArray) + shp = promote_shape(size(A), size(B)) + all(B) || throw(DivideByZeroError()) + return reshape(copy(A), shp) +end +div(A::BitArray, B::Array{Bool}) = div(A, bitpack(B)) +div(A::Array{Bool}, B::BitArray) = div(bitpack(A), B) +function div(B::BitArray, x::Bool) + return x ? copy(B) : throw(DivideByZeroError()) +end +function div(x::Bool, B::BitArray) + all(B) || throw(DivideByZeroError()) + return x ? trues(size(B)) : falses(size(B)) +end +function div(x::Number, B::BitArray) + all(B) || throw(DivideByZeroError) + pt = promote_array_type(typeof(x), Bool) + y = div(x, true) + reshape(pt[ y for i = 1:length(B) ], size(B)) +end + +function mod(A::BitArray, B::BitArray) + shp = promote_shape(size(A), size(B)) + all(B) || throw(DivideByZeroError()) + return falses(shp) +end +mod(A::BitArray, B::Array{Bool}) = mod(A, bitpack(B)) +mod(A::Array{Bool}, B::BitArray) = mod(bitpack(A), B) +function mod(B::BitArray, x::Bool) + return x ? falses(size(B)) : throw(DivideByZeroError()) +end +function mod(x::Bool, B::BitArray) + all(B) || throw(DivideByZeroError()) + return falses(size(B)) +end +function mod(x::Number, B::BitArray) + all(B) || throw(DivideByZeroError) + pt = promote_array_type(typeof(x), Bool) + y = mod(x, true) + reshape(pt[ y for i = 1:length(B) ], size(B)) +end + +for f in (:div, :mod) @eval begin - function ($f){T<:Integer}(A::BitArray{T}, B::BitArray{T}) - F = BitArray(T, promote_shape(size(A),size(B))...) - fc = F.chunks - ac = A.chunks - bc = B.chunks - if !isempty(ac) && !isempty(bc) - for i = 1:length(F.chunks) - 1 - fc[i] = ($f)(ac[i], bc[i]) - end - msk = @_msk_end length(F) - F.chunks[end] = msk & ($f)(A.chunks[end], B.chunks[end]) + function ($f)(B::BitArray, x::Number) + F = Array(promote_array_type(typeof(x), Bool), size(B)) + for i = 1:length(F) + F[i] = ($f)(B[i], x) end return F end - ($f)(x::Number, B::BitArray) = ($f)(x, bitunpack(B)) - ($f)(A::BitArray, x::Number) = ($f)(x, A) end end -(.*){T<:Integer}(A::BitArray{T}, B::BitArray{T}) = A & B -(.*)(x::Number, B::BitArray) = x .* bitunpack(B) -(.*)(A::BitArray, x::Number) = x .* A +function (&)(B::BitArray, x::Bool) + x ? copy(B) : falses(size(B)) +end +(&)(x::Bool, B::BitArray) = B & x -for f in (:+, :-, :div, :mod, :./, :.^, :.*, :&, :|, :$) +function (|)(B::BitArray, x::Bool) + x ? trues(size(B)) : copy(B) +end +(|)(x::Bool, B::BitArray) = B | x + +function ($)(B::BitArray, x::Bool) + x ? ~B : copy(B) +end +($)(x::Bool, B::BitArray) = B $ x + +for f in (:&, :|, :$) @eval begin - ($f)(A::BitArray, B::AbstractArray) = ($f)(bitunpack(A), B) - ($f)(A::AbstractArray, B::BitArray) = ($f)(A, bitunpack(B)) + function ($f)(A::BitArray, B::BitArray) + F = BitArray(promote_shape(size(A),size(B))...) + Fc = F.chunks + Ac = A.chunks + Bc = B.chunks + if !isempty(Ac) && !isempty(Bc) + for i = 1:length(Fc) - 1 + Fc[i] = ($f)(Ac[i], Bc[i]) + end + msk = @_msk_end length(F) + Fc[end] = msk & ($f)(Ac[end], Bc[end]) + end + return F + end + ($f)(A::Array{Bool}, B::BitArray) = ($f)(bitpack(A), B) + ($f)(B::BitArray, A::Array{Bool}) = ($f)(B, bitpack(A)) + ($f)(x::Number, B::BitArray) = ($f)(x, bitunpack(B)) + ($f)(B::BitArray, x::Number) = ($f)(bitunpack(B), x) end end -# specialized Bool versions -function (&)(x::Number, B::BitArray{Bool}) - if bool(x) - return copy(B) - else - return bitzeros(Bool, size(B)) +function (.^)(A::BitArray, B::BitArray) + F = BitArray(promote_shape(size(A),size(B))...) + Fc = F.chunks + Ac = A.chunks + Bc = B.chunks + if !isempty(Ac) && !isempty(Bc) + for i = 1:length(Fc) - 1 + Fc[i] = Ac[i] | ~Bc[i] + end + msk = @_msk_end length(F) + Fc[end] = msk & (Ac[end] | ~Bc[end]) end + return F +end +(.^)(A::Array{Bool}, B::BitArray) = (.^)(bitpack(A), B) +(.^)(B::BitArray, A::Array{Bool}) = (.^)(B, bitpack(A)) +function (.^)(B::BitArray, x::Bool) + x ? copy(B) : trues(size(B)) +end +function (.^)(x::Bool, B::BitArray) + x ? trues(size(B)) : ~B +end +function (.^){T<:Number}(x::T, B::BitArray) + z = x ^ false + u = x ^ true + reshape([ B[i] ? u : z for i = 1:length(B) ], size(B)) end -function (|)(x::Number, B::BitArray{Bool}) - if bool(x) - return bitones(Bool, size(B)) +function (.^){T<:Integer}(B::BitArray, x::T) + if x == 0 + return trues(size(B)) + elseif x < 0 + throw(DomainError()) else return copy(B) end end -function ($)(x::Number, B::BitArray{Bool}) - if bool(x) - return ~B +function (.^){T<:Number}(B::BitArray, x::T) + if x == 0 + return ones(typeof(true ^ x), size(B)) + elseif T <: Real && x > 0 + return convert(Array{T}, B) else - return copy(B) + z = nothing + u = nothing + zerr = nothing + uerr = nothing + try + z = false .^ x + catch err + zerr = err + end + try + u = true .^ x + catch err + uerr = err + end + if zerr == nothing && uerr == nothing + t = promote_type(typeof(z), typeof(u)) + elseif zerr == nothing + t = typeof(z) + else + t = typeof(u) + end + F = Array(t, size(B)) + for i = 1:length(B) + if B[i] + if uerr == nothing + F[i] = u + else + throw(uerr) + end + else + if zerr == nothing + F[i] = z + else + throw(zerr) + end + end + end + return F + end +end +function (.^){T<:Integer}(A::BitArray, B::Array{T}) + F = BitArray(promote_shape(size(A),size(B))...) + for i = 1:length(A) + F[i] = A[i] .^ B[i] + end + return F +end + +(.*)(A::BitArray, B::BitArray) = A & B +(.*)(A::Array{Bool}, B::BitArray) = A & B +(.*)(B::BitArray, A::Array{Bool}) = A & B +(.*)(x::Bool, B::BitArray) = x & B +(.*)(B::BitArray, x::Bool) = B & x +(.*)(x::Number, B::BitArray) = x .* bitunpack(B) +(.*)(B::BitArray, x::Number) = bitunpack(B) .* x + +for f in (:+, :-, :div, :mod, :./, :.^, :.*, :&, :|, :$) + @eval begin + ($f)(A::BitArray, B::AbstractArray) = ($f)(bitunpack(A), B) + ($f)(A::AbstractArray, B::BitArray) = ($f)(A, bitunpack(B)) end end -(.*)(x::Number, B::BitArray{Bool}) = x & B ## promotion to complex ## @@ -1014,44 +1192,33 @@ end ## element-wise comparison operators returning BitArray{Bool} ## -for (f,scalarf,t) in ((:(.==),:(==),:Number), - (:.<, :<,:Real), - (:.!=,:!=,:Number), - (:.<=,:<=,:Real)) +for (f,scalarf) in ((:(.==),:(==)), + (:.<, :<), + (:.!=,:!=), + (:.<=,:<=)) @eval begin function ($f)(A::AbstractArray, B::AbstractArray) - F = BitArray(Bool, promote_shape(size(A),size(B))) - for i = 1:numel(B) + F = BitArray(promote_shape(size(A),size(B))) + for i = 1:length(B) F[i] = ($scalarf)(A[i], B[i]) end return F end - ($f)(A, B::AbstractArray) = - reshape([ ($scalarf)(A, B[i]) for i=1:length(B)], size(B)) - ($f)(A::AbstractArray, B) = - reshape([ ($scalarf)(A[i], B) for i=1:length(A)], size(A)) - - function ($f)(x::($t), B::BitArray) - F = similar(B, Bool) - for i = 1:numel(F) - F[i] = ($scalarf)(x, B[i]) + function ($f)(A, B::AbstractArray) + F = BitArray(size(B)) + for i = 1:length(F) + F[i] = ($scalarf)(A, B[i]) end return F end - function ($f)(A::BitArray, x::($t)) - F = similar(A, Bool) - for i = 1:numel(F) - F[i] = ($scalarf)(A[i], x) + function ($f)(A::AbstractArray, B) + F = BitArray(size(A)) + for i = 1:length(F) + F[i] = ($scalarf)(A[i], B) end return F end - end -end -for f in (:(==), :(.==), :!=, :.!=, :<, :.<, :<=, :.<=) - @eval begin - ($f)(A::BitArray, B::Array) = ($f)(bitunpack(A), B) - ($f)(A::Array, B::BitArray) = ($f)(A, bitunpack(B)) end end @@ -1081,6 +1248,16 @@ function (!=)(A::BitArray, B::BitArray) return false end +for f in (:(==), :!=) + @eval begin + ($f)(A::BitArray, B::AbstractArray{Bool}) = ($f)(A, bitpack(B)) + ($f)(A::AbstractArray{Bool}, B::BitArray) = ($f)(bitpack(A), B) + ($f)(A::BitArray, B::AbstractArray) = ($f)(bitunpack(A), B) + ($f)(A::AbstractArray, B::BitArray) = ($f)(A, bitunpack(B)) + end +end + + ## Data movement ## # TODO some of this could be optimized @@ -1091,10 +1268,10 @@ function slicedim(A::BitArray, d::Integer, i::Integer) d_out = tuple(leading..., 1, d_in[(d+1):end]...) M = prod(leading) - N = numel(A) + N = length(A) stride = M * d_in[d] - B = similar(A, d_out) + B = BitArray(d_out) index_offset = 1 + (i-1)*M l = 1 @@ -1140,7 +1317,7 @@ function flipdim(A::BitArray, d::Integer) d_in = size(A) leading = d_in[1:(d-1)] M = prod(leading) - N = numel(A) + N = length(A) stride = M * sd if M==1 @@ -1156,49 +1333,21 @@ function flipdim(A::BitArray, d::Integer) for j=0:stride:(N-stride) offs = j + 1 + (i-1)*M boffs = j + 1 + (ri-1)*M - _jl_copy_chunks(B.chunks, boffs, A.chunks, offs, M) + copy_chunks(B.chunks, boffs, A.chunks, offs, M) end end end return B end -function rotl90(A::BitMatrix) - m,n = size(A) - B = similar(A,(n,m)) - for i=1:m, j=1:n - B[n-j+1,i] = A[i,j] - end - return B -end -function rotr90(A::BitMatrix) - m,n = size(A) - B = similar(A,(n,m)) - for i=1:m, j=1:n - B[j,m-i+1] = A[i,j] - end - return B -end -function rot180(A::BitMatrix) - m,n = size(A) - B = similar(A) - for i=1:m, j=1:n - B[m-i+1,n-j+1] = A[i,j] - end - return B -end - -# implemented as a macro to improve performance -macro _jl_reverse_bits(dest, src) - quote - z = $(esc(src)) - z = ((z >>> 1) & 0x5555555555555555) | ((z << 1) & 0xaaaaaaaaaaaaaaaa) - z = ((z >>> 2) & 0x3333333333333333) | ((z << 2) & 0xcccccccccccccccc) - z = ((z >>> 4) & 0x0f0f0f0f0f0f0f0f) | ((z << 4) & 0xf0f0f0f0f0f0f0f0) - z = ((z >>> 8) & 0x00ff00ff00ff00ff) | ((z << 8) & 0xff00ff00ff00ff00) - z = ((z >>> 16) & 0x0000ffff0000ffff) | ((z << 16) & 0xffff0000ffff0000) - $(esc(dest)) = ((z >>> 32) & 0x00000000ffffffff) | ((z << 32) & 0xffffffff00000000) - end +function reverse_bits(src::Uint64) + z = src + z = ((z >>> 1) & 0x5555555555555555) | ((z << 1) & 0xaaaaaaaaaaaaaaaa) + z = ((z >>> 2) & 0x3333333333333333) | ((z << 2) & 0xcccccccccccccccc) + z = ((z >>> 4) & 0x0f0f0f0f0f0f0f0f) | ((z << 4) & 0xf0f0f0f0f0f0f0f0) + z = ((z >>> 8) & 0x00ff00ff00ff00ff) | ((z << 8) & 0xff00ff00ff00ff00) + z = ((z >>> 16) & 0x0000ffff0000ffff) | ((z << 16) & 0xffff0000ffff0000) + return ((z >>> 32) & 0x00000000ffffffff) | ((z << 32) & 0xffffffff00000000) end function reverse!(B::BitVector) @@ -1213,10 +1362,10 @@ function reverse!(B::BitVector) for i = 1 : hnc j = ((i - 1) << 6) - @_jl_reverse_bits aux_chunks[1] B.chunks[i] - _jl_copy_chunks(B.chunks, j+1, B.chunks, n-63-j, 64) - @_jl_reverse_bits B.chunks[i] B.chunks[i] - _jl_copy_chunks(B.chunks, n-63-j, aux_chunks, 1, 64) + aux_chunks[1] = reverse_bits(B.chunks[i]) + copy_chunks(B.chunks, j+1, B.chunks, n-63-j, 64) + B.chunks[i] = reverse_bits(B.chunks[i]) + copy_chunks(B.chunks, n-63-j, aux_chunks, 1, 64) end if pnc == 0 @@ -1228,132 +1377,157 @@ function reverse!(B::BitVector) l = (@_mod64 (n+63)) + 1 msk = @_mskr l - @_jl_reverse_bits aux_chunks[1] (B.chunks[i] & msk) + aux_chunks[1] = reverse_bits(B.chunks[i] & msk) aux_chunks[1] >>>= (64 - l) - _jl_copy_chunks(B.chunks, j+1, aux_chunks, 1, l) + copy_chunks(B.chunks, j+1, aux_chunks, 1, l) return B end reverse(v::BitVector) = reverse!(copy(v)) -function (<<){T}(B::BitVector{T}, i::Int64) +function (<<)(B::BitVector, i::Int64) n = length(B) i %= n if i == 0; return copy(B); end - A = bitzeros(T, n); - _jl_copy_chunks(A.chunks, 1, B.chunks, i+1, n-i) + A = falses(n); + copy_chunks(A.chunks, 1, B.chunks, i+1, n-i) return A end -(<<){T}(B::BitVector{T}, i::Int32) = B << int64(i) -(<<){T}(B::BitVector{T}, i::Integer) = B << int64(i) +(<<)(B::BitVector, i::Int32) = B << int64(i) +(<<)(B::BitVector, i::Integer) = B << int64(i) -function (>>>){T}(B::BitVector{T}, i::Int64) +function (>>>)(B::BitVector, i::Int64) n = length(B) i %= n if i == 0; return copy(B); end - A = bitzeros(T, n); - _jl_copy_chunks(A.chunks, i+1, B.chunks, 1, n-i) + A = falses(n); + copy_chunks(A.chunks, i+1, B.chunks, 1, n-i) return A end -(>>>){T}(B::BitVector{T}, i::Int32) = B >>> int64(i) -(>>>){T}(B::BitVector{T}, i::Integer) = B >>> int64(i) +(>>>)(B::BitVector, i::Int32) = B >>> int64(i) +(>>>)(B::BitVector, i::Integer) = B >>> int64(i) (>>)(B::BitVector, i::Int32) = B >>> i (>>)(B::BitVector, i::Integer) = B >>> i -function rotl{T}(B::BitVector{T}, i::Integer) +function rol(B::BitVector, i::Integer) n = length(B) i %= n if i == 0; return copy(B); end - A = BitArray(T, n); - _jl_copy_chunks(A.chunks, 1, B.chunks, i+1, n-i) - _jl_copy_chunks(A.chunks, n-i+1, B.chunks, 1, i) + A = BitArray(n); + copy_chunks(A.chunks, 1, B.chunks, i+1, n-i) + copy_chunks(A.chunks, n-i+1, B.chunks, 1, i) return A end -function rotr{T}(B::BitVector{T}, i::Integer) +function ror(B::BitVector, i::Integer) n = length(B) i %= n if i == 0; return copy(B); end - A = BitArray(T, n); - _jl_copy_chunks(A.chunks, i+1, B.chunks, 1, n-i) - _jl_copy_chunks(A.chunks, 1, B.chunks, n-i+1, i) + A = BitArray(n); + copy_chunks(A.chunks, i+1, B.chunks, 1, n-i) + copy_chunks(A.chunks, 1, B.chunks, n-i+1, i) return A end +#TODO: rol!, ror! ## nnz & find ## function nnz(B::BitArray) n = 0 - for i = 1:length(B.chunks) - n += count_ones(B.chunks[i]) + Bc = B.chunks + for i = 1:length(Bc) + n += count_ones(Bc[i]) end return n end -# returns the index of the first non-zero element, or 0 if all zeros -function findfirst(B::BitArray) - for i = 1:length(B.chunks) - if B.chunks[i] != 0 - return (i-1) << 6 + trailing_zeros(B.chunks[i]) + 1 +# returns the index of the next non-zero element, or 0 if all zeros +function findnext(B::BitArray, start::Integer) + Bc = B.chunks + + chunk_start = @_div64(start-1)+1 + within_chunk_start = @_mod64(start-1) + mask = _msk64 << within_chunk_start + + if Bc[chunk_start] & mask != 0 + return (chunk_start-1) << 6 + trailing_zeros(Bc[chunk_start] & mask) + 1 + end + + for i = chunk_start+1:length(Bc) + if Bc[i] != 0 + return (i-1) << 6 + trailing_zeros(Bc[i]) + 1 end end return 0 end +#findfirst(B::BitArray) = findnext(B, 1) ## defined in array.jl # aux function: same as findfirst(~B), but performed without temporaries -function _jl_findfirstnot(B::BitArray) - l = length(B.chunks) +function findnextnot(B::BitArray, start::Integer) + Bc = B.chunks + l = length(Bc) if l == 0 return 0 end - for i = 1:l-1 - if B.chunks[i] != _msk64 - return (i-1) << 6 + trailing_ones(B.chunks[i]) + 1 + + chunk_start = @_div64(start-1)+1 + within_chunk_start = @_mod64(start-1) + mask = ~(_msk64 << within_chunk_start) + + if Bc[chunk_start] | mask != _msk64 + return (chunk_start-1) << 6 + trailing_ones(Bc[chunk_start] | mask) + 1 + end + + for i = chunk_start+1:l-1 + if Bc[i] != _msk64 + return (i-1) << 6 + trailing_ones(Bc[i]) + 1 end end - ce = B.chunks[end] + ce = Bc[end] if ce != @_msk_end length(B) return (l-1) << 6 + trailing_ones(ce) + 1 end return 0 end +findfirstnot(B::BitArray) = findnextnot(B,1) # returns the index of the first matching element -function findfirst{T}(B::BitArray{T}, v) - if v == zero(T) - return _jl_findfirstnot(B) - elseif v == one(T) - return findfirst(B) +function findnext(B::BitArray, v, start::Integer) + if v == false + return findnextnot(B, start) + elseif v == true + return findnext(B, start) else return 0 end end +#findfirst(B::BitArray, v) = findnext(B, 1, v) ## defined in array.jl # returns the index of the first element for which the function returns true -function findfirst{T}(testf::Function, B::BitArray{T}) - f0::Bool = testf(zero(T)) - f1::Bool = testf(one(T)) +function findnext(testf::Function, B::BitArray, start::Integer) + f0::Bool = testf(false) + f1::Bool = testf(true) if length(B) == 0 || !(f0 || f1) return 0 elseif f0 && f1 return 1 elseif !f0 && f1 - return findfirst(B) + return findnext(B, start) else - return _jl_findfirstnot(B) + return findnextnot(B, start) end end +#findfirst(testf::Function, B::BitArray) = findnext(testf, B, 1) ## defined in array.jl -function find{T<:Integer}(B::BitArray{T}) +function find(B::BitArray) nnzB = nnz(B) I = Array(Int, nnzB) - z = zero(T) count = 1 for i = 1:length(B) - if B[i] != z + if B[i] I[count] = i count += 1 end @@ -1363,14 +1537,13 @@ end findn(B::BitVector) = find(B) -function findn{T<:Integer}(B::BitMatrix{T}) +function findn(B::BitMatrix) nnzB = nnz(B) I = Array(Int, nnzB) J = Array(Int, nnzB) - z = zero(T) count = 1 for j=1:size(B,2), i=1:size(B,1) - if !isequal(B[i,j], z) + if B[i,j] I[count] = i J[count] = j count += 1 @@ -1383,16 +1556,16 @@ let findn_cache = nothing function findn_one(ivars) s = { quote I[$i][count] = $(ivars[i]) end for i = 1:length(ivars)} quote - Bind = B[$(ivars...)] - if Bind != z - $(s...) - count +=1 - end + Bind = B[$(ivars...)] + if Bind + $(s...) + count +=1 + end end end global findn -function findn{T}(B::BitArray{T}) +function findn(B::BitArray) ndimsB = ndims(B) nnzB = nnz(B) I = ntuple(ndimsB, x->Array(Int, nnzB)) @@ -1404,55 +1577,96 @@ function findn{T}(B::BitArray{T}) end gen_cartesian_map(findn_cache, findn_one, ranges, - (:B, :I, :count, :z), B, I, 1, zero(T)) + (:B, :I, :count), B, I, 1) end return I end end -function findn_nzs{T<:Integer}(B::BitMatrix{T}) +function findnz(B::BitMatrix) I, J = findn(B) - return (I, J, bitones(T, length(I))) + return (I, J, trues(length(I))) end -nonzeros{T<:Integer}(B::BitArray{T}) = bitones(T, nnz(B)) +nonzeros(B::BitArray) = trues(nnz(B)) ## Reductions ## -sum(A::BitArray, region::Dimspec) = areduce(+,A,region,0,Array(Int,reduced_dims(A,region))) +sum(A::BitArray, region) = reducedim(+,A,region,0,Array(Int,reduced_dims(A,region))) + +sum(B::BitArray) = nnz(B) + +function all(B::BitArray) + if length(B) == 0 + return true + end + Bc = B.chunks + for i = 1:length(Bc)-1 + if Bc[i] != _msk64 + return false + end + end + if Bc[end] != @_msk_end length(B) + return false + end + return true +end + +function any(B::BitArray) + if length(B) == 0 + return false + end + Bc = B.chunks + for i = 1:length(Bc) + if Bc[i] != 0 + return true + end + end + return false +end + +min(B::BitArray) = isempty(B) ? error("min: argument is empty") : all(B) +max(B::BitArray) = isempty(B) ? error("max: argument is empty") : any(B) ## map over bitarrays ## -function map_to(f, dest::BitArray, A::Union(StridedArray,BitArray)) - for i=1:numel(A) +function map!(f, A::Union(StridedArray,BitArray)) + for i=1:length(A) + A[i] = f(A[i]) + end + return A +end + +function map!(f, dest::Union(StridedArray,BitArray), A::Union(StridedArray,BitArray)) + for i=1:length(A) dest[i] = f(A[i]) end return dest end -function map_to(f, dest::BitArray, A::Union(StridedArray,BitArray), B::Union(StridedArray,BitArray)) - for i=1:numel(A) +function map!(f, dest::Union(StridedArray,BitArray), A::Union(StridedArray,BitArray), B::Union(StridedArray,BitArray)) + for i=1:length(A) dest[i] = f(A[i], B[i]) end return dest end -function map_to(f, dest::BitArray, A::Union(StridedArray,BitArray), B::Number) - for i=1:numel(A) +function map!(f, dest::Union(StridedArray,BitArray), A::Union(StridedArray,BitArray), B::Number) + for i=1:length(A) dest[i] = f(A[i], B) end return dest end -function map_to(f, dest::BitArray, A::Number, B::Union(StridedArray,BitArray)) - for i=1:numel(B) +function map!(f, dest::Union(StridedArray,BitArray), A::Number, B::Union(StridedArray,BitArray)) + for i=1:length(B) dest[i] = f(A, B[i]) end return dest end -function map_to(f, dest::BitArray, As::Union(StridedArray,BitArray)...) - n = numel(As[1]) +function map!(f, dest::Union(StridedArray,BitArray), As::Union(StridedArray,BitArray)...) + n = length(As[1]) i = 1 ith = a->a[i] for i=1:n @@ -1474,23 +1688,20 @@ transpose(B::BitVector) = reshape(copy(B), 1, length(B)) # fast 8x8 bit transpose from Henry S. Warrens's "Hacker's Delight" # http://www.hackersdelight.org/HDcode/transpose8.c.txt -# implemented as a macro to improve performance -macro _jl_transpose8x8(x) - quote - y = $(esc(x)) - t = (y $ (y >>> 7)) & 0x00aa00aa00aa00aa; - y = y $ t $ (t << 7) - t = (y $ (y >>> 14)) & 0x0000cccc0000cccc - y = y $ t $ (t << 14) - t = (y $ (y >>> 28)) & 0x00000000f0f0f0f0 - $(esc(x)) = y $ t $ (t << 28) - end +function transpose8x8(x::Uint64) + y = x + t = (y $ (y >>> 7)) & 0x00aa00aa00aa00aa + y = y $ t $ (t << 7) + t = (y $ (y >>> 14)) & 0x0000cccc0000cccc + y = y $ t $ (t << 14) + t = (y $ (y >>> 28)) & 0x00000000f0f0f0f0 + return y $ t $ (t << 28) end -function _jl_form_8x8_chunk(B::BitMatrix, i1::Int, i2::Int, m::Int, cgap::Int, cinc::Int, nc::Int, msk8::Uint64) +function form_8x8_chunk(B::BitMatrix, i1::Int, i2::Int, m::Int, cgap::Int, cinc::Int, nc::Int, msk8::Uint64) x = uint64(0) - k, l = _jl_get_chunks_id(i1 + (i2 - 1) * m) + k, l = get_chunks_id(i1 + (i2 - 1) * m) r = 0 for j = 1 : 8 if k > nc @@ -1509,8 +1720,8 @@ function _jl_form_8x8_chunk(B::BitMatrix, i1::Int, i2::Int, m::Int, cgap::Int, c end # note: assumes B is filled with 0's -function _jl_put_8x8_chunk(B::BitMatrix, i1::Int, i2::Int, x::Uint64, m::Int, cgap::Int, cinc::Int, nc::Int, msk8::Uint64) - k, l = _jl_get_chunks_id(i1 + (i2 - 1) * m) +function put_8x8_chunk(B::BitMatrix, i1::Int, i2::Int, x::Uint64, m::Int, cgap::Int, cinc::Int, nc::Int, msk8::Uint64) + k, l = get_chunks_id(i1 + (i2 - 1) * m) r = 0 for j = 1 : 8 if k > nc @@ -1528,10 +1739,10 @@ function _jl_put_8x8_chunk(B::BitMatrix, i1::Int, i2::Int, x::Uint64, m::Int, cg return end -function transpose{T<:Integer}(B::BitMatrix{T}) +function transpose(B::BitMatrix) l1 = size(B, 1) l2 = size(B, 2) - Bt = bitzeros(T, l2, l1) + Bt = falses(l2, l1) cgap1 = @_div64 l1 cinc1 = @_mod64 l1 @@ -1549,15 +1760,15 @@ function transpose{T<:Integer}(B::BitMatrix{T}) end for j = 1 : 8 : l2 - x = _jl_form_8x8_chunk(B, i, j, l1, cgap1, cinc1, nc, msk8_1) - @_jl_transpose8x8 x + x = form_8x8_chunk(B, i, j, l1, cgap1, cinc1, nc, msk8_1) + x = transpose8x8(x) msk8_2 = uint64(0xff) if (l2 < j + 7) msk8_2 >>>= j + 7 - l2 end - _jl_put_8x8_chunk(Bt, j, i, x, l2, cgap2, cinc2, nc, msk8_2) + put_8x8_chunk(Bt, j, i, x, l2, cgap2, cinc2, nc, msk8_2) end end return Bt @@ -1565,22 +1776,26 @@ end ctranspose(B::BitArray) = transpose(B) -## Permute ## +## Permute array dims ## -let permute_cache = nothing, stridenames::Array{Any,1} = {} -global permute -function permute(B::BitArray, perm) +let permutedims_cache = nothing, stridenames::Array{Any,1} = {} +global permutedims +function permutedims(B::Union(BitArray,StridedArray), perm) dimsB = size(B) ndimsB = length(dimsB) dimsP = ntuple(ndimsB, i->dimsB[perm[i]]) P = similar(B, dimsP) - ranges = ntuple(ndimsB, i->(colon(1,dimsP[i]))) + ranges = ntuple(ndimsB, i->(1:dimsP[i])) while length(stridenames) < ndimsB - push(stridenames, gensym()) + push!(stridenames, gensym()) end #calculates all the strides - strides = [ prod(dimsB[1:(perm[dim]-1)])::Int for dim = 1:length(perm) ] + if isa(B,BitArray) + strides = [ prod(dimsB[1:(perm[dim]-1)])::Int for dim = 1:length(perm) ] + else + strides = [ stride(B, perm[dim]) for dim = 1:length(perm) ] + end #Creates offset, because indexing starts at 1 offset = 0 @@ -1589,11 +1804,16 @@ function permute(B::BitArray, perm) end offset = 1-offset - function permute_one(ivars) + if isa(B,SubArray) + offset += (B.first_index-1) + B = B.parent + end + + function permute_one_dim(ivars) len = length(ivars) - counts = { gensym() for i=1:len} + counts = { symbol(string("count",i)) for i=1:len} toReturn = cell(len+1,2) - for i = 1:numel(toReturn) + for i = 1:length(toReturn) toReturn[i] = nothing end @@ -1624,11 +1844,11 @@ function permute(B::BitArray, perm) toReturn end - if is(permute_cache,nothing) - permute_cache = Dict() + if is(permutedims_cache,nothing) + permutedims_cache = Dict() end - gen_cartesian_map(permute_cache, permute_one, ranges, + gen_cartesian_map(permutedims_cache, permute_one_dim, ranges, tuple(:B, :P, :perm, :offset, stridenames[1:ndimsB]...), B, P, perm, offset, strides...) @@ -1638,33 +1858,33 @@ end # let ## Concatenation ## -function hcat{T}(B::BitVector{T}...) +function hcat(B::BitVector...) height = length(B[1]) for j = 2:length(B) if length(B[j]) != height; error("hcat: mismatched dimensions"); end end - M = BitArray(T, height, length(B)) + M = BitArray(height, length(B)) for j = 1:length(B) - _jl_copy_chunks(M.chunks, (height*(j-1))+1, B[j].chunks, 1, height) + copy_chunks(M.chunks, (height*(j-1))+1, B[j].chunks, 1, height) end return M end -function vcat{T}(V::BitVector{T}...) +function vcat(V::BitVector...) n = 0 for Vk in V n += length(Vk) end - B = BitArray(T, n) + B = BitArray(n) j = 1 for Vk in V - _jl_copy_chunks(B.chunks, j, Vk.chunks, 1, length(Vk)) + copy_chunks(B.chunks, j, Vk.chunks, 1, length(Vk)) j += length(Vk) end return B end -function hcat{T}(A::Union(BitMatrix{T},BitVector{T})...) +function hcat(A::Union(BitMatrix,BitVector)...) nargs = length(A) nrows = size(A[1], 1) ncols = 0 @@ -1676,32 +1896,32 @@ function hcat{T}(A::Union(BitMatrix{T},BitVector{T})...) if size(Aj, 1) != nrows; error("hcat: mismatched dimensions"); end end - B = BitArray(T, nrows, ncols) + B = BitArray(nrows, ncols) pos = 1 for k=1:nargs Ak = A[k] - n = numel(Ak) - _jl_copy_chunks(B.chunks, pos, Ak.chunks, 1, n) + n = length(Ak) + copy_chunks(B.chunks, pos, Ak.chunks, 1, n) pos += n end return B end -function vcat{T}(A::BitMatrix{T}...) +function vcat(A::BitMatrix...) nargs = length(A) nrows = sum(a->size(a, 1), A)::Int ncols = size(A[1], 2) for j = 2:nargs if size(A[j], 2) != ncols; error("vcat: mismatched dimensions"); end end - B = BitArray(T, nrows, ncols) + B = BitArray(nrows, ncols) nrowsA = [size(a, 1) for a in A] pos_d = 1 pos_s = ones(Int, nargs) for j = 1:ncols for k=1:nargs - _jl_copy_chunks(B.chunks, pos_d, A[k].chunks, pos_s[k], nrowsA[k]) + copy_chunks(B.chunks, pos_d, A[k].chunks, pos_s[k], nrowsA[k]) pos_s[k] += nrowsA[k] pos_d += nrowsA[k] end @@ -1710,7 +1930,7 @@ function vcat{T}(A::BitMatrix{T}...) end # general case, specialized for BitArrays and Integers -function cat{T}(catdim::Integer, X::Union(BitArray{T}, Integer)...) +function cat(catdim::Integer, X::Union(BitArray, Integer)...) nargs = length(X) # using integers results in conversion to Array{Int} # (except in the all-Bool case) @@ -1771,7 +1991,7 @@ function cat{T}(catdim::Integer, X::Union(BitArray{T}, Integer)...) dimsC = ntuple(ndimsC, compute_dims)::(Int...) typeC = promote_type(map(x->isa(x,BitArray) ? eltype(x) : typeof(x), X)...) if !has_integer || typeC == Bool - C = BitArray(typeC, dimsC) + C = BitArray(dimsC) else C = Array(typeC, dimsC) end @@ -1791,43 +2011,8 @@ end # hvcat -> use fallbacks in abstractarray.jl -## Reductions and scans ## - isequal(A::BitArray, B::BitArray) = (A == B) -function cumsum{T}(v::BitVector{T}) - n = length(v) - c = Array(T, n) - if n == 0; return c; end +# Hashing - c[1] = v[1] - for i=2:n - c[i] = v[i] + c[i-1] - end - return c -end -function cumsum(v::BitVector{Bool}) - n = length(v) - c = bitones(Bool, n) - for i=1:n - if !v[i] - c[i] = false - else - break - end - end - return c -end - -function cumprod{T}(v::BitVector{T}) - n = length(v) - c = bitzeros(T, n) - for i=1:n - if v[i] == one(T) - c[i] = one(T) - else - break - end - end - return c -end +hash(B::BitArray) = hash({B.dims, B.chunks}) diff --git a/base/blas.jl b/base/blas.jl deleted file mode 100644 index 31ab320ddc6a1..0000000000000 --- a/base/blas.jl +++ /dev/null @@ -1,440 +0,0 @@ -typealias LapackType Union(Float64,Float32,Complex128,Complex64) - -module BLAS - -export copy!, - scal!, - scal, - dot, - nrm2, - axpy!, - syrk!, - syrk, - herk!, - herk, - gbmv!, - gbmv, - sbmv!, - sbmv, - gemm!, - gemm, - symm!, - symm, - symv!, - symv - -libblas = Base.libblas_name - -# SUBROUTINE DCOPY(N,DX,INCX,DY,INCY) -for (fname, elty) in ((:dcopy_,:Float64), (:scopy_,:Float32), - (:zcopy_,:Complex128), (:ccopy_,:Complex64)) - @eval begin - function copy!(n::Integer, DX::Union(Ptr{$elty},Array{$elty}), incx::Integer, DY::Union(Ptr{$elty},Array{$elty}), incy::Integer) - ccall(($(string(fname)),libblas), Void, - (Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}), - &n, DX, &incx, DY, &incy) - DY - end - end -end - -# SUBROUTINE DSCAL(N,DA,DX,INCX) -for (fname, elty) in ((:dscal_,:Float64), (:sscal_,:Float32), - (:zscal_,:Complex128), (:cscal_,:Complex64)) - @eval begin - function scal!(n::Integer, DA::$elty, DX::Union(Ptr{$elty},Array{$elty}), incx::Integer) - ccall(($(string(fname)),libblas), Void, - (Ptr{Int32}, Ptr{$elty}, Ptr{$elty}, Ptr{Int32}), - &n, &DA, DX, &incx) - DX - end - function scal(n::Integer, DA::$elty, DX_orig::Union(Ptr{$elty},Array{$elty}), incx::Integer) - DX = copy(DX_orig) - ccall(($(string(fname)),libblas), Void, - (Ptr{Int32}, Ptr{$elty}, Ptr{$elty}, Ptr{Int32}), - &n, &DA, DX, &incx) - DX - end - end -end - -# ccall is unable to return complex values (Issue #85) -#@blas_dot :zdotc_ Complex128 -#@blas_dot :cdotc_ Complex64 -# DOUBLE PRECISION FUNCTION DDOT(N,DX,INCX,DY,INCY) -for (fname, elty) in ((:ddot_,:Float64), (:sdot_,:Float32)) - @eval begin - function dot(n::Integer, DX::Union(Ptr{$elty},Array{$elty}), incx::Integer, DY::Union(Ptr{$elty},Array{$elty}), incy::Integer) - ccall(($(string(fname)),libblas), $elty, - (Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}), - &n, DX, &incx, DY, &incy) - end - end -end - -# DOUBLE PRECISION FUNCTION DNRM2(N,X,INCX) -for (fname, elty, ret_type) in ((:dnrm2_,:Float64,:Float64), - (:snrm2_,:Float32,:Float32), - (:dznrm2_,:Complex128,:Float64), - (:scnrm2_,:Complex64,:Float32)) - @eval begin - function nrm2(n::Integer, X::Union(Ptr{$elty},Array{$elty}), incx::Integer) - ccall(($(string(fname)),libblas), $ret_type, - (Ptr{Int32}, Ptr{$elty}, Ptr{Int32}), - &n, X, &incx) - end - end -end - -# SUBROUTINE DAXPY(N,DA,DX,INCX,DY,INCY) -# DY <- DA*DX + DY -#* .. Scalar Arguments .. -# DOUBLE PRECISION DA -# INTEGER INCX,INCY,N -#* .. Array Arguments .. -# DOUBLE PRECISION DX(*),DY(*) -for (fname, elty) in ((:daxpy_,:Float64), (:saxpy_,:Float32), - (:zaxpy_,:Complex128), (:caxpy_,:Complex64)) - @eval begin - function axpy!(n::Integer, alpha::($elty), - dx::Union(Ptr{$elty},Array{$elty}), incx::Integer, - dy::Union(Ptr{$elty},Array{$elty}), incy::Integer) - ccall(($(string(fname)),libblas), Void, - (Ptr{Int32}, Ptr{$elty}, Ptr{$elty}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}), - &n, &alpha, dx, &incx, dy, &incy) - return dy - end - end -end - -function axpy!{T,Ta<:Number}(alpha::Ta, x::Array{T}, y::Array{T}) - if length(x) != length(y) - error("Inputs should be of the same length") - end - return axpy!(length(x), convert(T, alpha), x, 1, y, 1) -end - -function axpy!{T,Ta<:Number,Ti<:Integer}(alpha::Ta, x::Array{T}, rx::Union(Range1{Ti},Range{Ti}), y::Array{T}, ry::Union(Range1{Ti},Range{Ti})) - - if length(rx) != length(ry) - error("Ranges should be of the same length") - end - - if min(rx) < 1 || max(rx) > length(x) || min(ry) < 1 || max(ry) > length(y) - throw(BoundsError()) - end - - return axpy!(length(rx), convert(T, alpha), pointer(x)+(first(rx)-1)*sizeof(T), step(rx), pointer(y)+(first(ry)-1)*sizeof(T), step(ry)) -end - - -# SUBROUTINE DSYRK(UPLO,TRANS,N,K,ALPHA,A,LDA,BETA,C,LDC) -# * .. Scalar Arguments .. -# REAL ALPHA,BETA -# INTEGER K,LDA,LDC,N -# CHARACTER TRANS,UPLO -# * .. -# * .. Array Arguments .. -# REAL A(LDA,*),C(LDC,*) -for (fname, elty) in ((:dsyrk_,:Float64), (:ssyrk_,:Float32), - (:zsyrk_,:Complex128), (:csyrk_,:Complex64)) - @eval begin - function syrk!(uplo, trans, alpha::($elty), A::StridedVecOrMat{$elty}, - beta::($elty), C::StridedMatrix{$elty}) - m, n = size(C) - if m != n error("syrk!: matrix C must be square") end - nn = size(A, trans == 'N' ? 1 : 2) - if nn != n error("syrk!: dimension mismatch") end - k = size(A, trans == 'N' ? 2 : 1) - ccall(($(string(fname)),libblas), Void, - (Ptr{Uint8}, Ptr{Uint8}, Ptr{Int32}, Ptr{Int32}, Ptr{$elty}, - Ptr{$elty}, Ptr{Int32}, Ptr{$elty}, Ptr{$elty}, Ptr{Int32}), - &uplo, &trans, &n, &k, &alpha, A, &stride(A,2), &beta, C, &stride(C,2)) - C - end - function syrk(uplo, trans, alpha::($elty), A::StridedVecOrMat{$elty}) - n = size(A, trans == 'N' ? 1 : 2) - k = size(A, trans == 'N' ? 2 : 1) - C = Array($elty, (n, n)) - ccall(($(string(fname)),libblas), Void, - (Ptr{Uint8}, Ptr{Uint8}, Ptr{Int32}, Ptr{Int32}, Ptr{$elty}, - Ptr{$elty}, Ptr{Int32}, Ptr{$elty}, Ptr{$elty}, Ptr{Int32}), - &uplo, &trans, &n, &k, &alpha, A, &stride(A,2), &0., C, &stride(C,2)) - C - end - end -end - -# SUBROUTINE CHERK(UPLO,TRANS,N,K,ALPHA,A,LDA,BETA,C,LDC) -# * .. Scalar Arguments .. -# REAL ALPHA,BETA -# INTEGER K,LDA,LDC,N -# CHARACTER TRANS,UPLO -# * .. -# * .. Array Arguments .. -# COMPLEX A(LDA,*),C(LDC,*) -for (fname, elty) in ((:zherk_,:Complex128), (:cherk_,:Complex64)) - @eval begin - function herk!(uplo, trans, alpha::($elty), A::StridedVecOrMat{$elty}, - beta::($elty), C::StridedMatrix{$elty}) - m, n = size(C) - if m != n error("syrk!: matrix C must be square") end - nn = size(A, trans == 'N' ? 1 : 2) - if nn != n error("syrk!: dimension mismatch") end - k = size(A, trans == 'N' ? 2 : 1) - ccall(($(string(fname)),libblas), Void, - (Ptr{Uint8}, Ptr{Uint8}, Ptr{Int32}, Ptr{Int32}, Ptr{$elty}, - Ptr{$elty}, Ptr{Int32}, Ptr{$elty}, Ptr{$elty}, Ptr{Int32}), - &uplo, &trans, &n, &k, &alpha, A, &stride(A,2), &beta, C, &stride(C,2)) - C - end - function herk(uplo, trans, alpha::($elty), A::StridedVecOrMat{$elty}) - n = size(A, trans == 'N' ? 1 : 2) - k = size(A, trans == 'N' ? 2 : 1) - C = Array($elty, (n, n)) - ccall(($(string(fname)),libblas), Void, - (Ptr{Uint8}, Ptr{Uint8}, Ptr{Int32}, Ptr{Int32}, Ptr{$elty}, - Ptr{$elty}, Ptr{Int32}, Ptr{$elty}, Ptr{$elty}, Ptr{Int32}), - &uplo, &trans, &n, &k, &alpha, A, &stride(A,2), &0., C, &stride(C,2)) - C - end - end -end - -# (GB) general banded matrix-vector multiplication -# SUBROUTINE DGBMV(TRANS,M,N,KL,KU,ALPHA,A,LDA,X,INCX,BETA,Y,INCY) -# * .. Scalar Arguments .. -# DOUBLE PRECISION ALPHA,BETA -# INTEGER INCX,INCY,KL,KU,LDA,M,N -# CHARACTER TRANS -# * .. -# * .. Array Arguments .. -# DOUBLE PRECISION A(LDA,*),X(*),Y(*) -for (fname, elty) in ((:dgbmv_,:Float64), (:sgbmv_,:Float32), - (:zgbmv_,:Complex128), (:cgbmv_,:Complex64)) - @eval begin - function gbmv!(trans, m::Integer, kl::Integer, ku::Integer, - alpha::($elty), A::StridedMatrix{$elty}, x::StridedVector{$elty}, - beta::($elty), y::StridedVector{$elty}) - ccall(($(string(fname)),libblas), Void, - (Ptr{Uint8}, Ptr{Int32}, Ptr{Int32}, Ptr{Int32}, Ptr{Int32}, - Ptr{$elty}, Ptr{$elty}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, - Ptr{$elty}, Ptr{$elty}, Ptr{Int32}), - &trans, &m, &size(A,2), &kl, &ku, &alpha, A, &stride(A,2), - x, &stride(x,1), &beta, y, &stride(y,1)) - y - end - function gbmv(trans, m::Integer, kl::Integer, ku::Integer, - alpha::($elty), A::StridedMatrix{$elty}, x::StridedVector{$elty}) - n = stride(A,2) - y = Array($elty, n) - ccall(($(string(fname)),libblas), Void, - (Ptr{Uint8}, Ptr{Int32}, Ptr{Int32}, Ptr{Int32}, Ptr{Int32}, - Ptr{$elty}, Ptr{$elty}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, - Ptr{$elty}, Ptr{$elty}, Ptr{Int32}), - &trans, &m, &n, &kl, &ku, &alpha, A, &stride(A,2), - x, &stride(x,1), &0., y, &1) - y - end - - end -end - -# (SB) symmetric banded matrix-vector multiplication -# SUBROUTINE DSBMV(UPLO,N,K,ALPHA,A,LDA,X,INCX,BETA,Y,INCY) -# * .. Scalar Arguments .. -# DOUBLE PRECISION ALPHA,BETA -# INTEGER INCX,INCY,K,LDA,N -# CHARACTER UPLO -# * .. -# * .. Array Arguments .. -# DOUBLE PRECISION A(LDA,*),X(*),Y(*) -for (fname, elty) in ((:dsbmv_,:Float64), (:ssbmv_,:Float32), - (:zsbmv_,:Complex128), (:csbmv_,:Complex64)) - @eval begin - function sbmv!(uplo, k::Integer, - alpha::($elty), A::StridedMatrix{$elty}, x::StridedVector{$elty}, - beta::($elty), y::StridedVector{$elty}) - ccall(($(string(fname)),libblas), Void, - (Ptr{Uint8}, Ptr{Int32}, Ptr{Int32}, Ptr{$elty}, Ptr{$elty}, Ptr{Int32}, - Ptr{$elty}, Ptr{Int32}, Ptr{$elty}, Ptr{$elty}, Ptr{Int32}), - &uplo, &size(A,2), &k, &alpha, A, &stride(A,2), x, &stride(x,1), &beta, y, &stride(y,1)) - y - end - function sbmv(uplo, k::Integer, alpha::($elty), A::StridedMatrix{$elty}, - x::StridedVector{$elty}) - n = size(A,2) - y = Array($elty, n) - ccall(($(string(fname)),libblas), Void, - (Ptr{Uint8}, Ptr{Int32}, Ptr{Int32}, Ptr{$elty}, Ptr{$elty}, Ptr{Int32}, - Ptr{$elty}, Ptr{Int32}, Ptr{$elty}, Ptr{$elty}, Ptr{Int32}), - &uplo, &size(A,2), &k, &alpha, A, &stride(A,2), x, &stride(x,1), &0., y, &1) - y - end - end -end - -# (GE) general matrix-matrix multiplication -# SUBROUTINE DGEMM(TRANSA,TRANSB,M,N,K,ALPHA,A,LDA,B,LDB,BETA,C,LDC) -# * .. Scalar Arguments .. -# DOUBLE PRECISION ALPHA,BETA -# INTEGER K,LDA,LDB,LDC,M,N -# CHARACTER TRANSA,TRANSB -# * .. Array Arguments .. -# DOUBLE PRECISION A(LDA,*),B(LDB,*),C(LDC,*) -for (fname, elty) in ((:dgemm_,:Float64), (:sgemm_,:Float32), - (:zgemm_,:Complex128), (:cgemm_,:Complex64)) - @eval begin - function gemm!(transA, transB, alpha::($elty), A::StridedMatrix{$elty}, - B::StridedMatrix{$elty}, beta::($elty), C::StridedMatrix{$elty}) - m = size(A, transA == 'N' ? 1 : 2) - k = size(A, transA == 'N' ? 2 : 1) - n = size(B, transB == 'N' ? 2 : 1) - if m != size(C,1) || n != size(C,2) error("gemm!: mismatched dimensions") end - ccall(($(string(fname)),libblas), Void, - (Ptr{Uint8}, Ptr{Uint8}, Ptr{Int32}, Ptr{Int32}, Ptr{Int32}, - Ptr{$elty}, Ptr{$elty}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, - Ptr{$elty}, Ptr{$elty}, Ptr{Int32}), - &transA, &transB, &m, &n, &k, &alpha, A, &stride(A,2), - B, &stride(B,2), &beta, C, &stride(C,2)) - C - end - function gemm(transA, transB, alpha::($elty), A::StridedMatrix{$elty}, B::StridedMatrix{$elty}) - m = size(A, transA == 'N' ? 1 : 2) - k = size(A, transA == 'N' ? 2 : 1) - if k != size(B, transB == 'N' ? 1 : 2) error("gemm!: mismatched dimensions") end - n = size(B, transB == 'N' ? 2 : 1) - C = Array($elty, (m, n)) - ccall(($(string(fname)),libblas), Void, - (Ptr{Uint8}, Ptr{Uint8}, Ptr{Int32}, Ptr{Int32}, Ptr{Int32}, - Ptr{$elty}, Ptr{$elty}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, - Ptr{$elty}, Ptr{$elty}, Ptr{Int32}), - &transA, &transB, &m, &n, &k, &alpha, A, &stride(A,2), - B, &stride(B,2), &0., C, &stride(C,2)) - C - end - end -end - -#SUBROUTINE DGEMV(TRANS,M,N,ALPHA,A,LDA,X,INCX,BETA,Y,INCY) -#* .. Scalar Arguments .. -# DOUBLE PRECISION ALPHA,BETA -# INTEGER INCX,INCY,LDA,M,N -# CHARACTER TRANS -#* .. Array Arguments .. -# DOUBLE PRECISION A(LDA,*),X(*),Y(*) - -for (fname, elty) in ((:dgemv_,:Float64), (:sgemv_,:Float32), - (:zgemv_,:Complex128), (:cgemv_,:Complex64)) - @eval begin - function gemv!(trans, alpha::($elty), A::StridedMatrix{$elty}, - X::StridedVector{$elty}, beta::($elty), Y::StridedVector{$elty}) - ccall(($(string(fname)),libblas), Void, - (Ptr{Uint8}, Ptr{Int32}, Ptr{Int32}, Ptr{$elty}, Ptr{$elty}, Ptr{Int32}, - Ptr{$elty}, Ptr{Int32}, Ptr{$elty}, Ptr{$elty}, Ptr{Int32}), - &trans, &size(A,1), &size(A,2), &alpha, A, &stride(A,2), - X, &stride(X,1), &beta, Y, &stride(Y,1)) - Y - end - function gemv!(trans, alpha::($elty), A::StridedMatrix{$elty}, X::StridedVector{$elty}) - Y = Array($elty, size(A,1)) - ccall(($(string(fname)),libblas), Void, - (Ptr{Uint8}, Ptr{Int32}, Ptr{Int32}, Ptr{$elty}, Ptr{$elty}, Ptr{Int32}, - Ptr{$elty}, Ptr{Int32}, Ptr{$elty}, Ptr{$elty}, Ptr{Int32}), - &trans, &size(A,1), &size(A,2), &alpha, A, &stride(A,2), - X, &stride(X,1), &0., Y, &1) - Y - end - end -end - -# (SY) symmetric matrix-matrix and matrix-vector multiplication - -# SUBROUTINE DSYMM(SIDE,UPLO,M,N,ALPHA,A,LDA,B,LDB,BETA,C,LDC) -# .. Scalar Arguments .. -# DOUBLE PRECISION ALPHA,BETA -# INTEGER LDA,LDB,LDC,M,N -# CHARACTER SIDE,UPLO -# .. Array Arguments .. -# DOUBLE PRECISION A(LDA,*),B(LDB,*),C(LDC,*) - -# SUBROUTINE DSYMV(UPLO,N,ALPHA,A,LDA,X,INCX,BETA,Y,INCY) -# .. Scalar Arguments .. -# DOUBLE PRECISION ALPHA,BETA -# INTEGER INCX,INCY,LDA,N -# CHARACTER UPLO -# .. Array Arguments .. -# DOUBLE PRECISION A(LDA,*),X(*),Y(*) - -for (vfname, mfname, elty) in - ((:dsymv_,:dsymm_,:Float64), - (:ssymv_,:ssymm_,:Float32), - (:zsymv_,:zsymm_,:Complex128), - (:csymv_,:csymm_,:Complex64)) - @eval begin - function symv!(uplo, alpha::($elty), A::StridedMatrix{$elty}, X::StridedVector{$elty}, - beta::($elty), Y::StridedVector{$elty}) - m, n = size(A) - if m != n error("symm!: matrix A is $m by $n but must be square") end - if m != length(X) || m != length(Y) error("symm!: dimension mismatch") end - ccall(($(string(vfname)),libblas), Void, - (Ptr{Uint8}, Ptr{Int32}, Ptr{$elty}, Ptr{$elty}, Ptr{Int32}, - Ptr{$elty}, Ptr{Int32}, Ptr{$elty}, Ptr{$elty}, Ptr{Int32}), - &uplo, &n, &alpha, A, &stride(A,2), X, &stride(X,1), &beta, Y, &stride(Y,1)) - Y - end - function symv(uplo, alpha::($elty), A::StridedMatrix{$elty}, X::StridedVector{$elty}) - symv!(uplo, alpha, A, X, zero($elty), similar(X)) - end - function symm!(side, uplo, alpha::($elty), A::StridedMatrix{$elty}, B::StridedMatrix{$elty}, - beta::($elty), C::StridedMatrix{$elty}) - side = uppercase(convert(Char, side)) - m, n = size(C) - k, j = size(A) - if k != j error("symm!: matrix A is $k by $j but must be square") end - if j != (side == 'L' ? m : n) || size(B,2) != n error("symm!: Dimension mismatch") end - ccall(($(string(mfname)),libblas), Void, - (Ptr{Uint8}, Ptr{Uint8}, Ptr{Int32}, Ptr{Int32}, Ptr{$elty}, Ptr{$elty}, Ptr{Int32}, - Ptr{$elty}, Ptr{Int32}, Ptr{$elty}, Ptr{$elty}, Ptr{Int32}), - &side, &uplo, &m, &n, &alpha, A, &stride(A,2), B, &stride(B,2), - &beta, C, &stride(C,2)) - C - end - function symm(side, uplo, alpha::($elty), A::StridedMatrix{$elty}, B::StridedMatrix{$elty}) - symm!(side, uplo, alpha, A, B, zero($elty), similar(B)) - end - end -end - -end # module - -# Use BLAS copy for small arrays where it is faster than memcpy, and for strided copying - -function copy_to{T<:LapackType}(dest::Ptr{T}, src::Ptr{T}, n::Integer) - if n < 200 - BLAS.copy!(n, src, 1, dest, 1) - else - ccall(:memcpy, Ptr{Void}, (Ptr{Void}, Ptr{Void}, Uint), dest, src, n*sizeof(T)) - end - return dest -end - -function copy_to{T<:LapackType}(dest::Array{T}, src::Array{T}) - n = numel(src) - if n > numel(dest); throw(BoundsError()); end - copy_to(pointer(dest), pointer(src), n) - return dest -end - -function copy_to{T<:LapackType,Ti<:Integer}(dest::Array{T}, rdest::Union(Range1{Ti},Range{Ti}), - src::Array{T}, rsrc::Union(Range1{Ti},Range{Ti})) - if min(rdest) < 1 || max(rdest) > length(dest) || min(rsrc) < 1 || max(rsrc) > length(src) - throw(BoundsError()) - end - if length(rdest) != length(rsrc) - error("Ranges must be of the same length") - end - BLAS.copy!(length(rsrc), pointer(src)+(first(rsrc)-1)*sizeof(T), step(rsrc), - pointer(dest)+(first(rdest)-1)*sizeof(T), step(rdest)) - return dest -end diff --git a/base/bool.jl b/base/bool.jl index c78b4059d2a8b..f2afccc5eae49 100644 --- a/base/bool.jl +++ b/base/bool.jl @@ -1,5 +1,6 @@ ## boolean conversions ## +convert(::Type{Bool}, x::Bool) = x convert(::Type{Bool}, x::Real) = (x!=0) # promote Bool to any other numeric type @@ -23,15 +24,6 @@ isequal(x::Bool, y::Bool) = eq_int(unbox(Bool,x),unbox(Bool,y)) (|)(x::Bool, y::Bool) = box(Bool,or_int(unbox(Bool,x),unbox(Bool,y))) ($)(x::Bool, y::Bool) = (x!=y) -any() = false -all() = true - -any(x::Bool) = x -all(x::Bool) = x - -any(x::Bool, y::Bool) = x | y -all(x::Bool, y::Bool) = x & y - ## do arithmetic as Int ## signbit(x::Bool) = 0 @@ -39,17 +31,20 @@ sign(x::Bool) = int(x) abs(x::Bool) = int(x) <(x::Bool, y::Bool) = y&!x +<=(x::Bool, y::Bool) = y|!x ==(x::Bool, y::Bool) = eq_int(unbox(Bool,x),unbox(Bool,y)) ++(x::Bool) = int(x) -(x::Bool) = -int(x) +(x::Bool, y::Bool) = int(x)+int(y) -(x::Bool, y::Bool) = int(x)-int(y) -*(x::Bool, y::Bool) = int(x)*int(y) +*(x::Bool, y::Bool) = x&y /(x::Bool, y::Bool) = int(x)/int(y) -^(x::Bool, y::Bool) = int(x)^int(y) +^(x::Bool, y::Bool) = x|!y +^(x::Integer, y::Bool) = y ? x : one(x) -div(x::Bool, y::Bool) = div(int(x),int(y)) -fld(x::Bool, y::Bool) = fld(int(x),int(y)) -rem(x::Bool, y::Bool) = rem(int(x),int(y)) -mod(x::Bool, y::Bool) = mod(int(x),int(y)) +div(x::Bool, y::Bool) = y ? x : throw(DivideByZeroError()) +fld(x::Bool, y::Bool) = div(x,y) +rem(x::Bool, y::Bool) = y ? false : throw(DivideByZeroError()) +mod(x::Bool, y::Bool) = rem(x,y) diff --git a/base/boot.jl b/base/boot.jl index d21a7dbfb8cb8..1a584d16087f6 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -3,7 +3,7 @@ #abstract Any <: Any #abstract Type{T} -#abstract ...{T} +#abstract Vararg{T} #Tuple = (Any...) #type Symbol @@ -14,27 +14,21 @@ # name::Symbol #end -#type AbstractKind <: Type -# name::TypeName -# super::Type -# parameters::Tuple -#end - -#type CompositeKind <: Type +#type DataType <: Type # name::TypeName # super::Type # parameters::Tuple # names::Tuple # types::Tuple +# ctor +# instance +# size::Int32 +# abstract::Bool +# mutable::Bool +# pointerfree::Bool #end -#type BitsKind <: Type -# name::TypeName -# super::Type -# parameters::Tuple -#end - -#type UnionKind <: Type +#type UnionType <: Type # types::Tuple #end @@ -109,7 +103,7 @@ # type Task # parent::Task # last::Task -# tls::Any +# storage::Any # consumers # done::Bool # runnable::Bool @@ -118,43 +112,52 @@ import Main import Intrinsics.ccall -export ..., ANY, ASCIIString, AbstractArray, AbstractKind, Any, Array, - BitsKind, Bool, BoundsError, Box, ByteString, Char, CompositeKind, - Main, DirectIndexString, DivideByZeroError, DomainError, EOFError, - Exception, Expr, FloatingPoint, Float32, Float64, Function, GotoNode, IOError, - InexactError, Integer, Int, Int8, Int16, Int32, Int64, Int128, - InterruptException, - IntrinsicFunction, LabelNode, LambdaStaticData, LineNumberNode, - MemoryError, Method, MethodTable, Module, NTuple, None, Nothing, Number, - OverflowError, Ptr, QuoteNode, Real, Signed, StackOverflowError, String, - Symbol, SymbolNode, Task, Top, TopNode, Tuple, Type, TypeConstructor, - TypeName, TypeVar, UTF8String, Uint, Uint8, Uint16, Uint32, Uint64, Uint128, - UndefRefError, Union, UnionKind, Unsigned, Void, +export + # key types + Any, DataType, Vararg, ANY, NTuple, None, Top, + Tuple, Type, TypeConstructor, TypeName, TypeVar, Union, UnionType, Void, + AbstractArray, + # special objects + Box, Function, IntrinsicFunction, LambdaStaticData, Method, MethodTable, + Module, Nothing, Symbol, Task, Array, + # numeric types + Bool, FloatingPoint, Float32, Float64, Number, Integer, Int, Int8, Int16, + Int32, Int64, Int128, Ptr, Real, Signed, Uint, Uint8, Uint16, Uint32, + Uint64, Uint128, Unsigned, + # string types + Char, ASCIIString, ByteString, DirectIndexString, String, UTF8String, + # errors + BoundsError, DivideByZeroError, DomainError, Exception, + InexactError, InterruptException, MemoryError, OverflowError, + StackOverflowError, UndefRefError, + # AST representation + Expr, GotoNode, LabelNode, LineNumberNode, QuoteNode, SymbolNode, TopNode, GetfieldNode, - # functions - setfield, applicable, apply, apply_type, arraylen, arrayref, arrayset, - arraysize, convert_default, convert_tuple, fieldtype, getfield, - include, invoke, is, ===, isa, isdefined, method_exists, - subtype, throw, tuple, tuplelen, tupleref, typeassert, typeof, yieldto, + # object model functions + apply, arraylen, arrayref, arrayset, arraysize, fieldtype, getfield, + setfield, yieldto, throw, tuple, tuplelen, tupleref, is, ===, isdefined, + convert_default, convert_tuple, kwcall, + # type reflection + subtype, typeassert, typeof, apply_type, isa, + # method reflection + applicable, invoke, method_exists, # constants - JULIA_HOME, nothing, + JULIA_HOME, nothing, Main, # intrinsics module Intrinsics #ccall, abs_float, add_float, add_int, and_int, ashr_int, - #box, bswap_int, checked_fptosi32, - #checked_fptosi64, checked_fptoui32, checked_fptoui64, checked_sadd, + #box, bswap_int, checked_fptosi, checked_fptoui, checked_sadd, #checked_smul, checked_ssub, checked_uadd, checked_umul, checked_usub, - #copysign_float, ctlz_int, ctpop_int, cttz_int, + #nan_dom_err, copysign_float, ctlz_int, ctpop_int, cttz_int, #div_float, eq_float, eq_int, eqfsi64, eqfui64, flipsign_int, #fpext64, fpiseq32, fpiseq64, fpislt32, fpislt64, #fpsiround32, fpsiround64, fptosi32, fptosi64, fptoui32, fptoui64, #fptrunc32, fpuiround32, fpuiround64, le_float, lefsi64, lefui64, lesif64, #leuif64, lshr_int, lt_float, ltfsi64, ltfui64, ltsif64, ltuif64, mul_float, #mul_int, ne_float, ne_int, neg_float, neg_int, not_int, or_int, rem_float, - #sdiv_int, sext16, sext32, sext64, shl_int, sitofp32, sitofp64, sle_int, - #slt_int, smod_int, srem_int, sub_float, sub_int, trunc16, trunc32, - #trunc64, trunc8, trunc_int, udiv_int, uitofp32, uitofp64, ule_int, ult_int, - #unbox, urem_int, xor_int, zext16, zext32, zext64, sext_int, zext_int + #sdiv_int, shl_int, sitofp32, sitofp64, sle_int, slt_int, smod_int, + #srem_int, sub_float, sub_int, trunc_int, udiv_int, uitofp32, uitofp64, + #ule_int, ult_int, unbox, urem_int, xor_int, sext_int, zext_int type Nothing; end @@ -200,9 +203,7 @@ type DomainError <: Exception end type OverflowError <: Exception end type InexactError <: Exception end type MemoryError <: Exception end -type IOError <: Exception end type StackOverflowError <: Exception end -type EOFError <: Exception end type UndefRefError <: Exception end type InterruptException <: Exception end @@ -224,11 +225,11 @@ type GetfieldNode typ end -type ASCIIString <: DirectIndexString +immutable ASCIIString <: DirectIndexString data::Array{Uint8,1} end -type UTF8String <: String +immutable UTF8String <: String data::Array{Uint8,1} end diff --git a/base/c.jl b/base/c.jl new file mode 100644 index 0000000000000..ab14b8957a421 --- /dev/null +++ b/base/c.jl @@ -0,0 +1,70 @@ +# definitions related to C interface + +ptr_arg_convert{T}(::Type{Ptr{T}}, x) = convert(T, x) +ptr_arg_convert(::Type{Ptr{Void}}, x) = x + +# conversion used by ccall +cconvert(T, x) = convert(T, x) +# use the code in ccall.cpp to safely allocate temporary pointer arrays +cconvert{T}(::Type{Ptr{Ptr{T}}}, a::Array) = a +# TODO: for some reason this causes a strange type inference problem +#cconvert(::Type{Ptr{Uint8}}, s::String) = bytestring(s) + +# constants to match JL_RTLD_* in src/julia.h +const RTLD_LOCAL = 0x00000000 +const RTLD_GLOBAL = 0x00000001 +const RTLD_LAZY = 0x00000002 +const RTLD_NOW = 0x00000004 +const RTLD_NODELETE = 0x00000008 +const RTLD_NOLOAD = 0x00000010 +const RTLD_DEEPBIND = 0x00000020 +const RTLD_FIRST = 0x00000040 + +dlsym(hnd, s::Union(Symbol,String)) = ccall(:jl_dlsym, Ptr{Void}, (Ptr{Void}, Ptr{Uint8}), hnd, s) +dlsym_e(hnd, s::Union(Symbol,String)) = ccall(:jl_dlsym_e, Ptr{Void}, (Ptr{Void}, Ptr{Uint8}), hnd, s) +dlopen(s::String, flags::Integer) = ccall(:jl_load_dynamic_library, Ptr{Void}, (Ptr{Uint8},Uint32), s, flags) +dlopen_e(s::String, flags::Integer) = ccall(:jl_load_dynamic_library_e, Ptr{Void}, (Ptr{Uint8},Uint32), s, flags) +dlopen(s::String) = dlopen(s, RTLD_LAZY | RTLD_DEEPBIND) +dlopen_e(s::String) = dlopen_e(s, RTLD_LAZY | RTLD_DEEPBIND) +dlclose(p::Ptr) = ccall(:uv_dlclose,Void,(Ptr{Void},),p) + +cfunction(f::Function, r, a) = + ccall(:jl_function_ptr, Ptr{Void}, (Any, Any, Any), f, r, a) + +if ccall(:jl_is_char_signed, Any, ()) + typealias Cchar Int8 +else + typealias Cchar Uint8 +end +typealias Cuchar Uint8 +typealias Cshort Int16 +typealias Cushort Uint16 +typealias Cint Int32 +typealias Cuint Uint32 +if OS_NAME === :Windows + typealias Clong Int32 + typealias Culong Uint32 +else + typealias Clong Int + typealias Culong Uint +end +typealias Cptrdiff_t Int +typealias Csize_t Uint +typealias Clonglong Int64 +typealias Culonglong Uint64 +typealias Cfloat Float32 +typealias Cdouble Float64 +#typealias Ccomplex_float Complex64 +#typealias Ccomplex_double Complex128 + +# deferring (or un-deferring) ctrl-c handler for external C code that +# is not interrupt safe (see also issue #2622). The sigatomic_begin/end +# functions should always be called in matched pairs, ideally via: +# disable_sigint() do .. end +# reennable_sigint is provided so that immediate ctrl-c handling is +# re-enabled within a sigatomic region, e.g. inside a Julia callback function +# within a long-running C routine. +sigatomic_begin() = ccall(:jl_sigatomic_begin, Void, ()) +sigatomic_end() = ccall(:jl_sigatomic_end, Void, ()) +disable_sigint(f::Function) = try sigatomic_begin(); f(); finally sigatomic_end(); end +reenable_sigint(f::Function) = try sigatomic_end(); f(); finally sigatomic_begin(); end diff --git a/base/char.jl b/base/char.jl index fb7ea1b975e17..2b4e62c4db662 100644 --- a/base/char.jl +++ b/base/char.jl @@ -1,31 +1,10 @@ -## char conversions ## - -convert(::Type{Char}, x::Bool ) = box(Char,sext32(unbox(Bool,x))) -convert(::Type{Char}, x::Int8 ) = box(Char,sext32(unbox(Int8,x))) -convert(::Type{Char}, x::Uint8 ) = box(Char,zext32(unbox(Uint8,x))) -convert(::Type{Char}, x::Int16 ) = box(Char,sext32(unbox(Int16,x))) -convert(::Type{Char}, x::Uint16 ) = box(Char,zext32(unbox(Uint16,x))) -convert(::Type{Char}, x::Int32 ) = box(Char,unbox(Int32,x)) -convert(::Type{Char}, x::Uint32 ) = box(Char,unbox(Uint32,x)) -convert(::Type{Char}, x::Int64 ) = box(Char,trunc32(unbox(Int64,x))) -convert(::Type{Char}, x::Uint64 ) = box(Char,trunc32(unbox(Uint64,x))) -convert(::Type{Char}, x::Int128 ) = box(Char,trunc32(unbox(Int128,x))) -convert(::Type{Char}, x::Uint128) = box(Char,trunc32(unbox(Uint128,x))) -convert(::Type{Char}, x::Float32) = box(Char,fptoui32(unbox(Float32,x))) -convert(::Type{Char}, x::Float64) = box(Char,fptoui32(unbox(Float64,x))) - char(x) = convert(Char, x) +char(x::FloatingPoint) = char(iround(x)) -function safe_char(x) - c = char(x) - if '\ud800' <= c <= '\udfff' || '\U10ffff' < c - error("invalid Unicode code point: U+", hex(c)) - end - return c -end +is_valid_char(c) = !('\ud800' <= c <= '\udfff' || '\U10ffff' < c) -integer(x::Char) = int32(x) -unsigned(x::Char) = uint32(x) +integer(x::Char) = int(x) +unsigned(x::Char) = uint(x) ## char promotions ## @@ -42,20 +21,24 @@ promote_rule(::Type{Char}, ::Type{Uint128}) = Uint128 ## character operations & comparisons ## --(x::Char) = -int(x) -+(x::Char, y::Char) = int(x) + int(y) --(x::Char, y::Char) = int(x) - int(y) -*(x::Char, y::Char) = int(x) * int(y) +# numeric operations ++(x::Char , y::Char ) = int(x)+int(y) +*(x::Char , y::Char ) = int(x)*int(y) +div(x::Char , y::Char ) = div(int(x),int(y)) + +# ordinal operations ++(x::Char , y::Integer) = char(int(x)+int(y)) ++(x::Integer, y::Char ) = y+x +-(x::Char , y::Char ) = int(x)-int(y) +-(x::Char , y::Integer) = char(int(x)-int(y)) -div(x::Char, y::Char) = div(int(x), int(y)) -fld(x::Char, y::Char) = div(int(x), int(y)) -rem(x::Char, y::Char) = rem(int(x), int(y)) -mod(x::Char, y::Char) = rem(int(x), int(y)) +# bitwise operations +(~)(x::Char) = char(~uint32(x)) +(&)(x::Char, y::Char) = char(uint32(x) & uint32(y)) +(|)(x::Char, y::Char) = char(uint32(x) | uint32(y)) +($)(x::Char, y::Char) = char(uint32(x) $ uint32(y)) -~(x::Char) = ~uint32(x) -(&)(x::Char, y::Char) = uint32(x) & uint32(y) -|(x::Char, y::Char) = uint32(x) | uint32(y) -($)(x::Char, y::Char) = uint32(x) $ uint32(y) +bswap(x::Char) = char(bswap(uint32(x))) <<(x::Char, y::Int32) = uint32(x) << y >>(x::Char, y::Int32) = uint32(x) >>> y @@ -72,17 +55,4 @@ sizeof(::Type{Char}) = 4 ## printing & showing characters ## print(io::IO, c::Char) = (write(io,c); nothing) -show(io, c::Char) = (print(io,'\''); print_escaped(io,string(c),"'"); print(io,'\'')) - -## libc character class testing functions ## - -iswascii(c::Char) = c < 0x80 - -for f = (:iswalnum, :iswalpha, :iswblank, :iswcntrl, :iswdigit, - :iswgraph, :iswlower, :iswprint, :iswpunct, :iswspace, - :iswupper, :iswxdigit, - # these are BSD-only - #:iswhexnumber, :iswideogram, :iswnumber, :iswphonogram, :iswrune, :iswspecial, - ) - @eval ($f)(c::Char) = bool(ccall($(expr(:quote,f)), Int32, (Char,), c)) -end +show(io::IO, c::Char) = (print(io,'\''); print_escaped(io,CharString(c),"'"); print(io,'\'')) diff --git a/base/client.jl b/base/client.jl index 4c6e8038a56c6..7670c3910ec43 100644 --- a/base/client.jl +++ b/base/client.jl @@ -1,125 +1,154 @@ ## client.jl - frontend handling command line options, environment setup, ## and REPL -const _jl_color_normal = "\033[0m" - -function _jl_answer_color() - c = get(ENV, "JL_ANSWER_COLOR", "") - return c == "black" ? "\033[1m\033[30m" : - c == "red" ? "\033[1m\033[31m" : - c == "green" ? "\033[1m\033[32m" : - c == "yellow" ? "\033[1m\033[33m" : - c == "magenta" ? "\033[1m\033[35m" : - c == "cyan" ? "\033[1m\033[36m" : - c == "white" ? "\033[1m\033[37m" : - "\033[1m\033[34m" -end +const text_colors = { + :black => "\033[1m\033[30m", + :red => "\033[1m\033[31m", + :green => "\033[1m\033[32m", + :yellow => "\033[1m\033[33m", + :blue => "\033[1m\033[34m", + :magenta => "\033[1m\033[35m", + :cyan => "\033[1m\033[36m", + :white => "\033[1m\033[37m", + :normal => "\033[0m", + :bold => "\033[1m", +} -_jl_banner() = print(_jl_have_color ? _jl_banner_color : _jl_banner_plain) +have_color = false +@unix_only default_color_answer = text_colors[:bold] +@unix_only default_color_input = text_colors[:bold] +@windows_only default_color_answer = text_colors[:normal] +@windows_only default_color_input = text_colors[:normal] +color_normal = text_colors[:normal] -function repl_callback(ast::ANY, show_value) - # use root task to execute user input - del_fd_handler(STDIN.fd) - put(_jl_repl_channel, (ast, show_value)) +function answer_color() + c = symbol(get(ENV, "JULIA_ANSWER_COLOR", "")) + return get(text_colors, c, default_color_answer) end -# called to show a REPL result -repl_show(v::ANY) = repl_show(OUTPUT_STREAM, v) -function repl_show(io, v::ANY) - if !(isa(v,Function) && isgeneric(v)) - if isa(v,AbstractVector) && !isa(v,Ranges) - print(io, summary(v)) - if !isempty(v) - println(io, ":") - print_matrix(io, reshape(v,(length(v),1))) - end - else - show(io, v) - end - end - if isgeneric(v) && !isa(v,CompositeKind) - show(io, v.env) - end +function input_color() + c = symbol(get(ENV, "JULIA_INPUT_COLOR", "")) + return get(text_colors, c, default_color_input) end -function add_backtrace(e, bt) - if isa(e,LoadError) - if isa(e.error,LoadError) - add_backtrace(e.error,bt) - else - e.error = BackTrace(e.error, bt) - e - end - else - BackTrace(e, bt) +banner() = print(have_color ? banner_color : banner_plain) + +exit(n) = ccall(:jl_exit, Void, (Int32,), n) +exit() = exit(0) +quit() = exit() + +function repl_callback(ast::ANY, show_value) + global _repl_enough_stdin = true + stop_reading(STDIN) + STDIN.readcb = false + put(repl_channel, (ast, show_value)) +end + +display_error(er) = display_error(er, {}) +function display_error(er, bt) + with_output_color(:red, OUTPUT_STREAM) do io + print(io, "ERROR: ") + error_show(io, er, bt) end end -function _jl_eval_user_input(ast::ANY, show_value) +function eval_user_input(ast::ANY, show_value) iserr, lasterr, bt = false, (), nothing while true try - if _jl_have_color - print(_jl_color_normal) + if have_color + print(color_normal) end if iserr - show(add_backtrace(lasterr,bt)) + display_error(lasterr,bt) println() iserr, lasterr = false, () else + ast = expand(ast) value = eval(Main,ast) global ans = value if !is(value,nothing) && show_value - if _jl_have_color - print(_jl_answer_color()) + if have_color + print(answer_color()) end try repl_show(value) catch err - throw(ShowError(value,err)) + println("Error showing value of type ", typeof(value), ":") + rethrow(err) end println() end end break catch err + if iserr + println("SYSTEM: show(lasterr) caused an error") + end iserr, lasterr = true, err - bt = backtrace() + bt = catch_backtrace() end end println() end +function readBuffer(stream::AsyncStream, nread) + global _repl_enough_stdin::Bool + while !_repl_enough_stdin && nb_available(stream.buffer) > 0 + nread = int(search(stream.buffer,'\n')) # never more than one line or readline explodes :O + nread2 = int(search(stream.buffer,'\r')) + if nread == 0 + if nread2 == 0 + nread = nb_available(stream.buffer) + else + nread = nread2 + end + else + if nread2 != 0 && nread2 < nread + nread = nread2 + end + end + ptr = pointer(stream.buffer.data,stream.buffer.ptr) + skip(stream.buffer,nread) + #println(STDERR,stream.buffer.data[stream.buffer.ptr-nread:stream.buffer.ptr-1]) + ccall(:jl_readBuffer,Void,(Ptr{Void},Int32),ptr,nread) + end + return false +end + function run_repl() - global const _jl_repl_channel = RemoteRef() + global const repl_channel = RemoteRef() - if _jl_have_color + if have_color ccall(:jl_enable_color, Void, ()) end - atexit() do - if _jl_have_color - print(_jl_color_normal) - end - println() - end - # ctrl-C interrupt for interactive use + # install Ctrl-C interrupt handler (InterruptException) ccall(:jl_install_sigint_handler, Void, ()) + STDIN.closecb = (x...)->put(repl_channel,(nothing,-1)) while true ccall(:repl_callback_enable, Void, ()) - add_fd_handler(STDIN.fd, fd->ccall(:jl_stdin_callback, Void, ())) - (ast, show_value) = take(_jl_repl_channel) + global _repl_enough_stdin = false + start_reading(STDIN, readBuffer) + if have_color + print(input_color()) + end + (ast, show_value) = take(repl_channel) if show_value == -1 # exit flag break end - _jl_eval_user_input(ast, show_value!=0) + eval_user_input(ast, show_value!=0) + end + + if have_color + print(color_normal) end end function parse_input_line(s::String) # s = bytestring(s) - # (expr, pos) = parse(s, 1, true) + # (expr, pos) = parse(s, 1) # (ex, pos) = ccall(:jl_parse_string, Any, # (Ptr{Uint8},Int32,Int32), # s, int32(pos)-1, 1) @@ -138,13 +167,11 @@ function try_include(f::String) end function process_options(args::Array{Any,1}) - global ARGS + global ARGS, bind_addr quiet = false repl = true startup = true - if has(ENV, "JL_POST_BOOT") - eval(Main,parse_input_line(ENV["JL_POST_BOOT"])) - end + color_set = false i = 1 while i <= length(args) if args[i]=="-q" || args[i]=="--quiet" @@ -152,36 +179,42 @@ function process_options(args::Array{Any,1}) elseif args[i]=="--worker" start_worker() # doesn't return - elseif args[i]=="-e" - # TODO: support long options + elseif args[i]=="--bind-to" + i += 1 + bind_addr = args[i] + elseif args[i]=="-e" || args[i]=="--eval" repl = false i+=1 ARGS = args[i+1:end] eval(Main,parse_input_line(args[i])) break - elseif args[i]=="-E" + elseif args[i]=="-E" || args[i]=="--print" repl = false i+=1 ARGS = args[i+1:end] show(eval(Main,parse_input_line(args[i]))) println() break - elseif args[i]=="-P" + elseif args[i]=="-P" || args[i]=="--post-boot" i+=1 eval(Main,parse_input_line(args[i])) - elseif args[i]=="-L" + elseif args[i]=="-L" || args[i]=="--load" i+=1 - load(args[i]) + require(args[i]) elseif args[i]=="-p" i+=1 - np = int32(args[i]) + if i > length(args) || !isdigit(args[i][1]) + np = CPU_CORES + else + np = int(args[i]) + end addprocs_local(np-1) elseif args[i]=="--machinefile" i+=1 machines = split(readall(args[i]), '\n', false) addprocs_ssh(machines) elseif args[i]=="-v" || args[i]=="--version" - println("julia version $VERSION") + println("julia version ", VERSION) exit(0) elseif args[i]=="--no-history" # see repl-readline.c @@ -189,8 +222,25 @@ function process_options(args::Array{Any,1}) startup = false elseif args[i] == "-F" # load juliarc now before processing any more options - try_include(strcat(ENV["HOME"],"/.juliarc.jl")) + try_include(string(ENV["HOME"],"/.juliarc.jl")) startup = false + elseif beginswith(args[i], "--color") + if args[i] == "--color" + color_set = true + global have_color = true + elseif args[i][8] == '=' + val = args[i][9:] + if contains(("no","0","false"), val) + color_set = true + global have_color = false + elseif contains(("yes","1","true"), val) + color_set = true + global have_color = true + end + end + if !color_set + error("invalid option: ", args[i]) + end elseif args[i][1]!='-' # program repl = false @@ -203,87 +253,122 @@ function process_options(args::Array{Any,1}) end i += 1 end - return (quiet,repl,startup) + return (quiet,repl,startup,color_set) end -const _jl_roottask = current_task() -const _jl_roottask_wi = WorkItem(_jl_roottask) +const roottask = current_task() +const roottask_wi = WorkItem(roottask) + +is_interactive = false +isinteractive() = (is_interactive::Bool) -_jl_is_interactive = false -isinteractive() = (_jl_is_interactive::Bool) +function init_load_path() + vers="v$(VERSION.major).$(VERSION.minor)" + global const LOAD_PATH = ByteString[ + ".", # TODO: should we really look here? + abspath(Pkg.dir()), + abspath(JULIA_HOME,"..","share","julia","extras"), + abspath(JULIA_HOME,"..","local","share","julia","site",vers), + abspath(JULIA_HOME,"..","share","julia","site",vers) + ] +end -julia_pkgdir() = abs_path(get(ENV,"JULIA_PKGDIR",string(ENV["HOME"],"/.julia"))) +function init_sched() + global const Workqueue = WorkItem[] + global const Waiting = Dict() +end + +function init_head_sched() + # start in "head node" mode + global const Scheduler = Task(()->event_loop(true), 1024*1024) + global PGRP + PGRP.myid = 1 + assert(PGRP.np == 0) + push!(PGRP.workers,LocalProcess()) + push!(PGRP.locs,("",0)) + PGRP.np = 1 + # make scheduler aware of current (root) task + unshift!(Workqueue, roottask_wi) + yield() +end function _start() # set up standard streams - global const stdout_stream = make_stdout_stream() - global const stdin_stream = make_stdin_stream() - global const stderr_stream = make_stderr_stream() - global OUTPUT_STREAM = stdout_stream - + reinit_stdio() + # Initialize RNG librandom_init() + # Check that OpenBLAS is correctly built + check_openblas() + + # set default local address + global bind_addr = getipaddr() + + @windows_only begin + user_data_dir = abspath(ENV["AppData"],"julia") + if !isdir(user_data_dir) + mkdir(user_data_dir) + end + if !has(ENV,"HOME") + ENV["HOME"] = user_data_dir + end + end # set CPU core count global const CPU_CORES = ccall(:jl_cpu_cores, Int32, ()) - atexit(()->flush(stdout_stream)) + #atexit(()->flush(STDOUT)) try - ccall(:jl_start_io_thread, Void, ()) - global const Workqueue = WorkItem[] - global const Waiting = Dict(64) - - if !anyp(a->(a=="--worker"), ARGS) - # start in "head node" mode - global const Scheduler = Task(()->event_loop(true), 1024*1024) - global PGRP = ProcessGroup(1, {LocalProcess()}, {Location("",0)}) - # make scheduler aware of current (root) task - enq_work(_jl_roottask_wi) - yield() - else - global PGRP = ProcessGroup(0, {}, {}) + init_sched() + if !any(a->(a=="--worker"), ARGS) + init_head_sched() end - global const LOAD_PATH = ByteString[ - ".", - julia_pkgdir(), - abs_path("$JULIA_HOME/../share/julia"), - abs_path("$JULIA_HOME/../share/julia/base"), - abs_path("$JULIA_HOME/../share/julia/extras"), - abs_path("$JULIA_HOME/../share/julia/ui"), - ] + init_load_path() - (quiet,repl,startup) = process_options(ARGS) + (quiet,repl,startup,color_set) = process_options(ARGS) if repl - if startup - try_include(strcat(ENV["HOME"],"/.juliarc.jl")) + startup && try_include(joinpath(ENV["HOME"],".juliarc.jl")) + + if !color_set + @unix_only global have_color = (beginswith(get(ENV,"TERM",""),"xterm") || success(`tput setaf 0`)) + @windows_only global have_color = true end - global _jl_have_color = begins_with(get(ENV,"TERM",""),"xterm") || - success(`tput setaf 0`) - global _jl_is_interactive = true - if !quiet - _jl_banner() + global is_interactive = true + quiet || banner() + + if has(ENV,"JL_ANSWER_COLOR") + warn("JL_ANSWER_COLOR is deprecated, use JULIA_ANSWER_COLOR instead.") + ENV["JULIA_ANSWER_COLOR"] = ENV["JL_ANSWER_COLOR"] end + run_repl() end - catch e - show(add_backtrace(e,backtrace())) + catch err + display_error(err,catch_backtrace()) println() exit(1) end + if is_interactive + if have_color + print(color_normal) + end + println() + end + ccall(:uv_atexit_hook, Void, ()) end -const _jl_atexit_hooks = {} +const atexit_hooks = {} -atexit(f::Function) = (enqueue(_jl_atexit_hooks, f); nothing) +atexit(f::Function) = (unshift!(atexit_hooks, f); nothing) function _atexit() - for f in _jl_atexit_hooks + for f in atexit_hooks try f() - catch e - show(e) + catch err + show(err) println() end end diff --git a/base/combinatorics.jl b/base/combinatorics.jl index 26ff247dd3af2..5349ec2c4e1c1 100644 --- a/base/combinatorics.jl +++ b/base/combinatorics.jl @@ -22,12 +22,8 @@ function factorial{T<:Integer}(n::T, k::T) return f end -nPr(n, r) = factorial(n, n-r) - function binomial{T<:Integer}(n::T, k::T) - if k < 0 - return zero(T) - end + k < 0 && return zero(T) sgn = one(T) if n < 0 n = -n + k -1 @@ -35,15 +31,9 @@ function binomial{T<:Integer}(n::T, k::T) sgn = -sgn end end - if k > n # TODO: is this definitely right? - return zero(T) - end - if k == 0 || k == n - return sgn - end - if k == 1 - return sgn*n - end + k > n && return zero(T) + (k == 0 || k == n) && return sgn + k == 1 && return sgn*n if k > (n>>1) k = (n - k) end @@ -51,34 +41,30 @@ function binomial{T<:Integer}(n::T, k::T) nn += 1.0 rr = 2.0 while rr <= k - x *= (nn/rr) + x *= nn/rr rr += 1 nn += 1 end - return sgn*iround(T,x) + sgn*iround(T,x) end -const nCr = binomial - pascal(n) = [binomial(i+j-2,i-1) for i=1:n,j=1:n] ## other ordering related functions ## function shuffle!(a::AbstractVector) for i = length(a):-1:2 - j = randi(i) + j = rand(1:i) a[i], a[j] = a[j], a[i] end return a end -@in_place_matrix_op shuffle - function randperm(n::Integer) a = Array(typeof(n), n) a[1] = 1 for i = 2:n - j = randi(i) + j = rand(1:i) a[i] = a[j] a[j] = i end @@ -89,7 +75,7 @@ function randcycle(n::Integer) a = Array(typeof(n), n) a[1] = 1 for i = 2:n - j = randi(i-1) + j = rand(1:i-1) a[i] = a[j] a[j] = i end @@ -97,8 +83,8 @@ function randcycle(n::Integer) end function nthperm!(a::AbstractVector, k::Integer) + k -= 1 # make k 1-indexed n = length(a) - k -= 1 # make k 1-indexed f = factorial(oftype(k, n-1)) for i=1:n-1 j = div(k, f) + 1 @@ -144,6 +130,54 @@ function isperm(a::AbstractVector) return isempty(b) || b[1]!=0 end +function permute!!(a, p::AbstractVector{Int}) + count = 0 + start = 0 + while count < length(a) + ptr = start = findnext(p, start+1) + temp = a[start] + next = p[start] + count += 1 + while next != start + a[ptr] = a[next] + p[ptr] = 0 + ptr = next + next = p[next] + count += 1 + end + a[ptr] = temp + p[ptr] = 0 + end + a +end + +permute!(a, p::AbstractVector{Int}) = permute!!(a, copy(p)) + +function ipermute!!(a, p::AbstractVector{Int}) + count = 0 + start = 0 + while count < length(a) + start = findnext(p, start+1) + temp = a[start] + next = p[start] + count += 1 + while next != start + temp_next = a[next] + a[next] = temp + temp = temp_next + ptr = p[next] + p[next] = 0 + next = ptr + count += 1 + end + a[next] = temp + p[next] = 0 + end + a +end + +ipermute!(a, p::AbstractVector{Int}) = ipermute!!(a, copy(p)) + # Algorithm T from TAoCP 7.2.1.3 function combinations(a::AbstractVector, t::Integer) # T1 @@ -257,12 +291,12 @@ function partitions{T}(s::AbstractVector{T}) # convert from restricted growth string a[1:n] to set of sets temp = [ Array(T,0) for k = 1:n ] for k = 1:n - push(temp[a[k]+1], s[k]) + push!(temp[a[k]+1], s[k]) end result = Array(Array{T,1},0) for arr in temp if !isempty(arr) - push(result, arr) + push!(result, arr) end end #produce(a[1:n]) # this is the string representing set assignment diff --git a/base/complex.jl b/base/complex.jl index 006cb1bd45be1..18fccb9746dad 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -1,6 +1,43 @@ -## generic complex number definitions ## +immutable Complex{T<:Real} <: Number + re::T + im::T +end +Complex(x::Real, y::Real) = Complex(promote(x,y)...) +Complex(x::Real) = Complex(x, zero(x)) + +typealias Complex128 Complex{Float64} +typealias Complex64 Complex{Float32} +typealias ComplexPair Complex + +real(z::Complex) = z.re +imag(z::Complex) = z.im +real(x::Real) = x +imag(x::Real) = zero(x) + +convert{T<:Real}(::Type{Complex{T}}, x::Real) = + Complex{T}(convert(T,x), convert(T,0)) +convert{T<:Real}(::Type{Complex{T}}, z::Complex{T}) = z +convert{T<:Real}(::Type{Complex{T}}, z::Complex) = + Complex{T}(convert(T,real(z)),convert(T,imag(z))) + +convert{T<:Real}(::Type{T}, z::Complex) = (imag(z)==0 ? convert(T,real(z)) : + throw(InexactError())) + +promote_rule{T<:Real}(::Type{Complex{T}}, ::Type{T}) = Complex{T} +promote_rule{T<:Real,S<:Real}(::Type{Complex{T}}, ::Type{S}) = + Complex{promote_type(T,S)} +promote_rule{T<:Real,S<:Real}(::Type{Complex{T}}, ::Type{Complex{S}}) = + Complex{promote_type(T,S)} -abstract Complex{T<:Real} <: Number +complex(x, y) = Complex(x, y) +complex(x) = Complex(x) + +complex128(r::Float64, i::Float64) = Complex{Float64}(r, i) +complex128(r::Real, i::Real) = complex128(float64(r),float64(i)) +complex128(z) = complex128(real(z), imag(z)) +complex64(r::Float32, i::Float32) = Complex{Float32}(r, i) +complex64(r::Real, i::Real) = complex64(float32(r),float32(i)) +complex64(z) = complex64(real(z), imag(z)) iscomplex(x::Complex) = true iscomplex(x::Number) = false @@ -8,13 +45,10 @@ iscomplex(x::Number) = false real_valued{T<:Real}(z::Complex{T}) = imag(z) == 0 integer_valued(z::Complex) = real_valued(z) && integer_valued(real(z)) -real(x::Real) = x -imag(x::Real) = zero(x) - isfinite(z::Complex) = isfinite(real(z)) && isfinite(imag(z)) reim(z) = (real(z), imag(z)) -function _jl_show(io, z::Complex, compact::Bool) +function complex_show(io::IO, z::Complex, compact::Bool) r, i = reim(z) if isnan(r) || isfinite(i) compact ? showcompact(io,r) : show(io,r) @@ -34,150 +68,35 @@ function _jl_show(io, z::Complex, compact::Bool) print(io, "complex(",r,",",i,")") end end -show(io, z::Complex) = _jl_show(io, z, false) -showcompact(io, z::Complex) = _jl_show(io, z, true) - -convert{T<:Real}(::Type{T}, z::Complex) = (imag(z)==0 ? convert(T,real(z)) : - throw(InexactError())) - -## packed complex float types ## - -bitstype 128 Complex128 <: Complex{Float64} - -function complex128(r::Float64, i::Float64) - box(Complex128, - or_int(shl_int(zext_int(Complex128,unbox(Float64,i)), 64), - zext_int(Complex128,unbox(Float64,r)))) -end - -complex128(r::Real, i::Real) = complex128(float64(r),float64(i)) -complex128(z) = complex128(real(z), imag(z)) - -real(c::Complex128) = box(Float64,trunc64(c)) -imag(c::Complex128) = box(Float64,trunc64(ashr_int(c, 64))) - -convert(::Type{Complex128}, x::Real) = complex128(x,0) -convert(::Type{Complex128}, z::Complex128) = z -convert(::Type{Complex128}, z::Complex) = complex128(real(z),imag(z)) - -promote_rule(::Type{Complex128}, ::Type{Float64}) = Complex128 -promote_rule(::Type{Complex128}, ::Type{Float32}) = Complex128 -promote_rule{S<:Integer}(::Type{Complex128}, ::Type{S}) = Complex128 -promote_rule{S<:Real}(::Type{Complex128}, ::Type{S}) = - (P = promote_type(Float64,S); - is(P,Float64) ? Complex128 : ComplexPair{P}) - -function read(s, ::Type{Complex128}) - r = read(s,Float64) - i = read(s,Float64) - complex128(r,i) -end -function write(s, z::Complex128) - write(s,real(z)) - write(s,imag(z)) -end - -sizeof(::Type{Complex128}) = 16 - -bitstype 64 Complex64 <: Complex{Float32} - -function complex64(r::Float32, i::Float32) - box(Complex64, - or_int(shl_int(zext_int(Complex64,unbox(Float32,i)), 32), - zext_int(Complex64,unbox(Float32,r)))) -end - -complex64(r::Real, i::Real) = complex64(float32(r),float32(i)) -complex64(z) = complex64(real(z), imag(z)) +show(io::IO, z::Complex) = complex_show(io, z, false) +showcompact(io::IO, z::Complex) = complex_show(io, z, true) -real(c::Complex64) = box(Float32,trunc32(c)) -imag(c::Complex64) = box(Float32,trunc32(ashr_int(c, 32))) - -convert(::Type{Complex64}, x::Real) = complex64(x,0) -convert(::Type{Complex64}, z::Complex64) = z -convert(::Type{Complex64}, z::Complex) = complex64(real(z),imag(z)) - -promote_rule(::Type{Complex64}, ::Type{Float64}) = Complex128 -promote_rule(::Type{Complex64}, ::Type{Float32}) = Complex64 -promote_rule{S<:Integer}(::Type{Complex64}, ::Type{S}) = Complex64 -promote_rule{S<:Real}(::Type{Complex64}, ::Type{S}) = - (P = promote_type(Float32,S); - is(P,Float64) ? Complex128 : - is(P,Float32) ? Complex64 : ComplexPair{P}) -promote_rule(::Type{Complex128}, ::Type{Complex64}) = Complex128 - -function read(s, ::Type{Complex64}) - r = read(s,Float32) - i = read(s,Float32) - complex64(r,i) +function read{T<:Real}(s::IO, ::Type{Complex{T}}) + r = read(s,T) + i = read(s,T) + Complex{T}(r,i) end -function write(s, z::Complex64) +function write(s::IO, z::Complex) write(s,real(z)) write(s,imag(z)) end -sizeof(::Type{Complex64}) = 8 - -complex(x::Float64, y::Float64) = complex128(x, y) -complex(x::Float32, y::Float32) = complex64(x, y) -complex(x::FloatingPoint, y::FloatingPoint) = complex(promote(x,y)...) -complex(x::FloatingPoint, y::Real) = complex(promote(x,y)...) -complex(x::Real, y::FloatingPoint) = complex(promote(x,y)...) -complex(x::FloatingPoint) = complex(x, zero(x)) - - -## complex with arbitrary component type ## - -type ComplexPair{T<:Real} <: Complex{T} - re::T - im::T -end -ComplexPair(x::Real, y::Real) = ComplexPair(promote(x,y)...) -ComplexPair(x::Real) = ComplexPair(x, zero(x)) - -real(z::ComplexPair) = z.re -imag(z::ComplexPair) = z.im - -convert{T<:Real}(::Type{ComplexPair{T}}, x::Real) = - ComplexPair(convert(T,x), convert(T,0)) -convert{T<:Real}(::Type{ComplexPair{T}}, z::ComplexPair{T}) = z -convert{T<:Real}(::Type{ComplexPair{T}}, z::Complex) = - ComplexPair(convert(T,real(z)),convert(T,imag(z))) - -promote_rule{T<:Real}(::Type{ComplexPair{T}}, ::Type{T}) = - ComplexPair{T} -promote_rule{T<:Real,S<:Real}(::Type{ComplexPair{T}}, ::Type{S}) = - ComplexPair{promote_type(T,S)} -promote_rule{T<:Real,S<:Real}(::Type{ComplexPair{T}}, ::Type{ComplexPair{S}}) = - ComplexPair{promote_type(T,S)} -promote_rule{T<:Real}(::Type{ComplexPair{T}}, ::Type{Complex128}) = - (P = promote_type(Float64,T); - is(P,Float64) ? Complex128 : ComplexPair{P}) -promote_rule{T<:Real}(::Type{ComplexPair{T}}, ::Type{Complex64}) = - (P = promote_type(Float32,T); - is(P,Float64) ? Complex128 : is(P,Float32) ? Complex64 : ComplexPair{P}) - -complex(x, y) = ComplexPair(x, y) -complex(x) = ComplexPair(x) - ## singleton type for imaginary unit constant ## -type ImaginaryUnit <: Complex{Int32}; end +type ImaginaryUnit <: Number end const im = ImaginaryUnit() -convert{T<:Real}(::Type{ComplexPair{T}}, ::ImaginaryUnit) = - ComplexPair(zero(T),one(T)) -convert(::Type{Complex128}, ::ImaginaryUnit) = complex128(0,1) -convert(::Type{Complex64}, ::ImaginaryUnit) = complex64(0,1) +iscomplex(::ImaginaryUnit) = true + +convert{T<:Real}(::Type{Complex{T}}, ::ImaginaryUnit) = Complex{T}(zero(T),one(T)) +convert(::Type{Complex}, ::ImaginaryUnit) = Complex(real(im),imag(im)) real(::ImaginaryUnit) = int32(0) imag(::ImaginaryUnit) = int32(1) promote_rule{T<:Complex}(::Type{ImaginaryUnit}, ::Type{T}) = T -promote_rule{T<:Real}(::Type{ImaginaryUnit}, ::Type{T}) = ComplexPair{T} -promote_rule(::Type{ImaginaryUnit}, ::Type{Float64}) = Complex128 -promote_rule(::Type{ImaginaryUnit}, ::Type{Float32}) = Complex64 +promote_rule{T<:Real}(::Type{ImaginaryUnit}, ::Type{T}) = Complex{T} ## generic functions of complex numbers ## @@ -195,8 +114,6 @@ isequal(x::Real, z::Complex) = real_valued(z) && isequal(real(z),x) hash(z::Complex) = (r = hash(real(z)); real_valued(z) ? r : bitmix(r,hash(imag(z)))) -eps(z::Complex) = eps(abs(z)) - conj(z::Complex) = complex(real(z),-imag(z)) abs(z::Complex) = hypot(real(z), imag(z)) abs2(z::Complex) = real(z)*real(z) + imag(z)*imag(z) @@ -254,15 +171,14 @@ end function sqrt(z::Complex) rz = float(real(z)) iz = float(imag(z)) - T = promote_type(typeof(rz),typeof(z)) - r = sqrt(0.5*(hypot(rz,iz)+abs(rz))) + r = sqrt((hypot(rz,iz)+abs(rz))/2) if r == 0 - return convert(T,complex(0.0, iz)) + return complex(zero(iz), iz) end if rz >= 0 - return convert(T,complex(r, 0.5*iz/r)) + return complex(r, iz/r/2) end - return convert(T,complex(0.5*abs(iz)/r, iz >= 0 ? r : -r)) + return complex(abs(iz)/r/2, iz >= 0 ? r : -r) end cis(theta::Real) = complex(cos(theta),sin(theta)) @@ -317,66 +233,55 @@ function exp(z::Complex) end function ^{T<:Complex}(z::T, p::T) - realp = real(p) - if imag(p) == 0 - if realp == 0 - return one(z) - elseif realp == 1 - return z - elseif realp == 2 - return z*z - elseif realp == 0.5 - return sqrt(z) - end - end + realp = real(p); imagp = imag(p) + realz = real(z); imagz = imag(z) r = abs(z) rp = r^realp - realz = real(z) - zer = zero(r) - if imag(p) == 0 + theta = atan2(imagz, realz) + ntheta = realp*theta + if imagp != 0 && r != 0 + rp = rp*exp(-imagp*theta) + ntheta = ntheta + imagp*log(r) + end + cosntheta = cos(ntheta) + sinntheta = sin(ntheta) + re, im = rp*cosntheta, rp*sinntheta + if isinf(rp) + if isnan(re) + re = copysign(zero(re), cosntheta) + end + if isnan(im) + im = copysign(zero(im), sinntheta) + end + end + + # apply some corrections to force known zeros + if imagp == 0 ip = itrunc(realp) if ip == realp - # integer multiples of pi/2 - if imag(z) == 0 && realz < 0 - return complex(isodd(ip) ? -rp : rp, zer) - elseif realz == 0 && imag(z) < 0 + if imagz == 0 + im = copysign(zero(im), im) + elseif realz == 0 if isodd(ip) - return complex(zer, isodd(div(ip-1,2)) ? rp : -rp) + re = copysign(zero(re), re) else - return complex(isodd(div(ip,2)) ? -rp : rp, zer) - end - elseif realz == 0 && imag(z) > 0 - if isodd(ip) - return complex(zer, isodd(div(ip-1,2)) ? -rp : rp) - else - return complex(isodd(div(ip,2)) ? -rp : rp, zer) + im = copysign(zero(im), im) end end else dr = realp*2 ip = itrunc(dr) - # 1/2 multiples of pi - if ip == dr && imag(z) == 0 + if ip == dr && imagz == 0 if realz < 0 - return complex(zer, isodd(div(ip-1,2)) ? -rp : rp) - elseif realz >= 0 - return complex(rp, zer) + re = copysign(zero(re), re) + else + im = copysign(zero(im), im) end end end end - imagz = imag(z) - if imagz==0 && realz>=0 - ntheta = imag(p)*log(r) - else - theta = atan2(imagz, realz) - ntheta = realp*theta - if imag(p) != 0 - rp = rp*exp(-imag(p)*theta) - ntheta = ntheta + imag(p)*log(r) - end - end - complex(rp*cos(ntheta), rp*sin(ntheta)) + + complex(re, im) end function tan(z::Complex) diff --git a/base/darray.jl b/base/darray.jl index dcaf753e0149d..cd44abc28e7a5 100644 --- a/base/darray.jl +++ b/base/darray.jl @@ -56,9 +56,9 @@ function serialize{T,N,dd}(s, d::DArray{T,N,dd}) emptylocl = Array(T, ntuple(length(sz), i->(i==d.distdim ? 0 : sz[i]))) invoke(serialize, (Any, Any), s, - ccall(:jl_new_structt, Any, (Any, Any), + ccall(:jl_new_struct, Any, (Any, Any...), DArray{T,N,dd}, - (sz, emptylocl, d.pmap, d.dist, d.distdim, 0, d.go))) + sz, emptylocl, d.pmap, d.dist, d.distdim, 0, d.go)) else serialize(s, d.go) end @@ -174,7 +174,7 @@ function localize_copy(src::SubDArray, dest::DArray) end # piece numbers covered by a subarray -function _jl_sub_da_pieces(s::SubDArray) +function sub_da_pieces(s::SubDArray) dd = s.parent.distdim sdi = s.indexes[dd] if isa(sdi,Integer) @@ -189,10 +189,10 @@ function _jl_sub_da_pieces(s::SubDArray) return lo:hi end -procs(s::SubDArray) = s.parent.pmap[_jl_sub_da_pieces(s)] +procs(s::SubDArray) = s.parent.pmap[sub_da_pieces(s)] function dist(s::SubDArray) - pcs = _jl_sub_da_pieces(s) + pcs = sub_da_pieces(s) sizes = [ length(pieceindex(s, p)) for p = pcs ] cumsum([1, sizes]) end @@ -221,9 +221,9 @@ function locate(d::DArray, I::Range1{Int}) if i >= d.dist[j+1] j += 1 else - push(pmap,j) + push!(pmap,j) i = min(imax+1,d.dist[j+1]) - push(dist,i) + push!(dist,i) j += 1 end end @@ -246,9 +246,9 @@ function locate(d::DArray, I::AbstractVector{Int}) if i >= d.dist[j+1] j += 1 else - push(pmap,j) + push!(pmap,j) i = min(imax+1,d.dist[j+1]) - push(dist,i) + push!(dist,i) j += 1 end end @@ -311,21 +311,21 @@ similar(d::DArray, T::Type, dims::Dims) = copy{T}(d::SubOrDArray{T}) = darray((T,lsz,da)->localize_copy(d, da), T, size(d), distdim(d), procs(d)) -function copy_to(d::DArray, src::SubOrDArray) +function copy!(d::DArray, src::SubOrDArray) @sync begin for p = d.pmap - @spawnat p copy_to(localize(d), localize(src, d)) + @spawnat p copy!(localize(d), localize(src, d)) end end return d end -function copy_to(d::DArray, src::AbstractArray) +function copy!(d::DArray, src::AbstractArray) @sync begin for i = 1:length(d.pmap) p = d.pmap[i] block = src[pieceindexes(d, i)...] - @spawnat p copy_to(localize(d), block) + @spawnat p copy!(localize(d), block) end end return d @@ -347,12 +347,12 @@ function distribute{T}(a::Array{T}, distdim) # create a remotely-visible reference to the array rr = RemoteRef() put(rr, a) - darray((T,lsz,da)->_jl_distribute_one(T,lsz,da,distdim,owner,rr), + darray((T,lsz,da)->distribute_one(T,lsz,da,distdim,owner,rr), T, size(a), distdim) end # fetch one processor's piece of an array being distributed -function _jl_distribute_one(T, lsz, da, distdim, owner, orig_array) +function distribute_one(T, lsz, da, distdim, owner, orig_array) if prod(lsz)==0 return Array(T, lsz) end @@ -362,7 +362,7 @@ function _jl_distribute_one(T, lsz, da, distdim, owner, orig_array) # indexes of original array I will take idxs = { 1:lsz[i] for i=1:length(da.dims) } idxs[distdim] = (i1:iend) - remote_call_fetch(owner, ref, orig_array, idxs...) + remote_call_fetch(owner, getindex, orig_array, idxs...) end convert{T,N}(::Type{Array}, d::DArray{T,N}) = convert(Array{T,N}, d) @@ -391,7 +391,7 @@ function changedist{T}(A::DArray{T}, to_dist) return darray((T,sz,da)->A[myindexes(da)...], T, size(A), to_dist, A.pmap) end -function _jl_da_reshape(T, sz, da, A) +function da_reshape(T, sz, da, A) mi = myindexes(da) i0s = map(first, mi) i1s = map(last, mi) @@ -402,10 +402,10 @@ function _jl_da_reshape(T, sz, da, A) end function reshape(A::DArray, dims::Dims) - if prod(dims) != numel(A) + if prod(dims) != length(A) error("reshape: invalid dimensions") end - darray((T,sz,da)->_jl_da_reshape(T,sz,da,A), + darray((T,sz,da)->da_reshape(T,sz,da,A), eltype(A), dims, maxdim(dims), A.pmap) end @@ -415,47 +415,47 @@ ctranspose{T<:Real}(v::DArray{T,1}) = transpose(v) ## Indexing ## -ref(r::RemoteRef) = invoke(ref, (RemoteRef, Any...), r) -function ref(r::RemoteRef, args...) +getindex(r::RemoteRef) = invoke(getindex, (RemoteRef, Any...), r) +function getindex(r::RemoteRef, args...) if r.where==myid() - ref(fetch(r), args...) + getindex(fetch(r), args...) else - remote_call_fetch(r.where, ref, r, args...) + remote_call_fetch(r.where, getindex, r, args...) end end -function assign(r::RemoteRef, args...) +function setindex!(r::RemoteRef, args...) if r.where==myid() - assign(fetch(r), args...) + setindex!(fetch(r), args...) else - sync_add(remote_call(r.where, assign, r, args...)) + sync_add(remote_call(r.where, setindex!, r, args...)) end end -# 1d scalar ref -function ref{T}(d::DArray{T,1}, i::Int) +# 1d scalar getindex +function getindex{T}(d::DArray{T,1}, i::Int) p = locate(d, i) if p==d.localpiece offs = d.dist[p]-1 return localize(d)[i-offs] end - return remote_call_fetch(d.pmap[p], ref, d, i)::T + return remote_call_fetch(d.pmap[p], getindex, d, i)::T end -# 1d scalar assign -function assign{T}(d::DArray{T,1}, v, i::Int) +# 1d scalar setindex! +function setindex!{T}(d::DArray{T,1}, v, i::Int) p = locate(d, i) if p==d.localpiece offs = d.dist[p]-1 localize(d)[i-offs] = v else - sync_add(remote_call(d.pmap[p], assign, d, v, i)) + sync_add(remote_call(d.pmap[p], setindex!, d, v, i)) end d end -# Nd scalar ref -function ref_elt{T}(d::DArray{T}, sub::(Int...)) +# Nd scalar getindex +function getindex_elt{T}(d::DArray{T}, sub::(Int...)) p = locate(d, sub[d.distdim]) if p==d.localpiece offs = d.dist[p]-1 @@ -465,23 +465,23 @@ function ref_elt{T}(d::DArray{T}, sub::(Int...)) end return localize(d)[sub...]::T end - return remote_call_fetch(d.pmap[p], ref_elt, d, sub)::T + return remote_call_fetch(d.pmap[p], getindex_elt, d, sub)::T end -ref(d::DArray, i::Int) = ref_elt(d, ind2sub(d.dims, i)) -ref(d::DArray, I::Int...) = ref_elt(d, I) +getindex(d::DArray, i::Int) = getindex_elt(d, ind2sub(d.dims, i)) +getindex(d::DArray, I::Int...) = getindex_elt(d, I) -ref(d::DArray) = d +getindex(d::DArray) = d -function _jl_da_sub(d::DArray, I::Range1{Int}...) +function da_sub(d::DArray, I::Range1{Int}...) offs = d.dist[d.localpiece]-1 J = ntuple(ndims(d), i -> (i == d.distdim ? I[i]-offs : I[i])) return sub(localize(d), J) end -# Nd ref with Range1 indexes -function ref{T}(d::DArray{T}, I::Range1{Int}...) +# Nd getindex with Range1 indexes +function getindex{T}(d::DArray{T}, I::Range1{Int}...) (pmap, dist) = locate(d, I[d.distdim]) np = length(pmap) if np == 1 && pmap[1] == d.localpiece @@ -495,9 +495,9 @@ function ref{T}(d::DArray{T}, I::Range1{Int}...) K = [ i==d.distdim ? (dist[p]:(dist[p+1]-1)) : I[i] for i=1:ndims(d) ] if np == 1 # use remote_call_fetch if we only need to communicate with 1 proc - deps[p] = remote_call_fetch(d.pmap[pmap[p]], _jl_da_sub, d, K...) + deps[p] = remote_call_fetch(d.pmap[pmap[p]], da_sub, d, K...) else - deps[p] = remote_call(d.pmap[pmap[p]], _jl_da_sub, d, K...) + deps[p] = remote_call(d.pmap[pmap[p]], da_sub, d, K...) end end for p = 1:np @@ -509,15 +509,15 @@ function ref{T}(d::DArray{T}, I::Range1{Int}...) end # combinations of Range1 and scalar indexes -ref(d::DArray, I::Range1{Int}, j::Int) = d[I, j:j] -ref(d::DArray, i::Int, J::Range1{Int}) = d[i:i, J] +getindex(d::DArray, I::Range1{Int}, j::Int) = d[I, j:j] +getindex(d::DArray, i::Int, J::Range1{Int}) = d[i:i, J] -ref(d::DArray, I::Union(Int,Range1{Int})...) = +getindex(d::DArray, I::Union(Int,Range1{Int})...) = d[[isa(i,Int) ? (i:i) : i for i in I ]...] -# Nd ref with vector indexes -function ref{T}(d::DArray{T}, I::AbstractVector{Int}...) +# Nd getindex with vector indexes +function getindex{T}(d::DArray{T}, I::AbstractVector{Int}...) (pmap, dist, perm) = locate(d,[I[d.distdim]]) np = length(pmap) if np == 1 && pmap[1] == d.localpiece @@ -538,9 +538,9 @@ function ref{T}(d::DArray{T}, I::AbstractVector{Int}...) end K = [ i==d.distdim ? II[lower:(j-1)] : I[i] for i=1:ndims(d) ] if np == 1 - deps[p] = remote_call_fetch(d.pmap[pmap[p]], ref, d, K...) + deps[p] = remote_call_fetch(d.pmap[pmap[p]], getindex, d, K...) else - deps[p] = remote_call(d.pmap[pmap[p]], ref, d, K...) + deps[p] = remote_call(d.pmap[pmap[p]], getindex, d, K...) end end j = 1 @@ -557,14 +557,14 @@ function ref{T}(d::DArray{T}, I::AbstractVector{Int}...) end # combinations of vector and scalar indexes -ref(d::DArray, I::AbstractVector{Int}, j::Int) = d[I, [j]] -ref(d::DArray, i::Int, J::AbstractVector{Int}) = d[[i], J] +getindex(d::DArray, I::AbstractVector{Int}, j::Int) = d[I, [j]] +getindex(d::DArray, i::Int, J::AbstractVector{Int}) = d[[i], J] -ref(d::DArray, I::Union(Int,AbstractVector{Int})...) = +getindex(d::DArray, I::Union(Int,AbstractVector{Int})...) = d[[isa(i,Int) ? [i] : i for i in I]...] -# Nd scalar assign -function assign_elt(d::DArray, v, sub::(Int...)) +# Nd scalar setindex! +function setindex!_elt(d::DArray, v, sub::(Int...)) p = locate(d, sub[d.distdim]) if p==d.localpiece offs = d.dist[p]-1 @@ -574,19 +574,19 @@ function assign_elt(d::DArray, v, sub::(Int...)) end localize(d)[sub...] = v else - sync_add(remote_call(d.pmap[p], assign_elt, d, v, sub)) + sync_add(remote_call(d.pmap[p], setindex!_elt, d, v, sub)) end d end -assign(d::DArray, v, i::Int) = assign_elt(d, v, ind2sub(d.dims, i)) -assign(d::DArray, v, i0::Int, I::Int...) = assign_elt(d, v, tuple(i0,I...)) +setindex!(d::DArray, v, i::Int) = setindex!_elt(d, v, ind2sub(d.dims, i)) +setindex!(d::DArray, v, i0::Int, I::Int...) = setindex!_elt(d, v, tuple(i0,I...)) #TODO: Fix this -assign(d::DArray, v) = error("distributed arrays of dimension 0 not supported") +setindex!(d::DArray, v) = error("distributed arrays of dimension 0 not supported") -# Nd assign, scalar fill case, with Range1 indexes -function assign(d::DArray, v, I::Range1{Int}...) +# Nd setindex!, scalar fill case, with Range1 indexes +function setindex!(d::DArray, v, I::Range1{Int}...) (pmap, dist) = locate(d, I[d.distdim]) if length(pmap) == 1 && pmap[1] == d.localpiece offs = d.dist[pmap[1]]-1 @@ -596,14 +596,14 @@ function assign(d::DArray, v, I::Range1{Int}...) end for p = 1:length(pmap) K = [ i==d.distdim ? (dist[p]:(dist[p+1]-1)) : I[i] for i=1:ndims(d) ] - sync_add(remote_call(d.pmap[pmap[p]], assign, d, v, K...)) + sync_add(remote_call(d.pmap[pmap[p]], setindex!, d, v, K...)) end return d end -# Nd assign, array copy case, with Range1 indexes -function assign(d::DArray, v::AbstractArray, I::Range1{Int}...) - assign_shape_check(v, I...) +# Nd setindex!, array copy case, with Range1 indexes +function setindex!(d::DArray, v::AbstractArray, I::Range1{Int}...) + setindex_shape_check(v, I...) (pmap, dist) = locate(d, I[d.distdim]) if length(pmap) == 1 && pmap[1] == d.localpiece offs = d.dist[pmap[1]]-1 @@ -620,13 +620,13 @@ function assign(d::DArray, v::AbstractArray, I::Range1{Int}...) (1:length(I[i])))) K = ntuple(ndims(d),i->(i==d.distdim ? (dist[p]:(dist[p+1]-1)) : I[i])) - sync_add(remote_call(d.pmap[pmap[p]], assign, d, sub(v,J), K...)) + sync_add(remote_call(d.pmap[pmap[p]], setindex!, d, sub(v,J), K...)) end return d end -# Nd assign, scalar fill case, vector indexes -function assign(d::DArray, v, I::AbstractVector{Int}...) +# Nd setindex!, scalar fill case, vector indexes +function setindex!(d::DArray, v, I::AbstractVector{Int}...) (pmap, dist, perm) = locate(d, I[d.distdim]) if length(pmap) == 1 && pmap[1] == d.localpiece offs = d.dist[pmap[1]]-1 @@ -644,14 +644,14 @@ function assign(d::DArray, v, I::AbstractVector{Int}...) j += 1 end K = [ i==d.distdim ? II[lower:(j-1)] : I[i] for i=1:ndims(d) ] - sync_add(remote_call(d.pmap[pmap[p]], assign, d, v, K...)) + sync_add(remote_call(d.pmap[pmap[p]], setindex!, d, v, K...)) end return d end -# Nd assign, array copy case, vector indexes -function assign(d::DArray, v::AbstractArray, I::AbstractVector{Int}...) - assign_shape_check(v, I...) +# Nd setindex!, array copy case, vector indexes +function setindex!(d::DArray, v::AbstractArray, I::AbstractVector{Int}...) + setindex_shape_check(v, I...) (pmap, dist, perm) = locate(d, I[d.distdim]) if length(pmap) == 1 && pmap[1] == d.localpiece offs = d.dist[pmap[1]]-1 @@ -675,22 +675,22 @@ function assign(d::DArray, v::AbstractArray, I::AbstractVector{Int}...) (1:length(I[i])))) K = ntuple(ndims(d),i->(i==d.distdim ? II[lower:(j-1)] : I[i])) - sync_add(remote_call(d.pmap[pmap[p]], assign, d, sub(v,J), K...)) + sync_add(remote_call(d.pmap[pmap[p]], setindex!, d, sub(v,J), K...)) end return d end -# assign with combinations of Range1 and scalar indexes -assign(d::DArray, v, I::Union(Int,Range1{Int})...) = - assign(d, v, [isa(i,Int) ? (i:i) : i for i in I]...) +# setindex! with combinations of Range1 and scalar indexes +setindex!(d::DArray, v, I::Union(Int,Range1{Int})...) = + setindex!(d, v, [isa(i,Int) ? (i:i) : i for i in I]...) -# assign with combinations of vector and scalar indexes -assign(d::DArray, v, I::Union(Int,AbstractVector{Int})...) = - assign(d, v, [isa(i,Int) ? [i] : i for i in I]...) +# setindex! with combinations of vector and scalar indexes +setindex!(d::DArray, v, I::Union(Int,AbstractVector{Int})...) = + setindex!(d, v, [isa(i,Int) ? [i] : i for i in I]...) ## matrix multiply ## -function _jl_node_multiply2{T}(A::AbstractArray{T}, B, sz) +function node_multiply2{T}(A::AbstractArray{T}, B, sz) locl = Array(T, sz) if !isempty(locl) Bdata = localize(B) @@ -710,16 +710,16 @@ function _jl_node_multiply2{T}(A::AbstractArray{T}, B, sz) end function (*){T}(A::DArray{T,2,1}, B::DArray{T,2,2}) - darray((T,sz,da)->_jl_node_multiply2(A,B,sz), T, (size(A,1),size(B,2)), 2, + darray((T,sz,da)->node_multiply2(A,B,sz), T, (size(A,1),size(B,2)), 2, B.pmap) end function (*){T}(A::DArray{T,2}, B::DArray{T,2,2}) - darray((T,sz,da)->_jl_node_multiply2(A,B,sz), T, (size(A,1),size(B,2)), 2, + darray((T,sz,da)->node_multiply2(A,B,sz), T, (size(A,1),size(B,2)), 2, B.pmap) end -function _jl_node_multiply1{T}(A::AbstractArray{T}, B, sz) +function node_multiply1{T}(A::AbstractArray{T}, B, sz) locl = Array(T, sz) if !isempty(locl) Adata = localize(A) @@ -739,7 +739,7 @@ function _jl_node_multiply1{T}(A::AbstractArray{T}, B, sz) end function (*){T}(A::DArray{T,2,1}, B::DArray{T,2}) - darray((T,sz,da)->_jl_node_multiply1(A,B,sz), T, (size(A,1),size(B,2)), 1, + darray((T,sz,da)->node_multiply1(A,B,sz), T, (size(A,1),size(B,2)), 1, A.pmap) end @@ -807,7 +807,7 @@ end # for function map(f, A::SubOrDArray) T = typeof(f(A[1])) - darray((T,lsz,da)->map_to(f, Array(T,lsz), localize(A, da)), + darray((T,lsz,da)->map!(f, Array(T,lsz), localize(A, da)), T, size(A), distdim(A), procs(A)) end @@ -853,7 +853,7 @@ function (==)(A::DArray, B::DArray) if size(A) != size(B) return false end - mapreduce(all, fetch, + mapreduce(fetch, all, { @spawnat p localize(A)==localize(B,A) for p in procs(A) }) end @@ -861,18 +861,18 @@ function (!=)(A::DArray, B::DArray) if size(A) != size(B) return true end - mapreduce(any, fetch, + mapreduce(fetch, any, { @spawnat p localize(A)!=localize(B,A) for p in procs(A) }) end function reduce(f, v::DArray) - mapreduce(f, fetch, + mapreduce(fetch, f, { @spawnat p reduce(f,localize(v)) for p = procs(v) }) end -function mapreduce(op, f, v::DArray) - mapreduce(op, fetch, - { @spawnat p mapreduce(op,f,localize(v)) for p = procs(v) }) +function mapreduce(f, op, v::DArray) + mapreduce(fetch, op, + { @spawnat p mapreduce(f,op,localize(v)) for p = procs(v) }) end sum(d::DArray) = reduce(+, d) @@ -880,7 +880,7 @@ prod(d::DArray) = reduce(*, d) min(d::DArray) = reduce(min, d) max(d::DArray) = reduce(max, d) -areduce(f::Function, d::DArray, r::Dimspec, v0, T::Type) = error("not yet implemented") +reducedim(f::Function, d::DArray, r, v0, T::Type) = error("not yet implemented") cumsum(d::DArray) = error("not yet implemented") cumprod(d::DArray) = error("not yet implemented") @@ -895,7 +895,7 @@ function sum{T}(A::DArray{T}, d::Int) sz = ntuple(ndims(A), i->(i==d ? 1 : size(A,i))) if d == distdim(A) darray(S, sz, distdim(A)) do T,lsz,da - mapreduce(+, fetch, + mapreduce(fetch, +, {@spawnat p sum(localize(A),d) for p in procs(A)}) end else diff --git a/base/darray2.jl b/base/darray2.jl index dcacfa55503f2..d211257308276 100644 --- a/base/darray2.jl +++ b/base/darray2.jl @@ -34,7 +34,7 @@ function DArray(init, dims, procs, dist) for i = 1:np chunks[i] = remote_call(procs[i], init, idxs[i]) end - p = max(1, localpiece(procs)) + p = max(1, localpartindex(procs)) A = remote_call_fetch(procs[p], r->typeof(fetch(r)), chunks[p]) DArray{eltype(A),length(dims),A}(dims, chunks, procs, idxs, cuts) end @@ -60,7 +60,7 @@ function defaultdist(dims, procs) dims = [dims...] chunks = ones(Int, length(dims)) np = length(procs) - f = sortr(keys(factor(np))) + f = sort!(keys(factor(np)), Sort.Reverse) k = 1 while np > 1 # repeatedly allocate largest factor to largest dim @@ -86,7 +86,7 @@ end # get array of start indexes for dividing sz into nc chunks function defaultdist(sz::Int, nc::Int) if sz >= nc - linspace(1, sz+1, nc+1) + iround(linspace(1, sz+1, nc+1)) else [[1:(sz+1)], zeros(Int, nc-sz)] end @@ -103,7 +103,7 @@ function chunk_idxs(dims, chunks) idxs, cuts end -function localpiece(pmap::Vector{Int}) +function localpartindex(pmap::Vector{Int}) mi = myid() for i = 1:length(pmap) if pmap[i] == mi @@ -113,20 +113,26 @@ function localpiece(pmap::Vector{Int}) return 0 end -localpiece(d::DArray) = localpiece(d.pmap) +localpartindex(d::DArray) = localpartindex(d.pmap) -localize{T,N,A}(d::DArray{T,N,A}) = fetch(d.chunks[localpiece(d)])::A -myindexes(d::DArray) = d.indexes[localpiece(d)] +localpart{T,N,A}(d::DArray{T,N,A}) = fetch(d.chunks[localpartindex(d)])::A +myindexes(d::DArray) = d.indexes[localpartindex(d)] # find which piece holds index (I...) function locate(d::DArray, I::Int...) - ntuple(ndims(d), i->search_sorted_last(d.cuts[i], I[i])) + ntuple(ndims(d), i->searchsortedlast(d.cuts[i], I[i])) end chunk{T,N,A}(d::DArray{T,N,A}, i...) = fetch(d.chunks[i...])::A ## convenience constructors ## +dzeros(args...) = DArray(I->zeros(map(length,I)), args...) +dzeros(d::Int...) = dzeros(d) +dones(args...) = DArray(I->ones(map(length,I)), args...) +dones(d::Int...) = dones(d) +dfill(v, args...) = DArray(I->fill(v, map(length,I)), args...) +dfill(v, d::Int...) = dfill(v, d) drand(args...) = DArray(I->rand(map(length,I)), args...) drand(d::Int...) = drand(d) drandn(args...) = DArray(I->randn(map(length,I)), args...) @@ -171,7 +177,7 @@ function convert{S,T,N}(::Type{Array{S,N}}, s::SubDArray{T,N}) end function reshape{T,S<:Array}(A::DArray{T,1,S}, d::Dims) - if prod(d) != numel(A) + if prod(d) != length(A) error("reshape: invalid dimensions") end DArray(d) do I @@ -183,7 +189,7 @@ function reshape{T,S<:Array}(A::DArray{T,1,S}, d::Dims) nr = size(B,1) sztail = size(B)[2:] - for i=1:div(numel(B),nr) + for i=1:div(length(B),nr) i2 = ind2sub(sztail, i) globalidx = [ I[j][i2[j-1]] for j=2:nd ] @@ -197,18 +203,18 @@ end ## indexing ## -function ref(r::RemoteRef, args...) +function getindex(r::RemoteRef, args...) if r.where==myid() - ref(fetch(r), args...) + getindex(fetch(r), args...) else - remote_call_fetch(r.where, ref, r, args...) + remote_call_fetch(r.where, getindex, r, args...) end end -ref(d::DArray, i::Int) = ref(d, ind2sub(size(d), i)) -ref(d::DArray, i::Int...) = ref(d, sub2ind(size(d), i...)) +getindex(d::DArray, i::Int) = getindex(d, ind2sub(size(d), i)) +getindex(d::DArray, i::Int...) = getindex(d, sub2ind(size(d), i...)) -function ref{T}(d::DArray{T}, I::(Int...)) +function getindex{T}(d::DArray{T}, I::(Int...)) chidx = locate(d, I...) chunk = d.chunks[chidx...] idxs = d.indexes[chidx...] @@ -216,15 +222,15 @@ function ref{T}(d::DArray{T}, I::(Int...)) chunk[localidx...]::T end -ref(d::DArray) = d[1] -ref(d::DArray, I::Union(Int,Range1{Int})...) = sub(d,I) +getindex(d::DArray) = d[1] +getindex(d::DArray, I::Union(Int,Range1{Int})...) = sub(d,I) copy(d::SubOrDArray) = d # local copies are obtained by convert(Array, ) or assigning from # a SubDArray to a local Array. -function assign(a::Array, d::DArray, I::Range1{Int}...) +function setindex!(a::Array, d::DArray, I::Range1{Int}...) n = length(I) @sync begin for i = 1:length(d.chunks) @@ -235,7 +241,7 @@ function assign(a::Array, d::DArray, I::Range1{Int}...) a end -function assign(a::Array, s::SubDArray, I::Range1{Int}...) +function setindex!(a::Array, s::SubDArray, I::Range1{Int}...) n = length(I) d = s.parent J = s.indexes @@ -248,7 +254,7 @@ function assign(a::Array, s::SubDArray, I::Range1{Int}...) for i = 1:length(d.chunks) K_c = {d.indexes[i]...} K = [ intersect(J[j],K_c[j]) for j=1:n ] - if !anyp(isempty, K) + if !any(isempty, K) idxs = [ I[j][K[j]-offs[j]] for j=1:n ] if isequal(K, K_c) # whole chunk @@ -265,7 +271,7 @@ function assign(a::Array, s::SubDArray, I::Range1{Int}...) end # to disambiguate -assign(a::Array{Any}, d::SubOrDArray, i::Int) = arrayset(a, d, i) +setindex!(a::Array{Any}, d::SubOrDArray, i::Int) = arrayset(a, d, i) -assign(a::Array, d::SubOrDArray, I::Union(Int,Range1{Int})...) = - assign(a, d, [isa(i,Int) ? (i:i) : i for i in I ]...) +setindex!(a::Array, d::SubOrDArray, I::Union(Int,Range1{Int})...) = + setindex!(a, d, [isa(i,Int) ? (i:i) : i for i in I ]...) diff --git a/base/datafmt.jl b/base/datafmt.jl index 2be6b41527877..e64419f2b2402 100644 --- a/base/datafmt.jl +++ b/base/datafmt.jl @@ -1,36 +1,36 @@ ## file formats ## -const _jl_invalid_dlm = char(0xfffffffe) +const invalid_dlm = char(0xfffffffe) -function _jl_dlm_readrow(io::IO, dlm, eol::Char) +function dlm_readrow(io::IO, dlm, eol::Char) row_string = readuntil(io, eol) while length(row_string)==1 && row_string[1] == eol row_string = readuntil(io, eol) end - if dlm == _jl_invalid_dlm + if dlm == invalid_dlm row = split(row_string) else row = split(row_string, dlm, true) end - if ends_with(row[end], eol) + if endswith(row[end], eol) row[end] = chop(row[end]) end row end # all strings -function _jl_dlmread(a, io, dlm, nr, nc, row, eol) +function readdlm(a, io, dlm, nr, nc, row, eol) for i=1:nr a[i,:] = row if i < nr - row = _jl_dlm_readrow(io, dlm, eol) + row = dlm_readrow(io, dlm, eol) end end a end # all numeric, with NaN for invalid data -function _jl_dlmread{T<:Number}(a::Array{T}, io, dlm, nr, nc, row, eol) +function readdlm{T<:Number}(a::Array{T}, io, dlm, nr, nc, row, eol) tmp = Array(Float64,1) for i=1:nr for j=1:nc @@ -41,15 +41,15 @@ function _jl_dlmread{T<:Number}(a::Array{T}, io, dlm, nr, nc, row, eol) end end if i < nr - row = _jl_dlm_readrow(io, dlm, eol) + row = dlm_readrow(io, dlm, eol) end end end # float64 or string -_jl_dlmread(a::Array{Any}, io, dlm, nr, nc, row, eol) = - _jl_dlmread(a, io, dlm, nr, nc, row, eol, 1, 1) -function _jl_dlmread(a::Array{Any}, io, dlm, nr, nc, row, eol, i0, j0) +readdlm(a::Array{Any}, io, dlm, nr, nc, row, eol) = + readdlm(a, io, dlm, nr, nc, row, eol, 1, 1) +function readdlm(a::Array{Any}, io, dlm, nr, nc, row, eol, i0, j0) tmp = Array(Float64,1) j = j0 for i=i0:nr @@ -64,41 +64,41 @@ function _jl_dlmread(a::Array{Any}, io, dlm, nr, nc, row, eol, i0, j0) end j = 1 if i < nr - row = _jl_dlm_readrow(io, dlm, eol) + row = dlm_readrow(io, dlm, eol) end end a end # float64 or cell depending on data -function _jl_dlmread_auto(a, io, dlm, nr, nc, row, eol) +function readdlm_auto(a, io, dlm, nr, nc, row, eol) tmp = Array(Float64, 1) for i=1:nr for j=1:nc el = row[j] if !float64_isvalid(el, tmp) a = convert(Array{Any,2}, a) - _jl_dlmread(a, io, dlm, nr, nc, row, eol, i, j) + readdlm(a, io, dlm, nr, nc, row, eol, i, j) return a else a[i,j] = tmp[1] end end if i < nr - row = _jl_dlm_readrow(io, dlm, eol) + row = dlm_readrow(io, dlm, eol) end end a end -countlines(io) = countlines(io, '\n') +countlines(nameorfile) = countlines(nameorfile, '\n') function countlines(filename::String, eol::Char) open(filename) do io countlines(io, eol) end end -function countlines(io::IOStream, eol::Char) - if !iswascii(eol) +function countlines(io::IO, eol::Char) + if !isascii(eol) error("countlines: only ASCII line terminators supported") end a = Array(Uint8, 8192) @@ -121,45 +121,45 @@ function countlines(io::IOStream, eol::Char) nl end -function _jl_dlmread_setup(fname::String, dlm, eol) +function readdlm_setup(fname::String, dlm, eol) if length(dlm) == 0 - error("dlmread: no separator characters specified") + error("readdlm: no separator characters specified") end nr = countlines(fname,eol) io = open(fname) - row = _jl_dlm_readrow(io, dlm, eol) + row = dlm_readrow(io, dlm, eol) nc = length(row) return (io, nr, nc, row) end -dlmread(fname::String, T::Type) = dlmread(fname, _jl_invalid_dlm, T, '\n') +readdlm(fname::String, T::Type) = readdlm(fname, invalid_dlm, T, '\n') -dlmread(fname::String, dlm, T::Type) = dlmread(fname, dlm, T, '\n') +readdlm(fname::String, dlm, T::Type) = readdlm(fname, dlm, T, '\n') -function dlmread(fname::String, dlm, T::Type, eol::Char) - (io, nr, nc, row) = _jl_dlmread_setup(fname, dlm, eol) +function readdlm(fname::String, dlm, T::Type, eol::Char) + (io, nr, nc, row) = readdlm_setup(fname, dlm, eol) a = Array(T, nr, nc) - _jl_dlmread(a, io, dlm, nr, nc, row, eol) + readdlm(a, io, dlm, nr, nc, row, eol) close(io) return a end -dlmread(fname::String) = dlmread(fname, _jl_invalid_dlm, '\n') -dlmread(fname::String, dlm) = dlmread(fname, dlm, '\n') +readdlm(fname::String) = readdlm(fname, invalid_dlm, '\n') +readdlm(fname::String, dlm) = readdlm(fname, dlm, '\n') -function dlmread(fname::String, dlm, eol::Char) - (io, nr, nc, row) = _jl_dlmread_setup(fname, dlm, eol) +function readdlm(fname::String, dlm, eol::Char) + (io, nr, nc, row) = readdlm_setup(fname, dlm, eol) a = Array(Float64, nr, nc) - a = _jl_dlmread_auto(a, io, dlm, nr, nc, row, eol) + a = readdlm_auto(a, io, dlm, nr, nc, row, eol) close(io) return a end -csvread(io) = dlmread(io, ',') -csvread(io, T::Type) = dlmread(io, ',', T) +readcsv(io) = readdlm(io, ',') +readcsv(io, T::Type) = readdlm(io, ',', T) # todo: keyword argument for # of digits to print -function dlmwrite(io, a::Matrix, dlm::Char) +function writedlm(io::IO, a::Matrix, dlm::Char) nr, nc = size(a) for i = 1:nr for j = 1:nc @@ -178,13 +178,13 @@ function dlmwrite(io, a::Matrix, dlm::Char) nothing end -dlmwrite(io, a::Vector, dlm::Char) = dlmwrite(io, reshape(a,length(a),1), dlm) +writedlm(io::IO, a::Vector, dlm::Char) = writedlm(io, reshape(a,length(a),1), dlm) -function dlmwrite(fname::String, a::Matrix, dlm::Char) +function writedlm(fname::String, a::Matrix, dlm::Char) open(fname, "w") do io - dlmwrite(io, a, dlm) + writedlm(io, a, dlm) end end -dlmwrite(io, a) = dlmwrite(io, a, ',') -csvwrite(io, a) = dlmwrite(io, a, ',') +writedlm(io, a) = writedlm(io, a, '\t') +writecsv(io, a) = writedlm(io, a, ',') diff --git a/base/deepcopy.jl b/base/deepcopy.jl index 6c820ff84de4e..3bb3d4ad9faea 100644 --- a/base/deepcopy.jl +++ b/base/deepcopy.jl @@ -6,7 +6,7 @@ deepcopy(x) = deepcopy_internal(x, ObjectIdDict()) deepcopy_internal(x::Union(Symbol,LambdaStaticData,TopNode,QuoteNode, - BitsKind,CompositeKind,AbstractKind,UnionKind), + DataType,UnionType), stackdict::ObjectIdDict) = x deepcopy_internal(x::Tuple, stackdict::ObjectIdDict) = ntuple(length(x), i->deepcopy_internal(x[i], stackdict)) @@ -26,8 +26,10 @@ function deepcopy_internal(x, stackdict::ObjectIdDict) _deepcopy_t(x, typeof(x), stackdict) end -_deepcopy_t(x, T::BitsKind, stackdict::ObjectIdDict) = x -function _deepcopy_t(x, T::CompositeKind, stackdict::ObjectIdDict) +function _deepcopy_t(x, T::DataType, stackdict::ObjectIdDict) + if T.names===() || !T.mutable + return x + end ret = ccall(:jl_new_struct_uninit, Any, (Any,), T) stackdict[x] = ret for f in T.names @@ -37,8 +39,6 @@ function _deepcopy_t(x, T::CompositeKind, stackdict::ObjectIdDict) end return ret end -_deepcopy_t(x, T, stackdict::ObjectIdDict) = - error("deepcopy of objects of type ", T, " not supported") function deepcopy_internal(x::Array, stackdict::ObjectIdDict) @@ -48,8 +48,10 @@ function deepcopy_internal(x::Array, stackdict::ObjectIdDict) _deepcopy_array_t(x, eltype(x), stackdict) end -_deepcopy_array_t(x, T::BitsKind, stackdict::ObjectIdDict) = copy(x) function _deepcopy_array_t(x, T, stackdict::ObjectIdDict) + if isbits(T) + return copy(x) + end dest = similar(x) stackdict[x] = dest for i=1:length(x) diff --git a/base/deprecated.jl b/base/deprecated.jl new file mode 100644 index 0000000000000..19735b3125e22 --- /dev/null +++ b/base/deprecated.jl @@ -0,0 +1,187 @@ +macro deprecate(old,new) + if isa(old,Symbol) + oldname = Expr(:quote,old) + newname = Expr(:quote,new) + Expr(:toplevel, + Expr(:export,esc(old)), + :(function $(esc(old))(args...) + warn_once(string($oldname," is deprecated, use ",$newname," instead.")) + $(esc(new))(args...) + end)) + elseif isa(old,Expr) && old.head == :call + oldcall = sprint(io->show_unquoted(io,old)) + newcall = sprint(io->show_unquoted(io,new)) + Expr(:toplevel, + Expr(:export,esc(old.args[1])), + :($(esc(old)) = begin + warn_once(string($oldcall," is deprecated, use ",$newcall," instead.")) + $(esc(new)) + end)) + else + error("invalid usage of @deprecate") + end +end + +# 0.1 + +@deprecate push push! +@deprecate pop pop! +@deprecate grow grow! +@deprecate enqueue unshift! +@deprecate unshift unshift! +@deprecate shift shift! +@deprecate insert insert! +@deprecate del delete! +@deprecate del_all empty! +@deprecate add add! +@deprecate add_each add_each! +@deprecate del_each del_each! +@deprecate toggle symdiff! +@deprecate toggle_each symdiff! +@deprecate xor! symdiff! +@deprecate load require +@deprecate idump xdump +@deprecate cwd pwd +@deprecate strlen length +@deprecate strchr search +@deprecate memchr search +@deprecate lc lowercase +@deprecate uc uppercase +@deprecate nCr binomial +@deprecate julia_pkgdir Pkg.dir +@deprecate tintersect typeintersect +@deprecate searchsorted searchsortedfirst +@deprecate choose first +@deprecate system run +@deprecate order sortperm +@deprecate numel length +@deprecate islogical isbool +@deprecate csvread readcsv +@deprecate dlmread readdlm +@deprecate csvwrite writecsv +@deprecate dlmwrite writedlm +@deprecate chi2rnd randchi2 +@deprecate betarnd randbeta +@deprecate exprnd randexp +@deprecate rot90 rotl90 +@deprecate chars collect +@deprecate elements collect +@deprecate pairs collect +@deprecate strcat string +@deprecate iswalnum isalnum +@deprecate iswalpha isalpha +@deprecate iswascii isascii +@deprecate iswblank isblank +@deprecate iswcntrl iscntrl +@deprecate iswdigit isdigit +@deprecate iswgraph isgraph +@deprecate iswlower islower +@deprecate iswprint isprint +@deprecate iswpunct ispunct +@deprecate iswspace isspace +@deprecate iswupper isupper +@deprecate iswxdigit isxdigit +@deprecate copy_to copy! +@deprecate countp count +@deprecate anyp any +@deprecate allp all +@deprecate resize sizehint +@deprecate permute permutedims +@deprecate ipermute ipermutedims +@deprecate is_hex_digit isxdigit +@deprecate read_from readsfrom +@deprecate write_to writesto +@deprecate download_file download +@deprecate histc hist +@deprecate map_to map! +@deprecate rotl rol +@deprecate rotr ror +@deprecate flipbits (~) +@deprecate cor_pearson cor +@deprecate cov_pearson cov +@deprecate areduce reducedim +@deprecate tmpnam tempname +@deprecate lud lufact +@deprecate chold cholfact +@deprecate cholpd cholpfact +@deprecate qrd qrfact +@deprecate qrpd qrpfact +@deprecate key getkey + +@deprecate grow!(a,d) resize!(a,length(a)+d) +@deprecate keytype(a) eltype(a)[1] +@deprecate valtype(a) eltype(a)[2] +@deprecate randi(n,x...) rand(1:n,x...) +@deprecate randival(lo,hi,x...) rand(lo:hi,x...) +@deprecate squeeze(A) squeeze(A,find([size(A)...].==1)) +@deprecate getenv(var) ENV[var] +@deprecate hasenv(var) has(ENV,var) +@deprecate setenv(var,val) ENV[var] = val +@deprecate unsetenv(var) delete!(ENV,var) + +function svd(a::StridedMatrix, vecs::Bool, thin::Bool) + warn_once("The second argument ``vecs`` is no longer supported. Use svd(a, thin) instead.") + svd(a, thin) +end + +function svdt(a::StridedMatrix, vecs::Bool, thin::Bool) + warn_once("The second argument ``vecs`` is no longer supported. Use svdt(a, thin) instead.") + svdt(a, thin) +end + +# discontinued functions + +export randexp, randg, randbeta, randchi +for (fun,typ) in {(:randexp,:Exponential), (:randg,:Gamma), (:randbeta,:Beta), (:randchi,:Chisq)} +@eval $fun(x...) = error($fun," is no longer supported, use the Distributions package instead: + + using Distributions + rand(",$(Expr(:quote,typ)),"()) +") +end + +const IOString = IOBuffer +export IOString +const PipeString = PipeBuffer +export PipeString + +# @spawnlocal deprecated + +# 0.2 + +@deprecate localize localpart +@deprecate logb exponent +@deprecate ilogb exponent +@deprecate ref_shape index_shape +@deprecate assign_shape_check setindex_shape_check +@deprecate quote_string repr +@deprecate safe_char(c) (is_valid_char(char(c))||error())&&char(c) +@deprecate check_ascii(x) (is_valid_ascii(x)?x:error()) +@deprecate check_utf8(x) (is_valid_utf8(x)?x:error()) +@deprecate each_line eachline +@deprecate each_match eachmatch +@deprecate function_loc functionloc +@deprecate compile_hint precompile +@deprecate begins_with beginswith +@deprecate ends_with endswith +@deprecate parse_float parsefloat +@deprecate parse_int parseint +@deprecate parse_bin(T,s) parseint(T,s,2) +@deprecate parse_bin(s) parseint(s,2) +@deprecate parse_oct(T,s) parseint(T,s,8) +@deprecate parse_oct(s) parseint(s,8) +@deprecate parse_hex(T,s) parseint(T,s,16) +@deprecate parse_hex(s) parseint(s,16) +@deprecate wait_accept accept +@deprecate findn_nzs findnz + +@deprecate expr(hd, a...) Expr(hd, a...) +@deprecate expr(hd, a::Array{Any,1}) Expr(hd, a...) + +# note removed macros: str, B_str, I_str, E_str, L_str, L_mstr, I_mstr, E_mstr + +# renamings +const ref = getindex +export ref +const assign = setindex! +export assign diff --git a/base/dict.jl b/base/dict.jl index cb249f65dbe88..45f639bff771e 100644 --- a/base/dict.jl +++ b/base/dict.jl @@ -2,12 +2,12 @@ abstract Associative{K,V} -const _jl_secret_table_token = :__c782dbf1cf4d6a2e5e3865d7e95634f2e09b5902__ +const secret_table_token = :__c782dbf1cf4d6a2e5e3865d7e95634f2e09b5902__ -has(t::Associative, key) = !is(get(t, key, _jl_secret_table_token), - _jl_secret_table_token) +has(t::Associative, key) = !is(get(t, key, secret_table_token), + secret_table_token) -function show{K,V}(io, t::Associative{K,V}) +function show{K,V}(io::IO, t::Associative{K,V}) if isempty(t) print(io, typeof(t),"()") else @@ -49,16 +49,6 @@ function values(T, a::Associative) end values{K,V}(a::Associative{K,V}) = values(V,a) -function pairs(T::(Union(Type,Tuple),Union(Type,Tuple)), a::Associative) - i = 0 - pairz = Array(T,length(a)) - for (k,v) in a - pairz[i+=1] = (k,v) - end - return pairz -end -pairs{K,V}(a::Associative{K,V}) = pairs((K,V),a) - function copy(a::Associative) b = similar(a) for (k,v) in a @@ -80,34 +70,47 @@ merge(d::Associative, others::Associative...) = merge!(copy(d), others...) function filter!(f::Function, d::Associative) for (k,v) in d if !f(k,v) - del(d,k) + delete!(d,k) end end return d end filter(f::Function, d::Associative) = filter!(f,copy(d)) -keytype{K,V}(a::Associative{K, V}) = K -valtype{K,V}(a::Associative{K, V}) = V - -# some support functions +eltype{K,V}(a::Associative{K,V}) = (K,V) -function _tablesz(i::Integer) - if i < 16 - return 16 +function hash(d::Associative) + h = 0 + for (k,v) in d + h $= bitmix(hash(k),~hash(v)) end - if i&(i-1) == 0 - return i + h +end + +# Used as default value arg to get in isequal: something that will +# never be found in any dictionary. +const _MISSING = gensym() + +function isequal(l::Associative, r::Associative) + if isa(l,ObjectIdDict) != isa(r,ObjectIdDict) + return false end - while (i&(i-1) != 0) - i = i&(i-1) + if length(l) != length(r) return false end + for (key, value) in l + if !isequal(value, get(r, key, _MISSING)) + return false + end end - return i<<1 + true end -function ref(t::Associative, key) - v = get(t, key, _jl_secret_table_token) - if is(v,_jl_secret_table_token) +# some support functions + +_tablesz(x::Integer) = x < 16 ? 16 : one(x)<<((sizeof(x)<<3)-leading_zeros(x-1)) + +function getindex(t::Associative, key) + v = get(t, key, secret_table_token) + if is(v, secret_table_token) throw(KeyError(key)) end return v @@ -117,13 +120,12 @@ end type ObjectIdDict <: Associative{Any,Any} ht::Array{Any,1} - ObjectIdDict(sz::Integer) = new(cell(2*_tablesz(sz))) - ObjectIdDict() = ObjectIdDict(0) + ObjectIdDict() = new(cell(32)) end similar(d::ObjectIdDict) = ObjectIdDict() -function assign(t::ObjectIdDict, v::ANY, k::ANY) +function setindex!(t::ObjectIdDict, v::ANY, k::ANY) t.ht = ccall(:jl_eqtable_put, Array{Any,1}, (Any, Any, Any), t.ht, k, v) return t end @@ -131,10 +133,15 @@ end get(t::ObjectIdDict, key::ANY, default::ANY) = ccall(:jl_eqtable_get, Any, (Any, Any, Any), t.ht, key, default) -del(t::ObjectIdDict, key::ANY) = - (ccall(:jl_eqtable_del, Int32, (Any, Any), t.ht, key); t) +delete!(t::ObjectIdDict, key::ANY, default::ANY) = + ccall(:jl_eqtable_del, Any, (Any, Any, Any), t.ht, key, default) + +function delete!(t::ObjectIdDict, key::ANY) + val = delete!(t, key, secret_table_token) + !is(val,secret_table_token) ? val : throw(KeyError(key)) +end -del_all(t::ObjectIdDict) = (t.ht = cell(length(t.ht)); t) +empty!(t::ObjectIdDict) = (t.ht = cell(length(t.ht)); t) start(t::ObjectIdDict) = 0 done(t::ObjectIdDict, i) = is(next(t,i),()) @@ -154,7 +161,7 @@ end bitmix(a::Union(Int32,Uint32), b::Union(Int32,Uint32)) = ccall(:int64to32hash, Uint32, (Uint64,), - or_int(shl_int(zext64(unbox(Uint32,a)), 32), zext64(unbox(Uint32,b)))) + or_int(shl_int(zext_int(Uint64,unbox(Uint32,a)), 32), zext_int(Uint64,unbox(Uint32,b)))) bitmix(a::Union(Int64,Uint64), b::Union(Int64, Uint64)) = ccall(:int64hash, Uint64, (Uint64,), @@ -162,18 +169,18 @@ bitmix(a::Union(Int64,Uint64), b::Union(Int64, Uint64)) = shl_int(unbox(Uint64,b), 32)))) if WORD_SIZE == 64 - _jl_hash64(x::Float64) = + hash64(x::Float64) = ccall(:int64hash, Uint64, (Uint64,), box(Uint64,unbox(Float64,x))) - _jl_hash64(x::Union(Int64,Uint64)) = + hash64(x::Union(Int64,Uint64)) = ccall(:int64hash, Uint64, (Uint64,), x) else - _jl_hash64(x::Float64) = + hash64(x::Float64) = ccall(:int64to32hash, Uint32, (Uint64,), box(Uint64,unbox(Float64,x))) - _jl_hash64(x::Union(Int64,Uint64)) = + hash64(x::Union(Int64,Uint64)) = ccall(:int64to32hash, Uint32, (Uint64,), x) end -hash(x::Integer) = _jl_hash64(uint64(x)) +hash(x::Integer) = hash64(uint64(x)) @eval function hash(x::FloatingPoint) if trunc(x) == x # hash as integer if equal to some integer. note the result of @@ -189,7 +196,7 @@ hash(x::Integer) = _jl_hash64(uint64(x)) end end end - isnan(x) ? $(_jl_hash64(NaN)) : _jl_hash64(float64(x)) + isnan(x) ? $(hash64(NaN)) : hash64(float64(x)) end function hash(t::Tuple) @@ -235,22 +242,20 @@ type Dict{K,V} <: Associative{K,V} count::Int deleter::Function - Dict() = Dict{K,V}(0) - function Dict(n::Integer) - n = _tablesz(n) + function Dict() + n = 16 new(zeros(Uint8,n), Array(K,n), Array(V,n), 0, 0, identity) end function Dict(ks, vs) n = length(ks) - h = Dict{K,V}(n) + h = Dict{K,V}() for i=1:n h[ks[i]] = vs[i] end return h end end -Dict() = Dict(0) -Dict(n::Integer) = Dict{Any,Any}(n) +Dict() = Dict{Any,Any}() Dict{K,V}(ks::AbstractArray{K}, vs::AbstractArray{V}) = Dict{K,V}(ks,vs) Dict(ks, vs) = Dict{Any,Any}(ks, vs) @@ -273,7 +278,7 @@ end function deserialize{K,V}(s, T::Type{Dict{K,V}}) n = read(s, Int32) - t = T(n) + t = T(); sizehint(t, n) for i = 1:n k = deserialize(s) v = deserialize(s) @@ -294,10 +299,18 @@ function rehash{K,V}(h::Dict{K,V}, newsz) oldv = h.vals sz = length(olds) newsz = _tablesz(newsz) + nel = h.count + h.ndel = h.count = 0 + if nel == 0 + resize!(h.slots, newsz) + fill!(h.slots, 0) + resize!(h.keys, newsz) + resize!(h.vals, newsz) + return h + end h.slots = zeros(Uint8,newsz) h.keys = Array(K, newsz) h.vals = Array(V, newsz) - h.ndel = h.count = 0 for i = 1:sz if olds[i] == 0x1 @@ -316,7 +329,20 @@ function rehash{K,V}(h::Dict{K,V}, newsz) return h end -function del_all{K,V}(h::Dict{K,V}) +function sizehint(d::Dict, newsz) + oldsz = length(d.slots) + if newsz <= oldsz + # todo: shrink + # be careful: rehash() assumes everything fits. it was only designed + # for growing. + return d + end + # grow at least 25% + newsz = max(newsz, (oldsz*5)>>2) + rehash(d, newsz) +end + +function empty!{K,V}(h::Dict{K,V}) fill!(h.slots, 0x0) sz = length(h.slots) h.keys = Array(K, sz) @@ -326,8 +352,9 @@ function del_all{K,V}(h::Dict{K,V}) return h end -function assign{K,V}(h::Dict{K,V}, v, key) +function setindex!{K,V}(h::Dict{K,V}, v, key) key = convert(K,key) + v = convert(V, v) sz = length(h.keys) @@ -383,7 +410,7 @@ function assign{K,V}(h::Dict{K,V}, v, key) rehash(h, h.count > 64000 ? sz*2 : sz*4) - assign(h, v, key) + setindex!(h, v, key) end # get the index where a key is stored, or -1 if not present @@ -413,7 +440,7 @@ function ht_keyindex{K,V}(h::Dict{K,V}, key) return -1 end -function ref{K,V}(h::Dict{K,V}, key) +function getindex{K,V}(h::Dict{K,V}, key) index = ht_keyindex(h, key) return (index<0) ? throw(KeyError(key)) : h.vals[index]::V end @@ -425,22 +452,29 @@ end has(h::Dict, key) = (ht_keyindex(h, key) >= 0) -function key{K,V}(h::Dict{K,V}, key, deflt) +function getkey{K,V}(h::Dict{K,V}, key, deflt) index = ht_keyindex(h, key) return (index<0) ? deflt : h.keys[index]::K end -function del(h::Dict, key) +function _delete!(h::Dict, index) + val = h.vals[index] + h.slots[index] = 0x2 + ccall(:jl_arrayunset, Void, (Any, Uint), h.keys, index-1) + ccall(:jl_arrayunset, Void, (Any, Uint), h.vals, index-1) + h.ndel += 1 + h.count -= 1 + return val +end + +function delete!(h::Dict, key) index = ht_keyindex(h, key) - if index > 0 - h.slots[index] = 0x2 - ccall(:jl_arrayunset, Void, (Any, Uint), h.keys, index-1) - ccall(:jl_arrayunset, Void, (Any, Uint), h.vals, index-1) - h.ndel += 1 - h.count -= 1 - return h - end - throw(KeyError(key)) + index > 0 ? _delete!(h, index) : throw(KeyError(key)) +end + +function delete!(h::Dict, key, default) + index = ht_keyindex(h, key) + index > 0 ? _delete!(h, index) : default end function skip_deleted(h::Dict, i) @@ -458,37 +492,23 @@ next(t::Dict, i) = ((t.keys[i],t.vals[i]), skip_deleted(t,i+1)) isempty(t::Dict) = (t.count == 0) length(t::Dict) = t.count -# Used as default value arg to get in isequal: something that will -# never be found in any dictionary. -const _MISSING = gensym() - -function isequal(l::Dict, r::Dict) - if ! (length(l) == length(r)) return false end - for (key, value) in l - if ! isequal(value, get(r, key, _MISSING)) - return false - end - end - true -end - # weak key dictionaries function add_weak_key(t::Dict, k, v) if is(t.deleter, identity) - t.deleter = x->del(t, x) + t.deleter = x->delete!(t, x) end t[WeakRef(k)] = v # TODO: it might be better to avoid the finalizer, allow # wiped WeakRefs to remain in the table, and delete them as - # they are discovered by ref and assign. + # they are discovered by getindex and setindex!. finalizer(k, t.deleter) return t end function add_weak_value(t::Dict, k, v) t[k] = WeakRef(v) - finalizer(v, x->del(t, k)) + finalizer(v, x->delete!(t, k)) return t end @@ -499,21 +519,22 @@ type WeakKeyDict{K,V} <: Associative{K,V} end WeakKeyDict() = WeakKeyDict{Any,Any}() -assign{K}(wkh::WeakKeyDict{K}, v, key) = add_weak_key(wkh.ht, convert(K,key), v) +setindex!{K}(wkh::WeakKeyDict{K}, v, key) = add_weak_key(wkh.ht, convert(K,key), v) -function key{K}(wkh::WeakKeyDict{K}, kk, deflt) - k = key(wkh.ht, kk, _jl_secret_table_token) - if is(k, _jl_secret_table_token) +function getkey{K}(wkh::WeakKeyDict{K}, kk, deflt) + k = getkey(wkh.ht, kk, secret_table_token) + if is(k, secret_table_token) return deflt end return k.value::K end -get{K}(wkh::WeakKeyDict{K}, key, deflt) = get(wkh.ht, key, deflt) -del{K}(wkh::WeakKeyDict{K}, key) = del(wkh.ht, key) -del_all(wkh::WeakKeyDict) = (del_all(wkh.ht); wkh) +get{K}(wkh::WeakKeyDict{K}, key, def) = get(wkh.ht, key, def) +delete!{K}(wkh::WeakKeyDict{K}, key) = delete!(wkh.ht, key) +delete!{K}(wkh::WeakKeyDict{K}, key, def) = delete!(wkh.ht, key, def) +empty!(wkh::WeakKeyDict) = (empty!(wkh.ht); wkh) has{K}(wkh::WeakKeyDict{K}, key) = has(wkh.ht, key) -ref{K}(wkh::WeakKeyDict{K}, key) = ref(wkh.ht, key) +getindex{K}(wkh::WeakKeyDict{K}, key) = getindex(wkh.ht, key) isempty(wkh::WeakKeyDict) = isempty(wkh.ht) start(t::WeakKeyDict) = start(t.ht) @@ -523,4 +544,3 @@ function next{K}(t::WeakKeyDict{K}, i) ((kv[1].value::K,kv[2]), i) end length(t::WeakKeyDict) = length(t.ht) - diff --git a/base/dsp.jl b/base/dsp.jl index 1d3e1a3916c87..411b108c60368 100644 --- a/base/dsp.jl +++ b/base/dsp.jl @@ -1,11 +1,14 @@ module DSP -using Base.FFTW +importall Base.FFTW +import Base.FFTW.normalization export FFTW, filt, deconv, conv, conv2, xcorr, fftshift, ifftshift, + dct, idct, dct!, idct!, plan_dct, plan_idct, plan_dct!, plan_idct!, # the rest are defined imported from FFTW: - bfft, bfftn, brfft, brfftn, fft, fft2, fft3, fftn, - ifft, ifft2, ifft3, ifftn, irfft, irfftn, rfft, rfftn + fft, bfft, ifft, rfft, brfft, irfft, + plan_fft, plan_bfft, plan_ifft, plan_rfft, plan_brfft, plan_irfft, + fft!, bfft!, ifft!, plan_fft!, plan_bfft!, plan_ifft! function filt(b,a,x) if a[1]==0 @@ -75,7 +78,8 @@ end function conv{T}(u::Vector{T}, v::Vector{T}) n = size(u,1)+size(v,1)-1 u, v = [u;zeros(T,size(v,1)-1)], [v;zeros(T,size(u,1)-1)] - y = ifft(fft(u).*fft(v)) + p = plan_fft(u) + y = ifft(p(u).*p(v)) if T <: Real return real(y) end @@ -89,7 +93,7 @@ function conv2{T}(y::Vector{T}, x::Vector{T}, A::Matrix{T}) B[1:size(A,1),1:size(A,2)] = A y = fft([y;zeros(T,m-length(y))]) x = fft([x;zeros(T,n-length(x))]) - C = ifft2(fft2(B) .* (y * x.')) + C = ifft(fft(B) .* (y * x.')) if T <: Real return real(C) end @@ -102,7 +106,8 @@ function conv2{T}(A::Matrix{T}, B::Matrix{T}) Bt = zeros(T, sa[1]+sb[1]-1, sa[2]+sb[2]-1) At[1:sa[1], 1:sa[2]] = A Bt[1:sb[1], 1:sb[2]] = B - C = ifft2(fft2(At).*fft2(Bt)) + p = plan_fft(At) + C = ifft(p(At).*p(Bt)) if T <: Real return real(C) end @@ -135,4 +140,108 @@ function ifftshift(x,dim) circshift(x, s) end +# Discrete cosine and sine transforms via FFTW's r2r transforms; +# we follow the Matlab convention and adopt a unitary normalization here. +# Unlike Matlab we compute the multidimensional transform by default, +# similar to the Julia fft functions. + +fftwcopy{T<:fftwNumber}(X::StridedArray{T}) = copy(X) +fftwcopy{T<:Real}(X::StridedArray{T}) = float(X) +fftwcopy{T<:Complex}(X::StridedArray{T}) = complex128(X) + +for (f, fr2r, Y, Tx) in ((:dct, :r2r, :Y, :Number), + (:dct!, :r2r!, :X, :fftwNumber)) + plan_f = symbol(string("plan_",f)) + plan_fr2r = symbol(string("plan_",fr2r)) + fi = symbol(string("i",f)) + plan_fi = symbol(string("plan_",fi)) + Ycopy = Y == :X ? 0 : :(Y = fftwcopy(X)) + @eval begin + function $f{T<:$Tx}(X::StridedArray{T}, region) + $Y = $fr2r(X, REDFT10, region) + scale!($Y, sqrt(0.5^length(region) * normalization(X,region))) + sqrthalf = sqrt(0.5) + r = map(n -> 1:n, [size(X)...]) + for d in region + r[d] = 1:1 + $Y[r...] *= sqrthalf + r[d] = 1:size(X,d) + end + return $Y + end + + function $plan_f{T<:$Tx}(X::StridedArray{T}, region, + flags::Unsigned, timelimit::Real) + p = $plan_fr2r(X, REDFT10, region, flags, timelimit) + sqrthalf = sqrt(0.5) + r = map(n -> 1:n, [size(X)...]) + nrm = sqrt(0.5^length(region) * normalization(X,region)) + return X::StridedArray{T} -> begin + $Y = p(X) + scale!($Y, nrm) + for d in region + r[d] = 1:1 + $Y[r...] *= sqrthalf + r[d] = 1:size(X,d) + end + return $Y + end + end + + function $fi{T<:$Tx}(X::StridedArray{T}, region) + $Ycopy + scale!($Y, sqrt(0.5^length(region) * normalization(X, region))) + sqrt2 = sqrt(2) + r = map(n -> 1:n, [size(X)...]) + for d in region + r[d] = 1:1 + $Y[r...] *= sqrt2 + r[d] = 1:size(X,d) + end + return r2r!($Y, REDFT01, region) + end + + function $plan_fi{T<:$Tx}(X::StridedArray{T}, region, + flags::Unsigned, timelimit::Real) + p = $plan_fr2r(X, REDFT01, region, flags, timelimit) + sqrt2 = sqrt(2) + r = map(n -> 1:n, [size(X)...]) + nrm = sqrt(0.5^length(region) * normalization(X,region)) + return X::StridedArray{T} -> begin + $Ycopy + scale!($Y, nrm) + for d in region + r[d] = 1:1 + $Y[r...] *= sqrt2 + r[d] = 1:size(X,d) + end + return p($Y) + end + end + + end + for (g,plan_g) in ((f,plan_f), (fi, plan_fi)) + @eval begin + $g{T<:$Tx}(X::StridedArray{T}) = $g(X, 1:ndims(X)) + + $plan_g(X, region, flags::Unsigned) = + $plan_g(X, region, flags, NO_TIMELIMIT) + $plan_g(X, region) = + $plan_g(X, region, ESTIMATE, NO_TIMELIMIT) + $plan_g{T<:$Tx}(X::StridedArray{T}) = + $plan_g(X, 1:ndims(X), ESTIMATE, NO_TIMELIMIT) + end + end +end + +# DCT of scalar is just the identity: +dct(x::Number, dims) = length(dims) == 0 || dims[1] == 1 ? x : throw(BoundsError())x +idct(x::Number, dims) = dct(x, dims) +dct(x::Number) = x +idct(x::Number) = x +plan_dct(x::Number, dims, flags, tlim) = length(dims) == 0 || dims[1] == 1 ? y::Number -> y : throw(BoundsError()) +plan_idct(x::Number, dims, flags, tlim) = plan_dct(x, dims) +plan_dct(x::Number) = y::Number -> y +plan_idct(x::Number) = y::Number -> y + end # module diff --git a/base/env.jl b/base/env.jl index 3e02287aff3d0..fed629fdb22e1 100644 --- a/base/env.jl +++ b/base/env.jl @@ -1,29 +1,56 @@ ## core libc calls ## -hasenv(s::String) = ccall(:getenv, Ptr{Uint8}, (Ptr{Uint8},), s) != C_NULL +@unix_only begin + _getenv(var::String) = ccall(:getenv, Ptr{Uint8}, (Ptr{Uint8},), var) + _hasenv(s::String) = _getenv(s) != C_NULL +end +@windows_only begin +_getenvlen(var::String) = ccall(:GetEnvironmentVariableA,stdcall,Uint32,(Ptr{Uint8},Ptr{Uint8},Uint32),var,C_NULL,0) +_hasenv(s::String) = _getenvlen(s)!=0 +function _jl_win_getenv(s::String,len::Uint32) + val=zeros(Uint8,len-1) + ret=ccall(:GetEnvironmentVariableA,stdcall,Uint32,(Ptr{Uint8},Ptr{Uint8},Uint32),s,val,len) + if(ret==0||ret!=len-1) #Trailing 0 is only included on first call to GetEnvA + error("getenv: unknown system error: ", s, len, ret) + end + val +end +end + -function getenv(var::String) - val = ccall(:getenv, Ptr{Uint8}, (Ptr{Uint8},), var) - if val == C_NULL - error("getenv: undefined variable: ", var) +macro accessEnv(var,errorcase) +@unix_only return quote + val=_getenv($var) + if val == C_NULL + $errorcase + end + bytestring(val) +end +@windows_only return quote + len=_getenvlen($var) + if len == 0 + $errorcase end - bytestring(val) + bytestring(_jl_win_getenv($var,len)) +end end -function setenv(var::String, val::String, overwrite::Bool) +function _setenv(var::String, val::String, overwrite::Bool) @unix_only begin ret = ccall(:setenv, Int32, (Ptr{Uint8},Ptr{Uint8},Int32), var, val, overwrite) system_error(:setenv, ret != 0) end @windows_only begin - ret = ccall(:SetEnvironmentVariableA,stdcall,Int32,(Ptr{Uint8},Ptr{Uint8}),var,val) - system_error(:setenv, ret == 0) + if(overwrite||!_hasenv(var)) + ret = ccall(:SetEnvironmentVariableA,stdcall,Int32,(Ptr{Uint8},Ptr{Uint8}),var,val) + system_error(:setenv, ret == 0) + end end end -setenv(var::String, val::String) = setenv(var, val, true) +_setenv(var::String, val::String) = _setenv(var, val, true) -function unsetenv(var::String) +function _unsetenv(var::String) @unix_only begin ret = ccall(:unsetenv, Int32, (Ptr{Uint8},), var) system_error(:unsetenv, ret != 0) @@ -36,32 +63,24 @@ end ## ENV: hash interface ## -type EnvHash <: Associative{ByteString,ByteString}; end - -const ENV = EnvHash() - -function ref(::EnvHash, k::String) - val = ccall(:getenv, Ptr{Uint8}, (Ptr{Uint8},), k) - if val == C_NULL - throw(KeyError(k)) - end - bytestring(val) -end - -function get(::EnvHash, k::String, deflt) - val = ccall(:getenv, Ptr{Uint8}, (Ptr{Uint8},), k) - if val == C_NULL - return deflt - end - bytestring(val) +@unix_only type EnvHash <: Associative{ByteString,ByteString}; end +@windows_only type EnvHash <: Associative{ByteString,ByteString} + block::Ptr{Uint8} + EnvHash() = new(C_NULL) end +const ENV = EnvHash() -has(::EnvHash, k::String) = hasenv(k) -del(::EnvHash, k::String) = unsetenv(k) -assign(::EnvHash, v, k::String) = setenv(k,string(v)) +getindex(::EnvHash, k::String) = @accessEnv k throw(KeyError(k)) +get(::EnvHash, k::String, def) = @accessEnv k (return def) +has(::EnvHash, k::String) = _hasenv(k) +delete!(::EnvHash, k::String) = (v = ENV[k]; _unsetenv(k); v) +delete!(::EnvHash, k::String, def) = has(ENV,k) ? delete!(ENV,k) : def +setindex!(::EnvHash, v, k::String) = _setenv(k,string(v)) +@unix_only begin start(::EnvHash) = 0 done(::EnvHash, i) = (ccall(:jl_environ, Any, (Int32,), i) == nothing) + function next(::EnvHash, i) env = ccall(:jl_environ, Any, (Int32,), i) if env == nothing @@ -74,6 +93,30 @@ function next(::EnvHash, i) end (m.captures, i+1) end +end + +@windows_only begin +start(hash::EnvHash) = (hash.block = ccall(:GetEnvironmentStringsA,stdcall,Ptr{Uint8},())) +function done(hash::EnvHash, pos::Ptr{Uint8}) + if(ccall(:jl_env_done,Any,(Ptr{Uint8},),pos)::Bool) + ccall(:FreeEnvironmentStringsA,stdcall,Int32,(Ptr{Uint8},),hash.block) + hash.block=C_NULL + return true + end + false +end +function next(hash::EnvHash, pos::Ptr{Uint8}) + len = ccall(:strlen, Uint, (Ptr{Uint8},), pos) + env=ccall(:jl_pchar_to_string, Any, (Ptr{Uint8},Int), pos, len)::ByteString + m = match(r"^(.*?)=(.*)$"s, env) + if m == nothing + error("malformed environment entry: $env") + end + (m.captures, pos+len+1) +end +end + +#TODO: Make these more efficent function length(::EnvHash) i = 0 for (k,v) in ENV @@ -82,7 +125,7 @@ function length(::EnvHash) return i end -function show(io, ::EnvHash) +function show(io::IO, ::EnvHash) for (k,v) = ENV println(io, "$k=$v") end @@ -90,5 +133,5 @@ end ## misc environment-related functionality ## -tty_cols() = parse_int(Int32, get(ENV,"COLUMNS","80"), 10) -tty_rows() = parse_int(Int32, get(ENV,"LINES","25"), 10) +tty_cols() = parseint(Int32, get(ENV,"COLUMNS","80"), 10) +tty_rows() = parseint(Int32, get(ENV,"LINES","25"), 10) diff --git a/base/errno.jl b/base/errno.jl new file mode 100644 index 0000000000000..283e9e7a5ae71 --- /dev/null +++ b/base/errno.jl @@ -0,0 +1,135 @@ +module Errno +include("errno_h.jl") +export + E2BIG, + EACCES, + EADDRINUSE, + EADDRNOTAVAIL, + EADV, + EAFNOSUPPORT, + EAGAIN, + EALREADY, + EBADE, + EBADF, + EBADFD, + EBADMSG, + EBADR, + EBADRQC, + EBADSLT, + EBFONT, + EBUSY, + ECANCELED, + ECHILD, + ECHRNG, + ECOMM, + ECONNABORTED, + ECONNREFUSED, + ECONNRESET, + EDEADLK, + EDESTADDRREQ, + EDOM, + EDOTDOT, + EDQUOT, + EEXIST, + EFAULT, + EFBIG, + EHOSTDOWN, + EHOSTUNREACH, + EHWPOISON, + EIDRM, + EILSEQ, + EINPROGRESS, + EINTR, + EINVAL, + EIO, + EISCONN, + EISDIR, + EISNAM, + EKEYEXPIRED, + EKEYREJECTED, + EKEYREVOKED, + EL2HLT, + EL2NSYNC, + EL3HLT, + EL3RST, + ELIBACC, + ELIBBAD, + ELIBEXEC, + ELIBMAX, + ELIBSCN, + ELNRNG, + ELOOP, + EMEDIUMTYPE, + EMFILE, + EMLINK, + EMSGSIZE, + EMULTIHOP, + ENAMETOOLONG, + ENAVAIL, + ENETDOWN, + ENETRESET, + ENETUNREACH, + ENFILE, + ENOANO, + ENOBUFS, + ENOCSI, + ENODATA, + ENODEV, + ENOENT, + ENOEXEC, + ENOKEY, + ENOLCK, + ENOLINK, + ENOMEDIUM, + ENOMEM, + ENOMSG, + ENONET, + ENOPKG, + ENOPROTOOPT, + ENOSPC, + ENOSR, + ENOSTR, + ENOSYS, + ENOTBLK, + ENOTCONN, + ENOTDIR, + ENOTEMPTY, + ENOTNAM, + ENOTRECOVERABLE, + ENOTSOCK, + ENOTTY, + ENOTUNIQ, + ENXIO, + EOPNOTSUPP, + EOVERFLOW, + EOWNERDEAD, + EPERM, + EPFNOSUPPORT, + EPIPE, + EPROTO, + EPROTONOSUPPORT, + EPROTOTYPE, + ERANGE, + EREMCHG, + EREMOTE, + EREMOTEIO, + ERESTART, + ERFKILL, + EROFS, + ESHUTDOWN, + ESOCKTNOSUPPORT, + ESPIPE, + ESRCH, + ESRMNT, + ESTALE, + ESTRPIPE, + ETIME, + ETIMEDOUT, + ETOOMANYREFS, + ETXTBSY, + EUCLEAN, + EUNATCH, + EUSERS, + EXDEV, + EXFULL +end diff --git a/base/error.jl b/base/error.jl index d77f863defd14..b7d19eb9cf522 100644 --- a/base/error.jl +++ b/base/error.jl @@ -1,3 +1,19 @@ +# pseudo-definitions to show how everything behaves +# +# throw(label, val) = # throw a value to a dynamically enclosing block +# +# function rethrow(val) +# global current_exception = val +# throw(current_handler(), current_exception) +# end +# +# rethrow() = rethrow(current_exception) +# +# function throw(val) +# global catch_backtrace = backtrace() +# rethrow(val) +# end + ## native julia error handling ## error(e::Exception) = throw(e) @@ -9,10 +25,10 @@ macro unexpected() :(error("unexpected branch reached")) end -rethrow() = ccall(:jl_rethrow, Void, ()) -rethrow(e) = ccall(:jl_rethrow_other, Void, (Any,), e) - -backtrace() = ccall(:jl_get_backtrace, Array{Any,1}, ()) +rethrow() = ccall(:jl_rethrow, Void, ())::None +rethrow(e) = ccall(:jl_rethrow_other, Void, (Any,), e)::None +backtrace() = ccall(:jl_backtrace_from_here, Array{Ptr{Void},1}, ()) +catch_backtrace() = ccall(:jl_get_backtrace, Array{Ptr{Void},1}, ()) ## system error handling ## @@ -25,7 +41,27 @@ system_error(p, b::Bool) = b ? throw(SystemError(string(p))) : nothing assert(x) = assert(x,'?') assert(x,labl) = x ? nothing : error("assertion failed: ", labl) - macro assert(ex) :($(esc(ex)) ? nothing : error("assertion failed: ", $(string(ex)))) end + +## printing with color ## + +function with_output_color(f::Function, color::Symbol, io::IO, args...) + have_color || return f(io, args...) + print(io, get(text_colors, color, color_normal)) + try f(io, args...) + finally + print(io, color_normal) + end +end + +print_with_color(color::Symbol, io::IO, msg::String...) = + with_output_color(print, color, io, msg...) +print_with_color(color::Symbol, msg::String...) = + print_with_color(color, OUTPUT_STREAM, msg...) + +# use colors to print messages and warnings in the REPL + +info(msg::String...) = print_with_color(:blue, STDERR, "MESSAGE: ", msg..., "\n") +warn(msg::String...) = print_with_color(:red, STDERR, "WARNING: ", msg..., "\n") diff --git a/base/export.jl b/base/exports.jl similarity index 63% rename from base/export.jl rename to base/exports.jl index 4a125ae662f11..490d228feb389 100644 --- a/base/export.jl +++ b/base/exports.jl @@ -1,29 +1,36 @@ export # Modules - Grisu, - Printf, PCRE, FFTW, DSP, - LAPACK, - BLAS, + LinAlg, LibRandom, - RNG, + Random, Math, - + GMP, + Sort, + Test, + Pkg, + Operators, + Errno, + Meta, + # Types AbstractMatrix, AbstractSparseMatrix, AbstractVector, Array, Associative, + AsyncStream, + Bidiagonal, BitArray, + BigFloat, + BigInt, BitMatrix, BitVector, CharString, - Chars, Cmd, - Cmds, + #Cmds, Colon, Complex, Complex128, @@ -33,37 +40,33 @@ export Dict, Dims, EachLine, - EachSearch, Enumerate, EnvHash, - Executable, - FDSet, - FileDes, + #FileDes, FileOffset, - Filter, - GenericString, + Filter, IO, IOStream, + IOBuffer, ImaginaryUnit, - Indices, IntSet, LocalProcess, - Location, Matrix, ObjectIdDict, - Pipe, - PipeEnd, - PipeIn, - PipeOut, - Port, - Ports, - ProcessExited, + #Pipe, + #PipeEnd, + #PipeIn, + #PipeOut, + PipeBuffer, + #Port, + #Ports, + #ProcessExited, ProcessGroup, - ProcessNotRun, - ProcessRunning, - ProcessSignaled, - ProcessStatus, - ProcessStopped, + #ProcessNotRun, + #ProcessRunning, + #ProcessSignaled, + #ProcessStatus, + #ProcessStopped, Range, Range1, RangeIndex, @@ -72,7 +75,6 @@ export Regex, RegexMatch, RegexMatchIterator, - Dimspec, RemoteRef, RepString, RevString, @@ -80,6 +82,7 @@ export RopeString, Set, SparseMatrixCSC, + SpawnNullStream, StridedArray, StridedMatrix, StridedVecOrMat, @@ -89,8 +92,9 @@ export SubOrDArray, SubString, SymTridiagonal, - TransformedString, + TcpSocket, Tridiagonal, + UVError, VecOrMat, Vector, VersionNumber, @@ -101,17 +105,50 @@ export Stat, Factorization, BunchKaufman, - CholeskyDense, - LUDense, + Cholesky, + CholeskyPivoted, + Eigen, + GeneralizedSchur, + GeneralizedSVD, + Hessenberg, + LU, LUTridiagonal, LDLTTridiagonal, - QRDense, - QRPDense, - + QR, + QRPivoted, + Schur, + SVD, + GeneralizedSVD, + Hermitian, + Triangular, + Diagonal, + InsertionSort, + QuickSort, + MergeSort, + TimSort, + +# Ccall types + Cchar, + Cuchar, + Cshort, + Cushort, + Cint, + Cuint, + Clong, + Culong, + Cptrdiff_t, + Csize_t, + Clonglong, + Culonglong, + Cfloat, + Cdouble, + #Ccomplex_float, + #Ccomplex_double, + # Exceptions ArgumentError, - BackTrace, DisconnectException, + EOFError, ErrorException, KeyError, LoadError, @@ -119,7 +156,7 @@ export ParseError, SystemError, TypeError, - + # Global constants and variables ARGS, C_NULL, @@ -136,149 +173,22 @@ export NaN, NaN32, OUTPUT_STREAM, + RTLD_LOCAL, + RTLD_GLOBAL, + RTLD_LAZY, + RTLD_NOW, + RTLD_NODELETE, + RTLD_DEEPBIND, + RTLD_FIRST, STDERR, STDIN, STDOUT, VERSION, WORD_SIZE, - Scheduler, e, im, pi, - -# Unix error codes - E2BIG, - EACCES, - EADDRINUSE, - EADDRNOTAVAIL, - EADV, - EAFNOSUPPORT, - EAGAIN, - EALREADY, - EBADE, - EBADF, - EBADFD, - EBADMSG, - EBADR, - EBADRQC, - EBADSLT, - EBFONT, - EBUSY, - ECANCELED, - ECHILD, - ECHRNG, - ECOMM, - ECONNABORTED, - ECONNREFUSED, - ECONNRESET, - EDEADLK, - EDESTADDRREQ, - EDOM, - EDOTDOT, - EDQUOT, - EEXIST, - EFAULT, - EFBIG, - EHOSTDOWN, - EHOSTUNREACH, - EHWPOISON, - EIDRM, - EILSEQ, - EINPROGRESS, - EINTR, - EINVAL, - EIO, - EISCONN, - EISDIR, - EISNAM, - EKEYEXPIRED, - EKEYREJECTED, - EKEYREVOKED, - EL2HLT, - EL2NSYNC, - EL3HLT, - EL3RST, - ELIBACC, - ELIBBAD, - ELIBEXEC, - ELIBMAX, - ELIBSCN, - ELNRNG, - ELOOP, - EMEDIUMTYPE, - EMFILE, - EMLINK, - EMSGSIZE, - EMULTIHOP, - ENAMETOOLONG, - ENAVAIL, - ENETDOWN, - ENETRESET, - ENETUNREACH, - ENFILE, - ENOANO, - ENOBUFS, - ENOCSI, - ENODATA, - ENODEV, - ENOENT, - ENOEXEC, - ENOKEY, - ENOLCK, - ENOLINK, - ENOMEDIUM, - ENOMEM, - ENOMSG, - ENONET, - ENOPKG, - ENOPROTOOPT, - ENOSPC, - ENOSR, - ENOSTR, - ENOSYS, - ENOTBLK, - ENOTCONN, - ENOTDIR, - ENOTEMPTY, - ENOTNAM, - ENOTRECOVERABLE, - ENOTSOCK, - ENOTTY, - ENOTUNIQ, - ENXIO, - EOPNOTSUPP, - EOVERFLOW, - EOWNERDEAD, - EPERM, - EPFNOSUPPORT, - EPIPE, - EPROTO, - EPROTONOSUPPORT, - EPROTOTYPE, - ERANGE, - EREMCHG, - EREMOTE, - EREMOTEIO, - ERESTART, - ERFKILL, - EROFS, - ESHUTDOWN, - ESOCKTNOSUPPORT, - ESPIPE, - ESRCH, - ESRMNT, - ESTALE, - ESTRPIPE, - ETIME, - ETIMEDOUT, - ETOOMANYREFS, - ETXTBSY, - EUCLEAN, - EUNATCH, - EUSERS, - EXDEV, - EXFULL, - + # Operators !, !=, @@ -302,7 +212,6 @@ export .^, /, //, - :, <, <:, <<, @@ -322,6 +231,7 @@ export ^, |, ~, + :, A_ldiv_Bc, A_ldiv_Bt, A_mul_B, @@ -331,6 +241,7 @@ export A_rdiv_Bt, Ac_ldiv_B, Ac_ldiv_Bc, + Ac_mul_b_RFP, Ac_mul_B, Ac_mul_Bc, Ac_rdiv_B, @@ -341,7 +252,7 @@ export At_mul_Bt, At_rdiv_B, At_rdiv_Bt, - + # scalar math abs, abs2, @@ -392,6 +303,7 @@ export csc, cscd, csch, + dawson, degrees2radians, den, digamma, @@ -399,9 +311,12 @@ export eps, erf, erfc, + erfcx, + erfi, exp, exp2, expm1, + exponent, factor, factorial, fld, @@ -419,7 +334,6 @@ export hypot, iceil, ifloor, - ilogb, imag, inf, int, @@ -441,7 +355,6 @@ export isfinite, isinf, isinteger, - islogical, isnan, isodd, ispow2, @@ -458,13 +371,10 @@ export log10, log1p, log2, - logb, maxintfloat, mod, mod1, modf, - nCr, - nPr, nan, nextfloat, nextpow, @@ -472,13 +382,11 @@ export num, num2hex, one, - power_by_squaring, powermod, prevfloat, prevpow, prevpow2, radians2degrees, - rational, real, real_valued, realmax, @@ -517,36 +425,35 @@ export zero, nextprod, prevprod, - isinteger, typemax, typemin, -#specfun - airy, - airyai, - airyprime, - airyaiprime, - airybi, +# specfun + airy, + airyai, + airyprime, + airyaiprime, + airybi, airybiprime, - besselj0, - besselj1, - besselj, - bessely0, - bessely1, + besselj0, + besselj1, + besselj, + bessely0, + bessely1, bessely, - hankelh1, - hankelh2, - besseli, - besselk, + hankelh1, + hankelh2, + besseli, + besselk, besselh, - beta, - lbeta, - eta, + beta, + lbeta, + eta, zeta, - + # arrays - amap, - areduce, + mapslices, + reducedim, bsxfun, cartesian_map, cat, @@ -554,25 +461,22 @@ export circshift, colon, conj!, - copy_to, + copy!, cumprod, cumsum, cumsum_kbn, - diff, - each_col, - each_col!, - each_row, - each_row!, - each_vec, - each_vec!, - falses, + cummin, + cummax, fill, fill!, find, + findin, findmax, findmin, findn, - findn_nzs, + findnz, + findfirst, + findnext, first, flipdim, fliplr, @@ -586,7 +490,8 @@ export indmax, indmin, invperm, - ipermute, + ipermute!, + ipermutedims, isperm, issorted, last, @@ -600,10 +505,10 @@ export nthperm, nthperm!, ones, - order, partitions, pascal, - permute, + permute!, + permutedims, prod, promote_shape, randcycle, @@ -613,26 +518,21 @@ export reverse, reverse!, rot180, - rot90, rotl90, rotr90, - search_sorted, - search_sorted_first, - search_sorted_last, + searchsortedfirst, + searchsortedlast, select, select!, - shuffle, shuffle!, size, slice, slicedim, sort, sort!, - sort_by, - sort_by!, + sortby, + sortby!, sortperm, - sortr, - sortr!, squeeze, step, stride, @@ -641,24 +541,20 @@ export sub2ind, sum, sum_kbn, - trues, vcat, vec, zeros, - findfirst, - ref_shape, - assign_shape_check, - indices, - make_loop_nest, - check_bounds, + index_shape, + setindex_shape_check, + check_bounds, # linear algebra - axpy, chol, - chold, - chold!, - cholpd, - cholpd!, + cholfact, + cholfact!, + cholp, + cholpfact, + cholpfact!, cond, cross, ctranspose, @@ -667,12 +563,23 @@ export diagm, diagmm, diagmm!, + diff, dot, eig, + eigfact, + eigfact!, + eigmax, + eigmin, + eigs, eigvals, + eigvecs, expm, + sqrtm, eye, factors, + hess, + hessfact, + hessfact!, ishermitian, isposdef, isposdef!, @@ -683,31 +590,39 @@ export ldltd!, ldltd, linreg, + logdet, lu, - lud, - lud!, + lufact, + lufact!, norm, + normfro, null, pinv, qr, - qrd!, - qrd, + qrfact!, + qrfact, qrp, - qrpd!, - qrpd, + qrpfact!, + qrpfact, + qmulQR, + qTmulQR, randsym, rank, rref, + scale!, + schur, + schurfact, + schurfact!, solve, svd, + svdfact!, + svdfact, + svds, + svdvals!, svdvals, - sdd, - sddvals, - symmetrize, symmetrize!, trace, transpose, - trideig, tril, triu, tril!, @@ -718,6 +633,7 @@ export full, issparse, sparse, + sparsevec, speye, spones, sprand, @@ -726,139 +642,116 @@ export spzeros, # bitarrays - biteye, bitpack, - bitshow, bitunpack, - flipbits, + falses, + flipbits!, + rol, + ror, + trues, # dequeues append!, - grow, - insert, - shift, - unshift, - enqueue, + prepend!, + resize!, + insert!, + shift!, + unshift!, + pop!, + push!, # collections - add, - add_each, - add_weak_key, - add_weak_value, + add!, + add_each!, all, - allp, any, - anyp, - assign, - choose, + collect, complement, complement!, contains, - contains_is, - count, - countp, - del, - del_all, - del_each, - elements, + delete!, + empty!, + endof, + del_each!, eltype, get, + getindex, has, - hash, intersect, intersect!, isempty, - key, + getkey, keys, - keytype, length, - setdiff, map, - map_to, - map_to2, + map!, mapreduce, merge, merge!, - numel, - pairs, reduce, - ref, + setindex!, + sizehint, similar, - toggle, - toggle_each, + setdiff, + symdiff, + symdiff!, union, union!, unique, values, - valtype, - xor!, - pop, - push, filter, filter!, - + # strings and text output ascii, - begins_with, - byte_string_classify, + beginswith, char, - chars, charwidth, - check_ascii, - check_utf8, chomp, chop, chr2ind, bytestring, - each_match, - each_search, - ends_with, + eachmatch, + endswith, escape_string, first_utf8_byte, ind2chr, is_utf8_start, is_valid_ascii, is_valid_utf8, + is_valid_char, isvalid, - iswalnum, - iswalpha, - iswascii, - iswblank, - iswcntrl, - iswdigit, - iswgraph, - iswlower, - iswprint, - iswpunct, - iswspace, - iswupper, - iswxdigit, + isalnum, + isalpha, + isascii, + isblank, + iscntrl, + isdigit, + isgraph, + islower, + isprint, + ispunct, + isspace, + isupper, + isxdigit, join, - lc, lcfirst, lowercase, lpad, lstrip, match, ismatch, - memchr, nextind, prevind, replace, rpad, rstrip, - safe_char, search, split, - strcat, - strchr, string, strip, - strlen, strwidth, thisind, - transform_to_utf8, - uc, ucfirst, uppercase, utf8, @@ -869,18 +762,14 @@ export dump, float32_isvalid, float64_isvalid, - fprintf, hex, - idump, - is_hex_digit, + xdump, ndigits, ndigits0z, + digits, oct, - parse_bin, - parse_float, - parse_hex, - parse_int, - parse_oct, + parsefloat, + parseint, print, print_escaped, print_joined, @@ -890,92 +779,81 @@ export print_shortest, print_unescaped, print_unescaped_chars, - printf, println, - quote_string, repeat, repl_show, show, showall, showcompact, sprint, - sprintf, repr, summary, unescape_chars, unescape_string, base, - -# statistics and random numbers - betarnd, - chi2rnd, + print_with_color, + info, + warn, + +# random numbers + AbstractRNG, + MersenneTwister, + rand!, + rand, + randbool!, + randbool, + randn!, + randn, + srand, + +# statistics cor, - cor_pearson, - cor_spearman, cov, - cov_pearson, - cov_spearman, - decile, - exprnd, hist, - histc, - mad, + histrange, mean, median, + midpoints, quantile, - quartile, - quintile, - Rng_MT, - Rng, - rand, - rand!, - randbeta, - randbeta!, - randbool, - randbool!, - randchi2, - randchi2!, - randexp, - randexp!, - randg, - randg!, - randg2, - randi, - randi!, - randival, - randival!, - randn, - randn!, - srand, std, - tiedrank, + stdm, var, - weighted_mean, - + varm, + # signal processing bfft, - bfftn, + bfft!, + plan_bfft, + plan_bfft!, brfft, - brfftn, + plan_brfft, conv, conv2, deconv, fft, - fft2, - fft3, - fftn, + fft!, + plan_fft, + plan_fft!, fftshift, filt, ifft, - ifft2, - ifft3, - ifftn, + ifft!, + plan_ifft, + plan_ifft!, ifftshift, irfft, - irfftn, + plan_irfft, rfft, - rfftn, + plan_rfft, xcorr, + dct, + idct, + dct!, + idct!, + plan_dct, + plan_idct, + plan_dct!, + plan_idct!, # iteration start, @@ -983,26 +861,27 @@ export next, enumerate, zip, - times, - + # object identity and equality copy, deepcopy, deepcopy_internal, isequal, isless, + hash, identity, object_id, sizeof, isimmutable, - + isbits, + # tasks consume, current_task, istaskdone, produce, - tls, - + task_local_storage, + # time sleep, strftime, @@ -1012,14 +891,15 @@ export time_ns, toc, toq, - + # errors assert, error, rethrow, backtrace, + catch_backtrace, system_error, - + # types convert, isleaftype, @@ -1028,55 +908,53 @@ export promote_rule, promote_type, super, - tintersect, - + typeintersect, + typejoin, + # syntax expand, macroexpand, esc, - expr, gensym, parse, - parse_input_line, - parseatom, symbol, - + # help and reflection ans, apropos, - function_loc, + functionloc, edit, methods, + methodswith, help, less, names, module_name, module_parent, + versioninfo, which, whicht, whos, isinteractive, disassemble, finfer, - + # loading source files evalfile, - find_in_path, + include, include_string, - load, + reload, require, - julia_pkgdir, - + # RTS internals - compile_hint, + precompile, finalizer, gc, gc_disable, gc_enable, - isbuiltin, isconst, isgeneric, - + # misc exit, quit, @@ -1087,16 +965,18 @@ export tty_rows, # I/O and events - add_fd_handler, + accept, + listen, + bind, + connect, close, countlines, - csvread, - csvwrite, - del_fd_handler, + readcsv, + writecsv, deserialize, - dlmread, - dlmwrite, - each_line, + readdlm, + writedlm, + eachline, eatwspace, eatwspace_comment, eof, @@ -1112,12 +992,14 @@ export memio, mmap, mmap_array, + mmap_bitarray, mmap_grow, mmap_stream_settings, msync, munmap, nb_available, open, + open_any_tcp_port, position, read, readall, @@ -1128,91 +1010,78 @@ export readuntil, seek, seek_end, - select_read, serialize, skip, - stderr, - stderr_stream, - stdin, - stdin_stream, - stdout, - stdout_stream, + start_reading, + stop_reading, + start_timer, + stop_timer, takebuf_array, takebuf_string, truncate, - with_output_to_string, + uv_error, write, - + # multiprocessing addprocs_local, addprocs_sge, addprocs_ssh, addprocs_ssh_tunnel, - at_each, fetch, isready, - make_scheduled, yield, - enq_work, myid, nprocs, - pfor, pmap, - preduce, put, remote_call, remote_call_fetch, remote_call_wait, remote_do, - rr2id, - spawn, - spawnat, - spawnlocal, take, - + wait, + # distributed arrays - defaultdist, distribute, + dfill, + dones, drand, drandn, - localize, + dzeros, + localpart, myindexes, procs, - + # paths and file names - basename, - fullfile, - tmpnam, - basename, + splitdir, + splitdrive, + splitext, dirname, - dirname_basename, - file_path, - path_expand, - abs_path, - abs_path_split, - split_extension, - split_path, - fileparts, - isrooted, - tilde_expand, + basename, + isabspath, + isdirpath, + joinpath, + normpath, + abspath, + realpath, + expanduser, # filesystem operations cd, - cwd, - is_file_readable, + pwd, ls, - file_copy, - file_remove, - file_create, - path_rename, + cp, + rm, + touch, + mv, mkdir, + mkpath, rmdir, tempdir, tempname, mktemp, mktempdir, - download_file, - realpath, + download, filemode, filesize, mtime, @@ -1235,21 +1104,12 @@ export isexecutable, uperm, gperm, - operm, - -# external processes - cmd_stdin_stream, - cmd_stdout_stream, - cmds, - connect, - dup2, - exec, - fork, + operm, + +# external processes ## TODO: whittle down these exports. getpid, ignorestatus, - make_pipe, - other, - output, + kill, pipeline_error, process_exit_status, process_exited, @@ -1257,50 +1117,48 @@ export process_running, process_signaled, process_status, - process_stop_signal, - process_stopped, + #process_stop_signal, + #process_stopped, process_term_signal, - read_from, + readsfrom, + readandwrite, run, - setsuccess, + spawn, + spawn_nostdin, success, - successful, - system, - wait, - wait_nohang, - write_to, - + writesto, + # C interface c_free, dlopen, + dlopen_e, + dlclose, dlsym, dlsym_e, errno, - getenv, - hasenv, pointer, pointer_to_array, cfunction, - setenv, strerror, unsafe_ref, unsafe_assign, - unsetenv, - + unsafe_pointer_to_objref, + pointer_from_objref, + disable_sigint, + reenable_sigint, + # Macros + @b_str, + @r_str, @v_str, + @mstr, @unexpected, @assert, - @r_str, - @str, - @S_str, - @I_str, - @E_str, - @B_str, - @b_str, @cmd, @time, + @timed, @elapsed, + @which, @windows_only, @unix_only, @osx_only, @@ -1308,7 +1166,7 @@ export @sync, @async, @spawn, - @spawnlocal, + @spawnlocal, # deprecated @spawnat, @everywhere, @parallel, @@ -1316,7 +1174,6 @@ export @eval, @task, @thunk, - @L_str, @vectorize_1arg, @vectorize_2arg, @show, diff --git a/base/expr.jl b/base/expr.jl index a3d2010b37751..e93dd44fd9f18 100644 --- a/base/expr.jl +++ b/base/expr.jl @@ -1,9 +1,11 @@ ## symbols ## +symbol(s::Symbol) = s symbol(s::ASCIIString) = symbol(s.data) symbol(s::UTF8String) = symbol(s.data) symbol(a::Array{Uint8,1}) = ccall(:jl_symbol_n, Any, (Ptr{Uint8}, Int32), a, length(a))::Symbol +symbol(x::Char) = symbol(string(x)) gensym() = ccall(:jl_gensym, Any, ())::Symbol @@ -14,21 +16,23 @@ gensym(a::Array{Uint8,1}) = gensym(ss::Union(ASCIIString, UTF8String)...) = map(gensym, ss) macro gensym(names...) - blk = expr(:block) + blk = Expr(:block) for name in names - push(blk.args, :($(esc(name)) = gensym($(string(name))))) + push!(blk.args, :($(esc(name)) = gensym($(string(name))))) end - push(blk.args, :nothing) + push!(blk.args, :nothing) return blk end -esc(e::ANY) = expr(:escape, {e}) +esc(e::ANY) = Expr(:escape, e) ## expressions ## -expr(hd::Symbol, args::ANY...) = Expr(hd, {args...}, Any) -expr(hd::Symbol, args::Array{Any,1}) = Expr(hd, args, Any) -copy(e::Expr) = Expr(e.head, isempty(e.args) ? e.args : astcopy(e.args), e.typ) +splicedexpr(hd::Symbol, args::Array{Any,1}) = (e=Expr(hd); e.args=args; e) +copy(e::Expr) = (n = Expr(e.head); + n.args = astcopy(e.args); + n.typ = e.typ; + n) copy(s::SymbolNode) = SymbolNode(s.name, s.typ) copy(n::GetfieldNode) = GetfieldNode(n.value, n.name, n.typ) @@ -42,7 +46,7 @@ isequal(x::SymbolNode, y::SymbolNode) = is(x.name,y.name) isequal(x::SymbolNode, y::Symbol) = is(x.name,y) isequal(x::Symbol , y::SymbolNode) = is(x,y.name) -function show(io, tv::TypeVar) +function show(io::IO, tv::TypeVar) if !is(tv.lb, None) show(io, tv.lb) print(io, "<:") @@ -60,5 +64,5 @@ macroexpand(x) = ccall(:jl_macroexpand, Any, (Any,), x) ## misc syntax ## macro eval(x) - :($(esc(:eval))($(expr(:quote,x)))) + :($(esc(:eval))($(Expr(:quote,x)))) end diff --git a/base/fftw.jl b/base/fftw.jl index c0c38771fb877..92907d296d917 100644 --- a/base/fftw.jl +++ b/base/fftw.jl @@ -1,12 +1,27 @@ module FFTW -export bfft, bfftn, brfft, brfftn, fft, fft2, fft3, fftn, - ifft, ifft2, ifft3, ifftn, irfft, irfftn, rfft, rfftn +export fft, bfft, ifft, rfft, brfft, irfft, + plan_fft, plan_bfft, plan_ifft, plan_rfft, plan_brfft, plan_irfft, + fft!, bfft!, ifft!, plan_fft!, plan_bfft!, plan_ifft!, + r2r, r2r!, plan_r2r, plan_r2r!, + export_wisdom, import_wisdom, import_system_wisdom, forget_wisdom, + MEASURE, DESTROY_INPUT, UNALIGNED, CONSERVE_MEMORY, EXHAUSTIVE, + PRESERVE_INPUT, PATIENT, ESTIMATE, WISDOM_ONLY, NO_TIMELIMIT, + R2HC, HC2R, DHT, REDFT00, REDFT01, REDFT10, REDFT11, + RODFT00, RODFT01, RODFT10, RODFT11, + fftwNumber, fftwReal, fftwComplex ## FFT: Implement fft by calling fftw. +@unix_only begin const libfftw = "libfftw3_threads" const libfftwf = "libfftw3f_threads" +end + +@windows_only begin +const libfftw = "libfftw3" +const libfftwf = "libfftw3f" +end ## Direction of FFT @@ -23,6 +38,7 @@ const EXHAUSTIVE = uint32(1 << 3) # NO_EXHAUSTIVE is default const PRESERVE_INPUT = uint32(1 << 4) # cancels DESTROY_INPUT const PATIENT = uint32(1 << 5) # IMPATIENT is default const ESTIMATE = uint32(1 << 6) +const WISDOM_ONLY = uint32(1 << 21) ## R2R transform kinds @@ -38,23 +54,58 @@ const RODFT01 = int32(8) const RODFT10 = int32(9) const RODFT11 = int32(10) +# FFTW floating-point types: + +typealias fftwNumber Union(Float64,Float32,Complex128,Complex64) +typealias fftwReal Union(Float64,Float32) +typealias fftwComplex Union(Complex128,Complex64) +typealias fftwDouble Union(Float64,Complex128) +typealias fftwSingle Union(Float32,Complex64) +typealias fftwTypeDouble Union(Type{Float64},Type{Complex128}) +typealias fftwTypeSingle Union(Type{Float32},Type{Complex64}) + ## Julia wrappers around FFTW functions # Wisdom -function import_64bit_wisdom(filename::String) - stat = ccall((:fftw_import_wisdom_from_filename,libfftw), - Int32, (Ptr{Uint8},), bytestring(filename)) - if stat == 0 - error("failed to import wisdom from $filename") +# Import and export wisdom to/from a single file for all precisions, +# which is more user-friendly than requiring the user to call a +# separate routine depending on the fp precision of the plans. This +# requires a bit of trickness since we have to (a) use the libc file +# I/O routines with fftw_export_wisdom_to_file/import_wisdom_from_file +# (b) we need 256 bytes of space padding between the wisdoms to work +# around FFTW's internal file i/o buffering [see the BUFSZ constant in +# FFTW's api/import-wisdom-from-file.c file]. + +function export_wisdom(fname::String) + f = ccall(:fopen, Ptr{Void}, (Ptr{Uint8},Ptr{Uint8}), + bytestring(fname), bytestring("w")) + if f == C_NULL + error("could not open wisdom file $fname") + end + ccall((:fftw_export_wisdom_to_file,libfftw), Void, (Ptr{Void},), f) + ccall(:fputs, Int32, (Ptr{Uint8},Ptr{Void}), bytestring(" "^256), f) + ccall((:fftwf_export_wisdom_to_file,libfftwf), Void, (Ptr{Void},), f) + ccall(:fclose, Void, (Ptr{Void},), f) +end + +function import_wisdom(fname::String) + f = ccall(:fopen, Ptr{Void}, (Ptr{Uint8},Ptr{Uint8}), + bytestring(fname), bytestring("r")) + if f == C_NULL + error("could not open wisdom file $fname") + end + if ccall((:fftw_import_wisdom_from_file,libfftw),Int32,(Ptr{Void},),f)==0|| + ccall((:fftwf_import_wisdom_from_file,libfftwf),Int32,(Ptr{Void},),f)==0 + error("failed to import wisdom from $fname") end + ccall(:fclose, Void, (Ptr{Void},), f) end -function import_32bit_wisdom(filename::String) - stat = ccall((:fftwf_import_wisdom_from_filename,libfftwf), - Int32, (Ptr{Uint8},), bytestring(filename)) - if stat == 0 - error("failed to import wisdom from $filename") +function import_system_wisdom() + if ccall((:fftw_import_system_wisdom,libfftw), Int32, ()) == 0 || + ccall((:fftwf_import_system_wisdom,libfftwf), Int32, ()) == 0 + error("failed to import system wisdom") end end @@ -66,13 +117,16 @@ end # Threads let initialized = false - global num_threads - function num_threads(nthreads::Integer) + global set_num_threads + function set_num_threads(nthreads::Integer) if !initialized + # must re-initialize FFTW if any FFTW routines have been called + ccall((:fftw_cleanup,libfftw), Void, ()) + ccall((:fftwf_cleanup,libfftwf), Void, ()) stat = ccall((:fftw_init_threads,libfftw), Int32, ()) statf = ccall((:fftwf_init_threads,libfftwf), Int32, ()) if stat == 0 || statf == 0 - error("could not initialize fft threads") + error("could not initialize FFTW threads") end initialized = true end @@ -83,236 +137,672 @@ end # Execute -execute(precision::Union(Type{Float64}, Type{Complex128}), plan) = +execute(precision::fftwTypeDouble, plan) = ccall((:fftw_execute,libfftw), Void, (Ptr{Void},), plan) -execute(precision::Union(Type{Float32}, Type{Complex64}), plan) = +execute(precision::fftwTypeSingle, plan) = ccall((:fftwf_execute,libfftwf), Void, (Ptr{Void},), plan) +execute(plan, X::StridedArray{Complex128}, Y::StridedArray{Complex128}) = + ccall((:fftw_execute_dft,libfftw), Void, + (Ptr{Void},Ptr{Complex128},Ptr{Complex128}), plan, X, Y) + +execute(plan, X::StridedArray{Complex64}, Y::StridedArray{Complex64}) = + ccall((:fftwf_execute_dft,libfftwf), Void, + (Ptr{Void},Ptr{Complex64},Ptr{Complex64}), plan, X, Y) + +execute(plan, X::StridedArray{Float64}, Y::StridedArray{Complex128}) = + ccall((:fftw_execute_dft_r2c,libfftw), Void, + (Ptr{Void},Ptr{Float64},Ptr{Complex128}), plan, X, Y) + +execute(plan, X::StridedArray{Float32}, Y::StridedArray{Complex64}) = + ccall((:fftwf_execute_dft_r2c,libfftwf), Void, + (Ptr{Void},Ptr{Float32},Ptr{Complex64}), plan, X, Y) + +execute(plan, X::StridedArray{Complex128}, Y::StridedArray{Float64}) = + ccall((:fftw_execute_dft_c2r,libfftw), Void, + (Ptr{Void},Ptr{Complex128},Ptr{Float64}), plan, X, Y) + +execute(plan, X::StridedArray{Complex64}, Y::StridedArray{Float32}) = + ccall((:fftwf_execute_dft_c2r,libfftwf), Void, + (Ptr{Void},Ptr{Complex64},Ptr{Float32}), plan, X, Y) + +execute_r2r{T<:fftwDouble}(plan, X::StridedArray{T}, Y::StridedArray{T}) = + ccall((:fftw_execute_r2r,libfftw), Void, + (Ptr{Void},Ptr{T},Ptr{T}), plan, X, Y) + +execute_r2r{T<:fftwSingle}(plan, X::StridedArray{T}, Y::StridedArray{T}) = + ccall((:fftwf_execute_r2r,libfftwf), Void, + (Ptr{Void},Ptr{T},Ptr{T}), plan, X, Y) + +execute{T<:fftwReal}(plan, X::StridedArray{T}, Y::StridedArray{T}) = + execute_r2r(plan, X, Y) + # Destroy plan -destroy_plan(precision::Union(Type{Float64}, Type{Complex128}), plan) = +destroy_plan(precision::fftwTypeDouble, plan) = ccall((:fftw_destroy_plan,libfftw), Void, (Ptr{Void},), plan) -destroy_plan(precision::Union(Type{Float32}, Type{Complex64}), plan) = +destroy_plan(precision::fftwTypeSingle, plan) = ccall((:fftwf_destroy_plan,libfftwf), Void, (Ptr{Void},), plan) -# Create nd plan +# Planner timelimits + +const NO_TIMELIMIT = -1.0 # from fftw3.h + +set_timelimit(precision::fftwTypeDouble,seconds) = + ccall((:fftw_set_timelimit,libfftw), Void, (Float64,), seconds) + +set_timelimit(precision::fftwTypeSingle,seconds) = + ccall((:fftwf_set_timelimit,libfftwf), Void, (Float64,), seconds) + +# Array alignment mod 16: +# FFTW plans may depend on the alignment of the array mod 16 bytes, +# i.e. the address mod 16 of the first element of the array, in order +# to exploit SIMD operations. Julia arrays are, by default, aligned +# to 16-byte boundaries (address mod 16 == 0), but this may not be +# true for data imported from external C code, or for SubArrays. +# Use the undocumented routine fftw_alignment_of to determine the +# alignment of a given pointer modulo whatever FFTW needs. + +alignment_of{T<:fftwDouble}(A::StridedArray{T}) = + ccall((:fftw_alignment_of, libfftw), Int32, (Ptr{T},), A) + +alignment_of{T<:fftwSingle}(A::StridedArray{T}) = + ccall((:fftwf_alignment_of, libfftwf), Int32, (Ptr{T},), A) + +# Plan (low-level) + +# low-level storage of the FFTW plan, along with the information +# needed to determine whether it is applicable. We need to put +# this into a type to support a finalizer on the fftw_plan. +type Plan{T<:fftwNumber} + plan::Ptr{Void} + sz::Dims # size of array on which plan operates (Int tuple) + istride::Dims # strides of input + ialign::Int32 # alignment mod 16 of input + function Plan(plan::Ptr{Void}, sz::Dims, istride::Dims, ialign::Int32) + p = new(plan,sz,istride,ialign) + finalizer(p, p -> destroy_plan(T, p.plan)) + return p + end +end +Plan{T<:fftwNumber}(plan::Ptr{Void}, X::StridedArray{T}) = Plan{T}(plan, size(X), strides(X), alignment_of(X)) + +# Check whether a Plan is applicable to a given input array, and +# throw an informative error if not: +function assert_applicable{T<:fftwNumber}(p::Plan{T}, X::StridedArray{T}) + if size(X) != p.sz + throw(ArgumentError("FFTW plan applied to wrong-size array")) + elseif strides(X) != p.istride + throw(ArgumentError("FFTW plan applied to wrong-strides array")) + elseif alignment_of(X) != p.ialign + throw(ArgumentError("FFTW plan applied to array with wrong memory alignment")) + end +end + +# NOTE ON GC (garbage collection): +# The Plan has a finalizer so that gc will destroy the plan, +# which is necessary for gc to work with plan_fft. However, +# even when we are creating a single-use Plan [e.g. for fftn(x)], +# we intentionally do NOT call destroy_plan explicitly, and instead +# wait for garbage collection. The reason is that, in the common +# case where the user calls fft(x) a second time soon afterwards, +# if destroy_plan has not yet been called then FFTW will internally +# re-use the table of trigonometric constants from the first plan. + +# Compute dims and howmany for FFTW guru planner +function dims_howmany(X::StridedArray, Y::StridedArray, + sz::Array{Int,1}, region) + reg = [region...] + if length(unique(reg)) < length(reg) + throw(ArgumentError("each dimension can be transformed at most once")) + end + ist = [strides(X)...] + ost = [strides(Y)...] + dims = [sz[reg] ist[reg] ost[reg]]' + oreg = [1:ndims(X)] + oreg[reg] = 0 + oreg = filter(d -> d > 0, oreg) + howmany = [sz[oreg] ist[oreg] ost[oreg]]' + return (dims, howmany) +end -for (libname, fname_complex, fname_r2c, fname_c2r, T_in, T_out) in - ((:libfftw,"fftw_plan_dft","fftw_plan_dft_r2c","fftw_plan_dft_c2r",:Float64,:Complex128), - (:libfftwf,"fftwf_plan_dft","fftwf_plan_dft_r2c","fftwf_plan_dft_c2r",:Float32,:Complex64)) - @eval begin - function plan_dft(X::Array{$T_out}, Y::Array{$T_out}, direction::Integer) - ccall(($fname_complex,$libname), - Ptr{Void}, - (Int32, Ptr{Int32}, Ptr{$T_out}, Ptr{$T_out}, Int32, Uint32, ), - ndims(X), int32(reverse([size(X)...])), X, Y, direction, ESTIMATE) - end - function plan_dft(X::Array{$T_in}, Y::Array{$T_out}) - ccall(($fname_r2c,$libname), - Ptr{Void}, - (Int32, Ptr{Int32}, Ptr{$T_in}, Ptr{$T_out}, Uint32, ), - ndims(X), int32(reverse([size(X)...])), X, Y, ESTIMATE) +# check & convert kinds into int32 array with same length as region +function fix_kinds(region, kinds) + if length(kinds) != length(region) + if length(kinds) > length(region) + throw(ArgumentError("too many transform kinds")) + else + if length(kinds) == 0 + throw(ArgumentError("must supply a transform kind")) + end + k = Array(Int32, length(region)) + k[1:length(kinds)] = [kinds...] + k[length(kinds)+1:end] = kinds[end] + kinds = k end - function plan_dft(X::Array{$T_out}, Y::Array{$T_in}) - ccall(($fname_c2r,$libname), - Ptr{Void}, - (Int32, Ptr{Int32}, Ptr{$T_out}, Ptr{$T_in}, Uint32), - ndims(Y), int32(reverse([size(Y)...])), X, Y, ESTIMATE) + else + kinds = int32([kinds...]) + end + for i = 1:length(kinds) + if kinds[i] < 0 || kinds[i] > 10 + throw(ArgumentError("invalid transform kind")) end end + return kinds end -# Guru plans +# low-level Plan creation (for internal use in FFTW module) + +for (Tr,Tc,fftw,lib) in ((:Float64,:Complex128,"fftw",libfftw), + (:Float32,:Complex64,"fftwf",libfftwf)) + + @eval function Plan(X::StridedArray{$Tc}, Y::StridedArray{$Tc}, + region, direction::Integer, + flags::Unsigned, timelimit::Real) + set_timelimit($Tr, timelimit) + dims, howmany = dims_howmany(X, Y, [size(X)...], region) + plan = ccall(($(string(fftw,"_plan_guru64_dft")),$lib), + Ptr{Void}, + (Int32, Ptr{Int}, Int32, Ptr{Int}, + Ptr{$Tc}, Ptr{$Tc}, Int32, Uint32), + size(dims,2), dims, size(howmany,2), howmany, + X, Y, direction, flags) + set_timelimit($Tr, NO_TIMELIMIT) + if plan == C_NULL + error("FFTW could not create plan") # shouldn't normally happen + end + return Plan(plan, X) + end -for (libname, fname_complex, fname_r2c, fname_c2r, T_in, T_out) in - ((:libfftw,"fftw_plan_guru64_dft","fftw_plan_guru64_dft_r2c","fftw_plan_guru64_dft_c2r",:Float64,:Complex128), - (:libfftwf,"fftwf_plan_guru64_dft","fftwf_plan_guru64_dft_r2c","fftwf_plan_guru64_dft_c2r",:Float32,:Complex64)) - @eval begin - function plan_guru_dft(dims::Array{Int,2}, howmany::Array{Int,2}, - X::Array{$T_out}, Y::Array{$T_out}, direction::Int32) - ccall(($fname_complex,$libname), - Ptr{Void}, - (Int32, Ptr{Int}, Int32, Ptr{Int}, - Ptr{$T_out}, Ptr{$T_out}, Int32, Uint32), - size(dims,2), dims, size(howmany,2), howmany, - X, Y, direction, ESTIMATE) + @eval function Plan(X::StridedArray{$Tr}, Y::StridedArray{$Tc}, + region, flags::Unsigned, timelimit::Real) + region = circshift([region...],-1) # FFTW halves last dim + set_timelimit($Tr, timelimit) + dims, howmany = dims_howmany(X, Y, [size(X)...], region) + plan = ccall(($(string(fftw,"_plan_guru64_dft_r2c")),$lib), + Ptr{Void}, + (Int32, Ptr{Int}, Int32, Ptr{Int}, + Ptr{$Tr}, Ptr{$Tc}, Uint32), + size(dims,2), dims, size(howmany,2), howmany, + X, Y, flags) + set_timelimit($Tr, NO_TIMELIMIT) + if plan == C_NULL + error("FFTW could not create plan") # shouldn't normally happen + end + return Plan(plan, X) + end + + @eval function Plan(X::StridedArray{$Tc}, Y::StridedArray{$Tr}, + region, flags::Unsigned, timelimit::Real) + region = circshift([region...],-1) # FFTW halves last dim + set_timelimit($Tr, timelimit) + dims, howmany = dims_howmany(X, Y, [size(Y)...], region) + plan = ccall(($(string(fftw,"_plan_guru64_dft_c2r")),$lib), + Ptr{Void}, + (Int32, Ptr{Int}, Int32, Ptr{Int}, + Ptr{$Tc}, Ptr{$Tr}, Uint32), + size(dims,2), dims, size(howmany,2), howmany, + X, Y, flags) + set_timelimit($Tr, NO_TIMELIMIT) + if plan == C_NULL + error("FFTW could not create plan") # shouldn't normally happen end - function plan_guru_dft(dims::Array{Int,2}, howmany::Array{Int,2}, - X::Array{$T_in}, Y::Array{$T_out}) - ccall(($fname_r2c,$libname), - Ptr{Void}, - (Int32, Ptr{Int}, Int32, Ptr{Int}, - Ptr{$T_in}, Ptr{$T_out}, Uint32), - size(dims,2), dims, size(howmany,2), howmany, - X, Y, ESTIMATE) + return Plan(plan, X) + end + + @eval function Plan_r2r(X::StridedArray{$Tr}, Y::StridedArray{$Tr}, + region, kinds, + flags::Unsigned, timelimit::Real) + kinds = fix_kinds(region, kinds) + set_timelimit($Tr, timelimit) + dims, howmany = dims_howmany(X, Y, [size(X)...], region) + plan = ccall(($(string(fftw,"_plan_guru64_r2r")),$lib), + Ptr{Void}, + (Int32, Ptr{Int}, Int32, Ptr{Int}, + Ptr{$Tr}, Ptr{$Tr}, Ptr{Int32}, Uint32), + size(dims,2), dims, size(howmany,2), howmany, + X, Y, kinds, flags) + set_timelimit($Tr, NO_TIMELIMIT) + if plan == C_NULL + error("FFTW could not create plan") # shouldn't normally happen end - function plan_guru_dft(dims::Array{Int,2}, howmany::Array{Int,2}, - X::Array{$T_out}, Y::Array{$T_in}) - ccall(($fname_c2r,$libname), - Ptr{Void}, - (Int32, Ptr{Int}, Int32, Ptr{Int}, - Ptr{$T_out}, Ptr{$T_in}, Uint32), - size(dims,2), dims, size(howmany,2), howmany, - X, Y, ESTIMATE) + return Plan(plan, X) + end + + # support r2r transforms of complex = transforms of real & imag parts + @eval function Plan_r2r(X::StridedArray{$Tc}, Y::StridedArray{$Tc}, + region, kinds, + flags::Unsigned, timelimit::Real) + kinds = fix_kinds(region, kinds) + set_timelimit($Tr, timelimit) + dims, howmany = dims_howmany(X, Y, [size(X)...], region) + dims[2:3, 1:size(dims,2)] *= 2 + howmany[2:3, 1:size(howmany,2)] *= 2 + howmany = [howmany [2,1,1]] # append loop over real/imag parts + plan = ccall(($(string(fftw,"_plan_guru64_r2r")),$lib), + Ptr{Void}, + (Int32, Ptr{Int}, Int32, Ptr{Int}, + Ptr{$Tc}, Ptr{$Tc}, Ptr{Int32}, Uint32), + size(dims,2), dims, size(howmany,2), howmany, + X, Y, kinds, flags) + set_timelimit($Tr, NO_TIMELIMIT) + if plan == C_NULL + error("FFTW could not create plan") # shouldn't normally happen end + return Plan(plan, X) end -end -# fftn/ifftn +end -for (fname,direction) in ((:fftn,:FORWARD),(:bfftn,:BACKWARD)) +# Convert arrays of numeric types to FFTW-supported packed complex-float types +# (FIXME: is there a way to use the Julia promotion rules more cleverly here?) +complexfloat{T<:fftwComplex}(X::StridedArray{T}) = X +complexfloat{T<:fftwReal}(X::StridedArray{T}) = complex(X) +complexfloat{T<:Real}(X::StridedArray{T}) = complex128(X) +complexfloat{T<:Complex}(X::StridedArray{T}) = complex128(X) + +# In the Julia interface, a "plan" is just a function that executes +# an efficient FFT of fixed size/strides/alignment. For each FFT function +# (fft, bfft, ifft, rfft, ...), we have at least two interfaces: +# +# fft(x [, region]) - FFT of x, creating and destroying a plan, +# optionally acting only on a subset of the dimensions +# p = plan_fft(x, [, region [, flags [, timelimit]]]) +# -- returns a function p(x) that performs efficient FFTs +# of a given size (on given dimensions) with variants +# to specify the FFTW planner flags (default is ESTIMATE) and +# timelimit (default: NO_TIMELIMIT). +# +# along with in-place variants fft! and plan_fft! if feasible. + +for (f,direction) in ((:fft,:FORWARD), (:bfft,:BACKWARD)) + f! = symbol(string(f,"!")) + plan_f = symbol(string("plan_",f)) + plan_f! = symbol(string("plan_",f,"!")) @eval begin - function ($fname){T<:Union(Complex128,Complex64)}(X::Array{T}) + function $f{T<:fftwComplex}(X::StridedArray{T}, region) Y = similar(X, T) - plan = plan_dft(X, Y, $direction) - execute(T, plan) - destroy_plan(T, plan) + p = Plan(X, Y, region, $direction, ESTIMATE, NO_TIMELIMIT) + execute(T, p.plan) + # do not destroy_plan ... see above note on gc return Y end - function ($fname){T<:Union(Float64,Float32)}(X::Array{T}) - Y = complex(X) # in-place transform - plan = plan_dft(Y, Y, $direction) - execute(T, plan) - destroy_plan(T, plan) - return Y + # in-place version + function $f!{T<:fftwComplex}(X::StridedArray{T},region) + p = Plan(X, X, region, $direction, ESTIMATE, NO_TIMELIMIT) + execute(T, p.plan) + # do not destroy_plan ... see above note on gc + return X + end + + function $f{T<:Number}(X::StridedArray{T}, region) + Y = complexfloat(X) # in-place transform + return $f!(Y, region) end - end -end -ifftn(X) = bfftn(X)./length(X) + function $plan_f{T<:fftwComplex}(X::StridedArray{T}, + region, + flags::Unsigned, + tlim::Real) + Y = similar(X, T) + p = Plan(X, Y, region, $direction, flags, tlim) + return Z::StridedArray{T} -> begin + assert_applicable(p, Z) + W = similar(Z, T) + execute(p.plan, Z, W) + return W + end + end + + function $plan_f{T<:Number}(X::StridedArray{T}, region, + flags::Unsigned, tlim::Real) + Y = complexfloat(X) # in-place transform + p = Plan(Y, Y, region, $direction, flags, tlim) + return Z::StridedArray{T} -> begin + W = complexfloat(Z) # in-place transform + assert_applicable(p, W) + execute(p.plan, W, W) + return W + end + end + + function $plan_f!{T<:fftwComplex}(X::StridedArray{T}, + region, + flags::Unsigned, + tlim::Real) + p = Plan(X, X, region, $direction, flags, tlim) + return Z::StridedArray{T} -> begin + assert_applicable(p, Z) + execute(p.plan, Z, Z) + return Z + end + end -# Convenience functions + $f(X::StridedArray) = $f(X, 1:ndims(X)) + $f!(X::StridedArray) = $f!(X, 1:ndims(X)) + end + for pf in (plan_f, plan_f!) + @eval begin + $pf{T<:Number}(X::StridedArray{T}, region, flags::Unsigned) = + $pf(X, region, flags, NO_TIMELIMIT) + $pf{T<:Number}(X::StridedArray{T}, region) = + $pf(X, region, ESTIMATE, NO_TIMELIMIT) + $pf{T<:Number}(X::StridedArray{T}) = + $pf(X, 1:ndims(X), ESTIMATE, NO_TIMELIMIT) + end + end +end -fft2{T}(X::Matrix{T}) = fftn(X) -fft3{T}(X::Array{T,3}) = fftn(X) -ifft2{T}(X::Matrix{T}) = ifftn(X) -ifft3{T}(X::Array{T,3}) = ifftn(X) +# Normalization for ifft -# Compute fft and ifft of slices of arrays +normalization(X::StridedArray, region) = 1 / prod([size(X)...][[region...]]) +normalization(X::StridedArray) = 1 / length(X) -fft(X) = fft(X, 1) -ifft(X) = ifft(X, 1) -ifft(X,dim) = bfft(X,dim)./size(X,dim) +# Normalized ifft inverse transforms: -for (fname,direction) in ((:fft,:FORWARD),(:bfft,:BACKWARD)) +for (f,fb) in ((:ifft,:bfft), (:ifft!,:bfft!)) + pf = symbol(string("plan_", f)) + pfb = symbol(string("plan_", fb)) @eval begin - function ($fname){T<:Union(Complex128,Complex64)}(X::Array{T}, dim::Int) - s = [size(X)...] - strides = [ prod(s[1:i-1]) for i=1:length(s) ] - dims = [s[dim],strides[dim],strides[dim]]'' - del(s, dim) - del(strides, dim) - howmany = [s strides strides]' - Y = similar(X, T) - plan = plan_guru_dft(dims, howmany, X, Y, $direction) - execute(T, plan) - destroy_plan(T, plan) - return Y - end + $f(X, region) = scale!($fb(X, region), normalization(X, region)) + $f(X) = scale!($fb(X), normalization(X)) - function ($fname){T<:Union(Float64,Float32)}(X::Array{T}, dim::Int) - s = [size(X)...] - strides = [ prod(s[1:i-1]) for i=1:length(s) ] - n = s[dim] - dims = [n,strides[dim],strides[dim]]'' - del(s, dim) - del(strides, dim) - howmany = [s strides strides]' - Y = complex(X) # in-place transform - plan = plan_guru_dft(dims, howmany, Y, Y, $direction) - execute(T, plan) - destroy_plan(T, plan) - return Y + function $pf(X, region, flags, tlim) + nrm = normalization(X, region) + p = $pfb(X, region, flags, tlim) + return Z -> scale!(p(Z), nrm) + end + $pf(X, region, flags) = $pf(X, region, flags, NO_TIMELIMIT) + $pf(X, region) = $pf(X, region, ESTIMATE, NO_TIMELIMIT) + function $pf(X) + nrm = normalization(X) + p = $pfb(X) + return Z -> scale!(p(Z), nrm) end end end -# rfft/rfftn +# rfft/brfft and planned variants. No in-place version for now. -rfft(X) = rfft(X, 1) for (Tr,Tc) in ((:Float32,:Complex64),(:Float64,:Complex128)) @eval begin - function rfftn(X::Array{$Tr}) + function rfft(X::StridedArray{$Tr}, region) + d1 = region[1] osize = [size(X)...] - osize[1] = ifloor(osize[1]/2) + 1 + osize[d1] = osize[d1]>>1 + 1 Y = Array($Tc, osize...) - plan = plan_dft(X, Y) - execute($Tr, plan) - destroy_plan($Tr, plan) + p = Plan(X, Y, region, ESTIMATE, NO_TIMELIMIT) + execute($Tr, p.plan) + # do not destroy_plan ... see above note on gc return Y end - function rfft(X::Array{$Tr}, dim::Int) - isize = [size(X)...] + function rfft{T<:Real}(X::StridedArray{T}, region) + Xr = float(X) + return rfft(Xr, region) + end + + function plan_rfft(X::StridedArray{$Tr}, region, + flags::Unsigned, tlim::Real) + d1 = region[1] osize = [size(X)...] - osize[dim] = ifloor(osize[dim]/2) + 1 - istrides = [ prod(isize[1:i-1]) for i=1:length(isize) ] - ostrides = [ prod(osize[1:i-1]) for i=1:length(osize) ] + osize[d1] = osize[d1]>>1 + 1 Y = Array($Tc, osize...) - dims = [isize[dim],istrides[dim],ostrides[dim]]'' - del(isize, dim) - del(istrides, dim) - del(ostrides, dim) - howmany = [isize istrides ostrides]' - plan = plan_guru_dft(dims, howmany, X, Y) - execute($Tr, plan) - destroy_plan($Tr, plan) - return Y + p = Plan(X, Y, region, flags, tlim) + return Z::StridedArray{$Tr} -> begin + assert_applicable(p, Z) + W = Array($Tc, osize...) + execute(p.plan, Z, W) + return W + end end - function brfftn(X::Array{$Tc}, d::Int) + # FFTW currently doesn't support PRESERVE_INPUT for + # multidimensional out-of-place c2r transforms, so + # we have to handle 1d and >1d cases separately. Ugh. + + function brfft(X::StridedArray{$Tc}, d::Integer, region::Integer) osize = [size(X)...] - @assert osize[1] == ifloor(d/2) + 1 - osize[1] = d + @assert osize[region] == d>>1 + 1 + osize[region] = d Y = Array($Tr, osize...) - plan = plan_dft(X, Y) - execute($Tr, plan) - destroy_plan($Tr, plan) + p = Plan(X, Y, region, ESTIMATE | PRESERVE_INPUT, NO_TIMELIMIT) + execute($Tr, p.plan) + # do not destroy_plan ... see above note on gc return Y end - function brfft(X::Array{$Tc}, d::Int, dim::Int) - isize = [size(X)...] + # variant that destroys input X + function brfftd(X::StridedArray{$Tc}, d::Integer, region) + d1 = region[1] osize = [size(X)...] - @assert osize[dim] == ifloor(d/2) + 1 - osize[dim] = d - istrides = [ prod(isize[1:i-1]) for i=1:length(isize) ] - ostrides = [ prod(osize[1:i-1]) for i=1:length(osize) ] + @assert osize[d1] == d>>1 + 1 + osize[d1] = d Y = Array($Tr, osize...) - dims = [osize[dim],istrides[dim],ostrides[dim]]'' - del(osize, dim) - del(istrides, dim) - del(ostrides, dim) - howmany = [osize istrides ostrides]' - plan = plan_guru_dft(dims, howmany, X, Y) - execute($Tr, plan) - destroy_plan($Tr, plan) + p = Plan(X, Y, region, ESTIMATE, NO_TIMELIMIT) + execute($Tr, p.plan) + # do not destroy_plan ... see above note on gc return Y end + + function brfft(X::StridedArray{$Tc}, d::Integer, region) + if length(region) == 1 + return brfft(X, d, convert(Int, region[1])) + end + X = copy(X) # TODO: work in-place instead? + return brfftd(X, d, region) + end + + function brfft{T<:Number}(X::StridedArray{T}, d::Integer, region) + Xc = complexfloat(X) + return brfftd(Xc, d, region) + end + + function plan_brfft(X::StridedArray{$Tc}, d::Integer, region::Integer, + flags::Unsigned, tlim::Real) + osize = [size(X)...] + @assert osize[region] == d>>1 + 1 + osize[region] = d + Y = Array($Tr, osize...) + p = Plan(X, Y, region, flags | PRESERVE_INPUT, tlim) + return Z::StridedArray{$Tc} -> begin + assert_applicable(p, Z) + W = Array($Tr, osize...) + execute(p.plan, Z, W) + return W + end + end + + function plan_brfft(X::StridedArray{$Tc}, d::Integer, region, + flags::Unsigned, tlim::Real) + if length(region) == 1 + return plan_brfft(X, d, convert(Int, region[1]), flags, tlim) + end + d1 = region[1] + osize = [size(X)...] + @assert osize[d1] == d>>1 + 1 + osize[d1] = d + Y = Array($Tr, osize...) + X = copy(X) + p = Plan(X, Y, region, flags, tlim) + return Z::StridedArray{$Tc} -> begin + assert_applicable(p, Z) + Z = copy(Z) + W = Array($Tr, osize...) + execute(p.plan, Z, W) + return W + end + end + + rfft(X::StridedArray) = rfft(X, 1:ndims(X)) + brfft(X::StridedArray,d) = brfft(X, d, 1:ndims(X)) + + plan_rfft(X::StridedArray, region, flags) = + plan_rfft(X, region, flags, NO_TIMELIMIT) + plan_rfft(X::StridedArray, region) = + plan_rfft(X, region, ESTIMATE, NO_TIMELIMIT) + plan_rfft(X::StridedArray) = + plan_rfft(X, 1:ndims(X), ESTIMATE, NO_TIMELIMIT) + + plan_brfft(X::StridedArray, d, region, flags) = + plan_brfft(X, d, region, flags, NO_TIMELIMIT) + plan_brfft(X::StridedArray, d, region) = + plan_brfft(X, d, region, ESTIMATE, NO_TIMELIMIT) + plan_brfft(X::StridedArray, d) = + plan_brfft(X, d, 1:ndims(X), ESTIMATE, NO_TIMELIMIT) end end -brfft(X,d) = brfft(X,d,1) -irfft(X,d) = irfft(X,d,1) -irfft(X,d,dim) = brfft(X,d,dim)./d -irfftn(X,d) = (Y=brfftn(X,d); Y./length(Y)) +# Normalized rfft inverse transforms: + +function irfft(X, d, region) + Y = brfft(X, d, region) + return scale!(Y, normalization(Y, region)) +end + +function irfft(X, d) + Y = brfft(X, d) + return scale!(Y, normalization(Y)) +end + +function plan_irfft(X::StridedArray, d::Integer, region, flags, tlim) + p = plan_brfft(X, d, region, flags, tlim) + d1 = region[1] + osize = [size(X)...] + osize[d1] = d + nrm = 1 / prod(osize[[region...]]) + return Z -> scale!(p(Z), nrm) +end + +plan_irfft(X, d, region, flags) = plan_irfft(X, d, region, flags, NO_TIMELIMIT) +plan_irfft(X, d, region) = plan_irfft(X, d, region, ESTIMATE, NO_TIMELIMIT) +plan_irfft(X, d) = plan_irfft(X, d, 1:ndims(X), ESTIMATE, NO_TIMELIMIT) + +# A DFT is unambiguously defined as just the identity operation for scalars +fft(x::Number) = x +ifft(x::Number) = x +bfft(x::Number) = x +rfft(x::Real) = x +irfft(x::Number, d::Integer) = d == 1 ? real(x) : throw(BoundsError()) +brfft(x::Number, d::Integer) = d == 1 ? real(x) : throw(BoundsError()) +fft(x::Number, dims) = length(dims) == 0 || dims[1] == 1 ? x : throw(BoundsError()) +ifft(x::Number, dims) = length(dims) == 0 || dims[1] == 1 ? x : throw(BoundsError()) +bfft(x::Number, dims) = length(dims) == 0 || dims[1] == 1 ? x : throw(BoundsError()) +fft(x::Number, dims) = length(dims) == 0 || dims[1] == 1 ? x : throw(BoundsError()) +rfft(x::Real, dims) = dims[1] == 1 ? x : throw(BoundsError()) +irfft(x::Number, d::Integer, dims) = d == 1 && dims[1] == 1 ? real(x) : throw(BoundsError()) +brfft(x::Number, d::Integer, dims) = d == 1 && dims[1] == 1 ? real(x) : throw(BoundsError()) + +plan_fft(x::Number) = x -> x +plan_ifft(x::Number) = x -> x +plan_bfft(x::Number) = x -> x +plan_rfft(x::Real) = x -> x +plan_irfft(x::Number, d::Integer) = (irfft(x,d); x -> real(x)) +plan_brfft(x::Number, d::Integer) = (brfft(x,d); x -> real(x)) + +plan_fft(x::Number, dims) = (fft(x,dims); x -> x) +plan_ifft(x::Number, dims) = (ifft(x,dims); x -> x) +plan_bfft(x::Number, dims) = (bfft(x,dims); x -> x) +plan_rfft(x::Real, dims) = (rfft(x,dims); x -> x) +plan_irfft(x::Number, d::Integer, dims) = (irfft(x,d,dims); x -> real(x)) +plan_brfft(x::Number, d::Integer, dims) = (brfft(x,d,dims); x -> real(x)) + +plan_fft(x::Number, dims, flags) = plan_fft(x, dims) +plan_ifft(x::Number, dims, flags) = plan_ifft(x, dims) +plan_bfft(x::Number, dims, flags) = plan_bfft(x, dims) +plan_rfft(x::Real, dims, flags) = plan_rfft(x, dims) +plan_irfft(x::Number, d::Integer, dims, flags) = plan_irfft(x, d, dims) +plan_brfft(x::Number, d::Integer, dims, flags) = plan_brfft(x, d, dims) + +plan_fft(x::Number, dims, flags, tlim) = plan_fft(x, dims) +plan_ifft(x::Number, dims, flags, tlim) = plan_ifft(x, dims) +plan_bfft(x::Number, dims, flags, tlim) = plan_bfft(x, dims) +plan_rfft(x::Real, dims, flags, tlim) = plan_rfft(x, dims) +plan_irfft(x::Number, d::Integer, dims, flags, tlim) = plan_irfft(x, d, dims) +plan_brfft(x::Number, d::Integer, dims, flags, tlim) = plan_brfft(x, d, dims) + +# FFTW r2r transforms (low-level interface) + +function r2r{T<:fftwNumber}(X::StridedArray{T}, kinds, region) + Y = similar(X, T) + p = Plan_r2r(X, Y, region, kinds, ESTIMATE, NO_TIMELIMIT) + execute(T, p.plan) + # do not destroy_plan ... see above note on gc + return Y +end + +function r2r!{T<:fftwNumber}(X::StridedArray{T}, kinds, region) + p = Plan_r2r(X, X, region, kinds, ESTIMATE, NO_TIMELIMIT) + execute(T, p.plan) + # do not destroy_plan ... see above note on gc + return X +end + +r2r{T<:Real}(X::StridedArray{T}, kinds, region) = r2r!(float(X), kinds, region) +r2r{T<:Complex}(X::StridedArray{T}, kinds, region) = r2r!(complexfloat(X), kinds, region) + +for f in (:r2r, :r2r!) + @eval $f(X, kinds) = $f(X, kinds, 1:ndims(X)) +end + +function plan_r2r{T<:fftwNumber}( + X::StridedArray{T}, kinds, region, flags::Unsigned, tlim::Real) + Y = similar(X, T) + p = Plan_r2r(X, Y, region, kinds, flags, tlim) + return Z::StridedArray{T} -> begin + assert_applicable(p, Z) + W = similar(Z, T) + execute_r2r(p.plan, Z, W) + return W + end +end + +function plan_r2r{T<:Number}(X::StridedArray{T}, kinds, region, + flags::Unsigned, tlim::Real) + Y = T<:Complex ? complexfloat(X) : float(X) + p = Plan_r2r(Y, Y, region, kinds, flags, tlim) + return Z::StridedArray{T} -> begin + W = T<:Complex ? complexfloat(Z) : float(Z) + execute_r2r(p.plan, W, W) + return W + end +end + +function plan_r2r!{T<:fftwNumber}( + X::StridedArray{T}, kinds,region,flags::Unsigned, tlim::Real) + p = Plan_r2r(X, X, region, kinds, flags, tlim) + return Z::StridedArray{T} -> begin + assert_applicable(p, Z) + execute_r2r(p.plan, Z, Z) + return Z + end +end + +for f in (:plan_r2r, :plan_r2r!) + @eval begin + $f(X, kinds, region, flags) = $f(X, kinds, region, flags, NO_TIMELIMIT) + $f(X, kinds, region) = $f(X, kinds, region, ESTIMATE, NO_TIMELIMIT) + $f(X, kinds) = $f(X, kinds, 1:ndims(X), ESTIMATE, NO_TIMELIMIT) + end +end -# Transpose -# NOTE: Using MEASURE and PATIENT zeros out the input the -# first time it is used for a particular size. Use ESTIMATE +# FFTW-based transpose routines +# TODO: implement in-place transpose! routine (this is supported by FFTW) +# TODO: fftw/fftwf can transpose matrices of any type, provided that the +# element size is a multiple of sizeof(double) or sizeof(float). -for (libname, fname, elty) in ((:libfftw ,"fftw_plan_guru_r2r",:Float64), - (:libfftwf,"fftwf_plan_guru_r2r",:Float32)) +for (libname, fname, elty) in ((:libfftw ,"fftw_plan_guru64_r2r",:Float64), + (:libfftwf,"fftwf_plan_guru64_r2r",:Float32)) @eval begin function transpose(X::Matrix{$elty}) P = similar(X) (n1, n2) = size(X) plan = ccall(($fname,$libname), Ptr{Void}, - (Int32, Ptr{Int32}, Int32, Ptr{Int32}, Ptr{$elty}, Ptr{$elty}, Ptr{Int32}, Uint32), - 0, C_NULL, 2, int32([n1,n2,1,n2,1,n1]), X, P, [HC2R], ESTIMATE | PRESERVE_INPUT) + (Int32, Ptr{Int}, Int32, Ptr{Int}, Ptr{$elty}, Ptr{$elty}, Ptr{Int32}, Uint32), + 0, C_NULL, 2, [n1,n2,1,n2,1,n1], X, P, [HC2R], ESTIMATE | PRESERVE_INPUT) execute($elty, plan) destroy_plan($elty, plan) return P @@ -320,15 +810,15 @@ for (libname, fname, elty) in ((:libfftw ,"fftw_plan_guru_r2r",:Float64), end end -for (libname, fname, celty) in ((:libfftw ,"fftw_plan_guru_dft",:Complex128), - (:libfftwf,"fftwf_plan_guru_dft",:Complex64)) +for (libname, fname, celty) in ((:libfftw ,"fftw_plan_guru64_dft",:Complex128), + (:libfftwf,"fftwf_plan_guru64_dft",:Complex64)) @eval begin function transpose(X::Matrix{$celty}) P = similar(X) (n1, n2) = size(X) plan = ccall(($fname,$libname), Ptr{Void}, - (Int32, Ptr{Int32}, Int32, Ptr{Int32}, Ptr{$celty}, Ptr{$celty}, Int32, Uint32), - 0, C_NULL, 2, int32([n1,n2,1,n2,1,n1]), X, P, FORWARD, ESTIMATE | PRESERVE_INPUT) + (Int32, Ptr{Int}, Int32, Ptr{Int}, Ptr{$celty}, Ptr{$celty}, Int32, Uint32), + 0, C_NULL, 2, [n1,n2,1,n2,1,n1], X, P, FORWARD, ESTIMATE | PRESERVE_INPUT) execute($celty, plan) destroy_plan($celty, plan) return P diff --git a/base/file.jl b/base/file.jl index d60e17ec72291..1869e2952cc28 100644 --- a/base/file.jl +++ b/base/file.jl @@ -1,194 +1,71 @@ -# File and path name manipulation -# These do not examine the filesystem at all, they just work on strings -@unix_only begin - const os_separator = "/" - const os_separator_match = r"/+" - const os_separator_match_chars = "/" -end -@windows_only begin - const os_separator = "\\" - const os_separator_match = r"[/\\]" # permit either slash type on Windows - const os_separator_match_chars = "/\\" # to permit further concatenation -end -# Match only the final separator -const last_separator = Regex(strcat(os_separator_match.pattern, "(?!.*", os_separator_match.pattern, ")")) -# Match the "." indicating a file extension. Must satisfy the -# following requirements: -# - It's not followed by a later "." or os_separator -# (handles cases like myfile.txt.gz, or Mail.directory/cur) -# - It's not the first character in a string, nor is it preceded by -# an os_separator (handles cases like .bashrc or /home/fred/.juliarc) -const extension_separator_match = Regex(strcat(L"(?= length(temppath) || lentemppath == 0 + error("GetTempPath failed") + end + resize!(temppath,lentemppath) + return convert(ASCIIString,temppath) +end +GetTempFileName(uunique::Uint32) = GetTempFileName(GetTempPath(), uunique) +function GetTempFileName(temppath::String,uunique::Uint32) + tname = Array(Uint8,261) + uunique = ccall(:GetTempFileNameA,stdcall,Uint32,(Ptr{Uint8},Ptr{Uint8},Uint32,Ptr{Uint8}),temppath,"julia",uunique,tname) + lentname = findfirst(tname,0)-1 + if uunique == 0 || lentname <= 0 + error("GetTempFileName failed") + end + resize!(tname,lentname) + return convert(ASCIIString, tname) +end +function mktemp() + filename = GetTempFileName(uint32(0)) + return (filename, open(filename,"r+")) +end end # Create and return the name of a temporary directory @unix_only function mktempdir() - b = file_path(tempdir(), "tmpXXXXXX") - p = ccall(:mkdtemp, Ptr{Uint8}, (Ptr{Uint8}, ), b) - return bytestring(p) + b = joinpath(tempdir(), "tmpXXXXXX") + p = ccall(:mkdtemp, Ptr{Uint8}, (Ptr{Uint8}, ), b) + return bytestring(p) end @windows_only function mktempdir() - error("not yet implemented") + seed = rand(Uint32) + while true + filename = GetTempFileName(seed) + ret = ccall(:_mkdir, Int32, (Ptr{Uint8},), filename) + if ret == 0 + return filename + end + system_error(:mktempdir, errno()!=EEXIST) + seed += 1 + end end downloadcmd = nothing -function download_file(url::String, filename::String) +function download(url::String, filename::String) global downloadcmd if downloadcmd === nothing for checkcmd in (:curl, :wget, :fetch) - if system("which $checkcmd > /dev/null") == 0 + if success(`which $checkcmd` > SpawnNullStream()) downloadcmd = checkcmd break end @@ -271,7 +162,7 @@ function download_file(url::String, filename::String) if downloadcmd == :wget run(`wget -O $filename $url`) elseif downloadcmd == :curl - run(`curl -o $filename $url`) + run(`curl -o $filename -L $url`) elseif downloadcmd == :fetch run(`fetch -f $filename $url`) else @@ -279,40 +170,40 @@ function download_file(url::String, filename::String) end filename end -function download_file(url::String) - filename = tempname() - download_file(url, filename) +function download(url::String) + filename = tempname() + download(url, filename) end function readdir(path::String) - # Allocate space for uv_fs_t struct - uv_readdir_req = zeros(Uint8, ccall(:jl_sizeof_uv_fs_t, Int, ())) - - # defined in sys.c, to call uv_fs_readdir - file_count = ccall(:jl_readdir, Int, (Ptr{Uint8}, Ptr{Uint8}), - bytestring(path), uv_readdir_req) + # Allocate space for uv_fs_t struct + uv_readdir_req = zeros(Uint8, ccall(:jl_sizeof_uv_fs_t, Int32, ())) - if file_count < 0 - error("Unable to read directory $path.") - end + # defined in sys.c, to call uv_fs_readdir + file_count = ccall(:jl_readdir, Int32, (Ptr{Uint8}, Ptr{Uint8}), + bytestring(path), uv_readdir_req) - # The list of dir entries is returned as a contiguous sequence of null-terminated - # strings, the first of which is pointed to by ptr in uv_readdir_req. - # The following lines extracts those strings into dirent - entries = String[] - offset = 0 + if file_count < 0 + error("Unable to read directory $path.") + end - for i = 1:file_count - entry = bytestring(ccall(:jl_uv_fs_t_ptr_offset, Ptr{Uint8}, - (Ptr{Uint8}, Int), uv_readdir_req, offset)) - push(entries, entry) - offset += length(entry) + 1 # offset to the next entry - end + # The list of dir entries is returned as a contiguous sequence of null-terminated + # strings, the first of which is pointed to by ptr in uv_readdir_req. + # The following lines extracts those strings into dirent + entries = String[] + offset = 0 + + for i = 1:file_count + entry = bytestring(ccall(:jl_uv_fs_t_ptr_offset, Ptr{Uint8}, + (Ptr{Uint8}, Int), uv_readdir_req, offset)) + push!(entries, entry) + offset += length(entry) + 1 # offset to the next entry + end - # Clean up the request string - ccall(:jl_uv_fs_req_cleanup, Void, (Ptr{Uint8},), uv_readdir_req) + # Clean up the request string + ccall(:jl_uv_fs_req_cleanup, Void, (Ptr{Uint8},), uv_readdir_req) - entries + entries end readdir(cmd::Cmd) = readdir(string(cmd)[2:end-1]) diff --git a/base/float.jl b/base/float.jl index 928d81d52724f..535ceae7fc71d 100644 --- a/base/float.jl +++ b/base/float.jl @@ -6,10 +6,12 @@ convert(::Type{Float32}, x::Int8) = box(Float32,sitofp32(unbox(Int8,x))) convert(::Type{Float32}, x::Int16) = box(Float32,sitofp32(unbox(Int16,x))) convert(::Type{Float32}, x::Int32) = box(Float32,sitofp32(unbox(Int32,x))) convert(::Type{Float32}, x::Int64) = box(Float32,sitofp32(unbox(Int64,x))) +convert(::Type{Float32}, x::Int128) = float32(uint128(abs(x)))*(1-2(x<0)) convert(::Type{Float32}, x::Uint8) = box(Float32,uitofp32(unbox(Uint8,x))) convert(::Type{Float32}, x::Uint16) = box(Float32,uitofp32(unbox(Uint16,x))) convert(::Type{Float32}, x::Uint32) = box(Float32,uitofp32(unbox(Uint32,x))) convert(::Type{Float32}, x::Uint64) = box(Float32,uitofp32(unbox(Uint64,x))) +convert(::Type{Float32}, x::Uint128) = float32(uint64(x)) + ldexp(float32(uint64(x>>>64)),64) convert(::Type{Float32}, x::Float64) = box(Float32,fptrunc32(unbox(Float64,x))) convert(::Type{Float64}, x::Bool) = box(Float64,uitofp64(unbox(Bool,x))) @@ -18,22 +20,26 @@ convert(::Type{Float64}, x::Int8) = box(Float64,sitofp64(unbox(Int8,x))) convert(::Type{Float64}, x::Int16) = box(Float64,sitofp64(unbox(Int16,x))) convert(::Type{Float64}, x::Int32) = box(Float64,sitofp64(unbox(Int32,x))) convert(::Type{Float64}, x::Int64) = box(Float64,sitofp64(unbox(Int64,x))) +convert(::Type{Float64}, x::Int128) = float64(uint128(abs(x)))*(1-2(x<0)) convert(::Type{Float64}, x::Uint8) = box(Float64,uitofp64(unbox(Uint8,x))) convert(::Type{Float64}, x::Uint16) = box(Float64,uitofp64(unbox(Uint16,x))) convert(::Type{Float64}, x::Uint32) = box(Float64,uitofp64(unbox(Uint32,x))) convert(::Type{Float64}, x::Uint64) = box(Float64,uitofp64(unbox(Uint64,x))) +convert(::Type{Float64}, x::Uint128) = float64(uint64(x)) + ldexp(float64(uint64(x>>>64)),64) convert(::Type{Float64}, x::Float32) = box(Float64,fpext64(unbox(Float32,x))) -convert(::Type{FloatingPoint}, x::Bool) = convert(Float32, x) -convert(::Type{FloatingPoint}, x::Char) = convert(Float32, x) -convert(::Type{FloatingPoint}, x::Int8) = convert(Float32, x) -convert(::Type{FloatingPoint}, x::Int16) = convert(Float32, x) -convert(::Type{FloatingPoint}, x::Int32) = convert(Float64, x) -convert(::Type{FloatingPoint}, x::Int64) = convert(Float64, x) # LOSSY -convert(::Type{FloatingPoint}, x::Uint8) = convert(Float32, x) -convert(::Type{FloatingPoint}, x::Uint16) = convert(Float32, x) -convert(::Type{FloatingPoint}, x::Uint32) = convert(Float64, x) -convert(::Type{FloatingPoint}, x::Uint64) = convert(Float64, x) # LOSSY +convert(::Type{FloatingPoint}, x::Bool) = convert(Float32, x) +convert(::Type{FloatingPoint}, x::Char) = convert(Float32, x) +convert(::Type{FloatingPoint}, x::Int8) = convert(Float32, x) +convert(::Type{FloatingPoint}, x::Int16) = convert(Float32, x) +convert(::Type{FloatingPoint}, x::Int32) = convert(Float64, x) +convert(::Type{FloatingPoint}, x::Int64) = convert(Float64, x) # LOSSY +convert(::Type{FloatingPoint}, x::Int128) = convert(Float64, x) # LOSSY +convert(::Type{FloatingPoint}, x::Uint8) = convert(Float32, x) +convert(::Type{FloatingPoint}, x::Uint16) = convert(Float32, x) +convert(::Type{FloatingPoint}, x::Uint32) = convert(Float64, x) +convert(::Type{FloatingPoint}, x::Uint64) = convert(Float64, x) # LOSSY +convert(::Type{FloatingPoint}, x::Uint128) = convert(Float64, x) # LOSSY float32(x) = convert(Float32, x) float64(x) = convert(Float64, x) @@ -44,33 +50,39 @@ float(x) = convert(FloatingPoint, x) if WORD_SIZE == 64 iround(x::Float32) = iround(float64(x)) itrunc(x::Float32) = itrunc(float64(x)) + iround(x::Float64) = box(Int64,fpsiround64(unbox(Float64,x))) + itrunc(x::Float64) = box(Int64,fptosi64(unbox(Float64,x))) else iround(x::Float32) = box(Int32,fpsiround32(unbox(Float32,x))) itrunc(x::Float32) = box(Int32,fptosi32(unbox(Float32,x))) + iround(x::Float64) = int32(box(Int64,fpsiround64(unbox(Float64,x)))) + itrunc(x::Float64) = int32(box(Int64,fptosi64(unbox(Float64,x)))) end -iround(x::Float64) = box(Int64,fpsiround64(unbox(Float64,x))) -itrunc(x::Float64) = box(Int64,fptosi64(unbox(Float64,x))) - -iround(::Type{Int8}, x::Float32) = box(Int8,trunc8(fpsiround32(unbox(Float32,x)))) -iround(::Type{Int8}, x::Float64) = box(Int8,trunc8(fpsiround64(unbox(Float64,x)))) -iround(::Type{Uint8}, x::Float32) = box(Uint8,trunc8(fpuiround32(unbox(Float32,x)))) -iround(::Type{Uint8}, x::Float64) = box(Uint8,trunc8(fpuiround64(unbox(Float64,x)))) -iround(::Type{Int16}, x::Float32) = box(Int16,trunc16(fpsiround32(unbox(Float32,x)))) -iround(::Type{Int16}, x::Float64) = box(Int16,trunc16(fpsiround64(unbox(Float64,x)))) -iround(::Type{Uint16}, x::Float32) = box(Uint16,trunc16(fpuiround32(unbox(Float32,x)))) -iround(::Type{Uint16}, x::Float64) = box(Uint16,trunc16(fpuiround64(unbox(Float64,x)))) + +for to in (Int8, Uint8, Int16, Uint16) + @eval begin + iround(::Type{$to}, x::Float32) = box($to,trunc_int($to,fpsiround32(unbox(Float32,x)))) + iround(::Type{$to}, x::Float64) = box($to,trunc_int($to,fpsiround64(unbox(Float64,x)))) + end +end + iround(::Type{Int32}, x::Float32) = box(Int32,fpsiround32(unbox(Float32,x))) -iround(::Type{Int32}, x::Float64) = box(Int32,trunc32(fpsiround64(unbox(Float64,x)))) +iround(::Type{Int32}, x::Float64) = box(Int32,trunc_int(Int32,fpsiround64(unbox(Float64,x)))) iround(::Type{Uint32}, x::Float32) = box(Uint32,fpuiround32(unbox(Float32,x))) -iround(::Type{Uint32}, x::Float64) = box(Uint32,trunc32(fpuiround64(unbox(Float64,x)))) +iround(::Type{Uint32}, x::Float64) = box(Uint32,trunc_int(Uint32,fpuiround64(unbox(Float64,x)))) iround(::Type{Int64}, x::Float32) = box(Int64,fpsiround64(fpext64(unbox(Float32,x)))) iround(::Type{Int64}, x::Float64) = box(Int64,fpsiround64(unbox(Float64,x))) iround(::Type{Uint64}, x::Float32) = box(Uint64,fpuiround64(fpext64(unbox(Float32,x)))) iround(::Type{Uint64}, x::Float64) = box(Uint64,fpuiround64(unbox(Float64,x))) -# TODO: Int128 + +iround(::Type{Int128}, x::Float32) = convert(Int128,round(x)) +iround(::Type{Int128}, x::Float64) = convert(Int128,round(x)) +iround(::Type{Uint128}, x::Float32) = convert(Uint128,round(x)) +iround(::Type{Uint128}, x::Float64) = convert(Uint128,round(x)) # this is needed very early because it is used by Range and colon -floor(x::Float64) = ccall((:floor,:libopenlibm), Float64, (Float64,), x) +round(x::Float64) = ccall((:round, Base.libm_name), Float64, (Float64,), x) +floor(x::Float64) = ccall((:floor, Base.libm_name), Float64, (Float64,), x) iceil(x::FloatingPoint) = itrunc(ceil(x)) # TODO: fast primitive for iceil ifloor(x::FloatingPoint) = itrunc(floor(x)) # TOOD: fast primitive for ifloor diff --git a/base/floatfuncs.jl b/base/floatfuncs.jl index 0c6ac003f76af..6eb85d352fe7f 100644 --- a/base/floatfuncs.jl +++ b/base/floatfuncs.jl @@ -36,9 +36,9 @@ num2hex(x::Float64) = hex(box(Uint64,unbox(Float64,x)),16) function hex2num(s::String) if length(s) <= 8 - return box(Float32,unbox(Int32,parse_hex(Int32,s))) + return box(Float32,unbox(Int32,parseint(Int32,s,16))) end - return box(Float64,unbox(Int64,parse_hex(Int64,s))) + return box(Float64,unbox(Int64,parseint(Int64,s,16))) end @vectorize_1arg Real iround diff --git a/base/fs.jl b/base/fs.jl new file mode 100644 index 0000000000000..01e0eb14910b5 --- /dev/null +++ b/base/fs.jl @@ -0,0 +1,116 @@ +## UV based file operations ## + +module FS + +const S_IRUSR = 0o400 +const S_IWUSR = 0o200 +const S_IXUSR = 0o100 +const S_IRWXU = 0o700 +const S_IRGRP = 0o040 +const S_IWGRP = 0o020 +const S_IXGRP = 0o010 +const S_IRWXG = 0o070 +const S_IROTH = 0o004 +const S_IWOTH = 0o002 +const S_IXOTH = 0o001 +const S_IRWXO = 0o007 + +export File, + # open, + # close, + # write, + unlink, + JL_O_WRONLY, + JL_O_RDONLY, + JL_O_RDWR, + JL_O_APPEND, + JL_O_CREAT, + JL_O_EXCL, + JL_O_TRUNC, + JL_O_TEMPORARY, + JL_O_SHORT_LIVED, + JL_O_SEQUENTIAL, + JL_O_RANDOM, + S_IRUSR, S_IWUSR, S_IXUSR, S_IRWXU, + S_IRGRP, S_IWGRP, S_IXGRP, S_IRWXG, + S_IROTH, S_IWOTH, S_IXOTH, S_IRWXO + +#import Base.show, Base.open, Base.close, Base.write +import Base.uvtype, Base.uvhandle, Base.eventloop + +include("file_constants.jl") + +abstract AbstractFile <: IO + +const _sizeof_uv_fs_t = ccall(:jl_sizeof_uv_fs_t,Int32,()) + +type File <: AbstractFile + path::String + open::Bool + handle::Int32 + File(path::String) = new(path,false,-1) +end + +type AsyncFile <: AbstractFile + path::String + open::Bool +end + +uvtype(::File) = Base.UV_RAW_FD +uvhandle(file::File) = file.handle + +_uv_fs_result(req) = ccall(:jl_uv_fs_result,Int32,(Ptr{Void},),req) + +function open(f::File,flags::Integer,mode::Integer) + req = Base.Intrinsics.box(Ptr{Void},Intrinsics.jl_alloca(Base.Intrinsics.unbox(Int32,_sizeof_uv_fs_t))) + ret = ccall(:uv_fs_open,Int32,(Ptr{Void},Ptr{Void},Ptr{Uint8},Int32,Int32,Ptr{Void}), + eventloop(),req,bytestring(f.path),flags,mode,C_NULL) + uv_error(:open,ret==-1) + f.handle = _uv_fs_result(req) + f.open = true + ccall(:uv_fs_req_cleanup,Void,(Ptr{Void},),req) + f +end +open(f::String,flags,mode) = open(File(f),flags,mode) +open(f::String,flags) = open(f,flags,0) + +function close(f::File) + if(!f.open) + error("File is already closed") + end + req = Intrinsics.box(Ptr{Void},Intrinsics.jl_alloca(Intrinsics.unbox(Int32,_sizeof_uv_fs_t))) + err = ccall(:uv_fs_close,Int32,(Ptr{Void},Ptr{Void},Int32,Ptr{Void}), + eventloop(),req,f.handle,C_NULL) + uv_error(err) + f.handle = -1 + f.open = false + ccall(:uv_fs_req_cleanup,Void,(Ptr{Void},),req) + f +end + +function unlink(p::String) + req = box(Ptr{Void},Intrinsics.jl_alloca(unbox(Int32,_sizeof_uv_fs_t))) + err = ccall(:uv_fs_unlink,Int32,(Ptr{Void},Ptr{Void},Ptr{Uint8},Ptr{Void}), + eventloop(),req,bytestring(p),C_NULL) + uv_error(err) +end +function unlink(f::File) + if(f.open) + close(f) + end + unlink(f.path) + f +end + +function write(f::File,buf::Ptr{Uint8},len::Int32,offset::Int64) + if(!f.open) + error("File is not open") + end + req = box(Ptr{Void},Intrinsics.jl_alloca(unbox(Int32,_sizeof_uv_fs_t))) + err = ccall(:uv_fs_close,Int32,(Ptr{Void},Ptr{Void},Int32,Ptr{Uint8},Int32,Int64,Ptr{Void}), + eventloop(),req,f.handle,buf,len,offset,C_NULL) + uv_error(err) + f +end + +end diff --git a/base/git.jl b/base/git.jl index d671bc7327fd2..4ea318e36ff7f 100644 --- a/base/git.jl +++ b/base/git.jl @@ -15,12 +15,49 @@ dirty(paths) = !success(`git diff --quiet HEAD -- $paths`) staged(paths) = !success(`git diff --quiet --cached -- $paths`) unstaged(paths) = !success(`git diff --quiet -- $paths`) -attached() = success(`git symbolic-ref -q HEAD` > "/dev/null") +attached() = success(`git symbolic-ref -q HEAD` > SpawnNullStream()) branch() = readchomp(`git rev-parse --symbolic-full-name --abbrev-ref HEAD`) +head() = readchomp(`git rev-parse HEAD`) + +immutable State + head::ASCIIString + index::ASCIIString + work::ASCIIString +end + +function snapshot() + head = readchomp(`git rev-parse HEAD`) + index = readchomp(`git write-tree`) + work = try + run(`git add --all`) + run(`git add .`) + readchomp(`git write-tree`) + finally + run(`git read-tree $index`) # restore index + end + State(head, index, work) +end + +function restore(s::State) + run(`git reset -q --`) # unstage everything + run(`git read-tree $(s.work)`) # move work tree to index + run(`git checkout-index -fa`) # check the index out to work + run(`git clean -qdf`) # remove everything else + run(`git read-tree $(s.index)`) # restore index + run(`git reset -q --soft $(s.head)`) # restore head +end + +function transact(f::Function) + state = snapshot() + try f() catch + restore(state) + rethrow() + end +end function each_tagged_version() - git_dir = abs_path(dir()) - @task for line in each_line(`git --git-dir=$git_dir show-ref --tags`) + git_dir = abspath(dir()) + @task for line in eachline(`git --git-dir=$git_dir show-ref --tags`) m = match(r"^([0-9a-f]{40}) refs/tags/(v\S+)$", line) if m != nothing && ismatch(Base.VERSION_REGEX, m.captures[2]) produce((convert(VersionNumber,m.captures[2]),m.captures[1])) @@ -31,7 +68,7 @@ each_tagged_version(dir::String) = cd(each_tagged_version,dir) function each_submodule(f::Function, recursive::Bool, dir::ByteString) cmd = `git submodule foreach --quiet 'echo "$name $path $sha1"'` - for line in each_line(cmd) + for line in eachline(cmd) name, path, sha1 = match(r"^(.*) (.*) ([0-9a-f]{40})$", line).captures cd(dir) do f(name, path, sha1) @@ -47,12 +84,12 @@ function each_submodule(f::Function, recursive::Bool, dir::ByteString) end end end -each_submodule(f::Function, r::Bool) = each_submodule(f, r, cwd()) +each_submodule(f::Function, r::Bool) = each_submodule(f, r, pwd()) function read_config(file::String) cfg = Dict() # TODO: use --null option for better handling of weird values. - for line in each_line(`git config -f $file --get-regexp '.*'`) + for line in eachline(`git config -f $file --get-regexp '.*'`) key, val = match(r"^(\S+)\s+(.*)$", line).captures cfg[key] = has(cfg,key) ? [cfg[key],val] : val end @@ -61,9 +98,11 @@ end # TODO: provide a clean way to avoid this disaster function read_config_blob(blob::String) - tmp = tmpnam() - open(tmp,"w") do io + tmp, io = mktemp() + try write(io, readall(`git cat-file blob $blob`)) + finally + close(io) end cfg = read_config(tmp) run(`rm -f tmp`) @@ -71,7 +110,7 @@ function read_config_blob(blob::String) end function write_config(file::String, cfg::Dict) - tmp = tmpnam() + tmp = tempname() for key in sort!(keys(cfg)) val = cfg[key] if isa(val,Array) @@ -82,8 +121,10 @@ function write_config(file::String, cfg::Dict) run(`git config -f $tmp $key $val`) end end - open(file,"w") do io - print(io,readall(tmp)) + if isfile(tmp) + open(file,"w") do io + print(io,readall(tmp)) + end end end @@ -93,7 +134,7 @@ function config_sections(cfg::Dict) sections = Set{ByteString}() for (key,_) in cfg m = match(r"^(.+)\.", key) - if m != nothing add(sections,m.captures[1]) end + if m != nothing add!(sections,m.captures[1]) end end sections end @@ -106,9 +147,9 @@ function merge_configs(Bc::Dict, Lc::Dict, Rc::Dict) # expunge removed submodules from left and right sides deleted = Set{ByteString}() for section in Bs - Ls & Rs - filter!((k,v)->!begins_with(k,"$section."),Lc) - filter!((k,v)->!begins_with(k,"$section."),Rc) - add(deleted, section) + filter!((k,v)->!beginswith(k,"$section."),Lc) + filter!((k,v)->!beginswith(k,"$section."),Rc) + add!(deleted, section) end # merge the remaining config key-value pairs cfg = Dict() diff --git a/base/gmp.jl b/base/gmp.jl new file mode 100644 index 0000000000000..f0dae0bc6429b --- /dev/null +++ b/base/gmp.jl @@ -0,0 +1,49 @@ +module GMP + +export BigInt, BigFloat + +import + Base.(*), + Base.+, + Base.-, + Base./, + Base.<, + Base.<<, + Base.>>, + Base.<=, + Base.==, + Base.>, + Base.>=, + Base.^, + Base.(~), + Base.(&), + Base.(|), + Base.($), + Base.binomial, + Base.ceil, + Base.cmp, + Base.complex, + Base.convert, + Base.div, + Base.factorial, + Base.fld, + Base.floor, + Base.gcd, + Base.gcdx, + Base.isinf, + Base.isnan, + Base.lcm, + Base.mod, + Base.ndigits, + Base.promote_rule, + Base.rem, + Base.show, + Base.showcompact, + Base.sqrt, + Base.string, + Base.trunc + +include("bigint.jl") +include("bigfloat.jl") + +end # module diff --git a/base/grisu.jl b/base/grisu.jl index 1ff47b55eb90b..d3de6ae6eca02 100644 --- a/base/grisu.jl +++ b/base/grisu.jl @@ -46,12 +46,16 @@ function grisu_sig(x::Real, n::Integer) grisu(float64(x), PRECISION, int32(n)) end -function _show(io, x::FloatingPoint, mode::Int32, n::Int) - if isnan(x); return write(io, isa(x,Float32) ? "NaN32" : "NaN"); end - if x < 0 write(io,'-') end - if isinf(x); return write(io, isa(x,Float32) ? "Inf32" : "Inf"); end +function _show(io::IO, x::FloatingPoint, mode::Int32, n::Int) + if isnan(x) return write(io, isa(x,Float32) ? "NaN32" : "NaN") end + if isinf(x) + if x < 0 write(io,'-') end + write(io, isa(x,Float32) ? "Inf32" : "Inf") + return + end @grisu_ccall x mode n pdigits = pointer(DIGITS) + neg = NEG[1] len = LEN[1] pt = POINT[1] if mode == PRECISION @@ -59,6 +63,7 @@ function _show(io, x::FloatingPoint, mode::Int32, n::Int) len -= 1 end end + if neg write(io,'-') end if pt <= -4 || pt > 6 # .00001 to 100000. # => #.#######e### write(io, pdigits, 1) @@ -96,9 +101,9 @@ function _show(io, x::FloatingPoint, mode::Int32, n::Int) nothing end -show(io, x::Float64) = _show(io, x, SHORTEST, 0) -show(io, x::Float32) = _show(io, x, SHORTEST_SINGLE, 0) -showcompact(io, x::FloatingPoint) = _show(io, x, PRECISION, 6) +show(io::IO, x::Float64) = _show(io, x, SHORTEST, 0) +show(io::IO, x::Float32) = _show(io, x, SHORTEST_SINGLE, 0) +showcompact(io::IO, x::FloatingPoint) = _show(io, x, PRECISION, 6) # normal: # 0 < pt < len ####.#### len+1 @@ -109,7 +114,7 @@ showcompact(io, x::FloatingPoint) = _show(io, x, PRECISION, 6) # pt <= 0 ########e-### len+k+2 # 0 < pt ########e### len+k+1 -function _print_shortest(io, x::FloatingPoint, dot::Bool, mode::Int32) +function _print_shortest(io::IO, x::FloatingPoint, dot::Bool, mode::Int32) if isnan(x); return write(io, isa(x,Float32) ? "NaN32" : "NaN"); end if x < 0 write(io,'-') end if isinf(x); return write(io, isa(x,Float32) ? "Inf32" : "Inf"); end @@ -152,8 +157,8 @@ function _print_shortest(io, x::FloatingPoint, dot::Bool, mode::Int32) nothing end -print_shortest(io, x::Float64, dot::Bool) = _print_shortest(io, x, dot, SHORTEST) -print_shortest(io, x::Float32, dot::Bool) = _print_shortest(io, x, dot, SHORTEST_SINGLE) -print_shortest(io, x::Union(FloatingPoint,Integer)) = print_shortest(io, float(x), false) +print_shortest(io::IO, x::Float64, dot::Bool) = _print_shortest(io, x, dot, SHORTEST) +print_shortest(io::IO, x::Float32, dot::Bool) = _print_shortest(io, x, dot, SHORTEST_SINGLE) +print_shortest(io::IO, x::Union(FloatingPoint,Integer)) = print_shortest(io, float(x), false) end # module diff --git a/base/help.jl b/base/help.jl new file mode 100644 index 0000000000000..09f070704cdc3 --- /dev/null +++ b/base/help.jl @@ -0,0 +1,207 @@ +module Help + +export help, apropos + +CATEGORY_LIST = nothing +CATEGORY_DICT = nothing +MODULE_DICT = nothing +FUNCTION_DICT = nothing + +function clear_cache() + global CATEGORY_LIST = nothing + global CATEGORY_DICT = nothing + global MODULE_DICT = nothing + global FUNCTION_DICT = nothing +end + +function decor_help_desc(func::String, mfunc::String, desc::String) + sd = split(desc, '\n') + for i = 1:length(sd) + if beginswith(sd[i], func) + sd[i] = mfunc * sd[i][length(func)+1:end] + else + break + end + end + return join(sd, '\n') +end + +function helpdb_filename() + root = "$JULIA_HOME/../share/julia" + file = "helpdb.jl" + for loc in [Base.locale()] + fn = joinpath(root, loc, file) + if isfile(fn) + return fn + end + end + joinpath(root, file) +end + +function init_help() + global CATEGORY_LIST, CATEGORY_DICT, + MODULE_DICT, FUNCTION_DICT + if CATEGORY_DICT == nothing + println("Loading help data...") + helpdb = evalfile(helpdb_filename()) + CATEGORY_LIST = {} + CATEGORY_DICT = Dict() + MODULE_DICT = Dict() + FUNCTION_DICT = Dict() + for (cat,mod,func,desc) in helpdb + if !has(CATEGORY_DICT, cat) + push!(CATEGORY_LIST, cat) + CATEGORY_DICT[cat] = {} + end + if !isempty(mod) + if beginswith(func, '@') + mfunc = "@" * mod * "." * func[2:] + else + mfunc = mod * "." * func + end + desc = decor_help_desc(func, mfunc, desc) + else + mfunc = func + end + push!(CATEGORY_DICT[cat], mfunc) + if !has(FUNCTION_DICT, mfunc) + FUNCTION_DICT[mfunc] = {} + end + push!(FUNCTION_DICT[mfunc], desc) + if !has(MODULE_DICT, func) + MODULE_DICT[func] = {} + end + if !contains(MODULE_DICT[func], mod) + push!(MODULE_DICT[func], mod) + end + end + end +end + +function help() + init_help() + print( +""" + + Welcome to Julia. The full manual is available at + + http://docs.julialang.org + + To get help, try help(function), help("@macro"), or help("variable"). + To search all help text, try apropos("string"). To see available functions, + try help(category), for one of the following categories: + +""") + for cat = CATEGORY_LIST + if !isempty(CATEGORY_DICT[cat]) + print(" ") + show(cat); println() + end + end +end + +function help(cat::String) + init_help() + if !has(CATEGORY_DICT, cat) + # if it's not a category, try another named thing + return help_for(cat) + end + println("Help is available for the following items:") + for func = CATEGORY_DICT[cat] + print(func, " ") + end + println() +end + +function print_help_entries(entries) + first = true + for desc in entries + if !first + println() + end + println(strip(desc)) + first = false + end +end + +help_for(s::String) = help_for(s, 0) +function help_for(fname::String, obj) + init_help() + found = false + if has(FUNCTION_DICT, fname) + print_help_entries(FUNCTION_DICT[fname]) + found = true + else + macrocall = "" + if beginswith(fname, '@') + sfname = fname[2:] + macrocall = "@" + else + sfname = fname + end + if has(MODULE_DICT, fname) + allmods = MODULE_DICT[fname] + alldesc = {} + for mod in allmods + mod_prefix = isempty(mod) ? "" : mod * "." + append!(alldesc, FUNCTION_DICT[macrocall * mod_prefix * sfname]) + end + print_help_entries(alldesc) + found = true + end + end + if !found + if isgeneric(obj) + repl_show(obj); println() + else + println("No help information found.") + end + end +end + +function apropos(txt::String) + init_help() + n = 0 + r = Regex("\\Q$txt", PCRE.CASELESS) + for (cat, _) in CATEGORY_DICT + if ismatch(r, cat) + println("Category: \"$cat\"") + end + end + for (func, entries) in FUNCTION_DICT + if ismatch(r, func) || any(e->ismatch(r,e), entries) + for desc in entries + nl = search(desc,'\n') + if nl != 0 + println(desc[1:(nl-1)]) + else + println(desc) + end + end + n+=1 + end + end + if n == 0 + println("No help information found.") + end +end + +function help(f::Function) + if is(f,help) + return help() + end + help_for(string(f), f) +end + +help(t::DataType) = help_for(string(t.name),t) + +function help(x) + show(x) + t = typeof(x) + println(" is of type $t") + if isa(t,DataType) && length(t.names)>0 + println(" which has fields $(t.names)") + end +end + +end # module diff --git a/base/i18n.jl b/base/i18n.jl new file mode 100644 index 0000000000000..8b9cf7e2e49c0 --- /dev/null +++ b/base/i18n.jl @@ -0,0 +1,24 @@ +module I18n + +export locale + +LOCALE = nothing +CALLBACKS = Function[] + +function locale() + if LOCALE === nothing + # XXX:TBD return default locale + return "" + end + LOCALE +end + +function locale(s::ByteString) + global LOCALE = s + # XXX:TBD call setlocale + for cb in CALLBACKS + cb() + end +end + +end # module diff --git a/base/inference.jl b/base/inference.jl index ebb57333662b8..22ed71f6ae55a 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -1,6 +1,6 @@ # parameters limiting potentially-infinite types -const MAX_TYPEUNION_LEN = 2 -const MAX_TYPE_DEPTH = 2 +const MAX_TYPEUNION_LEN = 3 +const MAX_TYPE_DEPTH = 4 const MAX_TUPLETYPE_LEN = 8 const MAX_TUPLE_DEPTH = 4 @@ -42,21 +42,29 @@ function is_static_parameter(sv::StaticVarInfo, s::Symbol) return false end +function contains_is(itr, x::ANY) + for y in itr + if is(y,x) + return true + end + end + return false +end + is_local(sv::StaticVarInfo, s::Symbol) = contains_is(sv.vars, s) is_closed(sv::StaticVarInfo, s::Symbol) = has(sv.cenv, s) is_global(sv::StaticVarInfo, s::Symbol) = !is_local(sv,s) && !is_closed(sv,s) && !is_static_parameter(sv,s) -tintersect(a::ANY,b::ANY) = ccall(:jl_type_intersection, Any, (Any,Any), a, b) +typeintersect(a::ANY,b::ANY) = ccall(:jl_type_intersection, Any, (Any,Any), a, b) -methods(f::Union(Function,CompositeKind),t) = methods(f,t,-1)::Array{Any,1} -methods(f::Union(Function,CompositeKind),t,lim) = ccall(:jl_matching_methods, Any, (Any,Any,Int32), f, t, lim) +methods(f::ANY,t::ANY) = _methods(f,t,-1)::Array{Any,1} +_methods(f::ANY,t::ANY,lim) = ccall(:jl_matching_methods, Any, (Any,Any,Int32), f, t, lim) -typeseq(a,b) = subtype(a,b)&&subtype(b,a) +typeseq(a::ANY,b::ANY) = subtype(a,b)&&subtype(b,a) -isbuiltin(f) = ccall(:jl_is_builtin, Int32, (Any,), f) != 0 -isgeneric(f) = (isa(f,Function)||isa(f,CompositeKind)) && isa(f.env,MethodTable) -isleaftype(t) = ccall(:jl_is_leaf_type, Int32, (Any,), t) != 0 +isgeneric(f::ANY) = (isa(f,Function)||isa(f,DataType)) && isa(f.env,MethodTable) +isleaftype(t::ANY) = ccall(:jl_is_leaf_type, Int32, (Any,), t) != 0 isconst(s::Symbol) = ccall(:jl_is_const, Int32, (Ptr{Void}, Any), C_NULL, s) != 0 @@ -69,13 +77,13 @@ function _iisconst(s::Symbol) isdefined(m,s) && (ccall(:jl_is_const, Int32, (Any, Any), m, s) != 0) end -_ieval(x) = eval((inference_stack::CallStack).mod, x) -_iisdefined(x) = isdefined((inference_stack::CallStack).mod, x) +_ieval(x::ANY) = eval((inference_stack::CallStack).mod, x) +_iisdefined(x::ANY) = isdefined((inference_stack::CallStack).mod, x) _iisconst(s::SymbolNode) = _iisconst(s.name) _iisconst(s::TopNode) = isconst(_basemod(), s.name) _iisconst(x::Expr) = false -_iisconst(x) = true +_iisconst(x::ANY) = true function _basemod() m = (inference_stack::CallStack).mod @@ -87,9 +95,9 @@ end cmp_tfunc = (x,y)->Bool -isType(t::ANY) = isa(t,AbstractKind) && is((t::AbstractKind).name,Type.name) +isType(t::ANY) = isa(t,DataType) && is((t::DataType).name,Type.name) -isseqtype(t::ANY) = isa(t,AbstractKind) && is((t::AbstractKind).name.name,:...) +isvarargtype(t::ANY) = isa(t,DataType)&&is((t::DataType).name,Vararg.name) const t_func = ObjectIdDict() #t_func[tuple] = (0, Inf, (args...)->limit_tuple_depth(args)) @@ -119,6 +127,7 @@ t_func[fpiseq32] = (2, 2, cmp_tfunc) t_func[fpiseq64] = (2, 2, cmp_tfunc) t_func[fpislt32] = (2, 2, cmp_tfunc) t_func[fpislt64] = (2, 2, cmp_tfunc) +t_func[nan_dom_err] = (2, 2, (a, b)->a) t_func[eval(Core,:ccall)] = (3, Inf, (fptr, rt, at, a...)->(is(rt,Type{Void}) ? Nothing : isType(rt) ? rt.parameters[1] : Any)) @@ -127,7 +136,7 @@ t_func[subtype] = (2, 2, cmp_tfunc) t_func[isa] = (2, 2, cmp_tfunc) t_func[isdefined] = (1, 2, (args...)->Bool) t_func[Union] = (0, Inf, - (args...)->(if allp(isType,args) + (args...)->(if all(isType,args) Type{Union(map(t->t.parameters[1],args)...)} else Type @@ -136,27 +145,31 @@ t_func[method_exists] = (2, 2, cmp_tfunc) t_func[applicable] = (1, Inf, (f, args...)->Bool) t_func[tuplelen] = (1, 1, x->Int) t_func[arraylen] = (1, 1, x->Int) -#t_func[arrayref] = (2,Inf,(a,i...)->(isa(a,CompositeKind) && subtype(a,Array) ? +#t_func[arrayref] = (2,Inf,(a,i...)->(isa(a,DataType) && subtype(a,Array) ? # a.parameters[1] : Any)) #t_func[arrayset] = (3, Inf, (a,v,i...)->a) arraysize_tfunc(a, d) = Int function arraysize_tfunc(a) - if isa(a,CompositeKind) && subtype(a,Array) - return NTuple{a.parameters[2],Int} + if isa(a,DataType) && subtype(a,Array) + N = a.parameters[2] + return isa(N,Int) ? NTuple{N,Int} : (Int...) else - return NTuple{Array.parameters[2],Int} + return (Int...) end end t_func[arraysize] = (1, 2, arraysize_tfunc) -t_func[pointerref] = (2,2,(a,i)->(subtype(a,Ptr) ? a.parameters[1] : Any)) +t_func[pointerref] = (2,2,(a,i)->(isa(a,DataType)&&subtype(a,Ptr) ? a.parameters[1] : Any)) t_func[pointerset] = (3, 3, (a,v,i)->a) function static_convert(to::ANY, from::ANY) if !isa(to,Tuple) || !isa(from,Tuple) + if isa(to,TypeVar) + return to + end if subtype(from, to) return from end - t = tintersect(from,to) + t = typeintersect(from,to) return is(t,None) ? to : t end if is(to,Tuple) @@ -170,19 +183,22 @@ function static_convert(to::ANY, from::ANY) if pseq elseif i <= pl pe = to[i] - if isseqtype(pe) + if isvarargtype(pe) pe = pe.parameters[1] pseq = true + elseif isa(pe,TypeVar) && isvarargtype(pe.ub) + pe = pe.ub.parameters[1] + pseq = true end else return None end # tuple conversion calls convert recursively - if isseqtype(ce) + if isvarargtype(ce) R = abstract_call_gf(convert, (), (Type{pe}, ce.parameters[1]), ()) #R = static_convert(pe, ce.parameters[1]) isType(R) && (R = R.parameters[1]) - result[i] = ...{R} + result[i] = Vararg{R} else R = abstract_call_gf(convert, (), (Type{pe}, ce), ()) #R = static_convert(pe, ce) @@ -195,7 +211,7 @@ end t_func[convert_default] = (3, 3, (t,x,f)->(isType(t) ? static_convert(t.parameters[1],x) : Any)) t_func[convert_tuple] = - (3, 3, (t,x,f)->(if isa(t,Tuple) && allp(isType,t) + (3, 3, (t,x,f)->(if isa(t,Tuple) && all(isType,t) t = Type{map(t->t.parameters[1],t)} end; isType(t) ? static_convert(t.parameters[1],x) : @@ -208,13 +224,13 @@ const typeof_tfunc = function (t) else Type{typeof(t)} end - elseif isa(t,AbstractKind) || isa(t,CompositeKind) || isa(t,BitsKind) + elseif isa(t,DataType) if isleaftype(t) Type{t} else Type{TypeVar(:_,t)} end - elseif isa(t,UnionKind) + elseif isa(t,UnionType) Union(map(typeof_tfunc, t.types)...) elseif isa(t,Tuple) map(typeof_tfunc, t) @@ -228,16 +244,16 @@ t_func[typeof] = (1, 1, typeof_tfunc) # involving constants: typeassert, tupleref, getfield, fieldtype, apply_type # therefore they get their arguments unevaluated t_func[typeassert] = - (2, 2, (A, v, t)->(isType(t) ? tintersect(v,t.parameters[1]) : - isa(t,Tuple) && allp(isType,t) ? - tintersect(v,map(t->t.parameters[1],t)) : + (2, 2, (A, v, t)->(isType(t) ? typeintersect(v,t.parameters[1]) : + isa(t,Tuple) && all(isType,t) ? + typeintersect(v,map(t->t.parameters[1],t)) : Any)) const tupleref_tfunc = function (A, t, i) if is(t,()) return None end - if isa(t,AbstractKind) && is(t.name,NTuple.name) + if isa(t,DataType) && is(t.name,NTuple.name) return t.parameters[2] end if !isa(t,Tuple) @@ -245,7 +261,7 @@ const tupleref_tfunc = function (A, t, i) end n = length(t) last = tupleref(t,n) - vararg = isseqtype(last) + vararg = isvarargtype(last) if isa(A[2],Integer) # index is a constant i = A[2] @@ -279,7 +295,7 @@ const getfield_tfunc = function (A, s, name) return Any end end - if !isa(s,CompositeKind) + if !isa(s,DataType) || s.abstract return Any end if isa(A[2],QuoteNode) && isa(A[2].value,Symbol) @@ -304,7 +320,7 @@ end t_func[getfield] = (2, 2, getfield_tfunc) t_func[setfield] = (3, 3, (o, f, v)->v) const fieldtype_tfunc = function (A, s, name) - if !isa(s,CompositeKind) + if !isa(s,DataType) return Type end t = getfield_tfunc(A, s, name) @@ -314,7 +330,6 @@ const fieldtype_tfunc = function (A, s, name) Type{t} end t_func[fieldtype] = (2, 2, fieldtype_tfunc) -t_func[Expr] = (3, 3, (a,b,c)->Expr) t_func[Box] = (1, 1, (a,)->Box) # TODO: handle e.g. apply_type(T, R::Union(Type{Int32},Type{Float64})) @@ -323,7 +338,7 @@ const apply_type_tfunc = function (A, args...) return Any end headtype = args[1].parameters[1] - if isa(headtype,UnionKind) || isa(headtype,Tuple) + if isa(headtype,UnionType) || isa(headtype,Tuple) return args[1] end tparams = () @@ -348,6 +363,9 @@ const apply_type_tfunc = function (A, args...) appl = args[1] uncertain = true end + if type_too_complex(appl,0) + return args[1] + end uncertain ? Type{TypeVar(:_,appl)} : Type{appl} end t_func[apply_type] = (1, Inf, apply_type_tfunc) @@ -357,25 +375,28 @@ t_func[apply_type] = (1, Inf, apply_type_tfunc) function builtin_tfunction(f::ANY, args::ANY, argtypes::ANY) if is(f,tuple) return limit_tuple_depth(argtypes) - end - if is(f,arrayset) + elseif is(f,arrayset) if length(argtypes) < 3 return None end return argtypes[1] - end - if is(f,arrayref) + elseif is(f,arrayref) if length(argtypes) < 2 return None end a = argtypes[1] - return (isa(a,CompositeKind) && subtype(a,Array) ? + return (isa(a,DataType) && subtype(a,Array) ? a.parameters[1] : Any) + elseif is(f,Expr) + if length(argtypes) < 1 + return None + end + return Expr end tf = get(t_func::ObjectIdDict, f, false) if is(tf,false) # struct constructor - if isa(f, CompositeKind) + if isstructtype(f) return f end # unknown/unhandled builtin @@ -403,7 +424,7 @@ function a2t(a::AbstractVector) return tuple(a...) end -function isconstantfunc(f, sv::StaticVarInfo) +function isconstantfunc(f::ANY, sv::StaticVarInfo) if isa(f,TopNode) m = _basemod() return isconst(m, f.name) && isdefined(m, f.name) && f @@ -440,12 +461,12 @@ end const isconstantref = isconstantfunc -isvatuple(t::Tuple) = (n = length(t); n > 0 && isseqtype(t[n])) +isvatuple(t::Tuple) = (n = length(t); n > 0 && isvarargtype(t[n])) const limit_tuple_depth = t->limit_tuple_depth_(t,0) const limit_tuple_depth_ = function (t,d::Int) - if isa(t,UnionKind) + if isa(t,UnionType) # also limit within Union types. # may have to recur into other stuff in the future too. return Union(limit_tuple_depth_(t.types,d)...) @@ -463,12 +484,12 @@ const limit_tuple_type = function (t::Tuple) n = length(t) if n > MAX_TUPLETYPE_LEN last = t[n] - if isseqtype(last) + if isvarargtype(last) last = last.parameters[1] end tail = tuple(t[MAX_TUPLETYPE_LEN:(n-1)]..., last) - tail = tintersect(reduce(tmerge, None, tail), Any) - return tuple(t[1:(MAX_TUPLETYPE_LEN-1)]..., ...{tail}) + tail = typeintersect(reduce(tmerge, None, tail), Any) + return tuple(t[1:(MAX_TUPLETYPE_LEN-1)]..., Vararg{tail}) end return t end @@ -477,7 +498,7 @@ function abstract_call_gf(f, fargs, argtypes, e) if length(argtypes)>1 && isa(argtypes[1],Tuple) && argtypes[2]===Int # allow tuple indexing functions to take advantage of constant # index arguments. - if f === Main.Base.ref + if f === Main.Base.getindex e.head = :call1 return tupleref_tfunc(fargs, argtypes[1], argtypes[2]) elseif f === Main.Base.next @@ -488,6 +509,19 @@ function abstract_call_gf(f, fargs, argtypes, e) return (tupleref_tfunc(fargs, argtypes[1], argtypes[2]), Int) end end + if f === Main.Base.promote_type || f === Main.Base.typejoin + la = length(argtypes) + c = cell(la) + for i = 1:la + t = argtypes[i] + if isType(t) && !isa(t.parameters[1],TypeVar) + c[i] = t.parameters[1] + else + return Type + end + end + return Type{f(c...)} + end # don't consider more than N methods. this trades off between # compiler performance and generated code performance. # typically, considering many methods means spending lots of time @@ -496,7 +530,7 @@ function abstract_call_gf(f, fargs, argtypes, e) # function, so we can still know that error() is always None. # here I picked 4. argtypes = limit_tuple_type(argtypes) - applicable = methods(f, argtypes, 4) + applicable = _methods(f, argtypes, 4) rettype = None if is(applicable,false) # this means too many methods matched @@ -537,7 +571,7 @@ function abstract_call_gf(f, fargs, argtypes, e) end function invoke_tfunc(f, types, argtypes) - argtypes = tintersect(types,limit_tuple_type(argtypes)) + argtypes = typeintersect(types,limit_tuple_type(argtypes)) if is(argtypes,None) return None end @@ -558,92 +592,98 @@ function invoke_tfunc(f, types, argtypes) end function abstract_call(f, fargs, argtypes, vtypes, sv::StaticVarInfo, e) - if isbuiltin(f) - if is(f,apply) && length(fargs)>0 + if is(f,apply) && length(fargs)>0 + if isType(argtypes[1]) && isleaftype(argtypes[1].parameters[1]) + af = argtypes[1].parameters[1] + else af = isconstantfunc(fargs[1], sv) - if !is(af,false) - aargtypes = argtypes[2:] - if allp(x->isa(x,Tuple), aargtypes) && - !anyp(isvatuple, aargtypes[1:(length(aargtypes)-1)]) - e.head = :call1 - # apply with known func with known tuple types - # can be collapsed to a call to the applied func - at = length(aargtypes) > 0 ? - limit_tuple_type(apply(tuple,aargtypes...)) : () - return abstract_call(_ieval(af), (), at, vtypes, sv, ()) - end - af = _ieval(af) - if is(af,tuple) && length(fargs)==2 - # tuple(xs...) - aat = aargtypes[1] - if aat <: AbstractArray - # tuple(array...) - # TODO: > 1 array of the same type - tn = AbstractArray.name - while isa(aat, AbstractKind) || isa(aat, BitsKind) || - isa(aat, CompositeKind) - if is(aat.name, tn) - et = aat.parameters[1] - if !isa(et,TypeVar) - return (et...) - end - end - if is(aat, Any) - break + end + if !is(af,false) + aargtypes = argtypes[2:] + if all(x->isa(x,Tuple), aargtypes) && + !any(isvatuple, aargtypes[1:(length(aargtypes)-1)]) + e.head = :call1 + # apply with known func with known tuple types + # can be collapsed to a call to the applied func + at = length(aargtypes) > 0 ? + limit_tuple_type(apply(tuple,aargtypes...)) : () + return abstract_call(_ieval(af), (), at, vtypes, sv, ()) + end + af = _ieval(af) + if is(af,tuple) && length(fargs)==2 + # tuple(xs...) + aat = aargtypes[1] + if aat <: AbstractArray + # tuple(array...) + # TODO: > 1 array of the same type + tn = AbstractArray.name + while isa(aat, DataType) + if is(aat.name, tn) + et = aat.parameters[1] + if !isa(et,TypeVar) + return (et...) end - aat = aat.super end - end - return Tuple - end - else - ft = abstract_eval(fargs[1], vtypes, sv) - if isType(ft) - # TODO: improve abstract_call_constructor - st = ft.parameters[1] - if isa(st,TypeVar) && isa(st.ub,CompositeKind) - return st.ub - end - if isa(st,CompositeKind) - return st + if is(aat, Any) + break + end + aat = aat.super end end + return Tuple end end - if is(f,invoke) && length(fargs)>1 - af = isconstantfunc(fargs[1], sv) - if !is(af,false) && (af=_ieval(af);isgeneric(af)) - sig = argtypes[2] - if isa(sig,Tuple) && allp(isType, sig) - sig = map(t->t.parameters[1], sig) - return invoke_tfunc(af, sig, argtypes[3:]) - end + end + if isgeneric(f) + return abstract_call_gf(f, fargs, argtypes, e) + end + if is(f,invoke) && length(fargs)>1 + af = isconstantfunc(fargs[1], sv) + if !is(af,false) && (af=_ieval(af);isgeneric(af)) + sig = argtypes[2] + if isa(sig,Tuple) && all(isType, sig) + sig = map(t->t.parameters[1], sig) + return invoke_tfunc(af, sig, argtypes[3:]) end end - if !is(f,apply) && isa(e,Expr) && (isa(f,Function) || isa(f,IntrinsicFunction)) - e.head = :call1 + end + if !is(f,apply) && isa(e,Expr) && (isa(f,Function) || isa(f,IntrinsicFunction)) + e.head = :call1 + end + if is(f,getfield) + val = isconstantref(e, sv) + if !is(val,false) + return abstract_eval_constant(_ieval(val)) end - if is(f,getfield) - val = isconstantref(e, sv) - if !is(val,false) - return abstract_eval_constant(_ieval(val)) + end + if is(f,kwcall) + if length(argtypes) < 3 + return None + end + if length(fargs) < 2 + return Any + end + ff = isconstantfunc(fargs[1], sv) + if !(ff===false) + ff = _ieval(ff) + if isgeneric(ff) && isdefined(ff.env,:kwsorter) + # use the fact that kwcall(...) calls ff.env.kwsorter + kwcount = fargs[2] + posargt = argtypes[(4+2*kwcount):end] + return abstract_call_gf(ff.env.kwsorter, (), tuple(Tuple, posargt...), e) end end - rt = builtin_tfunction(f, fargs, argtypes) - #print("=> ", rt, "\n") - return rt - elseif isgeneric(f) - return abstract_call_gf(f, fargs, argtypes, e) - else - #print("=> ", Any, "\n") return Any end + rt = builtin_tfunction(f, fargs, argtypes) + #print("=> ", rt, "\n") + return rt end function abstract_eval_arg(a, vtypes, sv) t = abstract_eval(a, vtypes, sv) if isa(a,Symbol) || isa(a,SymbolNode) - t = tintersect(t,Any) # remove Undef + t = typeintersect(t,Any) # remove Undef end return t end @@ -651,7 +691,7 @@ end function abstract_eval_call(e, vtypes, sv::StaticVarInfo) fargs = e.args[2:] argtypes = tuple([abstract_eval_arg(a, vtypes, sv) for a in fargs]...) - if anyp(x->is(x,None), argtypes) + if any(x->is(x,None), argtypes) return None end called = e.args[1] @@ -666,10 +706,11 @@ function abstract_eval_call(e, vtypes, sv::StaticVarInfo) ft = abstract_eval(called, vtypes, sv) if isType(ft) st = ft.parameters[1] - if isa(st,TypeVar) && isa(st.ub,CompositeKind) - return st.ub + if isa(st,TypeVar) + st = st.ub end - if isa(st,CompositeKind) + if isa(st,DataType) + _methods(st,(),0) if isgeneric(st) && isleaftype(st) return abstract_call_gf(st, fargs, argtypes, e) end @@ -698,13 +739,19 @@ function abstract_eval(e::Expr, vtypes, sv::StaticVarInfo) else t = Any end + for i = 2:length(e.args) + abstract_eval(e.args[i], vtypes, sv) + end elseif is(e.head,:&) abstract_eval(e.args[1], vtypes, sv) t = Any elseif is(e.head,:static_typeof) t = abstract_eval(e.args[1], vtypes, sv) # intersect with Any to remove Undef - t = tintersect(t, Any) + t = typeintersect(t, Any) + if isa(t,UnionType) + t = typejoin(t.types...) + end if is(t,None) elseif isleaftype(t) t = Type{t} @@ -727,6 +774,8 @@ function abstract_eval(e::Expr, vtypes, sv::StaticVarInfo) t = Type{TypeVar(:_,t)} end end + elseif is(e.head,:method) + t = Function else t = Any end @@ -742,16 +791,18 @@ function abstract_eval(e::TopNode, vtypes, sv::StaticVarInfo) return abstract_eval_global(_basemod(), e.name) end -const _jl_Type_Array = Type{Array} +const Type_Array = Type{Array} function abstract_eval_constant(x::ANY) - if isa(x,AbstractKind) || isa(x,BitsKind) || isa(x,CompositeKind) || - isa(x,UnionKind) || isa(x,TypeConstructor) + if isa(x,DataType) || isa(x,UnionType) || isa(x,TypeConstructor) if is(x,Array) - return _jl_Type_Array + return Type_Array end return Type{x} end + #if isa(x,Tuple) && all(e->isa(e,Type), x) + # return Type{x} + #end return typeof(x) end @@ -789,6 +840,12 @@ function abstract_eval(s::Symbol, vtypes, sv::StaticVarInfo) val = sp[i+1] if isa(val,TypeVar) # static param bound to typevar + if Any <: val.ub + # if the tvar does not refer to anything more specific + # than Any, the static param might actually be an + # integer, symbol, etc. + return Any + end return Type{val} end return abstract_eval_constant(val) @@ -815,7 +872,7 @@ type StateUpdate state::VarTable end -function ref(x::StateUpdate, s::Symbol) +function getindex(x::StateUpdate, s::Symbol) if is(x.var,s) return x.vtype end @@ -839,7 +896,9 @@ function abstract_interpret(e::Expr, vtypes, sv::StaticVarInfo) elseif is(e.head,:gotoifnot) abstract_eval(e.args[1], vtypes, sv) elseif is(e.head,:method) - return StateUpdate(e.args[1], Function, vtypes) + fname = e.args[1] + if isa(fname,Expr); fname = fname.args[1]; end + return StateUpdate(fname, Function, vtypes) end return vtypes end @@ -863,10 +922,10 @@ function type_too_complex(t::ANY, d) if d > MAX_TYPE_DEPTH return true end - if isa(t,UnionKind) + if isa(t,UnionType) p = t.types - elseif isa(t,CompositeKind) || isa(t,AbstractKind) || isa(t,BitsKind) - return false + elseif isa(t,DataType) + p = t.parameters elseif isa(t,Tuple) p = t elseif isa(t,TypeVar) @@ -980,17 +1039,16 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop) tf = def.tfunc if !is(tf,()) tfarr = tf::Array{Any,1} - for i = 1:2:length(tfarr) + for i = 1:3:length(tfarr) if typeseq(tfarr[i],atypes) code = tfarr[i+1] - assert(isa(code, Tuple)) - if code[5] - curtype = code[3] + curtype = ccall(:jl_ast_rettype, Any, (Any,Any), def, code) + if tfarr[i+2] redo = true tfunc_idx = i+1 break end - return (code, code[3]) + return (code, curtype) end end end @@ -1000,12 +1058,12 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop) #if dbg # print("typeinf ", linfo.name, " ", object_id(ast0), "\n") #end - #print("typeinf ", linfo.name, " ", atypes, "\n") - # if isdefined(:stdout_stream) - # write(stdout_stream, "typeinf ") - # write(stdout_stream, string(linfo.name)) - # write(stdout_stream, string(atypes)) - # write(stdout_stream, '\n') + #print("typeinf ", linfo.name, " ", atypes, " ", linfo.file,":",linfo.line,"\n") + # if isdefined(:STDOUT) + # write(STDOUT, "typeinf ") + # write(STDOUT, string(linfo.name)) + # write(STDOUT, string(atypes)) + # write(STDOUT, '\n') # end #print("typeinf ", ast0, " ", sparams, " ", atypes, "\n") @@ -1057,20 +1115,28 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop) recpts = IntSet() # statements that depend recursively on our value W = IntSet() # initial set of pc - add(W,1) + add!(W,1) # initial types s[1] = ObjectIdDict() for v in vars s[1][v] = Undef end if la > 0 - if is(atypes,Tuple) - atypes = tuple(NTuple{la,Any}..., Tuple[1]) - end lastarg = ast.args[1][la] if is_rest_arg(lastarg) - s[1][args[la]] = limit_tuple_depth(atypes[la:]) + if atypes === Tuple + if la > 1 + atypes = tuple(NTuple{la-1,Any}..., Tuple[1]) + end + s[1][args[la]] = Tuple + else + s[1][args[la]] = limit_tuple_depth(atypes[la:]) + end la -= 1 + else + if atypes === Tuple + atypes = tuple(NTuple{la,Any}..., Tuple[1]) + end end end for i=1:la @@ -1104,10 +1170,10 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop) handler_at = { () for i=1:n } while !isempty(W) - pc = choose(W) + pc = first(W) while true #print(pc,": ",s[pc],"\n") - del(W, pc) + delete!(W, pc, 0) if is(handler_at[pc],()) handler_at[pc] = cur_hand else @@ -1120,7 +1186,7 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop) if !(isa(frame.prev,CallStack) && frame.prev.recurred) toprec = true end - add(recpts, pc) + add!(recpts, pc) #if dbg # show(pc); print(" recurred\n") #end @@ -1130,7 +1196,7 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop) # propagate type info to exception handler l = cur_hand[1]::Int if stchanged(changes, s[l], vars) - add(W, l) + add!(W, l) s[l] = stupdate(s[l], changes, vars) end end @@ -1150,14 +1216,14 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop) # general case handler_at[l] = cur_hand if stchanged(changes, s[l], vars) - add(W, l) + add!(W, l) s[l] = stupdate(s[l], changes, vars) end end elseif is(hd,:type_goto) l = findlabel(body,stmt.args[1]) if stchanged(changes, s[l], vars) - add(W, l) + add!(W, l) s[l] = stupdate(s[l], changes, vars) end elseif is(hd,:return) @@ -1168,7 +1234,7 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop) if !(isa(frame.prev,CallStack) && frame.prev.recurred) toprec = true end - add(recpts, pc) + add!(recpts, pc) #if dbg # show(pc); print(" recurred\n") #end @@ -1189,7 +1255,7 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop) # show(r) # print("\n") #end - add(W,r) + add!(W,r) end end elseif is(hd,:enter) @@ -1225,23 +1291,23 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop) sv.vars = append_any(f_argnames(fulltree), fulltree.args[2][1]) tuple_elim_pass(fulltree) linfo.inferred = true + fulltree = ccall(:jl_compress_ast, Any, (Any,Any), def, fulltree) end - compr = ccall(:jl_compress_ast, Any, (Any, Any,), def, fulltree) - if !redo if is(def.tfunc,()) def.tfunc = {} end - compr = (compr[1],compr[2],compr[3],compr[4],rec) - push(def.tfunc::Array{Any,1}, atypes) - push(def.tfunc::Array{Any,1}, compr) + push!(def.tfunc::Array{Any,1}, atypes) + push!(def.tfunc::Array{Any,1}, fulltree) + push!(def.tfunc::Array{Any,1}, rec) else - def.tfunc[tfunc_idx] = (compr[1],compr[2],compr[3],compr[4],rec) + def.tfunc[tfunc_idx] = fulltree + def.tfunc[tfunc_idx+1] = rec end inference_stack = (inference_stack::CallStack).prev - return (compr, frame.result) + return (fulltree, frame.result) end function record_var_type(e::Symbol, t, decls) @@ -1284,7 +1350,10 @@ function eval_annotate(e::Expr, vtypes, sv, decls, clo) end i0 = is(head,:method) ? 2 : 1 for i=i0:length(e.args) - e.args[i] = eval_annotate(e.args[i], vtypes, sv, decls, clo) + subex = e.args[i] + if !(isa(subex,Number) || isa(subex,String)) + e.args[i] = eval_annotate(subex, vtypes, sv, decls, clo) + end end e end @@ -1309,7 +1378,7 @@ end eval_annotate(s, vtypes, sv, decls, clo) = s function eval_annotate(l::LambdaStaticData, vtypes, sv, decls, clo) - push(clo, l) + push!(clo, l) l end @@ -1350,8 +1419,8 @@ function type_annotate(ast::Expr, states::Array{Any,1}, sv::ANY, rettype::ANY, end end na = length(a.args[1]) - typeinf(li, ntuple(na+1, i->(i>na ? (Tuple)[1] : Any)), - li.sparams, li, false) + li.ast, _ = typeinf(li, ntuple(na+1, i->(i>na ? (Tuple)[1] : Any)), + li.sparams, li, false) end end @@ -1404,7 +1473,7 @@ function resolve_relative(sym, from, to, typ, orig) end m = _basemod() if is(from,m) || is(from,Core) - return _jl_tn(sym) + return tn(sym) end end return GetfieldNode(from, sym, typ) @@ -1414,7 +1483,10 @@ end function resolve_globals(e::Expr, from, to, env1, env2) if !is(e.head,:line) for i=1:length(e.args) - e.args[i] = resolve_globals(e.args[i], from, to, env1, env2) + subex = e.args[i] + if !(isa(subex,Number) || isa(subex,String)) + e.args[i] = resolve_globals(subex, from, to, env1, env2) + end end end e @@ -1465,6 +1537,8 @@ function exprtype(x::ANY) return Any end return abstract_eval(x, (), sv) + elseif isa(x,QuoteNode) + return typeof(x.value) elseif isa(x,Type) return Type{x} elseif isa(x,LambdaStaticData) @@ -1481,7 +1555,7 @@ function without_linenums(a::Array{Any,1}) for x in a if (isa(x,Expr) && is(x.head,:line)) || isa(x,LineNumberNode) else - push(l, x) + push!(l, x) end end l @@ -1493,19 +1567,31 @@ function effect_free(e) isa(e,TopNode) || isa(e,QuoteNode) return true end - if isa(e,Expr) && (e.head === :call || e.head === :call1) + if isa(e,Expr) + if e.head === :static_typeof + return true + end ea = e.args - for a in ea - if !effect_free(a) - return false + if e.head === :call || e.head === :call1 + for a in ea + if !effect_free(a) + return false + end end - end - if isa(ea[1],TopNode) - n = ea[1].name - if (n === :getfield || n === :tuple || n === :tupleref || - n === :tuplelen || n === :fieldtype) - return true + if isa(ea[1],TopNode) + n = ea[1].name + if (n === :getfield || n === :tuple || n === :tupleref || + n === :tuplelen || n === :fieldtype) + return true + end end + elseif e.head === :new + for a in ea + if !effect_free(a) + return false + end + end + return true end end return false @@ -1517,7 +1603,7 @@ end # static parameters are ok if all the static parameter values are leaf types, # meaning they are fully known. function inlineable(f, e::Expr, sv, enclosing_ast) - if !(isa(f,Function)||isa(f,CompositeKind)||isa(f,IntrinsicFunction)) + if !(isa(f,Function) || isstructtype(f) || isa(f,IntrinsicFunction)) return NF end argexprs = e.args[2:] @@ -1535,7 +1621,7 @@ function inlineable(f, e::Expr, sv, enclosing_ast) isType(e.typ) && isleaftype(e.typ.parameters[1]) return (e.typ.parameters[1],()) end - if length(atypes)==2 && is(f,unbox) && isa(atypes[2],BitsKind) + if length(atypes)==2 && is(f,unbox) && isa(atypes[2],DataType) return (e.args[3],()) end if isa(f,IntrinsicFunction) @@ -1557,6 +1643,7 @@ function inlineable(f, e::Expr, sv, enclosing_ast) return NF end sp = meth[2]::Tuple + sp = tuple(sp..., meth[3].sparams...) spvals = { sp[i] for i in 2:2:length(sp) } for i=1:length(spvals) if isa(spvals[i],TypeVar) @@ -1567,8 +1654,10 @@ function inlineable(f, e::Expr, sv, enclosing_ast) if is(ast,()) return NF end - if isa(ast,Tuple) - ast = ccall(:jl_uncompress_ast, Any, (Any,), ast) + needcopy = true + if !isa(ast,Expr) + ast = ccall(:jl_uncompress_ast, Any, (Any,Any), meth[3], ast) + needcopy = false end ast = ast::Expr for vi in ast.args[2][2] @@ -1614,10 +1703,10 @@ function inlineable(f, e::Expr, sv, enclosing_ast) if occ > 1 vnew = unique_name(enclosing_ast) add_variable(enclosing_ast, vnew, aeitype) - push(stmts, Expr(:(=), {vnew, aei}, Any)) + push!(stmts, Expr(:(=), vnew, aei)) argexprs[i] = aeitype===Any ? vnew : SymbolNode(vnew,aeitype) elseif !isType(aeitype) && !effect_free(aei) - push(stmts, aei) + push!(stmts, aei) end end end @@ -1625,7 +1714,7 @@ function inlineable(f, e::Expr, sv, enclosing_ast) # ok, substitute argument expressions for argument names in the body spnames = { sp[i].name for i=1:2:length(sp) } - expr = astcopy(expr) + if needcopy; expr = astcopy(expr); end mfrom = meth[3].module; mto = (inference_stack::CallStack).mod if !is(mfrom, mto) expr = resolve_globals(expr, mfrom, mto, args, spnames) @@ -1633,20 +1722,22 @@ function inlineable(f, e::Expr, sv, enclosing_ast) return (sym_replace(expr, args, spnames, argexprs, spvals), stmts) end -_jl_tn(sym::Symbol) = +tn(sym::Symbol) = ccall(:jl_new_struct, Any, (Any,Any...), TopNode, sym, Any) -const _jl_top_tupleref = _jl_tn(:tupleref) -const _jl_top_tuple = _jl_tn(:tuple) +const top_tupleref = tn(:tupleref) +const top_tuple = tn(:tuple) function mk_tupleref(texpr, i) - e = :(($_jl_top_tupleref)($texpr, $i)) + e = :(($top_tupleref)($texpr, $i)) e.typ = exprtype(texpr)[i] e end function mk_tuplecall(args) - Expr(:call1, {_jl_top_tuple, args...}, tuple(map(exprtype, args)...)) + e = Expr(:call1, top_tuple, args...) + e.typ = tuple(map(exprtype, args)...) + e end const basenumtype = Union(Int32,Int64,Float32,Float64,Complex64,Complex128,Rational) @@ -1678,7 +1769,7 @@ function inlining_pass(e::Expr, sv, ast) if isa(res[2],Array) sts = res[2]::Array{Any,1} for j = 1:length(sts) - insert(eargs, i, sts[j]) + insert!(eargs, i, sts[j]) i += 1 end end @@ -1719,10 +1810,10 @@ function inlining_pass(e::Expr, sv, ast) if isa(a1,basenumtype) || ((isa(a1,Symbol) || isa(a1,SymbolNode)) && exprtype(a1) <: basenumtype) if e.args[3]==2 - e.args = {_jl_tn(:*), a1, a1} + e.args = {tn(:*), a1, a1} f = * elseif e.args[3]==3 - e.args = {_jl_tn(:*), a1, a1, a1} + e.args = {tn(:*), a1, a1, a1} f = * end end @@ -1779,8 +1870,8 @@ function add_variable(ast, name, typ) vinf = {name,typ,2} locllist = ast.args[2][1]::Array{Any,1} vinflist = ast.args[2][2]::Array{Any,1} - push(locllist, name) - push(vinflist, vinf) + push!(locllist, name) + push!(vinflist, vinf) end const some_names = {:_var0, :_var1, :_var2, :_var3, :_var4, :_var5, :_var6, @@ -1830,7 +1921,7 @@ function find_sa_vars(ast) for vi in ast.args[2][2] if (vi[3]&1)!=0 # remove captured vars - del(av, vi[1]) + delete!(av, vi[1], nothing) end end av @@ -1888,7 +1979,7 @@ function tuple_elim_pass(ast::Expr) continue end - del(body, i) # remove tuple allocation + delete!(body, i) # remove tuple allocation # convert tuple allocation to a series of local var assignments vals = cell(nv) n_ins = 0 @@ -1899,9 +1990,9 @@ function tuple_elim_pass(ast::Expr) else elty = exprtype(tupelt) tmpv = unique_name(ast) - tmp = Expr(:(=), {tmpv,tupelt}, Any) + tmp = Expr(:(=), tmpv, tupelt) add_variable(ast, tmpv, elty) - insert(body, i+n_ins, tmp) + insert!(body, i+n_ins, tmp) vals[j] = SymbolNode(tmpv, elty) n_ins += 1 end @@ -1929,11 +2020,11 @@ function replace_tupleref(e, tupname, vals, sv, i0) end end -function finfer(f, types) +function finfer(f::Union(Function,DataType), types) x = methods(f,types)[1] (tree, ty) = typeinf(x[3], x[1], x[2]) - if isa(tree,Tuple) - return ccall(:jl_uncompress_ast, Any, (Any,), tree) + if !isa(tree,Expr) + return ccall(:jl_uncompress_ast, Any, (Any,Any), x[3], tree) end tree end diff --git a/base/int.jl b/base/int.jl index 79b8096b979a6..7804a66d2e75a 100644 --- a/base/int.jl +++ b/base/int.jl @@ -1,204 +1,3 @@ -## integer conversions ## - -convert(::Type{Int8}, x::Bool ) = box(Int8,zext_int(Int8,unbox(Bool,x))) -convert(::Type{Int8}, x::Uint8 ) = box(Int8,unbox(Uint8,x)) -convert(::Type{Int8}, x::Int16 ) = box(Int8,trunc8(unbox(Int16,x))) -convert(::Type{Int8}, x::Uint16 ) = box(Int8,trunc8(unbox(Uint16,x))) -convert(::Type{Int8}, x::Char ) = box(Int8,trunc8(unbox(Char,x))) -convert(::Type{Int8}, x::Int32 ) = box(Int8,trunc8(unbox(Int32,x))) -convert(::Type{Int8}, x::Uint32 ) = box(Int8,trunc8(unbox(Uint32,x))) -convert(::Type{Int8}, x::Int64 ) = box(Int8,trunc8(unbox(Int64,x))) -convert(::Type{Int8}, x::Uint64 ) = box(Int8,trunc8(unbox(Uint64,x))) -convert(::Type{Int8}, x::Int128 ) = box(Int8,trunc8(unbox(Int128,x))) -convert(::Type{Int8}, x::Uint128) = box(Int8,trunc8(unbox(Uint128,x))) -convert(::Type{Int8}, x::Float32) = box(Int8,trunc8(checked_fptosi32(unbox(Float32,x)))) -convert(::Type{Int8}, x::Float64) = box(Int8,trunc8(checked_fptosi64(unbox(Float64,x)))) - -convert(::Type{Uint8}, x::Bool ) = box(Uint8,zext_int(Int8,unbox(Bool,x))) -convert(::Type{Uint8}, x::Int8 ) = box(Uint8,unbox(Uint8,x)) -convert(::Type{Uint8}, x::Int16 ) = box(Uint8,trunc8(unbox(Int16,x))) -convert(::Type{Uint8}, x::Uint16 ) = box(Uint8,trunc8(unbox(Uint16,x))) -convert(::Type{Uint8}, x::Char ) = box(Uint8,trunc8(unbox(Char,x))) -convert(::Type{Uint8}, x::Int32 ) = box(Uint8,trunc8(unbox(Int32,x))) -convert(::Type{Uint8}, x::Uint32 ) = box(Uint8,trunc8(unbox(Uint32,x))) -convert(::Type{Uint8}, x::Int64 ) = box(Uint8,trunc8(unbox(Int64,x))) -convert(::Type{Uint8}, x::Uint64 ) = box(Uint8,trunc8(unbox(Uint64,x))) -convert(::Type{Uint8}, x::Int128 ) = box(Uint8,trunc8(unbox(Int128,x))) -convert(::Type{Uint8}, x::Uint128) = box(Uint8,trunc8(unbox(Uint128,x))) -convert(::Type{Uint8}, x::Float32) = box(Uint8,trunc8(checked_fptoui32(unbox(Float32,x)))) -convert(::Type{Uint8}, x::Float64) = box(Uint8,trunc8(checked_fptoui64(unbox(Float64,x)))) - -convert(::Type{Int16}, x::Bool ) = box(Int16,zext16(unbox(Bool,x))) -convert(::Type{Int16}, x::Int8 ) = box(Int16,sext16(unbox(Int8,x))) -convert(::Type{Int16}, x::Uint8 ) = box(Int16,zext16(unbox(Uint8,x))) -convert(::Type{Int16}, x::Uint16 ) = box(Int16,unbox(Uint16,x)) -convert(::Type{Int16}, x::Char ) = box(Int16,trunc16(unbox(Char,x))) -convert(::Type{Int16}, x::Int32 ) = box(Int16,trunc16(unbox(Int32,x))) -convert(::Type{Int16}, x::Uint32 ) = box(Int16,trunc16(unbox(Uint32,x))) -convert(::Type{Int16}, x::Int64 ) = box(Int16,trunc16(unbox(Int64,x))) -convert(::Type{Int16}, x::Uint64 ) = box(Int16,trunc16(unbox(Uint64,x))) -convert(::Type{Int16}, x::Int128 ) = box(Int16,trunc16(unbox(Int128,x))) -convert(::Type{Int16}, x::Uint128) = box(Int16,trunc16(unbox(Uint128,x))) -convert(::Type{Int16}, x::Float32) = box(Int16,trunc16(checked_fptosi32(unbox(Float32,x)))) -convert(::Type{Int16}, x::Float64) = box(Int16,trunc16(checked_fptosi64(unbox(Float64,x)))) - -convert(::Type{Uint16}, x::Bool ) = box(Uint16,zext16(unbox(Bool,x))) -convert(::Type{Uint16}, x::Int8 ) = box(Uint16,sext16(unbox(Int8,x))) -convert(::Type{Uint16}, x::Uint8 ) = box(Uint16,zext16(unbox(Uint8,x))) -convert(::Type{Uint16}, x::Int16 ) = box(Uint16,unbox(Int16,x)) -convert(::Type{Uint16}, x::Char ) = box(Uint16,trunc16(unbox(Char,x))) -convert(::Type{Uint16}, x::Int32 ) = box(Uint16,trunc16(unbox(Int32,x))) -convert(::Type{Uint16}, x::Uint32 ) = box(Uint16,trunc16(unbox(Uint32,x))) -convert(::Type{Uint16}, x::Int64 ) = box(Uint16,trunc16(unbox(Int64,x))) -convert(::Type{Uint16}, x::Uint64 ) = box(Uint16,trunc16(unbox(Uint64,x))) -convert(::Type{Uint16}, x::Int128 ) = box(Uint16,trunc16(unbox(Int128,x))) -convert(::Type{Uint16}, x::Uint128) = box(Uint16,trunc16(unbox(Uint128,x))) -convert(::Type{Uint16}, x::Float32) = box(Uint16,trunc16(checked_fptoui32(unbox(Float32,x)))) -convert(::Type{Uint16}, x::Float64) = box(Uint16,trunc16(checked_fptoui64(unbox(Float64,x)))) - -convert(::Type{Int32}, x::Bool ) = box(Int32,zext32(unbox(Bool,x))) -convert(::Type{Int32}, x::Int8 ) = box(Int32,sext32(unbox(Int8,x))) -convert(::Type{Int32}, x::Uint8 ) = box(Int32,zext32(unbox(Uint8,x))) -convert(::Type{Int32}, x::Int16 ) = box(Int32,sext32(unbox(Int16,x))) -convert(::Type{Int32}, x::Uint16 ) = box(Int32,zext32(unbox(Uint16,x))) -convert(::Type{Int32}, x::Char ) = box(Int32,unbox(Char,x)) -convert(::Type{Int32}, x::Uint32 ) = box(Int32,unbox(Uint32,x)) -convert(::Type{Int32}, x::Int64 ) = box(Int32,trunc32(unbox(Int64,x))) -convert(::Type{Int32}, x::Uint64 ) = box(Int32,trunc32(unbox(Uint64,x))) -convert(::Type{Int32}, x::Int128 ) = box(Int32,trunc32(unbox(Int128,x))) -convert(::Type{Int32}, x::Uint128) = box(Int32,trunc32(unbox(Uint128,x))) -convert(::Type{Int32}, x::Float32) = box(Int32,checked_fptosi32(unbox(Float32,x))) -convert(::Type{Int32}, x::Float64) = box(Int32,trunc32(checked_fptosi64(unbox(Float64,x)))) - -convert(::Type{Uint32}, x::Bool ) = box(Uint32,zext32(unbox(Bool,x))) -convert(::Type{Uint32}, x::Int8 ) = box(Uint32,sext32(unbox(Int8,x))) -convert(::Type{Uint32}, x::Uint8 ) = box(Uint32,zext32(unbox(Uint8,x))) -convert(::Type{Uint32}, x::Int16 ) = box(Uint32,sext32(unbox(Int16,x))) -convert(::Type{Uint32}, x::Uint16 ) = box(Uint32,zext32(unbox(Uint16,x))) -convert(::Type{Uint32}, x::Char ) = box(Uint32,unbox(Char,x)) -convert(::Type{Uint32}, x::Int32 ) = box(Uint32,unbox(Int32,x)) -convert(::Type{Uint32}, x::Int64 ) = box(Uint32,trunc32(unbox(Int64,x))) -convert(::Type{Uint32}, x::Uint64 ) = box(Uint32,trunc32(unbox(Uint64,x))) -convert(::Type{Uint32}, x::Int128 ) = box(Uint32,trunc32(unbox(Int128,x))) -convert(::Type{Uint32}, x::Uint128) = box(Uint32,trunc32(unbox(Uint128,x))) -convert(::Type{Uint32}, x::Float32) = box(Uint32,checked_fptoui32(unbox(Float32,x))) -convert(::Type{Uint32}, x::Float64) = box(Uint32,trunc32(checked_fptoui64(unbox(Float64,x)))) - -convert(::Type{Int64}, x::Bool ) = box(Int64,zext64(unbox(Bool,x))) -convert(::Type{Int64}, x::Int8 ) = box(Int64,sext64(unbox(Int8,x))) -convert(::Type{Int64}, x::Uint8 ) = box(Int64,zext64(unbox(Uint8,x))) -convert(::Type{Int64}, x::Int16 ) = box(Int64,sext64(unbox(Int16,x))) -convert(::Type{Int64}, x::Uint16 ) = box(Int64,zext64(unbox(Uint16,x))) -convert(::Type{Int64}, x::Char ) = box(Int64,zext64(unbox(Char,x))) -convert(::Type{Int64}, x::Int32 ) = box(Int64,sext64(unbox(Int32,x))) -convert(::Type{Int64}, x::Uint32 ) = box(Int64,zext64(unbox(Uint32,x))) -convert(::Type{Int64}, x::Uint64 ) = box(Int64,unbox(Uint64,x)) -convert(::Type{Int64}, x::Int128 ) = box(Int64,trunc64(unbox(Int128,x))) -convert(::Type{Int64}, x::Uint128) = box(Int64,trunc64(unbox(Uint128,x))) -convert(::Type{Int64}, x::Float32) = box(Int64,checked_fptosi64(fpext64(unbox(Float32,x)))) -convert(::Type{Int64}, x::Float64) = box(Int64,checked_fptosi64(unbox(Float64,x))) - -convert(::Type{Uint64}, x::Bool ) = box(Uint64,zext64(unbox(Bool,x))) -convert(::Type{Uint64}, x::Int8 ) = box(Uint64,sext64(unbox(Int8,x))) -convert(::Type{Uint64}, x::Uint8 ) = box(Uint64,zext64(unbox(Uint8,x))) -convert(::Type{Uint64}, x::Int16 ) = box(Uint64,sext64(unbox(Int16,x))) -convert(::Type{Uint64}, x::Uint16 ) = box(Uint64,zext64(unbox(Uint16,x))) -convert(::Type{Uint64}, x::Char ) = box(Uint64,zext64(unbox(Char,x))) -convert(::Type{Uint64}, x::Int32 ) = box(Uint64,sext64(unbox(Int32,x))) -convert(::Type{Uint64}, x::Uint32 ) = box(Uint64,zext64(unbox(Uint32,x))) -convert(::Type{Uint64}, x::Int64 ) = box(Uint64,unbox(Int64,x)) -convert(::Type{Uint64}, x::Int128 ) = box(Uint64,trunc64(unbox(Int128,x))) -convert(::Type{Uint64}, x::Uint128) = box(Uint64,trunc64(unbox(Uint128,x))) -convert(::Type{Uint64}, x::Float32) = box(Uint64,checked_fptoui64(fpext64(unbox(Float32,x)))) -convert(::Type{Uint64}, x::Float64) = box(Uint64,checked_fptoui64(unbox(Float64,x))) - -convert(::Type{Int128}, x::Bool ) = box(Int128,zext_int(Int128,unbox(Bool,x))) -convert(::Type{Int128}, x::Int8 ) = box(Int128,sext_int(Int128,unbox(Int8,x))) -convert(::Type{Int128}, x::Uint8 ) = box(Int128,zext_int(Uint128,unbox(Uint8,x))) -convert(::Type{Int128}, x::Int16 ) = box(Int128,sext_int(Int128,unbox(Int16,x))) -convert(::Type{Int128}, x::Uint16 ) = box(Int128,zext_int(Uint128,unbox(Uint16,x))) -convert(::Type{Int128}, x::Char ) = box(Int128,zext_int(Uint128,unbox(Char,x))) -convert(::Type{Int128}, x::Int32 ) = box(Int128,sext_int(Int128,unbox(Int32,x))) -convert(::Type{Int128}, x::Uint32 ) = box(Int128,zext_int(Uint128,unbox(Uint32,x))) -convert(::Type{Int128}, x::Int64 ) = box(Int128,sext_int(Int128,unbox(Int64,x))) -convert(::Type{Int128}, x::Uint64 ) = box(Int128,zext_int(Uint128,unbox(Uint64,x))) -convert(::Type{Int128}, x::Uint128) = box(Int128,unbox(Uint128,x)) -# TODO: convert(::Type{Int128}, x::Float32) -# TODO: convert(::Type{Int128}, x::Float64) - -convert(::Type{Uint128}, x::Bool ) = box(Uint128,zext_int(Int128,unbox(Bool,x))) -convert(::Type{Uint128}, x::Int8 ) = box(Uint128,sext_int(Int128,unbox(Int8,x))) -convert(::Type{Uint128}, x::Uint8 ) = box(Uint128,zext_int(Uint128,unbox(Uint8,x))) -convert(::Type{Uint128}, x::Int16 ) = box(Uint128,sext_int(Int128,unbox(Int16,x))) -convert(::Type{Uint128}, x::Uint16 ) = box(Uint128,zext_int(Uint128,unbox(Uint16,x))) -convert(::Type{Uint128}, x::Char ) = box(Uint128,zext_int(Uint128,unbox(Char,x))) -convert(::Type{Uint128}, x::Int32 ) = box(Uint128,sext_int(Int128,unbox(Int32,x))) -convert(::Type{Uint128}, x::Uint32 ) = box(Uint128,zext_int(Uint128,unbox(Uint32,x))) -convert(::Type{Uint128}, x::Int64 ) = box(Uint128,sext_int(Int128,unbox(Int64,x))) -convert(::Type{Uint128}, x::Uint64 ) = box(Uint128,zext_int(Uint128,unbox(Uint64,x))) -convert(::Type{Uint128}, x::Int128 ) = box(Uint128,unbox(Int128,x)) -# TODO: convert(::Type{Uint128}, x::Float32) -# TODO: convert(::Type{Uint128}, x::Float64) - -convert(::Type{Signed}, x::Uint8 ) = convert(Int,x) -convert(::Type{Signed}, x::Uint16 ) = convert(Int,x) -convert(::Type{Signed}, x::Uint32 ) = convert(Int,x) -convert(::Type{Signed}, x::Uint64 ) = convert(Int64,x) -convert(::Type{Signed}, x::Uint128) = convert(Int128,x) -convert(::Type{Signed}, x::Float32) = convert(Int,x) -convert(::Type{Signed}, x::Float64) = convert(Int64,x) - -convert(::Type{Unsigned}, x::Int8 ) = convert(Uint8,x) -convert(::Type{Unsigned}, x::Int16 ) = convert(Uint16,x) -convert(::Type{Unsigned}, x::Int32 ) = convert(Uint32,x) -convert(::Type{Unsigned}, x::Int64 ) = convert(Uint64,x) -convert(::Type{Unsigned}, x::Int128 ) = convert(Uint128,x) -convert(::Type{Unsigned}, x::Float32) = convert(Uint,x) -convert(::Type{Unsigned}, x::Float64) = convert(Uint64,x) - -convert(::Type{Integer}, x::Float32) = convert(Int,x) -convert(::Type{Integer}, x::Float64) = convert(Int64,x) - -int8(x) = convert(Int8,x) -int16(x) = convert(Int16,x) -int32(x) = convert(Int32,x) -int64(x) = convert(Int64,x) -int128(x) = convert(Int128,x) - -uint8(x) = convert(Uint8,x) -uint16(x) = convert(Uint16,x) -uint32(x) = convert(Uint32,x) -uint64(x) = convert(Uint64,x) -uint128(x) = convert(Uint128,x) - -signed(x) = convert(Signed,x) -unsigned(x) = convert(Unsigned,x) -integer(x) = convert(Integer,x) - -round(x::Integer) = x -trunc(x::Integer) = x -floor(x::Integer) = x - ceil(x::Integer) = x - -iround(x::Integer) = x -iround{T<:Integer}(::Type{T}, x::Integer) = convert(T, x) -itrunc(x::Integer) = x -ifloor(x::Integer) = x - iceil(x::Integer) = x - -morebits(::Type{Int8}) = Int16 -morebits(::Type{Int16}) = Int32 -morebits(::Type{Int32}) = Int64 -morebits(::Type{Int64}) = Int128 -morebits(::Type{Uint8}) = Uint16 -morebits(::Type{Uint16}) = Uint32 -morebits(::Type{Uint32}) = Uint64 -morebits(::Type{Uint64}) = Uint128 - -## system word size ## - -const WORD_SIZE = int(Int.nbits) - ## integer arithmetic ## -(x::Signed) = -int(x) @@ -238,8 +37,8 @@ const WORD_SIZE = int(Int.nbits) *(x::Int64, y::Int64) = box(Int64,mul_int(unbox(Int64,x),unbox(Int64,y))) *(x::Uint64, y::Uint64) = box(Uint64,mul_int(unbox(Uint64,x),unbox(Uint64,y))) -/(x::Integer, y::Integer) = float64(x)/float64(y) -inv(x::Integer) = 1.0/float64(x) +/(x::Integer, y::Integer) = float(x)/float(y) +inv(x::Integer) = float(one(x))/float(x) div{T<:Signed}(x::T, y::T) = div(int(x),int(y)) rem{T<:Signed}(x::T, y::T) = rem(int(x),int(y)) @@ -470,6 +269,112 @@ trailing_ones(x::Integer) = trailing_zeros(~x) <=(x::Signed, y::Unsigned) = (x <= 0) | (unsigned(x) <= y) <=(x::Unsigned, y::Signed ) = (y >= 0) & (x <= unsigned(y)) +## integer conversions ## + +const _inttypes = (Bool, Int8, Uint8, Int16, Uint16, Int32, Uint32, Char, + Int64, Uint64, Int128, Uint128) + +for to in _inttypes, from in _inttypes + if !(to===from) && !(to===Bool) + if to.size < from.size + @eval convert(::Type{$to}, x::($from)) = box($to,trunc_int($to,unbox($from,x))) + elseif from.size < to.size || from===Bool + if subtype(from, Signed) + @eval convert(::Type{$to}, x::($from)) = box($to,sext_int($to,unbox($from,x))) + else + @eval convert(::Type{$to}, x::($from)) = box($to,zext_int($to,unbox($from,x))) + end + else + @eval convert(::Type{$to}, x::($from)) = box($to,unbox($from,x)) + end + end +end + +for to in (Int8, Int16, Int32, Int64) + @eval begin + convert(::Type{$to}, x::Float32) = box($to,checked_fptosi($to,unbox(Float32,x))) + convert(::Type{$to}, x::Float64) = box($to,checked_fptosi($to,unbox(Float64,x))) + end +end + +for to in (Uint8, Uint16, Uint32, Uint64) + @eval begin + convert(::Type{$to}, x::Float32) = box($to,checked_fptoui($to,unbox(Float32,x))) + convert(::Type{$to}, x::Float64) = box($to,checked_fptoui($to,unbox(Float64,x))) + end +end + +function convert(::Type{Int128}, x::Float64) + ax = abs(x) + top = trunc(ldexp(ax,-64)) + bot = ax - ldexp(top,64) + n = int128(convert(Uint64,top))<<64 + int128(convert(Uint64,bot)) + return x<0 ? -n : n +end +convert(::Type{Int128}, x::Float32) = convert(Int128, float64(x)) + +function convert(::Type{Uint128}, x::Float64) + ax = abs(x) + top = trunc(ldexp(ax,-64)) + bot = ax - ldexp(top,64) + n = uint128(convert(Uint64,top))<<64 + uint128(convert(Uint64,bot)) + return x<0 ? -n : n +end +convert(::Type{Uint128}, x::Float32) = convert(Uint128, float64(x)) + +convert(::Type{Char}, x::Float32) = char(convert(Int, x)) +convert(::Type{Char}, x::Float64) = char(convert(Int, x)) + +convert(::Type{Signed}, x::Uint8 ) = convert(Int,x) +convert(::Type{Signed}, x::Uint16 ) = convert(Int,x) +convert(::Type{Signed}, x::Uint32 ) = convert(Int,x) +convert(::Type{Signed}, x::Uint64 ) = convert(Int64,x) +convert(::Type{Signed}, x::Uint128) = convert(Int128,x) +convert(::Type{Signed}, x::Float32) = convert(Int,x) +convert(::Type{Signed}, x::Float64) = convert(Int,x) + +convert(::Type{Unsigned}, x::Int8 ) = convert(Uint,x) +convert(::Type{Unsigned}, x::Int16 ) = convert(Uint,x) +convert(::Type{Unsigned}, x::Int32 ) = convert(Uint,x) +convert(::Type{Unsigned}, x::Int64 ) = convert(Uint64,x) +convert(::Type{Unsigned}, x::Int128 ) = convert(Uint128,x) +convert(::Type{Unsigned}, x::Float32) = convert(Uint,x) +convert(::Type{Unsigned}, x::Float64) = convert(Uint,x) + +convert(::Type{Integer}, x::Float32) = convert(Int,x) +convert(::Type{Integer}, x::Float64) = convert(Int,x) + +int8(x) = convert(Int8,x) +int16(x) = convert(Int16,x) +int32(x) = convert(Int32,x) +int64(x) = convert(Int64,x) +int128(x) = convert(Int128,x) + +uint8(x) = convert(Uint8,x) +uint16(x) = convert(Uint16,x) +uint32(x) = convert(Uint32,x) +uint64(x) = convert(Uint64,x) +uint128(x) = convert(Uint128,x) + +signed(x) = convert(Signed,x) +unsigned(x) = convert(Unsigned,x) +integer(x) = convert(Integer,x) + +round(x::Integer) = x +trunc(x::Integer) = x +floor(x::Integer) = x + ceil(x::Integer) = x + +iround(x::Integer) = x +iround{T<:Integer}(::Type{T}, x::Integer) = convert(T, x) +itrunc(x::Integer) = x +ifloor(x::Integer) = x + iceil(x::Integer) = x + +## system word size ## + +const WORD_SIZE = int(Int.size)*8 + ## integer promotions ## promote_rule(::Type{Int16}, ::Type{Int8} ) = Int @@ -566,6 +471,15 @@ sizeof(::Type{Uint64}) = 8 sizeof(::Type{Int128}) = 16 sizeof(::Type{Uint128}) = 16 +morebits(::Type{Int8}) = Int16 +morebits(::Type{Int16}) = Int32 +morebits(::Type{Int32}) = Int64 +morebits(::Type{Int64}) = Int128 +morebits(::Type{Uint8}) = Uint16 +morebits(::Type{Uint16}) = Uint32 +morebits(::Type{Uint32}) = Uint64 +morebits(::Type{Uint64}) = Uint128 + ## float to integer coercion ## # requires int arithmetic defined, for the loops to work diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 1c2649d253f94..dedb3984e1270 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -10,7 +10,7 @@ signbit(x::Int32) = int(x>>>31) signbit(x::Int64) = int(x>>>63) signbit(x::Int128) = int(x>>>127) -flipsign(x::Int32, y::Int32) = box(Int32,flipsign_int(unbox(Int32,x),unbox(Int32,y))) +flipsign(x::Int, y::Int) = box(Int,flipsign_int(unbox(Int,x),unbox(Int,y))) flipsign(x::Int64, y::Int64) = box(Int64,flipsign_int(unbox(Int64,x),unbox(Int64,y))) flipsign(x::Int128, y::Int128) = box(Int128,flipsign_int(unbox(Int128,x),unbox(Int128,y))) @@ -28,6 +28,8 @@ copysign(x::Signed, y::Real) = copysign(x, -oftype(x,signbit(y))) abs(x::Unsigned) = x abs(x::Signed) = flipsign(x,x) +~(n::Integer) = -n-1 + ## number-theoretic functions ## function gcd{T<:Integer}(a::T, b::T) @@ -68,15 +70,18 @@ function invmod(n, m) end # ^ for any x supporting * +to_power_type(x::Number) = oftype(x*x, x) +to_power_type(x) = x function power_by_squaring(x, p::Integer) + x = to_power_type(x) if p == 1 return x elseif p == 0 return one(x) - elseif p < 0 - throw(DomainError()) elseif p == 2 return x*x + elseif p < 0 + throw(DomainError()) end t = 1 while t <= p @@ -153,9 +158,8 @@ function prevpow(a, x) return n + int(a.^(n+1) .<= x) end - # decimal digits in an unsigned integer -const _jl_powers_of_ten = [ +const powers_of_ten = [ 0x0000000000000001, 0x000000000000000a, 0x0000000000000064, 0x00000000000003e8, 0x0000000000002710, 0x00000000000186a0, 0x00000000000f4240, 0x0000000000989680, 0x0000000005f5e100, 0x000000003b9aca00, 0x00000002540be400, 0x000000174876e800, @@ -165,7 +169,7 @@ const _jl_powers_of_ten = [ function ndigits0z(x::Union(Uint8,Uint16,Uint32,Uint64)) lz = (sizeof(x)<<3)-leading_zeros(x) nd = (1233*lz)>>12+1 - nd -= x < _jl_powers_of_ten[nd] + nd -= x < powers_of_ten[nd] end function ndigits0z(x::Uint128) n = 0 @@ -177,35 +181,24 @@ function ndigits0z(x::Uint128) end ndigits0z(x::Integer) = ndigits0z(unsigned(abs(x))) -if WORD_SIZE == 32 -const _jl_ndigits_max_mul = 69000000 -else -const _jl_ndigits_max_mul = 290000000000000000 -end - -function ndigits0z(n::Unsigned, b::Integer) - if b == 2 return (sizeof(n)<<3-leading_zeros(n)); end - if b == 8 return div((sizeof(n)<<3)-leading_zeros(n)+2,3); end - if b == 16 return (sizeof(n)<<1)-(leading_zeros(n)>>2); end - if b == 10 return ndigits0z(n); end - nd = 1 - if n <= _jl_ndigits_max_mul - # multiplication method is faster, but doesn't work for extreme values - d = b - while n >= d - nd += 1 - d *= b - end - else - while true - n = div(n, b) - if n == 0 - break - end - nd += 1 - end +const ndigits_max_mul = WORD_SIZE==32 ? 69000000 : 290000000000000000 + +function ndigits0z(n::Unsigned, b::Int) + b == 2 && return (sizeof(n)<<3-leading_zeros(n)) + b == 8 && return div((sizeof(n)<<3)-leading_zeros(n)+2,3) + b == 16 && return (sizeof(n)<<1)-(leading_zeros(n)>>2) + b == 10 && return ndigits0z(n) + d = 0 + while ndigits_max_mul < n + n = div(n,b) + d += 1 end - return nd + m = 1 + while m <= n + m *= b + d += 1 + end + return d end ndigits0z(x::Integer, b::Integer) = ndigits0z(unsigned(abs(x)),b) @@ -217,7 +210,7 @@ ndigits(x::Integer) = ndigits(unsigned(abs(x))) ## integer to string functions ## -const _jl_dig_syms = uint8(['0':'9','a':'z','A':'Z']) +const dig_syms = uint8(['0':'9','a':'z','A':'Z']) function bin(x::Unsigned, pad::Int, neg::Bool) i = neg + max(pad,sizeof(x)<<3-leading_zeros(x)) @@ -259,7 +252,7 @@ function hex(x::Unsigned, pad::Int, neg::Bool) i = neg + max(pad,(sizeof(x)<<1)-(leading_zeros(x)>>2)) a = Array(Uint8,i) while i > neg - a[i] = _jl_dig_syms[(x&0xf)+1] + a[i] = dig_syms[(x&0xf)+1] x >>= 4 i -= 1 end @@ -267,7 +260,9 @@ function hex(x::Unsigned, pad::Int, neg::Bool) ASCIIString(a) end -function base(symbols::Array{Uint8}, b::Int, x::Unsigned, pad::Int, neg::Bool) +num2hex(n::Integer) = hex(n, sizeof(n)*2) + +function _base(symbols::Array{Uint8}, b::Int, x::Unsigned, pad::Int, neg::Bool) if !(2 <= b <= length(symbols)) error("invalid base: $b") end i = neg + max(pad,ndigits0z(x,b)) a = Array(Uint8,i) @@ -279,12 +274,10 @@ function base(symbols::Array{Uint8}, b::Int, x::Unsigned, pad::Int, neg::Bool) if neg; a[1]='-'; end ASCIIString(a) end -base(b::Int, x::Unsigned, p::Int, n::Bool) = base(_jl_dig_syms, b, x, p, n) -base(s::Array{Uint8}, x::Unsigned, p::Int, n::Bool) = base(s, length(s), x, p, n) -base(b::Union(Int,Array{Uint8}), x::Unsigned, p::Int) = base(b,x,p,false) -base(b::Union(Int,Array{Uint8}), x::Unsigned) = base(b,x,1,false) -base(b::Union(Int,Array{Uint8}), x::Integer, p::Int) = base(b,unsigned(abs(x)),p,x<0) -base(b::Union(Int,Array{Uint8}), x::Integer) = base(b,unsigned(abs(x)),1,x<0) + +base(base::Integer, n::Integer, pad::Integer) = _base(dig_syms,int(base),unsigned(abs(n)),pad,n<0) +base(symbols::Array{Uint8}, n::Integer, p::Integer) = _base(symbols,length(symbols),unsigned(abs(n)),p,n<0) +base(base_or_symbols::Union(Integer,Array{Uint8}), n::Integer) = base(base_or_symbols, n, 1) for sym in (:bin, :oct, :dec, :hex) @eval begin @@ -301,6 +294,17 @@ bits(x::Union(Char,Int32,Uint32,Float32)) = bin(reinterpret(Uint32,x),32) bits(x::Union(Int64,Uint64,Float64)) = bin(reinterpret(Uint64,x),64) bits(x::Union(Int128,Uint128)) = bin(reinterpret(Uint128,x),128) +function digits{T<:Integer}(n::Integer, base::T=10, pad::Int=1) + 2 <= base || error("invalid base: $base") + m = max(pad,ndigits0z(n,base)) + a = zeros(T,m) + for i = 1:m + a[i] = rem(n,base) + n = div(n,base) + end + return a +end + const PRIMES = [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, diff --git a/base/intset.jl b/base/intset.jl index 12bc8e5c65242..5f34c8a6d1ae8 100644 --- a/base/intset.jl +++ b/base/intset.jl @@ -6,91 +6,103 @@ type IntSet IntSet() = new(zeros(Uint32,256>>>5), 256, false) end -IntSet(args...) = (s=IntSet(); for a in args; add(s,a); end; s) +IntSet(args...) = (s=IntSet(); for a in args; add!(s,a); end; s) similar(s::IntSet) = IntSet() copy(s::IntSet) = union!(IntSet(), s) -function grow(s::IntSet, top::Integer) +function sizehint(s::IntSet, top::Integer) if top >= s.limit lim = ((top+31) & -32)>>>5 olsz = length(s.bits) if olsz < lim - grow(s.bits, lim-olsz) + resize!(s.bits, lim) fill = s.fill1s ? uint32(-1) : uint32(0) for i=(olsz+1):lim; s.bits[i] = fill; end end s.limit = top end - s.limit + s end -function add(s::IntSet, n::Integer) +function add!(s::IntSet, n::Integer) if n >= s.limit if s.fill1s return s else lim = int(n + div(n,2)) - grow(s, lim) + sizehint(s, lim) end end s.bits[n>>5 + 1] |= (uint32(1)<<(n&31)) return s end -function add_each(s::IntSet, ns) +function add_each!(s::IntSet, ns) for n in ns - add(s, n) + add!(s, n) end return s end -function del(s::IntSet, n::Integer) +function delete!(s::IntSet, n::Integer, deflt) if n >= s.limit if s.fill1s lim = int(n + div(n,2)) - grow(s, lim) + sizehint(s, lim) else - return s + return deflt end end - s.bits[n>>5 + 1] &= ~(uint32(1)<<(n&31)) - return s + mask = uint32(1)<<(n&31) + idx = n>>5 + 1 + b = s.bits[idx] + if (b&mask)==0; return deflt; end + s.bits[idx] = b&~mask + return n end -function del_each(s::IntSet, ns) +function delete!(s::IntSet, n::Integer) + if delete!(s, n, n+1) == n+1 + throw(KeyError(n)) + end + return n +end + +function del_each!(s::IntSet, ns) for n in ns - del(s, n) + delete!(s, n) end return s end -setdiff(a::IntSet, b::IntSet) = del_each(copy(a),b) +setdiff(a::IntSet, b::IntSet) = del_each!(copy(a),b) +symdiff(a::IntSet, b::IntSet) = a $ b -function del_all(s::IntSet) +function empty!(s::IntSet) s.bits[:] = 0 return s end -function toggle(s::IntSet, n::Integer) +function symdiff!(s::IntSet, n::Integer) if n >= s.limit lim = int(n + dim(n,2)) - grow(s, lim) + sizehint(s, lim) end s.bits[n>>5 + 1] $= (uint32(1)<<(n&31)) - return s + return s end -function toggle_each(s::IntSet, ns) +function symdiff!(s::IntSet, ns) for n in ns - toggle(s, n) + symdiff!(s, n) end return s end -function copy_to(to::IntSet, from::IntSet) - del_all(to) +function copy!(to::IntSet, from::IntSet) + empty!(to) union!(to, from) end @@ -116,24 +128,20 @@ end isempty(s::IntSet) = !s.fill1s && ccall(:bitvector_any1, Uint32, (Ptr{Uint32}, Uint64, Uint64), s.bits, 0, s.limit)==0 -function choose(s::IntSet) +function first(s::IntSet) n = next(s,0)[1] if n >= s.limit - error("choose: set is empty") + error("first: set is empty") end return n end -function pop(s::IntSet) - n = choose(s) - del(s, n) - n -end +shift!(s::IntSet) = delete!(s, first(s)) length(s::IntSet) = int(ccall(:bitvector_count, Uint64, (Ptr{Uint32}, Uint64, Uint64), s.bits, 0, s.limit)) + (s.fill1s ? typemax(Int) - s.limit : 0) -function show(io, s::IntSet) +function show(io::IO, s::IntSet) print(io, "IntSet(") first = true for n in s @@ -157,7 +165,7 @@ end # Math functions function union!(s::IntSet, s2::IntSet) if s2.limit > s.limit - grow(s, s2.limit) + sizehint(s, s2.limit) end lim = length(s2.bits) for n = 1:lim @@ -174,11 +182,11 @@ end union(s1::IntSet, s2::IntSet) = (s1.limit >= s2.limit ? union!(copy(s1), s2) : union!(copy(s2), s1)) -add_each(s::IntSet, s2::IntSet) = union!(s, s2) +add_each!(s::IntSet, s2::IntSet) = union!(s, s2) function intersect!(s::IntSet, s2::IntSet) if s2.limit > s.limit - grow(s, s2.limit) + sizehint(s, s2.limit) end lim = length(s2.bits) for n = 1:lim @@ -205,9 +213,9 @@ end complement(s::IntSet) = complement!(copy(s)) -function xor!(s::IntSet, s2::IntSet) +function symdiff!(s::IntSet, s2::IntSet) if s2.limit > s.limit - grow(s, s2.limit) + sizehint(s, s2.limit) end lim = length(s2.bits) for n = 1:lim @@ -222,7 +230,8 @@ function xor!(s::IntSet, s2::IntSet) s end -($)(s1::IntSet, s2::IntSet) = (s1.limit >= s2.limit ? xor!(copy(s1), s2) : xor!(copy(s2), s1)) +($)(s1::IntSet, s2::IntSet) = + (s1.limit >= s2.limit ? symdiff!(copy(s1), s2) : symdiff!!(copy(s2), s1)) |(s::IntSet, s2::IntSet) = union(s, s2) (&)(s::IntSet, s2::IntSet) = intersect(s, s2) diff --git a/base/io.jl b/base/io.jl index 5cef56089bcc8..b3881acc98664 100644 --- a/base/io.jl +++ b/base/io.jl @@ -1,6 +1,6 @@ ## core stream types ## -abstract IO +# the first argument to any IO MUST be a POINTER (to a JL_STREAM) or using show on it will cause memory corruption # Generic IO functions @@ -28,16 +28,20 @@ end write(s::IO, x::Uint8) = error(typeof(s)," does not support byte I/O") if ENDIAN_BOM == 0x01020304 - function write(s, x::Integer) - for n = sizeof(x):-1:1 + function write(s::IO, x::Integer) + sz = sizeof(x) + for n = sz:-1:1 write(s, uint8((x>>>((n-1)<<3)))) end + sz end else - function write(s, x::Integer) - for n = 1:sizeof(x) + function write(s::IO, x::Integer) + sz = sizeof(x) + for n = 1:sz write(s, uint8((x>>>((n-1)<<3)))) end + sz end end @@ -46,9 +50,11 @@ write(s::IO, x::Float32) = write(s, box(Int32,unbox(Float32,x))) write(s::IO, x::Float64) = write(s, box(Int64,unbox(Float64,x))) function write(s::IO, a::AbstractArray) - for i = 1:numel(a) - write(s, a[i]) + nb = 0 + for i = 1:length(a) + nb += write(s, a[i]) end + nb end function write(s::IO, c::Char) @@ -70,8 +76,9 @@ function write(s::IO, c::Char) write(s, uint8(((c >> 6) & 0x3F ) | 0x80)) write(s, uint8(( c & 0x3F ) | 0x80)) return 4 + else + return write(s, '\ufffd') end - error("invalid Unicode code point: U+", hex(c)) end # all subtypes should implement this @@ -97,7 +104,7 @@ read{T}(s::IO, t::Type{T}, d1::Integer, dims::Integer...) = read{T}(s::IO, ::Type{T}, dims::Dims) = read(s, Array(T, dims)) function read{T}(s::IO, a::Array{T}) - for i = 1:numel(a) + for i = 1:length(a) a[i] = read(s, T) end return a @@ -110,7 +117,7 @@ function read(s::IO, ::Type{Char}) end # mimic utf8.next function - trailing = Base._jl_utf8_trailing[ch+1] + trailing = Base.utf8_trailing[ch+1] c::Uint32 = 0 for j = 1:trailing c += ch @@ -118,13 +125,18 @@ function read(s::IO, ::Type{Char}) ch = read(s, Uint8) end c += ch - c -= Base._jl_utf8_offset[trailing+1] + c -= Base.utf8_offset[trailing+1] char(c) end -function readuntil(s::IO, delim) +function readuntil(s::IO, delim::Char) + if delim < 0x80 + data = readuntil(s, uint8(delim)) + enc = byte_string_classify(data) + return (enc==1) ? ASCIIString(data) : UTF8String(data) + end out = memio() - while (!eof(s)) + while !eof(s) c = read(s, Char) write(out, c) if c == delim @@ -134,43 +146,59 @@ function readuntil(s::IO, delim) takebuf_string(out) end +function readuntil{T}(s::IO, delim::T) + out = T[] + while !eof(s) + c = read(s, T) + push!(out, c) + if c == delim + break + end + end + out +end + readline(s::IO) = readuntil(s, '\n') function readall(s::IO) out = memio() - while (!eof(s)) + while !eof(s) a = read(s, Uint8) write(out, a) end takebuf_string(out) end -readchomp(x) = chomp(readall(x)) +readchomp(x) = chomp!(readall(x)) ## high-level iterator interfaces ## type EachLine stream::IO + ondone::Function + EachLine(stream) = EachLine(stream, ()->nothing) + EachLine(stream, ondone) = new(stream, ondone) end -each_line(stream::IO) = EachLine(stream) +eachline(stream::IO) = EachLine(stream) -start(itr::EachLine) = readline(itr.stream) -function done(itr::EachLine, line) - if !isempty(line) +start(itr::EachLine) = nothing +function done(itr::EachLine, nada) + if !eof(itr.stream) return false end close(itr.stream) + itr.ondone() true end -next(itr::EachLine, this_line) = (this_line, readline(itr.stream)) +next(itr::EachLine, nada) = (readline(itr.stream), nothing) function readlines(s, fx::Function...) a = {} - for l = each_line(s) + for l in eachline(s) for f in fx l = f(l) end - push(a, l) + push!(a, l) end return a end @@ -188,26 +216,26 @@ else end type IOStream <: IO - # NOTE: for some reason the order of these field is significant!? + handle::Ptr{Void} ios::Array{Uint8,1} name::String - IOStream(name::String, buf::Array{Uint8,1}) = new(buf, name) - - # TODO: delay adding finalizer, e.g. for memio with a small buffer, or - # in the case where we takebuf it. - function IOStream(name::String, finalize::Bool) - x = new(zeros(Uint8,sizeof_ios_t), name) - if finalize - finalizer(x, close) - end - return x + IOStream(name::String, buf::Array{Uint8,1}) = new(pointer(buf), buf, name) +end +# TODO: delay adding finalizer, e.g. for memio with a small buffer, or +# in the case where we takebuf it. +function IOStream(name::String, finalize::Bool) + buf = zeros(Uint8,sizeof_ios_t) + x = IOStream(name, buf) + if finalize + finalizer(x, close) end - IOStream(name::String) = IOStream(name, true) + return x end +IOStream(name::String) = IOStream(name, true) convert(T::Type{Ptr{Void}}, s::IOStream) = convert(T, s.ios) -show(io, s::IOStream) = print(io, "IOStream(", s.name, ")") +show(io::IO, s::IOStream) = print(io, "IOStream(", s.name, ")") fd(s::IOStream) = ccall(:jl_ios_fd, Int, (Ptr{Void},), s.ios) close(s::IOStream) = ccall(:ios_close, Void, (Ptr{Void},), s.ios) flush(s::IOStream) = ccall(:ios_flush, Void, (Ptr{Void},), s.ios) @@ -245,12 +273,8 @@ fdio(name::String, fd::Integer) = fdio(name, fd, false) fdio(fd::Integer, own::Bool) = fdio(string(""), fd, own) fdio(fd::Integer) = fdio(fd, false) -make_stdin_stream() = fdio("", ccall(:jl_stdin, Int32, ())) -make_stderr_stream() = fdio("", ccall(:jl_stderr, Int32, ())) -make_stdout_stream() = IOStream("", ccall(:jl_stdout_stream, Any, ())) - function open(fname::String, rd::Bool, wr::Bool, cr::Bool, tr::Bool, ff::Bool) - s = IOStream(strcat("")) + s = IOStream(string("")) if ccall(:ios_file, Ptr{Void}, (Ptr{Uint8}, Ptr{Uint8}, Int32, Int32, Int32, Int32), s.ios, fname, rd, wr, cr, tr) == C_NULL @@ -292,31 +316,32 @@ memio() = memio(0, true) ## low-level calls ## -write(s::IOStream, b::Uint8) = ccall(:ios_putc, Int32, (Int32, Ptr{Void}), b, s.ios) +write(s::IOStream, b::Uint8) = int(ccall(:jl_putc, Int32, (Uint8, Ptr{Void}), b, s.ios)) function write{T}(s::IOStream, a::Array{T}) - if isa(T,BitsKind) - ccall(:ios_write, Uint, (Ptr{Void}, Ptr{Void}, Uint), - s.ios, a, numel(a)*sizeof(T)) + if isbits(T) + ccall(:ios_write, Int, (Ptr{Void}, Ptr{Void}, Uint), + s.ios, a, length(a)*sizeof(T)) else - invoke(write, (Any, Array), s, a) + invoke(write, (IO, Array), s, a) end end function write(s::IOStream, p::Ptr, nb::Integer) - ccall(:ios_write, Uint, (Ptr{Void}, Ptr{Void}, Uint), s.ios, p, nb) + ccall(:ios_write, Int, (Ptr{Void}, Ptr{Void}, Uint), s.ios, p, nb) end function write{T,N,A<:Array}(s::IOStream, a::SubArray{T,N,A}) - if !isa(T,BitsKind) || stride(a,1)!=1 + if !isbits(T) || stride(a,1)!=1 return invoke(write, (Any, AbstractArray), s, a) end colsz = size(a,1)*sizeof(T) if N<=1 - write(s, pointer(a, 1), colsz) + return write(s, pointer(a, 1), colsz) else cartesian_map((idxs...)->write(s, pointer(a, idxs), colsz), tuple(1, size(a)[2:]...)) + return colsz*trailingsize(a,2) end end @@ -331,18 +356,22 @@ function read(s::IOStream, ::Type{Uint8}) uint8(b) end -function read{T<:Union(Int8,Uint8,Int16,Uint16,Int32,Uint32,Int64,Uint64,Int128,Uint128,Float32,Float64,Complex64,Complex128)}(s::IOStream, a::Array{T}) - nb = numel(a)*sizeof(T) - if ccall(:ios_readall, Uint, - (Ptr{Void}, Ptr{Void}, Uint), s.ios, a, nb) < nb - throw(EOFError()) +function read{T}(s::IOStream, a::Array{T}) + if isbits(T) + nb = length(a)*sizeof(T) + if ccall(:ios_readall, Uint, + (Ptr{Void}, Ptr{Void}, Uint), s.ios, a, nb) < nb + throw(EOFError()) + end + else + invoke(read, (IO, Array), s, a) end a end ## text I/O ## -write(s::IOStream, c::Char) = ccall(:ios_pututf8, Int32, (Ptr{Void}, Char), s.ios, c) +write(s::IOStream, c::Char) = int(ccall(:ios_pututf8, Int32, (Ptr{Void}, Char), s.ios, c)) read(s::IOStream, ::Type{Char}) = ccall(:jl_getutf8, Char, (Ptr{Void},), s.ios) takebuf_string(s::IOStream) = @@ -371,25 +400,10 @@ function repr(x) takebuf_string(s) end -# using this is not recommended -function with_output_to_string(thunk) - global OUTPUT_STREAM - oldio = OUTPUT_STREAM - m = memio() - OUTPUT_STREAM = m - try - thunk() - finally - OUTPUT_STREAM = oldio - end - takebuf_string(m) -end - -write(x) = write(OUTPUT_STREAM::IOStream, x) +write(x) = write(OUTPUT_STREAM::IO, x) -function readuntil(s::IOStream, delim) - # TODO: faster versions that avoid the encoding check - ccall(:jl_readuntil, ByteString, (Ptr{Void}, Uint8), s.ios, delim) +function readuntil(s::IOStream, delim::Uint8) + ccall(:jl_readuntil, Array{Uint8,1}, (Ptr{Void}, Uint8), s.ios, delim) end function readall(s::IOStream) @@ -399,111 +413,85 @@ function readall(s::IOStream) end readall(filename::String) = open(readall, filename) -## select interface ## - -const sizeof_fd_set = int(ccall(:jl_sizeof_fd_set, Int32, ())) - -type FDSet - data::Array{Uint8,1} - nfds::Int32 - - function FDSet() - ar = Array(Uint8, sizeof_fd_set) - ccall(:jl_fd_zero, Void, (Ptr{Void},), ar) - new(ar, 0) - end -end - -isempty(s::FDSet) = (s.nfds==0) - -function add(s::FDSet, i::Integer) - if !(0 <= i < sizeof_fd_set*8) - error("invalid descriptor ", i) - end - ccall(:jl_fd_set, Void, (Ptr{Void}, Int32), s.data, i) - if i >= s.nfds - s.nfds = i+1 - end - return s -end - -function has(s::FDSet, i::Integer) - if 0 <= i < sizeof_fd_set*8 - return ccall(:jl_fd_isset, Int32, (Ptr{Void}, Int32), s.data, i)!=0 - end - return false -end - -function del(s::FDSet, i::Integer) - if 0 <= i < sizeof_fd_set*8 - ccall(:jl_fd_clr, Void, (Ptr{Void}, Int32), s.data, i) - if i == s.nfds-1 - s.nfds -= 1 - while s.nfds>0 && !has(s, s.nfds-1) - s.nfds -= 1 +# based on code by Glen Hertz +function readuntil(s::IO, t::String) + l = length(t) + if l == 0 + return "" + end + if l > 40 + warn("readuntil(IO,String) will perform poorly with a long string") + end + out = IOBuffer() + m = Array(Char, l) # last part of stream to match + t = collect(t) + i = 0 + while !eof(s) + i += 1 + c = read(s, Char) + write(out, c) + if i <= l + m[i] = c + else + # shift to last part of s + for j = 2:l + m[j-1] = m[j] end + m[l] = c + end + if i >= l && m == t + break end end - return s + return takebuf_string(out) end -function del_all(s::FDSet) - ccall(:jl_fd_zero, Void, (Ptr{Void},), s.data) - s.nfds = 0 - return s +## Character streams ## +const _chtmp = Array(Char, 1) +function peekchar(s::IOStream) + if ccall(:ios_peekutf8, Int32, (Ptr{Void}, Ptr{Uint32}), s, _chtmp) < 0 + return char(-1) + end + return _chtmp[1] end -begin - local tv = Array(Uint8, int(ccall(:jl_sizeof_timeval, Int32, ()))) - global select_read - function select_read(readfds::FDSet, timeout::Real) - if timeout == Inf - tout = C_NULL - else - ccall(:jl_set_timeval, Void, (Ptr{Void}, Float64), tv, timeout) - tout = convert(Ptr{Void}, tv) - end - ccall(:select, Int32, - (Int32, Ptr{Void}, Ptr{Void}, Ptr{Void}, Ptr{Void}), - readfds.nfds, readfds.data, C_NULL, C_NULL, tout) - end +function peek(s::IOStream) + ccall(:ios_peekc, Int32, (Ptr{Void},), s) end -## Character streams ## -const _wstmp = Array(Char, 1) function eatwspace(s::IOStream) - status = ccall(:ios_peekutf8, Int32, (Ptr{Void}, Ptr{Uint32}), s.ios, _wstmp) - while status > 0 && iswspace(_wstmp[1]) + ch = peekchar(s); status = int(ch) + while status >= 0 && isspace(ch) read(s, Char) # advance one character - status = ccall(:ios_peekutf8, Int32, (Ptr{Void}, Ptr{Uint32}), s.ios, _wstmp) + ch = peekchar(s); status = int(ch) end end function eatwspace_comment(s::IOStream, cmt::Char) - status = ccall(:ios_peekutf8, Int32, (Ptr{Void}, Ptr{Uint32}), s.ios, _wstmp) - while status > 0 && (iswspace(_wstmp[1]) || _wstmp[1] == cmt) - if _wstmp[1] == cmt + ch = peekchar(s); status = int(ch) + while status >= 0 && (isspace(ch) || ch == cmt) + if ch == cmt readline(s) else read(s, Char) # advance one character end - status = ccall(:ios_peekutf8, Int32, (Ptr{Void}, Ptr{Uint32}), s.ios, _wstmp) + ch = peekchar(s); status = int(ch) end end -# bit array I/O +# BitArray I/O write(s::IO, B::BitArray) = write(s, B.chunks) read(s::IO, B::BitArray) = read(s, B.chunks) -function mmap_bitarray{T<:Integer,N}(::Type{T}, dims::NTuple{N,Int}, s::IOStream, offset::FileOffset) +function mmap_bitarray{N}(dims::NTuple{N,Int}, s::IOStream, offset::FileOffset) prot, flags, iswrite = mmap_stream_settings(s) if length(dims) == 0 dims = 0 end n = prod(dims) - nc = _jl_num_bit_chunks(n) - B = BitArray{T,N}() + nc = num_bit_chunks(n) + B = BitArray{N}() chunks = mmap_array(Uint64, (nc,), s, offset) if iswrite chunks[end] &= @_msk_end n @@ -517,7 +505,10 @@ function mmap_bitarray{T<:Integer,N}(::Type{T}, dims::NTuple{N,Int}, s::IOStream B.dims = dims return B end -mmap_bitarray{T<:Integer,N}(::Type{T}, dims::NTuple{N,Int}, s::IOStream) = mmap_bitarray(T, dims, s, position(s)) +mmap_bitarray{N}(::Type{Bool}, dims::NTuple{N,Int}, s::IOStream, offset::FileOffset) = + mmap_bitarray(dims, s, offset) +mmap_bitarray{N}(::Type{Bool}, dims::NTuple{N,Int}, s::IOStream) = mmap_bitarray(dims, s, position(s)) +mmap_bitarray{N}(dims::NTuple{N,Int}, s::IOStream) = mmap_bitarray(dims, s, position(s)) -msync{T}(B::BitArray{T}, flags::Integer) = msync(pointer(B.chunks), flags) -msync{T}(B::BitArray{T}) = msync(B.chunks,MS_SYNC) +msync(B::BitArray, flags::Integer) = msync(pointer(B.chunks), flags) +msync(B::BitArray) = msync(B.chunks,MS_SYNC) diff --git a/base/iobuffer.jl b/base/iobuffer.jl new file mode 100644 index 0000000000000..3038697ed81c7 --- /dev/null +++ b/base/iobuffer.jl @@ -0,0 +1,209 @@ +## work with Vector{Uint8} via I/O primitives ## + +# Stateful string +type IOBuffer <: IO + data::Vector{Uint8} + readable::Bool + writable::Bool + seekable::Bool # if not seekable, free to destroy (compact) past read data + append::Bool # add data at end instead of at pointer + size::Int + maxsize::Int # pre-allocated, fixed array size + ptr::Int # read (and maybe write) pointer + IOBuffer(data::Vector{Uint8},readable::Bool,writable::Bool,seekable::Bool,append::Bool,maxsize::Int) = + new(data,readable,writable,seekable,append,length(data),maxsize,1) +end + +# PipeBuffers behave like Unix Pipes. They are readable and writable, the act appendable, and not seekable. +PipeBuffer(data::Vector{Uint8},maxsize::Int) = IOBuffer(data,true,true,false,true,maxsize) +PipeBuffer(data::Vector{Uint8}) = PipeBuffer(data,typemax(Int)) +PipeBuffer() = PipeBuffer(Uint8[]) +PipeBuffer(maxsize::Int) = (x = PipeBuffer(Array(Uint8,maxsize),data,maxsize); x.size=0; x) + +# IOBuffers behave like Files. They are readable and writable. They are seekable. (They can be appendable). +IOBuffer(data::Vector{Uint8},readable::Bool,writable::Bool,maxsize::Int) = + IOBuffer(data,readable,writable,true,false,maxsize) +IOBuffer(data::Vector{Uint8},readable::Bool,writable::Bool) = IOBuffer(data,readable,writable,typemax(Int)) +IOBuffer(data::Vector{Uint8}) = IOBuffer(data, true, false) +IOBuffer(str::String) = IOBuffer(str.data, true, false) +IOBuffer(readable::Bool,writable::Bool) = IOBuffer(Uint8[],readable,writable) +IOBuffer() = IOBuffer(Uint8[], true, true) +IOBuffer(maxsize::Int) = (x=IOBuffer(Array(Uint8,maxsize),true,true,maxsize); x.size=0; x) + +function read{T}(from::IOBuffer, a::Array{T}) + if !from.readable error("read failed") end + if isbits(T) + nb = length(a)*sizeof(T) + if nb > nb_available(from) + throw(EOFError()) + end + ccall(:memcpy, Void, (Ptr{Void}, Ptr{Void}, Int), a, pointer(from.data,from.ptr), nb) + from.ptr += nb + return a + else + error("Read from IOBuffer only supports bits types or arrays of bits types; got "*string(T)*".") + end +end + +function read(from::IOBuffer, ::Type{Uint8}) + if !from.readable error("read failed") end + if from.ptr > from.size + throw(EOFError()) + end + byte = from.data[from.ptr] + from.ptr += 1 + return byte +end + +read{T}(from::IOBuffer, ::Type{Ptr{T}}) = convert(Ptr{T}, read(from, Uint)) + +# TODO: IOBuffer is not iterable, so doesn't really have a length. +# This should maybe be sizeof() instead. +#length(io::IOBuffer) = (io.seekable ? io.size : nb_available(io)) +nb_available(io::IOBuffer) = io.size - io.ptr + 1 +skip(io::IOBuffer, n::Integer) = (io.ptr = min(io.ptr + n, io.size+1)) +function seek(io::IOBuffer, n::Integer) + if !io.seekable error("seek failed") end + io.ptr = min(n+1, io.size+1) + return true +end +function seek_end(io::IOBuffer) + io.ptr = io.size+1 + return true +end +position(io::IOBuffer) = io.ptr-1 +function truncate(io::IOBuffer, n::Integer) + if !io.writable error("truncate failed") end + if !io.seekable error("truncate failed") end #because absolute offsets are meaningless + if n > io.maxsize || n < 0 error("truncate failed") end + if n > length(io.data) + resize!(io.data, n) + end + io.data[io.size+1:end] = 0 + io.size = n + io.ptr = min(io.ptr, n+1) + return true +end +function compact(io::IOBuffer) + if !io.writable error("compact failed") end + if io.seekable error("compact failed") end + ccall(:memmove, Void, (Ptr{Void},Ptr{Void},Int), io.data, pointer(io.data,io.ptr), nb_available(io)) + io.size -= io.ptr - 1 + io.ptr = 1 + return true +end +function ensureroom(io::IOBuffer, nshort::Int) + if !io.writable error("ensureroom failed") end + if !io.seekable + if nshort < 0 error("ensureroom failed") end + if io.ptr > 1 && io.size <= io.ptr - 1 + io.ptr = 1 + io.size = 0 + elseif (io.size+nshort > io.maxsize) || + (io.ptr > io.size - io.ptr > 4096) || + (io.ptr > 262144) + # apply somewhat arbitrary heuristics to decide when to destroy + # old, read data to make more room for new data + compact(io) + end + end + n = min(nshort + (io.append ? io.size : io.ptr-1), io.maxsize) + if n > length(io.data) + resize!(io.data, n) + end + return io +end +eof(io::IOBuffer) = (io.ptr-1 == io.size) +function close(io::IOBuffer) + if io.writable + resize!(io.data, 0) + else + io.data = Uint8[] + end + io.readable = false + io.writable = false + io.seekable = false + io.size = 0 + io.maxsize = 0 + io.ptr = 1 + nothing +end +function bytestring(io::IOBuffer) + if !io.readable error("bytestring read failed") end + if !io.seekable error("bytestring read failed") end + bytestring(io.data[1:io.size]) +end +function takebuf_array(io::IOBuffer) + if io.seekable + data = io.data + if io.writable + maxsize = (io.maxsize == typemax(Int) ? 0 : io.maxsize) + io.data = Array(Uint8,maxsize) + else + data = copy(data) + end + resize!(data,io.size) + else + nbytes = nb_available(io) + a = Array(Uint8, nbytes) + data = read(io, a) + end + if io.writable + io.ptr = 1 + io.size = 0 + end + data +end +takebuf_string(io::IOBuffer) = bytestring(takebuf_array(io)) + +function write_sub{T}(to::IOBuffer, a::Array{T}, offs, nel) + if !to.writable; error("write failed") end + if offs+nel-1 > length(a) || offs < 1 || nel < 0 + throw(BoundsError()) + end + if isbits(T) + nb = nel*sizeof(T) + ensureroom(to, nb) + ptr = (to.append ? to.size+1 : to.ptr) + nb = min(nb, length(to.data) - ptr + 1) + ccall(:memcpy, Void, (Ptr{Void}, Ptr{Void}, Int), pointer(to.data,ptr), pointer(a,offs), nb) + to.size = max(to.size, ptr - 1 + nb) + if !to.append; to.ptr += nb; end + else + error("Write to IOBuffer only supports bits types or arrays of bits types; got "*string(T)*".") + end + nb +end + +write(to::IOBuffer, a::Array) = write_sub(to, a, 1, length(a)) + +function write(to::IOBuffer, a::Uint8) + if !to.writable error("write failed") end + ensureroom(to, 1) + ptr = (to.append ? to.size+1 : to.ptr) + if ptr > to.maxsize + return 0 + else + to.data[ptr] = a + end + to.size = max(to.size, ptr) + if !to.append; to.ptr += 1; end + sizeof(Uint8) +end + +write(to::IOBuffer, p::Ptr) = write(to, convert(Uint, p)) + +readbytes(io::IOBuffer,nb::Integer) = bytestring(read(io, Array(Uint8, nb))) +readall(io::IOBuffer) = readbytes(io,nb_available(io)) +function search(buf::IOBuffer, delim) + p = pointer(buf.data, buf.ptr) + q = ccall(:memchr,Ptr{Uint8},(Ptr{Uint8},Int32,Int32),p,delim,nb_available(buf)) + nb = (q == C_NULL ? 0 : q-p+1) +end +function readuntil(io::IOBuffer, delim::Uint8) + nb = search(io, delim) + if nb == 0 + nb = nb_available(io) + end + read(io, Array(Uint8, nb)) +end diff --git a/base/iterator.jl b/base/iterator.jl index fb3d7709eff98..25a11329d8c86 100644 --- a/base/iterator.jl +++ b/base/iterator.jl @@ -17,19 +17,18 @@ done(e::Enumerate, state) = done(e.itr, state[2]) type Zip itrs::Vector{Any} - Zip(itrs...) = new({itrs...}) + vals::Vector{Any} # temp storage for use by next() + Zip(itrs...) = new({itrs...}, Array(Any, length(itrs))) end zip(itrs...) = Zip(itrs...) length(z::Zip) = min(length, z.itrs) start(z::Zip) = { start(itr) for itr in z.itrs } function next(z::Zip, state) - v = Array(Any, length(z.itrs)) - s = Array(Any, length(z.itrs)) for i = 1:length(z.itrs) - v[i], s[i] = next(z.itrs[i], state[i]) + z.vals[i], state[i] = next(z.itrs[i], state[i]) end - tuple(v...), s + tuple(z.vals...), state end function done(z::Zip, state) if isempty(z.itrs) @@ -51,8 +50,8 @@ type Filter{I} end filter(flt::Function, itr) = Filter(flt, itr) -start(f::Filter) = _jl_start_filter(f.flt, f.itr) -function _jl_start_filter(pred, itr) +start(f::Filter) = start_filter(f.flt, f.itr) +function start_filter(pred, itr) s = start(itr) while !done(itr,s) v,t = next(itr,s) @@ -64,8 +63,8 @@ function _jl_start_filter(pred, itr) s end -next(f::Filter, s) = _jl_advance_filter(f.flt, f.itr, s) -function _jl_advance_filter(pred, itr, s) +next(f::Filter, s) = advance_filter(f.flt, f.itr, s) +function advance_filter(pred, itr, s) v,s = next(itr,s) while !done(itr,s) w,t = next(itr,s) @@ -79,6 +78,17 @@ end done(f::Filter, s) = done(f.itr,s) +# Rest -- iterate starting at the given state +immutable Rest{I,S} + itr::I + st::S +end +rest(itr,state) = Rest(itr,state) + +start(i::Rest) = i.st +next(i::Rest, st) = next(i.itr, st) +done(i::Rest, st) = done(i.itr, st) + # reverse type Reverse diff --git a/base/lapack.jl b/base/lapack.jl deleted file mode 100644 index e294e00f2fd94..0000000000000 --- a/base/lapack.jl +++ /dev/null @@ -1,1513 +0,0 @@ -## The LAPACK module of interfaces to LAPACK subroutines -module LAPACK - -liblapack = Base.liblapack_name - -typealias LapackChar Char -type LapackException <: Exception - info::Int32 -end -type LapackDimMisMatch <: Exception - name::ASCIIString -end - -function chkstride1(A::StridedVecOrMat...) - for a in A - if stride(a,1) != 1 error("LAPACK: Matrix must have contiguous columns") end - end -end - -function chksquare(A::Matrix...) - for a in A - m, n = size(a) - if m != n error("LAPACK: Matrix must be square") end - end -end - -# (GB) general banded matrices, LU decomposition and solver -for (gbtrf, gbtrs, elty) in - ((:dgbtrf_,:dgbtrs_,:Float64), - (:sgbtrf_,:sgbtrs_,:Float32), - (:zgbtrf_,:zgbtrs_,:Complex128), - (:cgbtrf_,:cgbtrs_,:Complex64)) - @eval begin - # SUBROUTINE DGBTRF( M, N, KL, KU, AB, LDAB, IPIV, INFO ) - # * .. Scalar Arguments .. - # INTEGER INFO, KL, KU, LDAB, M, N - # * .. Array Arguments .. - # INTEGER IPIV( * ) - # DOUBLE PRECISION AB( LDAB, * ) - function gbtrf!(kl::Integer, ku::Integer, m::Integer, AB::StridedMatrix{$elty}) - chkstride1(AB) - info = Array(Int32, 1) - n = size(AB, 2) - mnmn = min(m, n) - ipiv = Array(Int32, mnmn) - ccall(($(string(gbtrf)),liblapack), Void, - (Ptr{Int32}, Ptr{Int32}, Ptr{Int32}, Ptr{Int32}, - Ptr{$elty}, Ptr{Int32}, Ptr{Int32}, Ptr{Int32}), - &m, &n, &kl, &ku, AB, &stride(AB,2), ipiv, info) - if info[1] != 0 throw(LapackException(info[1])) end - AB, ipiv - end - # SUBROUTINE DGBTRS( TRANS, N, KL, KU, NRHS, AB, LDAB, IPIV, B, LDB, INFO) - # * .. Scalar Arguments .. - # CHARACTER TRANS - # INTEGER INFO, KL, KU, LDAB, LDB, N, NRHS - # * .. Array Arguments .. - # INTEGER IPIV( * ) - # DOUBLE PRECISION AB( LDAB, * ), B( LDB, * ) - function gbtrs!(trans::LapackChar, kl::Integer, ku::Integer, m::Integer, - AB::StridedMatrix{$elty}, ipiv::Vector{Int32}, - B::StridedVecOrMat{$elty}) - chkstride1(AB, B) - info = Array(Int32, 1) - n = size(AB,2) - if m != n || m != size(B,1) throw(LapackDimMisMatch("gbtrs!")) end - ccall(($(string(gbtrs)),liblapack), Void, - (Ptr{Uint8}, Ptr{Int32}, Ptr{Int32}, Ptr{Int32}, Ptr{Int32}, - Ptr{$elty}, Ptr{Int32}, Ptr{Int32}, Ptr{Int32}), - &trans, &n, &kl, &ku, &size(B,2), AB, &stride(AB,2), ipiv, - B, &stride(B,2), info) - if info[1] != 0 throw(LapackException(info[1])) end - B - end - end -end - -## (GE) general matrices: balancing and back-transforming -for (gebal, gebak, elty, relty) in - ((:dgebal_, :dgebak_, :Float64, :Float64), - (:sgebal_, :sgebak_, :Float32, :Float32), - (:zgebal_, :zgebak_, :Complex128, :Float64), - (:cgebal_, :cgebak_, :Complex64, :Float32)) - @eval begin - # SUBROUTINE DGEBAL( JOB, N, A, LDA, ILO, IHI, SCALE, INFO ) - #* .. Scalar Arguments .. - # CHARACTER JOB - # INTEGER IHI, ILP, INFO, LDA, N - # .. Array Arguments .. - # DOUBLE PRECISION A( LDA, * ), SCALE( * ) - function gebal!(job::LapackChar, A::StridedMatrix{$elty}) - chkstride1(A) - chksquare(A) - n = size(A, 2) - info = Array(Int32, 1) - ihi = Array(Int32, 1) - ilo = Array(Int32, 1) - scale = Array($relty, n) - ccall(($(string(gebal)),liblapack), Void, - (Ptr{Uint8}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, - Ptr{Int32}, Ptr{Int32}, Ptr{$relty}, Ptr{Int32}), - &job, &n, A, &stride(A,2), ilo, ihi, scale, info) - if info[1] != 0 throw(LapackException(info[1])) end - ilo[1], ihi[1], scale - end - # SUBROUTINE DGEBAK( JOB, SIDE, N, ILO, IHI, SCALE, M, V, LDV, INFO ) - #* .. Scalar Arguments .. - # CHARACTER JOB, SIDE - # INTEGER IHI, ILP, INFO, LDV, M, N - # .. Array Arguments .. - # DOUBLE PRECISION SCALE( * ), V( LDV, * ) - function gebak!(job::LapackChar, side::LapackChar, - ilo::Int32, ihi::Int32, scale::Vector{$elty}, - V::StridedMatrix{$elty}) - chkstride1(V) - chksquare(V) - info = Array(Int32, 1) - ccall(($(string(gebak)),liblapack), Void, - (Ptr{Uint8}, Ptr{Uint8}, Ptr{Int32}, Ptr{Int32}, Ptr{Int32}, - Ptr{$elty}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, Ptr{Int32}), - &job, &side, &size(V,1), &ilo, &ihi, scale, &n, V, &stride(V,2), info) - if info[1] != 0 throw(LapackException(info[1])) end - V - end - end -end - -# (GE) general matrices, direct decompositions -# gebrd - reduction to bidiagonal form Q'*A*P=B where Q and P are orthogonal -# gelqf - unpivoted LQ decomposition -# geqlf - unpivoted QL decomposition -# geqrf - unpivoted QR decomposition -# gegp3 - pivoted QR decomposition -# gerqf - unpivoted RQ decomposition -# getrf - LU decomposition -for (gebrd, gelqf, geqlf, geqrf, geqp3, gerqf, getrf, elty) in - ((:dgebrd_,:dgelqf_,:dgeqlf_,:dgeqrf_,:dgeqp3_,:dgerqf_,:dgetrf_,:Float64), - (:sgebrd_,:sgelqf_,:sgeqlf_,:sgeqrf_,:sgeqp3_,:sgerqf_,:sgetrf_,:Float32), - (:zgebrd_,:zgelqf_,:zgeqlf_,:zgeqrf_,:zgeqp3_,:zgerqf_,:zgetrf_,:Complex128), - (:cgebrd_,:cgelqf_,:cgeqlf_,:cgeqrf_,:cgeqp3_,:cgerqf_,:cgetrf_,:Complex64)) - @eval begin - # SUBROUTINE DGEBRD( M, N, A, LDA, D, E, TAUQ, TAUP, WORK, LWORK, - # INFO ) - # .. Scalar Arguments .. - # INTEGER INFO, LDA, LWORK, M, N - # .. Array Arguments .. - # DOUBLE PRECISION A( LDA, * ), D( * ), E( * ), TAUP( * ), - # TAUQ( * ), WORK( * ) - function gebrd!(A::StridedMatrix{$elty}) - chkstride1(A) - m, n = size(A) - k = min(m, n) - d = Array($elty, k) - s = Array($elty, k) - tauq = Array($elty, k) - taup = Array($elty, k) - work = Array($elty, 1) - lwork = int32(-1) - info = Array(Int32, 1) - for i in 1:2 - ccall(($(string(gebrd)),liblapack), Void, - (Ptr{Int32}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, - Ptr{$elty}, Ptr{$elty}, Ptr{$elty}, Ptr{$elty}, - Ptr{$elty}, Ptr{Int32}, Ptr{Int32}), - &m, &n, A, &stride(A,2), d, s, tauq, taup, work, &lwork, info) - if info[1] != 0 throw(LapackException(info[1])) end - if lwork < 0 - lwork = int32(real(work[1])) - work = Array($elty, lwork) - end - end - end - # SUBROUTINE DGELQF( M, N, A, LDA, TAU, WORK, LWORK, INFO ) - # * .. Scalar Arguments .. - # INTEGER INFO, LDA, LWORK, M, N - # * .. Array Arguments .. - # DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * ) - function gelqf!(A::StridedMatrix{$elty}) - chkstride1(A) - info = Array(Int32, 1) - m = int32(size(A, 1)) - n = int32(size(A, 2)) - lda = int32(stride(A, 2)) - tau = Array($elty, n) - lwork = int32(-1) - work = Array($elty, (1,)) - for i in 1:2 # first call returns lwork as work[1] - ccall(($(string(gelqf)),liblapack), Void, - (Ptr{Int32}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, - Ptr{$elty}, Ptr{$elty}, Ptr{Int32}, Ptr{Int32}), - &m, &n, A, &lda, tau, work, &lwork, info) - if info[1] != 0 throw(LapackException(info[1])) end - if lwork < 0 - lwork = int32(real(work[1])) - work = Array($elty, lwork) - end - end - A, tau - end - # SUBROUTINE DGEQLF( M, N, A, LDA, TAU, WORK, LWORK, INFO ) - # * .. Scalar Arguments .. - # INTEGER INFO, LDA, LWORK, M, N - # * .. Array Arguments .. - # DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * ) - function geqlf!(A::StridedMatrix{$elty}) - chkstride1(A) - info = Array(Int32, 1) - m = int32(size(A, 1)) - n = int32(size(A, 2)) - lda = int32(stride(A, 2)) - tau = Array($elty, n) - lwork = int32(-1) - work = Array($elty, (1,)) - for i in 1:2 # first call returns lwork as work[1] - ccall(($(string(geqlf)),liblapack), Void, - (Ptr{Int32}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, - Ptr{$elty}, Ptr{$elty}, Ptr{Int32}, Ptr{Int32}), - &m, &n, A, &lda, tau, work, &lwork, info) - if info[1] != 0 throw(LapackException(info[1])) end - if lwork < 0 - lwork = int32(real(work[1])) - work = Array($elty, lwork) - end - end - A, tau - end - # SUBROUTINE DGEQP3( M, N, A, LDA, JPVT, TAU, WORK, LWORK, INFO ) - # * .. Scalar Arguments .. - # INTEGER INFO, LDA, LWORK, M, N - # * .. Array Arguments .. - # INTEGER JPVT( * ) - # DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * ) - function geqp3!(A::StridedMatrix{$elty}) - chkstride1(A) - m, n = size(A) - jpvt = zeros(Int32, n) - tau = Array($elty, n) - work = Array($elty, 1) - lwork = int32(-1) - info = Array(Int32, 1) - Rtyp = typeof(real(A[1])) - cmplx = iscomplex(A) - if cmplx rwork = Array(Rtyp, 2n) end - for i in 1:2 - if cmplx - ccall(($(string(geqp3)),liblapack), Void, - (Ptr{Int32}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, - Ptr{Int32}, Ptr{$elty}, Ptr{$elty}, Ptr{Int32}, - Ptr{Rtyp}, Ptr{Int32}), - &m, &n, A, &stride(A,2), jpvt, tau, work, &lwork, rwork, info) - else - ccall(($(string(geqp3)),liblapack), Void, - (Ptr{Int32}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, - Ptr{Int32}, Ptr{$elty}, Ptr{$elty}, Ptr{Int32}, - Ptr{Int32}), - &m, &n, A, &stride(A,2), jpvt, tau, work, &lwork, info) - end - if info[1] != 0 throw(LapackException(info[1])) end - if lwork < 0 - lwork = int32(real(work[1])) - work = Array($elty, lwork) - end - end - A, tau, jpvt - end - ## Several variants of geqrf! could be defined. - ## geqrfp! - positive elements on diagonal of R - ## geqrt! - compact WY representation of Q (blocked algorithm) - ## geqrt3! - recursive algorithm producing compact WY representation of Q - # SUBROUTINE DGEQRF( M, N, A, LDA, TAU, WORK, LWORK, INFO ) - # * .. Scalar Arguments .. - # INTEGER INFO, LDA, LWORK, M, N - # * .. Array Arguments .. - # DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * ) - function geqrf!(A::StridedMatrix{$elty}) - chkstride1(A) - m, n = size(A) - tau = Array($elty, n) - work = Array($elty, 1) - lwork = int32(-1) - info = Array(Int32, 1) - for i in 1:2 # first call returns lwork as work[1] - ccall(($(string(geqrf)),liblapack), Void, - (Ptr{Int32}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, - Ptr{$elty}, Ptr{$elty}, Ptr{Int32}, Ptr{Int32}), - &m, &n, A, &stride(A,2), tau, work, &lwork, info) - if info[1] != 0 throw(LapackException(info[1])) end - if lwork < 0 - lwork = int32(real(work[1])) - work = Array($elty, lwork) - end - end - A, tau - end - # SUBROUTINE DGERQF( M, N, A, LDA, TAU, WORK, LWORK, INFO ) - # * .. Scalar Arguments .. - # INTEGER INFO, LDA, LWORK, M, N - # * .. Array Arguments .. - # DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * ) - function gerqf!(A::StridedMatrix{$elty}) - chkstride1(A) - info = Array(Int32, 1) - m, n = size(A) - tau = Array($elty, n) - lwork = int32(-1) - work = Array($elty, 1) - for i in 1:2 # first call returns lwork as work[1] - ccall(($(string(gerqf)),liblapack), Void, - (Ptr{Int32}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, - Ptr{$elty}, Ptr{$elty}, Ptr{Int32}, Ptr{Int32}), - &m, &n, A, &stride(A,2), tau, work, &lwork, info) - if info[1] != 0 throw(LapackException(info[1])) end - if lwork < 0 - lwork = int32(real(work[1])) - work = Array($elty, lwork) - end - end - A, tau - end - # SUBROUTINE DGETRF( M, N, A, LDA, IPIV, INFO ) - # * .. Scalar Arguments .. - # INTEGER INFO, LDA, M, N - # * .. Array Arguments .. - # INTEGER IPIV( * ) - # DOUBLE PRECISION A( LDA, * ) - function getrf!(A::StridedMatrix{$elty}) - chkstride1(A) - info = Array(Int32, 1) - m, n = size(A) - lda = stride(A, 2) - ipiv = Array(Int32, min(m,n)) - ccall(($(string(getrf)),liblapack), Void, - (Ptr{Int32}, Ptr{Int32}, Ptr{$elty}, - Ptr{Int32}, Ptr{Int32}, Ptr{Int32}), - &m, &n, A, &lda, ipiv, info) - if info[1] < 0 throw(LapackException(info[1])) end - A, ipiv, info[1] - end - end -end - -## (GE) general matrices, solvers with factorization, solver and inverse -for (gels, gesv, getrs, getri, elty) in - ((:dgels_,:dgesv_,:dgetrs_,:dgetri_,:Float64), - (:sgels_,:sgesv_,:sgetrs_,:sgetri_,:Float32), - (:zgels_,:zgesv_,:zgetrs_,:zgetri_,:Complex128), - (:cgels_,:cgesv_,:cgetrs_,:cgetri_,:Complex64)) - @eval begin - # SUBROUTINE DGELS( TRANS, M, N, NRHS, A, LDA, B, LDB, WORK, LWORK,INFO) - # * .. Scalar Arguments .. - # CHARACTER TRANS - # INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS - function gels!(trans::LapackChar, A::StridedMatrix{$elty}, B::StridedVecOrMat{$elty}) - chkstride1(A, B) - btrn = trans == 'T' - m, n = size(A) - if size(B,1) != (btrn ? n : m) throw(LapackDimMisMatch("gels!")) end - info = Array(Int32, 1) - work = Array($elty, 1) - lwork = int32(-1) - for i in 1:2 - ccall(($(string(gels)),liblapack), Void, - (Ptr{Uint8}, Ptr{Int32}, Ptr{Int32}, Ptr{Int32}, - Ptr{$elty}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, - Ptr{$elty}, Ptr{Int32}, Ptr{Int32}), - &(btrn?'T':'N'), &m, &n, &size(B,2), A, &stride(A,2), - B, &stride(B,2), work, &lwork, info) - if info[1] != 0 throw(LapackException(info[1])) end - if lwork < 0 - lwork = int32(real(work[1])) - work = Array($elty, lwork) - end - end - k = min(m, n) - F = m < n ? tril(A[1:k, 1:k]) : triu(A[1:k, 1:k]) - F, isa(B, Vector) ? B[1:k] : B[1:k,:], [sum(B[(k+1):size(B,1), i].^2) for i=1:size(B,2)] - end - # SUBROUTINE DGESV( N, NRHS, A, LDA, IPIV, B, LDB, INFO ) - # * .. Scalar Arguments .. - # INTEGER INFO, LDA, LDB, N, NRHS - # * .. - # * .. Array Arguments .. - # INTEGER IPIV( * ) - # DOUBLE PRECISION A( LDA, * ), B( LDB, * ) - function gesv!(A::StridedMatrix{$elty}, B::StridedVecOrMat{$elty}) - chkstride1(A, B) - chksquare(A) - n = size(A,1) - if size(B,1) != n throw(LapackDimMisMatch("gesv!")) end - ipiv = Array(Int32, n) - info = Array(Int32, 1) - ccall(($(string(gesv)),liblapack), Void, - (Ptr{Int32}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, Ptr{Int32}, - Ptr{$elty}, Ptr{Int32}, Ptr{Int32}), - &n, &size(B,2), A, &stride(A,2), ipiv, B, &stride(B,2), info) - if info[1] < 0 throw(LapackException(info[1])) end - B, A, ipiv, info[1] - end - # SUBROUTINE DGETRS( TRANS, N, NRHS, A, LDA, IPIV, B, LDB, INFO ) - #* .. Scalar Arguments .. - # CHARACTER TRANS - # INTEGER INFO, LDA, LDB, N, NRHS - # .. Array Arguments .. - # INTEGER IPIV( * ) - # DOUBLE PRECISION A( LDA, * ), B( LDB, * ) - function getrs!(trans::LapackChar, A::StridedMatrix{$elty}, ipiv::Vector{Int32}, B::StridedVecOrMat{$elty}) - chkstride1(A, B) - m, n = size(A) - if m != n || size(B, 1) != m error("getrs!: dimension mismatch") end - nrhs = size(B, 2) - info = Array(Int32, 1) - ccall(($(string(getrs)),liblapack), Void, - (Ptr{Uint8}, Ptr{Int32}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, - Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, Ptr{Int32}), - &trans, &n, &size(B,2), A, &stride(A,2), ipiv, B, &stride(B,2), info) - if info[1] != 0 throw(LapackException(info[1])) end - B - end - # SUBROUTINE DGETRI( N, A, LDA, IPIV, WORK, LWORK, INFO ) - #* .. Scalar Arguments .. - # INTEGER INFO, LDA, LWORK, N - #* .. Array Arguments .. - # INTEGER IPIV( * ) - # DOUBLE PRECISION A( LDA, * ), WORK( * ) - function getri!(A::StridedMatrix{$elty}, ipiv::Vector{Int32}) - chkstride1(A) - m, n = size(A) - if m != n || n != numel(ipiv) error("getri!: dimension mismatch") end - lda = stride(A, 2) - info = Array(Int32, 1) - lwork = -1 - work = Array($elty, 1) - for i in 1:2 - ccall(($(string(getri)),liblapack), Void, - (Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, Ptr{Int32}, - Ptr{$elty}, Ptr{Int32}, Ptr{Int32}), - &n, A, &lda, ipiv, work, &lwork, info) - if info[1] != 0 error("getri!: error $(info[1])") end - if lwork < 0 - lwork = int32(real(work[1])) - work = Array($elty, lwork) - end - end - A - end - end -end -for (gelsd, elty) in ((:dgelsd_, Float64), - (:sgelsd_, Float32)) - @eval begin - # SUBROUTINE DGELSD( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK, - # $ WORK, LWORK, IWORK, INFO ) - # * .. Scalar Arguments .. - # INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK - # DOUBLE PRECISION RCOND - # * .. - # * .. Array Arguments .. - # INTEGER IWORK( * ) - # DOUBLE PRECISION A( LDA, * ), B( LDB, * ), S( * ), WORK( * ) - function gelsd!(A::StridedMatrix{$elty}, B::StridedVecOrMat{$elty}, rcond) - LAPACK.chkstride1(A, B) - m, n = size(A) - if size(B,1) != m; throw(LAPACK.LapackDimMisMatch("gelsd!")); end - s = Array($elty, min(m, n)) - rnk = Array(Int32, 1) - info = Array(Int32, 1) - work = Array($elty, 1) - lwork = int32(-1) - iwork = Array(Int32, 1) - for i in 1:2 - ccall(($(string(gelsd)),liblapack), Void, - (Ptr{Int32}, Ptr{Int32}, Ptr{Int32}, - Ptr{$elty}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, - Ptr{$elty}, Ptr{$elty}, Ptr{Int32}, Ptr{$elty}, - Ptr{Int32}, Ptr{Int32}, Ptr{Int32}), - &m, &n, &size(B,2), A, &max(1,stride(A,2)), - B, &max(1,stride(B,2)), s, &rcond, rnk, work, &lwork, iwork, info) - if info[1] != 0 throw(LapackException(info[1])) end - if lwork < 0 - lwork = int32(real(work[1])) - work = Array($elty, lwork) - iwork = Array(Int32, iwork[1]) - end - end - isa(B, Vector) ? B[1:n] : B[1:n,:], rnk[1] - end - gelsd!(A::StridedMatrix{$elty}, B::StridedVecOrMat{$elty}) = gelsd!(A, B, -1.) - end -end -for (gelsd, elty, relty) in ((:zgelsd_, Complex128, Float64), - (:cgelsd_, Complex64, Float32)) - @eval begin - # SUBROUTINE ZGELSD( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK, - # $ WORK, LWORK, RWORK, IWORK, INFO ) - # * .. Scalar Arguments .. - # INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK - # DOUBLE PRECISION RCOND - # * .. - # * .. Array Arguments .. - # INTEGER IWORK( * ) - # DOUBLE PRECISION RWORK( * ), S( * ) - # COMPLEX*16 A( LDA, * ), B( LDB, * ), WORK( * ) - function gelsd!(A::StridedMatrix{$elty}, B::StridedVecOrMat{$elty}, rcond) - LAPACK.chkstride1(A, B) - m, n = size(A) - if size(B,1) != m; throw(LAPACK.LapackDimMisMatch("gelsd!")); end - s = Array($elty, min(m, n)) - rnk = Array(Int32, 1) - info = Array(Int32, 1) - work = Array($elty, 1) - lwork = int32(-1) - rwork = Array($relty, 1) - iwork = Array(Int32, 1) - for i in 1:2 - ccall(($(string(gelsd)),liblapack), Void, - (Ptr{Int32}, Ptr{Int32}, Ptr{Int32}, Ptr{$elty}, - Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, Ptr{$relty}, - Ptr{$relty}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, - Ptr{$relty}, Ptr{Int32}, Ptr{Int32}), - &m, &n, &size(B,2), A, &max(1,stride(A,2)), - B, &max(1,stride(B,2)), s, &rcond, rnk, work, &lwork, rwork, iwork, info) - if info[1] != 0 throw(LapackException(info[1])) end - if lwork < 0 - lwork = int32(real(work[1])) - work = Array($elty, lwork) - rwork = Array($relty, int(rwork[1])) - iwork = Array(Int32, iwork[1]) - end - end - isa(B, Vector) ? B[1:n] : B[1:n,:], rnk[1] - end - gelsd!(A::StridedMatrix{$elty}, B::StridedVecOrMat{$elty}) = gelsd!(A, B, -1.) - end -end - -# (GE) general matrices eigenvalue-eigenvector and singular value decompositions -for (geev, gesvd, gesdd, elty) in - ((:dgeev_,:dgesvd_,:dgesdd_,:Float64), - (:sgeev_,:sgesvd_,:sgesdd_,:Float32), - (:zgeev_,:zgesvd_,:zgesdd_,:Complex128), - (:cgeev_,:cgesvd_,:cgesdd_,:Complex64)) - @eval begin - # SUBROUTINE DGEEV( JOBVL, JOBVR, N, A, LDA, WR, WI, VL, LDVL, VR, - # $ LDVR, WORK, LWORK, INFO ) - # * .. Scalar Arguments .. - # CHARACTER JOBVL, JOBVR - # INTEGER INFO, LDA, LDVL, LDVR, LWORK, N - # * .. Array Arguments .. - # DOUBLE PRECISION A( LDA, * ), VL( LDVL, * ), VR( LDVR, * ), - # $ WI( * ), WORK( * ), WR( * ) - function geev!(jobvl::LapackChar, jobvr::LapackChar, A::StridedMatrix{$elty}) - chkstride1(A) - chksquare(A) - m, n = size(A) - lvecs = jobvl == 'V' - rvecs = jobvr == 'V' - VL = Array($elty, (n, lvecs ? n : 0)) - VR = Array($elty, (n, rvecs ? n : 0)) - Rtyp = typeof(real(A[1])) - cmplx = iscomplex(A) - if cmplx - W = Array($elty, n) - rwork = Array(Rtyp, 2n) - else - WR = Array($elty, n) - WI = Array($elty, n) - end - work = Array($elty, 1) - lwork = int32(-1) - info = Array(Int32, 1) - for i = 1:2 - if cmplx - ccall(($(string(geev)),liblapack), Void, - (Ptr{Uint8}, Ptr{Uint8}, Ptr{Int32}, Ptr{$elty}, - Ptr{Int32}, Ptr{$elty}, Ptr{$elty}, Ptr{Int32}, - Ptr{$elty}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, - Ptr{Rtyp}, Ptr{Int32}), - &jobvl, &jobvr, &n, A, &stride(A,2), W, VL, &n, VR, &n, - work, &lwork, rwork, info) - else - ccall(($(string(geev)),liblapack), Void, - (Ptr{Uint8}, Ptr{Uint8}, Ptr{Int32}, Ptr{$elty}, - Ptr{Int32}, Ptr{$elty}, Ptr{$elty}, Ptr{$elty}, - Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, Ptr{$elty}, - Ptr{Int32}, Ptr{Int32}), - &jobvl, &jobvr, &n, A, &stride(A,2), WR, WI, VL, &n, - VR, &n, work, &lwork, info) - end - if info[1] != 0 throw(LapackException(info[1])) end - if lwork < 0 - lwork = int32(real(work[1])) - work = Array($elty, lwork) - end - end - cmplx ? (VL, W, VR) : (VL, WR, WI, VR) - end - # SUBROUTINE DGESDD( JOBZ, M, N, A, LDA, S, U, LDU, VT, LDVT, WORK, - # LWORK, IWORK, INFO ) - #* .. Scalar Arguments .. - # CHARACTER JOBZ - # INTEGER INFO, LDA, LDU, LDVT, LWORK, M, N - #* .. - #* .. Array Arguments .. - # INTEGER IWORK( * ) - # DOUBLE PRECISION A( LDA, * ), S( * ), U( LDU, * ), - # VT( LDVT, * ), WORK( * ) - function gesdd!(job::LapackChar, A::StridedMatrix{$elty}) - chkstride1(A) - m, n = size(A) - minmn = min(m, n) - if job == 'A' - U = Array($elty, (m, m)) - VT = Array($elty, (n, n)) - elseif job == 'S' - U = Array($elty, (m, minmn)) - VT = Array($elty, (minmn, n)) - elseif job == 'O' - U = Array($elty, (m, m >= n ? 0 : m)) - VT = Array($elty, (n, m >= n ? n : 0)) - else - U = Array($elty, (m, 0)) - VT = Array($elty, (n, 0)) - end - work = Array($elty, 1) - lwork = int32(-1) - Rtyp = typeof(real(A[1])) - S = Array(Rtyp, minmn) - cmplx = iscomplex(A) - if cmplx - rwork = Array(Rtyp, job == 'N' ? 5*minmn : minmn*max(5*minmn+7,2*max(m,n)+2*minmn+1)) - end - iwork = Array(Int32, 8*minmn) - info = Array(Int32, 1) - for i = 1:2 - if cmplx - ccall(($(string(gesdd)),liblapack), Void, - (Ptr{Uint8}, Ptr{Int32}, Ptr{Int32}, Ptr{$elty}, - Ptr{Int32}, Ptr{$elty}, Ptr{$elty}, Ptr{Int32}, - Ptr{$elty}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, - Ptr{Rtyp}, Ptr{Int32}, Ptr{Int32}), - &job, &m, &n, A, &stride(A,2), S, U, &max(1,stride(U,2)), VT, &max(1,stride(VT,2)), - work, &lwork, rwork, iwork, info) - else - ccall(($(string(gesdd)),liblapack), Void, - (Ptr{Uint8}, Ptr{Int32}, Ptr{Int32}, Ptr{$elty}, - Ptr{Int32}, Ptr{$elty}, Ptr{$elty}, Ptr{Int32}, - Ptr{$elty}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, - Ptr{Int32}, Ptr{Int32}), - &job, &m, &n, A, &stride(A,2), S, U, &max(1,stride(U,2)), VT, &max(1,stride(VT,2)), - work, &lwork, iwork, info) - end - if info[1] != 0 throw(LapackException(info[1])) end - if lwork < 0 - lwork = int32(real(work[1])) - work = Array($elty, lwork) - end - end - if job == 'O' - if m >= n return (A, S, VT) - else return (U, S, A) - end - end - return (U, S, VT) - end - # SUBROUTINE DGESVD( JOBU, JOBVT, M, N, A, LDA, S, U, LDU, VT, LDVT, WORK, LWORK, INFO ) - # * .. Scalar Arguments .. - # CHARACTER JOBU, JOBVT - # INTEGER INFO, LDA, LDU, LDVT, LWORK, M, N - # * .. Array Arguments .. - # DOUBLE PRECISION A( LDA, * ), S( * ), U( LDU, * ), - # $ VT( LDVT, * ), WORK( * ) - function gesvd!(jobu::LapackChar, jobvt::LapackChar, A::StridedMatrix{$elty}) - chkstride1(A) - Rtyp = typeof(real(A[1])) - m, n = size(A) - minmn = min(m, n) - S = Array(Rtyp, minmn) - U = Array($elty, jobu == 'A'? (m, m):(jobu == 'S'? (m, minmn) : (m, 0))) - VT = Array($elty, jobvt == 'A'? (n, n):(jobvt == 'S'? (minmn, n) : (n, 0))) - work = Array($elty, 1) - cmplx = iscomplex(A) - if cmplx rwork = Array(Rtyp, 5minmn) end - lwork = int32(-1) - info = Array(Int32, 1) - for i in 1:2 - if cmplx - ccall(($(string(gesvd)),liblapack), Void, - (Ptr{Uint8}, Ptr{Uint8}, Ptr{Int32}, Ptr{Int32}, - Ptr{$elty}, Ptr{Int32}, Ptr{$elty}, Ptr{$elty}, - Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, Ptr{$elty}, - Ptr{Int32}, Ptr{Rtyp}, Ptr{Int32}), - &jobu, &jobvt, &m, &n, A, &stride(A,2), S, U, &max(1,stride(U,2)), VT, &max(1,stride(VT,2)), - work, &lwork, rwork, info) - else - ccall(($(string(gesvd)),liblapack), Void, - (Ptr{Uint8}, Ptr{Uint8}, Ptr{Int32}, Ptr{Int32}, - Ptr{$elty}, Ptr{Int32}, Ptr{$elty}, Ptr{$elty}, - Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, Ptr{$elty}, - Ptr{Int32}, Ptr{Int32}), - &jobu, &jobvt, &m, &n, A, &stride(A,2), S, U, &max(1,stride(U,2)), VT, &max(1,stride(VT,2)), - work, &lwork, info) - end - if info[1] != 0 throw(LapackException(info[1])) end - if lwork < 0 - lwork = int32(real(work[1])) - work = Array($elty, lwork) - end - end - if jobu == 'O' return A, S, VT end - if jobvt == 'O' return U, S, A end - U, S, VT - end - end -end - -# (GT) General tridiagonal, decomposition, solver and direct solver -for (gtsv, gttrf, gttrs, elty) in - ((:dgtsv_,:dgttrf_,:dgttrs_,:Float64), - (:sgtsv_,:sgttrf_,:sgttrs_,:Float32), - (:zgtsv_,:zgttrf_,:zgttrs_,:Complex128), - (:cgtsv_,:cgttrf_,:cgttrs_,:Complex64)) - @eval begin - # SUBROUTINE DGTSV( N, NRHS, DL, D, DU, B, LDB, INFO ) - # .. Scalar Arguments .. - # INTEGER INFO, LDB, N, NRHS - # .. Array Arguments .. - # DOUBLE PRECISION B( LDB, * ), D( * ), DL( * ), DU( * ) - function gtsv!(dl::Vector{$elty}, d::Vector{$elty}, du::Vector{$elty}, - B::StridedVecOrMat{$elty}) - chkstride1(B) - n = length(d) - if length(dl) != n - 1 || length(du) != n - 1 - throw(LapackDimMisMatch("gtsv!")) - end - if n != size(B,1) throw(LapackDimMisMatch("gtsv!")) end - info = Array(Int32, 1) - ccall(($(string(gtsv)),liblapack), Void, - (Ptr{Int32}, Ptr{Int32}, Ptr{$elty}, Ptr{$elty}, Ptr{$elty}, - Ptr{$elty}, Ptr{Int32}, Ptr{Int32}), - &n, &size(B,2), dl, d, du, B, &stride(B,2), info) - if info[1] != 0 throw(LapackException(info[1])) end - B - end - # SUBROUTINE DGTTRF( N, DL, D, DU, DU2, IPIV, INFO ) - # .. Scalar Arguments .. - # INTEGER INFO, N - # .. Array Arguments .. - # INTEGER IPIV( * ) - # DOUBLE PRECISION D( * ), DL( * ), DU( * ), DU2( * ) - function gttrf!(dl::Vector{$elty}, d::Vector{$elty}, du::Vector{$elty}) - n = length(d) - if length(dl) != (n-1) || length(du) != (n-1) - throw(LapackDimMisMatch("gttrf!")) - end - du2 = Array($elty, n-2) - ipiv = Array(Int32, n) - info = Array(Int32, 1) - ccall(($(string(gttrf)),liblapack), Void, - (Ptr{Int32}, Ptr{$elty}, Ptr{$elty}, Ptr{$elty}, Ptr{$elty}, - Ptr{Int32}, Ptr{Int32}), - &n, dl, d, du, du2, ipiv, info) - if info[1] != 0 throw(LapackException(info[1])) end - dl, d, du, du2, ipiv - end - # SUBROUTINE DGTTRS( TRANS, N, NRHS, DL, D, DU, DU2, IPIV, B, LDB, INFO ) - # .. Scalar Arguments .. - # CHARACTER TRANS - # INTEGER INFO, LDB, N, NRHS - # .. Array Arguments .. - # INTEGER IPIV( * ) - # DOUBLE PRECISION B( LDB, * ), D( * ), DL( * ), DU( * ), DU2( * ) - function gttrs!(trans::LapackChar, dl::Vector{$elty}, d::Vector{$elty}, - du::Vector{$elty}, du2::Vector{$elty}, ipiv::Vector{Int32}, - B::StridedVecOrMat{$elty}) - chkstride1(B) - n = length(d) - if length(dl) != n - 1 || length(du) != n - 1 throw(LapackDimMisMatch("gttrs!")) end - if n != size(B,1) throw(LapackDimMisMatch("gttrs!")) end - info = Array(Int32, 1) - ccall(($(string(gttrs)),liblapack), Void, - (Ptr{Uint8}, Ptr{Int32}, Ptr{Int32}, - Ptr{$elty}, Ptr{$elty}, Ptr{$elty}, Ptr{$elty}, - Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, Ptr{Int32}), - &trans, &n, &size(B,2), dl, d, du, du2, ipiv, B, &stride(B,2), info) - if info[1] != 0 throw(LapackException(info[1])) end - B - end - end -end - -## (OR) orthogonal (or UN, unitary) matrices, extractors and multiplication -for (orglq, orgqr, ormlq, ormqr, elty) in - ((:dorglq_,:dorgqr_,:dormlq_,:dormqr_,:Float64), - (:sorglq_,:sorgqr_,:sormlq_,:sormqr_,:Float32), - (:zunglq_,:zungqr_,:zunmlq_,:zunmqr_,:Complex128), - (:cunglq_,:cungqr_,:cunmlq_,:cunmqr_,:Complex64)) - @eval begin - # SUBROUTINE DORGLQ( M, N, K, A, LDA, TAU, WORK, LWORK, INFO ) - # * .. Scalar Arguments .. - # INTEGER INFO, K, LDA, LWORK, M, N - # * .. Array Arguments .. - # DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * ) - function orglq!(A::StridedMatrix{$elty}, tau::Vector{$elty}, k::Integer) - chkstride1(A) - work = Array($elty, 1) - lwork = int32(-1) - info = Array(Int32, 1) - for i in 1:2 - ccall(($(string(orglq)),liblapack), Void, - (Ptr{Int32}, Ptr{Int32}, Ptr{Int32}, Ptr{$elty}, - Ptr{Int32}, Ptr{$elty}, Ptr{$elty}, Ptr{Int32}, Ptr{Int32}), - &size(A,1), &size(A,2), &k, A, &stride(A,2), tau, work, &lwork, info) - if info[1] != 0 throw(LapackException(info[1])) end - if lwork < 0 - lwork = int32(real(work[1])) - work = Array($elty, lwork) - end - end - A - end - # SUBROUTINE DORGQR( M, N, K, A, LDA, TAU, WORK, LWORK, INFO ) - # * .. Scalar Arguments .. - # INTEGER INFO, K, LDA, LWORK, M, N - # * .. Array Arguments .. - # DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * ) - function orgqr!(A::StridedMatrix{$elty}, tau::Vector{$elty}, k::Integer) - chkstride1(A) - work = Array($elty, 1) - lwork = int32(-1) - info = Array(Int32, 1) - for i in 1:2 - ccall(($(string(orgqr)),liblapack), Void, - (Ptr{Int32}, Ptr{Int32}, Ptr{Int32}, Ptr{$elty}, - Ptr{Int32}, Ptr{$elty}, Ptr{$elty}, Ptr{Int32}, Ptr{Int32}), - &size(A,1), &size(A,2), &k, A, &stride(A,2), tau, work, &lwork, info) - if info[1] != 0 throw(LapackException(info[1])) end - if lwork < 0 - lwork = int32(real(work[1])) - work = Array($elty, lwork) - end - end - A - end - # SUBROUTINE DORMLQ( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, - # WORK, LWORK, INFO ) - # .. Scalar Arguments .. - # CHARACTER SIDE, TRANS - # INTEGER INFO, K, LDA, LDC, LWORK, M, N - # .. Array Arguments .. - # DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ), WORK( * ) - function ormlq!(side::LapackChar, trans::LapackChar, A::StridedMatrix{$elty}, - k::Integer, tau::Vector{$elty}, C::StridedVecOrMat{$elty}) - chkstride1(A, C) - m = size(C, 1) - n = size(C, 2) # m, n = size(C) won't work if C is a Vector - work = Array($elty, 1) - lwork = int32(-1) - info = Array(Int32, 1) - for i in 1:2 - ccall(($(string(ormlq)),liblapack), Void, - (Ptr{Uint8}, Ptr{Uint8}, Ptr{Int32}, Ptr{Int32}, Ptr{Int32}, - Ptr{$elty}, Ptr{Int32}, Ptr{$elty}, Ptr{$elty}, Ptr{Int32}, - Ptr{$elty}, Ptr{Int32}, Ptr{Int32}), - &side, &trans, &m, &n, &k, A, &stride(A,2), tau, - C, &stride(C,2), work, &lwork, info) - if info[1] != 0 throw(LapackException(info[1])) end - if lwork < 0 - lwork = int32(real(work[1])) - work = Array($elty, lwork) - end - end - C - end - # SUBROUTINE DORMQR( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, - # WORK, INFO ) - # .. Scalar Arguments .. - # CHARACTER SIDE, TRANS - # INTEGER INFO, K, LDA, LDC, M, N - # .. Array Arguments .. - # DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ), WORK( * ) - function ormqr!(side::LapackChar, trans::LapackChar, A::StridedMatrix{$elty}, - k::Integer, tau::Vector{$elty}, C::StridedVecOrMat{$elty}) - chkstride1(A, C) - m = size(C, 1) - n = size(C, 2) # m, n = size(C) won't work if C is a Vector - work = Array($elty, 1) - lwork = int32(-1) - info = Array(Int32, 1) - for i in 1:2 - ccall(($(string(ormqr)),liblapack), Void, - (Ptr{Uint8}, Ptr{Uint8}, Ptr{Int32}, Ptr{Int32}, Ptr{Int32}, - Ptr{$elty}, Ptr{Int32}, Ptr{$elty}, Ptr{$elty}, Ptr{Int32}, - Ptr{$elty}, Ptr{Int32}, Ptr{Int32}), - &side, &trans, &m, &n, &k, A, &stride(A,2), tau, - C, &stride(C,2), work, &lwork, info) - if info[1] != 0 throw(LapackException(info[1])) end - if lwork < 0 - lwork = int32(real(work[1])) - work = Array($elty, lwork) - end - end - C - end - end -end - -# (PO) positive-definite symmetric matrices, -# Cholesky decomposition, solvers (direct and factored) and inverse. -for (posv, potrf, potri, potrs, pstrf, elty, rtyp) in - ((:dposv_,:dpotrf_,:dpotri_,:dpotrs_,:dpstrf_,:Float64,:Float64), - (:sposv_,:spotrf_,:spotri_,:spotrs_,:spstrf_,:Float32,:Float32), - (:zposv_,:zpotrf_,:zpotri_,:zpotrs_,:zpstrf_,:Complex128,:Float64), - (:cposv_,:cpotrf_,:cpotri_,:cpotrs_,:cpstrf_,:Complex64,:Float32)) - @eval begin - ## Caller should check if returned info[1] is zero, - ## positive values indicate indefiniteness - # SUBROUTINE DPOSV( UPLO, N, NRHS, A, LDA, B, LDB, INFO ) - #* .. Scalar Arguments .. - # CHARACTER UPLO - # INTEGER INFO, LDA, LDB, N, NRHS - # .. Array Arguments .. - # DOUBLE PRECISION A( LDA, * ), B( LDB, * ) - function posv!(uplo::LapackChar, A::StridedMatrix{$elty}, B::StridedVecOrMat{$elty}) - chkstride1(A, B) - chksquare(A) - n = size(A,1) - if size(B,1) != n throw(LapackDimMisMatch("posv!")) end - info = Array(Int32, 1) - ccall(($(string(posv)),liblapack), Void, - (Ptr{Uint8}, Ptr{Int32}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, - Ptr{$elty}, Ptr{Int32}, Ptr{Int32}), - &uplo, &n, &size(B,2), A, &stride(A,2), B, &stride(B,2), info) - if info[1] < 0 throw(LapackException(info[1])) end - A, B, info[1] - end - ## Caller should check if returned info[1] is zero, - ## positive values indicate indefiniteness - # SUBROUTINE DPOTRF( UPLO, N, A, LDA, INFO ) - # * .. Scalar Arguments .. - # CHARACTER UPLO - # INTEGER INFO, LDA, N - # * .. Array Arguments .. - # DOUBLE PRECISION A( LDA, * ) - function potrf!(uplo::LapackChar, A::StridedMatrix{$elty}) - chkstride1(A) - chksquare(A) - info = Array(Int32, 1) - ccall(($(string(potrf)),liblapack), Void, - (Ptr{Uint8}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, Ptr{Int32}), - &uplo, &size(A,1), A, &stride(A,2), info) - if info[1] < 0 throw(LapackException(info[1])) end - A, info[1] - end - ## Caller should check if returned info[1] is zero, - ## positive values indicate singularity - # SUBROUTINE DPOTRI( UPLO, N, A, LDA, INFO ) - # .. Scalar Arguments .. - # CHARACTER UPLO - # INTEGER INFO, LDA, N - # .. Array Arguments .. - # DOUBLE PRECISION A( LDA, * ) - function potri!(uplo::LapackChar, A::StridedMatrix{$elty}) - chkstride1(A) - info = Array(Int32, 1) - ccall(($(string(potri)),liblapack), Void, - (Ptr{Uint8}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, Ptr{Int32}), - &uplo, &size(A,1), A, &stride(A,2), info) - if info[1] < 0 throw(LapackException(info[1])) end - A, info[1] - end - # SUBROUTINE DPOTRS( UPLO, N, NRHS, A, LDA, B, LDB, INFO ) - # .. Scalar Arguments .. - # CHARACTER UPLO - # INTEGER INFO, LDA, LDB, N, NRHS - # .. Array Arguments .. - # DOUBLE PRECISION A( LDA, * ), B( LDB, * ) - function potrs!(uplo::LapackChar, A::StridedMatrix{$elty}, B::StridedVecOrMat{$elty}) - chkstride1(A, B) - chksquare(A) - n = size(A,2) - if size(B,1) != n error("potrs!: dimension mismatch") end - info = Array(Int32, 1) - ccall(($(string(potrs)),liblapack), Void, - (Ptr{Uint8}, Ptr{Int32}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, - Ptr{$elty}, Ptr{Int32}, Ptr{Int32}), - &uplo, &n, &size(B,2), A, &stride(A,2), B, &stride(B,2), info) - if info[1] != 0 throw(LapackException(info[1])) end - B - end - # SUBROUTINE DPSTRF( UPLO, N, A, LDA, PIV, RANK, TOL, WORK, INFO ) - # .. Scalar Arguments .. - # DOUBLE PRECISION TOL - # INTEGER INFO, LDA, N, RANK - # CHARACTER UPLO - # .. Array Arguments .. - # DOUBLE PRECISION A( LDA, * ), WORK( 2*N ) - # INTEGER PIV( N ) - function pstrf!(uplo::LapackChar, A::StridedMatrix{$elty}, tol::Real) - chkstride1(A) - chksquare(A) - n = size(A,1) - piv = Array(Int32, n) - rank = Array(Int32, 1) - work = Array($rtyp, 2n) - info = Array(Int32, 1) - ccall(($(string(pstrf)),liblapack), Void, - (Ptr{Uint8}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, Ptr{Int32}, - Ptr{Int32}, Ptr{$rtyp}, Ptr{$rtyp}, Ptr{Int32}), - &uplo, &n, A, &stride(A,2), piv, rank, &tol, work, info) - if info[1] < 0 throw(LapackException(info[1])) end - A, piv, rank[1], info[1] - end - end -end - -## (PT) positive-definite, symmetric, tri-diagonal matrices -## Direct solvers for general tridiagonal and symmetric positive-definite tridiagonal -for (ptsv, pttrf, pttrs, elty, relty) in - ((:dptsv_,:dpttrf_,:dpttrs_,:Float64,:Float64), - (:sptsv_,:spttrf_,:spttrs_,:Float32,:Float32), - (:zptsv_,:zpttrf_,:zpttrs_,:Complex128,:Float64), - (:cptsv_,:cpttrf_,:cpttrs_,:Complex64,:Float32)) - @eval begin - # SUBROUTINE DPTSV( N, NRHS, D, E, B, LDB, INFO ) - # .. Scalar Arguments .. - # INTEGER INFO, LDB, N, NRHS - # .. Array Arguments .. - # DOUBLE PRECISION B( LDB, * ), D( * ), E( * ) - function ptsv!(D::Vector{$relty}, E::Vector{$elty}, B::StridedVecOrMat{$elty}) - chkstride1(B) - n = length(D) - if length(E) != n - 1 || n != size(B,1) throw(LapackDimMismatch("ptsv!")) end - info = Array(Int32, 1) - ccall(($(string(ptsv)),liblapack), Void, - (Ptr{Int32}, Ptr{Int32}, Ptr{$relty}, Ptr{$elty}, - Ptr{$elty}, Ptr{Int32}, Ptr{Int32}), - &n, &size(B,2), D, E, B, &stride(B,2), info) - if info[1] != 0 throw(LapackException(info[1])) end - B - end - # SUBROUTINE DPTTRF( N, D, E, INFO ) - # .. Scalar Arguments .. - # INTEGER INFO, N - # .. Array Arguments .. - # DOUBLE PRECISION D( * ), E( * ) - function pttrf!(D::Vector{$relty}, E::Vector{$elty}) - n = length(D) - if length(E) != (n-1) throw(LapackDimMisMatch("pttrf!")) end - info = Array(Int32, 1) - ccall(($(string(pttrf)),liblapack), Void, - (Ptr{Int32}, Ptr{$relty}, Ptr{$elty}, Ptr{Int32}), - &n, D, E, info) - if info[1] != 0 throw(LapackException(info[1])) end - D, E - end - end -end -for (pttrs, elty, relty) in - ((:dpttrs_,:Float64,:Float64), - (:spttrs_,:Float32,:Float32)) - @eval begin - # SUBROUTINE DPTTRS( N, NRHS, D, E, B, LDB, INFO ) - # .. Scalar Arguments .. - # INTEGER INFO, LDB, N, NRHS - # .. Array Arguments .. - # DOUBLE PRECISION B( LDB, * ), D( * ), E( * ) - function pttrs!(D::Vector{$relty}, E::Vector{$elty}, B::StridedVecOrMat{$elty}) - chkstride1(B) - n = length(D) - if length(E) != (n-1) || size(B,1) != n throw(LapackDimMisMatch("pttrs!")) end - info = Array(Int32, 1) - ccall(($(string(pttrs)),liblapack), Void, - (Ptr{Int32}, Ptr{Int32}, Ptr{$relty}, Ptr{$elty}, - Ptr{$elty}, Ptr{Int32}, Ptr{Int32}), - &n, &size(B,2), D, E, B, &stride(B,2), info) - if info[1] != 0 throw(LapackException(info[1])) end - B - end - end -end -for (pttrs, elty, relty) in - ((:zpttrs_,:Complex128,:Float64), - (:cpttrs_,:Complex64,:Float32)) - @eval begin -# SUBROUTINE ZPTTRS( UPLO, N, NRHS, D, E, B, LDB, INFO ) -# * .. Scalar Arguments .. -# CHARACTER UPLO -# INTEGER INFO, LDB, N, NRHS -# * .. -# * .. Array Arguments .. -# DOUBLE PRECISION D( * ) -# COMPLEX*16 B( LDB, * ), E( * ) - function pttrs!(uplo::LapackChar, D::Vector{$relty}, E::Vector{$elty}, B::StridedVecOrMat{$elty}) - chkstride1(B) - n = length(D) - if length(E) != (n-1) || size(B,1) != n throw(LapackDimMisMatch("pttrs!")) end - info = Array(Int32, 1) - ccall(($(string(pttrs)),liblapack), Void, - (Ptr{Uint8}, Ptr{Int32}, Ptr{Int32}, Ptr{$relty}, Ptr{$elty}, - Ptr{$elty}, Ptr{Int32}, Ptr{Int32}), - &uplo, &n, &size(B,2), D, E, B, &stride(B,2), info) - if info[1] != 0 throw(LapackException(info[1])) end - B - end - end -end - -## (TR) triangular matrices: solver and inverse -for (trtri, trtrs, elty) in - ((:dtrtri_,:dtrtrs_,:Float64), - (:strtri_,:strtrs_,Float32), - (:ztrtri_,:ztrtrs_,:Complex128), - (:ctrtri_,:ctrtrs_,:Complex64)) - @eval begin - # SUBROUTINE DTRTRI( UPLO, DIAG, N, A, LDA, INFO ) - #* .. Scalar Arguments .. - # CHARACTER DIAG, UPLO - # INTEGER INFO, LDA, N - # .. Array Arguments .. - # DOUBLE PRECISION A( LDA, * ) - function trtri!(uplo::LapackChar, diag::LapackChar, A::StridedMatrix{$elty}) - chkstride1(A) - m, n = size(A) - if m != n error("trtri!: dimension mismatch") end - lda = stride(A, 2) - info = Array(Int32, 1) - ccall(($trtri,liblapack), Void, - (Ptr{Uint8}, Ptr{Uint8}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, - Ptr{Int32}), - &uplo, &diag, &n, A, &lda, info) - if info[1] < 0 error("trtri!: error $(info[1])") end - A, info[1] - end - # SUBROUTINE DTRTRS( UPLO, TRANS, DIAG, N, NRHS, A, LDA, B, LDB, INFO ) - # * .. Scalar Arguments .. - # CHARACTER DIAG, TRANS, UPLO - # INTEGER INFO, LDA, LDB, N, NRHS - # * .. Array Arguments .. - # DOUBLE PRECISION A( LDA, * ), B( LDB, * ) - function trtrs!(uplo::LapackChar, trans::LapackChar, diag::LapackChar, - A::StridedMatrix{$elty}, B::StridedVecOrMat{$elty}) - chkstride1(A) - chksquare(A) - n = size(A,2) - if size(B,1) != n throw(LapackDimMisMatch("trtrs!")) end - info = Array(Int32, 1) - ccall(($(string(trtrs)),liblapack), Void, - (Ptr{Uint8}, Ptr{Uint8}, Ptr{Uint8}, Ptr{Int32}, Ptr{Int32}, - Ptr{$elty}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, Ptr{Int32}), - &uplo, &trans, &diag, &n, &size(B,2), A, &stride(A,2), - B, &stride(B,2), info) - if info[1] < 0 throw(LapackException(info[1])) end - B, info[1] - end - end -end - -## (ST) Symmetric tridiagonal - eigendecomposition -for (stev, elty) in - ((:dstev_,:Float64), - (:sstev_,:Float32) -# , (:zstev_,:Complex128) Need to rewrite for ZHEEV, rwork, etc. -# , (:cstev_,:Complex64) - ) - @eval begin - function stev!(job::LapackChar, dv::Vector{$elty}, ev::Vector{$elty}) - n = length(dv) - if length(ev) != (n-1) throw(LapackDimMisMatch("stev!")) end - Zmat = Array($elty, (n, job != 'N' ? n : 0)) - work = Array($elty, max(1, 2n-2)) - info = Array(Int32, 1) - ccall(($(string(stev)),liblapack), Void, - (Ptr{Uint8}, Ptr{Int32}, Ptr{$elty}, Ptr{$elty}, Ptr{$elty}, - Ptr{Int32}, Ptr{$elty}, Ptr{Int32}), - &job, &n, dv, ev, Zmat, &n, work, info) - if info[1] != 0 throw(LapackException(info[1])) end - dv, Zmat - end - end -end - -## (SY) symmetric matrices - eigendecomposition, Bunch-Kaufman decomposition, -## solvers (direct and factored) and inverse. -for (syconv, syev, sysv, sytrf, sytri, sytrs, elty) in - ((:dsyconv_,:dsyev_,:dsysv_,:dsytrf_,:dsytri_,:dsytrs_,:Float64), - (:ssyconv_,:ssyev_,:ssysv_,:ssytrf_,:ssytri_,:ssytrs_,:Float32), - (:zheconv_,:zheev_,:zhesv_,:zhetrf_,:zhetri_,:zhetrs_,:Complex128), - (:checonv_,:cheev_,:chesv_,:chetrf_,:chetri_,:chetrs_,:Complex64)) - @eval begin - # SUBROUTINE DSYCONV( UPLO, WAY, N, A, LDA, IPIV, WORK, INFO ) - # * .. Scalar Arguments .. - # CHARACTER UPLO, WAY - # INTEGER INFO, LDA, N - # * .. Array Arguments .. - # INTEGER IPIV( * ) - # DOUBLE PRECISION A( LDA, * ), WORK( * ) - function syconv!(uplo::LapackChar, A::StridedMatrix{$elty}, ipiv::Vector{Int32}) - chkstride1(A) - chksquare(A) - n = size(A,1) - work = Array($elty, n) - info = Array(Int32, 1) - ccall(($(string(syconv)),liblapack), Void, - (Ptr{Uint8}, Ptr{Uint8}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, - Ptr{Int32}, Ptr{$elty}, Ptr{Int32}), - &uplo, &'C', &n, A, &stride(A,2), ipiv, work, info) - if info[1] != 0 throw(LapackException(info[1])) end - A, work - end - # SUBROUTINE DSYEV( JOBZ, UPLO, N, A, LDA, W, WORK, LWORK, INFO ) - # * .. Scalar Arguments .. - # CHARACTER JOBZ, UPLO - # INTEGER INFO, LDA, LWORK, N - # * .. Array Arguments .. - # DOUBLE PRECISION A( LDA, * ), W( * ), WORK( * ) - function syev!(jobz::LapackChar, uplo::LapackChar, A::StridedMatrix{$elty}) - chkstride1(A) - chksquare(A) - cmplx = iscomplex(A) - Rtyp = typeof(real(A[1])) - n = size(A, 1) - W = Array(Rtyp, n) - work = Array($elty, 1) - lwork = int32(-1) - if cmplx - rwork = Array(Rtyp, max(1, 3n-2)) - end - info = Array(Int32, 1) - for i in 1:2 - if cmplx - ccall(($(string(syev)),liblapack), Void, - (Ptr{Uint8}, Ptr{Uint8}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, - Ptr{Rtyp}, Ptr{$elty}, Ptr{Int32}, Ptr{Rtyp}, Ptr{Int32}), - &jobz, &uplo, &n, A, &stride(A,2), W, work, &lwork, rwork, info) - else - ccall(($(string(syev)),liblapack), Void, - (Ptr{Uint8}, Ptr{Uint8}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, - Ptr{Rtyp}, Ptr{$elty}, Ptr{Int32}, Ptr{Int32}), - &jobz, &uplo, &n, A, &stride(A,2), W, work, &lwork, info) - end - if info[1] != 0 throw(LapackException(info[1])) end - if lwork < 0 - lwork = int32(real(work[1])) - work = Array($elty, lwork) - end - end - jobz == 'V' ? (W, A) : W - end - # SUBROUTINE DSYSV( UPLO, N, NRHS, A, LDA, IPIV, B, LDB, WORK, - # LWORK, INFO ) - # .. Scalar Arguments .. - # CHARACTER UPLO - # INTEGER INFO, LDA, LDB, LWORK, N, NRHS - # .. Array Arguments .. - # INTEGER IPIV( * ) - # DOUBLE PRECISION A( LDA, * ), B( LDB, * ), WORK( * ) - function sysv!(uplo::LapackChar, A::StridedMatrix{$elty}, B::StridedVecOrMat{$elty}) - chkstride1(A,B) - chksquare(A) - n = size(A,1) - if n != size(B,1) throw(LapackDimMismatch("sysv!")) end - ipiv = Array(Int32, n) - work = Array($elty, 1) - lwork = int32(-1) - info = Array(Int32, 1) - for i in 1:2 - ccall(($(string(sysv)),liblapack), Void, - (Ptr{Uint8}, Ptr{Int32}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, Ptr{Int32}, - Ptr{$elty}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, Ptr{Int32}), - &uplo, &n, &size(B,2), A, &stride(A,2), ipiv, B, &stride(B,2), - work, &lwork, info) - if info[1] < 0 throw(LapackException(info[1])) end - if lwork < 0 - lwork = int32(real(work[1])) - work = Array($elty, lwork) - end - end - B, A, ipiv, info[1] - end - # SUBROUTINE DSYTRF( UPLO, N, A, LDA, IPIV, WORK, LWORK, INFO ) - # * .. Scalar Arguments .. - # CHARACTER UPLO - # INTEGER INFO, LDA, LWORK, N - # * .. Array Arguments .. - # INTEGER IPIV( * ) - # DOUBLE PRECISION A( LDA, * ), WORK( * ) - function sytrf!(uplo::LapackChar, A::StridedMatrix{$elty}) - chkstride1(A) - chksquare(A) - n = size(A,1) - ipiv = Array(Int32, n) - work = Array($elty, 1) - lwork = int32(-1) - info = Array(Int32, 1) - for i in 1:2 - ccall(($(string(sytrf)),liblapack), Void, - (Ptr{Uint8}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, - Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, Ptr{Int32}), - &uplo, &n, A, &stride(A,2), ipiv, work, &lwork, info) - if info[1] != 0 throw(LapackException(info[1])) end - if lwork < 0 - lwork = int32(real(work[1])) - work = Array($elty, lwork) - end - end - A, ipiv - end - # SUBROUTINE DSYTRI2( UPLO, N, A, LDA, IPIV, WORK, LWORK, INFO ) - # * .. Scalar Arguments .. - # CHARACTER UPLO - # INTEGER INFO, LDA, LWORK, N - # * .. Array Arguments .. - # INTEGER IPIV( * ) - # DOUBLE PRECISION A( LDA, * ), WORK( * ) -# function sytri!(uplo::LapackChar, A::StridedMatrix{$elty}, ipiv::Vector{Int32}) -# chkstride1(A) -# chksquare(A) -# n = size(A,1) -# work = Array($elty, 1) -# lwork = int32(-1) -# info = Array(Int32, 1) -# for i in 1:2 -# ccall(($(string(sytri)),liblapack), Void, -# (Ptr{Uint8}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, -# Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, Ptr{Int32}), -# &uplo, &n, A, &stride(A,2), ipiv, work, &lwork, info) -# if info[1] != 0 throw(LapackException(info[1])) end -# if lwork < 0 -# lwork = int32(real(work[1])) -# work = Array($elty, lwork) -# end -# end -# A -# end - # SUBROUTINE DSYTRI( UPLO, N, A, LDA, IPIV, WORK, INFO ) - # .. Scalar Arguments .. - # CHARACTER UPLO - # INTEGER INFO, LDA, N - # .. Array Arguments .. - # INTEGER IPIV( * ) - # DOUBLE PRECISION A( LDA, * ), WORK( * ) - function sytri!(uplo::LapackChar, A::StridedMatrix{$elty}, ipiv::Vector{Int32}) - chkstride1(A) - chksquare(A) - n = size(A,1) - work = Array($elty, n) - info = Array(Int32, 1) - ccall(($(string(sytri)),liblapack), Void, - (Ptr{Uint8}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, - Ptr{Int32}, Ptr{$elty}, Ptr{Int32}), - &uplo, &n, A, &stride(A,2), ipiv, work, info) - if info[1] != 0 throw(LapackException(info[1])) end - A - end - # SUBROUTINE DSYTRS( UPLO, N, NRHS, A, LDA, IPIV, B, LDB, INFO ) - # - # .. Scalar Arguments .. - # CHARACTER UPLO - # INTEGER INFO, LDA, LDB, N, NRHS - # .. Array Arguments .. - # INTEGER IPIV( * ) - # DOUBLE PRECISION A( LDA, * ), B( LDB, * ) - function sytrs!(uplo::LapackChar, A::StridedMatrix{$elty}, - ipiv::Vector{Int32}, B::StridedVecOrMat{$elty}) - chkstride1(A,B) - chksquare(A) - n = size(A,1) - if n != size(B,1) throw(LapackDimMismatch("sytrs!")) end - info = Array(Int32, 1) - ccall(($(string(sytrs)),liblapack), Void, - (Ptr{Uint8}, Ptr{Int32}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, - Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, Ptr{Int32}), - &uplo, &n, &size(B,2), A, &stride(A,2), ipiv, B, &stride(B,2), info) - if info[1] != 0 throw(LapackException(info[1])) end - B - end - end -end -for (syevr, elty) in - ((:dsyevr_,:Float64), - (:ssyevr_,:Float32)) - @eval begin - function syevr!(jobz::LapackChar, range::LapackChar, uplo::LapackChar, A::StridedMatrix{$elty}, vl::FloatingPoint, vu::FloatingPoint, il::Integer, iu::Integer, Z::StridedMatrix{$elty}, abstol::FloatingPoint) - # SUBROUTINE DSYEVR( JOBZ, RANGE, UPLO, N, A, LDA, VL, VU, IL, IU, - # $ ABSTOL, M, W, Z, LDZ, ISUPPZ, WORK, LWORK, - # $ IWORK, LIWORK, INFO ) - # * .. Scalar Arguments .. - # CHARACTER JOBZ, RANGE, UPLO - # INTEGER IL, INFO, IU, LDA, LDZ, LIWORK, LWORK, M, N - # DOUBLE PRECISION ABSTOL, VL, VU - # * .. - # * .. Array Arguments .. - # INTEGER ISUPPZ( * ), IWORK( * ) - # DOUBLE PRECISION A( LDA, * ), W( * ), WORK( * ), Z( LDZ, * ) - chkstride1(A, Z) - chksquare(A) - n = size(A, 2) - lda = max(1,stride(A,2)) - m = Array(Int32, 1) - w = Array($elty, n) - if jobz == 'N' - ldz = 1 - elseif jobz == 'V' - if stride(Z, 2) < n; error("Z has too few rows"); end - if size(Z, 2) < n; error("Z has too few columns"); end - ldz = max(1, stride(Z, 2)) - else - error("joz must be 'N' of 'V'") - end - isuppz = Array(Int, 2*n) - work = Array($elty, 1) - lwork = int32(-1) - iwork = Array(Int32, 1) - liwork = int32(-1) - info = Array(Int32, 1) - for i in 1:2 - ccall(($(string(syevr)),liblapack), Void, - (Ptr{Uint8}, Ptr{Uint8}, Ptr{Uint8}, Ptr{Int32}, - Ptr{$elty}, Ptr{Int32}, Ptr{$elty}, Ptr{$elty}, - Ptr{Int32}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, - Ptr{$elty}, Ptr{$elty}, Ptr{Int32}, Ptr{Int32}, - Ptr{$elty}, Ptr{Int32}, Ptr{Int32}, Ptr{Int32}, - Ptr{Int32}), - &jobz, &range, &uplo, &n, - A, &lda, &vl, &vu, - &il, &iu, &abstol, m, - w, Z, &ldz, isuppz, - work, &lwork, iwork, &liwork, - info) - if info[1] != 0 throw(LapackException(info[1])) end - if lwork < 0 - lwork = int32(work[1]) - work = Array($elty, lwork) - liwork = iwork[1] - iwork = Array(Int32, liwork) - end - end - return w[1:m[1]] - end - end -end -for (syevr, elty, relty) in - ((:zheevr_,:Complex128,:Float64), - (:cheevr_,:Complex64,:Float32)) - @eval begin - function syevr!(jobz::LapackChar, range::LapackChar, uplo::LapackChar, A::StridedMatrix{$elty}, vl::FloatingPoint, vu::FloatingPoint, il::Integer, iu::Integer, Z::StridedMatrix{$elty}, abstol::FloatingPoint) -# SUBROUTINE ZHEEVR( JOBZ, RANGE, UPLO, N, A, LDA, VL, VU, IL, IU, -# $ ABSTOL, M, W, Z, LDZ, ISUPPZ, WORK, LWORK, -# $ RWORK, LRWORK, IWORK, LIWORK, INFO ) -# * .. Scalar Arguments .. -# CHARACTER JOBZ, RANGE, UPLO -# INTEGER IL, INFO, IU, LDA, LDZ, LIWORK, LRWORK, LWORK, -# $ M, N -# DOUBLE PRECISION ABSTOL, VL, VU -# * .. -# * .. Array Arguments .. -# INTEGER ISUPPZ( * ), IWORK( * ) -# DOUBLE PRECISION RWORK( * ), W( * ) -# COMPLEX*16 A( LDA, * ), WORK( * ), Z( LDZ, * ) - chkstride1(A, Z) - chksquare(A) - n = size(A, 2) - lda = max(1,stride(A,2)) - m = Array(Int32, 1) - w = Array($relty, n) - if jobz == 'N' - ldz = 1 - elseif jobz == 'V' - if stride(Z, 2) < n; error("Z has too few rows"); end - if size(Z, 2) < n; error("Z has too few columns"); end - ldz = max(1, stride(Z, 2)) - else - error("joz must be 'N' of 'V'") - end - isuppz = Array(Int, 2*n) - work = Array($elty, 1) - lwork = int32(-1) - rwork = Array($relty, 1) - lrwork = int32(-1) - iwork = Array(Int32, 1) - liwork = int32(-1) - info = Array(Int32, 1) - for i in 1:2 - ccall(($(string(syevr)),liblapack), Void, - (Ptr{Uint8}, Ptr{Uint8}, Ptr{Uint8}, Ptr{Int32}, - Ptr{$elty}, Ptr{Int32}, Ptr{$elty}, Ptr{$elty}, - Ptr{Int32}, Ptr{Int32}, Ptr{$elty}, Ptr{Int32}, - Ptr{$elty}, Ptr{$elty}, Ptr{Int32}, Ptr{Int32}, - Ptr{$elty}, Ptr{Int32}, Ptr{$relty}, Ptr{Int32}, - Ptr{Int32}, Ptr{Int32}, Ptr{Int32}), - &jobz, &range, &uplo, &n, - A, &lda, &vl, &vu, - &il, &iu, &abstol, m, - w, Z, &ldz, isuppz, - work, &lwork, rwork, &lrwork, - iwork, &liwork, info) - if info[1] != 0 throw(LapackException(info[1])) end - if lwork < 0 - lwork = int32(real(work[1])) - work = Array($elty, lwork) - lrwork = int32(rwork[1]) - rwork = Array($elty, lrwork) - liwork = iwork[1] - iwork = Array(Int32, liwork) - end - end - return w[1:m[1]] - end - end -end -syevr!(A::StridedMatrix, Z::StridedMatrix) = syevr!('V', 'A', 'U', A, 0.0, 0.0, 0, 0, Z, -1.0) -syevr!{T}(A::StridedMatrix{T}) = syevr!('N', 'A', 'U', A, 0.0, 0.0, 0, 0, zeros(T,0,0), -1.0) -end # module diff --git a/base/libc.jl b/base/libc.jl index 69de18eeb9983..89693da8e4673 100644 --- a/base/libc.jl +++ b/base/libc.jl @@ -1,7 +1,8 @@ ## time-related functions ## # TODO: check for usleep errors? -sleep(s::Real) = ccall(:usleep, Int32, (Uint32,), uint32(iround(s*1e6))) +@unix_only systemsleep(s::Real) = ccall(:usleep, Int32, (Uint32,), uint32(iround(s*1e6))) +@windows_only systemsleep(s::Real) = (ccall(:Sleep, stdcall, Void, (Uint32,), uint32(iround(s*1e3))); return int32(0)) strftime(t) = strftime("%c", t) function strftime(fmt::ByteString, t) @@ -29,14 +30,17 @@ end ## process-related functions ## -getpid() = int(ccall(:getpid, Int32, ())) -system(cmd::String) = int(ccall(:system, Int32, (Ptr{Uint8},), cmd)) +getpid() = ccall(:jl_getpid, Int32, ()) ## network functions ## function gethostname() - hn = Array(Uint8, 128) - ccall(:gethostname, Int32, (Ptr{Uint8}, Uint), hn, length(hn)) + hn = Array(Uint8, 256) + @unix_only err=ccall(:gethostname, Int32, (Ptr{Uint8}, Uint), hn, length(hn)) + @windows_only err=ccall(:gethostname, stdcall, Int32, (Ptr{Uint8}, Uint32), hn, length(hn)) + if err != 0 + error("gethostname") + end bytestring(convert(Ptr{Uint8},hn)) end @@ -46,10 +50,7 @@ function getipaddr() bytestring(convert(Ptr{Uint8},ip)) end -## get a temporary file name ## - -tmpnam() = bytestring(ccall(:tmpnam, Ptr{Uint8}, (Ptr{Uint8},), C_NULL)) - ## Memory related ## c_free(p::Ptr) = ccall(:free, Void, (Ptr{Void},), p) +c_malloc(size::Integer) = ccall(:malloc, Ptr{Void}, (Int,), size) diff --git a/base/librandom.jl b/base/librandom.jl index ad66cb454edfa..e43628ae44854 100644 --- a/base/librandom.jl +++ b/base/librandom.jl @@ -101,7 +101,7 @@ for (genrand_fill, gv_genrand_fill, genrand_fill_name, gv_genrand_fill_name) in @eval begin function ($genrand_fill_name)(s::DSFMT_state, A::Array{Float64}) - n = numel(A) + n = length(A) if n <= dsfmt_min_array_size for i = 1:n A[i] = rand() @@ -109,8 +109,8 @@ for (genrand_fill, gv_genrand_fill, genrand_fill_name, gv_genrand_fill_name) in else ccall(($(string(genrand_fill)),:librandom), Void, - (Ptr{Void}, Ptr{Float64}, Int32), - s.val, A, n & 0xfffffffe) + (Ptr{Void}, Ptr{Float64}, Int), + s.val, A, n & 0xfffffffffffffffe) if isodd(n) A[n] = rand() end @@ -119,7 +119,7 @@ for (genrand_fill, gv_genrand_fill, genrand_fill_name, gv_genrand_fill_name) in end function ($gv_genrand_fill_name)(A::Array{Float64}) - n = numel(A) + n = length(A) if n <= dsfmt_min_array_size for i = 1:n A[i] = rand() @@ -127,8 +127,8 @@ for (genrand_fill, gv_genrand_fill, genrand_fill_name, gv_genrand_fill_name) in else ccall(($(string(gv_genrand_fill)),:librandom), Void, - (Ptr{Void}, Int32), - A, n & 0xfffffffe) + (Ptr{Void}, Int), + A, n & 0xfffffffffffffffe) if isodd(n) A[n] = rand() end @@ -170,7 +170,7 @@ function randmtzig_fill_randn!(A) ccall((:randmtzig_fill_randn,:librandom), Void, (Ptr{Float64}, Int), - A, numel(A)) + A, length(A)) return A end @@ -184,7 +184,7 @@ function randmtzig_fill_exprnd!(A) ccall((:randmtzig_fill_exprnd,:librandom), Void, (Ptr{Float64}, Int), - A, numel(A)) + A, length(A)) return A end @@ -192,7 +192,7 @@ end @windows_only begin function win32_SystemFunction036!(a::Array{Uint32}) - ccall((:SystemFunction036,:Advapi32),stdcall,Uint8,(Ptr{Void},Uint64),convert(Ptr{Void},a),8) + ccall((:SystemFunction036,:Advapi32),stdcall,Uint8,(Ptr{Void},Uint32),a,length(a)*sizeof(eltype(a))) end end diff --git a/base/linalg.jl b/base/linalg.jl index 45af6d870d5d2..ef0a8003af77f 100644 --- a/base/linalg.jl +++ b/base/linalg.jl @@ -1,109 +1,189 @@ -## linalg.jl: Some generic Linear Algebra definitions - -cross(a::Vector, b::Vector) = - [a[2]*b[3]-a[3]*b[2], a[3]*b[1]-a[1]*b[3], a[1]*b[2]-a[2]*b[1]] - -triu(M::AbstractMatrix) = triu(M,0) -tril(M::AbstractMatrix) = tril(M,0) -#triu{T}(M::AbstractMatrix{T}, k::Integer) -#tril{T}(M::AbstractMatrix{T}, k::Integer) -triu!(M::AbstractMatrix) = triu!(M,0) -tril!(M::AbstractMatrix) = tril!(M,0) - -#diff(a::AbstractVector) -#diff(a::AbstractMatrix, dim::Integer) -diff(a::AbstractMatrix) = diff(a, 1) - -gradient(F::AbstractVector) = gradient(F, [1:length(F)]) -gradient(F::AbstractVector, h::Real) = gradient(F, [h*(1:length(F))]) -#gradient(F::AbstractVector, h::AbstractVector) - -diag(A::AbstractVector) = error("Perhaps you meant to use diagm().") -#diag(A::AbstractMatrix) - -#diagm{T}(v::Union(AbstractVector{T},AbstractMatrix{T})) - -function norm(x::AbstractVector, p::Number) - if length(x) == 0 - return zero(eltype(x)) - elseif p == Inf - return max(abs(x)) - elseif p == -Inf - return min(abs(x)) - else - return sum(abs(x).^p).^(1/p) +module LinAlg + +importall Base +import Base.USE_LIB64, Base.size, Base.copy, Base.copy_transpose!, Base.power_by_squaring + +export +# Types + BunchKaufman, + SymTridiagonal, + Tridiagonal, + Bidiagonal, + Woodbury, + Factorization, + BunchKaufman, + Cholesky, + CholeskyPivoted, + Eigen, + GeneralizedSVD, + GeneralizedSchur, + Hessenberg, + LU, + LUTridiagonal, + LDLTTridiagonal, + QR, + QRPivoted, + Schur, + SVD, + Hermitian, + Triangular, + Diagonal, + +# Functions + check_openblas, + chol, + cholfact, + cholfact!, + cholp, + cholpfact, + cholpfact!, + cond, + copy!, + cross, + ctranspose, + det, + diag, + diagm, + diagmm, + diagmm!, + diff, + dot, + eig, + eigfact, + eigfact!, + eigmax, + eigmin, + eigs, + eigvals, + eigvecs, + expm, + sqrtm, + eye, + factors, + hess, + hessfact, + hessfact!, + ishermitian, + isposdef, + isposdef!, + issym, + istril, + istriu, + kron, + ldltd!, + ldltd, + linreg, + logdet, + lu, + lufact, + lufact!, + norm, + normfro, + null, + pinv, + qr, + qrfact!, + qrfact, + qrp, + qrpfact!, + qrpfact, + qmulQR, + qTmulQR, + randsym, + rank, + rref, + scale!, + schur, + schurfact!, + schurfact, + solve, + svd, + svdfact!, + svdfact, + svds, + svdvals!, + svdvals, + symmetrize!, + trace, + transpose, + tril, + triu, + tril!, + triu!, + +# Operators + \, + /, + A_ldiv_Bc, + A_ldiv_Bt, + A_mul_B, + A_mul_Bc, + A_mul_Bt, + A_rdiv_Bc, + A_rdiv_Bt, + Ac_ldiv_B, + Ac_ldiv_Bc, + Ac_mul_b_RFP, + Ac_mul_B, + Ac_mul_Bc, + Ac_rdiv_B, + Ac_rdiv_Bc, + At_ldiv_B, + At_ldiv_Bt, + At_mul_B, + At_mul_Bt, + At_rdiv_B, + At_rdiv_Bt + + +typealias BlasFloat Union(Float64,Float32,Complex128,Complex64) +typealias BlasChar Char + +function check_openblas() + libblas = dlopen( Base.libblas_name ) + if dlsym_e( libblas, :openblas_get_config ) != C_NULL + openblas_config = bytestring( ccall((:openblas_get_config, Base.libblas_name), Ptr{Uint8}, () )) + openblas64 = ismatch(r".*USE64BITINT.*", openblas_config) + if Base.USE_LIB64 != openblas64 + println("OpenBLAS is incorrectly configured. Quitting.") + quit() + end end end -norm(x::AbstractVector) = sqrt(real(dot(x,x))) - -function norm(A::AbstractMatrix, p) - m, n = size(A) - if m == 0 || n == 0 - return zero(eltype(A)) - elseif m == 1 || n == 1 - return norm(reshape(A, numel(A)), p) - elseif p == 1 - return max(sum(abs(A),1)) - elseif p == 2 - return max(svdvals(A)) - elseif p == Inf - return max(sum(abs(A),2)) - elseif p == "fro" - return sqrt(sum(diag(A'*A))) - else - error("invalid parameter to matrix norm") - end -end - -norm(A::AbstractMatrix) = norm(A, 2) -rank(A::AbstractMatrix, tol::Real) = sum(svdvals(A) .> tol) -function rank(A::AbstractMatrix) - m,n = size(A) - if m == 0 || n == 0; return 0; end - sv = svdvals(A) - sum(sv .> max(size(A,1),size(A,2))*eps(sv[1])) -end - -trace(A::AbstractMatrix) = sum(diag(A)) - -#kron(a::AbstractVector, b::AbstractVector) -#kron{T,S}(a::AbstractMatrix{T}, b::AbstractMatrix{S}) - -#det(a::AbstractMatrix) -inv(a::AbstractMatrix) = a \ one(a) -cond(a::AbstractMatrix, p) = norm(a, p) * norm(inv(a), p) -cond(a::AbstractMatrix) = cond(a, 2) - -#issym(A::AbstractMatrix) -#ishermitian(A::AbstractMatrix) -#istriu(A::AbstractMatrix) -#istril(A::AbstractMatrix) - -function linreg{T<:Number}(X::StridedVecOrMat{T}, y::Vector{T}) - [ones(T, size(X,1)) X] \ y +if USE_LIB64 + typealias BlasInt Int64 + blas_int(x) = int64(x) +else + typealias BlasInt Int32 + blas_int(x) = int32(x) end -# weighted least squares -function linreg(x::AbstractVector, y::AbstractVector, w::AbstractVector) - w = sqrt(w) - [w w.*x] \ (w.*y) -end +include("linalg/generic.jl") -# multiply by diagonal matrix as vector -#diagmm!(C::AbstractMatrix, A::AbstractMatrix, b::AbstractVector) +include("linalg/blas.jl") +include("linalg/matmul.jl") +include("linalg/lapack.jl") -#diagmm!(C::AbstractMatrix, b::AbstractVector, A::AbstractMatrix) +include("linalg/dense.jl") +include("linalg/factorization.jl") -diagmm!(A::AbstractMatrix, b::AbstractVector) = diagmm!(A,A,b) -diagmm!(b::AbstractVector, A::AbstractMatrix) = diagmm!(A,b,A) +include("linalg/bunchkaufman.jl") +include("linalg/triangular.jl") +include("linalg/hermitian.jl") +include("linalg/woodbury.jl") +include("linalg/tridiag.jl") +include("linalg/bidiag.jl") +include("linalg/diagonal.jl") +include("linalg/rectfullpacked.jl") -#diagmm(A::AbstractMatrix, b::AbstractVector) -#diagmm(b::AbstractVector, A::AbstractMatrix) +include("linalg/bitarray.jl") -#^(A::AbstractMatrix, p::Number) +include("linalg/sparse.jl") +include("linalg/umfpack.jl") +include("linalg/cholmod.jl") -#findmax(a::AbstractArray) -#findmin(a::AbstractArray) +include("linalg/arpack.jl") +include("linalg/arnoldi.jl") -#rref{T}(A::AbstractMatrix{T}) +end # module LinAlg diff --git a/base/linalg/arnoldi.jl b/base/linalg/arnoldi.jl new file mode 100644 index 0000000000000..f598f64f0da26 --- /dev/null +++ b/base/linalg/arnoldi.jl @@ -0,0 +1,167 @@ +using ARPACK + +## eigs + +function eigs{T <: BlasFloat}(A::AbstractMatrix{T}, nev::Integer, evtype::ASCIIString, rvec::Bool) + (m, n) = size(A) + if m != n; error("Input must be square"); end + sym = issym(A) + cmplx = iscomplex(A) + bmat = "I" + + # Compute the Ritz values and Ritz vectors + (select, tol, resid, ncv, v, ldv, iparam, ipntr, workd, workl, lworkl, rwork) = + aupd_wrapper(T, n, sym, cmplx, bmat, nev, evtype, (x) -> A * x) + + # Postprocessing to get eigenvalues and eigenvectors + return eupd_wrapper(T, n, sym, cmplx, bmat, nev, evtype, rvec, + select, tol, resid, ncv, v, ldv, iparam, ipntr, workd, workl, lworkl, rwork) + +end + +eigs(A::AbstractMatrix, nev::Integer, typ::ASCIIString) = eigs(A, nev, which, true) +eigs(A::AbstractMatrix, nev::Integer, rvec::Bool) = eigs(A, nev, "LM", rvec) +eigs(A::AbstractMatrix, rvec::Bool) = eigs(A, 6, "LM", rvec) +eigs(A::AbstractMatrix, nev::Integer) = eigs(A, nev, "LM", true) +eigs(A::AbstractMatrix) = eigs(A, 6, "LM", true) + +## svds + +# For a dense matrix A is ignored and At is actually A'*A +sarupdate{T}(A::StridedMatrix{T}, At::StridedMatrix{T}, X::StridedVector{T}) = BLAS.symv('U', one(T), At, X) +sarupdate{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, At::SparseMatrixCSC{Tv,Ti}, X::StridedVector{Tv}) = At*(A*X) + +function svds{T <: Union(Float64,Float32)}(A::AbstractMatrix{T}, nev::Integer, + which::ASCIIString, rvec::Bool) + + (m, n) = size(A) + if m < n error("m = $m, n = $n and only the m >= n case is implemented") end + sym = true + cmplx = false + bmat = "I" + At = isa(A, StridedMatrix) ? BLAS.syrk('U','T',1.0,A) : A' + + # Compute the Ritz values and Ritz vectors + (select, tol, resid, ncv, v, ldv, iparam, ipntr, workd, workl, lworkl, rwork) = + aupd_wrapper(T, n, sym, cmplx, bmat, nev, which, (x) -> sarupdate(A, At, x)) + + # Postprocessing to get eigenvalues and eigenvectors + (svals, svecs) = eupd_wrapper(T, n, sym, cmplx, bmat, nev, which, rvec, + select, tol, resid, ncv, v, ldv, iparam, ipntr, + workd, workl, lworkl, rwork) + + svals = sqrt(svals) + rvec ? (A*svecs*diagm(1./svals), svals, v.') : svals +end + +svds(A::AbstractMatrix, nev::Integer, which::ASCIIString) = svds(A, nev, which, true) +svds(A::AbstractMatrix, nev::Integer, rvec::Bool) = svds(A, nev, "LA", rvec) +svds(A::AbstractMatrix, rvec::Bool) = svds(A, 6, "LA", rvec) +svds(A::AbstractMatrix, nev::Integer) = svds(A, nev, "LA", true) +svds(A::AbstractMatrix) = svds(A, 6, "LA", true) + +## aupd and eupd wrappers + +function aupd_wrapper(T, n::Integer, sym::Bool, cmplx::Bool, bmat::ASCIIString, + nev::Integer, evtype::ASCIIString, linop::Function) + + ncv = min(max(nev*2, 20), n) + + bmat = "I" + lworkl = cmplx ? ncv * (3*ncv + 5) : ( lworkl = sym ? ncv * (ncv + 8) : ncv * (3*ncv + 6) ) + TR = cmplx ? T.types[1] : T + + v = Array(T, n, ncv) + workd = Array(T, 3*n) + workl = Array(T, lworkl) + rwork = cmplx ? Array(TR, ncv) : Array(TR, 0) + resid = Array(T, n) + select = Array(BlasInt, ncv) + iparam = zeros(BlasInt, 11) + ipntr = zeros(BlasInt, 14) + + tol = zeros(TR, 1) + ido = zeros(BlasInt, 1) + info = zeros(BlasInt, 1) + + iparam[1] = blas_int(1) # ishifts + iparam[3] = blas_int(1000) # maxitr + iparam[7] = blas_int(1) # mode 1 + + zernm1 = 0:(n-1) + + while true + if cmplx + naupd(ido, bmat, n, evtype, nev, tol, resid, ncv, v, n, + iparam, ipntr, workd, workl, lworkl, rwork, info) + elseif sym + saupd(ido, bmat, n, evtype, nev, tol, resid, ncv, v, n, + iparam, ipntr, workd, workl, lworkl, info) + else + naupd(ido, bmat, n, evtype, nev, tol, resid, ncv, v, n, + iparam, ipntr, workd, workl, lworkl, info) + end + if info[1] != 0; error("error code $(info[1]) from ARPACK aupd"); end + if (ido[1] != -1 && ido[1] != 1); break; end + workd[ipntr[2]+zernm1] = linop(getindex(workd, ipntr[1]+zernm1)) + end + + return (select, tol, resid, ncv, v, n, iparam, ipntr, workd, workl, lworkl, rwork) +end + +function eupd_wrapper(T, n::Integer, sym::Bool, cmplx::Bool, bmat::ASCIIString, + nev::Integer, evtype::ASCIIString, rvec::Bool, + select, tol, resid, ncv, v, ldv, iparam, ipntr, workd, workl, lworkl, rwork) + + howmny = "A" + info = zeros(BlasInt, 1) + + if cmplx + + d = Array(T, nev+1) + sigma = zeros(T, 1) + workev = Array(T, 2ncv) + neupd(rvec, howmny, select, d, v, ldv, workev, sigma, + bmat, n, evtype, nev, tol, resid, ncv, v, ldv, + iparam, ipntr, workd, workl, lworkl, rwork, info) + if info[1] != 0; error("error code $(info[1]) from ARPACK eupd"); end + return rvec ? (d, v[1:n, 1:nev]) : d + + elseif sym + + d = Array(T, nev) + sigma = zeros(T, 1) + seupd(rvec, howmny, select, d, v, ldv, sigma, + bmat, n, evtype, nev, tol, resid, ncv, v, ldv, + iparam, ipntr, workd, workl, lworkl, info) + if info[1] != 0; error("error code $(info[1]) from ARPACK eupd"); end + return rvec ? (d, v[1:n, 1:nev]) : d + + else + + dr = Array(T, nev+1) + di = Array(T, nev+1) + sigmar = zeros(T, 1) + sigmai = zeros(T, 1) + workev = Array(T, 3*ncv) + neupd(rvec, howmny, select, dr, di, v, ldv, sigmar, sigmai, + workev, bmat, n, evtype, nev, tol, resid, ncv, v, ldv, + iparam, ipntr, workd, workl, lworkl, info) + if info[1] != 0; error("error code $(info[1]) from ARPACK eupd"); end + evec = complex(zeros(T, n, nev+1), zeros(T, n, nev+1)) + j = 1 + while j <= nev + if di[j] == 0.0 + evec[:,j] = v[:,j] + else + evec[:,j] = v[:,j] + im*v[:,j+1] + evec[:,j+1] = v[:,j] - im*v[:,j+1] + j += 1 + end + j += 1 + end + d = complex(dr[1:nev],di[1:nev]) + return rvec ? (d, evec[1:n, 1:nev]) : d + end + +end diff --git a/base/linalg/arpack.jl b/base/linalg/arpack.jl new file mode 100644 index 0000000000000..7a9907b265d18 --- /dev/null +++ b/base/linalg/arpack.jl @@ -0,0 +1,106 @@ +module ARPACK + +export naupd, neupd, saupd, seupd + +import LinAlg.BlasInt +import LinAlg.blas_int + +for (T, saupd_name, seupd_name, naupd_name, neupd_name) in + ((:Float64, :dsaupd_, :dseupd_, :dnaupd_, :dneupd_), + (:Float32, :ssaupd_, :sseupd_, :snaupd_, :sneupd_)) + @eval begin + + function naupd(ido, bmat, n, evtype, nev, tol, resid, ncv, v, ldv, + iparam, ipntr, workd::Array{$T}, workl::Array{$T}, lworkl, info) + + ccall(($(string(naupd_name)), :libarpack), Void, + (Ptr{BlasInt}, Ptr{Uint8}, Ptr{BlasInt}, Ptr{Uint8}, Ptr{BlasInt}, + Ptr{$T}, Ptr{$T}, Ptr{BlasInt}, Ptr{$T}, Ptr{BlasInt}, + Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$T}, Ptr{$T}, Ptr{BlasInt}, Ptr{BlasInt}), + ido, bmat, &n, evtype, &nev, tol, resid, &ncv, v, &ldv, + iparam, ipntr, workd, workl, &lworkl, info) + end + + function neupd(rvec, howmny, select, dr, di, z, ldz, sigmar, sigmai, + workev, bmat, n, evtype, nev, tol, resid, ncv, v, ldv, + iparam, ipntr, workd::Array{$T}, workl::Array{$T}, lworkl, info) + + ccall(($(string(neupd_name)), :libarpack), Void, + (Ptr{BlasInt}, Ptr{Uint8}, Ptr{BlasInt}, Ptr{$T}, Ptr{$T}, Ptr{$T}, + Ptr{BlasInt}, Ptr{$T}, Ptr{$T}, Ptr{$T}, Ptr{Uint8}, Ptr{BlasInt}, + Ptr{Uint8}, Ptr{BlasInt}, Ptr{$T}, Ptr{$T}, Ptr{BlasInt}, Ptr{$T}, + Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$T}, Ptr{$T}, + Ptr{BlasInt}, Ptr{BlasInt}), + &rvec, howmny, select, dr, di, z, &ldz, sigmar, sigmai, + workev, bmat, &n, evtype, &nev, tol, resid, &ncv, v, &ldv, + iparam, ipntr, workd, workl, &lworkl, info) + end + + function saupd(ido, bmat, n, which, nev, tol, resid, ncv, v, ldv, + iparam, ipntr, workd::Array{$T}, workl::Array{$T}, lworkl, info) + + ccall(($(string(saupd_name)), :libarpack), Void, + (Ptr{BlasInt}, Ptr{Uint8}, Ptr{BlasInt}, Ptr{Uint8}, Ptr{BlasInt}, + Ptr{$T}, Ptr{$T}, Ptr{BlasInt}, Ptr{$T}, Ptr{BlasInt}, + Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$T}, Ptr{$T}, Ptr{BlasInt}, Ptr{BlasInt}), + ido, bmat, &n, which, &nev, tol, resid, &ncv, v, &ldv, + iparam, ipntr, workd, workl, &lworkl, info) + + end + + function seupd(rvec, howmny, select, d, z, ldz, sigma, + bmat, n, evtype, nev, tol, resid, ncv, v, ldv, + iparam, ipntr, workd::Array{$T}, workl::Array{$T}, lworkl, info) + + ccall(($(string(seupd_name)), :libarpack), Void, + (Ptr{BlasInt}, Ptr{Uint8}, Ptr{BlasInt}, Ptr{$T}, Ptr{$T}, Ptr{BlasInt}, Ptr{$T}, + Ptr{Uint8}, Ptr{BlasInt}, Ptr{Uint8}, Ptr{BlasInt}, + Ptr{$T}, Ptr{$T}, Ptr{BlasInt}, Ptr{$T}, Ptr{BlasInt}, Ptr{BlasInt}, + Ptr{BlasInt}, Ptr{$T}, Ptr{$T}, Ptr{BlasInt}, Ptr{BlasInt}), + &rvec, howmny, select, d, z, &ldz, sigma, + bmat, &n, evtype, &nev, tol, resid, &ncv, v, &ldv, + iparam, ipntr, workd, workl, &lworkl, info) + end + + end +end + +for (T, TR, naupd_name, neupd_name) in + ((:Complex128, :Float64, :znaupd_, :zneupd_), + (:Complex64, :Float32, :cnaupd_, :cneupd_)) + @eval begin + + function naupd(ido, bmat, n, evtype, nev, tol, resid, ncv, v, ldv, + iparam, ipntr, workd::Array{$T}, workl::Array{$T}, lworkl, + rwork::Array{$TR}, info) + + ccall(($(string(naupd_name)), :libarpack), Void, + (Ptr{BlasInt}, Ptr{Uint8}, Ptr{BlasInt}, Ptr{Uint8}, Ptr{BlasInt}, + Ptr{$TR}, Ptr{$T}, Ptr{BlasInt}, Ptr{$T}, Ptr{BlasInt}, + Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$T}, Ptr{$T}, Ptr{BlasInt}, + Ptr{$TR}, Ptr{BlasInt}), + ido, bmat, &n, evtype, &nev, tol, resid, &ncv, v, &ldv, + iparam, ipntr, workd, workl, &lworkl, rwork, info) + + end + + function neupd(rvec, howmny, select, d, z, ldz, workev, sigma, + bmat, n, evtype, nev, tol, resid, ncv, v, ldv, + iparam, ipntr, workd::Array{$T}, workl::Array{$T}, lworkl, + rwork::Array{$TR}, info) + + ccall(($(string(neupd_name)), :libarpack), Void, + (Ptr{BlasInt}, Ptr{Uint8}, Ptr{BlasInt}, Ptr{$T}, Ptr{$T}, Ptr{BlasInt}, + Ptr{$T}, Ptr{$T}, Ptr{Uint8}, Ptr{BlasInt}, Ptr{Uint8}, Ptr{BlasInt}, + Ptr{$TR}, Ptr{$T}, Ptr{BlasInt}, Ptr{$T}, Ptr{BlasInt}, Ptr{BlasInt}, + Ptr{BlasInt}, Ptr{$T}, Ptr{$T}, Ptr{BlasInt}, Ptr{$TR}, Ptr{BlasInt}), + &rvec, howmny, select, d, z, &ldz, workev, sigma, + bmat, &n, evtype, &nev, tol, resid, &ncv, v, &ldv, + iparam, ipntr, workd, workl, &lworkl, rwork, info) + + end + + end +end + +end # module ARPACK diff --git a/base/linalg/bidiag.jl b/base/linalg/bidiag.jl new file mode 100644 index 0000000000000..110543b8f5d99 --- /dev/null +++ b/base/linalg/bidiag.jl @@ -0,0 +1,128 @@ +#### Specialized matrix types #### + +## Bidiagonal matrices + + +type Bidiagonal{T} <: AbstractMatrix{T} + dv::Vector{T} # diagonal + ev::Vector{T} # sub/super diagonal + isupper::Bool # is upper bidiagonal (true) or lower (false) + function Bidiagonal{T}(dv::Vector{T}, ev::Vector{T}, isupper::Bool) + if length(ev)!=length(dv)-1 error("dimension mismatch") end + new(dv, ev, isupper) + end +end + +Bidiagonal{T<:BlasFloat}(dv::Vector{T}, ev::Vector{T}, isupper::Bool)=Bidiagonal{T}(copy(dv), copy(ev), isupper) +Bidiagonal{T}(dv::Vector{T}, ev::Vector{T}) = error("Did you want an upper or lower Bidiagonal? Try again with an additional true (upper) or false (lower) argument.") + + +#Convert from BLAS uplo flag to boolean internal +function Bidiagonal{T<:BlasFloat}(dv::Vector{T}, ev::Vector{T}, uplo::BlasChar) + if uplo=='U' + isupper = true + elseif uplo=='L' + isupper = false + else + error(string("Bidiagonal can only be upper 'U' or lower 'L' but you said '", uplo, "'")) + end + Bidiagonal{T}(copy(dv), copy(ev), isupper) +end + +function Bidiagonal{Td<:Number,Te<:Number}(dv::Vector{Td}, ev::Vector{Te}, isupper::Bool) + T = promote(Td,Te) + Bidiagonal(convert(Vector{T}, dv), convert(Vector{T}, ev), isupper) +end + +Bidiagonal(A::AbstractMatrix, isupper::Bool)=Bidiagonal(diag(A), diag(A, isupper?1:-1), isupper) + +#Converting from Bidiagonal to dense Matrix +full{T}(M::Bidiagonal{T}) = convert(Matrix{T}, M) +convert{T}(::Type{Matrix{T}}, A::Bidiagonal{T})=diagm(A.dv) + diagm(A.ev, A.isupper?1:-1) +promote_rule{T}(::Type{Matrix{T}}, ::Type{Bidiagonal{T}})=Matrix{T} +promote_rule{T,S}(::Type{Matrix{T}}, ::Type{Bidiagonal{S}})=Matrix{promote_type(T,S)} + +#Converting from Bidiagonal to Tridiagonal +Tridiagonal{T}(M::Bidiagonal{T}) = convert(Tridiagonal{T}, M) +function convert{T}(::Type{Tridiagonal{T}}, A::Bidiagonal{T}) + z = zeros(T, size(A)[1]-1) + A.isupper ? Tridiagonal(A.ev, A.dv, z) : Tridiagonal(z, A.dv, A.ev) +end +promote_rule{T}(::Type{Tridiagonal{T}}, ::Type{Bidiagonal{T}})=Tridiagonal{T} +promote_rule{T,S}(::Type{Tridiagonal{T}}, ::Type{Bidiagonal{S}})=Tridiagonal{promote_type(T,S)} + + +function show(io::IO, M::Bidiagonal) + println(io, summary(M), ":") + print(io, "diag: ") + print_matrix(io, (M.dv)') + print(io, M.isupper?"\n sup: ":"\n sub: ") + print_matrix(io, (M.ev)') +end + +size(M::Bidiagonal) = (length(M.dv), length(M.dv)) +size(M::Bidiagonal, d::Integer) = d<1 ? error("dimension out of range") : (d<=2 ? length(M.dv) : 1) + +#Elementary operations +copy(M::Bidiagonal) = Bidiagonal(copy(M.dv), copy(M.ev), copy(M.isupper)) +round(M::Bidiagonal) = Bidiagonal(round(M.dv), round(M.ev), M.isupper) +iround(M::Bidiagonal) = Bidiagonal(iround(M.dv), iround(M.ev), M.isupper) + +conj(M::Bidiagonal) = Bidiagonal(conj(M.dv), conj(M.ev), M.isupper) +transpose(M::Bidiagonal) = Bidiagonal(M.dv, M.ev, !M.isupper) +ctranspose(M::Bidiagonal) = Bidiagonal(conj(M.dv), conj(M.ev), !M.isupper) + +function +(A::Bidiagonal, B::Bidiagonal) + if A.isupper==B.isupper + Bidiagonal(A.dv+B.dv, A.ev+B.ev, A.isupper) + else #return tridiagonal + if A.isupper #&& !B.isupper + Tridiagonal(B.ev,A.dv+B.dv,A.ev) + else + Tridiagonal(A.ev,A.dv+B.dv,B.ev) + end + end +end + +function -(A::Bidiagonal, B::Bidiagonal) + if A.isupper==B.isupper + Bidiagonal(A.dv-B.dv, A.ev-B.ev, A.isupper) + else #return tridiagonal + if A.isupper #&& !B.isupper + Tridiagonal(-B.ev,A.dv-B.dv,A.ev) + else + Tridiagonal(A.ev,A.dv-B.dv,-B.ev) + end + end +end + +-(A::Bidiagonal)=Bidiagonal(-A.dv,-A.ev) +#XXX Returns dense matrix but really should be banded +*(A::Bidiagonal, B::Bidiagonal) = full(A)*full(B) +*(A::Bidiagonal, B::Number) = Bidiagonal(A.dv*B, A.ev*B, A.isupper) +*(B::Number, A::Bidiagonal) = A*B +/(A::Bidiagonal, B::Number) = Bidiagonal(A.dv/B, A.ev/B, A.isupper) +==(A::Bidiagonal, B::Bidiagonal) = (A.dv==B.dv) && (A.ev==B.ev) && (A.isupper==B.isupper) + +*(A::SymTridiagonal, B::Bidiagonal) = full(A)*full(B) +*(A::Bidiagonal, B::SymTridiagonal) = full(A)*full(B) +*(A::Tridiagonal, B::Bidiagonal) = full(A)*full(B) +*(A::Bidiagonal, B::Tridiagonal) = full(A)*full(B) + +# solver uses tridiagonal gtsv! +function \{T<:BlasFloat}(M::Bidiagonal{T}, rhs::StridedVecOrMat{T}) + if stride(rhs, 1) == 1 + z = zeros(size(M)[1]) + if M.isupper + return LAPACK.gtsv!(z, copy(M.dv), copy(M.ev), copy(rhs)) + else + return LAPACK.gtsv!(copy(M.ev), copy(M.dv), z, copy(rhs)) + end + end + solve(M, rhs) # use the Julia "fallback" +end + +#Wrap bdsdc to compute singular values and vectors +svdvals{T<:Real}(M::Bidiagonal{T})=LAPACK.bdsdc!(M.isupper?'U':'L', 'N', copy(M.dv), copy(M.ev)) +svd {T<:Real}(M::Bidiagonal{T})=LAPACK.bdsdc!(M.isupper?'U':'L', 'I', copy(M.dv), copy(M.ev)) + diff --git a/base/linalg_bitarray.jl b/base/linalg/bitarray.jl similarity index 56% rename from base/linalg_bitarray.jl rename to base/linalg/bitarray.jl index 4e9d02ab2eac1..88b5c1252b981 100644 --- a/base/linalg_bitarray.jl +++ b/base/linalg/bitarray.jl @@ -1,6 +1,6 @@ -function dot{T,S}(x::BitVector{T}, y::BitVector{S}) +function dot(x::BitVector, y::BitVector) # simplest way to mimic Array dot behavior - s = zero(one(T) * one(S)) + s = 0 for i = 1 : length(x.chunks) s += count_ones(x.chunks[i] & y.chunks[i]) end @@ -10,23 +10,24 @@ end ## slower than the unpacked version, which is MUCH slower # than blas'd (this one saves storage though, keeping it commented # just in case) -#function aTb{T,S}(A::BitMatrix{T}, B::BitMatrix{S}) +#function aTb(A::BitMatrix, B::BitMatrix) #(mA, nA) = size(A) #(mB, nB) = size(B) - #C = zeros(promote_type(T,S), nA, nB) + #C = falses(nA, nB) #if mA != mB; error("*: argument shapes do not match"); end #if mA == 0; return C; end - #col_ch = _jl_num_bit_chunks(mA) + #col_ch = num_bit_chunks(mA) ## TODO: avoid using aux chunks and copy (?) #aux_chunksA = zeros(Uint64, col_ch) #aux_chunksB = [zeros(Uint64, col_ch) for j=1:nB] #for j = 1:nB - #_jl_copy_chunks(aux_chunksB[j], 1, B.chunks, (j-1)*mA+1, mA) + #copy_chunks(aux_chunksB[j], 1, B.chunks, (j-1)*mA+1, mA) #end #for i = 1:nA - #_jl_copy_chunks(aux_chunksA, 1, A.chunks, (i-1)*mA+1, mA) + #copy_chunks(aux_chunksA, 1, A.chunks, (i-1)*mA+1, mA) #for j = 1:nB #for k = 1:col_ch + ## TODO: improve #C[i, j] += count_ones(aux_chunksA[k] & aux_chunksB[j][k]) #end #end @@ -36,60 +37,34 @@ end #aCb{T, S}(A::BitMatrix{T}, B::BitMatrix{S}) = aTb(A, B) -function triu{T}(B::BitMatrix{T}, k::Int) +function triu(B::BitMatrix, k::Int) m,n = size(B) - A = bitzeros(T, m,n) + A = falses(m,n) for i = max(k+1,1):n j = clamp((i - 1) * m + 1, 1, i * m) - _jl_copy_chunks(A.chunks, j, B.chunks, j, min(i-k, m)) + Base.copy_chunks(A.chunks, j, B.chunks, j, min(i-k, m)) end return A end triu(B::BitMatrix, k::Integer) = triu(B, int(k)) -function tril{T}(B::BitMatrix{T}, k::Int) +function tril(B::BitMatrix, k::Int) m,n = size(B) - A = bitzeros(T, m, n) + A = falses(m, n) for i = 1:min(n, m+k) j = clamp((i - 1) * m + i - k, 1, i * m) - _jl_copy_chunks(A.chunks, j, B.chunks, j, max(m-i+k+1, 0)) + Base.copy_chunks(A.chunks, j, B.chunks, j, max(m-i+k+1, 0)) end return A end tril(B::BitMatrix, k::Integer) = tril(B, int(k)) -## Matrix multiplication and division - -#disambiguations -(*){T<:Integer,S<:Integer}(A::BitMatrix{T}, B::BitVector{S}) = bitunpack(A) * bitunpack(B) -(*){T<:Integer,S<:Integer}(A::BitVector{T}, B::BitMatrix{S}) = bitunpack(A) * bitunpack(B) -(*){T<:Integer,S<:Integer}(A::BitMatrix{T}, B::BitMatrix{S}) = bitunpack(A) * bitunpack(B) -(*){T<:Integer}(A::BitMatrix{T}, B::AbstractVector) = (*)(bitunpack(A), B) -(*){T<:Integer}(A::BitVector{T}, B::AbstractMatrix) = (*)(bitunpack(A), B) -(*){T<:Integer}(A::BitMatrix{T}, B::AbstractMatrix) = (*)(bitunpack(A), B) -(*){T<:Integer}(A::AbstractVector, B::BitMatrix{T}) = (*)(A, bitunpack(B)) -(*){T<:Integer}(A::AbstractMatrix, B::BitVector{T}) = (*)(A, bitunpack(B)) -(*){T<:Integer}(A::AbstractMatrix, B::BitMatrix{T}) = (*)(A, bitunpack(B)) -#end disambiguations - -for f in (:/, :\, :*) - @eval begin - ($f)(A::BitArray, B::BitArray) = ($f)(bitunpack(A), bitunpack(B)) - ($f)(A::BitArray, B::AbstractArray) = ($f)(bitunpack(A), B) - ($f)(A::AbstractArray, B::BitArray) = ($f)(A, bitunpack(B)) - end -end - -# specialized Bool versions - -#disambiguations (TODO: improve!) -(*)(A::BitMatrix{Bool}, B::BitVector{Bool}) = bitpack(bitunpack(A) * bitunpack(B)) -(*)(A::BitVector{Bool}, B::BitMatrix{Bool}) = bitpack(bitunpack(A) * bitunpack(B)) -(*)(A::BitMatrix{Bool}, B::BitMatrix{Bool}) = bitpack(bitunpack(A) * bitunpack(B)) -#end disambiguations - # TODO: improve this! -(*)(A::BitArray{Bool}, B::BitArray{Bool}) = bitpack(bitunpack(A) * bitunpack(B)) +(*)(A::BitArray, B::BitArray) = bitpack(bitunpack(A) * bitunpack(B)) +(*)(A::BitArray, B::Array{Bool}) = bitpack(bitunpack(A) * B) +(*)(A::Array{Bool}, B::BitArray) = bitpack(A * bitunpack(B)) +(*)(A::BitArray, B::AbstractArray) = bitunpack(A) * B +(*)(A::AbstractArray, B::BitArray) = A * bitunpack(B) ## diff and gradient @@ -111,15 +86,15 @@ function diag(B::BitMatrix) return v end -function diagm{T}(v::Union(BitVector{T},BitMatrix{T})) +function diagm(v::Union(BitVector,BitMatrix)) if isa(v, BitMatrix) if (size(v,1) != 1 && size(v,2) != 1) error("Input should be nx1 or 1xn") end end - n = numel(v) - a = bitzeros(T, n, n) + n = length(v) + a = falses(n, n) for i=1:n a[i,i] = v[i] end @@ -135,29 +110,28 @@ qr(A::BitMatrix) = qr(float(A)) ## kron -function kron{T,S}(a::BitVector{T}, b::BitVector{S}) +function kron(a::BitVector, b::BitVector) m = length(a) n = length(b) - R = BitArray(promote_type(T,S), m, n) + R = BitArray(m, n) zS = zero(S) for j = 1:n if b[j] != zS - _jl_copy_chunks(R.chunks, (j-1)*m+1, a.chunks, 1, m) + Base.copy_chunks(R.chunks, (j-1)*m+1, a.chunks, 1, m) end end return R end -function kron{T,S}(a::BitMatrix{T}, b::BitMatrix{S}) +function kron(a::BitMatrix, b::BitMatrix) mA,nA = size(a) mB,nB = size(b) - R = bitzeros(promote_type(T,S), mA*mB, nA*nB) + R = falses(mA*mB, nA*nB) - zT = zero(T) for i = 1:mA ri = (1:mB)+(i-1)*mB for j = 1:nA - if a[i,j] != zT + if a[i,j] rj = (1:nB)+(j-1)*nB R[ri,rj] = b end @@ -170,16 +144,16 @@ end function issym(A::BitMatrix) m, n = size(A) - if m != n; error("matrix must be square, got $(m)x$(n)"); end + if m != n; return false; end return nnz(A - A.') == 0 end ishermitian(A::BitMatrix) = issym(A) -function _jl_nonzero_chunks(chunks::Vector{Uint64}, pos0::Int, pos1::Int) +function nonzero_chunks(chunks::Vector{Uint64}, pos0::Int, pos1::Int) - k0, l0 = _jl_get_chunks_id(pos0) - k1, l1 = _jl_get_chunks_id(pos1) + k0, l0 = get_chunks_id(pos0) + k1, l1 = get_chunks_id(pos1) delta_k = k1 - k0 @@ -217,7 +191,7 @@ function istriu(A::BitMatrix) m, n = size(A) for j = 1:min(n,m-1) stride = (j-1)*m - if _jl_nonzero_chunks(A.chunks, stride+j+1, stride+m) + if nonzero_chunks(A.chunks, stride+j+1, stride+m) return false end end @@ -231,7 +205,7 @@ function istril(A::BitMatrix) end for j = 2:n stride = (j-1)*m - if _jl_nonzero_chunks(A.chunks, stride+1, stride+min(j-1,m)) + if nonzero_chunks(A.chunks, stride+1, stride+min(j-1,m)) return false end end @@ -240,17 +214,16 @@ end function findmax(a::BitArray) if length(a) == 0 - return (typemin(eltype(a)), 0) + error("findmax: array is empty") end - m = zero(eltype(a)) - o = one(eltype(a)) + m = false mi = 1 ti = 1 for i=1:length(a.chunks) k = trailing_zeros(a.chunks[i]) ti += k if k != 64 - m = o + m = true mi = ti break end @@ -260,25 +233,24 @@ end function findmin(a::BitArray) if length(a) == 0 - return (typemax(eltype(a)), 0) + error("findmin: array is empty") end - m = one(eltype(a)) - z = zero(eltype(a)) + m = true mi = 1 ti = 1 for i=1:length(a.chunks) - 1 k = trailing_ones(a.chunks[i]) ti += k if k != 64 - return (z, ti) + return (false, ti) end end - l = (@_mod64 (length(a)-1)) + 1 - msk = @_mskr l + l = (Base.@_mod64 (length(a)-1)) + 1 + msk = Base.@_mskr l k = trailing_ones(a.chunks[end] & msk) ti += k if k != l - m = z + m = false mi = ti end return (m, mi) diff --git a/base/linalg/blas.jl b/base/linalg/blas.jl new file mode 100644 index 0000000000000..e4e888aba7934 --- /dev/null +++ b/base/linalg/blas.jl @@ -0,0 +1,581 @@ +module BLAS + +import Base.copy! + +export copy!, + scal!, + scal, + dot, + asum, + nrm2, + axpy!, + syrk!, + syrk, + herk!, + herk, + gbmv!, + gbmv, + sbmv!, + sbmv, + gemm!, + gemm, + symm!, + symm, + symv!, + symv + +const libblas = Base.libblas_name + +import LinAlg.BlasFloat +import LinAlg.BlasChar +import LinAlg.BlasInt +import LinAlg.blas_int + +# SUBROUTINE DCOPY(N,DX,INCX,DY,INCY) +for (fname, elty) in ((:dcopy_,:Float64), (:scopy_,:Float32), + (:zcopy_,:Complex128), (:ccopy_,:Complex64)) + @eval begin + function copy!(n::Integer, DX::Union(Ptr{$elty},Array{$elty}), incx::Integer, DY::Union(Ptr{$elty},Array{$elty}), incy::Integer) + ccall(($(string(fname)),libblas), Void, + (Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}), + &n, DX, &incx, DY, &incy) + DY + end + end +end + +# SUBROUTINE DSCAL(N,DA,DX,INCX) +for (fname, elty) in ((:dscal_,:Float64), (:sscal_,:Float32), + (:zscal_,:Complex128), (:cscal_,:Complex64)) + @eval begin + function scal!(n::Integer, DA::$elty, DX::Union(Ptr{$elty},Array{$elty}), incx::Integer) + ccall(($(string(fname)),libblas), Void, + (Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}), + &n, &DA, DX, &incx) + DX + end + function scal(n::Integer, DA::$elty, DX_orig::Union(Ptr{$elty},Array{$elty}), incx::Integer) + DX = copy(DX_orig) + ccall(($(string(fname)),libblas), Void, + (Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}), + &n, &DA, DX, &incx) + DX + end + end +end + +# dot +for (fname, elty) in ((:ddot_,:Float64), (:sdot_,:Float32)) + @eval begin +# DOUBLE PRECISION FUNCTION DDOT(N,DX,INCX,DY,INCY) +# * .. Scalar Arguments .. +# INTEGER INCX,INCY,N +# * .. +# * .. Array Arguments .. +# DOUBLE PRECISION DX(*),DY(*) + function dot(n::Integer, DX::Union(Ptr{$elty},Array{$elty}), incx::Integer, DY::Union(Ptr{$elty},Array{$elty}), incy::Integer) + ccall(($(string(fname)),libblas), $elty, + (Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}), + &n, DX, &incx, DY, &incy) + end + end +end +for (fname, elty, relty) in ((:zdotc_,:Complex128,:Float64), (:cdotc_,:Complex64,:Float32)) + @eval begin +# DOUBLE COMPLEX FUNCTION ZDOTC(N,ZX,INCX,ZY,INCY) +# * .. Scalar Arguments .. +# INTEGER INCX,INCY,N +# * .. +# * .. Array Arguments .. +# DOUBLE COMPLEX ZX(*),ZY(*) + function dot(n::Integer, DX::Union(Ptr{$elty},Array{$elty}), incx::Integer, DY::Union(Ptr{$elty},Array{$elty}), incy::Integer) + convert($elty, ccall(($(string(fname)),libblas), ComplexPair{$relty}, + (Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}), + &n, DX, &incx, DY, &incy)) + end + end +end +function dot{T<:BlasFloat}(DX::Array{T}, DY::Array{T}) + n = length(DX) + if n != length(DY) throw(BlasDimMisMatch) end + return dot(n, DX, 1, DY, 1) +end + +# SUBROUTINE DNRM2(N,X,INCX) +for (fname, elty, ret_type) in ((:dnrm2_,:Float64,:Float64), + (:snrm2_,:Float32,:Float32), + (:dznrm2_,:Complex128,:Float64), + (:scnrm2_,:Complex64,:Float32)) + @eval begin + function nrm2(n::Integer, X::Union(Ptr{$elty},Array{$elty}), incx::Integer) + ccall(($(string(fname)),libblas), $ret_type, + (Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}), + &n, X, &incx) + end + end +end + +nrm2(A::Array) = nrm2(length(A), A, 1) + +# SUBROUTINE ASUM(N, X, INCX) +for (fname, elty, ret_type) in ((:dasum_,:Float64,:Float64), + (:sasum_,:Float32,:Float32), + (:dzasum_,:Complex128,:Float64), + (:scasum_,:Complex64,:Float32)) + @eval begin + function asum(n::Integer, X::Union(Ptr{$elty},Array{$elty}), incx::Integer) + ccall(($(string(fname)),libblas), $ret_type, + (Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}), + &n, X, &incx) + end + end +end + +asum(A::Array) = asum(length(A), A, 1) + +# SUBROUTINE DAXPY(N,DA,DX,INCX,DY,INCY) +# DY <- DA*DX + DY +#* .. Scalar Arguments .. +# DOUBLE PRECISION DA +# INTEGER INCX,INCY,N +#* .. Array Arguments .. +# DOUBLE PRECISION DX(*),DY(*) +for (fname, elty) in ((:daxpy_,:Float64), (:saxpy_,:Float32), + (:zaxpy_,:Complex128), (:caxpy_,:Complex64)) + @eval begin + function axpy!(n::Integer, alpha::($elty), + dx::Union(Ptr{$elty},Array{$elty}), incx::Integer, + dy::Union(Ptr{$elty},Array{$elty}), incy::Integer) + ccall(($(string(fname)),libblas), Void, + (Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}), + &n, &alpha, dx, &incx, dy, &incy) + return dy + end + end +end + +function axpy!{T,Ta<:Number}(alpha::Ta, x::Array{T}, y::Array{T}) + if length(x) != length(y) + error("Inputs should be of the same length") + end + return axpy!(length(x), convert(T, alpha), x, 1, y, 1) +end + +function axpy!{T,Ta<:Number,Ti<:Integer}(alpha::Ta, x::Array{T}, rx::Union(Range1{Ti},Range{Ti}), y::Array{T}, ry::Union(Range1{Ti},Range{Ti})) + + if length(rx) != length(ry) + error("Ranges should be of the same length") + end + + if min(rx) < 1 || max(rx) > length(x) || min(ry) < 1 || max(ry) > length(y) + throw(BoundsError()) + end + + return axpy!(length(rx), convert(T, alpha), pointer(x)+(first(rx)-1)*sizeof(T), step(rx), pointer(y)+(first(ry)-1)*sizeof(T), step(ry)) +end + +for (fname, elty) in ((:dsyrk_,:Float64), (:ssyrk_,:Float32), + (:zsyrk_,:Complex128), (:csyrk_,:Complex64)) + @eval begin + # SUBROUTINE DSYRK(UPLO,TRANS,N,K,ALPHA,A,LDA,BETA,C,LDC) + # * .. Scalar Arguments .. + # REAL ALPHA,BETA + # INTEGER K,LDA,LDC,N + # CHARACTER TRANS,UPLO + # * .. Array Arguments .. + # REAL A(LDA,*),C(LDC,*) + function syrk!(uplo::BlasChar, trans::BlasChar, alpha::($elty), A::StridedVecOrMat{$elty}, + beta::($elty), C::StridedMatrix{$elty}) + m, n = size(C) + if m != n error("syrk!: matrix C must be square") end + nn = size(A, trans == 'N' ? 1 : 2) + if nn != n error("syrk!: dimension mismatch") end + k = size(A, trans == 'N' ? 2 : 1) + ccall(($(string(fname)),libblas), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}), + &uplo, &trans, &n, &k, &alpha, A, &stride(A,2), &beta, C, &stride(C,2)) + C + end + function syrk(uplo::BlasChar, trans::BlasChar, alpha::($elty), A::StridedVecOrMat{$elty}) + n = size(A, trans == 'N' ? 1 : 2) + syrk!(uplo, trans, alpha, A, zero($elty), Array($elty, (n, n))) + end + syrk(uplo::BlasChar, trans::BlasChar, A::StridedVecOrMat{$elty}) = syrk(uplo, trans, one($elty), A) + end +end + +# SUBROUTINE CHERK(UPLO,TRANS,N,K,ALPHA,A,LDA,BETA,C,LDC) +# * .. Scalar Arguments .. +# REAL ALPHA,BETA +# INTEGER K,LDA,LDC,N +# CHARACTER TRANS,UPLO +# * .. +# * .. Array Arguments .. +# COMPLEX A(LDA,*),C(LDC,*) +for (fname, elty) in ((:zherk_,:Complex128), (:cherk_,:Complex64)) + @eval begin + function herk!(uplo::BlasChar, trans::BlasChar, alpha::($elty), A::StridedVecOrMat{$elty}, + beta::($elty), C::StridedMatrix{$elty}) + m, n = size(C) + if m != n error("syrk!: matrix C must be square") end + nn = size(A, trans == 'N' ? 1 : 2) + if nn != n error("syrk!: dimension mismatch") end + k = size(A, trans == 'N' ? 2 : 1) + ccall(($(string(fname)),libblas), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}), + &uplo, &trans, &n, &k, &alpha, A, &stride(A,2), &beta, C, &stride(C,2)) + C + end + function herk(uplo::BlasChar, trans::BlasChar, alpha::($elty), A::StridedVecOrMat{$elty}) + n = size(A, trans == 'N' ? 1 : 2) + herk!(uplo, trans, alpha, A, zero($elty), Array($elty, (n,n))) + end + herk(uplo::BlasChar, trans::BlasChar, A::StridedVecOrMat{$elty}) = herk(uplo, trans, one($elty), A) + end +end + +# (GB) general banded matrix-vector multiplication +# SUBROUTINE DGBMV(TRANS,M,N,KL,KU,ALPHA,A,LDA,X,INCX,BETA,Y,INCY) +# * .. Scalar Arguments .. +# DOUBLE PRECISION ALPHA,BETA +# INTEGER INCX,INCY,KL,KU,LDA,M,N +# CHARACTER TRANS +# * .. +# * .. Array Arguments .. +# DOUBLE PRECISION A(LDA,*),X(*),Y(*) +for (fname, elty) in ((:dgbmv_,:Float64), (:sgbmv_,:Float32), + (:zgbmv_,:Complex128), (:cgbmv_,:Complex64)) + @eval begin + function gbmv!(trans::BlasChar, m::Integer, kl::Integer, ku::Integer, + alpha::($elty), A::StridedMatrix{$elty}, x::StridedVector{$elty}, + beta::($elty), y::StridedVector{$elty}) + ccall(($(string(fname)),libblas), Void, + (Ptr{Uint8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}), + &trans, &m, &size(A,2), &kl, &ku, &alpha, A, &stride(A,2), + x, &stride(x,1), &beta, y, &stride(y,1)) + y + end + function gbmv(trans::BlasChar, m::Integer, kl::Integer, ku::Integer, + alpha::($elty), A::StridedMatrix{$elty}, x::StridedVector{$elty}) + n = stride(A,2) + gbmv!(trans, m, kl, ku, alpha, A, x, zero($elty), Array($elty, n)) + end + function gbmv(trans::BlasChar, m::Integer, kl::Integer, ku::Integer, + A::StridedMatrix{$elty}, x::StridedVector{$elty}) + gbmv(trans, m, kl, ku, one($elty), A, x) + end + end +end + +# (SB) symmetric banded matrix-vector multiplication +# SUBROUTINE DSBMV(UPLO,N,K,ALPHA,A,LDA,X,INCX,BETA,Y,INCY) +# * .. Scalar Arguments .. +# DOUBLE PRECISION ALPHA,BETA +# INTEGER INCX,INCY,K,LDA,N +# CHARACTER UPLO +# * .. +# * .. Array Arguments .. +# DOUBLE PRECISION A(LDA,*),X(*),Y(*) +for (fname, elty) in ((:dsbmv_,:Float64), (:ssbmv_,:Float32), + (:zsbmv_,:Complex128), (:csbmv_,:Complex64)) + @eval begin + function sbmv!(uplo::BlasChar, k::Integer, + alpha::($elty), A::StridedMatrix{$elty}, x::StridedVector{$elty}, + beta::($elty), y::StridedVector{$elty}) + ccall(($(string(fname)),libblas), Void, + (Ptr{Uint8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}), + &uplo, &size(A,2), &k, &alpha, A, &stride(A,2), x, &stride(x,1), &beta, y, &stride(y,1)) + y + end + function sbmv(uplo::BlasChar, k::Integer, alpha::($elty), A::StridedMatrix{$elty}, + x::StridedVector{$elty}) + n = size(A,2) + sbmv!(uplo, k, alpha, A, x, zero($elty), Array($elty, n)) + end + function sbmv(uplo::BlasChar, k::Integer, A::StridedMatrix{$elty}, x::StridedVector{$elty}) + sbmv(uplo, k, one($elty), A, x) + end + end +end + +# (GE) general matrix-matrix and matrix-vector multiplication +for (gemm, gemv, elty) in + ((:dgemm_,:dgemv_,:Float64), + (:sgemm_,:sgemv_,:Float32), + (:zgemm_,:zgemv_,:Complex128), + (:cgemm_,:cgemv_,:Complex64)) + @eval begin + # SUBROUTINE DGEMM(TRANSA,TRANSB,M,N,K,ALPHA,A,LDA,B,LDB,BETA,C,LDC) + # * .. Scalar Arguments .. + # DOUBLE PRECISION ALPHA,BETA + # INTEGER K,LDA,LDB,LDC,M,N + # CHARACTER TRANSA,TRANSB + # * .. Array Arguments .. + # DOUBLE PRECISION A(LDA,*),B(LDB,*),C(LDC,*) + function gemm!(transA::BlasChar, transB::BlasChar, + alpha::($elty), A::StridedVecOrMat{$elty}, + B::StridedMatrix{$elty}, + beta::($elty), C::StridedVecOrMat{$elty}) +# if any([stride(A,1), stride(B,1), stride(C,1)] .!= 1) +# error("gemm!: BLAS module requires contiguous matrix columns") +# end # should this be checked on every call? + m = size(A, transA == 'N' ? 1 : 2) + k = size(A, transA == 'N' ? 2 : 1) + n = size(B, transB == 'N' ? 2 : 1) + if m != size(C,1) || n != size(C,2) + error("gemm!: mismatched dimensions") + end + ccall(($(string(gemm)),libblas), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}), + &transA, &transB, &m, &n, &k, &alpha, A, &stride(A,2), + B, &stride(B,2), &beta, C, &stride(C,2)) + C + end + function gemm(transA::BlasChar, transB::BlasChar, + alpha::($elty), A::StridedMatrix{$elty}, + B::StridedMatrix{$elty}) + gemm!(transA, transB, alpha, A, B, zero($elty), + Array($elty, (size(A, transA == 'N' ? 1 : 2), + size(B, transB == 'N' ? 2 : 1)))) + end + function gemm(transA::BlasChar, transB::BlasChar, + A::StridedMatrix{$elty}, B::StridedMatrix{$elty}) + gemm(transA, transB, one($elty), A, B) + end + #SUBROUTINE DGEMV(TRANS,M,N,ALPHA,A,LDA,X,INCX,BETA,Y,INCY) + #* .. Scalar Arguments .. + # DOUBLE PRECISION ALPHA,BETA + # INTEGER INCX,INCY,LDA,M,N + # CHARACTER TRANS + #* .. Array Arguments .. + # DOUBLE PRECISION A(LDA,*),X(*),Y(*) + function gemv!(trans::BlasChar, + alpha::($elty), A::StridedMatrix{$elty}, + X::StridedVector{$elty}, + beta::($elty), Y::StridedVector{$elty}) + ccall(($(string(gemv)),libblas), Void, + (Ptr{Uint8}, Ptr{BlasInt}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}), + &trans, &size(A,1), &size(A,2), &alpha, A, &stride(A,2), + X, &stride(X,1), &beta, Y, &stride(Y,1)) + Y + end + function gemv(trans::BlasChar, + alpha::($elty), A::StridedMatrix{$elty}, + X::StridedVector{$elty}) + gemv!(trans, alpha, A, X, zero($elty), + Array($elty, size(A, (trans == 'N' ? 1 : 2)))) + end + function gemv(trans::BlasChar, A::StridedMatrix{$elty}, X::StridedVector{$elty}) + gemv!(trans, one($elty), A, X, zero($elty), + Array($elty, size(A, (trans == 'N' ? 1 : 2)))) + end + end +end + +# (SY) symmetric matrix-matrix and matrix-vector multiplication +for (mfname, vfname, elty) in + ((:dsymm_,:dsymv_,:Float64), + (:ssymm_,:ssymv_,:Float32), + (:zsymm_,:zsymv_,:Complex128), + (:csymm_,:csymv_,:Complex64)) + @eval begin + # SUBROUTINE DSYMM(SIDE,UPLO,M,N,ALPHA,A,LDA,B,LDB,BETA,C,LDC) + # .. Scalar Arguments .. + # DOUBLE PRECISION ALPHA,BETA + # INTEGER LDA,LDB,LDC,M,N + # CHARACTER SIDE,UPLO + # .. Array Arguments .. + # DOUBLE PRECISION A(LDA,*),B(LDB,*),C(LDC,*) + function symm!(side::BlasChar, uplo::BlasChar, alpha::($elty), A::StridedMatrix{$elty}, + B::StridedMatrix{$elty}, beta::($elty), C::StridedMatrix{$elty}) + m, n = size(C) + k, j = size(A) + if k != j error("symm!: matrix A is $k by $j but must be square") end + if j != (side == 'L' ? m : n) || size(B,2) != n error("symm!: Dimension mismatch") end + ccall(($(string(mfname)),libblas), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}), + &side, &uplo, &m, &n, &alpha, A, &stride(A,2), B, &stride(B,2), + &beta, C, &stride(C,2)) + C + end + function symm(side::BlasChar, uplo::BlasChar, alpha::($elty), A::StridedMatrix{$elty}, + B::StridedMatrix{$elty}) + symm!(side, uplo, alpha, A, B, zero($elty), similar(B)) + end + function symm(side::BlasChar, uplo::BlasChar, A::StridedMatrix{$elty}, B::StridedMatrix{$elty}) + symm(side, uplo, one($elty), A, B) + end + # SUBROUTINE DSYMV(UPLO,N,ALPHA,A,LDA,X,INCX,BETA,Y,INCY) + # .. Scalar Arguments .. + # DOUBLE PRECISION ALPHA,BETA + # INTEGER INCX,INCY,LDA,N + # CHARACTER UPLO + # .. Array Arguments .. + # DOUBLE PRECISION A(LDA,*),X(*),Y(*) + function symv!(uplo::BlasChar, alpha::($elty), A::StridedMatrix{$elty}, x::StridedVector{$elty}, + beta::($elty), y::StridedVector{$elty}) + m, n = size(A) + if m != n error("symm!: matrix A is $m by $n but must be square") end + if m != length(x) || m != length(y) error("symm!: dimension mismatch") end + ccall(($(string(vfname)),libblas), Void, + (Ptr{Uint8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}), + &uplo, &n, &alpha, A, &stride(A,2), x, &stride(x,1), &beta, y, &stride(y,1)) + y + end + function symv(uplo::BlasChar, alpha::($elty), A::StridedMatrix{$elty}, x::StridedVector{$elty}) + symv!(uplo, alpha, A, x, zero($elty), similar(x)) + end + function symv(uplo::BlasChar, A::StridedMatrix{$elty}, x::StridedVector{$elty}) + symv(uplo, one($elty), A, x) + end + end +end + +# (TR) Triangular matrix multiplication +# Vector +for (fname, elty) in + ((:dtrmv_,:Float64), + (:strmv_,:Float32), + (:ztrmv_,:Complex128), + (:ctrmv_,:Complex64)) + @eval begin +# SUBROUTINE DTRMV(UPLO,TRANS,DIAG,N,A,LDA,X,INCX) +# * .. Scalar Arguments .. +# INTEGER INCX,LDA,N +# CHARACTER DIAG,TRANS,UPLO +# * .. +# * .. Array Arguments .. +# DOUBLE PRECISION A(LDA,*),X(*) + function trmv!(uplo::Char, trans::Char, diag::Char, A::StridedMatrix{$elty}, x::StridedVector{$elty}) + n, m = size(A) + if m != n throw(BlasDimMisMatch("Matrix must be square")) end + if n != length(x) throw(BlasDimMisMatch("Length of Vector must match matrix dimension")) end + lda = max(1,stride(A, 2)) + ccall(($(string(fname)), libblas), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{Uint8}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}), + &uplo, &trans, &diag, &n, + A, &lda, x, &1) + return x + end + trmv(uplo::Char, trans::Char, diag::Char, A::StridedMatrix{$elty}, x::StridedVector{$elty}) = trmv!(uplo, trans, diag, A, copy(x)) + + end +end + +# Matrix +for (fname, elty) in + ((:dtrmm_,:Float64), + (:strmm_,:Float32), + (:ztrmm_,:Complex128), + (:ctrmm_,:Complex64)) + @eval begin +# SUBROUTINE DTRMM(SIDE,UPLO,TRANSA,DIAG,M,N,ALPHA,A,LDA,B,LDB) +# * .. Scalar Arguments .. +# DOUBLE PRECISION ALPHA +# INTEGER LDA,LDB,M,N +# CHARACTER DIAG,SIDE,TRANSA,UPLO +# * .. +# * .. Array Arguments .. +# DOUBLE PRECISION A(LDA,*),B(LDB,*) + function trmm!(side::Char, uplo::Char, transa::Char, diag::Char, alpha::Number, A::StridedMatrix{$elty}, B::StridedMatrix{$elty}) + m, n = size(B) + mA, nA = size(A) + if mA != nA throw(BlasDimMisMatch("Matrix must be square")) end + if side == 'L' && nA != m throw(BlasDimMisMatch("")) end + if side == 'R' && nA != n throw(BlasDimMisMatch("")) end + lda = max(1,stride(A, 2)) + ldb = max(1,stride(B, 2)) + ccall(($(string(fname)), libblas), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{Uint8}, Ptr{Uint8}, + Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, + Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}), + &side, &uplo, &transa, &diag, + &m, &n, &alpha, A, + &lda, B, &ldb) + return B + end + trmm(side::Char, uplo::Char, transa::Char, diag::Char, alpha::$elty, A::StridedMatrix{$elty}, B::StridedMatrix{$elty}) = trmm!(side, uplo, transa, diag, alpha, A, copy(B)) + + end +end + +# (TR) Triangular solve matrix +# Vector + +# Matrix +for (fname, elty) in + ((:dtrsm_,:Float64), + (:strsm_,:Float32), + (:ztrsm_,:Complex128), + (:ctrsm_,:Complex64)) + @eval begin +# SUBROUTINE DTRSM(SIDE,UPLO,TRANSA,DIAG,M,N,ALPHA,A,LDA,B,LDB) +# * .. Scalar Arguments .. +# DOUBLE PRECISION ALPHA +# INTEGER LDA,LDB,M,N +# CHARACTER DIAG,SIDE,TRANSA,UPLO +# * .. +# * .. Array Arguments .. +# DOUBLE PRECISION A(LDA,*),B(LDB,*) + function trsm!(side::Char, uplo::Char, transa::Char, diag::Char, alpha::$elty, A::StridedMatrix{$elty}, B::StridedMatrix{$elty}) + m, n = size(B) + if size(A, 1) != size(A, 2) throw(DimensionMismatch("Matrix must square")) end + # if (side == 'L' && size(A, 1) != m) || (side == 'R' && side(A, 1) != n) throw(DimensionMismatch("Left and right hand side does not fit")) end + ccall(($(string(fname)), libblas), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{Uint8}, Ptr{Uint8}, + Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, + Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}), + &side, &uplo, &transa, &diag, + &m, &n, &alpha, A, + &max(1, stride(A, 2)), B, &max(1,stride(B, 2))) + return B + end + end +end + + +end # module + +# Use BLAS copy for small arrays where it is faster than memcpy, and for strided copying + +function copy!{T<:BlasFloat}(dest::Ptr{T}, src::Ptr{T}, n::Integer) + if n < 200 + BLAS.copy!(n, src, 1, dest, 1) + else + ccall(:memcpy, Ptr{Void}, (Ptr{Void}, Ptr{Void}, Uint), dest, src, n*sizeof(T)) + end + return dest +end + +function copy!{T<:BlasFloat}(dest::Array{T}, src::Array{T}) + n = length(src) + if n > length(dest); throw(BoundsError()); end + copy!(pointer(dest), pointer(src), n) + return dest +end + +function copy!{T<:BlasFloat,Ti<:Integer}(dest::Array{T}, rdest::Union(Range1{Ti},Range{Ti}), + src::Array{T}, rsrc::Union(Range1{Ti},Range{Ti})) + if min(rdest) < 1 || max(rdest) > length(dest) || min(rsrc) < 1 || max(rsrc) > length(src) + throw(BoundsError()) + end + if length(rdest) != length(rsrc) + error("Ranges must be of the same length") + end + BLAS.copy!(length(rsrc), pointer(src)+(first(rsrc)-1)*sizeof(T), step(rsrc), + pointer(dest)+(first(rdest)-1)*sizeof(T), step(rdest)) + return dest +end diff --git a/base/linalg/bunchkaufman.jl b/base/linalg/bunchkaufman.jl new file mode 100644 index 0000000000000..fb60dee16746a --- /dev/null +++ b/base/linalg/bunchkaufman.jl @@ -0,0 +1,26 @@ +## Create an extractor that extracts the modified original matrix, e.g. +## LD for BunchKaufman, UL for CholeskyDense, LU for LUDense and +## define size methods for Factorization types using it. + +type BunchKaufman{T<:BlasFloat} <: Factorization{T} + LD::Matrix{T} + ipiv::Vector{BlasInt} + uplo::Char + function BunchKaufman(A::Matrix{T}, uplo::Char) + LD, ipiv = LAPACK.sytrf!(uplo , copy(A)) + new(LD, ipiv, uplo) + end +end +BunchKaufman{T<:BlasFloat}(A::StridedMatrix{T}, uplo::Char) = BunchKaufman{T}(A, uplo) +BunchKaufman{T<:Real}(A::StridedMatrix{T}, uplo::Char) = BunchKaufman(float64(A), uplo) +BunchKaufman{T<:Number}(A::StridedMatrix{T}) = BunchKaufman(A, 'U') + +size(B::BunchKaufman) = size(B.LD) +size(B::BunchKaufman,d::Integer) = size(B.LD,d) + +function inv(B::BunchKaufman) + symmetrize_conj!(LAPACK.sytri!(B.uplo, copy(B.LD), B.ipiv), B.uplo) +end + +\{T<:BlasFloat}(B::BunchKaufman{T}, R::StridedVecOrMat{T}) = + LAPACK.sytrs!(B.uplo, B.LD, B.ipiv, copy(R)) diff --git a/base/linalg/cholmod.jl b/base/linalg/cholmod.jl new file mode 100644 index 0000000000000..869caa171fdeb --- /dev/null +++ b/base/linalg/cholmod.jl @@ -0,0 +1,960 @@ +module CHOLMOD + +export # types + CholmodDense, + CholmodFactor, + CholmodSparse, + CholmodTriplet, + + CholmodSparse!, # destructive constructors + CholmodDense!, + + etree + +using Base.LinAlg.UMFPACK # for decrement, increment, etc. + +import Base.(*) +import Base.convert +import Base.copy +import Base.ctranspose +import Base.eltype +import Base.findnz +import Base.getindex +import Base.hcat +import Base.isvalid +import Base.nnz +import Base.show +import Base.size +import Base.sort! +import Base.transpose +import Base.vcat + +import LinAlg.(\) +import LinAlg.A_mul_Bc +import LinAlg.A_mul_Bt +import LinAlg.Ac_ldiv_B +import LinAlg.Ac_mul_B +import LinAlg.At_ldiv_B +import LinAlg.At_mul_B +import LinAlg.Factorization +import LinAlg.cholfact +import LinAlg.cholfact! +import LinAlg.copy +import LinAlg.dense +import LinAlg.det +import LinAlg.diag +import LinAlg.diagmm +import LinAlg.diagmm! +import LinAlg.full +import LinAlg.logdet +import LinAlg.norm +import LinAlg.solve +import LinAlg.sparse + +include("linalg/cholmod_h.jl") + +const chm_com_sz = ccall((:jl_cholmod_common_size,:libsuitesparse_wrapper),Int,()) +const chm_com = fill(0xff, chm_com_sz) +const chm_l_com = fill(0xff, chm_com_sz) +## chm_com and chm_l_com must be initialized at runtime because they contain pointers +## to functions in libc.so, whose addresses can change +function cmn(::Type{Int32}) + if isnan(reinterpret(Float64,chm_com[1:8])[1]) + status = ccall((:cholmod_start, :libcholmod), Cint, (Ptr{Uint8},), chm_com) + if status != CHOLMOD_TRUE throw(CholmodException) end + end + chm_com +end +function cmn(::Type{Int64}) + if isnan(reinterpret(Float64,chm_l_com[1:8])[1]) + status = ccall((:cholmod_l_start, :libcholmod), Cint, (Ptr{Uint8},), chm_l_com) + if status != CHOLMOD_TRUE throw(CholmodException) end + end + chm_l_com +end + +typealias CHMITypes Union(Int32,Int64) +typealias CHMVTypes Union(Complex64, Complex128, Float32, Float64) + +type CholmodException <: Exception end + +## macro to generate the name of the C function according to the integer type +macro chm_nm(nm,typ) string("cholmod_", eval(typ) == Int64 ? "l_" : "", nm) end + +### A way of examining some of the fields in chm_com +### Probably better to make this a Dict{ASCIIString,Tuple} and +### save the offsets and the lengths and the types. Then the names can be checked. +type ChmCommon + dbound::Float64 + maxrank::Int + supernodal_switch::Float64 + supernodal::Int32 + final_asis::Int32 + final_super::Int32 + final_ll::Int32 + final_pack::Int32 + final_monotonic::Int32 + final_resymbol::Int32 + prefer_zomplex::Int32 # should always be false + prefer_upper::Int32 + print::Int32 # print level. Default: 3 + precise::Int32 # print 16 digits, otherwise 5 + nmethods::Int32 # number of ordering methods + selected::Int32 + postorder::Int32 + itype::Int32 + dtype::Int32 +end + +### These offsets should be reconfigured to be less error-prone in matches +const chm_com_offsets = Array(Int, length(ChmCommon.types)) +ccall((:jl_cholmod_common_offsets, :libsuitesparse_wrapper), + Void, (Ptr{Uint8},), chm_com_offsets) +const chm_final_ll_inds = (1:4) + chm_com_offsets[7] +const chm_prt_inds = (1:4) + chm_com_offsets[13] +const chm_ityp_inds = (1:4) + chm_com_offsets[18] + +### there must be an easier way but at least this works. +function ChmCommon(aa::Array{Uint8,1}) + typs = ChmCommon.types + sz = map(sizeof, typs) + args = map(i->reinterpret(typs[i], aa[chm_com_offsets[i] + (1:sz[i])])[1], 1:length(sz)) + eval(Expr(:call, unshift!(args, :ChmCommon), Any)) +end + +function set_chm_prt_lev(cm::Array{Uint8}, lev::Integer) # can probably be removed + cm[(1:4) + chm_com_offsets[13]] = reinterpret(Uint8, [int32(lev)]) +end + +## cholmod_dense pointers passed to or returned from C functions are of Julia type +## Ptr{c_CholmodDense}. The CholmodDense type contains a c_CholmodDense object and other +## fields then ensure the memory pointed to is freed when it should be and not before. +type c_CholmodDense{T<:CHMVTypes} + m::Int + n::Int + nzmax::Int + lda::Int + xpt::Ptr{T} + zpt::Ptr{Void} + xtype::Cint + dtype::Cint +end + +type CholmodDense{T<:CHMVTypes} + c::c_CholmodDense + mat::Matrix{T} +end + +type c_CholmodFactor{Tv<:CHMVTypes,Ti<:CHMITypes} + n::Int + minor::Int + Perm::Ptr{Ti} + ColCount::Ptr{Ti} + nzmax::Int + p::Ptr{Ti} + i::Ptr{Ti} + x::Ptr{Tv} + z::Ptr{Void} + nz::Ptr{Ti} + next::Ptr{Ti} + prev::Ptr{Ti} + nsuper::Int + ssize::Int + xsize::Int + maxcsize::Int + maxesize::Int + super::Ptr{Ti} + pi::Ptr{Ti} + px::Ptr{Tv} + s::Ptr{Ti} + ordering::Cint + is_ll::Cint + is_super::Cint + is_monotonic::Cint + itype::Cint + xtype::Cint + dtype::Cint +end + +type CholmodFactor{Tv<:CHMVTypes,Ti<:CHMITypes} + c::c_CholmodFactor{Tv,Ti} + Perm::Vector{Ti} + ColCount::Vector{Ti} + p::Vector{Ti} + i::Vector{Ti} + x::Vector{Tv} + nz::Vector{Ti} + next::Vector{Ti} + prev::Vector{Ti} + super::Vector{Ti} + pi::Vector{Ti} + px::Vector{Tv} + s::Vector{Ti} +end + +type c_CholmodSparse{Tv<:CHMVTypes,Ti<:CHMITypes} + m::Int + n::Int + nzmax::Int + ppt::Ptr{Ti} + ipt::Ptr{Ti} + nzpt::Ptr{Void} + xpt::Ptr{Tv} + zpt::Ptr{Void} + stype::Cint + itype::Cint + xtype::Cint + dtype::Cint + sorted::Cint + packed::Cint +end + +type CholmodSparse{Tv<:CHMVTypes,Ti<:CHMITypes} + c::c_CholmodSparse{Tv,Ti} + colptr0::Vector{Ti} + rowval0::Vector{Ti} + nzval::Vector{Tv} +end + +type c_CholmodTriplet{Tv<:CHMVTypes,Ti<:CHMITypes} + m::Int + n::Int + nzmax::Int + nnz::Int + i::Ptr{Ti} + j::Ptr{Ti} + x::Ptr{Tv} + z::Ptr{Void} + stype:Cint + itype::Cint + xtype::Cint + dtype::Cint +end + +type CholmodTriplet{Tv<:CHMVTypes,Ti<:CHMITypes} + c::c_CholmodTriplet{Tv,Ti} + i::Vector{Ti} + j::Vector{Ti} + x::Vector{Tv} +end + +eltype{T<:CHMVTypes}(A::CholmodDense{T}) = T +eltype{T<:CHMVTypes}(A::CholmodFactor{T}) = T +eltype{T<:CHMVTypes}(A::CholmodSparse{T}) = T +eltype{T<:CHMVTypes}(A::CholmodTriplet{T}) = T + +## The CholmodDense! constructor does not copy the contents, which is generally what you +## want as most uses of CholmodDense objects are read-only. +function CholmodDense!{T<:CHMVTypes}(aa::VecOrMat{T}) # uses the memory from Julia + m = size(aa,1); n = size(aa,2) + CholmodDense(c_CholmodDense{T}(m, n, m*n, stride(aa,2), convert(Ptr{T}, aa), + C_NULL, xtyp(T), dtyp(T)), + length(size(aa)) == 2 ? aa : reshape(aa, (m,n))) +end + +## The CholmodDense constructor copies the contents +function CholmodDense{T<:CHMVTypes}(aa::VecOrMat{T}) + m = size(aa,1); n = size(aa,2) + acp = length(size(aa)) == 2 ? copy(aa) : reshape(copy(aa), (m,n)) + CholmodDense(c_CholmodDense{T}(m, n, m*n, stride(aa,2), convert(Ptr{T}, acp), + C_NULL, xtyp(T), dtyp(T)), acp) +end + +function CholmodDense{T<:CHMVTypes}(c::Ptr{c_CholmodDense{T}}) + cp = unsafe_ref(c) + if cp.lda != cp.m || cp.nzmax != cp.m * cp.n + error("overallocated cholmod_dense returned object of size $(cp.m) by $(cp.n) with leading dim $(cp.lda) and nzmax $(cp.nzmax)") + end + ## the true in the call to pointer_to_array means Julia will free the memory + val = CholmodDense(cp, pointer_to_array(cp.xpt, (cp.m,cp.n), true)) + c_free(c) + val +end +CholmodDense!{T<:CHMVTypes}(c::Ptr{c_CholmodDense{T}}) = CholmodDense(c) # no distinction + +function isvalid{T<:CHMVTypes}(cd::CholmodDense{T}) + bool(ccall((:cholmod_check_dense, :libcholmod), Cint, + (Ptr{c_CholmodDense{T}}, Ptr{Uint8}), &cd.c, cmn(Int32))) +end + +function chm_eye{T<:Union(Float64,Complex128)}(m::Integer, n::Integer, t::T) + CholmodDense(ccall((:cholmod_eye, :libcholmod), Ptr{c_CholmodDense{T}}, + (Int, Int, Cint, Ptr{Uint8}), + m, n,xtyp(T),cmn(Int32))) +end +chm_eye(m::Integer, n::Integer) = chm_eye(m, n, 1.) +chm_eye(n::Integer) = chm_eye(n, n, 1.) + +function chm_ones{T<:Union(Float64,Complex128)}(m::Integer, n::Integer, t::T) + CholmodDense(ccall((:cholmod_ones, :libcholmod), Ptr{c_CholmodDense{T}}, + (Int, Int, Cint, Ptr{Uint8}), + m, n, xtyp(T), cmn(Int32))) +end +chm_ones(m::Integer, n::Integer) = chm_ones(m, n, 1.) + +function chm_zeros{T<:Union(Float64,Complex128)}(m::Integer, n::Integer, t::T) + CholmodDense(ccall((:cholmod_zeros, :libcholmod), Ptr{c_CholmodDense{T}}, + (Int, Int, Cint, Ptr{Uint8}), + m, n, xtyp(T), cmn(Int32))) +end +chm_zeros(m::Integer, n::Integer) = chm_zeros(m, n, 1.) + +function chm_print{T<:CHMVTypes}(cd::CholmodDense{T}, lev::Integer, nm::ASCIIString) + cm = cmn(Int32) + orig = cm[chm_prt_inds] + cm[chm_prt_inds] = reinterpret(Uint8, [int32(lev)]) + status = ccall((:cholmod_print_dense, :libcholmod), Cint, + (Ptr{c_CholmodDense{T}}, Ptr{Uint8}, Ptr{Uint8}), + &cd.c, nm, cm) + cm[chm_prt_inds] = orig + if status != CHOLMOD_TRUE throw(CholmodException) end +end +chm_print(cd::CholmodDense, lev::Integer) = chm_print(cd, lev, "") +chm_print(cd::CholmodDense) = chm_print(cd, int32(4), "") +show(io::IO,cd::CholmodDense) = chm_print(cd, int32(4), "") + +function copy{Tv<:CHMVTypes}(B::CholmodDense{Tv}) + CholmodDense(ccall((:cholmod_copy_dense,:libcholmod), Ptr{c_CholmodDense{Tv}}, + (Ptr{c_CholmodDense{Tv}},Ptr{Uint8}), &B.c, cmn(Int32))) +end + +function norm{Tv<:CHMVTypes}(D::CholmodDense{Tv},p::Number) + ccall((:cholmod_norm_dense, :libcholmod), Float64, + (Ptr{c_CholmodDense{Tv}}, Cint, Ptr{Uint8}), + &D.c, p == 1 ? 1 :(p == Inf ? 1 : error("p must be 1 or Inf")),cmn(Int32)) +end +norm{Tv<:CHMVTypes}(D::CholmodDense{Tv}) = norm(D,1) + +function CholmodFactor{Tv<:CHMVTypes,Ti<:CHMITypes}(cp::Ptr{c_CholmodFactor{Tv,Ti}}) + cfp = unsafe_ref(cp) + Perm = pointer_to_array(cfp.Perm, (cfp.n,), true) + ColCount = pointer_to_array(cfp.ColCount, (cfp.n,), true) + p = pointer_to_array(cfp.p, (cfp.p == C_NULL ? 0 : cfp.n + 1,), true) + i = pointer_to_array(cfp.i, (cfp.i == C_NULL ? 0 : cfp.nzmax,), true) + x = pointer_to_array(cfp.x, (cfp.x == C_NULL ? 0 : cfp.nzmax,), true) + nz = pointer_to_array(cfp.nz, (cfp.nz == C_NULL ? 0 : cfp.n,), true) + next = pointer_to_array(cfp.next, (cfp.next == C_NULL ? 0 : cfp.n + 2,), true) + prev = pointer_to_array(cfp.prev, (cfp.prev == C_NULL ? 0 : cfp.n + 2,), true) + super = pointer_to_array(cfp.super, (cfp.super == C_NULL ? 0 : cfp.nsuper + 1,), true) + pi = pointer_to_array(cfp.pi, (cfp.pi == C_NULL ? 0 : cfp.nsuper + 1,), true) + px = pointer_to_array(cfp.px, (cfp.px == C_NULL ? 0 : cfp.nsuper + 1,), true) + s = pointer_to_array(cfp.s, (cfp.s == C_NULL ? 0 : cfp.ssize + 1,), true) + cf = CholmodFactor{Tv,Ti}(cfp, Perm, ColCount, p, i, x, nz, next, prev, + super, pi, px, s) + c_free(cp) + cf +end + +function CholmodSparse!{Tv<:CHMVTypes,Ti<:CHMITypes}(colpt::Vector{Ti}, + rowval::Vector{Ti}, + nzval::Vector{Tv}, + m::Integer, + n::Integer, + stype::Signed) + bb = colpt[1] + if bb != 0 && bb != 1 error("colpt[1] is $bb, must be 0 or 1") end + if any(diff(colpt) .< 0) error("elements of colpt must be non-decreasing") end + if length(colpt) != n + 1 error("length(colptr) = $(length(colpt)), should be $(n+1)") end + if bool(bb) # one-based + decrement!(colpt) + decrement!(rowval) + end + nz = colpt[end] + if length(rowval) != nz || length(nzval) != nz + error("length(rowval) = $(length(rowval)) and length(nzval) = $(length(nzval)) should be $nz") + end + if any(rowval .< 0) || any(rowval .>= m) + error("all elements of rowval must be in the range [0,$(m-1)]") + end + it = ityp(Ti) + sort!(CholmodSparse(c_CholmodSparse{Tv,Ti}(m,n,int(nz),convert(Ptr{Ti},colpt), + convert(Ptr{Ti},rowval), C_NULL, + convert(Ptr{Tv},nzval), C_NULL, + int32(stype), ityp(Ti), + xtyp(Tv),dtyp(Tv), + CHOLMOD_FALSE,CHOLMOD_TRUE), + colpt,rowval,nzval)) +end +function CholmodSparse{Tv<:CHMVTypes,Ti<:CHMITypes}(colpt::Vector{Ti}, + rowval::Vector{Ti}, + nzval::Vector{Tv}, + m::Integer, + n::Integer, + stype::Signed) + CholmodSparse!(copy(colpt),copy(rowval),copy(nzval),m,n,stype) +end +function CholmodSparse!{Tv<:CHMVTypes,Ti<:CHMITypes}(A::SparseMatrixCSC{Tv,Ti}, stype::Signed) + CholmodSparse!(A.colptr,A.rowval,A.nzval,size(A,1),size(A,2),stype) +end +function CholmodSparse{Tv<:CHMVTypes,Ti<:CHMITypes}(A::SparseMatrixCSC{Tv,Ti}, stype::Signed) + CholmodSparse!(copy(A.colptr),copy(A.rowval),copy(A.nzval),size(A,1),size(A,2),stype) +end +function CholmodSparse(A::SparseMatrixCSC) + stype = ishermitian(A) ? 1 : 0 + CholmodSparse(stype > 0 ? triu(A) : A, stype) +end +function CholmodSparse{Tv<:CHMVTypes,Ti<:CHMITypes}(cp::Ptr{c_CholmodSparse{Tv,Ti}}) + csp = unsafe_ref(cp) + colptr0 = pointer_to_array(csp.ppt, (csp.n + 1,), true) + nnz = int(colptr0[end]) + cms = CholmodSparse{Tv,Ti}(csp, colptr0, + pointer_to_array(csp.ipt, (nnz,), true), + pointer_to_array(csp.xpt, (nnz,), true)) + c_free(cp) + cms +end +CholmodSparse!{Tv<:CHMVTypes,Ti<:CHMITypes}(cp::Ptr{c_CholmodSparse{Tv,Ti}}) = CholmodSparse(cp) +CholmodSparse{Tv<:CHMVTypes}(D::CholmodDense{Tv}) = CholmodSparse(D,1) # default Ti is Int + +function CholmodTriplet{Tv<:CHMVTypes,Ti<:CHMITypes}(tp::Ptr{c_CholmodTriplet{Tv,Ti}}) + ctp = unsafe_ref(tp) + i = pointer_to_array(ctp.i, (ctp.nnz,), true) + j = pointer_to_array(ctp.j, (ctp.nnz,), true) + x = pointer_to_array(ctp.x, (ctp.x == C_NULL ? 0 : ctp.nnz), true) + ct = CholmodTriplet{Tv,Ti}(ctp, i, j, x) + c_free(tp) + ct +end + +function chm_rdsp(fnm::String) + fd = ccall(:fopen, Ptr{Void}, (Ptr{Uint8},Ptr{Uint8}), fnm, "r") + res = ccall((:cholmod_read_sparse,:libcholmod), Ptr{c_CholmodSparse{Float64,Cint}}, + (Ptr{Void},Ptr{Uint8}),fd,cmn(Cint)) + ccall(:fclose, Cint, (Ptr{Void},), fd) # should do this in try/finally/end + CholmodSparse(res) +end + +for Ti in (:Int32,:Int64) + @eval begin + function (*){Tv<:CHMVTypes}(A::CholmodSparse{Tv,$Ti}, + B::CholmodSparse{Tv,$Ti}) + CholmodSparse(ccall((@chm_nm "ssmult" $Ti + , :libcholmod), Ptr{c_CholmodSparse{Tv,$Ti}}, + (Ptr{c_CholmodSparse{Tv,$Ti}},Ptr{c_CholmodSparse{Tv,$Ti}}, + Cint,Cint,Cint,Ptr{Uint8}), &A.c,&B.c,0,true,true,cmn($Ti))) + end + function A_mul_Bc{Tv<:Union(Float32,Float64)}(A::CholmodSparse{Tv,$Ti}, + B::CholmodSparse{Tv,$Ti}) + cm = cmn($Ti) + aa = Array(Ptr{c_CholmodSparse{Tv,$Ti}}, 2) + if !is(A,B) + aa[1] = ccall((@chm_nm "transpose" $Ti + ,:libcholmod), Ptr{c_CholmodSparse{Tv,$Ti}}, + (Ptr{c_CholmodSparse{Tv,$Ti}}, Ptr{Uint8}), + &B.c,cm) + aa[2] = ccall((@chm_nm "ssmult" $Ti + ,:libcholmod), Ptr{c_CholmodSparse{Tv,$Ti}}, + (Ptr{c_CholmodSparse{Tv,$Ti}}, + Ptr{c_CholmodSparse{Tv,$Ti}}, Ptr{Uint8}), + &A.c, aa[1], cmn($Ti)) + status = ccall((@chm_nm "free_sparse" $Ti + ,:libcholmod), Cint, + (Ptr{Ptr{c_CholmodSparse{Tv,$Ti}}}, Ptr{Uint8}), aa, cm) + if status != CHOLMOD_TRUE throw(CholmodException) end + return CholmodSparse(aa[2]) + end + ## The A*A' case is handled by cholmod_aat. Strangely the matrix returned by + ## cholmod_aat is not marked as symmetric. The code following the call to + ## cholmod_aat is to create the symmetric-storage version of the result then + ## transpose it to provide sorted columns. The result is stored in the upper + ## triangle + aa[1] = ccall((@chm_nm "aat" $Ti + , :libcholmod), Ptr{c_CholmodSparse{Tv,$Ti}}, + (Ptr{c_CholmodSparse{Tv,$Ti}}, Ptr{Void}, Int, Cint, Ptr{Uint8}), + &A.c, C_NULL, 0, 1, cm) + ## Create the lower triangle unsorted + aa[2] = ccall((@chm_nm "copy" $Ti + , :libcholmod), Ptr{c_CholmodSparse{Tv,$Ti}}, + (Ptr{c_CholmodSparse{Tv,$Ti}}, Cint, Cint, Ptr{Uint8}), + aa[1], -1, 1, cm) + status = ccall((@chm_nm "free_sparse" $Ti + , :libcholmod), Cint, + (Ptr{Ptr{c_CholmodSparse{Tv,$Ti}}}, Ptr{Uint8}), aa, cm) + if status != CHOLMOD_TRUE throw(CholmodException) end + aa[1] = aa[2] + r = unsafe_ref(aa[1]) + ## Now transpose the lower triangle to the upper triangle to do the sorting + rpt = ccall((@chm_nm "allocate_sparse" $Ti + ,:libcholmod),Ptr{c_CholmodSparse{Tv,$Ti}}, + (Csize_t,Csize_t,Csize_t,Cint,Cint,Cint,Cint,Ptr{Cuchar}), + r.m,r.n,r.nzmax,r.sorted,r.packed,-r.stype,r.xtype,cm) + status = ccall((@chm_nm "transpose_sym" $Ti + ,:libcholmod),Cint, + (Ptr{c_CholmodSparse{Tv,$Ti}}, Cint, Ptr{$Ti}, + Ptr{c_CholmodSparse{Tv,$Ti}}, Ptr{Uint8}), + aa[1],1,C_NULL,rpt,cm) + if status != CHOLMOD_TRUE throw(CholmodException) end + status = ccall((@chm_nm "free_sparse" $Ti + , :libcholmod), Cint, + (Ptr{Ptr{c_CholmodSparse{Tv,$Ti}}}, Ptr{Uint8}), aa, cm) + if status != CHOLMOD_TRUE throw(CholmodException) end + CholmodSparse(rpt) + end + function Ac_mul_B{Tv<:Union(Float32,Float64)}(A::CholmodSparse{Tv,$Ti}, + B::CholmodSparse{Tv,$Ti}) + cm = cmn($Ti) + aa = Array(Ptr{c_CholmodSparse{Tv,$Ti}}, 2) + aa[1] = ccall((@chm_nm "transpose" $Ti + ,:libcholmod), Ptr{c_CholmodSparse{Tv,$Ti}}, + (Ptr{c_CholmodSparse{Tv,$Ti}}, Ptr{Uint8}), + &B.c,cm) + if is(A,B) + Ac = CholmodSparse(aa[1]) + return A_mul_Bc(Ac,Ac) + end + aa[2] = ccall((@chm_nm "ssmult" $Ti + ,:libcholmod), Ptr{c_CholmodSparse{Tv,$Ti}}, + (Ptr{c_CholmodSparse{Tv,$Ti}}, + Ptr{c_CholmodSparse{Tv,$Ti}}, Ptr{Uint8}), + aa[1],&B.c,cm) + status = ccall((@chm_nm "free_sparse" $Ti + , :libcholmod), Cint, + (Ptr{Ptr{c_CholmodSparse{Tv,$Ti}}}, Ptr{Uint8}), aa, cm) + if status != CHOLMOD_TRUE throw(CholmodException) end + CholmodSparse(aa[2]) + end + function CholmodDense{Tv<:CHMVTypes}(A::CholmodSparse{Tv,$Ti}) + CholmodDense(ccall((@chm_nm "sparse_to_dense" $Ti + ,:libcholmod), Ptr{c_CholmodDense{Tv,$Ti}}, + (Ptr{c_CholmodSparse{Tv,Ti}},Ptr{Uint8}), + &A.c,cmn($Ti))) + end + function CholmodSparse{Tv<:CHMVTypes}(D::CholmodDense{Tv},i::$Ti) + CholmodSparse(ccall((@chm_nm "dense_to_sparse" $Ti + ,:libcholmod), Ptr{c_CholmodSparse{Tv,Ti}}, + (Ptr{c_CholmodDense{Tv,Ti}},Ptr{Uint8}), + &D.c,cmn($Ti))) + end + function CholmodSparse{Tv<:CHMVTypes}(L::CholmodFactor{Tv,$Ti}) + if bool(L.c.is_ll) + return CholmodSparse(ccall((@chm_nm "factor_to_sparse" $Ti + ,:libcholmod), Ptr{c_CholmodSparse{Tv,$Ti}}, + (Ptr{c_CholmodFactor{Tv,$Ti}},Ptr{Uint8}), + &L.c,cmn($Ti))) + end + cm = cmn($Ti) + Lcll = ccall((@chm_nm "copy_factor" $Ti + ,:libcholmod), Ptr{c_CholmodFactor{Tv,$Ti}}, + (Ptr{c_CholmodFactor{Tv,$Ti}},Ptr{Uint8}), + &L.c,cm) + status = ccall((@chm_nm "change_factor" $Ti + ,:libcholmod), Cint, + (Cint,Cint,Cint,Cint,Cint,Ptr{c_CholmodFactor{Tv,$Ti}},Ptr{Uint8}), + L.c.xtype,true,L.c.is_super,true,true,Lcll,cm) + if status != CHOLMOD_TRUE throw(CholmodException) end + val = CholmodSparse(ccall((@chm_nm "factor_to_sparse" $Ti + ,:libcholmod), Ptr{c_CholmodSparse{Tv,$Ti}}, + (Ptr{c_CholmodFactor{Tv,$Ti}},Ptr{Uint8}), + Lcll,cmn($Ti))) + status = ccall((@chm_nm "free_factor" $Ti + ,:libcholmod), Cint, + (Ptr{Ptr{c_CholmodFactor{Tv,$Ti}}},Ptr{Uint8}), + [Lcll],cm) + if status != CHOLMOD_TRUE throw(CholmodException) end + val + end + function CholmodSparse{Tv<:CHMVTypes,Ti<:$Ti}(T::CholmodTriplet{Tv,Ti}) + CholmodSparse(ccall((@chm_nm "triplet_to_sparse" $Ti + ,:libcholmod), Ptr{c_CholmodSparse{Tv,Ti}}, + (Ptr{c_CholmodTriplet{Tv,Ti}},Ptr{Uint8}), + &T.c,cmn($Ti))) + end + function CholmodTriplet{Tv<:CHMVTypes,Ti<:$Ti}(A::CholmodSparse{Tv,Ti}) + CholmodTriplet(ccall((@chm_nm "sparse_to_triplet" $Ti + ,:libcholmod), Ptr{c_CholmodTriplet{Tv,Ti}}, + (Ptr{c_CholmodSparse{Tv,Ti}},Ptr{Uint8}), + &A.c,cmn($Ti))) + end + function isvalid{Tv<:CHMVTypes}(L::CholmodFactor{Tv,$Ti}) + bool(ccall((@chm_nm "check_factor" $Ti + ,:libcholmod), Cint, + (Ptr{c_CholmodFactor{Tv,$Ti}}, Ptr{Uint8}), + &L.c, cmn($Ti))) + end + function isvalid{Tv<:CHMVTypes}(A::CholmodSparse{Tv,$Ti}) + bool(ccall((@chm_nm "check_sparse" $Ti + ,:libcholmod), Cint, + (Ptr{c_CholmodSparse{Tv,$Ti}}, Ptr{Uint8}), + &A.c, cmn($Ti))) + end + function isvalid{Tv<:CHMVTypes}(T::CholmodTriplet{Tv,$Ti}) + bool(ccall((@chm_nm "check_triplet" $Ti + ,:libcholmod), Cint, + (Ptr{c_CholmodTriplet{Tv,$Ti}}, Ptr{Uint8}), + &T.c, cmn($Ti))) + end + function cholfact{Tv<:CHMVTypes}(A::CholmodSparse{Tv,$Ti}, ll::Bool) + cm = cmn($Ti) + ## may need to change final_asis as well as final_ll + if ll cm[chm_final_ll_inds] = reinterpret(Uint8, [one(Cint)]) end + Lpt = ccall((@chm_nm "analyze" $Ti + ,:libcholmod), Ptr{c_CholmodFactor{Tv,$Ti}}, + (Ptr{c_CholmodSparse{Tv,$Ti}}, Ptr{Uint8}), &A.c, cm) + status = ccall((@chm_nm "factorize" $Ti + ,:libcholmod), Cint, + (Ptr{c_CholmodSparse{Tv,$Ti}}, + Ptr{c_CholmodFactor{Tv,$Ti}}, Ptr{Uint8}), + &A.c, Lpt, cm) + if status != CHOLMOD_TRUE throw(CholmodException) end + CholmodFactor(Lpt) + end + function chm_analyze{Tv<:CHMVTypes}(A::CholmodSparse{Tv,$Ti}) + CholmodFactor(ccall((@chm_nm "analyze" $Ti + ,:libcholmod), Ptr{c_CholmodFactor{Tv,$Ti}}, + (Ptr{c_CholmodSparse{Tv,$Ti}}, Ptr{Uint8}), &A.c, cmn($Ti))) + end + # update the factorization - need a better name, "update"? + function chm_factorize!{Tv<:CHMVTypes}(L::CholmodFactor{Tv,$Ti}, + A::CholmodSparse{Tv,$Ti}) + status = ccall((@chm_nm "factorize" $Ti + ,:libcholmod), Cint, + (Ptr{c_CholmodSparse{Tv,$Ti}}, + Ptr{c_CholmodFactor{Tv,$Ti}}, Ptr{Uint8}), + &A.c, &L.c, cmn($Ti)) + if status != CHOLMOD_TRUE throw(CholmodException) end + end + function chm_pack!{Tv<:CHMVTypes}(L::CholmodFactor{Tv,$Ti}) + status = ccall((@chm_nm "pack_factor" $Ti + ,:libcholmod), Cint, + (Ptr{c_CholmodFactor{Tv,$Ti}}, Ptr{Uint8}), + &L.c,cmn($Ti)) + if status != CHOLMOD_TRUE throw(CholmodException) end + end + function chm_print{Tv<:CHMVTypes}(L::CholmodFactor{Tv,$Ti},lev,nm) + cm = cmn($Ti) + orig = cm[chm_prt_inds] + cm[chm_prt_inds] = reinterpret(Uint8, [int32(lev)]) + status = ccall((@chm_nm "print_factor" $Ti + ,:libcholmod), Cint, + (Ptr{c_CholmodFactor{Tv,$Ti}}, Ptr{Uint8}, Ptr{Uint8}), + &L.c, nm, cm) + cm[chm_prt_inds] = orig + if status != CHOLMOD_TRUE throw(CholmodException) end + end + function chm_print{Tv<:CHMVTypes}(A::CholmodSparse{Tv,$Ti},lev,nm) + cm = cmn($Ti) + orig = cm[chm_prt_inds] + cm[chm_prt_inds] = reinterpret(Uint8, [int32(lev)]) + status = ccall((@chm_nm "print_sparse" $Ti + ,:libcholmod), Cint, + (Ptr{c_CholmodSparse{Tv,$Ti}}, Ptr{Uint8}, Ptr{Uint8}), + &A.c, nm, cm) + cm[chm_prt_inds] = orig + if status != CHOLMOD_TRUE throw(CholmodException) end + end + function chm_scale!{Tv<:CHMVTypes}(A::CholmodSparse{Tv,$Ti}, + S::CholmodDense{Tv}, + typ::Integer) + status = ccall((@chm_nm "scale" $Ti + ,:libcholmod), Cint, + (Ptr{c_CholmodDense{Tv}},Cint,Ptr{c_CholmodSparse{Tv,$Ti}}, + Ptr{Uint8}), &S.c, typ, &A.c, cmn($Ti)) + if status != CHOLMOD_TRUE throw(CholmodException) end + end + function chm_sdmult{Tv<:CHMVTypes}(A::CholmodSparse{Tv,$Ti}, + trans::Bool, + alpha::Real, + beta::Real, + X::CholmodDense{Tv}) + m,n = size(A) + nc = trans ? m : n + nr = trans ? n : m + if nc != size(X,1) + error("Incompatible dimensions, $nc and $(size(X,1)), in chm_sdmult") + end + aa = float64([alpha, 0.]) + bb = float64([beta, 0.]) + Y = CholmodDense(zeros(Tv,nr,size(X,2))) + status = ccall((@chm_nm "sdmult" $Ti + ,:libcholmod), Cint, + (Ptr{c_CholmodSparse{Tv,$Ti}},Cint,Ptr{Cdouble},Ptr{Cdouble}, + Ptr{c_CholmodDense{Tv}}, Ptr{c_CholmodDense{Tv}}, Ptr{Uint8}), + &A.c,trans,aa,bb,&X.c,&Y.c,cmn($Ti)) + if status != CHOLMOD_TRUE throw(CholmodException) end + Y + end + function chm_speye{Tv<:CHMVTypes,Ti<:$Ti}(m::Ti, n::Ti, x::Tv) + CholmodSparse(ccall((@chm_nm "speye" $Ti + , :libcholmod), Ptr{c_CholmodSparse{Tv,$Ti}}, + (Int, Int, Cint, Ptr{Uint8}), + m, n, xtyp{Tv}, cmn($Ti))) + end + function chm_spzeros{Tv<:Union(Float64,Complex128)}(m::$Ti, n::$Ti, nzmax::$Ti, x::Tv) + CholmodSparse(ccall((@chm_nm "spzeros" $Ti + , :libcholmod), Ptr{c_CholmodSparse{Tv,$Ti}}, + (Int, Int, Int, Ptr{Uint8}), + m, n, nzmax, xtyp{Tv}, cmn($Ti))) + end +## add chm_xtype and chm_pack + function copy{Tv<:CHMVTypes}(L::CholmodFactor{Tv,$Ti}) + CholmodFactor(ccall((@chm_nm "copy_factor" $Ti + ,:libcholmod), Ptr{c_CholmodFactor{Tv,$Ti}}, + (Ptr{c_CholmodFactor{Tv,$Ti}},Ptr{Uint8}), &L.c, cmn($Ti))) + end + function copy{Tv<:CHMVTypes}(A::CholmodSparse{Tv,$Ti}) + CholmodSparse(ccall((@chm_nm "copy_sparse" $Ti + ,:libcholmod), Ptr{c_CholmodSparse{Tv,$Ti}}, + (Ptr{c_CholmodSparse{Tv,$Ti}},Ptr{Uint8}), &A.c, cmn($Ti))) + end + function copy{Tv<:CHMVTypes}(T::CholmodTriplet{Tv,$Ti}) + CholmodTriplet(ccall((@chm_nm "copy_triplet" $Ti + ,:libcholmod), Ptr{c_CholmodTriplet{Tv,$Ti}}, + (Ptr{c_CholmodTriplet{Tv,$Ti}},Ptr{Uint8}), &T.c, cmn($Ti))) + end + function ctranspose{Tv<:CHMVTypes}(A::CholmodSparse{Tv,$Ti}) + CholmodSparse(ccall((@chm_nm "transpose" $Ti + ,:libcholmod),Ptr{c_CholmodSparse{Tv,$Ti}}, + (Ptr{c_CholmodSparse{Tv,$Ti}}, Cint, Ptr{Uint8}), + &A.c, 2, cmn($Ti))) + end + function etree{Tv<:CHMVTypes}(A::CholmodSparse{Tv,$Ti}) + tr = Array($Ti,size(A,2)) + status = ccall((@chm_nm "etree" $Ti + ,:libcholmod), Cint, + (Ptr{c_CholmodSparse{Tv,$Ti}},Ptr{$Ti},Ptr{Uint8}), + &A.c,tr,cmn($Ti)) + if status != CHOLMOD_TRUE throw(CholmodException) end + tr + end + function hcat{Tv<:CHMVTypes}(A::CholmodSparse{Tv,$Ti},B::CholmodSparse{Tv,$Ti}) + ccall((@chm_nm "horzcat" $Ti + , :libcholmod), Ptr{c_CholmodSparse{Tv,$Ti}}, + (Ptr{c_CholmodSparse{Tv,$Ti}},Ptr{c_CholmodSparse{Tv,$Ti}},Cint,Ptr{Uint8}), + &A.c,&B.c,true,cmn($Ti)) + end + function nnz{Tv<:CHMVTypes}(A::CholmodSparse{Tv,$Ti}) + ccall((@chm_nm "nnz" $Ti + ,:libcholmod), Int, (Ptr{c_CholmodSparse{Tv,$Ti}},Ptr{Uint8}),&A.c,cmn($Ti)) + end + function norm{Tv<:CHMVTypes}(A::CholmodSparse{Tv,$Ti},p::Number) + ccall((@chm_nm "norm_sparse" $Ti + , :libcholmod), Float64, + (Ptr{c_CholmodSparse{Tv,$Ti}}, Cint, Ptr{Uint8}), + &A.c,p == 1 ? 1 :(p == Inf ? 1 : error("p must be 1 or Inf")),cmn($Ti)) + end + function solve{Tv<:CHMVTypes}(L::CholmodFactor{Tv,$Ti}, + B::CholmodDense{Tv}, typ::Integer) + CholmodDense(ccall((@chm_nm "solve" $Ti + ,:libcholmod), Ptr{c_CholmodDense{Tv}}, + (Cint, Ptr{c_CholmodFactor{Tv,$Ti}}, + Ptr{c_CholmodDense{Tv}}, Ptr{Uint8}), + typ, &L.c, &B.c, cmn($Ti))) + end + function solve{Tv<:CHMVTypes}(L::CholmodFactor{Tv,$Ti}, + B::CholmodSparse{Tv,$Ti}, + typ::Integer) + CholmodSparse(ccall((@chm_nm "spsolve" $Ti + ,:libcholmod), Ptr{c_CholmodSparse{Tv,$Ti}}, + (Cint, Ptr{c_CholmodFactor{Tv,$Ti}}, + Ptr{c_CholmodSparse{Tv,$Ti}}, Ptr{Uint8}), + typ, &L.c, &B.c, cmn($Ti))) + end + function sort!{Tv<:CHMVTypes}(A::CholmodSparse{Tv,$Ti}) + status = ccall((@chm_nm "sort" $Ti + ,:libcholmod), Cint, + (Ptr{c_CholmodSparse{Tv,$Ti}}, Ptr{Uint8}), + &A.c, cmn($Ti)) + if status != CHOLMOD_TRUE throw(CholmodException) end + A + end + function copysym{Tv<:CHMVTypes}(A::CholmodSparse{Tv,$Ti}) + CholmodSparse(ccall((@chm_nm "copy" $Ti + ,:libcholmod),Ptr{c_CholmodSparse{Tv,$Ti}}, + (Ptr{c_CholmodSparse{Tv,$Ti}},Cint,Cint,Ptr{Uint8}), + &A.c,0,1,cmn($Ti))) + end + function transpose{Tv<:CHMVTypes}(A::CholmodSparse{Tv,$Ti}) + CholmodSparse(ccall((@chm_nm "transpose" $Ti + ,:libcholmod),Ptr{c_CholmodSparse{Tv,$Ti}}, + (Ptr{c_CholmodSparse{Tv,$Ti}}, Cint, Ptr{Uint8}), + &A.c, 1, cmn($Ti))) + end + function vcat{Tv<:CHMVTypes}(A::CholmodSparse{Tv,$Ti},B::CholmodSparse{Tv,$Ti}) + ccall((@chm_nm "vertcat" $Ti + , :libcholmod), Ptr{c_CholmodSparse{Tv,$Ti}}, + (Ptr{c_CholmodSparse{Tv,$Ti}},Ptr{c_CholmodSparse{Tv,$Ti}},Cint,Ptr{Uint8}), + &A.c,&B.c,true,cmn($Ti)) + end + end +end +(*){Tv<:CHMVTypes}(A::CholmodSparse{Tv},B::CholmodDense{Tv}) = chm_sdmult(A,false,1.,0.,B) +(*){Tv<:CHMVTypes}(A::CholmodSparse{Tv},B::VecOrMat{Tv}) = chm_sdmult(A,false,1.,0.,CholmodDense(B)) + +(\){T<:CHMVTypes}(L::CholmodFactor{T},B::CholmodDense{T}) = solve(L,B,CHOLMOD_A) +(\){T<:CHMVTypes}(L::CholmodFactor{T},B::VecOrMat{T}) = solve(L,CholmodDense(B),CHOLMOD_A) +function (\){Tv<:CHMVTypes,Ti<:CHMITypes}(L::CholmodFactor{Tv,Ti},B::CholmodSparse{Tv,Ti}) + solve(L,B,CHOLMOD_A) +end +function (\){Tv<:CHMVTypes,Ti<:CHMITypes}(L::CholmodFactor{Tv,Ti},B::SparseMatrixCSC{Tv,Ti}) + solve(L,CholmodSparse(B),CHOLMOD_A) +end + +function A_mul_Bt{Tv<:Union(Float32,Float64),Ti<:CHMITypes}(A::CholmodSparse{Tv,Ti}, + B::CholmodSparse{Tv,Ti}) + A_mul_Bc(A,B) # in the unlikely event of writing A*B.' instead of A*B' +end + +Ac_ldiv_B{T<:CHMVTypes}(L::CholmodFactor{T},B::CholmodDense{T}) = solve(L,B,CHOLMOD_A) +Ac_ldiv_B{T<:CHMVTypes}(L::CholmodFactor{T},B::VecOrMat{T}) = solve(L,CholmodDense(B),CHOLMOD_A) +function Ac_ldiv_B{Tv<:CHMVTypes,Ti<:CHMITypes}(L::CholmodFactor{Tv,Ti},B::CholmodSparse{Tv,Ti}) + solve(L,B,CHOLMOD_A) +end +function Ac_ldiv_B{Tv<:CHMVTypes,Ti<:CHMITypes}(L::CholmodFactor{Tv,Ti},B::SparseMatrixCSC{Tv,Ti}) + solve(L,CholmodSparse(B),CHOLMOD_A) +end + +function Ac_mul_B{Tv<:CHMVTypes}(A::CholmodSparse{Tv},B::CholmodDense{Tv}) + chm_sdmult(A,true,1.,0.,B) +end +function Ac_mul_B{Tv<:CHMVTypes}(A::CholmodSparse{Tv},B::VecOrMat{Tv}) + chm_sdmult(A,true,1.,0.,CholmodDense(B)) +end + +function At_mul_B{Tv<:Union(Float32,Float64),Ti<:CHMITypes}(A::CholmodSparse{Tv,Ti}, + B::CholmodSparse{Tv,Ti}) + Ac_mul_B(A,B) # in the unlikely event of writing A.'*B instead of A'*B +end + +cholfact(A::CholmodSparse,ll::Bool) = cholfact(A,ll) +cholfact(A::CholmodSparse) = cholfact(A,false) +cholfact(A::SparseMatrixCSC,ll::Bool) = cholfact(CholmodSparse(A),ll) +cholfact(A::SparseMatrixCSC) = cholfact(CholmodSparse(A),false) + +chm_analyze(A::SparseMatrixCSC) = chm_analyze(CholmodSparse(A)) + +chm_print(A::CholmodSparse, lev::Integer) = chm_print(A, lev, "") +chm_print(A::CholmodFactor, lev::Integer) = chm_print(L, lev, "") + +function chm_scale!{T<:CHMVTypes}(A::CholmodSparse{T},b::Vector{T},typ::Integer) + chm_scale!(A,CholmodDense(b),typ) + A +end +chm_scale{T<:CHMVTypes}(A::CholmodSparse{T},b::Vector{T},typ::Integer) = chm_scale!(copy(A),b,typ) + +chm_speye(m::Integer, n::Integer) = chm_speye(m, n, 1., 1) # default element type is Float32 +chm_speye(n::Integer) = chm_speye(n, n, 1.) # default shape is square + +chm_spzeros(m::Integer,n::Integer,nzmax::Integer) = chm_spzeros(m,n,nzmax,1.) + +function diagmm!{T<:CHMVTypes}(b::Vector{T}, A::CholmodSparse{T}) + chm_scale!(A,CholmodDense(b),CHOLMOD_ROW) + A +end +diagmm{T<:CHMVTypes}(b::Vector{T}, A::CholmodSparse{T}) = diagmm!(b,copy(A)) +function diagmm!{T<:CHMVTypes}(A::CholmodSparse{T},b::Vector{T}) + chm_scale!(A,CholmodDense(b),CHOLMOD_COL) + A +end +diagmm{T<:CHMVTypes}(A::CholmodSparse{T},b::Vector{T}) = diagmm!(copy(A), b) + +norm(A::CholmodSparse) = norm(A,1) + +show(io::IO,L::CholmodFactor) = chm_print(L,int32(4),"") +show(io::IO,A::CholmodSparse) = chm_print(A,int32(4),"") + +size(B::CholmodDense) = size(B.mat) +size(B::CholmodDense,d) = size(B.mat,d) +size(A::CholmodSparse) = (int(A.c.m), int(A.c.n)) +function size(A::CholmodSparse, d::Integer) + d == 1 ? A.c.m : (d == 2 ? A.c.n : 1) +end +size(L::CholmodFactor) = (n = int(L.c.n); (n,n)) +size(L::CholmodFactor,d::Integer) = d < 1 ? error("dimension out of range") : (d <= 2 ? int(L.c.n) : 1) + +function solve{Tv<:CHMVTypes,Ti<:CHMITypes}(L::CholmodFactor{Tv,Ti}, + B::SparseMatrixCSC{Tv,Ti},typ::Integer) + solve(L,CholmodSparse(B),typ) +end +function solve{Tv<:CHMVTypes,Ti<:CHMITypes}(L::CholmodFactor{Tv,Ti},B::SparseMatrixCSC{Tv,Ti}) + solve(L,CholmodSparse(B),CHOLMOD_A) +end +function solve{Tv<:CHMVTypes,Ti<:CHMITypes}(L::CholmodFactor{Tv,Ti},B::CholmodSparse{Tv,Ti}) + solve(L,B,CHOLMOD_A) +end +function (\){Tv<:CHMVTypes,Ti<:CHMITypes}(L::CholmodFactor{Tv,Ti},B::CholmodSparse{Tv,Ti}) + solve(L,B,CHOLMOD_A) +end +solve{T<:CHMVTypes}(L::CholmodFactor{T},B::VecOrMat{T},typ::Integer)=solve(L,CholmodDense(B),typ) +solve{T<:CHMVTypes}(L::CholmodFactor{T},B::CholmodDense{T}) = solve(L,B,CHOLMOD_A) + +function findnz{Tv,Ti}(A::CholmodSparse{Tv,Ti}) + jj = similar(A.rowval0) # expand A.colptr0 to a vector of indices + for j in 1:A.c.n, k in (A.colptr0[j]+1):A.colptr0[j+1] + jj[k] = j + end + + ind = similar(A.rowval0) + ipos = 1 + count = 0 + for k in 1:length(A.nzval) + if A.nzval[k] != 0 + ind[ipos] = k + ipos += 1 + count += 1 + else + println("Warning: sparse matrix contains explicitly stored zeros.") + end + end + ind = ind[1:count] # ind is the indices of nonzeros in A.nzval + (increment!(A.rowval0[ind]), jj[ind], A.nzval[ind]) +end + +findnz(L::CholmodFactor) = findnz(CholmodSparse(L)) + +function diag{Tv}(A::CholmodSparse{Tv}) + minmn = min(size(A)) + res = zeros(Tv,minmn) + cp0 = A.colptr0 + rv0 = A.rowval0 + anz = A.nzval + for j in 1:minmn, k in (cp0[j]+1):cp0[j+1] + if rv0[k] == j-1 + res[j] += anz[k] + end + end + res +end + +function diag{Tv}(L::CholmodFactor{Tv}) + res = zeros(Tv,L.c.n) + if L.c.is_super != 0 error("Method for supernodal factors not yet written") end + c0 = L.p + r0 = L.i + xv = L.x + for j in 1:length(c0)-1 + jj = c0[j]+1 + assert(r0[jj] == j-1) + res[j] = xv[jj] + end + res +end + +function logdet{Tv,Ti}(L::CholmodFactor{Tv,Ti},sub) + if L.c.is_super != 0 error("Method for supernodal factors not yet written") end + c0 = L.p + r0 = L.i + xv = L.x + res = zero(Tv) + for j in (1:length(c0)-1)[sub] + jj = c0[j]+1 + assert(r0[jj] == j-1) + res += log(xv[jj]) + end + bool(L.c.is_ll) ? 2res : res +end +logdet(L::CholmodFactor) = logdet(L, 1:L.c.n) +det(L::CholmodFactor) = exp(logdet(L)) + +dense(A::CholmodSparse) = CholmodDense(A).mat +full(A::CholmodSparse) = dense(A) +function sparse(A::CholmodSparse) + if bool(A.c.stype) return sparse!(copysym(A)) end + SparseMatrixCSC(A.c.m, A.c.n, increment(A.colptr0), increment(A.rowval0), copy(A.nzval)) +end +function sparse!(A::CholmodSparse) + SparseMatrixCSC(A.c.m, A.c.n, increment!(A.colptr0), increment!(A.rowval0), A.nzval) +end +sparse(L::CholmodFactor) = sparse!(CholmodSparse(L)) +sparse(D::CholmodDense) = sparse!(CholmodSparse(D)) +sparse(T::CholmodTriplet) = sparse!(CholmodSparse(T)) +end #module diff --git a/base/linalg/cholmod_h.jl b/base/linalg/cholmod_h.jl new file mode 100644 index 0000000000000..944893d95c7d8 --- /dev/null +++ b/base/linalg/cholmod_h.jl @@ -0,0 +1,44 @@ +## CHOLMOD +const CHOLMOD_TRUE = int32(1) +const CHOLMOD_FALSE = int32(0) + +## itype defines the types of integer used: +const CHOLMOD_INT = int32(0) # all integer arrays are int +const CHOLMOD_LONG = int32(2) # all integer arrays are UF_long +ityp(::Type{Int32}) = CHOLMOD_INT +ityp(::Type{Int64}) = CHOLMOD_LONG + +## dtype defines what the numerical type is (double or float): +const CHOLMOD_DOUBLE = int32(0) # all numerical values are double +const CHOLMOD_SINGLE = int32(1) # all numerical values are float +dtyp(::Type{Float32}) = CHOLMOD_SINGLE +dtyp(::Type{Float64}) = CHOLMOD_DOUBLE +dtyp(::Type{Complex64}) = CHOLMOD_SINGLE +dtyp(::Type{Complex128}) = CHOLMOD_DOUBLE + +## xtype defines the kind of numerical values used: +const CHOLMOD_PATTERN = int32(0) # pattern only, no numerical values +const CHOLMOD_REAL = int32(1) # a real matrix +const CHOLMOD_COMPLEX = int32(2) # a complex matrix (ANSI C99 compatible) +const CHOLMOD_ZOMPLEX = int32(3) # a complex matrix (MATLAB compatible) +xtyp(::Type{Float32}) = CHOLMOD_REAL +xtyp(::Type{Float64}) = CHOLMOD_REAL +xtyp(::Type{Complex64}) = CHOLMOD_COMPLEX +xtyp(::Type{Complex128}) = CHOLMOD_COMPLEX + +## Scaling modes, selected by the scale input parameter: +const CHOLMOD_SCALAR = int32(0) # A = s*A +const CHOLMOD_ROW = int32(1) # A = diag(s)*A +const CHOLMOD_COL = int32(2) # A = A*diag(s) +const CHOLMOD_SYM = int32(3) # A = diag(s)*A*diag(s) + +## Types of systems to solve +const CHOLMOD_A = int32(0) # solve Ax=b +const CHOLMOD_LDLt = int32(1) # solve LDL'x=b +const CHOLMOD_LD = int32(2) # solve LDx=b +const CHOLMOD_DLt = int32(3) # solve DL'x=b +const CHOLMOD_L = int32(4) # solve Lx=b +const CHOLMOD_Lt = int32(5) # solve L'x=b +const CHOLMOD_D = int32(6) # solve Dx=b +const CHOLMOD_P = int32(7) # permute x=Px +const CHOLMOD_Pt = int32(8) # permute x=P'x diff --git a/base/linalg/dense.jl b/base/linalg/dense.jl new file mode 100644 index 0000000000000..19b924c5bf3e8 --- /dev/null +++ b/base/linalg/dense.jl @@ -0,0 +1,486 @@ +# Linear algebra functions for dense matrices in column major format + +scale!(X::Array{Float32}, s::Real) = BLAS.scal!(length(X), float32(s), X, 1) +scale!(X::Array{Float64}, s::Real) = BLAS.scal!(length(X), float64(s), X, 1) +scale!(X::Array{Complex64}, s::Real) = (ccall(("sscal_",Base.libblas_name), Void, (Ptr{BlasInt}, Ptr{Float32}, Ptr{Complex64}, Ptr{BlasInt}), &(2*length(X)), &s, X, &1); X) +scale!(X::Array{Complex128}, s::Real) = (ccall(("dscal_",Base.libblas_name), Void, (Ptr{BlasInt}, Ptr{Float64}, Ptr{Complex128}, Ptr{BlasInt}), &(2*length(X)), &s, X, &1); X) + +#Test whether a matrix is positive-definite + +isposdef!{T<:BlasFloat}(A::Matrix{T}, UL::Char) = LAPACK.potrf!(UL, A)[2] == 0 +isposdef!(A::Matrix) = ishermitian(A) && isposdef!(A, 'U') + +isposdef{T<:BlasFloat}(A::Matrix{T}, UL::Char) = isposdef!(copy(A), UL) +isposdef{T<:BlasFloat}(A::Matrix{T}) = isposdef!(copy(A)) +isposdef{T<:Number}(A::Matrix{T}, UL::Char) = isposdef!(float64(A), UL) +isposdef{T<:Number}(A::Matrix{T}) = isposdef!(float64(A)) + +isposdef(x::Number) = imag(x)==0 && real(x) > 0 + +norm{T<:BlasFloat}(x::Vector{T}) = BLAS.nrm2(length(x), x, 1) + +function norm{T<:BlasFloat, TI<:Integer}(x::Vector{T}, rx::Union(Range1{TI},Range{TI})) + if min(rx) < 1 || max(rx) > length(x) + throw(BoundsError()) + end + BLAS.nrm2(length(rx), pointer(x)+(first(rx)-1)*sizeof(T), step(rx)) +end + +function norm{T<:BlasFloat}(x::Vector{T}, p::Number) + n = length(x) + if n == 0 + a = zero(T) + elseif p == 2 + BLAS.nrm2(n, x, 1) + elseif p == 1 + BLAS.asum(n, x, 1) + elseif p == Inf + max(abs(x)) + elseif p == -Inf + min(abs(x)) + elseif p == 0 + convert(T, nnz(x)) + else + absx = abs(x) + dx = max(absx) + if dx != zero(T) + scale!(absx, 1/dx) + a = dx * (sum(absx.^p).^(1/p)) + else + zero(T) + end + end +end + +function triu!{T}(M::Matrix{T}, k::Integer) + m, n = size(M) + idx = 1 + for j = 0:n-1 + ii = min(max(0, j+1-k), m) + for i = (idx+ii):(idx+m-1) + M[i] = zero(T) + end + idx += m + end + return M +end + +triu(M::Matrix, k::Integer) = triu!(copy(M), k) + +function tril!{T}(M::Matrix{T}, k::Integer) + m, n = size(M) + idx = 1 + for j = 0:n-1 + ii = min(max(0, j-k), m) + for i = idx:(idx+ii-1) + M[i] = zero(T) + end + idx += m + end + return M +end + +tril(M::Matrix, k::Integer) = tril!(copy(M), k) + +diff(a::Vector) = [ a[i+1] - a[i] for i=1:length(a)-1 ] + +function diff(a::Matrix, dim::Integer) + if dim == 1 + [ a[i+1,j] - a[i,j] for i=1:size(a,1)-1, j=1:size(a,2) ] + else + [ a[i,j+1] - a[i,j] for i=1:size(a,1), j=1:size(a,2)-1 ] + end +end + +function gradient(F::Vector, h::Vector) + n = length(F) + g = similar(F) + if n > 0 + g[1] = 0 + end + if n > 1 + g[1] = (F[2] - F[1]) / (h[2] - h[1]) + g[n] = (F[n] - F[n-1]) / (h[end] - h[end-1]) + end + if n > 2 + h = h[3:n] - h[1:n-2] + g[2:n-1] = (F[3:n] - F[1:n-2]) ./ h + end + return g +end + +function diag{T}(A::Matrix{T}, k::Integer) + m, n = size(A) + if k >= 0 && k < n + nV = min(m, n-k) + elseif k < 0 && -k < m + nV = min(m+k, n) + else + throw(BoundsError()) + end + + V = zeros(T, nV) + + if k > 0 + for i=1:nV + V[i] = A[i, i+k] + end + else + for i=1:nV + V[i] = A[i-k, i] + end + end + + return V +end + +diag(A) = diag(A, 0) + +function diagm{T}(v::VecOrMat{T}, k::Integer) + if isa(v, Matrix) + if (size(v,1) != 1 && size(v,2) != 1) + error("Input should be nx1 or 1xn") + end + end + + n = length(v) + if k >= 0 + a = zeros(T, n+k, n+k) + for i=1:n + a[i,i+k] = v[i] + end + else + a = zeros(T, n-k, n-k) + for i=1:n + a[i-k,i] = v[i] + end + end + + return a +end + +diagm(v) = diagm(v, 0) + +diagm(x::Number) = (X = Array(typeof(x),1,1); X[1,1] = x; X) + +function trace{T}(A::Matrix{T}) + t = zero(T) + for i=1:min(size(A)) + t += A[i,i] + end + return t +end + +kron(a::Vector, b::Vector)=vec(kron(reshape(a,length(a),1),reshape(b,length(b),1))) + +kron(a::Matrix, b::Vector)=kron(a,reshape(b,length(b),1)) + +kron(a::Vector, b::Matrix)=kron(reshape(a,length(a),1),b) + +function kron{T,S}(a::Matrix{T}, b::Matrix{S}) + R = Array(promote_type(T,S), size(a,1)*size(b,1), size(a,2)*size(b,2)) + + m = 1 + for j = 1:size(a,2) + for l = 1:size(b,2) + for i = 1:size(a,1) + aij = a[i,j] + for k = 1:size(b,1) + R[m] = aij*b[k,l] + m += 1 + end + end + end + end + R +end + +kron(a::Number, b::Number) = a * b +kron(a::Vector, b::Number) = a * b +kron(a::Number, b::Vector) = a * b +kron(a::Matrix, b::Number) = a * b +kron(a::Number, b::Matrix) = a * b + +randsym(n) = symmetrize!(randn(n,n)) + +^(A::Matrix, p::Integer) = p < 0 ? inv(A^-p) : Base.power_by_squaring(A,p) + +function ^(A::Matrix, p::Number) + if integer_valued(p) + ip = integer(real(p)) + if ip < 0 + return inv(Base.power_by_squaring(A, -ip)) + else + return Base.power_by_squaring(A, ip) + end + end + if size(A,1) != size(A,2) + error("matrix must be square") + end + (v, X) = eig(A) + if isreal(v) && any(v.<0) + v = complex(v) + end + if ishermitian(A) + Xinv = X' + else + Xinv = inv(X) + end + diagmm(X, v.^p)*Xinv +end + +function rref{T}(A::Matrix{T}) + nr, nc = size(A) + U = copy!(similar(A, T <: Complex ? Complex128 : Float64), A) + e = eps(norm(U,Inf)) + i = j = 1 + while i <= nr && j <= nc + (m, mi) = findmax(abs(U[i:nr,j])) + mi = mi+i - 1 + if m <= e + U[i:nr,j] = 0 + j += 1 + else + for k=j:nc + U[i, k], U[mi, k] = U[mi, k], U[i, k] + end + d = U[i,j] + for k = j:nc + U[i,k] /= d + end + for k = 1:nr + if k != i + d = U[k,j] + for l = j:nc + U[k,l] -= d*U[i,l] + end + end + end + i += 1 + j += 1 + end + end + return U +end + +rref(x::Number) = one(x) + +## Destructive matrix exponential using algorithm from Higham, 2008, +## "Functions of Matrices: Theory and Computation", SIAM +function expm!{T<:BlasFloat}(A::StridedMatrix{T}) + m, n = size(A) + if m != n error("expm!: Matrix A must be square") end + if m < 2 return exp(A) end + ilo, ihi, scale = LAPACK.gebal!('B', A) # modifies A + nA = norm(A, 1) + I = eye(T,n) + ## For sufficiently small nA, use lower order Padé-Approximations + if (nA <= 2.1) + if nA > 0.95 + C = T[17643225600.,8821612800.,2075673600.,302702400., + 30270240., 2162160., 110880., 3960., + 90., 1.] + elseif nA > 0.25 + C = T[17297280.,8648640.,1995840.,277200., + 25200., 1512., 56., 1.] + elseif nA > 0.015 + C = T[30240.,15120.,3360., + 420., 30., 1.] + else + C = T[120.,60.,12.,1.] + end + A2 = A * A + P = copy(I) + U = C[2] * P + V = C[1] * P + for k in 1:(div(size(C, 1), 2) - 1) + k2 = 2 * k + P *= A2 + U += C[k2 + 2] * P + V += C[k2 + 1] * P + end + U = A * U + X = V + U + LAPACK.gesv!(V-U, X) + else + s = log2(nA/5.4) # power of 2 later reversed by squaring + if s > 0 + si = iceil(s) + A /= oftype(T,2^si) + end + CC = T[64764752532480000.,32382376266240000.,7771770303897600., + 1187353796428800., 129060195264000., 10559470521600., + 670442572800., 33522128640., 1323241920., + 40840800., 960960., 16380., + 182., 1.] + A2 = A * A + A4 = A2 * A2 + A6 = A2 * A4 + U = A * (A6 * (CC[14]*A6 + CC[12]*A4 + CC[10]*A2) + + CC[8]*A6 + CC[6]*A4 + CC[4]*A2 + CC[2]*I) + V = A6 * (CC[13]*A6 + CC[11]*A4 + CC[9]*A2) + + CC[7]*A6 + CC[5]*A4 + CC[3]*A2 + CC[1]*I + + X = V + U + LAPACK.gesv!(V-U, X) + + if s > 0 # squaring to reverse dividing by power of 2 + for t in 1:si X *= X end + end + end + # Undo the balancing + doscale = false # check if rescaling is needed + for i = ilo:ihi + if scale[i] != 1. + doscale = true + break + end + end + if doscale + for j = ilo:ihi + scj = scale[j] + if scj != 1. # is this overkill? + for i = ilo:ihi + X[i,j] *= scale[i]/scj + end + else + for i = ilo:ihi + X[i,j] *= scale[i] + end + end + end + end + if ilo > 1 # apply lower permutations in reverse order + for j in (ilo-1):1:-1 rcswap!(j, int(scale[j]), X) end + end + if ihi < n # apply upper permutations in forward order + for j in (ihi+1):n rcswap!(j, int(scale[j]), X) end + end + X +end + +## Swap rows j and jp and columns j and jp in X +function rcswap!{T<:Number}(j::Integer, jp::Integer, X::StridedMatrix{T}) + for k in 1:size(X, 2) + tmp = X[k,j] + X[k,j] = X[k,jp] + X[k,jp] = tmp + tmp = X[j,k] + X[j,k] = X[jp,k] + X[jp,k] = tmp + end +end + +# Matrix exponential +expm{T<:Union(Float32,Float64,Complex64,Complex128)}(A::StridedMatrix{T}) = expm!(copy(A)) +expm{T<:Integer}(A::StridedMatrix{T}) = expm!(float(A)) +expm(x::Number) = exp(x) + +function sqrtm(A::StridedMatrix, cond::Bool) + m, n = size(A) + if m != n error("DimentionMismatch") end + if ishermitian(A) + return sqrtm(Hermitian(A), cond) + else + SchurF = schurfact!(iscomplex(A) ? copy(A) : complex(A)) + R = zeros(eltype(SchurF[:T]), n, n) + for j = 1:n + R[j,j] = sqrt(SchurF[:T][j,j]) + for i = j - 1:-1:1 + r = SchurF[:T][i,j] + for k = i + 1:j - 1 + r -= R[i,k]*R[k,j] + end + if r != 0 + R[i,j] = r / (R[i,i] + R[j,j]) + end + end + end + end + retmat = SchurF[:vectors]*R*SchurF[:vectors]' + if cond + alpha = norm(R)^2/norm(SchurF[:T]) + return (all(imag(retmat) .== 0) ? real(retmat) : retmat), alpha + else + return (all(imag(retmat) .== 0) ? real(retmat) : retmat) + end +end + +sqrtm{T<:Integer}(A::StridedMatrix{T}, cond::Bool) = sqrtm(float(A), cond) +sqrtm{T<:Integer}(A::StridedMatrix{ComplexPair{T}}, cond::Bool) = sqrtm(complex128(A), cond) +sqrtm(A::StridedMatrix) = sqrtm(A, false) +sqrtm(a::Number) = isreal(a) ? (b = sqrt(complex(a)); imag(b) == 0 ? real(b) : b) : sqrt(a) + +function det(A::Matrix) + m, n = size(A) + if m != n; throw(LAPACK.DimensionMismatch("det only defined for square matrices")); end + if istriu(A) | istril(A); return det(Triangular(A, 'U', false)); end + return det(lufact(A)) +end +det(x::Number) = x + +logdet(A::Matrix) = 2.0 * sum(log(diag(cholfact(A)[:U]))) + +function inv(A::StridedMatrix) + if istriu(A) return inv(Triangular(A, 'U')) end + if istril(A) return inv(Triangular(A, 'L')) end + if ishermitian(A) return inv(Hermitian(A)) end + return inv(lufact(A)) +end + +function (\){T<:BlasFloat}(A::StridedMatrix{T}, B::StridedVecOrMat{T}) + if size(A, 1) == size(A, 2) # Square + if istriu(A) return Triangular(A, 'U')\B end + if istril(A) return Triangular(A, 'L')\B end + if ishermitian(A) return Hermitian(A)\B end + ans, _, _, info = LAPACK.gesv!(copy(A), copy(B)) + if info > 0; throw(LinAlg.LAPACK.SingularException(info)); end + return ans + end + LAPACK.gelsd!(copy(A), copy(B))[1] +end + +(\){T1<:BlasFloat, T2<:BlasFloat}(A::StridedMatrix{T1}, B::StridedVecOrMat{T2}) = + (\)(convert(Array{promote_type(T1,T2)},A), convert(Array{promote_type(T1,T2)},B)) +(\){T1<:BlasFloat, T2<:Real}(A::StridedMatrix{T1}, B::StridedVecOrMat{T2}) = (\)(A, convert(Array{T1}, B)) +(\){T1<:Real, T2<:BlasFloat}(A::StridedMatrix{T1}, B::StridedVecOrMat{T2}) = (\)(convert(Array{T2}, A), B) +(\){T1<:Real, T2<:Real}(A::StridedMatrix{T1}, B::StridedVecOrMat{T2}) = (\)(float64(A), float64(B)) +(\){T1<:Number, T2<:Number}(A::StridedMatrix{T1}, B::StridedVecOrMat{T2}) = (\)(complex128(A), complex128(B)) +(\)(a::Vector, B::StridedVecOrMat) = (\)(reshape(a, length(a), 1), B) + +## Moore-Penrose inverse +function pinv{T<:BlasFloat}(A::StridedMatrix{T}) + SVD = svdfact(A, true) + Sinv = zeros(T, length(SVD[:S])) + index = SVD[:S] .> eps(real(one(T)))*max(size(A))*max(SVD[:S]) + Sinv[index] = 1.0 ./ SVD[:S][index] + SVD[:Vt]'diagmm(Sinv, SVD[:U]') +end +pinv{T<:Integer}(A::StridedMatrix{T}) = pinv(float(A)) +pinv(a::StridedVector) = pinv(reshape(a, length(a), 1)) +pinv(x::Number) = one(x)/x + +## Basis for null space +function null{T<:BlasFloat}(A::StridedMatrix{T}) + m,n = size(A) + SVD = svdfact(A) + if m == 0; return eye(T, n); end + indstart = sum(SVD[:S] .> max(m,n)*max(SVD[:S])*eps(eltype(SVD[:S]))) + 1 + SVD[:V][:,indstart:] +end +null{T<:Integer}(A::StridedMatrix{T}) = null(float(A)) +null(a::StridedVector) = null(reshape(a, length(a), 1)) + +function cond(A::StridedMatrix, p) + if p == 2 + v = svdvals(A) + maxv = max(v) + return maxv == 0.0 ? Inf : maxv / min(v) + elseif p == 1 || p == Inf + m, n = size(A) + if m != n; error("Use 2-norm for non-square matrices"); end + return cond(lufact(A), p) + end + error("Norm type must be 1, 2 or Inf") +end +cond(A::StridedMatrix) = cond(A, 2) diff --git a/base/linalg/diagonal.jl b/base/linalg/diagonal.jl new file mode 100644 index 0000000000000..c73937ad565f5 --- /dev/null +++ b/base/linalg/diagonal.jl @@ -0,0 +1,82 @@ +## Diagonal matrices + +type Diagonal{T} <: AbstractMatrix{T} + diag::Vector{T} +end + +size(D::Diagonal) = (length(D.diag),length(D.diag)) +size(D::Diagonal,d::Integer) = d<1 ? error("dimension out of range") : (d<=2 ? length(D.diag) : 1) + +convert{T}(::Type{Matrix{T}}, D::Diagonal{T}) = diagm(D.diag) +convert{T}(::Type{SymTridiagonal{T}}, D::Diagonal{T}) = SymTridiagonal(D.diag,zeros(T,length(D.diag)-1)) +convert{T}(::Type{Tridiagonal{T}}, D::Diagonal{T}) = Tridiagonal(zeros(T,length(D.diag)-1),D.diag,zeros(T,length(D.diag)-1)) + +full(D::Diagonal) = diagm(D.diag) +function show(io::IO, D::Diagonal) + println(io, summary(D), ":") + print(io, "diag: ") + print_matrix(io, (D.diag)') +end + +ishermitian(D::Diagonal) = true +issym(D::Diagonal) = true +isposdef(D::Diagonal) = all(D.diag .> 0) + +==(Da::Diagonal, Db::Diagonal) = Da.diag == Db.diag + ++(Da::Diagonal, Db::Diagonal) = Diagonal(Da.diag + Db.diag) +-(Da::Diagonal, Db::Diagonal) = Diagonal(Da.diag - Db.diag) + +*(Da::Diagonal, Db::Diagonal) = Diagonal(Da.diag .* Db.diag) +*(D::Diagonal, V::Vector) = D.diag .* V +*(A::Matrix, D::Diagonal) = diagmm(A,D.diag) +*(D::Diagonal, A::Matrix) = diagmm(D.diag,A) + +\(Da::Diagonal, Db::Diagonal) = Diagonal(Db.diag ./ Da.diag ) +/(Da::Diagonal, Db::Diagonal) = Diagonal(Da.diag ./ Db.diag ) +\(D::Diagonal, V::Vector) = V ./ D.diag +function \(D::Diagonal, A::Matrix) + m, n = size(A) + if m != length(D.diag) + error("argument dimensions do not match") + end + C = Array(promote_type(eltype(A),eltype(D.diag)),size(A)) + for i = 1:m + di = D.diag[i] + for j = 1:n + C[i,j] = A[i,j] / di + end + end + return C +end +function /(A::Matrix, D::Diagonal) + m, n = size(A) + if n != length(D.diag) + error("argument dimensions do not match") + end + C = Array(promote_type(eltype(A),eltype(D.diag)),size(A)) + for j = 1:n + dj = D.diag[j] + for i = 1:m + C[i,j] = A[i,j] / dj + end + end + return C +end + +conj(D::Diagonal) = Diagonal(conj(D.diag)) +transpose(D::Diagonal) = D +ctranspose(D::Diagonal) = conj(D) + +diag(D::Diagonal) = D.diag +det(D::Diagonal) = prod(D.diag) +logdet(D::Diagonal) = sum(log(D.diag)) +inv(D::Diagonal) = Diagonal(1 ./ D.diag) + +eigvals(D::Diagonal) = sort(D.diag) + +expm(D::Diagonal) = Diagonal(exp(D.diag)) +sqrtm(D::Diagonal) = Diagonal(sqrt(D.diag)) + +# identity matrices via eye(Diagonal{type},n) +eye{T}(::Type{Diagonal{T}}, n::Int) = Diagonal(ones(T,n)) diff --git a/base/linalg/factorization.jl b/base/linalg/factorization.jl new file mode 100644 index 0000000000000..4cfc0aab44823 --- /dev/null +++ b/base/linalg/factorization.jl @@ -0,0 +1,627 @@ +## Matrix factorizations and decompositions + +abstract Factorization{T} + +type Cholesky{T<:BlasFloat} <: Factorization{T} + UL::Matrix{T} + uplo::Char +end + +function cholfact!(A::StridedMatrix, uplo::Symbol) + uplochar = string(uplo)[1] + C, info = LAPACK.potrf!(uplochar, A) + if info > 0 throw(LinAlg.LAPACK.PosDefException(info)) end + Cholesky(uplochar == 'L' ? tril(C) : triu(C), uplochar) +end +cholfact(A::StridedMatrix, uplo::Symbol) = cholfact!(copy(A), uplo) +cholfact!(A::StridedMatrix) = cholfact!(A, :U) +cholfact(A::StridedMatrix) = cholfact(A, :U) +cholfact{T<:Integer}(A::StridedMatrix{T}, args...) = cholfact(float(A), args...) +cholfact(x::Number) = imag(x) == 0 && real(x) > 0 ? Cholesky(fill(sqrt(x), 1, 1), 'U') : throw(LinAlg.LAPACK.PosDefException(1)) + +chol(A::Union(Number, StridedMatrix), uplo::Symbol) = cholfact(A, uplo)[uplo] +chol(A::Union(Number, StridedMatrix)) = cholfact(A, :U)[:U] + +size(C::Cholesky) = size(C.UL) +size(C::Cholesky,d::Integer) = size(C.UL,d) + +function getindex(C::Cholesky, d::Symbol) + if d == :U || d == :L + return symbol(C.uplo) == d ? C.UL : C.UL' + elseif d == :UL + return Triangular(C.UL, C.uplo) + end + error("No such type field") +end + +\{T<:BlasFloat}(C::Cholesky{T}, B::StridedVecOrMat{T}) = + LAPACK.potrs!(C.uplo, C.UL, copy(B)) + +function det{T}(C::Cholesky{T}) + dd = one(T) + for i in 1:size(C.UL,1) dd *= abs2(C.UL[i,i]) end + dd +end + +function inv(C::Cholesky) + Ci, info = LAPACK.potri!(C.uplo, copy(C.UL)) + if info != 0; throw(LAPACK.SingularException(info)); end + symmetrize_conj!(Ci, C.uplo) +end + +## Pivoted Cholesky +type CholeskyPivoted{T<:BlasFloat} <: Factorization{T} + UL::Matrix{T} + uplo::Char + piv::Vector{BlasInt} + rank::BlasInt + tol::Real + info::BlasInt +end +function CholeskyPivoted{T<:BlasFloat}(A::StridedMatrix{T}, uplo::Char, tol::Real) + A, piv, rank, info = LAPACK.pstrf!(uplo, A, tol) + CholeskyPivoted{T}(uplo == 'U' ? triu!(A) : tril!(A), uplo, piv, rank, tol, info) +end + +cholpfact!(A::StridedMatrix, uplo::Symbol, tol::Real) = CholeskyPivoted(A, string(uplo)[1], tol) +cholpfact(A::StridedMatrix, uplo::Symbol, tol::Real) = cholpfact!(copy(A), uplo, tol) +cholpfact!(A::StridedMatrix, tol::Real) = cholpfact!(A, :U, tol) +cholpfact(A::StridedMatrix, tol::Real) = cholpfact(A, :U, tol) +cholpfact!(A::StridedMatrix) = cholpfact!(A, -1.) +cholpfact(A::StridedMatrix) = cholpfact(A, -1.) +cholpfact{T<:Int}(A::StridedMatrix{T}, args...) = cholpfact(float(A), args...) + +size(C::CholeskyPivoted) = size(C.UL) +size(C::CholeskyPivoted,d::Integer) = size(C.UL,d) + +getindex(C::CholeskyPivoted) = C.UL, C.piv +function getindex{T<:BlasFloat}(C::CholeskyPivoted{T}, d::Symbol) + if d == :U || d == :L + return symbol(C.uplo) == d ? C.UL : C.UL' + end + if d == :p return C.piv end + if d == :P + n = size(C, 1) + P = zeros(T, n, n) + for i in 1:n + P[C.piv[i],i] = one(T) + end + return P + end + error("No such type field") +end + +function \{T<:BlasFloat}(C::CholeskyPivoted{T}, B::StridedVector{T}) + if C.rank < size(C.UL, 1); throw(LAPACK.RankDeficientException(C.info)); end + LAPACK.potrs!(C.uplo, C.UL, copy(B)[C.piv])[invperm(C.piv)] +end + +function \{T<:BlasFloat}(C::CholeskyPivoted{T}, B::StridedMatrix{T}) + if C.rank < size(C.UL, 1); throw(LAPACK.RankDeficientException(C.info)); end + LAPACK.potrs!(C.uplo, C.UL, copy(B)[C.piv,:])[invperm(C.piv),:] +end + +rank(C::CholeskyPivoted) = C.rank + +function det{T}(C::CholeskyPivoted{T}) + if C.rank < size(C.UL, 1) + return real(zero(T)) + else + return prod(abs2(diag(C.UL))) + end +end + +function inv(C::CholeskyPivoted) + if C.rank < size(C.UL, 1) throw(LAPACK.RankDeficientException(C.info)) end + Ci, info = LAPACK.potri!(C.uplo, copy(C.UL)) + if info != 0 throw(LAPACK.RankDeficientException(info)) end + ipiv = invperm(C.piv) + (symmetrize!(Ci, C.uplo))[ipiv, ipiv] +end + +## LU +type LU{T} <: Factorization{T} + factors::Matrix{T} + ipiv::Vector{BlasInt} + info::BlasInt +end +function LU{T<:BlasFloat}(A::StridedMatrix{T}) + factors, ipiv, info = LAPACK.getrf!(A) + LU{T}(factors, ipiv, info) +end + +lufact!(A::StridedMatrix) = LU(A) +lufact(A::StridedMatrix) = lufact!(copy(A)) +lufact!{T<:Integer}(A::StridedMatrix{T}) = lufact!(float(A)) +lufact{T<:Integer}(A::StridedMatrix{T}) = lufact(float(A)) +lufact(x::Number) = LU(fill(x, 1, 1), [1], x == 0 ? 1 : 0) + +function lu(A::Union(Number, StridedMatrix)) + F = lufact(A) + return (F[:L], F[:U], F[:P]) +end + +size(A::LU) = size(A.factors) +size(A::LU,n) = size(A.factors,n) + +function getindex{T}(A::LU{T}, d::Symbol) + if d == :L; return tril(A.factors, -1) + eye(T, size(A, 1)); end; + if d == :U; return triu(A.factors); end; + if d == :p + n = size(A, 1) + p = [1:n] + for i in 1:n + tmp = p[i] + p[i] = p[A.ipiv[i]] + p[A.ipiv[i]] = tmp + end + return p + end + if d == :P + p = A[:p] + n = length(p) + P = zeros(T, n, n) + for i in 1:n + P[i,p[i]] = one(T) + end + return P + end + error("No such type field") +end + +function det{T}(A::LU{T}) + m, n = size(A) + if A.info > 0; return zero(typeof(A.factors[1])); end + prod(diag(A.factors)) * (bool(sum(A.ipiv .!= 1:n) % 2) ? -one(T) : one(T)) +end + +function (\)(A::LU, B::StridedVecOrMat) + if A.info > 0; throw(LAPACK.SingularException(A.info)); end + LAPACK.getrs!('N', A.factors, A.ipiv, copy(B)) +end + +function inv(A::LU) + if A.info > 0; return throw(LAPACK.SingularException(A.info)); end + LAPACK.getri!(copy(A.factors), A.ipiv) +end + +cond(A::LU, p) = 1.0/LinAlg.LAPACK.gecon!(p == 1 ? '1' : 'I', A.factors, norm(A[:L][A[:p],:]*A[:U], p)) + +## QR decomposition without column pivots. By the faster geqrt3 +type QR{S<:BlasFloat} <: Factorization{S} + vs::Matrix{S} # the elements on and above the diagonal contain the N-by-N upper triangular matrix R; the elements below the diagonal are the columns of V + T::Matrix{S} # upper triangular factor of the block reflector. +end +QR(A::StridedMatrix) = QR(LAPACK.geqrt3!(A)...) + +qrfact!(A::StridedMatrix) = QR(A) +qrfact(A::StridedMatrix) = qrfact!(copy(A)) +qrfact{T<:Integer}(A::StridedMatrix{T}) = qrfact(float(A)) +qrfact(x::Number) = QR(fill(one(x), 1, 1), fill(x, 1, 1)) +qrfact(x::Integer) = qrfact(float(x)) + +function qr(A::Union(Number, StridedMatrix), thin::Bool) + F = qrfact(A) + return (full(F[:Q], thin), F[:R]) +end +qr(A::Union(Number, StridedMatrix)) = qr(A, true) + +size(A::QR, args::Integer...) = size(A.vs, args...) + +function getindex(A::QR, d::Symbol) + if d == :R; return triu(A.vs[1:min(size(A)),:]); end; + if d == :Q; return QRPackedQ(A); end + error("No such type field") +end + +type QRPackedQ{S} <: AbstractMatrix{S} + vs::Matrix{S} + T::Matrix{S} +end +QRPackedQ(A::QR) = QRPackedQ(A.vs, A.T) + +size(A::QRPackedQ, args::Integer...) = size(A.vs, args...) + +function full{T<:BlasFloat}(A::QRPackedQ{T}, thin::Bool) + if thin return A * eye(T, size(A.T, 1)) end + return A * eye(T, size(A, 1)) +end +full(A::QRPackedQ) = full(A, true) + +print_matrix(io::IO, A::QRPackedQ) = print_matrix(io, full(A)) + +## Multiplication by Q from the QR decomposition +function *{T<:BlasFloat}(A::QRPackedQ{T}, B::StridedVecOrMat{T}) + m = size(B, 1) + n = size(B, 2) + if m == size(A.vs, 1) + Bc = copy(B) + elseif m == size(A.vs, 2) + Bc = [B; zeros(T, size(A.vs, 1) - m, n)] + else + throw(LAPACK.DimensionMismatch("")) + end + LAPACK.gemqrt!('L', 'N', A.vs, A.T, Bc) +end +Ac_mul_B(A::QRPackedQ, B::StridedVecOrMat) = LAPACK.gemqrt!('L', iscomplex(A.vs[1]) ? 'C' : 'T', A.vs, A.T, copy(B)) +*(A::StridedVecOrMat, B::QRPackedQ) = LAPACK.gemqrt!('R', 'N', B.vs, B.T, copy(A)) +function A_mul_Bc{T<:BlasFloat}(A::StridedVecOrMat{T}, B::QRPackedQ{T}) + m = size(A, 1) + n = size(A, 2) + if n == size(B.vs, 1) + Ac = copy(A) + elseif n == size(B.vs, 2) + Ac = [B zeros(T, m, size(B.vs, 1) - n)] + else + throw(LAPACK.DimensionMismatch("")) + end + LAPACK.gemqrt!('R', iscomplex(B.vs[1]) ? 'C' : 'T', B.vs, B.T, Ac) +end +## Least squares solution. Should be more careful about cases with m < n +(\)(A::QR, B::StridedVector) = Triangular(A[:R], 'U')\(A[:Q]'B)[1:size(A, 2)] +(\)(A::QR, B::StridedMatrix) = Triangular(A[:R], 'U')\(A[:Q]'B)[1:size(A, 2),:] + +type QRPivoted{T} <: Factorization{T} + hh::Matrix{T} + tau::Vector{T} + jpvt::Vector{BlasInt} + function QRPivoted(hh::Matrix{T}, tau::Vector{T}, jpvt::Vector{BlasInt}) + m, n = size(hh) + if length(tau) != min(m,n) || length(jpvt) != n + throw(LAPACK.DimensionMismatch("")) + end + new(hh,tau,jpvt) + end +end +qrpfact!{T<:BlasFloat}(A::StridedMatrix{T}) = QRPivoted{T}(LAPACK.geqp3!(A)...) + +qrpfact(A::StridedMatrix) = qrpfact!(copy(A)) + +function qrp(A::StridedMatrix, thin::Bool) + F = qrpfact(A) + return full(F[:Q], thin), F[:R], F[:P] +end +qrp(A::StridedMatrix) = qrp(A, false) + +size(A::QRPivoted, args::Integer...) = size(A.hh, args...) + +function getindex{T<:BlasFloat}(A::QRPivoted{T}, d::Symbol) + if d == :R; return triu(A.hh[1:min(size(A)),:]); end; + if d == :Q; return QRPivotedQ(A); end + if d == :p; return A.jpvt; end + if d == :P + p = A[:p] + n = length(p) + P = zeros(T, n, n) + for i in 1:n + P[p[i],i] = one(T) + end + return P + end + error("No such type field") +end + +(\)(A::QRPivoted, B::StridedVector) = (Triangular(A[:R])\(A[:Q]'B)[1:size(A, 2)])[invperm(A.jpvt)] +(\)(A::QRPivoted, B::StridedMatrix) = (Triangular(A[:R])\(A[:Q]'B)[1:size(A, 2),:])[invperm(A.jpvt),:] + +type QRPivotedQ{T} <: AbstractMatrix{T} + hh::Matrix{T} # Householder transformations and R + tau::Vector{T} # Scalar factors of transformations +end +QRPivotedQ(A::QRPivoted) = QRPivotedQ(A.hh, A.tau) + +size(A::QRPivotedQ, args...) = size(A.hh, args...) + +function full{T<:BlasFloat}(A::QRPivotedQ{T}, thin::Bool) + if !thin + Q = Array(T, size(A, 1), size(A, 1)) + Q[:,1:size(A, 2)] = copy(A.hh) + return LAPACK.orgqr!(Q, A.tau) + else + return LAPACK.orgqr!(copy(A.hh), A.tau) + end +end +full(A::QRPivotedQ) = full(A, true) +print_matrix(io::IO, A::QRPivotedQ) = print_matrix(io, full(A)) + +## Multiplication by Q from the Pivoted QR decomposition +function *{T<:BlasFloat}(A::QRPivotedQ{T}, B::StridedVecOrMat{T}) + m = size(B, 1) + n = size(B, 2) + if m == size(A.hh, 1) + Bc = copy(B) + elseif m == size(A.hh, 2) + Bc = [B; zeros(T, size(A.hh, 1) - m, n)] + else + throw(LAPACK.DimensionMismatch("")) + end + LAPACK.ormqr!('L', 'N', A.hh, A.tau, Bc) +end +Ac_mul_B(A::QRPivotedQ, B::StridedVecOrMat) = LAPACK.ormqr!('L', iscomplex(A.hh[1]) ? 'C' : 'T', A.hh, A.tau, copy(B)) +*(A::StridedVecOrMat, B::QRPivotedQ) = LAPACK.ormqr!('R', 'N', B.hh, B.tau, copy(A)) +function A_mul_Bc{T<:BlasFloat}(A::StridedVecOrMat{T}, B::QRPivotedQ{T}) + m = size(A, 1) + n = size(A, 2) + if n == size(B.hh, 1) + Ac = copy(A) + elseif n == size(B.hh, 2) + Ac = [B zeros(T, m, size(B.hh, 1) - n)] + else + throw(LAPACK.DimensionMismatch("")) + end + LAPACK.ormqr!('R', iscomplex(B.hh[1]) ? 'C' : 'T', B.hh, B.tau, Ac) +end + +##TODO: Add methods for rank(A::QRP{T}) and adjust the (\) method accordingly +## Add rcond methods for Cholesky, LU, QR and QRP types +## Lower priority: Add LQ, QL and RQ factorizations + +# FIXME! Should add balancing option through xgebal +type Hessenberg{T} <: Factorization{T} + hh::Matrix{T} + tau::Vector{T} + function Hessenberg(hh::Matrix{T}, tau::Vector{T}) + if size(hh, 1) != size(hh, 2) throw(LAPACK.DimensionMismatch("")) end + return new(hh, tau) + end +end +Hessenberg{T<:BlasFloat}(hh::Matrix{T}, tau::Vector{T}) = Hessenberg{T}(hh, tau) +Hessenberg(A::StridedMatrix) = Hessenberg(LAPACK.gehrd!(A)...) + +hessfact!(A::StridedMatrix) = Hessenberg(A) +hessfact(A::StridedMatrix) = hessfact!(copy(A)) + +type HessenbergQ{T} <: AbstractMatrix{T} + hh::Matrix{T} + tau::Vector{T} +end +HessenbergQ(A::Hessenberg) = HessenbergQ(A.hh, A.tau) +size(A::HessenbergQ, args...) = size(A.hh, args...) +getindex(A::HessenbergQ, args...) = getindex(full(A), args...) + +function getindex(A::Hessenberg, d::Symbol) + if d == :Q; return HessenbergQ(A); end + if d == :H; return triu(A.hh, -1); end + error("No such type field") +end + +full(A::HessenbergQ) = LAPACK.orghr!(1, size(A.hh, 1), copy(A.hh), A.tau) + +# Eigenvalues +type Eigen{T,V} <: Factorization{T} + values::Vector{V} + vectors::Matrix{T} +end + +function getindex(A::Eigen, d::Symbol) + if d == :values return A.values end + if d == :vectors return A.vectors end + error("No such type field") +end + +function eigfact!{T<:BlasFloat}(A::StridedMatrix{T}) + n = size(A, 2) + if n == 0; return Eigen(zeros(T, 0), zeros(T, 0, 0)) end + if ishermitian(A) return eigfact!(Hermitian(A)) end + if iscomplex(A) return Eigen(LAPACK.geev!('N', 'V', A)[[1,3]]...) end + + WR, WI, VL, VR = LAPACK.geev!('N', 'V', A) + if all(WI .== 0.) return Eigen(WR, VR) end + evec = complex(zeros(T, n, n)) + j = 1 + while j <= n + if WI[j] == 0.0 + evec[:,j] = VR[:,j] + else + evec[:,j] = VR[:,j] + im*VR[:,j+1] + evec[:,j+1] = VR[:,j] - im*VR[:,j+1] + j += 1 + end + j += 1 + end + return Eigen(complex(WR, WI), evec) +end + +eigfact(A::StridedMatrix) = eigfact!(copy(A)) +eigfact{T<:Integer}(x::StridedMatrix{T}) = eigfact(float64(x)) +eigfact(x::Number) = Eigen([x], fill(one(x), 1, 1)) + +function eig(A::Union(Number, StridedMatrix)) + F = eigfact(A) + return F[:values], F[:vectors] +end + +#Calculates eigenvectors +eigvecs(A::Union(Number, StridedMatrix)) = eigfact(A)[:vectors] + +function eigvals(A::StridedMatrix) + if ishermitian(A) return eigvals(Hermitian(A)) end + if iscomplex(A) return LAPACK.geev!('N', 'N', copy(A))[1] end + valsre, valsim, _, _ = LAPACK.geev!('N', 'N', copy(A)) + if all(valsim .== 0) return valsre end + return complex(valsre, valsim) +end + +eigvals(x::Number) = [one(x)] + +#Computes maximum and minimum eigenvalue +function eigmax(A::Union(Number, StridedMatrix)) + v = eigvals(A) + iscomplex(v) ? error("Complex eigenvalues cannot be ordered") : max(v) +end +function eigmin(A::Union(Number, StridedMatrix)) + v = eigvals(A) + iscomplex(v) ? error("Complex eigenvalues cannot be ordered") : min(v) +end + +inv(A::Eigen) = diagmm(A.vectors, 1.0/A.values)*A.vectors' +det(A::Eigen) = prod(A.values) + +# SVD +type SVD{T<:BlasFloat,Tr} <: Factorization{T} + U::Matrix{T} + S::Vector{Tr} + Vt::Matrix{T} +end +function svdfact!(A::StridedMatrix, thin::Bool) + m,n = size(A) + if m == 0 || n == 0 + u,s,vt = (eye(m, thin ? n : m), zeros(0), eye(n,n)) + else + u,s,vt = LAPACK.gesdd!(thin ? 'S' : 'A', A) + end + return SVD(u,s,vt) +end +svdfact(A::StridedMatrix, thin::Bool) = svdfact!(copy(A), thin) +svdfact(a::Vector, thin::Bool) = svdfact(reshape(a, length(a), 1), thin) +svdfact(x::Number, thin::Bool) = SVD(x == 0 ? fill(one(x), 1, 1) : fill(x/abs(x), 1, 1), [abs(x)], fill(one(x), 1, 1)) +svdfact(x::Integer, thin::Bool) = svdfact(float(x), thin) +svdfact(A::Union(Number, StridedVecOrMat)) = svdfact(A, false) + +function svd(A::Union(Number, StridedVecOrMat), thin::Bool) + F = svdfact(A, thin) + return F.U, F.S, F.Vt' +end +svd(A::Union(Number, StridedVecOrMat)) = svd(A, true) + +function getindex(F::SVD, d::Symbol) + if d == :U return F.U end + if d == :S return F.S end + if d == :Vt return F.Vt end + if d == :V return F.Vt' end + error("No such type field") +end + +function svdvals!{T<:BlasFloat}(A::StridedMatrix{T}) + m,n = size(A) + if m == 0 || n == 0 return zeros(T, 0) end + return LAPACK.gesdd!('N', A)[2] +end + +svdvals(A) = svdvals!(copy(A)) +svdvals(A::Number) = [A] + +# SVD least squares +function \{T<:BlasFloat}(A::SVD{T}, B::StridedVecOrMat{T}) + n = length(A.S) + Sinv = zeros(T, n) + Sinv[A.S .> sqrt(eps())] = 1.0 ./ A.S + return diagmm(A.Vt', Sinv) * A.U[:,1:n]'B +end + +# Generalized svd +type GeneralizedSVD{T} <: Factorization{T} + U::Matrix{T} + V::Matrix{T} + Q::Matrix{T} + a::Vector + b::Vector + k::Int + l::Int + R::Matrix{T} +end + +function svdfact!(A::StridedMatrix, B::StridedMatrix) + U, V, Q, a, b, k, l, R = LAPACK.ggsvd!('U', 'V', 'Q', A, B) + return GeneralizedSVD(U, V, Q, a, b, int(k), int(l), R) +end + +svdfact(A::StridedMatrix, B::StridedMatrix) = svdfact!(copy(A), copy(B)) + +function svd(A::StridedMatrix, B::StridedMatrix) + F = svdfact(A, B) + return F[:U], F[:V], F[:Q]*F[:R0]', F[:D1], F[:D2] +end + +function getindex{T}(obj::GeneralizedSVD{T}, d::Symbol) + if d == :U return obj.U end + if d == :V return obj.V end + if d == :Q return obj.Q end + if d == :alpha || d == :a return obj.a end + if d == :beta || d == :b return obj.b end + if d == :vals || d == :S return obj.a[1:obj.k + obj.l] ./ obj.b[1:obj.k + obj.l] end + if d == :D1 + m = size(obj.U, 1) + if m - obj.k - obj.l >= 0 + return [eye(T, obj.k) zeros(T, obj.k, obj.l); zeros(T, obj.l, obj.k) diagm(obj.a[obj.k + 1:obj.k + obj.l]); zeros(T, m - obj.k - obj.l, obj.k + obj.l)] + else + return [eye(T, m, obj.k) [zeros(T, obj.k, m - obj.k); diagm(obj.a[obj.k + 1:m])] zeros(T, m, obj.k + obj.l - m)] + end + end + if d == :D2 + m = size(obj.U, 1) + p = size(obj.V, 1) + if m - obj.k - obj.l >= 0 + return [zeros(T, obj.l, obj.k) diagm(obj.b[obj.k + 1:obj.k + obj.l]); zeros(T, p - obj.l, obj.k + obj.l)] + else + return [zeros(T, p, obj.k) [diagm(obj.b[obj.k + 1:m]); zeros(T, obj.k + p - m, m - obj.k)] [zeros(T, m - obj.k, obj.k + obj.l - m); eye(T, obj.k + p - m, obj.k + obj.l - m)]] + end + end + if d == :R return obj.R end + if d == :R0 + m = size(obj.U, 1) + n = size(obj.Q, 1) + if m - obj.k - obj.l >= 0 + return [zeros(T, obj.k + obj.l, n - obj.k - obj.l) obj.R] + else + return [zeros(T, obj.k + obj.l, n - obj.k - obj.l) obj.R] + end + end + error("No such type field") +end + +function svdvals(A::StridedMatrix, B::StridedMatrix) + _, _, _, a, b, k, l, _ = LAPACK.ggsvd!('N', 'N', 'N', copy(A), copy(B)) + return a[1:k + l] ./ b[1:k + l] +end + +type Schur{Ty<:BlasFloat} <: Factorization{Ty} + T::Matrix{Ty} + Z::Matrix{Ty} + values::Vector +end + +schurfact!{T<:BlasFloat}(A::StridedMatrix{T}) = Schur(LinAlg.LAPACK.gees!('V', A)...) +schurfact!{T<:Integer}(A::StridedMatrix{T}) = schurfact!(schurfact!(float(A))) +schurfact(A::StridedMatrix) = schurfact!(copy(A)) + +function getindex(F::Schur, d::Symbol) + if d == :T || d == :Schur return F.T end + if d == :Z || d == :vectors return F.Z end + if d == :values return F.values end + error("No such type field") +end + +function schur(A::StridedMatrix) + SchurF = schurfact(A) + return SchurF[:T], SchurF[:Z], SchurF[:values] +end + +type GeneralizedSchur{Ty<:BlasFloat} <: Factorization{Ty} + S::Matrix{Ty} + T::Matrix{Ty} + alpha::Vector + beta::Vector{Ty} + Q::Matrix{Ty} + Z::Matrix{Ty} +end + +schurfact!(A::StridedMatrix, B::StridedMatrix) = GeneralizedSchur(LinAlg.LAPACK.gges!('V', 'V', A, B)...) +schurfact!{T<:Integer}(A::StridedMatrix{T}, B::StridedMatrix{T}) = schurfact!(schurfact!(float(A), float(B))) +schurfact(A::StridedMatrix, B::StridedMatrix) = schurfact!(copy(A), copy(B)) + +function getindex(F::GeneralizedSchur, d::Symbol) + if d == :S return F.S end + if d == :T return F.T end + if d == :alpha return F.alpha end + if d == :beta return F.beta end + if d == :values return F.alpha./F.beta end + if d == :Q || d == :left return F.Q end + if d == :Z || d == :right return F.Z end + error("No such type field") +end + +function schur(A::StridedMatrix, B::StridedMatrix) + SchurF = schurfact(A, B) + return SchurF[:S], SchurF[:T], SchurF[:Q], SchurF[:Z] +end \ No newline at end of file diff --git a/base/linalg/generic.jl b/base/linalg/generic.jl new file mode 100644 index 0000000000000..a475ae27797a3 --- /dev/null +++ b/base/linalg/generic.jl @@ -0,0 +1,187 @@ +## linalg.jl: Some generic Linear Algebra definitions + +function scale!{T<:Number}(X::AbstractArray{T}, s::Real) + # FIXME: could use BLAS in more cases + for i in 1:length(X) + X[i] *= s; + end + return X +end + +cross(a::AbstractVector, b::AbstractVector) = + [a[2]*b[3]-a[3]*b[2], a[3]*b[1]-a[1]*b[3], a[1]*b[2]-a[2]*b[1]] + +triu(M::AbstractMatrix) = triu(M,0) +tril(M::AbstractMatrix) = tril(M,0) +#triu{T}(M::AbstractMatrix{T}, k::Integer) +#tril{T}(M::AbstractMatrix{T}, k::Integer) +triu!(M::AbstractMatrix) = triu!(M,0) +tril!(M::AbstractMatrix) = tril!(M,0) + +#diff(a::AbstractVector) +#diff(a::AbstractMatrix, dim::Integer) +diff(a::AbstractMatrix) = diff(a, 1) + +gradient(F::AbstractVector) = gradient(F, [1:length(F)]) +gradient(F::AbstractVector, h::Real) = gradient(F, [h*(1:length(F))]) +#gradient(F::AbstractVector, h::AbstractVector) + +diag(A::AbstractVector) = error("Perhaps you meant to use diagm().") +#diag(A::AbstractMatrix) + +#diagm{T}(v::Union(AbstractVector{T},AbstractMatrix{T})) + +function norm{T}(x::AbstractVector{T}, p::Number) + if length(x) == 0 + a = zero(T) + elseif p == Inf + a = max(abs(x)) + elseif p == -Inf + a = min(abs(x)) + else + absx = abs(x) + dx = max(absx) + if dx != zero(T) + scale!(absx, 1/dx) + a = dx * (sum(absx.^p).^(1/p)) + else + a = sum(absx.^p).^(1/p) + end + end + return float(a) +end +norm{T<:Integer}(x::AbstractVector{T}, p::Number) = norm(float(x), p) +norm(x::AbstractVector) = norm(x, 2) + +function norm(A::AbstractMatrix, p::Number) + m, n = size(A) + if m == 0 || n == 0 + a = zero(eltype(A)) + elseif m == 1 || n == 1 + a = norm(reshape(A, length(A)), p) + elseif p == 1 + a = max(sum(abs(A),1)) + elseif p == 2 + a = max(svdvals(A)) + elseif p == Inf + a = max(sum(abs(A),2)) + else + error("invalid parameter p given to compute matrix norm") + end + return float(a) +end + +norm(A::AbstractMatrix) = norm(A, 2) + +norm(x::Number) = abs(x) +norm(x::Number, p) = abs(x) + +normfro(A::AbstractMatrix) = norm(reshape(A, length(A))) +normfro(x::Number) = abs(x) + +rank(A::AbstractMatrix, tol::Real) = sum(svdvals(A) .> tol) +function rank(A::AbstractMatrix) + m,n = size(A) + if m == 0 || n == 0; return 0; end + sv = svdvals(A) + sum(sv .> max(size(A))*eps(sv[1])) +end +rank(x::Number) = x == 0 ? 0 : 1 + +trace(A::AbstractMatrix) = sum(diag(A)) +trace(x::Number) = x + +#kron(a::AbstractVector, b::AbstractVector) +#kron{T,S}(a::AbstractMatrix{T}, b::AbstractMatrix{S}) + +#det(a::AbstractMatrix) +inv(a::AbstractMatrix) = a \ one(a) + +inv(a::AbstractVector) = inv(reshape(a, length(a), 1)) + +\(a::AbstractVector, b::AbstractArray) = reshape(a, length(a), 1) \ b +(/)(A::AbstractVector, B::AbstractVector) = (B' \ A')' +(/)(A::AbstractVector, B::AbstractMatrix) = (B' \ A')' +(/)(A::AbstractMatrix, B::AbstractVector) = (B' \ A')' +(/)(A::AbstractMatrix, B::AbstractMatrix) = (B' \ A')' + + +cond(x::Number) = x == 0 ? Inf : 1.0 +cond(x::Number, p) = cond(x) + +function issym(A::AbstractMatrix) + m, n = size(A) + if m != n; return false; end + for i = 1:(n-1), j = (i+1):n + if A[i,j] != A[j,i] + return false + end + end + return true +end + +issym(x::Number) = true + +function ishermitian(A::AbstractMatrix) + m, n = size(A) + if m != n; return false; end + for i = 1:n, j = i:n + if A[i,j] != conj(A[j,i]) + return false + end + end + return true +end + +ishermitian(x::Number) = (x == conj(x)) + +function istriu(A::AbstractMatrix) + m, n = size(A) + for j = 1:min(n,m-1), i = j+1:m + if A[i,j] != 0 + return false + end + end + return true +end + +function istril(A::AbstractMatrix) + m, n = size(A) + for j = 2:n, i = 1:min(j-1,m) + if A[i,j] != 0 + return false + end + end + return true +end + +istriu(x::Number) = true +istril(x::Number) = true + +function linreg{T<:Number}(X::StridedVecOrMat{T}, y::Vector{T}) + [ones(T, size(X,1)) X] \ y +end + +# weighted least squares +function linreg(x::AbstractVector, y::AbstractVector, w::AbstractVector) + w = sqrt(w) + [w w.*x] \ (w.*y) +end + +# multiply by diagonal matrix as vector +#diagmm!(C::AbstractMatrix, A::AbstractMatrix, b::AbstractVector) + +#diagmm!(C::AbstractMatrix, b::AbstractVector, A::AbstractMatrix) + +diagmm!(A::AbstractMatrix, b::AbstractVector) = diagmm!(A,A,b) +diagmm!(b::AbstractVector, A::AbstractMatrix) = diagmm!(A,b,A) + +#diagmm(A::AbstractMatrix, b::AbstractVector) +#diagmm(b::AbstractVector, A::AbstractMatrix) + +#^(A::AbstractMatrix, p::Number) + +#findmax(a::AbstractArray) +#findmin(a::AbstractArray) + +#rref{T}(A::AbstractMatrix{T}) diff --git a/base/linalg/hermitian.jl b/base/linalg/hermitian.jl new file mode 100644 index 0000000000000..81f5b7ee9b916 --- /dev/null +++ b/base/linalg/hermitian.jl @@ -0,0 +1,61 @@ +## Hermitian matrices + +type Hermitian{T<:BlasFloat} <: AbstractMatrix{T} + S::Matrix{T} + uplo::Char + function Hermitian(S::Matrix{T}, uplo::Char) + if size(S, 1) != size(S, 2) throw(LAPACK.DimensionMismatch("Matrix must be square")); end + return new(S, uplo) + end +end + +Hermitian{T<:BlasFloat}(S::Matrix{T}, uplo::Char) = Hermitian{T}(S, uplo) +Hermitian(A::StridedMatrix) = Hermitian(A, 'U') + +size(A::Hermitian, args...) = size(A.S, args...) +print_matrix(io::IO, A::Hermitian) = print_matrix(io, full(A)) +full(A::Hermitian) = A.S +ishermitian(A::Hermitian) = true +issym{T<:Union(Float64, Float32)}(A::Hermitian{T}) = true +ctranspose(A::Hermitian) = A + +*(A::Hermitian, B::Hermitian) = *(full(A), full(B)) +*(A::Hermitian, B::StridedMatrix) = *(full(A), B) +*(A::StridedMatrix, B::Hermitian) = *(A, full(B)) + +function \(A::Hermitian, B::StridedVecOrMat) + r, _, _, info = LAPACK.sysv!(A.uplo, copy(A.S), copy(B)) + if info > 0 throw(LAPACK.SingularException(info)) end + return r +end + +inv(A::Hermitian) = inv(BunchKaufman(copy(A.S), A.uplo)) + +eigfact!(A::Hermitian) = Eigen(LAPACK.syevr!('V', 'A', A.uplo, A.S, 0.0, 0.0, 0, 0, -1.0)...) +eigfact(A::Hermitian) = Eigen(LAPACK.syevr!('V', 'A', A.uplo, copy(A.S), 0.0, 0.0, 0, 0, -1.0)...) +eigvals(A::Hermitian, il::Int, ih::Int) = LAPACK.syevr!('N', 'I', A.uplo, copy(A.S), 0.0, 0.0, il, ih, -1.0)[1] +eigvals(A::Hermitian, vl::Real, vh::Real) = LAPACK.syevr!('N', 'V', A.uplo, copy(A.S), vl, vh, 0, 0, -1.0)[1] +eigvals(A::Hermitian) = eigvals(A, 1, size(A, 1)) +eigmax(A::Hermitian) = eigvals(A, size(A, 1), size(A, 1))[1] +eigmin(A::Hermitian) = eigvals(A, 1, 1)[1] + +function expm(A::Hermitian) + F = eigfact(A) + diagmm(F[:vectors], exp(F[:values])) * F[:vectors]' +end + +function sqrtm(A::Hermitian, cond::Bool) + F = eigfact(A) + vsqrt = sqrt(complex(F[:values])) + if all(imag(vsqrt) .== 0) + retmat = symmetrize!(diagmm(F[:vectors], real(vsqrt)) * F[:vectors]') + else + zc = complex(F[:vectors]) + retmat = symmetrize!(diagmm(zc, vsqrt) * zc') + end + if cond + return retmat, norm(vsqrt, Inf)^2/norm(F[:values], Inf) + else + return retmat + end +end diff --git a/base/linalg/lapack.jl b/base/linalg/lapack.jl new file mode 100644 index 0000000000000..5eb12b0aa7612 --- /dev/null +++ b/base/linalg/lapack.jl @@ -0,0 +1,2418 @@ +## The LAPACK module of interfaces to LAPACK subroutines +module LAPACK + +const liblapack = Base.liblapack_name + +import LinAlg.BlasFloat +import LinAlg.BlasChar +import LinAlg.BlasInt +import LinAlg.blas_int + +type LAPACKException <: Exception + info::BlasInt +end + +type SingularException <: Exception + info::BlasInt +end + +type PosDefException <: Exception + info::BlasInt +end + +type RankDeficientException <: Exception + info::BlasInt +end + +type DimensionMismatch <: Exception + name::ASCIIString +end + +function chkstride1(A::StridedVecOrMat...) + for a in A + if stride(a,1) != 1 error("LAPACK: Matrix must have contiguous columns") end + end +end + +function chksquare(A::Matrix...) + for a in A + m, n = size(a) + if m != n throw(DimensionMismatch("Matrix must be square")) end + end +end + +# (GB) general banded matrices, LU decomposition and solver +for (gbtrf, gbtrs, elty) in + ((:dgbtrf_,:dgbtrs_,:Float64), + (:sgbtrf_,:sgbtrs_,:Float32), + (:zgbtrf_,:zgbtrs_,:Complex128), + (:cgbtrf_,:cgbtrs_,:Complex64)) + @eval begin + # SUBROUTINE DGBTRF( M, N, KL, KU, AB, LDAB, IPIV, INFO ) + # * .. Scalar Arguments .. + # INTEGER INFO, KL, KU, LDAB, M, N + # * .. Array Arguments .. + # INTEGER IPIV( * ) + # DOUBLE PRECISION AB( LDAB, * ) + function gbtrf!(kl::Integer, ku::Integer, m::Integer, AB::StridedMatrix{$elty}) + chkstride1(AB) + info = Array(BlasInt, 1) + n = size(AB, 2) + mnmn = min(m, n) + ipiv = Array(BlasInt, mnmn) + ccall(($(string(gbtrf)),liblapack), Void, + (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}), + &m, &n, &kl, &ku, AB, &stride(AB,2), ipiv, info) + if info[1] != 0 throw(LAPACKException(info[1])) end + AB, ipiv + end + # SUBROUTINE DGBTRS( TRANS, N, KL, KU, NRHS, AB, LDAB, IPIV, B, LDB, INFO) + # * .. Scalar Arguments .. + # CHARACTER TRANS + # INTEGER INFO, KL, KU, LDAB, LDB, N, NRHS + # * .. Array Arguments .. + # INTEGER IPIV( * ) + # DOUBLE PRECISION AB( LDAB, * ), B( LDB, * ) + function gbtrs!(trans::BlasChar, kl::Integer, ku::Integer, m::Integer, + AB::StridedMatrix{$elty}, ipiv::Vector{BlasInt}, + B::StridedVecOrMat{$elty}) + chkstride1(AB, B) + info = Array(BlasInt, 1) + n = size(AB,2) + if m != n || m != size(B,1) throw(DimensionMismatch("gbtrs!")) end + ccall(($(string(gbtrs)),liblapack), Void, + (Ptr{Uint8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{BlasInt}), + &trans, &n, &kl, &ku, &size(B,2), AB, &stride(AB,2), ipiv, + B, &stride(B,2), info) + if info[1] != 0 throw(LAPACKException(info[1])) end + B + end + end +end + +## (GE) general matrices: balancing and back-transforming +for (gebal, gebak, elty, relty) in + ((:dgebal_, :dgebak_, :Float64, :Float64), + (:sgebal_, :sgebak_, :Float32, :Float32), + (:zgebal_, :zgebak_, :Complex128, :Float64), + (:cgebal_, :cgebak_, :Complex64, :Float32)) + @eval begin + # SUBROUTINE DGEBAL( JOB, N, A, LDA, ILO, IHI, SCALE, INFO ) + #* .. Scalar Arguments .. + # CHARACTER JOB + # INTEGER IHI, ILP, INFO, LDA, N + # .. Array Arguments .. + # DOUBLE PRECISION A( LDA, * ), SCALE( * ) + function gebal!(job::BlasChar, A::StridedMatrix{$elty}) + chkstride1(A) + chksquare(A) + n = size(A, 2) + info = Array(BlasInt, 1) + ihi = Array(BlasInt, 1) + ilo = Array(BlasInt, 1) + scale = Array($relty, n) + ccall(($(string(gebal)),liblapack), Void, + (Ptr{Uint8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$relty}, Ptr{BlasInt}), + &job, &n, A, &stride(A,2), ilo, ihi, scale, info) + if info[1] != 0 throw(LAPACKException(info[1])) end + ilo[1], ihi[1], scale + end + # SUBROUTINE DGEBAK( JOB, SIDE, N, ILO, IHI, SCALE, M, V, LDV, INFO ) + #* .. Scalar Arguments .. + # CHARACTER JOB, SIDE + # INTEGER IHI, ILP, INFO, LDV, M, N + # .. Array Arguments .. + # DOUBLE PRECISION SCALE( * ), V( LDV, * ) + function gebak!(job::BlasChar, side::BlasChar, + ilo::BlasInt, ihi::BlasInt, scale::Vector{$elty}, + V::StridedMatrix{$elty}) + chkstride1(V) + chksquare(V) + info = Array(BlasInt, 1) + ccall(($(string(gebak)),liblapack), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), + &job, &side, &size(V,1), &ilo, &ihi, scale, &n, V, &stride(V,2), info) + if info[1] != 0 throw(LAPACKException(info[1])) end + V + end + end +end + +# (GE) general matrices, direct decompositions +# gebrd - reduction to bidiagonal form Q'*A*P=B where Q and P are orthogonal +# gelqf - unpivoted LQ decomposition +# geqlf - unpivoted QL decomposition +# geqrf - unpivoted QR decomposition +# gegp3 - pivoted QR decomposition +# geqrt3! - recursive algorithm producing compact WY representation of Q +# gerqf - unpivoted RQ decomposition +# getrf - LU decomposition +for (gebrd, gelqf, geqlf, geqrf, geqp3, geqrt3, gerqf, getrf, elty, relty) in + ((:dgebrd_,:dgelqf_,:dgeqlf_,:dgeqrf_,:dgeqp3_,:dgeqrt3_,:dgerqf_,:dgetrf_,:Float64,:Float64), + (:sgebrd_,:sgelqf_,:sgeqlf_,:sgeqrf_,:sgeqp3_,:sgeqrt3_,:sgerqf_,:sgetrf_,:Float32,:Float32), + (:zgebrd_,:zgelqf_,:zgeqlf_,:zgeqrf_,:zgeqp3_,:zgeqrt3_,:zgerqf_,:zgetrf_,:Complex128,:Float64), + (:cgebrd_,:cgelqf_,:cgeqlf_,:cgeqrf_,:cgeqp3_,:cgeqrt3_,:cgerqf_,:cgetrf_,:Complex64,:Float32)) + @eval begin + # SUBROUTINE DGEBRD( M, N, A, LDA, D, E, TAUQ, TAUP, WORK, LWORK, + # INFO ) + # .. Scalar Arguments .. + # INTEGER INFO, LDA, LWORK, M, N + # .. Array Arguments .. + # DOUBLE PRECISION A( LDA, * ), D( * ), E( * ), TAUP( * ), + # TAUQ( * ), WORK( * ) + function gebrd!(A::StridedMatrix{$elty}) + chkstride1(A) + m, n = size(A) + k = min(m, n) + d = Array($elty, k) + s = Array($elty, k) + tauq = Array($elty, k) + taup = Array($elty, k) + work = Array($elty, 1) + lwork = blas_int(-1) + info = Array(BlasInt, 1) + for i in 1:2 + ccall(($(string(gebrd)),liblapack), Void, + (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{$elty}, Ptr{$elty}, Ptr{$elty}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), + &m, &n, A, &stride(A,2), d, s, tauq, taup, work, &lwork, info) + if info[1] != 0 throw(LAPACKException(info[1])) end + if lwork < 0 + lwork = blas_int(real(work[1])) + work = Array($elty, lwork) + end + end + end + # SUBROUTINE DGELQF( M, N, A, LDA, TAU, WORK, LWORK, INFO ) + # * .. Scalar Arguments .. + # INTEGER INFO, LDA, LWORK, M, N + # * .. Array Arguments .. + # DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * ) + function gelqf!(A::StridedMatrix{$elty}) + chkstride1(A) + info = Array(BlasInt, 1) + m = blas_int(size(A, 1)) + n = blas_int(size(A, 2)) + lda = blas_int(stride(A, 2)) + tau = Array($elty, n) + lwork = blas_int(-1) + work = Array($elty, (1,)) + for i in 1:2 # first call returns lwork as work[1] + ccall(($(string(gelqf)),liblapack), Void, + (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), + &m, &n, A, &lda, tau, work, &lwork, info) + if info[1] != 0 throw(LAPACKException(info[1])) end + if lwork < 0 + lwork = blas_int(real(work[1])) + work = Array($elty, lwork) + end + end + A, tau + end + # SUBROUTINE DGEQLF( M, N, A, LDA, TAU, WORK, LWORK, INFO ) + # * .. Scalar Arguments .. + # INTEGER INFO, LDA, LWORK, M, N + # * .. Array Arguments .. + # DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * ) + function geqlf!(A::StridedMatrix{$elty}) + chkstride1(A) + info = Array(BlasInt, 1) + m = blas_int(size(A, 1)) + n = blas_int(size(A, 2)) + lda = blas_int(stride(A, 2)) + tau = Array($elty, n) + lwork = blas_int(-1) + work = Array($elty, (1,)) + for i in 1:2 # first call returns lwork as work[1] + ccall(($(string(geqlf)),liblapack), Void, + (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), + &m, &n, A, &lda, tau, work, &lwork, info) + if info[1] != 0 throw(LAPACKException(info[1])) end + if lwork < 0 + lwork = blas_int(real(work[1])) + work = Array($elty, lwork) + end + end + A, tau + end + # SUBROUTINE DGEQP3( M, N, A, LDA, JPVT, TAU, WORK, LWORK, INFO ) + # * .. Scalar Arguments .. + # INTEGER INFO, LDA, LWORK, M, N + # * .. Array Arguments .. + # INTEGER JPVT( * ) + # DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * ) + function geqp3!(A::StridedMatrix{$elty}) + chkstride1(A) + m, n = size(A) + jpvt = zeros(BlasInt, n) + tau = Array($elty, n) + work = Array($elty, 1) + lwork = blas_int(-1) + info = Array(BlasInt, 1) + cmplx = iscomplex(A) + if cmplx; rwork = Array($relty, 2n); end + for i in 1:2 + if cmplx + ccall(($(string(geqp3)),liblapack), Void, + (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$relty}, Ptr{BlasInt}), + &m, &n, A, &stride(A,2), jpvt, tau, work, &lwork, rwork, info) + else + ccall(($(string(geqp3)),liblapack), Void, + (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{BlasInt}), + &m, &n, A, &stride(A,2), jpvt, tau, work, &lwork, info) + end + if info[1] != 0 throw(LAPACKException(info[1])) end + if lwork < 0 + lwork = blas_int(real(work[1])) + work = Array($elty, lwork) + end + end + A, tau, jpvt + end + function geqrt3!(A::StridedMatrix{$elty}) + m, n = size(A) + lda = max(1, stride(A, 2)) + T = Array($elty, n, n) + info = Array(BlasInt, 1) + ccall(($(string(geqrt3)), liblapack), Void, + (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), + &m, &n, A, &lda, + T, &n, info) + if info[1] < 0 throw(LAPACKException(info[1])) end + return A, T + end + ## Several variants of geqrf! could be defined. + ## geqrfp! - positive elements on diagonal of R + ## geqrt! - compact WY representation of Q (blocked algorithm) + # SUBROUTINE DGEQRF( M, N, A, LDA, TAU, WORK, LWORK, INFO ) + # * .. Scalar Arguments .. + # INTEGER INFO, LDA, LWORK, M, N + # * .. Array Arguments .. + # DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * ) + function geqrf!(A::StridedMatrix{$elty}) + chkstride1(A) + m, n = size(A) + tau = Array($elty, n) + work = Array($elty, 1) + lwork = blas_int(-1) + info = Array(BlasInt, 1) + for i in 1:2 # first call returns lwork as work[1] + ccall(($(string(geqrf)),liblapack), Void, + (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), + &m, &n, A, &stride(A,2), tau, work, &lwork, info) + if info[1] != 0 throw(LAPACKException(info[1])) end + if lwork < 0 + lwork = blas_int(real(work[1])) + work = Array($elty, lwork) + end + end + A, tau + end + # SUBROUTINE DGERQF( M, N, A, LDA, TAU, WORK, LWORK, INFO ) + # * .. Scalar Arguments .. + # INTEGER INFO, LDA, LWORK, M, N + # * .. Array Arguments .. + # DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * ) + function gerqf!(A::StridedMatrix{$elty}) + chkstride1(A) + info = Array(BlasInt, 1) + m, n = size(A) + tau = Array($elty, n) + lwork = blas_int(-1) + work = Array($elty, 1) + for i in 1:2 # first call returns lwork as work[1] + ccall(($(string(gerqf)),liblapack), Void, + (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), + &m, &n, A, &stride(A,2), tau, work, &lwork, info) + if info[1] != 0 throw(LAPACKException(info[1])) end + if lwork < 0 + lwork = blas_int(real(work[1])) + work = Array($elty, lwork) + end + end + A, tau + end + # SUBROUTINE DGETRF( M, N, A, LDA, IPIV, INFO ) + # * .. Scalar Arguments .. + # INTEGER INFO, LDA, M, N + # * .. Array Arguments .. + # INTEGER IPIV( * ) + # DOUBLE PRECISION A( LDA, * ) + function getrf!(A::StridedMatrix{$elty}) + chkstride1(A) + info = Array(BlasInt, 1) + m, n = size(A) + lda = stride(A, 2) + ipiv = Array(BlasInt, min(m,n)) + ccall(($(string(getrf)),liblapack), Void, + (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, + Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}), + &m, &n, A, &lda, ipiv, info) + if info[1] < 0 throw(LAPACKException(info[1])) end + A, ipiv, info[1] + end + end +end + +## (GE) general matrices, solvers with factorization, solver and inverse +for (gels, gesv, getrs, getri, elty) in + ((:dgels_,:dgesv_,:dgetrs_,:dgetri_,:Float64), + (:sgels_,:sgesv_,:sgetrs_,:sgetri_,:Float32), + (:zgels_,:zgesv_,:zgetrs_,:zgetri_,:Complex128), + (:cgels_,:cgesv_,:cgetrs_,:cgetri_,:Complex64)) + @eval begin + # SUBROUTINE DGELS( TRANS, M, N, NRHS, A, LDA, B, LDB, WORK, LWORK,INFO) + # * .. Scalar Arguments .. + # CHARACTER TRANS + # INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS + function gels!(trans::BlasChar, A::StridedMatrix{$elty}, B::StridedVecOrMat{$elty}) + chkstride1(A, B) + btrn = trans == 'T' + m, n = size(A) + if size(B,1) != (btrn ? n : m) throw(DimensionMismatch("gels!")) end + info = Array(BlasInt, 1) + work = Array($elty, 1) + lwork = blas_int(-1) + for i in 1:2 + ccall(($(string(gels)),liblapack), Void, + (Ptr{Uint8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), + &(btrn?'T':'N'), &m, &n, &size(B,2), A, &stride(A,2), + B, &stride(B,2), work, &lwork, info) + if info[1] != 0 throw(LAPACKException(info[1])) end + if lwork < 0 + lwork = blas_int(real(work[1])) + work = Array($elty, lwork) + end + end + k = min(m, n) + F = m < n ? tril(A[1:k, 1:k]) : triu(A[1:k, 1:k]) + F, isa(B, Vector) ? B[1:k] : B[1:k,:], [sum(B[(k+1):size(B,1), i].^2) for i=1:size(B,2)] + end + # SUBROUTINE DGESV( N, NRHS, A, LDA, IPIV, B, LDB, INFO ) + # * .. Scalar Arguments .. + # INTEGER INFO, LDA, LDB, N, NRHS + # * .. + # * .. Array Arguments .. + # INTEGER IPIV( * ) + # DOUBLE PRECISION A( LDA, * ), B( LDB, * ) + function gesv!(A::StridedMatrix{$elty}, B::StridedVecOrMat{$elty}) + chkstride1(A, B) + chksquare(A) + n = size(A,1) + if size(B,1) != n throw(DimensionMismatch("gesv!")) end + ipiv = Array(BlasInt, n) + info = Array(BlasInt, 1) + ccall(($(string(gesv)),liblapack), Void, + (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), + &n, &size(B,2), A, &stride(A,2), ipiv, B, &stride(B,2), info) + if info[1] < 0 throw(LAPACKException(info[1])) end + B, A, ipiv, info[1] + end + # SUBROUTINE DGETRS( TRANS, N, NRHS, A, LDA, IPIV, B, LDB, INFO ) + #* .. Scalar Arguments .. + # CHARACTER TRANS + # INTEGER INFO, LDA, LDB, N, NRHS + # .. Array Arguments .. + # INTEGER IPIV( * ) + # DOUBLE PRECISION A( LDA, * ), B( LDB, * ) + function getrs!(trans::BlasChar, A::StridedMatrix{$elty}, ipiv::Vector{BlasInt}, B::StridedVecOrMat{$elty}) + chkstride1(A, B) + m, n = size(A) + if m != n || size(B, 1) != m throw(DimensionMismatch("Matrix must be square")) end + nrhs = size(B, 2) + info = Array(BlasInt, 1) + ccall(($(string(getrs)),liblapack), Void, + (Ptr{Uint8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), + &trans, &n, &size(B,2), A, &stride(A,2), ipiv, B, &stride(B,2), info) + if info[1] != 0 throw(LAPACKException(info[1])) end + B + end + # SUBROUTINE DGETRI( N, A, LDA, IPIV, WORK, LWORK, INFO ) + #* .. Scalar Arguments .. + # INTEGER INFO, LDA, LWORK, N + #* .. Array Arguments .. + # INTEGER IPIV( * ) + # DOUBLE PRECISION A( LDA, * ), WORK( * ) + function getri!(A::StridedMatrix{$elty}, ipiv::Vector{BlasInt}) + chkstride1(A) + m, n = size(A) + if m != n || n != length(ipiv) throw(DimensionMismatch("Matrix must be square")) end + lda = stride(A, 2) + info = Array(BlasInt, 1) + lwork = -1 + work = Array($elty, 1) + for i in 1:2 + ccall(($(string(getri)),liblapack), Void, + (Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), + &n, A, &lda, ipiv, work, &lwork, info) + if info[1] != 0 throw(LAPACKException(info[1])) end + if lwork < 0 + lwork = blas_int(real(work[1])) + work = Array($elty, lwork) + end + end + A + end + end +end +for (gelsd, elty) in ((:dgelsd_, :Float64), + (:sgelsd_, :Float32)) + @eval begin + # SUBROUTINE DGELSD( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK, + # $ WORK, LWORK, IWORK, INFO ) + # * .. Scalar Arguments .. + # INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK + # DOUBLE PRECISION RCOND + # * .. + # * .. Array Arguments .. + # INTEGER IWORK( * ) + # DOUBLE PRECISION A( LDA, * ), B( LDB, * ), S( * ), WORK( * ) + function gelsd!(A::StridedMatrix{$elty}, B::StridedVecOrMat{$elty}, rcond) + LAPACK.chkstride1(A, B) + m, n = size(A) + if size(B, 1) != m; throw(DimensionMismatch("gelsd!")); end + if size(B, 1) < n + newB = Array($elty, n, size(B, 2)) + newB[1:size(B, 1), :] = B + else + newB = B + end + s = Array($elty, min(m, n)) + rnk = Array(BlasInt, 1) + info = Array(BlasInt, 1) + work = Array($elty, 1) + lwork = blas_int(-1) + iwork = Array(BlasInt, 1) + for i in 1:2 + ccall(($(string(gelsd)),liblapack), Void, + (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, + Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}), + &m, &n, &size(B,2), A, &max(1,stride(A,2)), + newB, &max(1,stride(B,2),n), s, &rcond, rnk, work, &lwork, iwork, info) + if info[1] != 0 throw(LAPACKException(info[1])) end + if lwork < 0 + lwork = blas_int(real(work[1])) + work = Array($elty, lwork) + iwork = Array(BlasInt, iwork[1]) + end + end + isa(B, Vector) ? newB[1:n] : newB[1:n,:], rnk[1] + end + gelsd!(A::StridedMatrix{$elty}, B::StridedVecOrMat{$elty}) = gelsd!(A, B, -1.) + end +end +for (gelsd, elty, relty) in ((:zgelsd_, :Complex128, :Float64), + (:cgelsd_, :Complex64, :Float32)) + @eval begin + # SUBROUTINE ZGELSD( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK, + # $ WORK, LWORK, RWORK, IWORK, INFO ) + # * .. Scalar Arguments .. + # INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK + # DOUBLE PRECISION RCOND + # * .. + # * .. Array Arguments .. + # INTEGER IWORK( * ) + # DOUBLE PRECISION RWORK( * ), S( * ) + # COMPLEX*16 A( LDA, * ), B( LDB, * ), WORK( * ) + function gelsd!(A::StridedMatrix{$elty}, B::StridedVecOrMat{$elty}, rcond) + LAPACK.chkstride1(A, B) + m, n = size(A) + if size(B,1) != m; throw(DimensionMismatch("gelsd!")); end + if size(B, 1) < n + newB = Array($elty, n, size(B, 2)) + newB[1:size(B, 1), :] = B + else + newB = B + end + s = Array($elty, min(m, n)) + rnk = Array(BlasInt, 1) + info = Array(BlasInt, 1) + work = Array($elty, 1) + lwork = blas_int(-1) + rwork = Array($relty, 1) + iwork = Array(BlasInt, 1) + for i in 1:2 + ccall(($(string(gelsd)),liblapack), Void, + (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, + Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$relty}, + Ptr{$relty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$relty}, Ptr{BlasInt}, Ptr{BlasInt}), + &m, &n, &size(B,2), A, &max(1,stride(A,2)), + newB, &max(1,stride(B,2),n), s, &rcond, rnk, work, &lwork, rwork, iwork, info) + if info[1] != 0 throw(LAPACKException(info[1])) end + if lwork < 0 + lwork = blas_int(real(work[1])) + work = Array($elty, lwork) + rwork = Array($relty, blas_int(rwork[1])) + iwork = Array(BlasInt, iwork[1]) + end + end + isa(B, Vector) ? newB[1:n] : newB[1:n,:], rnk[1] + end + gelsd!(A::StridedMatrix{$elty}, B::StridedVecOrMat{$elty}) = gelsd!(A, B, -1.) + end +end + +# (GE) general matrices eigenvalue-eigenvector and singular value decompositions +for (geev, gesvd, gesdd, ggsvd, elty, relty) in + ((:dgeev_,:dgesvd_,:dgesdd_,:dggsvd_,:Float64,:Float64), + (:sgeev_,:sgesvd_,:sgesdd_,:sggsvd_,:Float32,:Float32), + (:zgeev_,:zgesvd_,:zgesdd_,:zggsvd_,:Complex128,:Float64), + (:cgeev_,:cgesvd_,:cgesdd_,:cggsvd_,:Complex64,:Float32)) + @eval begin + # SUBROUTINE DGEEV( JOBVL, JOBVR, N, A, LDA, WR, WI, VL, LDVL, VR, + # $ LDVR, WORK, LWORK, INFO ) + # * .. Scalar Arguments .. + # CHARACTER JOBVL, JOBVR + # INTEGER INFO, LDA, LDVL, LDVR, LWORK, N + # * .. Array Arguments .. + # DOUBLE PRECISION A( LDA, * ), VL( LDVL, * ), VR( LDVR, * ), + # $ WI( * ), WORK( * ), WR( * ) + function geev!(jobvl::BlasChar, jobvr::BlasChar, A::StridedMatrix{$elty}) + chkstride1(A) + chksquare(A) + m, n = size(A) + lvecs = jobvl == 'V' + rvecs = jobvr == 'V' + VL = Array($elty, (n, lvecs ? n : 0)) + VR = Array($elty, (n, rvecs ? n : 0)) + cmplx = iscomplex(A) + if cmplx + W = Array($elty, n) + rwork = Array($relty, 2n) + else + WR = Array($elty, n) + WI = Array($elty, n) + end + work = Array($elty, 1) + lwork = blas_int(-1) + info = Array(BlasInt, 1) + for i = 1:2 + if cmplx + ccall(($(string(geev)),liblapack), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{BlasInt}, Ptr{$elty}, + Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$relty}, Ptr{BlasInt}), + &jobvl, &jobvr, &n, A, &stride(A,2), W, VL, &n, VR, &n, + work, &lwork, rwork, info) + else + ccall(($(string(geev)),liblapack), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{BlasInt}, Ptr{$elty}, + Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{$elty}, + Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, + Ptr{BlasInt}, Ptr{BlasInt}), + &jobvl, &jobvr, &n, A, &stride(A,2), WR, WI, VL, &n, + VR, &n, work, &lwork, info) + end + if info[1] != 0 throw(LAPACKException(info[1])) end + if lwork < 0 + lwork = blas_int(real(work[1])) + work = Array($elty, lwork) + end + end + cmplx ? (W, VL, VR) : (WR, WI, VL, VR) + end + # SUBROUTINE DGESDD( JOBZ, M, N, A, LDA, S, U, LDU, VT, LDVT, WORK, + # LWORK, IWORK, INFO ) + #* .. Scalar Arguments .. + # CHARACTER JOBZ + # INTEGER INFO, LDA, LDU, LDVT, LWORK, M, N + #* .. + #* .. Array Arguments .. + # INTEGER IWORK( * ) + # DOUBLE PRECISION A( LDA, * ), S( * ), U( LDU, * ), + # VT( LDVT, * ), WORK( * ) + function gesdd!(job::BlasChar, A::StridedMatrix{$elty}) + chkstride1(A) + m, n = size(A) + minmn = min(m, n) + if job == 'A' + U = Array($elty, (m, m)) + VT = Array($elty, (n, n)) + elseif job == 'S' + U = Array($elty, (m, minmn)) + VT = Array($elty, (minmn, n)) + elseif job == 'O' + U = Array($elty, (m, m >= n ? 0 : m)) + VT = Array($elty, (n, m >= n ? n : 0)) + else + U = Array($elty, (m, 0)) + VT = Array($elty, (n, 0)) + end + work = Array($elty, 1) + lwork = blas_int(-1) + S = Array($relty, minmn) + cmplx = iscomplex(A) + if cmplx + rwork = Array($relty, job == 'N' ? 7*minmn : 5*minmn*minmn + 5*minmn) + end + iwork = Array(BlasInt, 8*minmn) + info = Array(BlasInt, 1) + for i = 1:2 + if cmplx + ccall(($(string(gesdd)),liblapack), Void, + (Ptr{Uint8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, + Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$relty}, Ptr{BlasInt}, Ptr{BlasInt}), + &job, &m, &n, A, &stride(A,2), S, U, &max(1,stride(U,2)), VT, &max(1,stride(VT,2)), + work, &lwork, rwork, iwork, info) + else + ccall(($(string(gesdd)),liblapack), Void, + (Ptr{Uint8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, + Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{BlasInt}, Ptr{BlasInt}), + &job, &m, &n, A, &stride(A,2), S, U, &max(1,stride(U,2)), VT, &max(1,stride(VT,2)), + work, &lwork, iwork, info) + end + if info[1] != 0 throw(LAPACKException(info[1])) end + if lwork < 0 + lwork = blas_int(real(work[1])) + work = Array($elty, lwork) + end + end + if job == 'O' + if m >= n return (A, S, VT) + else return (U, S, A) + end + end + return (U, S, VT) + end + # SUBROUTINE DGESVD( JOBU, JOBVT, M, N, A, LDA, S, U, LDU, VT, LDVT, WORK, LWORK, INFO ) + # * .. Scalar Arguments .. + # CHARACTER JOBU, JOBVT + # INTEGER INFO, LDA, LDU, LDVT, LWORK, M, N + # * .. Array Arguments .. + # DOUBLE PRECISION A( LDA, * ), S( * ), U( LDU, * ), + # $ VT( LDVT, * ), WORK( * ) + function gesvd!(jobu::BlasChar, jobvt::BlasChar, A::StridedMatrix{$elty}) + chkstride1(A) + m, n = size(A) + minmn = min(m, n) + S = Array($relty, minmn) + U = Array($elty, jobu == 'A'? (m, m):(jobu == 'S'? (m, minmn) : (m, 0))) + VT = Array($elty, jobvt == 'A'? (n, n):(jobvt == 'S'? (minmn, n) : (n, 0))) + work = Array($elty, 1) + cmplx = iscomplex(A) + if cmplx; rwork = Array($relty, 5minmn); end + lwork = blas_int(-1) + info = Array(BlasInt, 1) + for i in 1:2 + if cmplx + ccall(($(string(gesvd)),liblapack), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{BlasInt}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, + Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, + Ptr{BlasInt}, Ptr{$relty}, Ptr{BlasInt}), + &jobu, &jobvt, &m, &n, A, &stride(A,2), S, U, &max(1,stride(U,2)), VT, &max(1,stride(VT,2)), + work, &lwork, rwork, info) + else + ccall(($(string(gesvd)),liblapack), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{BlasInt}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, + Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, + Ptr{BlasInt}, Ptr{BlasInt}), + &jobu, &jobvt, &m, &n, A, &stride(A,2), S, U, &max(1,stride(U,2)), VT, &max(1,stride(VT,2)), + work, &lwork, info) + end + if info[1] != 0 throw(LAPACKException(info[1])) end + if lwork < 0 + lwork = blas_int(real(work[1])) + work = Array($elty, lwork) + end + end + if jobu == 'O' return A, S, VT end + if jobvt == 'O' return U, S, A end + U, S, VT + end +# SUBROUTINE ZGGSVD( JOBU, JOBV, JOBQ, M, N, P, K, L, A, LDA, B, +# $ LDB, ALPHA, BETA, U, LDU, V, LDV, Q, LDQ, WORK, +# $ RWORK, IWORK, INFO ) +# * .. Scalar Arguments .. +# CHARACTER JOBQ, JOBU, JOBV +# INTEGER INFO, K, L, LDA, LDB, LDQ, LDU, LDV, M, N, P +# * .. +# * .. Array Arguments .. +# INTEGER IWORK( * ) +# DOUBLE PRECISION ALPHA( * ), BETA( * ), RWORK( * ) +# COMPLEX*16 A( LDA, * ), B( LDB, * ), Q( LDQ, * ), +# $ U( LDU, * ), V( LDV, * ), WORK( * ) + function ggsvd!(jobu::BlasChar, jobv::BlasChar, jobq::BlasChar, A::Matrix{$elty}, B::Matrix{$elty}) + m, n = size(A) + if size(B, 2) != n; throw(DimensionMismatch); end + p = size(B, 1) + k = Array(BlasInt, 1) + l = Array(BlasInt, 1) + lda = max(1,stride(A, 2)) + ldb = max(1,stride(B, 2)) + alpha = Array($relty, n) + beta = Array($relty, n) + ldu = max(1, m) + U = jobu == 'U' ? Array($elty, ldu, m) : Array($elty, 0) + ldv = max(1, p) + V = jobv == 'V' ? Array($elty, ldv, p) : Array($elty, 0) + ldq = max(1, n) + Q = jobq == 'Q' ? Array($elty, ldq, n) : Array($elty, 0) + work = Array($elty, max(3n, m, p) + n) + cmplx = iscomplex(A) + if cmplx; rwork = Array($relty, 2n); end + iwork = Array(BlasInt, n) + info = Array(BlasInt, 1) + if cmplx + ccall(($(string(ggsvd)),liblapack), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{Uint8}, Ptr{BlasInt}, + Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$relty}, Ptr{$relty}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{$relty}, Ptr{BlasInt}, Ptr{BlasInt}), + &jobu, &jobv, &jobq, &m, + &n, &p, k, l, + A, &lda, B, &ldb, + alpha, beta, U, &ldu, + V, &ldv, Q, &ldq, + work, rwork, iwork, info) + else + ccall(($(string(ggsvd)),liblapack), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{Uint8}, Ptr{BlasInt}, + Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$relty}, Ptr{$relty}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), + &jobu, &jobv, &jobq, &m, + &n, &p, k, l, + A, &lda, B, &ldb, + alpha, beta, U, &ldu, + V, &ldv, Q, &ldq, + work, iwork, info) + end + if info[1] != 0; throw(LAPACKException(info[1])); end + if m - k[1] - l[1] >= 0 + R = triu(A[1:k[1] + l[1],n - k[1] - l[1] + 1:n]) + else + R = triu([A[1:m, n - k[1] - l[1] + 1:n]; B[m - k[1] + 1:l[1], n - k[1] - l[1] + 1:n]]) + end + return U, V, Q, alpha, beta, k[1], l[1], R + end + end +end + +# (GT) General tridiagonal, decomposition, solver and direct solver +for (gtsv, gttrf, gttrs, elty) in + ((:dgtsv_,:dgttrf_,:dgttrs_,:Float64), + (:sgtsv_,:sgttrf_,:sgttrs_,:Float32), + (:zgtsv_,:zgttrf_,:zgttrs_,:Complex128), + (:cgtsv_,:cgttrf_,:cgttrs_,:Complex64)) + @eval begin + # SUBROUTINE DGTSV( N, NRHS, DL, D, DU, B, LDB, INFO ) + # .. Scalar Arguments .. + # INTEGER INFO, LDB, N, NRHS + # .. Array Arguments .. + # DOUBLE PRECISION B( LDB, * ), D( * ), DL( * ), DU( * ) + function gtsv!(dl::Vector{$elty}, d::Vector{$elty}, du::Vector{$elty}, + B::StridedVecOrMat{$elty}) + chkstride1(B) + n = length(d) + if length(dl) != n - 1 || length(du) != n - 1 + throw(DimensionMismatch("gtsv!")) + end + if n != size(B,1) throw(DimensionMismatch("gtsv!")) end + info = Array(BlasInt, 1) + ccall(($(string(gtsv)),liblapack), Void, + (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{$elty}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), + &n, &size(B,2), dl, d, du, B, &stride(B,2), info) + if info[1] != 0 throw(LAPACKException(info[1])) end + B + end + # SUBROUTINE DGTTRF( N, DL, D, DU, DU2, IPIV, INFO ) + # .. Scalar Arguments .. + # INTEGER INFO, N + # .. Array Arguments .. + # INTEGER IPIV( * ) + # DOUBLE PRECISION D( * ), DL( * ), DU( * ), DU2( * ) + function gttrf!(dl::Vector{$elty}, d::Vector{$elty}, du::Vector{$elty}) + n = length(d) + if length(dl) != (n-1) || length(du) != (n-1) + throw(DimensionMismatch("gttrf!")) + end + du2 = Array($elty, n-2) + ipiv = Array(BlasInt, n) + info = Array(BlasInt, 1) + ccall(($(string(gttrf)),liblapack), Void, + (Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{$elty}, Ptr{$elty}, + Ptr{BlasInt}, Ptr{BlasInt}), + &n, dl, d, du, du2, ipiv, info) + if info[1] != 0 throw(LAPACKException(info[1])) end + dl, d, du, du2, ipiv + end + # SUBROUTINE DGTTRS( TRANS, N, NRHS, DL, D, DU, DU2, IPIV, B, LDB, INFO ) + # .. Scalar Arguments .. + # CHARACTER TRANS + # INTEGER INFO, LDB, N, NRHS + # .. Array Arguments .. + # INTEGER IPIV( * ) + # DOUBLE PRECISION B( LDB, * ), D( * ), DL( * ), DU( * ), DU2( * ) + function gttrs!(trans::BlasChar, dl::Vector{$elty}, d::Vector{$elty}, + du::Vector{$elty}, du2::Vector{$elty}, ipiv::Vector{BlasInt}, + B::StridedVecOrMat{$elty}) + chkstride1(B) + n = length(d) + if length(dl) != n - 1 || length(du) != n - 1 throw(DimensionMismatch("gttrs!")) end + if n != size(B,1) throw(DimensionMismatch("gttrs!")) end + info = Array(BlasInt, 1) + ccall(($(string(gttrs)),liblapack), Void, + (Ptr{Uint8}, Ptr{BlasInt}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{$elty}, Ptr{$elty}, Ptr{$elty}, + Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), + &trans, &n, &size(B,2), dl, d, du, du2, ipiv, B, &stride(B,2), info) + if info[1] != 0 throw(LAPACKException(info[1])) end + B + end + end +end + +## (OR) orthogonal (or UN, unitary) matrices, extractors and multiplication +for (orglq, orgqr, ormlq, ormqr, gemqrt, elty) in + ((:dorglq_,:dorgqr_,:dormlq_,:dormqr_,:dgemqrt_,:Float64), + (:sorglq_,:sorgqr_,:sormlq_,:sormqr_,:sgemqrt_,:Float32), + (:zunglq_,:zungqr_,:zunmlq_,:zunmqr_,:zgemqrt_,:Complex128), + (:cunglq_,:cungqr_,:cunmlq_,:cunmqr_,:cgemqrt_,:Complex64)) + @eval begin + # SUBROUTINE DORGLQ( M, N, K, A, LDA, TAU, WORK, LWORK, INFO ) + # * .. Scalar Arguments .. + # INTEGER INFO, K, LDA, LWORK, M, N + # * .. Array Arguments .. + # DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * ) + function orglq!(A::StridedMatrix{$elty}, tau::Vector{$elty}, k::Integer) + chkstride1(A) + work = Array($elty, 1) + lwork = blas_int(-1) + info = Array(BlasInt, 1) + for i in 1:2 + ccall(($(string(orglq)),liblapack), Void, + (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, + Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), + &size(A,1), &size(A,2), &k, A, &stride(A,2), tau, work, &lwork, info) + if info[1] != 0 throw(LAPACKException(info[1])) end + if lwork < 0 + lwork = blas_int(real(work[1])) + work = Array($elty, lwork) + end + end + A + end + # SUBROUTINE DORGQR( M, N, K, A, LDA, TAU, WORK, LWORK, INFO ) + # * .. Scalar Arguments .. + # INTEGER INFO, K, LDA, LWORK, M, N + # * .. Array Arguments .. + # DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * ) + function orgqr!(A::StridedMatrix{$elty}, tau::Vector{$elty}) + chkstride1(A) + m, n = size(A) + k = length(tau) + if k > n throw(DimensionMismatch("Wrong number of reflectors")) end + work = Array($elty, 1) + lwork = blas_int(-1) + info = Array(BlasInt, 1) + for i in 1:2 + ccall(($(string(orgqr)),liblapack), Void, + (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, + Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), + &m, &n, &k, A, + &max(1,stride(A,2)), tau, work, &lwork, + info) + if info[1] != 0 throw(LAPACKException(info[1])) end + if lwork < 0 + lwork = blas_int(work[1]) + work = Array($elty, lwork) + end + end + A + end + # SUBROUTINE DORMLQ( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, + # WORK, LWORK, INFO ) + # .. Scalar Arguments .. + # CHARACTER SIDE, TRANS + # INTEGER INFO, K, LDA, LDC, LWORK, M, N + # .. Array Arguments .. + # DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ), WORK( * ) + function ormlq!(side::BlasChar, trans::BlasChar, A::StridedMatrix{$elty}, + k::Integer, tau::Vector{$elty}, C::StridedVecOrMat{$elty}) + chkstride1(A, C) + m = size(C, 1) + n = size(C, 2) # m, n = size(C) won't work if C is a Vector + work = Array($elty, 1) + lwork = blas_int(-1) + info = Array(BlasInt, 1) + for i in 1:2 + ccall(($(string(ormlq)),liblapack), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), + &side, &trans, &m, &n, &k, A, &stride(A,2), tau, + C, &stride(C,2), work, &lwork, info) + if info[1] != 0 throw(LAPACKException(info[1])) end + if lwork < 0 + lwork = blas_int(real(work[1])) + work = Array($elty, lwork) + end + end + C + end + # SUBROUTINE DORMQR( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, + # WORK, INFO ) + # .. Scalar Arguments .. + # CHARACTER SIDE, TRANS + # INTEGER INFO, K, LDA, LDC, M, N + # .. Array Arguments .. + # DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ), WORK( * ) + function ormqr!(side::BlasChar, trans::BlasChar, A::StridedMatrix{$elty}, + tau::Vector{$elty}, C::StridedVecOrMat{$elty}) + chkstride1(A, C) + m = size(C, 1) + n = size(C, 2) # m, n = size(C) won't work if C is a Vector + mA = size(A, 1) + k = length(tau) + if side == 'L' && m != mA throw(DimensionMismatch("")) end + if side == 'R' && n != mA throw(DimensionMismatch("")) end + if (side == 'L' && k > m) || (side == 'R' && k > n) throw(DimensionMismatch("Wrong number of reflectors")) end + work = Array($elty, 1) + lwork = blas_int(-1) + info = Array(BlasInt, 1) + for i in 1:2 + ccall(($(string(ormqr)),liblapack), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{BlasInt}, Ptr{BlasInt}, + Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{BlasInt}), + &side, &trans, &m, &n, + &k, A, &max(1,stride(A,2)), tau, + C, &max(1, stride(C,2)), work, &lwork, + info) + if info[1] != 0 throw(LAPACKException(info[1])) end + if lwork < 0 + lwork = blas_int(real(work[1])) + work = Array($elty, lwork) + end + end + C + end + function gemqrt!(side::Char, trans::Char, V::Matrix{$elty}, T::Matrix{$elty}, C::StridedVecOrMat{$elty}) + m = size(C, 1) + n = size(C, 2) + k = size(T, 1) + if side == 'L' + ldv = max(1, m) + wss = n*k + if m != size(V, 1) throw(DimensionMismatch("")) end + elseif side == 'R' + ldv = max(1, n) + wss = m*k + if n != size(V, 1) throw(DimensionMismatch("")) end + else + error("side must be either 'L' or 'R'") + end + ldc = max(1, stride(C, 2)) + work = Array($elty, wss) + info = Array(BlasInt, 1) + ccall(($(string(gemqrt)), liblapack), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{BlasInt}, Ptr{BlasInt}, + Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}), + &side, &trans, &m, &n, + &k, &k, V, &ldv, + T, &k, C, &ldc, + work, info) + if info[1] < 0 throw(LAPACKException(info[1])) end + return C + end + end +end + +# (PO) positive-definite symmetric matrices, +# Cholesky decomposition, solvers (direct and factored) and inverse. +for (posv, potrf, potri, potrs, pstrf, elty, rtyp) in + ((:dposv_,:dpotrf_,:dpotri_,:dpotrs_,:dpstrf_,:Float64,:Float64), + (:sposv_,:spotrf_,:spotri_,:spotrs_,:spstrf_,:Float32,:Float32), + (:zposv_,:zpotrf_,:zpotri_,:zpotrs_,:zpstrf_,:Complex128,:Float64), + (:cposv_,:cpotrf_,:cpotri_,:cpotrs_,:cpstrf_,:Complex64,:Float32)) + @eval begin + ## Caller should check if returned info[1] is zero, + ## positive values indicate indefiniteness + # SUBROUTINE DPOSV( UPLO, N, NRHS, A, LDA, B, LDB, INFO ) + #* .. Scalar Arguments .. + # CHARACTER UPLO + # INTEGER INFO, LDA, LDB, N, NRHS + # .. Array Arguments .. + # DOUBLE PRECISION A( LDA, * ), B( LDB, * ) + function posv!(uplo::BlasChar, A::StridedMatrix{$elty}, B::StridedVecOrMat{$elty}) + chkstride1(A, B) + chksquare(A) + n = size(A,1) + if size(B,1) != n throw(DimensionMismatch("posv!")) end + info = Array(BlasInt, 1) + ccall(($(string(posv)),liblapack), Void, + (Ptr{Uint8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), + &uplo, &n, &size(B,2), A, &stride(A,2), B, &stride(B,2), info) + if info[1] < 0 throw(LAPACKException(info[1])) end + A, B, info[1] + end + ## Caller should check if returned info[1] is zero, + ## positive values indicate indefiniteness + # SUBROUTINE DPOTRF( UPLO, N, A, LDA, INFO ) + # * .. Scalar Arguments .. + # CHARACTER UPLO + # INTEGER INFO, LDA, N + # * .. Array Arguments .. + # DOUBLE PRECISION A( LDA, * ) + function potrf!(uplo::BlasChar, A::StridedMatrix{$elty}) + chkstride1(A) + chksquare(A) + info = Array(BlasInt, 1) + ccall(($(string(potrf)),liblapack), Void, + (Ptr{Uint8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), + &uplo, &size(A,1), A, &stride(A,2), info) + if info[1] < 0 throw(LAPACKException(info[1])) end + A, info[1] + end + ## Caller should check if returned info[1] is zero, + ## positive values indicate singularity + # SUBROUTINE DPOTRI( UPLO, N, A, LDA, INFO ) + # .. Scalar Arguments .. + # CHARACTER UPLO + # INTEGER INFO, LDA, N + # .. Array Arguments .. + # DOUBLE PRECISION A( LDA, * ) + function potri!(uplo::BlasChar, A::StridedMatrix{$elty}) + chkstride1(A) + info = Array(BlasInt, 1) + ccall(($(string(potri)),liblapack), Void, + (Ptr{Uint8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), + &uplo, &size(A,1), A, &stride(A,2), info) + if info[1] < 0 throw(LAPACKException(info[1])) end + A, info[1] + end + # SUBROUTINE DPOTRS( UPLO, N, NRHS, A, LDA, B, LDB, INFO ) + # .. Scalar Arguments .. + # CHARACTER UPLO + # INTEGER INFO, LDA, LDB, N, NRHS + # .. Array Arguments .. + # DOUBLE PRECISION A( LDA, * ), B( LDB, * ) + function potrs!(uplo::BlasChar, A::StridedMatrix{$elty}, B::StridedVecOrMat{$elty}) + chkstride1(A, B) + chksquare(A) + n = size(A,2) + if size(B,1) != n throw(DimensionMismatch("Left and right hand side does not fit")) end + info = Array(BlasInt, 1) + ccall(($(string(potrs)),liblapack), Void, + (Ptr{Uint8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), + &uplo, &n, &size(B,2), A, &stride(A,2), B, &stride(B,2), info) + if info[1] != 0 throw(LAPACKException(info[1])) end + B + end + # SUBROUTINE DPSTRF( UPLO, N, A, LDA, PIV, RANK, TOL, WORK, INFO ) + # .. Scalar Arguments .. + # DOUBLE PRECISION TOL + # INTEGER INFO, LDA, N, RANK + # CHARACTER UPLO + # .. Array Arguments .. + # DOUBLE PRECISION A( LDA, * ), WORK( 2*N ) + # INTEGER PIV( N ) + function pstrf!(uplo::BlasChar, A::StridedMatrix{$elty}, tol::Real) + chkstride1(A) + chksquare(A) + n = size(A,1) + piv = Array(BlasInt, n) + rank = Array(BlasInt, 1) + work = Array($rtyp, 2n) + info = Array(BlasInt, 1) + ccall(($(string(pstrf)),liblapack), Void, + (Ptr{Uint8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}, + Ptr{BlasInt}, Ptr{$rtyp}, Ptr{$rtyp}, Ptr{BlasInt}), + &uplo, &n, A, &stride(A,2), piv, rank, &tol, work, info) + if info[1] < 0 throw(LAPACKException(info[1])) end + A, piv, rank[1], info[1] + end + end +end + +## (PT) positive-definite, symmetric, tri-diagonal matrices +## Direct solvers for general tridiagonal and symmetric positive-definite tridiagonal +for (ptsv, pttrf, pttrs, elty, relty) in + ((:dptsv_,:dpttrf_,:dpttrs_,:Float64,:Float64), + (:sptsv_,:spttrf_,:spttrs_,:Float32,:Float32), + (:zptsv_,:zpttrf_,:zpttrs_,:Complex128,:Float64), + (:cptsv_,:cpttrf_,:cpttrs_,:Complex64,:Float32)) + @eval begin + # SUBROUTINE DPTSV( N, NRHS, D, E, B, LDB, INFO ) + # .. Scalar Arguments .. + # INTEGER INFO, LDB, N, NRHS + # .. Array Arguments .. + # DOUBLE PRECISION B( LDB, * ), D( * ), E( * ) + function ptsv!(D::Vector{$relty}, E::Vector{$elty}, B::StridedVecOrMat{$elty}) + chkstride1(B) + n = length(D) + if length(E) != n - 1 || n != size(B,1) throw(DimensionMismatch("ptsv!")) end + info = Array(BlasInt, 1) + ccall(($(string(ptsv)),liblapack), Void, + (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$relty}, Ptr{$elty}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), + &n, &size(B,2), D, E, B, &stride(B,2), info) + if info[1] != 0 throw(LAPACKException(info[1])) end + B + end + # SUBROUTINE DPTTRF( N, D, E, INFO ) + # .. Scalar Arguments .. + # INTEGER INFO, N + # .. Array Arguments .. + # DOUBLE PRECISION D( * ), E( * ) + function pttrf!(D::Vector{$relty}, E::Vector{$elty}) + n = length(D) + if length(E) != (n-1) throw(DimensionMismatch("pttrf!")) end + info = Array(BlasInt, 1) + ccall(($(string(pttrf)),liblapack), Void, + (Ptr{BlasInt}, Ptr{$relty}, Ptr{$elty}, Ptr{BlasInt}), + &n, D, E, info) + if info[1] != 0 throw(LAPACKException(info[1])) end + D, E + end + end +end +for (pttrs, elty, relty) in + ((:dpttrs_,:Float64,:Float64), + (:spttrs_,:Float32,:Float32)) + @eval begin + # SUBROUTINE DPTTRS( N, NRHS, D, E, B, LDB, INFO ) + # .. Scalar Arguments .. + # INTEGER INFO, LDB, N, NRHS + # .. Array Arguments .. + # DOUBLE PRECISION B( LDB, * ), D( * ), E( * ) + function pttrs!(D::Vector{$relty}, E::Vector{$elty}, B::StridedVecOrMat{$elty}) + chkstride1(B) + n = length(D) + if length(E) != (n-1) || size(B,1) != n throw(DimensionMismatch("pttrs!")) end + info = Array(BlasInt, 1) + ccall(($(string(pttrs)),liblapack), Void, + (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$relty}, Ptr{$elty}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), + &n, &size(B,2), D, E, B, &stride(B,2), info) + if info[1] != 0 throw(LAPACKException(info[1])) end + B + end + end +end +for (pttrs, elty, relty) in + ((:zpttrs_,:Complex128,:Float64), + (:cpttrs_,:Complex64,:Float32)) + @eval begin +# SUBROUTINE ZPTTRS( UPLO, N, NRHS, D, E, B, LDB, INFO ) +# * .. Scalar Arguments .. +# CHARACTER UPLO +# INTEGER INFO, LDB, N, NRHS +# * .. +# * .. Array Arguments .. +# DOUBLE PRECISION D( * ) +# COMPLEX*16 B( LDB, * ), E( * ) + function pttrs!(uplo::BlasChar, D::Vector{$relty}, E::Vector{$elty}, B::StridedVecOrMat{$elty}) + chkstride1(B) + n = length(D) + if length(E) != (n-1) || size(B,1) != n throw(DimensionMismatch("pttrs!")) end + info = Array(BlasInt, 1) + ccall(($(string(pttrs)),liblapack), Void, + (Ptr{Uint8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$relty}, Ptr{$elty}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), + &uplo, &n, &size(B,2), D, E, B, &stride(B,2), info) + if info[1] != 0 throw(LAPACKException(info[1])) end + B + end + end +end + +## (TR) triangular matrices: solver and inverse +for (trtri, trtrs, elty) in + ((:dtrtri_,:dtrtrs_,:Float64), + (:strtri_,:strtrs_,:Float32), + (:ztrtri_,:ztrtrs_,:Complex128), + (:ctrtri_,:ctrtrs_,:Complex64)) + @eval begin + # SUBROUTINE DTRTRI( UPLO, DIAG, N, A, LDA, INFO ) + #* .. Scalar Arguments .. + # CHARACTER DIAG, UPLO + # INTEGER INFO, LDA, N + # .. Array Arguments .. + # DOUBLE PRECISION A( LDA, * ) + function trtri!(uplo::BlasChar, diag::BlasChar, A::StridedMatrix{$elty}) + chkstride1(A) + m, n = size(A) + if m != n throw(DimensionMismatch("")) end + lda = stride(A, 2) + info = Array(BlasInt, 1) + ccall(($(string(trtri)),liblapack), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{BlasInt}), + &uplo, &diag, &n, A, &lda, info) + if info[1] < 0 throw(LAPACKException(info[1])) end + A, info[1] + end + # SUBROUTINE DTRTRS( UPLO, TRANS, DIAG, N, NRHS, A, LDA, B, LDB, INFO ) + # * .. Scalar Arguments .. + # CHARACTER DIAG, TRANS, UPLO + # INTEGER INFO, LDA, LDB, N, NRHS + # * .. Array Arguments .. + # DOUBLE PRECISION A( LDA, * ), B( LDB, * ) + function trtrs!(uplo::BlasChar, trans::BlasChar, diag::BlasChar, + A::StridedMatrix{$elty}, B::StridedVecOrMat{$elty}) + chkstride1(A) + chksquare(A) + n = size(A,2) + if size(B,1) != n throw(DimensionMismatch("trtrs!")) end + info = Array(BlasInt, 1) + ccall(($(string(trtrs)),liblapack), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{Uint8}, Ptr{BlasInt}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), + &uplo, &trans, &diag, &n, &size(B,2), A, &stride(A,2), + B, &stride(B,2), info) + if info[1] < 0 throw(LAPACKException(info[1])) end + B, info[1] + end + end +end + +## (ST) Symmetric tridiagonal - eigendecomposition +for (stev, stebz, stegr, stein, elty) in + ((:dstev_,:dstebz_,:dstegr_,:dstein_,:Float64), + (:sstev_,:sstebz_,:sstegr_,:sstein_,:Float32) +# , (:zstev_,:Complex128) Need to rewrite for ZHEEV, rwork, etc. +# , (:cstev_,:Complex64) + ) + @eval begin + #* DSTEV computes all eigenvalues and, optionally, eigenvectors of a + #* real symmetric tridiagonal matrix A. + function stev!(job::BlasChar, dv::Vector{$elty}, ev::Vector{$elty}) + n = length(dv) + if length(ev) != (n-1) throw(DimensionMismatch("stev!")) end + Zmat = Array($elty, (n, job != 'N' ? n : 0)) + work = Array($elty, max(1, 2n-2)) + info = Array(BlasInt, 1) + ccall(($(string(stev)),liblapack), Void, + (Ptr{Uint8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{$elty}, + Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}), + &job, &n, dv, ev, Zmat, &n, work, info) + if info[1] != 0 throw(LAPACKException(info[1])) end + dv, Zmat + end + #* DSTEBZ computes the eigenvalues of a symmetric tridiagonal + #* matrix T. The user may ask for all eigenvalues, all eigenvalues + #* in the half-open interval (VL, VU], or the IL-th through IU-th + #* eigenvalues. + function stebz!(range::Char, order::Char, vl::$elty, vu::$elty, il::Integer, iu::Integer, abstol::Real, dv::Vector{$elty}, ev::Vector{$elty}) + n = length(dv) + if length(ev) != (n-1) throw(DimensionMismatch("stebz!")) end + m = Array(BlasInt,1) + nsplit = Array(BlasInt,1) + w = Array($elty, n) + tmp = 0.0 + iblock = Array(BlasInt,n) + isplit = Array(BlasInt,n) + work = Array($elty, 4*n) + iwork = Array(BlasInt,3*n) + info = Array(BlasInt, 1) + ccall(($(string(stebz)),liblapack), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{BlasInt}, Ptr{$elty}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, + Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, + Ptr{BlasInt}, Ptr{BlasInt}), + &range, &order, &n, &vl, + &vu, &il, &iu, &abstol, + dv, ev, m, nsplit, + w, iblock, isplit, work, + iwork, info) + if info[1] != 0 throw(LAPACKException(info[1])) end + w[1:m[1]], iblock[1:m[1]], isplit[1:nsplit[1]], info[1] + end + #* DSTEGR computes selected eigenvalues and, optionally, eigenvectors + #* of a real symmetric tridiagonal matrix T. Any such unreduced matrix has + #* a well defined set of pairwise different real eigenvalues, the corresponding + #* real eigenvectors are pairwise orthogonal. + #* + #* The spectrum may be computed either completely or partially by specifying + #* either an interval (VL,VU] or a range of indices IL:IU for the desired + #* eigenvalues. + function stegr!(jobz::BlasChar, range::BlasChar, dv::Vector{$elty}, ev::Vector{$elty}, vl::Real, vu::Real, il::Integer, iu::Integer, abstol::Real) + n = length(dv) + if length(ev) != (n-1) throw(DimensionMismatch("stebz!")) end + eev = [ev, zero($elty)] + m = Array(BlasInt, 1) + w = Array($elty, n) + ldz = jobz == 'N' ? 1 : n + Z = Array($elty, ldz, n) + isuppz = Array(BlasInt, 2n) + work = Array($elty, 1) + lwork = -one(BlasInt) + iwork = Array(BlasInt, 1) + liwork = -one(BlasInt) + info = Array(BlasInt, 1) + for i = 1:2 + ccall(($(string(stegr)), liblapack), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{BlasInt}, Ptr{$elty}, + Ptr{$elty}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, + Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}), + &jobz, &range, &n, dv, + eev, &vl, &vu, &il, + &iu, &abstol, m, w, + Z, &ldz, isuppz, work, + &lwork, iwork, &liwork, info) + if i == 1 + lwork = int(work[1]) + work = Array($elty, lwork) + liwork = iwork[1] + iwork = Array(BlasInt, liwork) + end + end + if info[1] != 0 throw(LAPACKException(info[1])) end + return w[1:m[1]], Z[:,1:m[1]] + end + #* DSTEIN computes the eigenvectors of a real symmetric tridiagonal + #* matrix T corresponding to specified eigenvalues, using inverse + #* iteration. + # SUBROUTINE DSTEIN( N, D, E, M, W, IBLOCK, ISPLIT, Z, LDZ, WORK, + # $ IWORK, IFAIL, INFO ) + # We allow the user to specify exactly which eigenvectors to get by + # specifying the eigenvalues (which may be approximate) via w_in + function stein!(dv::Vector{$elty}, ev_in::Vector{$elty}, w_in::Vector{$elty}, iblock_in::Vector{BlasInt}, isplit_in::Vector{BlasInt}) + n = length(dv) + if length(ev_in) != (n-1) throw(DimensionMismatch("stein!")) end + ev = [ev_in; zeros($elty,1)] + ldz = n #Leading dimension + #Number of eigenvalues to find + 1<=length(w_in)<=n ? (m=length(w_in)) : throw(DimensionMismatch("stein!")) + #If iblock and isplit are invalid input, assume worst-case block paritioning, + # i.e. set the block scheme to be the entire matrix + iblock = Array(BlasInt,n) + isplit = Array(BlasInt,n) + w = Array($elty,n) + if length(iblock_in) < m #Not enough block specifications + iblock[1:m] = ones(BlasInt, m) + w[1:m] = sort(w_in) + else + iblock[1:m] = iblock_in + w[1:m] = w_in #Assume user has sorted the eigenvalues properly + end + if length(isplit_in) < 1 #Not enough block specifications + isplit[1] = n + else + isplit[1:length(isplit_in)] = isplit_in + end + + z = Array($elty,(n,m)) + work = Array($elty, 5*n) + iwork = Array(BlasInt,n) + ifail = Array(BlasInt,m) + info = Array(BlasInt,1) + + ccall(($(string(stein)),liblapack), Void, + (Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, + Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}, + Ptr{BlasInt}), + &n, dv, ev, &m, w, iblock, isplit, z, &ldz, work, iwork, ifail, info) + + if (info[1] < 0) throw(LAPACKException(info[1])) end + (z, ifail, info[1]) + end + end +end +stegr!(jobz::BlasChar, dv::Vector, ev::Vector) = stegr!(jobz, 'A', dv, ev, 0.0, 0.0, 0, 0, -1.0) +stegr!(dv::Vector, ev::Vector) = stegr!('N', 'A', dv, ev, 0.0, 0.0, 0, 0, -1.0) + +# Allow user to skip specification of iblock and isplit +stein!(dv::Vector, ev::Vector, w_in::Vector)=stein!(dv, ev, w_in, zeros(BlasInt,0), zeros(BlasInt,0)) +# Allow user to specify just one eigenvector to get in stein! +stein!(dv::Vector, ev::Vector, eval::Real)=stein!(dv, ev, [eval], zeros(BlasInt,0), zeros(BlasInt,0)) + +## (SY) symmetric matrices - eigendecomposition, Bunch-Kaufman decomposition, +## solvers (direct and factored) and inverse. +for (syconv, syev, sysv, sytrf, sytri, sytrs, elty, relty) in + ((:dsyconv_,:dsyev_,:dsysv_,:dsytrf_,:dsytri_,:dsytrs_,:Float64, :Float64), + (:ssyconv_,:ssyev_,:ssysv_,:ssytrf_,:ssytri_,:ssytrs_,:Float32, :Float32), + (:zheconv_,:zheev_,:zhesv_,:zhetrf_,:zhetri_,:zhetrs_,:Complex128, :Float64), + (:checonv_,:cheev_,:chesv_,:chetrf_,:chetri_,:chetrs_,:Complex64, :Float32)) + @eval begin + # SUBROUTINE DSYCONV( UPLO, WAY, N, A, LDA, IPIV, WORK, INFO ) + # * .. Scalar Arguments .. + # CHARACTER UPLO, WAY + # INTEGER INFO, LDA, N + # * .. Array Arguments .. + # INTEGER IPIV( * ) + # DOUBLE PRECISION A( LDA, * ), WORK( * ) + function syconv!(uplo::BlasChar, A::StridedMatrix{$elty}, ipiv::Vector{BlasInt}) + chkstride1(A) + chksquare(A) + n = size(A,1) + work = Array($elty, n) + info = Array(BlasInt, 1) + ccall(($(string(syconv)),liblapack), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}), + &uplo, &'C', &n, A, &stride(A,2), ipiv, work, info) + if info[1] != 0 throw(LAPACKException(info[1])) end + A, work + end + # SUBROUTINE DSYEV( JOBZ, UPLO, N, A, LDA, W, WORK, LWORK, INFO ) + # * .. Scalar Arguments .. + # CHARACTER JOBZ, UPLO + # INTEGER INFO, LDA, LWORK, N + # * .. Array Arguments .. + # DOUBLE PRECISION A( LDA, * ), W( * ), WORK( * ) + function syev!(jobz::BlasChar, uplo::BlasChar, A::StridedMatrix{$elty}) + chkstride1(A) + chksquare(A) + cmplx = iscomplex(A) + n = size(A, 1) + W = Array($relty, n) + work = Array($elty, 1) + lwork = blas_int(-1) + if cmplx + rwork = Array($relty, max(1, 3n-2)) + end + info = Array(BlasInt, 1) + for i in 1:2 + if cmplx + ccall(($(string(syev)),liblapack), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$relty}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$relty}, Ptr{BlasInt}), + &jobz, &uplo, &n, A, &stride(A,2), W, work, &lwork, rwork, info) + else + ccall(($(string(syev)),liblapack), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$relty}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), + &jobz, &uplo, &n, A, &stride(A,2), W, work, &lwork, info) + end + if info[1] != 0 throw(LAPACKException(info[1])) end + if lwork < 0 + lwork = blas_int(real(work[1])) + work = Array($elty, lwork) + end + end + jobz == 'V' ? (W, A) : W + end + # SUBROUTINE DSYSV( UPLO, N, NRHS, A, LDA, IPIV, B, LDB, WORK, + # LWORK, INFO ) + # .. Scalar Arguments .. + # CHARACTER UPLO + # INTEGER INFO, LDA, LDB, LWORK, N, NRHS + # .. Array Arguments .. + # INTEGER IPIV( * ) + # DOUBLE PRECISION A( LDA, * ), B( LDB, * ), WORK( * ) + function sysv!(uplo::BlasChar, A::StridedMatrix{$elty}, B::StridedVecOrMat{$elty}) + chkstride1(A,B) + chksquare(A) + n = size(A,1) + if n != size(B,1) throw(DimensionMismatch("sysv!")) end + ipiv = Array(BlasInt, n) + work = Array($elty, 1) + lwork = blas_int(-1) + info = Array(BlasInt, 1) + for i in 1:2 + ccall(($(string(sysv)),liblapack), Void, + (Ptr{Uint8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), + &uplo, &n, &size(B,2), A, &stride(A,2), ipiv, B, &stride(B,2), + work, &lwork, info) + if info[1] < 0 throw(LAPACKException(info[1])) end + if lwork < 0 + lwork = blas_int(real(work[1])) + work = Array($elty, lwork) + end + end + B, A, ipiv, info[1] + end + # SUBROUTINE DSYTRF( UPLO, N, A, LDA, IPIV, WORK, LWORK, INFO ) + # * .. Scalar Arguments .. + # CHARACTER UPLO + # INTEGER INFO, LDA, LWORK, N + # * .. Array Arguments .. + # INTEGER IPIV( * ) + # DOUBLE PRECISION A( LDA, * ), WORK( * ) + function sytrf!(uplo::BlasChar, A::StridedMatrix{$elty}) + chkstride1(A) + chksquare(A) + n = size(A,1) + ipiv = Array(BlasInt, n) + work = Array($elty, 1) + lwork = blas_int(-1) + info = Array(BlasInt, 1) + for i in 1:2 + ccall(($(string(sytrf)),liblapack), Void, + (Ptr{Uint8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), + &uplo, &n, A, &stride(A,2), ipiv, work, &lwork, info) + if info[1] < 0 throw(LAPACKException(info[1])) end + if info[1] > 0 throw(SingularException(info[1])) end + if lwork < 0 + lwork = blas_int(real(work[1])) + work = Array($elty, lwork) + end + end + A, ipiv, info + end + # SUBROUTINE DSYTRI2( UPLO, N, A, LDA, IPIV, WORK, LWORK, INFO ) + # * .. Scalar Arguments .. + # CHARACTER UPLO + # INTEGER INFO, LDA, LWORK, N + # * .. Array Arguments .. + # INTEGER IPIV( * ) + # DOUBLE PRECISION A( LDA, * ), WORK( * ) +# function sytri!(uplo::BlasChar, A::StridedMatrix{$elty}, ipiv::Vector{BlasInt}) +# chkstride1(A) +# chksquare(A) +# n = size(A,1) +# work = Array($elty, 1) +# lwork = blas_int(-1) +# info = Array(BlasInt, 1) +# for i in 1:2 +# ccall(($(string(sytri)),liblapack), Void, +# (Ptr{Uint8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, +# Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), +# &uplo, &n, A, &stride(A,2), ipiv, work, &lwork, info) +# if info[1] != 0 throw(LAPACKException(info[1])) end +# if lwork < 0 +# lwork = blas_int(real(work[1])) +# work = Array($elty, lwork) +# end +# end +# A +# end + # SUBROUTINE DSYTRI( UPLO, N, A, LDA, IPIV, WORK, INFO ) + # .. Scalar Arguments .. + # CHARACTER UPLO + # INTEGER INFO, LDA, N + # .. Array Arguments .. + # INTEGER IPIV( * ) + # DOUBLE PRECISION A( LDA, * ), WORK( * ) + function sytri!(uplo::BlasChar, A::StridedMatrix{$elty}, ipiv::Vector{BlasInt}) + chkstride1(A) + chksquare(A) + n = size(A,1) + work = Array($elty, n) + info = Array(BlasInt, 1) + ccall(($(string(sytri)),liblapack), Void, + (Ptr{Uint8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}), + &uplo, &n, A, &stride(A,2), ipiv, work, info) + if info[1] != 0 throw(LAPACKException(info[1])) end + A + end + # SUBROUTINE DSYTRS( UPLO, N, NRHS, A, LDA, IPIV, B, LDB, INFO ) + # + # .. Scalar Arguments .. + # CHARACTER UPLO + # INTEGER INFO, LDA, LDB, N, NRHS + # .. Array Arguments .. + # INTEGER IPIV( * ) + # DOUBLE PRECISION A( LDA, * ), B( LDB, * ) + function sytrs!(uplo::BlasChar, A::StridedMatrix{$elty}, + ipiv::Vector{BlasInt}, B::StridedVecOrMat{$elty}) + chkstride1(A,B) + chksquare(A) + n = size(A,1) + if n != size(B,1) throw(DimensionMismatch("sytrs!")) end + info = Array(BlasInt, 1) + ccall(($(string(sytrs)),liblapack), Void, + (Ptr{Uint8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), + &uplo, &n, &size(B,2), A, &stride(A,2), ipiv, B, &stride(B,2), info) + if info[1] != 0 throw(LAPACKException(info[1])) end + B + end + end +end + + + +#Find the leading dimension +ld = x->max(1,stride(x,2)) +function validate(uplo) + if !(uplo=='U' || uplo=='L') + error(string("Invalid UPLO: must be 'U' or 'L' but you said", uplo)) + end +end +## (BD) Bidiagonal matrices - singular value decomposition +for (bdsqr, relty, elty) in + ((:dbdsqr_,:Float64,:Float64), + (:sbdsqr_,:Float32,:Float32), + (:zbdsqr_,:Float64,:Complex128), + (:cbdsqr_,:Float32,:Complex64)) + @eval begin + #*> DBDSQR computes the singular values and, optionally, the right and/or + #*> left singular vectors from the singular value decomposition (SVD) of + #*> a real N-by-N (upper or lower) bidiagonal matrix B using the implicit + #*> zero-shift QR algorithm. + function bdsqr!(uplo::BlasChar, d::Vector{$relty}, e_::Vector{$relty}, + vt::StridedMatrix{$elty}, u::StridedMatrix{$elty}, c::StridedMatrix{$elty}) + + validate(uplo) + n = length(d) + if length(e_) != n-1 throw(DimensionMismatch("bdsqr!")) end + ncvt, nru, ncc = size(vt)[2], size(u)[1], size(c)[2] + ldvt, ldu, ldc = ld(vt), ld(u), ld(c) + work=Array($elty, 4n) + info=Array(BlasInt,1) + + ccall(($(string(bdsqr)),liblapack), Void, + (Ptr{BlasChar}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, + Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}), + &uplo, &n, ncvt, &nru, &ncc, + d, e_, vt, &ldvt, u, + &ldu, c, &ldc, work, info) + + if info[1] != 0 throw(LAPACKException(info[1])) end + d, vt, u, c #singular values in descending order, P**T * VT, U * Q, Q**T * C + end + end +end + +#Defined only for real types +for (bdsdc, elty) in + ((:dbdsdc_,:Float64), + (:sbdsdc_,:Float32)) + @eval begin + #* DBDSDC computes the singular value decomposition (SVD) of a real + #* N-by-N (upper or lower) bidiagonal matrix B: B = U * S * VT, + #* using a divide and conquer method + #* .. Scalar Arguments .. + # CHARACTER COMPQ, UPLO + # INTEGER INFO, LDU, LDVT, N + #* .. + #* .. Array Arguments .. + # INTEGER IQ( * ), IWORK( * ) + # DOUBLE PRECISION D( * ), E( * ), Q( * ), U( LDU, * ), + # $ VT( LDVT, * ), WORK( * ) + function bdsdc!(uplo::BlasChar, compq::BlasChar, d::Vector{$elty}, e_::Vector{$elty}) + validate(uplo) + n, ldiq, ldq, ldu, ldvt = length(d), 1, 1, 1, 1 + if compq == 'N' + lwork = 4n + elseif compq == 'P' + warn("COMPQ='P' is not tested") + #TODO turn this into an actual LAPACK call + #smlsiz=ilaenv(9, $elty==:Float64 ? 'dbdsqr' : 'sbdsqr', string(uplo, compq), n,n,n,n) + smlsiz=100 #For now, completely overkill + ldq = n*(11+2*smlsiz+8*int(log((n/(smlsiz+1)))/log(2))) + ldiq = n*(3+3*int(log(n/(smlsiz+1))/log(2))) + lwork = 6n + elseif compq == 'I' + ldvt=ldu=max(1, n) + lwork=3*n^2 + 4n + else + error(string("Invalid COMPQ. Valid choices are 'N', 'P' or 'I' but you said '",compq,"'")) + end + u = Array($elty, (ldu, n)) + vt= Array($elty, (ldvt, n)) + q = Array($elty, ldq) + iq= Array(BlasInt, ldiq) + work =Array($elty, lwork) + iwork=Array(BlasInt, 7n) + info =Array(BlasInt, 1) + ccall(($(string(bdsdc)),liblapack), Void, + (Ptr{BlasChar}, Ptr{BlasChar}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), + &uplo, &compq, &n, d, e_, + u, &ldu, vt, &ldvt, + q, iq, work, iwork, info) + + if info[1] != 0 throw(LAPACKException(info[1])) end + if compq == 'N' + d + elseif compq == 'P' + d, q, iq + else #compq == 'I' + u, d, vt' + end + end + end +end + + + +# New symmetric eigen solver +for (syevr, elty) in + ((:dsyevr_,:Float64), + (:ssyevr_,:Float32)) + @eval begin + function syevr!(jobz::BlasChar, range::BlasChar, uplo::BlasChar, A::StridedMatrix{$elty}, vl::FloatingPoint, vu::FloatingPoint, il::Integer, iu::Integer, abstol::FloatingPoint) + # SUBROUTINE DSYEVR( JOBZ, RANGE, UPLO, N, A, LDA, VL, VU, IL, IU, + # $ ABSTOL, M, W, Z, LDZ, ISUPPZ, WORK, LWORK, + # $ IWORK, LIWORK, INFO ) + # * .. Scalar Arguments .. + # CHARACTER JOBZ, RANGE, UPLO + # INTEGER IL, INFO, IU, LDA, LDZ, LIWORK, LWORK, M, N + # DOUBLE PRECISION ABSTOL, VL, VU + # * .. + # * .. Array Arguments .. + # INTEGER ISUPPZ( * ), IWORK( * ) + # DOUBLE PRECISION A( LDA, * ), W( * ), WORK( * ), Z( LDZ, * ) + chkstride1(A) + chksquare(A) + n = size(A, 2) + lda = max(1,stride(A,2)) + m = Array(BlasInt, 1) + w = Array($elty, n) + if jobz == 'N' + ldz = 1 + Z = Array($elty, ldz, 0) + elseif jobz == 'V' + ldz = n + Z = Array($elty, ldz, n) + else + error("jobz must be 'N' of 'V'") + end + isuppz = Array(BlasInt, 2*n) + work = Array($elty, 1) + lwork = blas_int(-1) + iwork = Array(BlasInt, 1) + liwork = blas_int(-1) + info = Array(BlasInt, 1) + for i in 1:2 + ccall(($(string(syevr)),liblapack), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{Uint8}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, + Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, + Ptr{BlasInt}), + &jobz, &range, &uplo, &n, + A, &lda, &vl, &vu, + &il, &iu, &abstol, m, + w, Z, &ldz, isuppz, + work, &lwork, iwork, &liwork, + info) + if info[1] != 0 throw(LAPACKException(info[1])) end + if lwork < 0 + lwork = blas_int(work[1]) + work = Array($elty, lwork) + liwork = iwork[1] + iwork = Array(BlasInt, liwork) + end + end + return w[1:m[1]], Z[:,1:(jobz == 'V' ? m[1] : 0)] + end + end +end +for (syevr, elty, relty) in + ((:zheevr_,:Complex128,:Float64), + (:cheevr_,:Complex64,:Float32)) + @eval begin + function syevr!(jobz::BlasChar, range::BlasChar, uplo::BlasChar, A::StridedMatrix{$elty}, vl::FloatingPoint, vu::FloatingPoint, il::Integer, iu::Integer, abstol::FloatingPoint) +# SUBROUTINE ZHEEVR( JOBZ, RANGE, UPLO, N, A, LDA, VL, VU, IL, IU, +# $ ABSTOL, M, W, Z, LDZ, ISUPPZ, WORK, LWORK, +# $ RWORK, LRWORK, IWORK, LIWORK, INFO ) +# * .. Scalar Arguments .. +# CHARACTER JOBZ, RANGE, UPLO +# INTEGER IL, INFO, IU, LDA, LDZ, LIWORK, LRWORK, LWORK, +# $ M, N +# DOUBLE PRECISION ABSTOL, VL, VU +# * .. +# * .. Array Arguments .. +# INTEGER ISUPPZ( * ), IWORK( * ) +# DOUBLE PRECISION RWORK( * ), W( * ) +# COMPLEX*16 A( LDA, * ), WORK( * ), Z( LDZ, * ) + chkstride1(A) + chksquare(A) + n = size(A, 2) + lda = max(1,stride(A,2)) + m = Array(BlasInt, 1) + w = Array($relty, n) + if jobz == 'N' + ldz = 1 + Z = Array($elty, ldz, 0) + elseif jobz == 'V' + ldz = n + Z = Array($elty, ldz, n) + else + error("jobz must be 'N' of 'V'") + end + isuppz = Array(BlasInt, 2*n) + work = Array($elty, 1) + lwork = blas_int(-1) + rwork = Array($relty, 1) + lrwork = blas_int(-1) + iwork = Array(BlasInt, 1) + liwork = blas_int(-1) + info = Array(BlasInt, 1) + for i in 1:2 + ccall(($(string(syevr)),liblapack), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{Uint8}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, + Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{$relty}, Ptr{BlasInt}, + Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}), + &jobz, &range, &uplo, &n, + A, &lda, &vl, &vu, + &il, &iu, &abstol, m, + w, Z, &ldz, isuppz, + work, &lwork, rwork, &lrwork, + iwork, &liwork, info) + if info[1] != 0 throw(LAPACKException(info[1])) end + if lwork < 0 + lwork = blas_int(real(work[1])) + work = Array($elty, lwork) + lrwork = blas_int(rwork[1]) + rwork = Array($relty, lrwork) + liwork = iwork[1] + iwork = Array(BlasInt, liwork) + end + end + return w[1:m[1]], Z[:,1:(jobz == 'V' ? m[1] : 0)] + end + end +end +syevr!(jobz::Char, A::StridedMatrix) = syevr!(jobz, 'A', 'U', A, 0.0, 0.0, 0, 0, -1.0) + +# Estimate condition number +for (gecon, elty) in + ((:dgecon_,:Float64), + (:sgecon_,:Float32)) + @eval begin + function gecon!(normtype::BlasChar, A::StridedMatrix{$elty}, anorm::$elty) +# SUBROUTINE DGECON( NORM, N, A, LDA, ANORM, RCOND, WORK, IWORK, +# $ INFO ) +# * .. Scalar Arguments .. +# CHARACTER NORM +# INTEGER INFO, LDA, N +# DOUBLE PRECISION ANORM, RCOND +# * .. +# * .. Array Arguments .. +# INTEGER IWORK( * ) +# DOUBLE PRECISION A( LDA, * ), WORK( * ) + chkstride1(A) + n = size(A, 2) + lda = max(1, size(A, 1)) + rcond = Array($elty, 1) + work = Array($elty, 4n) + iwork = Array(BlasInt, n) + info = Array(BlasInt, 1) + ccall(($(string(gecon)),liblapack), Void, + (Ptr{Uint8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{BlasInt}), + &normtype, &n, A, &lda, &anorm, rcond, work, iwork, + info) + if info[1] != 0 throw(LAPACKException(info[1])) end + return rcond[1] + end + end +end +for (gecon, elty, relty) in + ((:zgecon_,:Complex128,:Float64), + (:cgecon_,:Complex64, :Float32)) + @eval begin + function gecon!(normtype::BlasChar, A::StridedMatrix{$elty}, anorm::$relty) + chkstride1(A) +# SUBROUTINE ZGECON( NORM, N, A, LDA, ANORM, RCOND, WORK, RWORK, +# $ INFO ) +# * .. Scalar Arguments .. +# CHARACTER NORM +# INTEGER INFO, LDA, N +# DOUBLE PRECISION ANORM, RCOND +# * .. +# * .. Array Arguments .. +# DOUBLE PRECISION RWORK( * ) +# COMPLEX*16 A( LDA, * ), WORK( * ) + chkstride1(A) + n = size(A, 2) + lda = max(1, size(A, 1)) + rcond = Array($relty, 1) + work = Array($elty, 2n) + rwork = Array($relty, 2n) + info = Array(BlasInt, 1) + ccall(($(string(gecon)),liblapack), Void, + (Ptr{Uint8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$relty}, Ptr{$relty}, Ptr{$elty}, Ptr{$relty}, + Ptr{BlasInt}), + &normtype, &n, A, &lda, &anorm, rcond, work, rwork, + info) + if info[1] < 0 throw(LAPACKException(info[1])) end + return rcond[1] + end + end +end + +# Hessenberg form +for (gehrd, elty) in + ((:dgehrd_,:Float64), + (:sgehrd_,:Float32), + (:zgehrd_,:Complex128), + (:cgehrd_,:Complex64)) + @eval begin + function gehrd!(ilo::Integer, ihi::Integer, A::StridedMatrix{$elty}) +# .. Scalar Arguments .. +# INTEGER IHI, ILO, INFO, LDA, LWORK, N +# * .. +# * .. Array Arguments .. +# DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * ) + chkstride1(A) + chksquare(A) + n = size(A, 1) + tau = Array($elty, n - 1) + work = Array($elty, 1) + lwork = blas_int(-1) + info = Array(BlasInt, 1) + for i = 1:2 + ccall(($(string(gehrd)),liblapack), Void, + (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, + Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{BlasInt}), + &n, &ilo, &ihi, A, + &max(1,n), tau, work, &lwork, + info) + if info[1] < 0 throw(LAPACKException(info[1])) end + if lwork < 0 + lwork = blas_int(work[1]) + work = Array($elty, lwork) + end + end + return A, tau + end + end +end +gehrd!(A::StridedMatrix) = gehrd!(1, size(A, 1), A) + +# construct Q from Hessenberg +for (orghr, elty) in + ((:dorghr_,:Float64), + (:sorghr_,:Float32), + (:zunghr_,:Complex128), + (:cunghr_,:Complex64)) + @eval begin + function orghr!(ilo::Integer, ihi::Integer, A::StridedMatrix{$elty}, tau::StridedVector{$elty}) +# * .. Scalar Arguments .. +# INTEGER IHI, ILO, INFO, LDA, LWORK, N +# * .. +# * .. Array Arguments .. +# DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * ) + chkstride1(A) + chksquare(A) + n = size(A, 1) + if n - length(tau) != 1 throw(DimensionMismatch) end + work = Array($elty, 1) + lwork = blas_int(-1) + info = Array(BlasInt, 1) + for i = 1:2 + ccall(($(string(orghr)),liblapack), Void, + (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, + Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{BlasInt}), + &n, &ilo, &ihi, A, + &max(1,n), tau, work, &lwork, + info) + if info[1] < 0 throw(LAPACKException(info[1])) end + if lwork < 0 + lwork = blas_int(work[1]) + work = Array($elty, lwork) + end + end + return A + end + end +end +# Schur forms +for (gees, gges, elty) in + ((:dgees_,:dgges_,:Float64), + (:sgees_,:sgges_,:Float32)) + @eval begin + function gees!(jobvs::BlasChar, A::StridedMatrix{$elty}) +# .. Scalar Arguments .. +# CHARACTER JOBVS, SORT +# INTEGER INFO, LDA, LDVS, LWORK, N, SDIM +# .. +# .. Array Arguments .. +# LOGICAL BWORK( * ) +# DOUBLE PRECISION A( LDA, * ), VS( LDVS, * ), WI( * ), WORK( * ), +# $ WR( * ) + chkstride1(A) + chksquare(A) + n = size(A, 1) + sdim = Array(BlasInt, 1) + wr = Array($elty, n) + wi = Array($elty, n) + ldvs = jobvs == 'V' ? n : 1 + vs = Array($elty, ldvs, n) + work = Array($elty, 1) + lwork = blas_int(-1) + info = Array(BlasInt, 1) + for i = 1:2 + ccall(($(string(gees)),liblapack), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{Void}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, + Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, + Ptr{BlasInt}, Ptr{Void}, Ptr{BlasInt}), + &jobvs, &'N', [], &n, + A, &max(1, n), sdim, wr, + wi, vs, &ldvs, work, + &lwork, [], info) + if info[1] != 0 throw(LAPACKException(info[1])) end + if lwork < 0 + lwork = blas_int(work[1]) + work = Array($elty, lwork) + end + end + if all(wi .== 0) + return A, vs, wr + else + return A, vs, complex(wr, wi) + end + end + function gges!(jobvsl::Char, jobvsr::Char, A::StridedMatrix{$elty}, B::StridedMatrix{$elty}) +# * .. Scalar Arguments .. +# CHARACTER JOBVSL, JOBVSR, SORT +# INTEGER INFO, LDA, LDB, LDVSL, LDVSR, LWORK, N, SDIM +# * .. +# * .. Array Arguments .. +# LOGICAL BWORK( * ) +# DOUBLE PRECISION A( LDA, * ), ALPHAI( * ), ALPHAR( * ), +# $ B( LDB, * ), BETA( * ), VSL( LDVSL, * ), +# $ VSR( LDVSR, * ), WORK( * ) + n = size(A, 1) + if size(A, 2) != n || size(B, 1) != size(B, 2) throw(DimensionMismatch("Matrices must be square")) end + if size(B, 1) != n throw(DimensionMismatch("Matrices are not of same size")) end + sdim = blas_int(0) + alphar = Array($elty, n) + alphai = Array($elty, n) + beta = Array($elty, n) + ldvsl = jobvsl == 'V' ? n : 1 + vsl = Array($elty, ldvsl, n) + ldvsr = jobvsr == 'V' ? n : 1 + vsr = Array($elty, ldvsr, n) + work = Array($elty, 1) + lwork = blas_int(-1) + info = Array(BlasInt, 1) + for i = 1:2 + ccall(($(string(gges)), liblapack), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{Uint8}, Ptr{Void}, + Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, + Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, + Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, + Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{Void}, + Ptr{BlasInt}), + &jobvsl, &jobvsr, &'N', [], + &n, A, &max(1,n), B, + &max(1,n), &sdim, alphar, alphai, + beta, vsl, &ldvsl, vsr, + &ldvsr, work, &lwork, [], + info) + if i == 1 + lwork = blas_int(work[1]) + work = Array($elty, lwork) + end + end + if info[1] != 0 throw(LAPACKException(info[1])) end + return A, B, complex(alphar, alphai), beta, vsl[1:(jobvsl == 'V' ? n : 0),:], vsr[1:(jobvsr == 'V' ? n : 0),:] + end + end +end +for (gees, gges, elty, relty) in + ((:zgees_,:zgges_,:Complex128,:Float64), + (:cgees_,:cgges_,:Complex64,:Float32)) + @eval begin + function gees!(jobvs::BlasChar, A::StridedMatrix{$elty}) +# * .. Scalar Arguments .. +# CHARACTER JOBVS, SORT +# INTEGER INFO, LDA, LDVS, LWORK, N, SDIM +# * .. +# * .. Array Arguments .. +# LOGICAL BWORK( * ) +# DOUBLE PRECISION RWORK( * ) +# COMPLEX*16 A( LDA, * ), VS( LDVS, * ), W( * ), WORK( * ) + chkstride1(A) + chksquare(A) + sort = 'N' + n = size(A, 1) + sdim = blas_int(0) + w = Array($elty, n) + ldvs = jobvs == 'V' ? n : 1 + vs = Array($elty, ldvs, n) + work = Array($elty, 1) + lwork = blas_int(-1) + rwork = Array($relty, n) + info = Array(BlasInt, 1) + for i = 1:2 + ccall(($(string(gees)),liblapack), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{Void}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$relty}, Ptr{Void}, Ptr{BlasInt}), + &jobvs, &sort, [], &n, + A, &max(1, n), &sdim, w, + vs, &ldvs, work, &lwork, + rwork, [], info) + if info[1] != 0 throw(LAPACKException(info[1])) end + if lwork < 0 + lwork = blas_int(work[1]) + work = Array($elty, lwork) + end + end + return A, vs, w + end + function gges!(jobvsl::Char, jobvsr::Char, A::StridedMatrix{$elty}, B::StridedMatrix{$elty}) +# * .. Scalar Arguments .. +# CHARACTER JOBVSL, JOBVSR, SORT +# INTEGER INFO, LDA, LDB, LDVSL, LDVSR, LWORK, N, SDIM +# * .. +# * .. Array Arguments .. +# LOGICAL BWORK( * ) +# DOUBLE PRECISION RWORK( * ) +# COMPLEX*16 A( LDA, * ), ALPHA( * ), B( LDB, * ), +# $ BETA( * ), VSL( LDVSL, * ), VSR( LDVSR, * ), +# $ WORK( * ) + n = size(A, 1) + if size(A, 2) != n || size(B, 1) != size(B, 2) throw(DimensionMismatch("Matrices must be square")) end + if size(B, 1) != n throw(DimensionMismatch("Matrices are not of same size")) end + sdim = blas_int(0) + alpha = Array($elty, n) + beta = Array($elty, n) + ldvsl = jobvsl == 'V' ? n : 1 + vsl = Array($elty, ldvsl, n) + ldvsr = jobvsr == 'V' ? n : 1 + vsr = Array($elty, ldvsr, n) + work = Array($elty, 1) + lwork = blas_int(-1) + rwork = Array($relty, 8n) + info = Array(BlasInt, 1) + for i = 1:2 + ccall(($(string(gges)), liblapack), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{Uint8}, Ptr{Void}, + Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, + Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{$relty}, Ptr{Void}, + Ptr{BlasInt}), + &jobvsl, &jobvsr, &'N', [], + &n, A, &max(1,n), B, + &max(1,n), &sdim, alpha, beta, + vsl, &ldvsl, vsr, &ldvsr, + work, &lwork, rwork, [], + info) + if i == 1 + lwork = blas_int(work[1]) + work = Array($elty, lwork) + end + end + if info[1] != 0 throw(LAPACKException(info[1])) end + return A, B, alpha, beta, vsl[1:(jobvsl == 'V' ? n : 0),:], vsr[1:(jobvsr == 'V' ? n : 0),:] + end + end +end + +### Rectangular full packed format + +# Symmetric rank-k operation for matrix in RFP format. +for (fn, elty, relty) in ((:dsfrk_, :Float64, :Float64), + (:ssfrk_, :Float32, :Float32), + (:zhfrk_, :Complex128, :Float64), + (:chfrk_, :Complex64, :Float32)) + @eval begin + function sfrk!(transr::Char, uplo::Char, trans::Char, alpha::Real, A::StridedMatrix{$elty}, beta::Real, C::StridedVector{$elty}) + if trans == 'N' + n, k = size(A) + elseif trans == 'T' + k, n = size(A) + else + throw(LAPACKException(0)) + end + lda = max(1, stride(A, 2)) + ccall(($(string(fn)), liblapack), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{Uint8}, Ptr{BlasInt}, + Ptr{BlasInt}, Ptr{$relty}, Ptr{$elty}, Ptr{BlasInt}, + Ptr{$relty}, Ptr{$elty}), + &transr, &uplo, &trans, &n, + &k, &alpha, A, &lda, + &beta, C) + return C + end + end +end + +# Cholesky factorization of a real symmetric positive definite matrix A +for (fn, elty) in ((:dpftrf_, :Float64), + (:spftrf_, :Float32), + (:zpftrf_, :Complex128), + (:cpftrf_, :Complex64)) + @eval begin + function pftrf!(transr::Char, uplo::Char, A::StridedVector{$elty}) + n = int(div(sqrt(8length(A)), 2)) + info = Array(BlasInt, 1) + ccall(($(string(fn)), liblapack), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{BlasInt}, Ptr{$elty}, + Ptr{BlasInt}), + &transr, &uplo, &n, A, + info) + if info[1] < 0 throw(LAPACKException(info[1])) end + return A, info[1] + end + end +end + +# Computes the inverse of a (real) symmetric positive definite matrix A using the Cholesky factorization +for (fn, elty) in ((:dpftri_, :Float64), + (:spftri_, :Float32), + (:zpftri_, :Complex128), + (:cpftri_, :Complex64)) + @eval begin + function pftri!(transr::Char, uplo::Char, A::StridedVector{$elty}) + n = int(div(sqrt(8length(A)), 2)) + info = Array(BlasInt, 1) + ccall(($(string(fn)), liblapack), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{BlasInt}, Ptr{$elty}, + Ptr{BlasInt}), + &transr, &uplo, &n, A, + info) + if info[1] < 0 throw(LAPACKException(info[1])) end + return A, info[1] + end + end +end + +# DPFTRS solves a system of linear equations A*X = B with a symmetric positive definite matrix A using the Cholesky factorization +for (fn, elty) in ((:dpftrs_, :Float64), + (:spftrs_, :Float32), + (:zpftrs_, :Complex128), + (:cpftrs_, :Complex64)) + @eval begin + function pftrs!(transr::Char, uplo::Char, A::StridedVector{$elty}, B::StridedVecOrMat{$elty}) + n = int(div(sqrt(8length(A)), 2)) + if n != size(B, 1) throw(DimensionMismatch("A and B must have the same number of rows")) end + nhrs = size(B, 2) + ldb = max(1, stride(B, 2)) + info = Array(BlasInt, 1) + ccall(($(string(fn)), liblapack), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{BlasInt}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), + &transr, &uplo, &n, &nhrs, + A, B, &ldb, info) + if info[1] < 0 throw(LAPACKException(info[1])) end + return B + end + end +end + +# Solves a matrix equation (one operand is a triangular matrix in RFP format) +for (fn, elty) in ((:dtfsm_, :Float64), + (:stfsm_, :Float32), + (:ztfsm_, :Complex128), + (:ctfsm_, :Complex64)) + @eval begin + function pftrs!(transr::Char, side::Char, uplo::Char, trans::Char, diag::Char, alpha::Real, A::StridedVector{$elty}, B::StridedMatrix{$elty}) + m, n = size(B) + if int(div(sqrt(8length(A)), 2)) != m throw(DimensionMismatch("")) end + ldb = max(1, stride(B, 2)) + ccall(($(string(fn)), liblapack), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{Uint8}, Ptr{Uint8}, + Ptr{Uint8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, + Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}), + &transr, &side, &uplo, &trans, + &diag, &m, &n, &alpha, + A, B, &ldb) + return B + end + end +end + +# Computes the inverse of a triangular matrix A stored in RFP format. +for (fn, elty) in ((:dtftri_, :Float64), + (:stftri_, :Float32), + (:ztftri_, :Complex128), + (:ctftri_, :Complex64)) + @eval begin + function tftri!(transr::Char, uplo::Char, diag::Char, A::StridedVector{$elty}) + n = int(div(sqrt(8length(A)), 2)) + info = Array(BlasInt, 1) + ccall(($(string(fn)), liblapack), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{Uint8}, Ptr{BlasInt}, + Ptr{$elty}, Ptr{BlasInt}), + &transr, &uplo, &diag, &n, + A, info) + if info[1] < 0 throw(LAPACKException(info[1])) end + return A, info[1] + end + end +end + +# Copies a triangular matrix from the rectangular full packed format (TF) to the standard full format (TR) +for (fn, elty) in ((:dtfttr_, :Float64), + (:stfttr_, :Float32), + (:ztfttr_, :Complex128), + (:ctfttr_, :Complex64)) + @eval begin + function tfttr!(transr::Char, uplo::Char, Arf::StridedVector{$elty}) + n = int(div(sqrt(8length(Arf)), 2)) + info = Array(BlasInt, 1) + A = Array($elty, n, n) + ccall(($(string(fn)), liblapack), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{BlasInt}, Ptr{$elty}, + Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), + &transr, &uplo, &n, Arf, + A, &n, info) + if info[1] < 0 throw(LAPACKException(info[1])) end + return A, info[1] + end + end +end + +# Copies a triangular matrix from the standard full format (TR) to the rectangular full packed format (TF). +for (fn, elty) in ((:dtrttf_, :Float64), + (:strttf_, :Float32), + (:ztrttf_, :Complex128), + (:ctrttf_, :Complex64)) + @eval begin + function trttf!(transr::Char, uplo::Char, A::StridedMatrix{$elty}) + n = size(A, 1) + lda = max(1, stride(A, 2)) + info = Array(BlasInt, 1) + Arf = Array($elty, div(n*(n+1), 2)) + ccall(($(string(fn)), liblapack), Void, + (Ptr{Uint8}, Ptr{Uint8}, Ptr{BlasInt}, Ptr{$elty}, + Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}), + &transr, &uplo, &n, A, + &lda, Arf, info) + if info[1] < 0 throw(LAPACKException(info[1])) end + return Arf, info[1] + end + end +end +end # module diff --git a/base/matmul.jl b/base/linalg/matmul.jl similarity index 79% rename from base/matmul.jl rename to base/linalg/matmul.jl index 9e331f9b1be33..1b170303d0b30 100644 --- a/base/matmul.jl +++ b/base/linalg/matmul.jl @@ -36,22 +36,14 @@ diagmm(b::Vector, A::Matrix) = # Dot products -function dot{T<:Union(Vector{Float64}, Vector{Float32})}(x::T, y::T) - length(x) != length(y) ? error("Inputs should be of same length") : true - BLAS.dot(length(x), x, 1, y, 1) -end - -function dot{T<:Union(Float64, Float32), TI<:Integer}(x::Vector{T}, rx::Union(Range1{TI},Range{TI}), y::Vector{T}, ry::Union(Range1{TI},Range{TI})) +dot{T<:Union(Float32, Float64)}(x::Vector{T}, y::Vector{T}) = BLAS.dot(x, y) +function dot{T<:BLAS.BlasFloat, TI<:Integer}(x::Vector{T}, rx::Union(Range1{TI},Range{TI}), y::Vector{T}, ry::Union(Range1{TI},Range{TI})) length(rx) != length(ry) ? error("Ranges should be of same length") : true if min(rx) < 1 || max(rx) > length(x) || min(ry) < 1 || max(ry) > length(y) throw(BoundsError()) end BLAS.dot(length(rx), pointer(x)+(first(rx)-1)*sizeof(T), step(rx), pointer(y)+(first(ry)-1)*sizeof(T), step(ry)) end - -Ac_mul_B(x::Vector, y::Vector) = [dot(x, y)] -At_mul_B{T<:Real}(x::Vector{T}, y::Vector{T}) = [dot(x, y)] - function dot(x::Vector, y::Vector) s = zero(eltype(x)) for i=1:length(x) @@ -59,33 +51,45 @@ function dot(x::Vector, y::Vector) end s end +dot(x::Number, y::Number) = conj(x) * y +Ac_mul_B(x::Vector, y::Vector) = [dot(x, y)] +At_mul_B{T<:Real}(x::Vector{T}, y::Vector{T}) = [dot(x, y)] + +dot(x::Number, y::Number) = conj(x) * y # Matrix-vector multiplication -function (*){T<:LapackType}(A::StridedMatrix{T}, - X::StridedVector{T}) +function (*){T<:BlasFloat}(A::StridedMatrix{T}, X::StridedVector{T}) Y = similar(A, size(A,1)) gemv(Y, 'N', A, X) end -A_mul_B{T<:LapackType}(y::StridedVector{T}, A::StridedMatrix{T}, x::StridedVector{T}) = gemv(y, 'N', A, x) +A_mul_B{T<:BlasFloat}(y::StridedVector{T}, A::StridedMatrix{T}, x::StridedVector{T}) = gemv(y, 'N', A, x) A_mul_B(y::StridedVector, A::StridedMatrix, x::StridedVector) = generic_matvecmul(y, 'N', A, x) -function At_mul_B{T<:LapackType}(A::StridedMatrix{T}, x::StridedVector{T}) +function At_mul_B{T<:BlasFloat}(A::StridedMatrix{T}, x::StridedVector{T}) y = similar(A, size(A, 2)) gemv(y, 'T', A, x) end -At_mul_B{T<:LapackType}(y::StridedVector{T}, A::StridedMatrix{T}, x::StridedVector{T}) = gemv(y, 'T', A, x) +At_mul_B{T<:BlasFloat}(y::StridedVector{T}, A::StridedMatrix{T}, x::StridedVector{T}) = gemv(y, 'T', A, x) At_mul_B(y::StridedVector, A::StridedMatrix, x::StridedVector) = generic_matvecmul(y, 'T', A, x) +Ac_mul_B{T<:Union(Float64,Float32)}(A::StridedMatrix{T}, x::StridedVector{T}) = At_mul_B(A, x) +function Ac_mul_B{T<:Union(Complex128,Complex64)}(A::StridedMatrix{T}, x::StridedVector{T}) + y = similar(A, size(A, 2)) + gemv(y, 'C', A, x) +end +Ac_mul_B(y::StridedVector, A::StridedMatrix, x::StridedVector) = generic_matvecmul(y, 'C', A, x) + + # Matrix-matrix multiplication -(*){T<:LapackType}(A::StridedMatrix{T}, B::StridedMatrix{T}) = gemm_wrapper('N', 'N', A, B) -A_mul_B{T<:LapackType}(C::StridedMatrix{T}, A::StridedMatrix{T}, B::StridedMatrix{T}) = gemm_wrapper(C, 'N', 'N', A, B) +(*){T<:BlasFloat}(A::StridedMatrix{T}, B::StridedMatrix{T}) = gemm_wrapper('N', 'N', A, B) +A_mul_B{T<:BlasFloat}(C::StridedMatrix{T}, A::StridedMatrix{T}, B::StridedMatrix{T}) = gemm_wrapper(C, 'N', 'N', A, B) A_mul_B{T,S,R}(C::StridedMatrix{R}, A::StridedMatrix{T}, B::StridedMatrix{S}) = generic_matmatmul(C, 'N', 'N', A, B) -function At_mul_B{T<:LapackType}(A::StridedMatrix{T}, +function At_mul_B{T<:BlasFloat}(A::StridedMatrix{T}, B::StridedMatrix{T}) if is(A, B) syrk_wrapper('T', A) @@ -94,11 +98,11 @@ function At_mul_B{T<:LapackType}(A::StridedMatrix{T}, end end -At_mul_B{T<:LapackType}(C::StridedMatrix{T}, A::StridedMatrix{T}, B::StridedMatrix{T}) = gemm_wrapper(C, 'T', 'N', A, B) +At_mul_B{T<:BlasFloat}(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedMatrix{T}) = gemm_wrapper(C, 'T', 'N', A, B) At_mul_B{T,S}(A::StridedMatrix{T}, B::StridedMatrix{S}) = generic_matmatmul('T', 'N', A, B) -At_mul_B{T,S,R}(C::StridedMatrix{R}, A::StridedMatrix{T}, B::StridedMatrix{S}) = generic_matmatmul(C, 'T', 'N', A, B) +At_mul_B{T,S,R}(C::StridedMatrix{R}, A::StridedVecOrMat{T}, B::StridedMatrix{S}) = generic_matmatmul(C, 'T', 'N', A, B) -function A_mul_Bt{T<:LapackType}(A::StridedMatrix{T}, +function A_mul_Bt{T<:BlasFloat}(A::StridedMatrix{T}, B::StridedMatrix{T}) if is(A, B) syrk_wrapper('N', A) @@ -107,12 +111,12 @@ function A_mul_Bt{T<:LapackType}(A::StridedMatrix{T}, end end -A_mul_Bt{T<:LapackType}(C::StridedMatrix{T}, A::StridedMatrix{T}, B::StridedMatrix{T}) = gemm_wrapper(C, 'N', 'T', A, B) +A_mul_Bt{T<:BlasFloat}(C::StridedVecOrMat{T}, A::StridedMatrix{T}, B::StridedMatrix{T}) = gemm_wrapper(C, 'N', 'T', A, B) A_mul_Bt{T,S}(A::StridedMatrix{T}, B::StridedMatrix{S}) = generic_matmatmul('N', 'T', A, B) -A_mul_Bt{T,S,R}(C::StridedMatrix{R}, A::StridedMatrix{T}, B::StridedMatrix{S}) = generic_matmatmul(C, 'N', 'T', A, B) +A_mul_Bt{T,S,R}(C::StridedVecOrMat{R}, A::StridedMatrix{T}, B::StridedMatrix{S}) = generic_matmatmul(C, 'N', 'T', A, B) -At_mul_Bt{T<:LapackType}(A::StridedMatrix{T}, B::StridedMatrix{T}) = gemm_wrapper('T', 'T', A, B) -At_mul_Bt{T<:LapackType}(C::StridedMatrix{T}, A::StridedMatrix{T}, B::StridedMatrix{T}) = gemm_wrapper(C, 'T', 'T', A, B) +At_mul_Bt{T<:BlasFloat}(A::StridedMatrix{T}, B::StridedMatrix{T}) = gemm_wrapper('T', 'T', A, B) +At_mul_Bt{T<:BlasFloat}(C::StridedMatrix{T}, A::StridedMatrix{T}, B::StridedMatrix{T}) = gemm_wrapper(C, 'T', 'T', A, B) At_mul_Bt{T,S}(A::StridedMatrix{T}, B::StridedMatrix{S}) = generic_matmatmul('T', 'T', A, B) At_mul_Bt{T,S,R}(C::StridedMatrix{R}, A::StridedMatrix{T}, B::StridedMatrix{S}) = generic_matmatmul(C, 'T', 'T', A, B) @@ -146,56 +150,60 @@ A_mul_Bc{T<:Union(Complex128,Complex64)}(C::StridedMatrix{T}, A::StridedMatrix{T A_mul_Bc{T,S}(A::StridedMatrix{T}, B::StridedMatrix{S}) = generic_matmatmul('N', 'C', A, B) A_mul_Bc{T,S,R}(C::StridedMatrix{R}, A::StridedMatrix{T}, B::StridedMatrix{S}) = generic_matmatmul(C, 'N', 'C', A, B) -Ac_mul_Bc{T<:LapackType}(A::StridedMatrix{T}, B::StridedMatrix{T}) = gemm_wrapper('C', 'C', A, B) -Ac_mul_Bc{T<:LapackType}(C::StridedMatrix{T}, A::StridedMatrix{T}, B::StridedMatrix{T}) = gemm_wrapper(C, 'C', 'C', A, B) +Ac_mul_Bc{T<:BlasFloat}(A::StridedMatrix{T}, B::StridedMatrix{T}) = gemm_wrapper('C', 'C', A, B) +Ac_mul_Bc{T<:BlasFloat}(C::StridedMatrix{T}, A::StridedMatrix{T}, B::StridedMatrix{T}) = gemm_wrapper(C, 'C', 'C', A, B) Ac_mul_Bt{T,S}(A::StridedMatrix{T}, B::StridedMatrix{S}) = generic_matmatmul('C', 'C', A, B) Ac_mul_Bt{T,S,R}(C::StridedMatrix{R}, A::StridedMatrix{T}, B::StridedMatrix{S}) = generic_matmatmul(C, 'C', 'C', A, B) # Supporting functions for matrix multiplication -function symmetrize!(A::StridedMatrix, upper::Bool) +function symmetrize!(A::StridedMatrix, UL::BlasChar) m, n = size(A) if m != n error("symmetrize: Matrix must be square") end - if upper + if UL == 'U' for i = 1:(n-1) for j = (i+1):n A[j,i] = A[i,j] end end - else + elseif UL == 'L' for i = 1:(n-1) for j = (i+1):n A[i,j] = A[j,i] end end + else + error("Second argument UL should be 'U' or 'L'") end return A end -symmetrize!(A) = symmetrize!(A, true) +symmetrize!(A) = symmetrize!(A, 'U') -function symmetrize_conj!(A::StridedMatrix, upper::Bool) +function symmetrize_conj!(A::StridedMatrix, UL::BlasChar) m, n = size(A) if m != n error("symmetrize: Matrix must be square") end - if upper + if UL == 'U' for i = 1:(n-1) for j = (i+1):n A[j,i] = conj(A[i,j]) end end - else + elseif UL == 'L' for i = 1:(n-1) for j = (i+1):n A[i,j] = conj(A[j,i]) end end + else + error("Second argument UL should be 'U' or 'L'") end return A end -symmetrize_conj!(A) = symmetrize_conj!(A, true) +symmetrize_conj!(A) = symmetrize_conj!(A, 'U') -function gemv{T<:LapackType}(y::StridedVector{T}, +function gemv{T<:BlasFloat}(y::StridedVector{T}, tA, A::StridedMatrix{T}, x::StridedVector{T}) @@ -211,11 +219,12 @@ function gemv{T<:LapackType}(y::StridedVector{T}, if nA != length(x); error("*: argument shapes do not match"); end if mA != length(y); error("*: output size is incorrect"); end + if mA == 0; return zeros(T, 0); end BLAS.gemv!(tA, one(T), A, x, zero(T), y) end -function syrk_wrapper{T<:LapackType}(tA, A::StridedMatrix{T}) +function syrk_wrapper{T<:BlasFloat}(tA, A::StridedMatrix{T}) if tA == 'T' (nA, mA) = size(A) tAt = 'N' @@ -234,7 +243,7 @@ function syrk_wrapper{T<:LapackType}(tA, A::StridedMatrix{T}) symmetrize!(BLAS.syrk('U', tA, one(T), A)) end -function herk_wrapper{T<:LapackType}(tA, A::StridedMatrix{T}) +function herk_wrapper{T<:BlasFloat}(tA, A::StridedMatrix{T}) if tA == 'C' (nA, mA) = size(A) tAt = 'N' @@ -256,8 +265,8 @@ function herk_wrapper{T<:LapackType}(tA, A::StridedMatrix{T}) symmetrize_conj!(BLAS.herk('U', tA, one(T), A)) end -function gemm_wrapper{T<:LapackType}(tA, tB, - A::StridedMatrix{T}, +function gemm_wrapper{T<:BlasFloat}(tA, tB, + A::StridedVecOrMat{T}, B::StridedMatrix{T}) mA, nA = lapack_size(tA, A) mB, nB = lapack_size(tB, B) @@ -265,8 +274,8 @@ function gemm_wrapper{T<:LapackType}(tA, tB, gemm_wrapper(C, tA, tB, A, B) end -function gemm_wrapper{T<:LapackType}(C::StridedMatrix{T}, tA, tB, - A::StridedMatrix{T}, +function gemm_wrapper{T<:BlasFloat}(C::StridedVecOrMat{T}, tA, tB, + A::StridedVecOrMat{T}, B::StridedMatrix{T}) mA, nA = lapack_size(tA, A) mB, nB = lapack_size(tB, B) @@ -289,22 +298,22 @@ end lapack_size(t::Char, M::StridedVecOrMat) = (t == 'N') ? (size(M, 1), size(M, 2)) : (size(M,2), size(M, 1)) -function copy_to{R,S}(B::Matrix{R}, ir_dest::Range1{Int}, jr_dest::Range1{Int}, tM::Char, M::StridedMatrix{S}, ir_src::Range1{Int}, jr_src::Range1{Int}) +function copy!{R,S}(B::Matrix{R}, ir_dest::Range1{Int}, jr_dest::Range1{Int}, tM::Char, M::StridedMatrix{S}, ir_src::Range1{Int}, jr_src::Range1{Int}) if tM == 'N' - copy_to(B, ir_dest, jr_dest, M, ir_src, jr_src) + copy!(B, ir_dest, jr_dest, M, ir_src, jr_src) else - copy_to_transpose(B, ir_dest, jr_dest, M, jr_src, ir_src) + Base.copy_transpose!(B, ir_dest, jr_dest, M, jr_src, ir_src) if tM == 'C' conj!(B) end end end -function copy_to_transpose{R,S}(B::Matrix{R}, ir_dest::Range1{Int}, jr_dest::Range1{Int}, tM::Char, M::StridedMatrix{S}, ir_src::Range1{Int}, jr_src::Range1{Int}) +function copy_transpose!{R,S}(B::Matrix{R}, ir_dest::Range1{Int}, jr_dest::Range1{Int}, tM::Char, M::StridedMatrix{S}, ir_src::Range1{Int}, jr_src::Range1{Int}) if tM == 'N' - copy_to_transpose(B, ir_dest, jr_dest, M, ir_src, jr_src) + Base.copy_transpose!(B, ir_dest, jr_dest, M, ir_src, jr_src) else - copy_to(B, ir_dest, jr_dest, M, jr_src, ir_src) + copy!(B, ir_dest, jr_dest, M, jr_src, ir_src) if tM == 'C' conj!(B) end @@ -319,11 +328,7 @@ end (*){T,S}(A::StridedMatrix{T}, B::StridedVector{S}) = generic_matvecmul('N', A, B) function generic_matvecmul{T,S}(tA, A::StridedMatrix{T}, B::StridedVector{S}) - if tA == 'N' - C = Array(promote_type(T,S), size(A, 1)) - else - C = Array(promote_type(T,S), size(A, 2)) - end + C = Array(promote_type(T,S), size(A, tA=='N' ? 1 : 2)) generic_matvecmul(C, tA, A, B) end @@ -371,9 +376,9 @@ end # NOTE: the generic version is also called as fallback for strides != 1 cases # in libalg_blas.jl -(*){T,S}(A::StridedMatrix{T}, B::StridedMatrix{S}) = generic_matmatmul('N', 'N', A, B) +(*){T,S}(A::StridedVecOrMat{T}, B::StridedMatrix{S}) = generic_matmatmul('N', 'N', A, B) -function generic_matmatmul{T,S}(tA, tB, A::StridedMatrix{T}, B::StridedMatrix{S}) +function generic_matmatmul{T,S}(tA, tB, A::StridedVecOrMat{T}, B::StridedMatrix{S}) mA, nA = lapack_size(tA, A) mB, nB = lapack_size(tB, B) C = Array(promote_type(T,S), mA, nB) @@ -385,7 +390,7 @@ const Abuf = Array(Uint8, tilebufsize) const Bbuf = Array(Uint8, tilebufsize) const Cbuf = Array(Uint8, tilebufsize) -function generic_matmatmul{T,S,R}(C::StridedMatrix{R}, tA, tB, A::StridedMatrix{T}, B::StridedMatrix{S}) +function generic_matmatmul{T,S,R}(C::StridedVecOrMat{R}, tA, tB, A::StridedVecOrMat{T}, B::StridedMatrix{S}) mA, nA = lapack_size(tA, A) mB, nB = lapack_size(tB, B) if nA != mB; error("*: argument shapes do not match"); end @@ -394,7 +399,7 @@ function generic_matmatmul{T,S,R}(C::StridedMatrix{R}, tA, tB, A::StridedMatrix{ if mA == nA == nB == 2; return matmul2x2(C, tA, tB, A, B); end if mA == nA == nB == 3; return matmul3x3(C, tA, tB, A, B); end - if isa(R, BitsKind) + if isbits(R) tile_size = int(ifloor(sqrt(tilebufsize/sizeof(R)))) sz = (tile_size, tile_size) Atile = pointer_to_array(convert(Ptr{R}, pointer(Abuf)), sz) @@ -403,8 +408,8 @@ function generic_matmatmul{T,S,R}(C::StridedMatrix{R}, tA, tB, A::StridedMatrix{ z = zero(R) if mA < tile_size && nA < tile_size && nB < tile_size - copy_to_transpose(Atile, 1:nA, 1:mA, tA, A, 1:mA, 1:nA) - copy_to(Btile, 1:mB, 1:nB, tB, B, 1:mB, 1:nB) + Base.copy_transpose!(Atile, 1:nA, 1:mA, tA, A, 1:mA, 1:nA) + copy!(Btile, 1:mB, 1:nB, tB, B, 1:mB, 1:nB) for j = 1:nB boff = (j-1)*tile_size for i = 1:mA @@ -428,8 +433,8 @@ function generic_matmatmul{T,S,R}(C::StridedMatrix{R}, tA, tB, A::StridedMatrix{ for kb = 1:tile_size:nA klim = min(kb+tile_size-1,mB) klen = klim-kb+1 - copy_to_transpose(Atile, 1:klen, 1:ilen, tA, A, ib:ilim, kb:klim) - copy_to(Btile, 1:klen, 1:jlen, tB, B, kb:klim, jb:jlim) + Base.copy_transpose!(Atile, 1:klen, 1:ilen, tA, A, ib:ilim, kb:klim) + copy!(Btile, 1:klen, 1:jlen, tB, B, kb:klim, jb:jlim) for j=1:jlen bcoff = (j-1)*tile_size for i = 1:ilen @@ -442,12 +447,12 @@ function generic_matmatmul{T,S,R}(C::StridedMatrix{R}, tA, tB, A::StridedMatrix{ end end end - copy_to(C, ib:ilim, jb:jlim, Ctile, 1:ilen, 1:jlen) + copy!(C, ib:ilim, jb:jlim, Ctile, 1:ilen, 1:jlen) end end end else - # Multiplication for non-BitsKind uses the naive algorithm + # Multiplication for non-plain-data uses the naive algorithm if tA == 'N' if tB == 'N' for i = 1:mA @@ -552,9 +557,7 @@ end # multiply 2x2 matrices function matmul2x2{T,S}(tA, tB, A::StridedMatrix{T}, B::StridedMatrix{S}) - R = promote_type(T,S) - C = Array(R, 2, 2) - matmul2x2(C, tA, tB, A, B) + matmul2x2(Array(promote_type(T,S), 2, 2), tA, tB, A, B) end function matmul2x2{T,S,R}(C::StridedMatrix{R}, tA, tB, A::StridedMatrix{T}, B::StridedMatrix{S}) @@ -583,9 +586,7 @@ end # Multiply 3x3 matrices function matmul3x3{T,S}(tA, tB, A::StridedMatrix{T}, B::StridedMatrix{S}) - R = promote_type(T,S) - C = Array(R, 3, 3) - matmul3x3(C, tA, tB, A, B) + matmul3x3(Array(promote_type(T,S), 3, 3), tA, tB, A, B) end function matmul3x3{T,S,R}(C::StridedMatrix{R}, tA, tB, A::StridedMatrix{T}, B::StridedMatrix{S}) diff --git a/base/linalg/rectfullpacked.jl b/base/linalg/rectfullpacked.jl new file mode 100644 index 0000000000000..e057f9e3e5066 --- /dev/null +++ b/base/linalg/rectfullpacked.jl @@ -0,0 +1,49 @@ +# Rectangular Full Packed Matrices + +type SymmetricRFP{T<:BlasFloat} <: AbstractMatrix{T} + data::Vector{T} + transr::Char + uplo::Char +end + +function Ac_mul_A_RFP{T<:BlasFloat}(A::Matrix{T}) + n = size(A, 2) + C = LAPACK.sfrk!('N', 'U', 'T', 1.0, A, 0.0, Array(T, div(n*(n+1),2))) + return SymmetricRFP(C, 'N', 'U') +end + +type TriangularRFP{T<:BlasFloat} <: AbstractMatrix{T} + data::Vector{T} + transr::Char + uplo::Char +end +TriangularRFP(A::Matrix) = TriangularRFP(trttf!('N', 'U', A)[1], 'N', 'U') + +function full(A::TriangularRFP) + B = LAPACK.tfttr!(A.transr, A.uplo, A.data)[1] + if A.uplo == 'U' + return triu!(B) + else + return tril!(B) + end +end + +type CholeskyDenseRFP{T<:BlasFloat} <: Factorization{T} + data::Vector{T} + transr::Char + uplo::Char +end + +function chol(A::SymmetricRFP) + C, info = LAPACK.pftrf!(A.transr, A.uplo, copy(A.data)) + return CholeskyDenseRFP(C, A.transr, A.uplo) +end + +# Least squares +\(A::CholeskyDenseRFP, B::VecOrMat) = LAPACK.pftrs!(A.transr, A.uplo, A.data, copy(B)) + +function inv(A::CholeskyDenseRFP) + B, info = LAPACK.pftri!(A.transr, A.uplo, copy(A.data)) + if info > 0 throw(LAPACK.SingularException(info)) end + return B +end diff --git a/base/linalg_sparse.jl b/base/linalg/sparse.jl similarity index 92% rename from base/linalg_sparse.jl rename to base/linalg/sparse.jl index fadb5a5dc36b7..fa30d80472e52 100644 --- a/base/linalg_sparse.jl +++ b/base/linalg/sparse.jl @@ -1,5 +1,13 @@ ## sparse matrix multiplication +function (*){TvA,TiA,TvB,TiB}(A::SparseMatrixCSC{TvA,TiA}, B::SparseMatrixCSC{TvB,TiB}) + Tv = promote_type(TvA, TvB) + Ti = promote_type(TiA, TiB) + A = convert(SparseMatrixCSC{Tv,Ti}, A) + B = convert(SparseMatrixCSC{Tv,Ti}, B) + return A * B +end + # In matrix-vector multiplication, the correct orientation of the vector is assumed. function (*){T1,T2}(A::SparseMatrixCSC{T1}, X::Vector{T2}) if A.n != length(X); error("mismatched dimensions"); end @@ -72,8 +80,8 @@ function (*){Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, B::SparseMatrixCSC{Tv,Ti}) x = zeros(Tv, mA) for i in 1:nB if ip + mA - 1 > nnzC - rowvalC = grow(rowvalC, max(nnzC,mA)) - nzvalC = grow(nzvalC, max(nnzC,mA)) + resize!(rowvalC, nnzC + max(nnzC,mA)) + resize!(nzvalC, nnzC + max(nnzC,mA)) nnzC = length(nzvalC) end colptrC[i] = ip @@ -99,8 +107,8 @@ function (*){Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, B::SparseMatrixCSC{Tv,Ti}) end colptrC[nB+1] = ip - rowvalC = del(rowvalC, colptrC[end]:length(rowvalC)) - nzvalC = del(nzvalC, colptrC[end]:length(nzvalC)) + delete!(rowvalC, colptrC[end]:length(rowvalC)) + delete!(nzvalC, colptrC[end]:length(nzvalC)) # The Gustavson algorithm does not guarantee the product to have sorted row indices. return ((SparseMatrixCSC(mA, nB, colptrC, rowvalC, nzvalC).').') @@ -108,7 +116,7 @@ end ## triu, tril -function triu{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}, k::Int) +function triu{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}, k::Integer) m,n = size(S) colptr = Array(Ti, n+1) nnz = 0 @@ -139,7 +147,7 @@ function triu{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}, k::Int) end triu{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}, k::Integer) = triu(S, int(k)) -function tril{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}, k::Int) +function tril{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}, k::Integer) m,n = size(S) colptr = Array(Ti, n+1) nnz = 0 @@ -175,7 +183,7 @@ tril{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}, k::Integer) = tril(S, int(k)) ## diff -function _jl_sparse_diff1{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}) +function sparse_diff1{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}) m,n = size(S) if m <= 1 return SparseMatrixCSC{Tv,Ti}(0, n, ones(n+1), Ti[], Tv[]) @@ -214,12 +222,12 @@ function _jl_sparse_diff1{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}) end colptr[col+1] = numnz+1 end - del(rowval, numnz+1:length(rowval)) - del(nzval, numnz+1:length(nzval)) + delete!(rowval, numnz+1:length(rowval)) + delete!(nzval, numnz+1:length(nzval)) return SparseMatrixCSC{Tv,Ti}(m-1, n, colptr, rowval, nzval) end -function _jl_sparse_diff2{Tv,Ti}(a::SparseMatrixCSC{Tv,Ti}) +function sparse_diff2{Tv,Ti}(a::SparseMatrixCSC{Tv,Ti}) m,n = size(a) colptr = Array(Ti, max(n,1)) @@ -306,16 +314,16 @@ function _jl_sparse_diff2{Tv,Ti}(a::SparseMatrixCSC{Tv,Ti}) colptr[col+1] = ptrS end - del(rowval, ptrS:length(rowval)) - del(nzval, ptrS:length(nzval)) + delete!(rowval, ptrS:length(rowval)) + delete!(nzval, ptrS:length(nzval)) return SparseMatrixCSC{Tv,Ti}(m, n-1, colptr, rowval, nzval) end function diff(a::SparseMatrixCSC, dim::Integer) if dim == 1 - _jl_sparse_diff1(a) + sparse_diff1(a) else - _jl_sparse_diff2(a) + sparse_diff2(a) end end @@ -328,14 +336,14 @@ function diagm{Tv,Ti}(v::SparseMatrixCSC{Tv,Ti}) error("Input should be nx1 or 1xn") end - n = numel(v) + n = length(v) numnz = nnz(v) colptr = Array(Ti, n+1) rowval = Array(Ti, numnz) nzval = Array(Tv, numnz) if size(v,1) == 1 - copy_to(colptr, 1, v.colptr, 1, n+1) + copy!(colptr, 1, v.colptr, 1, n+1) ptr = 1 for col = 1:n if colptr[col] != colptr[col+1] @@ -345,8 +353,8 @@ function diagm{Tv,Ti}(v::SparseMatrixCSC{Tv,Ti}) end end else - copy_to(rowval, 1, v.rowval, 1, numnz) - copy_to(nzval, 1, v.nzval, 1, numnz) + copy!(rowval, 1, v.rowval, 1, numnz) + copy!(nzval, 1, v.nzval, 1, numnz) colptr[1] = 1 ptr = 1 col = 1 @@ -374,7 +382,7 @@ function spdiagm{T}(v::Union(AbstractVector{T},AbstractMatrix{T})) end end - n = numel(v) + n = length(v) numnz = nnz(v) colptr = Array(Int, n+1) rowval = Array(Int, numnz) @@ -490,13 +498,13 @@ end function issym(A::SparseMatrixCSC) m, n = size(A) - if m != n; error("matrix must be square, got $(m)x$(n)"); end + if m != n; return false; end return nnz(A - A.') == 0 end function ishermitian(A::SparseMatrixCSC) m, n = size(A) - if m != n; error("matrix must be square, got $(m)x$(n)"); end + if m != n; return false; end return nnz(A - A') == 0 end diff --git a/base/linalg/spqr_h.jl b/base/linalg/spqr_h.jl new file mode 100644 index 0000000000000..58fbc99bb7886 --- /dev/null +++ b/base/linalg/spqr_h.jl @@ -0,0 +1,31 @@ +## SuiteSparseQR + +## ordering options +const SPQR_ORDERING_FIXED = int32(0) +const SPQR_ORDERING_NATURAL = int32(1) +const SPQR_ORDERING_COLAMD = int32(2) +const SPQR_ORDERING_GIVEN = int32(3) # only used for C/C++ interface +const SPQR_ORDERING_CHOLMOD = int32(4) # CHOLMOD best-effort (COLAMD, METIS,...) +const SPQR_ORDERING_AMD = int32(5) # AMD(A'*A) +const SPQR_ORDERING_METIS = int32(6) # metis(A'*A) +const SPQR_ORDERING_DEFAULT = int32(7) # SuiteSparseQR default ordering +const SPQR_ORDERING_BEST = int32(8) # try COLAMD, AMD, and METIS; pick best +const SPQR_ORDERING_BESTAMD = int32(9) # try COLAMD and AMD; pick best + +# Let [m n] = size of the matrix after pruning singletons. The default +# ordering strategy is to use COLAMD if m <= 2*n. Otherwise, AMD(A'A) is +# tried. If there is a high fill-in with AMD then try METIS(A'A) and take +# the best of AMD and METIS. METIS is not tried if it isn't installed. + +## Operations in qmult +const SPQR_QTX = int32(0) # Y = Q'*X +const SPQR_QX = int32(1) # Y = Q*X +const SPQR_XQT = int32(2) # Y = X*Q' +const SPQR_XQ = int32(3) # Y = X*Q + +## Types of systems to solve +const SPQR_RX_EQUALS_B = int32(0) # solve R*X=B or X = R\B +const SPQR_RETX_EQUALS_B = int32(1) # solve R*E'*X=B or X = E*(R\B) +const SPQR_RTX_EQUALS_B = int32(2) # solve R'*X=B or X = R'\B +const SPQR_RTX_EQUALS_ETB = int32(3) # solve R'*X=E'*B or X = R'\(E'*B) + diff --git a/base/linalg/triangular.jl b/base/linalg/triangular.jl new file mode 100644 index 0000000000000..b485b041d7418 --- /dev/null +++ b/base/linalg/triangular.jl @@ -0,0 +1,67 @@ +## Triangular +type Triangular{T<:BlasFloat} <: AbstractMatrix{T} + UL::Matrix{T} + uplo::Char + unitdiag::Char + function Triangular(A::Matrix{T}, uplo::Char, unitdiag::Char) + if size(A, 1) != size(A, 2) throw(LAPACK.DimensionMismatch("Matrix must be square")) end + return new(A, uplo, unitdiag) + end +end +Triangular{T<:BlasFloat}(A::Matrix{T}, uplo::Char, unitdiag::Char) = Triangular{T}(A, uplo, unitdiag) +Triangular(A::Matrix, uplo::Char, unitdiag::Bool) = Triangular(A, uplo, unitdiag ? 'U' : 'N') +Triangular(A::Matrix, uplo::Char) = Triangular(A, uplo, all(diag(A) .== 1) ? true : false) +function Triangular(A::Matrix) + if istriu(A) return Triangular(A, 'U') end + if istril(A) return Triangular(A, 'L') end + error("Matrix is not triangular") +end + +size(A::Triangular, args...) = size(A.UL, args...) +function full(A::Triangular) + if + istril(A) return tril(A.UL) + else + return triu(A.UL) + end +end +print_matrix(io::IO, A::Triangular) = print_matrix(io, full(A)) + +istril(A::Triangular) = A.uplo == 'L' +istriu(A::Triangular) = A.uplo == 'U' + +# Vector multiplication +*(A::Triangular, b::Vector) = BLAS.trmv(A.uplo, 'N', A.unitdiag, A.UL, b) +Ac_mul_B{T<:Union(Complex128, Complex64)}(A::Triangular{T}, b::Vector{T}) = BLAS.trmv(A.uplo, 'C', A.unitdiag, A.UL, b) +At_mul_B{T<:Union(Float64, Float32)}(A::Triangular{T}, b::Vector{T}) = BLAS.trmv(A.uplo, 'T', A.unitdiag, A.UL, b) + +# Matrix multiplication +*{T<:BlasFloat}(A::Triangular{T}, B::StridedMatrix{T}) = BLAS.trmm('L', A.uplo, 'N', A.unitdiag, one(T), A.UL, B) +*{T<:BlasFloat}(A::StridedMatrix{T}, B::Triangular{T}) = BLAS.trmm('R', B.uplo, 'N', B.unitdiag, one(T), A, B.UL) +Ac_mul_B{T<:Union(Complex128, Complex64)}(A::Triangular{T}, B::StridedMatrix{T}) = BLAS.trmm('L', A.uplo, 'C', A.unitdiag, one(T), A.UL, B) +Ac_mul_B{T<:Union(Float64, Float32)}(A::Triangular{T}, B::StridedMatrix{T}) = BLAS.trmm('L', A.uplo, 'T', A.unitdiag, one(T), A.UL, B) +A_mul_Bc{T<:Union(Complex128, Complex64)}(A::StridedMatrix{T}, B::Triangular{T}) = BLAS.trmm('R', B.uplo, 'C', B.unitdiag, one(T), B.UL, A) +A_mul_Bc{T<:Union(Float64, Float32)}(A::StridedMatrix{T}, B::Triangular{T}) = BLAS.trmm('R', B.uplo, 'T', B.unitdiag, one(T), B.UL, A) + +function \(A::Triangular, B::StridedVecOrMat) + r, info = LAPACK.trtrs!(A.uplo, 'N', A.unitdiag, A.UL, copy(B)) + if info > 0 throw(LAPACK.SingularException(info)) end + return r +end +function Ac_ldiv_B{T<:Union(Float64, Float32)}(A::Triangular{T}, B::StridedVecOrMat{T}) + r, info = LAPACK.trtrs!(A.uplo, 'T', A.unitdiag, A.UL, copy(B)) + if info > 0 throw(LAPACK.SingularException(info)) end + return r +end +function Ac_ldiv_B{T<:Union(Complex128, Complex64)}(A::Triangular{T}, B::StridedVecOrMat{T}) + r, info = LAPACK.trtrs!(A.uplo, 'C', A.unitdiag, A.UL, copy(B)) + if info > 0 throw(LAPACK.SingularException(info)) end + return r +end +/{T<:BlasFloat}(A::StridedVecOrMat{T}, B::Triangular{T}) = BLAS.trsm!('R', B.uplo, 'N', B.unitdiag, one(T), B.UL, copy(A)) +A_rdiv_Bc{T<:Union(Float64, Float32)}(A::StridedVecOrMat{T}, B::Triangular{T}) = BLAS.trsm!('R', B.uplo, 'T', B.unitdiag, one(T), B.UL, copy(A)) +A_rdiv_Bc{T<:Union(Complex128, Complex64)}(A::StridedVecOrMat{T}, B::Triangular{T}) = BLAS.trsm!('R', B.uplo, 'C', B.unitdiag, one(T), B.UL, copy(A)) + +det(A::Triangular) = prod(diag(A.UL)) + +inv(A::Triangular) = LAPACK.trtri!(A.uplo, A.unitdiag, copy(A.UL))[1] diff --git a/base/linalg/tridiag.jl b/base/linalg/tridiag.jl new file mode 100644 index 0000000000000..ea4bc2ef9816f --- /dev/null +++ b/base/linalg/tridiag.jl @@ -0,0 +1,360 @@ +#### Specialized matrix types #### + +import Base.conj, Base.transpose, Base.ctranspose, Base.convert + +## Hermitian tridiagonal matrices +type SymTridiagonal{T<:BlasFloat} <: AbstractMatrix{T} + dv::Vector{T} # diagonal + ev::Vector{T} # sub/super diagonal + function SymTridiagonal(dv::Vector{T}, ev::Vector{T}) + if length(ev) != length(dv) - 1 error("dimension mismatch") end + new(dv,ev) + end +end + +SymTridiagonal{T<:BlasFloat}(dv::Vector{T}, ev::Vector{T}) = SymTridiagonal{T}(copy(dv), copy(ev)) + +function SymTridiagonal{T<:Real}(dv::Vector{T}, ev::Vector{T}) + SymTridiagonal{Float64}(float64(dv),float64(ev)) +end + +function SymTridiagonal{Td<:Number,Te<:Number}(dv::Vector{Td}, ev::Vector{Te}) + T = promote(Td,Te) + SymTridiagonal(convert(Vector{T}, dv), convert(Vector{T}, ev)) +end + +SymTridiagonal(M::AbstractMatrix) = diag(A,1)==diag(A,-1)?SymTridiagonal(diag(A), diag(A,1)):error("Matrix is not symmetric, cannot convert to SymTridiagonal") +full{T}(M::SymTridiagonal{T}) = convert(Matrix{T}, M) +convert{T}(::Type{Matrix{T}}, M::SymTridiagonal{T})=diagm(M.dv)+diagm(M.ev,-1)+diagm(M.ev,1) + +function show(io::IO, S::SymTridiagonal) + println(io, summary(S), ":") + print(io, "diag: ") + print_matrix(io, (S.dv)') + print(io, "\n sup: ") + print_matrix(io, (S.ev)') +end + +size(m::SymTridiagonal) = (length(m.dv), length(m.dv)) +size(m::SymTridiagonal, d::Integer) = d<1 ? error("dimension out of range") : (d<=2 ? length(m.dv) : 1) + +#Elementary operations +copy(S::SymTridiagonal) = SymTridiagonal(copy(S.dv), copy(S.ev)) +round(M::SymTridiagonal) = SymTridiagonal(round(M.dv), round(M.ev)) +iround(M::SymTridiagonal) = SymTridiagonal(iround(M.dv), iround(M.ev)) + +conj(M::SymTridiagonal) = SymTridiagonal(conj(M.dv), conj(M.ev)) +transpose(M::SymTridiagonal) = M #Identity operation +ctranspose(M::SymTridiagonal) = conj(M) + ++(A::SymTridiagonal, B::SymTridiagonal) = SymTridiagonal(A.dv+B.dv, A.ev+B.ev) +-(A::SymTridiagonal, B::SymTridiagonal) = SymTridiagonal(A.dv-B.dv, A.ev-B.ev) +*(A::SymTridiagonal, B::SymTridiagonal) = full(A)*full(B) +*(A::SymTridiagonal, B::Number) = SymTridiagonal(A.dv*B, A.ev*B) +*(B::Number, A::SymTridiagonal) = A*B +/(A::SymTridiagonal, B::Number) = SymTridiagonal(A.dv/B, A.ev/B) +==(A::SymTridiagonal, B::SymTridiagonal) = (A.dv==B.dv) && (A.ev==B.ev) + +## Solver +function \{T<:BlasFloat}(M::SymTridiagonal{T}, rhs::StridedVecOrMat{T}) + if stride(rhs, 1) == 1 + return LAPACK.gtsv!(copy(M.dv), copy(M.ev), copy(M.dv), copy(rhs)) + end + solve(Tridiagonal(M), rhs) # use the Julia "fallback" +end + +#Wrap LAPACK DSTE{GR,BZ} to compute eigenvalues +eig(m::SymTridiagonal) = LAPACK.stegr!('V', copy(m.dv), copy(m.ev)) +eigvals(m::SymTridiagonal, il::Int, iu::Int) = LAPACK.stebz!('I', 'E', 0.0, 0.0, il, iu, -1.0, copy(m.dv), copy(m.ev))[1] +eigvals(m::SymTridiagonal, vl::Float64, vu::Float64) = LAPACK.stebz!('V', 'E', vl, vu, 0, 0, -1.0, copy(m.dv), copy(m.ev))[1] +eigvals(m::SymTridiagonal) = LAPACK.stebz!('A', 'E', 0.0, 0.0, 0, 0, -1.0, copy(m.dv), copy(m.ev))[1] + +#Computes largest and smallest eigenvalue +eigmax(m::SymTridiagonal) = eigvals(m, size(m, 1), size(m, 1))[1] +eigmin(m::SymTridiagonal) = eigvals(m, 1, 1)[1] + +#Compute selected eigenvectors only corresponding to particular eigenvalues +eigvecs(m::SymTridiagonal) = eig(m)[2] +eigvecs{Eigenvalue<:Real}(m::SymTridiagonal, eigvals::Vector{Eigenvalue}) = LAPACK.stein!(m.dv, m.ev, eigvals) + +## Tridiagonal matrices ## +type Tridiagonal{T} <: AbstractMatrix{T} + dl::Vector{T} # sub-diagonal + d::Vector{T} # diagonal + du::Vector{T} # sup-diagonal + dutmp::Vector{T} # scratch space for vector RHS solver, sup-diagonal + rhstmp::Vector{T}# scratch space, rhs + + function Tridiagonal(N::Integer) + dutmp = Array(T, N-1) + rhstmp = Array(T, N) + new(dutmp, rhstmp, dutmp, dutmp, rhstmp) # first three will be overwritten + end +end + +function Tridiagonal{T<:Number}(dl::Vector{T}, d::Vector{T}, du::Vector{T}) + N = length(d) + if (length(dl) != N-1 || length(du) != N-1) + error(string("Cannot make Tridiagonal from incompatible lengths of subdiagonal, diagonal and superdiagonal: (", length(dl), ", ", length(d), ", ", length(du),")")) + end + M = Tridiagonal{T}(N) + M.dl = copy(dl) + M.d = copy(d) + M.du = copy(du) + return M +end +function Tridiagonal{Tl<:Number, Td<:Number, Tu<:Number}(dl::Vector{Tl}, d::Vector{Td}, du::Vector{Tu}) + R = promote(Tl, Td, Tu) + Tridiagonal(convert(Vector{R}, dl), convert(Vector{R}, d), convert(Vector{R}, du)) +end + +size(M::Tridiagonal) = (length(M.d), length(M.d)) +size(M::Tridiagonal, d::Integer) = d<1 ? error("dimension out of range") : (d<=2 ? length(M.d) : 1) + +function show(io::IO, M::Tridiagonal) + println(io, summary(M), ":") + print(io, " sub: ") + print_matrix(io, (M.dl)') + print(io, "\ndiag: ") + print_matrix(io, (M.d)') + print(io, "\n sup: ") + print_matrix(io, (M.du)') +end +full{T}(M::Tridiagonal{T}) = convert(Matrix{T}, M) +function convert{T}(::Type{Matrix{T}}, M::Tridiagonal{T}) + A = zeros(T, size(M)) + for i = 1:length(M.d) + A[i,i] = M.d[i] + end + for i = 1:length(M.d)-1 + A[i+1,i] = M.dl[i] + A[i,i+1] = M.du[i] + end + return A +end +function similar(M::Tridiagonal, T, dims::Dims) + if length(dims) != 2 || dims[1] != dims[2] + error("Tridiagonal matrices must be square") + end + return Tridiagonal{T}(dims[1]) +end + +# Operations on Tridiagonal matrices +copy(A::Tridiagonal) = Tridiagonal(copy(A.dl), copy(A.d), copy(A.du)) +round(M::Tridiagonal) = Tridiagonal(round(M.dl), round(M.d), round(M.du)) +iround(M::Tridiagonal) = Tridiagonal(iround(M.dl), iround(M.d), iround(M.du)) + +conj(M::Tridiagonal) = Tridiagonal(conj(M.dl), conj(M.d), conj(M.du)) +transpose(M::Tridiagonal) = Tridiagonal(M.du, M.d, M.dl) +ctranspose(M::Tridiagonal) = conj(transpose(M)) + ++(A::Tridiagonal, B::Tridiagonal) = Tridiagonal(A.dl+B.dl, A.d+B.d, A.du+B.du) +-(A::Tridiagonal, B::Tridiagonal) = Tridiagonal(A.dl-B.dl, A.d-B.d, A.du+B.du) +*(A::Tridiagonal, B::Tridiagonal) = full(A)*full(B) +*(A::Tridiagonal, B::Number) = Tridiagonal(A.dl*B, A.d*B, A.du*B) +*(B::Number, A::SymTridiagonal) = A*B +/(A::Tridiagonal, B::Number) = Tridiagonal(A.dl/B, A.d/B, A.du/B) + +==(A::Tridiagonal, B::Tridiagonal) = (A.dl==B.dl) && (A.d==B.d) && (A.du==B.du) +==(A::Tridiagonal, B::SymTridiagonal) = (A.dl==A.du==B.ev) && (A.d==B.dv) +==(A::SymTridiagonal, B::SymTridiagonal) = B==A + +# Elementary operations that mix Tridiagonal and SymTridiagonal matrices +convert(::Type{Tridiagonal}, A::SymTridiagonal) = Tridiagonal(A.ev, A.dv, A.ev) ++(A::Tridiagonal, B::SymTridiagonal) = Tridiagonal(A.dl+B.ev, A.d+B.dv, A.du+B.ev) ++(A::SymTridiagonal, B::Tridiagonal) = Tridiagonal(A.ev+B.dl, A.dv+B.d, A.ev+B.du) +-(A::Tridiagonal, B::SymTridiagonal) = Tridiagonal(A.dl-B.ev, A.d-B.dv, A.du-B.ev) +-(A::SymTridiagonal, B::Tridiagonal) = Tridiagonal(A.ev-B.dl, A.dv-B.d, A.ev-B.du) +#XXX Returns dense matrix but really should be banded +*(A::SymTridiagonal, B::Tridiagonal) = full(A)*full(B) +*(A::Tridiagonal, B::SymTridiagonal) = full(A)*full(B) + +convert{T}(::Type{Tridiagonal{T}}, M::SymTridiagonal{T}) = Tridiagonal(M) +convert{T}(::Type{SymTridiagonal{T}}, M::Tridiagonal) = M.dl==M.du ? (SymTridiagonal(M.dl, M.d)) : + error("Tridiagonal is not symmetric, cannot convert to SymTridiagonal") + +## Solvers + +#### Tridiagonal matrix routines #### +function \{T<:BlasFloat}(M::Tridiagonal{T}, rhs::StridedVecOrMat{T}) + if stride(rhs, 1) == 1 + return LAPACK.gtsv!(copy(M.dl), copy(M.d), copy(M.du), copy(rhs)) + end + solve(M, rhs) # use the Julia "fallback" +end + +# This is definitely not going to work +#eig(M::Tridiagonal) = LAPACK.stev!('V', copy(M)) + +# Allocation-free variants +# Note that solve is non-aliasing, so you can use the same array for +# input and output +function solve(x::AbstractArray, xrng::Ranges{Int}, M::Tridiagonal, rhs::AbstractArray, rhsrng::Ranges{Int}) + d = M.d + N = length(d) + if length(xrng) != N || length(rhsrng) != N + error("dimension mismatch") + end + dl = M.dl + du = M.du + dutmp = M.dutmp + rhstmp = M.rhstmp + xstart = first(xrng) + xstride = step(xrng) + rhsstart = first(rhsrng) + rhsstride = step(rhsrng) + # Forward sweep + denom = d[1] + dulast = du[1] / denom + dutmp[1] = dulast + rhslast = rhs[rhsstart] / denom + rhstmp[1] = rhslast + irhs = rhsstart+rhsstride + for i in 2:N-1 + dltmp = dl[i-1] + denom = d[i] - dltmp*dulast + dulast = du[i] / denom + dutmp[i] = dulast + rhslast = (rhs[irhs] - dltmp*rhslast)/denom + rhstmp[i] = rhslast + irhs += rhsstride + end + dltmp = dl[N-1] + denom = d[N] - dltmp*dulast + xlast = (rhs[irhs] - dltmp*rhslast)/denom + # Backward sweep + ix = xstart + (N-2)*xstride + x[ix+xstride] = xlast + for i in N-1:-1:1 + xlast = rhstmp[i] - dutmp[i]*xlast + x[ix] = xlast + ix -= xstride + end + return x +end + +solve(x::StridedVector, M::Tridiagonal, rhs::StridedVector) = solve(x, 1:length(x), M, rhs, 1:length(rhs)) + +function solve(M::Tridiagonal, rhs::StridedVector) + x = similar(rhs) + solve(x, M, rhs) +end + +function solve(X::StridedMatrix, M::Tridiagonal, B::StridedMatrix) + if size(B, 1) != size(M, 1) + error("dimension mismatch") + end + if size(X) != size(B) + error("dimension mismatch in output") + end + m, n = size(B) + for j = 1:n + r = Range1((j-1)*m+1,m) + solve(X, r, M, B, r) + end + return X +end + +function solve(M::Tridiagonal, B::StridedMatrix) + X = similar(B) + solve(X, M, B) +end + +# User-friendly solver +\(M::Tridiagonal, rhs::Union(StridedVector,StridedMatrix)) = solve(M, rhs) + +# Tridiagonal multiplication +function mult(x::AbstractArray, xrng::Ranges{Int}, M::Tridiagonal, v::AbstractArray, vrng::Ranges{Int}) + dl = M.dl + d = M.d + du = M.du + N = length(d) + xi = first(xrng) + xstride = step(xrng) + vi = first(vrng) + vstride = step(vrng) + x[xi] = d[1]*v[vi] + du[1]*v[vi+vstride] + xi += xstride + for i = 2:N-1 + x[xi] = dl[i-1]*v[vi] + d[i]*v[vi+vstride] + du[i]*v[vi+2*vstride] + xi += xstride + vi += vstride + end + x[xi] = dl[N-1]*v[vi] + d[N]*v[vi+vstride] + return x +end + +mult(x::StridedVector, M::Tridiagonal, v::StridedVector) = mult(x, 1:length(x), M, v, 1:length(v)) + +function mult(X::StridedMatrix, M::Tridiagonal, B::StridedMatrix) + if size(B, 1) != size(M, 1) + error("dimension mismatch") + end + if size(X) != size(B) + error("dimension mismatch in output") + end + m, n = size(B) + for j = 1:n + r = Range1((j-1)*m+1,m) + mult(X, r, M, B, r) + end + return X +end + +mult(X::StridedMatrix, M1::Tridiagonal, M2::Tridiagonal) = mult(X, M1, full(M2)) + +function *(M::Tridiagonal, B::Union(StridedVector,StridedMatrix)) + X = similar(B) + mult(X, M, B) +end + +*(A::Tridiagonal, B::Tridiagonal) = A*full(B) + +#### Factorizations for Tridiagonal #### +type LDLTTridiagonal{T<:BlasFloat,S<:BlasFloat} <: Factorization{T} + D::Vector{S} + E::Vector{T} + function LDLTTridiagonal(D::Vector{S}, E::Vector{T}) + if typeof(real(E[1])) != eltype(D) error("Wrong eltype") end + new(D, E) + end +end + +LDLTTridiagonal{S<:BlasFloat,T<:BlasFloat}(D::Vector{S}, E::Vector{T}) = LDLTTridiagonal{T,S}(D, E) + +ldltd!{T<:BlasFloat}(A::SymTridiagonal{T}) = LDLTTridiagonal(LAPACK.pttrf!(real(A.dv),A.ev)...) +ldltd{T<:BlasFloat}(A::SymTridiagonal{T}) = ldltd!(copy(A)) + +function (\){T<:BlasFloat}(C::LDLTTridiagonal{T}, B::StridedVecOrMat{T}) + if iscomplex(B) return LAPACK.pttrs!('L', C.D, C.E, copy(B)) end + LAPACK.pttrs!(C.D, C.E, copy(B)) +end + +type LUTridiagonal{T} <: Factorization{T} + dl::Vector{T} + d::Vector{T} + du::Vector{T} + du2::Vector{T} + ipiv::Vector{BlasInt} + function LUTridiagonal(dl::Vector{T}, d::Vector{T}, du::Vector{T}, + du2::Vector{T}, ipiv::Vector{BlasInt}) + n = length(d) + if length(dl) != n - 1 || length(du) != n - 1 || length(ipiv) != n || length(du2) != n-2 + error("LUTridiagonal: dimension mismatch") + end + new(dl, d, du, du2, ipiv) + end +end +LUTridiagonal{T}(A::Tridiagonal{T}) = LUTridiagonal{T}(LAPACK.gttrf!(A.dl,A.d,A.du)...) + +#show(io, lu::LUTridiagonal) = print(io, "LU decomposition of ", summary(lu.lu)) + +function det{T}(lu::LUTridiagonal{T}) + n = length(lu.d) + prod(lu.d) * (bool(sum(lu.ipiv .!= 1:n) % 2) ? -one(T) : one(T)) +end + +det(A::Tridiagonal) = det(LUTridiagonal(copy(A))) + +(\){T<:BlasFloat}(lu::LUTridiagonal{T}, B::StridedVecOrMat{T}) = + LAPACK.gttrs!('N', lu.dl, lu.d, lu.du, lu.du2, lu.ipiv, copy(B)) diff --git a/base/linalg/umfpack.jl b/base/linalg/umfpack.jl new file mode 100644 index 0000000000000..83945099dacdb --- /dev/null +++ b/base/linalg/umfpack.jl @@ -0,0 +1,355 @@ +module UMFPACK + +export UmfpackLU, + + decrement, + decrement!, + increment, + increment! + +import Base.(\) +import Base.Ac_ldiv_B +import Base.At_ldiv_B +import Base.findnz +import Base.getindex +import Base.nnz +import Base.show +import Base.size + +import LinAlg.Factorization +import LinAlg.det +import LinAlg.lufact +import LinAlg.lufact! +import LinAlg.solve + +include("linalg/umfpack_h.jl") + +type MatrixIllConditionedException <: Exception end + +function decrement!{T<:Integer}(A::AbstractArray{T}) + for i in 1:length(A) A[i] -= one(T) end + A +end +decrement{T<:Integer}(A::AbstractArray{T}) = decrement!(copy(A)) +function increment!{T<:Integer}(A::AbstractArray{T}) + for i in 1:length(A) A[i] += one(T) end + A +end +increment{T<:Integer}(A::AbstractArray{T}) = increment!(copy(A)) + +typealias UMFVTypes Union(Float64,Complex128) +typealias UMFITypes Union(Int32,Int64) + +## UMFPACK + +# the control and info arrays +const umf_ctrl = Array(Float64, UMFPACK_CONTROL) +ccall((:umfpack_dl_defaults,:libumfpack), Void, (Ptr{Float64},), umf_ctrl) +const umf_info = Array(Float64, UMFPACK_INFO) + +function show_umf_ctrl(level::Real) + old_prt::Float64 = umf_ctrl[1] + umf_ctrl[1] = float64(level) + ccall((:umfpack_dl_report_control, :libumfpack), Void, (Ptr{Float64},), umf_ctrl) + umf_ctrl[1] = old_prt +end +show_umf_ctrl() = show_umf_ctrl(2.) + +function show_umf_info(level::Real) + old_prt::Float64 = umf_ctrl[1] + umf_ctrl[1] = float64(level) + ccall((:umfpack_dl_report_info, :libumfpack), Void, + (Ptr{Float64}, Ptr{Float64}), umf_ctrl, umf_info) + umf_ctrl[1] = old_prt +end +show_umf_info() = show_umf_info(2.) + +## Should this type be immutable? +type UmfpackLU{Tv<:UMFVTypes,Ti<:UMFITypes} <: Factorization{Tv} + symbolic::Ptr{Void} + numeric::Ptr{Void} + m::Int + n::Int + colptr::Vector{Ti} # 0-based column pointers + rowval::Vector{Ti} # 0-based row indices + nzval::Vector{Tv} +end + +function lufact{Tv<:UMFVTypes,Ti<:UMFITypes}(S::SparseMatrixCSC{Tv,Ti}) + zerobased = S.colptr[1] == 0 + res = UmfpackLU(C_NULL, C_NULL, S.m, S.n, + zerobased ? copy(S.colptr) : decrement(S.colptr), + zerobased ? copy(S.rowval) : decrement(S.rowval), + copy(S.nzval)) + finalizer(res, umfpack_free_symbolic) + umfpack_numeric!(res) +end + +function lufact!{Tv<:UMFVTypes,Ti<:UMFITypes}(S::SparseMatrixCSC{Tv,Ti}) + zerobased = S.colptr[1] == 0 + res = UmfpackLU(C_NULL, C_NULL, S.m, S.n, + zerobased ? S.colptr : decrement!(S.colptr), + zerobased ? S.rowval : decrement!(S.rowval), + S.nzval) + finalizer(res, umfpack_free_symbolic) + umfpack_numeric!(res) +end + +function show(io::IO, f::UmfpackLU) + @printf(io, "UMFPACK LU Factorization of a %d-by-%d sparse matrix\n", + f.m, f.n) + if f.numeric != C_NULL println(f.numeric) end +end + +## Wrappers for UMFPACK functions + +for (sym_r,sym_c,num_r,num_c,sol_r,sol_c,det_r,det_z,lunz,get_num_r,get_num_z,itype) in + (("umfpack_di_symbolic","umfpack_zi_symbolic", + "umfpack_di_numeric","umfpack_zi_numeric", + "umfpack_di_solve","umfpack_zi_solve", + "umfpack_di_get_determinant","umfpack_zi_get_determinant", + "umfpack_di_get_lunz","umfpack_di_get_numeric","umfpack_zi_get_numeric",:Int32), + ("umfpack_dl_symbolic","umfpack_zl_symbolic", + "umfpack_dl_numeric","umfpack_zl_numeric", + "umfpack_dl_solve","umfpack_zl_solve", + "umfpack_dl_get_determinant","umfpack_zl_get_determinant", + "umfpack_dl_get_lunz","umfpack_dl_get_numeric","umfpack_zl_get_numeric",:Int64)) + @eval begin + function umfpack_symbolic!{Tv<:Float64,Ti<:$itype}(U::UmfpackLU{Tv,Ti}) + if U.symbolic != C_NULL return U end + tmp = Array(Ptr{Void},1) + status = ccall(($sym_r, :libumfpack), Ti, + (Ti, Ti, Ptr{Ti}, Ptr{Ti}, Ptr{Tv}, Ptr{Void}, + Ptr{Float64}, Ptr{Float64}), + U.m, U.n, U.colptr, U.rowval, U.nzval, tmp, + umf_ctrl, umf_info) + if status != UMFPACK_OK; error("Error code $status from symbolic factorization"); end + U.symbolic = tmp[1] + U + end + function umfpack_symbolic!{Tv<:Complex128,Ti<:$itype}(U::UmfpackLU{Tv,Ti}) + if U.symbolic != C_NULL return U end + tmp = Array(Ptr{Void},1) + status = ccall(($sym_r, :libumfpack), Ti, + (Ti, Ti, Ptr{Ti}, Ptr{Ti}, Ptr{Float64}, Ptr{Float64}, Ptr{Void}, + Ptr{Float64}, Ptr{Float64}), + U.m, U.n, U.colptr, U.rowval, real(U.nzval), imag(U.nzval), tmp, + umf_ctrl, umf_info) + if status != UMFPACK_OK; error("Error code $status from symbolic factorization"); end + U.symbolic = tmp[1] + U + end + function umfpack_numeric!{Tv<:Float64,Ti<:$itype}(U::UmfpackLU{Tv,Ti}) + if U.numeric != C_NULL return U end + if U.symbolic == C_NULL umfpack_symbolic!(U) end + tmp = Array(Ptr{Void}, 1) + status = ccall(($num_r, :libumfpack), Ti, + (Ptr{Ti}, Ptr{Ti}, Ptr{Float64}, Ptr{Void}, Ptr{Void}, + Ptr{Float64}, Ptr{Float64}), + U.colptr, U.rowval, U.nzval, U.symbolic, tmp, + umf_ctrl, umf_info) + if status > 0; throw(MatrixIllConditionedException); end + if status != UMFPACK_OK; error("Error code $status from numeric factorization"); end + U.numeric = tmp[1] + U + end + function umfpack_numeric!{Tv<:Complex128,Ti<:$itype}(U::UmfpackLU{Tv,Ti}) + if U.numeric != C_NULL return U end + if U.symbolic == C_NULL umfpack_symbolic!(U) end + tmp = Array(Ptr{Void}, 1) + status = ccall(($num_r, :libumfpack), Ti, + (Ptr{Ti}, Ptr{Ti}, Ptr{Float64}, Ptr{Float64}, Ptr{Void}, Ptr{Void}, + Ptr{Float64}, Ptr{Float64}), + U.colptr, U.rowval, real(U.nzval), imag(U.nzval), U.symbolic, tmp, + umf_ctrl, umf_info) + if status > 0; throw(MatrixIllConditionedException); end + if status != UMFPACK_OK; error("Error code $status from numeric factorization"); end + U.numeric = tmp[1] + U + end + function solve{Tv<:Float64,Ti<:$itype}(lu::UmfpackLU{Tv,Ti}, b::Vector{Tv}, typ::Integer) + umfpack_numeric!(lu) + x = similar(b) + status = ccall(($sol_r, :libumfpack), Ti, + (Ti, Ptr{Ti}, Ptr{Ti}, Ptr{Float64}, Ptr{Float64}, + Ptr{Float64}, Ptr{Void}, Ptr{Float64}, Ptr{Float64}), + typ, lu.colptr, lu.rowval, lu.nzval, x, b, lu.numeric, umf_ctrl, umf_info) + if status != UMFPACK_OK; error("Error code $status in umfpack_solve"); end + return x + end + function solve{Tv<:Complex128,Ti<:$itype}(lu::UmfpackLU{Tv,Ti}, b::Vector{Tv}, typ::Integer) + umfpack_numeric!(lu) + xr = similar(b, Float64) + xi = similar(b, Float64) + status = ccall(($sol_c, :libumfpack), + Ti, + (Ti, Ptr{Ti}, Ptr{Ti}, Ptr{Float64}, Ptr{Float64}, + Ptr{Float64}, Ptr{Float64}, Ptr{Float64}, Ptr{Float64}, + Ptr{Void}, Ptr{Float64}, Ptr{Float64}), + typ, lu.colptr, lu.rowval, real(lu.nzval), imag(lu.nzval), + xr, xi, real(b), imag(b), + lu.num, umf_ctrl, umf_info) + if status != UMFPACK_OK; error("Error code $status from umfpack_solve"); end + return complex(xr,xi) + end + function det{Tv<:Float64,Ti<:$itype}(lu::UmfpackLU{Tv,Ti}) + mx = Array(Tv,1) + status = ccall(($det_r,:libumfpack), Ti, + (Ptr{Tv},Ptr{Tv},Ptr{Void},Ptr{Float64}), + mx, C_NULL, lu.numeric, umf_info) + if status != UMFPACK_OK error("Error code $status from umfpack_get_determinant") end + mx[1] + end + function det{Tv<:Complex128,Ti<:$itype}(lu::UmfpackLU{Tv,Ti}) + mx = Array(Float64,1) + mz = Array(Float64,1) + status = ccall(($det_z,:libumfpack), Ti, + (Ptr{Float64},Ptr{Float64},Ptr{Float64},Ptr{Void},Ptr{Float64}), + mx, mz, C_NULL, lu.numeric, umf_info) + if status != UMFPACK_OK error("Error code $status from umfpack_get_determinant") end + complex(mx[1], mz[1]) + end + function umf_lunz{Tv<:UMFVTypes,Ti<:$itype}(lu::UmfpackLU{Tv,Ti}) + lnz = Array(Ti, 1) + unz = Array(Ti, 1) + n_row = Array(Ti, 1) + n_col = Array(Ti, 1) + nz_diag = Array(Ti, 1) + status = ccall(($lunz,:libumfpack), Ti, + (Ptr{Ti},Ptr{Ti},Ptr{Ti},Ptr{Ti},Ptr{Ti},Ptr{Void}), + lnz, unz, n_row, n_col, nz_diag, lu.numeric) + if status != UMFPACK_OK error("Error code $status from umfpack_get_lunz") end + (lnz[1], unz[1], n_row[1], n_col[1], nz_diag[1]) + end + function umf_extract{Tv<:Float64,Ti<:$itype}(lu::UmfpackLU{Tv,Ti}) + umfpack_numeric!(lu) # ensure the numeric decomposition exists + (lnz,unz,n_row,n_col,nz_diag) = umf_lunz(lu) + Lp = Array(Ti, n_col + 1) + Lj = Array(Ti, lnz) # L is returned in CSR (compressed sparse row) format + Lx = Array(Tv, lnz) + Up = Array(Ti, n_col + 1) + Ui = Array(Ti, unz) + Ux = Array(Tv, unz) + P = Array(Ti, n_row) + Q = Array(Ti, n_col) + Rs = Array(Tv, n_row) + status = ccall(($get_num_r,:libumfpack), Ti, + (Ptr{Ti},Ptr{Ti},Ptr{Tv}, + Ptr{Ti},Ptr{Ti},Ptr{Tv}, + Ptr{Ti},Ptr{Ti},Ptr{Void}, + Ptr{Ti},Ptr{Tv},Ptr{Void}), + Lp,Lj,Lx, + Up,Ui,Ux, + P, Q, C_NULL, + &0, Rs, lu.numeric) + if status != UMFPACK_OK error("Error code $status from numeric") end + (transpose(SparseMatrixCSC(n_row,n_row,increment!(Lp),increment!(Lj),Lx)), + SparseMatrixCSC(n_row,n_col,increment!(Up),increment!(Ui),Ux), + increment!(P), increment!(Q), Rs) + end + end +end + +### Solve with Factorization + +(\){T<:UMFVTypes}(fact::UmfpackLU{T}, b::Vector{T}) = solve(fact, b) +(\){Ts<:UMFVTypes,Tb<:Number}(fact::UmfpackLU{Ts}, b::Vector{Tb}) = fact\convert(Vector{Ts},b) +At_ldiv_B{T<:UMFVTypes}(fact::UmfpackLU{T}, b::Vector{T}) = solve(fact, b, UMFPACK_Aat) +At_ldiv_B{Ts<:UMFVTypes,Tb<:Number}(fact::UmfpackLU{Ts}, b::Vector{Tb}) = fact.'\convert(Vector{Ts},b) +Ac_ldiv_B{T<:UMFVTypes}(fact::UmfpackLU{T}, b::Vector{T}) = solve(fact, b, UMFPACK_At) +Ac_ldiv_B{Ts<:UMFVTypes,Tb<:Number}(fact::UmfpackLU{Ts}, b::Vector{Tb}) = fact'\convert(Vector{Ts},b) + +### Solve directly with matrix + +(\)(S::SparseMatrixCSC, b::Vector) = lufact(S) \ b +At_ldiv_B{T<:UMFVTypes}(S::SparseMatrixCSC{T}, b::Vector{T}) = solve(lufact(S), b, UMFPACK_Aat) +function At_ldiv_B{Ts<:UMFVTypes,Tb<:Number}(S::SparseMatrixCSC{Ts}, b::Vector{Tb}) + ## should be more careful here in case Ts<:Real and Tb<:Complex + At_ldiv_B(S, convert(Vector{Ts}, b)) +end +Ac_ldiv_B{T<:UMFVTypes}(S::SparseMatrixCSC{T}, b::Vector{T}) = solve(lufact(S), b, UMFPACK_At) +function Ac_ldiv_B{Ts<:UMFVTypes,Tb<:Number}(S::SparseMatrixCSC{Ts}, b::Vector{Tb}) + ## should be more careful here in case Ts<:Real and Tb<:Complex + Ac_ldiv_B(S, convert(Vector{Ts}, b)) +end + +solve(lu::UmfpackLU, b::Vector) = solve(lu, b, UMFPACK_A) + +function getindex(lu::UmfpackLU, d::Symbol) + L,U,p,q,Rs = umf_extract(lu) + d == :L ? L : + (d == :U ? U : + (d == :p ? p : + (d == :q ? q : + (d == :Rs ? Rs : + (d == :(:) ? (L,U,p,q,Rs) : + error("No component for symbol $d")))))) +end + +## The C functions called by these Julia functions do not depend on +## the numeric and index types, even though the umfpack names indicate +## they do. The umfpack_free_* functions can be called on C_NULL without harm. +function umfpack_free_symbolic(symb::Ptr{Void}) + tmp = [symb] + ccall((:umfpack_dl_free_symbolic, :libumfpack), Void, (Ptr{Void},), tmp) +end +show_umf_info() = show_umf_info(2.) + +function umfpack_free_symbolic(lu::UmfpackLU) + if lu.symbolic == C_NULL return lu end + umfpack_free_numeric(lu) + umfpack_free_symbolic(lu.symbolic) + lu.symbolic = C_NULL + lu +end + +function umfpack_free_numeric(num::Ptr{Void}) + tmp = [num] + ccall((:umfpack_dl_free_numeric, :libumfpack), Void, (Ptr{Void},), tmp) +end + +function umfpack_free_numeric(lu::UmfpackLU) + if lu.numeric == C_NULL return lu end + umfpack_free_numeric(lu.numeric) + lu.numeric = C_NULL + lu +end + +function umfpack_report_symbolic(symb::Ptr{Void}, level::Real) + old_prl::Float64 = umf_ctrl[UMFPACK_PRL] + umf_ctrl[UMFPACK_PRL] = float64(level) + status = ccall((:umfpack_dl_report_symbolic, :libumfpack), Int, + (Ptr{Void}, Ptr{Float64}), symb, umf_ctrl) + umf_ctrl[UMFPACK_PRL] = old_prl + if status != 0 + error("Error code $status from umfpack_report_symbolic") + end +end + +umfpack_report_symbolic(symb::Ptr{Void}) = umfpack_report_symbolic(symb, 4.) + +function umfpack_report_symbolic(lu::UmfpackLU, level::Real) + umfpack_report_symbolic(umfpack_symbolic!(lu).symbolic, level) +end + +umfpack_report_symbolic(lu::UmfpackLU) = umfpack_report_symbolic(lu.symbolic,4.) +function umfpack_report_numeric(num::Ptr{Void}, level::Real) + old_prl::Float64 = umf_ctrl[UMFPACK_PRL] + umf_ctrl[UMFPACK_PRL] = float64(level) + status = ccall((:umfpack_dl_report_numeric, :libumfpack), Int, + (Ptr{Void}, Ptr{Float64}), num, umf_ctrl) + umf_ctrl[UMFPACK_PRL] = old_prl + if status != 0 + error("Error code $status from umfpack_report_numeric") + end +end + +umfpack_report_numeric(num::Ptr{Void}) = umfpack_report_numeric(num, 4.) +function umfpack_report_numeric(lu::UmfpackLU, level::Real) + umfpack_report_numeric(umfpack_numeric!(lu).numeric, level) +end + +umfpack_report_numeric(lu::UmfpackLU) = umfpack_report_numeric(lu,4.) + +end # UMFPACK module + diff --git a/base/linalg/umfpack_h.jl b/base/linalg/umfpack_h.jl new file mode 100644 index 0000000000000..6f30f21f93553 --- /dev/null +++ b/base/linalg/umfpack_h.jl @@ -0,0 +1,41 @@ +## UMFPACK + +## Type of solve +const UMFPACK_A = 0 # Ax=b +const UMFPACK_At = 1 # A'x=b +const UMFPACK_Aat = 2 # A.'x=b +const UMFPACK_Pt_L = 3 # P'Lx=b +const UMFPACK_L = 4 # Lx=b +const UMFPACK_Lt_P = 5 # L'Px=b +const UMFPACK_Lat_P = 6 # L.'Px=b +const UMFPACK_Lt = 7 # L'x=b +const UMFPACK_Lat = 8 # L.'x=b +const UMFPACK_U_Qt = 9 # UQ'x=b +const UMFPACK_U = 10 # Ux=b +const UMFPACK_Q_Ut = 11 # QU'x=b +const UMFPACK_Q_Uat = 12 # QU.'x=b +const UMFPACK_Ut = 13 # U'x=b +const UMFPACK_Uat = 14 # U.'x=b + +## Sizes of Control and Info arrays for returning information from solver +const UMFPACK_INFO = 90 +const UMFPACK_CONTROL = 20 +const UMFPACK_PRL = 1 + +## Status codes +const UMFPACK_OK = 0 +const UMFPACK_WARNING_singular_matrix = 1 +const UMFPACK_WARNING_determinant_underflow = 2 +const UMFPACK_WARNING_determinant_overflow = 3 +const UMFPACK_ERROR_out_of_memory = -1 +const UMFPACK_ERROR_invalid_Numeric_object = -3 +const UMFPACK_ERROR_invalid_Symbolic_object = -4 +const UMFPACK_ERROR_argument_missing = -5 +const UMFPACK_ERROR_n_nonpositive = -6 +const UMFPACK_ERROR_invalid_matrix = -8 +const UMFPACK_ERROR_different_pattern = -11 +const UMFPACK_ERROR_invalid_system = -13 +const UMFPACK_ERROR_invalid_permutation = -15 +const UMFPACK_ERROR_internal_error = -911 +const UMFPACK_ERROR_file_IO = -17 +const UMFPACK_ERROR_ordering_failed = -18 diff --git a/base/linalg/woodbury.jl b/base/linalg/woodbury.jl new file mode 100644 index 0000000000000..4e502927d17ce --- /dev/null +++ b/base/linalg/woodbury.jl @@ -0,0 +1,129 @@ +#### Woodbury matrices #### +# This type provides support for the Woodbury matrix identity +type Woodbury{T} <: AbstractMatrix{T} + A + U::Matrix{T} + C + Cp + V::Matrix{T} + tmpN1::Vector{T} + tmpN2::Vector{T} + tmpk1::Vector{T} + tmpk2::Vector{T} + + function Woodbury(A::AbstractMatrix{T}, U::Matrix{T}, C, V::Matrix{T}) + N = size(A, 1) + k = size(U, 2) + if size(A, 2) != N || size(U, 1) != N || size(V, 1) != k || size(V, 2) != N + error("Sizes do not match") + end + if k > 1 + if size(C, 1) != k || size(C, 2) != k + error("Size of C is incorrect") + end + end + Cp = inv(inv(C) + V*(A\U)) + # temporary space for allocation-free solver + tmpN1 = Array(T, N) + tmpN2 = Array(T, N) + tmpk1 = Array(T, k) + tmpk2 = Array(T, k) + # don't copy A, it could be huge + new(A, copy(U), copy(C), Cp, copy(V), tmpN1, tmpN2, tmpk1, tmpk2) + end +end + +Woodbury{T}(A::AbstractMatrix{T}, U::Matrix{T}, C, V::Matrix{T}) = Woodbury{T}(A, U, C, V) + +Woodbury{T}(A::AbstractMatrix{T}, U::Vector{T}, C, V::Matrix{T}) = Woodbury{T}(A, reshape(U, length(U), 1), C, V) + +size(W::Woodbury) = size(W.A) + +function show(io::IO, W::Woodbury) + println(io, summary(W), ":") + print(io, "A: ", W.A) + print(io, "\nU:\n") + print_matrix(io, W.U) + if isa(W.C, Matrix) + print(io, "\nC:\n") + print_matrix(io, W.C) + else + print(io, "\nC: ", W.C) + end + print(io, "\nV:\n") + print_matrix(io, W.V) +end + +full{T}(W::Woodbury{T}) = convert(Matrix{T}, W) + +convert{T}(::Type{Matrix{T}}, W::Woodbury{T}) = full(W.A) + W.U*W.C*W.V + +function similar(W::Woodbury, T, dims::Dims) + if length(dims) != 2 || dims[1] != dims[2] + error("Woodbury matrices must be square") + end + n = size(W, 1) + k = size(W.U, 2) + return Woodbury{T}(similar(W.A), Array(T, n, k), Array(T, k, k), Array(T, k, n)) +end + +copy(W::Woodbury) = Woodbury(W.A, W.U, W.C, W.V) + +## Woodbury matrix routines ## + +function *(W::Woodbury, B::StridedVecOrMat) + return W.A*B + W.U*(W.C*(W.V*B)) +end + +function \(W::Woodbury, R::StridedVecOrMat) + AinvR = W.A\R + return AinvR - W.A\(W.U*(W.Cp*(W.V*AinvR))) +end + +function det(W::Woodbury) + det(W.A)*det(W.C)/det(W.Cp) +end + +# Allocation-free solver for arbitrary strides (requires that W.A has a +# non-aliasing "solve" routine, e.g., is Tridiagonal) +function solve(x::AbstractArray, xrng::Ranges{Int}, W::Woodbury, rhs::AbstractArray, rhsrng::Ranges{Int}) + solve(W.tmpN1, 1:length(W.tmpN1), W.A, rhs, rhsrng) + A_mul_B(W.tmpk1, W.V, W.tmpN1) + A_mul_B(W.tmpk2, W.Cp, W.tmpk1) + A_mul_B(W.tmpN2, W.U, W.tmpk2) + solve(W.tmpN2, W.A, W.tmpN2) + indx = first(xrng) + xinc = step(xrng) + for i = 1:length(W.tmpN2) + x[indx] = W.tmpN1[i] - W.tmpN2[i] + indx += xinc + end +end + +solve(x::AbstractVector, W::Woodbury, rhs::AbstractVector) = solve(x, 1:length(x), W, rhs, 1:length(rhs)) + +function solve(W::Woodbury, rhs::AbstractVector) + x = similar(rhs) + solve(x, W, rhs) +end + +function solve(X::StridedMatrix, W::Woodbury, B::StridedMatrix) + if size(B, 1) != size(W, 1) + error("dimension mismatch") + end + if size(X) != size(B) + error("dimension mismatch in output") + end + m, n = size(B) + r = 1:m + for j = 1:n + r.start = (j-1)*m+1 + solve(X, r, W, B, r) + end + return X +end + +function solve(W::Woodbury, B::StridedMatrix) + X = similar(B) + solve(X, W, B) +end diff --git a/base/linalg_dense.jl b/base/linalg_dense.jl deleted file mode 100644 index b1c832089b0e1..0000000000000 --- a/base/linalg_dense.jl +++ /dev/null @@ -1,1196 +0,0 @@ -function issym(A::Matrix) - m, n = size(A) - if m != n; error("matrix must be square, got $(m)x$(n)"); end - for i = 1:(n-1), j = (i+1):n - if A[i,j] != A[j,i] - return false - end - end - return true -end - -function ishermitian(A::Matrix) - m, n = size(A) - if m != n; error("matrix must be square, got $(m)x$(n)"); end - for i = 1:n, j = i:n - if A[i,j] != conj(A[j,i]) - return false - end - end - return true -end - -function istriu(A::Matrix) - m, n = size(A) - for j = 1:min(n,m-1), i = j+1:m - if A[i,j] != 0 - return false - end - end - return true -end - -function istril(A::Matrix) - m, n = size(A) - for j = 2:n, i = 1:min(j-1,m) - if A[i,j] != 0 - return false - end - end - return true -end - -#Test whether a matrix is positive-definite - -isposdef!{T<:LapackType}(A::Matrix{T}, upper::Bool) = - LAPACK.potrf!(upper ? 'U' : 'L', A)[2] == 0 -isposdef!{T<:LapackType}(A::Matrix{T}) = ishermitian(A) && isposdef!(A, true) - -isposdef{T<:LapackType}(A::Matrix{T}, upper::Bool) = isposdef!(copy(A), upper) -isposdef{T<:LapackType}(A::Matrix{T}) = isposdef!(copy(A)) -isposdef{T<:Number}(A::Matrix{T}, upper::Bool) = isposdef!(float64(A), upper) -isposdef{T<:Number}(A::Matrix{T}) = isposdef!(float64(A)) - -norm{T<:LapackType}(x::Vector{T}) = BLAS.nrm2(length(x), x, 1) - -function norm{T<:LapackType, TI<:Integer}(x::Vector{T}, rx::Union(Range1{TI},Range{TI})) - if min(rx) < 1 || max(rx) > length(x) - throw(BoundsError()) - end - BLAS.nrm2(length(rx), pointer(x)+(first(rx)-1)*sizeof(T), step(rx)) -end - -function triu!{T}(M::Matrix{T}, k::Integer) - m, n = size(M) - idx = 1 - for j = 0:n-1 - ii = min(max(0, j+1-k), m) - for i = (idx+ii):(idx+m-1) - M[i] = zero(T) - end - idx += m - end - return M -end - -triu(M::Matrix, k::Integer) = triu!(copy(M), k) - -function tril!{T}(M::Matrix{T}, k::Integer) - m, n = size(M) - idx = 1 - for j = 0:n-1 - ii = min(max(0, j-k), m) - for i = idx:(idx+ii-1) - M[i] = zero(T) - end - idx += m - end - return M -end - -tril(M::Matrix, k::Integer) = tril!(copy(M), k) - -diff(a::Vector) = [ a[i+1] - a[i] for i=1:length(a)-1 ] - -function diff(a::Matrix, dim::Integer) - if dim == 1 - [ a[i+1,j] - a[i,j] for i=1:size(a,1)-1, j=1:size(a,2) ] - else - [ a[i,j+1] - a[i,j] for i=1:size(a,1), j=1:size(a,2)-1 ] - end -end - -function gradient(F::Vector, h::Vector) - n = length(F) - g = similar(F) - if n > 0 - g[1] = 0 - end - if n > 1 - g[1] = (F[2] - F[1]) / (h[2] - h[1]) - g[n] = (F[n] - F[n-1]) / (h[end] - h[end-1]) - end - if n > 2 - h = h[3:n] - h[1:n-2] - g[2:n-1] = (F[3:n] - F[1:n-2]) ./ h - end - return g -end - -diag(A::Matrix) = [ A[i,i] for i=1:min(size(A,1),size(A,2)) ] - -function diagm{T}(v::Union(Vector{T},Matrix{T})) - if isa(v, Matrix) - if (size(v,1) != 1 && size(v,2) != 1) - error("Input should be nx1 or 1xn") - end - end - - n = numel(v) - a = zeros(T, n, n) - for i=1:n - a[i,i] = v[i] - end - - return a -end - -function trace{T}(A::Matrix{T}) - t = zero(T) - for i=1:min(size(A)) - t += A[i,i] - end - return t -end - -kron(a::Vector, b::Vector) = [ a[i]*b[j] for i=1:length(a), j=1:length(b) ] - -function kron{T,S}(a::Matrix{T}, b::Matrix{S}) - R = Array(promote_type(T,S), size(a,1)*size(b,1), size(a,2)*size(b,2)) - - m = 1 - for j = 1:size(a,2) - for l = 1:size(b,2) - for i = 1:size(a,1) - aij = a[i,j] - for k = 1:size(b,1) - R[m] = aij*b[k,l] - m += 1 - end - end - end - end - R -end - -function randsym(n) - a = randn(n,n) - for j=1:n-1, i=j+1:n - x = (a[i,j]+a[j,i])/2 - a[i,j] = x - a[j,i] = x - end - a -end - -^(A::Matrix, p::Integer) = p < 0 ? inv(A^-p) : power_by_squaring(A,p) - -function ^(A::Matrix, p::Number) - if integer_valued(p) - ip = integer(real(p)) - if ip < 0 - return inv(power_by_squaring(A, -ip)) - else - return power_by_squaring(A, ip) - end - end - if size(A,1) != size(A,2) - error("matrix must be square") - end - (v, X) = eig(A) - if isreal(v) && any(v.<0) - v = complex(v) - end - if ishermitian(A) - Xinv = X' - else - Xinv = inv(X) - end - diagmm(X, v.^p)*Xinv -end - -function rref{T}(A::Matrix{T}) - nr, nc = size(A) - U = copy_to(similar(A,Float64), A) - e = eps(norm(U,Inf)) - i = j = 1 - while i <= nr && j <= nc - (m, mi) = findmax(abs(U[i:nr,j])) - mi = mi+i - 1 - if m <= e - U[i:nr,j] = 0 - j += 1 - else - for k=j:nc - U[i, k], U[mi, k] = U[mi, k], U[i, k] - end - d = U[i,j] - for k = j:nc - U[i,k] /= d - end - for k = 1:nr - if k != i - d = U[k,j] - for l = j:nc - U[k,l] -= d*U[i,l] - end - end - end - i += 1 - j += 1 - end - end - return U -end - -## Destructive matrix exponential using algorithm from Higham, 2008, -## "Functions of Matrices: Theory and Computation", SIAM -function expm!{T<:LapackType}(A::StridedMatrix{T}) - m, n = size(A) - if m != n error("expm!: Matrix A must be square") end - if m < 2 return exp(A) end - ilo, ihi, scale = LAPACK.gebal!('B', A) # modifies A - nA = norm(A, 1) - I = eye(T,n) - ## For sufficiently small nA, use lower order Padé-Approximations - if (nA <= 2.1) - if nA > 0.95 - C = T[17643225600.,8821612800.,2075673600.,302702400., - 30270240., 2162160., 110880., 3960., - 90., 1.] - elseif nA > 0.25 - C = T[17297280.,8648640.,1995840.,277200., - 25200., 1512., 56., 1.] - elseif nA > 0.015 - C = T[30240.,15120.,3360., - 420., 30., 1.] - else - C = T[120.,60.,12.,1.] - end - A2 = A * A - P = copy(I) -# U = C[2] * P -# V = C[1] * P - U = zeros(T, n, n) - V = zeros(T, n, n) - C2 = C[2]; C1 = C[1] - for i=1:n - U[i,i] = C2 - V[i,i] = C1 - end - for k in 1:(div(size(C, 1), 2) - 1) - k2 = 2 * k - P *= A2 - #U += C[k2 + 2] * P - #V += C[k2 + 1] * P - Ck21 = C[k2 + 1] - Ck22 = C[k2 + 2] - for i=1:length(P) - U[i] += Ck22 * P[i] - V[i] += Ck21 * P[i] - end - end - U = A * U - #X = (V - U)\(V + U) - X = V + U - LAPACK.gesv!(V-U, X) - else - s = log2(nA/5.4) # power of 2 later reversed by squaring - if s > 0 - si = iceil(s) - A /= oftype(T,2^si) - end - CC = T[64764752532480000.,32382376266240000.,7771770303897600., - 1187353796428800., 129060195264000., 10559470521600., - 670442572800., 33522128640., 1323241920., - 40840800., 960960., 16380., - 182., 1.] - A2 = A * A - A4 = A2 * A2 - A6 = A2 * A4 -# U = A * (A6 * (CC[14]*A6 + CC[12]*A4 + CC[10]*A2) + -# CC[8]*A6 + CC[6]*A4 + CC[4]*A2 + CC[2]*I) -# V = A6 * (CC[13]*A6 + CC[11]*A4 + CC[9]*A2) + -# CC[7]*A6 + CC[5]*A4 + CC[3]*A2 + CC[1]*I - P1 = zeros(T, n, n) - P2 = zeros(T, n, n) - P3 = zeros(T, n, n) - P4 = zeros(T, n, n) - CC14 = CC[14]; CC12 = CC[12]; CC10 = CC[10] - CC8 = CC[8]; CC6 = CC[6]; CC4 = CC[4]; CC2 = CC[2]; - CC13 = CC[13]; CC11 = CC[11]; CC9 = CC[9] - CC7 = CC[7]; CC5 = CC[5]; CC3 = CC[3]; CC1 = CC[1] - for i=1:length(I) - P1[i] += CC14*A6[i] + CC12*A4[i] + CC10*A2[i] - P2[i] += CC8*A6[i] + CC6*A4[i] + CC4*A2[i] + CC2*I[i] - P3[i] += CC13*A6[i] + CC11*A4[i] + CC9*A2[i] - P4[i] += CC7*A6[i] + CC5*A4[i] + CC3*A2[i] + CC1*I[i] - end - #U = A * (A6*P1 + P2) - #V = A6*P3 + P4 - U = A * (BLAS.gemm!('N', 'N', one(T), A6, P1, one(T), P2)) - V = BLAS.gemm!('N', 'N', one(T), A6, P3, one(T), P4) - - #X = (V-U)\(V+U) - X = V + U - LAPACK.gesv!(V-U, X) - - if s > 0 # squaring to reverse dividing by power of 2 - for t in 1:si X *= X end - end - end - # Undo the balancing - doscale = false # check if rescaling is needed - for i = ilo:ihi - if scale[i] != 1. - doscale = true - break - end - end - if doscale - for j = ilo:ihi - scj = scale[j] - if scj != 1. # is this overkill? - for i = ilo:ihi - X[i,j] *= scale[i]/scj - end - else - for i = ilo:ihi - X[i,j] *= scale[i] - end - end - end - end - if ilo > 1 # apply lower permutations in reverse order - for j in (ilo-1):1:-1 rcswap!(j, int(scale[j]), X) end - end - if ihi < n # apply upper permutations in forward order - for j in (ihi+1):n rcswap!(j, int(scale[j]), X) end - end - X -end - -## Swap rows j and jp and columns j and jp in X -function rcswap!{T<:Number}(j::Int, jp::Int, X::StridedMatrix{T}) - for k in 1:size(X, 2) - tmp = X[k,j] - X[k,j] = X[k,jp] - X[k,jp] = tmp - tmp = X[j,k] - X[j,k] = X[jp,k] - X[jp,k] = tmp - end -end - -# Matrix exponential -expm{T<:Union(Float32,Float64,Complex64,Complex128)}(A::StridedMatrix{T}) = expm!(copy(A)) -expm{T<:Integer}(A::StridedMatrix{T}) = expm!(float(A)) - -## Matrix factorizations and decompositions - -abstract Factorization{T} -## Create an extractor that extracts the modified original matrix, e.g. -## LD for BunchKaufman, LR for CholeskyDense, LU for LUDense and -## define size methods for Factorization types using it. - -type BunchKaufman{T<:LapackType} <: Factorization{T} - LD::Matrix{T} - ipiv::Vector{Int32} - upper::Bool - function BunchKaufman(A::Matrix{T}, upper::Bool) - LD, ipiv = LAPACK.sytrf!(upper ? 'U' : 'L' , copy(A)) - new(LD, ipiv, upper) - end -end - -BunchKaufman{T<:LapackType}(A::StridedMatrix{T}, upper::Bool) = BunchKaufman{T}(A, upper) -BunchKaufman{T<:Real}(A::StridedMatrix{T}, upper::Bool) = BunchKaufman(float64(A), upper) -BunchKaufman{T<:Number}(A::StridedMatrix{T}) = BunchKaufman(A, true) - -size(B::BunchKaufman) = size(B.LD) -size(B::BunchKaufman,d::Integer) = size(B.LD,d) -## need to work out how to extract the factors. -#factors(B::BunchKaufman) = LAPACK.syconv!(B.upper ? 'U' : 'L', copy(B.LD), B.ipiv) - -function inv(B::BunchKaufman) - symmetrize!(LAPACK.sytri!(B.upper ? 'U' : 'L', copy(B.LD), B.ipiv), B.upper) -end - -\{T<:LapackType}(B::BunchKaufman{T}, R::StridedVecOrMat{T}) = - LAPACK.sytrs!(B.upper ? 'U' : 'L', B.LD, B.ipiv, copy(R)) - -type CholeskyDense{T<:LapackType} <: Factorization{T} - LR::Matrix{T} - upper::Bool - function CholeskyDense(A::Matrix{T}, upper::Bool) - A, info = LAPACK.potrf!(upper ? 'U' : 'L' , A) - if info != 0 error("Matrix A not positive-definite") end - new(upper? triu!(A) : tril!(A), upper) - end -end - -size(C::CholeskyDense) = size(C.LR) -size(C::CholeskyDense,d::Integer) = size(C.LR,d) - -factors(C::CholeskyDense) = C.LR - -\{T<:LapackType}(C::CholeskyDense{T}, B::StridedVecOrMat{T}) = - LAPACK.potrs!(C.upper ? 'U' : 'L', C.LR, copy(B)) - -function det{T}(C::CholeskyDense{T}) - ff = C.LR - dd = one(T) - for i in 1:size(ff,1) dd *= abs2(ff[i,i]) end - dd -end - -function inv(C::CholeskyDense) - Ci, info = LAPACK.potri!(C.upper ? 'U' : 'L', copy(C.LR)) - if info != 0 error("Matrix singular") end - symmetrize!(Ci, C.upper) -end - -## Should these functions check that the matrix is Hermitian? -chold!{T<:LapackType}(A::Matrix{T}, upper::Bool) = CholeskyDense{T}(A, upper) -chold!{T<:LapackType}(A::Matrix{T}) = chold!(A, true) -chold{T<:LapackType}(A::Matrix{T}, upper::Bool) = chold!(copy(A), upper) -chold{T<:Number}(A::Matrix{T}, upper::Bool) = chold(float64(A), upper) -chold{T<:Number}(A::Matrix{T}) = chold(A, true) - -## Matlab (and R) compatible -chol{T<:Number}(A::Matrix{T}) = factors(chold(A)) - -type CholeskyDensePivoted{T<:LapackType} <: Factorization{T} - LR::Matrix{T} - upper::Bool - piv::Vector{Int32} - rank::Int32 - tol::Real - function CholeskyDensePivoted(A::Matrix{T}, upper::Bool, tol::Real) - A, piv, rank, info = LAPACK.pstrf!(upper ? 'U' : 'L' , A, tol) - if info != 0 error("Matrix A not positive-definite") end - new(upper? triu!(A) : tril!(A), upper, piv, rank, tol) - end -end - -size(C::CholeskyDensePivoted) = size(C.LR) -size(C::CholeskyDensePivoted,d::Integer) = size(C.LR,d) - -factors(C::CholeskyDensePivoted) = C.LR, C.piv - -\{T<:LapackType}(C::CholeskyDensePivoted{T}, B::StridedVecOrMat{T}) = - LAPACK.potrs!(C.upper ? 'U' : 'L', C.LR, copy(B)[C.piv])[invperm(C.piv)] - -rank(C::CholeskyDensePivoted) = C.rank - -det(C::CholeskyDensePivoted) = prod(abs2(diag(C.LR))) - -function inv(C::CholeskyDensePivoted) - if C.rank < size(C.LR, 1) error("Matrix singular") end - Ci, info = LAPACK.potri!(C.upper ? 'U' : 'L', copy(C.LR)) - if info != 0 error("Matrix singular") end - ipiv = invperm(C.piv) - (symmetrize!(Ci, C.upper))[ipiv, ipiv] -end - -## Should these functions check that the matrix is Hermitian? -cholpd!{T<:LapackType}(A::Matrix{T}, upper::Bool, tol::Real) = CholeskyDensePivoted{T}(A, upper, tol) -cholpd!{T<:LapackType}(A::Matrix{T}, upper::Bool) = cholpd!(A, upper, -1.) -cholpd!{T<:LapackType}(A::Matrix{T}, tol::Real) = cholpd!(A, true, tol) -cholpd!{T<:LapackType}(A::Matrix{T}) = cholpd!(A, true, -1.) -cholpd{T<:Number}(A::Matrix{T}, upper::Bool, tol::Real) = cholpd(float64(A), upper, tol) -cholpd{T<:Number}(A::Matrix{T}, upper::Bool) = cholpd(float64(A), upper, -1.) -cholpd{T<:Number}(A::Matrix{T}, tol::Real) = cholpd(float64(A), true, tol) -cholpd{T<:Number}(A::Matrix{T}) = cholpd(float64(A), true, -1.) -cholpd{T<:LapackType}(A::Matrix{T}, upper::Bool, tol::Real) = cholpd!(copy(A), upper, tol) -cholpd{T<:LapackType}(A::Matrix{T}, upper::Bool) = cholpd!(copy(A), upper, -1.) -cholpd{T<:LapackType}(A::Matrix{T}, tol::Real) = cholpd!(copy(A), true, tol) -cholpd{T<:LapackType}(A::Matrix{T}) = cholpd!(copy(A), true, -1.) - -type LUDense{T} <: Factorization{T} - lu::Matrix{T} - ipiv::Vector{Int32} - info::Int32 - function LUDense(lu::Matrix{T}, ipiv::Vector{Int32}, info::Int32) - m, n = size(lu) - m == n ? new(lu, ipiv, info) : error("LUDense only defined for square matrices") - end -end - -size(A::LUDense) = size(A.lu) -size(A::LUDense,n) = size(A.lu,n) - -function factors{T}(lu::LUDense{T}) - LU, ipiv = lu.lu, lu.ipiv - m, n = size(LU) - - L = m >= n ? tril(LU, -1) + eye(T,m,n) : tril(LU, -1)[:, 1:m] + eye(T,m) - U = m <= n ? triu(LU) : triu(LU)[1:n, :] - P = [1:m] - for i = 1:min(m,n) - t = P[i] - P[i] = P[ipiv[i]] - P[ipiv[i]] = t - end - L, U, P -end - -function lud!{T<:LapackType}(A::Matrix{T}) - lu, ipiv, info = LAPACK.getrf!(A) - LUDense{T}(lu, ipiv, info) -end - -lud{T<:LapackType}(A::Matrix{T}) = lud!(copy(A)) -lud{T<:Number}(A::Matrix{T}) = lud(float64(A)) - -## Matlab-compatible -lu{T<:Number}(A::Matrix{T}) = factors(lud(A)) - -function det{T}(lu::LUDense{T}) - m, n = size(lu) - if lu.info > 0; return zero(typeof(lu.lu[1])); end - prod(diag(lu.lu)) * (bool(sum(lu.ipiv .!= 1:n) % 2) ? -one(T) : one(T)) -end - -function det(A::Matrix) - m, n = size(A) - if m != n; error("det only defined for square matrices"); end - if istriu(A) | istril(A); return prod(diag(A)); end - return det(lud(A)) -end - -function (\){T<:LapackType}(lu::LUDense{T}, B::StridedVecOrMat{T}) - if lu.info > 0; error("Singular system"); end - LAPACK.getrs!('N', lu.lu, lu.ipiv, copy(B)) -end - -function inv{T<:LapackType}(lu::LUDense{T}) - m, n = size(lu.lu) - if m != n; error("inv only defined for square matrices"); end - if lu.info > 0; return error("Singular system"); end - LAPACK.getri!(copy(lu.lu), lu.ipiv) -end - -## QR decomposition without column pivots -type QRDense{T} <: Factorization{T} - hh::Matrix{T} # Householder transformations and R - tau::Vector{T} # Scalar factors of transformations - function QRDense(hh::Matrix{T}, tau::Vector{T}) - numel(tau) == min(size(hh)) ? new(hh, tau) : error("QR: mismatched dimensions") - end -end -size(A::QRDense) = size(A.hh) -size(A::QRDense,n) = size(A.hh,n) - -qrd!{T<:LapackType}(A::StridedMatrix{T}) = QRDense{T}(LAPACK.geqrf!(A)...) -qrd{T<:LapackType}(A::StridedMatrix{T}) = qrd!(copy(A)) -qrd{T<:Real}(A::StridedMatrix{T}) = qrd(float64(A)) - -function factors{T<:LapackType}(qrd::QRDense{T}) - aa = copy(qrd.hh) - R = triu(aa[1:min(size(aa)),:]) # must be *before* call to orgqr! - LAPACK.orgqr!(aa, qrd.tau, size(aa,2)), R -end - -qr{T<:Number}(x::StridedMatrix{T}) = factors(qrd(x)) - -## Multiplication by Q from the QR decomposition -(*){T<:LapackType}(A::QRDense{T}, B::StridedVecOrMat{T}) = - LAPACK.ormqr!('L', 'N', A.hh, size(A.hh,2), A.tau, copy(B)) - -## Multiplication by Q' from the QR decomposition -Ac_mul_B{T<:LapackType}(A::QRDense{T}, B::StridedVecOrMat{T}) = - LAPACK.ormqr!('L', iscomplex(A.tau)?'C':'T', A.hh, size(A.hh,2), A.tau, copy(B)) - -## Least squares solution. Should be more careful about cases with m < n -function (\){T<:LapackType}(A::QRDense{T}, B::StridedVecOrMat{T}) - n = length(A.tau) - ans, info = LAPACK.trtrs!('U','N','N',A.hh[1:n,:],(A'*B)[1:n,:]) - if info > 0; error("Singular system"); end - return ans -end - -type QRPDense{T} <: Factorization{T} - hh::Matrix{T} - tau::Vector{T} - jpvt::Vector{Int32} - function QRPDense(hh::Matrix{T}, tau::Vector{T}, jpvt::Vector{Int32}) - m, n = size(hh) - if length(tau) != min(m,n) || length(jpvt) != n - error("QRPDense: mismatched dimensions") - end - new(hh,tau,jpvt) - end -end -size(x::QRPDense) = size(x.hh) -size(x::QRPDense,d) = size(x.hh,d) -## Multiplication by Q from the QR decomposition -(*){T<:LapackType}(A::QRPDense{T}, B::StridedVecOrMat{T}) = - LAPACK.ormqr!('L', 'N', A.hh, size(A,2), A.tau, copy(B)) -## Multiplication by Q' from the QR decomposition -Ac_mul_B{T<:LapackType}(A::QRPDense{T}, B::StridedVecOrMat{T}) = - LAPACK.ormqr!('L', iscomplex(A.tau)?'C':'T', A.hh, size(A,2), A.tau, copy(B)) - -qrpd!{T<:LapackType}(A::StridedMatrix{T}) = QRPDense{T}(LAPACK.geqp3!(A)...) -qrpd{T<:LapackType}(A::StridedMatrix{T}) = qrpd!(copy(A)) -qrpd{T<:Real}(x::StridedMatrix{T}) = qrpd(float64(x)) - -function factors{T<:LapackType}(x::QRPDense{T}) - aa = copy(x.hh) - R = triu(aa[1:min(size(aa)),:]) - LAPACK.orgqr!(aa, x.tau, size(aa,2)), R, x.jpvt -end - -qrp{T<:LapackType}(x::StridedMatrix{T}) = factors(qrpd(x)) -qrp{T<:Real}(x::StridedMatrix{T}) = qrp(float64(x)) - -function (\){T<:LapackType}(A::QRPDense{T}, B::StridedVecOrMat{T}) - n = length(A.tau) - x, info = LAPACK.trtrs!('U','N','N',A.hh[1:n,:],(A'*B)[1:n,:]) - if info > 0; error("Singular system"); end - isa(B, Vector) ? x[invperm(A.jpvt)] : x[:,invperm(A.jpvt)] -end - -function eig{T<:LapackType}(A::StridedMatrix{T}, vecs::Bool) - n = size(A, 2) - if n == 0; return vecs ? (zeros(T, 0), zeros(T, 0, 0)) : zeros(T, 0, 0); end - - if ishermitian(A) - if vecs - Z = similar(A) - W = LAPACK.syevr!(copy(A), Z) - return W, Z - else - W = LAPACK.syevr!(copy(A)) - return W - end - end - - if iscomplex(A) - W, VR = LAPACK.geev!('N', vecs ? 'V' : 'N', copy(A))[2:3] - if vecs; return W, VR; end - return W - end - - VL, WR, WI, VR = LAPACK.geev!('N', vecs ? 'V' : 'N', copy(A)) - if all(WI .== 0.) - if vecs; return WR, VR; end - return WR - end - if vecs - evec = complex(zeros(T, n, n)) - j = 1 - while j <= n - if WI[j] == 0.0 - evec[:,j] = VR[:,j] - else - evec[:,j] = VR[:,j] + im*VR[:,j+1] - evec[:,j+1] = VR[:,j] - im*VR[:,j+1] - j += 1 - end - j += 1 - end - return complex(WR, WI), evec - end - complex(WR, WI) -end - -eig{T<:Integer}(x::StridedMatrix{T}, vecs::Bool) = eig(float64(x), vecs) -eig(x::StridedMatrix) = eig(x, true) -eigvals(x::StridedMatrix) = eig(x, false) - -# This is the svd based on the LAPACK GESVD, which is slower, but takes -# lesser memory. It should be made available through a keyword argument -# at a later date. -# -# function svd{T<:LapackType}(A::StridedMatrix{T},vecs::Bool,thin::Bool) -# m,n = size(A) -# if m == 0 || n == 0 -# if vecs; return (eye(m, thin ? n : m), zeros(0), eye(n,n)); end -# return (zeros(T, 0, 0), zeros(T, 0), zeros(T, 0, 0)) -# end -# if vecs; return LAPACK.gesvd!(thin ? 'S' : 'A', thin ? 'S' : 'A', copy(A)); end -# LAPACK.gesvd!('N', 'N', copy(A)) -# end -# -# svd{T<:Integer}(x::StridedMatrix{T},vecs,thin) = svd(float64(x),vecs,thin) -# svd(A::StridedMatrix) = svd(A,true,false) -# svd(A::StridedMatrix, thin::Bool) = svd(A,true,thin) -# svdvals(A) = svd(A,false,true)[2] - -function svd{T<:LapackType}(A::StridedMatrix{T},vecs::Bool,thin::Bool) - m,n = size(A) - if m == 0 || n == 0 - if vecs; return (eye(m, thin ? n : m), zeros(0), eye(n,n)); end - return (zeros(T, 0, 0), zeros(T, 0), zeros(T, 0, 0)) - end - if vecs; return LAPACK.gesdd!(thin ? 'S' : 'A', copy(A)); end - LAPACK.gesdd!('N', copy(A)) -end - -svd{T<:Integer}(x::StridedMatrix{T},vecs,thin) = svd(float64(x),vecs,thin) -svd(A::StridedMatrix) = svd(A,true,false) -svd(A::StridedMatrix, thin::Bool) = svd(A,true,thin) -svdvals(A) = svd(A,false,true)[2] - -function (\){T<:LapackType}(A::StridedMatrix{T}, B::StridedVecOrMat{T}) - Acopy = copy(A) - m, n = size(Acopy) - X = copy(B) - - if m == n # Square - if istriu(A) - ans, info = LAPACK.trtrs!('U', 'N', 'N', Acopy, X) - if info > 0; error("Singular system"); end - return ans - end - if istril(A) - ans, info = LAPACK.trtrs!('L', 'N', 'N', Acopy, X) - if info > 0; error("Singular system"); end - return ans - end - if ishermitian(A) - ans, _, _, info = LAPACK.sysv!('U', Acopy, X) - if info > 0; error("Singular system"); end - return ans - end - ans, _, _, info = LAPACK.gesv!(Acopy, X) - if info > 0; error("Singular system"); end - return ans - end - LAPACK.gelsd!(Acopy, X)[1] -end - -(\){T1<:LapackType, T2<:LapackType}(A::StridedMatrix{T1}, B::StridedVecOrMat{T2}) = - (\)(convert(Array{promote_type(T1,T2)},A), convert(Array{promote_type(T1,T2)},B)) -(\){T1<:LapackType, T2<:Real}(A::StridedMatrix{T1}, B::StridedVecOrMat{T2}) = (\)(A, convert(Array{T1}, B)) -(\){T1<:Real, T2<:LapackType}(A::StridedMatrix{T1}, B::StridedVecOrMat{T2}) = (\)(convert(Array{T2}, A), B) -(\){T1<:Real, T2<:Real}(A::StridedMatrix{T1}, B::StridedVecOrMat{T2}) = (\)(float64(A), float64(B)) -(\){T1<:Number, T2<:Number}(A::StridedMatrix{T1}, B::StridedVecOrMat{T2}) = (\)(complex128(A), complex128(B)) - -(/)(A::StridedVecOrMat, B::StridedVecOrMat) = (B' \ A')' - -##TODO: Add methods for rank(A::QRP{T}) and adjust the (\) method accordingly -## Add rcond methods for Cholesky, LU, QR and QRP types -## Lower priority: Add LQ, QL and RQ factorizations - -## Moore-Penrose inverse -function pinv{T<:LapackType}(A::StridedMatrix{T}) - u,s,vt = svd(A, true) - sinv = zeros(T, length(s)) - index = s .> eps(real(one(T)))*max(size(A))*max(s) - sinv[index] = 1 ./ s[index] - vt'diagmm(sinv, u') -end -pinv(A::StridedMatrix{Int}) = pinv(float(A)) -pinv(a::StridedVector) = pinv(reshape(a, length(a), 1)) - -## Basis for null space -function null{T<:LapackType}(A::StridedMatrix{T}) - m,n = size(A) - if m >= n; return zeros(T, n, 0); end; - u,s,vt = svd(A) - vt[m+1:,:]' -end -null(A::StridedMatrix{Int}) = null(float(A)) -null(a::StridedVector) = null(reshape(a, length(a), 1)) - -#### Specialized matrix types #### - -## Symmetric tridiagonal matrices -type SymTridiagonal{T<:LapackType} <: AbstractMatrix{T} - dv::Vector{T} # diagonal - ev::Vector{T} # sub/super diagonal - function SymTridiagonal(dv::Vector{T}, ev::Vector{T}) - if length(ev) != length(dv) - 1 error("dimension mismatch") end - new(dv,ev) - end -end - -SymTridiagonal{T<:LapackType}(dv::Vector{T}, ev::Vector{T}) = SymTridiagonal{T}(copy(dv), copy(ev)) -function SymTridiagonal{T<:Real}(dv::Vector{T}, ev::Vector{T}) - SymTridiagonal{Float64}(float64(dv),float64(ev)) -end -function SymTridiagonal{Td<:Number,Te<:Number}(dv::Vector{Td}, ev::Vector{Te}) - T = promote(Td,Te) - SymTridiagonal(convert(Vector{T}, dv), convert(Vector{T}, ev)) -end -copy(S::SymTridiagonal) = SymTridiagonal(S.dv,S.ev) -function full(S::SymTridiagonal) - M = diagm(S.dv) - for i in 1:length(S.ev) - j = i + 1 - M[i,j] = M[j,i] = S.ev[i] - end - M -end - -function show(io, S::SymTridiagonal) - println(io, summary(S), ":") - print(io, "diag: ") - print_matrix(io, (S.dv)') - print(io, "\n sup: ") - print_matrix(io, (S.ev)') -end - -size(m::SymTridiagonal) = (length(m.dv), length(m.dv)) -size(m::SymTridiagonal,d::Integer) = d<1 ? error("dimension out of range") : (d<2 ? length(m.dv) : 1) - -eig(m::SymTridiagonal, vecs::Bool) = LAPACK.stev!(vecs ? 'V' : 'N', copy(m.dv), copy(m.ev)) -eig(m::SymTridiagonal) = eig(m::SymTridiagonal, true) -## This function has been in Julia for some time. Could probably be dropped. -trideig{T<:LapackType}(d::Vector{T}, e::Vector{T}) = LAPACK.stev!('N', copy(d), copy(e))[1] - -## Tridiagonal matrices ## -type Tridiagonal{T} <: AbstractMatrix{T} - dl::Vector{T} # sub-diagonal - d::Vector{T} # diagonal - du::Vector{T} # sup-diagonal - dutmp::Vector{T} # scratch space for vector RHS solver, sup-diagonal - rhstmp::Vector{T}# scratch space, rhs - - function Tridiagonal(N::Int) - dutmp = Array(T, N-1) - rhstmp = Array(T, N) - new(dutmp, rhstmp, dutmp, dutmp, rhstmp) # first three will be overwritten - end -end - -function Tridiagonal{T<:Number}(dl::Vector{T}, d::Vector{T}, du::Vector{T}) - N = length(d) - if length(dl) != N-1 || length(du) != N-1 - error("The sub- and super-diagonals must have length N-1") - end - M = Tridiagonal{T}(N) - M.dl = copy(dl) - M.d = copy(d) - M.du = copy(du) - return M -end -function Tridiagonal{Tl<:Number, Td<:Number, Tu<:Number}(dl::Vector{Tl}, d::Vector{Td}, du::Vector{Tu}) - R = promote(Tl, Td, Tu) - Tridiagonal(convert(Vector{R}, dl), convert(Vector{R}, d), convert(Vector{R}, du)) -end - -size(M::Tridiagonal) = (length(M.d), length(M.d)) -function show(io, M::Tridiagonal) - println(io, summary(M), ":") - print(io, " sub: ") - print_matrix(io, (M.dl)') - print(io, "\ndiag: ") - print_matrix(io, (M.d)') - print(io, "\n sup: ") - print_matrix(io, (M.du)') -end -full{T}(M::Tridiagonal{T}) = convert(Matrix{T}, M) -function convert{T}(::Type{Matrix{T}}, M::Tridiagonal{T}) - A = zeros(T, size(M)) - for i = 1:length(M.d) - A[i,i] = M.d[i] - end - for i = 1:length(M.d)-1 - A[i+1,i] = M.dl[i] - A[i,i+1] = M.du[i] - end - return A -end -function similar(M::Tridiagonal, T, dims::Dims) - if length(dims) != 2 || dims[1] != dims[2] - error("Tridiagonal matrices must be square") - end - return Tridiagonal{T}(dims[1]) -end -copy(M::Tridiagonal) = Tridiagonal(M.dl, M.d, M.du) - -# Operations on Tridiagonal matrices -round(M::Tridiagonal) = Tridiagonal(round(M.dl), round(M.d), round(M.du)) -iround(M::Tridiagonal) = Tridiagonal(iround(M.dl), iround(M.d), iround(M.du)) - -## Solvers - -#### Tridiagonal matrix routines #### -function \{T<:LapackType}(M::Tridiagonal{T}, rhs::StridedVecOrMat{T}) - if stride(rhs, 1) == 1 - return LAPACK.gtsv!(copy(M.dl), copy(M.d), copy(M.du), copy(rhs)) - end - solve(M, rhs) # use the Julia "fallback" -end - -# This is definitely not going to work -#eig(M::Tridiagonal) = LAPACK.stev!('V', copy(M)) - -# Allocation-free variants -# Note that solve is non-aliasing, so you can use the same array for -# input and output -function solve(x::AbstractArray, xrng::Ranges{Int}, M::Tridiagonal, rhs::AbstractArray, rhsrng::Ranges{Int}) - d = M.d - N = length(d) - if length(xrng) != N || length(rhsrng) != N - error("dimension mismatch") - end - dl = M.dl - du = M.du - dutmp = M.dutmp - rhstmp = M.rhstmp - xstart = first(xrng) - xstride = step(xrng) - rhsstart = first(rhsrng) - rhsstride = step(rhsrng) - # Forward sweep - denom = d[1] - dulast = du[1] / denom - dutmp[1] = dulast - rhslast = rhs[rhsstart] / denom - rhstmp[1] = rhslast - irhs = rhsstart+rhsstride - for i in 2:N-1 - dltmp = dl[i-1] - denom = d[i] - dltmp*dulast - dulast = du[i] / denom - dutmp[i] = dulast - rhslast = (rhs[irhs] - dltmp*rhslast)/denom - rhstmp[i] = rhslast - irhs += rhsstride - end - dltmp = dl[N-1] - denom = d[N] - dltmp*dulast - xlast = (rhs[irhs] - dltmp*rhslast)/denom - # Backward sweep - ix = xstart + (N-2)*xstride - x[ix+xstride] = xlast - for i in N-1:-1:1 - xlast = rhstmp[i] - dutmp[i]*xlast - x[ix] = xlast - ix -= xstride - end - return x -end -solve(x::StridedVector, M::Tridiagonal, rhs::StridedVector) = solve(x, 1:length(x), M, rhs, 1:length(rhs)) -function solve(M::Tridiagonal, rhs::StridedVector) - x = similar(rhs) - solve(x, M, rhs) -end -function solve(X::StridedMatrix, M::Tridiagonal, B::StridedMatrix) - if size(B, 1) != size(M, 1) - error("dimension mismatch") - end - if size(X) != size(B) - error("dimension mismatch in output") - end - m, n = size(B) - r = 1:m - for j = 1:n - r.start = (j-1)*m+1 - solve(X, r, M, B, r) - end - return X -end -function solve(M::Tridiagonal, B::StridedMatrix) - X = similar(B) - solve(X, M, B) -end - -# User-friendly solver -\(M::Tridiagonal, rhs::Union(StridedVector,StridedMatrix)) = solve(M, rhs) - -# Tridiagonal multiplication -function mult(x::AbstractArray, xrng::Ranges{Int}, M::Tridiagonal, v::AbstractArray, vrng::Ranges{Int}) - dl = M.dl - d = M.d - du = M.du - N = length(d) - xi = first(xrng) - xstride = step(xrng) - vi = first(vrng) - vstride = step(vrng) - x[xi] = d[1]*v[vi] + du[1]*v[vi+vstride] - xi += xstride - for i = 2:N-1 - x[xi] = dl[i-1]*v[vi] + d[i]*v[vi+vstride] + du[i]*v[vi+2*vstride] - xi += xstride - vi += vstride - end - x[xi] = dl[N-1]*v[vi] + d[N]*v[vi+vstride] - return x -end -mult(x::StridedVector, M::Tridiagonal, v::StridedVector) = mult(x, 1:length(x), M, v, 1:length(v)) -function mult(X::StridedMatrix, M::Tridiagonal, B::StridedMatrix) - if size(B, 1) != size(M, 1) - error("dimension mismatch") - end - if size(X) != size(B) - error("dimension mismatch in output") - end - m, n = size(B) - r = 1:m - for j = 1:n - r.start = (j-1)*m+1 - mult(X, r, M, B, r) - end - return X -end -mult(X::StridedMatrix, M1::Tridiagonal, M2::Tridiagonal) = mult(X, M1, full(M2)) -function *(M::Tridiagonal, B::Union(StridedVector,StridedMatrix)) - X = similar(B) - mult(X, M, B) -end -*(A::Tridiagonal, B::Tridiagonal) = A*full(B) - -#### Factorizations for Tridiagonal #### -type LDLTTridiagonal{T<:LapackType,S<:LapackType} <: Factorization{T} - D::Vector{S} - E::Vector{T} - function LDLTTridiagonal(D::Vector{S}, E::Vector{T}) - if typeof(real(E[1])) != eltype(D) error("Wrong eltype") end - new(D, E) - end -end -LDLTTridiagonal{S<:LapackType,T<:LapackType}(D::Vector{S}, E::Vector{T}) = LDLTTridiagonal{T,S}(D, E) - -ldltd!{T<:LapackType}(A::SymTridiagonal{T}) = LDLTTridiagonal(LAPACK.pttrf!(real(A.dv),A.ev)...) -ldltd{T<:LapackType}(A::SymTridiagonal{T}) = ldltd!(copy(A)) - -function (\){T<:LapackType}(C::LDLTTridiagonal{T}, B::StridedVecOrMat{T}) - if iscomplex(B) return LAPACK.pttrs!('L', C.D, C.E, copy(B)) end - LAPACK.pttrs!(C.D, C.E, copy(B)) -end - -type LUTridiagonal{T} <: Factorization{T} - dl::Vector{T} - d::Vector{T} - du::Vector{T} - du2::Vector{T} - ipiv::Vector{Int32} - function LUTridiagonal(dl::Vector{T}, d::Vector{T}, du::Vector{T}, - du2::Vector{T}, ipiv::Vector{Int32}) - n = length(d) - if length(dl) != n - 1 || length(du) != n - 1 || length(ipiv) != n || length(du2) != n-2 - error("LUTridiagonal: dimension mismatch") - end - new(dl, d, du, du2, ipiv) - end -end -#show(io, lu::LUTridiagonal) = print(io, "LU decomposition of ", summary(lu.lu)) - -lud!{T}(A::Tridiagonal{T}) = LUTridiagonal{T}(LAPACK.gttrf!(A.dl,A.d,A.du)...) -lud{T}(A::Tridiagonal{T}) = - LUTridiagonal{T}(LAPACK.gttrf!(copy(A.dl),copy(A.d),copy(A.du))...) -lu(A::Tridiagonal) = factors(lud(A)) - -function det{T}(lu::LUTridiagonal{T}) - n = length(lu.d) - prod(lu.d) * (bool(sum(lu.ipiv .!= 1:n) % 2) ? -one(T) : one(T)) -end - -det(A::Tridiagonal) = det(lud(A)) - -(\){T<:LapackType}(lu::LUTridiagonal{T}, B::StridedVecOrMat{T}) = - LAPACK.gttrs!('N', lu.dl, lu.d, lu.du, lu.du2, lu.ipiv, copy(B)) - - -#### Woodbury matrices #### -# This type provides support for the Woodbury matrix identity -type Woodbury{T} <: AbstractMatrix{T} - A - U::Matrix{T} - C - Cp - V::Matrix{T} - tmpN1::Vector{T} - tmpN2::Vector{T} - tmpk1::Vector{T} - tmpk2::Vector{T} - - function Woodbury(A::AbstractMatrix{T}, U::Matrix{T}, C, V::Matrix{T}) - N = size(A, 1) - k = size(U, 2) - if size(A, 2) != N || size(U, 1) != N || size(V, 1) != k || size(V, 2) != N - error("Sizes do not match") - end - if k > 1 - if size(C, 1) != k || size(C, 2) != k - error("Size of C is incorrect") - end - end - Cp = inv(inv(C) + V*(A\U)) - # temporary space for allocation-free solver - tmpN1 = Array(T, N) - tmpN2 = Array(T, N) - tmpk1 = Array(T, k) - tmpk2 = Array(T, k) - # don't copy A, it could be huge - new(A, copy(U), copy(C), Cp, copy(V), tmpN1, tmpN2, tmpk1, tmpk2) - end -end -Woodbury{T}(A::AbstractMatrix{T}, U::Matrix{T}, C, V::Matrix{T}) = Woodbury{T}(A, U, C, V) -Woodbury{T}(A::AbstractMatrix{T}, U::Vector{T}, C, V::Matrix{T}) = Woodbury{T}(A, reshape(U, length(U), 1), C, V) - -size(W::Woodbury) = size(W.A) -function show(io, W::Woodbury) - println(io, summary(W), ":") - print(io, "A: ", W.A) - print(io, "\nU:\n") - print_matrix(io, W.U) - if isa(W.C, Matrix) - print(io, "\nC:\n") - print_matrix(io, W.C) - else - print(io, "\nC: ", W.C) - end - print(io, "\nV:\n") - print_matrix(io, W.V) -end -full{T}(W::Woodbury{T}) = convert(Matrix{T}, W) -convert{T}(::Type{Matrix{T}}, W::Woodbury{T}) = full(W.A) + W.U*W.C*W.V -function similar(W::Woodbury, T, dims::Dims) - if length(dims) != 2 || dims[1] != dims[2] - error("Woodbury matrices must be square") - end - n = size(W, 1) - k = size(W.U, 2) - return Woodbury{T}(similar(W.A), Array(T, n, k), Array(T, k, k), Array(T, k, n)) -end -copy(W::Woodbury) = Woodbury(W.A, W.U, W.C, W.V) - -## Woodbury matrix routines ## - -function *(W::Woodbury, B::StridedVecOrMat) - return W.A*B + W.U*(W.C*(W.V*B)) -end -function \(W::Woodbury, R::StridedVecOrMat) - AinvR = W.A\R - return AinvR - W.A\(W.U*(W.Cp*(W.V*AinvR))) -end -function det(W::Woodbury) - det(W.A)*det(W.C)/det(W.Cp) -end - -# Allocation-free solver for arbitrary strides (requires that W.A has a -# non-aliasing "solve" routine, e.g., is Tridiagonal) -function solve(x::AbstractArray, xrng::Ranges{Int}, W::Woodbury, rhs::AbstractArray, rhsrng::Ranges{Int}) - solve(W.tmpN1, 1:length(W.tmpN1), W.A, rhs, rhsrng) - A_mul_B(W.tmpk1, W.V, W.tmpN1) - A_mul_B(W.tmpk2, W.Cp, W.tmpk1) - A_mul_B(W.tmpN2, W.U, W.tmpk2) - solve(W.tmpN2, W.A, W.tmpN2) - indx = first(xrng) - xinc = step(xrng) - for i = 1:length(W.tmpN2) - x[indx] = W.tmpN1[i] - W.tmpN2[i] - indx += xinc - end -end -solve(x::AbstractVector, W::Woodbury, rhs::AbstractVector) = solve(x, 1:length(x), W, rhs, 1:length(rhs)) -function solve(W::Woodbury, rhs::AbstractVector) - x = similar(rhs) - solve(x, W, rhs) -end -function solve(X::StridedMatrix, W::Woodbury, B::StridedMatrix) - if size(B, 1) != size(W, 1) - error("dimension mismatch") - end - if size(X) != size(B) - error("dimension mismatch in output") - end - m, n = size(B) - r = 1:m - for j = 1:n - r.start = (j-1)*m+1 - solve(X, r, W, B, r) - end - return X -end -function solve(W::Woodbury, B::StridedMatrix) - X = similar(B) - solve(X, W, B) -end diff --git a/base/loading.jl b/base/loading.jl new file mode 100644 index 0000000000000..c2e388c39bccb --- /dev/null +++ b/base/loading.jl @@ -0,0 +1,136 @@ +# require + +function is_file_readable(path) + s = stat(bytestring(path)) + return isfile(s) && isreadable(s) +end + +function find_in_path(name::String) + name[1] == '/' && return abspath(name) + isfile(name) && return abspath(name) + base = name + if endswith(name,".jl") + base = match(r"^(.*)\.jl$",name).captures[1] + else + name = string(base,".jl") + end + for prefix in LOAD_PATH + path = string(prefix,"/",base,"/src/",name) + is_file_readable(path) && return abspath(path) + path = string(prefix,"/",name) + is_file_readable(path) && return abspath(path) + end + return abspath(name) +end + +function find_in_node1_path(name) + if myid()==1 + return find_in_path(name) + else + return remote_call_fetch(1, find_in_path, name) + end +end + +# Store list of files and their load time +package_list = (ByteString=>Float64)[] +require(fname::String) = require(bytestring(fname)) +require(f::String, fs::String...) = (require(f); for x in fs require(x); end) +function require(name::ByteString) + if myid() == 1 + @sync begin + for p = 2:nprocs() + @spawnat p require(name) + end + end + end + path = find_in_node1_path(name) + if !has(package_list,path) + reload_path(path) + end +end + +function reload(name::String) + if myid() == 1 + @sync begin + for p = 2:nprocs() + @spawnat p reload(name) + end + end + end + reload_path(find_in_node1_path(name)) +end + +# remote/parallel load + +include_string(txt::ByteString, fname::ByteString) = + ccall(:jl_load_file_string, Void, (Ptr{Uint8},Ptr{Uint8}), txt, fname) + +include_string(txt::ByteString) = include_string(txt, "string") + +function source_path(default) + t = current_task() + while true + s = t.storage + if !is(s, nothing) && has(s, :SOURCE_PATH) + return s[:SOURCE_PATH] + end + if is(t, t.parent) + return default + end + t = t.parent + end +end +source_path() = source_path("") + +function include_from_node1(path) + prev = source_path(nothing) + path = (prev == nothing) ? abspath(path) : joinpath(dirname(prev),path) + tls = task_local_storage() + tls[:SOURCE_PATH] = path + try + if myid()==1 + Core.include(path) + else + include_string(remote_call_fetch(1, readall, path), path) + end + finally + if prev == nothing + delete!(tls, :SOURCE_PATH) + else + tls[:SOURCE_PATH] = prev + end + end + nothing +end + +function reload_path(path) + had = has(package_list, path) + package_list[path] = time() + tls = task_local_storage() + prev = delete!(tls, :SOURCE_PATH, nothing) + try + eval(Main, :(Base.include_from_node1($path))) + catch e + if !had + delete!(package_list, path) + end + rethrow(e) + finally + if prev != nothing + tls[:SOURCE_PATH] = prev + end + end + nothing +end + +function evalfile(path::String) + s = readall(path) + m = Module(:__anon__) + body = Expr(:toplevel) + i = 1 + while !done(s,i) + ex, i = parse(s,i) + push!(body.args, ex) + end + return eval(m, body) +end diff --git a/base/math.jl b/base/math.jl index b91c771370360..95a402a33180b 100644 --- a/base/math.jl +++ b/base/math.jl @@ -6,9 +6,10 @@ export sin, cos, tan, sinh, cosh, tanh, asin, acos, atan, cosd, cotd, cscd, secd, sind, tand, acosd, acotd, acscd, asecd, asind, atand, atan2, radians2degrees, degrees2radians, - log, log2, log10, log1p, logb, exp, exp2, expm1, - cbrt, sqrt, square, erf, erfc, ceil, floor, trunc, round, - lgamma, hypot, gamma, lfact, max, min, ilogb, ldexp, frexp, + log, log2, log10, log1p, exponent, exp, exp2, expm1, + cbrt, sqrt, square, erf, erfc, erfcx, erfi, dawson, + ceil, floor, trunc, round, significand, + lgamma, hypot, gamma, lfact, max, min, ldexp, frexp, clamp, modf, ^, airy, airyai, airyprime, airyaiprime, airybi, airybiprime, besselj0, besselj1, besselj, bessely0, bessely1, bessely, @@ -20,15 +21,30 @@ import Base.log, Base.exp, Base.sin, Base.cos, Base.tan, Base.sinh, Base.cosh, Base.atanh, Base.sqrt, Base.log2, Base.log10, Base.max, Base.min, Base.ceil, Base.floor, Base.trunc, Base.round, Base.^ +import Intrinsics.nan_dom_err + # non-type specific math functions clamp(x::Real, lo::Real, hi::Real) = (x > hi ? hi : (x < lo ? lo : x)) +clamp{T<:Real}(x::AbstractArray{T,1}, lo::Real, hi::Real) = [clamp(xx, lo, hi) for xx in x] +clamp{T<:Real}(x::AbstractArray{T,2}, lo::Real, hi::Real) = + [clamp(x[i,j], lo, hi) for i in 1:size(x,1), j in 1:size(x,2)] +clamp{T<:Real}(x::AbstractArray{T}, lo::Real, hi::Real) = + reshape([clamp(xx, lo, hi) for xx in x], size(x)) sinc(x::Number) = x==0 ? one(x) : (pix=pi*x; oftype(x,sin(pix)/pix)) +sinc(x::Integer) = x==0 ? one(x) : zero(x) +sinc{T<:Integer}(x::Complex{T}) = sinc(complex(float(real(x)),float(imag(x)))) +@vectorize_1arg Number sinc cosc(x::Number) = x==0 ? zero(x) : (pix=pi*x; oftype(x,cos(pix)/x-sin(pix)/(pix*x))) +cosc(x::Integer) = cosc(float(x)) +cosc{T<:Integer}(x::Complex{T}) = cosc(complex(float(real(x)),float(imag(x)))) +@vectorize_1arg Number cosc radians2degrees(z::Real) = oftype(z, (180/pi) * z) degrees2radians(z::Real) = oftype(z, (pi/180) * z) +radians2degrees(z::Integer) = oftype(float(z), (180/pi) * z) +degrees2radians(z::Integer) = oftype(float(z), (pi/180) * z) for (finv, f) in ((:sec, :cos), (:csc, :sin), (:cot, :tan), (:sech, :cosh), (:csch, :sinh), (:coth, :tanh)) @@ -54,7 +70,7 @@ end for (fd, f) in ((:asind, :asin), (:acosd, :acos), (:atand, :atan), (:asecd, :asec), (:acscd, :acsc), (:acotd, :acot)) @eval begin - ($fd)(y) = degrees2radians(($f)(y)) + ($fd)(y) = radians2degrees(($f)(y)) end end @@ -67,99 +83,119 @@ function hypot(x::Real, y::Real) r = y/x return x*sqrt(one(r)+r*r) end + r = x/y + s = y*sqrt(one(r)+r*r) if y == 0 - return sqrt(y) # to give same type as other cases + return zero(s) end - r = x/y - return y*sqrt(one(r)+r*r) + return s end square(x::Number) = x*x # type specific math functions -for f in (:cbrt, :sin, :cos, :tan, :sinh, :cosh, :tanh, :asin, :acos, :atan, - :asinh, :acosh, :atanh, :log, :log2, :log10, :exp, :erf, :erfc, :lgamma, :sqrt, :exp2) +const libm = Base.libm_name +const openlibm_extras = "libopenlibm-extras" + +# functions with no domain error +for f in (:cbrt, :sinh, :cosh, :tanh, :atan, :asinh, :exp, :erf, :erfc, :exp2, :expm1) + @eval begin + ($f)(x::Float64) = ccall(($(string(f)),libm), Float64, (Float64,), x) + ($f)(x::Float32) = ccall(($(string(f,"f")),libm), Float32, (Float32,), x) + ($f)(x::Integer) = ($f)(float(x)) + @vectorize_1arg Number $f + end +end + +# functions that return NaN on non-NaN argument for domain error +for f in (:sin, :cos, :tan, :asin, :acos, :acosh, :atanh, :log, :log2, :log10, + :lgamma, :sqrt, :log1p) @eval begin - ($f)(x::Float64) = ccall(($(string(f)),:libopenlibm), Float64, (Float64,), x) - ($f)(x::Float32) = ccall(($(string(f,"f")),:libopenlibm), Float32, (Float32,), x) - ($f)(x::Real) = ($f)(float(x)) + ($f)(x::Float64) = nan_dom_err(ccall(($(string(f)),libm), Float64, (Float64,), x), x) + ($f)(x::Float32) = nan_dom_err(ccall(($(string(f,"f")),libm), Float32, (Float32,), x), x) + ($f)(x::Integer) = ($f)(float(x)) @vectorize_1arg Number $f end end -for f in (:log1p, :logb, :expm1, :ceil, :floor, :trunc, :round, :significand) # :rint, :nearbyint +for f in (:ceil, :trunc, :significand) # :rint, :nearbyint @eval begin - ($f)(x::Float64) = ccall(($(string(f)),:libopenlibm), Float64, (Float64,), x) - ($f)(x::Float32) = ccall(($(string(f,"f")),:libopenlibm), Float32, (Float32,), x) - ($f)(x::Real) = ($f)(float(x)) + ($f)(x::Float64) = ccall(($(string(f)),libm), Float64, (Float64,), x) + ($f)(x::Float32) = ccall(($(string(f,"f")),libm), Float32, (Float32,), x) @vectorize_1arg Real $f end end -atan2(x::Real, y::Real) = atan2(float64(x), float64(y)) +round(x::Float32) = ccall((:roundf, libm), Float32, (Float32,), x) +@vectorize_1arg Real round + +floor(x::Float32) = ccall((:floorf, libm), Float32, (Float32,), x) +@vectorize_1arg Real floor + +atan2(x::Real, y::Real) = atan2(float(x), float(y)) hypot(x::Float32, y::Float64) = hypot(float64(x), y) hypot(x::Float64, y::Float32) = hypot(x, float64(y)) for f in (:atan2, :hypot) @eval begin - ($f)(x::Float64, y::Float64) = ccall(($(string(f)),:libopenlibm), Float64, (Float64, Float64,), x, y) - ($f)(x::Float32, y::Float32) = ccall(($(string(f,"f")),:libopenlibm), Float32, (Float32, Float32), x, y) + ($f)(x::Float64, y::Float64) = ccall(($(string(f)),libm), Float64, (Float64, Float64,), x, y) + ($f)(x::Float32, y::Float32) = ccall(($(string(f,"f")),libm), Float32, (Float32, Float32), x, y) @vectorize_2arg Number $f end end -gamma(x::Float64) = ccall((:tgamma,:libopenlibm), Float64, (Float64,), x) +gamma(x::Float64) = nan_dom_err(ccall((:tgamma,libm), Float64, (Float64,), x), x) gamma(x::Float32) = float32(gamma(float64(x))) -gamma(x::Real) = gamma(float(x)) +gamma(x::Integer) = gamma(float(x)) @vectorize_1arg Number gamma -lfact(x::Real) = (x<=1 ? zero(x) : lgamma(x+one(x))) +lfact(x::Real) = (x<=1 ? zero(float(x)) : lgamma(x+one(x))) @vectorize_1arg Number lfact -max(x::Float64, y::Float64) = ccall((:fmax,:libopenlibm), Float64, (Float64,Float64), x, y) -max(x::Float32, y::Float32) = ccall((:fmaxf,:libopenlibm), Float32, (Float32,Float32), x, y) +max(x::Float64, y::Float64) = ccall((:fmax,libm), Float64, (Float64,Float64), x, y) +max(x::Float32, y::Float32) = ccall((:fmaxf,libm), Float32, (Float32,Float32), x, y) @vectorize_2arg Real max -min(x::Float64, y::Float64) = ccall((:fmin,:libopenlibm), Float64, (Float64,Float64), x, y) -min(x::Float32, y::Float32) = ccall((:fminf,:libopenlibm), Float32, (Float32,Float32), x, y) +min(x::Float64, y::Float64) = ccall((:fmin,libm), Float64, (Float64,Float64), x, y) +min(x::Float32, y::Float32) = ccall((:fminf,libm), Float32, (Float32,Float32), x, y) @vectorize_2arg Real min -function ilogb(x::Float64) - if x==0 || isnan(x) +function exponent(x::Float64) + if x==0 || !isfinite(x) throw(DomainError()) end - int(ccall((:ilogb,:libopenlibm), Int32, (Float64,), x)) + int(ccall((:ilogb,libm), Int32, (Float64,), x)) end -function ilogb(x::Float32) - if x==0 || isnan(x) +function exponent(x::Float32) + if x==0 || !isfinite(x) throw(DomainError()) end - int(ccall((:ilogbf,:libopenlibm), Int32, (Float32,), x)) + int(ccall((:ilogbf,libm), Int32, (Float32,), x)) end -@vectorize_1arg Real ilogb +@vectorize_1arg Real exponent -ldexp(x::Float64,e::Int) = ccall((:ldexp,:libopenlibm), Float64, (Float64,Int32), x, int32(e)) -ldexp(x::Float32,e::Int) = ccall((:ldexpf,:libopenlibm), Float32, (Float32,Int32), x, int32(e)) +ldexp(x::Float64,e::Int) = ccall((:scalbn,libm), Float64, (Float64,Int32), x, int32(e)) +ldexp(x::Float32,e::Int) = ccall((:scalbnf,libm), Float32, (Float32,Int32), x, int32(e)) # TODO: vectorize ldexp begin local exp::Array{Int32,1} = zeros(Int32,1) global frexp function frexp(x::Float64) - s = ccall((:frexp,:libopenlibm), Float64, (Float64, Ptr{Int32}), x, exp) + s = ccall((:frexp,libm), Float64, (Float64, Ptr{Int32}), x, exp) (s, int(exp[1])) end function frexp(x::Float32) - s = ccall((:frexpf,:libopenlibm), Float32, (Float32, Ptr{Int32}), x, exp) + s = ccall((:frexpf,libm), Float32, (Float32, Ptr{Int32}), x, exp) (s, int(exp[1])) end function frexp(A::Array{Float64}) f = similar(A) e = Array(Int, size(A)) - for i = 1:numel(A) - f[i] = ccall((:frexp,:libopenlibm), Float64, (Float64, Ptr{Int32}), A[i], exp) + for i = 1:length(A) + f[i] = ccall((:frexp,libm), Float64, (Float64, Ptr{Int32}), A[i], exp) e[i] = exp[1] end return (f, e) @@ -167,8 +203,8 @@ begin function frexp(A::Array{Float32}) f = similar(A) e = Array(Int, size(A)) - for i = 1:numel(A) - f[i] = ccall((:frexpf,:libopenlibm), Float32, (Float32, Ptr{Int32}), A[i], exp) + for i = 1:length(A) + f[i] = ccall((:frexpf,libm), Float32, (Float32, Ptr{Int32}), A[i], exp) e[i] = exp[1] end return (f, e) @@ -177,26 +213,26 @@ end modf(x) = rem(x,one(x)), trunc(x) -^(x::Float64, y::Float64) = ccall((:pow,:libopenlibm), Float64, (Float64,Float64), x, y) -^(x::Float32, y::Float32) = ccall((:powf,:libopenlibm), Float32, (Float32,Float32), x, y) +^(x::Float64, y::Float64) = ccall((:pow,libm), Float64, (Float64,Float64), x, y) +^(x::Float32, y::Float32) = ccall((:powf,libm), Float32, (Float32,Float32), x, y) ^(x::Float64, y::Integer) = x^float64(y) ^(x::Float32, y::Integer) = x^float32(y) # special functions -besselj0(x::Float64) = ccall((:j0,:libopenlibm), Float64, (Float64,), x) -besselj0(x::Float32) = ccall((:j0f,:libopenlibm), Float32, (Float32,), x) +besselj0(x::Float64) = ccall((:j0,openlibm_extras), Float64, (Float64,), x) +besselj0(x::Float32) = ccall((:j0f,openlibm_extras), Float32, (Float32,), x) @vectorize_1arg Real besselj0 -besselj1(x::Float64) = ccall((:j1,:libopenlibm), Float64, (Float64,), x) -besselj1(x::Float32) = ccall((:j1f,:libopenlibm), Float32, (Float32,), x) +besselj1(x::Float64) = ccall((:j1,openlibm_extras), Float64, (Float64,), x) +besselj1(x::Float32) = ccall((:j1f,openlibm_extras), Float32, (Float32,), x) @vectorize_1arg Real besselj1 -bessely0(x::Float64) = ccall((:y0,:libopenlibm), Float64, (Float64,), x) -bessely0(x::Float32) = ccall((:y0f,:libopenlibm), Float32, (Float32,), x) +bessely0(x::Float64) = ccall((:y0,openlibm_extras), Float64, (Float64,), x) +bessely0(x::Float32) = ccall((:y0f,openlibm_extras), Float32, (Float32,), x) @vectorize_1arg Real bessely0 -bessely1(x::Float64) = ccall((:y1,:libopenlibm), Float64, (Float64,), x) -bessely1(x::Float32) = ccall((:y1f,:libopenlibm), Float32, (Float32,), x) +bessely1(x::Float64) = ccall((:y1,openlibm_extras), Float64, (Float64,), x) +bessely1(x::Float32) = ccall((:y1f,openlibm_extras), Float32, (Float32,), x) @vectorize_1arg Real bessely1 let @@ -206,7 +242,7 @@ global airy function airy(k::Int, z::Complex128) id = int32(k==1 || k==3) if k == 0 || k == 1 - ccall((:zairy_,:libopenlibm), Void, + ccall((:zairy_,openlibm_extras), Void, (Ptr{Float64}, Ptr{Float64}, Ptr{Int32}, Ptr{Int32}, Ptr{Float64}, Ptr{Float64}, Ptr{Int32}, Ptr{Int32}), &real(z), &imag(z), @@ -215,7 +251,7 @@ function airy(k::Int, z::Complex128) pointer(ae,1), pointer(ae,2)) return complex(ai[1],ai[2]) elseif k == 2 || k == 3 - ccall((:zbiry_,:libopenlibm), Void, + ccall((:zbiry_,openlibm_extras), Void, (Ptr{Float64}, Ptr{Float64}, Ptr{Int32}, Ptr{Int32}, Ptr{Float64}, Ptr{Float64}, Ptr{Int32}, Ptr{Int32}), &real(z), &imag(z), @@ -230,16 +266,23 @@ end end airy(z) = airy(0,z) +@vectorize_1arg Number airy airyprime(z) = airy(1,z) +@vectorize_1arg Number airyprime airyai(z) = airy(0,z) +@vectorize_1arg Number airyai airyaiprime(z) = airy(1,z) +@vectorize_1arg Number airyaiprime airybi(z) = airy(2,z) +@vectorize_1arg Number airybi airybiprime(z) = airy(3,z) +@vectorize_1arg Number airybiprime -airy(k, x::FloatingPoint) = oftype(x, real(airy(k, complex(x)))) -airy(k, x::Real) = airy(k, float(x)) -airy(k, z::Complex64) = complex64(airy(k, complex128(z))) -airy(k, z::Complex) = airy(k, complex128(z)) +airy(k::Number, x::FloatingPoint) = oftype(x, real(airy(k, complex(x)))) +airy(k::Number, x::Integer) = airy(k, float(x)) +airy(k::Number, z::Complex64) = complex64(airy(k, complex128(z))) +airy(k::Number, z::Complex) = airy(convert(Int,k), complex128(z)) +@vectorize_2arg Number airy let const cy::Array{Float64,1} = Array(Float64,2) @@ -247,7 +290,7 @@ let const wrk::Array{Float64,1} = Array(Float64,2) function _besselh(nu::Float64, k::Integer, z::Complex128) - ccall((:zbesh_,:libopenlibm), Void, + ccall((:zbesh_,openlibm_extras), Void, (Ptr{Float64}, Ptr{Float64}, Ptr{Float64}, Ptr{Int32}, Ptr{Int32}, Ptr{Int32}, Ptr{Float64}, Ptr{Float64}, Ptr{Int32}, Ptr{Int32}), &real(z), &imag(z), &nu, &1, &k, &1, @@ -257,7 +300,7 @@ let end function _besseli(nu::Float64, z::Complex128) - ccall((:zbesi_,:libopenlibm), Void, + ccall((:zbesi_,openlibm_extras), Void, (Ptr{Float64}, Ptr{Float64}, Ptr{Float64}, Ptr{Int32}, Ptr{Int32}, Ptr{Float64}, Ptr{Float64}, Ptr{Int32}, Ptr{Int32}), &real(z), &imag(z), &nu, &1, &1, @@ -267,7 +310,7 @@ let end function _besselj(nu::Float64, z::Complex128) - ccall((:zbesj_,:libopenlibm), Void, + ccall((:zbesj_,openlibm_extras), Void, (Ptr{Float64}, Ptr{Float64}, Ptr{Float64}, Ptr{Int32}, Ptr{Int32}, Ptr{Float64}, Ptr{Float64}, Ptr{Int32}, Ptr{Int32}), &real(z), &imag(z), &nu, &1, &1, @@ -277,7 +320,7 @@ let end function _besselk(nu::Float64, z::Complex128) - ccall((:zbesk_,:libopenlibm), Void, + ccall((:zbesk_,openlibm_extras), Void, (Ptr{Float64}, Ptr{Float64}, Ptr{Float64}, Ptr{Int32}, Ptr{Int32}, Ptr{Float64}, Ptr{Float64}, Ptr{Int32}, Ptr{Int32}), &real(z), &imag(z), &nu, &1, &1, @@ -287,7 +330,7 @@ let end function _bessely(nu::Float64, z::Complex128) - ccall((:zbesy_,:libopenlibm), Void, + ccall((:zbesy_,openlibm_extras), Void, (Ptr{Float64}, Ptr{Float64}, Ptr{Float64}, Ptr{Int32}, Ptr{Int32}, Ptr{Float64}, Ptr{Float64}, Ptr{Int32}, Ptr{Float64}, Ptr{Float64}, Ptr{Int32}), @@ -357,10 +400,12 @@ besselh(nu, z) = besselh(nu, 1, z) besselh(nu::Real, k::Integer, z::Complex64) = complex64(besselh(float64(nu), k, complex128(z))) besselh(nu::Real, k::Integer, z::Complex) = besselh(float64(nu), k, complex128(z)) besselh(nu::Real, k::Integer, x::Real) = besselh(float64(nu), k, complex128(x)) +@vectorize_2arg Number besselh besseli(nu::Real, z::Complex64) = complex64(bessely(float64(nu), complex128(z))) besseli(nu::Real, z::Complex) = besseli(float64(nu), complex128(z)) besseli(nu::Real, x::Real) = besseli(float64(nu), complex128(x)) +@vectorize_2arg Number besseli function besselj(nu::FloatingPoint, x::FloatingPoint) ans = besselj(float64(nu), complex128(x)) @@ -369,19 +414,25 @@ end besselj(nu::Real, z::Complex64) = complex64(besselj(float64(nu), complex128(z))) besselj(nu::Real, z::Complex) = besselj(float64(nu), complex128(z)) -besselj(nu::Integer, x::Real) = besselj(nu, float(x)) -besselj(nu::Real, x::Real) = besselj(float(nu), float(x)) +besselj(nu::Integer, x::Integer) = besselj(nu, float(x)) +@vectorize_2arg Number besselj besselk(nu::Real, z::Complex64) = complex64(besselk(float64(nu), complex128(z))) besselk(nu::Real, z::Complex) = besselk(float64(nu), complex128(z)) besselk(nu::Real, x::Real) = besselk(float64(nu), complex128(x)) +@vectorize_2arg Number besselk bessely(nu::Real, z::Complex64) = complex64(bessely(float64(nu), complex128(z))) bessely(nu::Real, z::Complex) = bessely(float64(nu), complex128(z)) bessely(nu::Real, x::Real) = bessely(float64(nu), complex128(x)) +@vectorize_2arg Number bessely hankelh1(nu, z) = besselh(nu, 1, z) +@vectorize_2arg Number hankelh1 + hankelh2(nu, z) = besselh(nu, 2, z) +@vectorize_2arg Number hankelh2 + function angle_restrict_symm(theta) P1 = 4 * 7.8539812564849853515625e-01 @@ -440,8 +491,8 @@ const digamma_EUL = 0.57721566490153286061 const digamma_coefs = [8.33333333333333333333e-2,-2.10927960927960927961e-2, 7.57575757575757575758e-3, -4.16666666666666666667e-3, 3.96825396825396825397e-3,-8.33333333333333333333e-3, 8.33333333333333333333e-2] + function digamma(x::Float64) - negative = false nz = 0.0 @@ -510,6 +561,8 @@ digamma(x::Real) = digamma(float64(x)) beta(x::Number, w::Number) = exp(lgamma(x)+lgamma(w)-lgamma(x+w)) lbeta(x::Number, w::Number) = lgamma(x)+lgamma(w)-lgamma(x+w) +@vectorize_2arg Number beta +@vectorize_2arg Number lbeta const eta_coeffs = [.99999999999999999997, @@ -613,10 +666,33 @@ end eta(x::Integer) = eta(float64(x)) eta(x::Real) = oftype(x,eta(float64(x))) eta(z::Complex) = oftype(z,eta(complex128(z))) +@vectorize_1arg Number eta function zeta(z::Number) zz = 2^z eta(z) * zz/(zz-2) end +@vectorize_1arg Number zeta + +if WORD_SIZE == 64 +# TODO: complex return only on 64-bit for now +for f in (:erf, :erfc, :erfcx, :erfi, :Dawson) + fname = (f === :Dawson) ? :dawson : f + @eval begin + ($fname)(z::Complex128) = complex128(ccall(($(string("Faddeeva_",f)),openlibm_extras), ComplexPair{Float64}, (ComplexPair{Float64}, Float64), z, zero(Float64))) + ($fname)(z::Complex64) = complex64(ccall(($(string("Faddeeva_",f)),openlibm_extras), ComplexPair{Float64}, (ComplexPair{Float64}, Float64), complex128(z), float64(eps(Float32)))) + ($fname)(z::Complex) = ($fname)(complex128(z)) + end +end +end +for f in (:erfcx, :erfi, :Dawson) + fname = (f === :Dawson) ? :dawson : f + @eval begin + ($fname)(x::Float64) = ccall(($(string("Faddeeva_",f,"_re")),openlibm_extras), Float64, (Float64,), x) + ($fname)(x::Float32) = float32(ccall(($(string("Faddeeva_",f,"_re")),openlibm_extras), Float64, (Float64,), float64(x))) + ($fname)(x::Integer) = ($fname)(float(x)) + @vectorize_1arg Number $fname + end +end end # module diff --git a/base/meta.jl b/base/meta.jl new file mode 100644 index 0000000000000..883cbd7502601 --- /dev/null +++ b/base/meta.jl @@ -0,0 +1,47 @@ +module Meta +# +# convenience functions for metaprogramming +# + +export quot, + isexpr, + show_sexpr + +quot(ex) = Expr(:quote, ex) + +isexpr(ex::Expr, head) = ex.head === head +isexpr(ex::Expr, heads::Set) = has(heads, ex.head) +isexpr(ex::Expr, heads::Vector) = contains(heads, ex.head) +isexpr(ex, head) = false + +isexpr(ex, head, n::Int) = isexpr(ex, head) && length(ex.args) == n + + +# ---- show_sexpr: print an AST as an S-expression ---- + +show_sexpr(ex) = show_sexpr(OUTPUT_STREAM, ex) +show_sexpr(io::IO, ex) = show_sexpr(io, ex, 0) +show_sexpr(io::IO, ex, indent::Int) = show(io, ex) + +const sexpr_indent_width = 2 + +function show_sexpr(io::IO, ex::QuoteNode, indent::Int) + inner = indent + sexpr_indent_width + print(io, "(:quote, #QuoteNode\n", " "^inner) + show_sexpr(io, ex.value, inner) + print(io, '\n', " "^indent, ')') +end +function show_sexpr(io::IO, ex::Expr, indent::Int) + inner = indent + sexpr_indent_width + print(io, '(') + show_sexpr(io, ex.head, inner) + for arg in ex.args + print(io, ex.head === :block ? ",\n"*" "^inner : ", ") + show_sexpr(io, arg, inner) + end + if length(ex.args) == 0; print(io, ",)") + else print(io, (ex.head === :block ? "\n"*" "^indent : ""), ')') + end +end + +end # module diff --git a/base/mmap.jl b/base/mmap.jl index ea76cd051282e..773975d6591c9 100644 --- a/base/mmap.jl +++ b/base/mmap.jl @@ -66,7 +66,7 @@ end # Higher-level functions # Determine a stream's read/write mode, and return prot & flags # appropriate for mmap -function mmap_stream_settings(s::IOStream) +function mmap_stream_settings(s::IO) const PROT_READ::Int32 = 1 const PROT_WRITE::Int32 = 2 const MAP_SHARED::Int32 = 1 @@ -88,7 +88,7 @@ function mmap_stream_settings(s::IOStream) end # Mmapped-array constructor -function mmap_array{T,N}(::Type{T}, dims::NTuple{N,Int}, s::IOStream, offset::FileOffset) +function mmap_array{T,N}(::Type{T}, dims::NTuple{N,Int}, s::IO, offset::FileOffset) prot, flags, iswrite = mmap_stream_settings(s) len = prod(dims)*sizeof(T) if iswrite @@ -100,7 +100,7 @@ function mmap_array{T,N}(::Type{T}, dims::NTuple{N,Int}, s::IOStream, offset::Fi finalizer(A,x->munmap(pmap,len+delta)) return A end -mmap_array{T,N}(::Type{T}, dims::NTuple{N,Int}, s::IOStream) = mmap_array(T, dims, s, position(s)) +mmap_array{T,N}(::Type{T}, dims::NTuple{N,Int}, s::IO) = mmap_array(T, dims, s, position(s)) msync{T}(A::Array{T}, flags::Int) = msync(pointer(A), prod(size(A))*sizeof(T), flags) msync{T}(A::Array{T}) = msync(A,MS_SYNC) diff --git a/base/multi.jl b/base/multi.jl index 3cd94e14d9262..2b679b3591ff5 100644 --- a/base/multi.jl +++ b/base/multi.jl @@ -52,7 +52,7 @@ # - timer events # - send pings at some interval to detect failed/hung machines # - integrate event loop with other kinds of i/o (non-messages) -# ? method_missing for waiting (ref/assign/localdata seems to cover a lot) +# ? method_missing for waiting (getindex/setindex!/localdata seems to cover a lot) # * serializing closures # * recover from i/o errors # * handle remote execution errors @@ -66,11 +66,11 @@ ## workers and message i/o ## -function send_msg_unknown(s::IOStream, kind, args) +function send_msg_unknown(s::IO, kind, args) error("attempt to send to unknown socket") end -function send_msg(s::IOStream, kind, args...) +function send_msg(s::IO, kind, args...) id = worker_id_from_socket(s) if id > -1 return send_msg(worker_from_id(id), kind, args...) @@ -78,7 +78,7 @@ function send_msg(s::IOStream, kind, args...) send_msg_unknown(s, kind, args) end -function send_msg_now(s::IOStream, kind, args...) +function send_msg_now(s::IO, kind, args...) id = worker_id_from_socket(s) if id > -1 return send_msg_now(worker_from_id(id), kind, args...) @@ -87,34 +87,25 @@ function send_msg_now(s::IOStream, kind, args...) end type Worker - host::String - port::Int16 - fd::Int32 - socket::IOStream - sendbuf::IOStream + host::ByteString + port::Uint16 + socket::TcpSocket + sendbuf::IOBuffer del_msgs::Array{Any,1} add_msgs::Array{Any,1} id::Int gcflag::Bool - function Worker(host::ByteString, port, tunnel_user) - if tunnel_user != "" - connect_host = "localhost" - connect_port = ssh_tunnel(tunnel_user, host, port) - else - connect_host, connect_port = host, port - end - fd = ccall(:connect_to_host, Int32, (Ptr{Uint8}, Int16), - connect_host, connect_port) - if fd == -1 - error("could not connect to $host:$port, errno=$(errno())\n") - end - Worker(host, port, fd, fdio(fd, true), 0) - end - - Worker(host::ByteString, port) = Worker(host, port, "") - Worker(host,port,fd,sock,id) = new(host, port, fd, sock, memio(), {}, {}, id, false) + Worker(host::String, port::Integer, sock::TcpSocket, id::Int) = + new(bytestring(host), uint16(port), sock, IOBuffer(), {}, {}, id, false) end +Worker(host::String, port::Integer, sock::TcpSocket) = + Worker(host, port, sock, 0) +Worker(host::String, port::Integer) = + Worker(host, port, connect(host,uint16(port))) +Worker(host::String, port::Integer, tunnel_user::String) = + Worker(host, port, connect("localhost", + ssh_tunnel(tunnel_user, host, uint16(port)))) function send_msg_now(w::Worker, kind, args...) send_msg_(w, kind, args, true) @@ -128,37 +119,42 @@ function flush_gc_msgs(w::Worker) w.gcflag = false msgs = w.add_msgs if !isempty(msgs) - del_all(w.add_msgs) + empty!(w.add_msgs) remote_do(w, add_clients, msgs...) end msgs = w.del_msgs if !isempty(msgs) - del_all(w.del_msgs) + empty!(w.del_msgs) #print("sending delete of $msgs\n") remote_do(w, del_clients, msgs...) end end +#TODO: Move to different Thread +function enq_send_req(sock::TcpSocket,buf,now::Bool) + arr=takebuf_array(buf) + write(sock,arr) + #TODO implement "now" +end + function send_msg_(w::Worker, kind, args, now::Bool) + #println("Sending msg $kind") buf = w.sendbuf - ccall(:jl_buf_mutex_lock, Void, (Ptr{Void},), buf.ios) serialize(buf, kind) for arg in args serialize(buf, arg) end - ccall(:jl_buf_mutex_unlock, Void, (Ptr{Void},), buf.ios) if !now && w.gcflag flush_gc_msgs(w) else - ccall(:jl_enq_send_req, Void, (Ptr{Void}, Ptr{Void}, Int32), - w.socket.ios, w.sendbuf.ios, now ? int32(1) : int32(0)) + enq_send_req(w.socket,buf,now) end end function flush_gc_msgs() - for w = (PGRP::ProcessGroup).workers + for w in (PGRP::ProcessGroup).workers if isa(w,Worker) k = w::Worker if k.gcflag @@ -173,12 +169,6 @@ end type LocalProcess end -type Location - host::String - port::Int16 - Location(h,p::Integer) = new(h,int16(p)) -end - type ProcessGroup myid::Int workers::Array{Any,1} @@ -192,48 +182,27 @@ type ProcessGroup return new(myid, w, locs, length(w), Dict()) end end +const PGRP = ProcessGroup(0, {}, {}) function add_workers(PGRP::ProcessGroup, w::Array{Any,1}) n = length(w) - locs = map(x->Location(x.host,x.port), w) + locs = map(x->(x.host,x.port), w) # NOTE: currently only node 1 can add new nodes, since nobody else # has the full list of address:port newlocs = [PGRP.locs, locs] - sockets = Dict() - handler = fd->message_handler(fd, sockets) for i=1:n - push(PGRP.workers, w[i]) + push!(PGRP.workers, w[i]) w[i].id = PGRP.np+i send_msg_now(w[i], w[i].id, newlocs) - sockets[w[i].fd] = w[i].socket - add_fd_handler(w[i].fd, handler) + create_message_handler_loop(w[i].socket) end PGRP.locs = newlocs PGRP.np += n :ok end -function _jl_join_pgroup(myid, locs, sockets) - # joining existing process group - np = length(locs) - w = cell(np) - w[myid] = LocalProcess() - handler = fd->message_handler(fd, sockets) - for i = 2:(myid-1) - w[i] = Worker(locs[i].host, locs[i].port) - w[i].id = i - sockets[w[i].fd] = w[i].socket - add_fd_handler(w[i].fd, handler) - send_msg_now(w[i], :identify_socket, myid) - end - for i = (myid+1):np - w[i] = nothing - end - ProcessGroup(myid, w, locs) -end - -myid() = (PGRP::ProcessGroup).myid -nprocs() = (PGRP::ProcessGroup).np +myid() = PGRP.myid +nprocs() = PGRP.np function worker_from_id(i) pg = PGRP::ProcessGroup @@ -261,24 +230,24 @@ function worker_id_from_socket(s) end # establish a Worker connection for processes that connected to us -function _jl_identify_socket(otherid, fd, sock) +function identify_socket(otherid, sock) i = otherid #locs = PGRP.locs @assert i > PGRP.myid d = i-length(PGRP.workers) if d > 0 - grow(PGRP.workers, d) + resize!(PGRP.workers, i) PGRP.workers[(end-d+1):end] = nothing PGRP.np += d end - PGRP.workers[i] = Worker("", 0, fd, sock, i) - #write(stdout_stream, "$(PGRP.myid) heard from $i\n") + PGRP.workers[i] = Worker("", 0, sock, i) + #write(STDOUT, "$(PGRP.myid) heard from $i\n") nothing end ## remote refs and core messages: do, call, fetch, wait, ref, put ## -const _jl_client_refs = WeakKeyDict() +const client_refs = WeakKeyDict() type RemoteRef where::Int @@ -288,11 +257,11 @@ type RemoteRef function RemoteRef(w, wh, id) r = new(w,wh,id) - found = key(_jl_client_refs, r, false) + found = getkey(client_refs, r, false) if !is(found,false) return found end - _jl_client_refs[r] = true + client_refs[r] = true finalizer(r, send_del_client) r end @@ -348,7 +317,7 @@ function lookup_ref(id) wi = WorkItem(bottom_func) # this WorkItem is just for storing the result value GRP.refs[id] = wi - add(wi.clientset, id[1]) + add!(wi.clientset, id[1]) end wi end @@ -372,9 +341,9 @@ end function del_client(id, client) wi = lookup_ref(id) - del(wi.clientset, client) + delete!(wi.clientset, client) if isempty(wi.clientset) - del((PGRP::ProcessGroup).refs, id) + delete!((PGRP::ProcessGroup).refs, id) #print("$(myid()) collected $id\n") end nothing @@ -386,19 +355,22 @@ function del_clients(pairs::(Any,Any)...) end end +any_gc_flag = false + function send_del_client(rr::RemoteRef) if rr.where == myid() del_client(rr2id(rr), myid()) else w = worker_from_id(rr.where) - push(w.del_msgs, (rr2id(rr), myid())) + push!(w.del_msgs, (rr2id(rr), myid())) w.gcflag = true + global any_gc_flag = true end end function add_client(id, client) wi = lookup_ref(id) - add(wi.clientset, client) + add!(wi.clientset, client) nothing end @@ -416,8 +388,9 @@ function send_add_client(rr::RemoteRef, i) # to the processor that owns the remote ref. it will add_client # itself inside deserialize(). w = worker_from_id(rr.where) - push(w.add_msgs, (rr2id(rr), i)) + push!(w.add_msgs, (rr2id(rr), i)) w.gcflag = true + global any_gc_flag = true end end @@ -430,12 +403,12 @@ function serialize(s, rr::RemoteRef) end function deserialize(s, t::Type{RemoteRef}) - rr = invoke(deserialize, (Any, CompositeKind), s, t) + rr = invoke(deserialize, (Any, DataType), s, t) where = rr.where if where == myid() add_client(rr2id(rr), myid()) end - # call ctor to make sure this rr gets added to the _jl_client_refs table + # call ctor to make sure this rr gets added to the client_refs table RemoteRef(where, rr.whence, rr.id) end @@ -445,7 +418,7 @@ schedule_call(rid, f_thk, args_thk) = function schedule_call(rid, thunk) wi = WorkItem(thunk) (PGRP::ProcessGroup).refs[rid] = wi - add(wi.clientset, rid[1]) + add!(wi.clientset, rid[1]) enq_work(wi) wi end @@ -579,7 +552,7 @@ fetch(x::ANY) = x # writing to an uninitialized ref function put_ref(rid, val::ANY) wi = lookup_ref(rid) - if wi.done + while wi.done wi.notify = ((), :take, rid, wi.notify) yield(WaitFor(:take, RemoteRef(myid(), rid[1], rid[2]))) end @@ -600,7 +573,7 @@ end function take_ref(rid) wi = lookup_ref(rid) - if !wi.done + while !wi.done wait(RemoteRef(myid(), rid[1], rid[2])) end val = wi.result @@ -646,13 +619,16 @@ type WaitFor rr end -enq_work(wi::WorkItem) = enqueue(Workqueue, wi) +function enq_work(wi::WorkItem) + ccall(:uv_stop,Void,(Ptr{Void},),eventloop()) + unshift!(Workqueue, wi) +end enq_work(f::Function) = enq_work(WorkItem(f)) enq_work(t::Task) = enq_work(WorkItem(t)) function perform_work() - job = pop(Workqueue) + job = pop!(Workqueue) perform_work(job) end @@ -667,15 +643,13 @@ function perform_work(job::WorkItem) result = is(arg,()) ? yieldto(job.task) : yieldto(job.task, arg) else job.task = Task(job.thunk) - job.task.tls = nothing result = yieldto(job.task) end - catch e - #show(e) + catch err print("exception on ", myid(), ": ") - show(e) + display_error(err,catch_backtrace()) println() - result = e + result = err end # restart job by yielding back to whatever task just switched to us job.task = current_task().last @@ -700,7 +674,7 @@ function perform_work(job::WorkItem) if P.consumers === nothing P.consumers = {job} else - enqueue(P.consumers, job) + unshift!(P.consumers, job) end else # add to waiting set to wait on a sync event @@ -712,16 +686,20 @@ function perform_work(job::WorkItem) if isequal(waiters,false) Waiting[oid] = {waitinfo} else - push(waiters, waitinfo) + push!(waiters, waitinfo) end end + elseif isa(result,WaitTask) + job.task.runnable = false + wt::WaitTask = result + wt.job = job elseif job.task.runnable # otherwise return to queue enq_work(job) end end -function deliver_result(sock::IOStream, msg, oid, value) +function deliver_result(sock::IO, msg, oid, value) #print("$(myid()) sending result $oid\n") if is(msg,:fetch) || is(msg,:call_fetch) val = value @@ -731,29 +709,29 @@ function deliver_result(sock::IOStream, msg, oid, value) end try send_msg_now(sock, :result, msg, oid, val) - catch e + catch err # send exception in case of serialization error; otherwise # request side would hang. - send_msg_now(sock, :result, msg, oid, e) + send_msg_now(sock, :result, msg, oid, err) end end -const _jl_empty_cell_ = {} +const empty_cell_ = {} function deliver_result(sock::(), msg, oid, value) # restart task that's waiting on oid - jobs = get(Waiting, oid, _jl_empty_cell_) + jobs = get(Waiting, oid, empty_cell_) for i = 1:length(jobs) j = jobs[i] if j[1]==msg job = j[2] job.argument = value enq_work(job) - del(jobs, i) + delete!(jobs, i) break end end - if isempty(jobs) && !is(jobs,_jl_empty_cell_) - del(Waiting, oid) + if isempty(jobs) && !is(jobs,empty_cell_) + delete!(Waiting, oid) end nothing end @@ -772,7 +750,7 @@ function notify_done(job::WorkItem, take) if is(msg,:call_fetch) # can delete the ref right away since we know it is # unreferenced by the client - del((PGRP::ProcessGroup).refs, oid) + delete!((PGRP::ProcessGroup).refs, oid) end end else @@ -786,40 +764,48 @@ end ## message event handlers ## # activity on accept fd -function accept_handler(accept_fd, sockets) - global PGRP - connectfd = ccall(:accept, Int32, (Int32, Ptr{Void}, Ptr{Void}), - accept_fd, C_NULL, C_NULL) - #print("accepted.\n") - if connectfd==-1 - print("accept error: ", strerror(), "\n") - else - first = isempty(sockets) - sock = fdio(connectfd, true) - sockets[connectfd] = sock - if first - # first connection; get process group info from client - _myid = deserialize(sock) - locs = deserialize(sock) - PGRP = _jl_join_pgroup(_myid, locs, sockets) - PGRP.workers[1] = Worker("", 0, connectfd, sock, 1) - end - add_fd_handler(connectfd, fd->message_handler(fd, sockets)) +function accept_handler(server::TcpSocket, status::Int32) + if(status == -1) + error("An error occured during the creation of the server") end + client = accept_nonblock(server) + create_message_handler_loop(client) end type DisconnectException <: Exception end -# activity on message socket -function message_handler(fd, sockets) - refs = (PGRP::ProcessGroup).refs - sock = sockets[fd] - first = true - while first || nb_available(sock)>0 - first = false - try - msg = deserialize(sock) - #print("$(myid()) got $msg\n") +function create_message_handler_loop(sock::AsyncStream) #returns immediately + enq_work(@task begin + global PGRP + #println("message_handler_loop") + start_reading(sock) + wait_connected(sock) + if PGRP.np == 0 + # first connection; get process group info from client + PGRP.myid = deserialize(sock) + PGRP.locs = locs = deserialize(sock) + #print("\nLocation: ",locs,"\nId:",PGRP.myid,"\n") + # joining existing process group + PGRP.np = length(PGRP.locs) + PGRP.workers = w = cell(PGRP.np) + fill!(w, nothing) + w[1] = Worker("", 0, sock, 1) + for i = 2:(PGRP.myid-1) + w[i] = Worker(locs[i][1], locs[i][2]) + w[i].id = i + create_message_handler_loop(w[i].socket) + send_msg_now(w[i], :identify_socket, PGRP.myid) + end + w[PGRP.myid] = LocalProcess() + for i = (PGRP.myid+1):PGRP.np + w[i] = nothing + end + end + #println("loop") + while true + #try + msg = deserialize(sock) + #println("got msg: ",msg) # handle message if is(msg, :call) || is(msg, :call_fetch) || is(msg, :call_wait) id = deserialize(sock) @@ -835,7 +821,7 @@ function message_handler(fd, sockets) elseif is(msg, :do) f = deserialize(sock) args = deserialize(sock) - #print("$(myid()) got $args\n") + #print("got args: $args\n") let func=f, ar=args enq_work(WorkItem(()->apply(func, ar))) end @@ -847,7 +833,7 @@ function message_handler(fd, sockets) deliver_result((), mkind, oid, val) elseif is(msg, :identify_socket) otherid = deserialize(sock) - _jl_identify_socket(otherid, fd, sock) + identify_socket(otherid, sock) else # the synchronization messages oid = deserialize(sock)::(Int,Int) @@ -861,81 +847,68 @@ function message_handler(fd, sockets) wi.notify = (sock, msg, oid, wi.notify) end end - catch e - if isa(e,EOFError) + #catch e + # if isa(e,EOFError) #print("eof. $(myid()) exiting\n") - del_fd_handler(fd) - # TODO: remove machine from group - throw(DisconnectException()) - else - print("deserialization error: ", e, "\n") - read(sock, Uint8, nb_available(sock)) - #while nb_available(sock) > 0 #|| select(sock) - # read(sock, Uint8) + # stop_reading(sock) + # # TODO: remove machine from group + # throw(DisconnectException()) + # else + # print("deserialization: ", e, "\n") + # #while nb_available(sock) > 0 #|| select(sock) + # # read(sock, Uint8) + # #end #end - end + #end end - end + end) end ## worker creation and setup ## # the entry point for julia worker processes. does not return. # argument is descriptor to write listening port # to. -start_worker() = start_worker(1) -function start_worker(wrfd) - port = [int16(9009)] - sockfd = ccall(:open_any_tcp_port, Int32, (Ptr{Int16},), port) - if sockfd == -1 - error("could not bind socket") - end - io = fdio(wrfd) - write(io, "julia_worker:") # print header - write(io, "$(dec(port[1]))#") # print port - write(io, getipaddr()) # print hostname - write(io, '\n') - flush(io) - # close stdin; workers will not use it - ccall(:close, Int32, (Int32,), 0) +start_worker() = start_worker(STDOUT) +function start_worker(out::IO) + default_port = uint16(9009) + (actual_port,sock) = open_any_tcp_port(accept_handler,default_port) + write(out, "julia_worker:") # print header + write(out, "$(dec(actual_port))#") # print port + write(out, bind_addr) #TODO: print hostname + write(out, '\n') + # close STDIN; workers will not use it + #close(STDIN) ccall(:jl_install_sigint_handler, Void, ()) global const Scheduler = current_task() - worker_sockets = Dict() - add_fd_handler(sockfd, fd->accept_handler(fd, worker_sockets)) - try event_loop(false) - catch e - print("unhandled exception on $(myid()): $e\nexiting.\n") + catch err + print("unhandled exception on $(myid()): $(err)\nexiting.\n") end - ccall(:close, Int32, (Int32,), sockfd) - ccall(:exit , Void , (Int32,), 0) + close(sock) + exit(0) end start_remote_workers(m, c) = start_remote_workers(m, c, false) function start_remote_workers(machines, cmds, tunnel) n = length(cmds) outs = cell(n) + w = cell(n) for i=1:n - let fd = read_from(cmds[i]).fd - let stream = fdio(fd, true) - outs[i] = stream - # redirect console output from workers to the client's stdout - add_fd_handler(fd, fd->write(stdout_stream, readline(stream))) - end - end - end - for c in cmds - spawn(c) + outs[i],_ = readsfrom(cmds[i]) + outs[i].line_buffered = true end - w = cell(n) for i=1:n local hostname::String, port::Int16 + stream = outs[i] + stream.line_buffered = true while true - conninfo = readline(outs[i]) + wait_readline(stream) + conninfo = readline(stream.buffer) hostname, port = parse_connection_info(conninfo) if hostname != "" break @@ -952,6 +925,21 @@ function start_remote_workers(machines, cmds, tunnel) else w[i] = Worker(hostname, port) end + let wrker = w[i] + # redirect console output from workers to the client's stdout: + start_reading(stream,function(stream::AsyncStream,nread::Int) + if(nread>0) + try + line = readbytes(stream.buffer, nread) + print("\tFrom worker $(wrker.id):\t",line) + catch err + println("\tError parsing reply from worker $(wrker.id):\t",err) + return false + end + end + true + end) + end end w end @@ -959,23 +947,23 @@ end function parse_connection_info(str) m = match(r"^julia_worker:(\d+)#(.*)", str) if m != nothing - (m.captures[2], parse_int(Int16, m.captures[1])) + (m.captures[2], parseint(Int16, m.captures[1])) else ("", int16(-1)) end end -_jl_tunnel_port = 9201 +tunnel_port = 9201 # establish an SSH tunnel to a remote worker # returns P such that localhost:P connects to host:port ssh_tunnel(host, port) = ssh_tunnel(ENV["USER"], host, port) function ssh_tunnel(user, host, port) - global _jl_tunnel_port - localp = _jl_tunnel_port::Int + global tunnel_port + localp = tunnel_port::Int while !success(`ssh -f -o ExitOnForwardFailure=yes $(user)@$host -L $localp:$host:$port -N`) localp += 1 end - _jl_tunnel_port = localp+1 + tunnel_port = localp+1 localp end @@ -1001,15 +989,15 @@ end #function addprocs_ssh(machines, keys) # if !(isa(keys, Array)) && isa(machines,Array) # key = keys -# keys = [ key for x = 1:numel(machines)] -# cmdargs = { {machines[x],keys[x]} for x = 1:numel(machines)} +# keys = [ key for x = 1:length(machines)] +# cmdargs = { {machines[x],keys[x]} for x = 1:length(machines)} # else # cmdargs = {{machines,keys}} # end #if/else # add_workers(PGRP, start_remote_workers(machines, map(x->worker_ssh_cmd(x[1],x[2]), cmdargs))) #end -worker_local_cmd() = `$JULIA_HOME/julia-release-basic --worker` +worker_local_cmd() = `$JULIA_HOME/julia-release-basic --bind-to $bind_addr --worker` addprocs_local(np::Integer) = add_workers(PGRP, start_remote_workers({ "localhost" for i=1:np }, @@ -1018,17 +1006,16 @@ addprocs_local(np::Integer) = function start_sge_workers(n) home = JULIA_HOME - sgedir = "$home/../../SGE" + sgedir = joinpath(pwd(),"SGE") run(`mkdir -p $sgedir`) - qsub_cmd = `qsub -N JULIA -terse -e $sgedir -o $sgedir -t 1:$n` - `echo $home/julia-release-basic --worker` | qsub_cmd - out = cmd_stdout_stream(qsub_cmd) + qsub_cmd = `echo $home/julia-release-basic --worker` | `qsub -N JULIA -terse -cwd -j y -o $sgedir -t 1:$n` + out,_ = readsfrom(qsub_cmd) if !success(qsub_cmd) error("batch queue not available (could not run qsub)") end - id = split(readline(out),'.')[1] + id = chomp(split(readline(out),'.')[1]) println("job id is $id") - print("waiting for job to start"); flush(stdout_stream) + print("waiting for job to start"); workers = cell(n) for i=1:n # wait for each output stream file to get created @@ -1047,7 +1034,7 @@ function start_sge_workers(n) end fexists = (hostname != "") catch - print("."); flush(stdout_stream) + print("."); sleep(0.5) end end @@ -1062,15 +1049,15 @@ addprocs_sge(n) = add_workers(PGRP, start_sge_workers(n)) ## higher-level functions: spawn, pmap, pfor, etc. ## -sync_begin() = tls(:SPAWNS, ({}, get(tls(), :SPAWNS, ()))) +sync_begin() = task_local_storage(:SPAWNS, ({}, get(task_local_storage(), :SPAWNS, ()))) function sync_end() - spawns = get(tls(), :SPAWNS, ()) + spawns = get(task_local_storage(), :SPAWNS, ()) if is(spawns,()) error("sync_end() without sync_begin()") end refs = spawns[1] - tls(:SPAWNS, spawns[2]) + task_local_storage(:SPAWNS, spawns[2]) for r in refs wait(r) end @@ -1086,9 +1073,9 @@ macro sync(block) end function sync_add(r) - spawns = get(tls(), :SPAWNS, ()) + spawns = get(task_local_storage(), :SPAWNS, ()) if !is(spawns,()) - push(spawns[1], r) + push!(spawns[1], r) end r end @@ -1096,8 +1083,8 @@ end spawnat(p, thunk) = sync_add(remote_call(p, thunk)) let lastp = 1 - global spawn - function spawn(thunk::Function) + global chooseproc + function chooseproc(thunk::Function) p = -1 env = thunk.env if isa(env,Tuple) @@ -1116,17 +1103,19 @@ let lastp = 1 lastp = 1 end end - spawnat(p, thunk) + p end end +spawn_somewhere(thunk) = spawnat(chooseproc(thunk),thunk) + find_vars(e) = find_vars(e, {}) function find_vars(e, lst) if isa(e,Symbol) if !isdefined(e) || isconst(e) # exclude global constants else - push(lst, e) + push!(lst, e) end elseif isa(e,Expr) for x in e.args @@ -1137,17 +1126,21 @@ function find_vars(e, lst) end # wrap an expression in "let a=a,b=b,..." for each var it references -function localize_vars(expr) +localize_vars(expr) = localize_vars(expr, true) +function localize_vars(expr, esca) v = find_vars(expr) # requires a special feature of the front end that knows how to insert # the correct variables. the list of free variables cannot be computed # from a macro. - Expr(:localize, {:(()->($expr)), v...}, Any) + if esca + v = map(esc,v) + end + Expr(:localize, :(()->($expr)), v...) end macro spawn(expr) - expr = localize_vars(:(()->($expr))) - :(spawn($(esc(expr)))) + expr = localize_vars(:(()->($expr)), false) + :(spawn_somewhere($(esc(expr)))) end function spawnlocal(thunk) @@ -1156,23 +1149,24 @@ function spawnlocal(thunk) rid = rr2id(rr) wi = WorkItem(thunk) (PGRP::ProcessGroup).refs[rid] = wi - add(wi.clientset, rid[1]) - push(Workqueue, wi) # add to the *front* of the queue, work first + add!(wi.clientset, rid[1]) + push!(Workqueue, wi) # add to the *front* of the queue, work first yield() rr end -macro spawnlocal(expr) - expr = localize_vars(:(()->($expr))) +macro async(expr) + expr = localize_vars(:(()->($expr)), false) :(spawnlocal($(esc(expr)))) end -macro async(expr) - :(@spawnlocal $(esc(expr))) +macro spawnlocal(expr) + warn_once("@spawnlocal is deprecated, use @async instead.") + :(@async $(esc(expr))) end macro spawnat(p, expr) - expr = localize_vars(:(()->($expr))) + expr = localize_vars(:(()->($expr)), false) :(spawnat($(esc(p)), $(esc(expr)))) end @@ -1185,7 +1179,7 @@ end macro everywhere(ex) quote @sync begin - at_each(()->eval(Main,$(expr(:quote,ex)))) + at_each(()->eval(Main,$(Expr(:quote,ex)))) end end end @@ -1248,7 +1242,7 @@ function preduce(reducer, f, r::Range1{Int}) end results[i] = @spawn f(lo, hi) end - mapreduce(reducer, fetch, results) + mapreduce(fetch, reducer, results) end function pfor(f, r::Range1{Int}) @@ -1359,12 +1353,6 @@ end ## event processing, I/O and work scheduling ## -function make_scheduled(t::Task) - t.parent = Scheduler - enq_work(WorkItem(t)) - t -end - function yield(args...) ct = current_task() # preserve Task.last across calls to the scheduler @@ -1374,58 +1362,39 @@ function yield(args...) return v end -const _jl_fd_handlers = Dict() - -add_fd_handler(fd::Int32, H) = (_jl_fd_handlers[fd]=H) -del_fd_handler(fd::Int32) = del(_jl_fd_handlers, fd) - function event_loop(isclient) - fdset = FDSet() - iserr, lasterr = false, () - + iserr, lasterr, bt = false, nothing, {} while true try if iserr - show(lasterr) - iserr, lasterr = false, () - end - while true - del_all(fdset) - for (fd,_) = _jl_fd_handlers - add(fdset, fd) - end - - bored = isempty(Workqueue) - if bored - flush_gc_msgs() - end - nselect = select_read(fdset, bored ? 10.0 : 0.0) - if nselect == 0 - if !isempty(Workqueue) - perform_work() - end - else - for fd=int32(0):int32(fdset.nfds-1) - if has(fdset,fd) - h = _jl_fd_handlers[fd] - h(fd) + display_error(lasterr, bt) + iserr, lasterr, bt = false, nothing, {} + else + while true + if isempty(Workqueue) + if any_gc_flag + flush_gc_msgs() end + process_events(true) + else + perform_work() + process_events(false) end end end - catch e - if isa(e,DisconnectException) + catch err + bt = catch_backtrace() + if isa(err,DisconnectException) # TODO: wake up tasks waiting for failed process if !isclient return end - elseif isclient && isa(e,InterruptException) && - !has(_jl_fd_handlers, STDIN.fd) + elseif isclient && isa(err,InterruptException) # root task is waiting for something on client. allow C-C # to interrupt. - interrupt_waiting_task(_jl_roottask_wi, e) + interrupt_waiting_task(roottask_wi,err) end - iserr, lasterr = true, e + iserr, lasterr = true, err end end end @@ -1441,4 +1410,6 @@ function interrupt_waiting_task(wi::WorkItem, with_value) end end end + wi.argument = with_value + enq_work(wi) end diff --git a/base/number.jl b/base/number.jl index 4a7c9178f556a..9bf7c9b45912d 100644 --- a/base/number.jl +++ b/base/number.jl @@ -11,15 +11,20 @@ integer_valued(x::Integer) = true isbool(x::Number) = false isbool(x::Bool) = true -const islogical = isbool size(x::Number) = () +size(x::Number,d) = convert(Int,d)<1 ? throw(BoundsError()) : 1 eltype(x::Number) = typeof(x) eltype{T<:Number}(::Type{T}) = T ndims(x::Number) = 0 ndims{T<:Number}(::Type{T}) = 0 length(x::Number) = 1 -ref(x::Number) = x +endof(x::Number) = 1 +getindex(x::Number) = x +getindex(x::Number, i::Integer) = i == 1 ? x : throw(BoundsError()) +getindex(x::Number, i::Real) = getindex(x, to_index(i)) +first(x::Number) = x +last(x::Number) = x signbit(x::Real) = int(x < 0) sign(x::Real) = x < 0 ? -one(x) : x > 0 ? one(x) : x @@ -32,11 +37,12 @@ ctranspose(x::Number) = conj(x) inv(x::Number) = one(x)/x angle(z::Real) = atan2(zero(z), z) -# TODO: should we really treat numbers as iterable? -start(a::Real) = a -next(a::Real, i) = (a, a+1) -done(a::Real, i) = (i > a) -isempty(a::Number) = false -contains(s::Number, n::Number) = (s == n) +start(x::Number) = false +next(x::Number, state) = (x, true) +done(x::Number, state) = state +isempty(x::Number) = false +contains(x::Number, y::Number) = x == y reinterpret{T<:Real}(::Type{T}, x::Real) = box(T,x) + +map(f, x::Number) = f(x) diff --git a/base/operators.jl b/base/operators.jl index cadb524985fa1..904fc2bccdf65 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -2,7 +2,7 @@ const (<:) = subtype -super(T::Union(CompositeKind,BitsKind,AbstractKind)) = T.super +super(T::DataType) = T.super ## comparison ## @@ -123,24 +123,16 @@ zero(x) = oftype(x,0) one(x) = oftype(x,1) sizeof(T::Type) = error(string("size of type ",T," unknown")) -sizeof(T::BitsKind) = div(T.nbits,8) +sizeof(T::DataType) = if isleaftype(T) T.size else error("type does not have a native size") end sizeof(x) = sizeof(typeof(x)) # copying immutable things copy(x::Union(Symbol,Number,String,Function,Tuple,LambdaStaticData, - TopNode,QuoteNode,BitsKind,CompositeKind,AbstractKind, - UnionKind)) = x + TopNode,QuoteNode,DataType,UnionType)) = x -# function composition & pipelining -one(f::Function) = identity -one(::Type{Function}) = identity -*(f::Function, g::Function) = x->f(g(x)) +# function pipelining |(x, f::Function) = f(x) -# currying of map, filter, etc. -map(f::Function) = (x...)->map(f, x...) -filter(f::Function) = (x...)->filter(f, x...) - # array shape rules function promote_shape(a::(Int,), b::(Int,)) @@ -176,25 +168,25 @@ function promote_shape(a::Dims, b::Dims) return a end -# shape of array to create for ref() with indexes I -function ref_shape(I...) +# shape of array to create for getindex() with indexes I +function index_shape(I...) n = length(I) while n > 0 && isa(I[n],Real); n-=1; end tuple([length(I[i]) for i=1:n]...) end -ref_shape(i::Real) = () -ref_shape(i) = (length(i),) -ref_shape(i::Real,j::Real) = () -ref_shape(i ,j::Real) = (length(i),) -ref_shape(i ,j) = (length(i),length(j)) -ref_shape(i::Real,j::Real,k::Real) = () -ref_shape(i ,j::Real,k::Real) = (length(i),) -ref_shape(i ,j ,k::Real) = (length(i),length(j)) -ref_shape(i ,j ,k ) = (length(i),length(j),length(k)) +index_shape(i::Real) = () +index_shape(i) = (length(i),) +index_shape(i::Real,j::Real) = () +index_shape(i ,j::Real) = (length(i),) +index_shape(i ,j) = (length(i),length(j)) +index_shape(i::Real,j::Real,k::Real) = () +index_shape(i ,j::Real,k::Real) = (length(i),) +index_shape(i ,j ,k::Real) = (length(i),length(j)) +index_shape(i ,j ,k ) = (length(i),length(j),length(k)) # check for valid sizes in A[I...] = X where X <: AbstractArray -function assign_shape_check(X::AbstractArray, I...) +function setindex_shape_check(X::AbstractArray, I...) nel = 1 for idx in I nel *= length(idx) @@ -211,39 +203,92 @@ function assign_shape_check(X::AbstractArray, I...) end end -# convert Real to integer index +# convert to integer index +to_index(i) = i to_index(i::Real) = convert(Int, i) +to_index(i::Int) = i # vectorization macro vectorize_1arg(S,f) S = esc(S); f = esc(f); T = esc(:T) quote - function ($f){$T<:$S}(x::AbstractArray{$T,1}) - [ ($f)(x[i]) for i=1:length(x) ] - end - function ($f){$T<:$S}(x::AbstractArray{$T,2}) + ($f){$T<:$S}(x::AbstractArray{$T,1}) = [ ($f)(x[i]) for i=1:length(x) ] + ($f){$T<:$S}(x::AbstractArray{$T,2}) = [ ($f)(x[i,j]) for i=1:size(x,1), j=1:size(x,2) ] - end - function ($f){$T<:$S}(x::AbstractArray{$T}) - reshape([ ($f)(x[i]) for i=1:numel(x) ], size(x)) - end + ($f){$T<:$S}(x::AbstractArray{$T}) = + reshape([ ($f)(x[i]) for i=1:length(x) ], size(x)) end end macro vectorize_2arg(S,f) S = esc(S); f = esc(f); T1 = esc(:T1); T2 = esc(:T2) quote - function ($f){$T1<:$S, $T2<:$S}(x::($T1), y::AbstractArray{$T2}) - reshape([ ($f)(x, y[i]) for i=1:numel(y) ], size(y)) - end - function ($f){$T1<:$S, $T2<:$S}(x::AbstractArray{$T1}, y::($T2)) - reshape([ ($f)(x[i], y) for i=1:numel(x) ], size(x)) - end + ($f){$T1<:$S, $T2<:$S}(x::($T1), y::AbstractArray{$T2}) = + reshape([ ($f)(x, y[i]) for i=1:length(y) ], size(y)) + ($f){$T1<:$S, $T2<:$S}(x::AbstractArray{$T1}, y::($T2)) = + reshape([ ($f)(x[i], y) for i=1:length(x) ], size(x)) function ($f){$T1<:$S, $T2<:$S}(x::AbstractArray{$T1}, y::AbstractArray{$T2}) shp = promote_shape(size(x),size(y)) - reshape([ ($f)(x[i], y[i]) for i=1:numel(x) ], shp) + reshape([ ($f)(x[i], y[i]) for i=1:length(x) ], shp) end end end + +# some operators not defined yet +global //, .>>, .<<, &>, &>>, &<, &<< + +module Operators + +export + !, + !=, + $, + %, + &, + *, + +, + -, + .!=, + .+, + .-, + .*, + ./, + .<, + .<=, + .==, + .>, + .>=, + .\, + .^, + /, + //, + <, + <:, + <<, + <=, + ==, + >, + >=, + >>, + .>>, + .<<, + >>>, + &>, + &>>, + &<, + &<<, + \, + ^, + |, + ~ + +import + Base.!, Base.!=, Base.$, Base.%, Base.&, Base.*, Base.+, Base.-, Base..!=, + Base..+, Base..-, Base..*, Base../, Base..<, Base..<=, Base..==, Base..>, + Base..>=, Base..\, Base..^, Base./, Base.//, Base.<, Base.<:, Base.<<, + Base.<=, Base.==, Base.>, Base.>=, Base.>>, Base..>>, Base..<<, Base.>>>, + Base.&>, Base.&>>, Base.&<, Base.&<<, Base.\, Base.^, Base.|, Base.~ + +end diff --git a/base/osutils.jl b/base/osutils.jl index 41db3353b0858..73d7bb659aee6 100644 --- a/base/osutils.jl +++ b/base/osutils.jl @@ -1,11 +1,18 @@ -include("os_detect.jl") +function is_unix(os::Symbol) + if (os==:Windows) return false; + elseif (os==:Linux) return true; + elseif (os==:FreeBSD) return true; + elseif (os==:Darwin) return true; + else error("Unknown Operating System") + end +end macro windows_only(ex) OS_NAME == :Windows ? esc(ex) : :nothing end macro unix_only(ex) - _jl_is_unix(OS_NAME) ? esc(ex) : :nothing + is_unix(OS_NAME) ? esc(ex) : :nothing end macro osx_only(ex) @@ -13,7 +20,7 @@ macro osx_only(ex) end macro linux_only(ex) - _jl_is_unix(OS_NAME) && OS_NAME != :Darwin ? esc(ex) : :nothing + is_unix(OS_NAME) && OS_NAME != :Darwin ? esc(ex) : :nothing end -_jl_os_name(os::Symbol) = string(os) +os_name(os::Symbol) = string(os) diff --git a/base/path.jl b/base/path.jl new file mode 100644 index 0000000000000..aa2580b7d5f4b --- /dev/null +++ b/base/path.jl @@ -0,0 +1,124 @@ +@unix_only begin + const path_separator = "/" + const path_separator_re = r"/+" + const path_absolute_re = r"^/" + const path_directory_re = r"(?:^|/)\.{0,2}$" + const path_dir_splitter = r"^(.*?)(/+)([^/]*)$" + const path_ext_splitter = r"^((?:.*/)?(?:\.|[^/\.])[^/]*?)(\.[^/\.]*|)$" + + splitdrive(path::String) = ("",path) +end +@windows_only begin + const path_separator = "\\" + const path_separator_re = r"[/\\]+" + const path_absolute_re = r"^(?:\w+:)[/\\]" + const path_directory_re = r"(?:^|[/\\])\.{0,2}$" + const path_dir_splitter = r"^(.*?)([/\\]+)([^/\\]*)$" + const path_ext_splitter = r"^((?:.*[/\\])?(?:\.|[^/\\\.])[^/\\]*?)(\.[^/\\\.]*|)$" + + function splitdrive(path::String) + m = match(r"^(\w+:|\\\\\w+\\\w+|\\\\\?\\UNC\\\w+\\\w+|\\\\\?\\\w+:|)(.*)$", path) + m.captures[1], m.captures[2] + end +end + +isabspath(path::String) = ismatch(path_absolute_re, path) +isdirpath(path::String) = ismatch(path_directory_re, splitdrive(path)[2]) + +function splitdir(path::ByteString) + a, b = splitdrive(path) + m = match(path_dir_splitter,b) + m == nothing && return (a,b) + a = string(a, isempty(m.captures[1]) ? m.captures[2][1] : m.captures[1]) + a, m.captures[3] +end +splitdir(path::String) = splitdir(bytestring(path)) + + dirname(path::String) = splitdir(path)[1] +basename(path::String) = splitdir(path)[2] + +function splitext(path::String) + a, b = splitdrive(path) + m = match(path_ext_splitter, b) + m == nothing && return (path,"") + a*m.captures[1], m.captures[2] +end + +function pathsep(paths::String...) + for path in paths + m = match(path_separator_re, path) + m != nothing && return m.match[1] + end + return path_separator +end + +joinpath(a::String) = a +joinpath(a::String, b::String, c::String...) = joinpath(joinpath(a,b), c...) + +function joinpath(a::String, b::String) + isabspath(b) && return b + A, a = splitdrive(a) + B, b = splitdrive(b) + !isempty(B) && A != B && error("drive mismatch: $A$a $B$b") + C = isempty(B) ? A : B + isempty(a) ? string(C,b) : + ismatch(path_separator_re, a[end:end]) ? string(C,a,b) : + string(C,a,pathsep(a,b),b) +end + +function normpath(path::String) + isabs = isabspath(path) + isdir = isdirpath(path) + drive, path = splitdrive(path) + parts = split(path, path_separator_re) + filter!(x->!isempty(x) && x!=".", parts) + while true + clean = true + for j = 1:length(parts)-1 + if parts[j] != ".." && parts[j+1] == ".." + delete!(parts, j:j+1) + clean = false + break + end + end + clean && break + end + if isabs + while !isempty(parts) && parts[1] == ".." + shift!(parts) + end + elseif isempty(parts) + push!(parts, ".") + end + path = join(parts, path_separator) + if isabs + path = path_separator*path + end + if isdir && !isdirpath(path) + path *= path_separator + end + string(drive,path) +end +normpath(a::String, b::String...) = normpath(joinpath(a,b...)) + +abspath(a::String) = normpath(isabspath(a) ? a : joinpath(pwd(),a)) +abspath(a::String, b::String...) = abspath(joinpath(a,b...)) + +function realpath(path::String) + p = ccall(:realpath, Ptr{Uint8}, (Ptr{Uint8}, Ptr{Uint8}), path, C_NULL) + system_error(:realpath, p == C_NULL) + s = bytestring(p) + c_free(p) + return s +end + +@windows_only expanduser(path::String) = path # on windows, ~ means "temporary file" +@unix_only function expanduser(path::String) + i = start(path) + c, i = next(path,i) + if c != '~' return path end + if done(path,i) return ENV["HOME"] end + c, j = next(path,i) + if c == '/' return ENV["HOME"]*path[i:end] end + error("~user tilde expansion not yet implemented") +end diff --git a/base/pcre.jl b/base/pcre.jl index 7273d3d5818b9..c72a4cb88ebc5 100644 --- a/base/pcre.jl +++ b/base/pcre.jl @@ -15,6 +15,7 @@ const COMPILE_MASK = DOTALL | EXTENDED | FIRSTLINE | + JAVASCRIPT_COMPAT | MULTILINE | NEWLINE_ANY | NEWLINE_ANYCRLF | @@ -69,9 +70,9 @@ function compile(pattern::String, options::Integer) (Ptr{Uint8}, Int32, Ptr{Ptr{Uint8}}, Ptr{Int32}, Ptr{Uint8}), pattern, options, errstr, erroff, C_NULL))() if re_ptr == C_NULL - error("compile: $(errstr[1])", + error("compile: $(bytestring(errstr[1]))", " at position $(erroff[1]+1)", - " in $(quote_string(pattern))") + " in $(repr(pattern))") end size = info(re_ptr, C_NULL, INFO_SIZE, Int32) regex = Array(Uint8,size) @@ -82,19 +83,22 @@ end function study(regex::Array{Uint8}, options::Integer) # NOTE: options should always be zero in current PCRE errstr = Array(Ptr{Uint8},1) - extra = (()->ccall((:pcre_study, :libpcre), Ptr{Void}, - (Ptr{Void}, Int32, Ptr{Ptr{Uint8}}), - regex, options, errstr))() + extra = ccall((:pcre_study, :libpcre), Ptr{Void}, + (Ptr{Void}, Int32, Ptr{Ptr{Uint8}}), + regex, options, errstr) if errstr[1] != C_NULL - error("study: $(errstr[1])") + error("study: $(bytestring(errstr[1]))") end extra end study(re::Array{Uint8}) = study(re, int32(0)) +free_study(extra::Ptr{Void}) = + ccall((:pcre_free_study, :libpcre), Void, (Ptr{Void},), extra) + function exec(regex::Array{Uint8}, extra::Ptr{Void}, str::ByteString, offset::Integer, options::Integer, cap::Bool) - if offset < 0 || length(str) < offset + if offset < 0 || length(str.data) < offset error(BoundsError) end ncap = info(regex, extra, INFO_CAPTURECOUNT, Int32) @@ -102,7 +106,7 @@ function exec(regex::Array{Uint8}, extra::Ptr{Void}, n = ccall((:pcre_exec, :libpcre), Int32, (Ptr{Void}, Ptr{Void}, Ptr{Uint8}, Int32, Int32, Int32, Ptr{Int32}, Int32), - regex, extra, str, length(str), + regex, extra, str, length(str.data), offset, options, ovec, length(ovec)) if n < -1 error("exec: error $n") diff --git a/base/pkg.jl b/base/pkg.jl index f5817bc789fad..57c1f265e91bf 100644 --- a/base/pkg.jl +++ b/base/pkg.jl @@ -1,45 +1,109 @@ -require("git") -require("pkgmetadata") - module Pkg # # Julia's git-based declarative package manager # +include("pkg/metadata.jl") +include("pkg/resolve.jl") + using Metadata +using Resolve import Git -# default locations: local package repo, remote metadata repo - const DEFAULT_META = "git://github.com/JuliaLang/METADATA.jl.git" # some utility functions +@unix_only const DIR_NAME = ".julia" +@windows_only const DIR_NAME = "packages" + +function dir() + b = abspath(get(ENV,"JULIA_PKGDIR",joinpath(ENV["HOME"],DIR_NAME))) + x, y = VERSION.major, VERSION.minor + d = joinpath(b,"v$x.$y") + isdir(d) && return d + d = joinpath(b,"v$x") + isdir(d) && return d + return b +end +dir(pkg::String...) = joinpath(dir(),pkg...) + function cd_pkgdir(f::Function) - dir = julia_pkgdir() - if !isdir(dir) - error("Package directory $dir doesn't exist; run Pkg.init() to create it.") + d = dir() + if !isdir(d) + if has(ENV,"JULIA_PKGDIR") + error("Package directory $d doesn't exist; run Pkg.init() to create it.") + else + info("Auto-initializing default package repository $d.") + init() + end + end + cd(f,d) +end + +function packages(reqs::Vector{VersionSet}) + pkgs = sort!(map(r->r.package, reqs)) + for pkg in pkgs + isdir(pkg) || continue + head = cd(Git.head,pkg) + ver = Metadata.version(pkg,head) + meta = isa(ver,VersionNumber) && cd(pkg) do + !Git.attached() && success(`git diff --quiet HEAD -- REQUIRE`) + end + reqfile = meta ? "METADATA/$pkg/versions/$ver/requires" : "$pkg/REQUIRE" + # TODO: I thought we had a union! function to do this... + # this is just union!(pkgs, map(r->r.package, parse_requires(reqfile))) + isfile(reqfile) || continue + for r in sort!(parse_requires(reqfile)) + if !contains(pkgs,r.package) && isdir(r.package) + push!(pkgs,r.package) + end + end + end + return pkgs +end +packages() = packages(parse_requires("REQUIRE")) + +function print_pkg_status(io::IO, pkg::String) + if !isdir(pkg) + error("Package repository $pkg doesn't exist") + end + cd(pkg) do + head = Git.head() + ver = Git.attached() ? Git.branch() : cd("..") do + Metadata.version(pkg,head) + end + dirty = Git.dirty() ? " (dirty)" : "" + println(io,"$(rpad(pkg,16)) $ver$dirty") + end +end + +# show the status packages in the repo +status() = status(OUTPUT_STREAM) +status(io::IO) = cd_pkgdir() do + for pkg in packages() + print_pkg_status(io, pkg) end - cd(f,dir) end +status(io::IO, pkg::String) = print_pkg_status(io, pkg) +status(pkg::String) = status(OUTPUT_STREAM, pkg) # create a new empty packge repository function init(meta::String) - dir = julia_pkgdir() - if isdir(dir) - error("Package directory $dir already exists.") - end + d = dir() + isdir(d) && error("Package directory $d already exists.") try - run(`mkdir -p $dir`) - cd(dir) do + run(`mkdir -p $d`) + cd(d) do # create & configure + promptuserinfo() run(`git init`) run(`git commit --allow-empty -m "Initial empty commit"`) run(`git remote add origin .`) - if success(`git config --global github.user` > "/dev/null") - base = basename(dir) + if success(`git config --global github.user` > SpawnNullStream()) + base = basename(d) user = readchomp(`git config --global github.user`) run(`git config remote.origin.url git@github.com:$user/$base`) else @@ -50,13 +114,14 @@ function init(meta::String) # initial content run(`touch REQUIRE`) run(`git add REQUIRE`) - run(`git submodule add $meta METADATA`) + run(`git submodule add -b devel $meta METADATA`) run(`git commit -m "Empty package repo"`) cd(Git.autoconfig_pushurl,"METADATA") Metadata.gen_hashes() end - catch - run(`rm -rf $dir`) + catch e + run(`rm -rf $d`) + rethrow(e) end end init() = init(DEFAULT_META) @@ -76,56 +141,69 @@ end # add and remove packages by name add(pkgs::Vector{VersionSet}) = cd_pkgdir() do - for pkg in pkgs - if !contains(Metadata.packages(),pkg.package) - error("Unknown package $(pkg.package); Perhaps you need to Pkg.update() for new metadata?") - end - reqs = parse_requires("REQUIRE") - if anyp(req->req.package==pkg.package,reqs) - error("package already required: $pkg") - end - open("REQUIRE","a") do io - print(io,pkg.package) - for ver in pkg.versions - print(io,"\t$ver") + run(`git add REQUIRE`) + try + for pkg in pkgs + if !contains(Metadata.packages(),pkg.package) + error("Unknown package $(pkg.package); Perhaps you need to Pkg.update() for new metadata?") + end + reqs = parse_requires("REQUIRE") + if any(req->req.package==pkg.package,reqs) + warn("You've already required $pkg, ignoring.") + return + end + open("REQUIRE","a") do io + print(io,pkg.package) + for ver in pkg.versions + print(io,"\t$ver") + end + println(io) end - println(io) end + _resolve() + catch + run(`git checkout -- REQUIRE`) + rethrow() end run(`git add REQUIRE`) - _resolve() end function add(pkgs::Union(String,VersionSet)...) pkgs_ = VersionSet[] for pkg in pkgs - Base.push(pkgs_, isa(pkg,VersionSet) ? pkg : VersionSet(pkg)) + Base.push!(pkgs_, isa(pkg,VersionSet) ? pkg : VersionSet(pkg)) end add(pkgs_) end rm(pkgs::Vector{String}) = cd_pkgdir() do - for pkg in pkgs - if !contains(Metadata.packages(),pkg) - error("invalid package: $pkg") - end - reqs = parse_requires("REQUIRE") - if !anyp(req->req.package==pkg,reqs) - error("package not required: $pkg") - end - open("REQUIRE") do r - open("REQUIRE.new","w") do w - for line in each_line(r) - fields = split(line) - if isempty(fields) || fields[1]!=pkg - print(w,line) + run(`git add REQUIRE`) + try + for pkg in pkgs + if !contains(Metadata.packages(),pkg) + error("Invalid package: $pkg") + end + reqs = parse_requires("REQUIRE") + if !any(req->req.package==pkg,reqs) + error("Package not required: $pkg") + end + open("REQUIRE") do r + open("REQUIRE.new","w") do w + for line in eachline(r) + fields = split(line) + if isempty(fields) || fields[1]!=pkg + print(w,line) + end end end end + run(`mv REQUIRE.new REQUIRE`) end - run(`mv REQUIRE.new REQUIRE`) + _resolve() + catch + run(`git checkout -- REQUIRE`) + rethrow() end run(`git add REQUIRE`) - _resolve() end rm(pkgs::String...) = rm(String[pkgs...]) @@ -138,36 +216,100 @@ end required() = cd_pkgdir() do parse_requires("REQUIRE") end +required(pkg::String) = cd_pkgdir() do + req = required() + for vset in req + if isequal(vset.package, pkg) + return vset.versions + end + end + return nothing +end installed() = cd_pkgdir() do h = Dict{String,Union(VersionNumber,String)}() - Git.each_submodule(false) do name, path, sha1 - if name != "METADATA" - h[name] = Metadata.version(name,sha1) - end + for pkg in packages() + isdir(pkg) || continue + sha1 = cd(Git.head,pkg) + h[pkg] = Metadata.version(pkg,sha1) end return h end +installed(pkg::String) = cd_pkgdir() do + get(installed(), pkg, nothing) +end + +function runbuildscript(pkg) + d = dir(pkg) + path = joinpath(d, "deps") + if isdir(path) + cd(path) do + if isfile("build.jl") + info("Running build script for package $pkg") + evalfile("build.jl") + end + end + end +end # update packages from requirements function _resolve() have = (String=>ASCIIString)[] reqs = parse_requires("REQUIRE") - Git.each_submodule(false) do pkg, path, sha1 - if pkg != "METADATA" - have[pkg] = sha1 - if cd(Git.attached,path) && isfile("$path/REQUIRE") - append!(reqs,parse_requires("$path/REQUIRE")) - if isfile("$path/VERSION") - ver = convert(VersionNumber,readchomp("$path/VERSION")) - Base.push(reqs,VersionSet(pkg,[ver])) - end + fixed = (String=>VersionNumber)["julia"=>VERSION] + index = readchomp(`git write-tree`) + for pkg in packages(parse_requires(`git cat-file blob $index:REQUIRE`)) + isdir(pkg) || continue + have[pkg] = cd(Git.head,pkg) + if cd(Git.attached,pkg) && isfile("$pkg/REQUIRE") + if isfile("$pkg/VERSION") + fixed[pkg] = convert(VersionNumber,readchomp("$pkg/VERSION")) end + append!(reqs,parse_requires("$pkg/REQUIRE")) end end sort!(reqs) - want = Metadata.resolve(reqs) + + pkgs = Metadata.packages() + vers = Metadata.versions(pkgs) + deps = Metadata.dependencies(union(pkgs,keys(fixed))) + filter!(reqs) do r + if has(fixed, r.package) + if !contains(r, Version(r.package,fixed[r.package])) + warn("$(r.package) is fixed at $(repr(fixed[r.package])) which doesn't satisfy $(r.versions).") + end + false + else + true + end + end + filter!(pkgs) do p + !has(fixed, p) + end + filter!(vers) do v + !has(fixed, v.package) + end + unsatisfiable = Set{Version}() + filter!(deps) do d + p = d[2].package + if has(fixed, p) + if !contains(d[2], Version(p, fixed[p])) + add!(unsatisfiable, d[1]) + end + false # drop + else + true # keep + end + end + filter!(vers) do v + !contains(unsatisfiable, v) + end + filter!(deps) do d + !contains(unsatisfiable, d[1]) + end + want = Resolve.resolve(reqs,vers,deps) + pkgs = sort!(keys(merge(want,have))) for pkg in pkgs if has(have,pkg) @@ -179,16 +321,17 @@ function _resolve() if have[pkg] != want[pkg] oldver = Metadata.version(pkg,have[pkg]) newver = Metadata.version(pkg,want[pkg]) - up = oldver <= newver ? "Up" : "Down" - println("$(up)grading $pkg: v$oldver => v$newver") + up = !is(oldver,VersionNumber) || !is(newver,VersionNumber) || oldver <= newver ? "Up" : "Down" + info("$(up)grading $pkg: v$oldver => v$newver") cd(pkg) do run(`git checkout -q $(want[pkg])`) end run(`git add -- $pkg`) + runbuildscript(pkg) end else ver = Metadata.version(pkg,have[pkg]) - println("Removing $pkg v$ver") + info("Removing $pkg v$ver") run(`git rm -qrf --cached -- $pkg`) Git.modules(`--remove-section submodule.$pkg`) run(`git add .gitmodules`) @@ -196,7 +339,7 @@ function _resolve() end else ver = Metadata.version(pkg,want[pkg]) - println("Installing $pkg: v$ver") + info("Installing $pkg v$ver") if ispath(pkg) # TODO: maybe if this is a git repo or submodule, just take it over? error("Path $pkg already exists! Please remove to allow installation.") @@ -204,7 +347,7 @@ function _resolve() url = Metadata.pkg_url(pkg) run(`git submodule add --reference . $url $pkg`) cd(pkg) do - try run(`git checkout -q $(want[pkg])` .> "/dev/null") + try run(`git checkout -q $(want[pkg])` .> SpawnNullStream()) catch run(`git fetch -q`) try run(`git checkout -q $(want[pkg])`) @@ -215,30 +358,32 @@ function _resolve() Git.autoconfig_pushurl() end run(`git add -- $pkg`) + runbuildscript(pkg) end end end -resolve() = cd(_resolve,julia_pkgdir()) +resolve() = cd(_resolve,dir()) # clone a new package repo from a URL # TODO: this is horribly broken function clone(url::String) - dir = julia_pkgdir() - if isdir(dir) - error("Package directory $dir already exists.") + d = dir() + if isdir(d) + error("Package directory $d already exists.") end tmpdir = mktempdir() run(`git clone $url $tmpdir`) cd(tmpdir) do - gitdir = abs_path(readchomp(`git rev-parse --git-dir`)) - Git.each_submodule(false) do name, path, sha1 - cd(path) do + gitdir = abspath(readchomp(`git rev-parse --git-dir`)) + for pkg in packages() + cd(pkg) do + sha1 = Git.head() run(`git fetch-pack $gitdir $sha1`) end end end - run(`mv $tmpdir $dir`) + run(`mv $tmpdir $d`) end # record all submodule commits as tags @@ -276,9 +421,13 @@ function commit(f::Function, msg::String) assert_git_clean() try f() catch - print(stderr_stream, - "\n\n*** ERROR ENCOUNTERED ***\n\n", - "Rolling back to HEAD...\n") + warn(""" + + *** ERROR ENCOUNTERED *** + + Rolling back to HEAD... + + """) checkout() rethrow() end @@ -287,7 +436,7 @@ function commit(f::Function, msg::String) run(`git diff --name-only --diff-filter=D HEAD^ HEAD` | `xargs rm -rf`) checkout() elseif !Git.dirty() - println(stderr_stream, "Nothing to commit.") + warn("nothing to commit.") else error("There are both staged and unstaged changes to packages.") end @@ -295,20 +444,27 @@ end # set package remote in METADATA -pkg_origin(pkg::String, remote::String) = cd_pkgdir() do - for line in each_line(`git --git-dir=$(file_path(pkg,".git")) remote -v`) +get_origin(pkg::String, remote::String) = cd_pkgdir() do + for line in eachline(`git --git-dir=$(joinpath(pkg,".git")) remote -v`) m = match(r"^(\S*)\s*(\S*)\s*\(fetch\)", line) if m != nothing && m.captures[1] == remote - cd(file_path("METADATA", pkg)) do - open("url", "w") do io - println(io, m.captures[2]) - end - end - return + return m.captures[2] end end + error("The git remote '", remote, "' is not present in the configuration file") end -pkg_origin(pkg) = pkg_origin(pkg, "origin") +get_origin(pkg::String) = get_origin(pkg, "origin") + +set_origin(pkg::String, url::String) = cd_pkgdir() do + cd(joinpath("METADATA", pkg)) do + open("url", "w") do io + println(io, url) + end + end +end + +pkg_origin(pkg::String, remote::String) = set_origin(pkg, get_origin(pkg, remote)) +pkg_origin(pkg::String) = pkg_origin(pkg, "origin") # push & pull package repos to/from remotes @@ -327,7 +483,7 @@ pull() = cd_pkgdir() do run(`git fetch`) # see how far git gets with merging - if success(`git merge -m "[jul] pull (simple merge)" FETCH_HEAD`) return end + success(`git merge -m "[jul] pull (simple merge)" FETCH_HEAD`) && return # get info about local, remote and base trees L = readchomp(`git rev-parse --verify HEAD`) @@ -343,18 +499,20 @@ pull() = cd_pkgdir() do Cc, conflicts, deleted = Git.merge_configs(Bc,Lc,Rc) # warn about config conflicts for (key,vals) in conflicts - print(stderr_stream, - "\nModules config conflict for $key:\n", - " local value = $(vals[1])\n", - " remote value = $(vals[2])\n", - "\n", - "Both values written to .gitmodules -- please edit and choose one.\n\n", - ) Cc[key] = vals + warn(""" + + Modules config conflict for $key: + local value = $(vals[1]) + remote value = $(vals[2]) + + Both values written to .gitmodules -- please edit and choose one. + + """) end # remove submodules that were deleted for section in deleted - if !begins_with(section,"submodule.") continue end + if !beginswith(section,"submodule.") continue end path = get(Lc,"$section.path",nothing) if path == nothing continue end run(`git rm -qrf --cached --ignore-unmatch -- $path`) @@ -380,12 +538,17 @@ pull() = cd_pkgdir() do if Git.unstaged() unmerged = readall(`git ls-files -m` | `sort` | `uniq`) unmerged = replace(unmerged, r"^", " ") - print(stderr_stream, - "\n\n*** WARNING ***\n\n", - "You have unresolved merge conflicts in the following files:\n\n", - unmerged, - "\nPlease resolve these conflicts, `git add` the files, and commit.\n" - ) + warn(""" + + *** WARNING *** + + You have unresolved merge conflicts in the following files: + + $unmerged + + Please resolve these conflicts, `git add` the files, and commit. + + """) error("pull: merge conflicts") end @@ -399,16 +562,20 @@ end update() = cd_pkgdir() do cd("METADATA") do + run(`git fetch -q --all`) + run(`git checkout -q HEAD^0`) + run(`git branch -f devel origin/devel`) + run(`git checkout -q devel`) run(`git pull`) end Metadata.gen_hashes() run(`git add METADATA`) # TODO: handle package deletions - Git.each_submodule(false) do pkg, path, sha1 + for pkg in packages() url = Metadata.pkg_url(pkg) if url != nothing Git.modules(`submodule.$pkg.url $url`) - cd(path) do + cd(pkg) do if !Git.dirty() if Git.attached() run(ignorestatus(`git pull --ff-only`)) @@ -428,7 +595,7 @@ end latest_version(pkg::String) = cd_pkgdir() do vers = VersionNumber[] for (ver, _) in Metadata.each_tagged_version(pkg) - Base.push(vers, ver) + Base.push!(vers, ver) end max(vers) end @@ -439,8 +606,8 @@ version(pkg::String, ver::VersionNumber) = cd_pkgdir() do error("The latest version of package $(pkg) is $(string(ver)). You must specify a later version.") end else - if !isdir(file_path("METADATA", pkg)) - mkdir(file_path("METADATA", pkg)) + if !isdir(joinpath("METADATA", pkg)) + mkdir(joinpath("METADATA", pkg)) end end sha1 = "" @@ -450,19 +617,21 @@ version(pkg::String, ver::VersionNumber) = cd_pkgdir() do run(`git tag $(string(ver)) HEAD`) end end - cd(file_path("METADATA", pkg)) do + cd(joinpath("METADATA", pkg)) do if !isdir("hashes") mkdir("hashes") end if !isdir("versions") mkdir("versions") end cd("versions") do if !isdir(string(ver)) mkdir(string(ver)) end - open(file_path(string(ver), "sha1"), "w") do io + open(joinpath(string(ver), "sha1"), "w") do io println(io, sha1) end end end - file_copy( - file_path(pkg, "REQUIRE"), - file_path("METADATA", pkg, "versions", string(ver), "requires")) + if isfile(joinpath(pkg, "REQUIRE")) + cp( + joinpath(pkg, "REQUIRE"), + joinpath("METADATA", pkg, "versions", string(ver), "requires")) + end Metadata.gen_hashes(pkg) end @@ -483,63 +652,122 @@ function major(pkg) version(pkg, VersionNumber(lver.major+1)) end -# Create a skeleton package that can be easily filled in -function new(package_name::String) - cd_pkgdir() do - try - mkdir(package_name) - catch - error("Unable to create directory for new package: $(package_name)") +function promptuserinfo() + if(isempty(chomp(readall(ignorestatus(`git config --global user.name`))))) + info(""" + Git would like to know your name to initialize your .julia directory. + Enter it below: + """) + name = chomp(readline(STDIN)) + if(isempty(name)) + error("Could not read name") + else + run(`git config --global user.name $name`) + info("Thank you. You can change it using run(`git config --global user.name NAME`)") end - try - sha1 = "" - cd(package_name) do - run(`git init`) - run(`git commit --allow-empty -m "Initial empty commit"`) - file_create("LICENSE.md") # Should insert MIT content - file_create("README.md") - file_create("REQUIRE") - mkdir("src") - file_create(file_path("src", strcat(package_name, ".jl"))) - mkdir("test") - run(`git add --all`) - run(`git commit -m "Scaffold for Julia package $(package_name)"`) - sha1 = readchomp(`git rev-parse HEAD`) - end - version(package_name, v"0.0.0") - catch - error("Unable to initialize contents of new package") + end + if(isempty(chomp(readall(ignorestatus(`git config --global user.email`))))) + info(""" + Git would like to know your email to initialize your .julia directory. + Enter it below: + """) + email = chomp(readline(STDIN)) + if(isempty(email)) + error("Could not read email") + else + run(`git config --global user.email $email`) + info("Thank you. You can change it using run(`git config --global user.email EMAIL`)") end - newpath = file_path(julia_pkgdir(), package_name) - println( -" -You have created a new package in + end +end + +function new(pkg::String) + newpath = joinpath(dir(), pkg) + cd_pkgdir() do + if isdir(pkg) + # This is an existing package that we assume is ready to go + version(pkg, v"0.0.0") + try + pkg_origin(pkg, "origin") + catch + error(""" + Your package in - $(file_path(julia_pkgdir(), package_name)) + $newpath -When the package is ready to submit, push it to a public repository, set it as -the remote \"origin\", then run: + is almost ready. But the default remote, "origin", does not exist in + this repository's configuration. To finish the process, run - > Pkg.set_origin($(package_name)) - > Pkg.patch($(package_name)) + > Pkg.pkg_origin("$pkg", remotename) -to prepare METADATA with the details for your package." - ) + with the correct remote name for your repository. + """) + end + else + # Create a skeleton package that can be easily filled in + try + mkdir(pkg) + catch + error("Unable to create directory for new package: $pkg") + end + try + sha1 = "" + cd(pkg) do + promptuserinfo() + run(`git init`) + run(`git commit --allow-empty -m "Initial empty commit"`) + touch("LICENSE.md") # Should insert MIT content + touch("README.md") + touch("REQUIRE") + mkdir("src") + touch(joinpath("src", string(pkg, ".jl"))) + mkdir("test") + run(`git add --all`) + run(`git commit -m "Scaffold for Julia package $pkg"`) + sha1 = readchomp(`git rev-parse HEAD`) + end + version(pkg, v"0.0.0") + catch + error("Unable to initialize contents of new package") + end + println(""" + You have created a new package in + + $newpath + + When the package is ready to submit, push it to a public repository, set it as + the remote "origin", then run: + + > Pkg.pkg_origin("$pkg") + > Pkg.patch("$pkg") + + to prepare METADATA with the details for your package. + """) + end end end # Remove local traces of a package (broken due to a bad .new(), for instance) -obliterate(package_name::String) = cd_pkgdir() do - run(`rm -rf $(package_name) $(file_path("METADATA", package_name))`) +obliterate(pkg::String) = cd_pkgdir() do + run(`rm -rf $pkg $(joinpath("METADATA", pkg))`) end -# If a package contains data, make it easy to find its location -function package_directory(package_name::String) - if has(ENV, "JULIA_PKGDIR") - return file_path(ENV["JULIA_PKGDIR"], package_name) - else - return path_expand(file_path("~/.julia", package_name)) - end +# Repository sanity check +check_repository() = cd_pkgdir() do + try + Resolve.sanity_check() + catch err + if !isa(err, Resolve.MetadataError) + rethrow(err) + end + warning = "Packages with unsatisfiable requirements found:" + for (v, pp) in err.info + warning *= " $(v.package) v$(v.version) : no valid versions exist for package $pp" + end + warn(warning) + return false + end + return true end end # module diff --git a/base/pkgmetadata.jl b/base/pkg/metadata.jl similarity index 57% rename from base/pkgmetadata.jl rename to base/pkg/metadata.jl index 378fc80ca81f3..d7f954b684c45 100644 --- a/base/pkgmetadata.jl +++ b/base/pkg/metadata.jl @@ -1,14 +1,9 @@ -require("linprog") - module Metadata -using LinProgGLPK - import Git -import GLPK -import Base.isequal, Base.isless, Base.contains +import Base.isequal, Base.isless, Base.contains, Base.hash -export parse_requires, Version, VersionSet +export parse_requires, Version, VersionSet, packages, versions, dependencies function gen_versions(pkg::String) for (ver,sha1) in Git.each_tagged_version(pkg) @@ -47,19 +42,19 @@ function version(pkg::String, sha1::String) end each_package() = @task begin - for line in each_line(`ls -1 METADATA`) + for line in eachline(`ls -1 METADATA`) line = chomp(line) # stat() chokes if we try to check if the subdirectory of a non-directory exists - if isdir(file_path("METADATA", line)) && isdir(file_path("METADATA", line, "versions")) + if isdir(joinpath("METADATA", line)) && isdir(joinpath("METADATA", line, "versions")) produce(line) end end end each_tagged_version(pkg::String) = @task begin - for line in each_line(`ls -1 $(file_path("METADATA", pkg, "versions"))`) + for line in eachline(`ls -1 $(joinpath("METADATA", pkg, "versions"))`) line = chomp(line) - if isdir(file_path("METADATA", pkg, "versions", line)) && ismatch(Base.VERSION_REGEX, line) + if isdir(joinpath("METADATA", pkg, "versions", line)) && ismatch(Base.VERSION_REGEX, line) ver = convert(VersionNumber,line) dir = "METADATA/$pkg/versions/$(line)" if isfile("$dir/sha1") @@ -72,7 +67,7 @@ end function packages() pkgs = String[] for pkg in each_package() - push(pkgs,pkg) + push!(pkgs,pkg) end sort!(pkgs) end @@ -94,13 +89,15 @@ function versions(pkgs) vers = Version[] for pkg in pkgs for (ver,dir) in each_tagged_version(pkg) - push(vers,Version(pkg,ver)) + push!(vers,Version(pkg,ver)) end end sort!(vers) end versions() = versions(packages()) +hash(v::Version) = hash([v.(n) for n in Version.names]) + type VersionSet package::ByteString versions::Vector{VersionNumber} @@ -113,6 +110,9 @@ type VersionSet end end VersionSet(pkg::ByteString) = VersionSet(pkg, VersionNumber[]) + +isequal(a::VersionSet, b::VersionSet) = + a.package == b.package && a.versions == b.versions isless(a::VersionSet, b::VersionSet) = a.package < b.package function contains(s::VersionSet, v::Version) @@ -123,26 +123,27 @@ function contains(s::VersionSet, v::Version) return isempty(s.versions) end -function parse_requires(file::String) +hash(s::VersionSet) = hash([s.(n) for n in VersionSet.names]) + +function parse_requires(readable) reqs = VersionSet[] - open(file) do io - for line in each_line(io) - if ismatch(r"^\s*(?:#|$)", line) continue end - line = replace(line, r"#.*$", "") - fields = split(line) - pkg = shift(fields) - vers = [ convert(VersionNumber,x) for x=fields ] - if !issorted(vers) - error("invalid requires entry for $pkg in $file: $vers") - end - # TODO: merge version sets instead of appending? - push(reqs,VersionSet(pkg,vers)) + for line in eachline(readable) + if ismatch(r"^\s*(?:#|$)", line) continue end + line = replace(line, r"#.*$", "") + fields = split(line) + pkg = shift!(fields) + vers = [ convert(VersionNumber,x) for x=fields ] + if !issorted(vers) + error("invalid requires entry for $pkg: $vers") end + # TODO: merge version sets instead of appending? + push!(reqs,VersionSet(pkg,vers)) end sort!(reqs) end +parse_requires(file::String) = open(parse_requires,file) -function dependencies(pkgs,vers) +function dependencies(pkgs) deps = Array((Version,VersionSet),0) for pkg in each_package() for (ver,dir) in each_tagged_version(pkg) @@ -151,9 +152,9 @@ function dependencies(pkgs,vers) if isfile(file) for d in parse_requires("$dir/requires") if !contains(pkgs,d.package) - error("Unknown dependency for $pkg: $(d.package)") + error("unknown dependency for $pkg: $(d.package)") end - push(deps,(v,d)) + push!(deps,(v,d)) end end end @@ -163,42 +164,4 @@ end older(a::Version, b::Version) = a.package == b.package && a.version < b.version -function resolve(reqs::Vector{VersionSet}) - pkgs = packages() - vers = versions(pkgs) - deps = dependencies(pkgs,vers) - - n = length(vers) - z = zeros(Int,n) - u = ones(Int,n) - - G = [ v == d[1] ? 1 : 0 for v=vers, d=deps ] - G *= [ contains(d[2],v) ? 1 : 0 for d=deps, v=vers ] - G += [ older(a,b) ? 2 : 0 for a=vers, b=vers ] - I = find(G) - W = zeros(Int,length(I),n) - for (r,i) in enumerate(I) - W[r,rem(i-1,n)+1] = -1 - W[r,div(i-1,n)+1] = G[i] - end - mipopts = GLPK.IntoptParam() - mipopts["msg_lev"] = GLPK.MSG_ERR - mipopts["presolve"] = GLPK.ON - w = iround(mixintprog(u,W,-ones(Int,length(I)),nothing,nothing,u,nothing,nothing,mipopts)[2]) - - V = [ p == v.package ? 1 : 0 for p=pkgs, v=vers ] - R = [ contains(r,v) ? -1 : 0 for r=reqs, v=vers ] - D = [ d[1] == v ? 1 : contains(d[2],v) ? -1 : 0 for d=deps, v=vers ] - b = [ ones(Int,length(pkgs)) - -ones(Int,length(reqs)) - zeros(Int,length(deps)) ] - - x = mixintprog(w,[V;R;D],b,nothing,nothing,z,u,nothing,mipopts)[2] .== 1 - h = (String=>ASCIIString)[] - for v in vers[x] - h[v.package] = readchomp("METADATA/$(v.package)/versions/$(v.version)/sha1") - end - return h -end - end # module diff --git a/base/pkg/resolve.jl b/base/pkg/resolve.jl new file mode 100644 index 0000000000000..7f2c2b565516a --- /dev/null +++ b/base/pkg/resolve.jl @@ -0,0 +1,1402 @@ +module Resolve +# +# Use max-sum algorithm to resolve packages dependencies +# + +using Metadata + +import Base.<, Base.<=, Base.==, Base.-, Base.+, + Base.zero, Base.isless, Base.abs, Base.typemin, Base.typemax, + Base.indmax + +export resolve, sanity_check, MetadataError + +# An exception type used internally to signal that an unsatisfiable +# constraint was detected +type UnsatError <: Exception + info +end + +type MetadataError <: Exception + info +end + +# Some parameters to drive the decimation process +type ResolveParams + nondec_iterations # number of initial iterations before starting + # decimation + dec_interval # number of iterations between decimations + dec_fraction # fraction of nodes to decimate at every decimation + # step + + function ResolveParams() + accuracy = int(get(ENV, "JULIA_PKGRESOLVE_ACCURACY", 1)) + if accuracy <= 0 + error("JULIA_PKGRESOLVE_ACCURACY must be >= 1") + end + nondec_iterations = accuracy * 20 + dec_interval = accuracy * 10 + dec_fraction = 0.05 / accuracy + return new(nondec_iterations, dec_interval, dec_fraction) + end +end + +# Fetch all data and keep it in a single structure +type ReqsStruct + reqs::Vector{VersionSet} + pkgs::Vector{String} + vers::Vector{Version} + deps::Vector{(Version,VersionSet)} + np::Int + + function ReqsStruct( + reqs::Vector{VersionSet}, + pkgs::Vector{String}, + vers::Vector{Version}, + deps::Vector{(Version,VersionSet)}) + new(reqs, pkgs, vers, deps, length(pkgs)) + end +end + +function ReqsStruct(reqs::Vector{VersionSet}, vers::Vector{Version}, deps::Vector{(Version,VersionSet)}) + pkgs = Set{String}() + for r in reqs add!(pkgs, r.package) end + for v in vers add!(pkgs, v.package) end + for d in deps + add!(pkgs, d[1].package) + add!(pkgs, d[2].package) + end + ReqsStruct(reqs, sort!(collect(pkgs)), vers, deps) +end + +# The numeric type used to determine how the different +# versions of a package should be weighed +typealias VersionWeight Int + +# Auxiliary structure to map data from ReqsStruct into +# internal representation and vice versa +type PkgStruct + # states per package: one per version + uninstalled + spp::Vector{Int} + + # pakage dict: associates an index to each package name + pdict::Dict{String,Int} + + # package versions: for each package, keep the list of the + # possible version numbers; this defines a + # mapping from version numbers of a package + # to indices + pvers::Vector{Vector{VersionNumber}} + + # versions dict: associates a package number and a version index + # to each Version: suppose we have v::Version such that + # v.package == p + # v.version == vn + # and that + # vdict[v] = (p0, v0) + # then + # pdict[p] = p0 + # pvers[p0][v0] = vn + vdict::Dict{Version,(Int,Int)} + + # version weights: the weight for each version of each package + # (versions include the uninstalled state; the + # higher the weight, the more favored the version) + vweight::Vector{Vector{VersionWeight}} + + # has version pruning been performed? + # (used for debug purposes only) + waspruned::Bool + + PkgStruct(spp::Vector{Int}, pdict::Dict{String,Int}, + pvers::Vector{Vector{VersionNumber}}, + vdict::Dict{Version,(Int,Int)}, + vweight::Vector{Vector{VersionWeight}}) = + new(spp, pdict, pvers, vdict, vweight, false) +end + +# The initial constructor function (pre variable pruning) +function PkgStruct(reqsstruct::ReqsStruct) + + pkgs = reqsstruct.pkgs + vers = reqsstruct.vers + np = reqsstruct.np + + pdict = [ pkgs[i] => i for i = 1:np ] + + spp, pvers = gen_pvers(np, pdict, vers) + vdict = gen_vdict(pdict, pvers, vers) + + # the version weights are just progressive integer numbers, + # there is no difference between major, minor, patch etc. + # TODO: change this to weigh differently major, minor etc. ? + vweight = [ [ v0-1 for v0 = 1:spp[p0] ] for p0 = 1:np ] + + return PkgStruct(spp, pdict, pvers, vdict, vweight) +end + +# Generate the pvers field in PkgStruct; used by the +# constructor and within `prune_versions!` +function gen_pvers(np::Int, pdict::Dict{String,Int}, vers::Vector{Version}) + spp = ones(Int, np) + + pvers = [ VersionNumber[] for i = 1:np ] + + for v in vers + vp = v.package + vv = v.version + j = pdict[vp] + spp[j] += 1 + push!(pvers[j], vv) + end + for j = 1:np + sort!(pvers[j]) + end + + return spp, pvers +end + +# Generate the vdict field in PkgStruct; used by the +# constructor and within `prune_versions!` +function gen_vdict(pdict::Dict{String,Int}, pvers::Vector{Vector{VersionNumber}}, + vers::Vector{Version}) + + vdict = (Version=>(Int,Int))[] + for v in vers + vp = v.package + vv = v.version + j = pdict[vp] + for i in 1:length(pvers[j]) + if pvers[j][i] == vv + vdict[v] = (j, i) + break + end + end + end + return vdict +end + +# Reduce the number of versions by creating equivalence classes, and retaining +# only the highest version for each equivalence class. +# Two versions are equivalent if: +# 1) They appear together as dependecies of another package (i.e. for each +# dependency relation, they are both required or both not required) +# 2) They have the same dependencies +# Also, for each package explicitly required, dicards all versions outside +# the allowed range (checking for impossible ranges while at it). +# This function mutates both input structs. +prune_versions!(reqsstruct::ReqsStruct, pkgstruct::PkgStruct) = prune_versions!(reqsstruct, pkgstruct, true) +function prune_versions!(reqsstruct::ReqsStruct, pkgstruct::PkgStruct, prune_reqs::Bool) + + np = reqsstruct.np + reqs = reqsstruct.reqs + pkgs = reqsstruct.pkgs + vers = reqsstruct.vers + deps = reqsstruct.deps + spp = pkgstruct.spp + pdict = pkgstruct.pdict + pvers = pkgstruct.pvers + vdict = pkgstruct.vdict + vweight = pkgstruct.vweight + + # To each version in each package, we associate a BitVector. + # It is going to hold a pattern such that all versions with + # the same pattern are equivalent. + vmask = [ [ BitVector() for v0 = 1:spp[p0]-1 ] for p0 = 1:np ] + + # From the point of view of resolve(), VectorSet(pkg,[]) and + # VectorSet(pkg, [v0]) are equivelent if v0 is the first + # available version of pkg + function contains_any(vs::VersionSet, first::VersionNumber) + vvs = vs.versions + return isempty(vvs) || (length(vvs) == 1 && vvs[1] == first) + end + + # Parse requirements and store allowed versions. + allowed = [ trues(spp[p0]-1) for p0 = 1:np ] + if prune_reqs + for r in reqs + p = r.package + p0 = pdict[p] + pvers0 = pvers[p0] + allowed0 = allowed[p0] + for v0 = 1:spp[p0]-1 + v = pvers0[v0] + allowed0[v0] = contains(r, Version(p, v)) + end + end + for p0 = 1:np + allowed0 = allowed[p0] + if !any(allowed0) + error("Invalid requirements: no version allowed for package $(pkgs[p0])") + end + end + end + + # Parse the dependency list, segregate them according to the + # dependant package and version + pdeps = [ [ VersionSet[] for v0 = 1:spp[p0]-1 ] for p0 = 1:np ] + for d in deps + p0, v0 = vdict[d[1]] + if !allowed[p0][v0] + continue + end + p1 = pdict[d[2].package] + if contains_any(d[2], pvers[p1][1]) + dd = VersionSet(d[2].package) + else + dd = d[2] + end + push!(pdeps[p0][v0], dd) + end + + # For each package, we examine the dependencies of its versions + # and put together those which are equal. + # While we're at it, we also collect all dependencies into alldeps + alldeps = VersionSet[] + for p0 = 1:np + pdeps0 = pdeps[p0] + + # Extract unique dependencies lists (aka classes), thereby + # assigning an index to each class. + uniqdepssets = unique(pdeps0) + + # Store all dependencies seen so far for later use + for dd in uniqdepssets, v in dd + push!(alldeps, v) + end + + # If the package has just one version, it's uninteresting + if spp[p0] == 2 + continue + end + + # Grow the pattern by the number of classes + ff = falses(length(uniqdepssets)) + vmask0 = vmask[p0] + vmind_base = length(vmask0[1]) + for vm in vmask0 + append!(vm, ff) + end + + # For each version, determine to which class it belongs and + # store that info in the patterns + for v0 = 1:spp[p0]-1 + if !allowed[p0][v0] + continue + end + vmind = findfirst(uniqdepssets, pdeps0[v0]) + @assert vmind >= 0 + vmind += vmind_base + vm = vmask0[v0] + vm[vmind] = true + end + end + + # Produce dependency patterns. Ideally, one would use unique(alldeps) + # here (or better still, use a Set from the beginning), but it takes + # more time than it saves - better waste a little extra memory. + for r in alldeps + p = r.package + p0 = pdict[p] + + # packages with just one version, or dependencies + # which do not distiguish between versions, are not + # interesting + if spp[p0] == 2 || contains_any(r, pvers[p0][1]) + continue + end + + pvers0 = pvers[p0] + + # Grow the patterns by one bit + vmask0 = vmask[p0] + for vm in vmask0 + resize!(vm, length(vm)+1) + end + + # Store the dependency info in the patterns + for v0 = 1:spp[p0]-1 + v = pvers0[v0] + vm = vmask0[v0] + vm[end] = contains(r, Version(p, v)) + end + end + + # At this point, the vmask patterns are computed. We divide them into + # classes so that we can keep just one version for each class. + pruned_vers_id = [ Int[] for p0 = 1:np ] + eq_classes_map = [ (VersionNumber=>VersionNumber)[] for p0 = 1:np ] + for p0 = 1:np + vmask0 = vmask[p0] + vmask0_uniq = unique(vmask0) + nc = length(vmask0_uniq) + classes = [ Int[] for c0 = 1:nc ] + for v0 = 1:spp[p0]-1 + if !allowed[p0][v0] + continue + end + vm = vmask0[v0] + c0 = findfirst(vmask0_uniq, vm) + push!(classes[c0], v0) + end + + # For each nonempty class, we store only the last entry (i.e. the + # highest version) + pruned0 = pruned_vers_id[p0] + eqclass0 = eq_classes_map[p0] + pvers0 = pvers[p0] + for cl in classes + if !isempty(cl) + vtop0 = cl[end] + push!(pruned0, vtop0) + if !prune_reqs + vtop = pvers0[vtop0] + for v0 in cl + eqclass0[pvers0[v0]] = vtop + end + end + end + end + sort!(pruned0) + end + + # All that follows is just recomputing the structures' fields + # by throwing away unnecessary versions + + # Recompute pvers + new_pvers = [ pvers[p0][pruned_vers_id[p0]] for p0 = 1:np ] + + # Recompute vers + new_vers = Version[] + for p0 = 1:np + p = pkgs[p0] + for v in new_pvers[p0] + push!(new_vers, Version(p, v)) + end + end + + # Reompute deps. We could simplify them, but it's not worth it + new_deps = Array((Version,VersionSet), 0) + + for d0 = 1:length(deps) + d = deps[d0] + p0, v0 = vdict[d[1]] + if !contains(pruned_vers_id[p0], v0) + continue + end + push!(new_deps, d) + end + + reqsstruct.vers = new_vers + reqsstruct.deps = new_deps + + # Finally, mutate pkgstruct fields by regenerating pvers, vdict + # and vweights + + new_spp, new_pvers = gen_pvers(np, pdict, new_vers) + new_vdict = gen_vdict(pdict, new_pvers, new_vers) + + new_vweight = [ Array(VersionWeight,new_spp[p0]) for p0 = 1:np ] + for p0 = 1:np + vweight0 = vweight[p0] + new_vweight0 = new_vweight[p0] + pversid0 = pruned_vers_id[p0] + for v0 = 1:length(pversid0) + new_vweight0[v0] = vweight0[pversid0[v0]] + end + new_vweight0[end] = vweight0[end] + end + + pkgstruct.spp = new_spp + pkgstruct.pvers = new_pvers + pkgstruct.vdict = new_vdict + pkgstruct.vweight = new_vweight + if prune_reqs + pkgstruct.waspruned = true + end + + #println("pruning stats:") + #println(" before: vers=$(length(vers)) deps=$(length(deps))") + #println(" after: vers=$(length(new_vers)) deps=$(length(new_deps))") + + return eq_classes_map +end + +# FieldValue is a numeric type which helps dealing with +# infinities. It holds 5 numbers l0,l1,l2,l3,l4. It can +# be interpreted as a polynomial +# x = a^4 * l0 + a^3 * l1 + a^2 + l2 + a^1 * l3 + l4 +# where a -> Inf +# The levels are used as such: +# l0 : for hard constraints (dependencies and requirements) +# l1 : for favoring higher versions of the explicitly required +# packages +# l2 : for favoring higher versions of all other packages (and +# favoring uninstallation of non-needed packages) +# l3 : for favoring dependants over dependencies +# l4 : for symmetry-breaking random noise +# +type FieldValue + v::Vector{Int} + function FieldValue(v::Vector{Int}) + if length(v) != 5 + error("FieldValue only accepts Vectors of length 5") + end + new(v) + end +end +FieldValue(l0::Int,l1::Int,l2::Int,l3::Int,l4::Int) = FieldValue([l0, l1, l2, l3, l4]) +FieldValue(l0::Int,l1::Int,l2::Int,l3::Int) = FieldValue([l0, l1, l2, l3, 0]) +FieldValue(l0::Int,l1::Int,l2::Int) = FieldValue([l0, l1, l2, 0, 0]) +FieldValue(l0::Int,l1::Int) = FieldValue([l0, l1, 0, 0, 0]) +FieldValue(l0::Int) = FieldValue([l0, 0, 0, 0, 0]) +FieldValue() = FieldValue([0,0,0,0,0]) + +zero(::Type{FieldValue}) = FieldValue() + +typemin(::Type{FieldValue}) = FieldValue([typemin(Int) for i = 1:5]) +typemax(::Type{FieldValue}) = FieldValue([typemax(Int) for i = 1:5]) + +(-)(a::FieldValue, b::FieldValue) = FieldValue(a.v - b.v) +(+)(a::FieldValue, b::FieldValue) = FieldValue(a.v + b.v) + +(==)(a::FieldValue, b::FieldValue) = (a.v == b.v) + +function (<)(a::FieldValue, b::FieldValue) + va = a.v + vb = b.v + va[1] < vb[1] && return true + va[1] > vb[1] && return false + va[2] < vb[2] && return true + va[2] > vb[2] && return false + va[3] < vb[3] && return true + va[3] > vb[3] && return false + va[4] < vb[4] && return true + va[4] > vb[4] && return false + va[5] < vb[5] && return true + return false +end + +isless(a::FieldValue, b::FieldValue) = a < b + +abs(a::FieldValue) = FieldValue(abs(a.v)) +abs(v::Vector{FieldValue}) = FieldValue[abs(a) for a in v] + +# A faster, in-place version of +# a += FieldValue(0,0,0,x,0) +# where the position of the x is set by n +inplaceadd!(a::FieldValue, x::Int, n::Int) = (a.v[n] = x) + +# A faster, in-place version of +# a += b +function inplaceadd!(a::FieldValue, b::FieldValue) + av = a.v + bv = b.v + for i = 1:5 + av[i] += bv[i] + end +end + +# if the maximum field has l0 < 0, it means that +# some hard constraint is being violated +validmax(a::FieldValue) = a.v[1] >= 0 + +# like usual indmax, but favors the highest indices +# in case of a tie +function indmax(v::Vector{FieldValue}) + m = typemin(FieldValue) + mi = 0 + for j = length(v):-1:1 + if v[j] > m + m = v[j] + mi = j + end + end + @assert mi != 0 + return mi +end + +# secondmax returns the (normalized) value of the second maximum in a +# field (i.e. a Vector of FieldValues. It's used to determine the most +# polarized field. +function secondmax(v::Vector{FieldValue}) + m = typemin(FieldValue) + m2 = typemin(FieldValue) + for i = 1:length(v) + a = v[i] + if a > m + m2 = m + m = a + elseif a > m2 + m2 = a + end + end + return m2 - m +end + +# Graph holds the graph structure onto which max-sum is run, in +# sparse format +type Graph + # adjacency matrix: + # for each package, has the list of neighbors + # indices (both dependencies and dependants) + gadj::Vector{Vector{Int}} + + # compatibility mask: + # for each package p0 has a list of bool masks. + # Each entry in the list gmsk[p0] is relative to the + # package p1 as read from gadj[p0]. + # Each mask has dimension spp1 x spp0, where + # spp0 is the number of states of p0, and + # spp1 is the number of states of p1. + gmsk::Vector{Vector{Matrix{Bool}}} + + # dependency direction: + # keeps track of which direction the dependency goes + # takes 3 values: + # 1 = dependant + # -1 = dependency + # 0 = both + # Used to break symmetry between dependants and + # dependencies (introduces a FieldValue at level l3). + # The "both" case is for when there are dependency + # relations which go both ways, in which case the + # noise is left to discriminate in case of ties + gdir::Vector{Vector{Int}} + + # adjacency dict: + # allows to retrieve the indices in gadj, so that + # gadj[p0][adjdict[p1][p0]] = p1 + adjdict::Vector{Dict{Int,Int}} + + # states per package: same as in PkgStruct + spp::Vector{Int} + + # update order: shuffled at each iteration + perm::Vector{Int} + + # number of packages (all Vectors above have this length) + np::Int + + function Graph(reqsstruct::ReqsStruct, + pkgstruct::PkgStruct) + + deps = reqsstruct.deps + np = reqsstruct.np + + spp = pkgstruct.spp + pdict = pkgstruct.pdict + pvers = pkgstruct.pvers + vdict = pkgstruct.vdict + + gadj = [ Int[] for i = 1:np ] + gmsk = [ Matrix{Bool}[] for i = 1:np ] + gdir = [ Int[] for i = 1:np ] + adjdict = [ (Int=>Int)[] for i = 1:np ] + + for d in deps + p0, v0 = vdict[d[1]] + vs = d[2] + p1 = pdict[vs.package] + + j0 = 1 + while j0 <= length(gadj[p0]) && gadj[p0][j0] != p1 + j0 += 1 + end + j1 = 1 + while j1 <= length(gadj[p1]) && gadj[p1][j1] != p0 + j1 += 1 + end + @assert (j0 > length(gadj[p0]) && j1 > length(gadj[p1])) || + (j0 <= length(gadj[p0]) && j1 <= length(gadj[p1])) + + if j0 > length(gadj[p0]) + push!(gadj[p0], p1) + push!(gadj[p1], p0) + j0 = length(gadj[p0]) + j1 = length(gadj[p1]) + + adjdict[p1][p0] = j0 + adjdict[p0][p1] = j1 + + bm = ones(Bool, spp[p1], spp[p0]) + bmt = bm' + + push!(gmsk[p0], bm) + push!(gmsk[p1], bmt) + + push!(gdir[p0], 1) + push!(gdir[p1], -1) + else + bm = gmsk[p0][j0] + bmt = gmsk[p1][j1] + if gdir[p0][j0] == -1 + gdir[p0][j0] = 0 + gdir[p1][j0] = 0 + end + end + + for v1 = 1:length(pvers[p1]) + if !contains(vs, Version(vs.package, pvers[p1][v1])) + bm[v1, v0] = false + bmt[v0, v1] = false + end + end + bm[end,v0] = false + bmt[v0,end] = false + end + + perm = [1:np] + + return new(gadj, gmsk, gdir, adjdict, spp, perm, np) + end +end + +# Messages has the cavity messages and the total fields, and +# gets updated iteratively (and occasionally decimated) until +# convergence +type Messages + # cavity incoming messages: for each package p0, + # for each neighbor p1 of p0, + # msg[p0][p1] is a vector of length spp[p0] + # messages are normalized (i.e. the max is always 0) + msg::Vector{Vector{Vector{FieldValue}}} + + # overall fields: for each package p0, + # fld[p0] is a vector of length spp[p0] + # fields are not normalized + fld::Vector{Vector{FieldValue}} + + # keep track of which variables have been decimated + decimated::BitVector + num_nondecimated::Int + + function Messages(reqsstruct::ReqsStruct, + pkgstruct::PkgStruct, + graph::Graph) + + reqs = reqsstruct.reqs + pkgs = reqsstruct.pkgs + vers = reqsstruct.vers + np = reqsstruct.np + spp = pkgstruct.spp + pvers = pkgstruct.pvers + vdict = pkgstruct.vdict + vweight = pkgstruct.vweight + + # a "deterministic noise" function based on hashes + function noise(p0::Int, v0::Int) + s = pkgs[p0] * string(v0 == spp[p0] ? "UNINST" : pvers[p0][v0]) + int(hash(s)) >>> 30 + end + + # external fields: there are 2 terms, a noise to break potential symmetries + # and one to favor newest versions over older, and no-version over all + fld = [ [ FieldValue(0,0,vweight[p0][v0],0,noise(p0,v0)) for v0 = 1:spp[p0] ] for p0 = 1:np] + + # enforce requirements as infinite external fields over the desired + # version ranges + reqps = falses(np) + reqmsk = [ falses(spp[p0]) for p0 = 1:np ] + + for r in reqs, v in vers + if contains(r, v) + p0, v0 = vdict[v] + reqps[p0] = true + reqmsk[p0][v0] = true + end + end + for p0 = 1:np + if reqps[p0] + for v0 = 1:spp[p0] + if !reqmsk[p0][v0] + # the state is forbidden by requirements + fld[p0][v0] = FieldValue(-1) + else + # the state is one of those explicitly requested: + # favor it at a higer level than normal (upgrade + # FieldValue from l2 to l1) + fld[p0][v0] += FieldValue(0,vweight[p0][v0],-vweight[p0][v0]) + end + end + end + end + # normalize fields + for p0 = 1:np + m = max(fld[p0]) + for v0 = 1:spp[p0] + fld[p0][v0] -= m + end + end + + # initialize cavity messages to 0 + gadj = graph.gadj + msg = [ [ zeros(FieldValue,spp[p0]) for p1 = 1:length(gadj[p0])] for p0 = 1:np] + + return new(msg, fld, falses(np), np) + end +end + +function getsolution(msgs::Messages) + # the solution is just the location of the maximum in + # each field + + fld = msgs.fld + np = length(fld) + sol = Array(Int, np) + for p0 = 1:np + fld0 = fld[p0] + s0 = indmax(fld0) + if !validmax(fld0[s0]) + throw(UnsatError(p0)) + end + sol[p0] = s0 + end + return sol +end + +# This is the core of the max-sum solver: +# for a given node p0 (i.e. a package) updates all +# input cavity messages and fields of its neighbors +function update(p0::Int, graph::Graph, msgs::Messages) + + gadj = graph.gadj + gmsk = graph.gmsk + gdir = graph.gdir + adjdict = graph.adjdict + spp = graph.spp + np = graph.np + msg = msgs.msg + fld = msgs.fld + decimated = msgs.decimated + + maxdiff = zero(FieldValue) + + gadj0 = gadj[p0] + msg0 = msg[p0] + fld0 = fld[p0] + spp0 = spp[p0] + adjdict0 = adjdict[p0] + + # iterate over all neighbors of p0 + for j0 in 1:length(gadj0) + + p1 = gadj0[j0] + if decimated[p1] + continue + end + j1 = adjdict0[p1] + #@assert j0 == adjdict[p1][p0] + bm1 = gmsk[p1][j1] + dir1 = gdir[p1][j1] + spp1 = spp[p1] + msg1 = msg[p1] + + # compute the output cavity message p0->p1 + cavmsg = fld0 - msg0[j0] + + if dir1 == -1 + # p0 depends on p1 + for v0 = 1:spp0-1 + inplaceadd!(cavmsg[v0], v0, 4) + end + end + + # keep the old input cavity message p0->p1 + oldmsg = msg1[j1] + + # init the new message to minus infinity + newmsg = [ FieldValue(-1) for v1 = 1:spp1 ] + + # compute the new message by passing cavmsg + # through the constraint encoded in the bitmask + # (nearly equivalent to: + # newmsg = [ max(cavmsg[bm1[:,v1]]) for v1 = 1:spp1 ] + # except for the gnrg term) + m = FieldValue(-1) + for v1 = 1:spp1 + for v0 = 1:spp0 + if bm1[v0, v1] + newmsg[v1] = max(newmsg[v1], cavmsg[v0]) + end + end + if dir1 == 1 && v1 != spp1 + # p1 depends on p0 + # Note: cannot use inplaceadd! here since it may + # mutate cavmsg + newmsg[v1] += FieldValue(0,0,0,v1) + end + m = max(m, newmsg[v1]) + end + if !validmax(m) + # No state available without violating some + # hard constraint + throw(UnsatError(p1)) + end + + # normalize the new message + for v1 = 1:spp1 + newmsg[v1] -= m + end + + diff = newmsg - oldmsg + maxabsdiff = max(abs(diff)) + maxdiff = max(maxdiff, maxabsdiff) + + # update the field of p1 + fld1 = fld[p1] + for v1 = 1:spp1 + inplaceadd!(fld1[v1], diff[v1]) + end + + # put the newly computed message in place + msg1[j1] = newmsg + end + return maxdiff +end + +# A simple shuffling machinery for the update order in iterate() +# (woulnd't pass any random quality test but it's arguably enough) +let step=1 +global shuffleperm, shuffleperminit +shuffleperminit() = (step = 1) +function shuffleperm(graph::Graph) + perm = graph.perm + np = graph.np + for j = np:-1:2 + k = mod(step,j)+1 + perm[j], perm[k] = perm[k], perm[j] + step += isodd(j) ? 1 : k + end + #@assert isperm(perm) +end +end + +# Call update for all nodes (i.e. packages) in +# random order +function iterate(graph::Graph, msgs::Messages) + + np = graph.np + + maxdiff = zero(FieldValue) + shuffleperm(graph) + perm = graph.perm + for p0 in perm + maxdiff0 = update(p0, graph, msgs) + maxdiff = max(maxdiff, maxdiff0) + end + return maxdiff +end + +function decimate1(p0::Int, graph::Graph, msgs::Messages) + @assert !msgs.decimated[p0] + fld0 = msgs.fld[p0] + s0 = indmax(fld0) + #println("DECIMATING $p0 ($(packages()[p0]) s0=$s0)") + for v0 = 1:length(fld0) + if v0 != s0 + fld0[v0] -= FieldValue(1) + end + end + update(p0, graph, msgs) + msgs.decimated[p0] = true + msgs.num_nondecimated -= 1 +end + +# If normal convergence fails (or is too slow) fix the most +# polarized packages by adding extra infinite fields on every state +# but the maximum +function decimate(n::Int, graph::Graph, msgs::Messages) + #println("DECIMATING $n NODES") + fld = msgs.fld + decimated = msgs.decimated + fldorder = sortperm(fld, Sort.By(secondmax)) + for p0 in fldorder + if decimated[p0] + continue + end + decimate1(p0, graph, msgs) + n -= 1 + if n == 0 + break + end + end + @assert n == 0 + return +end + +# In case ties still exist at convergence, break them and +# keep converging +function break_ties(msgs::Messages) + fld = msgs.fld + for p0 = 1:length(fld) + fld0 = fld[p0] + z = 0 + m = typemin(FieldValue) + for v0 = 1:length(fld0) + if fld0[v0] > m + m = fld0[v0] + z = 1 + elseif fld0[v0] == m + z += 1 + end + end + if z > 1 + #println("TIE! p0=$p0") + decimate1(p0, msgs) + return false + end + end + return true +end + +# Iterative solver: run iterate() until convergence +# (occasionally calling decimate()) +function converge(graph::Graph, msgs::Messages) + + params = ResolveParams() + + it = 0 + shuffleperminit() + while true + it += 1 + maxdiff = iterate(graph, msgs) + #println("it = $it maxdiff = $maxdiff") + + if maxdiff == zero(FieldValue) + if break_ties(msgs) + break + else + continue + end + end + if it >= params.nondec_iterations && + (it - params.nondec_iterations) % params.dec_interval == 0 + numdec = clamp(ifloor(params.dec_fraction * graph.np), 1, msgs.num_nondecimated) + decimate(numdec, graph, msgs) + if msgs.num_nondecimated == 0 + break + end + end + end + + # Finally, decimate everything just to + # check against inconsistencies + # (old_numnondec is saved just to prevent + # wrong messages about accuracy) + old_numnondec = msgs.num_nondecimated + decimate(msgs.num_nondecimated, graph, msgs) + msgs.num_nondecimated = old_numnondec + + return getsolution(msgs) +end + +# The output format is a dict which associates sha1's to each installed package name +function compute_output_dict(reqsstruct::ReqsStruct, pkgstruct::PkgStruct, sol::Vector{Int}) + + pkgs = reqsstruct.pkgs + np = reqsstruct.np + pvers = pkgstruct.pvers + spp = pkgstruct.spp + + want = (String=>ASCIIString)[] + for p0 = 1:np + p = pkgs[p0] + s = sol[p0] + if s != spp[p0] + v = pvers[p0][s] + want[p] = readchomp("METADATA/$p/versions/$v/sha1") + #want[p] = "$v" + end + end + + return want +end + +# verifies that the solution fulfills all hard constraints +# (requirements and dependencies) +function verify_sol(reqsstruct::ReqsStruct, pkgstruct::PkgStruct, sol::Vector{Int}) + + reqs = reqsstruct.reqs + deps = reqsstruct.deps + spp = pkgstruct.spp + pdict = pkgstruct.pdict + pvers = pkgstruct.pvers + vdict = pkgstruct.vdict + + # verify requirements + for r in reqs + p = r.package + p0 = pdict[p] + @assert sol[p0] != spp[p0] + v = pvers[p0][sol[p0]] + @assert contains(r, Version(p, v)) + end + + # verify dependencies + for d in deps + p0, v0 = vdict[d[1]] + if sol[p0] == v0 + vs = d[2] + p = vs.package + p1 = pdict[p] + @assert sol[p1] != spp[p1] + v = pvers[p1][sol[p1]] + @assert contains(vs, Version(p, v)) + end + end + +end + +# Push the given solution to a local optimium if needed +function enforce_optimality(reqsstruct::ReqsStruct, pkgstruct::PkgStruct, sol::Vector{Int}) + np = reqsstruct.np + + reqs = reqsstruct.reqs + deps = reqsstruct.deps + spp = pkgstruct.spp + pdict = pkgstruct.pdict + pvers = pkgstruct.pvers + vdict = pkgstruct.vdict + waspruned = pkgstruct.waspruned + + # prepare some useful structures + # pdeps[p0][v0] has all dependencies of package p0 version v0 + pdeps = [ [ VersionSet[] for v0 = 1:spp[p0]-1 ] for p0 = 1:np ] + # prevdeps[p1][p0][v0] is the VersionSet of package p1 which package p0 version v0 + # depends upon + prevdeps = [ (Int=>Dict{Int,VersionSet})[] for p0 = 1:np ] + + for d in deps + p0, v0 = vdict[d[1]] + vs = d[2] + push!(pdeps[p0][v0], vs) + p1 = pdict[vs.package] + if !has(prevdeps[p1], p0) + prevdeps[p1][p0] = (Int=>VersionSet)[] + end + prevdeps[p1][p0][v0] = vs + end + + restart = true + while restart + restart = false + for p0 = 1:np + s0 = sol[p0] + if s0 >= spp[p0] - 1 + # either the package is not installed, + # or it's already at the maximum version + continue + end + viol = false + if !waspruned + # check if bumping would violate a requirement + for r in reqs + p = r.package + if p0 != pdict[p] + continue + end + v = pvers[p0][s0+1] + if !contains(r, Version(p, v)) + viol = true + break + end + end + if viol + continue + end + end + # check if the higher version has a depencency which + # would be violated by the state of the remaining packages + for vs in pdeps[p0][s0+1] + p = vs.package + p1 = pdict[p] + if sol[p1] == spp[p1] + # the dependency is violated because + # the other package is not being installed + viol = true + break + end + v = pvers[p1][sol[p1]] + if !contains(vs, Version(p, v)) + # the dependency is violated because + # the other package version is invalid + viol = true + break + end + end + if viol + continue + end + + # check if bumping the version would violate some + # dependency of another package + for (p1,d) in prevdeps[p0] + vs = get(d, sol[p1], nothing) + if vs == nothing + continue + end + p = vs.package + v = pvers[p0][s0+1] + if !contains(vs, Version(p, v)) + # bumping the version would violate + # the dependency + viol = true + break + end + end + if viol + continue + end + # So the solution is non-optimal: we bump it manually + #println(STDERR, "Warning: nonoptimal solution for package $(reqsstruct.pkgs[p0]): sol=$s0") + sol[p0] += 1 + restart = true + end + end + return +end + +# The external-facing function +function resolve(reqs::Vector{VersionSet}, vers::Vector{Version}, deps::Vector{(Version,VersionSet)}) + # fetch data + reqsstruct = ReqsStruct(reqs, vers, deps) + + # init structures + pkgstruct = PkgStruct(reqsstruct) + + prune_versions!(reqsstruct, pkgstruct) + + graph = Graph(reqsstruct, pkgstruct) + msgs = Messages(reqsstruct, pkgstruct, graph) + + # find solution + local sol::Vector{Int} + try + sol = converge(graph, msgs) + catch err + if isa(err, UnsatError) + p = reqsstruct.pkgs[err.info] + msg = "Unsatisfiable package requirements detected: " * + "no feasible version could be found for package: $p" + if msgs.num_nondecimated != graph.np + msg *= "\n (you may try increasing the value of the" * + "\n JULIA_PKGRESOLVE_ACCURACY environment variable)" + end + error(msg) + end + rethrow(err) + end + + # verify solution (debug code) and enforce its optimality + verify_sol(reqsstruct, pkgstruct, sol) + enforce_optimality(reqsstruct, pkgstruct, sol) + + # return the solution as a Dict mapping package_name => sha1 + return compute_output_dict(reqsstruct, pkgstruct, sol) +end + +# Build a subgraph incuding only the (direct and indirect) dependencies +# of a given package (used in check_sanity) +function substructs(reqsstruct0::ReqsStruct, pkgstruct0::PkgStruct, pdeps::Vector, v::Version) + + pkgs = reqsstruct0.pkgs + vers = reqsstruct0.vers + deps = reqsstruct0.deps + np = reqsstruct0.np + spp = pkgstruct0.spp + pdict = pkgstruct0.pdict + pvers = pkgstruct0.pvers + vdict = pkgstruct0.vdict + + p = v.package + vn = v.version + nvn = deepcopy(vn) + nvn.patch += 1 + reqs = [VersionSet(p, [vn, nvn])] + + p0 = pdict[p] + staged = IntSet(p0) + pset = IntSet(p0) + while !isempty(staged) + staged_next = IntSet() + for p0 in staged + for w in pdeps[p0], vs in w + p1 = pdict[vs.package] + add!(staged_next, p1) + end + end + pset = union(pset, staged_next) + staged = staged_next + end + + red_pkgs = [ pkgs[p0] for p0 in pset ] + red_vers = Version[] + for p0 in pset + pvers0 = pvers[p0] + for vn in pvers0 + push!(red_vers, Version(pkgs[p0], vn)) + end + end + red_deps = Array((Version,VersionSet),0) + for p0 in pset + pdeps0 = pdeps[p0] + pvers0 = pvers[p0] + p = pkgs[p0] + for v0 = 1:spp[p0]-1 + vn = pvers0[v0] + for vs in pdeps0[v0] + push!(red_deps, (Version(p, vn), vs)) + end + end + end + + reqsstruct = ReqsStruct(reqs, red_pkgs, red_vers, red_deps) + pkgstruct = PkgStruct(reqsstruct) + return reqsstruct, pkgstruct +end + +# Scan dependencies for (explicit or implicit) contradictions +function sanity_check() + reqsstruct0 = ReqsStruct(VersionSet[]) + pkgstruct0 = PkgStruct(reqsstruct0) + + eq_classes_map = prune_versions!(reqsstruct0, pkgstruct0, false) + + pkgs = reqsstruct0.pkgs + vers = reqsstruct0.vers + deps = reqsstruct0.deps + np = reqsstruct0.np + spp = pkgstruct0.spp + pdict = pkgstruct0.pdict + pvers = pkgstruct0.pvers + vdict = pkgstruct0.vdict + + pdeps = [ [ VersionSet[] for v0 = 1:spp[p0]-1 ] for p0 = 1:np ] + pndeps = [ zeros(Int,spp[p0]-1) for p0 = 1:np ] + for d in deps + p0, v0 = vdict[d[1]] + vs = d[2] + push!(pdeps[p0][v0], vs) + pndeps[p0][v0] += 1 + end + + rev_eq_classes_map = [ (VersionNumber=>Vector{VersionNumber})[] for p0 = 1:np ] + for p0 = 1:np + eqclass0 = eq_classes_map[p0] + reveqclass0 = rev_eq_classes_map[p0] + for (v,vtop) in eqclass0 + if !has(reveqclass0, vtop) + reveqclass0[vtop] = VersionNumber[v] + else + push!(reveqclass0[vtop], v) + end + end + end + + function vrank(v::Version) + p0, v0 = vdict[v] + return -pndeps[p0][v0] + end + svers = sort(vers, Sort.By(vrank)) + + nv = length(svers) + nnzv = findfirst(v->vrank(v)==0, svers) - 1 + + svdict = (Version=>Int)[] + i = 1 + for v in svers + svdict[v] = i + i += 1 + end + checked = falses(nv) + + insane_ids = Array((Int,Int),0) + problematic_pkgs = String[] + + i = 1 + psl = 0 + for v in svers + vr = -vrank(v) + if vr == 0 + break + end + if checked[i] + i += 1 + continue + elseif vr == 1 + p0, v0 = vdict[v] + vs = pdeps[p0][v0][1] + p1 = pdict[vs.package] + found = false + for vn in pvers[p1] + if contains(vs, Version(vs.package, vn)) + found = true + break + end + end + if !found + pp = vs.package + push!(insane_ids, (p0,v0)) + push!(problematic_pkgs, pp) + else + checked[i] = true + end + else + reqsstruct, pkgstruct = substructs(reqsstruct0, pkgstruct0, pdeps, v) + + graph = Graph(reqsstruct, pkgstruct) + msgs = Messages(reqsstruct, pkgstruct, graph) + + red_pkgs = reqsstruct.pkgs + red_np = reqsstruct.np + red_spp = pkgstruct.spp + red_pvers = pkgstruct.pvers + + local sol::Vector{Int} + try + sol = converge(graph, msgs) + verify_sol(reqsstruct, pkgstruct, sol) + + for p0 = 1:red_np + s0 = sol[p0] + if s0 != red_spp[p0] + j = svdict[Version(red_pkgs[p0], red_pvers[p0][s0])] + checked[j] = true + end + end + checked[i] = true + catch err + if isa(err, UnsatError) + pp = red_pkgs[err.info] + push!(insane_ids, vdict[v]) + push!(problematic_pkgs, pp) + else + rethrow(err) + end + end + end + i += 1 + end + + insane = Array((Version,String), 0) + if !isempty(insane_ids) + i = 1 + for (p0,v0) in insane_ids + p = pkgs[p0] + vn = pvers[p0][v0] + pp = problematic_pkgs[i] + for vneq in rev_eq_classes_map[p0][vn] + push!(insane, (Version(p, vneq), pp)) + end + i += 1 + end + sort!(insane, Sort.By(x->x[1])) + throw(MetadataError(insane)) + end + + return +end + +end # module diff --git a/base/pointer.jl b/base/pointer.jl index 763db946844ca..cde5e75018073 100644 --- a/base/pointer.jl +++ b/base/pointer.jl @@ -19,6 +19,7 @@ convert{T}(::Type{Ptr{T}}, a::Array) = ccall(:jl_array_ptr, Ptr{T}, (Any,), a) convert(::Type{Ptr{Uint8}}, s::ByteString) = convert(Ptr{Uint8}, s.data) pointer{T}(::Type{T}, x::Uint) = convert(Ptr{T}, x) +pointer{T}(::Type{T}, x::Ptr) = convert(Ptr{T}, x) # note: these definitions don't mean any AbstractArray is convertible to # pointer. they just map the array element type to the pointer type for # convenience in cases that work. @@ -37,6 +38,10 @@ unsafe_assign(p::Ptr{Any}, x::ANY, i::Integer) = pointerset(p, x, int(i)) unsafe_assign{T}(p::Ptr{T}, x, i::Integer) = pointerset(p, convert(T, x), int(i)) unsafe_assign{T}(p::Ptr{T}, x) = unsafe_assign(p, convert(T,x), 1) +# convert a raw Ptr to an object reference, and vice-versa +unsafe_pointer_to_objref(p::Ptr) = pointertoref(unbox(Ptr{Void},p)) +pointer_from_objref(x::Any) = ccall(:jl_value_ptr, Ptr{Void}, (Any,), x) + integer(x::Ptr) = convert(Uint, x) unsigned(x::Ptr) = convert(Uint, x) diff --git a/base/printf.jl b/base/printf.jl index 1dc1e51672a39..cb2d6a775e246 100644 --- a/base/printf.jl +++ b/base/printf.jl @@ -6,12 +6,12 @@ export @printf, @sprintf function _gen(s::String) args = {:(out::IO)} - blk = expr(:block, :(local neg, pt, len, exp)) + blk = Expr(:block, :(local neg, pt, len, exp)) for x in _parse(s) if isa(x,String) - push(blk.args, :(write(out, $(strlen(x)==1 ? x[1] : x)))) + push!(blk.args, :(write(out, $(length(x)==1 ? x[1] : x)))) else - c = lc(x[end]) + c = lowercase(x[end]) f = c=='f' ? _gen_f : c=='e' ? _gen_e : c=='g' ? _gen_g : @@ -20,11 +20,11 @@ function _gen(s::String) c=='p' ? _gen_p : _gen_d arg, ex = f(x...) - push(args, arg) - push(blk.args, ex) + push!(args, arg) + push!(blk.args, ex) end end - push(blk.args, :nothing) + push!(blk.args, :nothing) return args, blk end @@ -37,18 +37,18 @@ function _parse(s::String) while !done(s,j) c, k = next(s,j) if c == '%' - isempty(s[i:j-1]) || push(list, s[i:j-1]) + isempty(s[i:j-1]) || push!(list, s[i:j-1]) flags, width, precision, conversion, k = _parse1(s,k) contains(flags,'\'') && error("printf format flag ' not yet supported") conversion == 'a' && error("printf feature %a not yet supported") conversion == 'n' && error("printf feature %n not supported") - push(list, conversion == '%' ? "%" : (flags,width,precision,conversion)) + push!(list, conversion == '%' ? "%" : (flags,width,precision,conversion)) i = j = k else j = k end end - isempty(s[i:]) || push(list, s[i:]) + isempty(s[i:]) || push!(list, s[i:]) # coalesce adjacent strings i = 1 while i < length(list) @@ -60,7 +60,7 @@ function _parse(s::String) end list[i] *= list[j] end - del(list,i+1:j) + delete!(list,i+1:j) end i += 1 end @@ -133,7 +133,7 @@ end function _special_handler(flags::ASCIIString, width::Int) @gensym x - blk = expr(:block) + blk = Expr(:block) pad = contains(flags,'-') ? rpad : lpad pos = contains(flags,'+') ? "+" : contains(flags,' ') ? " " : "" @@ -225,22 +225,22 @@ function _gen_d(flags::ASCIIString, width::Int, precision::Int, c::Char) x, ex, blk = _special_handler(flags,width) # interpret the number prefix = "" - if lc(c)=='o' + if lowercase(c)=='o' f = contains(flags,'#') ? :_int_0ct : :_int_oct - push(blk.args, :(($f)($x))) + push!(blk.args, :(($f)($x))) elseif c=='x' if contains(flags,'#'); prefix = "0x"; end - push(blk.args, :(_int_hex($x))) + push!(blk.args, :(_int_hex($x))) elseif c=='X' if contains(flags,'#'); prefix = "0X"; end - push(blk.args, :(_int_HEX($x))) + push!(blk.args, :(_int_HEX($x))) else - push(blk.args, :(_int_dec($x))) + push!(blk.args, :(_int_dec($x))) end - push(blk.args, :(neg = NEG[1])) - push(blk.args, :(pt = POINT[1])) + push!(blk.args, :(neg = NEG[1])) + push!(blk.args, :(pt = POINT[1])) # calculate padding - width -= strlen(prefix) + width -= length(prefix) space_pad = width > max(1,precision) && contains(flags,'-') || precision < 0 && width > 1 && !contains(flags,'0') || precision >= 0 && width > precision @@ -260,29 +260,29 @@ function _gen_d(flags::ASCIIString, width::Int, precision::Int, c::Char) end # print space padding if padding != nothing && !contains(flags,'-') - push(blk.args, _pad(width-precision, padding, ' ')) + push!(blk.args, _pad(width-precision, padding, ' ')) end # print sign - contains(flags,'+') ? push(blk.args, :(write(out, neg?'-':'+'))) : - contains(flags,' ') ? push(blk.args, :(write(out, neg?'-':' '))) : - push(blk.args, :(neg && write(out, '-'))) + contains(flags,'+') ? push!(blk.args, :(write(out, neg?'-':'+'))) : + contains(flags,' ') ? push!(blk.args, :(write(out, neg?'-':' '))) : + push!(blk.args, :(neg && write(out, '-'))) # print prefix for ch in prefix - push(blk.args, :(write(out, $ch))) + push!(blk.args, :(write(out, $ch))) end # print zero padding & leading zeros if space_pad && precision > 1 - push(blk.args, _pad(precision-1, :($precision-pt), '0')) + push!(blk.args, _pad(precision-1, :($precision-pt), '0')) elseif !space_pad && width > 1 zeros = contains(flags,'+') || contains(flags,' ') ? :($(width-1)-pt) : :($width-neg-pt) - push(blk.args, _pad(width-1, zeros, '0')) + push!(blk.args, _pad(width-1, zeros, '0')) end # print integer - push(blk.args, :(write(out, pointer(DIGITS), pt))) + push!(blk.args, :(write(out, pointer(DIGITS), pt))) # print padding if padding != nothing && contains(flags,'-') - push(blk.args, _pad(width-precision, padding, ' ')) + push!(blk.args, _pad(width-precision, padding, ' ')) end # return arg, expr :(($x)::Real), ex @@ -302,10 +302,10 @@ function _gen_f(flags::ASCIIString, width::Int, precision::Int, c::Char) x, ex, blk = _special_handler(flags,width) # interpret the number if precision < 0; precision = 6; end - push(blk.args, :(_fix_dec($x,$precision))) - push(blk.args, :(neg = NEG[1])) - push(blk.args, :(pt = POINT[1])) - push(blk.args, :(len = LEN[1])) + push!(blk.args, :(_fix_dec($x,$precision))) + push!(blk.args, :(neg = NEG[1])) + push!(blk.args, :(pt = POINT[1])) + push!(blk.args, :(len = LEN[1])) # calculate padding padding = nothing if precision > 0 || contains(flags,'#') @@ -323,27 +323,27 @@ function _gen_f(flags::ASCIIString, width::Int, precision::Int, c::Char) end # print space padding if padding != nothing && !contains(flags,'-') && !contains(flags,'0') - push(blk.args, _pad(width-1, padding, ' ')) + push!(blk.args, _pad(width-1, padding, ' ')) end # print sign - contains(flags,'+') ? push(blk.args, :(write(out, neg?'-':'+'))) : - contains(flags,' ') ? push(blk.args, :(write(out, neg?'-':' '))) : - push(blk.args, :(neg && write(out, '-'))) + contains(flags,'+') ? push!(blk.args, :(write(out, neg?'-':'+'))) : + contains(flags,' ') ? push!(blk.args, :(write(out, neg?'-':' '))) : + push!(blk.args, :(neg && write(out, '-'))) # print zero padding if padding != nothing && !contains(flags,'-') && contains(flags,'0') - push(blk.args, _pad(width-1, padding, '0')) + push!(blk.args, _pad(width-1, padding, '0')) end # print digits if precision > 0 - push(blk.args, :(_print_fixed(out,$precision))) + push!(blk.args, :(_print_fixed(out,$precision))) else - push(blk.args, :(write(out, pointer(DIGITS), len))) - push(blk.args, :(while pt >= (len+=1) write(out,'0') end)) - contains(flags,'#') && push(blk.args, :(write(out, '.'))) + push!(blk.args, :(write(out, pointer(DIGITS), len))) + push!(blk.args, :(while pt >= (len+=1) write(out,'0') end)) + contains(flags,'#') && push!(blk.args, :(write(out, '.'))) end # print space padding if padding != nothing && contains(flags,'-') - push(blk.args, _pad(width-1, padding, ' ')) + push!(blk.args, _pad(width-1, padding, ' ')) end # return arg, expr :(($x)::Real), ex @@ -365,16 +365,16 @@ function _gen_e(flags::ASCIIString, width::Int, precision::Int, c::Char) # interpret the number if precision < 0; precision = 6; end ndigits = min(precision+1,BUFLEN-1) - push(blk.args, :(_ini_dec($x,$ndigits))) - push(blk.args, :(neg = NEG[1])) - push(blk.args, :(exp = POINT[1]-1)) + push!(blk.args, :(_ini_dec($x,$ndigits))) + push!(blk.args, :(neg = NEG[1])) + push!(blk.args, :(exp = POINT[1]-1)) expmark = c=='E' ? "E" : "e" if precision==0 && contains(flags,'#') - expmark = strcat(".",expmark) + expmark = string(".",expmark) end # calculate padding padding = nothing - width -= precision+strlen(expmark)+(precision>0)+4 + width -= precision+length(expmark)+(precision>0)+4 # 4 = leading + expsign + 2 exp digits if contains(flags,'+') || contains(flags,' ') width -= 1 # for the sign indicator @@ -388,33 +388,33 @@ function _gen_e(flags::ASCIIString, width::Int, precision::Int, c::Char) end # print space padding if padding != nothing && !contains(flags,'-') && !contains(flags,'0') - push(blk.args, _pad(width, padding, ' ')) + push!(blk.args, _pad(width, padding, ' ')) end # print sign - contains(flags,'+') ? push(blk.args, :(write(out, neg?'-':'+'))) : - contains(flags,' ') ? push(blk.args, :(write(out, neg?'-':' '))) : - push(blk.args, :(neg && write(out, '-'))) + contains(flags,'+') ? push!(blk.args, :(write(out, neg?'-':'+'))) : + contains(flags,' ') ? push!(blk.args, :(write(out, neg?'-':' '))) : + push!(blk.args, :(neg && write(out, '-'))) # print zero padding if padding != nothing && !contains(flags,'-') && contains(flags,'0') - push(blk.args, _pad(width, padding, '0')) + push!(blk.args, _pad(width, padding, '0')) end # print digits - push(blk.args, :(write(out, DIGITS[1]))) + push!(blk.args, :(write(out, DIGITS[1]))) if precision > 0 - push(blk.args, :(write(out, '.'))) - push(blk.args, :(write(out, pointer(DIGITS)+1, $(ndigits-1)))) + push!(blk.args, :(write(out, '.'))) + push!(blk.args, :(write(out, pointer(DIGITS)+1, $(ndigits-1)))) if ndigits < precision+1 n = precision+1-ndigits - push(blk.args, _pad(n, n, '0')) + push!(blk.args, _pad(n, n, '0')) end end for ch in expmark - push(blk.args, :(write(out, $ch))) + push!(blk.args, :(write(out, $ch))) end - push(blk.args, :(_print_exp(out, exp))) + push!(blk.args, :(_print_exp(out, exp))) # print space padding if padding != nothing && contains(flags,'-') - push(blk.args, _pad(width, padding, ' ')) + push!(blk.args, _pad(width, padding, ' ')) end # return arg, expr :(($x)::Real), ex @@ -429,14 +429,14 @@ function _gen_c(flags::ASCIIString, width::Int, precision::Int, c::Char) # (-): left justify # @gensym x - blk = expr(:block, :($x = char($x))) + blk = Expr(:block, :($x = char($x))) if width > 1 && !contains(flags,'-') p = contains(flags,'0') ? '0' : ' ' - push(blk.args, _pad(width-1, :($width-charwidth($x)), p)) + push!(blk.args, _pad(width-1, :($width-charwidth($x)), p)) end - push(blk.args, :(write(out, $x))) + push!(blk.args, :(write(out, $x))) if width > 1 && contains(flags,'-') - push(blk.args, _pad(width-1, :($width-charwidth($x)), ' ')) + push!(blk.args, _pad(width-1, :($width-charwidth($x)), ' ')) end :(($x)::Integer), blk end @@ -450,25 +450,25 @@ function _gen_s(flags::ASCIIString, width::Int, precision::Int, c::Char) # (-): left justify # @gensym x - blk = expr(:block) + blk = Expr(:block) if width > 0 if !contains(flags,'#') - push(blk.args, :($x = string($x))) + push!(blk.args, :($x = string($x))) else - push(blk.args, :($x = repr($x))) + push!(blk.args, :($x = repr($x))) end if !contains(flags,'-') - push(blk.args, _pad(width, :($width-strwidth($x)), ' ')) + push!(blk.args, _pad(width, :($width-strwidth($x)), ' ')) end - push(blk.args, :(write(out, $x))) + push!(blk.args, :(write(out, $x))) if contains(flags,'-') - push(blk.args, _pad(width, :($width-strwidth($x)), ' ')) + push!(blk.args, _pad(width, :($width-strwidth($x)), ' ')) end else if !contains(flags,'#') - push(blk.args, :(print(out, $x))) + push!(blk.args, :(print(out, $x))) else - push(blk.args, :(show(out, $x))) + push!(blk.args, :(show(out, $x))) end end :(($x)::Any), blk @@ -481,17 +481,17 @@ function _gen_p(flags::ASCIIString, width::Int, precision::Int, c::Char) # [p]: the only option # @gensym x - blk = expr(:block) + blk = Expr(:block) ptrwidth = WORD_SIZE>>2 width -= ptrwidth+2 if width > 0 && !contains(flags,'-') - push(blk.args, _pad(width, width, ' ')) + push!(blk.args, _pad(width, width, ' ')) end - push(blk.args, :(write(out, '0'))) - push(blk.args, :(write(out, 'x'))) - push(blk.args, :(write(out, bytestring(hex(unsigned($x), $ptrwidth))))) + push!(blk.args, :(write(out, '0'))) + push!(blk.args, :(write(out, 'x'))) + push!(blk.args, :(write(out, bytestring(hex(unsigned($x), $ptrwidth))))) if width > 0 && contains(flags,'-') - push(blk.args, _pad(width, width, ' ')) + push!(blk.args, _pad(width, width, ' ')) end :(($x)::Ptr), blk end @@ -754,7 +754,7 @@ end _is_str_expr(ex) = isa(ex,Expr) && ex.head==:macrocall && isa(ex.args[1],Symbol) && - (ex.args[1] == :str || ends_with(string(ex.args[1]),"_str")) + (ex.args[1] == :str || endswith(string(ex.args[1]),"_str")) macro printf(args...) if length(args) == 0 @@ -783,7 +783,7 @@ macro printf(args...) end for i = length(args):-1:1 var = sym_args[i].args[1] - unshift(blk.args, :($var = $(esc(args[i])))) + unshift!(blk.args, :($var = $(esc(args[i])))) end blk end diff --git a/base/process.jl b/base/process.jl index e8fadae666d77..34f53aef1c3ac 100644 --- a/base/process.jl +++ b/base/process.jl @@ -1,694 +1,473 @@ -## process status ## - -abstract ProcessStatus -type ProcessNotRun <: ProcessStatus; end -type ProcessRunning <: ProcessStatus; end -type ProcessExited <: ProcessStatus; status::Int32; end -type ProcessSignaled <: ProcessStatus; signal::Int32; end -type ProcessStopped <: ProcessStatus; signal::Int32; end - -process_running (s::Int32) = s == -1 -process_exited (s::Int32) = ccall(:jl_process_exited, Int32, (Int32,), s) != 0 -process_signaled(s::Int32) = ccall(:jl_process_signaled, Int32, (Int32,), s) != 0 -process_stopped (s::Int32) = ccall(:jl_process_stopped, Int32, (Int32,), s) != 0 - -process_exit_status(s::Int32) = ccall(:jl_process_exit_status, Int32, (Int32,), s) -process_term_signal(s::Int32) = ccall(:jl_process_term_signal, Int32, (Int32,), s) -process_stop_signal(s::Int32) = ccall(:jl_process_stop_signal, Int32, (Int32,), s) - -function process_status(s::Int32) - process_running (s) ? ProcessRunning() : - process_exited (s) ? ProcessExited (process_exit_status(s)) : - process_signaled(s) ? ProcessSignaled(process_term_signal(s)) : - process_stopped (s) ? ProcessStopped (process_stop_signal(s)) : - error("process status error") -end - -## file descriptors and pipes ## - -type FileDes; fd::Int32; end - -const STDIN = FileDes(ccall(:jl_stdin, Int32, ())) -const STDOUT = FileDes(ccall(:jl_stdout, Int32, ())) -const STDERR = FileDes(ccall(:jl_stderr, Int32, ())) - -isequal(fd1::FileDes, fd2::FileDes) = (fd1.fd == fd2.fd) - -hash(fd::FileDes) = hash(fd.fd) - -show(io, fd::FileDes) = - fd == STDIN ? print(io, "STDIN") : - fd == STDOUT ? print(io, "STDOUT") : - fd == STDERR ? print(io, "STDERR") : - invoke(show, (Any, Any), io, fd) - -type Pipe - in::FileDes - out::FileDes - - function Pipe(in::FileDes, out::FileDes) - if in == out - error("identical in and out file descriptors") - end - new(in,out) - end -end - -isequal(p1::Pipe, p2::Pipe) = (p1.in == p2.in && p1.out == p2.out) - -abstract PipeEnd -type PipeIn <: PipeEnd; pipe::Pipe; end -type PipeOut <: PipeEnd; pipe::Pipe; end - -isequal(p1::PipeEnd, p2::PipeEnd) = false -isequal(p1::PipeIn , p2::PipeIn ) = (p1.pipe == p2.pipe) -isequal(p1::PipeOut, p2::PipeOut) = (p1.pipe == p2.pipe) - -pipe_in (p::Pipe) = PipeIn(p) -pipe_out(p::Pipe) = PipeOut(p) -pipe_in (p::PipeEnd) = pipe_in(p.pipe) -pipe_out(p::PipeEnd) = pipe_out(p.pipe) - -fd(p::PipeIn) = p.pipe.in -fd(p::PipeOut) = p.pipe.out -other(p::PipeIn) = p.pipe.out -other(p::PipeOut) = p.pipe.in - -function make_pipe() - fds = Array(Int32, 2) - ret = ccall(:pipe, Int32, (Ptr{Int32},), fds) - system_error(:make_pipe, ret != 0) - Pipe(FileDes(fds[2]), FileDes(fds[1])) -end - -## core system calls for processes ## - -function fork() - pid = ccall(:fork, Int32, ()) - system_error(:fork, pid < 0) - return pid -end - -# WARNING: do not call this and keep the returned array of pointers -# around longer than the args vector and then use array of pointers. -# this could cause a segfault. this is really just for use by the -# spawn function below so that we can exec more efficiently. -# -function _jl_pre_exec(args::Vector{ByteString}) - if length(args) < 1 - error("exec: too few words to exec") - end - ptrs = Array(Ptr{Uint8}, length(args)+1) - for i = 1:length(args) - ptrs[i] = args[i].data - end - ptrs[length(args)+1] = C_NULL - return ptrs -end - -function exec(args::Vector{ByteString}) - ptrs = _jl_pre_exec(args) - ccall(:execvp, Int32, (Ptr{Uint8}, Ptr{Ptr{Uint8}}), ptrs[1], ptrs) - system_error(:exec, true) -end - -function exec(args::String...) - arr = Array(ByteString, length(args)) - for i = 1:length(args) - arr[i] = bytestring(args[i]) - end - exec(arr) -end +abstract AbstractCmd -function wait(pid::Int32, nohang::Bool) - status = Int32[0] - while true - ret = ccall(:waitpid, Int32, (Int32, Ptr{Int32}, Int32), pid, status, nohang) - if ret == 0 return int32(-1) end - if ret != -1 break end - system_error(:wait, errno() != EINTR) - end - status[1] -end -wait(x) = wait(x,false) -wait_nohang(x) = wait(x,true) - -exit(n) = ccall(:exit, Void, (Int32,), n) -_exit(n) = ccall(:_exit, Void, (Int32,), n) -exit() = exit(0) -quit() = exit() - -function dup2(fd1::FileDes, fd2::FileDes) - ret = ccall(:dup2, Int32, (Int32, Int32), fd1.fd, fd2.fd) - system_error(:dup2, ret == -1) -end - -function close(fd::FileDes) - ret = ccall(:close, Int32, (Int32,), fd.fd) - system_error(:close, ret != 0) -end - -## Executable: things that can be exec'd ## - -typealias Executable Union(Vector{ByteString},Function) - -function exec(thunk::Function) - try - thunk() - catch e - show(io, e) - _exit(0x7f) - end - _exit(0) -end - -type FileSink - s::IOStream - own::Bool - function FileSink(s::IOStream, own::Bool) - if fd(s) == -1 - error("Cannot use the given IOStream as FileSink") - end - this = new(s, own) - if own - finalizer(this, close_sink) - end - return this - end +type Cmd <: AbstractCmd + exec::Executable + ignorestatus::Bool + Cmd(exec::Executable) = new(exec,false) end -FileSink(s::IOStream) = FileSink(s, false) - -function FileSink(filename::String, args...) - s = open(filename, args...) - return FileSink(s, true) +function eachline(cmd::AbstractCmd,stdin) + out = NamedPipe() + processes = spawn(false, cmd, (stdin,out,STDERR)) + EachLine(out) end +eachline(cmd::AbstractCmd) = eachline(cmd,SpawnNullStream()) -function close_sink(sink::FileSink) - if sink.own - close(sink.s) - end +type OrCmds <: AbstractCmd + a::AbstractCmd + b::AbstractCmd + OrCmds(a::AbstractCmd, b::AbstractCmd) = new(a,b) end -fd(sink::FileSink) = fd(sink.s) - -type Cmd - exec::Executable - name::String - pipes::Dict{FileDes,PipeEnd} - sinks::Dict{FileDes,FileSink} - closed_fds::Vector{FileDes} - pipeline::Set{Cmd} - pid::Int32 - status::ProcessStatus - successful::Function - - function Cmd(exec::Executable) - if isa(exec,Vector{ByteString}) && length(exec) < 1 - error("Cmd: too few words to exec") - end - this = new(exec, - "", - (FileDes=>PipeEnd)[], - (FileDes=>FileSink)[], - FileDes[], - Set{Cmd}(), - 0, - ProcessNotRun(), - default_success) - add(this.pipeline, this) - this - end +type AndCmds <: AbstractCmd + a::AbstractCmd + b::AbstractCmd + AndCmds(a::AbstractCmd, b::AbstractCmd) = new(a,b) end -default_success(status::ProcessStatus) = false -default_success(status::ProcessExited) = status.status==0 - -ignore_success(status::ProcessStatus) = true -ignore_success(status::ProcessExited) = status.status!=0x7f - -setsuccess(cmd::Cmd, f::Function) = (cmd.successful=f; cmd) -ignorestatus(cmd::Cmd) = setsuccess(cmd, ignore_success) - -function show(io, cmd::Cmd) - if cmd.name != "" - show(io, cmd.name) - elseif isa(cmd.exec,Vector{ByteString}) +function show(io::IO, cmd::Cmd) + if isa(cmd.exec,Vector{ByteString}) esc = shell_escape(cmd.exec...) - print(io, '`') + print(io,'`') for c in esc if c == '`' - print(io, '\\') + print(io,'\\') end - print(io, c) + print(io,c) end - print(io, '`') + print(io,'`') else - invoke(show, (Any, Any,), io, cmd.exec) + print(io, cmd.exec) end end -exec(cmd::Cmd) = exec(cmd.exec) - -function close_sinks(cmd::Cmd) - for (f,s) in cmd.sinks - close_sink(s) +function show(io::IO, cmds::OrCmds) + if isa(cmds.a, AndCmds) + print("(") + show(io, cmds.a) + print(")") + else + show(io, cmds.a) end -end - -## Port: a file descriptor on a particular command ## - -type Port - cmd::Cmd - fd::FileDes -end - -function fd(cmd::Cmd, f::FileDes) - if !has(cmd.pipes, f) && !has(cmd.sinks, f) && !contains(cmd.closed_fds, f) - return Port(cmd,f) + print(" | ") + if isa(cmds.b, AndCmds) + print("(") + show(io, cmds.b) + print(")") + else + show(io, cmds.b) end - error("no ", f, " available in ", cmd) end -function fd(cmds::Set{Cmd}, f::FileDes) - set = Set{Port}() - for cmd in cmds - if !has(cmd.pipes, f) && !has(cmd.sinks, f) && !contains(cmd.closed_fds, f) - add(set, fd(cmd,f)) - end - end - if isempty(set) - error("no ", f, " available in ", cmds) +function show(io::IO, cmds::AndCmds) + if isa(cmds.a, OrCmds) + print("(") + show(io, cmds.a) + print(")") + else + show(io, cmds.a) end - set -end - -typealias Cmds Union(Cmd,Set{Cmd}) -typealias Ports Union(Port,Set{Port}) - -stdin (cmds::Cmds) = fd(cmds,STDIN) -stdout(cmds::Cmds) = fd(cmds,STDOUT) -stderr(cmds::Cmds) = fd(cmds,STDERR) - -cmds(port::Port) = Set(port.cmd) - -function cmds(ports::Ports) - c = Set{Cmd}() - for port in ports - add(c, port.cmd) + print(" & ") + if isa(cmds.b, OrCmds) + print("(") + show(io, cmds.b) + print(")") + else + show(io, cmds.b) end - return c end -## building connected and disconnected pipelines ## +const STDIN_NO = 0 +const STDOUT_NO = 1 +const STDERR_NO = 2 -add_cmds(set::Set{Cmd}, cmd::Cmd) = add(set, cmd) -add_cmds(set::Set{Cmd}, cmds::Set{Cmd}) = add_each(set, cmds) +typealias Redirectable Union(UVStream,FS.File) -function (&)(cmds::Cmds...) - set = Set{Cmd}() - for cmd in cmds - add_cmds(set, cmd) - end - set +type CmdRedirect <: AbstractCmd + cmd::AbstractCmd + handle::Redirectable + stream_no::Int end -add_ports(set::Set{Port}, port::Port) = add(set, port) -add_ports(set::Set{Port}, ports::Set{Port}) = add_each(set, ports) +ignorestatus(cmd::Cmd) = (cmd.ignorestatus=true; cmd) +ignorestatus(cmd::Union(OrCmds,AndCmds)) = (ignorestatus(cmd.a); ignorestatus(cmd.b); cmd) -function (&)(ports::Ports...) - set = Set{Port}() - for port in ports - add_ports(set, port) - end - set -end +(&)(left::AbstractCmd,right::AbstractCmd) = AndCmds(left,right) +(|)(src::AbstractCmd,dest::AbstractCmd) = OrCmds(src,dest) +(<)(left::AbstractCmd,right::Redirectable) = CmdRedirect(left,right,STDIN_NO) +(>)(left::AbstractCmd,right::Redirectable) = CmdRedirect(left,right,STDOUT_NO) +(<)(left::AbstractCmd,right::String) = left < FS.open(right,JL_O_RDONLY) +(>)(left::AbstractCmd,right::String) = left > FS.open(right,JL_O_WRONLY|JL_O_CREAT|JL_O_TRUNC,S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) +(>>)(left::AbstractCmd,right::String) = left > FS.open(right,JL_O_WRONLY|JL_O_APPEND|JL_O_CREAT,S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) +(>)(left::Any,right::AbstractCmd) = right < left +(.>)(left::AbstractCmd,right::Redirectable) = CmdRedirect(left,right,STDERR_NO) -output(cmds::Cmds) = stdout(cmds) & stderr(cmds) +typealias RawOrBoxedHandle Union(UVHandle,UVStream,FS.File) +typealias StdIOSet (RawOrBoxedHandle, RawOrBoxedHandle, RawOrBoxedHandle) -function connect(port::Port, pend::PipeEnd) - if contains(port.cmd.closed_fds, port.fd) - error(port.cmd, " port ", port.fd, " is closed") - end - if !has(port.cmd.pipes, port.fd) && !has(port.cmd.sinks, port.fd) - port.cmd.pipes[port.fd] = pend - elseif has(port.cmd.pipes, port.fd) && port.cmd.pipes[port.fd] != pend - error(port.cmd, " is already connected to ", - fd(port.cmd.pipes[port.fd])) - elseif has(port.cmd.sinks, port.fd) - error(port.cmd, " is already connected to ", - fd(port.cmd.sinks[port.fd])) - end - return pend -end - -function connect(ports::Ports, pend::PipeEnd) - for port in ports - connect(port, pend) - end - return pend -end - -function merge(cmds::Cmds) - if numel(cmds) > 1 - pipeline = Set{Cmd}() - for cmd in cmds - add_each(pipeline, cmd.pipeline) +type Process + cmd::Cmd + handle::Ptr{Void} + in::AsyncStream + out::AsyncStream + err::AsyncStream + exit_code::Int32 + term_signal::Int32 + exitcb::Callback + exitnotify::Vector{WaitTask} + closecb::Callback + closenotify::Vector{WaitTask} + function Process(cmd::Cmd,handle::Ptr{Void},in::RawOrBoxedHandle,out::RawOrBoxedHandle,err::RawOrBoxedHandle) + if(!isa(in,AsyncStream)) + in=null_handle + end + if(!isa(out,AsyncStream)) + out=null_handle end - for cmd in pipeline - cmd.pipeline = pipeline + if(!isa(err,AsyncStream)) + err=null_handle end + new(cmd,handle,in,out,err,-2,-2,false,WaitTask[],false,WaitTask[]) + end +end + +type ProcessChain + processes::Vector{Process} + in::UVStream + out::UVStream + err::UVStream + ProcessChain(stdios::StdIOSet) = new(Process[],stdios[1],stdios[2],stdios[3]) +end +typealias ProcessChainOrNot Union(Bool,ProcessChain) + +#SpawnNullStream is Singleton +type SpawnNullStream <: AsyncStream end +const null_handle = SpawnNullStream() +SpawnNullStream() = null_handle +copy(::SpawnNullStream) = null_handle +uvhandle(::SpawnNullStream) = C_NULL +uvhandle(x::Ptr) = x +uvtype(::Ptr) = UV_STREAM + +function _jl_spawn(cmd::Ptr{Uint8}, argv::Ptr{Ptr{Uint8}}, loop::Ptr{Void}, pp::Process, + in, out, err) + proc = c_malloc(ccall(:jl_sizeof_uv_process_t,Int64,())) + error = ccall(:jl_spawn, Int32, + (Ptr{Uint8}, Ptr{Ptr{Uint8}}, Ptr{Void}, Ptr{Void}, Any, Int32, + Ptr{Void}, Int32, Ptr{Void}, Int32, Ptr{Void}), + cmd, argv, loop, proc, pp, uvtype(in), + uvhandle(in), uvtype(out), uvhandle(out), uvtype(err), uvhandle(err)) + if(error != 0) + c_free(proc) + throw(UVError("spawn")) + end + return proc +end + +function _uv_hook_return_spawn(proc::Process, exit_status::Int32, term_signal::Int32) + proc.exit_code = exit_status + proc.term_signal = term_signal + if isa(proc.exitcb, Function) proc.exitcb(proc, exit_status, term_signal) end + ccall(:jl_close_uv,Void,(Ptr{Void},),proc.handle) + tasknotify(proc.exitnotify, proc) +end + +function _uv_hook_close(proc::Process) + proc.handle = 0 + if isa(proc.closecb, Function) proc.closecb(proc) end + tasknotify(proc.closenotify, proc) +end + +function spawn(pc::ProcessChainOrNot,cmd::Cmd,stdios::StdIOSet,exitcb::Callback,closecb::Callback) + loop = eventloop() + close_in,close_out,close_err = false,false,false + pp = Process(cmd,C_NULL,stdios[1],stdios[2],stdios[3]); + in,out,err=stdios + if(isa(stdios[1],NamedPipe)&&stdios[1].handle==C_NULL) + in = box(Ptr{Void},Intrinsics.jl_alloca(unbox(Int32,_sizeof_uv_pipe))) + #in = c_malloc(_sizeof_uv_pipe) + link_pipe(in,false,stdios[1],true) + close_in = true + end + if(isa(stdios[2],NamedPipe)&&stdios[2].handle==C_NULL) + out = box(Ptr{Void},Intrinsics.jl_alloca(unbox(Int32,_sizeof_uv_pipe))) + #out = c_malloc(_sizeof_uv_pipe) + link_pipe(stdios[2],false,out,true) + close_out = true + end + if(isa(stdios[3],NamedPipe)&&stdios[3].handle==C_NULL) + err = box(Ptr{Void},Intrinsics.jl_alloca(unbox(Int32,_sizeof_uv_pipe))) + #err = c_malloc(_sizof_uv_pipe) + link_pipe(stdios[3],false,err,true) + close_err = true + end + ptrs = _jl_pre_exec(cmd.exec) + pp.exitcb = exitcb + pp.closecb = closecb + pp.handle = _jl_spawn(ptrs[1], convert(Ptr{Ptr{Uint8}}, ptrs), loop, pp, + in,out,err) + if pc != false + push!(pc.processes, pp) + end + if(close_in) + close_pipe_sync(in) + #c_free(in) + end + if(close_out) + close_pipe_sync(out) + #c_free(out) + end + if(close_err) + close_pipe_sync(err) + #c_free(err) + end + pp +end + +function spawn(pc::ProcessChainOrNot,redirect::CmdRedirect,stdios::StdIOSet,exitcb::Callback,closecb::Callback) + spawn(pc,redirect.cmd,(redirect.stream_no==STDIN_NO ?redirect.handle:stdios[1], + redirect.stream_no==STDOUT_NO?redirect.handle:stdios[2], + redirect.stream_no==STDERR_NO?redirect.handle:stdios[3]),exitcb,closecb) +end + +function spawn(pc::ProcessChainOrNot,cmds::OrCmds,stdios::StdIOSet,exitcb::Callback,closecb::Callback) + out_pipe = box(Ptr{Void},Intrinsics.jl_alloca(unbox(Int32,_sizeof_uv_pipe))) + in_pipe = box(Ptr{Void},Intrinsics.jl_alloca(unbox(Int32,_sizeof_uv_pipe))) + #out_pipe = c_malloc(_sizeof_uv_pipe) + #in_pipe = c_malloc(_sizeof_uv_pipe) + link_pipe(in_pipe,false,out_pipe,false,null_handle) + if pc == false + pc = ProcessChain(stdios) end -end - -function read_from(ports::Ports) - merge(cmds(ports)) - other(connect(ports, pipe_in(make_pipe()))) -end - -function write_to(ports::Ports) - merge(cmds(ports)) - other(connect(ports, pipe_out(make_pipe()))) -end - -read_from(cmds::Cmds) = read_from(stdout(cmds)) -write_to(cmds::Cmds) = write_to(stdin(cmds)) - -function (|)(src::Port, dst::Port) - if has(dst.cmd.pipes, dst.fd) - connect(src, pipe_in(dst.cmd.pipes[dst.fd])) - elseif has(src.cmd.pipes, src.fd) - connect(dst, pipe_out(src.cmd.pipes[src.fd])) - else - p = make_pipe() - connect(src, pipe_in(p)) - connect(dst, pipe_out(p)) + try + spawn(pc, cmds.a, (stdios[1], out_pipe, stdios[3]), exitcb, closecb) + spawn(pc, cmds.b, (in_pipe, stdios[2], stdios[3]), exitcb, closecb) + catch err + close_pipe_sync(out_pipe) + close_pipe_sync(in_pipe) + rethrow(err) + end + close_pipe_sync(out_pipe) + close_pipe_sync(in_pipe) + pc +end + +function spawn(pc::ProcessChainOrNot,cmds::AndCmds,stdios::StdIOSet,exitcb::Callback,closecb::Callback) + if pc == false + pc = ProcessChain(stdios) + end + close_in,close_out,close_err = false,false,false + in,out,err = stdios + if(isa(stdios[1],NamedPipe)&&stdios[1].handle==C_NULL) + in = box(Ptr{Void},Intrinsics.jl_alloca(unbox(Int32,_sizeof_uv_pipe))) + #in = c_malloc(_sizeof_uv_pipe) + link_pipe(in,false,stdios[1],true) + close_in = true + end + if(isa(stdios[2],NamedPipe)&&stdios[2].handle==C_NULL) + out = box(Ptr{Void},Intrinsics.jl_alloca(unbox(Int32,_sizeof_uv_pipe))) + #out = c_malloc(_sizeof_uv_pipe) + link_pipe(stdios[2],false,out,true) + close_out = true + end + if(isa(stdios[3],NamedPipe)&&stdios[3].handle==C_NULL) + err = box(Ptr{Void},Intrinsics.jl_alloca(unbox(Int32,_sizeof_uv_pipe))) + #err = c_malloc(_sizof_uv_pipe) + link_pipe(stdios[3],false,err,true) + close_err = true + end + spawn(pc, cmds.a, (in,out,err), exitcb, closecb) + spawn(pc, cmds.b, (in,out,err), exitcb, closecb) + if(close_in) + close_pipe_sync(in) + #c_free(in) + end + if(close_out) + close_pipe_sync(out) + #c_free(out) end - merge(src.cmd & dst.cmd) -end - -(|)(src::Port, dsts::Ports) = for dst = dsts; src | dst; end -(|)(srcs::Ports, dst::Port) = for src = srcs; src | dst; end -(|)(srcs::Ports, dsts::Ports) = for src = srcs, dst = dsts; src | dst; end - -(|)(src::Cmds, dst::Ports) = stdout(src) | dst -(|)(src::Ports, dst::Cmds) = (src | stdin(dst); dst) -(|)(src::Cmds, dst::Cmds) = (stdout(src) | stdin(dst); src & dst) - -redir(port::Port, sink::FileSink) = port.cmd.sinks[port.fd] = sink -function redir(ports::Ports, sink::FileSink) - for port in ports - redir(port, sink) + if(close_err) + close_pipe_sync(err) + #c_free(err) end + pp + pc end -# redirect stdout -function (>)(src::String, dst::Cmds) - redir(stdin(dst), FileSink(src, "r")) - return dst -end - -(<)(dst::Cmds, src::String) = (>)(src, dst) - -function (>)(src::IOStream, dst::Cmds) - redir(stdin(dst), FileSink(src)) - return dst -end - -(<)(dst::Cmds, src::IOStream) = (>)(src, dst) - -function (>)(src::Cmds, dst::String) - redir(stdout(src), FileSink(dst, "w")) - return src -end - -function (>>)(src::Cmds, dst::String) - redir(stdout(src), FileSink(dst, "a")) - return src -end - -(<)(dst::String, src::Cmds) = (>)(src, dst) -(<<)(dst::String, src::Cmds) = (>>)(src, dst) - -function (>)(src::Cmds, dst::IOStream) - redir(stdout(src), FileSink(dst)) - return src +function reinit_stdio() + STDIN.handle = ccall(:jl_stdin_stream ,Ptr{Void},()) + STDOUT.handle = ccall(:jl_stdout_stream,Ptr{Void},()) + STDERR.handle = ccall(:jl_stderr_stream,Ptr{Void},()) + STDIN.buffer = PipeBuffer() + STDOUT.buffer = PipeBuffer() + STDERR.buffer = PipeBuffer() + for stream in (STDIN,STDOUT,STDERR) + ccall(:jl_uv_associate_julia_struct,Void,(Ptr{Void},Any),stream.handle,stream) + end end -(<)(dst::IOStream, src::Cmds) = (>)(src, dst) +# INTERNAL +# returns a tuple of function arguments to spawn: +# (stdios, exitcb, closecb) +# | | \ The function to be called once the uv handle is closed +# | \ The function to be called once the process exits +# \ A set of up to 256 stdio instructions, where each entry can be either: +# | - An AsyncStream to be passed to the child +# | - true: This will let the child inherit the parents' io (only valid for 0-2) +# \ - false: None (for 3-255) or /dev/null (for 0-2) -# redirect stderr -function (.>)(src::Cmds, dst::String) - redir(stderr(src), FileSink(dst, "w")) - return src -end -function (.>>)(src::Cmds, dst::String) - redir(stderr(src), FileSink(dst, "a")) - return src +for (sym, stdin, stdout, stderr) in {(:spawn_opts_inherit, STDIN,STDOUT,STDERR), + (:spawn_opts_swallow, null_handle,null_handle,null_handle)} +@eval begin + ($sym)(stdios::StdIOSet,exitcb::Callback,closecb::Callback) = (stdios,exitcb,closecb) + ($sym)(stdios::StdIOSet,exitcb::Callback) = (stdios,exitcb,false) + ($sym)(stdios::StdIOSet) = (stdios,false,false) + ($sym)() = (($stdin,$stdout,$stderr),false,false) + ($sym)(in::UVStream) = ((isa(in,AsyncStream)?in:$stdin,$stdout,$stderr),false,false) + ($sym)(in::UVStream,out::UVStream) = ((isa(in,AsyncStream)?in:$stdin,isa(out,AsyncStream)?out:$stdout,$stderr),false,false) + ($sym)(in::UVStream,out::UVStream,err::UVStream) = ((isa(in,AsyncStream)?in:$stdin,isa(out,AsyncStream)?out:$stdout,isa(err,AsyncStream)?err:$stderr),false,false) end - -(.<)(dst::String, src::Cmds) = (.>)(src, dst) -(.<<)(dst::String, src::Cmds) = (.>>)(src, dst) - -function (.>)(src::Cmds, dst::IOStream) - redir(stderr(src), FileSink(dst)) - return src end -(.<)(dst::IOStream, src::Cmds) = (.>)(src, dst) +spawn(pc::ProcessChainOrNot,cmds::AbstractCmd,args...) = spawn(pc,cmds,spawn_opts_swallow(args...)...) +spawn(cmds::AbstractCmd,args...) = spawn(false,cmds,spawn_opts_swallow(args...)...) -# redirect both stdout and stderr -function (&>)(src::Cmds, dst::String) - redir(output(src), FileSink(dst, "w")) - return src -end +spawn_nostdin(pc::ProcessChainOrNot,cmd::AbstractCmd,out::UVStream) = spawn(pc,cmd,(null_handle,out,null_handle),false,false) +spawn_nostdin(cmd::AbstractCmd,out::UVStream) = spawn(false,cmd,(null_handle,out,null_handle),false,false) -function (&>>)(src::Cmds, dst::String) - redir(output(src), FileSink(dst, "a")) - return src +#returns a pipe to read from the last command in the pipelines +readsfrom(cmds::AbstractCmd) = readsfrom(cmds, null_handle) +function readsfrom(cmds::AbstractCmd, stdin::AsyncStream) + out = NamedPipe() + processes = spawn(false, cmds, (stdin,out,STDERR)) + start_reading(out) + (out, processes) end -(&<)(dst::String, src::Cmds) = (&>)(src, dst) -(&<<)(dst::String, src::Cmds) = (&>>)(src, dst) - -function (&>)(src::Cmds, dst::IOStream) - redir(output(src), FileSink(dst)) - return src +writesto(cmds::AbstractCmd) = writesto(cmds, null_handle) +function writesto(cmds::AbstractCmd, stdout::UVStream) + in = NamedPipe() + processes = spawn(false, cmds, (in,stdout,null_handle)) + (in, processes) end -(&<)(dst::IOStream, src::Cmds) = (&>)(src, dst) - -# here-strings: -function (>>>)(src::String, dst::Cmds) - hscmd = Cmd(()->print(src)) - push(hscmd.closed_fds, STDIN) - push(hscmd.closed_fds, STDERR) - hscmd.name = "here-string<" * src * ">" - return hscmd | dst +function readandwrite(cmds::AbstractCmd) + in = NamedPipe() + (out, processes) = readsfrom(cmds, in) + return (out, in, processes) end -#(<<<)(dst::Cmds, src::String) = (>>>)(src, dst) - - -# spawn(cmd) starts all processes connected to cmd - -function spawn(cmd::Cmd) - fds = Set{FileDes}() - fds_ = Set{FileDes}() - for c in cmd.pipeline - if !isa(cmd.status,ProcessNotRun) - if isa(cmd.status,ProcessRunning) - error("already running: ", c) - else - error("already run: ", c) - end - end - for (f,p) in c.pipes - add(fds, fd(p)) - add(fds, other(p)) - add(fds_, fd(p)) - end +readall(cmd::AbstractCmd) = readall(cmd, null_handle) +function readall(cmd::AbstractCmd,stdin::AsyncStream) + (out,pc) = readsfrom(cmd, stdin) + if !wait_success(pc) + pipeline_error(pc) end - gc_disable() - for c = cmd.pipeline - # minimize work after fork, in particular no writing - c.status = ProcessRunning() - ptrs = isa(c.exec,Vector{ByteString}) ? _jl_pre_exec(c.exec) : nothing - dup2_fds = Array(Int32, 2*numel(c.pipes)) - dup2_sinks = Array(Int32, 2*numel(c.sinks)) - close_fds_ = copy(fds) - i = 0 - for (f,p) in c.pipes - dup2_fds[i+=1] = fd(p).fd - dup2_fds[i+=1] = f.fd - del(close_fds_, fd(p)) - end - i = 0 - for (f,s) in c.sinks - dup2_sinks[i+=1] = fd(s) - dup2_sinks[i+=1] = f.fd - end - close_fds = Array(Int32, numel(close_fds_)) - i = 0 - for f in close_fds_ - close_fds[i+=1] = f.fd - end - - # save the stderr descriptor because it may be redirected, but we may need to - # print errors from Julia - bk_stderr_fd = ccall(:dup, Int32, (Int32,), STDERR.fd) - if bk_stderr_fd == -1 - println(stderr_stream, "dup: ", strerror()) - exit(0x7f) - end - bk_stderr_stream = fdio(bk_stderr_fd, true) - - # now actually do the fork and exec without writes - pid = fork() - if pid == 0 - ccall(:setpgid, Int32, (Int32,Int32), 0, 0) - i = 1 - n = length(dup2_fds) - while i <= n - # dup2 manually inlined to avoid potential heap stomping - r = ccall(:dup2, Int32, (Int32, Int32), dup2_fds[i], dup2_fds[i+1]) - if r == -1 - println(bk_stderr_stream, "dup2: ", strerror()) - _exit(0x7f) - end - i += 2 - end - i = 1 - n = length(dup2_sinks) - while i <= n - # dup2 manually inlined to avoid potential heap stomping - r = ccall(:dup2, Int32, (Int32, Int32), dup2_sinks[i], dup2_sinks[i+1]) - if r == -1 - println(bk_stderr_stream, "dup2: ", strerror()) - _exit(0x7f) - end - i += 2 - end - i = 1 - n = length(close_fds) - while i <= n - # close manually inlined to avoid potential heap stomping - r = ccall(:close, Int32, (Int32,), close_fds[i]) - if r != 0 - println(bk_stderr_stream, "close: ", strerror()) - _exit(0x7f) - end - i += 1 - end - if !isequal(ptrs, nothing) - ccall(:execvp, Int32, (Ptr{Uint8}, Ptr{Ptr{Uint8}}), ptrs[1], ptrs) - println(bk_stderr_stream, "exec: ", strerror()) - _exit(0x7f) - end - # other ways of execing (e.g. a julia function) - gc_enable() - c.pid = pid - try - exec(c) - catch err - show(bk_stderr_stream, err) - _exit(0x7f) - end - error("exec should not return but has") - end - c.pid = pid - ccall(:setpgid, Int32, (Int32,Int32), pid, pid) - close(bk_stderr_stream) # do it manually since gc is disabled - end - for f in fds_ - close(f) - end - gc_enable() + wait_close(out) + return takebuf_string(out.buffer) end -# spawn(cmds) starts all pipelines of a set of commands -# they may not be connected, e.g.: `foo` & `bar` - -function spawn(cmds::Cmds) - for cmd in cmds - if isa(cmd.status,ProcessNotRun) - spawn(cmd) - end +writeall(cmd::AbstractCmd, stdin::String) = writeall(cmd, stdin, null_handle) +function writeall(cmd::AbstractCmd, stdin::String, stdout::AsyncStream) + (in,pc) = writesto(cmd, stdout) + write(in, stdin) + close(in) + if !wait_success(pc) + pipeline_error(pc) end + return true end -# wait for a single command process to finish - -successful(cmd::Cmd) = - isa(cmd.status,ProcessRunning) || cmd.successful(cmd.status) - -wait(cmd::Cmd, nohang::Bool) = - (cmd.status = process_status(wait(cmd.pid,nohang)); close_sinks(cmd); successful(cmd)) +function run(cmds::AbstractCmd,args...) + ps = spawn(cmds,spawn_opts_inherit(args...)...) + wait_success(ps) ? nothing : pipeline_error(ps) +end -# wait for a set of command processes to finish +success(proc::Process) = (assert(process_exited(proc)); proc.exit_code==0) +success(procs::Vector{Process}) = all(map(success, procs)) +success(procs::ProcessChain) = success(procs.processes) +success(cmd::AbstractCmd) = wait_success(spawn(cmd)) -function wait(cmds::Cmds, nohang::Bool) - success = true - for cmd in cmds - success &= wait(cmd, nohang) +function pipeline_error(proc::Process) + if !proc.cmd.ignorestatus + error("failed process: ",proc," [",proc.exit_code,"]") end - success + nothing end -# report what went wrong with a pipeline - -pipeline_error(cmd::Cmd) = error("failed process: ",cmd," [",cmd.status,"]") -function pipeline_error(cmds::Cmds) - failed = Cmd[] - for cmd in cmds - if !successful(cmd) - push(failed, cmd) +function pipeline_error(procs::ProcessChain) + failed = Process[] + for p = procs.processes + if !success(p) && !p.cmd.ignorestatus + push!(failed, p) end end - if numel(failed)==0 error("WTF: pipeline error but no processes failed!?") end - if numel(failed)==1 pipeline_error(failed[1]) end + if length(failed)==0 return nothing end + if length(failed)==1 pipeline_error(failed[1]) end msg = "failed processes:" - for cmd in failed - msg = string(msg,"\n ",cmd," [",cmd.status,"]") + for proc in failed + msg = string(msg,"\n ",proc," [",proc.exit_code,"]") end error(msg) end -# spawn and wait for a set of commands - -success(cmds::Cmds) = (spawn(cmds); wait(cmds)) -run(cmds::Cmds) = success(cmds) ? nothing : pipeline_error(cmds) - -# run some commands and read all output - -function _readall(ports::Ports, cmds::Cmds) - r = read_from(ports) - spawn(cmds) - o = readall(fdio(r.fd, false)) - if !wait(cmds) - close(r) - pipeline_error(cmds) +_jl_kill(p::Process,signum::Integer) = ccall(:uv_process_kill,Int32,(Ptr{Void},Int32),p.handle,signum) +function kill(p::Process,signum::Integer) + if process_running(p) + _jl_kill(p, signum) + else + int32(-1) end - close(r) - return o end +kill(ps::Vector{Process}) = map(kill, ps) +kill(ps::ProcessChain) = map(kill, ps.processes) +kill(p::Process) = kill(p,15) #SIGTERM -readall(ports::Ports) = _readall(ports, cmds(ports)) -readall(cmds::Cmds) = _readall(stdout(cmds), cmds) - -function _each_line(ports::Ports, cmds::Cmds) - r = read_from(ports) - spawn(cmds) - fh = fdio(r.fd, true) - EachLine(fh) +function _contains_newline(bufptr::Ptr{Void},len::Int32) + return (ccall(:memchr,Ptr{Uint8},(Ptr{Void},Int32,Uint),bufptr,'\n',len)!=C_NULL) end -each_line(ports::Ports) = _each_line(ports, cmds(ports)) -each_line(cmds::Cmds) = _each_line(stdout(cmds), cmds) +## process status ## +process_running(s::Process) = s.exit_code == -2 +process_running(s::Vector{Process}) = all(map(process_running,s)) +process_running(s::ProcessChain) = process_running(s.processes) + +process_exit_status(s::Process) = s.exit_code +process_exited(s::Process) = !process_running(s) +process_exited(s::Vector{Process}) = all(map(process_exited,s)) +process_exited(s::ProcessChain) = process_running(s.processes) + +process_term_signal(s::Process) = s.term_signal +process_signaled(s::Process) = (s.term_signal > 0) + +#process_stopped (s::Process) = false #not supported by libuv. Do we need this? +#process_stop_signal(s::Process) = false #not supported by libuv. Do we need this? + +function process_status(s::Process) + process_running (s) ? "ProcessRunning" : + process_signaled(s) ? "ProcessSignaled("*string(process_term_signal(s))*")" : + #process_stopped (s) ? "ProcessStopped("*string(process_stop_signal(s))*")" : + process_exited (s) ? "ProcessExited("*string(process_exit_status(s))*")" : + error("process status error") +end -cmd_stdin_stream (cmds::Cmds) = fdio(write_to(cmds).fd) -cmd_stdout_stream(cmds::Cmds) = fdio(read_from(cmds).fd) +# WARNING: do not call this and keep the returned array of pointers +# around longer than the args vector and then use array of pointers. +# this could cause a segfault. this is really just for use by the +# spawn function below so that we can exec more efficiently. +# +function _jl_pre_exec(args::Vector{ByteString}) + if length(args) < 1 + error("exec: too few words to exec") + end + ptrs = Array(Ptr{Uint8}, length(args)+1) + for i = 1:length(args) + ptrs[i] = args[i].data + end + ptrs[length(args)+1] = C_NULL + return ptrs +end ## implementation of `cmd` syntax ## @@ -699,7 +478,7 @@ function arg_gen(head) if applicable(start,head) vals = ByteString[] for x in head - push(vals,string(x)) + push!(vals,string(x)) end return vals else @@ -711,8 +490,8 @@ function arg_gen(head, tail...) head = arg_gen(head) tail = arg_gen(tail...) vals = ByteString[] - for h in head, t in tail - push(vals,bytestring(strcat(h,t))) + for h = head, t = tail + push!(vals,bytestring(h,t)) end vals end @@ -726,5 +505,25 @@ function cmd_gen(parsed) end macro cmd(str) - :(cmd_gen($(_jl_shell_parse(str)))) + :(cmd_gen($(shell_parse(str)))) end + +# Filters +wait_exit_filter(p::Process, args...) = !process_exited(p) +wait_close_filter(w::Union(AsyncStream,Process), args...) = w.open + +wait_exit(x::Union(Process,Vector)) = wait(x, :closenotify, wait_exit_filter) +wait_close(x) = wait(x, :closenotify, wait_close_filter) + +wait_exit(x::ProcessChain) = wait_exit(x.processes) +function wait_read(x::AsyncStream) + wait(x, :readnotify, false) +end +wait_success(x::ProcessChain) = wait_success(x.processes) +function wait_success(x::Union(Process,Vector{Process})) + wait_exit(x) + kill(x) + success(x) +end + +show(io::IO, p::Process) = print(io, "Process(", p.cmd, ", ", process_status(p), ")") diff --git a/base/promotion.jl b/base/promotion.jl index 9e9e8272b1110..1db4e4438ccbd 100644 --- a/base/promotion.jl +++ b/base/promotion.jl @@ -1,11 +1,106 @@ +## type join (closest common ancestor, or least upper bound) ## + +typejoin() = None +typejoin(t::ANY) = t +typejoin(t::ANY, ts...) = typejoin(t, typejoin(ts...)) +function typejoin(a::ANY, b::ANY) + if isa(a,TypeConstructor); a = a.body; end + if isa(b,TypeConstructor); b = b.body; end + if a <: b + return b + elseif b <: a + return a + end + if isa(a,TypeVar) + return typejoin(a.ub, b) + end + if isa(b,TypeVar) + return typejoin(a, b.ub) + end + if isa(a,UnionType) || isa(b,UnionType) + u = Union(a, b) + if !isa(u,UnionType) + return u + end + return reduce(typejoin, None, u.types) + end + if isa(a,Tuple) + if !isa(b,Tuple) + return Any + end + la = length(a)::Int; lb = length(b)::Int + if la==0 || lb==0 + return Tuple + end + if la < lb + if isvarargtype(a[la]) + c = cell(la) + c[la] = Vararg{typejoin(a[la].parameters[1], tailjoin(b,la))} + n = la-1 + else + c = cell(la+1) + c[la+1] = Vararg{tailjoin(b,la+1)} + n = la + end + elseif lb < la + if isvarargtype(b[lb]) + c = cell(lb) + c[lb] = Vararg{typejoin(b[lb].parameters[1], tailjoin(a,lb))} + n = lb-1 + else + c = cell(lb+1) + c[lb+1] = Vararg{tailjoin(a,lb+1)} + n = lb + end + else + c = cell(la) + n = la + end + for i=1:n + ai = a[i]; bi = b[i] + va = false + if isvarargtype(ai); va=true; ai = ai.parameters[1]; end + if isvarargtype(bi); va=true; bi = bi.parameters[1]; end + t = typejoin(ai,bi) + c[i] = va ? Vararg{t} : t + end + return tuple(c...) + elseif isa(b,Tuple) + return Any + end + while !is(b,Any) + if a <: b + return b + end + if a <: b.name.primary + return b.name.primary + end + b = super(b) + end + return Any +end + +# reduce typejoin over tup[i:end] +function tailjoin(tup, i) + t = None + for j = i:length(tup) + tj = tup[j] + t = typejoin(t, isvarargtype(tj)?tj.parameters[1]:tj) + end + return t +end + ## promotion mechanism ## -promote_type{T}(::Type{T}) = T +promote_type() = None +promote_type(T) = T +promote_type(T, S ) = typejoin(T, S) +promote_type(T, S...) = promote_type(T, promote_type(S...)) + promote_type(::Type{None}, ::Type{None}) = None promote_type{T}(::Type{T}, ::Type{T}) = T promote_type{T}(::Type{T}, ::Type{None}) = T promote_type{T}(::Type{None}, ::Type{T}) = T -promote_type(S::Type, T::Type...) = promote_type(S, promote_type(T...)) function promote_type{T,S}(::Type{T}, ::Type{S}) if applicable(promote_rule, T, S) @@ -13,7 +108,7 @@ function promote_type{T,S}(::Type{T}, ::Type{S}) elseif applicable(promote_rule, S, T) return promote_rule(S,T) else - error("no promotion exists for ",T," and ",S) + return typejoin(T,S) end end diff --git a/base/random.jl b/base/random.jl new file mode 100644 index 0000000000000..b6b440ebe8823 --- /dev/null +++ b/base/random.jl @@ -0,0 +1,196 @@ +module Random + +using Base.LibRandom + +export librandom_init, srand, + rand, rand!, + randn, randn!, + randbool, randbool!, + AbstractRNG, RNG, MersenneTwister + +abstract AbstractRNG + +type MersenneTwister <: AbstractRNG + state::DSFMT_state + seed::Union(Uint32,Vector{Uint32}) + len::Int # Use for iteration. Set to -1 otherwise. + + function MersenneTwister() + seed = uint32(0) + state = DSFMT_state() + dsfmt_init_gen_rand(state, seed) + return new(state, seed, -1) + end + + MersenneTwister(seed) = MersenneTwister(seed, -1) + + function MersenneTwister(seed::Uint32, len::Int) + state = DSFMT_state() + dsfmt_init_gen_rand(state, seed) + return new(state, seed, len) + end + + function MersenneTwister(seed::Vector{Uint32}, len::Int) + state = DSFMT_state() + dsfmt_init_by_array(state, seed) + return new(state, seed, len) + end +end + +function srand(r::MersenneTwister, seed) + r.seed = seed + dsfmt_init_gen_rand(r.state, seed) + return r +end + +## initialization + +function librandom_init() + +@unix_only begin + try + srand("/dev/urandom") + catch + println(STDERR, "Entropy pool not available to seed RNG, using ad-hoc entropy sources.") + seed = reinterpret(Uint64, time()) + seed = bitmix(seed, uint64(getpid())) + try + seed = bitmix(seed, parseint(Uint64, readall(`ifconfig`|`sha1sum`)[1:40], 16)) + catch + # ignore + end + srand(seed) + end +end + +@windows_only begin + a = zeros(Uint32, 2) + win32_SystemFunction036!(a) + srand(a) +end + randmtzig_create_ziggurat_tables() +end + +## srand() + +function srand(seed::Vector{Uint32}) + global RANDOM_SEED = seed + dsfmt_gv_init_by_array(seed) +end +srand(n::Integer) = srand(make_seed(n)) + +function make_seed(n::Integer) + n < 0 && throw(DomainError()) + seed = Uint32[] + while true + push!(seed, n & 0xffffffff) + n2 = n >> 32 + if n2 == 0 || n2 == n + return seed + end + n = n2 + end +end + +function srand(filename::String, n::Integer) + open(filename) do io + a = Array(Uint32, int(n)) + read(io, a) + srand(a) + end +end +srand(filename::String) = srand(filename, 4) + +## rand() + +rand() = dsfmt_gv_genrand_close_open() +rand(r::MersenneTwister) = dsfmt_genrand_close_open(r.state) + +rand!(A::Array{Float64}) = dsfmt_gv_fill_array_close_open!(A) +rand(dims::Dims) = rand!(Array(Float64, dims)) +rand(dims::Int...) = rand!(Array(Float64, dims...)) + +rand!(r::MersenneTwister, A::Array{Float64}) = dsfmt_fill_array_close_open!(r.state, A) +rand(r::AbstractRNG, dims::Dims) = rand!(r, Array(Float64, dims)) +rand(r::AbstractRNG, dims::Int...) = rand(r, dims) + +## random integers + +dsfmt_randui32() = dsfmt_gv_genrand_uint32() +dsfmt_randui64() = uint64(dsfmt_randui32()) | (uint64(dsfmt_randui32())<<32) + +rand(::Type{Uint32}) = dsfmt_randui32() +rand(::Type{Uint64}) = dsfmt_randui64() +rand(::Type{Uint128}) = uint128(rand(Uint64))<<64 | rand(Uint64) + +rand(::Type{Int32}) = int32(rand(Uint32)) +rand(::Type{Int64}) = int64(rand(Uint64)) +rand(::Type{Int128}) = int128(rand(Uint128)) + +for itype in (:Uint32, :Uint64, :Uint128, :Int32, :Int64, :Int128) + @eval begin + function rand!(A::Array{$itype}) + for i=1:length(A) + A[i] = rand($itype) + end + A + end + rand(::Type{$itype}, dims::Dims) = rand!(Array($itype, dims)) + rand(::Type{$itype}, dims::Int...) = rand($itype, dims) + end +end + +# random integer from lo to hi inclusive +function rand{T<:Integer}(r::Range1{T}) + lo = r[1] + hi = r[end] + + m = typemax(T) + s = abs(rand(T)) + if (hi-lo == m) + return s + lo + end + r = hi-lo+1 + if (r&(r-1))==0 + # power of 2 range + return s&(r-1) + lo + end + # note: m>=0 && r>=0 + lim = m - rem(rem(m,r)+1, r) + while s > lim + s = rand(T) + end + return rem(s,r) + lo +end + +function rand!{T<:Integer}(r::Range1{T}, A::Array{T}) + for i=1:length(A) + A[i] = rand(r) + end + return A +end + +rand{T<:Integer}(r::Range1{T}, dims::Dims) = rand!(r, Array(T, dims)) +rand{T<:Integer}(r::Range1{T}, dims::Int...) = rand(r, dims) + +## random Bools + +rand!(B::BitArray) = Base.bitarray_rand_fill!(B) + +randbool(dims::Dims) = rand!(BitArray(dims)) +randbool(dims::Int...) = rand!(BitArray(dims)) + +randbool() = ((dsfmt_randui32() & 1) == 1) +randbool!(B::BitArray) = rand!(B) + +## randn() - Normally distributed random numbers using Ziggurat algorithm + +# The Ziggurat Method for generating random variables - Marsaglia and Tsang +# Paper and reference code: http://www.jstatsoft.org/v05/i08/ + +randn() = randmtzig_randn() +randn!(A::Array{Float64}) = randmtzig_fill_randn!(A) +randn(dims::Dims) = randn!(Array(Float64, dims)) +randn(dims::Int...) = randn!(Array(Float64, dims...)) + +end # module diff --git a/base/range.jl b/base/range.jl index a2663d078d6ca..0711d8385c7be 100644 --- a/base/range.jl +++ b/base/range.jl @@ -2,9 +2,9 @@ typealias Dims (Int...) -abstract Ranges{T<:Real} <: AbstractArray{T,1} +abstract Ranges{T} <: AbstractArray{T,1} -type Range{T<:Real} <: Ranges{T} +immutable Range{T<:Real} <: Ranges{T} start::T step::T len::Int @@ -20,7 +20,7 @@ type Range{T<:Real} <: Ranges{T} end Range{T}(start::T, step, len::Integer) = Range{T}(start, step, len) -type Range1{T<:Real} <: Ranges{T} +immutable Range1{T<:Real} <: Ranges{T} start::T len::Int @@ -38,18 +38,40 @@ colon{T<:Integer}(start::T, stop::T) = Range1(start, max(0, stop-start+1)) function colon{T<:Real}(start::T, step::T, stop::T) - len = (stop-start)/step - if len >= typemax(Int) - error("Range: length ",len," is too large") + if (step<0) != (stop= typemax(Int) + error("Range: length ",n," is too large") + end end - Range(start, step, max(0, ifloor(len)+1)) + Range(start, step, len) end function colon{T<:Real}(start::T, stop::T) - len = stop-start - if len >= typemax(Int) - error("Range: length ",len," is too large") + if stop < start + len = 0 + else + n = round(stop-start+1) + if n >= typemax(Int) + error("Range: length ",n," is too large") + end + len = itrunc(n) end - Range1(start, max(0, ifloor(len)+1)) + Range1(start, len) end colon(start::Real, step::Real, stop::Real) = colon(promote(start, step, stop)...) @@ -58,48 +80,43 @@ colon(start::Real, stop::Real) = colon(promote(start, stop)...) similar(r::Ranges, T::Type, dims::Dims) = Array(T, dims) length(r::Ranges) = r.len -const numel = length size(r::Ranges) = (r.len,) isempty(r::Ranges) = r.len==0 first(r::Ranges) = r.start -last{T}(r::Range{T}) = r.start + oftype(T,r.len-1)*step(r) -last{T}(r::Range1{T}) = r.start + oftype(T,r.len-1) +last{T}(r::Range1{T}) = oftype(T, r.start + r.len-1) +last{T}(r::Range{T}) = oftype(T, r.start + (r.len-1)*r.step) step(r::Range) = r.step step(r::Range1) = one(r.start) -min(r::Range1) = r.start -max(r::Range1) = last(r) -min(r::Range) = r.step > 0 ? r.start : last(r) -max(r::Range) = r.step > 0 ? last(r) : r.start +min(r::Range1) = (isempty(r)&&error("min: range is empty")) || first(r) +max(r::Range1) = (isempty(r)&&error("max: range is empty")) || last(r) +min(r::Ranges) = (isempty(r)&&error("min: range is empty")) || (step(r) > 0 ? first(r) : last(r)) +max(r::Ranges) = (isempty(r)&&error("max: range is empty")) || (step(r) > 0 ? last(r) : first(r)) # Ranges are intended to be immutable copy(r::Ranges) = r -function ref{T}(r::Range{T}, i::Integer) - if !(1 <= i <= r.len); error(BoundsError); end - r.start + oftype(T,i-1)*step(r) -end -function ref{T}(r::Range1{T}, i::Integer) +function getindex{T}(r::Ranges{T}, i::Integer) if !(1 <= i <= r.len); error(BoundsError); end - r.start + oftype(T,i-1) + oftype(T, r.start + (i-1)*step(r)) end -ref(r::Range, s::Range{Int}) = +getindex(r::Range, s::Range{Int}) = r.len < last(s) ? error(BoundsError) : Range(r[s.start], r.step*s.step, s.len) -ref(r::Range1, s::Range{Int}) = +getindex(r::Range1, s::Range{Int}) = r.len < last(s) ? error(BoundsError) : Range(r[s.start], s.step, s.len) -ref(r::Range, s::Range1{Int}) = +getindex(r::Range, s::Range1{Int}) = r.len < last(s) ? error(BoundsError) : Range(r[s.start], r.step, s.len) -ref(r::Range1, s::Range1{Int}) = +getindex(r::Range1, s::Range1{Int}) = r.len < last(s) ? error(BoundsError) : Range1(r[s.start], s.len) -show(io, r::Range) = print(io, r.start,':',r.step,':',last(r)) -show(io, r::Range1) = print(io, r.start,':',last(r)) +show(io::IO, r::Range) = print(io, repr(r.start),':',repr(step(r)),':',repr(last(r))) +show(io::IO, r::Range1) = print(io, repr(r.start),':',repr(last(r))) start(r::Ranges) = 0 -next(r::Range, i) = (r.start + oftype(r.start,i)*step(r), i+1) -next(r::Range1, i) = (r.start + oftype(r.start,i), i+1) +next{T}(r::Range{T}, i) = (oftype(T, r.start + i*step(r)), i+1) +next{T}(r::Range1{T}, i) = (oftype(T, r.start + i), i+1) done(r::Ranges, i) = (length(r) <= i) isequal(r::Ranges, s::Ranges) = (r.start==s.start) & (step(r)==step(s)) & (r.len==s.len) @@ -130,6 +147,25 @@ function intersect(r::Range1, s::Range) end intersect(r::Range, s::Range1) = intersect(s, r) +# findin (the index of intersection) +function findin(r::Ranges, span::Range1) + local ifirst + local ilast + fspan = first(span) + lspan = last(span) + fr = first(r) + lr = last(r) + sr = step(r) + if sr > 0 + ifirst = fr >= fspan ? 1 : iceil((fspan-fr)/sr)+1 + ilast = lr <= lspan ? length(r) : length(r) - iceil((lr-lspan)/sr) + else + ifirst = fr <= lspan ? 1 : iceil((lspan-fr)/sr)+1 + ilast = lr >= fspan ? length(r) : length(r) - iceil((lr-fspan)/sr) + end + ifirst:ilast +end + ## linear operations on ranges ## -(r::Ranges) = Range(-r.start, -step(r), r.len) @@ -172,7 +208,7 @@ function ./(r::Ranges, s::Ranges) [ r[i]/s[i] for i = 1:length(r) ] end -function .*(r::Ranges, s::Ranges) +function .*{T<:Number,S<:Number}(r::Ranges{T}, s::Ranges{S}) if length(r) != length(s) error("argument dimensions must match") end @@ -181,7 +217,7 @@ end .^(x::Number, r::Ranges) = [ x^y for y=r ] .^(r::Ranges, y::Number) = [ x^y for x=r ] -function .^(r::Ranges, s::Ranges) +function .^{T<:Number,S<:Number}(r::Ranges{T}, s::Ranges{S}) if length(r) != length(s) error("argument dimensions must match") end @@ -201,6 +237,8 @@ function vcat{T}(r::Ranges{T}) return a end +convert{T}(::Type{Array{T,1}}, r::Ranges{T}) = vcat(r) + function vcat{T}(rs::Ranges{T}...) n = sum(length,rs)::Int a = Array(T,n) @@ -219,23 +257,22 @@ reverse{T<:Real}(r::Ranges{T}) = Range(last(r), -step(r), r.len) ## sorting ## issorted(r::Range1) = true -issorted(r::Range) = r.step > 0 +issorted(r::Ranges) = step(r) > 0 sort(r::Range1) = r sort!(r::Range1) = r sort{T<:Real}(r::Range{T}) = issorted(r) ? r : reverse(r) -sortperm(r::Range1) = (r, 1:length(r)) -sortperm{T<:Real}(r::Range{T}) = issorted(r) ? (r, 1:1:length(r)) : - (reverse(r), length(r):-1:1) +sortperm(r::Range1) = 1:length(r) +sortperm{T<:Real}(r::Range{T}) = issorted(r) ? (1:1:length(r)) : (length(r):-1:1) -function sum(r::Ranges) +function sum{T<:Real}(r::Ranges{T}) l = length(r) return l * first(r) + step(r) * div(l * (l - 1), 2) end -function map_to(f, dest, r::Ranges) +function map!(f, dest, r::Ranges) i = 1 for ri in r dest[i] = f(ri); i+=1; end dest diff --git a/base/rational.jl b/base/rational.jl index a42e4aeecbdd4..3a135bd602817 100644 --- a/base/rational.jl +++ b/base/rational.jl @@ -1,4 +1,4 @@ -type Rational{T<:Integer} <: Real +immutable Rational{T<:Integer} <: Real num::T den::T @@ -27,7 +27,7 @@ function //(x::Complex, y::Complex) complex(real(xy)//yy, imag(xy)//yy) end -function show(io, x::Rational) +function show(io::IO, x::Rational) if isinf(x) print(io, x.num > 0 ? "Inf" : "-Inf") else @@ -64,6 +64,8 @@ function convert{T<:Integer}(::Type{Rational{T}}, x::FloatingPoint, tol::Real) return convert(T,a)//convert(T,b) end convert{T<:Integer}(rt::Type{Rational{T}}, x::FloatingPoint) = convert(rt,x,eps(one(x))) +convert(::Type{Rational}, x::FloatingPoint, tol::Real) = convert(Rational{Int},x,tol) +convert(::Type{Rational}, x::FloatingPoint) = convert(Rational{Int},x,eps(one(x))) convert(::Type{Bool}, x::Rational) = (x!=0) # to resolve ambiguity convert{T<:Rational}(::Type{T}, x::Rational) = x convert{T<:Real}(::Type{T}, x::Rational) = convert(T, x.num/x.den) @@ -142,16 +144,6 @@ floor(x::Rational) = Rational(ifloor(x)) ceil (x::Rational) = Rational(iceil(x)) round(x::Rational) = Rational(iround(x)) -rational(x::Real) = rational(x, 0) -rational(x::Rational, tol::Real) = x -rational(x::Integer) = x // one(x) -rational(x::Integer, tol::Real) = x // one(x) -rational(x::Float32, tol::Real) = convert(Rational{Int32}, x, tol) -rational(x::Float64, tol::Real) = convert(Rational{Int64}, x, tol) -rational(z::Complex) = complex(rational(real(z)), rational(imag(z))) -rational(z::Complex, tol::Real) = - (tol /= sqrt(2); complex(rational(real(z), tol), rational(imag(z), tol))) - ## rational to int coercion ## for f in (:int8, :int16, :int32, :int64, :int128, diff --git a/base/reduce.jl b/base/reduce.jl index 093742ce2e008..a479173df35e9 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -29,7 +29,7 @@ end function max(itr) s = start(itr) if done(itr, s) - return typemin(eltype(itr)) + error("max: argument is empty") end (v, s) = next(itr, s) while !done(itr, s) @@ -42,7 +42,7 @@ end function min(itr) s = start(itr) if done(itr, s) - return typemax(eltype(itr)) + error("min: argument is empty") end (v, s) = next(itr, s) while !done(itr, s) @@ -106,7 +106,7 @@ function reduce(op::Function, v0, itr) return v end -function mapreduce(op, f, itr) +function mapreduce(f, op, itr) s = start(itr) if done(itr, s) return op() # empty collection @@ -120,7 +120,7 @@ function mapreduce(op, f, itr) return v end -function mapreduce(op::Function, f::Function, v0, itr) +function mapreduce(f::Function, op::Function, v0, itr) v = v0 for x in itr v = op(v,f(x)) @@ -136,7 +136,7 @@ function any(itr) end return false end -any(args::Bool...) = any(args) + function all(itr) for x in itr if !x @@ -145,35 +145,13 @@ function all(itr) end return true end -all(args::Bool...) = all(args) - -max(f::Function, itr) = mapreduce(max, f, itr) -min(f::Function, itr) = mapreduce(min, f, itr) -sum(f::Function, itr) = mapreduce(+, f, itr) -prod(f::Function, itr) = mapreduce(*, f, itr) -any(f::Function, itr) = anyp(f, itr) -all(f::Function, itr) = allp(f, itr) -count(f::Function, itr) = countp(f, itr) - -function count(itr) - c = 0 - for x in itr - c += (x ? 1 : 0) - end - return c -end -function countp(pred, itr) - c = 0 - for x in itr - if pred(x) - c += 1 - end - end - return c -end +max(f::Function, itr) = mapreduce(f, max, itr) +min(f::Function, itr) = mapreduce(f, min, itr) +sum(f::Function, itr) = mapreduce(f, + , itr) +prod(f::Function, itr) = mapreduce(f, * , itr) -function anyp(pred, itr) +function any(pred::Function, itr) for x in itr if pred(x) return true @@ -182,7 +160,7 @@ function anyp(pred, itr) return false end -function allp(pred, itr) +function all(pred::Function, itr) for x in itr if !pred(x) return false @@ -200,9 +178,9 @@ function contains(itr, x) return false end -function contains_is(itr, x::ANY) +function contains(eq::Function, itr, x) for y in itr - if is(y,x) + if eq(y,x) return true end end diff --git a/base/regex.jl b/base/regex.jl index eabf2a0312724..6f15f31a73a24 100644 --- a/base/regex.jl +++ b/base/regex.jl @@ -2,35 +2,27 @@ include("pcre.jl") -type Regex +const DEFAULT_OPTS = PCRE.JAVASCRIPT_COMPAT | PCRE.UTF8 + +immutable Regex pattern::ByteString - options::Int32 + options::Uint32 regex::Array{Uint8} - extra::Ptr{Void} - function Regex(pat::String, opts::Integer, study::Bool) - pat = bytestring(pat); opts = int32(opts) - if (opts & ~PCRE.OPTIONS_MASK) != 0 - error("invalid regex option(s)") + function Regex(pattern::String, options::Integer) + pattern = bytestring(pattern) + options = uint32(options) + if (options & ~PCRE.OPTIONS_MASK) != 0 + error("invalid regex options: $options") end - re = PCRE.compile(pat, opts & PCRE.COMPILE_MASK) - ex = study ? PCRE.study(re) : C_NULL - new(pat, opts, re, ex) + regex = PCRE.compile(pattern, options & PCRE.COMPILE_MASK) + new(pattern, options, regex) end end -Regex(p::String, s::Bool) = Regex(p, 0, s) -Regex(p::String, o::Integer) = Regex(p, o, false) -Regex(p::String) = Regex(p, 0, false) - -copy(r::Regex) = r -# TODO: make sure thing are escaped in a way PCRE -# likes so that Julia all the Julia string quoting -# constructs are correctly handled. - -macro r_str(pattern, flags...) - options = PCRE.UTF8 - for fx in flags, f in fx +function Regex(pattern::String, flags::String) + options = DEFAULT_OPTS + for f in flags options |= f=='i' ? PCRE.CASELESS : f=='m' ? PCRE.MULTILINE : f=='s' ? PCRE.DOTALL : @@ -39,10 +31,15 @@ macro r_str(pattern, flags...) end Regex(pattern, options) end +Regex(pattern::String) = Regex(pattern, DEFAULT_OPTS) + +macro r_str(pattern, flags...) Regex(pattern, flags...) end -function show(io, re::Regex) +copy(r::Regex) = r + +function show(io::IO, re::Regex) imsx = PCRE.CASELESS|PCRE.MULTILINE|PCRE.DOTALL|PCRE.EXTENDED - if (re.options & ~imsx) == PCRE.UTF8 + if (re.options & ~imsx) == DEFAULT_OPTS print(io, 'r') print_quoted_literal(io, re.pattern) if (re.options & PCRE.CASELESS ) != 0; print(io, 'i'); end @@ -61,14 +58,14 @@ end # TODO: map offsets into non-ByteStrings back to original indices. # or maybe it's better to just fail since that would be quite slow -type RegexMatch +immutable RegexMatch match::ByteString captures::Vector{Union(Nothing,ByteString)} offset::Int offsets::Vector{Int} end -function show(io, m::RegexMatch) +function show(io::IO, m::RegexMatch) print(io, "RegexMatch(") show(io, m.match) if !isempty(m.captures) @@ -84,39 +81,38 @@ function show(io, m::RegexMatch) print(io, ")") end -ismatch(r::Regex, s::String, o::Integer) = - PCRE.exec(r.regex, r.extra, bytestring(s), 0, o, false) -ismatch(r::Regex, s::String) = ismatch(r, s, r.options & PCRE.EXECUTE_MASK) +# TODO: add ismatch with an offset. +ismatch(r::Regex, s::String) = + PCRE.exec(r.regex, C_NULL, bytestring(s), 0, r.options & PCRE.EXECUTE_MASK, false) -contains(s::String, r::Regex, opts::Integer) = ismatch(r,s,opts) -contains(s::String, r::Regex) = ismatch(r,s) - -function match(re::Regex, str::ByteString, idx::Integer, opts::Integer) - m, n = PCRE.exec(re.regex, re.extra, str, idx-1, opts, true) +function match(re::Regex, str::ByteString, idx::Integer) + opts = re.options & PCRE.EXECUTE_MASK + m, n = PCRE.exec(re.regex, C_NULL, str, idx-1, opts, true) if isempty(m); return nothing; end mat = str[m[1]+1:m[2]] cap = Union(Nothing,ByteString)[ m[2i+1] < 0 ? nothing : str[m[2i+1]+1:m[2i+2]] for i=1:n ] - off = [ m[2i+1]::Int32+1 for i=1:n ] + off = Int[ m[2i+1]::Int32+1 for i=1:n ] RegexMatch(mat, cap, m[1]+1, off) end -match(r::Regex, s::String, i::Integer, o::Integer) = match(r, bytestring(s), i, o) -match(r::Regex, s::String, i::Integer) = match(r, s, i, r.options & PCRE.EXECUTE_MASK) match(r::Regex, s::String) = match(r, s, start(s)) +match(r::Regex, s::String, i::Integer) = + error("regex matching is only available for bytestrings; use bytestring(s) to convert") function search(str::ByteString, re::Regex, idx::Integer) - len = length(str) + len = length(str.data) if idx >= len+2 - return idx == len+2 ? (0,0) : error(BoundsError) + return idx == len+2 ? (0:-1) : error(BoundsError) end opts = re.options & PCRE.EXECUTE_MASK - m, n = PCRE.exec(re.regex, re.extra, str, idx-1, opts, true) - isempty(m) ? (0,0) : (m[1]+1,m[2]+1) + m, n = PCRE.exec(re.regex, C_NULL, str, idx-1, opts, true) + isempty(m) ? (0:-1) : ((m[1]+1):m[2]) end -search(s::String, r::Regex, idx::Integer) = error("regex search is only available for bytestrings; use bytestring(s) to convert") +search(s::String, r::Regex, idx::Integer) = + error("regex search is only available for bytestrings; use bytestring(s) to convert") search(s::String, r::Regex) = search(s,r,start(s)) -type RegexMatchIterator +immutable RegexMatchIterator regex::Regex string::ByteString overlap::Bool @@ -127,8 +123,8 @@ done(itr::RegexMatchIterator, m) = m == nothing next(itr::RegexMatchIterator, m) = (m, match(itr.regex, itr.string, m.offset + (itr.overlap ? 1 : length(m.match)))) -each_match(re::Regex, str::String, ovr::Bool) = RegexMatchIterator(re,str,ovr) -each_match(re::Regex, str::String) = RegexMatchIterator(re,str,false) +eachmatch(re::Regex, str::String, ovr::Bool) = RegexMatchIterator(re,str,ovr) +eachmatch(re::Regex, str::String) = RegexMatchIterator(re,str,false) # miscellaneous methods that depend on Regex being defined diff --git a/base/repl.jl b/base/repl.jl new file mode 100644 index 0000000000000..05038e86e7d05 --- /dev/null +++ b/base/repl.jl @@ -0,0 +1,118 @@ +# called to show a REPL result +repl_show(v::ANY) = repl_show(OUTPUT_STREAM, v) +function repl_show(io::IO, v::ANY) + if !(isa(v,Function) && isgeneric(v)) + if isa(v,AbstractVector) && !isa(v,Ranges) + print(io, summary(v)) + if !isempty(v) + println(io, ":") + print_matrix(io, reshape(v,(length(v),1))) + end + else + show(io, v) + end + end + if isgeneric(v) && !isa(v,DataType) + show(io, v.env) + end +end + +# showing exception objects as descriptive error messages + +error_show(io::IO, e) = show(io, e) + +function error_show(io::IO, e::TypeError) + ctx = isempty(e.context) ? "" : "in $(e.context), " + if e.expected === Bool + print(io, "type: non-boolean ($(typeof(e.got))) ", + "used in boolean context") + else + if isa(e.got,Type) + tstr = "Type{$(e.got)}" + else + tstr = string(typeof(e.got)) + end + print(io, "type: $(e.func): ", + "$(ctx)expected $(e.expected), ", + "got $tstr") + end +end + +function error_show(io::IO, e, bt) + error_show(io, e) + show_backtrace(io, bt) +end + +error_show(io::IO, e::LoadError) = error_show(io, e, {}) +function error_show(io::IO, e::LoadError, bt) + error_show(io, e.error, bt) + print(io, "\nat $(e.file):$(e.line)") +end + +error_show(io::IO, e::SystemError) = print(io, "$(e.prefix): $(strerror(e.errnum))") +error_show(io::IO, ::DivideByZeroError) = print(io, "integer divide by zero") +error_show(io::IO, ::StackOverflowError) = print(io, "stack overflow") +error_show(io::IO, ::UndefRefError) = print(io, "access to undefined reference") +error_show(io::IO, ::EOFError) = print(io, "read: end of file") +error_show(io::IO, e::ErrorException) = print(io, e.msg) +error_show(io::IO, e::KeyError) = print(io, "key not found: $(e.key)") +error_show(io::IO, e::InterruptException) = print(io, "interrupt") + +function error_show(io::IO, e::MethodError) + name = e.f.env.name + if is(e.f,convert) && length(e.args)==2 + print(io, "no method $(name)(Type{$(e.args[1])},$(typeof(e.args[2])))") + else + print(io, "no method $(name)$(typeof(e.args))") + end +end + +function show_trace_entry(io, fname, file, line, n) + print(io, "\n") + print(io, " in ", fname, " at ", file) + if line >= 1 + try + print(io, ":", line) + catch + print(io, '?') #for when dec is not yet defined + end + end + if n > 1 + print(io, " (repeats ", n, " times)") + end +end + +function show_backtrace(io::IO, t) + # we may not declare :eval_user_input + # directly so that we get a compile error + # in case its name changes in the future + const eval_function = try + symbol(string(eval_user_input)) + catch + :(:) #for when client.jl is not yet defined + end + n = 1 + lastfile = ""; lastline = -11; lastname = symbol("#") + local fname, file, line + for i = 1:length(t) + lkup = ccall(:jl_lookup_code_address, Any, (Ptr{Void}, Bool), t[i], false) + if lkup === () + continue + end + fname, file, line = lkup + if i == 1 && fname == :error; continue; end + if fname == eval_function; break; end + if file != lastfile || line != lastline || fname != lastname + if lastline != -11 + show_trace_entry(io, lastname, lastfile, lastline, n) + end + n = 1 + lastfile = file; lastline = line; lastname = fname + else + n += 1 + end + end + if n > 1 || lastline != -11 + show_trace_entry(io, lastname, lastfile, lastline, n) + end +end diff --git a/base/rng.jl b/base/rng.jl deleted file mode 100644 index 94503b2422511..0000000000000 --- a/base/rng.jl +++ /dev/null @@ -1,340 +0,0 @@ -module RNG - -using Base.LibRandom - -export librandom_init, srand, - rand, rand!, - randn, randn!, - randi, randi!, randival, randival!, - randg, randg!, - randexp, randexp!, exprnd, - randchi2, randchi2!, chi2rnd, - randbeta, randbeta!, betarnd, - randbool, randbool!, - Rng, Rng_MT - -abstract Rng - -start(r::Rng) = 0 -done(r::Rng, count) = r.len == count ? true : false -next(r::Rng, count) = (rand(r), count + 1) - -type Rng_MT <: Rng - state::DSFMT_state - seed::Union(Uint32,Vector{Uint32}) - len::Int # Use for iteration. Set to -1 otherwise. - - function Rng_MT() - seed = uint32(0) - state = DSFMT_state() - dsfmt_init_gen_rand(state, seed) - return new(state, seed, -1) - end - - Rng_MT(seed) = Rng_MT(seed, -1) - - function Rng_MT(seed::Uint32, len::Int) - state = DSFMT_state() - dsfmt_init_gen_rand(state, seed) - return new(state, seed, len) - end - - function Rng_MT(seed::Vector{Uint32}, len::Int) - state = DSFMT_state() - dsfmt_init_by_array(state, seed) - return new(state, seed, len) - end -end - -function srand(r::Rng_MT, seed) - r.seed = seed - dsfmt_init_gen_rand(r.state, seed) - return r -end - -## initialization - -function librandom_init() - -@unix_only begin - try - srand("/dev/urandom") - catch - println(stderr, "Entropy pool not available to seed RNG, using ad-hoc entropy sources.") - seed = reinterpret(Uint64, time()) - seed = bitmix(seed, uint64(getpid())) - try - seed = bitmix(seed, parse_int(Uint64, readall(`ifconfig`|`sha1sum`)[1:40], 16)) - catch - # ignore - end - srand(seed) - end -end - -@windows_only begin - a = zeros(Uint32, 2) - win32_SystemFunction036!(a) - srand(a) -end - - randmtzig_create_ziggurat_tables() -end - -# macros to generate random arrays - -macro rand_matrix_builder(T, f) - f! = esc(symbol("$(f)!")) - f = esc(f) - quote - function ($f!)(A::Array{$T}) - for i = 1:numel(A) - A[i] = ($f)() - end - return A - end - ($f)(dims::Dims) = ($f!)(Array($T, dims)) - ($f)(dims::Int...) = ($f)(dims) - end -end - -macro rand_matrix_builder_1arg(T, f) - f! = esc(symbol("$(f)!")) - f = esc(f) - quote - function ($f!)(arg, A::Array{$T}) - for i = 1:numel(A) - A[i] = ($f)(arg) - end - return A - end - ($f)(arg::Number, dims::Dims) = ($f!)(arg, Array($T, dims)) - ($f)(arg::Number, dims::Int...) = ($f)(arg, dims) - end -end - -## srand() - -function srand(seed::Uint32) - global RANDOM_SEED = seed - dsfmt_gv_init_gen_rand(seed) -end - -function srand(seed::Vector{Uint32}) - global RANDOM_SEED = seed - dsfmt_gv_init_by_array(seed) -end - -srand(seed::Uint64) = srand([uint32(seed),uint32(seed>>32)]) -srand(seed::Int32) = srand(uint32(seed)) -srand(seed::Int64) = srand(uint64(seed)) - -function srand(filename::String, n::Integer) - open(filename) do io - a = Array(Uint32, int(n)) - read(io, a) - srand(a) - end -end -srand(filename::String) = srand(filename, 4) - -## rand() - -rand() = dsfmt_gv_genrand_close_open() -rand(r::Rng_MT) = dsfmt_genrand_close_open(r.state) - -rand!(A::Array{Float64}) = dsfmt_gv_fill_array_close_open!(A) -rand(dims::Dims) = rand!(Array(Float64, dims)) -rand(dims::Int...) = rand(dims) - -rand!(r::Rng_MT, A::Array{Float64}) = dsfmt_fill_array_close_open!(r.state, A) -rand(r::Rng, dims::Dims) = rand!(r, Array(Float64, dims)) -rand(r::Rng, dims::Int...) = rand(r, dims) - -## random integers - -dsfmt_randui32() = dsfmt_gv_genrand_uint32() - -dsfmt_randui64() = uint64(dsfmt_randui32()) | (uint64(dsfmt_randui32())<<32) - -randi(::Type{Uint32}) = dsfmt_randui32() -randi(::Type{Uint64}) = dsfmt_randui64() -randi(::Type{Uint128}) = uint128(randi(Uint64))<<64 | randi(Uint64) - -randi(::Type{Int32}) = int32(randi(Uint32)) & typemax(Int32) -randi(::Type{Int64}) = int64(randi(Uint64)) & typemax(Int64) -randi(::Type{Int128}) = int128(randi(Uint128)) & typemax(Int128) - -randi() = randi(Int) - -# random integer from lo to hi inclusive -function randival{T<:Integer}(lo::T, hi::T) - if lo > hi - error("randi: invalid range") - end - m = typemax(T) - s = randi(T) - if (hi-lo == m) - return s + lo - end - r = hi-lo+1 - if (r&(r-1))==0 - # power of 2 range - return s&(r-1) + lo - end - # note: m>=0 && r>=0 - lim = m - rem(rem(m,r)+1, r) - while s > lim - s = randi(T) - end - return rem(s,r) + lo -end - -function randival!{T<:Integer}(lo, hi, A::Array{T}) - lo = convert(T,lo) - hi = convert(T,hi) - for i = 1:numel(A) - A[i] = randival(lo, hi) - end - return A -end -randival{T<:Integer}(lo::T, hi::T, dims::Dims) = randival!(lo, hi, Array(T, dims)) -randival(lo, hi, dims::Dims) = randival(promote(lo, hi)..., dims) -randival(lo, hi, dims::Int...) = randival(lo, hi, dims) - -randi!(max::Integer, A::Array) = randival!(one(max), max, A) -randi!(r::(Integer,Integer), A::Array) = randival!(r[1], r[2], A) - -randi(max::Integer) = randival(one(max), max) -randi(max::Integer, dims::Dims) = randival(one(max), max, dims) -randi(max::Integer, dims::Int...) = randival(one(max), max, dims) -randi(r::(Integer,Integer)) = randival(r[1], r[2]) -randi(r::(Integer,Integer), dims::Dims) = randival(r[1], r[2], dims) -randi(r::(Integer,Integer), dims::Int...) = randival(r[1], r[2], dims) - -## random Bools - -rand!(B::BitArray) = Base.bitarray_rand_fill!(B) - -randbool(dims::Dims) = rand!(BitArray(dims)) -randbool(dims::Int...) = rand!(BitArray(dims)) - -randbool() = ((dsfmt_randui32() & 1) == 1) - -randbool!(B::BitArray) = rand!(B) - -function randbool!(A::Array) - for i = 1:numel(A) - A[i] = randbool() - end - return A -end - -## randn() - Normally distributed random numbers using Ziggurat algorithm - -# The Ziggurat Method for generating random variables - Marsaglia and Tsang -# Paper and reference code: http://www.jstatsoft.org/v05/i08/ - -randn() = randmtzig_randn() -randn!(A::Array{Float64}) = randmtzig_fill_randn!(A) -randn(dims::Dims) = randn!(Array(Float64, dims)) -randn(dims::Int...) = randn(dims) - -## randexp() - Exponentially distributed random numbers using Ziggurat algorithm - -randexp() = randmtzig_exprnd() -randexp!(A::Array{Float64}) = randmtzig_fill_exprnd!(A) -randexp(dims::Dims) = randexp!(Array(Float64, dims)) -randexp(dims::Int...) = randexp(dims) - -const exprnd = randexp - -## randg() - -# A simple method for generating gamma variables - Marsaglia and Tsang (2000) -# http://www.cparity.com/projects/AcmClassification/samples/358414.pdf -# Page 369 - -# basic simulation loop for pre-computed d and c -function randg2(d::Float64, c::Float64) - while true - x = v = 0.0 - while v <= 0.0 - x = randn() - v = 1.0 + c*x - end - v = v^3 - U = rand() - x2 = x^2 - if U < 1.0-0.331*x2^2 || log(U) < 0.5*x2+d*(1.0-v+log(v)) - return d*v - end - end -end - -function randg!(a::Real, A::Array{Float64}) - if a <= 0. error("shape parameter a must be > 0") end - d = (a <= 1. ? a + 1 : a) - 1.0/3.0 - c = 1.0/sqrt(9.0d) - for i in 1:numel(A) A[i] = randg2(d, c) end - if a <= 1. - ainv = 1./a - for i in 1:numel(A) A[i] *= rand()^ainv end - end - A -end - -function randg(a::Real) - if a <= 0. error("shape parameter a must be > 0") end - d = (a <= 1. ? a + 1 : a) - 1.0/3.0 - randg2(d, 1.0/sqrt(9.0d)) * (a > 1. ? 1. : rand()^(1./a)) -end - -randg(a::Real, dims::Dims) = randg!(a, Array(Float64, dims)) -randg(a::Real, dims::Int...) = randg(a, dims) - -## randchi2 - the distribution chi^2(df) is 2*gamma(df/2) -## for integer n, a chi^2(n) is the sum of n squared standard normals - -function randchi2!(df::Real, A::Array{Float64}) - if df == 1 - for i in 1:numel(A) - A[i] = randn()^2 - end - return A - end - d = df >= 2 ? df/2. - 1.0/3.0 : error("require degrees of freedom df >= 2") - c = 1.0/sqrt(9.0d) - for i in 1:numel(A) A[i] = 2.randg2(d,c) end - A -end - -randchi2(df::Real) = df == 1 ? randn()^2 : 2.randg(df/2.) -randchi2(df::Real, dims::Dims) = randchi2!(df, Array(Float64, dims)) -randchi2(df::Real, dims::Int...) = randchi2(df, dims) - -const chi2rnd = randchi2 # alias chi2rnd - -function randbeta!(alpha::Real, beta::Real, A::Array{Float64}) - d1 = alpha >= 1 ? alpha - 1.0/3.0 : error("require alpha >= 1") - c1 = 1.0/sqrt(9.0d1) - d2 = beta >= 1 ? beta - 1.0/3.0 : error("require beta >= 1") - c2 = 1.0/sqrt(9.0d2) - for i in 1:numel(A) - u = randg2(d1,c1) - A[i] = u/(u + randg2(d2,c2)) - end - A -end - -randbeta(alpha::Real, beta::Real) = (u=randg(alpha); u/(u + randg(beta))) - -function randbeta(alpha::Real, beta::Real, dims::Dims) - randbeta!(alpha, beta, Array(Float64, dims)) -end - -randbeta(alpha::Real, beta::Real, dims::Int...) = randbeta(alpha, beta, dims) - -const betarnd = randbeta - -end # module diff --git a/base/serialize.jl b/base/serialize.jl index b65cdfbd584d7..ef34b37daef3c 100644 --- a/base/serialize.jl +++ b/base/serialize.jl @@ -6,14 +6,14 @@ abstract LongTuple abstract LongExpr abstract UndefRefTag -const _jl_ser_version = 1 # do not make changes without bumping the version #! -const _jl_ser_tag = ObjectIdDict() -const _jl_deser_tag = ObjectIdDict() +const ser_version = 1 # do not make changes without bumping the version #! +const ser_tag = ObjectIdDict() +const deser_tag = ObjectIdDict() let i = 2 - global _jl_ser_tag, _jl_deser_tag + global ser_tag, deser_tag for t = {Symbol, Int8, Uint8, Int16, Uint16, Int32, Uint32, Int64, Uint64, Int128, Uint128, Float32, Float64, Char, Ptr, - AbstractKind, UnionKind, BitsKind, CompositeKind, Function, + DataType, UnionType, Function, Tuple, Array, Expr, LongSymbol, LongTuple, LongExpr, LineNumberNode, SymbolNode, LabelNode, GotoNode, QuoteNode, TopNode, TypeVar, Box, LambdaStaticData, @@ -36,20 +36,20 @@ let i = 2 false, true, nothing, 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} - _jl_ser_tag[t] = int32(i) - _jl_deser_tag[int32(i)] = t + ser_tag[t] = int32(i) + deser_tag[int32(i)] = t i += 1 end end # tags >= this just represent themselves, their whole representation is 1 byte -const _jl_VALUE_TAGS = _jl_ser_tag[()] +const VALUE_TAGS = ser_tag[()] -writetag(s, x) = write(s, uint8(_jl_ser_tag[x])) +writetag(s, x) = write(s, uint8(ser_tag[x])) function write_as_tag(s, x) - t = _jl_ser_tag[x] - if t < _jl_VALUE_TAGS + t = ser_tag[x] + if t < VALUE_TAGS write(s, uint8(0)) end write(s, uint8(t)) @@ -57,6 +57,8 @@ end serialize(s, x::Bool) = write_as_tag(s, x) +serialize(s, ::Ptr) = error("cannot serialize a pointer") + serialize(s, ::()) = write_as_tag(s, ()) function serialize(s, t::Tuple) @@ -74,7 +76,7 @@ function serialize(s, t::Tuple) end function serialize(s, x::Symbol) - if has(_jl_ser_tag, x) + if has(ser_tag, x) return write_as_tag(s, x) end name = string(x) @@ -91,10 +93,10 @@ end function serialize_array_data(s, a) elty = eltype(a) - if elty === Bool && numel(a)>0 + if elty === Bool && length(a)>0 last = a[1] count = 1 - for i = 2:numel(a) + for i = 2:length(a) if a[i] != last || count == 127 write(s, uint8((uint8(last)<<7) | count)) last = a[i] @@ -114,10 +116,10 @@ function serialize(s, a::Array) elty = eltype(a) serialize(s, elty) serialize(s, size(a)) - if isa(elty,BitsKind) + if isbits(elty) serialize_array_data(s, a) else - for i = 1:numel(a) + for i = 1:length(a) if isdefined(a, i) serialize(s, a[i]) else @@ -128,7 +130,7 @@ function serialize(s, a::Array) end function serialize{T,N,A<:Array}(s, a::SubArray{T,N,A}) - if !isa(T,BitsKind) || stride(a,1)!=1 + if !isbits(T) || stride(a,1)!=1 return serialize(s, copy(a)) end writetag(s, Array) @@ -158,7 +160,7 @@ function serialize(s, m::Module) serialize(s, full_name(m)) end -function _jl_lambda_number(l::LambdaStaticData) +function lambda_number(l::LambdaStaticData) # a hash function that always gives the same number to the same # object on the same machine, and is unique over all machines. hash(uint64(object_id(l))+(uint64(myid())<<44)) @@ -201,11 +203,21 @@ end function serialize(s, linfo::LambdaStaticData) writetag(s, LambdaStaticData) - serialize(s, _jl_lambda_number(linfo)) + serialize(s, lambda_number(linfo)) serialize(s, linfo.ast) + if isdefined(linfo.def, :roots) + serialize(s, linfo.def.roots) + else + serialize(s, {}) + end serialize(s, linfo.sparams) serialize(s, linfo.inferred) serialize(s, linfo.module) + if isdefined(linfo, :capt) + serialize(s, linfo.capt) + else + serialize(s, nothing) + end end function serialize_type_data(s, t) @@ -220,40 +232,43 @@ function serialize_type_data(s, t) end end -function serialize(s, t::Union(AbstractKind,BitsKind,CompositeKind)) - if has(_jl_ser_tag,t) +function serialize(s, t::DataType) + if has(ser_tag,t) write_as_tag(s, t) else - writetag(s, AbstractKind) + writetag(s, DataType) + write(s, uint8(0)) serialize_type_data(s, t) end end -function serialize_type(s, t::Union(CompositeKind,BitsKind)) - if has(_jl_ser_tag,t) +function serialize_type(s, t::DataType) + if has(ser_tag,t) writetag(s, t) else - writetag(s, typeof(t)) + writetag(s, DataType) + write(s, uint8(1)) serialize_type_data(s, t) end end function serialize(s, x) - if has(_jl_ser_tag,x) + if has(ser_tag,x) return write_as_tag(s, x) end t = typeof(x) - if isa(t,BitsKind) - serialize_type(s, t) + serialize_type(s, t) + if length(t.names)==0 && t.size>0 write(s, x) - elseif isa(t,CompositeKind) - serialize_type(s, t) + else serialize(s, length(t.names)) - for n = t.names - serialize(s, getfield(x, n)) + for n in t.names + if isdefined(x, n) + serialize(s, getfield(x, n)) + else + writetag(s, UndefRefTag) + end end - else - error(x," is not serializable") end end @@ -265,10 +280,10 @@ end function handle_deserialize(s, b) if b == 0 - return _jl_deser_tag[int32(read(s, Uint8))] + return deser_tag[int32(read(s, Uint8))] end - tag = _jl_deser_tag[b] - if b >= _jl_VALUE_TAGS + tag = deser_tag[b] + if b >= VALUE_TAGS return tag elseif is(tag,Tuple) len = int32(read(s, Uint8)) @@ -294,7 +309,7 @@ function deserialize(s, ::Type{Module}) m end -const _jl_known_lambda_data = Dict() +const known_lambda_data = Dict() function deserialize(s, ::Type{Function}) b = read(s, Uint8) @@ -318,16 +333,22 @@ end function deserialize(s, ::Type{LambdaStaticData}) lnumber = deserialize(s) ast = deserialize(s) + roots = deserialize(s) sparams = deserialize(s) infr = deserialize(s) mod = deserialize(s) - if has(_jl_known_lambda_data, lnumber) - return _jl_known_lambda_data[lnumber] + capt = deserialize(s) + if has(known_lambda_data, lnumber) + return known_lambda_data[lnumber] else linfo = ccall(:jl_new_lambda_info, Any, (Any, Any), ast, sparams) linfo.inferred = infr linfo.module = mod - _jl_known_lambda_data[lnumber] = linfo + linfo.roots = roots + if !is(capt,nothing) + linfo.capt = capt + end + known_lambda_data[lnumber] = linfo return linfo end end @@ -335,7 +356,7 @@ end function deserialize(s, ::Type{Array}) elty = deserialize(s) dims = deserialize(s)::Dims - if isa(elty,BitsKind) + if isbits(elty) n = prod(dims)::Int if elty === Bool && n>0 A = Array(Bool, dims) @@ -355,9 +376,9 @@ function deserialize(s, ::Type{Array}) end end A = Array(elty, dims) - for i = 1:numel(A) + for i = 1:length(A) tag = int32(read(s, Uint8)) - if tag==0 || !is(_jl_deser_tag[tag], UndefRefTag) + if tag==0 || !is(deser_tag[tag], UndefRefTag) A[i] = handle_deserialize(s, tag) end end @@ -370,7 +391,8 @@ deserialize(s, ::Type{LongExpr}) = deserialize_expr(s, read(s, Int32)) function deserialize_expr(s, len) hd = deserialize(s)::Symbol ty = deserialize(s) - e = expr(hd, { deserialize(s) for i=1:len }) + e = Expr(hd) + e.args = { deserialize(s) for i=1:len } e.typ = ty e end @@ -383,58 +405,56 @@ function deserialize(s, ::Type{TypeVar}) TypeVar(name, lb, ub) end -function deserialize(s, ::Type{UnionKind}) +function deserialize(s, ::Type{UnionType}) nf_expected = deserialize(s) types = deserialize(s) Union(types...) end -function deserialize(s, ::Type{AbstractKind}) +function deserialize(s, ::Type{DataType}) + form = read(s, Uint8) name = deserialize(s)::Symbol mod = deserialize(s)::Module params = deserialize(s) ty = eval(mod,name) if is(params,()) - return ty + t = ty + else + t = apply_type(ty, params...) end - apply_type(ty, params...) -end - -function deserialize(s, ::Union(Type{CompositeKind}, Type{BitsKind})) - t = deserialize(s, AbstractKind) - # allow delegation to more specialized method - return deserialize(s, t) + if form == 0 + return t + end + deserialize(s, t) end -# default bits deserializer -deserialize(s, t::BitsKind) = read(s, t) +deserialize{T}(s, ::Type{Ptr{T}}) = pointer(T, 0) -# default structure deserializer -function deserialize(s, t::CompositeKind) +# default DataType deserializer +function deserialize(s, t::DataType) + if length(t.names)==0 && t.size>0 + # bits type + return read(s, t) + end nf_expected = deserialize(s) nf = length(t.names) if nf == 0 return ccall(:jl_new_struct, Any, (Any,Any...), t) - elseif nf == 1 - f1 = deserialize(s) - ccall(:jl_new_struct, Any, (Any,Any...), t, f1) - elseif nf == 2 + elseif nf == 1 && !t.mutable + return ccall(:jl_new_struct, Any, (Any,Any...), t, deserialize(s)) + elseif nf == 2 && !t.mutable f1 = deserialize(s) f2 = deserialize(s) - ccall(:jl_new_struct, Any, (Any,Any...), t, f1, f2) - elseif nf == 3 - f1 = deserialize(s) - f2 = deserialize(s) - f3 = deserialize(s) - ccall(:jl_new_struct, Any, (Any,Any...), t, f1, f2, f3) - elseif nf == 4 - f1 = deserialize(s) - f2 = deserialize(s) - f3 = deserialize(s) - f4 = deserialize(s) - ccall(:jl_new_struct, Any, (Any,Any...), t, f1, f2, f3, f4) + return ccall(:jl_new_struct, Any, (Any,Any...), t, f1, f2) + # TODO: handle immutable else - f = ntuple(nf, i->deserialize(s)) - ccall(:jl_new_structt, Any, (Any,Any), t, f) + x = ccall(:jl_new_struct_uninit, Any, (Any,), t) + for n in t.names + tag = int32(read(s, Uint8)) + if tag==0 || !is(deser_tag[tag], UndefRefTag) + setfield(x, n, handle_deserialize(s, tag)) + end + end + return x end end diff --git a/base/set.jl b/base/set.jl index 0f793dec392bc..d7ea4e9a9528b 100644 --- a/base/set.jl +++ b/base/set.jl @@ -1,39 +1,42 @@ type Set{T} - hash::Dict{T,Bool} + dict::Dict{T,Nothing} - Set() = new((T=>Bool)[]) - Set(x...) = add_each(new(Dict{T,Bool}(length(x))), x) + Set() = new(Dict{T,Nothing}()) + Set(x...) = add_each!(new(Dict{T,Nothing}()), x) end Set() = Set{Any}() Set(x...) = Set{Any}(x...) Set{T}(x::T...) = Set{T}(x...) -show(io, s::Set) = (show(io, typeof(s)); show_comma_array(io, s,'(',')')) +show(io::IO, s::Set) = (show(io, typeof(s)); show_comma_array(io, s,'(',')')) -isempty(s::Set) = isempty(s.hash) -length(s::Set) = length(s.hash) -elements(s::Set) = keys(s.hash) +isempty(s::Set) = isempty(s.dict) +length(s::Set) = length(s.dict) eltype{T}(s::Set{T}) = T -has(s::Set, x) = has(s.hash, x) +has(s::Set, x) = has(s.dict, x) contains(s::Set, x) = has(s, x) -get(s::Set, x, deflt) = get(s.hash, x, false) -add(s::Set, x) = (s.hash[x] = true; s) -del(s::Set, x) = (del(s.hash, x); s) +add!(s::Set, x) = (s.dict[x] = nothing; s) +delete!(s::Set, x) = (delete!(s.dict, x); x) +# TODO: this method doesn't make much sense for sets: +delete!(s::Set, x, deflt) = has(s.dict, x) ? delete!(s.dict, x) : deflt -add_each(s::Set, xs) = (for x=xs; add(s,x); end; s) -del_each(s::Set, xs) = (for x=xs; del(s,x); end; s) +add_each!(s::Set, xs) = (for x=xs; add!(s,x); end; s) +del_each!(s::Set, xs) = (for x=xs; delete!(s,x); end; s) similar{T}(s::Set{T}) = Set{T}() -copy(s::Set) = add_each(similar(s), s) +copy(s::Set) = add_each!(similar(s), s) -del_all{T}(s::Set{T}) = (del_all(s.hash); s) +empty!{T}(s::Set{T}) = (empty!(s.dict); s) -start(s::Set) = start(s.hash) -done(s::Set, state) = done(s.hash, state) +start(s::Set) = start(s.dict) +done(s::Set, state) = done(s.dict, state) # NOTE: manually optimized to take advantage of Dict representation -next(s::Set, i) = (s.hash.keys[i], skip_deleted(s.hash,i+1)) +next(s::Set, i) = (s.dict.keys[i], skip_deleted(s.dict,i+1)) + +# TODO: simplify me? +pop!(s::Set) = (val = s.dict.keys[start(s.dict)]; delete!(s.dict, val); val) union() = Set() union(s::Set) = copy(s) @@ -47,9 +50,9 @@ function union(s::Set, sets::Set...) end end u = Set{U}() - add_each(u,s) + add_each!(u,s) for t in sets - add_each(u,t) + add_each!(u,t) end return u end @@ -59,8 +62,8 @@ function intersect(s::Set, sets::Set...) i = copy(s) for x in s for t in sets - if !has(t,x) - del(i,x) + if !has(t,x) & has(i,x) + delete!(i,x) end end end @@ -71,7 +74,7 @@ function setdiff(a::Set, b::Set) d = copy(a) for x in b if has(d, x) - del(d, x) + delete!(d, x) end end d @@ -81,6 +84,26 @@ end (&)(s::Set...) = intersect(s...) -(a::Set, b::Set) = setdiff(a,b) -isequal(l::Set, r::Set) = length(l) == length(r) == length(intersect(l,r)) +isequal(l::Set, r::Set) = (length(l) == length(r)) && (l <= r) +isless(l::Set, r::Set) = (length(l) < length(r)) && (l <= r) +function <=(l::Set, r::Set) + for elt in l + if !has(r, elt) + return false + end + end + return true +end + +unique(C) = collect(add_each!(Set{eltype(C)}(), C)) + +function filter!(f::Function, s::Set) + for x in s + if !f(x) + delete!(s, x) + end + end + return s +end +filter(f::Function, s::Set) = filter!(f, copy(s)) -unique(C) = elements(add_each(Set{eltype(C)}(), C)) diff --git a/base/show.jl b/base/show.jl index bfaa8e15abaf2..e0728519f839f 100644 --- a/base/show.jl +++ b/base/show.jl @@ -1,35 +1,37 @@ # formerly built-in methods. can be replaced any time. -show(x) = show(OUTPUT_STREAM::IOStream, x) +show(x) = show(OUTPUT_STREAM::IO, x) -print(io::IOStream, s::Symbol) = ccall(:jl_print_symbol, Void, (Ptr{Void}, Any,), io, s) -show(io, x) = ccall(:jl_show_any, Void, (Any, Any,), io::IOStream, x) +print(io::IO, s::Symbol) = ccall(:jl_print_symbol, Void, (Ptr{Void}, Any,), io, s) +show(io::IO, x::ANY) = ccall(:jl_show_any, Void, (Any, Any,), io, x) -showcompact(io, x) = show(io, x) -showcompact(x) = showcompact(OUTPUT_STREAM::IOStream, x) +showcompact(io::IO, x) = show(io, x) +showcompact(x) = showcompact(OUTPUT_STREAM::IO, x) -macro show(ex) - quote - print($(sprint(show_unquoted, ex)*"\t= ")) - show($(esc(ex))) - println() +macro show(exs...) + blk = Expr(:block) + for ex in exs + push!(blk.args, :(println($(sprint(show_unquoted,ex)*" => "), + repr(begin value=$(esc(ex)) end)))) end + if !isempty(exs); push!(blk.args, :value); end + return blk end -show(io, s::Symbol) = show_indented(io, s) -show(io, tn::TypeName) = print(io, tn.name) -show(io, ::Nothing) = print(io, "nothing") -show(io, b::Bool) = print(io, b ? "true" : "false") -show(io, n::Signed) = (write(io, dec(n)); nothing) -show(io, n::Unsigned) = print(io, "0x", hex(n,sizeof(n)<<1)) +show(io::IO, s::Symbol) = show_indented(io, s) +show(io::IO, tn::TypeName) = print(io, tn.name) +show(io::IO, ::Nothing) = print(io, "nothing") +show(io::IO, b::Bool) = print(io, b ? "true" : "false") +show(io::IO, n::Signed) = (write(io, dec(n)); nothing) +show(io::IO, n::Unsigned) = print(io, "0x", hex(n,sizeof(n)<<1)) -show{T}(io, p::Ptr{T}) = +show{T}(io::IO, p::Ptr{T}) = print(io, is(T,None) ? "Ptr{Void}" : typeof(p), " @0x$(hex(unsigned(p), WORD_SIZE>>2))") full_name(m::Module) = m===Main ? () : tuple(full_name(module_parent(m))..., module_name(m)) -function show(io, m::Module) +function show(io::IO, m::Module) if is(m,Main) print(io, "Main") else @@ -37,13 +39,20 @@ function show(io, m::Module) end end -function show(io, l::LambdaStaticData) +uncompress_ast(l::LambdaStaticData) = ccall(:jl_uncompress_ast, Any, (Any,Any), l, l.ast) + +function show(io::IO, l::LambdaStaticData) print(io, "AST(") - show(io, l.ast) + if isa(l.ast,Expr) + show(io, l.ast) + else + ast = uncompress_ast(l) + show(io, ast) + end print(io, ")") end -function show_delim_array(io, itr, op, delim, cl, delim_one) +function show_delim_array(io::IO, itr, op, delim, cl, delim_one) print(io, op) state = start(itr) newline = true @@ -51,7 +60,7 @@ function show_delim_array(io, itr, op, delim, cl, delim_one) if !done(itr,state) while true x, state = next(itr,state) - multiline = isa(x,AbstractArray) && ndims(x)>1 && numel(x)>0 + multiline = isa(x,AbstractArray) && ndims(x)>1 && length(x)>0 if newline if multiline; println(io); end end @@ -74,8 +83,8 @@ function show_delim_array(io, itr, op, delim, cl, delim_one) print(io, cl) end -show_comma_array(io, itr, o, c) = show_delim_array(io, itr, o, ',', c, false) -show(io, t::Tuple) = show_delim_array(io, t, '(', ',', ')', true) +show_comma_array(io::IO, itr, o, c) = show_delim_array(io, itr, o, ',', c, false) +show(io::IO, t::Tuple) = show_delim_array(io, t, '(', ',', ')', true) ## AST decoding helpers ## @@ -136,9 +145,9 @@ function show_indented(io::IO, sym::Symbol, indent::Int) end end function default_show_quoted(io::IO, ex, indent::Int) - print(io, ":( ") + print(io, ":(") show_unquoted(io, ex, indent + indent_width) - print(io, " )") + print(io, ")") end ## AST printing helpers ## @@ -157,8 +166,8 @@ function show_expr_type(io::IO, ty) end end -show_linenumber(io::IO, line) = print(io,"\t# line ",line,':') -show_linenumber(io::IO, line, file) = print(io,"\t# ",file,", line ",line,':') +show_linenumber(io::IO, line) = print(io," # line ",line,':') +show_linenumber(io::IO, line, file) = print(io," # ",file,", line ",line,':') # show a block, e g if/for/etc function show_block(io::IO, head, args::Vector, body, indent::Int) @@ -197,6 +206,7 @@ end show_unquoted(io::IO, sym::Symbol, indent::Int) = print(io, sym) show_unquoted(io::IO, x::Number, indent::Int) = show(io, x) show_unquoted(io::IO, x::String, indent::Int) = show(io, x) +show_unquoted(io::IO, x::Char, indent::Int) = show(io, x) const _expr_infix_wide = Set(:(=), :(+=), :(-=), :(*=), :(/=), :(\=), :(&=), :(|=), :($=), :(>>>=), :(>>=), :(<<=), :(&&), :(||)) @@ -227,13 +237,13 @@ function show_unquoted(io::IO, ex::Expr, indent::Int) elseif has(_expr_parens, head) # :tuple/:vcat/:cell1d op, cl = _expr_parens[head] print(io, op) - show_list(io, args, ", ", indent) + show_list(io, args, ",", indent) if is(head, :tuple) && nargs == 1; print(io, ','); end print(io, cl) elseif has(_expr_calls, head) && nargs >= 1 # :call/:ref/:curly op, cl = _expr_calls[head] show_unquoted(io, args[1], indent) - show_enclosed_list(io, op, args[2:end], ", ", cl, indent) + show_enclosed_list(io, op, args[2:end], ",", cl, indent) elseif is(head, :comparison) && nargs >= 3 && (nargs&1==1) show_enclosed_list(io, '(', args, "", ')', indent) elseif is(head, :(...)) && nargs == 1 @@ -242,7 +252,7 @@ function show_unquoted(io::IO, ex::Expr, indent::Int) elseif (nargs == 1 && contains((:return, :abstract, :const), head)) || contains((:local, :global), head) print(io, head, ' ') - show_list(io, args, ", ", indent) + show_list(io, args, ",", indent) elseif is(head, :macrocall) && nargs >= 1 show_list(io, args, ' ', indent) elseif is(head, :typealias) && nargs == 2 @@ -276,7 +286,7 @@ function show_unquoted(io::IO, ex::Expr, indent::Int) elseif is(head, :null) print(io, "nothing") else - print(io, "\$(expr(") + print(io, "\$(Expr(") show_indented(io, ex.head, indent) for arg in args print(io, ", ") @@ -299,65 +309,30 @@ function show_unquoted(io::IO, ex::SymbolNode) show_expr_type(io, ex.typ) end +function clean_gensym(s::Symbol) + s = string(s) + i = search(s,'#') + if i > 0 + return s[1:i-1] + end + return s +end -function show(io, e::TypeError) - ctx = isempty(e.context) ? "" : "in $(e.context), " - if e.expected === Bool - print(io, "type error: non-boolean ($(typeof(e.got))) ", - "used in boolean context") - elseif e.expected === Function && e.func === :apply && isa(e.got,AbstractKind) - print(io, "type error: cannot instantiate abstract type $(e.got.name)") - else - if isa(e.got,Type) - tstr = "Type{$(e.got)}" - else - tstr = string(typeof(e.got)) - end - print(io, "type error: $(e.func): ", - "$(ctx)expected $(e.expected), ", - "got $tstr") - end -end - -show(io, e::LoadError) = (show(io, e.error); print(io, "\nat $(e.file):$(e.line)")) -show(io, e::SystemError) = print(io, "$(e.prefix): $(strerror(e.errnum))") -show(io, ::DivideByZeroError) = print(io, "error: integer divide by zero") -show(io, ::StackOverflowError) = print(io, "error: stack overflow") -show(io, ::UndefRefError) = print(io, "access to undefined reference") -show(io, ::EOFError) = print(io, "read: end of file") -show(io, e::ErrorException) = print(io, e.msg) -show(io, e::KeyError) = print(io, "key not found: $(e.key)") -show(io, e::InterruptException) = nothing - -function show(io, e::MethodError) - name = e.f.env.name - if is(e.f,convert) - print(io, "no method $(name)(Type{$(e.args[1])},$(typeof(e.args[2])))") - else - print(io, "no method $(name)$(typeof(e.args))") - end -end - -function show(io, bt::BackTrace) - show(io, bt.e) - t = bt.trace - # we may not declare :_jl_eval_user_input - # directly so that we get a compile error - # in case its name changes in the future - const _jl_eval_function = symbol(string(_jl_eval_user_input)) - for i = 1:3:length(t) - if i == 1 && t[i] == :error; continue; end - if t[i] == _jl_eval_function; break; end - print(io, "\n") - lno = t[i+2] - print(io, " in ", t[i], " at ", t[i+1]) - if lno >= 1 - print(io, ":", lno) - end +function argtype_decl_string(n, t) + if isa(n,Expr) + n = n.args[1] # handle n::T in arg list + end + n = clean_gensym(n) + if t === Any + return n end + if t <: Vararg && t.parameters[1] === Any + return string(n, "...") + end + return string(n, "::", t) end -function show(io, m::Method) +function show(io::IO, m::Method) tv = m.tvars if !isa(tv,Tuple) tv = (tv,) @@ -365,16 +340,24 @@ function show(io, m::Method) if !isempty(tv) show_delim_array(io, tv, '{', ',', '}', false) end - show(io, m.sig) li = m.func.code + e = li.ast + if !isa(e,Expr) + e = uncompress_ast(li) + end + argnames = e.args[1] + decls = map(argtype_decl_string, argnames, {m.sig...}) + print(io, "(") + print_joined(io, decls, ",", ",") + print(io, ")") if li.line > 0 print(io, " at ", li.file, ":", li.line) end end -function show(io, mt::MethodTable) +function show(io::IO, mt::MethodTable) name = mt.name - println(io, "Methods for generic function ", name) + println(io, "# methods for generic function ", name) d = mt.defs while !is(d,()) print(io, name) @@ -386,9 +369,9 @@ function show(io, mt::MethodTable) end end -# dump & idump - structured tree representation like R's str() +# dump & xdump - structured tree representation like R's str() # - dump is for the user-facing structure -# - idump is for the internal structure +# - xdump is for the internal structure # # x is the object # n is the depth of traversal in nested types (5 is the default) @@ -400,18 +383,18 @@ end # n > 0, dump each component. Limit to the first 10 entries. When # dumping components, decrement n, and add two spaces to indent. # -# Package writers should not overload idump. +# Package writers should not overload xdump. -function idump(fn::Function, io::IOStream, x, n::Int, indent) +function xdump(fn::Function, io::IO, x, n::Int, indent) T = typeof(x) print(io, T, " ") - if isa(T, CompositeKind) + if isa(T, DataType) println(io) if n > 0 for field in T.names if field != symbol("") # prevents segfault if symbol is blank print(io, indent, " ", field, ": ") - fn(io, getfield(x, field), n - 1, strcat(indent, " ")) + fn(io, getfield(x, field), n - 1, string(indent, " ")) end end end @@ -419,36 +402,40 @@ function idump(fn::Function, io::IOStream, x, n::Int, indent) println(io, x) end end -function idump(fn::Function, io::IOStream, x::Array{Any}, n::Int, indent) +function xdump(fn::Function, io::IO, x::Module, n::Int, indent) + print(io, Module, " ") + println(io, x) +end +function xdump(fn::Function, io::IO, x::Array{Any}, n::Int, indent) println("Array($(eltype(x)),$(size(x)))") if n > 0 for i in 1:(length(x) <= 10 ? length(x) : 5) print(io, indent, " ", i, ": ") - fn(io, x[i], n - 1, strcat(indent, " ")) + fn(io, x[i], n - 1, string(indent, " ")) end if length(x) > 10 println(io, indent, " ...") for i in length(x)-4:length(x) print(io, indent, " ", i, ": ") - fn(io, x[i], n - 1, strcat(indent, " ")) + fn(io, x[i], n - 1, string(indent, " ")) end end end end -idump(fn::Function, io::IOStream, x::Symbol, n::Int, indent) = println(io, typeof(x), " ", x) -idump(fn::Function, io::IOStream, x::Function, n::Int, indent) = println(io, x) -idump(fn::Function, io::IOStream, x::Array, n::Int, indent) = println(io, "Array($(eltype(x)),$(size(x)))", " ", x) +xdump(fn::Function, io::IO, x::Symbol, n::Int, indent) = println(io, typeof(x), " ", x) +xdump(fn::Function, io::IO, x::Function, n::Int, indent) = println(io, x) +xdump(fn::Function, io::IO, x::Array, n::Int, indent) = println(io, "Array($(eltype(x)),$(size(x)))", " ", x) # Types -idump(fn::Function, io::IOStream, x::UnionKind, n::Int, indent) = println(io, x) -function idump(fn::Function, io::IOStream, x::CompositeKind, n::Int, indent) +xdump(fn::Function, io::IO, x::UnionType, n::Int, indent) = println(io, x) +function xdump(fn::Function, io::IO, x::DataType, n::Int, indent) println(io, x, "::", typeof(x), " ", " <: ", super(x)) if n > 0 for idx in 1:min(10,length(x.names)) if x.names[idx] != symbol("") # prevents segfault if symbol is blank print(io, indent, " ", x.names[idx], "::") - if isa(x.types[idx], CompositeKind) - idump(fn, io, x.types[idx], n - 1, strcat(indent, " ")) + if isa(x.types[idx], DataType) + xdump(fn, io, x.types[idx], n - 1, string(indent, " ")) else println(x.types[idx]) end @@ -460,10 +447,10 @@ function idump(fn::Function, io::IOStream, x::CompositeKind, n::Int, indent) end end -# _jl_dumptype is for displaying abstract type hierarchies like Jameson +# dumptype is for displaying abstract type hierarchies like Jameson # Nash's wiki page: https://github.com/JuliaLang/julia/wiki/Types-Hierarchy -function _jl_dumptype(io::IOStream, x::Type, n::Int, indent) +function dumptype(io::IO, x, n::Int, indent) # based on Jameson Nash's examples/typetree.jl println(io, x) if n == 0 # too deeply nested @@ -484,17 +471,17 @@ function _jl_dumptype(io::IOStream, x::Type, n::Int, indent) length(t.parameters) > 0 ? "{$targs}" : "", " = ", t) end - elseif isa(t, UnionKind) - if any(map(tt -> string(x.name) == typargs(tt), t.types)) + elseif isa(t, UnionType) + if any(tt -> string(x.name) == typargs(tt), t.types) println(io, indent, " ", s, " = ", t) end - elseif isa(t, Type) && super(t).name == x.name + elseif isa(t, DataType) && super(t).name == x.name # type aliases if string(s) != string(t.name) println(io, indent, " ", s, " = ", t.name) elseif t != Any print(io, indent, " ") - _jl_dumptype(io, t, n - 1, strcat(indent, " ")) + dump(io, t, n - 1, string(indent, " ")) end end end @@ -504,31 +491,31 @@ end # For abstract types, use _dumptype only if it's a form that will be called # interactively. -idump(fn::Function, io::IOStream, x::AbstractKind) = _jl_dumptype(io, x, 5, "") -idump(fn::Function, io::IOStream, x::AbstractKind, n::Int) = _jl_dumptype(io, x, n, "") +xdump(fn::Function, io::IO, x::DataType) = x.abstract ? dumptype(io, x, 5, "") : xdump(fn, io, x, 5, "") +xdump(fn::Function, io::IO, x::DataType, n::Int) = x.abstract ? dumptype(io, x, n, "") : xdump(fn, io, x, n, "") # defaults: -idump(fn::Function, io::IOStream, x) = idump(idump, io, x, 5, "") # default is 5 levels -idump(fn::Function, io::IOStream, x, n::Int) = idump(idump, io, x, n, "") -idump(fn::Function, args...) = idump(fn, OUTPUT_STREAM::IOStream, args...) -idump(io::IOStream, args...) = idump(idump, io, args...) -idump(args...) = idump(idump, OUTPUT_STREAM::IOStream, args...) +xdump(fn::Function, io::IO, x) = xdump(xdump, io, x, 5, "") # default is 5 levels +xdump(fn::Function, io::IO, x, n::Int) = xdump(xdump, io, x, n, "") +xdump(fn::Function, args...) = xdump(fn, OUTPUT_STREAM::IO, args...) +xdump(io::IO, args...) = xdump(xdump, io, args...) +xdump(args...) = xdump(xdump, OUTPUT_STREAM::IO, args...) # Here are methods specifically for dump: -dump(io::IOStream, x, n::Int) = dump(io, x, n, "") -dump(io::IOStream, x) = dump(io, x, 5, "") # default is 5 levels -dump(args...) = dump(OUTPUT_STREAM::IOStream, args...) -dump(io::IOStream, x::String, n::Int, indent) = println(io, typeof(x), " \"", x, "\"") -dump(io::IOStream, x, n::Int, indent) = idump(dump, io, x, n, indent) +dump(io::IO, x, n::Int) = dump(io, x, n, "") +dump(io::IO, x) = dump(io, x, 5, "") # default is 5 levels +dump(args...) = dump(OUTPUT_STREAM::IO, args...) +dump(io::IO, x::String, n::Int, indent) = println(io, typeof(x), " \"", x, "\"") +dump(io::IO, x, n::Int, indent) = xdump(dump, io, x, n, indent) -function dump(io::IOStream, x::Dict, n::Int, indent) +function dump(io::IO, x::Dict, n::Int, indent) println(typeof(x), " len ", length(x)) if n > 0 i = 1 for (k,v) in x print(io, indent, " ", k, ": ") - dump(io, v, n - 1, strcat(indent, " ")) + dump(io, v, n - 1, string(indent, " ")) if i > 10 println(io, indent, " ...") break @@ -539,16 +526,15 @@ function dump(io::IOStream, x::Dict, n::Int, indent) end # More generic representation for common types: -dump(io::IOStream, x::AbstractKind, n::Int, indent) = println(io, x.name) -dump(io::IOStream, x::AbstractKind) = _jl_dumptype(io, x, 5, "") -dump(io::IOStream, x::AbstractKind, n::Int) = _jl_dumptype(io, x, n, "") -dump(io::IOStream, x::BitsKind, n::Int, indent) = println(io, x.name) -dump(io::IOStream, x::TypeVar, n::Int, indent) = println(io, x.name) +dump(io::IO, x::DataType, n::Int, indent) = println(io, x.name) +dump(io::IO, x::DataType, n::Int) = dump(io, x, n, "") +dump(io::IO, x::DataType) = dump(io, x, 5, "") +dump(io::IO, x::TypeVar, n::Int, indent) = println(io, x.name) -showall(x) = showall(OUTPUT_STREAM::IOStream, x) +showall(x) = showall(OUTPUT_STREAM::IO, x) -function showall{T}(io, a::AbstractArray{T,1}) +function showall{T}(io::IO, a::AbstractArray{T,1}) if is(T,Any) opn = '{'; cls = '}' else @@ -557,27 +543,27 @@ function showall{T}(io, a::AbstractArray{T,1}) show_comma_array(io, a, opn, cls) end -alignment(x::Any) = (0, strlen(sprint(showcompact, x))) -alignment(x::Number) = (strlen(sprint(showcompact, x)), 0) -alignment(x::Integer) = (strlen(sprint(showcompact, x)), 0) +alignment(x::Any) = (0, length(sprint(showcompact, x))) +alignment(x::Number) = (length(sprint(showcompact, x)), 0) +alignment(x::Integer) = (length(sprint(showcompact, x)), 0) function alignment(x::Real) m = match(r"^(.*?)((?:[\.eE].*)?)$", sprint(showcompact, x)) - m == nothing ? (strlen(sprint(showcompact, x)), 0) : - (strlen(m.captures[1]), strlen(m.captures[2])) + m == nothing ? (length(sprint(showcompact, x)), 0) : + (length(m.captures[1]), length(m.captures[2])) end function alignment(x::Complex) m = match(r"^(.*,)(.*)$", sprint(showcompact, x)) - m == nothing ? (strlen(sprint(showcompact, x)), 0) : - (strlen(m.captures[1]), strlen(m.captures[2])) + m == nothing ? (length(sprint(showcompact, x)), 0) : + (length(m.captures[1]), length(m.captures[2])) end function alignment(x::Rational) m = match(r"^(.*?/)(/.*)$", sprint(showcompact, x)) - m == nothing ? (strlen(sprint(showcompact, x)), 0) : - (strlen(m.captures[1]), strlen(m.captures[2])) + m == nothing ? (length(sprint(showcompact, x)), 0) : + (length(m.captures[1]), length(m.captures[2])) end -const _jl_undef_ref_str = "#undef" -const _jl_undef_ref_alignment = (3,3) +const undef_ref_str = "#undef" +const undef_ref_alignment = (3,3) function alignment( X::AbstractMatrix, @@ -591,26 +577,26 @@ function alignment( if isassigned(X,i,j) aij = alignment(X[i,j]) else - aij = _jl_undef_ref_alignment + aij = undef_ref_alignment end l = max(l, aij[1]) r = max(r, aij[2]) end - push(a, (l, r)) + push!(a, (l, r)) if length(a) > 1 && sum(map(sum,a)) + sep*length(a) >= cols_if_complete - pop(a) + pop!(a) break end end if 1 < length(a) < size(X,2) while sum(map(sum,a)) + sep*length(a) >= cols_otherwise - pop(a) + pop!(a) end end return a end -function print_matrix_row(io, +function print_matrix_row(io::IO, X::AbstractMatrix, A::Vector, i::Integer, cols::AbstractVector, sep::String ) @@ -621,8 +607,8 @@ function print_matrix_row(io, a = alignment(x) sx = sprint(showcompact, x) else - a = _jl_undef_ref_alignment - sx = _jl_undef_ref_str + a = undef_ref_alignment + sx = undef_ref_str end l = repeat(" ", A[k][1]-a[1]) r = repeat(" ", A[k][2]-a[2]) @@ -631,14 +617,14 @@ function print_matrix_row(io, end end -function print_matrix_vdots(io, +function print_matrix_vdots(io::IO, vdots::String, A::Vector, sep::String, M::Integer, m::Integer ) for k = 1:length(A) w = A[k][1] + A[k][2] if k % M == m - l = repeat(" ", max(0, A[k][1]-strlen(vdots))) - r = repeat(" ", max(0, w-strlen(vdots)-strlen(l))) + l = repeat(" ", max(0, A[k][1]-length(vdots))) + r = repeat(" ", max(0, w-length(vdots)-length(l))) print(io, l, vdots, r) else print(io, repeat(" ", w)) @@ -647,17 +633,17 @@ function print_matrix_vdots(io, end end -function print_matrix(io, +function print_matrix(io::IO, X::AbstractMatrix, rows::Integer, cols::Integer, pre::String, sep::String, post::String, hdots::String, vdots::String, ddots::String, hmod::Integer, vmod::Integer ) - cols -= strlen(pre) + strlen(post) - presp = repeat(" ", strlen(pre)) + cols -= length(pre) + length(post) + presp = repeat(" ", length(pre)) postsp = "" @assert strwidth(hdots) == strwidth(ddots) - ss = strlen(sep) + ss = length(sep) m, n = size(X) if m <= rows # rows fit A = alignment(X,1:m,1:n,cols,cols,ss) @@ -669,14 +655,14 @@ function print_matrix(io, if i != m; println(io, ); end end else # rows fit, cols don't - c = div(cols-strlen(hdots)+1,2)+1 + c = div(cols-length(hdots)+1,2)+1 R = reverse(alignment(X,1:m,n:-1:1,c,c,ss)) - c = cols - sum(map(sum,R)) - (length(R)-1)*ss - strlen(hdots) + c = cols - sum(map(sum,R)) - (length(R)-1)*ss - length(hdots) L = alignment(X,1:m,1:n,c,c,ss) for i = 1:m print(io, i == 1 ? pre : presp) print_matrix_row(io, X,L,i,1:length(L),sep) - print(io, i % hmod == 1 ? hdots : repeat(" ", strlen(hdots))) + print(io, i % hmod == 1 ? hdots : repeat(" ", length(hdots))) print_matrix_row(io, X,R,i,n-length(R)+1:n,sep) print(io, i == m ? post : postsp) if i != m; println(io, ); end @@ -699,15 +685,15 @@ function print_matrix(io, end end else # neither rows nor cols fit - c = div(cols-strlen(hdots)+1,2)+1 + c = div(cols-length(hdots)+1,2)+1 R = reverse(alignment(X,I,n:-1:1,c,c,ss)) - c = cols - sum(map(sum,R)) - (length(R)-1)*ss - strlen(hdots) + c = cols - sum(map(sum,R)) - (length(R)-1)*ss - length(hdots) L = alignment(X,I,1:n,c,c,ss) r = mod((length(R)-n+1),vmod) for i in I print(io, i == 1 ? pre : presp) print_matrix_row(io, X,L,i,1:length(L),sep) - print(io, i % hmod == 1 ? hdots : repeat(" ", strlen(hdots))) + print(io, i % hmod == 1 ? hdots : repeat(" ", length(hdots))) print_matrix_row(io, X,R,i,n-length(R)+1:n,sep) print(io, i == m ? post : postsp) if i != I[end]; println(io, ); end @@ -722,11 +708,11 @@ function print_matrix(io, end end end -print_matrix(io, X::AbstractMatrix, rows::Integer, cols::Integer) = +print_matrix(io::IO, X::AbstractMatrix, rows::Integer, cols::Integer) = print_matrix(io, X, rows, cols, " ", " ", "", " \u2026 ", "\u22ee", " \u22f1 ", 5, 5) -print_matrix(io, X::AbstractMatrix) = print_matrix(io, X, tty_rows()-4, tty_cols()) +print_matrix(io::IO, X::AbstractMatrix) = print_matrix(io, X, tty_rows()-4, tty_cols()) summary(x) = string(typeof(x)) @@ -737,17 +723,17 @@ dims2string(d) = length(d) == 0 ? "0-dimensional" : summary{T}(a::AbstractArray{T}) = string(dims2string(size(a)), " ", T, " ", typeof(a).name) -function show_nd(io, a::AbstractArray) +function show_nd(io::IO, a::AbstractArray) if isempty(a) return end tail = size(a)[3:] nd = ndims(a)-2 - function print_slice(io, idxs...) + function print_slice(io::IO, idxs...) for i = 1:nd ii = idxs[i] if size(a,i+2) > 10 - if ii == 4 && allp(x->x==1,idxs[1:i-1]) + if ii == 4 && all(x->x==1,idxs[1:i-1]) for j=i+1:nd szj = size(a,j+2) if szj>10 && 3 < idxs[j] <= szj-3 @@ -774,7 +760,7 @@ function show_nd(io, a::AbstractArray) end function whos(m::Module, pattern::Regex) - for s in sort(map(string, names(m))) + for s in sort!(map(string, names(m))) v = symbol(s) if isdefined(m,v) && ismatch(pattern, s) println(rpad(s, 30), summary(eval(m,v))) @@ -783,19 +769,19 @@ function whos(m::Module, pattern::Regex) end whos() = whos(r"") whos(m::Module) = whos(m, r"") -whos(pat::Regex) = whos(ccall(:jl_get_current_module, Module, ()), pat) +whos(pat::Regex) = whos(ccall(:jl_get_current_module, Any, ())::Module, pat) -function show{T}(io, x::AbstractArray{T,0}) +function show{T}(io::IO, x::AbstractArray{T,0}) println(io, summary(x),":") if isassigned(x) sx = sprint(showcompact, x[]) else - sx = _jl_undef_ref_str + sx = undef_ref_str end print(io, sx) end -function show(io, X::AbstractArray) +function show(io::IO, X::AbstractArray) print(io, summary(X)) if !isempty(X) println(io, ":") @@ -803,7 +789,7 @@ function show(io, X::AbstractArray) end end -function showall(io, X::AbstractMatrix) +function showall(io::IO, X::AbstractMatrix) print(io, summary(X)) if !isempty(X) println(io, ":") @@ -811,7 +797,7 @@ function showall(io, X::AbstractMatrix) end end -function showall(io, a::AbstractArray) +function showall(io::IO, a::AbstractArray) print(io, summary(a)) if isempty(a) return @@ -831,17 +817,22 @@ function showall(io, a::AbstractArray) cartesian_map(print_slice, tail) end -function show_vector(io, v, opn, cls) +function show_vector(io::IO, v, opn, cls) X = reshape(v,(1,length(v))) print_matrix(io, X, 1, tty_cols(), opn, ", ", cls, " \u2026 ", "\u22ee", " \u22f1 ", 5, 5) end -show(io, v::AbstractVector{Any}) = show_vector(io, v, "{", "}") -show(io, v::AbstractVector) = show_vector(io, v, "[", "]") +show(io::IO, v::AbstractVector{Any}) = show_vector(io, v, "{", "}") +show(io::IO, v::AbstractVector) = show_vector(io, v, "[", "]") + +# printing BitArrays + +summary(a::BitArray) = + string(dims2string(size(a)), " ", typeof(a).name) -# printing bit arrays +# (following functions not exported - mainly intended for debug) -function _jl_print_bit_chunk(io::IO, c::Uint64, l::Integer) +function print_bit_chunk(io::IO, c::Uint64, l::Integer) for s = 0 : l - 1 d = (c >>> s) & 1 print(io, "01"[d + 1]) @@ -851,22 +842,22 @@ function _jl_print_bit_chunk(io::IO, c::Uint64, l::Integer) end end -_jl_print_bit_chunk(io::IO, c::Uint64) = _jl_print_bit_chunk(io, c, 64) +print_bit_chunk(io::IO, c::Uint64) = print_bit_chunk(io, c, 64) -_jl_print_bit_chunk(c::Uint64, l::Integer) = _jl_print_bit_chunk(stdout_stream, c, l) -_jl_print_bit_chunk(c::Uint64) = _jl_print_bit_chunk(stdout_stream, c) +print_bit_chunk(c::Uint64, l::Integer) = print_bit_chunk(OUTPUT_STREAM, c, l) +print_bit_chunk(c::Uint64) = print_bit_chunk(OUTPUT_STREAM, c) function bitshow(io::IO, B::BitArray) if length(B) == 0 return end for i = 1 : length(B.chunks) - 1 - _jl_print_bit_chunk(io, B.chunks[i]) + print_bit_chunk(io, B.chunks[i]) print(io, ": ") end l = (@_mod64 (length(B)-1)) + 1 - _jl_print_bit_chunk(io, B.chunks[end], l) + print_bit_chunk(io, B.chunks[end], l) end -bitshow(B::BitArray) = bitshow(stdout_stream, B) +bitshow(B::BitArray) = bitshow(OUTPUT_STREAM, B) bitstring(B::BitArray) = sprint(bitshow, B) diff --git a/base/socket.jl b/base/socket.jl new file mode 100644 index 0000000000000..0cf7f211f906c --- /dev/null +++ b/base/socket.jl @@ -0,0 +1,341 @@ +## IP ADDRESS HANDLING ## +abstract IpAddr + +type IPv4 <: IpAddr + host::Uint32 + IPv4(host::Uint32) = new(host) + IPv4(a::Uint8,b::Uint8,c::Uint8,d::Uint8) = new(uint32(a)<<24| + uint32(b)<<16| + uint32(c)<<8| + d) + function IPv4(a::Integer,b::Integer,c::Integer,d::Integer) + if !(0<=a<=255 && 0<=b<=255 && 0<=c<=255 && 0<=d<=255) + throw(DomainError()) + end + IPv4(uint8(a),uint8(b),uint8(c),uint8(d)) + end +end + +show(io::IO,ip::IPv4) = print(io,"IPv4(",dec((ip.host&(0xFF000000))>>24),".", + dec((ip.host&(0xFF0000))>>16),".", + dec((ip.host&(0xFF00))>>8),".", + dec(ip.host&0xFF),")") + +type IPv6 <: IpAddr + host::Uint128 + IPv6(host::Uint128) = new(host) + IPv6(a::Uint16,b::Uint16,c::Uint16,d::Uint16, + e::Uint16,f::Uint16,g::Uint16,h::Uint16) = new(uint128(a)<<(7*16)| + uint128(b)<<(6*16)| + uint128(c)<<(5*16)| + uint128(d)<<(4*16)| + uint128(e)<<(3*16)| + uint128(f)<<(2*16)| + uint128(g)<<(1*16)| + h) + function IPv6(a::Integer,b::Integer,c::Integer,d::Integer, + e::Integer,f::Integer,g::Integer,h::Integer) + if !(0<=a<=0xFFFF && 0<=b<=0xFFFF && 0<=c<=0xFFFF && 0<=d<=0xFFFF && + 0<=e<=0xFFFF && 0<=f<=0xFFFF && 0<=g<=0xFFFF && 0<=h<=0xFFFF) + throw(DomainError()) + end + IPv6(uint16(a),uint16(b),uint16(c),uint16(d), + uint16(e),uint16(f),uint16(g),uint16(h)) + end +end + +show(io::IO,ip::IPv6) = print(io,"IPv6(", + hex((ip.host&(uint128(0xFFFF)<<(7*16)))>>(7*16)),":", + hex((ip.host&(uint128(0xFFFF)<<(6*16)))>>(7*16)),":", + hex((ip.host&(uint128(0xFFFF)<<(5*16)))>>(7*16)),":", + hex((ip.host&(uint128(0xFFFF)<<(4*16)))>>(7*16)),":", + hex((ip.host&(uint128(0xFFFF)<<(3*16)))>>(7*16)),":", + hex((ip.host&(uint128(0xFFFF)<<(2*16)))>>(7*16)),":", + hex((ip.host&0xFFFF), ")")) + +type InetAddr + host::IpAddr + port::Uint16 + function InetAddr(host,port) + if !(0 <= port <= typemax(Uint16)) + throw(DomainError()) + end + new(host,uint16(port)) + end +end + + +## SOCKETS ## + +abstract Socket <: AsyncStream + +type TcpSocket <: Socket + handle::Ptr{Void} + open::Bool + line_buffered::Bool + buffer::IOBuffer + readcb::Callback + readnotify::Vector{WaitTask} + ccb::Callback + connectnotify::Vector{WaitTask} + closecb::Callback + closenotify::Vector{WaitTask} + TcpSocket(handle,open)=new(handle,open,true,PipeBuffer(),false, + WaitTask[],false,WaitTask[],false,WaitTask[]) + function TcpSocket() + this = TcpSocket(C_NULL,false) + this.handle = ccall(:jl_make_tcp,Ptr{Void},(Ptr{Void},Any), + eventloop(),this) + if (this.handle == C_NULL) + error("Failed to start reading: ",_uv_lasterror()) + end + this + end +end + +type UdpSocket <: Socket + handle::Ptr{Void} + open::Bool + line_buffered::Bool + buffer::IOBuffer + readcb::Callback + readnotify::Vector{WaitTask} + ccb::Callback + connectnotify::Vector{WaitTask} + closecb::Callback + closenotify::Vector{WaitTask} + UdpSocket(handle,open)=new(handle,open,true,PipeBuffer(),false,WaitTask[], + false,WaitTask[],false,WaitTask[]) + function UdpSocket() + this = UdpSocket(C_NULL,false) + this.handle = ccall(:jl_make_tcp,Ptr{Void},(Ptr{Void},Any), + eventloop(),this) + this + end +end + +show(io::IO,sock::TcpSocket) = print(io,"TcpSocket(",sock.open?"connected,": + "disconnected,",nb_available(sock.buffer), + " bytes waiting)") + +show(io::IO,sock::UdpSocket) = print(io,"UdpSocket(",sock.open?"connected,": + "disconnected,",nb_available(sock.buffer), + " bytes waiting)") +_jl_tcp_init(loop::Ptr{Void}) = ccall(:jl_tcp_init,Ptr{Void},(Ptr{Void},),loop) +_jl_udp_init(loop::Ptr{Void}) = ccall(:jl_udp_init,Ptr{Void},(Ptr{Void},),loop) + +## VARIOUS METHODS TO BE MOVED TO BETTER LOCATION + +_jl_connect_raw(sock::TcpSocket,sockaddr::Ptr{Void}) = + ccall(:jl_connect_raw,Int32,(Ptr{Void},Ptr{Void}),sock.handle,sockaddr) +_jl_sockaddr_from_addrinfo(addrinfo::Ptr{Void}) = + ccall(:jl_sockaddr_from_addrinfo,Ptr{Void},(Ptr{Void},),addrinfo) +_jl_sockaddr_set_port(ptr::Ptr{Void},port::Uint16) = + ccall(:jl_sockaddr_set_port,Void,(Ptr{Void},Uint16),ptr,port) + + +## WAITING ## + +accept(server::TcpSocket) = accept(server, TcpSocket()) +function accept(server::TcpSocket, client::TcpSocket) + err = accept_nonblock(server,client) + if err == 0 + return client + else + err = _uv_lasterror() + if err != 4 #EAGAIN + error("accept: ", err, "\n") + end + end + wt = WaitTask() + while true + assert(current_task() != Scheduler, "Cannot execute blocking function from Scheduler") + push!(server.connectnotify,wt) + args = yield(wt) + if isa(args,InterruptException) + error(args) + end + status = args[2]::Int32 + if status == -1 + error("listen: ", _uv_lasterror(), "\n") + end + err = accept_nonblock(server,client) + if err == 0 + return client + else + err = _uv_lasterror() + if err != 4 #EAGAIN + error("accept: ", err, "\n") + end + end + end +end + +## + +bind(sock::Socket, addr::InetAddr) = bind(sock,addr.host,addr.port) +bind(sock::Socket, host::IpAddr, port) = bind(sock, InetAddr(host,port)) + +const UV_SUCCESS = 0 +const UV_EADDRINUSE = 5 + +function bind(sock::TcpSocket, host::IPv4, port::Uint16) + err = ccall(:jl_tcp_bind, Int32, (Ptr{Void}, Uint16, Uint32), + sock.handle, hton(port), hton(host.host)) + if(err == -1 && _uv_lasterror() != UV_EADDRINUSE) + throw(UVError("bind")) + end + err != -1 +end + +bind(sock::TcpSocket, host::IPv6, port::Uint16) = + error("IPv6 Support not fully implemented") + +## + +callback_dict = ObjectIdDict() + +function _uv_hook_getaddrinfo(cb::Function,addrinfo::Ptr{Void}, status::Int32) + delete!(callback_dict,cb) + if(status!=0) + throw(UVError("getaddrinfo callback")) + end + sockaddr = ccall(:jl_sockaddr_from_addrinfo,Ptr{Void},(Ptr{Void},),addrinfo) + if(ccall(:jl_sockaddr_is_ip4,Int,(Ptr{Void},),sockaddr)==1) + cb(IPv4(ntoh(ccall(:jl_sockaddr_host4,Uint32,(Ptr{Void},),sockaddr)))) + else + cb(IPv6(ntoh(ccall(:jl_sockaddr_host6,Uint128,(Ptr{Void},),sockaddr)))) + end +end + +jl_getaddrinfo(loop::Ptr{Void}, host::ByteString, service::Ptr{Void}, + cb::Function) = + ccall(:jl_getaddrinfo, Int32, (Ptr{Void}, Ptr{Uint8}, Ptr{Uint8}, Any), + loop, host, service, cb) + +getaddrinfo(cb::Function,host::ASCIIString) = begin + callback_dict[cb] = cb + jl_getaddrinfo(eventloop(),host,C_NULL,cb) +end + +function getaddrinfo(host::ASCIIString) + wt = WaitTask() + getaddrinfo(host) do IP + tasknotify([wt],IP) + end + (ip,) = yield(wt) + return ip +end + +## + +function connect(cb::Function, sock::TcpSocket, host::IPv4, port::Uint16) + sock.ccb = cb + uv_error("connect",ccall(:jl_tcp4_connect,Int32,(Ptr{Void},Uint32,Uint16), + sock.handle,hton(host.host),hton(port)) == -1) +end + +function connect(sock::TcpSocket, host::IPv4, port::Uint16) + uv_error("connect",ccall(:jl_tcp4_connect,Int32,(Ptr{Void},Uint32,Uint16), + sock.handle,hton(host.host),hton(port)) == -1) + wait_connected(sock) +end + +function connect(sock::TcpSocket, host::ASCIIString, port) + ipaddr = getaddrinfo(host) + connect(sock,ipaddr,port) +end + +function default_connectcb(sock,status) + if status == -1 + throw(UVError("connect callback")) + end +end + +function connect(cb::Function, sock::TcpSocket, host::ASCIIString, port) + getaddrinfo(host) do ipaddr + connect(cb,sock,ipaddr,port) + end +end + + +for (args,forward_args) in (((:(addr::InetAddr),), (:(addr.host),:(addr.port))), + ((:(host::IpAddr),:port),(:(InetAddr(host,port)),)), + ((:(addr::InetAddr),), (:(addr.host),:(addr.port))), + ((:(host::ASCIIString),:port), (:host,:port))) + @eval begin + connect(sock::Socket,$(args...)) = connect(sock,$(forward_args...)) + connect(cb::Function,sock::Socket,$(args...)) = + connect(cb,sock,$(forward_args...)) + function connect($(args...)) + sock = TcpSocket() + sock.ccb = default_connectcb + connect(sock,$(forward_args...)) + sock + end + function connect(cb::Function,$(args...)) + sock = TcpSocket() + sock.ccb = default_connectcb + connect(cb,sock,$(forward_args...)) + sock + end + end +end + +## + +function listen(host::IPv4, port::Uint16) + sock = TcpSocket() + uv_error("listen",!bind(sock,host,port)) + listen(sock) + sock +end +listen(port::Integer) = listen(IPv4(uint32(0)),uint16(port)) +listen(addr::InetAddr) = listen(addr.host,addr.port) +listen(host::IpAddr, port::Uint16) = listen(InetAddr(host,port)) + +listen(cb::Callback,args...) = (sock=listen(args...);sock.ccb=cb;sock) +listen(cb::Callback,sock::Socket) = (sock.ccb=cb;listen(sock)) + +## + +_jl_tcp_accept(server::Ptr{Void},client::Ptr{Void}) = + ccall(:uv_accept,Int32,(Ptr{Void},Ptr{Void}),server,client) +function accept_nonblock(server::TcpSocket,client::TcpSocket) + err = _jl_tcp_accept(server.handle,client.handle) + if err == 0 + client.open = true + end + err +end +function accept_nonblock(server::TcpSocket) + client = TcpSocket() + uv_error("accept",_jl_tcp_accept(server.handle,client.handle) == -1) + client.open = true + client +end + +## Utility functions + +function open_any_tcp_port(cb::Callback,default_port) + addr = InetAddr(IPv4(uint32(0)),default_port) + while true + sock = TcpSocket() + + if (bind(sock,addr) && listen(cb,sock)) + return (addr.port,sock) + end + err = _uv_lasterror() + system = _uv_lastsystemerror() + sock.open = true #need to make close() work + close(sock) + if (err != UV_SUCCESS && err != UV_EADDRINUSE) + throw(UVError("open_any_tcp_port",err,system)) + end + addr.port += 1 + if (addr.port==default_port) + error("Not a single port is available.") + end + end +end +open_any_tcp_port(default_port) = open_any_tcp_port(false,default_port) diff --git a/base/sort.jl b/base/sort.jl index 65d2273df0d8c..17695837c6ea4 100644 --- a/base/sort.jl +++ b/base/sort.jl @@ -1,438 +1,410 @@ -## standard sort comparisons ## - -_jl_fp_pos_lt(x::Float32, y::Float32) = slt_int(unbox(Float32,x),unbox(Float32,y)) -_jl_fp_pos_lt(x::Float64, y::Float64) = slt_int(unbox(Float64,x),unbox(Float64,y)) -_jl_fp_pos_le(x::Float32, y::Float32) = sle_int(unbox(Float32,x),unbox(Float32,y)) -_jl_fp_pos_le(x::Float64, y::Float64) = sle_int(unbox(Float64,x),unbox(Float64,y)) - -_jl_fp_neg_lt(x::Float32, y::Float32) = slt_int(unbox(Float32,y),unbox(Float32,x)) -_jl_fp_neg_lt(x::Float64, y::Float64) = slt_int(unbox(Float64,y),unbox(Float64,x)) -_jl_fp_neg_le(x::Float32, y::Float32) = sle_int(unbox(Float32,y),unbox(Float32,x)) -_jl_fp_neg_le(x::Float64, y::Float64) = sle_int(unbox(Float64,y),unbox(Float64,x)) - -## internal sorting functionality ## - -macro _jl_sort_functions(suffix, lt, args...) -insertionsort = esc(symbol("_jl_insertionsort$suffix")) -quicksort = esc(symbol("_jl_quicksort$suffix")) -mergesort = esc(symbol("_jl_mergesort$suffix")) -pivot_middle = esc(symbol("_jl_pivot_middle$suffix")) -lt = @eval (a,b)->$lt -quote - -# sorting should be stable -# Thus, if a permutation is required, or records are being sorted -# a stable sort should be used. -# If only numbers are being sorted, a faster quicksort can be used. - -# fast sort for small arrays -function ($insertionsort)($(args...), a::AbstractVector, lo::Int, hi::Int) - for i = lo+1:hi - j = i - x = a[i] - while j > lo - if $(lt(:x, :(a[j-1]))) - a[j] = a[j-1] - j -= 1 - continue - end - break - end - a[j] = x +module Sort + +import + Base.sort, + Base.sort!, + Base.issorted, + Base.sortperm + +export # also exported by Base + sort, + sort!, + sortby, + sortby!, + sortperm, + select, + select!, + issorted, + searchsortedfirst, + searchsortedlast, + InsertionSort, + QuickSort, + MergeSort, + TimSort + +export # not exported by Base + Ordering, Algorithm, + Forward, By, Lt, lt, + # Reverse, # TODO: clashes with Reverse iterator + DEFAULT_UNSTABLE, + DEFAULT_STABLE, + SMALL_ALGORITHM, + SMALL_THRESHOLD + +# not exported + # selectby + # selectby! + # sortpermby + +## notions of element ordering ## + +abstract Ordering + +type Forward <: Ordering end +type Reverse <: Ordering end +immutable By <: Ordering by::Function end +immutable Lt <: Ordering lt::Function end + +lt(o::Forward, a, b) = isless(a,b) +lt(o::Reverse, a, b) = isless(b,a) +lt(o::By, a, b) = isless(o.by(a),o.by(b)) +lt(o::Lt, a, b) = o.lt(a,b) + +## functions requiring only ordering ## + +function issorted(itr, o::Ordering) + state = start(itr) + done(itr,state) && return true + prev, state = next(itr, state) + while !done(itr, state) + this, state = next(itr, state) + lt(o, this, prev) && return false + prev = this end - return a + return true end +issorted{T<:Ordering}(itr, ::Type{T}) = issorted(itr, T()) +issorted (itr) = issorted(itr, Forward()) -# permutes an auxilliary array mirroring the sort -function ($insertionsort)($(args...), a::AbstractVector, p::AbstractVector{Int}, lo::Int, hi::Int) - for i = lo+1:hi - j = i - x = a[i] - xp = p[i] - while j > lo - if $(lt(:x, :(a[j-1]))) - a[j] = a[j-1] - p[j] = p[j-1] - j -= 1 - continue - end - break +function select!(v::AbstractVector, k::Int, lo::Int, hi::Int, o::Ordering) + lo <= k <= hi || error("select index $k is out of range $lo:$hi") + while lo < hi + pivot = v[(lo+hi)>>>1] + i, j = lo, hi + while true + while lt(o, v[i], pivot); i += 1; end + while lt(o, pivot, v[j]); j -= 1; end + i <= j || break + v[i], v[j] = v[j], v[i] + i += 1; j -= 1 end - a[j] = x - p[j] = xp + if k <= j + hi = j + elseif i <= k + lo = i + else + return pivot + end + end + return v[lo] +end +select! (v::AbstractVector, k::Int, o::Ordering) = select!(v, k, 1, length(v), o) +select!{T<:Ordering}(v::AbstractVector, k::Int, ::Type{T}) = select!(v, k, T()) +select! (v::AbstractVector, k::Int) = select!(v, k, Forward) + +select (v::AbstractVector, k::Int, o::Ordering) = select!(copy(v), k, o) +select{T<:Ordering}(v::AbstractVector, k::Int, ::Type{T}) = select (v, k, T()) +select (v::AbstractVector, k::Int) = select!(copy(v), k) + +for s in {:select!, :select} + @eval begin + $s(v::AbstractVector, k::Int, lt::Function) = $s(v, k, Sort.Lt(lt)) + $s(lt::Function, v::AbstractVector, k::Int) = $s(v, k, lt) end - return a, p end -($pivot_middle)(a,b,c) = $(lt(:a,:b)) ? ($(lt(:b,:c)) ? b : c) : ($(lt(:a,:c)) ? a : c) +for s in {:selectby!, :selectby} + @eval begin + $s(v::AbstractVector, k::Int, by::Function) = $s(v, k, Sort.By(by)) + $s(by::Function, v::AbstractVector, k::Int) = $s(v, k, by) + end +end -# very fast but unstable -function ($quicksort)($(args...), a::AbstractVector, lo::Int, hi::Int) - while hi > lo - if hi-lo <= 20 - return $(expr(:call, insertionsort, args..., :a, :lo, :hi)) - end - i, j = lo, hi - # pivot = (a[lo]+a[hi])/2 # 1.14x - pivot = a[(lo+hi)>>>1] # 1.15x - # pivot = (a[lo]+a[hi]+a[(lo+hi)>>>1])/3 # 1.16x - # pivot = _jl_pivot_middle(a[lo], a[hi], a[(lo+hi)>>>1]) # 1.23x - # pivot = a[randival(lo,hi)] # 1.28x - while i <= j - while $(lt(:(a[i]), :pivot)); i += 1; end - while $(lt(:pivot, :(a[j]))); j -= 1; end - if i <= j - a[i], a[j] = a[j], a[i] - i += 1 - j -= 1 - end - end - if lo < j - $(expr(:call, quicksort, args..., :a, :lo, :j)) +# reference on sorted binary search: +# http://www.tbray.org/ongoing/When/200x/2003/03/22/Binary + +# index of the first value of vector a that is greater than or equal to x; +# returns length(v)+1 if x is greater than all values in v. +function searchsortedfirst(v::AbstractVector, x, lo::Int, hi::Int, o::Ordering) + lo = lo-1 + hi = hi+1 + while lo < hi-1 + m = (lo+hi)>>>1 + if lt(o, v[m], x) + lo = m + else + hi = m end - lo = i end - return a + return hi end -# less fast & not in-place, but stable -function ($mergesort)($(args...), a::AbstractVector, lo::Int, hi::Int, b::AbstractVector) - if lo < hi - if hi-lo <= 20 - return ($insertionsort)($(args...), a, lo, hi) +# index of the last value of vector a that is less than or equal to x; +# returns 0 if x is less than all values of v. +function searchsortedlast(v::AbstractVector, x, lo::Int, hi::Int, o::Ordering) + lo = lo-1 + hi = hi+1 + while lo < hi-1 + m = (lo+hi)>>>1 + if lt(o, x, v[m]) + hi = m + else + lo = m end + end + return lo +end - m = (lo+hi)>>>1 - ($mergesort)($(args...), a, lo, m, b) - ($mergesort)($(args...), a, m+1, hi, b) +for s in {:searchsortedfirst, :searchsortedlast} + @eval begin + $s (v::AbstractVector, x, o::Ordering) = $s(v, x, 1, length(v), o) + $s{O<:Ordering}(v::AbstractVector, x, ::Type{O}) = $s(v, x, O()) + $s (v::AbstractVector, x) = $s(v, x, Forward()) + end +end - # merge(lo,m,hi) - i = 1 - j = lo - while j <= m - b[i] = a[j] - i += 1 - j += 1 - end +## sorting algorithms ## - i = 1 - k = lo - while k < j <= hi - if $(lt(:(a[j]), :(b[i]))) - a[k] = a[j] - j += 1 - else - a[k] = b[i] - i += 1 +abstract Algorithm + +type InsertionSort <: Algorithm end +type QuickSort <: Algorithm end +type MergeSort <: Algorithm end +type TimSort <: Algorithm end + +const DEFAULT_UNSTABLE = QuickSort() +const DEFAULT_STABLE = MergeSort() +const SMALL_ALGORITHM = InsertionSort() +const SMALL_THRESHOLD = 20 + +sort!(v::AbstractVector, a::Algorithm, o::Ordering) = sort!(v, 1, length(v), a, o) +sort (v::AbstractVector, a::Algorithm, o::Ordering) = sort!(copy(v), a, o) + +sort!{T<:Number}(v::AbstractVector{T}, o::Ordering) = sort!(v, DEFAULT_UNSTABLE, o) +sort {T<:Number}(v::AbstractVector{T}, o::Ordering) = sort (v, DEFAULT_UNSTABLE, o) + +sort!(v::AbstractVector, o::Ordering) = sort!(v, DEFAULT_STABLE, o) +sort (v::AbstractVector, o::Ordering) = sort (v, DEFAULT_STABLE, o) + +function sort!(v::AbstractVector, lo::Int, hi::Int, ::InsertionSort, o::Ordering) + for i = lo+1:hi + j = i + x = v[i] + while j > lo + if lt(o, x, v[j-1]) + v[j] = v[j-1] + j -= 1 + continue end - k += 1 + break end - while k < j - a[k] = b[i] - k += 1 - i += 1 + v[j] = x + end + return v +end + +function sort!(v::AbstractVector, lo::Int, hi::Int, a::QuickSort, o::Ordering) + while lo < hi + hi-lo <= SMALL_THRESHOLD && return sort!(v, lo, hi, SMALL_ALGORITHM, o) + pivot = v[(lo+hi)>>>1] + i, j = lo, hi + while true + while lt(o, v[i], pivot); i += 1; end + while lt(o, pivot, v[j]); j -= 1; end + i <= j || break + v[i], v[j] = v[j], v[i] + i += 1; j -= 1 end + lo < j && sort!(v, lo, j, a, o) + lo = i end - return a + return v end -# permutes auxilliary arrays mirroring the sort -function ($mergesort)($(args...), - a::AbstractVector, p::AbstractVector{Int}, lo::Int, hi::Int, - b::AbstractVector, pb::AbstractVector{Int}) +function sort!(v::AbstractVector, lo::Int, hi::Int, a::MergeSort, o::Ordering, t::AbstractVector) if lo < hi - if hi-lo <= 20 - return ($insertionsort)($(args...), a, p, lo, hi) - end + hi-lo <= SMALL_THRESHOLD && return sort!(v, lo, hi, SMALL_ALGORITHM, o) m = (lo+hi)>>>1 - ($mergesort)($(args...), a, p, lo, m, b, pb) - ($mergesort)($(args...), a, p, m+1, hi, b, pb) + sort!(v, lo, m, a, o, t) + sort!(v, m+1, hi, a, o, t) - # merge(lo,m,hi) - i = 1 - j = lo + i, j = 1, lo while j <= m - b[i] = a[j] - pb[i] = p[j] + t[i] = v[j] i += 1 j += 1 end - i = 1 - k = lo + i, k = 1, lo while k < j <= hi - if $(lt(:(a[j]), :(b[i]))) - a[k] = a[j] - p[k] = p[j] + if lt(o, v[j], t[i]) + v[k] = v[j] j += 1 else - a[k] = b[i] - p[k] = pb[i] + v[k] = t[i] i += 1 end k += 1 end while k < j - a[k] = b[i] - p[k] = pb[i] + v[k] = t[i] k += 1 i += 1 end end - return a, p -end -end; end # quote / macro + return v +end +sort!(v::AbstractVector, lo::Int, hi::Int, a::MergeSort, o::Ordering) = sort!(v, lo, hi, a, o, similar(v)) -@_jl_sort_functions "" :(isless($a,$b)) -@_jl_sort_functions "_r" :(isless($b,$a)) -@_jl_sort_functions "_lt" :(lt($a,$b)) lt::Function -@_jl_sort_functions "_by" :(isless(by($a),by($b))) by::Function +include("timsort.jl") -## external sorting functions ## +## sortperm: the permutation to sort an array ## -sort!{T<:Real}(a::AbstractVector{T}) = _jl_quicksort(a, 1, length(a)) -sortr!{T<:Real}(a::AbstractVector{T}) = _jl_quicksort_r(a, 1, length(a)) -sort!{T}(a::AbstractVector{T}) = _jl_mergesort(a, 1, length(a), Array(T,length(a))) -sortr!{T}(a::AbstractVector{T}) = _jl_mergesort_r(a, 1, length(a), Array(T,length(a))) +immutable Perm{O<:Ordering,V<:AbstractVector} <: Ordering + ord::O + vec::V +end +Perm{O<:Ordering,V<:AbstractVector}(o::O,v::V) = Perm{O,V}(o,v) -sort!{T}(lt::Function, a::AbstractVector{T}) = - _jl_mergesort_lt(lt, a, 1, length(a), Array(T,length(a))) -sort_by!{T}(by::Function, a::AbstractVector{T}) = - _jl_mergesort_by(by, a, 1, length(a), Array(T,length(a))) +lt(p::Perm, a, b) = lt(p.ord, p.vec[a], p.vec[b]) -## special sorting for floating-point arrays ## +sortperm(v::AbstractVector, a::Algorithm, o::Ordering) = sort!([1:length(v)], a, Perm(o,v)) +sortperm(v::AbstractVector, o::Ordering) = sortperm(v, DEFAULT_STABLE, o) -@_jl_sort_functions "_fp_pos" :(_jl_fp_pos_lt($a,$b)) -@_jl_sort_functions "_fp_neg" :(_jl_fp_neg_lt($a,$b)) +############## -# push NaNs to the end of a, returning # of non-NaNs -function _jl_nans_to_end{T<:FloatingPoint}(a::AbstractVector{T}) - n = length(a) - if n <= 1 - return n - end - i = 1 - while (i < n) & (a[i]==a[i]) - i += 1 - end - nnan = 0 - while true - if a[i]==a[i] - i += 1 - else - nnan += 1 - end - if i+nnan > n - break - end - if nnan > 0 - a[i], a[i+nnan] = a[i+nnan], a[i] - end - end - return n-nnan -end +# generic sorting methods -function sort!{T<:FloatingPoint}(a::AbstractVector{T}) - n = _jl_nans_to_end(a) - i, j = 1, n - while true - # TODO: faster positive negative int check? - while i <= j && _jl_fp_pos_lt(a[i],zero(T)); i += 1; end - while i <= j && _jl_fp_pos_le(zero(T),a[j]); j -= 1; end - if i <= j - a[i], a[j] = a[j], a[i] - i += 1 - j -= 1 - else - break - end - end - _jl_quicksort_fp_neg(a, 1, j) - _jl_quicksort_fp_pos(a, i, n) - return a -end +for s in {:sort!, :sort, :sortperm} + @eval begin + # default to forward sort ordering + $s(v::AbstractVector, a::Algorithm) = $s(v, a, Forward()) + $s(v::AbstractVector ) = $s(v, Forward()) -# TODO: something sensible should happen when each_col et. al. are used with a -# pure function argument -function each_col!(f::Function, a::AbstractMatrix) - m = size(a,1) - for i = 1:m:numel(a) - f(sub(a, i:(i+m-1))) - end - return a -end + # auto-instntiate algorithms and orderings from types + $s{A<:Algorithm,O<:Ordering}(v::AbstractVector, ::Type{A}, ::Type{O}) = $s(v, A(), O()) + $s{A<:Algorithm }(v::AbstractVector, ::Type{A}, o::Ordering) = $s(v, A(), o) + $s{ O<:Ordering}(v::AbstractVector, a::Algorithm, ::Type{O}) = $s(v, a, O()) + $s{A<:Algorithm }(v::AbstractVector, ::Type{A}) = $s(v, A()) + $s{ O<:Ordering}(v::AbstractVector, ::Type{O}) = $s(v, O()) -function each_row!(f::Function, a::AbstractMatrix) - m = size(a,1) - for i = 1:m - f(sub(a, i:m:numel(a))) + # also allow ordering before algorithm + $s (v::AbstractVector, o::Ordering, a::Algorithm) = $s(v, a, o) + $s{A<:Algorithm,O<:Ordering}(v::AbstractVector, ::Type{O}, ::Type{A}) = $s(v, A(), O()) + $s{A<:Algorithm }(v::AbstractVector, o::Ordering, ::Type{A}) = $s(v, A(), o) + $s{ O<:Ordering}(v::AbstractVector, ::Type{O}, a::Algorithm) = $s(v, a, O()) end - return a end -function each_vec!(f::Function, a::AbstractMatrix, dim::Integer) - if dim == 1; return each_col!(f,a); end - if dim == 2; return each_row!(f,a); end - error("invalid matrix dimensions: $dim") -end - -each_col(f::Function, a::AbstractMatrix) = each_col!(f,copy(a)) -each_row(f::Function, a::AbstractMatrix) = each_row!(f,copy(a)) -each_vec(f::Function, a::AbstractMatrix, d::Integer) = each_vec!(f,copy(a),d) - -## other sorting functions defined in terms of sort! ## - -macro in_place_matrix_op(out_of_place, args...) - in_place = esc(symbol("$(out_of_place)!")) - out_of_place = esc(out_of_place) - quote - function ($in_place)($(args...), a::AbstractMatrix, dim::Int) - m = size(a,1) - if dim == 1 - for i = 1:m:numel(a) - ($in_place)($(args...), sub(a, i:(i+m-1))) - end - elseif dim == 2 - for i = 1:m - ($in_place)($(args...), sub(a, i:m:numel(a))) - end - end - return a - end - # TODO: in-place generalized AbstractArray implementation - ($in_place)($(args...), a::AbstractArray) = ($in_place)($(args...), a,1) - - ($out_of_place)($(args...), a::AbstractVector) = ($in_place)($(args...), copy(a)) - ($out_of_place)($(args...), a::AbstractArray, d::Int) = ($in_place)($(args...), copy(a), d) - ($out_of_place)($(args...), a::AbstractArray) = ($out_of_place)($(args...), a,1) +for s in {:sort!, :sort, :sortperm} + @eval begin + $s{A<:Algorithm}(v::AbstractVector, a::Union(A,Type{A}), lt::Function) = $s(v, a, Sort.Lt(lt)) + $s{A<:Algorithm}(v::AbstractVector, lt::Function, a::Union(A,Type{A})) = $s(v, a, lt) + $s (v::AbstractVector, lt::Function) = $s(v, Sort.Lt(lt)) + $s (lt::Function, v::AbstractVector, args...) = $s(v, lt, args...) end end -@in_place_matrix_op sort -@in_place_matrix_op sort lt::Function -@in_place_matrix_op sortr -@in_place_matrix_op sort_by by::Function - -# TODO: implement generalized in-place, ditch this -function sort(a::AbstractArray, dim::Int) - X = similar(a) - n = size(a,dim) - if dim == 1 - for i = 1:n:numel(a) - this_slice = i:(i+n-1) - X[this_slice] = sort(sub(a, this_slice)) - end - else - p = [1:ndims(a)] - p[dim], p[1] = p[1], p[dim] - X = ipermute(sort(permute(a, p)), p) +for (sb,s) in {(:sortby!, :sort!), (:sortby, :sort), (:sortpermby, :sortperm)} + @eval begin + $sb{A<:Algorithm}(v::AbstractVector, a::Union(A,Type{A}), by::Function) = $s(v, a, Sort.By(by)) + $sb{A<:Algorithm}(v::AbstractVector, by::Function, a::Union(A,Type{A})) = $s(v, a, Sort.By(by)) + $sb (v::AbstractVector, by::Function) = $s(v, Sort.By(by)) + $sb (by::Function, v::AbstractVector, args...) = $s(v, Sort.By(by), args...) end - return X end -sortperm{T}(a::AbstractVector{T}) = - _jl_mergesort(copy(a), [1:length(a)], 1, length(a), - Array(T, length(a)), Array(Int, length(a))) - -function issorted(v::AbstractVector) - for i = 1:length(v)-1 - if isless(v[i+1], v[i]) - return false - end - end - return true -end +## fast clever sorting for floats ## -function _jl_quickselect(a::AbstractArray, k::Int, lo::Int, hi::Int) - if k < lo || k > hi; error("k is out of bounds"); end +module Float +using Sort - while true +import Sort.sort!, Sort.Perm, Sort.lt, Sort.Reverse +import Intrinsics.slt_int, Intrinsics.unbox - if lo == hi; return a[lo]; end +typealias Floats Union(Float32,Float64) +typealias Direct Union(Forward,Reverse) - i, j = lo, hi - pivot = _jl_pivot_middle(a[lo], a[hi], a[(lo+hi)>>>1]) - while i < j - while isless(a[i], pivot); i += 1; end - while isless(pivot, a[j]); j -= 1; end - if isequal(a[i], a[j]) - i += 1 - elseif i < j - a[i], a[j] = a[j], a[i] - end - end - pivot_ind = j +type Left <: Ordering end +type Right <: Ordering end - length = pivot_ind - lo + 1 - if k == length - return a[pivot_ind] - elseif k < length - hi = pivot_ind - 1 - else - lo = pivot_ind + 1 - k = k - length - end - - end # while true... +left(::Direct) = Left() +right(::Direct) = Right() -end +left{O<:Direct}(o::Perm{O}) = Perm(left(O()),o.vec) +right{O<:Direct}(o::Perm{O}) = Perm(right(O()),o.vec) -select(a::AbstractArray, k::Int) = _jl_quickselect(copy(a), k, 1, length(a)) -select!(a::AbstractArray, k::Int) = _jl_quickselect(a, k, 1, length(a)) +lt{T<:Floats}(::Left, x::T, y::T) = slt_int(unbox(T,y),unbox(T,x)) +lt{T<:Floats}(::Right, x::T, y::T) = slt_int(unbox(T,x),unbox(T,y)) -search_sorted(a::Vector, x) = search_sorted(a, x, 1, length(a)) +isnan(o::Direct, x::Floats) = (x!=x) +isnan{O<:Direct}(o::Perm{O}, i::Int) = isnan(O(),o.vec[i]) -function search_sorted(a::Vector, x, lo::Int, hi::Int) - if isless(a[hi], x) - return hi+1 +function nans2left!(v::AbstractVector, lo::Int, hi::Int, o::Ordering) + hi < lo && return lo, hi + i = lo + while (i < hi) & isnan(o, v[i]) + i += 1 end - while lo < hi-1 - i = (lo+hi)>>>1 - if isless(x,a[i]) - hi = i + r = 0 + while true + if isnan(o, v[i]) + i += 1 else - lo = i + r += 1 + end + j = i + r + j > hi && break + if r > 0 + v[i], v[j] = v[j], v[i] end end - return isless(a[lo],x) ? hi : lo + return i, hi end - -search_sorted_last(a::Vector, x) = search_sorted_last(a, x, 0, length(a)+1) - -function search_sorted_last(a::Vector, x, lo::Int, hi::Int) - ## Index of the last value of vector a that is less than or equal to x. - ## Returns 0 if x is less than all values of a. - ## - ## Good reference: http://www.tbray.org/ongoing/When/200x/2003/03/22/Binary - while lo < hi-1 - i = (lo+hi)>>>1 - if isless(x,a[i]) - hi = i +function nans2right!(v::AbstractVector, lo::Int, hi::Int, o::Ordering) + hi < lo && return lo, hi + i = hi + while (i > lo) & isnan(o, v[i]) + i -= 1 + end + r = 0 + while true + if isnan(o, v[i]) + i -= 1 else - lo = i + r += 1 + end + j = i - r + j < lo && break + if r > 0 + v[i], v[j] = v[j], v[i] end end - lo + return lo, i end +nans2left!(v::AbstractVector, o::Ordering) = nans2left!(v, 1, length(v), o) +nans2right!(v::AbstractVector, o::Ordering) = nans2right!(v, 1, length(v), o) -search_sorted_first(a::Vector, x) = search_sorted_first(a, x, 0, length(a)+1) +nans2end!(v::AbstractVector, o::Forward) = nans2right!(v, o) +nans2end!(v::AbstractVector, o::Reverse) = nans2left!(v, o) +nans2end!{O<:Forward}(v::AbstractVector{Int}, o::Perm{O}) = nans2right!(v, o) +nans2end!{O<:Reverse}(v::AbstractVector{Int}, o::Perm{O}) = nans2left!(v, o) -function search_sorted_first(a::Vector, x, lo::Int, hi::Int) - ## Index of the first value of vector a that is greater than or equal to x. - ## Returns length(a) + 1 if x is greater than all values in a. - ## - ## Good reference: http://www.tbray.org/ongoing/When/200x/2003/03/22/Binary - while lo < hi-1 - i = (lo+hi)>>>1 - if isless(a[i],x) - lo = i +issignleft(o::Direct, x::Floats) = lt(o, x, zero(x)) +issignleft{O<:Direct}(o::Perm{O}, i::Int) = issignleft(O(), o.vec[i]) + +function fpsort!(v::AbstractVector, a::Algorithm, o::Ordering) + i, j = lo, hi = nans2end!(v,o) + while true + while i <= j && issignleft(o, v[i]); i += 1; end + while i <= j && !issignleft(o, v[j]); j -= 1; end + if i <= j + v[i], v[j] = v[j], v[i] + i += 1 + j -= 1 else - hi = i + break end end - hi + sort!(v, lo, j, a, left(o)) + sort!(v, i, hi, a, right(o)) + return v end +sort!{T<:Floats}(v::AbstractVector{T}, a::Algorithm, o::Direct) = fpsort!(v, a, o) +sort!{O<:Direct,T<:Floats}(v::Vector{Int}, a::Algorithm, o::Perm{O,Vector{T}}) = fpsort!(v, a, o) + +end # module Sort.Float -order(a::AbstractVector) = sortperm(a)[2] +end # module Sort diff --git a/base/sparse.jl b/base/sparse.jl index 65cce338b4490..49de22084146d 100644 --- a/base/sparse.jl +++ b/base/sparse.jl @@ -18,24 +18,14 @@ type SparseMatrixCSC{Tv,Ti<:Integer} <: AbstractSparseMatrix{Tv,Ti} nzval::Vector{Tv} # Nonzero values end -function SparseMatrixCSC(Tv::Type, m::Int, n::Int, numnz::Integer) - colptr = Array(Int, n+1) - rowval = Array(Int, numnz) - nzval = Array(Tv, numnz) - - colptr[1] = 1 - colptr[end] = numnz+1 - SparseMatrixCSC{Tv,Int}(m, n, colptr, rowval, nzval) -end - -function SparseMatrixCSC(Tv::Type, Ti::Type, m::Int, n::Int, numnz::Integer) +function SparseMatrixCSC(Tv::Type, Ti::Type, m::Integer, n::Integer, numnz::Integer) colptr = Array(Ti, n+1) rowval = Array(Ti, numnz) nzval = Array(Tv, numnz) colptr[1] = 1 colptr[end] = numnz+1 - SparseMatrixCSC{Tv,Ti}(m, n, colptr, rowval, nzval) + SparseMatrixCSC{Tv,Ti}(int(m), int(n), colptr, rowval, nzval) end function SparseMatrixCSC(m::Integer, n::Integer, colptr::Vector, rowval::Vector, nzval::Vector) @@ -43,9 +33,9 @@ function SparseMatrixCSC(m::Integer, n::Integer, colptr::Vector, rowval::Vector, end size(S::SparseMatrixCSC) = (S.m, S.n) -nnz(S::SparseMatrixCSC) = S.colptr[end]-1 +nnz(S::SparseMatrixCSC) = int(S.colptr[end]-1) -function show(io, S::SparseMatrixCSC) +function show(io::IO, S::SparseMatrixCSC) println(io, S.m, "x", S.n, " sparse matrix with ", nnz(S), " nonzeros:") half_screen_rows = div(tty_rows() - 8, 2) @@ -56,7 +46,7 @@ function show(io, S::SparseMatrixCSC) println(io, "\t[", rpad(S.rowval[k], pad), ", ", lpad(col, pad), "] = ", sprint(showcompact, S.nzval[k])) elseif k == half_screen_rows - println(io, "\t."); println(io, "\t."); println(io, "\t."); + println("\t\u22ee") end k += 1 end @@ -68,14 +58,14 @@ function reinterpret{T,Tv,Ti}(::Type{T}, a::SparseMatrixCSC{Tv,Ti}) if sizeof(T) != sizeof(Tv) error("SparseMatrixCSC reinterpret is only supported for element types of the same size") end - mA,nA = size(a) + mA, nA = size(a) colptr = copy(a.colptr) rowval = copy(a.rowval) - nzval = reinterpret(T, a.nzval) + nzval = reinterpret(Tv, a.nzval) return SparseMatrixCSC{T,Ti}(mA, nA, colptr, rowval, nzval) end -function _jl_sparse_compute_reshaped_colptr_and_rowval(colptrS, rowvalS, mS, nS, colptrA, rowvalA, mA, nA) +function sparse_compute_reshaped_colptr_and_rowval(colptrS, rowvalS, mS, nS, colptrA, rowvalA, mA, nA) colptrS[1] = 1 colA = 1 @@ -107,7 +97,7 @@ function reinterpret{T,Tv,Ti,N}(::Type{T}, a::SparseMatrixCSC{Tv,Ti}, dims::NTup if sizeof(T) != sizeof(Tv) error("SparseMatrixCSC reinterpret is only supported for element types of the same size") end - if prod(dims) != numel(a) + if prod(dims) != length(a) error("reinterpret: invalid dimensions") end mS,nS = dims @@ -117,13 +107,13 @@ function reinterpret{T,Tv,Ti,N}(::Type{T}, a::SparseMatrixCSC{Tv,Ti}, dims::NTup rowval = Array(Ti, numnz) nzval = reinterpret(T, a.nzval) - _jl_sparse_compute_reshaped_colptr_and_rowval(colptr, rowval, mS, nS, a.colptr, a.rowval, mA, nA) + sparse_compute_reshaped_colptr_and_rowval(colptr, rowval, mS, nS, a.colptr, a.rowval, mA, nA) return SparseMatrixCSC{T,Ti}(mS, nS, colptr, rowval, nzval) end function reshape{Tv,Ti}(a::SparseMatrixCSC{Tv,Ti}, dims::NTuple{2,Int}) - if prod(dims) != numel(a) + if prod(dims) != length(a) error("reshape: invalid dimensions") end mS,nS = dims @@ -133,7 +123,7 @@ function reshape{Tv,Ti}(a::SparseMatrixCSC{Tv,Ti}, dims::NTuple{2,Int}) rowval = Array(Ti, numnz) nzval = a.nzval - _jl_sparse_compute_reshaped_colptr_and_rowval(colptr, rowval, mS, nS, a.colptr, a.rowval, mA, nA) + sparse_compute_reshaped_colptr_and_rowval(colptr, rowval, mS, nS, a.colptr, a.rowval, mA, nA) return SparseMatrixCSC{Tv,Ti}(mS, nS, colptr, rowval, nzval) end @@ -143,9 +133,11 @@ end copy(S::SparseMatrixCSC) = SparseMatrixCSC(S.m, S.n, copy(S.colptr), copy(S.rowval), copy(S.nzval)) -similar(S::SparseMatrixCSC, Tv::Type) = +similar(S::SparseMatrixCSC, Tv::NonTupleType) = SparseMatrixCSC(S.m, S.n, similar(S.colptr), similar(S.rowval), Array(Tv, length(S.rowval))) +similar(S::SparseMatrixCSC, Tv::Type, d::(Int,Int)) = spzeros(Tv, d[1], d[2]) + function similar(A::SparseMatrixCSC, Tv::Type, Ti::Type) colptrA = A.colptr; rowvalA = A.rowval; nzvalA = A.nzval @@ -164,32 +156,67 @@ function similar(A::SparseMatrixCSC, Tv::Type, Ti::Type) SparseMatrixCSC(S.m, S.n, similar(S.colptr), similar(S.rowval), Array(Tv, length(S.rowval))) end -function convert{T}(::Type{Matrix{T}}, S::SparseMatrixCSC{T}) - A = zeros(T, int(S.m), int(S.n)) +function convert{Tv,Ti,TvS,TiS}(::Type{SparseMatrixCSC{Tv,Ti}}, S::SparseMatrixCSC{TvS,TiS}) + if Tv == TvS && Ti == TiS + return S + else + return SparseMatrixCSC(S.m, S.n, + convert(Vector{Ti},S.colptr), + convert(Vector{Ti},S.rowval), + convert(Vector{Tv},S.nzval)) + end +end + +convert(::Type{SparseMatrixCSC}, M::Matrix) = sparse(M) + +convert(::Type{Matrix}, S::SparseMatrixCSC) = dense(S) + +full(S::SparseMatrixCSC) = dense(S) + +function dense{Tv}(S::SparseMatrixCSC{Tv}) + A = zeros(Tv, S.m, S.n) for col = 1 : S.n, k = S.colptr[col] : (S.colptr[col+1]-1) A[S.rowval[k], col] = S.nzval[k] end return A end -dense{T}(S::SparseMatrixCSC{T}) = convert(Matrix{T}, S) -full(S::SparseMatrixCSC) = dense(S) +# Construct a sparse vector + +sparsevec{K<:Integer,V}(d::Dict{K,V}, len::Int) = sparsevec(keys(d), values(d), len) + +sparsevec{K<:Integer,V}(d::Dict{K,V}) = sparsevec(keys(d), values(d)) + +sparsevec(I::AbstractVector, V, m::Integer) = sparsevec(I, V, m, +) + +sparsevec(I::AbstractVector, V) = sparsevec(I, V, max(I), +) + +function sparsevec(I::AbstractVector, V, m::Integer, combine::Function) + nI = length(I) + if isa(V, Number); V = fill(V, nI); end + p = sortperm(I) + I = I[p] + V = V[p] + sparse_IJ_sorted!(I, ones(Int, nI), V, m, 1, combine) +end -function sparse(a::Vector) - n = numel(a) +function sparsevec(a::Vector) + n = length(a) I = find(a) J = ones(Int, n) V = nonzeros(a) return sparse_IJ_sorted!(I,J,V,n,1,+) end +sparse(a::Vector) = sparsevec(a) + function sparse(A::Matrix) m, n = size(A) - (I, J, V) = findn_nzs(A) + (I, J, V) = findnz(A) return sparse_IJ_sorted!(I,J,V,m,n) end -sparse(S::SparseMatrixCSC) = S +sparse(S::SparseMatrixCSC) = copy(S) sparse_IJ_sorted!(I,J,V,m,n) = sparse_IJ_sorted!(I,J,V,m,n,+) @@ -197,7 +224,11 @@ sparse_IJ_sorted!(I,J,V::AbstractVector{Bool},m,n) = sparse_IJ_sorted!(I,J,V,m,n function sparse_IJ_sorted!{Ti<:Integer}(I::AbstractVector{Ti}, J::AbstractVector{Ti}, V::AbstractVector, - m::Int, n::Int, combine::Function) + m::Integer, n::Integer, combine::Function) + + m = m < 0 ? 0 : m + n = n < 0 ? 0 : n + if length(V) == 0; return spzeros(m,n); end cols = zeros(Ti, n+1) cols[1] = 1 # For cumsum purposes @@ -250,10 +281,12 @@ sparse(I,J,V::AbstractVector{Bool},m,n) = sparse(I, J, V, int(m), int(n), |) sparse(I,J,v::Number,m,n,combine::Function) = sparse(I, J, fill(v,length(I)), int(m), int(n), combine) -# Based on http://www.cise.ufl.edu/research/sparse/cholmod/CHOLMOD/Core/cholmod_triplet.c +# Based on Direct Methods for Sparse Linear Systems, T. A. Davis, SIAM, Philadelphia, Sept. 2006. +# Section 2.4: Triplet form +# http://www.cise.ufl.edu/research/sparse/CSparse/ function sparse{Tv,Ti<:Integer}(I::AbstractVector{Ti}, J::AbstractVector{Ti}, V::AbstractVector{Tv}, - nrow::Int, ncol::Int, combine::Function) + nrow::Integer, ncol::Integer, combine::Function) if length(I) == 0; return spzeros(eltype(V),nrow,ncol); end @@ -377,7 +410,7 @@ function findn{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}) return (I, J) end -function findn_nzs{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}) +function findnz{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}) numnz = nnz(S) I = Array(Ti, numnz) J = Array(Ti, numnz) @@ -404,10 +437,10 @@ function findn_nzs{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}) return (I, J, V) end -function sprand(m::Int, n::Int, density::FloatingPoint, rng::Function, v) +function sprand(m::Integer, n::Integer, density::FloatingPoint, rng::Function, v) numnz = int(m*n*density) - I = randival!(1, m, Array(Int, numnz)) - J = randival!(1, n, Array(Int, numnz)) + I = rand!(1:m, Array(Int, numnz)) + J = rand!(1:n, Array(Int, numnz)) S = sparse(I, J, v, m, n) if !isbool(v) S.nzval = rng(nnz(S)) @@ -416,26 +449,26 @@ function sprand(m::Int, n::Int, density::FloatingPoint, rng::Function, v) return S end -sprand(m::Int, n::Int, density::FloatingPoint, rng::Function) = sprand(m,n,density,rng, 1.0) -sprand(m::Int, n::Int, density::FloatingPoint) = sprand(m,n,density,rand, 1.0) -sprandn(m::Int, n::Int, density::FloatingPoint) = sprand(m,n,density,randn, 1.0) -sprandbool(m::Int, n::Int, density::FloatingPoint) = sprand(m,n,density,randbool, true) +sprand(m::Integer, n::Integer, density::FloatingPoint, rng::Function) = sprand(m,n,density,rng, 1.0) +sprand(m::Integer, n::Integer, density::FloatingPoint) = sprand(m,n,density,rand, 1.0) +sprandn(m::Integer, n::Integer, density::FloatingPoint) = sprand(m,n,density,randn, 1.0) +sprandbool(m::Integer, n::Integer, density::FloatingPoint) = sprand(m,n,density,randbool, true) spones{T}(S::SparseMatrixCSC{T}) = SparseMatrixCSC(S.m, S.n, copy(S.colptr), copy(S.rowval), ones(T, S.colptr[end]-1)) -spzeros(m::Int) = spzeros(m, m) -spzeros(m::Int, n::Int) = spzeros(Float64, m, n) -spzeros(Tv::Type, m::Int) = spzeros(Tv, m, m) -spzeros(Tv::Type, m::Int, n::Int) = +spzeros(m::Integer) = spzeros(m, m) +spzeros(m::Integer, n::Integer) = spzeros(Float64, m, n) +spzeros(Tv::Type, m::Integer) = spzeros(Tv, m, m) +spzeros(Tv::Type, m::Integer, n::Integer) = SparseMatrixCSC(m, n, ones(Int, n+1), Array(Int, 0), Array(Tv, 0)) -speye(n::Int) = speye(Float64, n) -speye(T::Type, n::Int) = speye(T, n, n) -speye(m::Int, n::Int) = speye(Float64, m, n) +speye(n::Integer) = speye(Float64, n) +speye(T::Type, n::Integer) = speye(T, n, n) +speye(m::Integer, n::Integer) = speye(Float64, m, n) speye{T}(S::SparseMatrixCSC{T}) = speye(T, size(S, 1), size(S, 2)) -function speye(T::Type, m::Int, n::Int) +function speye(T::Type, m::Integer, n::Integer) x = min(m,n) rowval = [1:x] colptr = [rowval, fill(int(x+1), n+1-x)] @@ -451,7 +484,9 @@ end ## Transpose -# Based on: http://www.cise.ufl.edu/research/sparse/CSparse/CSparse/Source/cs_transpose.c +# Based on Direct Methods for Sparse Linear Systems, T. A. Davis, SIAM, Philadelphia, Sept. 2006. +# Section 2.5: Transpose +# http://www.cise.ufl.edu/research/sparse/CSparse/ function transpose{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}) (nT, mT) = size(S) nnzS = nnz(S) @@ -510,12 +545,12 @@ function ctranspose{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}) SparseMatrixCSC(mT, nT, colptr_T, rowval_T, nzval_T) end -## Unary arithmetic operators +## Unary arithmetic and boolean operators for op in (:-, ) @eval begin - function ($op){Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}) + function ($op)(A::SparseMatrixCSC) B = copy(A) nzvalB = B.nzval for i=1:length(nzvalB) @@ -527,11 +562,20 @@ for op in (:-, ) end end -## Binary arithmetic operators +## Binary arithmetic and boolean operators -for op in (:+, :-, :.*, :.^) +for (op, restype) in ( (:+, Nothing), (:-, Nothing), (:.*, Nothing), (:.^, Nothing), + (:(.<), Bool) ) @eval begin + function ($op){TvA,TiA,TvB,TiB}(A::SparseMatrixCSC{TvA,TiA}, B::SparseMatrixCSC{TvB,TiB}) + Tv = promote_type(TvA, TvB) + Ti = promote_type(TiA, TiB) + A = convert(SparseMatrixCSC{Tv,Ti}, A) + B = convert(SparseMatrixCSC{Tv,Ti}, B) + return ($op)(A, B) + end + function ($op){Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, B::SparseMatrixCSC{Tv,Ti}) if size(A,1) != size(B,1) || size(A,2) != size(B,2) error("Incompatible sizes") @@ -543,7 +587,11 @@ for op in (:+, :-, :.*, :.^) nnzS = nnz(A) + nnz(B) colptrS = Array(Ti, A.n+1) rowvalS = Array(Ti, nnzS) - nzvalS = Array(Tv, nnzS) + if $restype == Nothing + nzvalS = Array(Tv, nnzS) + else + nzvalS = Array($restype, nnzS) + end z = zero(Tv) @@ -615,8 +663,8 @@ for op in (:+, :-, :.*, :.^) colptrS[col+1] = ptrS end - rowvalS = del(rowvalS, colptrS[end]:length(rowvalS)) - nzvalCS = del(nzvalS, colptrS[end]:length(nzvalS)) + delete!(rowvalS, colptrS[end]:length(rowvalS)) + delete!(nzvalS, colptrS[end]:length(nzvalS)) return SparseMatrixCSC(m, n, colptrS, rowvalS, nzvalS) end @@ -651,10 +699,13 @@ end # macro (.^)(A::SparseMatrixCSC, B::Array) = (.^)(dense(A), B) (.^)(A::Array, B::SparseMatrixCSC) = (.^)(A, dense(B)) +(.<)(A::SparseMatrixCSC, B::Number) = (.<)(dense(A), B) +(.<)(A::Number, B::SparseMatrixCSC) = (.<)(A, dense(B)) + # Reductions # TODO: Should the results of sparse reductions be sparse? -function areduce{Tv,Ti}(f::Function, A::SparseMatrixCSC{Tv,Ti}, region::Dimspec, v0) +function reducedim{Tv,Ti}(f::Function, A::SparseMatrixCSC{Tv,Ti}, region, v0) if region == 1 S = Array(Tv, 1, A.n) @@ -701,28 +752,32 @@ function areduce{Tv,Ti}(f::Function, A::SparseMatrixCSC{Tv,Ti}, region::Dimspec, end end -max{T}(A::SparseMatrixCSC{T}) = areduce(max,A,(1,2),typemin(T)) -max{T}(A::SparseMatrixCSC{T}, b::(), region::Dimspec) = areduce(max,A,region,typemin(T)) +max{T}(A::SparseMatrixCSC{T}) = + isempty(A) ? error("max: argument is empty") : reducedim(max,A,(1,2),typemin(T)) +max{T}(A::SparseMatrixCSC{T}, b::(), region) = + isempty(A) ? similar(A, reduced_dims0(A,region)) : reducedim(max,A,region,typemin(T)) -min{T}(A::SparseMatrixCSC{T}) = areduce(min,A,(1,2),typemax(T)) -min{T}(A::SparseMatrixCSC{T}, b::(), region::Dimspec) = areduce(min,A,region,typemax(T)) +min{T}(A::SparseMatrixCSC{T}) = + isempty(A) ? error("min: argument is empty") : reducedim(min,A,(1,2),typemax(T)) +min{T}(A::SparseMatrixCSC{T}, b::(), region) = + isempty(A) ? similar(A, reduced_dims0(A,region)) : reducedim(min,A,region,typemax(T)) -sum{T}(A::SparseMatrixCSC{T}) = areduce(+,A,(1,2),zero(T)) -sum{T}(A::SparseMatrixCSC{T}, region::Dimspec) = areduce(+,A,region,zero(T)) +sum{T}(A::SparseMatrixCSC{T}) = reducedim(+,A,(1,2),zero(T)) +sum{T}(A::SparseMatrixCSC{T}, region) = reducedim(+,A,region,zero(T)) -prod{T}(A::SparseMatrixCSC{T}) = areduce(*,A,(1,2),one(T)) -prod{T}(A::SparseMatrixCSC{T}, region::Dimspec) = areduce(*,A,region,one(T)) +prod{T}(A::SparseMatrixCSC{T}) = reducedim(*,A,(1,2),one(T)) +prod{T}(A::SparseMatrixCSC{T}, region) = reducedim(*,A,region,one(T)) -#all(A::SparseMatrixCSC{Bool}, region::Dimspec) = areduce(all,A,region,true) -#any(A::SparseMatrixCSC{Bool}, region::Dimspec) = areduce(any,A,region,false) -#sum(A::SparseMatrixCSC{Bool}, region::Dimspec) = areduce(+,A,region,0,Int) +#all(A::SparseMatrixCSC{Bool}, region) = reducedim(all,A,region,true) +#any(A::SparseMatrixCSC{Bool}, region) = reducedim(any,A,region,false) +#sum(A::SparseMatrixCSC{Bool}, region) = reducedim(+,A,region,0,Int) #sum(A::SparseMatrixCSC{Bool}) = nnz(A) -## ref -ref(A::SparseMatrixCSC, i::Integer) = ref(A, ind2sub(size(A),i)) -ref(A::SparseMatrixCSC, I::(Integer,Integer)) = ref(A, I[1], I[2]) +## getindex +getindex(A::SparseMatrixCSC, i::Integer) = getindex(A, ind2sub(size(A),i)) +getindex(A::SparseMatrixCSC, I::(Integer,Integer)) = getindex(A, I[1], I[2]) -function ref{T}(A::SparseMatrixCSC{T}, i0::Integer, i1::Integer) +function getindex{T}(A::SparseMatrixCSC{T}, i0::Integer, i1::Integer) if !(1 <= i0 <= A.m && 1 <= i1 <= A.n); error(BoundsError); end first = A.colptr[i1] last = A.colptr[i1+1]-1 @@ -740,10 +795,10 @@ function ref{T}(A::SparseMatrixCSC{T}, i0::Integer, i1::Integer) return zero(T) end -ref{T<:Integer}(A::SparseMatrixCSC, I::AbstractVector{T}, j::Integer) = ref(A,I,[j]) -ref{T<:Integer}(A::SparseMatrixCSC, i::Integer, J::AbstractVector{T}) = ref(A,[i],J) +getindex{T<:Integer}(A::SparseMatrixCSC, I::AbstractVector{T}, j::Integer) = getindex(A,I,[j]) +getindex{T<:Integer}(A::SparseMatrixCSC, i::Integer, J::AbstractVector{T}) = getindex(A,[i],J) -function ref_cols{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, J::AbstractVector) +function getindex_cols{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, J::AbstractVector) (m, n) = size(A) nJ = length(J) @@ -781,7 +836,7 @@ end # TODO: See if growing arrays is faster than pre-computing structure # and then populating nonzeros # TODO: Use binary search in cases where nI >> nnz(A[:,j]) or nI << nnz(A[:,j]) -function ref_I_sorted{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, I::Vector, J::AbstractVector) +function getindex_I_sorted{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, I::Vector, J::AbstractVector) (m, n) = size(A) nI = length(I) @@ -847,8 +902,8 @@ function ref_I_sorted{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, I::Vector, J::AbstractVe return SparseMatrixCSC(nI, nJ, colptrS, rowvalS, nzvalS) end -# ref_I_sorted based on merging of sorted lists -function ref_I_sorted_old{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, I::Vector, J::AbstractVector) +# getindex_I_sorted based on merging of sorted lists +function getindex_I_sorted_old{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, I::Vector, J::AbstractVector) (m, n) = size(A) nI = length(I) @@ -922,7 +977,7 @@ function ref_I_sorted_old{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, I::Vector, J::Abstra return SparseMatrixCSC(nI, nJ, colptrS, rowvalS, nzvalS) end -function ref_general{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, I::Vector, J::AbstractVector) +function getindex_general{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, I::Vector, J::AbstractVector) (m, n) = size(A) nI = length(I) nJ = length(J) @@ -931,7 +986,7 @@ function ref_general{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, I::Vector, J::AbstractVec nnzS = 0 - I, pI = sortperm(I) + pI = sortperm(I); I = I[pI] fI = find(I) W = zeros(Int, nI + 1) # Keep row counts @@ -1005,25 +1060,25 @@ function ref_general{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, I::Vector, J::AbstractVec end # S = A[I, J] -function ref{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, I::AbstractVector, J::AbstractVector) +function getindex{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, I::AbstractVector, J::AbstractVector) m = size(A, 1) if isa(I, Range) || isa(I, Range1); I = [I]; end if I == 1:m - return ref_cols(A, J) + return getindex_cols(A, J) elseif issorted(I) - return ref_I_sorted(A, I, J) + return getindex_I_sorted(A, I, J) else - return ref_general(A, I, J) + return getindex_general(A, I, J) end end -## assign -assign(A::SparseMatrixCSC, v, i::Integer) = assign(A, v, ind2sub(size(A),i)...) +## setindex! +setindex!(A::SparseMatrixCSC, v, i::Integer) = setindex!(A, v, ind2sub(size(A),i)...) -function assign{T,Ti}(A::SparseMatrixCSC{T,Ti}, v, i0::Integer, i1::Integer) +function setindex!{T,Ti}(A::SparseMatrixCSC{T,Ti}, v, i0::Integer, i1::Integer) i0 = convert(Ti, i0) i1 = convert(Ti, i1) if !(1 <= i0 <= A.m && 1 <= i1 <= A.n); error(BoundsError); end @@ -1045,8 +1100,8 @@ function assign{T,Ti}(A::SparseMatrixCSC{T,Ti}, v, i0::Integer, i1::Integer) end end if loc != -1 - del(A.rowval, loc) - del(A.nzval, loc) + delete!(A.rowval, loc) + delete!(A.nzval, loc) for j = (i1+1):(A.n+1) A.colptr[j] = A.colptr[j] - 1 end @@ -1120,41 +1175,41 @@ function assign{T,Ti}(A::SparseMatrixCSC{T,Ti}, v, i0::Integer, i1::Integer) else #last < first to begin with i = first end - insert(A.rowval, i, i0) - insert(A.nzval, i, v) + insert!(A.rowval, i, i0) + insert!(A.nzval, i, v) for j = (i1+1):(A.n+1) A.colptr[j] = A.colptr[j] + 1 end return A end -assign(A::SparseMatrixCSC, v::AbstractMatrix, i::Integer, J::AbstractVector) = assign(A, v, [i], J) -assign(A::SparseMatrixCSC, v::AbstractMatrix, I::AbstractVector, j::Integer) = assign(A, v, I, [j]) +setindex!(A::SparseMatrixCSC, v::AbstractMatrix, i::Integer, J::AbstractVector) = setindex!(A, v, [i], J) +setindex!(A::SparseMatrixCSC, v::AbstractMatrix, I::AbstractVector, j::Integer) = setindex!(A, v, I, [j]) -assign{Tv}(A::SparseMatrixCSC{Tv}, x::Number, I::AbstractVector, J::AbstractVector) = - assign(A, fill(x::Tv, (length(I), length(J))), I, J) +setindex!{Tv}(A::SparseMatrixCSC{Tv}, x::Number, I::AbstractVector, J::AbstractVector) = + setindex!(A, fill(x::Tv, (length(I), length(J))), I, J) -assign{Tv}(A::SparseMatrixCSC{Tv}, S::Matrix{Tv}, I::AbstractVector, J::AbstractVector) = - assign(A, sparse(S), I, J) +setindex!{Tv}(A::SparseMatrixCSC{Tv}, S::Matrix{Tv}, I::AbstractVector, J::AbstractVector) = + setindex!(A, sparse(S), I, J) # A[I,J] = B -function assign{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, B::SparseMatrixCSC{Tv,Ti}, I::AbstractVector, J::AbstractVector) +function setindex!{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, B::SparseMatrixCSC{Tv,Ti}, I::AbstractVector, J::AbstractVector) if size(B,1) != length(I) || size(B,2) != length(J) - return("error in assign: mismatched dimensions") + return("error in setindex!: mismatched dimensions") end issortedI = issorted(I) issortedJ = issorted(J) if ~issortedI && ~issortedJ - I, pI = sortperm(I) - J, pJ = sortperm(J) + pI = sortperm(I); I = I[pI] + pJ = sortperm(J); J = J[pJ] B = B[pI, pJ] elseif ~issortedI - I, pI = sortperm(I) + pI = sortperm(I); I = I[pI] B = B[pI,:] else ~issortedJ - J, pJ = sortperm(J) + pJ = sortperm(J); J = J[pJ] B = B[:, pJ] end @@ -1246,9 +1301,12 @@ function assign{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, B::SparseMatrixCSC{Tv,Ti}, I:: colB += 1 end + delete!(rowvalS, colptrS[end]:length(rowvalS)) + delete!(nzvalS, colptrS[end]:length(nzvalS)) + A.colptr = colptrS - A.rowval = del(rowvalS, colptrS[end]:length(rowvalS)) - A.nzval = del(nzvalS, colptrS[end]:length(nzvalS)) + A.rowval = rowvalS + A.nzval = nzvalS return A end @@ -1389,7 +1447,9 @@ function expandptr{T<:Integer}(V::Vector{T}) res end -# Based on the function cs_fkeep from the CSparse library +# Based on Direct Methods for Sparse Linear Systems, T. A. Davis, SIAM, Philadelphia, Sept. 2006. +# Section 2.7: Removing entries from a matrix +# http://www.cise.ufl.edu/research/sparse/CSparse/ function fkeep!{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, f, other) nzorig = nnz(A) nz = 1 @@ -1408,8 +1468,8 @@ function fkeep!{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, f, other) A.colptr[A.n + 1] = nz nz -= 1 if nz < nzorig - grow(A.nzval, nz - nzorig) - grow(A.rowval, nz - nzorig) + resize!(A.nzval, nz) + resize!(A.rowval, nz) end A end diff --git a/base/stat.jl b/base/stat.jl index 054521bfabde5..297de918d4cee 100644 --- a/base/stat.jl +++ b/base/stat.jl @@ -1,4 +1,4 @@ -type Stat +immutable Stat device :: Uint inode :: Uint mode :: Uint @@ -14,31 +14,33 @@ type Stat end Stat(buf::Vector{Uint8}) = Stat( - ccall(:jl_stat_dev, Uint, (Ptr{Uint8},), buf), - ccall(:jl_stat_ino, Uint, (Ptr{Uint8},), buf), - ccall(:jl_stat_mode, Uint, (Ptr{Uint8},), buf), - ccall(:jl_stat_nlink, Int, (Ptr{Uint8},), buf), - ccall(:jl_stat_uid, Uint, (Ptr{Uint8},), buf), - ccall(:jl_stat_uid, Uint, (Ptr{Uint8},), buf), - ccall(:jl_stat_rdev, Uint, (Ptr{Uint8},), buf), - ccall(:jl_stat_size, Int, (Ptr{Uint8},), buf), - ccall(:jl_stat_blksize, Int, (Ptr{Uint8},), buf), - ccall(:jl_stat_blocks, Int, (Ptr{Uint8},), buf), - ccall(:jl_stat_mtime, Float64, (Ptr{Uint8},), buf), - ccall(:jl_stat_ctime, Float64, (Ptr{Uint8},), buf), + uint(ccall(:jl_stat_dev, Uint32, (Ptr{Uint8},), buf)), + uint(ccall(:jl_stat_ino, Uint32, (Ptr{Uint8},), buf)), + uint(ccall(:jl_stat_mode, Uint32, (Ptr{Uint8},), buf)), + int(ccall(:jl_stat_nlink, Uint32, (Ptr{Uint8},), buf)), + uint(ccall(:jl_stat_uid, Uint32, (Ptr{Uint8},), buf)), + uint(ccall(:jl_stat_gid, Uint32, (Ptr{Uint8},), buf)), + uint(ccall(:jl_stat_rdev, Uint32, (Ptr{Uint8},), buf)), + ccall(:jl_stat_size, Int, (Ptr{Uint8},), buf), + int(ccall(:jl_stat_blksize, Uint32, (Ptr{Uint8},), buf)), + int(ccall(:jl_stat_blocks, Uint32, (Ptr{Uint8},), buf)), + ccall(:jl_stat_mtime, Float64, (Ptr{Uint8},), buf), + ccall(:jl_stat_ctime, Float64, (Ptr{Uint8},), buf), ) show(io::IO, st::Stat) = print("Stat(mode=$(oct(st.mode,6)), size=$(st.size))") # stat & lstat functions -const _jl_stat_buf = Array(Uint8, ccall(:jl_sizeof_stat, Int, ())) -macro _jl_stat_call(sym,arg) +const stat_buf = Array(Uint8, ccall(:jl_sizeof_stat, Int32, ())) +macro stat_call(sym,arg) quote - fill!(_jl_stat_buf,0) - r = ccall($(expr(:quote,sym)), Int32, (Ptr{Uint8},Ptr{Uint8}), $arg, _jl_stat_buf) - system_error("stat", r!=0 && errno()!=ENOENT) - st = Stat(_jl_stat_buf) + fill!(stat_buf,0) + r = ccall($(Expr(:quote,sym)), Int32, (Ptr{Uint8},Ptr{Uint8}), $arg, stat_buf) + uv_errno = _uv_lasterror(eventloop()) + ENOENT, ENOTDIR = 34, 27 + system_error(:stat, r!=0 && uv_errno!=ENOENT && uv_errno!=ENOTDIR) + st = Stat(stat_buf) if ispath(st) != (r==0) error("WTF: stat returned zero type for a valid path!?") end @@ -46,9 +48,12 @@ macro _jl_stat_call(sym,arg) end end -stat(path::String) = @_jl_stat_call jl_stat path -stat(fd::Integer) = @_jl_stat_call jl_fstat fd -lstat(path::String) = @_jl_stat_call jl_lstat path +stat(fd::Integer) = @stat_call jl_fstat fd +stat(path::String) = @stat_call jl_stat path +lstat(path::String) = @stat_call jl_lstat path + +stat(path...) = stat(joinpath(path...)) +lstat(path...) = lstat(joinpath(path...)) # mode type predicates @@ -63,13 +68,13 @@ isblockdev(mode::Unsigned) = mode & 0xf000 == 0x6000 # mode permission predicates -issetuid(mode::Unsigned) = (mode & 0x800) > 0 -issetgid(mode::Unsigned) = (mode & 0x400) > 0 -issticky(mode::Unsigned) = (mode & 0x200) > 0 +issetuid(mode::Unsigned) = (mode & 0o4000) > 0 +issetgid(mode::Unsigned) = (mode & 0o2000) > 0 +issticky(mode::Unsigned) = (mode & 0o1000) > 0 - isreadable(mode::Unsigned) = (mode & 0x124) > 0 - iswriteable(mode::Unsigned) = (mode & 0x092) > 0 -isexecutable(mode::Unsigned) = (mode & 0x049) > 0 + isreadable(mode::Unsigned) = (mode & 0o444) > 0 + iswriteable(mode::Unsigned) = (mode & 0o222) > 0 +isexecutable(mode::Unsigned) = (mode & 0o111) > 0 uperm(mode::Unsigned) = uint8(mode >> 6) & 0x7 gperm(mode::Unsigned) = uint8(mode >> 3) & 0x7 @@ -96,15 +101,18 @@ for f in { :gperm :operm } - @eval ($f)(st::Stat) = ($f)(st.mode) - @eval ($f)(path::String) = ($f)(stat(path)) + @eval ($f)(st::Stat) = ($f)(st.mode) + @eval ($f)(path...) = ($f)(stat(path...)) end -islink(path::String) = islink(lstat(path)) +islink(path...) = islink(lstat(path...)) # some convenience functions -filemode(path::String) = stat(path).mode -filesize(path::String) = stat(path).size - mtime(path::String) = stat(path).mtime - ctime(path::String) = stat(path).ctime +filemode(path...) = stat(path...).mode +filesize(path...) = stat(path...).size + mtime(path...) = stat(path...).mtime + ctime(path...) = stat(path...).ctime + +samefile(a::Stat, b::Stat) = a.device==b.device && a.inode==b.inode +samefile(a::String, b::String) = samefile(stat(a),stat(b)) diff --git a/base/statistics.jl b/base/statistics.jl index e41f8eff4ae5b..56f1a643d56a7 100644 --- a/base/statistics.jl +++ b/base/statistics.jl @@ -1,379 +1,252 @@ -mean(v::AbstractArray) = sum(v)/numel(v) -mean(v::AbstractArray, dim::Int) = sum(v,dim)/size(v,dim) -weighted_mean(v::AbstractArray, w::AbstractArray) = sum(v.*w)/sum(w) - -function median(v::AbstractArray) - n = numel(v) - if isodd(n) - return select(v, div(n+1, 2)) - else - vs = sort(v) - return (vs[div(n, 2)] + vs[div(n, 2) + 1]) / 2 +function mean(iterable) + state = start(iterable) + if done(iterable, state) + error("mean of empty collection undefined: $(repr(iterable))") end + count = 1 + total, state = next(iterable, state) + while !done(iterable, state) + value, state = next(iterable, state) + total += value + count += 1 + end + return total/count end +mean(v::AbstractArray, region) = sum(v, region) / prod(size(v)[region]) + +function median!{T<:Real}(v::AbstractVector{T}) + isempty(v) && error("median of an empty array is undefined") + sort!(v) # TODO: do something more efficient, e.g. select but detect NaNs + isnan(v[end]) && error("median is undefined in presence of NaNs") + isodd(length(v)) ? float(v[div(end+1,2)]) : (v[div(end,2)]+v[div(end,2)+1])/2 +end +median{T<:Real}(v::AbstractArray{T}) = median!(copy(vec(v))) ## variance with known mean -function var(v::AbstractVector, m::Number, corrected::Bool) +function varm(v::AbstractVector, m::Number) n = length(v) - if n == 0 || (n == 1 && corrected) + if n == 0 || n == 1 return NaN end x = v - m - return dot(x, x) / (n - (corrected ? 1 : 0)) + return dot(x, x) / (n - 1) end -var(v::AbstractVector, m::Number) = var(v, m, true) -var(v::AbstractArray, m::Number, corrected::Bool) = var(reshape(v, numel(v)), m, corrected) -var(v::AbstractArray, m::Number) = var(v, m, true) -function var(v::Ranges, m::Number, corrected::Bool) - f = first(v) - m - s = step(v) - l = length(v) - if l == 0 || (l == 1 && corrected) - return NaN - end - if corrected - return f^2 * l / (l - 1) + f * s * l + s^2 * l * (2 * l - 1) / 6 - else - return f^2 + f * s * (l - 1) + s^2 * (l - 1) * (2 * l - 1) / 6 - end -end -var(v::Ranges, m::Number) = var(v, m, true) +varm(v::AbstractArray, m::Number) = varm(vec(v), m) +varm(v::Ranges, m::Number) = var(v) ## variance -function var(v::Ranges, corrected::Bool) +function var(v::Ranges) s = step(v) l = length(v) - if l == 0 || (l == 1 && corrected) + if l == 0 || l == 1 return NaN end - return abs2(s) * (l + 1) * (corrected ? l : (l - 1)) / 12 + return abs2(s) * (l + 1) * l / 12 +end +var(v::AbstractArray) = varm(v, mean(v)) +function var(v::AbstractArray, region) + x = bsxfun(-, v, mean(v, region)) + return sum(x.^2, region) / (prod(size(v)[region]) - 1) end -var(v::AbstractVector, corrected::Bool) = var(v, mean(v), corrected) -var(v::AbstractArray, corrected::Bool) = var(reshape(v, numel(v)), corrected) -var(v::AbstractArray) = var(v, true) ## standard deviation with known mean -std(v::AbstractArray, m::Number, corrected::Bool) = sqrt(var(v, m, corrected)) -std(v::AbstractArray, m::Number) = std(v, m, true) +stdm(v, m::Number) = sqrt(varm(v, m)) ## standard deviation -std(v::AbstractArray, corrected::Bool) = std(v, mean(v), corrected) -std(v::AbstractArray) = std(v, true) -std(v::Ranges, corrected::Bool) = sqrt(var(v, corrected)) -std(v::Ranges) = std(v, true) +std(v) = sqrt(var(v)) +std(v, region) = sqrt(var(v, region)) -## median absolute deviation with known center -mad(v::AbstractArray, center::Number) = median(abs(v - center)) - -## median absolute deviation -mad(v::AbstractArray) = mad(v, median(v)) - -## hist ## - -function hist(v::StridedVector, nbins::Integer) - h = zeros(Int, nbins) - if nbins == 0 - return h +## nice-valued ranges for histograms +function histrange{T<:FloatingPoint,N}(v::AbstractArray{T,N}, n::Integer) + if length(v) == 0 + return Range(0.0,1.0,1) end lo, hi = min(v), max(v) - if lo == hi - lo -= div(nbins,2) - hi += div(nbins,2) + int(isodd(nbins)) + if hi == lo + step = 1.0 + else + bw = (hi - lo) / n + e = 10.0^floor(log10(bw)) + r = bw / e + if r <= 2 + step = 2*e + elseif r <= 5 + step = 5*e + else + step = 10*e + end end - binsz = (hi - lo) / nbins - for x in v - if isfinite(x) - i = iround((x - lo) / binsz + 0.5) - h[i > nbins ? nbins : i] += 1 + start = step*(ceil(lo/step)-1) + Range(start,step,1+iceil((hi - start)/step)) +end + +function histrange{T<:Integer,N}(v::AbstractArray{T,N}, n::Integer) + if length(v) == 0 + return Range(0,1,1) + end + lo, hi = min(v), max(v) + if hi == lo + step = 1 + else + bw = (hi - lo) / n + e = 10^max(0,ifloor(log10(bw))) + r = bw / e + if r <= 1 + step = e + elseif r <= 2 + step = 2*e + elseif r <= 5 + step = 5*e + else + step = 10*e end end - h + start = step*(iceil(lo/step)-1) + Range(start,step,1+iceil((hi - start)/step)) end -hist(x) = hist(x, 10) +## midpoints of intervals +midpoints(r::Ranges) = r[1:length(r)-1] + 0.5*step(r) +midpoints(v::AbstractVector) = [0.5*(v[i] + v[i+1]) for i in 1:length(v)-1] -function hist(A::StridedMatrix, nbins::Integer) - m, n = size(A) - h = Array(Int, nbins, n) - for j=1:n - h[:,j] = hist(sub(A, 1:m, j), nbins) + +## hist ## +function hist(v::AbstractVector, r::Ranges) + n = length(r)-1 + h = zeros(Int, n) + for x in v + i = iceil((x-first(r))/step(r)) + if 1 <= i <= n + h[i] += 1 + end end - h + r,h end +hist(v::AbstractVector, n::Integer) = hist(v,histrange(v,n)) +hist(v::AbstractVector) = hist(v,iceil(log2(length(v)))+1) # Sturges' formula -function histc(v::StridedVector, edg) - n = length(edg) +function hist(v::AbstractVector, edg::AbstractVector) + n = length(edg)-1 h = zeros(Int, n) - if n == 0 - return h - end - first = edg[1] - last = edg[n] for x in v - if !isless(last, x) && !isless(x, first) - i = search_sorted(edg, x) - while isless(x, edg[i]) - i -= 1 - end + i = searchsortedfirst(edg, x)-1 + if 1 <= i <= n h[i] += 1 end end - h + edg,h end -function histc(A::StridedMatrix, edg) +function hist(A::AbstractMatrix, edg::AbstractVector) m, n = size(A) - h = Array(Int, length(edg), n) - for j=1:n - h[:,j] = histc(sub(A, 1:m, j), edg) + H = Array(Int, length(edg)-1, n) + for j = 1:n + _,H[:,j] = hist(sub(A, 1:m, j), edg) end - h + edg,H end +hist(A::AbstractMatrix, n::Integer) = hist(A,histrange(A,n)) +hist(A::AbstractMatrix) = hist(A,iceil(log2(size(A,1)))+1) # Sturges' formula -## order (aka, rank), resolving ties using the mean rank -function tiedrank(v::AbstractArray) - n = length(v) - place = order(v) - ord = Array(Float64, n) +## pearson covariance functions ## - i = 1 - while i <= n - j = i - while j + 1 <= n && v[place[i]] == v[place[j + 1]] - j += 1 - end +typealias AbstractVecOrMat{T} Union(AbstractVector{T}, AbstractMatrix{T}) - if j > i - m = sum(i:j) / (j - i + 1) - for k = i:j - ord[place[k]] = m - end - else - ord[place[i]] = i +function center(x::AbstractMatrix) + m,n = size(x) + res = Array(promote_type(eltype(x),Float64), size(x)) + for j in 1:n + colmean = mean(x[:,j]) + for i in 1:m + res[i,j] = x[i,j] - colmean end - - i = j + 1 end - - return ord + res end -## pearson covariance functions ## - -# pearson covariance between two vectors, with known means -function _jl_cov_pearson1(x::AbstractArray, y::AbstractArray, mx::Number, my::Number, corrected::Bool) - n = numel(x) - if n == 0 || (n == 1 && corrected) - return NaN +function center(x::AbstractVector) + colmean = mean(x) + res = Array(promote_type(eltype(x),Float64), size(x)) + for i in 1:length(x) + res[i] = x[i] - colmean end - x0 = x - mx - y0 = y - my - return (x0'*y0)[1] / (n - (corrected ? 1 : 0)) + res end -# pearson covariance between two vectors -function cov_pearson(x::AbstractVector, y::AbstractVector, corrected::Bool) - if numel(x) != numel(y) - error("cov_pearson: incompatible dimensions") +function cov(x::AbstractVecOrMat, y::AbstractVecOrMat) + if size(x, 1) != size(y, 1) + error("incompatible matrices") end - - mx = mean(x) - my = mean(y) - _jl_cov_pearson1(x, y, mx, my, corrected) -end -cov_pearson(x::AbstractVector, y::AbstractVector) = cov_pearson(x, y, true) - -# pearson covariance over all pairs of columns of a matrix -function _jl_cov_pearson(x::AbstractMatrix, mxs::AbstractMatrix, corrected::Bool) n = size(x, 1) - if n == 0 || (n == 1 && corrected) - return NaN - end - x0 = x - repmat(mxs, n, 1) - return (x0'*x0) / (n - (corrected ? 1 : 0)) + xc = center(x) + yc = center(y) + conj(xc' * yc / (n - 1)) end -cov_pearson(x::AbstractMatrix, corrected::Bool) = _jl_cov_pearson(x, mean(x, 1), corrected) -cov_pearson(x::AbstractMatrix) = cov_pearson(x, true) +cov(x::AbstractVector, y::AbstractVector) = cov(x'', y)[1] -# pearson covariance over all pairs of columns of two matrices -function _jl_cov_pearson(x::AbstractMatrix, y::AbstractMatrix, - mxs::AbstractMatrix, mys::AbstractMatrix, - corrected::Bool) +function cov(x::AbstractVecOrMat) n = size(x, 1) - if n == 0 || (n == 1 && corrected) - return NaN - end - x0 = x - repmat(mxs, n, 1) - y0 = y - repmat(mys, n, 1) - return (x0'*y0) / (n - (corrected ? 1 : 0)) + xc = center(x) + conj(xc' * xc / (n - 1)) end -function cov_pearson(x::AbstractMatrix, y::AbstractMatrix, corrected::Bool) - if size(x) != size(y) - error("cov_pearson: incompatible dimensions") - end +cov(x::AbstractVector) = cov(x'')[1] - if is(x, y) - return cov_pearson(x, corrected) - end - - n = size(x, 1) - mxs = mean(x, 1) - mys = mean(y, 1) - return _jl_cov_pearson(x, y, mxs, mys, corrected) -end -cov_pearson(x::AbstractMatrix, y::AbstractMatrix) = cov_pearson(x, y, true) - -## spearman covariance functions ## - -# spearman covariance between two vectors -function cov_spearman(x::AbstractVector, y::AbstractVector, corrected::Bool) - cov_pearson(tiedrank(x), tiedrank(y), corrected) -end -cov_spearman(x::AbstractVector, y::AbstractVector) = cov_spearman(x, y, true) - -# spearman covariance over all pairs of columns of a matrix -function cov_spearman(x::AbstractMatrix, corrected::Bool) - cov_pearson(apply(hcat, amap(tiedrank, x, 2)), corrected) -end -cov_spearman(x::AbstractMatrix) = cov_spearman(x, true) - -# spearman covariance over all pairs of columns of two matrices -function cov_spearman(x::AbstractMatrix, y::AbstractMatrix, corrected::Bool) - if is(x, y) - return cov_spearman(x, corrected) - end - - cov_pearson( - apply(hcat, amap(tiedrank, x, 2)), - apply(hcat, amap(tiedrank, y, 2)), - corrected) -end -cov_spearman(x::AbstractMatrix, y::AbstractMatrix) = cov_spearman(x, y, true) - -const cov = cov_pearson - -## pearson correlation functions ## - -# pearson correlation between two vectors -function cor_pearson(x::AbstractVector, y::AbstractVector, corrected::Bool) - if numel(x) != numel(y) - error("cor_pearson: incompatible dimensions") - end - - mx = mean(x) - my = mean(y) - sx = std(x, mx, corrected) - sy = std(y, my, corrected) - - return _jl_cov_pearson1(x, y, mx, my, corrected) / (sx * sy) -end -cor_pearson(x::AbstractVector, y::AbstractVector) = cor_pearson(x, y, true) - -# pearson correlation over all pairs of columns of a matrix -function cor_pearson{T}(x::AbstractMatrix{T}, corrected::Bool) - (n,m) = size(x) - mxs = mean(x, 1) - sxs = similar(mxs) - for i = 1:m - sxs[i] = std(sub(x, (1:n, i)), mxs[i], corrected) - end - R = _jl_cov_pearson(x, mxs, corrected) ./ (sxs' * sxs) - - R[1:m+1:end] = one(T) # fix diagonal for numerical errors - - return R -end -cor_pearson(x::AbstractMatrix) = cor_pearson(x, true) - -# pearson correlation over all pairs of columns of two matrices -function cor_pearson(x::AbstractMatrix, y::AbstractMatrix, corrected::Bool) - if size(x) != size(y) - error("cor_pearson: incompatible dimensions") - end - - if is(x, y) - return cor_pearson(x, corrected) - end - - (n,m) = size(x) - mxs = mean(x, 1) - mys = mean(y, 1) - sxs = similar(mxs) - sys = similar(mys) - for i = 1:m - sxs[i] = std(sub(x, (1:n, i)), mxs[i], corrected) - sys[i] = std(sub(y, (1:n, i)), mys[i], corrected) - end - - return _jl_cov_pearson(x, y, mxs, mys, corrected) ./ (sxs' * sys) +function cor(x::AbstractVecOrMat, y::AbstractVecOrMat) + z = cov(x, y) + scale = Base.amap(std, x, 2) * Base.amap(std, y, 2)' + z ./ scale end -cor_pearson(x::AbstractMatrix, y::AbstractMatrix) = cor_pearson(x, y, true) - -## spearman correlation functions ## - -# spearman correlation between two vectors -function cor_spearman(x::AbstractVector, y::AbstractVector, corrected::Bool) - cor_pearson(tiedrank(x), tiedrank(y), corrected) -end -cor_spearman(x::AbstractVector, y::AbstractVector) = cor_spearman(x, y, true) - -# spearman correlation over all pairs of columns of a matrix -function cor_spearman(x::AbstractMatrix, corrected::Bool) - cor_pearson(apply(hcat, amap(tiedrank, x, 2)), corrected) -end -cor_spearman(x::AbstractMatrix) = cor_spearman(x, true) +cor(x::AbstractVector, y::AbstractVector) = + cov(x, y) / std(x) / std(y) + -# spearman correlation over all pairs of columns of two matrices -function cor_spearman(x::AbstractMatrix, y::AbstractMatrix, corrected::Bool) - if is(x, y) - return cor_spearman(x, corrected) +function cor(x::AbstractVecOrMat) + res = cov(x) + n = size(res, 1) + scale = 1 / sqrt(diag(res)) + for j in 1:n + for i in 1 : j - 1 + res[i,j] *= scale[i] * scale[j] + res[j,i] = res[i,j] + end + res[j,j] = 1.0 end - - cor_pearson( - apply(hcat, amap(tiedrank, x, 2)), - apply(hcat, amap(tiedrank, y, 2)), - corrected) + res end -cor_spearman(x::AbstractMatrix, y::AbstractMatrix) = cor_spearman(x, y, true) - -const cor = cor_pearson +cor(x::AbstractVector) = cor(x'')[1] ## quantiles ## # for now, use the R/S definition of quantile; may want variants later # see ?quantile in R -- this is type 7 -function quantile(x, qs) - # make sure the quantiles are in [0,1] - bqs = _bound_quantiles(qs) - - lx = length(x) - lqs = length(bqs) - - if lx > 0 && lqs > 0 - index = 1 + (lx-1) * bqs - lo = ifloor(index) - hi = iceil(index) - sortedX = sort(x) - i = index .> lo - ret = float(sortedX[lo]) - i = [1:length(i)][i] - h = (index - lo)[i] - ret[i] = (1-h) .* ret[i] + h .* sortedX[hi[i]] - else - ret = zeros(lqs) * NaN - end - - ret -end -quantile(x, q::Number) = quantile(x, [q])[1] -quartile(x) = quantile(x, [.25, .5, .75]) -quintile(x) = quantile(x, [.2:.2:.8]) -decile(x) = quantile(x, [.1:.1:.9]) +function quantile!(v::AbstractVector, q::AbstractVector) + isempty(v) && error("quantile: empty data array") + isempty(q) && error("quantile: empty quantile array") -function _bound_quantiles(qs) - epsilon = 100 * eps() - if (any(qs .< -epsilon) || any(qs .> 1 + epsilon)) - error("quantiles out of [0,1] range!") - end - [min(1, max(0, q)) for q = qs] + # make sure the quantiles are in [0,1] + q = bound_quantiles(q) + + lv = length(v) + lq = length(q) + + index = 1 + (lv-1)*q + lo = ifloor(index) + hi = iceil(index) + sort!(v) + isnan(v[end]) && error("quantiles are undefined in presence of NaNs") + i = find(index .> lo) + r = float(v[lo]) + h = (index-lo)[i] + r[i] = (1-h).*r[i] + h.*v[hi[i]] + return r +end +quantile(v::AbstractVector, q::AbstractVector) = quantile!(copy(v),q) +quantile(v::AbstractVector, q::Number) = quantile(v,[q])[1] + +function bound_quantiles(qs::AbstractVector) + epsilon = 100*eps() + if (any(qs .< -epsilon) || any(qs .> 1+epsilon)) + error("quantiles out of [0,1] range") + end + [min(1,max(0,q)) for q = qs] end diff --git a/base/statsold.jl b/base/statsold.jl new file mode 100644 index 0000000000000..00f6e4b821ab1 --- /dev/null +++ b/base/statsold.jl @@ -0,0 +1,213 @@ +mean(v::AbstractArray, dim::Int) = sum(v,dim)/size(v,dim) + +weighted_mean(v::AbstractArray, w::AbstractArray) = sum(v.*w)/sum(w) + +## median absolute deviation with known center with consistency adjustment +mad(v::AbstractArray, center::Number) = 1.4826 * median(abs(v - center)) + +## median absolute deviation +mad(v::AbstractArray) = mad(v, median(v)) + +## maximum likelihood estimate of skewness with known mean m +function skewness(v::AbstractVector, m::Number) + n = length(v) + empirical_third_centered_moment = 0.0 + empirical_variance = 0.0 + for x_i in v + empirical_third_centered_moment += (x_i - m)^3 + empirical_variance += (x_i - m)^2 + end + empirical_third_centered_moment /= n + empirical_variance /= n + return empirical_third_centered_moment / (empirical_variance^1.5) +end + +## maximum likelihood estimate of skewness +skewness(v::AbstractVector) = skewness(v, mean(v)) + +## maximum likelihood estimate of kurtosis with known mean m +function kurtosis(v::AbstractVector, m::Number) + n = length(v) + empirical_fourth_centered_moment = 0.0 + empirical_variance = 0.0 + for x_i in v + empirical_fourth_centered_moment += (x_i - m)^4 + empirical_variance += (x_i - m)^2 + end + empirical_fourth_centered_moment /= n + empirical_variance /= n + return (empirical_fourth_centered_moment / (empirical_variance^2)) - 3.0 +end + +## maximum likelihood estimate of kurtosis +kurtosis(v::AbstractVector) = kurtosis(v, mean(v)) + +## distance matrix +function dist(m::AbstractMatrix) + n = size(m, 1) + d = Array(Float64, n, n) + for i in 1:n + d[i, i] = 0.0 + for j in (i + 1):n + x = norm(m[i, :] - m[j, :]) + d[i, j] = x + d[j, i] = x + end + end + return d +end + +## order (aka, rank), resolving ties using the mean rank +function tiedrank(v::AbstractArray) + n = length(v) + place = sortperm(v) + ord = Array(Float64, n) + + i = 1 + while i <= n + j = i + while j + 1 <= n && v[place[i]] == v[place[j + 1]] + j += 1 + end + + if j > i + m = sum(i:j) / (j - i + 1) + for k = i:j + ord[place[k]] = m + end + else + ord[place[i]] = i + end + + i = j + 1 + end + + return ord +end +tiedrank(X::AbstractMatrix) = tiedrank(reshape(X, length(X))) +function tiedrank(X::AbstractMatrix, dim::Int) + retmat = apply(hcat, amap(tiedrank, X, 3 - dim)) + return dim == 1 ? retmat : retmat' +end + +## spearman covariance functions ## + +# spearman covariance between two vectors +cov_spearman(x::AbstractVector, y::AbstractVector, corrected::Bool) = cov(tiedrank(x), tiedrank(y), corrected) + +# spearman covariance over all pairs of columns of two matrices +cov_spearman(X::AbstractMatrix, Y::AbstractMatrix, corrected::Bool) = [cov_spearman(X[:,i], Y[:,j], corrected) for i = 1:size(X, 2), j = 1:size(Y,2)] +cov_spearman(x::AbstractVector, Y::AbstractMatrix, corrected::Bool) = [cov_spearman(x, Y[:,i], corrected) for i = 1:size(Y, 2)] +cov_spearman(X::AbstractMatrix, y::AbstractVector, corrected::Bool) = [cov_spearman(X[:,i], y, corrected) for i = 1:size(X, 2)] + +# spearman covariance over all pairs of columns of a matrix +cov_spearman(X::AbstractMatrix, corrected::Bool) = cov(tiedrank(X, 1), corrected) + +cov_spearman(x) = cov_spearman(x, true) +cov_spearman(x, y) = cov_spearman(x, y, true) + +## spearman correlation functions ## + +# spearman correlation between two vectors +cor_spearman(x::AbstractVector, y::AbstractVector, corrected::Bool) = cor(tiedrank(x), tiedrank(y), corrected) + +# spearman correlation over all pairs of columns of two matrices +cor_spearman(X::AbstractMatrix, Y::AbstractMatrix, corrected::Bool) = cor(tiedrank(X, 1), tiedrank(Y, 1)) +cor_spearman(X::AbstractMatrix, y::AbstractVector, corrected::Bool) = cor(tiedrank(X, 1), tiedrank(y)) +cor_spearman(x::AbstractVector, Y::AbstractMatrix, corrected::Bool) = cor(tiedrank(x), tiedrank(Y, 1)) + +# spearman correlation over all pairs of columns of a matrix +cor_spearman(X::AbstractMatrix, corrected::Bool) = cor(tiedrank(X, 1), corrected) + +cor_spearman(x) = cor_spearman(x, true) +cor_spearman(x, y) = cor_spearman(x, y, true) + +## autocorrelation at a specific lag +autocor(v::AbstractVector, lag::Int) = cor(v[1:end-lag], v[1+lag:end]) + +## autocorrelation at a default lag of 1 +autocor(v::AbstractVector) = autocor(v, 1) + + quantile(v::AbstractVector) = quantile(v,[.0,.25,.5,.75,1.0]) +percentile(v::AbstractVector) = quantile(v,[1:99]/100) + quartile(v::AbstractVector) = quantile(v,[.25,.5,.75]) + quintile(v::AbstractVector) = quantile(v,[.2,.4,.6,.8]) + decile(v::AbstractVector) = quantile(v,[.1,.2,.3,.4,.5,.6,.7,.8,.9]) + iqr(v::AbstractVector) = quantile(v,[0.25,0.75]) + +## run-length encoding +function rle{T}(v::Vector{T}) + n = length(v) + current_value = v[1] + current_length = 1 + values = Array(T, n) + total_values = 1 + lengths = Array(Int, n) + total_lengths = 1 + for i in 2:n + if v[i] == current_value + current_length += 1 + else + values[total_values] = current_value + total_values += 1 + lengths[total_lengths] = current_length + total_lengths += 1 + current_value = v[i] + current_length = 1 + end + end + values[total_values] = current_value + lengths[total_lengths] = current_length + return (values[1:total_values], lengths[1:total_lengths]) +end + +## inverse run-length encoding +function inverse_rle{T}(values::Vector{T}, lengths::Vector{Int}) + total_n = sum(lengths) + pos = 0 + res = Array(T, total_n) + n = length(values) + for i in 1:n + v = values[i] + l = lengths[i] + for j in 1:l + pos += 1 + res[pos] = v + end + end + return res +end + +## old stats tests ## + +@test abs(autocor([1, 2, 3, 4, 5]) - 1.0) < 10e-8 + +@test iqr([1, 2, 3, 4, 5]) == [2.0, 4.0] + +z = [true, true, false, false, true, false, true, true, true] +values, lengths = rle(z) +@test values == [true, false, true, false, true] +@test lengths == [2, 2, 1, 1, 3] +@test inverse_rle(values, lengths) == z + +z = [true, true, false, false, true, false, true, true, true, false] +values, lengths = rle(z) +@test values == [true, false, true, false, true, false] +@test lengths == [2, 2, 1, 1, 3, 1] +@test inverse_rle(values, lengths) == z + +m = [1 0; 0 1] +d = [0.0 sqrt(2); sqrt(2) 0.0] +@test norm(dist(m) - d) < 10e-8 + +m = [3.0 1.0; 5.0 1.0] +d = [0.0 2.0; 2.0 0.0] +@test norm(dist(m) - d) < 10e-8 + +m = [1 0 0; 0 1 0 ; 1 0 1] +d = [0.0 sqrt(2) 1.0; sqrt(2) 0.0 sqrt(3); 1.0 sqrt(3) 0.0] +@test norm(dist(m) - d) < 10e-8 + +@assert_approx_eq cov_spearman(X, y)[1] cov_spearman(X[:,1],y) +@assert_approx_eq cov_spearman(X) cov_spearman(X, X) +@assert_approx_eq cov_spearman(X, y) [-0.25, -0.1875] diff --git a/base/stream.jl b/base/stream.jl new file mode 100644 index 0000000000000..90ae68f32d319 --- /dev/null +++ b/base/stream.jl @@ -0,0 +1,482 @@ +#TODO: Move stdio detection from C to Julia (might require some Clang magic) +include("uv_constants.jl") + +## types ## +typealias Executable Union(Vector{ByteString},Function) +typealias Callback Union(Function,Bool) +type WaitTask + filter::Callback #runs task only if false + localdata::Any + job + + WaitTask(forwhat, test::Callback) = new(test, forwhat) + WaitTask() = new(false, nothing) +end + +abstract AsyncStream <: IO + +typealias UVHandle Ptr{Void} +typealias UVStream AsyncStream + +const _sizeof_uv_pipe = ccall(:jl_sizeof_uv_pipe_t,Int32,()) + +function eof(s::AsyncStream) + start_reading(s) + wait_readnb(s,1) + !s.open && nb_available(s.buffer)<=0 +end + +type NamedPipe <: AsyncStream + handle::Ptr{Void} + buffer::IOBuffer + open::Bool + line_buffered::Bool + readcb::Callback + readnotify::Vector{WaitTask} + closecb::Callback + closenotify::Vector{WaitTask} + NamedPipe() = new(C_NULL,PipeBuffer(),false,true,false,WaitTask[],false, + WaitTask[]) +end + +show(io::IO,stream::NamedPipe) = print(io,"NamedPipe(",stream.open?"connected,":"disconnected,",nb_available(stream.buffer)," bytes waiting)") + +type TTY <: AsyncStream + handle::Ptr{Void} + open::Bool + line_buffered::Bool + buffer::IOBuffer + readcb::Callback + readnotify::Vector{WaitTask} + closecb::Callback + closenotify::Vector{WaitTask} + TTY(handle,open)=new(handle,open,true,PipeBuffer(),false,WaitTask[],false,WaitTask[]) +end + +show(io::IO,stream::TTY) = print(io,"TTY(",stream.open?"connected,":"disconnected,",nb_available(stream.buffer)," bytes waiting)") + +uvtype(::AsyncStream) = UV_STREAM +uvhandle(stream::AsyncStream) = stream.handle + +copy(s::TTY) = TTY(s.handle,s.open) + +convert(T::Type{Ptr{Void}}, s::AsyncStream) = convert(T, s.handle) +handle(s::AsyncStream) = s.handle +handle(s::Ptr{Void}) = s + +make_stdout_stream() = _uv_tty2tty(ccall(:jl_stdout_stream, Ptr{Void}, ())) + +function _uv_tty2tty(handle::Ptr{Void}) + tty = TTY(handle,true) + tty.line_buffered = false + ccall(:jl_uv_associate_julia_struct,Void,(Ptr{Void},Any),handle,tty) + tty +end + +#macro init_stdio() +#begin + const STDIN = _uv_tty2tty(ccall(:jl_stdin_stream ,Ptr{Void},())) + const STDOUT = _uv_tty2tty(ccall(:jl_stdout_stream,Ptr{Void},())) + const STDERR = _uv_tty2tty(ccall(:jl_stderr_stream,Ptr{Void},())) + OUTPUT_STREAM = STDOUT +#end +#end + +#@init_stdio + +function _init_buf(stream::AsyncStream) + if(!isa(stream.buf,IOStream)) + stream.buf=memio() + end +end + +flush(::TTY) = nothing + +function tasknotify(waittasks::Vector{WaitTask}, args...) + newwts = WaitTask[] + ct = current_task() + for wt in waittasks + f = wt.filter + if (isa(f, Function) ? f(wt.localdata, args...) : f) === false + work = wt.job + work.argument = args + enq_work(work) + else + push!(newwts,wt) + end + end + resize!(waittasks,length(newwts)) + waittasks[:] = newwts +end + +wait_connect_filter(w::AsyncStream, args...) = !w.open +wait_readable_filter(w::AsyncStream, args...) = nb_available(w.buffer) <= 0 +wait_readnb_filter(w::(AsyncStream,Int), args...) = w[1].open && (nb_available(w[1].buffer) < w[2]) +wait_readbyte_filter(w::(AsyncStream,Uint8), args...) = w[1].open && (search(w[1].buffer,w[2]) <= 0) +wait_readline_filter(w::AsyncStream, args...) = w.open && (search(w.buffer,'\n') <= 0) + +function wait(forwhat::Vector, notify_list_name, filter_fcn) + args = () + for x in forwhat + args = wait(x, notify_list_name, filter_fcn) + end + args +end + +function wait(forwhat, notify_list_name, filter_fcn) + args = () + while filter_fcn(forwhat) + assert(current_task() != Scheduler, "Cannot execute blocking function from Scheduler") + thing = isa(forwhat,Tuple) ? forwhat[1] : forwhat + wt = WaitTask(forwhat, filter_fcn) + push!(thing.(notify_list_name), wt) + args = yield(wt) + if isa(args,InterruptException) + error(args) + end + end + args +end + +wait_connected(x) = wait(x, :connectnotify, wait_connect_filter) +wait_readable(x) = wait(x, :readnotify, wait_readable_filter) +wait_readline(x) = wait(x, :readnotify, wait_readline_filter) +wait_readnb(x::(AsyncStream,Int)) = wait(x, :readnotify, wait_readnb_filter) +wait_readnb(x::AsyncStream,b::Int) = wait_readnb((x,b)) +wait_readbyte(x::AsyncStream,c::Uint8) = wait((x,c), :readnotify, wait_readbyte_filter) + +#from `connect` +function _uv_hook_connectcb(sock::AsyncStream, status::Int32) + if status != -1 + sock.open = true + end + if isa(sock.ccb,Function) + sock.ccb(sock, status) + end + tasknotify(sock.connectnotify, sock, status) +end +#from `listen` +function _uv_hook_connectioncb(sock::AsyncStream, status::Int32) + if(isa(sock.ccb,Function)) + sock.ccb(sock,status) + end + tasknotify(sock.connectnotify, sock, status) +end + +## BUFFER ## +## Allocate a simple buffer +function alloc_request(buffer::IOBuffer, recommended_size::Int32) + ensureroom(buffer, int(recommended_size)) + ptr = buffer.append ? buffer.size + 1 : buffer.ptr + return (pointer(buffer.data, ptr), length(buffer.data)-ptr+1) +end +function _uv_hook_alloc_buf(stream::AsyncStream, recommended_size::Int32) + (buf,size) = alloc_request(stream.buffer, recommended_size) + assert(size>0) # because libuv requires this (TODO: possibly stop reading too if it fails) + (buf,int32(size)) +end + +function notify_filled(buffer::IOBuffer, nread::Int, base::Ptr{Void}, len::Int32) + if buffer.append + buffer.size += nread + else + buffer.ptr += nread + end +end +function notify_filled(stream::AsyncStream, nread::Int) + more = true + while more + if isa(stream.readcb,Function) + nreadable = (stream.line_buffered ? int(search(stream.buffer, '\n')) : nb_available(stream.buffer)) + if nreadable > 0 + more = stream.readcb(stream, nreadable) + else + more = false + end + else + more = false + end + end +end + +function _uv_hook_readcb(stream::AsyncStream, nread::Int, base::Ptr{Void}, len::Int32) + if(nread == -1) + if(_uv_lasterror() != 1) #UV_EOF == 1 + error = UVError("readcb") + close(stream) + throw(error) + end + close(stream) + tasknotify(stream.readnotify, stream) + #EOF + else + notify_filled(stream.buffer, nread, base, len) + notify_filled(stream, nread) + tasknotify(stream.readnotify, stream) + end +end +########################################## +# Async Workers +########################################## + +abstract AsyncWork + +type SingleAsyncWork <: AsyncWork + cb::Function + handle::Ptr{Void} + function SingleAsyncWork(loop::Ptr{Void},cb::Function) + if(loop == C_NULL) + return new(cb,C_NULL) + end + this=new(cb) + this.handle=ccall(:jl_make_async,Ptr{Void},(Ptr{Void},Any),loop,this) + this + end +end +SingleAsyncWork(cb::Function) = SingleAsyncWork(eventloop(),cb) + +type IdleAsyncWork <: AsyncWork + cb::Function + handle::Ptr{Void} + function IdleAsyncWork(loop::Ptr{Void},cb::Function) + this=new(cb) + this.handle=ccall(:jl_make_idle,Ptr{Void},(Ptr{Void},Any),loop,this) + this + end +end +IdleAsyncWork(cb::Function) = IdleAsyncWork(eventloop(),cb) + +type TimeoutAsyncWork <: AsyncWork + cb::Function + handle::Ptr{Void} + function TimeoutAsyncWork(loop::Ptr{Void},cb::Function) + this=new(cb) + this.handle=ccall(:jl_make_timer,Ptr{Void},(Ptr{Void},Any),loop,this) + this + end +end +TimeoutAsyncWork(cb::Function) = TimeoutAsyncWork(eventloop(),cb) + +function _uv_hook_close(uv::AsyncStream) + uv.handle = 0 + uv.open = false + if isa(uv.closecb, Function) uv.closecb(uv) end + tasknotify(uv.closenotify, uv) +end +_uv_hook_close(uv::AsyncWork) = (uv.handle = 0; nothing) + +# This serves as a common callback for all async classes +_uv_hook_asynccb(async::AsyncWork, status::Int32) = async.cb(status) + +function start_timer(timer::TimeoutAsyncWork,timeout::Int64,repeat::Int64) + ccall(:jl_timer_start,Int32,(Ptr{Void},Int64,Int64),timer.handle,timeout,repeat) +end + +function stop_timer(timer::TimeoutAsyncWork) + ccall(:jl_timer_stop,Int32,(Ptr{Void},),timer.handle) +end + +function sleep(sec::Real) + timer = TimeoutAsyncWork(status->tasknotify([wt], status)) + wt = WaitTask(timer, false) + start_timer(timer, int64(iround(sec*1000)), int64(0)) + args = yield(wt) + stop_timer(timer) + if isa(args,InterruptException) + error(args) + end + nothing +end + +assignIdleAsyncWork(work::IdleAsyncWork,cb::Function) = ccall(:jl_idle_start,Ptr{Void},(Ptr{Void},),work.handle) + +function add_idle_cb(loop::Ptr{Void},cb::Function) + work = initIdleAsyncWork(loop) + assignIdleAsyncWork(work,cb) + work +end + +function queueAsync(work::SingleAsyncWork) + ccall(:jl_async_send,Void,(Ptr{Void},),work.handle) +end + +## event loop ## +eventloop() = ccall(:jl_global_event_loop,Ptr{Void},()) +#mkNewEventLoop() = ccall(:jl_new_event_loop,Ptr{Void},()) # this would be fine, but is nowhere supported + +function run_event_loop(loop::Ptr{Void}) + ccall(:jl_run_event_loop,Void,(Ptr{Void},),loop) +end +function process_events(block::Bool,loop::Ptr{Void}) + if(block) + ccall(:jl_run_once,Int32,(Ptr{Void},),loop) + else + ccall(:jl_process_events,Int32,(Ptr{Void},),loop) + end +end +process_events(block::Bool) = process_events(block,eventloop()) +run_event_loop() = run_event_loop(eventloop()) + +##pipe functions +malloc_pipe() = c_malloc(_sizeof_uv_pipe) +function link_pipe(read_end::Ptr{Void},readable_julia_only::Bool,write_end::Ptr{Void},writeable_julia_only::Bool,pipe::AsyncStream) + #make the pipe an unbuffered stream for now + ccall(:jl_init_pipe, Ptr{Void}, (Ptr{Void},Bool,Bool,Any), read_end, 0, readable_julia_only, pipe) + ccall(:jl_init_pipe, Ptr{Void}, (Ptr{Void},Bool,Bool,Any), write_end, 1, readable_julia_only, pipe) + error = ccall(:uv_pipe_link, Int32, (Ptr{Void}, Ptr{Void}), read_end, write_end) + if error != 0 # don't use assert here as $string isn't be defined yet + error("uv_pipe_link failed") + end +end + +function link_pipe(read_end2::NamedPipe,readable_julia_only::Bool,write_end::Ptr{Void},writeable_julia_only::Bool) + if(read_end2.handle == C_NULL) + read_end2.handle = malloc_pipe() + end + link_pipe(read_end2.handle,readable_julia_only,write_end,writeable_julia_only,read_end2) + read_end2.open = true +end +function link_pipe(read_end::Ptr{Void},readable_julia_only::Bool,write_end::NamedPipe,writeable_julia_only::Bool) + if(write_end.handle == C_NULL) + write_end.handle = malloc_pipe() + end + link_pipe(read_end,readable_julia_only,write_end.handle,writeable_julia_only,write_end) + write_end.open = true +end +close_pipe_sync(handle::UVHandle) = ccall(:uv_pipe_close_sync,Void,(UVHandle,),handle) + +function close(stream::AsyncStream) + if stream.open + stream.open = false + ccall(:jl_close_uv,Void,(Ptr{Void},),stream.handle) + end +end + +##stream functions + +start_reading(stream::AsyncStream) = (stream.handle != 0 ? ccall(:jl_start_reading,Int32,(Ptr{Void},),handle(stream)) : int32(0)) +function start_reading(stream::AsyncStream,cb::Function) + start_reading(stream) + stream.readcb = cb + nread = nb_available(stream.buffer) + if nread > 0 + notify_filled(stream,nread) + end +end +start_reading(stream::AsyncStream,cb::Bool) = (start_reading(stream); stream.readcb = cb) + +stop_reading(stream::AsyncStream) = ccall(:uv_read_stop,Bool,(Ptr{Void},),handle(stream)) + +function readall(stream::AsyncStream) + start_reading(stream) + wait_close(stream) + return takebuf_string(stream.buffer) +end + +function read{T}(this::AsyncStream, a::Array{T}) + if isbits(T) + nb = length(a)*sizeof(T) + buf = this.buffer + assert(buf.seekable == false) + assert(buf.maxsize >= nb) + start_reading(this) + wait_readnb(this,nb) + read(this.buffer, a) + return a + else + #error("Read from Buffer only supports bits types or arrays of bits types; got $T.") + error("Read from Buffer only supports bits types or arrays of bits types") + end +end + +function read(this::AsyncStream,::Type{Uint8}) + buf = this.buffer + assert(buf.seekable == false) + start_reading(this) + wait_readnb(this,1) + read(buf,Uint8) +end + +function readline(this::AsyncStream) + buf = this.buffer + assert(buf.seekable == false) + start_reading(this) + wait_readline(this) + readline(buf) +end + +function readuntil(this::AsyncStream,c::Uint8) + buf = this.buffer + assert(buf.seekable == false) + start_reading(this) + wait_readbyte(this,c) + readuntil(buf,c) +end + +function finish_read(pipe::NamedPipe) + close(pipe) #handles to UV and ios will be invalid after this point +end + +function finish_read(state::(NamedPipe,ByteString)) + finish_read(state...) +end + + +## low-level calls + +write(s::AsyncStream, b::ASCIIString) = + int(ccall(:jl_puts, Int32, (Ptr{Uint8},Ptr{Void}),b.data,handle(s))) +write(s::AsyncStream, b::Uint8) = + int(ccall(:jl_putc, Int32, (Uint8, Ptr{Void}), b, handle(s))) +write(s::AsyncStream, c::Char) = + int(ccall(:jl_pututf8, Int32, (Ptr{Void},Char), handle(s), c)) +function write{T}(s::AsyncStream, a::Array{T}) + if isbits(T) + ccall(:jl_write, Int, (Ptr{Void}, Ptr{Void}, Uint32), handle(s), a, uint(length(a)*sizeof(T))) + else + invoke(write,(IO,Array),s,a) + end +end +write(s::AsyncStream, p::Ptr, nb::Integer) = + ccall(:jl_write, Int,(Ptr{Void}, Ptr{Void}, Uint),handle(s), p, uint(nb)) +_write(s::AsyncStream, p::Ptr{Void}, nb::Integer) = + ccall(:jl_write, Int,(Ptr{Void}, Ptr{Void}, Uint),handle(s),p,uint(nb)) + +## Libuv error handling +_uv_lasterror(loop::Ptr{Void}) = ccall(:jl_last_errno,Int32,(Ptr{Void},),loop) +_uv_lasterror() = _uv_lasterror(eventloop()) +_uv_lastsystemerror(loop::Ptr{Void}) = ccall(:jl_last_errno,Int32,(Ptr{Void},),loop) +_uv_lastsystemerror() = _uv_lasterror(eventloop()) + +type UV_error_t + uv_code::Int32 + system_code::Int32 +end +type UVError <: Exception + prefix::String + s::UV_error_t + UVError(p::String,e::UV_error_t)=new(p,e) +end +UVError(p::String) = UVError(p,_uv_lasterror(),_uv_lastsystemerror()) +UVError(p::String,uv::Integer,system::Integer) = UVError(p,UV_error_t(uv,system)) + +struverror(err::UVError) = bytestring(ccall(:jl_uv_strerror,Ptr{Uint8},(Int32,Int32),err.s.uv_code,err.s.system_code)) +uverrorname(err::UVError) = bytestring(ccall(:jl_uv_err_name,Ptr{Uint8},(Int32,Int32),err.s.uv_code,err.s.system_code)) + +uv_error(prefix, e::UV_error_t) = e.uv_code != 0 ? throw(UVError(string(prefix),e)) : nothing +uv_error(prefix, b::Bool) = b ? throw(UVError(string(prefix))) : nothing +uv_error(prefix) = uv_error(prefix, _uv_lasterror() != 0) + +show(io::IO, e::UVError) = print(io, e.prefix*": "*struverror(e)*" ("*uverrorname(e)*")") + +function readall(s::IOStream) + dest = memio() + ccall(:ios_copyall, Uint, (Ptr{Void}, Ptr{Void}), dest.ios, s.ios) + takebuf_string(dest) +end + +function listen(sock::AsyncStream, backlog::Integer) + err = ccall(:jl_listen, Int32, (Ptr{Void}, Int32), sock.handle, backlog) + err != -1 ? (sock.open = true): false +end +listen(sock::AsyncStream) = listen(sock, 511) # same default as node.js diff --git a/base/string.jl b/base/string.jl index 0d5f546193b42..69c0914a3d5f2 100644 --- a/base/string.jl +++ b/base/string.jl @@ -4,12 +4,12 @@ print(io::IO, x) = show(io, x) print(io::IO, xs...) = for x in xs print(io, x) end println(io::IO, xs...) = print(io, xs..., '\n') -print(xs...) = print(OUTPUT_STREAM::IOStream, xs...) -println(xs...) = println(OUTPUT_STREAM::IOStream, xs...) +print(xs...) = print(OUTPUT_STREAM, xs...) +println(xs...) = println(OUTPUT_STREAM, xs...) ## core string functions ## -length(s::String) = error("you must implement length(", typeof(s), ")") +endof(s::String) = error("you must implement endof(", typeof(s), ")") next(s::String, i::Int) = error("you must implement next(", typeof(s), ",Int)") next(s::DirectIndexString, i::Int) = (s[i],i+1) next(s::String, i::Integer) = next(s,int(i)) @@ -17,7 +17,7 @@ next(s::String, i::Integer) = next(s,int(i)) ## conversion of general objects to strings ## function print_to_string(xs...) - s = memio(isa(xs[1],String) ? length(xs[1]) : 0, false) + s = memio(isa(xs[1],String) ? endof(xs[1]) : 0, false) for x in xs print(s, x) end @@ -29,8 +29,8 @@ string(s::String) = s string(xs...) = print_to_string(xs...) bytestring() = "" -bytestring(s::Array{Uint8,1}) = utf8(s) -bytestring(s::String) = print_to_string(s) +bytestring(s::Array{Uint8,1}) = bytestring(pointer(s),length(s)) +bytestring(s::String...) = print_to_string(s...) function bytestring(p::Ptr{Uint8}) p == C_NULL ? error("cannot convert NULL to string") : @@ -49,14 +49,14 @@ convert(::Type{ByteString}, s::String) = bytestring(s) ## generic supplied functions ## start(s::String) = 1 -done(s::String,i) = (i > length(s)) +done(s::String,i) = (i > endof(s)) isempty(s::String) = done(s,start(s)) -ref(s::String, i::Int) = next(s,i)[1] -ref(s::String, i::Integer) = s[int(i)] -ref(s::String, x::Real) = s[to_index(x)] -ref{T<:Integer}(s::String, r::Range1{T}) = s[int(first(r)):int(last(r))] +getindex(s::String, i::Int) = next(s,i)[1] +getindex(s::String, i::Integer) = s[int(i)] +getindex(s::String, x::Real) = s[to_index(x)] +getindex{T<:Integer}(s::String, r::Range1{T}) = s[int(first(r)):int(last(r))] # TODO: handle other ranges with stride ±1 specially? -ref(s::String, v::AbstractVector) = +getindex(s::String, v::AbstractVector) = sprint(length(v), io->(for i in v write(io,s[i]) end)) symbol(s::String) = symbol(bytestring(s)) @@ -65,15 +65,11 @@ print(io::IO, s::String) = for c in s write(io, c) end write(io::IO, s::String) = print(io, s) show(io::IO, s::String) = print_quoted(io, s) -(*)(s::String...) = strcat(s...) +(*)(s::String...) = string(s...) (^)(s::String, r::Integer) = repeat(s,r) -size(s::String) = (length(s),) -size(s::String, d::Integer) = d==1 ? length(s) : - error("in size: dimension ",d," out of range") - -strlen(s::DirectIndexString) = length(s) -function strlen(s::String) +length(s::DirectIndexString) = endof(s) +function length(s::String) i = start(s) if done(s,i) return 0 @@ -89,7 +85,7 @@ function strlen(s::String) end end -isvalid(s::DirectIndexString, i::Integer) = (start(s) <= i <= length(s)) +isvalid(s::DirectIndexString, i::Integer) = (start(s) <= i <= endof(s)) function isvalid(s::String, i::Integer) try next(s,i) @@ -115,12 +111,12 @@ function thisind(s::String, i::Integer) end function nextind(s::String, i::Integer) - for j = i+1:length(s) + for j = i+1:endof(s) if isvalid(s,j) return j end end - length(s)+1 # out of range + endof(s)+1 # out of range end ind2chr(s::DirectIndexString, i::Integer) = i @@ -158,7 +154,13 @@ end typealias Chars Union(Char,AbstractVector{Char},Set{Char}) -function strchr(s::String, c::Chars, i::Integer) +function search(s::String, c::Chars, i::Integer) + if isempty(c) + return 1 <= i <= endof(s)+1 ? i : + i == endof(s)+2 ? 0 : + error(BoundsError) + end + if i < 1 error(BoundsError) end i = nextind(s,i-1) while !done(s,i) @@ -170,31 +172,20 @@ function strchr(s::String, c::Chars, i::Integer) end return 0 end -strchr(s::String, c::Chars) = strchr(s,c,start(s)) - -contains(s::String, c::Char) = (strchr(s,c)!=0) - -function search(s::String, c::Chars, i::Integer) - if isempty(c) - return 1 <= i <= length(s)+1 ? (i,i) : - i == length(s)+2 ? (0,0) : - error(BoundsError) - end - i=strchr(s,c,i) - (i, nextind(s,i)) -end search(s::String, c::Chars) = search(s,c,start(s)) +contains(s::String, c::Char) = (search(s,c)!=0) + function search(s::String, t::String, i::Integer) if isempty(t) - return 1 <= i <= length(s)+1 ? (i,i) : - i == length(s)+2 ? (0,0) : + return 1 <= i <= endof(s)+1 ? (i:i-1) : + i == endof(s)+2 ? (0:-1) : error(BoundsError) end t1, j2 = next(t,start(t)) while true - i = strchr(s,t1,i) - if i == 0 return (0,0) end + i = search(s,t1,i) + if i == 0 return (0:-1) end c, ii = next(s,i) j = j2; k = ii matched = true @@ -211,33 +202,13 @@ function search(s::String, t::String, i::Integer) end end if matched - return (i,k) + return i:k-1 end i = ii end end search(s::String, t::String) = search(s,t,start(s)) -type EachSearch - string::String - pattern -end -each_search(string::String, pattern) = EachSearch(string, pattern) - -start(itr::EachSearch) = search(itr.string, itr.pattern) -done(itr::EachSearch, st) = (st[1]==0) -next(itr::EachSearch, st) = - (st, search(itr.string, itr.pattern, max(nextind(itr.string,st[1]),st[2]))) - -function chars(s::String) - cx = Array(Char,strlen(s)) - i = 0 - for c in s - cx[i+=1] = c - end - return cx -end - function cmp(a::String, b::String) i = start(a) j = start(b) @@ -259,7 +230,7 @@ hash(s::String) = hash(bytestring(s)) # begins with and ends with predicates -function begins_with(a::String, b::String) +function beginswith(a::String, b::String) i = start(a) j = start(b) while !done(a,i) && !done(b,i) @@ -269,11 +240,11 @@ function begins_with(a::String, b::String) end done(b,i) end -begins_with(a::String, c::Char) = length(a) > 0 && a[start(a)] == c +beginswith(a::String, c::Char) = !isempty(a) && a[start(a)] == c -function ends_with(a::String, b::String) - i = thisind(a,length(a)) - j = thisind(b,length(b)) +function endswith(a::String, b::String) + i = endof(a) + j = endof(b) a1 = start(a) b1 = start(b) while a1 <= i && b1 <= j @@ -285,14 +256,17 @@ function ends_with(a::String, b::String) end j < b1 end -ends_with(a::String, c::Char) = length(a) > 0 && a[thisind(a,end)] == c +endswith(a::String, c::Char) = !isempty(a) && a[end] == c # faster comparisons for byte strings cmp(a::ByteString, b::ByteString) = cmp(a.data, b.data) -isequal(a::ByteString, b::ByteString) = length(a)==length(b) && cmp(a,b)==0 +isequal(a::ByteString, b::ByteString) = endof(a)==endof(b) && cmp(a,b)==0 +beginswith(a::ByteString, b::ByteString) = beginswith(a.data, b.data) -# TODO: fast begins_with and ends_with +beginswith(a::Array{Uint8,1}, b::Array{Uint8,1}) = (length(a) >= length(b) && ccall(:strncmp, Int32, (Ptr{Uint8}, Ptr{Uint8}, Uint), a, b, length(b)) == 0) + +# TODO: fast endswith ## character column width function ## @@ -301,18 +275,30 @@ strwidth(s::String) = (w=0; for c in s; w += charwidth(c); end; w) strwidth(s::ByteString) = ccall(:u8_strwidth, Int, (Ptr{Uint8},), s.data) # TODO: implement and use u8_strnwidth that takes a length argument -## generic string uses only length and next ## +## libc character class predicates ## + +isascii(c::Char) = c < 0x80 -type GenericString <: String +for name = ("alnum", "alpha", "cntrl", "digit", "graph", + "lower", "print", "punct", "space", "upper") + f = symbol(string("is",name)) + @eval ($f)(c::Char) = bool(ccall($(string("isw",name)), Int32, (Char,), c)) +end + +isblank(c::Char) = c==' ' || c=='\t' + +## generic string uses only endof and next ## + +immutable GenericString <: String string::String end -length(s::GenericString) = length(s.string) +endof(s::GenericString) = endof(s.string) next(s::GenericString, i::Int) = next(s.string, i) ## plain old character arrays ## -type CharString <: String +immutable CharString <: DirectIndexString chars::Array{Char,1} CharString(a::Array{Char,1}) = new(a) @@ -321,15 +307,15 @@ end CharString(x...) = CharString(map(char,x)...) next(s::CharString, i::Int) = (s.chars[i], i+1) +endof(s::CharString) = length(s.chars) length(s::CharString) = length(s.chars) -strlen(s::CharString) = length(s) ## substrings reference original strings ## -type SubString{T<:String} <: String +immutable SubString{T<:String} <: String string::T offset::Int - length::Int + endof::Int SubString(s::T, i::Int, j::Int) = (o=nextind(s,i-1)-1; new(s,o,nextind(s,j)-o-1)) @@ -337,24 +323,26 @@ end SubString{T<:String}(s::T, i::Int, j::Int) = SubString{T}(s, i, j) SubString(s::SubString, i::Int, j::Int) = SubString(s.string, s.offset+i, s.offset+j) SubString(s::String, i::Integer, j::Integer) = SubString(s, int(i), int(j)) -SubString(s::String, i::Integer) = SubString(s, i, length(s)) +SubString(s::String, i::Integer) = SubString(s, i, endof(s)) + +write{T<:ByteString}(to::IOBuffer, s::SubString{T}) = write_sub(to, s.string.data, s.offset+1, s.endof) function next(s::SubString, i::Int) - if i < 1 || i > s.length + if i < 1 || i > s.endof error(BoundsError) end c, i = next(s.string, i+s.offset) c, i-s.offset end -length(s::SubString) = s.length -# TODO: strlen(s::SubString) = ?? +endof(s::SubString) = s.endof +# TODO: length(s::SubString) = ?? # default implementation will work but it's slow # can this be delegated efficiently somehow? # that may require additional string interfaces -function ref(s::String, r::Range1{Int}) - if first(r) < 1 || length(s) < last(r) +function getindex(s::String, r::Range1{Int}) + if first(r) < 1 || endof(s) < last(r) error(BoundsError) end SubString(s, first(r), last(r)) @@ -362,16 +350,16 @@ end ## efficient representation of repeated strings ## -type RepString <: String +immutable RepString <: String string::String repeat::Integer end +endof(s::RepString) = endof(s.string)*s.repeat length(s::RepString) = length(s.string)*s.repeat -strlen(s::RepString) = strlen(s.string)*s.repeat function next(s::RepString, i::Int) - if i < 1 || i > length(s) + if i < 1 || i > endof(s) error(BoundsError) end j = mod1(i,length(s.string)) @@ -390,16 +378,15 @@ convert(::Type{RepString}, s::String) = RepString(s,1) ## reversed strings without data movement ## -type RevString <: String +immutable RevString <: String string::String end +endof(s::RevString) = endof(s.string) length(s::RevString) = length(s.string) -strlen(s::RevString) = strlen(s.string) -start(s::RevString) = (n=length(s); n-thisind(s.string,n)+1) function next(s::RevString, i::Int) - n = length(s); j = n-i+1 + n = endof(s); j = n-i+1 (s.string[j], n-thisind(s.string,j-1)+1) end @@ -408,29 +395,29 @@ reverse(s::RevString) = s.string ## ropes for efficient concatenation, etc. ## -type RopeString <: String +immutable RopeString <: String head::String tail::String depth::Int32 - length::Int + endof::Int RopeString(h::RopeString, t::RopeString) = strdepth(h.tail) + strdepth(t) < strdepth(h.head) ? RopeString(h.head, RopeString(h.tail, t)) : - new(h, t, max(h.depth,t.depth)+1, length(h)+length(t)) + new(h, t, max(h.depth,t.depth)+1, endof(h)+endof(t)) RopeString(h::RopeString, t::String) = strdepth(h.tail) < strdepth(h.head) ? RopeString(h.head, RopeString(h.tail, t)) : - new(h, t, h.depth+1, length(h)+length(t)) + new(h, t, h.depth+1, endof(h)+endof(t)) RopeString(h::String, t::RopeString) = strdepth(t.head) < strdepth(t.tail) ? RopeString(RopeString(h, t.head), t.tail) : - new(h, t, t.depth+1, length(h)+length(t)) + new(h, t, t.depth+1, endof(h)+endof(t)) RopeString(h::String, t::String) = - new(h, t, 1, length(h)+length(t)) + new(h, t, 1, endof(h)+endof(t)) end RopeString(s::String) = RopeString(s,"") @@ -438,104 +425,37 @@ strdepth(s::String) = 0 strdepth(s::RopeString) = s.depth function next(s::RopeString, i::Int) - if i <= length(s.head) + eh = endof(s.head) + if i <= eh return next(s.head, i) else - c, j = next(s.tail, i-length(s.head)) - return c, j+length(s.head) + c, j = next(s.tail, i-eh) + return c, j+eh end end -length(s::RopeString) = s.length -strlen(s::RopeString) = strlen(s.head) + strlen(s.tail) - -strcat() = "" -strcat(s::String) = s -strcat(s::String, t::String...) = - (t = strcat(t...); isempty(s) ? t : isempty(t) ? s : RopeString(s, t)) -strcat(xs...) = string(xs...) # backwards compat - +endof(s::RopeString) = s.endof print(io::IO, s::RopeString) = print(io, s.head, s.tail) - write(io::IO, s::RopeString) = (write(io, s.head); write(io, s.tail)) -## transformed strings ## - -type TransformedString <: String - transform::Function - string::String -end - -length(s::TransformedString) = length(s.string) -strlen(s::TransformedString) = strlen(s.string) - -function next(s::TransformedString, i::Int) - c, j = next(s.string,i) - c = s.transform(c, i) - return c, j -end - ## uppercase and lowercase transformations ## -const _TF_U = (c,i)->uppercase(c) -const _TF_L = (c,i)->lowercase(c) -const _TF_u = (c,i)->i==1 ? uppercase(c) : c -const _TF_l = (c,i)->i==1 ? lowercase(c) : c -const _TF_C = (c,i)->i==1 ? uppercase(c) : lowercase(c) -const _TF_c = (c,i)->i==1 ? lowercase(c) : uppercase(c) - uppercase(c::Char) = ccall(:towupper, Char, (Char,), c) lowercase(c::Char) = ccall(:towlower, Char, (Char,), c) uppercase(c::Uint8) = ccall(:toupper, Uint8, (Uint8,), c) lowercase(c::Uint8) = ccall(:tolower, Uint8, (Uint8,), c) -uppercase(s::String) = TransformedString(_TF_U, s) -lowercase(s::String) = TransformedString(_TF_L, s) - -ucfirst(s::String) = TransformedString(_TF_u, s) -lcfirst(s::String) = TransformedString(_TF_l, s) - -function _transfunc_compose(f2::Function, f1::Function) - allf = [_TF_U, _TF_L, _TF_u, _TF_l, _TF_C, _TF_c] - if !contains(allf, f2) || !contains(allf, f1) - return nothing - end - if f2 == _TF_U || f2 == _TF_L || f2 == _TF_C || f2 == _TF_c || - f2 == f1 || - (f2 == _TF_u && f1 == _TF_l) || - (f2 == _TF_l && f1 == _TF_u) - return f2 - elseif (f2 == _TF_u && (f1 == _TF_U || f1 == _TF_C)) || - (f2 == _TF_l && (f1 == _TF_L || f1 == _TF_c)) - return f1 - elseif (f2 == _TF_u && f1 == _TF_L) - return _TF_C - elseif (f2 == _TF_l && f1 == _TF_U) - return _TF_c - elseif (f2 == _TF_u && f1 == _TF_c) - return _TF_U - elseif (f2 == _TF_l && f1 == _TF_C) - return _TF_L - end - error("this is a bug") -end - -function TransformedString(transform::Function, s::TransformedString) - newtf = _transfunc_compose(transform, s.transform) - if newtf === nothing - return invoke(TransformedString, (Function, String), transform, s) - end - TransformedString(newtf, s.string) -end +uppercase(s::String) = map(uppercase, s) +lowercase(s::String) = map(lowercase, s) -const uc = uppercase -const lc = lowercase +ucfirst(s::String) = isupper(s[1]) ? s : string(uppercase(s[1]),s[nextind(s,1):end]) +lcfirst(s::String) = islower(s[1]) ? s : string(lowercase(s[1]),s[nextind(s,1):end]) ## string map, filter, has ## function map(f::Function, s::String) - out = memio(length(s)) + out = memio(endof(s)) for c in s write(out, f(c)::Char) end @@ -543,7 +463,7 @@ function map(f::Function, s::String) end function filter(f::Function, s::String) - out = memio(length(s)) + out = memio(endof(s)) for c in s if f(c) write(out, c) @@ -552,8 +472,6 @@ function filter(f::Function, s::String) takebuf_string(out) end -has(s::String, c::Char) = contains(s, c) - ## string promotion rules ## promote_rule(::Type{UTF8String} , ::Type{ASCIIString}) = UTF8String @@ -574,35 +492,34 @@ end ## string escaping & unescaping ## escape_nul(s::String, i::Int) = - !done(s,i) && '0' <= next(s,i)[1] <= '7' ? L"\x00" : L"\0" + !done(s,i) && '0' <= next(s,i)[1] <= '7' ? "\\x00" : "\\0" -is_hex_digit(c::Char) = '0'<=c<='9' || 'a'<=c<='f' || 'A'<=c<='F' -need_full_hex(s::String, i::Int) = !done(s,i) && is_hex_digit(next(s,i)[1]) +isxdigit(c::Char) = '0'<=c<='9' || 'a'<=c<='f' || 'A'<=c<='F' +need_full_hex(s::String, i::Int) = !done(s,i) && isxdigit(next(s,i)[1]) function print_escaped(io, s::String, esc::String) i = start(s) while !done(s,i) c, j = next(s,i) c == '\0' ? print(io, escape_nul(s,j)) : - c == '\e' ? print(io, L"\e") : + c == '\e' ? print(io, "\\e") : c == '\\' ? print(io, "\\\\") : contains(esc,c) ? print(io, '\\', c) : - 7 <= c <= 13 ? print(io, '\\', "abtnvfr"[c-6]) : - iswprint(c) ? print(io, c) : - c <= '\x7f' ? print(io, L"\x", hex(c, 2)) : - c <= '\uffff' ? print(io, L"\u", hex(c, need_full_hex(s,j) ? 4 : 2)) : - print(io, L"\U", hex(c, need_full_hex(s,j) ? 8 : 4)) + 7 <= c <= 13 ? print(io, '\\', "abtnvfr"[int(c-6)]) : + isprint(c) ? print(io, c) : + c <= '\x7f' ? print(io, "\\x", hex(c, 2)) : + c <= '\uffff' ? print(io, "\\u", hex(c, need_full_hex(s,j) ? 4 : 2)) : + print(io, "\\U", hex(c, need_full_hex(s,j) ? 8 : 4)) i = j end end -escape_string(s::String) = sprint(length(s), print_escaped, s, "\"") +escape_string(s::String) = sprint(endof(s), print_escaped, s, "\"") function print_quoted(io, s::String) print(io, '"') print_escaped(io, s, "\"\$") #"# work around syntax highlighting problem print(io, '"') end -quote_string(s::String) = sprint(length(s)+2, io->print_quoted(io,s)) # bare minimum unescaping function unescapes only given characters @@ -621,7 +538,7 @@ function print_unescaped_chars(io, s::String, esc::String) end unescape_chars(s::String, esc::String) = - sprint(length(s), print_unescaped_chars, s, esc) + sprint(endof(s), print_unescaped_chars, s, esc) # general unescaping of traditional C and Unicode escape sequences @@ -678,78 +595,117 @@ function print_unescaped(io, s::String) end end -unescape_string(s::String) = sprint(length(s), print_unescaped, s) +unescape_string(s::String) = sprint(endof(s), print_unescaped, s) ## checking UTF-8 & ACSII validity ## -byte_string_classify(s::ByteString) = - ccall(:u8_isvalid, Int32, (Ptr{Uint8}, Int), s.data, length(s)) +byte_string_classify(data::Array{Uint8,1}) = + ccall(:u8_isvalid, Int32, (Ptr{Uint8}, Int), data, length(data)) +byte_string_classify(s::ByteString) = byte_string_classify(s.data) # 0: neither valid ASCII nor UTF-8 # 1: valid ASCII # 2: valid UTF-8 -is_valid_ascii(s::ByteString) = byte_string_classify(s) == 1 -is_valid_utf8 (s::ByteString) = byte_string_classify(s) != 0 +is_valid_ascii(s::Union(Array{Uint8,1},ByteString)) = byte_string_classify(s) == 1 +is_valid_utf8 (s::Union(Array{Uint8,1},ByteString)) = byte_string_classify(s) != 0 -check_ascii(s::ByteString) = is_valid_ascii(s) ? s : error("invalid ASCII sequence") -check_utf8 (s::ByteString) = is_valid_utf8(s) ? s : error("invalid UTF-8 sequence") +## multiline strings ## -## string interpolation parsing ## +function blank_width(c::Char) + c == ' ' ? 1 : + c == '\t' ? 8 : + error("not a blank character") +end -function _jl_interp_parse(s::String, unescape::Function, printer::Function) - sx = {} - i = j = start(s) - while !done(s,j) - c, k = next(s,j) - if c == '$' - if !isempty(s[i:j-1]) - push(sx, unescape(s[i:j-1])) - end - ex, j = parseatom(s,k) - if isa(ex,Expr) && is(ex.head,:continue) - throw(ParseError("incomplete expression")) +# width of leading blank space, also check if string is blank +function indentation(s::String) + count = 0 + for c in s + if isblank(c) + count += blank_width(c) + else + return count, false + end + end + count, true +end + +function unindent(s::String, indent::Int) + buf = memio(endof(s), false) + a = i = start(s) + cutting = false + cut = 0 + while !done(s,i) + c,i_ = next(s,i) + if cutting && isblank(c) + a = i_ + cut += blank_width(c) + if cut > indent + cutting = false + for _ = (indent+1):cut write(buf, ' ') end end - push(sx, esc(ex)) - i = j - elseif c == '\\' && !done(s,k) - if s[k] == '$' - if !isempty(s[i:j-1]) - push(sx, unescape(s[i:j-1])) + elseif c == '\n' + print(buf, s[a:i]) + a = i_ + cutting = true + cut = 0 + else + cutting = false + end + i = i_ + end + print(buf, s[a:end]) + takebuf_string(buf) +end + +function triplequoted(args...) + sx = { isa(arg,ByteString) ? arg : esc(arg) for arg in args } + + indent = 0 + rlines = split(reverse(sx[end]), '\n', 2) + last_line = rlines[1] + if length(rlines) > 1 && lstrip(last_line) == "" + indent,_ = indentation(last_line) + else + indent = typemax(Int) + for s in sx + if isa(s,ByteString) + lines = split(s,'\n') + for line in lines[2:end] + n,blank = indentation(line) + if !blank + indent = min(indent, n) + end end - i = k end - c, j = next(s,k) - else - j = k end end - if !isempty(s[i:]) - push(sx, unescape(s[i:j-1])) + + for i in 1:length(sx) + if isa(sx[i],ByteString) + sx[i] = unindent(sx[i], indent) + end end - length(sx) == 1 && isa(sx[1],ByteString) ? sx[1] : - expr(:call, :sprint, printer, sx...) -end -_jl_interp_parse(s::String, u::Function) = _jl_interp_parse(s, u, print) -_jl_interp_parse(s::String) = _jl_interp_parse(s, x->check_utf8(unescape_string(x))) + # strip leading blank line + s = sx[1] + j = search(s,'\n') + if j != 0 && lstrip(s[1:j]) == "" + sx[1] = s[j+1:end] + end -function _jl_interp_parse_bytes(s::String) - writer(io,x...) = for w=x; write(io,w); end - _jl_interp_parse(s, unescape_string, writer) + length(sx) == 1 ? sx[1] : Expr(:call, :string, sx...) end ## core string macros ## -macro str(s); _jl_interp_parse(s); end -macro S_str(s); _jl_interp_parse(s); end -macro I_str(s); _jl_interp_parse(s, x->unescape_chars(x,"\"")); end -macro E_str(s); check_utf8(unescape_string(s)); end -macro B_str(s); _jl_interp_parse_bytes(s); end -macro b_str(s); ex = _jl_interp_parse_bytes(s); :(($ex).data); end +macro b_str(s); :($(unescape_string(s)).data); end + +macro mstr(s...); triplequoted(s...); end ## shell-like command parsing ## -function _jl_shell_parse(raw::String, interp::Bool) +function shell_parse(raw::String, interp::Bool) s = strip(raw) in_single_quotes = false @@ -762,24 +718,24 @@ function _jl_shell_parse(raw::String, interp::Bool) function update_arg(x) if !isa(x,String) || !isempty(x) - push(arg, x) + push!(arg, x) end end function append_arg() if isempty(arg); arg = {"",}; end - push(args, arg) + push!(args, arg) arg = {} end while !done(s,j) c, k = next(s,j) - if !in_single_quotes && !in_double_quotes && iswspace(c) + if !in_single_quotes && !in_double_quotes && isspace(c) update_arg(s[i:j-1]) append_arg() j = k while !done(s,j) c, k = next(s,j) - if !iswspace(c) + if !isspace(c) i = j break end @@ -790,10 +746,10 @@ function _jl_shell_parse(raw::String, interp::Bool) if done(s,k) error("\$ right before end of command") end - if iswspace(s[k]) + if isspace(s[k]) error("space not allowed right after \$") end - ex, j = parseatom(s,j) + ex, j = parse(s,j,false) update_arg(esc(ex)); i = j else if !in_double_quotes && c == '\'' @@ -834,19 +790,19 @@ function _jl_shell_parse(raw::String, interp::Bool) end # construct an expression - exprs = {} + ex = Expr(:tuple) for arg in args - push(exprs, expr(:tuple, arg)) + push!(ex.args, Expr(:tuple, arg...)) end - expr(:tuple,exprs) + ex end -_jl_shell_parse(s::String) = _jl_shell_parse(s,true) +shell_parse(s::String) = shell_parse(s,true) function shell_split(s::String) - parsed = _jl_shell_parse(s,false) + parsed = shell_parse(s,false) args = String[] for arg in parsed - push(args, string(arg...)) + push!(args, string(arg...)) end args end @@ -858,7 +814,7 @@ function print_shell_word(io, word::String) has_single = false has_special = false for c in word - if iswspace(c) || c=='\\' || c=='\'' || c=='"' || c=='$' + if isspace(c) || c=='\\' || c=='\'' || c=='"' || c=='$' has_special = true if c == '\'' has_single = true @@ -894,29 +850,38 @@ shell_escape(cmd::String, args::String...) = ## interface to parser ## -function parse(s::String, pos, greedy) +function parse(str::String, pos::Int, greedy::Bool, err::Bool) # returns (expr, end_pos). expr is () in case of parse error. ex, pos = ccall(:jl_parse_string, Any, (Ptr{Uint8}, Int32, Int32), - s, pos-1, greedy ? 1:0) - if isa(ex,Expr) && is(ex.head,:error) + str, pos-1, greedy ? 1:0) + if err && isa(ex,Expr) && is(ex.head,:error) throw(ParseError(ex.args[1])) end - if ex == (); throw(ParseError("end of input")); end + if ex == () + if err + throw(ParseError("end of input")) + else + ex = Expr(:error, "end of input") + end + end ex, pos+1 # C is zero-based, Julia is 1-based end +parse(str::String, pos::Int, greedy::Bool) = parse(str, pos, greedy, true) +parse(str::String, pos::Int) = parse(str, pos, true) -parse(s::String) = parse(s, 1, true) -parse(s::String, pos) = parse(s, pos, true) -parseatom(s::String) = parse(s, 1, false) -parseatom(s::String, pos) = parse(s, pos, false) +function parse(str::String) + ex, pos = parse(str, start(str)) + done(str, pos) || error("syntax: extra token after end of expression") + return ex +end ## miscellaneous string functions ## function lpad(s::String, n::Integer, p::String) - m = n - strlen(s) + m = n - length(s) if m <= 0; return s; end - l = strlen(p) + l = length(p) if l==1 return bytestring(p^m * s) end @@ -926,9 +891,9 @@ function lpad(s::String, n::Integer, p::String) end function rpad(s::String, n::Integer, p::String) - m = n - strlen(s) + m = n - length(s) if m <= 0; return s; end - l = strlen(p) + l = length(p) if l==1 return bytestring(s * p^m) end @@ -949,20 +914,22 @@ rpad(s, n::Integer) = rpad(string(s), n, " ") function split(str::String, splitter, limit::Integer, keep_empty::Bool) strs = String[] i = start(str) - n = length(str) - j, k = search(str,splitter,i) + n = endof(str) + r = search(str,splitter,i) + j, k = first(r), last(r)+1 while 0 < j <= n && length(strs) != limit-1 if i < k if keep_empty || i < j - push(strs, str[i:j-1]) + push!(strs, str[i:j-1]) end i = k end if k <= j; k = nextind(str,j) end - j, k = search(str,splitter,k) + r = search(str,splitter,k) + j, k = first(r), last(r)+1 end if keep_empty || !done(str,i) - push(strs, str[i:]) + push!(strs, str[i:]) end return strs end @@ -978,42 +945,28 @@ function replace(str::ByteString, pattern, repl::Function, limit::Integer) n = 1 rstr = "" i = a = start(str) - j, k = search(str,pattern,i) + r = search(str,pattern,i) + j, k = first(r), last(r)+1 + out = IOBuffer() while j != 0 if i == a || i < k - rstr = RopeString(rstr,SubString(str,i,j-1)) - rstr = RopeString(rstr,string(repl(SubString(str,j,k-1)))) + write(out, SubString(str,i,j-1)) + write(out, string(repl(SubString(str,j,k-1)))) i = k end if k <= j; k = nextind(str,j) end - j, k = search(str,pattern,k) + r = search(str,pattern,k) + j, k = first(r), last(r)+1 if n == limit break end n += 1 end - rstr = RopeString(rstr,SubString(str,i)) - bytestring(rstr) + write(out, SubString(str,i)) + takebuf_string(out) end replace(s::String, pat, f::Function, n::Integer) = replace(bytestring(s), pat, f, n) replace(s::String, pat, r, n::Integer) = replace(s, pat, x->r, n) replace(s::String, pat, r) = replace(s, pat, r, 0) -function search_count(str::String, pattern, limit::Integer) - n = 0 - i = a = start(str) - j, k = search(str,pattern,i) - while j != 0 - if i == a || i < k - n += 1 - if n == limit break end - i = k - end - if k <= j; k = nextind(str,j) end - j, k = search(str,pattern,k) - end - return n -end -search_count(s::String, pat) = search_count(s, pat, 0) - function print_joined(io, strings, delim, last) i = start(strings) if done(strings,i) @@ -1042,24 +995,34 @@ print_joined(io, strings) = print_joined(io, strings, "") join(args...) = sprint(print_joined, args...) -chop(s::String) = s[1:thisind(s,length(s))-1] +chop(s::String) = s[1:end-1] function chomp(s::String) - i = thisind(s,length(s)) + i = endof(s) if (i < 1 || s[i] != '\n') return s end j = prevind(s,i) if (j < 1 || s[j] != '\r') return s[1:i-1] end return s[1:j-1] end chomp(s::ByteString) = - (length(s) < 1 || s.data[end] != 0x0a) ? s : - (length(s) < 2 || s.data[end-1] != 0x0d) ? s[1:end-1] : s[1:end-2] + (endof(s) < 1 || s.data[end] != 0x0a) ? s : + (endof(s) < 2 || s.data[end-1] != 0x0d) ? s[1:end-1] : s[1:end-2] + +# NOTE: use with caution -- breaks the immutable string convention! +function chomp!(s::ByteString) + if !isempty(s) && s.data[end] == 0x0a + n = (endof(s) < 2 || s.data[end-1] != 0x0d) ? 1 : 2 + ccall(:jl_array_del_end, Void, (Any, Uint), s.data, n) + end + return s +end +chomp!(s::String) = chomp(s) # copying fallback for other string types -function lstrip(s::String) +function lstrip(s::String, chars::String) i = start(s) while !done(s,i) c, j = next(s,i) - if !iswspace(c) + if !contains(chars, c) return s[i:end] end i = j @@ -1067,12 +1030,12 @@ function lstrip(s::String) "" end -function rstrip(s::String) +function rstrip(s::String, chars::String) r = reverse(s) i = start(r) while !done(r,i) c, j = next(r,i) - if !iswspace(c) + if !contains(chars, c) return s[1:end-i+1] end i = j @@ -1080,36 +1043,41 @@ function rstrip(s::String) "" end +for stripfn in {:lstrip, :rstrip} + @eval ($stripfn)(s::String) = ($stripfn)(s, " \f\n\r\t\v") +end + strip(s::String) = lstrip(rstrip(s)) +strip(s::String, chars::String) = lstrip(rstrip(s, chars), chars) ## string to integer functions ## -function parse_int{T<:Integer}(::Type{T}, s::String, base::Integer) +function parseint{T<:Integer}(::Type{T}, s::String, base::Integer) if !(2 <= base <= 36); error("invalid base: ",base); end i = start(s) while true if done(s,i) - throw(ArgumentError(strcat( + throw(ArgumentError(string( "premature end of integer (in ", repr(s) ,")" ))) end c,i = next(s,i) - if !iswspace(c) + if !isspace(c) break end end - sgn = one(T) + sgn = 1 if T <: Signed && c == '-' - sgn = -sgn + sgn = -1 if done(s,i) - throw(ArgumentError(strcat( + throw(ArgumentError(string( "premature end of integer (in ", repr(s), ")" ))) end c,i = next(s,i) elseif c == '+' if done(s,i) - throw(ArgumentError(strcat( + throw(ArgumentError(string( "premature end of integer (in ", repr(s), ")" ))) end @@ -1122,15 +1090,15 @@ function parse_int{T<:Integer}(::Type{T}, s::String, base::Integer) 'A' <= c <= 'Z' ? c-'A'+10 : 'a' <= c <= 'z' ? c-'a'+10 : typemax(Int) if d >= base - if !iswspace(c) - throw(ArgumentError(strcat( + if !isspace(c) + throw(ArgumentError(string( repr(c)," is not a valid digit (in ", repr(s), ")" ))) end while !done(s,i) c,i = next(s,i) - if !iswspace(c) - throw(ArgumentError(strcat( + if !isspace(c) + throw(ArgumentError(string( "extra characters after whitespace (in ", repr(s), ")" ))) end @@ -1145,38 +1113,29 @@ function parse_int{T<:Integer}(::Type{T}, s::String, base::Integer) c,i = next(s,i) end if T <: Signed - return flipsign(n,sgn) - else - return n + n = flipsign(n,sgn) end + return n end -parse_int(s::String, base::Integer) = parse_int(Int,s,base) -parse_int(T::Type, s::String) = parse_int(T,s,10) -parse_int(s::String) = parse_int(Int,s,10) - -parse_bin(T::Type, s::String) = parse_int(T,s,2) -parse_oct(T::Type, s::String) = parse_int(T,s,8) -parse_hex(T::Type, s::String) = parse_int(T,s,16) - -parse_bin(s::String) = parse_int(Int,s,2) -parse_oct(s::String) = parse_int(Int,s,8) -parse_hex(s::String) = parse_int(Int,s,16) +parseint(s::String, base::Integer) = parseint(Int,s,base) +parseint(T::Type, s::String) = parseint(T,s,10) +parseint(s::String) = parseint(Int,s,10) integer (s::String) = int(s) unsigned(s::String) = uint(s) -int (s::String) = parse_int(Int,s) -uint (s::String) = parse_int(Uint,s) -int8 (s::String) = parse_int(Int8,s) -uint8 (s::String) = parse_int(Uint8,s) -int16 (s::String) = parse_int(Int16,s) -uint16 (s::String) = parse_int(Uint16,s) -int32 (s::String) = parse_int(Int32,s) -uint32 (s::String) = parse_int(Uint32,s) -int64 (s::String) = parse_int(Int64,s) -uint64 (s::String) = parse_int(Uint64,s) -int128 (s::String) = parse_int(Int128,s) -uint128 (s::String) = parse_int(Uint128,s) +int (s::String) = parseint(Int,s) +uint (s::String) = parseint(Uint,s) +int8 (s::String) = parseint(Int8,s) +uint8 (s::String) = parseint(Uint8,s) +int16 (s::String) = parseint(Int16,s) +uint16 (s::String) = parseint(Uint16,s) +int32 (s::String) = parseint(Int32,s) +uint32 (s::String) = parseint(Uint32,s) +int64 (s::String) = parseint(Int64,s) +uint64 (s::String) = parseint(Uint64,s) +int128 (s::String) = parseint(Int128,s) +uint128 (s::String) = parseint(Uint128,s) ## stringifying integers more efficiently ## @@ -1209,9 +1168,9 @@ begin end float(x::String) = float64(x) -parse_float(x::String) = float64(x) -parse_float(::Type{Float64}, x::String) = float64(x) -parse_float(::Type{Float32}, x::String) = float32(x) +parsefloat(x::String) = float64(x) +parsefloat(::Type{Float64}, x::String) = float64(x) +parsefloat(::Type{Float32}, x::String) = float32(x) for conv in (:float, :float32, :float64, :int, :int8, :int16, :int32, :int64, @@ -1221,7 +1180,7 @@ end # find the index of the first occurrence of a value in a byte array -function memchr(a::Array{Uint8,1}, b::Integer, i::Integer) +function search(a::Array{Uint8,1}, b, i::Integer) if i < 1 error(BoundsError) end n = length(a) if i > n return i == n+1 ? 0 : error(BoundsError) end @@ -1229,12 +1188,12 @@ function memchr(a::Array{Uint8,1}, b::Integer, i::Integer) q = ccall(:memchr, Ptr{Uint8}, (Ptr{Uint8}, Int32, Uint), p+i-1, b, n-i+1) q == C_NULL ? 0 : int(q-p+1) end -memchr(a::Array{Uint8,1}, b::Integer) = memchr(a,b,1) +search(a::Array{Uint8,1}, b) = search(a,b,1) # return a random string (often useful for temporary filenames/dirnames) let -global randstring -const randstring_chars = ASCIIString(uint8([0x30:0x39,0x41:0x5a,0x61:0x7a])) -randstring(len::Int) = - randstring_chars[iceil(strlen(randstring_chars)*rand(len))] + global randstring + const b = uint8(['0':'9','A':'Z','a':'z']) + randstring(n::Int) = ASCIIString(b[rand(1:length(b),n)]) + randstring() = randstring(8) end diff --git a/base/subarray.jl b/base/subarray.jl index 3e70c07df2b8b..f1e3447aeb8f0 100644 --- a/base/subarray.jl +++ b/base/subarray.jl @@ -1,5 +1,7 @@ ## subarrays ## +typealias RangeIndex Union(Int, Range{Int}, Range1{Int}) + type SubArray{T,N,A<:AbstractArray,I<:(RangeIndex...,)} <: AbstractArray{T,N} parent::A indexes::I @@ -30,9 +32,9 @@ type SubArray{T,N,A<:AbstractArray,I<:(RangeIndex...,)} <: AbstractArray{T,N} if isa(i[j], Int) newfirst += (i[j]-1)*pstride else - push(newdims, length(i[j])) + push!(newdims, length(i[j])) #may want to return error if step(i[j]) <= 0 - push(newstrides, isa(i[j],Range1) ? pstride : + push!(newstrides, isa(i[j],Range1) ? pstride : pstride * step(i[j])) newfirst += (first(i[j])-1)*pstride end @@ -56,6 +58,8 @@ function sub{T,N}(A::AbstractArray{T,N}, i::NTuple{N,RangeIndex}) SubArray{T,L,typeof(A),typeof(i)}(A, i) end +sub{N}(A::SubArray, i::NTuple{N,RangeIndex}) = sub(A, i...) + sub(A::AbstractArray, i::RangeIndex...) = sub(A, i) function sub(A::SubArray, i::RangeIndex...) @@ -71,7 +75,8 @@ function sub(A::SubArray, i::RangeIndex...) j += 1 end end - sub(A.parent, tuple(newindexes...)) + ni = tuple(newindexes...) + SubArray{eltype(A),L,typeof(A.parent),typeof(ni)}(A.parent, ni) end function slice{T,N}(A::AbstractArray{T,N}, i::NTuple{N,RangeIndex}) @@ -143,26 +148,26 @@ end size(s::SubArray) = s.dims ndims{T,N}(s::SubArray{T,N}) = N -copy(s::SubArray) = copy_to(similar(s.parent, size(s)), s) +copy(s::SubArray) = copy!(similar(s.parent, size(s)), s) similar(s::SubArray, T, dims::Dims) = similar(s.parent, T, dims) -ref{T}(s::SubArray{T,0,AbstractArray{T,0}}) = s.parent[] -ref{T}(s::SubArray{T,0}) = s.parent[s.first_index] +getindex{T}(s::SubArray{T,0,AbstractArray{T,0}}) = s.parent[] +getindex{T}(s::SubArray{T,0}) = s.parent[s.first_index] -ref{T}(s::SubArray{T,1}, i::Integer) = s.parent[s.first_index + (i-1)*s.strides[1]] -ref{T}(s::SubArray{T,2}, i::Integer, j::Integer) = +getindex{T}(s::SubArray{T,1}, i::Integer) = s.parent[s.first_index + (i-1)*s.strides[1]] +getindex{T}(s::SubArray{T,2}, i::Integer, j::Integer) = s.parent[s.first_index + (i-1)*s.strides[1] + (j-1)*s.strides[2]] -ref(s::SubArray, i::Integer) = s[ind2sub(size(s), i)...] +getindex(s::SubArray, i::Integer) = s[ind2sub(size(s), i)...] -function ref{T}(s::SubArray{T,2}, ind::Integer) +function getindex{T}(s::SubArray{T,2}, ind::Integer) ld = size(s,1) i = rem(ind-1,ld)+1 j = div(ind-1,ld)+1 s.parent[s.first_index + (i-1)*s.strides[1] + (j-1)*s.strides[2]] end -function ref(s::SubArray, is::Integer...) +function getindex(s::SubArray, is::Integer...) index = s.first_index for i = 1:length(is) index += (is[i]-1)*s.strides[i] @@ -170,32 +175,80 @@ function ref(s::SubArray, is::Integer...) s.parent[index] end -ref{T}(s::SubArray{T,1}, I::Range1{Int}) = - ref(s.parent, (s.first_index+(first(I)-1)*s.strides[1]):s.strides[1]:(s.first_index+(last(I)-1)*s.strides[1])) +getindex{T}(s::SubArray{T,1}, I::Range1{Int}) = + getindex(s.parent, (s.first_index+(first(I)-1)*s.strides[1]):s.strides[1]:(s.first_index+(last(I)-1)*s.strides[1])) -ref{T}(s::SubArray{T,1}, I::Range{Int}) = - ref(s.parent, (s.first_index+(first(I)-1)*s.strides[1]):(s.strides[1]*step(I)):(s.first_index+(last(I)-1)*s.strides[1])) +getindex{T}(s::SubArray{T,1}, I::Range{Int}) = + getindex(s.parent, (s.first_index+(first(I)-1)*s.strides[1]):(s.strides[1]*step(I)):(s.first_index+(last(I)-1)*s.strides[1])) -function ref{T,S<:Integer}(s::SubArray{T,1}, I::AbstractVector{S}) +function getindex{T,S<:Integer}(s::SubArray{T,1}, I::AbstractVector{S}) t = Array(Int, length(I)) for i = 1:length(I) t[i] = s.first_index + (I[i]-1)*s.strides[1] end - ref(s.parent, t) + getindex(s.parent, t) end -function ref(s::SubArray, I::Indices...) +function translate_indexes(s::SubArray, I::Union(Real,AbstractArray)...) I = indices(I) - n = ndims(s.parent) - newindexes = Array(Indices, n) - for i = 1:n + nds = ndims(s) + n = length(I) + if n > nds + throw(BoundsError()) + end + ndp = ndims(s.parent) - (nds-n) + newindexes = Array(Any, ndp) + sp = strides(s.parent) + j = 1 + for i = 1:ndp t = s.indexes[i] - #TODO: don't generate the dense vector indexes if they can be ranges - newindexes[i] = isa(t, Int) ? t : t[I[i]] + if s.strides[j] == sp[i] + #TODO: don't generate the dense vector indexes if they can be ranges + if j==n && n < nds + newindexes[i] = translate_linear_indexes(s, j, I[j]) + else + newindexes[i] = isa(t, Int) ? t : t[I[j]] + end + j += 1 + else + newindexes[i] = t + end + end + newindexes +end + +# translate a linear index vector I for dim n to a linear index vector for +# the parent array +function translate_linear_indexes(s, n, I) + idx = Array(Int, length(I)) + ssztail = size(s)[n:] + pdims = parentdims(s) + psztail = size(s.parent)[pdims[n:]] + for j=1:length(I) + su = ind2sub(ssztail,I[j]) + idx[j] = sub2ind(psztail, [ s.indexes[pdims[n+k-1]][su[k]] for k=1:length(su) ]...) end + idx +end - rs = ref_shape(I...) - result = ref(s.parent, newindexes...) +function parentdims(s::SubArray) + dimindex = Array(Int, ndims(s)) + sp = strides(s.parent) + j = 1 + for i = 1:ndims(s.parent) + if sp[i] == s.strides[j] + dimindex[j] = i + j += 1 + end + end + dimindex +end + +function getindex(s::SubArray, I::Union(Real,AbstractVector)...) + newindexes = translate_indexes(s, I...) + + rs = index_shape(I...) + result = getindex(s.parent, newindexes...) if isequal(rs, size(result)) return result else @@ -203,9 +256,9 @@ function ref(s::SubArray, I::Indices...) end end -assign(s::SubArray, v, i::Integer) = assign(s, v, ind2sub(size(s), i)...) +setindex!(s::SubArray, v, i::Integer) = setindex!(s, v, ind2sub(size(s), i)...) -function assign{T}(s::SubArray{T,2}, v, ind::Integer) +function setindex!{T}(s::SubArray{T,2}, v, ind::Integer) ld = size(s,1) i = rem(ind-1,ld)+1 j = div(ind-1,ld)+1 @@ -213,7 +266,7 @@ function assign{T}(s::SubArray{T,2}, v, ind::Integer) return s end -function assign(s::SubArray, v, is::Integer...) +function setindex!(s::SubArray, v, is::Integer...) index = s.first_index for i = 1:length(is) index += (is[i]-1)*s.strides[i] @@ -222,44 +275,34 @@ function assign(s::SubArray, v, is::Integer...) return s end -assign{T}(s::SubArray{T,0,AbstractArray{T,0}},v) = assign(s.parent, v) +setindex!{T}(s::SubArray{T,0,AbstractArray{T,0}},v) = setindex!(s.parent, v) -assign{T}(s::SubArray{T,0}, v) = assign(s.parent, v, s.first_index) +setindex!{T}(s::SubArray{T,0}, v) = setindex!(s.parent, v, s.first_index) -assign{T}(s::SubArray{T,1}, v, i::Integer) = - assign(s.parent, v, s.first_index + (i-1)*s.strides[1]) +setindex!{T}(s::SubArray{T,1}, v, i::Integer) = + setindex!(s.parent, v, s.first_index + (i-1)*s.strides[1]) -assign{T}(s::SubArray{T,2}, v, i::Integer, j::Integer) = - assign(s.parent, v, s.first_index +(i-1)*s.strides[1]+(j-1)*s.strides[2]) +setindex!{T}(s::SubArray{T,2}, v, i::Integer, j::Integer) = + setindex!(s.parent, v, s.first_index +(i-1)*s.strides[1]+(j-1)*s.strides[2]) -assign{T}(s::SubArray{T,1}, v, I::Range1{Int}) = - assign(s.parent, v, (s.first_index+(first(I)-1)*s.strides[1]):s.strides[1]:(s.first_index+(last(I)-1)*s.strides[1])) +setindex!{T}(s::SubArray{T,1}, v, I::Range1{Int}) = + setindex!(s.parent, v, (s.first_index+(first(I)-1)*s.strides[1]):s.strides[1]:(s.first_index+(last(I)-1)*s.strides[1])) -assign{T}(s::SubArray{T,1}, v, I::Range{Int}) = - assign(s.parent, v, (s.first_index+(first(I)-1)*s.strides[1]):(s.strides[1]*step(I)):(s.first_index+(last(I)-1)*s.strides[1])) +setindex!{T}(s::SubArray{T,1}, v, I::Range{Int}) = + setindex!(s.parent, v, (s.first_index+(first(I)-1)*s.strides[1]):(s.strides[1]*step(I)):(s.first_index+(last(I)-1)*s.strides[1])) -function assign{T,S<:Integer}(s::SubArray{T,1}, v, I::AbstractVector{S}) +function setindex!{T,S<:Integer}(s::SubArray{T,1}, v, I::AbstractVector{S}) t = Array(Int, length(I)) for i = 1:length(I) t[i] = s.first_index + (I[i]-1)*s.strides[1] end - assign(s.parent, v, t) + setindex!(s.parent, v, t) end -function assign(s::SubArray, v, I::Indices...) - I = indices(I) - j = 1 #the jth dimension in subarray - n = ndims(s.parent) - newindexes = cell(n) - for i = 1:n - t = s.indexes[i] - #TODO: don't generate the dense vector indexes if they can be ranges - newindexes[i] = isa(t, Int) ? t : t[I[j]] - j += 1 - end - - assign(s.parent, v, newindexes...) +function setindex!(s::SubArray, v, I::Union(Real,AbstractArray)...) + newindexes = translate_indexes(s, I...) + setindex!(s.parent, v, newindexes...) end function stride(s::SubArray, i::Integer) @@ -285,4 +328,4 @@ function pointer(s::SubArray, is::(Int...)) end summary(s::SubArray) = - strcat(dims2string(size(s)), " SubArray of ", summary(s.parent)) + string(dims2string(size(s)), " SubArray of ", summary(s.parent)) diff --git a/base/sysimg.jl b/base/sysimg.jl index 8fba3c524bdfc..f5a46d19d7909 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -3,30 +3,32 @@ baremodule Base eval(x) = Core.eval(Base,x) eval(m,x) = Core.eval(m,x) -include("export.jl") +include = Core.include + +include("exports.jl") if false # simple print definitions for debugging. enable these if something # goes wrong during bootstrap before printing code is available. length(a::Array) = arraylen(a) - print(x) = print(stdout_stream, x) - show(x) = show(stdout_stream, x) - write(io, a::Array{Uint8,1}) = + print(x) = print(STDOUT, x) + show(x) = show(STDOUT, x) + write(io::IO, a::Array{Uint8,1}) = ccall(:ios_write, Uint, (Ptr{Void}, Ptr{Void}, Uint), io.ios, a, length(a)) - print(io, s::Symbol) = ccall(:jl_print_symbol, Void, (Ptr{Void},Any,), + print(io::IO, s::Symbol) = ccall(:jl_print_symbol, Void, (Ptr{Void},Any,), io.ios, s) - print(io, s::ASCIIString) = (write(io, s.data);nothing) - print(io, x) = show(io, x) - println(io, x) = (print(io, x); print(io, "\n")) - show(io, x) = ccall(:jl_show_any, Void, (Any, Any,), io, x) - show(io, s::ASCIIString) = (write(io, s.data);nothing) - show(io, s::Symbol) = print(io, s) - show(io, b::Bool) = print(io, b ? "true" : "false") - show(io, n::Int64) = ccall(:jl_print_int64, Void, (Ptr{Void}, Int64,), io, n) - show(io, n::Integer) = show(io, int64(n)) - print(io, a...) = for x=a; print(io, x); end - function show(io, e::Expr) + print(io::IO, s::ASCIIString) = (write(io, s.data);nothing) + print(io::IO, x) = show(io, x) + println(io::IO, x) = (print(io, x); print(io, "\n")) + show(io::IO, x) = ccall(:jl_show_any, Void, (Any, Any,), io, x) + show(io::IO, s::ASCIIString) = (write(io, s.data);nothing) + show(io::IO, s::Symbol) = print(io, s) + show(io::IO, b::Bool) = print(io, b ? "true" : "false") + show(io::IO, n::Int64) = ccall(:jl_print_int64, Void, (Ptr{Void}, Int64,), io, n) + show(io::IO, n::Integer) = show(io, int64(n)) + print(io::IO, a...) = for x=a; print(io, x); end + function show(io::IO, e::Expr) print(io, e.head) print(io, "(") for i=1:arraylen(e.args) @@ -40,6 +42,8 @@ end ## Load essential files and libraries include("base.jl") +include("build_h.jl") +include("c.jl") # core operations & types include("range.jl") @@ -49,10 +53,10 @@ include("expr.jl") include("error.jl") # core numeric operations & types +include("promotion.jl") include("bool.jl") include("number.jl") include("int.jl") -include("promotion.jl") include("operators.jl") include("pointer.jl") @@ -76,6 +80,13 @@ include("inference.jl") # I/O, strings & printing include("io.jl") +include("iobuffer.jl") +include("stream.jl") +include("socket.jl") +include("fs.jl") +importall FS +include("process.jl") +ccall(:jl_get_uv_hooks, Void, ()) include("char.jl") include("ascii.jl") include("utf8.jl") @@ -85,12 +96,11 @@ include("show.jl") include("grisu.jl") import Grisu.print_shortest include("printf.jl") -using Printf +importall Printf # concurrency and parallelism include("iterator.jl") include("task.jl") -include("process.jl") include("serialize.jl") include("multi.jl") @@ -98,27 +108,32 @@ include("multi.jl") include("osutils.jl") include("libc.jl") include("env.jl") -include("errno_h.jl") +include("errno.jl") +using Errno include("file.jl") +include("path.jl") include("stat.jl") -# front end +# front end & code loading +include("repl.jl") include("client.jl") +include("loading.jl") # core math functions include("intfuncs.jl") include("floatfuncs.jl") include("math.jl") -using Math +importall Math # random number generation and statistics include("statistics.jl") include("librandom.jl") -include("rng.jl") -using RNG +include("random.jl") +importall Random # Combinatorics include("sort.jl") +importall Sort include("combinatorics.jl") # distributed arrays and memory-mapped arrays @@ -126,146 +141,190 @@ include("combinatorics.jl") include("darray2.jl") include("mmap.jl") -# utilities - version, timing, help, edit +# utilities - version, timing, help, edit, metaprogramming include("version.jl") -include("util.jl") include("datafmt.jl") include("deepcopy.jl") +include("util.jl") +include("test.jl") +include("meta.jl") +include("i18n.jl") +include("help.jl") +using I18n +using Help +push!(I18n.CALLBACKS, Help.clear_cache) -# linear algebra -include("build_h.jl") -include("blas.jl") -include("lapack.jl") -include("matmul.jl") +# sparse matrices and linear algebra include("sparse.jl") include("linalg.jl") -include("linalg_dense.jl") -include("linalg_bitarray.jl") -include("linalg_sparse.jl") +importall LinAlg # signal processing include("fftw.jl") include("dsp.jl") -using DSP +importall DSP + +# BigInts and BigFloats +include("gmp.jl") +importall GMP + +# deprecated functions +include("deprecated.jl") + +# git utils & package manager +include("git.jl") +include("pkg.jl") + +include = include_from_node1 # prime method cache with some things we know we'll need right after startup -compile_hint(cwd, ()) -compile_hint(fdio, (Int32,)) -compile_hint(ProcessGroup, (Int, Array{Any,1}, Array{Any,1})) -compile_hint(select_read, (FDSet, Float64)) -compile_hint(next, (Dict{Any,Any}, Int)) -compile_hint(start, (Dict{Any,Any},)) -compile_hint(perform_work, ()) -compile_hint(isempty, (Array{Any,1},)) -compile_hint(isempty, (Array{WorkItem,1},)) -compile_hint(ref, (Dict{Any,Any}, Int32)) -compile_hint(event_loop, (Bool,)) -compile_hint(_start, ()) -compile_hint(process_options, (Array{Any,1},)) -compile_hint(run_repl, ()) -compile_hint(anyp, (Function, Array{Any,1})) -compile_hint(Dict{Any,Any}, (Int,)) -compile_hint(Set, ()) -compile_hint(assign, (Dict{Any,Any}, Bool, Cmd)) -compile_hint(rehash, (Dict{Any,Any}, Int)) -compile_hint(run, (Cmd,)) -compile_hint(spawn, (Cmd,)) -compile_hint(assign, (Dict{Any,Any}, Bool, FileDes)) -compile_hint(wait, (Int32,)) -compile_hint(system_error, (ASCIIString, Bool)) -compile_hint(SystemError, (ASCIIString,)) -compile_hint(has, (EnvHash, ASCIIString)) -compile_hint(parse_input_line, (ASCIIString,)) -compile_hint(cmp, (Int32, Int32)) -compile_hint(min, (Int32, Int32)) -compile_hint(==, (ASCIIString, ASCIIString)) -compile_hint(arg_gen, (ASCIIString,)) -compile_hint(RNG.librandom_init, ()) -compile_hint(RNG.srand, (ASCIIString, Int)) -compile_hint(open, (ASCIIString, Bool, Bool, Bool, Bool)) -compile_hint(RNG.srand, (Uint64,)) -compile_hint(done, (IntSet, Int64)) -compile_hint(next, (IntSet, Int64)) -compile_hint(ht_keyindex, (Dict{Any,Any}, Int32)) -compile_hint(perform_work, (WorkItem,)) -compile_hint(notify_done, (WorkItem,)) -compile_hint(work_result, (WorkItem,)) -compile_hint(del_fd_handler, (Int32,)) -compile_hint(enqueue, (Array{WorkItem,1}, WorkItem)) -compile_hint(enq_work, (WorkItem,)) -compile_hint(pop, (Array{WorkItem,1},)) -compile_hint(string, (Int,)) -compile_hint(parse_int, (Type{Int}, ASCIIString, Int)) -compile_hint(repeat, (ASCIIString, Int)) -compile_hint(KeyError, (Int,)) -compile_hint(show, (Float64,)) -compile_hint(match, (Regex, ASCIIString)) -compile_hint(strlen, (ASCIIString,)) -compile_hint(alignment, (Float64,)) -compile_hint(repl_callback, (Expr, Int)) -compile_hint(istaskdone, (Task,)) -compile_hint(make_stdout_stream, ()) -compile_hint(make_stdin_stream, ()) -compile_hint(make_stderr_stream, ()) -compile_hint(int, (Uint64,)) -compile_hint(copy, (Bool,)) -compile_hint(bool, (Bool,)) -compile_hint(bool, (RemoteRef,)) -compile_hint(wait, (RemoteRef,)) -compile_hint(hash, (RemoteRef,)) -compile_hint(take, (RemoteRef,)) -compile_hint(bitmix, (Int, Int)) -compile_hint(bitmix, (Uint, Int)) -compile_hint(bitmix, (Uint64, Int64)) -compile_hint(hash, (Int,)) -compile_hint(isequal, (Symbol, Symbol)) -compile_hint(isequal, (Bool, Bool)) -compile_hint(WaitFor, (Symbol, RemoteRef)) -compile_hint(_jl_answer_color, ()) -compile_hint(get, (EnvHash, ASCIIString, ASCIIString)) -compile_hint(notify_empty, (WorkItem,)) -compile_hint(rr2id, (RemoteRef,)) -compile_hint(isequal, (RemoteRef, WeakRef)) -compile_hint(isequal, (RemoteRef, RemoteRef)) -compile_hint(_ieval, (Symbol,)) -compile_hint(static_convert, (Nothing, Nothing)) -compile_hint(assign, (Array{Any,1}, WeakRef, Int)) -compile_hint(assign, (Dict{Any,Any}, WorkItem, (Int,Int))) -compile_hint(isequal, ((Int,Int),(Int,Int))) -compile_hint(isequal, (Int,Int)) -compile_hint(RemoteRef, (Int, Int, Int)) -compile_hint(_jl_eval_user_input, (Expr, Bool)) -compile_hint(print, (Float64,)) -compile_hint(a2t, (Array{Any,1},)) -compile_hint(flush, (IOStream,)) -compile_hint(ref, (Type{String}, ASCIIString, ASCIIString, ASCIIString, ASCIIString, ASCIIString)) -compile_hint(int, (Int,)) -compile_hint(uint, (Uint,)) -compile_hint(_atexit, ()) -compile_hint(read, (IOStream, Array{Uint32,1})) -compile_hint(hex, (Char, Int)) -compile_hint(abs, (Char,)) -compile_hint(abstract_eval, (LambdaStaticData, ObjectIdDict, StaticVarInfo)) -compile_hint(length, (Range1{Int},)) -compile_hint(start, (Range1{Int},)) -compile_hint(done, (Range1{Int},Int)) -compile_hint(next, (Range1{Int},Int)) -compile_hint(IOStream, (ASCIIString, Array{Uint8,1})) -compile_hint(mk_tupleref, (SymbolNode, Int)) -compile_hint(abstract_interpret, (Bool, ObjectIdDict, StaticVarInfo)) -compile_hint(eval_annotate, (LambdaStaticData, ObjectIdDict, StaticVarInfo, ObjectIdDict, Array{Any,1})) -compile_hint(occurs_more, (Bool, Function, Int)) -compile_hint(isconstantfunc, (SymbolNode, StaticVarInfo)) -compile_hint(CallStack, (Expr, Module, (Nothing,), EmptyCallStack)) -compile_hint(convert, (Type{Module}, Module)) -compile_hint(effect_free, (Expr,)) -compile_hint(effect_free, (TopNode,)) -compile_hint(abs_path, (ASCIIString,)) -compile_hint(isrooted, (ASCIIString,)) -compile_hint(split, (ASCIIString,)) -compile_hint(split, (ASCIIString, ASCIIString, Int, Bool)) -compile_hint(print_joined, (IOStream, Array{String,1}, ASCIIString)) -compile_hint(begins_with, (ASCIIString, ASCIIString)) +precompile(pwd, ()) +precompile(fdio, (Int32,)) +precompile(ProcessGroup, (Int, Array{Any,1}, Array{Any,1})) +precompile(next, (Dict{Any,Any}, Int)) +precompile(start, (Dict{Any,Any},)) +precompile(perform_work, ()) +precompile(isempty, (Array{Any,1},)) +precompile(isempty, (Array{WorkItem,1},)) +precompile(getindex, (Dict{Any,Any}, Int32)) +precompile(event_loop, (Bool,)) +precompile(_start, ()) +precompile(process_options, (Array{Any,1},)) +precompile(run_repl, ()) +precompile(any, (Function, Array{Any,1})) +precompile(Dict{Any,Any}, (Int,)) +precompile(Set, ()) +precompile(setindex!, (Dict{Any,Any}, Bool, Cmd)) +precompile(rehash, (Dict{Any,Any}, Int)) +precompile(wait, (Int32,)) +precompile(system_error, (Symbol, Bool)) +precompile(SystemError, (ASCIIString,)) +precompile(has, (EnvHash, ASCIIString)) +precompile(parse_input_line, (ASCIIString,)) +precompile(cmp, (Int32, Int32)) +precompile(min, (Int32, Int32)) +precompile(==, (ASCIIString, ASCIIString)) +precompile(arg_gen, (ASCIIString,)) +precompile(Random.librandom_init, ()) +precompile(Random.srand, (ASCIIString, Int)) +precompile(Random.srand, (Uint64,)) +precompile(open, (ASCIIString, Bool, Bool, Bool, Bool)) +precompile(done, (IntSet, Int64)) +precompile(next, (IntSet, Int64)) +precompile(ht_keyindex, (Dict{Any,Any}, Int32)) +precompile(perform_work, (WorkItem,)) +precompile(notify_done, (WorkItem,)) +precompile(work_result, (WorkItem,)) +precompile(unshift!, (Array{WorkItem,1}, WorkItem)) +precompile(enq_work, (WorkItem,)) +precompile(pop!, (Array{WorkItem,1},)) +precompile(string, (Int,)) +precompile(parseint, (Type{Int}, ASCIIString, Int)) +precompile(repeat, (ASCIIString, Int)) +precompile(KeyError, (Int,)) +precompile(show, (Float64,)) +precompile(match, (Regex, ASCIIString)) +precompile(length, (ASCIIString,)) +precompile(alignment, (Float64,)) +precompile(repl_callback, (Expr, Int)) +precompile(istaskdone, (Task,)) +precompile(int, (Uint64,)) +precompile(copy, (Bool,)) +precompile(bool, (Bool,)) +precompile(bool, (RemoteRef,)) +precompile(wait, (RemoteRef,)) +precompile(hash, (RemoteRef,)) +precompile(take, (RemoteRef,)) +precompile(bitmix, (Int, Int)) +precompile(bitmix, (Uint, Int)) +precompile(bitmix, (Uint64, Int64)) +precompile(hash, (Int,)) +precompile(isequal, (Symbol, Symbol)) +precompile(isequal, (Bool, Bool)) +precompile(WaitFor, (Symbol, RemoteRef)) +precompile(get, (EnvHash, ASCIIString, ASCIIString)) +precompile(notify_empty, (WorkItem,)) +precompile(rr2id, (RemoteRef,)) +precompile(isequal, (RemoteRef, WeakRef)) +precompile(isequal, (RemoteRef, RemoteRef)) +precompile(_ieval, (Symbol,)) +precompile(static_convert, (Nothing, Nothing)) +precompile(setindex!, (Array{Any,1}, WeakRef, Int)) +precompile(setindex!, (Dict{Any,Any}, WorkItem, (Int,Int))) +precompile(isequal, ((Int,Int),(Int,Int))) +precompile(isequal, (Int,Int)) +precompile(RemoteRef, (Int, Int, Int)) +precompile(eval_user_input, (Expr, Bool)) +precompile(print, (Float64,)) +precompile(a2t, (Array{Any,1},)) +precompile(flush, (IOStream,)) +precompile(getindex, (Type{ByteString}, ASCIIString, ASCIIString, ASCIIString, ASCIIString, ASCIIString)) +precompile(int, (Int,)) +precompile(uint, (Uint,)) +precompile(_atexit, ()) +precompile(read, (IOStream, Array{Uint32,1})) +precompile(hex, (Char, Int)) +precompile(abs, (Char,)) +precompile(abstract_eval, (LambdaStaticData, ObjectIdDict, StaticVarInfo)) +precompile(length, (Range1{Int},)) +precompile(start, (Range1{Int},)) +precompile(done, (Range1{Int},Int)) +precompile(next, (Range1{Int},Int)) +precompile(IOStream, (ASCIIString, Array{Uint8,1})) +precompile(mk_tupleref, (SymbolNode, Int)) +precompile(abstract_interpret, (Bool, ObjectIdDict, StaticVarInfo)) +precompile(eval_annotate, (LambdaStaticData, ObjectIdDict, StaticVarInfo, ObjectIdDict, Array{Any,1})) +precompile(occurs_more, (Bool, Function, Int)) +precompile(isconstantfunc, (SymbolNode, StaticVarInfo)) +precompile(CallStack, (Expr, Module, (Nothing,), EmptyCallStack)) +precompile(convert, (Type{Module}, Module)) +precompile(effect_free, (Expr,)) +precompile(effect_free, (TopNode,)) +precompile(abspath, (ASCIIString,)) +precompile(isabspath, (ASCIIString,)) +precompile(split, (ASCIIString,)) +precompile(split, (ASCIIString, ASCIIString, Int, Bool)) +precompile(split, (ASCIIString, Regex, Int, Bool)) +precompile(print_joined, (IOStream, Array{String,1}, ASCIIString)) +precompile(beginswith, (ASCIIString, ASCIIString)) +precompile(resolve_globals, (Symbol, Module, Module, Vector{Any}, Vector{Any})) +precompile(resolve_globals, (SymbolNode, Module, Module, Vector{Any}, Vector{Any})) +precompile(BitArray, (Int,)) +precompile(getindex, (BitArray{1}, Int,)) +precompile(setindex!, (BitArray{1}, Bool, Int,)) +precompile(fill!, (BitArray{1}, Bool)) +precompile(nnz, (BitArray{1},)) +precompile(get_chunks_id, (Int,)) +precompile(occurs_more, (Uint8, Function, Int)) +precompile(abstract_eval_arg, (Uint8, ObjectIdDict, StaticVarInfo)) +precompile(occurs_outside_tupleref, (Function, Symbol, StaticVarInfo, Int)) +precompile(search, (ASCIIString, Regex, Int)) +precompile(setindex!, (Vector{Any}, Uint8, Int)) +precompile(first, (Range1{Int},)) +precompile(last, (Range1{Int},)) +precompile(isempty, (ASCIIString,)) +precompile(normpath, (ASCIIString,)) +precompile(print, (ASCIIString,)) +precompile(println, (TTY,)) +precompile(print, (TTY,Char)) +precompile(==, (Bool,Bool)) +precompile(try_include, (ASCIIString,)) +precompile(is_file_readable, (ASCIIString,)) +precompile(include_from_node1, (ASCIIString,)) +precompile(source_path, (Nothing,)) +precompile(task_local_storage, ()) +precompile(atexit, (Function,)) +precompile(print, (TTY, ASCIIString)) +precompile(close, (TTY,)) +precompile(readBuffer, (TTY,Int)) +precompile(put, (RemoteRef, Any)) +precompile(getpid, ()) +precompile(print, (IOStream, Int32)) +precompile(show, (IOStream, Int32)) +precompile(open, (ASCIIString, ASCIIString)) +precompile(readline, (ASCIIString,)) +precompile(endof, (Array{Any,1},)) +precompile(sym_replace, (Uint8, Array{Any,1}, Array{Any,1}, Array{Any,1}, Array{Any,1})) # invoke type inference, running the existing inference code on the new # inference code to cache an optimized version of it. @@ -277,9 +336,9 @@ end end # baremodule Base -using Base +using Base.get, Base.ENV -let JL_PRIVATE_LIBDIR = getenv("JL_PRIVATE_LIBDIR") +let JL_PRIVATE_LIBDIR = get(ENV, "JL_PRIVATE_LIBDIR", "lib/julia") # create system image file ccall(:jl_save_system_image, Void, (Ptr{Uint8},), "$JULIA_HOME/../$JL_PRIVATE_LIBDIR/sys.ji") diff --git a/base/task.jl b/base/task.jl index 907441a800b0b..2dbbd065da94b 100644 --- a/base/task.jl +++ b/base/task.jl @@ -1,24 +1,17 @@ -show(io, t::Task) = print(io, "Task") +show(io::IO, t::Task) = print(io, "Task") -current_task() = ccall(:jl_get_current_task, Task, ()) +current_task() = ccall(:jl_get_current_task, Any, ())::Task istaskdone(t::Task) = t.done -# task-local storage -function tls() +function task_local_storage() t = current_task() - if is(t.tls, nothing) - t.tls = ObjectIdDict() + if is(t.storage, nothing) + t.storage = ObjectIdDict() end - (t.tls)::ObjectIdDict -end - -function tls(key) - tls()[key] -end - -function tls(key, val) - tls()[key] = val + (t.storage)::ObjectIdDict end +task_local_storage(key) = task_local_storage()[key] +task_local_storage(key, val) = (task_local_storage()[key] = val) function produce(v) ct = current_task() @@ -27,13 +20,14 @@ function produce(v) Q = q::Array{Any,1} if !isempty(Q) # make a task waiting for us runnable again - enq_work(pop(Q)) + enq_work(pop!(Q)) end end yieldto(ct.last, v) ct.parent = ct.last # always exit to last consumer nothing end +produce(v...) = produce(v) function consume(P::Task) while !(P.runnable || P.done) @@ -50,16 +44,19 @@ function consume(P::Task) if !is(q, nothing) Q = q::Array{Any,1} while !isempty(Q) - enq_work(pop(Q)) + enq_work(pop!(Q)) end end end v end -start(t::Task) = consume(t) -done(t::Task, val) = istaskdone(t) -next(t::Task, val) = (val, consume(t)) +start(t::Task) = nothing +function done(t::Task, val) + t.result = consume(t) + istaskdone(t) +end +next(t::Task, val) = (t.result, nothing) macro task(ex) :(Task(()->$(esc(ex)))) diff --git a/base/test.jl b/base/test.jl index 703fc2ee39fe5..10c992ee0b52d 100644 --- a/base/test.jl +++ b/base/test.jl @@ -1,5 +1,6 @@ module Test -export @test, @test_fails + +export @test, @test_fails, @test_approx_eq, @test_approx_eq_eps abstract Result type Success <: Result @@ -11,11 +12,20 @@ end type Error <: Result expr err + backtrace end default_handler(r::Success) = nothing default_handler(r::Failure) = error("test failed: $(r.expr)") -default_handler(r::Error) = error("test error during $(r.expr)\n$(r.err)") +default_handler(r::Error) = rethrow(r) + +import Base.error_show + +error_show(io::IO, r::Error) = error_show(io, r, {}) +function error_show(io::IO, r::Error, bt) + println(io, "test error during $(r.expr)") + error_show(io, r.err, r.backtrace) +end const handlers = [default_handler] @@ -23,7 +33,7 @@ function do_test(thk, qex) handlers[end](try thk() ? Success(qex) : Failure(qex) catch err - Error(qex,err) + Error(qex,err,catch_backtrace()) end) end @@ -37,11 +47,32 @@ function do_test_fails(thk, qex) end macro test(ex) - :(do_test(()->($(esc(ex))),$(expr(:quote,ex)))) + :(do_test(()->($(esc(ex))),$(Expr(:quote,ex)))) end macro test_fails(ex) - :(do_test_fails(()->($(esc(ex))),$(expr(:quote,ex)))) + :(do_test_fails(()->($(esc(ex))),$(Expr(:quote,ex)))) +end + +function test_approx_eq(va, vb, Eps, astr, bstr) + diff = max(abs(va - vb)) + sdiff = string("|", astr, " - ", bstr, "| < ", Eps) + if diff < Eps + nothing + else + error("assertion failed: ", sdiff, "\n ", astr, " = ", va, "\n ", + bstr, " = ", vb) + end +end + +test_approx_eq(va, vb, astr, bstr) = test_approx_eq(va, vb, 10^4*length(va)*eps(max(max(abs(va)), max(abs(vb)))) * max(1, max(abs(va)), max(abs(vb))), astr, bstr) + +macro test_approx_eq_eps(a, b, c) + :(test_approx_eq($(esc(a)), $(esc(b)), $(esc(c)), $(string(a)), $(string(b)))) +end + +macro test_approx_eq(a, b) + :(test_approx_eq($(esc(a)), $(esc(b)), $(string(a)), $(string(b)))) end end # module diff --git a/base/timsort.jl b/base/timsort.jl new file mode 100644 index 0000000000000..670ca788a4a0e --- /dev/null +++ b/base/timsort.jl @@ -0,0 +1,439 @@ +# Implementation of TimSort based on the algorithm description at: +# +# http://svn.python.org/projects/python/trunk/Objects/listsort.txt +# http://en.wikipedia.org/wiki/Timsort +# +# Original author: @kmsquire + +module _TimSort +using Sort + +import Sort.sort! + +typealias Run Range1{Int} + +const MIN_GALLOP = 7 + +type MergeState + runs::Vector{Run} + min_gallop::Int +end +MergeState() = MergeState(Run[], MIN_GALLOP) + +# Determine a good minimum run size for efficient merging +# For details, see "Computing minrun" in +# http://svn.python.org/projects/python/trunk/Objects/listsort.txt +function merge_compute_minrun(N::Int, bits::Int) + r = 0 + max_val = 2^bits + while N >= max_val + r |= (N & 1) + N >>= 1 + end + N + r +end +merge_compute_minrun(N::Int) = merge_compute_minrun(N, 6) + +# Galloping binary search starting at left +# Finds the last value in v <= x +function gallop_last(o::Ordering, v::AbstractVector, x, lo::Int, hi::Int) + i = lo + inc = 1 + lo = lo-1 + hi = hi+1 + while i < hi && !lt(o, x, v[i]) + lo = i + i += inc + inc <<= 1 + end + hi = min(i+1, hi) + # Binary search + while lo < hi-1 + i = (lo+hi)>>>1 + if lt(o, x, v[i]) + hi = i + else + lo = i + end + end + lo +end + +# Galloping binary search starting at right +# Finds the last value in v <= x +function rgallop_last(o::Ordering, v::AbstractVector, x, lo::Int, hi::Int) + i = hi + dec = 1 + lo = lo-1 + hi = hi+1 + while i > lo && lt(o, x, v[i]) + hi = i + i -= dec + dec <<= 1 + end + lo = max(lo, i-1) + # Binary search + while lo < hi-1 + i = (lo+hi)>>>1 + if lt(o, x, v[i]) + hi = i + else + lo = i + end + end + lo +end + +# Galloping binary search starting at left +# Finds the first value in v >= x +function gallop_first(o::Ordering, v::AbstractVector, x, lo::Int, hi::Int) + i = lo + inc = 1 + lo = lo-1 + hi = hi+1 + while i < hi && lt(o, v[i], x) + lo = i + i += inc + inc <<= 1 + end + hi = min(i+1, hi) + # Binary search + while lo < hi-1 + i = (lo+hi)>>>1 + if lt(o, v[i], x) + lo = i + else + hi = i + end + end + hi +end + +# Galloping binary search starting at right +# Finds the first value in v >= x +function rgallop_first(o::Ordering, v::AbstractVector, x, lo::Int, hi::Int) + i = hi + dec = 1 + lo = lo-1 + hi = hi+1 + while i > lo && !lt(o, v[i], x) + hi = i + i -= dec + dec <<= 1 + end + lo = max(lo, i-1) + # Binary search + while lo < hi-1 + i = (lo+hi)>>>1 + if lt(o, v[i], x) + lo = i + else + hi = i + end + end + hi +end + +# Get the next run +# Returns the v range a:b, or b:-1:a for a reversed sequence +function next_run(o::Ordering, v::AbstractVector, lo::Int, hi::Int) + lo == hi && return lo:hi + if !lt(o, v[lo+1], v[lo]) + for i = lo+2:hi + if lt(o, v[i], v[i-1]) + return lo:i-1 + end + end + return lo:hi + else + for i = lo+2:hi + if !lt(o, v[i], v[i-1]) + return i-1:-1:lo + end + end + return hi:-1:lo + end +end + +# Merge consecutive runs +# For A,B,C = last three lengths, merge_collapse!() +# maintains 2 invariants: +# +# A > B + C +# B > C +# +# If any of these are violated, a merge occurs to +# correct it +function merge_collapse(o::Ordering, v::AbstractVector, state::MergeState, force::Bool) + while length(state.runs) > 2 + (a,b,c) = state.runs[end-2:end] + if length(a) > length(b)+length(c) && length(b) > length(c) && !force + break # invariants are satisfied, leave loop + end + if length(a) < length(c) + merge(o,v,a,b,state) + pop!(state.runs) + pop!(state.runs) + pop!(state.runs) + push!(state.runs, first(a):last(b)) + push!(state.runs, c) + else + merge(o,v,b,c,state) + pop!(state.runs) + pop!(state.runs) + push!(state.runs, first(b):last(c)) + end + end + if length(state.runs) == 2 + (a,b) = state.runs[end-1:end] + if length(a) <= length(b) || force + merge(o,v,a,b,state) + pop!(state.runs) + pop!(state.runs) + push!(state.runs, first(a):last(b)) + end + end +end + +# Merge runs a and b in vector v +function merge(o::Ordering, v::AbstractVector, a::Run, b::Run, state::MergeState) + + # First elements in a <= b[1] are already in place + a = gallop_last(o, v, v[first(b)], first(a), last(a))+1: last(a) + + if length(a) == 0 return end + + # Last elements in b >= a[end] are already in place + b = first(b) : rgallop_first(o, v, v[last(a)], first(b), last(b))-1 + + # Choose merge_lo or merge_hi based on the amount + # of temporary memory needed (smaller of a and b) + if length(a) < length(b) + merge_lo(o, v, a, b, state) + else + merge_hi(o, v, a, b, state) + end +end + +# Merge runs a and b in vector v (a is smaller) +function merge_lo(o::Ordering, v::AbstractVector, a::Run, b::Run, state::MergeState) + + # Copy a + v_a = v[a] + + # Pointer into (sub)arrays + i = first(a) + from_a = 1 + from_b = first(b) + + mode = :normal + while true + if mode == :normal + # Compare and copy element by element + count_a = count_b = 0 + while from_a <= length(a) && from_b <= last(b) + if lt(o, v[from_b], v_a[from_a]) + v[i] = v[from_b] + from_b += 1 + count_a = 0 + count_b += 1 + else + v[i] = v_a[from_a] + from_a += 1 + count_a += 1 + count_b = 0 + end + i += 1 + + # Switch to galloping mode if a string of elements + # has come from the same set + if count_b >= state.min_gallop || count_a >= state.min_gallop + mode = :galloping + break + end + end + # Finalize if we've exited the loop normally + if mode == :normal + mode = :finalize + end + end + + if mode == :galloping + # Use binary search to find range to copy + while from_a <= length(a) && from_b <= last(b) + # Copy the next run from b + b_run = from_b : gallop_first(o, v, v_a[from_a], from_b, last(b)) - 1 + i_end = i + length(b_run) - 1 + v[i:i_end] = v[b_run] + i = i_end + 1 + from_b = last(b_run) + 1 + + # ... then copy the first element from a + v[i] = v_a[from_a] + i += 1 + from_a += 1 + + if from_a > length(a) || from_b > last(b) break end + + # Copy the next run from a + a_run = from_a : gallop_last(o, v_a, v[from_b], from_a, length(a)) + i_end = i + length(a_run) - 1 + v[i:i_end] = v_a[a_run] + i = i_end + 1 + from_a = last(a_run) + 1 + + # ... then copy the first element from b + v[i] = v[from_b] + i += 1 + from_b += 1 + + # Return to normal mode if we haven't galloped... + if length(a_run) < MIN_GALLOP && length(b_run) < MIN_GALLOP + mode = :normal + break + end + # Reduce min_gallop if this gallop was successful + state.min_gallop -= 1 + end + if mode == :galloping + mode = :finalize + end + state.min_gallop = max(state.min_gallop,0) + 2 # penalty for leaving gallop mode + end + + if mode == :finalize + # copy end of a + i_end = i + (length(a) - from_a) + v[i:i_end] = v_a[from_a:end] + break + end + end +end + +# Merge runs a and b in vector v (b is smaller) +function merge_hi(o::Ordering, v::AbstractVector, a::Run, b::Run, state::MergeState) + + # Copy b + v_b = v[b] + + # Pointer into (sub)arrays + i = last(b) + from_a = last(a) + from_b = length(b) + + mode = :normal + while true + if mode == :normal + # Compare and copy element by element + count_a = count_b = 0 + while from_a >= first(a) && from_b >= 1 + if !lt(o, v_b[from_b], v[from_a]) + v[i] = v_b[from_b] + from_b -= 1 + count_a = 0 + count_b += 1 + else + v[i] = v[from_a] + from_a -= 1 + count_a += 1 + count_b = 0 + end + i -= 1 + + # Switch to galloping mode if a string of elements + # has come from the same set + if count_b >= state.min_gallop || count_a >= state.min_gallop + mode = :galloping + break + end + end + # Finalize if we've exited the loop normally + if mode == :normal + mode = :finalize + end + end + + if mode == :galloping + # Use binary search to find range to copy + while from_a >= first(a) && from_b >= 1 + # Copy the next run from b + b_run = rgallop_first(o, v_b, v[from_a], 1, from_b) : from_b + i_start = i - length(b_run) + 1 + v[i_start:i] = v_b[b_run] + i = i_start - 1 + from_b = first(b_run) - 1 + + # ... then copy the first element from a + v[i] = v[from_a] + i -= 1 + from_a -= 1 + + if from_a < first(a) || from_b < 1 break end + + # Copy the next run from a + a_run = rgallop_last(o, v, v_b[from_b], first(a), from_a) + 1: from_a + i_start = i - length(a_run) + 1 + v[i_start:i] = v[a_run] + i = i_start - 1 + from_a = first(a_run) - 1 + + # ... then copy the first element from b + v[i] = v_b[from_b] + i -= 1 + from_b -= 1 + + # Return to normal mode if we haven't galloped... + if length(a_run) < MIN_GALLOP && length(b_run) < MIN_GALLOP + mode = :normal + break + end + # Reduce min_gallop if this gallop was successful + state.min_gallop -= 1 + end + if mode == :galloping + mode = :finalize + end + state.min_gallop = max(state.min_gallop, 0) + 2 # penalty for leaving gallop mode + end + + if mode == :finalize + # copy start of b + i_start = i - from_b + 1 + v[i_start:i] = v_b[1:from_b] + break + end + end +end + +# TimSort main method +function sort!(v::AbstractVector, lo::Int, hi::Int, ::TimSort, o::Ordering) + minrun = merge_compute_minrun(hi-lo+1) + state = MergeState() + i = lo + while i <= hi + run_range = next_run(o, v, i, hi) + count = length(run_range) + if count < minrun + # Make a run of length minrun + count = min(minrun, hi-i+1) + run_range = i:i+count-1 + sort!(v, i, i+count-1, SMALL_ALGORITHM, o) + else + if !issorted(run_range) + run_range = last(run_range):first(run_range) + reverse!(sub(v, run_range)) + end + end + # Push this run onto the queue and merge if needed + push!(state.runs, run_range) + i = i+count + merge_collapse(o, v, state, false) + end + # Force merge at the end + if length(state.runs) > 1 + merge_collapse(o, v, state, true) + end + return v +end + +end # module _TimSort diff --git a/base/tuple.jl b/base/tuple.jl index 5ccb6299a3e90..cfa917274b514 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -1,10 +1,12 @@ ## indexing ## length(t::Tuple) = tuplelen(t) +endof(t::Tuple) = tuplelen(t) size(t::Tuple, d) = d==1 ? tuplelen(t) : error("invalid tuple dimension") -ref(t::Tuple, i::Int) = tupleref(t, i) -ref(t::Tuple, i::Integer) = tupleref(t, int(i)) -ref(t::Tuple, r::Ranges) = tuple([t[ri] for ri in r]...) +getindex(t::Tuple, i::Int) = tupleref(t, i) +getindex(t::Tuple, i::Real) = tupleref(t, convert(Int, i)) +getindex(t::Tuple, r::AbstractArray) = tuple([t[ri] for ri in r]...) +getindex(t::Tuple, b::AbstractArray{Bool}) = getindex(t,find(b)) ## iterating ## @@ -15,17 +17,20 @@ next(t::Tuple, i::Int) = (t[i], i+1) # this allows partial evaluation of bounded sequences of next() calls on tuples, # while reducing to plain next() for arbitrary iterables. indexed_next(t::Tuple, i::Int, state) = (t[i], i+1) -indexed_next(I, i, state) = next(I, state) +indexed_next(a::Array, i::Int, state) = (a[i], i+1) +indexed_next(I, i, state) = done(I,state) ? throw(BoundsError()) : next(I, state) ## mapping ## -ntuple(n::Integer, f) = n<=0 ? () : - n==1 ? (f(1),) : - n==2 ? (f(1),f(2),) : - n==3 ? (f(1),f(2),f(3),) : - n==4 ? (f(1),f(2),f(3),f(4),) : - n==5 ? (f(1),f(2),f(3),f(4),f(5),) : - tuple(ntuple(n-2,f)..., f(n-1), f(n)) +ntuple(n::Integer, f::Function) = ntuple(f, n) # TODO: deprecate this? +ntuple(f::Function, n::Integer) = + n<=0 ? () : + n==1 ? (f(1),) : + n==2 ? (f(1),f(2),) : + n==3 ? (f(1),f(2),f(3),) : + n==4 ? (f(1),f(2),f(3),f(4),) : + n==5 ? (f(1),f(2),f(3),f(4),f(5),) : + tuple(ntuple(n-2,f)..., f(n-1), f(n)) # 0 argument function map(f) = f() diff --git a/base/utf8.jl b/base/utf8.jl index c40cc43280f42..311edbe9ddbe0 100644 --- a/base/utf8.jl +++ b/base/utf8.jl @@ -1,19 +1,19 @@ ## from base/boot.jl: # -# type UTF8String <: String +# immutable UTF8String <: String # data::Array{Uint8,1} # end # ## basic UTF-8 decoding & iteration ## -const _jl_utf8_offset = [ +const utf8_offset = [ 0x00000000, 0x00003080, 0x000e2080, 0x03c82080, 0xfa082080, 0x82082080, ] -const _jl_utf8_trailing = [ +const utf8_trailing = [ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -28,29 +28,40 @@ is_utf8_start(byte::Uint8) = ((byte&0xc0)!=0x80) ## required core functionality ## -length(s::UTF8String) = length(s.data) -strlen(s::UTF8String) = ccall(:u8_strlen, Int, (Ptr{Uint8},), s.data) - -function next(s::UTF8String, i::Int) - if !is_utf8_start(s.data[i]) - error("invalid UTF-8 character index") +endof(s::UTF8String) = thisind(s,length(s.data)) +length(s::UTF8String) = ccall(:u8_strlen, Int, (Ptr{Uint8},), s.data) + +function getindex(s::UTF8String, i::Int) + d = s.data + b = d[i] + if !is_utf8_start(b) + j = i-1 + while 0 < j && !is_utf8_start(d[j]) + j -= 1 + end + if 0 < j && i <= j+utf8_trailing[d[j]+1] <= length(d) + # b is a continuation byte of a valid UTF-8 character + error("invalid UTF-8 character index") + end + return '\ufffd' end - trailing = _jl_utf8_trailing[s.data[i]+1] - if length(s.data) < i + trailing - error("premature end of UTF-8 data") + trailing = utf8_trailing[b+1] + if length(d) < i + trailing + return '\ufffd' end c::Uint32 = 0 - for j = 1:trailing - c += s.data[i] + for j = 1:trailing+1 c <<= 6 + c += d[i] i += 1 end - c += s.data[i] - i += 1 - c -= _jl_utf8_offset[trailing+1] - char(c), i + c -= utf8_offset[trailing+1] + char(c) end +# this is a trick to allow inlining and tuple elision +next(s::UTF8String, i::Int) = (s[i], i+1+utf8_trailing[s.data[i]+1]) + function first_utf8_byte(c::Char) c < 0x80 ? uint8(c) : c < 0x800 ? uint8((c>>6 )|0xc0) : @@ -61,33 +72,28 @@ end ## overload methods for efficiency ## isvalid(s::UTF8String, i::Integer) = - (1 <= i <= length(s.data)) && is_utf8_start(s.data[i]) + (1 <= i <= endof(s.data)) && is_utf8_start(s.data[i]) -function ref(s::UTF8String, r::Range1{Int}) - i = isvalid(s,first(r)) ? first(r) : nextind(s,first(r)) - j = nextind(s,last(r))-1 +function getindex(s::UTF8String, r::Range1{Int}) + a, b = first(r), last(r) + i = isvalid(s,a) ? a : nextind(s,a) + j = b < endof(s) ? nextind(s,b)-1 : endof(s.data) UTF8String(s.data[i:j]) end -function strchr(s::UTF8String, c::Char, i::Integer) - if c < 0x80 return memchr(s.data, c, i) end +function search(s::UTF8String, c::Char, i::Integer) + if c < 0x80 return search(s.data, c, i) end while true - i = memchr(s.data, first_utf8_byte(c), i) + i = search(s.data, first_utf8_byte(c), i) if i==0 || s[i]==c return i end i = next(s,i)[2] end end -strcat(a::ByteString, b::ByteString, c::ByteString...) = +string(a::ByteString, b::ByteString, c::ByteString...) = # ^^ at least one must be UTF-8 or the ASCII-only method would get called UTF8String([a.data,b.data,map(s->s.data,c)...]) -transform_to_utf8(s::String, f::Function) = - sprint(length(s), io->for c in s; write(io,f(c)::Char); end) - -uppercase(s::UTF8String) = transform_to_utf8(s, uppercase) -lowercase(s::UTF8String) = transform_to_utf8(s, lowercase) - ucfirst(s::UTF8String) = string(uppercase(s[1]), s[2:]) lcfirst(s::UTF8String) = string(lowercase(s[1]), s[2:]) @@ -101,5 +107,5 @@ write(io::IO, s::UTF8String) = write(io, s.data) utf8(x) = convert(UTF8String, x) convert(::Type{UTF8String}, s::UTF8String) = s convert(::Type{UTF8String}, s::ASCIIString) = UTF8String(s.data) -convert(::Type{UTF8String}, a::Array{Uint8,1}) = check_utf8(UTF8String(a)) +convert(::Type{UTF8String}, a::Array{Uint8,1}) = is_valid_utf8(a) ? UTF8String(a) : error("invalid UTF-8 sequence") convert(::Type{UTF8String}, s::String) = utf8(bytestring(s)) diff --git a/base/util.jl b/base/util.jl index a09d4b4c73637..adcf9d73fef14 100644 --- a/base/util.jl +++ b/base/util.jl @@ -1,22 +1,26 @@ # timing +# system date in seconds time() = ccall(:clock_now, Float64, ()) +# high-resolution relative time, in nanoseconds +time_ns() = ccall(:jl_hrtime, Uint64, ()) + function tic() - t0 = time() - tls(:TIMERS, (t0, get(tls(), :TIMERS, ()))) + t0 = time_ns() + task_local_storage(:TIMERS, (t0, get(task_local_storage(), :TIMERS, ()))) return t0 end function toq() - t1 = time() - timers = get(tls(), :TIMERS, ()) + t1 = time_ns() + timers = get(task_local_storage(), :TIMERS, ()) if is(timers,()) error("toc() without tic()") end t0 = timers[1] - tls(:TIMERS, timers[2]) - t1-t0 + task_local_storage(:TIMERS, timers[2]) + (t1-t0)/1e9 end function toc() @@ -25,19 +29,13 @@ function toc() return t end -# high-resolution time -# returns in nanoseconds -function time_ns() - return ccall(:jl_hrtime, Uint64, ()) -end - # print elapsed time, return expression value macro time(ex) quote - local t0 = time() + local t0 = time_ns() local val = $(esc(ex)) - local t1 = time() - println("elapsed time: ", t1-t0, " seconds") + local t1 = time_ns() + println("elapsed time: ", (t1-t0)/1e9, " seconds") val end end @@ -45,9 +43,18 @@ end # print nothing, return elapsed time macro elapsed(ex) quote - local t0 = time() + local t0 = time_ns() local val = $(esc(ex)) - time()-t0 + (time_ns()-t0)/1e9 + end +end + +# print nothing, return value & elapsed time +macro timed(ex) + quote + local t0 = time_ns() + local val = $(esc(ex)) + val, (time_ns()-t0)/1e9 end end @@ -55,7 +62,7 @@ function peakflops(n) a = rand(n,n) t = @elapsed a*a t = @elapsed a*a - floprate = (2.0*n^3/t) + floprate = (2.0*float64(n)^3/t) println("The peak flop rate is ", floprate*1e-9, " gigaflops") floprate end @@ -64,19 +71,19 @@ peakflops() = peakflops(2000) # source files, editing, function reflection -function function_loc(f::Function, types) +function functionloc(f::Function, types) for m = methods(f, types) if isa(m[3],LambdaStaticData) lsd = m[3]::LambdaStaticData ln = lsd.line if ln > 0 - return (find_in_path(string(lsd.file)), ln) + return (find_source_file(string(lsd.file)), ln) end end end error("could not find function definition") end -function_loc(f::Function) = function_loc(f, (Any...)) +functionloc(f::Function) = functionloc(f, (Any...)) function whicht(f, types) for m = methods(f, types) @@ -85,8 +92,8 @@ function whicht(f, types) d = f.env.defs while !is(d,()) if is(d.func.code, lsd) - print(stdout_stream, f.env.name) - show(stdout_stream, d); println(stdout_stream) + print(OUTPUT_STREAM, f.env.name) + show(OUTPUT_STREAM, d); println(OUTPUT_STREAM) return end d = d.next @@ -97,358 +104,300 @@ end which(f, args...) = whicht(f, map(a->(isa(a,Type) ? Type{a} : typeof(a)), args)) -edit(file::String) = edit(file, 1) -function edit(file::String, line::Int) - editor = get(ENV, "JULIA_EDITOR", "emacs") - issrc = file[end-2:end] == ".jl" - if issrc - if file[1]!='/' && !is_file_readable(file) - file2 = "$JULIA_HOME/base/$file" +macro which(ex) + ex = expand(ex) + exret = Expr(:call, :error, "expression is not a function call") + if !isa(ex, Expr) + # do nothing -> error + elseif ex.head == :call + exret = Expr(:call, :which, map(esc, ex.args)...) + elseif ex.head == :body + a1 = ex.args[1] + if isa(a1, Expr) && a1.head == :call + a11 = a1.args[1] + if isa(a11, TopNode) && a11.name == :setindex! + exret = Expr(:call, :which, a11, map(esc, a1.args[2:end])...) + end + end + elseif ex.head == :thunk + exret = Expr(:call, :error, "expression is not a function call, or is too complex for @which to analyze; " + * "break it down to simpler parts if possible") + end + exret +end + +function find_source_file(file) + if file[1]!='/' && !is_file_readable(file) + file2 = find_in_path(file) + if is_file_readable(file2) + return file2 + else + file2 = "$JULIA_HOME/../share/julia/base/$file" if is_file_readable(file2) - file = file2 + return file2 end end - if editor == "emacs" - jmode = "$JULIA_HOME/contrib/julia-mode.el" + end + return file +end + +edit(file::String) = edit(file, 1) +function edit(file::String, line::Integer) + editor = get(ENV, "JULIA_EDITOR", "emacs") + issrc = length(file)>2 && file[end-2:end] == ".jl" + if issrc + file = find_source_file(file) + end + if editor == "emacs" + if issrc + jmode = "$JULIA_HOME/../../contrib/julia-mode.el" run(`emacs $file --eval "(progn (require 'julia-mode \"$jmode\") (julia-mode) (goto-line $line))"`) - elseif editor == "vim" - run(`vim $file +$line`) - elseif editor == "textmate" - run(`mate $file -l $line`) - elseif editor == "subl" - run(`subl $file:$line`) else - error("Invalid JULIA_EDITOR value: $(repr(editor))") - end - else - if editor == "emacs" run(`emacs $file --eval "(goto-line $line)"`) - elseif editor == "vim" - run(`vim $file +$line`) - elseif editor == "textmate" - run(`mate $file -l $line`) - elseif editor == "subl" - run(`subl $file:$line`) + end + elseif editor == "vim" + run(`vim $file +$line`) + elseif editor == "textmate" + run(`mate $file -l $line`) + elseif editor == "subl" + run(`subl $file:$line`) + elseif editor == "notepad" + run(`notepad $file`) + elseif editor == "start" || editor == "open" + if OS_NAME == :Windows + run(`start /b $file`) + elseif OS_NAME == :Darwin + run(`open -t $file`) else - error("Invalid JULIA_EDITOR value: $(repr(editor))") + error("Don't know how to launch the default editor on your platform") end + else + error("Invalid JULIA_EDITOR value: $(repr(editor))") end nothing end edit(file::String) = edit(file, 1) -function less(file::String, line::Int) +function less(file::String, line::Integer) pager = get(ENV, "PAGER", "less") run(`$pager +$(line)g $file`) end less(file::String) = less(file, 1) -edit(f::Function) = edit(function_loc(f)...) -edit(f::Function, t) = edit(function_loc(f,t)...) -less(f::Function) = less(function_loc(f)...) -less(f::Function, t) = less(function_loc(f,t)...) +edit(f::Function) = edit(functionloc(f)...) +edit(f::Function, t) = edit(functionloc(f,t)...) +less(f::Function) = less(functionloc(f)...) +less(f::Function, t) = less(functionloc(f,t)...) disassemble(f::Function, types::Tuple) = print(ccall(:jl_dump_function, Any, (Any,Any), f, types)::ByteString) function methods(f::Function) if !isgeneric(f) - error("methods: error: not a generic function") + error("methods: not a generic function") end f.env end -methods(t::CompositeKind) = (methods(t,Tuple); # force constructor creation - t.env) - - -# require -# Store list of files and their load time -_jl_package_list = (ByteString=>Float64)[] -require(fname::String) = require(bytestring(fname)) -require(f::String, fs::String...) = (require(f); for x in fs require(x); end) -function require(name::ByteString) - path = find_in_path(name) - if !has(_jl_package_list,path) - load_now(name) - else - # Determine whether the file has been modified since it was last loaded - if mtime(path) > _jl_package_list[path] - load_now(name) - end - end -end - -const load = require - -# remote/parallel load - -include_string(txt::ByteString) = ccall(:jl_load_file_string, Void, (Ptr{Uint8},), txt) +methods(t::DataType) = (methods(t,Tuple); # force constructor creation + t.env) -function is_file_readable(path) - s = stat(bytestring(path)) - return isfile(s) && isreadable(s) -end +# print a warning only once -function find_in_path(name::String) - name[1] == '/' && return realpath(name) - isfile(name) && return realpath(name) - base = name - if ends_with(name,".jl") - base = match(r"^(.*)\.jl$",name).captures[1] - else - name = strcat(base,".jl") - end - for prefix in LOAD_PATH - path = strcat(prefix,"/",base,"/src/",name) - is_file_readable(path) && return realpath(path) - path = strcat(prefix,"/",name) - is_file_readable(path) && return realpath(path) - end - return realpath(name) +const have_warned = (ByteString=>Bool)[] +function warn_once(msg::String...) + msg = bytestring(msg...) + has(have_warned,msg) && return + have_warned[msg] = true + warn(msg) end -begin -local in_load = false -local in_remote_load = false -local load_dict = {} -global load_now, remote_load - -load_now(fname::String) = load_now(bytestring(fname)) -function load_now(fname::ByteString) - if in_load - path = find_in_path(fname) - push(load_dict, fname) - f = open(path) - push(load_dict, readall(f)) - close(f) - include(path) - _jl_package_list[path] = time() - return - elseif in_remote_load - for i=1:2:length(load_dict) - if load_dict[i] == fname - return include_string(load_dict[i+1]) - end +# system information + +versioninfo() = versioninfo(false) +versioninfo(verbose::Bool) = versioninfo(OUTPUT_STREAM, verbose) +function versioninfo(io::IO, verbose::Bool) + println(io, "Julia $version_string") + println(io, commit_string) + println(io, "Platform Info:") + println(io, " OS_NAME: ", OS_NAME) + println(io, " WORD_SIZE: ", WORD_SIZE) + if verbose + lsb = readchomp(ignorestatus(`lsb_release -ds`) .> SpawnNullStream()) + if lsb != "" + println(io, " ", lsb) end + println(io, " uname: ",readchomp(`uname -mprsv`)) + println(io, "Memory: $(total_memory()/2^30) GB ($(free_memory()/2^20) MB free)") + try println(io, "Uptime: $(uptime()) sec") catch end + print(io, "Load Avg: ") + print_matrix(io, Base.loadavg()') + println(io ) + println(io, cpu_info()) + end + if Base.libblas_name == "libopenblas" + openblas_config = chop(bytestring( ccall((:openblas_get_config, Base.libblas_name), Ptr{Uint8}, () ))) + println(io, " BLAS: ",libblas_name, " (", openblas_config, ")") else - in_load = true - try - load_now(fname) - for p = 1:nprocs() - if p != myid() - remote_do(p, remote_load, load_dict) - end + println(io, " BLAS: ",libblas_name) + end + println(io, " LAPACK: ",liblapack_name) + println(io, " LIBM: ",libm_name) + if verbose + println(io, "Environment:") + for (k,v) in ENV + if !is(match(r"JULIA|PATH|FLAG|^TERM$|HOME",k), nothing) + println(io, " $(k) = $(v)") end - finally - load_dict = {} - in_load = false end + println(io ) + println(io, "Packages Installed:") + Pkg.status(io ) end end -function remote_load(dict) - load_dict = dict - in_remote_load = true - try - load_now(dict[1]) - finally - in_remote_load = false - end - nothing +type UV_cpu_info_t + model::Ptr{Uint8} + speed::Int32 + cpu_times!user::Uint64 + cpu_times!nice::Uint64 + cpu_times!sys::Uint64 + cpu_times!idle::Uint64 + cpu_times!irq::Uint64 end +type CPUinfo + model::ASCIIString + speed::Int32 + cpu_times!user::Uint64 + cpu_times!nice::Uint64 + cpu_times!sys::Uint64 + cpu_times!idle::Uint64 + cpu_times!irq::Uint64 + SC_CLK_TCK::Int + CPUinfo(model,speed,u,n,s,id,ir,ticks)=new(model,speed,u,n,s,id,ir,ticks) end - -evalfile(fname::String) = eval(Main,parse(readall(fname))[1]) - -# help - -_jl_help_category_list = nothing -_jl_help_category_dict = nothing -_jl_help_module_dict = nothing -_jl_help_function_dict = nothing - -function _jl_decor_help_desc(func::String, mfunc::String, desc::String) - sd = split(desc, '\n') - for i = 1:length(sd) - if begins_with(sd[i], func) - sd[i] = mfunc * sd[i][length(func)+1:end] +CPUinfo(info::UV_cpu_info_t, ticks) = CPUinfo(bytestring(info.model), info.speed, + info.cpu_times!user, info.cpu_times!nice, info.cpu_times!sys, + info.cpu_times!idle, info.cpu_times!irq, ticks) + +show(io::IO, cpu::CPUinfo) = show(io, cpu, true, " ") +function show(io::IO, info::CPUinfo, header::Bool, prefix::String) + tck = info.SC_CLK_TCK + if header + println(io, info.model, ": ") + print(" "^length(prefix)) + if tck > 0 + @printf io " %5s %9s %9s %9s %9s %9s\n" "speed" "user" "nice" "sys" "idle" "irq" else - break + @printf io " %5s %9s %9s %9s %9s %9s ticks\n" "speed" "user" "nice" "sys" "idle" "irq" end end - return join(sd, '\n') + print(prefix) + if tck > 0 + @printf io "%5d MHz %9d s %9d s %9d s %9d s %9d s" info.speed info.cpu_times!user/tck info.cpu_times!nice/tck info.cpu_times!sys/tck info.cpu_times!idle/tck info.cpu_times!irq/tck + else + @printf io "%5d MHz %9d %9d %9d %9d %9d ticks" info.speed info.cpu_times!user info.cpu_times!nice info.cpu_times!sys info.cpu_times!idle info.cpu_times!irq + end end - -function _jl_init_help() - global _jl_help_category_list, _jl_help_category_dict, - _jl_help_module_dict, _jl_help_function_dict - if _jl_help_category_dict == nothing - println("Loading help data...") - helpdb = evalfile("$JULIA_HOME/../share/julia/helpdb.jl") - _jl_help_category_list = {} - _jl_help_category_dict = Dict() - _jl_help_module_dict = Dict() - _jl_help_function_dict = Dict() - for (cat,mod,func,desc) in helpdb - if !has(_jl_help_category_dict, cat) - push(_jl_help_category_list, cat) - _jl_help_category_dict[cat] = {} - end - if !isempty(mod) - if begins_with(func, '@') - mfunc = "@" * mod * "." * func[2:] - else - mfunc = mod * "." * func - end - desc = _jl_decor_help_desc(func, mfunc, desc) - else - mfunc = func - end - push(_jl_help_category_dict[cat], mfunc) - if !has(_jl_help_function_dict, mfunc) - _jl_help_function_dict[mfunc] = {} - end - push(_jl_help_function_dict[mfunc], desc) - if !has(_jl_help_module_dict, func) - _jl_help_module_dict[func] = {} - end - if !contains(_jl_help_module_dict[func], mod) - push(_jl_help_module_dict[func], mod) - end +function cpu_summary(io::IO, cpu::Array{CPUinfo}, i, j) + if j-i < 9 + header = true + for x = i:j + if header == false println() end + show(io,cpu[x],header,"#$(x-i+1) ") + header = false end + else + summary = CPUinfo(cpu[i].model,0,0,0,0,0,0,cpu[i].SC_CLK_TCK) + count = j-i+1 + for x = i:j + summary.speed += cpu[i].speed + summary.cpu_times!user += cpu[x].cpu_times!user + summary.cpu_times!nice += cpu[x].cpu_times!nice + summary.cpu_times!sys += cpu[x].cpu_times!sys + summary.cpu_times!idle += cpu[x].cpu_times!idle + summary.cpu_times!irq += cpu[x].cpu_times!irq + end + summary.speed = div(summary.speed,count) + show(io,summary,true,"#1-$(count) ") end end - -function help() - _jl_init_help() - print( -" Welcome to Julia. The full manual is available at - - http://docs.julialang.org - - To get help on a function, try help(function). To search all help text, - try apropos(\"string\"). To see available functions, try help(category), - for one of the following categories: - -") - for cat = _jl_help_category_list - if !isempty(_jl_help_category_dict[cat]) - print(" ") - show(cat); println() +function show(io::IO, cpu::Array{CPUinfo}) + model = cpu[1].model + first = 1 + for i = 2:length(cpu) + if model != cpu[i].model + cpu_summary(io,cpu,first,i-1) + first = i end end + cpu_summary(io,cpu,first,length(cpu)) end - -function help(cat::String) - _jl_init_help() - if !has(_jl_help_category_dict, cat) - # if it's not a category, try another named thing - return help_for(cat) +repl_show(io::IO, cpu::Array{CPUinfo}) = show(io, cpu) +function cpu_info() + SC_CLK_TCK = ccall(:SC_CLK_TCK, Int, ()) + UVcpus = Array(Ptr{UV_cpu_info_t},1) + count = Array(Int32,1) + uv_error("uv_cpu_info",ccall(:uv_cpu_info, UV_error_t, (Ptr{Ptr{UV_cpu_info_t}}, Ptr{Int32}), UVcpus, count)) + cpus = Array(CPUinfo,count[1]) + for i = 1:length(cpus) + cpus[i] = CPUinfo(unsafe_ref(UVcpus[1],i),SC_CLK_TCK) end - println("Help is available for the following items:") - for func = _jl_help_category_dict[cat] - print(func, " ") - end - println() + ccall(:uv_free_cpu_info, Void, (Ptr{UV_cpu_info_t}, Int32), UVcpus[1], count[1]) + cpus end -function _jl_print_help_entries(entries) - first = true - for desc in entries - if !first - println() - end - println(strip(desc)) - first = false - end +function uptime() + uptime_ = Array(Float64,1) + uv_error("uv_uptime",ccall(:uv_uptime, UV_error_t, (Ptr{Float64},), uptime_)) + return uptime_[1] end -help_for(s::String) = help_for(s, 0) -function help_for(fname::String, obj) - _jl_init_help() - found = false - if contains(fname, '.') - if has(_jl_help_function_dict, fname) - _jl_print_help_entries(_jl_help_function_dict[fname]) - found = true - end - else - macrocall = "" - if begins_with(fname, '@') - sfname = fname[2:] - macrocall = "@" - else - sfname = fname - end - if has(_jl_help_module_dict, fname) - allmods = _jl_help_module_dict[fname] - alldesc = {} - for mod in allmods - mod_prefix = isempty(mod) ? "" : mod * "." - append!(alldesc, _jl_help_function_dict[macrocall * mod_prefix * sfname]) - end - _jl_print_help_entries(alldesc) - found = true - end - end - if !found - if isgeneric(obj) - repl_show(obj); println() - else - println("No help information found.") - end - end +function loadavg() + loadavg_ = Array(Float64,3) + ccall(:uv_loadavg, Void, (Ptr{Float64},), loadavg_) + return loadavg_ end -function apropos(txt::String) - _jl_init_help() - n = 0 - r = Regex("\\Q$txt", PCRE.CASELESS) - for (cat, _) in _jl_help_category_dict - if ismatch(r, cat) - println("Category: \"$cat\"") - end - end - for (func, entries) in _jl_help_function_dict - if ismatch(r, func) || anyp(e->ismatch(r,e), entries) - for desc in entries - nl = search(desc,'\n') - if nl[1] != 0 - println(desc[1:(nl[1]-1)]) - else - println(desc) - end - end - n+=1 - end - end - if n == 0 - println("No help information found.") - end -end +free_memory() = ccall(:uv_get_free_memory, Uint64, ()) +total_memory() = ccall(:uv_get_total_memory, Uint64, ()) -function help(f::Function) - if is(f,help) - return help() - end - help_for(string(f), f) -end -help(t::CompositeKind) = help_for(string(t.name),t) +# `methodswith` -- shows a list of methods using the type given -function help(x) - show(x) - t = typeof(x) - println(" is of type $t") - if isa(t,CompositeKind) - println(" which has fields $(t.names)") +function methodswith(io::IO, t::Type, m::Module, showparents::Bool) + for nm in names(m) + try + mt = eval(nm) + d = mt.env.defs + while !is(d,()) + if any(map(x -> x == t || (showparents && t <: x && x != Any && x != ANY && !isa(x, TypeVar)), d.sig)) + print(io, nm) + show(io, d) + println(io) + end + d = d.next + end + end end end -# misc - -times(f::Function, n::Int) = for i=1:n f() end +methodswith(t::Type, m::Module, showparents::Bool) = methodswith(OUTPUT_STREAM, t, m, showparents) +methodswith(t::Type, showparents::Bool) = methodswith(OUTPUT_STREAM, t, showparents) +methodswith(t::Type, m::Module) = methodswith(OUTPUT_STREAM, t, m, false) +methodswith(t::Type) = methodswith(OUTPUT_STREAM, t, false) +function methodswith(io::IO, t::Type, showparents::Bool) + mainmod = ccall(:jl_get_current_module, Any, ())::Module + # find modules in Main + for nm in names(mainmod) + if isdefined(mainmod,nm) + mod = eval(mainmod, nm) + if isa(mod, Module) + methodswith(io, t, mod, showparents) + end + end + end +end diff --git a/base/version.jl b/base/version.jl index c095f1113652a..5fe6366e64ae9 100644 --- a/base/version.jl +++ b/base/version.jl @@ -1,49 +1,45 @@ ## semantic version numbers (http://semver.org) -type VersionNumber +immutable VersionNumber major::Int minor::Int patch::Int - prerelease::Vector{Union(Int,ASCIIString)} - build::Vector{Union(Int,ASCIIString)} + prerelease::(Union(Int,ASCIIString)...) + build::(Union(Int,ASCIIString)...) - function VersionNumber(major::Int, minor::Int, patch::Int, pre::Vector, bld::Vector) + function VersionNumber(major::Integer, minor::Integer, patch::Integer, pre::(Union(Int,ASCIIString)...), bld::(Union(Int,ASCIIString)...)) if major < 0 error("invalid major version: $major") end if minor < 0 error("invalid minor version: $minor") end if patch < 0 error("invalid patch version: $patch") end - prerelease = Array(Union(Int,ASCIIString),length(pre)) - for i in 1:length(pre) - ident = ascii(string(pre[i])) - if isempty(ident) && !(length(pre)==1 && isempty(bld)) - error("invalid pre-release identifier: empty string") - end - if !ismatch(r"^(?:[0-9a-z-]*)?$"i, ident) - error("invalid pre-release identifier: $ident") + for ident in pre + if isa(ident,Int) + ident >= 0 || error("invalid negative pre-release identifier: $ident") + else + if !ismatch(r"^[0-9a-z-]*$"i, ident) + error("invalid pre-release identifier: $ident") + end + if isempty(ident) && !(length(pre)==1 && isempty(bld)) + error("invalid pre-release identifier: empty string") + end end - if ismatch(r"^\d+$", ident) - ident = parse_int(ident) - end - prerelease[i] = ident end - build = Array(Union(Int,ASCIIString),length(bld)) - for i in 1:length(bld) - ident = ascii(string(bld[i])) - if !ismatch(r"^(?:[0-9a-z-]+)?$"i, ident) + for ident in bld + if !ismatch(r"^[0-9a-z-]*$"i, ident) error("invalid build identifier: $ident") end - if ismatch(r"^\d+$", ident) - ident = parse_int(ident) + if isempty(ident) && length(bld)!=1 + error("invalid pre-release identifier: empty string") end - build[i] = ident end - new(major, minor, patch, prerelease, build) + new(major, minor, patch, pre, bld) end end -VersionNumber(x::Integer, y::Integer, z::Integer) = VersionNumber(x, y, z, [], []) -VersionNumber(x::Integer, y::Integer) = VersionNumber(x, y, 0, [], []) -VersionNumber(x::Integer) = VersionNumber(x, 0, 0, [], []) +VersionNumber(x::Integer, y::Integer, z::Integer) = VersionNumber(x, y, z, (), ()) +VersionNumber(x::Integer, y::Integer) = VersionNumber(x, y, 0, (), ()) +VersionNumber(x::Integer) = VersionNumber(x, 0, 0, (), ()) function print(io::IO, v::VersionNumber) + v == typemax(VersionNumber) && return print(io, "∞") print(io, v.major) print(io, '.') print(io, v.minor) @@ -58,7 +54,7 @@ function print(io::IO, v::VersionNumber) print_joined(io, v.build,'.') end end -show(io, v::VersionNumber) = print(io, "v\"", v, "\"") +show(io::IO, v::VersionNumber) = print(io, "v\"", v, "\"") convert(::Type{VersionNumber}, v::Integer) = VersionNumber(v) convert(::Type{VersionNumber}, v::Tuple) = VersionNumber(v...) @@ -70,37 +66,49 @@ const VERSION_REGEX = r"^ (?:\.(\d+))? # patch (optional) (?:(-)| (?:-((?:[0-9a-z-]+\.)*[0-9a-z-]+))? # pre-release (optional) + (?:(\+)| (?:\+((?:[0-9a-z-]+\.)*[0-9a-z-]+))? # build (optional) - ) + )) $"ix +function split_idents(s::String) + idents = split(s, '.') + ntuple(length(idents)) do i + ident = idents[i] + ismatch(r"^\d+$", ident) ? parseint(ident) : ident + end +end + function convert(::Type{VersionNumber}, v::String) m = match(VERSION_REGEX, v) if m == nothing error("invalid version string: $v") end - major, minor, patch, minus, prerl, build = m.captures + major, minor, patch, minus, prerl, plus, build = m.captures major = int(major) minor = minor != nothing ? int(minor) : 0 patch = patch != nothing ? int(patch) : 0 - prerl = prerl != nothing ? split(prerl,'.') : minus != nothing ? [""] : [] - build = build != nothing ? split(build,'.') : [] + prerl = prerl != nothing ? split_idents(prerl) : minus == "-" ? ("",) : () + build = build != nothing ? split_idents(build) : plus == "+" ? ("",) : () VersionNumber(major, minor, patch, prerl, build) end macro v_str(v); convert(VersionNumber, v); end -_jl_ident_cmp(a::Int, b::Int) = cmp(a,b) -_jl_ident_cmp(a::Int, b::ASCIIString) = isempty(b) ? +1 : -1 -_jl_ident_cmp(a::ASCIIString, b::Int) = isempty(a) ? -1 : +1 -_jl_ident_cmp(a::ASCIIString, b::ASCIIString) = cmp(a,b) +typemin(::Type{VersionNumber}) = v"0-" +typemax(::Type{VersionNumber}) = VersionNumber(typemax(Int),typemax(Int),typemax(Int),(),("",)) -function _jl_ident_cmp(A::Vector{Union(Int,ASCIIString)}, - B::Vector{Union(Int,ASCIIString)}) +ident_cmp(a::Int, b::Int) = cmp(a,b) +ident_cmp(a::Int, b::ASCIIString) = isempty(b) ? +1 : -1 +ident_cmp(a::ASCIIString, b::Int) = isempty(a) ? -1 : +1 +ident_cmp(a::ASCIIString, b::ASCIIString) = cmp(a,b) + +function ident_cmp(A::(Union(Int,ASCIIString)...), + B::(Union(Int,ASCIIString)...)) i = start(A) j = start(B) while !done(A,i) && !done(B,i) a,i = next(A,i) b,j = next(B,j) - c = _jl_ident_cmp(a,b) + c = ident_cmp(a,b) (c != 0) && return c end done(A,i) && !done(B,j) ? -1 : @@ -111,11 +119,13 @@ function isequal(a::VersionNumber, b::VersionNumber) (a.major != b.major) && return false (a.minor != b.minor) && return false (a.patch != b.patch) && return false - (_jl_ident_cmp(a.prerelease,b.prerelease) != 0) && return false - (_jl_ident_cmp(a.build,b.build) != 0) && return false + (ident_cmp(a.prerelease,b.prerelease) != 0) && return false + (ident_cmp(a.build,b.build) != 0) && return false return true end +issupbuild(v::VersionNumber) = length(v.build)==1 && isempty(v.build[1]) + function isless(a::VersionNumber, b::VersionNumber) (a.major < b.major) && return true (a.major > b.major) && return false @@ -125,66 +135,135 @@ function isless(a::VersionNumber, b::VersionNumber) (a.patch > b.patch) && return false (!isempty(a.prerelease) && isempty(b.prerelease)) && return true (isempty(a.prerelease) && !isempty(b.prerelease)) && return false - c = _jl_ident_cmp(a.prerelease,b.prerelease) + c = ident_cmp(a.prerelease,b.prerelease) (c < 0) && return true (c > 0) && return false - c = _jl_ident_cmp(a.build,b.build) + (!issupbuild(a) && issupbuild(b)) && return true + (issupbuild(a) && !issupbuild(b)) && return false + c = ident_cmp(a.build,b.build) (c < 0) && return true return false end +hash(v::VersionNumber) = hash([v.(n) for n in VersionNumber.names]) + ## julia version info +if(isfile("$JULIA_HOME/../../VERSION")) const VERSION = convert(VersionNumber,readchomp("$JULIA_HOME/../../VERSION")) -try +elseif(isfile("$JULIA_HOME/../share/julia/VERSION")) + const VERSION = convert(VersionNumber,readchomp("$JULIA_HOME/../share/julia/VERSION")) +else + const VERSION = convert(VersionNumber,"0.0.0") +end +if(isfile("$JULIA_HOME/../../COMMIT")) + const VERSION_COMMIT = "" + const commit_string = readchomp("$JULIA_HOME/../../COMMIT") +elseif(isfile("$JULIA_HOME/../share/julia/COMMIT")) + const VERSION_COMMIT = "" + const commit_string = readchomp("$JULIA_HOME/../share/julia/COMMIT") +else + +let + expected = ErrorException("don't copy this code, for breaking out of uv_run during boot-strapping only") + acceptable = ErrorException(expected.msg) # we would like to update the error msg for this later, but at + # this point in the bootstrapping, conflicts between old and new + # defintions for write, TTY, ASCIIString, and STDOUT make it fail ver = string(VERSION) - commit = readchomp(`git rev-parse HEAD`) - tagged = try readchomp(`git rev-parse --verify --quiet v$ver`) - catch "doesn't reference a commit"; end - ctim = int(readall(`git log -1 --pretty=format:%ct`)) - if commit != tagged - # 1250998746: ctime of first commit (Sat Aug 23 3:39:06 2009 UTC) - push(VERSION.build, ctim - 1250998746) - push(VERSION.build, "r$(commit[1:4])") + + outctim,ps = readsfrom(`git log -1 --pretty=format:%ct`) + ps.closecb = function(proc) + if !success(proc) + #acceptable.msg = string("failed process: ",proc," [",proc.exit_code,"]") + error(acceptable) + end + + ctim = int(readall(proc.out.buffer)) + + outdesc,ps = readsfrom(`git describe --tags --dirty --long --abbrev=10`) + ps.closecb = function(proc) + if !success(proc) + #acceptable.msg = string("failed process: ",proc," [",proc.exit_code,"]") + error(acceptable) + end + + description = readchomp(proc.out.buffer) + m = match(r"^(v\d+(?:\.\d+)+)-(\d+)-g([0-9a-f]{10})(-dirty)?$", description) + if m == nothing + error(acceptable) + end + tag = convert(VersionNumber, m.captures[1]) + commits_after_tag = int(m.captures[2]) + commit = m.captures[3] + dirty = m.captures[4] != nothing + + if commits_after_tag > 0 + field = tag < VERSION ? VERSION.prerelease : VERSION.build + field = tuple(field..., commits_after_tag, "r$(commit[1:8])") + if dirty + field = tuple(field..., "dirty") + end + tag = VersionNumber( + tag.major, + tag.minor, + tag.patch, + tag < VERSION ? field : tag.prerelease, + tag < VERSION ? tag.build : field, + ) + end + + isotime = strftime("%Y-%m-%d %H:%M:%S", ctim) + global const commit_string = "Commit $commit $isotime" * (dirty ? "*" : "") + global const VERSION_COMMIT = commit + error(expected) + end + end + try + run_event_loop() # equivalent to wait_exit() on a more sane version of the previous + # block of code, but Scheduler doesn't exist during bootstrapping + # so we do what we must, but don't do this in user-land code or you'll regret it + catch err + if err != expected + global const commit_string = "" + global const VERSION_COMMIT = "" + if err == acceptable + println("Warning: git failed in version.jl") + #println(err) # not a useful error msg currently + else + rethrow(err) + end + end end - clean = success(`git diff --quiet HEAD`) - if !clean; push(VERSION.build, "dirty"); end - clean = clean ? "" : "*" - isotime = strftime("%Y-%m-%d %H:%M:%S", ctim) - global const _jl_commit_string = "Commit $(commit[1:10]) ($isotime)$clean" - global const VERSION_COMMIT = commit[1:10] -catch - global const _jl_commit_string = "" - global const VERSION_COMMIT = "" end - +end begin -const _jl_version_string = "Version $VERSION" -const _jl_banner_plain = -I" _ +const version_string = "Version $VERSION" +const banner_plain = +""" + _ _ _ _(_)_ | A fresh approach to technical computing (_) | (_) (_) | Documentation: http://docs.julialang.org - _ _ _| |_ __ _ | Type \"help()\" to list help topics + _ _ _| |_ __ _ | Type "help()" to list help topics | | | | | | |/ _` | | - | | |_| | | | (_| | | $_jl_version_string - _/ |\__'_|_|_|\__'_| | $_jl_commit_string + | | |_| | | | (_| | | $version_string + _/ |\\__'_|_|_|\\__'_| | $commit_string |__/ | -" +""" local tx = "\033[0m\033[1m" # text local jl = "\033[0m\033[1m" # julia local d1 = "\033[34m" # first dot local d2 = "\033[31m" # second dot local d3 = "\033[32m" # third dot local d4 = "\033[35m" # fourth dot -const _jl_banner_color = +const banner_color = "\033[1m $(d3)_ $(d1)_ $(jl)_$(tx) $(d2)_$(d3)(_)$(d4)_$(tx) | A fresh approach to technical computing $(d1)(_)$(jl) | $(d2)(_)$(tx) $(d4)(_)$(tx) | Documentation: http://docs.julialang.org $(jl)_ _ _| |_ __ _$(tx) | Type \"help()\" to list help topics $(jl)| | | | | | |/ _` |$(tx) | - $(jl)| | |_| | | | (_| |$(tx) | $_jl_version_string - $(jl)_/ |\\__'_|_|_|\\__'_|$(tx) | $_jl_commit_string + $(jl)| | |_| | | | (_| |$(tx) | $version_string + $(jl)_/ |\\__'_|_|_|\\__'_|$(tx) | $commit_string $(jl)|__/$(tx) | \033[0m" diff --git a/contrib/Julia.tmbundle/.gitignore b/contrib/Julia.tmbundle/.gitignore new file mode 100644 index 0000000000000..c3ed10e928961 --- /dev/null +++ b/contrib/Julia.tmbundle/.gitignore @@ -0,0 +1 @@ +*.cache diff --git a/contrib/Julia.tmbundle/Syntaxes/Julia.tmLanguage b/contrib/Julia.tmbundle/Syntaxes/Julia.tmLanguage index 63ad5c9e128b5..a62cfc888af50 100644 --- a/contrib/Julia.tmbundle/Syntaxes/Julia.tmLanguage +++ b/contrib/Julia.tmbundle/Syntaxes/Julia.tmLanguage @@ -1,18 +1,18 @@ + fileTypes - j jl - jul - julia firstLineMatch - ^#!/usr/bin/env\s+julia\s*$ + ^#!.*\bjulia\s*$ foldingStartMarker - ^\s*(?:if|while|for|begin|function|macro|module|type|let)\b(?!.*\bend\b).*$ + ^\s*(?:if|while|for|begin|function|macro|module|baremodule|type|immutable|let)\b(?!.*\bend\b).*$ foldingStopMarker ^\s*(?:end)\b.*$ name @@ -92,7 +92,7 @@ begin - ([a-zA-Z0-9_]+)\w*\( + ([a-zA-Z0-9_]+!?)\w*\( beginCaptures 1 @@ -127,7 +127,7 @@ begin - (function)\w*([a-zA-Z0-9_]+)\w*\( + (function|macro)\s*([a-zA-Z0-9_\{]+!?)\w*([(\\{]) beginCaptures 1 @@ -142,7 +142,7 @@ end - \) + ([)\\}]) name meta.function.julia patterns @@ -161,37 +161,19 @@ match - \b(Any|Function|None|Range1?|NDRange|Tuple|Real|Vector|Array|AbstractArray|ObjectIdDict|Dict|WeakKeyDict|EnvHash|LineIterator|String|IntSet|FDSet|Set|Task|ASCIIString|UTF8String|Bool|Int(8|16|32|64)?|Uint(8|16|32|64)?|Float(32|64)?|Complex(64|128)|true|false?)\b - name - support.type.julia - - - match - \b(std(out|err|in)_stream)\b - name - support.constant.julia - - - match - \b(?:exit|whos|edit|load|isa?|is(equal|less)|typeof|n?tuple|uid|hash|finalizer|co(py|nvert)|promote|sub|type(min|max)|real(min|max)|sizeof|eps|promote_type|method_exists|applicable|invoke|start|done|next|isempty|numel|length|contains|reduce|m(ax|in)|sum|prod|anyp?|allp?|countp?|map|ref|assign|has|get|d(el|el_all)|add|intset|choose|union|p(ush|op)|enqueue|shift|insert|del|grow|append!?|str(len|cat|ing|chr)|cstring|(l|r)pad|split|join|ch(op|omp)|ind2chr|chr2ind|open|memio|fdio|flush|close|with_output_stream|write|read|position|s(eek|kip)|current_output_stream|set_current_output_stream|show(all)?|print(ln)?|dump|read(all|line|until|lines)|each_line|dlm(read|write)|csv(read|write)|div|fld|mod|sinc?|cosc?|sinh?|cosh?|tanh?|a(sin|cos|tan|tan2)|sech?|c(sc|ot)h?|a(cos|sin|tan|sec|csc|cot)h?|hypot|log|log2|log10|log1p|logb|ilobg|exp2?|expm1|ldexp|ceil|floor|trunc|round|i(ceil|floor|trunc|round|part)|fpart|m(in|ax)|clamp|abs2?|copysign|sign|signbit|pow|sqrt|cbrt|erfc?|gamma|lgamma|lfact|bessel(j0|j1|y1|y0)|real|imag|conj|angle|cis|binomial|factorial|gcd|lcm|nextpow2|powermod|eps|bin|hex|dec|oct|int2str|parse_int|bool|u?int(8|16|32|64)|float(32|64)|char|safe_char|complex|is(complex|real)|bswap|num2hex|hex2num|one|zero|is(denormal|finite|nan)|nextfloat|prevfloat|integer_valued|real_valued|exponent|mantissa|rand(f|i|bit|bool|n|g|chi2|exp)|srand|ndimds|size|eltype|numel|nnz|strides?|ref|cell|zeros|ones|trues|falses|fill!?|reshape|copy|similar|empty|reinterpret|eye|linspace|sub|slicedim|assign|cat|vcat|hcat|hvcat|flip(dim|pud|plr)|circshift|findn?|i?permute|squeeze|dot|cross|norm|chol|lu|qr|eig|svd|tri(u|l)|diagm?|rank|cond|trace|det|inv|repmat|kron|linreg|sort(r|perm)?!?|issorted|nthperm!?|rand(perm|cycle)|shuffle!?|reverse!?|select!?|mean|std|median|histc?|i?fft(2|3|n|shift)|deconv|conv|xcorr|addprocs_(local|ssh|sge)|nprocs|myid|remote_call|wait|fetch|remote_call_(wait|fetch)|put|take|d(array|zeros|ones|fill|randn?|cell|istribute)|localize|changedist|myindexes|owner|procs|distdim|system|get(hostname|ipaddr|cwd|pid)|setcwd|t(ime|ic|oc|oq)|dl(open|sym)|error|throw|strerror|assert|yieldto|current_task|istaskdone|consume|produce|make_scheduled|yield|tls)\b - name - support.function.julia - - - match - \b(?:function|type|macro|quote|abstract|bitstype|typealias|module|new)\b + \b(?:function|type|immutable|macro|quote|abstract|bitstype|typealias|module|baremodule|new)\b name keyword.other.julia match - \b(?:if|else|elseif|while|for|in|begin|let|end|do|try|catch|return|break|continue)\b + \b(?:if|else|elseif|while|for|in|begin|let|end|do|try|catch|finally|return|break|continue)\b name keyword.control.julia match - \b(?:global|local|const|export|import|using)\b + \b(?:global|local|const|export|import|importall|using)\b name storage.modifier.variable.julia @@ -199,7 +181,7 @@ match @\w+\b name - support.macro.julia + variable.macro.julia @@ -209,7 +191,7 @@ match - ((\b0(x|X)[0-9a-fA-F]*)|((\b[0-9]+\.?[0-9]*)|(\.[0-9]+))((e|E)(\+|-)?[0-9]*)?(im)?|\bInf(32)?\b|\bNaN(32)?\b) + ((\b0(x|X)[0-9a-fA-F]*)|((\b[0-9]+\.?[0-9]*)|(\.[0-9]+))((e|E)(\+|-)?[0-9]*)?(im)?|\bInf(32)?\b|\bNaN(32)?\b|\btrue\b|\bfalse\b) name constant.numeric.julia @@ -285,6 +267,12 @@ name keyword.operator.dots.julia + + match + (?:\$(?=.+)) + name + keyword.operator.interpolation.julia + captures @@ -306,7 +294,7 @@ begin \[ end - \)((?:'|(?:\.'))*\.?') + \]((?:'|(?:\.'))*\.?') endCaptures 1 @@ -467,7 +455,7 @@ name - string.quoted.double.julia + string.quoted.backtick.julia patterns @@ -531,7 +519,7 @@ match - (type)\s+([a-zA-Z0-9_]+)(\s*(<:)\s*[.a-zA-Z0-9_:]+)? + (type|immutable)\s+([a-zA-Z0-9_]+)(\s*(<:)\s*[.a-zA-Z0-9_:]+)? name meta.type.julia @@ -547,7 +535,7 @@ comments Matches a typed variable, such as 'id::String' match - ([a-zA-Z0-9_]+)(::[a-zA-Z0-9_]+) + ([a-zA-Z0-9_]+)(::[a-zA-Z0-9_{}]+) name other.typed-variable.julia diff --git a/contrib/Julia_Notepad++.xml b/contrib/Julia_Notepad++.xml new file mode 100644 index 0000000000000..c040cde3d58af --- /dev/null +++ b/contrib/Julia_Notepad++.xml @@ -0,0 +1,29 @@ + + + + + + + + 00# + ' - ! " $ % & * , . / : ; ? @ \ ^ ` | ~ + < = > <: :: .+ .- .* ./ .\ .^ && || // [ ] ( ) { } + begin do for function if immutable let quote try type while + elseif else + end + "00"00 + abstract bitstype break ccall const continue export global import importall in local macro module baremodule return typealias using + AbstractArray AbstractMatrix AbstractSparseMatrix AbstractVector Any Array ASCIIString Associative AsyncStream BitArray BigFloat BigInt BitMatrix BitVector Bool ByteString Char CharString Colon Complex Complex64 Complex128 ComplexPair DArray Dict Dims EachLine EnvHash Exception Expr FileOffset Filter Float Float32 Float64 Function ObjectIdDict Int Int8 Int16 Int32 Int64 Int128 Integer IntSet ImaginaryUnit IO IOBuffer IOStream LocalProcess Matrix Nothing None NTuple Number ObjectIdDict OrdinalRange PipeBuffer ProcessGroup Ptr Range Range1 RangeIndex Ranges Rational Real Regex RegexMatch RegexMatchIterator RemoteRef RepString RevString Reverse RopeString Set Signed SparseMatrixCSC SpawnNullStream StridedArray StridedMatrix StridedVecOrMat StridedVector String SubArray SubDArray SubOrDArray SubString Symbol SymTridiagonal Task TcpSocket Tridiagonal Tuple Type Uint Uint8 Uint16 Uint32 Uint64 Uint128 Union Unsigned UTF8String UVError VecOrMat Vector VersionNumber Void WeakKeyDict WeakRef Woodbury Zip Stat Factorization BunchKaufman CholeskyDense CholeskyPivotedDense LUDense LUTridiagonal LDLTTridiagonal QRDense QRPivotedDense SVDDense GSVDDense InsertionSort QuickSort MergeSort TimSort Cchar Cuchar Cshort Cushort Cint Cuint Clong Culong Cptrdiff_t Csize_t Clonglong Culonglong Cfloat Cdouble ArgumentError DisconnectException EOFError ErrorException KeyError LoadError MethodError ParseError SystemError TypeError + + + + + + + + + + + + + + diff --git a/contrib/Notepad++_2_Julia.ahk b/contrib/Notepad++_2_Julia.ahk new file mode 100644 index 0000000000000..4603a81b33eea --- /dev/null +++ b/contrib/Notepad++_2_Julia.ahk @@ -0,0 +1,74 @@ +global hasRunJulia = 0 +global JuliaPID = 0 +global NppPID = 0 + +OpenJulia() +{ + if %hasRunJulia% = 0 + { + Run julia.bat,,,JuliaPID + hasRunJulia = 1 + ReturnToNpp() + return + } + Process, Exist, %JuliaPID% + if %ErrorLevel% = 0 + { + Run julia.bat,,,JuliaPID + hasRunJulia = 1 + ReturnToNpp() + return + } +} + +ReOpenJulia() +{ + WinClose, ahk_pid %JuliaPID% + OpenJulia() +} + +SendToJulia() +{ + OpenJulia() + WinWait, ahk_pid %JuliaPID% + WinActivate, ahk_pid %JuliaPID% + WinWaitActive, ahk_pid %JuliaPID% + Send {Alt Down}{Space}{Alt up}ep{Enter} +} + +ReturnToNpp() +{ + WinActivate, ahk_pid %NppPID% +} + + +PassLine() +{ + WinGetCLASS, currentClass, A + If currentClass = Notepad++ + { + WinGet, NppPID, PID, A + send {Home}{Shift Down}{End}{Shift Up}{Ctrl Down}c{Ctrl Up}{End} + SendToJulia() + ReturnToNpp() + } +} + +PassBlock() +{ + WinGetCLASS, currentClass, A + If currentClass = Notepad++ + { + WinGet, NppPID, PID, A + send {Ctrl Down}c{Ctrl Up} + SendToJulia() + ReturnToNpp() + } +} + + +LShift & Enter:: PassLine() + +Ctrl & d:: PassBlock() + +$F3:: ReOpenJulia() diff --git a/contrib/ctags b/contrib/ctags new file mode 100644 index 0000000000000..5e119f1dfbae8 --- /dev/null +++ b/contrib/ctags @@ -0,0 +1,4 @@ +--langdef=julia +--langmap=julia:.jl +--regex-julia=/^[ \t]*function[ \t]+([^ \t({[]+).*$/\1/f,function/ +--regex-julia=/^[ \t]*(([^@#$ \t({[]+)|\(([^@#$ \t({[]+)\)|\((\$)\))[ \t]*(\{.*\})?[ \t]*\([^#]*\)[ \t]*=([^=].*$|$)/\2\3\4/f,function/ diff --git a/contrib/julia-mode.el b/contrib/julia-mode.el index e4d7789402804..3e6932e72f730 100644 --- a/contrib/julia-mode.el +++ b/contrib/julia-mode.el @@ -60,7 +60,7 @@ "for +.*[^ ].* \\(in\\)\\(\\s-\\|$\\)+") (defconst julia-font-lock-keywords - (list '("\\<\\(\\|Uint\\(8\\|16\\|32\\|64\\|128\\)\\|Int\\(8\\|16\\|32\\|64\\|128\\)\\|Integer\\|Float\\|Float32\\|Float64\\|Complex128\\|Complex64\\|ComplexPair\\|Bool\\|Char\\|Number\\|Real\\|Int\\|Uint\\|Array\\|DArray\\|AbstractArray\\|AbstractVector\\|AbstractMatrix\\|AbstractSparseMatrix\\|SubArray\\|StridedArray\\|StridedVector\\|StridedMatrix\\|VecOrMat\\|StridedVecOrMat\\|Range\\|Range1\\|SparseMatrixCSC\\|Tuple\\|NTuple\\|Symbol\\|Function\\|Vector\\|Matrix\\|Union\\|Type\\|Any\\|Complex\\|None\\|String\\|Ptr\\|Void\\|Exception\\|Task\\|Signed\\|Unsigned\\|Associative\\|Dict\\|IO\\|IOStream\\|Ranges\\|Rational\\|Regex\\|RegexMatch\\|Set\\|IntSet\\|ASCIIString\\|UTF8String\\|ByteString\\|Expr\\|WeakRef\\|Nothing\\|ObjectIdDict\\|SubString\\)\\>" . + (list '("\\<\\(\\|Uint\\(8\\|16\\|32\\|64\\|128\\)\\|Int\\(8\\|16\\|32\\|64\\|128\\)\\|Integer\\|FloatingPoint\\|Float32\\|Float64\\|Complex128\\|Complex64\\|ComplexPair\\|Bool\\|Char\\|Number\\|Real\\|Int\\|Uint\\|Array\\|DArray\\|AbstractArray\\|AbstractVector\\|AbstractMatrix\\|AbstractSparseMatrix\\|SubArray\\|StridedArray\\|StridedVector\\|StridedMatrix\\|VecOrMat\\|StridedVecOrMat\\|Range\\|Range1\\|SparseMatrixCSC\\|Tuple\\|NTuple\\|Symbol\\|Function\\|Vector\\|Matrix\\|Union\\|Type\\|Any\\|Complex\\|None\\|String\\|Ptr\\|Void\\|Exception\\|Task\\|Signed\\|Unsigned\\|Associative\\|Dict\\|IO\\|IOStream\\|Ranges\\|Rational\\|Regex\\|RegexMatch\\|Set\\|IntSet\\|ASCIIString\\|UTF8String\\|ByteString\\|Expr\\|WeakRef\\|Nothing\\|ObjectIdDict\\|SubString\\)\\>" . font-lock-type-face) (cons (concat "\\<\\(" @@ -70,7 +70,7 @@ "try" "catch" "return" "local" "abstract" "function" "macro" "ccall" "finally" "typealias" "break" "continue" "type" "global" "@\\w+" "module" "using" "import" "export" "const" "let" "bitstype" "do" - "baremodule" "importall") + "baremodule" "importall" "immutable") "\\|") "\\)\\>") 'font-lock-keyword-face) '("\\<\\(true\\|false\\|C_NULL\\|Inf\\|NaN\\|Inf32\\|NaN32\\|nothing\\)\\>" . font-lock-constant-face) @@ -82,7 +82,7 @@ (defconst julia-block-start-keywords (list "if" "while" "for" "begin" "try" "function" "type" "let" "macro" - "quote" "do")) + "quote" "do" "immutable")) (defconst julia-block-other-keywords (list "else" "elseif")) @@ -113,8 +113,6 @@ (defun julia-in-comment () (save-excursion - (end-of-line) - (backward-char 1) (julia-find-comment-open (line-beginning-position)))) (defun julia-strcount (str chr) diff --git a/contrib/julia.xml b/contrib/julia.xml index 311d4df57d8b0..a80447e1400a4 100644 --- a/contrib/julia.xml +++ b/contrib/julia.xml @@ -38,6 +38,7 @@ for function if + immutable let quote try @@ -71,26 +72,41 @@ baremodule return typealias + using AbstractArray AbstractMatrix + AbstractSparseMatrix AbstractVector Any Array ASCIIString Associative + AsyncStream + BitArray + BigFloat + BigInt + BitMatrix + BitVector Bool ByteString Char + CharString + Colon Complex Complex64 Complex128 ComplexPair DArray Dict + Dims + EachLine + EnvHash Exception Expr + FileOffset + Filter Float Float32 Float64 @@ -104,32 +120,53 @@ Int128 Integer IntSet + ImaginaryUnit IO + IOBuffer IOStream + LocalProcess Matrix Nothing None NTuple Number + ObjectIdDict + OrdinalRange + PipeBuffer + ProcessGroup Ptr Range Range1 + RangeIndex Ranges Rational Real Regex RegexMatch + RegexMatchIterator + RemoteRef + RepString + RevString + Reverse + RopeString Set Signed + SparseMatrixCSC + SpawnNullStream StridedArray StridedMatrix StridedVecOrMat StridedVector String SubArray + SubDArray + SubOrDArray SubString Symbol + SymTridiagonal Task + TcpSocket + Tridiagonal Tuple Type Uint @@ -141,10 +178,58 @@ Union Unsigned UTF8String + UVError VecOrMat Vector + VersionNumber Void + WeakKeyDict WeakRef + Woodbury + Zip + + Stat + Factorization + BunchKaufman + CholeskyDense + CholeskyPivotedDense + LUDense + LUTridiagonal + LDLTTridiagonal + QRDense + QRPivotedDense + SVDDense + GSVDDense + InsertionSort + QuickSort + MergeSort + TimSort + + Cchar + Cuchar + Cshort + Cushort + Cint + Cuint + Clong + Culong + Cptrdiff_t + Csize_t + Clonglong + Culonglong + Cfloat + Cdouble + + ArgumentError + DisconnectException + EOFError + ErrorException + KeyError + LoadError + MethodError + ParseError + SystemError + TypeError diff --git a/contrib/mac/app/.gitignore b/contrib/mac/app/.gitignore new file mode 100644 index 0000000000000..a89e5842a7fc3 --- /dev/null +++ b/contrib/mac/app/.gitignore @@ -0,0 +1,4 @@ +julia/ +Julia.app/ +*.dmg +julia.dmgCreator_build diff --git a/contrib/mac/app/Julia.dmged b/contrib/mac/app/Julia.dmged new file mode 100644 index 0000000000000..6016cf0faeb17 --- /dev/null +++ b/contrib/mac/app/Julia.dmged @@ -0,0 +1,154 @@ + + + + + + 134481920 + ED35BFF7-291A-4951-A7A5-40FB31286B28 + 118 + + + + NSPersistenceFrameworkVersion + 358 + NSStoreModelVersionHashes + + EULA + + sTAmkNX2hStMmlIuR8HmP79LxC9LuZvIymoobZFCMzU= + + EulaLocalization + + x4twSWb2rUS0yS13ryN+/DiJE5nutTutkRXlu5ZHtlI= + + ReleaseFile + + qJlS4UG9f0rCEd0Q4xIi7PXvnBCFelJqH0ealF3yFiQ= + + Setting + + 3mFXwDdwRACxvI5tqb/clEUFRXDuGqIRutmiI4lYcJU= + + + NSStoreModelVersionHashesVersion + 3 + NSStoreModelVersionIdentifiers + + + + + + + 0 + 5 + Dutch + + + + 0 + 4 + Italian + + + + 1 + 53 + Traditional Chinese + + + + 0 + 7 + Swedish + + + + 0 + 3 + German + + + + 0 + 17 + Finnish + + + + 1 + 14 + Japanese + + + + 0 + 1 + French + + + + 0 + 71 + Brasilian Portuguese + + + + /Users/viral/julia/contrib/mac-app/Julia.app + + + + 0 + 11 + Canadian French + + + + AAAAAUJ1ZDEAABAAAAAIAAAAEAAAAAQKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAIAAAAAAAA +AAAAAAAAAAAAAAAAAAACAAAAAAAAAAUAAAABAAAQAG9iAAAArmJwbGlzdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAEALmJ3c3BibG9iAAAArmJwbGlzdDAw1gECAwQFBgcICAgIDFxXaW5kb3dCb3VuZHNbU2hvd1NpZGViYXJdU2hvd1N0YXR1c0JhcltTaG93UGF0aGJhcltTaG93VG9vbGJhclxTaWRlYmFyV2lkdGhfEBd7ezE1LCA2NDB9LCB7MzE2LCAyMjJ9fQgICAgQAAgVIi48SFRhe3x9fn8AAAAAAAABAQAAAAAAAAANAAAAAAAAAAAAAAAAAAAAgQAAAAEALmljdnBibG9iAAABomJwbGlzdDAw3gECAwQFBgcICQoLDA0ODxAREhMUFRYXExAZGhtfEBNiYWNrZ3JvdW5kQ29sb3JCbHVlXxAPc2hvd0ljb25QcmV2aWV3WHRleHRTaXplXxASYmFja2dyb3VuZENvbG9yUmVkXmJhY2tncm91bmRUeXBlXxAUYmFja2dyb3VuZENvbG9yR3JlZW5bZ3JpZE9mZnNldFhbZ3JpZE9mZnNldFlcc2hvd0l0ZW1JbmZvXxASdmlld09wdGlvbnNWZXJzaW9uXWxhYmVsT25Cb3R0b21ZYXJyYW5nZUJ5WGljb25TaXplW2dyaWRTcGFjaW5nIz/wAAAAAAAACSNAKAAAAAAAACM/8AAAAAAAABAAIz/wAAAAAAAAIwAAAAAAAAAAIwAAAAAAAAAACAlUbm9uZSNASAAAAAAAACNAWQAAAAAAAAAIACUAOwBNAFYAawB6AJEAnQCpALYAywDZAOMA7AD4AQEBAgELARQBFgEfASgBMQEyATMBOAFBAAAAAAAAAgEAAAAAAAAAHAAAAAAAAAAAAAAAAAAAAUoAAAABAC52U3JubG9uZwAAAAEAAAAMAEEAcABwAGwAaQBjAGEAdABpAG8AbgBzSWxvY2Jsb2IAAAAQAAAAXAAAAB////////8AAAAAAAkASgB1AGwAaQBhAC4AYQBwAHBJbG9jYmxvYgAAABAAAABcAAAAfP///////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAgLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAACAAAAABAAAAQAAAAAEAAACAAAAAAQAAAQAAAAABAAACAAAAAAEAAAQAAAAAAAAAAAEAABAAAAAAAQAAIAAAAAABAABAAAAAAAEAAIAAAAAAAQABAAAAAAABAAIAAAAAAAEABAAAAAAAAQAIAAAAAAABABAAAAAAAAEAIAAAAAAAAQBAAAAAAAABAIAAAAAAAAEBAAAAAAAAAQIAAAAAAAABBAAAAAAAAAEIAAAAAAAAARAAAAAAAAABIAAAAAAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAEAsAAABFAAAECgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBERTREIAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAIAAAAGAAAAAAAAAAAQAAAIAAAAABAAABAAAAAAEAAAIAAAAAAAAAAAIAAAgAAAAYAAAAAAAAAAABAAAgAAAAAAEAAEAAAAAAAQAAgAAAAAABAAEAAAAAAAEAAgAAAAAAAQAEAAAAAAABAAgAAAAAAAEAEAAAAAAAAQAgAAAAAAABAEAAAAAAAAEAgAAAAAAAAQEAAAAAAAABAgAAAAAAAAEEAAAAAAAAAQgAAAAAAAABEAAAAAAAAAEgAAAAAAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== + + 0 + 0 + NO + 12 + 1 + 48 + Julia + Julia-0.1 + /Users/viral/julia/contrib/mac-app + 1 + /Users/viral/julia/contrib/mac-app/julia.dmgCreator_build + 1 + + + + + 0 + 32 + Danish + + + + 1 + 52 + Simplified Chinese + + + + 0 + 8 + Spanish + + + + 1 + 51 + Korean + + + + 0 + 0 + English + + + \ No newline at end of file diff --git a/contrib/mac/app/Julia.platypus b/contrib/mac/app/Julia.platypus new file mode 100644 index 0000000000000..2e86ea92ecbd8 --- /dev/null +++ b/contrib/mac/app/Julia.platypus @@ -0,0 +1,92 @@ + + + + + AcceptsFiles + + AcceptsText + + Authentication + + Author + The Julia Project + BundledFiles + + /Users/viral/julia/contrib/mac-app/julia + + Creator + Platypus-4.7 + DeclareService + + Destination + /Users/viral/Desktop/MyPlatypusApp.app + DestinationOverride + + DevelopmentVersion + + DocIcon + + Droppable + + ExecutablePath + /usr/local/share/platypus/ScriptExec + FileTypes + + **** + fold + + IconPath + /Users/viral/julia/contrib/mac-app/julia.icns + Identifier + org.julialang.Julia + Interpreter + /bin/sh + InterpreterArgs + + Name + Julia + NibPath + /usr/local/share/platypus/MainMenu.nib + OptimizeApplication + + Output + None + RemainRunning + + Role + Viewer + ScriptArgs + + ScriptPath + /Users/viral/julia/contrib/mac-app/script + Secure + + ShowInDock + + StatusItemDisplayType + Text + StatusItemIcon + + + StatusItemTitle + MyPlatypusApp + Suffixes + + * + + TextBackground + #ffffff + TextEncoding + 4 + TextFont + Monaco + TextForeground + #000000 + TextSize + 10 + UseXMLPlistFormat + + Version + 0.1 + + diff --git a/contrib/mac/app/Makefile b/contrib/mac/app/Makefile new file mode 100644 index 0000000000000..e6ebd91bcfd1a --- /dev/null +++ b/contrib/mac/app/Makefile @@ -0,0 +1,23 @@ +# Make sure that you are building openblas with OPENBLAS_DYNAMIC_ARCH=1 +# You may have to wipe your openblas build to ensure that it is built +# with support for all architectures, or else performance may suffer. + +all: clean copyfiles rewritepaths + +copyfiles: + make -C ../.. dist + tar zxf ../../julia-*.tar.gz + mv julia-* julia + cp -a ~/.julia/Cairo/deps/usr/* ./julia/ + cp -a ~/.julia/Tk/deps/usr/* ./julia/ + rm -f julia/lib/*.{a,la} + chmod a+w julia/lib/*.dylib + mkdir julia.dmgCreator_build + +rewritepaths: + (for lib in julia/lib/*.dylib; do ./run-install-name-tool-change.sh $$lib $$HOME/.julia/Cairo/deps/usr/lib/ lib/ change; done) + (for lib in julia/lib/*.dylib; do ./run-install-name-tool-change.sh $$lib $$HOME/.julia/Tk/deps/usr/lib/ lib/ change; done) + (cd julia/lib && for lib in *.dylib; do install_name_tool -id @executable_path/../lib/$$lib $$lib; done) + +clean: + rm -fr julia *.app julia.dmgCreator_build *.dmg diff --git a/contrib/mac/app/README b/contrib/mac/app/README new file mode 100644 index 0000000000000..c8b7b024a3855 --- /dev/null +++ b/contrib/mac/app/README @@ -0,0 +1,9 @@ +To build the Julia.app OS X application bundle: + +1. First install Winston, and compile all the relevant libraries with Pkg.add("Winston"). The libraries are copied from ~/.julia/{Cairo,Tk} in here. +2. Run `make` here to create a self-sufficient julia distribution with Cairo and Tk. +3. Update the Julia.platypus profile file to reflect your local paths +4. Use Platypus (http://sveinbjorn.org/platypus) using the `Julia.platypus` profile to create the app bundle. +5. Use dmgCreator (http://dmgcreator.sourceforge.net) with `Julia.dmged` to create the dmg file. + +The `julia.icns` file provides the Julia icon, and the `script` file launches julia in a terminal. diff --git a/contrib/mac/app/julia.icns b/contrib/mac/app/julia.icns new file mode 100644 index 0000000000000..691f1be5d1cfa Binary files /dev/null and b/contrib/mac/app/julia.icns differ diff --git a/contrib/mac/app/run-install-name-tool-change.sh b/contrib/mac/app/run-install-name-tool-change.sh new file mode 100755 index 0000000000000..3a3b6a88118d5 --- /dev/null +++ b/contrib/mac/app/run-install-name-tool-change.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +if [ $# -lt 3 ]; then + echo "Usage: $0 library old_prefix new_prefix action" + exit 1 +fi + +LIBRARY=$1 +WRONG_PREFIX=$2 +RIGHT_PREFIX="@executable_path/../$3" +ACTION=$4 + +if [ "x$ACTION" == "xchange" ]; then + libs="`otool -L $LIBRARY 2>/dev/null | fgrep compatibility | cut -d\( -f1 | grep $WRONG_PREFIX | sort | uniq`" + for lib in $libs; do + if ! echo $lib | grep --silent "@executable_path" ; then + fixed=`echo $lib | sed -e s,\$WRONG_PREFIX,\$RIGHT_PREFIX,` + install_name_tool -change $lib $fixed $LIBRARY + fi + done; +elif [ "x$ACTION" == "xid" ]; then + lib="`otool -D $LIBRARY 2>/dev/null | grep ^$WRONG_PREFIX`" + install_name_tool -id "$RIGHT_PREFIX/$lib" $LIBRARY; +fi + diff --git a/contrib/mac/app/script b/contrib/mac/app/script new file mode 100755 index 0000000000000..18832f598d956 --- /dev/null +++ b/contrib/mac/app/script @@ -0,0 +1,45 @@ +#!/bin/sh +# Copyright (C) 2007, Thomas Treichl and Paul Kienzle +# Copyright (C) 2008-2009, Thomas Treichl +# Copyright (C) 2013, Viral B. Shah (Adapted for Julia from Octave) +# +# This program is free software; you can 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 . + +ROOT="${0%/script}" + +# This is the startup procedure written as AppleScript to open a +# Terminal.app (if the Terminal.app is not already running) and start +# the Julia program. +# 20071007 removed: open -a /Applications/Utilities/Terminal.app +osascript 2>&1>/dev/null <&1>/dev/null <> .jhbuildrc-custom +setup_sdk(target=_target, sdk_version=_target, architectures=[_default_arch]) +os.environ["DYLD_LIBRARY_PATH"] = "" +build_policy = "updated-deps" +modules = [ "meta-gtk-osx-bootstrap", + "freetype", "fontconfig", + "meta-gtk-osx-core", + "meta-gtk-osx-themes", + "gtk-quartz-engine" ] +EOF + +jhbuild bootstrap --skip=libiconv --ignore-system +jhbuild build + +cd ~/gtk/source +curl -O http://ftp.gnome.org/pub/gnome/sources/gtk-mac-bundler/0.6/gtk-mac-bundler-0.6.1.tar.bz2 +tar jxvf gtk-mac-bundler-0.6.1.tar.bz2 +cd gtk-mac-bundler-0.6.1 +make install +cd ~/gtk + + diff --git a/contrib/macports.make b/contrib/mac/macports.make similarity index 100% rename from contrib/macports.make rename to contrib/mac/macports.make diff --git a/contrib/repackage_system_suitesparse3.make b/contrib/repackage_system_suitesparse3.make index 1b1cb16cb1518..155fd01eb574b 100755 --- a/contrib/repackage_system_suitesparse3.make +++ b/contrib/repackage_system_suitesparse3.make @@ -6,18 +6,18 @@ include $(JULIAHOME)/Make.inc all: default default: - mkdir -p $(USR)/$(JL_LIBDIR) + mkdir -p $(BUILD)/$(JL_LIBDIR) mkdir -p $(JULIAHOME)/deps/SuiteSparse-SYSTEM/lib cd $(JULIAHOME)/deps/SuiteSparse-SYSTEM/lib && \ rm -f *.a && \ cp -f $(shell find /lib /usr/lib /usr/local/lib $(shell eval $(JULIAHOME)/contrib/filterArgs.sh $(LDFLAGS)) -name libamd.a -o -name libcolamd.a -o -name libcholmod.a -o -name libumfpack.a -o -name libspqr.a 2>/dev/null) . && \ - $(CC) -shared $(WHOLE_ARCHIVE) libamd.a $(NO_WHOLE_ARCHIVE) -o $(USR)/$(JL_LIBDIR)/libamd.$(SHLIB_EXT) && \ - $(INSTALL_NAME_CMD)libamd.$(SHLIB_EXT) $(USR)/$(JL_LIBDIR)/libamd.$(SHLIB_EXT) && \ - $(CC) -shared $(WHOLE_ARCHIVE) libcolamd.a $(NO_WHOLE_ARCHIVE) -o $(USR)/$(JL_LIBDIR)/libcolamd.$(SHLIB_EXT) && \ - $(INSTALL_NAME_CMD)libcolamd.$(SHLIB_EXT) $(USR)/$(JL_LIBDIR)/libcolamd.$(SHLIB_EXT) && \ - $(CXX) -shared $(WHOLE_ARCHIVE) libcholmod.a $(NO_WHOLE_ARCHIVE) -o $(USR)/$(JL_LIBDIR)/libcholmod.$(SHLIB_EXT) $(LDFLAGS) -L$(USR)/$(JL_LIBDIR) -lcolamd -lamd $(LIBBLAS) && \ - $(INSTALL_NAME_CMD)libcholmod.$(SHLIB_EXT) $(USR)/$(JL_LIBDIR)/libcholmod.$(SHLIB_EXT) && \ - $(CXX) -shared $(WHOLE_ARCHIVE) libumfpack.a $(NO_WHOLE_ARCHIVE) -o $(USR)/$(JL_LIBDIR)/libumfpack.$(SHLIB_EXT) $(LDFLAGS) -L$(USR)/$(JL_LIBDIR) -lcholmod -lcolamd -lamd $(LIBBLAS) && \ - $(INSTALL_NAME_CMD)libumfpack.$(SHLIB_EXT) $(USR)/$(JL_LIBDIR)/libumfpack.$(SHLIB_EXT) && \ - $(CXX) -shared $(WHOLE_ARCHIVE) libspqr.a $(NO_WHOLE_ARCHIVE) -o $(USR)/$(JL_LIBDIR)/libspqr.$(SHLIB_EXT) $(LDFLAGS) -L$(USR)/$(JL_LIBDIR) -lcholmod -lcolamd -lamd $(LIBBLAS) && \ - $(INSTALL_NAME_CMD)libspqr.$(SHLIB_EXT) $(USR)/$(JL_LIBDIR)/libspqr.$(SHLIB_EXT) + $(CC) -shared $(WHOLE_ARCHIVE) libamd.a $(NO_WHOLE_ARCHIVE) -o $(BUILD)/$(JL_LIBDIR)/libamd.$(SHLIB_EXT) && \ + $(INSTALL_NAME_CMD)libamd.$(SHLIB_EXT) $(BUILD)/$(JL_LIBDIR)/libamd.$(SHLIB_EXT) && \ + $(CC) -shared $(WHOLE_ARCHIVE) libcolamd.a $(NO_WHOLE_ARCHIVE) -o $(BUILD)/$(JL_LIBDIR)/libcolamd.$(SHLIB_EXT) && \ + $(INSTALL_NAME_CMD)libcolamd.$(SHLIB_EXT) $(BUILD)/$(JL_LIBDIR)/libcolamd.$(SHLIB_EXT) && \ + $(CXX) -shared $(WHOLE_ARCHIVE) libcholmod.a $(NO_WHOLE_ARCHIVE) -o $(BUILD)/$(JL_LIBDIR)/libcholmod.$(SHLIB_EXT) $(LDFLAGS) -L$(BUILD)/$(JL_LIBDIR) -lcolamd -lamd $(LIBBLAS) && \ + $(INSTALL_NAME_CMD)libcholmod.$(SHLIB_EXT) $(BUILD)/$(JL_LIBDIR)/libcholmod.$(SHLIB_EXT) && \ + $(CXX) -shared $(WHOLE_ARCHIVE) libumfpack.a $(NO_WHOLE_ARCHIVE) -o $(BUILD)/$(JL_LIBDIR)/libumfpack.$(SHLIB_EXT) $(LDFLAGS) -L$(BUILD)/$(JL_LIBDIR) -lcholmod -lcolamd -lamd $(LIBBLAS) && \ + $(INSTALL_NAME_CMD)libumfpack.$(SHLIB_EXT) $(BUILD)/$(JL_LIBDIR)/libumfpack.$(SHLIB_EXT) && \ + $(CXX) -shared $(WHOLE_ARCHIVE) libspqr.a $(NO_WHOLE_ARCHIVE) -o $(BUILD)/$(JL_LIBDIR)/libspqr.$(SHLIB_EXT) $(LDFLAGS) -L$(BUILD)/$(JL_LIBDIR) -lcholmod -lcolamd -lamd $(LIBBLAS) && \ + $(INSTALL_NAME_CMD)libspqr.$(SHLIB_EXT) $(BUILD)/$(JL_LIBDIR)/libspqr.$(SHLIB_EXT) diff --git a/contrib/repackage_system_suitesparse4.make b/contrib/repackage_system_suitesparse4.make index 4d386e86c3ac8..4c5141680efd1 100755 --- a/contrib/repackage_system_suitesparse4.make +++ b/contrib/repackage_system_suitesparse4.make @@ -6,19 +6,19 @@ include $(JULIAHOME)/Make.inc all: default default: - mkdir -p $(USR)/$(JL_LIBDIR) + mkdir -p $(BUILD)/$(JL_LIBDIR) mkdir -p $(JULIAHOME)/deps/SuiteSparse-SYSTEM/lib cd $(JULIAHOME)/deps/SuiteSparse-SYSTEM/lib && \ rm -f *.a && \ cp -f $(shell find /lib /usr/lib /usr/local/lib $(shell eval $(JULIAHOME)/contrib/filterArgs.sh $(LDFLAGS)) -name libamd.a -o -name libcolamd.a -o -name libcholmod.a -o -name libumfpack.a -o -name libspqr.a -o -name libsuitesparseconfig.a 2>/dev/null) . && \ - $(CC) -shared $(WHOLE_ARCHIVE) libamd.a $(NO_WHOLE_ARCHIVE) -o $(USR)/$(JL_LIBDIR)/libamd.$(SHLIB_EXT) && \ - $(INSTALL_NAME_CMD)libamd.$(SHLIB_EXT) $(USR)/$(JL_LIBDIR)/libamd.$(SHLIB_EXT) && \ - $(CC) -shared $(WHOLE_ARCHIVE) libcolamd.a $(NO_WHOLE_ARCHIVE) -o $(USR)/$(JL_LIBDIR)/libcolamd.$(SHLIB_EXT) && \ - $(INSTALL_NAME_CMD)libcolamd.$(SHLIB_EXT) $(USR)/$(JL_LIBDIR)/libcolamd.$(SHLIB_EXT) && \ - $(CXX) -shared $(WHOLE_ARCHIVE) libsuitesparseconfig.a libcholmod.a $(NO_WHOLE_ARCHIVE) -o $(USR)/$(JL_LIBDIR)/libcholmod.$(SHLIB_EXT) $(LDFLAGS) -L$(USR)/$(JL_LIBDIR) -L. -lcolamd -lccolamd -lcamd -lamd $(LIBBLAS) $(RPATH_ORIGIN) && \ - $(INSTALL_NAME_CMD)libcholmod.$(SHLIB_EXT) $(USR)/$(JL_LIBDIR)/libcholmod.$(SHLIB_EXT) && \ - $(CXX) -shared $(WHOLE_ARCHIVE) libsuitesparseconfig.a libumfpack.a $(NO_WHOLE_ARCHIVE) -o $(USR)/$(JL_LIBDIR)/libumfpack.$(SHLIB_EXT) $(LDFLAGS) -L$(USR)/$(JL_LIBDIR) -L. -lcholmod -lcolamd -lcamd -lamd $(LIBBLAS) $(RPATH_ORIGIN) && \ - $(INSTALL_NAME_CMD)libumfpack.$(SHLIB_EXT) $(USR)/$(JL_LIBDIR)/libumfpack.$(SHLIB_EXT) && \ - $(CXX) -shared $(WHOLE_ARCHIVE) libsuitesparseconfig.a libspqr.a $(NO_WHOLE_ARCHIVE) -o $(USR)/$(JL_LIBDIR)/libspqr.$(SHLIB_EXT) $(LDFLAGS) -L$(USR)/$(JL_LIBDIR) -lcholmod -lcolamd -lamd $(LIBBLAS) $(RPATH_ORIGIN) && \ - $(INSTALL_NAME_CMD)libspqr.$(SHLIB_EXT) $(USR)/$(JL_LIBDIR)/libspqr.$(SHLIB_EXT) + $(CC) -shared $(WHOLE_ARCHIVE) libamd.a $(NO_WHOLE_ARCHIVE) -o $(BUILD)/$(JL_LIBDIR)/libamd.$(SHLIB_EXT) && \ + $(INSTALL_NAME_CMD)libamd.$(SHLIB_EXT) $(BUILD)/$(JL_LIBDIR)/libamd.$(SHLIB_EXT) && \ + $(CC) -shared $(WHOLE_ARCHIVE) libcolamd.a $(NO_WHOLE_ARCHIVE) -o $(BUILD)/$(JL_LIBDIR)/libcolamd.$(SHLIB_EXT) && \ + $(INSTALL_NAME_CMD)libcolamd.$(SHLIB_EXT) $(BUILD)/$(JL_LIBDIR)/libcolamd.$(SHLIB_EXT) && \ + $(CXX) -shared $(WHOLE_ARCHIVE) libsuitesparseconfig.a libcholmod.a $(NO_WHOLE_ARCHIVE) -o $(BUILD)/$(JL_LIBDIR)/libcholmod.$(SHLIB_EXT) $(LDFLAGS) -L$(BUILD)/$(JL_LIBDIR) -L. -lcolamd -lccolamd -lcamd -lamd $(LIBBLAS) $(RPATH_ORIGIN) && \ + $(INSTALL_NAME_CMD)libcholmod.$(SHLIB_EXT) $(BUILD)/$(JL_LIBDIR)/libcholmod.$(SHLIB_EXT) && \ + $(CXX) -shared $(WHOLE_ARCHIVE) libsuitesparseconfig.a libumfpack.a $(NO_WHOLE_ARCHIVE) -o $(BUILD)/$(JL_LIBDIR)/libumfpack.$(SHLIB_EXT) $(LDFLAGS) -L$(BUILD)/$(JL_LIBDIR) -L. -lcholmod -lcolamd -lcamd -lamd $(LIBBLAS) $(RPATH_ORIGIN) && \ + $(INSTALL_NAME_CMD)libumfpack.$(SHLIB_EXT) $(BUILD)/$(JL_LIBDIR)/libumfpack.$(SHLIB_EXT) && \ + $(CXX) -shared $(WHOLE_ARCHIVE) libsuitesparseconfig.a libspqr.a $(NO_WHOLE_ARCHIVE) -o $(BUILD)/$(JL_LIBDIR)/libspqr.$(SHLIB_EXT) $(LDFLAGS) -L$(BUILD)/$(JL_LIBDIR) -lcholmod -lcolamd -lamd $(LIBBLAS) $(RPATH_ORIGIN) && \ + $(INSTALL_NAME_CMD)libspqr.$(SHLIB_EXT) $(BUILD)/$(JL_LIBDIR)/libspqr.$(SHLIB_EXT) \ No newline at end of file diff --git a/contrib/run_bisect.sh b/contrib/run_bisect.sh deleted file mode 100755 index aa31a97ea65b0..0000000000000 --- a/contrib/run_bisect.sh +++ /dev/null @@ -1,13 +0,0 @@ -#! /bin/bash -# Instructions -# Create a .jl file that looks like this: -# function test() -# do some stuff, perhaps return a value -# end -# @assert test() == 5 # 5 is the correct answer if all is working -# exit() -# Then provide the name of that function after the "julia" call below -make clean # or cleanall if necessary -make -julia /tmp/test.jl -exit $? diff --git a/contrib/windows/julia.bat b/contrib/windows/julia.bat new file mode 100644 index 0000000000000..8c98dc0cb36e1 --- /dev/null +++ b/contrib/windows/julia.bat @@ -0,0 +1,14 @@ +@echo off +@rem +@rem This file is intended to simplify launching Julia on Windows. +@rem +@rem See prepare-julia-env.bat for more info + +pushd %cd% +setlocal enableextensions enabledelayedexpansion +call "%~dp0prepare-julia-env.bat" %* +call "%JULIA_HOME%julia-release-readline.exe" %* +endlocal +popd + +@echo on diff --git a/contrib/windows/prepare-julia-env.bat b/contrib/windows/prepare-julia-env.bat new file mode 100644 index 0000000000000..e9ec2e37f56df --- /dev/null +++ b/contrib/windows/prepare-julia-env.bat @@ -0,0 +1,19 @@ +@rem +@rem This file attempts to auto detect and configure the environment +@rem for starting julia and julia-web-server +@rem +@rem It sets the path as needed to reference various lib and bin +@rem files, and builds sys.ji if needed. +@rem + +set SYS_PATH=%PATH% +set PATH=%~dp0bin;%~dp0usr\bin;%~dp0..\usr\bin;%~dp0..\..\usr\bin;%SYS_PATH% +set JULIA_EXE=julia-release-readline.exe +for %%A in (%JULIA_EXE%) do set JULIA_HOME=%%~dp$PATH:A +set JULIA=%JULIA_HOME%%JULIA_EXE% +set PATH=%JULIA_HOME%;%JULIA_HOME%..\lib\julia;%JULIA_HOME%..\lib;.;%SYS_PATH%;%~dp0\Git\bin;C:\MinGW\msys\1.0\bin;C:\MinGW\bin;C:\Program Files\Git\bin;C:\Program Files (x86)\Git\bin;C:\Python27;C:\Python26;C:\Python25 +set HOME=%APPDATA%\julia +set JL_PRIVATE_LIBDIR=lib\julia +set JULIA_EDITOR=start + +if not exist "%JULIA_HOME%..\lib\julia\sys.ji" (echo "Preparing Julia for first launch. This may take a while" && echo "You may see two git related errors. This is completely normal" && cd "%JULIA_HOME%..\share\julia\base" && "%JULIA%" -b sysimg.jl && popd && pushd "%cd%") diff --git a/contrib/windows/test-julia.bat b/contrib/windows/test-julia.bat new file mode 100644 index 0000000000000..f49162d180644 --- /dev/null +++ b/contrib/windows/test-julia.bat @@ -0,0 +1,15 @@ +@echo off +@rem +@rem This file is intended to simplify launching Julia on Windows. +@rem +@rem See prepare-julia-env.bat for more info + +pushd %cd% +setlocal enableextensions enabledelayedexpansion +call %~dp0prepare-julia-env.bat %* +cd %JULIA_HOME%..\share\julia\test +call %JULIA_HOME%julia-release-readline.exe runtests.jl all +endlocal +popd +pause +@echo on diff --git a/deps/.gitignore b/deps/.gitignore index 297adf02563df..ac2b0f8b7af17 100644 --- a/deps/.gitignore +++ b/deps/.gitignore @@ -1,13 +1,16 @@ /arpack-* /clang-* /Clp-* +/clp-* /compiler-rt-* /double-conversion-* /dsfmt-* /fftw-* -/glpk-* +!fftw-config-nopthreads.patch +/git-* /gmp-* /grisu-* +/libgrisu.so /lapack-* /libunwind-* /lighttpd-* @@ -17,6 +20,7 @@ /pcre-* /readline-* /readline62-* +!readline-win.h /root /SuiteSparse-* /zlib-* diff --git a/deps/Makefile b/deps/Makefile index 7239e9605b3fa..86ac58738c833 100644 --- a/deps/Makefile +++ b/deps/Makefile @@ -1,27 +1,53 @@ include Versions.make -## optional packages ## +## optional packages and options # +LLVM_ASSERTIONS = 0 # set to 1 to get clang and compiler-rt BUILD_LLVM_CLANG = 0 +# set to 1 to get lldb (does not work with llvm3.1 and earlier) +# see http://lldb.llvm.org/build.html for dependancies +BUILD_LLDB = 0 ## high-level setup ## JULIAHOME = $(abspath ..) include $(JULIAHOME)/Make.inc +CONFIGURE_COMMON = --prefix=$(abspath $(BUILD)) F77="$(FC)" CC="$(CC)" CXX="$(CXX)" +ifneq ($(XC_HOST),) +CONFIG_GUESS := $(shell ./config.guess) +CONFIGURE_COMMON += --host=$(XC_HOST) --build=$(CONFIG_GUESS) +endif + +#autoconf configure-driven scripts: llvm readline pcre arpack fftw unwind gmp patchelf +#custom configure-driven script: zlib +#custom Makefile rules: openlibm Rmath double-conversion random suitesparse-wrapper suitesparse lapack openblas uv # prevent installing libs into usr/lib64 on opensuse unexport CONFIG_SITE -STAGE1_DEPS = uv openlibm random rmath double-conversion glpk -STAGE2_DEPS = gmp-wrapper +STAGE1_DEPS = uv random double-conversion +STAGE2_DEPS = STAGE3_DEPS = suitesparse-wrapper -ifeq ($(OS), Linux) -STAGE1_DEPS += unwind patchelf +ifeq ($(USE_SYSTEM_RMATH), 0) +STAGE1_DEPS += Rmath endif -ifeq ($(OS), FreeBSD) +ifeq ($(USE_SYSTEM_LIBUNWIND), 0) +ifeq ($(OS), Linux) STAGE1_DEPS += unwind +else ifeq ($(OS), FreeBSD) +STAGE1_DEPS += unwind +endif +endif + +ifeq ($(OS), Linux) +ifneq ($(shell patchelf --version 2>/dev/null), patchelf 0.6) +STAGE1_DEPS += patchelf +PATCHELF=$(BUILD)/bin/patchelf +else +PATCHELF=patchelf +endif endif WGET = $(abspath .)/jldownload @@ -29,15 +55,18 @@ WGET_DASH_O = $(WGET) ## USE_SYSTEM_LIBS options +ifeq ($(USE_SYSTEM_OPENLIBM), 0) +# No matter if we are using a system-libm or not, if we don't have a system-openlibm, we need the extras +STAGE1_DEPS += openlibm-extras +ifeq ($(USE_SYSTEM_LIBM), 0) +STAGE1_DEPS += openlibm +endif +endif + ifeq ($(USE_SYSTEM_LLVM), 0) STAGE1_DEPS += llvm endif -# Disable web repl -#ifneq ($(OS),WINNT) -#STAGE1_DEPS += lighttpd -#endif - ifeq ($(OS),WINNT) READLINE_VER = 5.0 endif @@ -70,43 +99,58 @@ ifeq ($(USE_SYSTEM_ARPACK), 0) STAGE2_DEPS += arpack endif -#ifeq ($(USE_SYSTEM_SUITESPARSE), 0) +ifeq ($(USE_SYSTEM_SUITESPARSE), 0) STAGE2_DEPS += suitesparse -#endif +endif #ifeq ($(USE_SYSTEM_LAPACK), 0) #STAGE2_DEPS += lapack #endif +#Platform specific flags + +ifeq ($(OS), WINNT) +LIBTOOL_CCLD = CCLD="$(CC) -no-undefined -avoid-version" +AUTOTOOLS_PATH_CORRECT = -cp -f $(BUILD)/bin/$(@F) $(BUILD)/lib/$(@F) +endif + ## Common build target prefixes LIBS = $(STAGE1_DEPS) $(STAGE2_DEPS) $(STAGE3_DEPS) -default: $(USR) install +default: $(BUILD) install +get: $(addprefix get-, $(LIBS)) +configure: $(addprefix configure-, $(LIBS)) compile: $(addprefix compile-, $(LIBS)) +check: $(addprefix check-, $(LIBS)) install: $(addprefix install-, $(LIBS)) cleanall: $(addprefix clean-, $(LIBS)) distclean: $(addprefix distclean-, $(LIBS)) - rm -rf $(USR) + rm -rf $(BUILD) +getall: get-llvm get-readline get-uv get-pcre get-double-conversion get-openlibm get-random get-openblas get-fftw get-suitesparse get-unwind get-gmp get-zlib get-patchelf ## PATHS ## -DIRS = $(addprefix $(USR)/,lib include bin share etc) +DIRS = $(addprefix $(BUILD)/,lib include bin share etc) $(foreach dir,$(DIRS),$(eval $(call dir_target,$(dir)))) -$(USR): $(DIRS) +$(BUILD): $(DIRS) ## LLVM ## +ifeq ($(BUILD_LLDB), 1) +BUILD_LLVM_CLANG = 1 +# because it's a build requirement +endif -LLVM_OBJ_TARGET = $(USR)/lib/libLLVM-$(LLVM_VER).$(SHLIB_EXT) -ifeq ($(OS),WINNT) - LLVM_OBJ_SOURCE = llvm-$(LLVM_VER)/Release/bin/LLVM-$(LLVM_VER).$(SHLIB_EXT) +ifeq ($(LLVM_ASSERTIONS), 1) +LLVM_BUILDDIR = build/Release+Asserts else - LLVM_OBJ_SOURCE = llvm-$(LLVM_VER)/Release/lib/libLLVM-$(LLVM_VER).$(SHLIB_EXT) +LLVM_BUILDDIR = build/Release endif -compile-llvm: $(LLVM_OBJ_SOURCE) -install-llvm: $(LLVM_OBJ_TARGET) +LLVM_LIB_FILE = libLLVMJIT.a +LLVM_OBJ_SOURCE = llvm-$(LLVM_VER)/$(LLVM_BUILDDIR)/lib/$(LLVM_LIB_FILE) +LLVM_OBJ_TARGET = $(BUILD)/lib/$(LLVM_LIB_FILE) ifeq ($(LLVM_VER), 3.0) LLVM_TAR=llvm-$(LLVM_VER).tar.gz @@ -114,11 +158,7 @@ else LLVM_TAR=llvm-$(LLVM_VER).src.tar.gz endif -ifneq ($(BUILD_LLVM_CLANG), 1) -LLVM_CLANG_TAR= -LLVM_COMPILER_RT_TAR= -else - +ifeq ($(BUILD_LLVM_CLANG),1) ifeq ($(LLVM_VER), 3.0) LLVM_CLANG_TAR=clang-$(LLVM_VER).tar.gz LLVM_COMPILER_RT_TAR= @@ -126,22 +166,59 @@ else LLVM_CLANG_TAR=clang-$(LLVM_VER).src.tar.gz LLVM_COMPILER_RT_TAR=compiler-rt-$(LLVM_VER).src.tar.gz endif +else +LLVM_CLANG_TAR= +LLVM_COMPILER_RT_TAR= +endif + +LLVM_TARGET_FLAGS= --enable-targets=host +LLVM_FLAGS = --disable-threads --disable-profiling --enable-shared --enable-static $(LLVM_TARGET_FLAGS) --disable-bindings --disable-docs +LLVM_MFLAGS = +ifeq ($(LLVM_ASSERTIONS), 1) +LLVM_FLAGS += --enable-assertions --enable-optimized +ifeq ($(OS), WINNT) +LLVM_FLAGS += --disable-embed-stdcxx +endif +else +LLVM_FLAGS += --disable-assertions --enable-optimized +endif +ifeq ($(BUILD_LLDB),1) +ifeq ($(USECLANG),1) +LLVM_FLAGS += --enable-cxx11 +else +LLVM_MFLAGS += CXXFLAGS=-std=c++0x +endif +endif + +ifeq ($(ARCH), ppc64) + LLVM_FLAGS += CXXFLAGS=-mminimal-toc + LLVM_MFLAGS += CXXFLAGS=-mminimal-toc endif ifneq ($(LLVM_CLANG_TAR),) $(LLVM_CLANG_TAR): - $(WGET) http://llvm.org/releases/$(LLVM_VER)/$@ + $(WGET_DASH_O) $@ http://llvm.org/releases/$(LLVM_VER)/$@ endif - ifneq ($(LLVM_COMPILER_RT_TAR),) $(LLVM_COMPILER_RT_TAR): - $(WGET) http://llvm.org/releases/$(LLVM_VER)/$@ + $(WGET_DASH_O) $@ http://llvm.org/releases/$(LLVM_VER)/$@ endif +$(LLVM_TAR): + $(WGET_DASH_O) $@ http://llvm.org/releases/$(LLVM_VER)/$@ +ifeq ($(BUILD_LLDB),1) +llvm-$(LLVM_VER)/tools/lldb: +llvm-$(LLVM_VER)/configure: llvm-$(LLVM_VER)/tools/lldb +endif -$(LLVM_TAR): - $(WGET) http://llvm.org/releases/$(LLVM_VER)/$@ +## LLVM needs python 2.x, but doesn't check for it, so we have to use an ugly workaround to make it compile +llvm-$(LLVM_VER)/python2_path: + mkdir -p llvm-$(LLVM_VER)/python2_path + -python -c 'import sys; sys.exit(not sys.version_info > (3, 0))' && \ + /usr/bin/python2 -c 'import sys; sys.exit(not sys.version_info < (3, 0))' && \ + ln -sf /usr/bin/python2 "llvm-$(LLVM_VER)/python2_path/python" +llvm_python_workaround=llvm-$(LLVM_VER)/python2_path llvm-$(LLVM_VER)/configure: $(LLVM_TAR) $(LLVM_CLANG_TAR) $(LLVM_COMPILER_RT_TAR) mkdir -p llvm-$(LLVM_VER) && \ @@ -154,112 +231,128 @@ ifneq ($(LLVM_COMPILER_RT_TAR),) mkdir -p llvm-$(LLVM_VER)/projects/compiler-rt && \ tar -C llvm-$(LLVM_VER)/projects/compiler-rt --strip-components 1 -xf $(LLVM_COMPILER_RT_TAR) endif - touch $@ +ifeq ($(BUILD_LLDB), 1) + ([ ! -d llvm-$(LLVM_VER)/tools/lldb ] && \ + (cd llvm-$(LLVM_VER)/tools && \ + git clone http://llvm.org/git/lldb.git)) || \ + ([ -d llvm-$(LLVM_VER)/tools/lldb ] && \ + (cd llvm-$(LLVM_VER)/tools/lldb && \ + git fetch)) + cd llvm-$(LLVM_VER)/tools/lldb && git checkout origin/release_32 +endif + touch -c $@ -## LLVM needs python 2.x, but doesn't check for it, so we have to use an ugly workaround to make it compile -llvm_python_workaround: - -python -c 'import sys; sys.exit(not sys.version_info > (3, 0))' && \ - /usr/bin/python2 -c 'import sys; sys.exit(not sys.version_info < (3, 0))' && \ +llvm-$(LLVM_VER)/build/config.status: llvm-$(LLVM_VER)/configure | $(llvm_python_workaround) + cd llvm-$(LLVM_VER) && \ + mkdir -p build && cd build && \ export PATH=$(abspath llvm-$(LLVM_VER)/python2_path):$$PATH && \ - test ! -e llvm-$(LLVM_VER)/python2_path/python && \ - mkdir -p llvm-$(LLVM_VER)/python2_path && \ - ln -s /usr/bin/python2 "llvm-$(LLVM_VER)/python2_path/python" + ../configure $(CONFIGURE_COMMON) $(LLVM_FLAGS) + touch -c $@ -LLVM_CXX = $(CXX) -ifeq ($(ARCH), ppc64) - LLVM_CXX += -mminimal-toc -endif +$(LLVM_OBJ_SOURCE): llvm-$(LLVM_VER)/build/config.status | $(llvm_python_workaround) + cd llvm-$(LLVM_VER)/build && \ + export PATH=$(abspath llvm-$(LLVM_VER)/python2_path):$$PATH && \ + $(MAKE) $(LLVM_MFLAGS) + touch -c $@ -$(LLVM_OBJ_SOURCE): llvm-$(LLVM_VER)/configure | llvm_python_workaround - cd llvm-$(LLVM_VER) && \ +llvm-$(LLVM_VER)/build/checked: $(LLVM_OBJ_SOURCE) | $(llvm_python_workaround) +ifeq ($(OS),$(BUILD_OS)) + cd llvm-$(LLVM_VER)/build && \ export PATH=$(abspath llvm-$(LLVM_VER)/python2_path):$$PATH && \ - ./configure --prefix=$(abspath $(USR)) --disable-threads --enable-optimized --disable-profiling --disable-assertions --enable-shared --enable-targets=host --disable-bindings --disable-docs CC="$(CC)" CXX="$(LLVM_CXX)" && \ - $(MAKE) -$(LLVM_OBJ_TARGET): $(LLVM_OBJ_SOURCE) | llvm_python_workaround + $(MAKE) $(LLVM_MFLAGS) check +endif + echo 1 > $@ + +$(LLVM_OBJ_TARGET): $(LLVM_OBJ_SOURCE) | $(llvm_python_workaround) export PATH=$(abspath llvm-$(LLVM_VER)/python2_path):$$PATH && \ - $(MAKE) -C llvm-$(LLVM_VER) install - $(INSTALL_NAME_CMD)libLLVM-$(LLVM_VER).$(SHLIB_EXT) $(USR)/lib/libLLVM-$(LLVM_VER).$(SHLIB_EXT) - touch $@ + $(MAKE) -C llvm-$(LLVM_VER)/build install + $(AUTOTOOLS_PATH_CORRECT) + touch -c $@ clean-llvm: - -$(MAKE) -C llvm-$(LLVM_VER) clean - -rm -f $(USRBIN)/llvm-config + -$(MAKE) -C llvm-$(LLVM_VER)/build clean + -rm -f $(BUILD)/bin/llvm-config distclean-llvm: -rm -rf llvm-$(LLVM_VER).tar.gz llvm-$(LLVM_VER).src.tar.gz clang-$(LLVM_VER).src.tar.gz clang-$(LLVM_VER).tar.gz compiler-rt-$(LLVM_VER).src.tar.gz llvm-$(LLVM_VER) -## GNU readline ## +get-llvm: $(LLVM_TAR) $(LLVM_CLANG_TAR) $(LLVM_COMPILER_RT_TAR) +configure-llvm: llvm-$(LLVM_VER)/build/config.status +compile-llvm: $(LLVM_OBJ_SOURCE) +check-llvm: llvm-$(LLVM_VER)/build/checked +install-llvm: $(LLVM_OBJ_TARGET) +#todo: LLVM make check target is broken on julia.mit.edu (and really slow elsewhere) -READLINE_OBJ_TARGET = $(USR)/lib/libreadline.$(SHLIB_EXT) -READLINE_OBJ_SOURCE = readline-$(READLINE_VER)/shlib/libreadline.$(READLINE_VER).$(SHLIB_EXT) -READLINE_OPTS = --disable-shared --enable-static -ifeq ($(OS),WINNT) - READLINE_URL = https://github.com/JuliaLang/readline/tarball/master - READLINE_CFLAGS = LOCAL_DEFS="-include $(abspath .)/readline-win.h" -else - READLINE_URL = ftp://ftp.gnu.org/gnu/readline/readline-$(READLINE_VER).tar.gz - READLINE_OPTS += --with-curses - READLINE_CFLAGS = -endif +## GNU readline ## -compile-readline: $(READLINE_OBJ_SOURCE) -install-readline: $(READLINE_OBJ_TARGET) ifeq ($(OS),WINNT) - +READLINE_OBJ_TARGET = $(BUILD)/lib/libreadline.a +READLINE_OBJ_SOURCE = readline-$(READLINE_VER)/libreadline.a +READLINE_URL = https://github.com/JuliaLang/readline/tarball/master +READLINE_OPTS = --disable-shared --enable-static --with-curses +READLINE_CFLAGS = LOCAL_DEFS="-include $(abspath .)/readline-win.h" readline-$(READLINE_VER).tar.gz: $(WGET_DASH_O) $@ $(READLINE_URL) + touch -c $@ readline-$(READLINE_VER)/configure: readline-$(READLINE_VER).tar.gz mkdir readline-$(READLINE_VER) tar -C readline-$(READLINE_VER) --strip-components 1 -xf $< - touch $@ -$(READLINE_OBJ_SOURCE): readline-$(READLINE_VER)/configure - cd readline-$(READLINE_VER) && \ - ./configure --prefix=$(abspath $(USR)) $(READLINE_OPTS) CC="$(CC)" CXX="$(CXX)" && \ - $(MAKE) $(READLINE_CFLAGS) - touch $@ -$(READLINE_OBJ_TARGET): $(READLINE_OBJ_SOURCE) + touch -c $@ +$(READLINE_OBJ_TARGET): $(READLINE_OBJ_SOURCE) readline-$(READLINE_VER)/checked $(MAKE) -C readline-$(READLINE_VER) $(READLINE_CFLAGS) install - touch $@ - -clean-readline: - -$(MAKE) -C readline-$(READLINE_VER) clean - -rm -f $(READLINE_OBJ_TARGET) -distclean-readline: - -rm -rf readline-$(READLINE_VER).tar.gz readline-$(READLINE_VER) - + touch -c $@ else - +READLINE_OBJ_TARGET = $(BUILD)/lib/libreadline.$(SHLIB_EXT) +ifneq ($(OS),Darwin) +READLINE_OBJ_SOURCE = readline-$(READLINE_VER)/shlib/libreadline.$(SHLIB_EXT).$(READLINE_VER) +else +READLINE_OBJ_SOURCE = readline-$(READLINE_VER)/shlib/libreadline.$(READLINE_VER).$(SHLIB_EXT) +endif +READLINE_URL = ftp://ftp.gnu.org/gnu/readline/readline-$(READLINE_VER).tar.gz +READLINE_OPTS = --enable-shared --enable-static --with-curses +READLINE_CFLAGS = readline-$(READLINE_VER).tar.gz: - $(WGET) http://ftp.gnu.org/gnu/readline/$@ - $(WGET) http://ftp.gnu.org/gnu/readline/readline-6.2-patches/readline62-001 - $(WGET) http://ftp.gnu.org/gnu/readline/readline-6.2-patches/readline62-002 - $(WGET) http://ftp.gnu.org/gnu/readline/readline-6.2-patches/readline62-003 - $(WGET) http://ftp.gnu.org/gnu/readline/readline-6.2-patches/readline62-004 + $(WGET_DASH_O) readline62-001 http://ftp.gnu.org/gnu/readline/readline-6.2-patches/readline62-001 + $(WGET_DASH_O) readline62-002 http://ftp.gnu.org/gnu/readline/readline-6.2-patches/readline62-002 + $(WGET_DASH_O) readline62-003 http://ftp.gnu.org/gnu/readline/readline-6.2-patches/readline62-003 + $(WGET_DASH_O) readline62-004 http://ftp.gnu.org/gnu/readline/readline-6.2-patches/readline62-004 + $(WGET_DASH_O) $@ http://ftp.gnu.org/gnu/readline/$@ + touch -c $@ readline-$(READLINE_VER)/configure: readline-$(READLINE_VER).tar.gz tar zxf $< cd readline-$(READLINE_VER) && patch -p0 < ../readline62-001 cd readline-$(READLINE_VER) && patch -p0 < ../readline62-002 cd readline-$(READLINE_VER) && patch -p0 < ../readline62-003 cd readline-$(READLINE_VER) && patch -p0 < ../readline62-004 - touch $@ -$(READLINE_OBJ_SOURCE): readline-$(READLINE_VER)/configure - cd readline-$(READLINE_VER) && \ - ./configure --prefix=$(abspath $(USR)) --enable-shared --enable-static --with-curses CC="$(CC)" CXX="$(CXX)" && \ - $(MAKE) - touch $@ -$(READLINE_OBJ_TARGET): $(READLINE_OBJ_SOURCE) + touch -c $@ +$(READLINE_OBJ_TARGET): $(READLINE_OBJ_SOURCE) readline-$(READLINE_VER)/checked $(MAKE) -C readline-$(READLINE_VER) install - chmod +w $(USR)/lib/libreadline.* $(USR)/lib/libhistory.* + chmod +w $(BUILD)/lib/libreadline.* $(BUILD)/lib/libhistory.* ifeq ($(OS), Darwin) - $(INSTALL_NAME_CMD)libreadline.$(SHLIB_EXT) $(USR)/lib/libreadline.$(SHLIB_EXT) - $(INSTALL_NAME_CMD)libhistory.dylib $(USR)/lib/libhistory.dylib + $(INSTALL_NAME_CMD)libreadline.$(SHLIB_EXT) $(BUILD)/lib/libreadline.$(SHLIB_EXT) + $(INSTALL_NAME_CMD)libhistory.dylib $(BUILD)/lib/libhistory.dylib else ifeq ($(OS), Linux) - for filename in $(USR)/lib/libhistory.so* $(USR)/lib/libreadline.so* ; do \ - $(USR)/bin/patchelf --set-rpath '$$ORIGIN' $$filename ;\ + for filename in $(BUILD)/lib/libhistory.so* $(BUILD)/lib/libreadline.so* ; do \ + $(PATCHELF) --set-rpath '$$ORIGIN' $$filename ;\ done endif - touch $@ + touch -c $@ +endif + +readline-$(READLINE_VER)/config.status: readline-$(READLINE_VER)/configure + cd readline-$(READLINE_VER) && \ + chmod a+x ./configure && \ + ./configure $(CONFIGURE_COMMON) $(READLINE_OPTS) + touch -c $@ +$(READLINE_OBJ_SOURCE): readline-$(READLINE_VER)/config.status + cd readline-$(READLINE_VER) && \ + $(MAKE) $(READLINE_CFLAGS) + touch -c $@ +readline-$(READLINE_VER)/checked: $(READLINE_OBJ_SOURCE) + cd readline-$(READLINE_VER) && \ + $(MAKE) check $(READLINE_CFLAGS) + echo 1 > $@ clean-readline: -$(MAKE) -C readline-$(READLINE_VER) clean @@ -267,11 +360,16 @@ clean-readline: distclean-readline: -rm -rf readline-$(READLINE_VER).tar.gz readline-$(READLINE_VER) -endif +get-readline: readline-$(READLINE_VER).tar.gz +configure-readline: readline-$(READLINE_VER)/config.status +compile-readline: $(READLINE_OBJ_SOURCE) +check-readline: readline-$(READLINE_VER)/checked +install-readline: $(READLINE_OBJ_TARGET) + -## LIBUV +## LIBUV ## -UV_OBJ_TARGET = $(USR)/lib/libuv.a +UV_OBJ_TARGET = $(BUILD)/lib/libuv.a UV_OBJ_SOURCE = libuv/libuv.a libuv/Makefile: @@ -282,45 +380,66 @@ endif ifeq (exists, $(shell [ -d $(JULIAHOME)/modules ] && echo exists )) $(UV_OBJ_SOURCE): $(JULIAHOME)/.git/modules/deps/libuv/HEAD endif +LIBUV_MAKE_FLAGS = -C libuv CC="$(CC)" AR="$(AR)" +ifeq ($(OS),WINNT) +LIBUV_MAKE_FLAGS += OS=mingw +endif $(UV_OBJ_SOURCE): libuv/Makefile -ifneq ($(OS), WINNT) - $(MAKE) libuv.${SHLIB_EXT} -C libuv CC="$(CC)" + $(MAKE) libuv.a $(LIBUV_MAKE_FLAGS) + touch -c $@ +libuv/checked: $(LIBUV_OBJ_SOURCE) +ifeq ($(OS),$(BUILD_OS)) + $(MAKE) test $(LIBUV_MAKE_FLAGS) endif - $(MAKE) libuv.a -C libuv CC="$(CC)" + echo 1 > $@ +#todo: libuv tests are really slow $(UV_OBJ_TARGET): $(UV_OBJ_SOURCE) - mkdir -p $(USR)/include - cp $(UV_OBJ_SOURCE) $(USR)/lib/ - cp -r libuv/include/* $(USR)/include -install-uv: $(UV_OBJ_TARGET) + mkdir -p $(BUILD)/include + cp $(UV_OBJ_SOURCE) $(BUILD)/lib/ + cp -r libuv/include/* $(BUILD)/include clean-uv: - -$(MAKE) -C libuv clean - -rm -rf $(USR)/lib/libuv.a $(USR)/include/uv.h $(USR)/include/uv-private + -$(MAKE) clean $(LIBUV_MAKE_FLAGS) + -rm -rf $(BUILD)/lib/libuv.a $(BUILD)/include/uv.h $(BUILD)/include/uv-private distclean-uv: clean-uv -## PCRE ## +get-uv: libuv/Makefile +configure-uv: get-uv +compile-uv: $(UV_OBJ_SOURCE) +check-uv: libuv/checked +install-uv: $(UV_OBJ_TARGET) -PCRE_OBJ_TARGET = $(USR)/lib/libpcre.$(SHLIB_EXT) -compile-pcre: install-pcre -install-pcre: $(PCRE_OBJ_TARGET) +## PCRE ## + +PCRE_SRC_TARGET = pcre-$(PCRE_VER)/.libs/libpcre.$(SHLIB_EXT) +PCRE_OBJ_TARGET = $(BUILD)/lib/libpcre.$(SHLIB_EXT) pcre-$(PCRE_VER).tar.bz2: $(WGET) ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/$@ pcre-$(PCRE_VER)/configure: pcre-$(PCRE_VER).tar.bz2 tar jxf $< - touch $@ + touch -c $@ pcre-$(PCRE_VER)/config.status: pcre-$(PCRE_VER)/configure cd pcre-$(PCRE_VER) && \ - ./configure --prefix=$(abspath $(USR)) --enable-utf --enable-unicode-properties --enable-jit CC="$(CC)" CXX="$(CXX)" -$(PCRE_OBJ_TARGET): pcre-$(PCRE_VER)/config.status - $(MAKE) -C pcre-$(PCRE_VER) install + ./configure $(CONFIGURE_COMMON) --enable-utf --enable-unicode-properties --enable-jit + touch -c $@ +$(PCRE_SRC_TARGET): pcre-$(PCRE_VER)/config.status + $(MAKE) -C pcre-$(PCRE_VER) $(LIBTOOL_CCLD) + touch -c $@ +pcre-$(PCRE_VER)/checked: $(PCRE_SRC_TARGET) +ifeq ($(OS),$(BUILD_OS)) + $(MAKE) -C pcre-$(PCRE_VER) check +endif + echo 1 > $@ +$(PCRE_OBJ_TARGET): $(PCRE_SRC_TARGET) pcre-$(PCRE_VER)/checked + $(MAKE) -C pcre-$(PCRE_VER) $(LIBTOOL_CCLD) install $(INSTALL_NAME_CMD)libpcre.dylib $@ ifeq ($(OS),WINNT) - -rm $(USR)/lib/libpcre.dll - mv $(USRBIN)/libpcre-1.dll $(USR)/lib/libpcre.dll + -rm $(BUILD)/lib/libpcre.dll + mv $(BUILD)/bin/libpcre.dll $(BUILD)/lib/libpcre.dll endif - touch $@ + touch -c $@ clean-pcre: -$(MAKE) -C pcre-$(PCRE_VER) clean @@ -328,20 +447,27 @@ clean-pcre: distclean-pcre: -rm -rf pcre-$(PCRE_VER).tar.bz2 pcre-$(PCRE_VER) -## Grisu floating-point printing library ## +get-pcre: pcre-$(PCRE_VER).tar.bz2 +configure-pcre: pcre-$(PCRE_VER)/config.status +compile-pcre: $(PCRE_SRC_TARGET) +check-pcre: pcre-$(PCRE_VER)/checked +install-pcre: $(PCRE_OBJ_TARGET) -GRISU_OPTS = -O3 -fvisibility=hidden $(fPIC) -compile-double-conversion: double-conversion-$(GRISU_VER)/src/libgrisu_.$(SHLIB_EXT) -install-double-conversion: $(USR)/lib/libgrisu.$(SHLIB_EXT) +## Grisu floating-point printing library ## + +GRISU_OPTS = $(CXXFLAGS) -O3 -fvisibility=hidden $(fPIC) double-conversion-$(GRISU_VER).tar.gz: - $(WGET) http://double-conversion.googlecode.com/files/double-conversion-$(GRISU_VER).tar.gz + $(WGET_DASH_O) $@ http://double-conversion.googlecode.com/files/$@ + touch -c $@ double-conversion-$(GRISU_VER)/Makefile: double-conversion-$(GRISU_VER).tar.gz mkdir -p double-conversion-$(GRISU_VER) && \ tar -C double-conversion-$(GRISU_VER) --strip-components 1 -xf double-conversion-$(GRISU_VER).tar.gz - touch $@ -double-conversion-$(GRISU_VER)/src/libgrisu.$(SHLIB_EXT): double-conversion-$(GRISU_VER)/Makefile + touch -c $@ + +ifeq ($(USE_SYSTEM_GRISU), 0) +libgrisu.$(SHLIB_EXT): double-conversion-$(GRISU_VER)/Makefile cd double-conversion-$(GRISU_VER) && \ $(CXX) -c $(GRISU_OPTS) -o src/bignum.o -Isrc src/bignum.cc && \ $(CXX) -c $(GRISU_OPTS) -o src/bignum-dtoa.o -Isrc src/bignum-dtoa.cc && \ @@ -352,92 +478,108 @@ double-conversion-$(GRISU_VER)/src/libgrisu.$(SHLIB_EXT): double-conversion-$(GR $(CXX) -c $(GRISU_OPTS) -o src/fixed-dtoa.o -Isrc src/fixed-dtoa.cc && \ $(CXX) -c $(GRISU_OPTS) -o src/strtod.o -Isrc src/strtod.cc && \ $(CXX) -c $(GRISU_OPTS) -o src/libdouble-conversion.o -I.. -Isrc ../double_conversion_wrapper.cpp && \ - $(CXX) $(GRISU_OPTS) src/*.o -shared -dead_strip -o src/libgrisu.$(SHLIB_EXT) -$(USR)/lib/libgrisu.$(SHLIB_EXT): double-conversion-$(GRISU_VER)/src/libgrisu.$(SHLIB_EXT) + $(CXX) $(GRISU_OPTS) src/*.o $(LDFLAGS) -shared -dead_strip -o ../libgrisu.$(SHLIB_EXT) +else +libgrisu.$(SHLIB_EXT): + $(CXX) $(GRISU_OPTS) -I/usr/include/double-conversion double_conversion_wrapper.cpp -shared $(LDFLAGS) -o libgrisu.$(SHLIB_EXT) -ldouble-conversion +endif + +$(BUILD)/lib/libgrisu.$(SHLIB_EXT): libgrisu.$(SHLIB_EXT) cp -f $< $@ - $(INSTALL_NAME_CMD)libgrisu.dylib $@ + $(INSTALL_NAME_CMD)libdouble-conversion.dylib $@ clean-double-conversion: -rm -f double-conversion-$(GRISU_VER)/src/*.o - -rm -f double-conversion-$(GRISU_VER)/src/libgrisu.$(SHLIB_EXT) + -rm -f libgrisu.$(SHLIB_EXT) distclean-double-conversion: - -rm -rf double-conversion-$(GRISU_VER).tar.gz double-conversion-$(GRISU_VER) + -rm -rf double-conversion-$(GRISU_VER).tar.gz double-conversion-$(GRISU_VER) libgrisu.${SHLIB_EXT} -## openlibm ## +get-double-conversion: double-conversion-$(GRISU_VER).tar.gz +configure-double-conversion: get-double-conversion +compile-double-conversion: double-conversion-$(GRISU_VER)/src/libgrisu.$(SHLIB_EXT) +check-double-conversion: compile-double-conversion +install-double-conversion: $(BUILD)/lib/libgrisu.$(SHLIB_EXT) -ifeq ($(OS), WINNT) #needs more advanced detection once 64bit build is possible -OPENLIBM_FLAGS = ARCH=i386 -endif -OPENLIBM_OBJ_TARGET = $(USR)/lib/libopenlibm.$(SHLIB_EXT) +## openlibm && openlibm-extras ## + +OPENLIBM_FLAGS = ARCH="$(ARCH)" CC="$(CC)" FC="$(FC)" AR="$(AR)" OS="$(OS)" USECLANG=$(USECLANG) USEGCC=$(USEGCC) + +OPENLIBM_OBJ_TARGET = $(BUILD)/lib/libopenlibm.$(SHLIB_EXT) OPENLIBM_OBJ_SOURCE = openlibm/libopenlibm.$(SHLIB_EXT) +OPENLIBMEXT_OBJ_TARGET = $(BUILD)/lib/libopenlibm-extras.$(SHLIB_EXT) +OPENLIBMEXT_OBJ_SOURCE = openlibm/libopenlibm-extras.$(SHLIB_EXT) -openlibm/Makefile: +openlibm/Makefile openlibm/Makefile.extras: (cd .. && git submodule init && git submodule update) ifeq (exists, $(shell [ -d openlibm/.git ] && echo exists )) $(OPENLIBM_OBJ_SOURCE): openlibm/.git/HEAD +$(OPENLIBMEXT_OBJ_SOURCE): openlibm/.git/HEAD endif ifeq (exists, $(shell [ -d $(JULIAHOME)/modules ] && echo exists )) $(OPENLIBM_OBJ_SOURCE): $(JULIAHOME)/.git/modules/deps/openlibm/HEAD +$(OPENLIBMEXT_OBJ_SOURCE): $(JULIAHOME)/.git/modules/deps/openlibm/HEAD endif $(OPENLIBM_OBJ_SOURCE): openlibm/Makefile - $(MAKE) -C openlibm $(OPENLIBM_FLAGS) CC="$(CC)" FC="$(FC)" USECLANG=$(USECLANG) USEGCC=$(USEGCC) -$(OPENLIBM_OBJ_TARGET): $(OPENLIBM_OBJ_SOURCE) | $(USR)/lib + $(MAKE) -C openlibm $(OPENLIBM_FLAGS) + touch -c $@ +$(OPENLIBMEXT_OBJ_SOURCE): openlibm/Makefile.extras + $(MAKE) -C openlibm -f Makefile.extras $(OPENLIBM_FLAGS) + touch -c $@ +$(OPENLIBM_OBJ_TARGET): $(OPENLIBM_OBJ_SOURCE) | $(BUILD)/lib + cp $< $@ + $(INSTALL_NAME_CMD)libopenlibm.$(SHLIB_EXT) $@ +$(OPENLIBMEXT_OBJ_TARGET): $(OPENLIBMEXT_OBJ_SOURCE) | $(BUILD)/lib cp $< $@ -install-openlibm: $(OPENLIBM_OBJ_TARGET) + $(INSTALL_NAME_CMD)libopenlibm-extras.$(SHLIB_EXT) $@ clean-openlibm: -$(MAKE) -C openlibm distclean -rm $(OPENLIBM_OBJ_TARGET) -distclean-openlibm: clean-openlibm +distclean-openlibm: clean-openlibm -## Rmath ## - -RMATH_OBJ_TARGET = $(USR)/lib/libRmath.$(SHLIB_EXT) -RMATH_OBJ_SOURCE = Rmath/src/libRmath.$(SHLIB_EXT) +clean-openlibm-extras: + -$(MAKE) -C openlibm -f Makefile.extras distclean + -rm $(OPENLIBMEXT_OBJ_TARGET) +distclean-openlibm-extras: clean-openlibm-extras -compile-rmath: $(RMATH_OBJ_SOURCE) -install-rmath: $(RMATH_OBJ_TARGET) - -$(RMATH_OBJ_SOURCE): Rmath/src/Makefile install-random - cd Rmath/src && \ - $(MAKE) CC="$(CC)" && \ - $(INSTALL_NAME_CMD)libRmath.$(SHLIB_EXT) libRmath.$(SHLIB_EXT) -$(RMATH_OBJ_TARGET): $(RMATH_OBJ_SOURCE) - cp $< $@ +get-openlibm: openlibm/Makefile +configure-openlibm: get-openlibm +compile-openlibm: $(OPENLIBM_OBJ_SOURCE) +check-openlibm: compile-openlibm +install-openlibm: $(OPENLIBM_OBJ_TARGET) -clean-rmath: - -cd Rmath/src && $(MAKE) clean - -rm -f $(RMATH_OBJ_SOURCE) $(RMATH_OBJ_TARGET) -distclean-rmath: clean-rmath +get-openlibm-extras: openlibm/Makefile.extras +configure-openlibm-extras: get-openlibm-extras +compile-openlibm-extras: $(OPENLIBMEXT_OBJ_SOURCE) +check-openlibm-extras: compile-openlibm-extras +install-openlibm-extras: $(OPENLIBMEXT_OBJ_TARGET) ## LIBRANDOM ## -LIBRANDOM_OBJ_TARGET = $(USR)/lib/librandom.$(SHLIB_EXT) +LIBRANDOM_OBJ_TARGET = $(BUILD)/lib/librandom.$(SHLIB_EXT) LIBRANDOM_OBJ_SOURCE = random/librandom.$(SHLIB_EXT) -LIBRANDOM_CFLAGS = $(CFLAGS) -O3 -finline-functions -fomit-frame-pointer -DNDEBUG -fno-strict-aliasing --param max-inline-insns-single=1800 -Wmissing-prototypes -Wall -std=c99 -DDSFMT_MEXP=19937 $(fPIC) -shared -DDSFMT_DO_NOT_USE_OLD_NAMES +LIBRANDOM_CFLAGS = $(CFLAGS) -O3 -finline-functions -fomit-frame-pointer -DNDEBUG -fno-strict-aliasing \ + --param max-inline-insns-single=1800 -Wmissing-prototypes -Wall -std=c99 \ + -DDSFMT_MEXP=19937 $(fPIC) -shared -DDSFMT_DO_NOT_USE_OLD_NAMES ifeq ($(ARCH), x86_64) LIBRANDOM_CFLAGS += -msse2 -DHAVE_SSE2 endif -compile-random: $(LIBRANDOM_OBJ_SOURCE) -install-random: $(LIBRANDOM_OBJ_TARGET) - random/dsfmt-$(DSFMT_VER).tar.gz: $(WGET_DASH_O) $@ http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/dSFMT-src-$(DSFMT_VER).tar.gz - touch $@ -random/jl_random.c: random/dsfmt-$(DSFMT_VER).tar.gz + touch -c $@ +random/dsfmt-$(DSFMT_VER)/config.status: random/dsfmt-$(DSFMT_VER).tar.gz cd random && \ mkdir -p dsfmt-$(DSFMT_VER) && \ tar -C dsfmt-$(DSFMT_VER) --strip-components 1 -xf dsfmt-$(DSFMT_VER).tar.gz && \ - cd dsfmt-$(DSFMT_VER) && patch < ../dSFMT.h.patch - touch $@ -$(LIBRANDOM_OBJ_SOURCE): random/jl_random.c random/randmtzig.c + cd dsfmt-$(DSFMT_VER) && patch < ../dSFMT.h.patch && patch < ../dSFMT.c.patch + echo 1 > $@ +$(LIBRANDOM_OBJ_SOURCE): random/jl_random.c random/randmtzig.c random/dsfmt-$(DSFMT_VER)/config.status cd random && \ - $(CC) $(LIBRANDOM_CFLAGS) jl_random.c -o librandom.$(SHLIB_EXT) && \ + $(CC) $(CPPFLAGS) $(LIBRANDOM_CFLAGS) $(LDFLAGS) jl_random.c -o librandom.$(SHLIB_EXT) && \ $(INSTALL_NAME_CMD)librandom.$(SHLIB_EXT) librandom.$(SHLIB_EXT) - $(LIBRANDOM_OBJ_TARGET): $(LIBRANDOM_OBJ_SOURCE) cp $< $@ @@ -446,68 +588,186 @@ clean-random: distclean-random: clean-random -cd random && rm -rf *.tar.gz dsfmt-$(DSFMT_VER) +get-random: random/dsfmt-$(DSFMT_VER).tar.gz +configure-random: random/dsfmt-$(DSFMT_VER)/config.status +compile-random: $(LIBRANDOM_OBJ_SOURCE) +check-random: compile-random +install-random: $(LIBRANDOM_OBJ_TARGET) + + +## Rmath ## + +RMATH_OBJ_TARGET = $(BUILD)/lib/libRmath.$(SHLIB_EXT) +RMATH_OBJ_SOURCE = Rmath/src/libRmath.$(SHLIB_EXT) + +RMATH_FLAGS += CC="$(CC)" USECLANG=$(USECLANG) USEGCC=$(USEGCC) \ + OS="$(OS)" ARCH="$(ARCH)" \ + USE_LIBRANDOM=1 LIBRANDOM_PATH="$(BUILD)/lib" + +Rmath/Make.inc: + (cd .. && git submodule init && git submodule update) +ifeq (exists, $(shell [ -d Rmath/.git ] && echo exists )) +$(RMATH_OBJ_SOURCE): Rmath/.git/HEAD +endif +ifeq (exists, $(shell [ -d $(JULIAHOME)/modules ] && echo exists )) +$(RMATH_OBJ_SOURCE): $(JULIAHOME)/.git/modules/deps/Rmath/HEAD +endif +$(RMATH_OBJ_SOURCE): Rmath/Make.inc $(LIBRANDOM_OBJ_TARGET) + $(MAKE) -C Rmath/src $(RMATH_FLAGS) + touch -c $@ +$(RMATH_OBJ_TARGET): $(RMATH_OBJ_SOURCE) | $(BUILD)/lib + cp $< $@ + $(INSTALL_NAME_CMD)libRmath.$(SHLIB_EXT) $@ + +clean-Rmath: + -$(MAKE) -C Rmath/src clean + -rm $(RMATH_OBJ_TARGET) +distclean-Rmath: clean-Rmath + +get-Rmath: Rmath/Make.inc +configure-Rmath: get-Rmath +compile-Rmath: $(RMATH_OBJ_SOURCE) +check-Rmath: compile-Rmath +install-Rmath: $(RMATH_OBJ_TARGET) + + ## OpenBLAS ## -ifeq ($(USE_SYSTEM_BLAS), 0) OPENBLAS_OBJ_SOURCE = openblas-$(OPENBLAS_VER)/libopenblas.$(SHLIB_EXT) -else -OPENBLAS_OBJ_SOURCE = -endif +OPENBLAS_OBJ_TARGET = $(BUILD)/lib/libopenblas.$(SHLIB_EXT) -OPENBLAS_BUILD_OPTS = CC="$(CC)" FC="$(FC)" FFLAGS="$(FFLAGS) $(JFFLAGS)" USE_THREAD=$(OPENBLAS_USE_THREAD) TARGET=$(OPENBLAS_TARGET_ARCH) +OPENBLAS_BUILD_OPTS = CC="$(CC)" FC="$(FC)" RANLIB="$(RANLIB)" FFLAGS="$(FFLAGS) $(JFFLAGS)" USE_THREAD=$(OPENBLAS_USE_THREAD) TARGET=$(OPENBLAS_TARGET_ARCH) ifeq ($(OPENBLAS_DYNAMIC_ARCH), 1) OPENBLAS_BUILD_OPTS += DYNAMIC_ARCH=1 +ifneq ($(ARCH),x86_64) +# assume we can't address much memory to spawn many threads +OPENBLAS_BUILD_OPTS += NUM_THREADS=30 +else +# assume we may want lots of threads on some future machine +OPENBLAS_BUILD_OPTS += NUM_THREADS=512 +endif endif -#ifeq ($(ARCH), x86_64) -#OPENBLAS_BUILD_OPTS += -DINTERFACE64=1 -#endif +ifeq ($(USE_LIB64), 1) +OPENBLAS_BUILD_OPTS += INTERFACE64=1 +endif -compile-openblas: $(OPENBLAS_OBJ_SOURCE) -install-openblas: $(USR)/lib/libopenblas.$(SHLIB_EXT) +ifneq ($(BUILD_OS),$(OS)) +OPENBLAS_BUILD_OPTS += OSNAME=$(OS) CROSS=1 +ifeq ($(ARCH),i686) +OPENBLAS_BUILD_OPTS += BINARY=32 +else ifeq ($(ARCH),x86_64) +OPENBLAS_BUILD_OPTS += BINARY=64 +else +$(error "unknown arch for openblas cross-compile") +endif +endif openblas-$(OPENBLAS_VER).tar.gz: $(WGET_DASH_O) $@ https://github.com/xianyi/OpenBLAS/tarball/$(OPENBLAS_VER) -openblas-$(OPENBLAS_VER)/Makefile: openblas-$(OPENBLAS_VER).tar.gz +openblas-$(OPENBLAS_VER)/config.status: openblas-$(OPENBLAS_VER).tar.gz mkdir -p openblas-$(OPENBLAS_VER) && \ tar -C openblas-$(OPENBLAS_VER) --strip-components 1 -xf $< perl -i -ple 's/^\s*(EXTRALIB\s*\+=\s*-lSystemStubs)\s*$$/# $$1/g' $@.system - touch $@ -$(OPENBLAS_OBJ_SOURCE): openblas-$(OPENBLAS_VER)/Makefile + echo 1 > $@ +$(OPENBLAS_OBJ_SOURCE): openblas-$(OPENBLAS_VER)/config.status $(MAKE) -C openblas-$(OPENBLAS_VER) $(OPENBLAS_BUILD_OPTS) -$(USR)/lib/libopenblas.$(SHLIB_EXT): $(OPENBLAS_OBJ_SOURCE) | $(USR)/lib - cp -f openblas-$(OPENBLAS_VER)/libopenblas.$(SHLIB_EXT) $(USR)/lib - $(INSTALL_NAME_CMD)libopenblas.$(SHLIB_EXT) $(USR)/lib/libopenblas.$(SHLIB_EXT) + touch -c $@ +$(OPENBLAS_OBJ_TARGET): $(OPENBLAS_OBJ_SOURCE) | $(BUILD)/lib + cp -f openblas-$(OPENBLAS_VER)/libopenblas.$(SHLIB_EXT) $(BUILD)/lib + $(INSTALL_NAME_CMD)libopenblas.$(SHLIB_EXT) $(BUILD)/lib/libopenblas.$(SHLIB_EXT) clean-openblas: -$(MAKE) -C openblas-$(OPENBLAS_VER) clean distclean-openblas: -rm -rf openblas-$(OPENBLAS_VER).tar.gz openblas-$(OPENBLAS_VER) +get-openblas: openblas-$(OPENBLAS_VER).tar.gz +configure-openblas: get-openblas +compile-openblas: $(OPENBLAS_OBJ_SOURCE) +check-openblas: compile-openblas +install-openblas: $(OPENBLAS_OBJ_TARGET) + + +## ATLAS (currently 3.10.0) ## + +# no threading, with full lapack, shared library +# should always be compiled with (a real) gcc, it's +# configure script will search for the best match +# (gcc 4.7, gcc, clang,ICC/microsoft/others) +ATLAS_OBJ_SOURCE = atlas/build/lib/libsatlas.$(SHLIB_EXT) +ATLAS_FLAGS = --shared --prefix=$(BUILD) --cc=gcc -t 0 \ + --with-netlib-lapack-tarfile=$(JULIAHOME)/deps/lapack-$(LAPACK_VER).tgz +ifeq ($(OS), WINNT) +ATLAS_FLAGS += -b 32 +endif + +#force backwards compatibility (pick any 1) +#ATLAS_FLAGS += -V 192 -A 13 # requires SSE2 (P4 & later) +#ATLAS_FLAGS += -V 128 -A 12 # requires SSE1 (P3 & later) +#ATLAS_FLAGS += -V -1 -A 11 # any x87 (PentiumPro or Athlon & later) +#ATLAS_FLAGS += -A 25 # requires Corei132 (Corei232 doesn't have definition yet) + +atlas/configure: + git clone git://github.com/vtjnash/atlas-3.10.0.git atlas +ifeq "$(MAKECMDGOALS)" "compile-atlas" +# only allow building atlas as the sole target (without -jN) +# since it internally handles parallelism, for tuning timing accuracy +atlas/build/Make.top: atlas/configure lapack-$(LAPACK_VER).tgz + cd atlas && \ + (test -d build || mkdir build) && cd build && \ + ../configure $(ATLAS_FLAGS) + touch -c $@ +$(ATLAS_OBJ_SOURCE): atlas/build/Make.top + $(MAKE) -C atlas/build -j1 + touch -c $@ +else +$(ATLAS_OBJ_SOURCE): + $(error cannot build atlas in parallel with anything else) +endif +$(BUILD)/lib/libsatlas.$(SHLIB_EXT): $(ATLAS_OBJ_SOURCE) + cp -f atlas/build/lib/libsatlas.$(SHLIB_EXT) $(BUILD)/lib + $(INSTALL_NAME_CMD)libsatlas.$(SHLIB_EXT) $(BUILD)/lib/libsatlas.$(SHLIB_EXT) + +clean-atlas: + rm -rf atlas/build +distclean-atlas: clean-atlas + rm -rf atlas + +get-atlas: atlas/configure +configure-atlas: atlas/build/Make.top +compile-atlas: $(ATLAS_OBJ_SOURCE) +check-atlas: compile-atlas +install-atlas: $(BUILD)/lib/libsatlas.$(SHLIB_EXT) + + ## LAPACK ## ifeq ($(USE_SYSTEM_LAPACK), 0) -LAPACK_OBJ_TARGET = $(USR)/lib/liblapack.$(SHLIB_EXT) +LAPACK_OBJ_TARGET = $(BUILD)/lib/liblapack.$(SHLIB_EXT) LAPACK_OBJ_SOURCE = lapack-$(LAPACK_VER)/liblapack.$(SHLIB_EXT) else LAPACK_OBJ_TARGET = LAPACK_OBJ_SOURCE = endif -compile-lapack: $(LAPACK_OBJ_SOURCE) -install-lapack: $(LAPACK_OBJ_TARGET) - lapack-$(LAPACK_VER).tgz: - $(WGET) http://www.netlib.org/lapack/$@ + $(WGET_DASH_O) $@ http://www.netlib.org/lapack/$@ lapack-$(LAPACK_VER)/Makefile: lapack-$(LAPACK_VER).tgz tar zxf $< - touch $@ -lapack-$(LAPACK_VER)/INSTALL/dlamch.o: lapack-$(LAPACK_VER)/Makefile $(OPENBLAS_OBJ_SOURCE) + touch -c $@ +ifeq ($(USE_SYSTEM_BLAS), 0) +lapack-$(LAPACK_VER)/INSTALL/dlamch.o: $(OPENBLAS_OBJ_TARGET) +endif +lapack-$(LAPACK_VER)/INSTALL/dlamch.o: lapack-$(LAPACK_VER)/Makefile cd lapack-$(LAPACK_VER) && \ cp INSTALL/make.inc.gfortran ./make.inc && \ $(MAKE) lapacklib NOOPT="-O0 $(fPIC)" OPTS="$(FFLAGS) $(JFFLAGS)" FORTRAN="$(FC)" LOADER="$(FC)" - touch $@ -$(LAPACK_OBJ_SOURCE): lapack-$(LAPACK_VER)/INSTALL/dlamch.o $(OPENBLAS_OBJ_SOURCE) + touch -c $@ +ifeq ($(USE_SYSTEM_BLAS), 0) +$(LAPACK_OBJ_SOURCE): $(OPENBLAS_OBJ_TARGET) +endif +$(LAPACK_OBJ_SOURCE): lapack-$(LAPACK_VER)/INSTALL/dlamch.o cd lapack-$(LAPACK_VER) && \ $(FC) -shared $(FFLAGS) $(JFFLAGS) SRC/*.o INSTALL/dlamch.o INSTALL/dsecnd_INT_ETIME.o INSTALL/ilaver.o INSTALL/slamch.o $(LIBBLAS) -o liblapack.$(SHLIB_EXT) $(LAPACK_OBJ_TARGET): $(LAPACK_OBJ_SOURCE) @@ -519,53 +779,101 @@ clean-lapack: distclean-lapack: -rm -rf lapack-$(LAPACK_VER).tgz lapack-$(LAPACK_VER) +get-lapack: lapack-$(LAPACK_VER).tgz +configure-lapack: get-lapack +compile-lapack: $(LAPACK_OBJ_SOURCE) +check-lapack: compile-lapack +install-lapack: $(LAPACK_OBJ_TARGET) + + ## ARPACK ## -ARPACK_OBJ_TARGET = $(USR)/lib/libarpack.$(SHLIB_EXT) -ARPACK_OBJ_SOURCE = arpack-ng_$(ARPACK_VER)/libarpack.$(SHLIB_EXT) +ifeq ($(USE_LIB64), 1) +ARPACK_FFLAGS = -fdefault-integer-8 +endif -compile-arpack: $(ARPACK_OBJ_SOURCE) -install-arpack: $(ARPACK_OBJ_TARGET) +ARPACK_OBJ_TARGET = $(BUILD)/lib/libarpack.$(SHLIB_EXT) +ifeq ($(OS),WINNT) +ARPACK_OBJ_SOURCE = arpack-ng-$(ARPACK_VER)/libarpack.$(SHLIB_EXT) +else +ARPACK_OBJ_SOURCE = arpack-ng-$(ARPACK_VER)/.libs/libarpack.$(SHLIB_EXT) +endif +ARPACK_ARGS = F77="$(FC)" MPIF77="$(FC)" +ARPACK_OPTS = $(FFLAGS) $(JFFLAGS) -arpack-ng_$(ARPACK_VER).tar.gz: - $(WGET_DASH_O) $@ http://forge.scilab.org/index.php/p/arpack-ng/downloads/get/arpack-ng_$(ARPACK_VER).tar.gz - touch $@ -arpack-ng_$(ARPACK_VER)/configure: arpack-ng_$(ARPACK_VER).tar.gz +arpack-ng-$(ARPACK_VER).tar.gz: + $(WGET_DASH_O) $@ http://forge.scilab.org/index.php/p/arpack-ng/downloads/get/arpack-ng-$(ARPACK_VER).tar.gz + touch -c $@ +arpack-ng-$(ARPACK_VER)/configure: arpack-ng-$(ARPACK_VER).tar.gz tar zxf $< - touch $@ -$(ARPACK_OBJ_SOURCE): arpack-ng_$(ARPACK_VER)/configure $(OPENBLAS_OBJ_SOURCE) - cd arpack-ng_$(ARPACK_VER) && \ - ./configure --prefix=$(abspath $(USR)) --with-blas="$(LIBBLAS)" --with-lapack="$(LIBLAPACK)" --disable-mpi --enable-shared F77="$(FC)" MPIF77="$(FC)" CC="$(CC)" CXX="$(CXX)" - touch $@ -$(ARPACK_OBJ_TARGET): $(ARPACK_OBJ_SOURCE) | $(USR)/lib - cd arpack-ng_$(ARPACK_VER) && \ - $(MAKE) install F77="$(FC)" MPIF77="$(FC)" - $(INSTALL_NAME_CMD)libarpack.$(SHLIB_EXT) $(USR)/lib/libarpack.$(SHLIB_EXT) + touch -c $@ +ifeq ($(USE_SYSTEM_BLAS), 0) +arpack-ng-$(ARPACK_VER)/config.status: $(OPENBLAS_OBJ_TARGET) +endif +arpack-ng-$(ARPACK_VER)/config.status: arpack-ng-$(ARPACK_VER)/configure +ifeq ($(OS),WINNT) + cd arpack-ng-$(ARPACK_VER) && \ + rm -f UTIL/second_NONE.f + echo 1 > $@ +else + cd arpack-ng-$(ARPACK_VER) && \ + ./configure $(CONFIGURE_COMMON) --with-blas="$(LIBBLAS)" --with-lapack="$(LIBLAPACK)" --disable-mpi --enable-shared FFLAGS="$(ARPACK_FFLAGS)" +endif + touch -c $@ +$(ARPACK_OBJ_SOURCE): arpack-ng-$(ARPACK_VER)/config.status +ifeq ($(OS),WINNT) + cd arpack-ng-$(ARPACK_VER) && \ + $(FC) -shared $(ARPACK_OPTS) SRC/*.f UTIL/*.f $(LIBLAPACK) $(LIBBLAS) -o libarpack.$(SHLIB_EXT) +else + cd arpack-ng-$(ARPACK_VER) && \ + $(MAKE) $(ARPACK_ARGS) +endif + touch -c $@ +arpack-ng-$(ARPACK_VER)/checked: $(ARPACK_OBJ_SOURCE) +ifneq ($(OS),WINNT) + cd arpack-ng-$(ARPACK_VER) && \ + $(MAKE) check $(ARPACK_ARGS) +endif + echo 1 > $@ +$(ARPACK_OBJ_TARGET): $(ARPACK_OBJ_SOURCE) arpack-ng-$(ARPACK_VER)/checked | $(BUILD)/lib +ifeq ($(OS),WINNT) + cd arpack-ng-$(ARPACK_VER) && \ + cp libarpack.$(SHLIB_EXT) $(BUILD)/lib/libarpack.$(SHLIB_EXT) +else + cd arpack-ng-$(ARPACK_VER) && \ + $(MAKE) install $(ARPACK_ARGS) + $(INSTALL_NAME_CMD)libarpack.$(SHLIB_EXT) $(BUILD)/lib/libarpack.$(SHLIB_EXT) ifeq ($(OS), Linux) - for filename in $(USR)/lib/libarpack.so* ; do \ - $(USR)/bin/patchelf --set-rpath '$$ORIGIN' $$filename ;\ + for filename in $(BUILD)/lib/libarpack.so* ; do \ + [ -L $$filename ] || $(PATCHELF) --set-rpath '$$ORIGIN' $$filename ;\ done endif - touch $@ +endif + touch -c $@ clean-arpack: - -$(MAKE) -C arpack-ng_$(ARPACK_VER) clean + -$(MAKE) -C arpack-ng-$(ARPACK_VER) clean -rm -f $(ARPACK_OBJ_SOURCE) $(ARPACK_OBJ_TARGET) distclean-arpack: - -rm -rf arpack-ng_$(ARPACK_VER).tar.gz arpack-ng_$(ARPACK_VER) + -rm -rf arpack-ng-$(ARPACK_VER).tar.gz arpack-ng-$(ARPACK_VER) -## FFTW ## - -FFTW_SINGLE_OBJ_TARGET = $(USR)/lib/libfftw3f.3.$(SHLIB_EXT) -FFTW_DOUBLE_OBJ_TARGET = $(USR)/lib/libfftw3.3.$(SHLIB_EXT) +get-arpack: arpack-ng-$(ARPACK_VER).tar.gz +configure-arpack: arpack-ng-$(ARPACK_VER)/config.status +compile-arpack: $(ARPACK_OBJ_SOURCE) +check-arpack: arpack-ng-$(ARPACK_VER)/checked +install-arpack: $(ARPACK_OBJ_TARGET) -compile-fftw: compile-fftw-single compile-fftw-double -compile-fftw-single: install-fftw-single -compile-fftw-double: install-fftw-double -install-fftw: install-fftw-single install-fftw-double -install-fftw-single: $(FFTW_SINGLE_OBJ_TARGET) -install-fftw-double: $(FFTW_DOUBLE_OBJ_TARGET) +## FFTW ## +ifeq ($(OS),WINNT) +FFTW_SINGLE_SRC_TARGET = fftw-$(FFTW_VER)-single/.libs/libfftw3f-3.$(SHLIB_EXT) +FFTW_DOUBLE_SRC_TARGET = fftw-$(FFTW_VER)-double/.libs/libfftw3-3.$(SHLIB_EXT) +else +FFTW_SINGLE_SRC_TARGET = fftw-$(FFTW_VER)-single/.libs/libfftw3f.$(SHLIB_EXT) +FFTW_DOUBLE_SRC_TARGET = fftw-$(FFTW_VER)-double/.libs/libfftw3.$(SHLIB_EXT) +endif +FFTW_SINGLE_OBJ_TARGET = $(BUILD)/lib/libfftw3f.$(SHLIB_EXT) +FFTW_DOUBLE_OBJ_TARGET = $(BUILD)/lib/libfftw3.$(SHLIB_EXT) FFTW_CONFIG = --enable-shared --disable-fortran --disable-mpi --enable-fma --enable-threads ifneq ($(ARCH), ppc64) @@ -576,57 +884,83 @@ ifeq ($(OS),WINNT) endif fftw-$(FFTW_VER).tar.gz: - $(WGET) http://www.fftw.org/$@ + $(WGET_DASH_O) $@ http://www.fftw.org/$@ fftw-$(FFTW_VER)-single/configure: fftw-$(FFTW_VER).tar.gz mkdir -p fftw-$(FFTW_VER)-single && \ tar -C fftw-$(FFTW_VER)-single --strip-components 1 -xf $< - touch $@ +ifeq ($(OS),WINNT) + patch fftw-$(FFTW_VER)-single/configure < fftw-config-nopthreads.patch + patch fftw-$(FFTW_VER)-single/kernel/ifftw.h < ifftw.h.patch +endif + touch -c $@ fftw-$(FFTW_VER)-single/config.status: fftw-$(FFTW_VER)-single/configure cd fftw-$(FFTW_VER)-single && \ - ./configure --prefix=$(abspath $(USR)) $(FFTW_CONFIG) --enable-single CC="$(CC)" CXX="$(CXX)" && \ + (./configure $(CONFIGURE_COMMON) $(FFTW_CONFIG) --enable-avx --enable-single || \ + ./configure $(CONFIGURE_COMMON) $(FFTW_CONFIG) --enable-single) && \ $(MAKE) clean - touch $@ -$(FFTW_SINGLE_OBJ_TARGET): fftw-$(FFTW_VER)-single/config.status + touch -c $@ +$(FFTW_SINGLE_SRC_TARGET): fftw-$(FFTW_VER)-single/config.status + $(MAKE) -C fftw-$(FFTW_VER)-single +fftw-$(FFTW_VER)-single/checked: $(FFTW_SINGLE_SRC_TARGET) +ifeq ($(OS),$(BUILD_OS)) + $(MAKE) -C fftw-$(FFTW_VER)-single check +endif + echo 1 > $@ +$(FFTW_SINGLE_OBJ_TARGET): $(FFTW_SINGLE_SRC_TARGET) fftw-$(FFTW_VER)-single/checked $(MAKE) -C fftw-$(FFTW_VER)-single install + touch -c $@ ifeq ($(OS), Darwin) - $(INSTALL_NAME_CMD)libfftw3f.dylib $(USR)/lib/libfftw3f.dylib - $(INSTALL_NAME_CMD)libfftw3f_threads.$(SHLIB_EXT) $(USR)/lib/libfftw3f_threads.$(SHLIB_EXT) - $(INSTALL_NAME_CHANGE_CMD) $(USR)/lib/libfftw3f.3.dylib $(INSTALL_NAME_ID_DIR)libfftw3f.dylib $(USR)/lib/libfftw3f_threads.dylib + $(INSTALL_NAME_CMD)libfftw3f.dylib $(BUILD)/lib/libfftw3f.dylib + $(INSTALL_NAME_CMD)libfftw3f_threads.$(SHLIB_EXT) $(BUILD)/lib/libfftw3f_threads.$(SHLIB_EXT) + $(INSTALL_NAME_CHANGE_CMD) $(BUILD)/lib/libfftw3f.3.dylib $(INSTALL_NAME_ID_DIR)libfftw3f.dylib $(BUILD)/lib/libfftw3f_threads.dylib else ifeq ($(OS),WINNT) - -rm $(USR)/lib/libfftw3f.dll - mv $(USRBIN)/libfftw3f-3.dll $(USR)/lib/libfftw3f.dll + -rm $(BUILD)/lib/libfftw3f.dll + mv $(BUILD)/bin/libfftw3f-3.dll $(BUILD)/lib/libfftw3f.dll else ifeq ($(OS), Linux) - for filename in $(USR)/lib/libfftw3f_threads.so* ; do \ - $(USR)/bin/patchelf --set-rpath '$$ORIGIN' $$filename ;\ + for filename in $(BUILD)/lib/libfftw3f_threads.so* ; do \ + [ -L $$filename ] || $(PATCHELF) --set-rpath '$$ORIGIN' $$filename ;\ done endif - touch $@ + touch -c $@ fftw-$(FFTW_VER)-double/configure: fftw-$(FFTW_VER).tar.gz mkdir -p fftw-$(FFTW_VER)-double && \ tar -C fftw-$(FFTW_VER)-double --strip-components 1 -xf $< - touch $@ +ifeq ($(OS),WINNT) + patch fftw-$(FFTW_VER)-double/configure < fftw-config-nopthreads.patch + patch fftw-$(FFTW_VER)-double/kernel/ifftw.h < ifftw.h.patch +endif + touch -c $@ fftw-$(FFTW_VER)-double/config.status: fftw-$(FFTW_VER)-double/configure cd fftw-$(FFTW_VER)-double && \ - ./configure --prefix=$(abspath $(USR)) $(FFTW_CONFIG) CC="$(CC)" CXX="$(CXX)" && \ + (./configure $(CONFIGURE_COMMON) $(FFTW_CONFIG) --enable-avx || \ + ./configure $(CONFIGURE_COMMON) $(FFTW_CONFIG)) && \ $(MAKE) clean - touch $@ -$(FFTW_DOUBLE_OBJ_TARGET): fftw-$(FFTW_VER)-double/config.status + touch -c $@ +$(FFTW_DOUBLE_SRC_TARGET): fftw-$(FFTW_VER)-double/config.status + $(MAKE) -C fftw-$(FFTW_VER)-double + touch -c $@ +fftw-$(FFTW_VER)-double/checked: $(FFTW_DOUBLE_SRC_TARGET) +ifeq ($(OS),$(BUILD_OS)) + $(MAKE) -C fftw-$(FFTW_VER)-double check +endif + echo 1 > $@ +$(FFTW_DOUBLE_OBJ_TARGET): $(FFTW_DOUBLE_SRC_TARGET) fftw-$(FFTW_VER)-double/checked $(MAKE) -C fftw-$(FFTW_VER)-double install ifeq ($(OS), Darwin) - $(INSTALL_NAME_CMD)libfftw3.$(SHLIB_EXT) $(USR)/lib/libfftw3.$(SHLIB_EXT) - $(INSTALL_NAME_CMD)libfftw3_threads.$(SHLIB_EXT) $(USR)/lib/libfftw3_threads.$(SHLIB_EXT) - $(INSTALL_NAME_CHANGE_CMD) $(USR)/lib/libfftw3.3.dylib $(INSTALL_NAME_ID_DIR)libfftw3.dylib $(USR)/lib/libfftw3_threads.dylib + $(INSTALL_NAME_CMD)libfftw3.$(SHLIB_EXT) $(BUILD)/lib/libfftw3.$(SHLIB_EXT) + $(INSTALL_NAME_CMD)libfftw3_threads.$(SHLIB_EXT) $(BUILD)/lib/libfftw3_threads.$(SHLIB_EXT) + $(INSTALL_NAME_CHANGE_CMD) $(BUILD)/lib/libfftw3.3.dylib $(INSTALL_NAME_ID_DIR)libfftw3.dylib $(BUILD)/lib/libfftw3_threads.dylib else ifeq ($(OS),WINNT) - -rm $(USR)/lib/libfftw3.dll - mv $(USRBIN)/libfftw3-3.dll $(USR)/lib/libfftw3.dll + -rm $(BUILD)/lib/libfftw3.dll + mv $(BUILD)/bin/libfftw3-3.dll $(BUILD)/lib/libfftw3.dll else ifeq ($(OS), Linux) - for filename in $(USR)/lib/libfftw3_threads.so* ; do \ - $(USR)/bin/patchelf --set-rpath '$$ORIGIN' $$filename ;\ + for filename in $(BUILD)/lib/libfftw3_threads.so* ; do \ + [ -L $$filename ] || $(PATCHELF) --set-rpath '$$ORIGIN' $$filename ;\ done endif - touch $@ + touch -c $@ clean-fftw: clean-fftw-single clean-fftw-double clean-fftw-single: @@ -638,50 +972,76 @@ clean-fftw-double: distclean-fftw: -rm -rf fftw-$(FFTW_VER).tar.gz fftw-$(FFTW_VER)-{single,double} +get-fftw: get-fftw-single get-fftw-double +configure-fftw: configure-fftw-single configure-fftw-double +compile-fftw: compile-fftw-single compile-fftw-double +check-fftw: check-fftw-single check-fftw-double +install-fftw: install-fftw-single install-fftw-double + +get-fftw-single: fftw-$(FFTW_VER).tar.gz +configure-fftw-single: fftw-$(FFTW_VER)-single/config.status +compile-fftw-single: $(FFTW_SINGLE_OBJ_TARGET) +check-fftw-single: fftw-$(FFTW_VER)-single/checked +install-fftw-single: $(FFTW_SINGLE_OBJ_TARGET) + +get-fftw-double: fftw-$(FFTW_VER).tar.gz +configure-fftw-double: fftw-$(FFTW_VER)-double/config.status +compile-fftw-double: $(FFTW_DOUBLE_OBJ_TARGET) +check-fftw-double: fftw-$(FFTW_VER)-double/checked +install-fftw-double: $(FFTW_DOUBLE_OBJ_TARGET) + ## SUITESPARSE ## -ifeq ($(USE_SYSTEM_SUITESPARSE), 0) SUITESPARSE_OBJ_SOURCE = SuiteSparse-$(SUITESPARSE_VER)/UMFPACK/Lib/libumfpack.a -SUITESPARSE_OBJ_TARGET = $(USR)/lib/libumfpack.$(SHLIB_EXT) +SUITESPARSE_OBJ_TARGET = $(BUILD)/lib/libumfpack.$(SHLIB_EXT) + +ifeq ($(USE_LIB64), 1) +UMFPACK_CONFIG = -DLONGBLAS='long long' +CHOLMOD_CONFIG = -DLONGBLAS='long long' endif SUITE_SPARSE_LIB = -lm ifneq ($(OS), Darwin) - SUITE_SPARSE_LIB += -lrt +ifneq ($(OS), WINNT) +SUITE_SPARSE_LIB += -lrt +endif +endif +ifneq ($(OS), WINNT) +SUITE_SPARSE_LIB += -Wl,-rpath,'$(BUILD)/lib' endif - -compile-suitesparse: $(SUITESPARSE_OBJ_SOURCE) -install-suitesparse: $(SUITESPARSE_OBJ_TARGET) $(USR)/lib/libsuitesparse_wrapper.$(SHLIB_EXT) SuiteSparse-$(SUITESPARSE_VER).tar.gz: - $(WGET) http://www.cise.ufl.edu/research/sparse/SuiteSparse/SuiteSparse-$(SUITESPARSE_VER).tar.gz + $(WGET_DASH_O) $@ http://www.cise.ufl.edu/research/sparse/SuiteSparse/$@ SuiteSparse-$(SUITESPARSE_VER)/Makefile: SuiteSparse-$(SUITESPARSE_VER).tar.gz mkdir -p SuiteSparse-$(SUITESPARSE_VER) tar -C SuiteSparse-$(SUITESPARSE_VER) --strip-components 1 -zxf $< - touch $@ -$(SUITESPARSE_OBJ_SOURCE): $(OPENBLAS_OBJ_SOURCE) SuiteSparse-$(SUITESPARSE_VER)/Makefile + touch -c $@ +ifeq ($(USE_SYSTEM_BLAS), 0) +$(SUITESPARSE_OBJ_SOURCE): $(OPENBLAS_OBJ_TARGET) +endif +#todo: rpath is missing on mac for tests +$(SUITESPARSE_OBJ_SOURCE): SuiteSparse-$(SUITESPARSE_VER)/Makefile cd SuiteSparse-$(SUITESPARSE_VER) && \ - $(MAKE) CC="$(CC)" CXX="$(CXX)" BLAS="$(LIBBLAS)" LAPACK="$(LIBLAPACK)" INSTALL_LIB="$(USR)/lib" INSTALL_INCLUDE="$(USRINC)" LIB="$(SUITE_SPARSE_LIB)" - touch $@ - -ifeq ($(USE_SYSTEM_SUITESPARSE), 0) + $(MAKE) library CC="$(CC)" CXX="$(CXX)" F77="$(FC)" AR="$(AR)" RANLIB="$(RANLIB)" BLAS="$(LIBBLAS)" LAPACK="$(LIBLAPACK)" \ + INSTALL_LIB="$(BUILD)/lib" INSTALL_INCLUDE="$(BUILD)/include" LIB="$(SUITE_SPARSE_LIB)" \ + UMFPACK_CONFIG="$(UMFPACK_CONFIG)" CHOLMOD_CONFIG="$(CHOLMOD_CONFIG)" + touch -c $@ $(SUITESPARSE_OBJ_TARGET): $(SUITESPARSE_OBJ_SOURCE) mkdir -p SuiteSparse-$(SUITESPARSE_VER)/lib && \ cd SuiteSparse-$(SUITESPARSE_VER)/lib && \ rm -f *.a && \ cp -f `find .. -name libamd.a -o -name libcolamd.a -o -name libcholmod.a -o -name libumfpack.a -o -name libsuitesparseconfig.a -o -name libspqr.a 2>/dev/null` . && \ - $(CC) -shared $(WHOLE_ARCHIVE) libamd.a $(NO_WHOLE_ARCHIVE) -o $(USR)/lib/libamd.$(SHLIB_EXT) && \ - $(INSTALL_NAME_CMD)libamd.$(SHLIB_EXT) $(USR)/lib/libamd.$(SHLIB_EXT) && \ - $(CC) -shared $(WHOLE_ARCHIVE) libcolamd.a $(NO_WHOLE_ARCHIVE) -o $(USR)/lib/libcolamd.$(SHLIB_EXT) && \ - $(INSTALL_NAME_CMD)libcolamd.$(SHLIB_EXT) $(USR)/lib/libcolamd.$(SHLIB_EXT) && \ - $(CXX) -shared $(WHOLE_ARCHIVE) libsuitesparseconfig.a libcholmod.a $(NO_WHOLE_ARCHIVE) -o $(USR)/lib/libcholmod.$(SHLIB_EXT) -L$(USR)/lib -lcolamd -lamd $(LIBBLAS) $(RPATH_ORIGIN) && \ - $(INSTALL_NAME_CMD)libcholmod.$(SHLIB_EXT) $(USR)/lib/libcholmod.$(SHLIB_EXT) && \ - $(CXX) -shared $(WHOLE_ARCHIVE) libsuitesparseconfig.a libumfpack.a $(NO_WHOLE_ARCHIVE) -o $(USR)/lib/libumfpack.$(SHLIB_EXT) -L$(USR)/lib -lcholmod -lcolamd -lamd $(LIBBLAS) $(RPATH_ORIGIN) && \ - $(INSTALL_NAME_CMD)libumfpack.$(SHLIB_EXT) $(USR)/lib/libumfpack.$(SHLIB_EXT) && \ - $(CXX) -shared $(WHOLE_ARCHIVE) libsuitesparseconfig.a libspqr.a $(NO_WHOLE_ARCHIVE) -o $(USR)/lib/libspqr.$(SHLIB_EXT) -L$(USR)/lib -lcholmod -lcolamd -lamd $(LIBBLAS) $(RPATH_ORIGIN) && \ - $(INSTALL_NAME_CMD)libspqr.$(SHLIB_EXT) $(USR)/lib/libspqr.$(SHLIB_EXT) -endif + $(CC) -shared $(WHOLE_ARCHIVE) libamd.a $(NO_WHOLE_ARCHIVE) -o $(BUILD)/lib/libamd.$(SHLIB_EXT) && \ + $(INSTALL_NAME_CMD)libamd.$(SHLIB_EXT) $(BUILD)/lib/libamd.$(SHLIB_EXT) && \ + $(CC) -shared $(WHOLE_ARCHIVE) libcolamd.a $(NO_WHOLE_ARCHIVE) -o $(BUILD)/lib/libcolamd.$(SHLIB_EXT) && \ + $(INSTALL_NAME_CMD)libcolamd.$(SHLIB_EXT) $(BUILD)/lib/libcolamd.$(SHLIB_EXT) && \ + $(CXX) -shared $(WHOLE_ARCHIVE) libsuitesparseconfig.a libcholmod.a $(NO_WHOLE_ARCHIVE) -o $(BUILD)/lib/libcholmod.$(SHLIB_EXT) -L$(BUILD)/lib -lcolamd -lamd $(LIBBLAS) $(RPATH_ORIGIN) && \ + $(INSTALL_NAME_CMD)libcholmod.$(SHLIB_EXT) $(BUILD)/lib/libcholmod.$(SHLIB_EXT) && \ + $(CXX) -shared $(WHOLE_ARCHIVE) libsuitesparseconfig.a libumfpack.a $(NO_WHOLE_ARCHIVE) -o $(BUILD)/lib/libumfpack.$(SHLIB_EXT) -L$(BUILD)/lib -lcholmod -lcolamd -lamd $(LIBBLAS) $(RPATH_ORIGIN) && \ + $(INSTALL_NAME_CMD)libumfpack.$(SHLIB_EXT) $(BUILD)/lib/libumfpack.$(SHLIB_EXT) && \ + $(CXX) -shared $(WHOLE_ARCHIVE) libsuitesparseconfig.a libspqr.a $(NO_WHOLE_ARCHIVE) -o $(BUILD)/lib/libspqr.$(SHLIB_EXT) -L$(BUILD)/lib -lcholmod -lcolamd -lamd $(LIBBLAS) $(RPATH_ORIGIN) && \ + $(INSTALL_NAME_CMD)libspqr.$(SHLIB_EXT) $(BUILD)/lib/libspqr.$(SHLIB_EXT) clean-suitesparse: -$(MAKE) -C SuiteSparse-$(SUITESPARSE_VER) clean @@ -689,6 +1049,12 @@ clean-suitesparse: distclean-suitesparse: clean-suitesparse -rm -rf SuiteSparse-$(SUITESPARSE_VER).tar.gz SuiteSparse-$(SUITESPARSE_VER) +get-suitesparse: SuiteSparse-$(SUITESPARSE_VER).tar.gz +configure-suitesparse: get-suitesparse +compile-suitesparse: $(SUITESPARSE_OBJ_SOURCE) +check-suitesparse: compile-suitesparse +install-suitesparse: $(SUITESPARSE_OBJ_TARGET) install-suitesparse-wrapper + # SUITESPARSE WRAPPER ifeq ($(USE_SYSTEM_SUITESPARSE), 1) @@ -696,139 +1062,95 @@ SUITESPARSE_INC = -I /usr/include/suitesparse SUITESPARSE_LIB = -lumfpack -lcholmod -lamd -lcamd -lcolamd -lspqr else SUITESPARSE_INC = -I SuiteSparse-$(SUITESPARSE_VER)/CHOLMOD/Include -I SuiteSparse-$(SUITESPARSE_VER)/SuiteSparse_config -I SuiteSparse-$(SUITESPARSE_VER)/SPQR/Include -SUITESPARSE_LIB = -L$(USR)/lib -lcholmod -lumfpack -lspqr $(RPATH_ORIGIN) +SUITESPARSE_LIB = -L$(BUILD)/lib -lcholmod -lumfpack -lspqr $(RPATH_ORIGIN) +$(BUILD)/lib/libsuitesparse_wrapper.$(SHLIB_EXT): $(SUITESPARSE_OBJ_TARGET) endif -$(USR)/lib/libsuitesparse_wrapper.$(SHLIB_EXT): SuiteSparse_wrapper.c $(SUITESPARSE_OBJ_TARGET) - $(CC) $(CFLAGS) $(LDFLAGS) -O2 -shared $(fPIC) $(SUITESPARSE_INC) SuiteSparse_wrapper.c -o $(USR)/lib/libsuitesparse_wrapper.$(SHLIB_EXT) $(SUITESPARSE_LIB) +$(BUILD)/lib/libsuitesparse_wrapper.$(SHLIB_EXT): SuiteSparse_wrapper.c + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -O2 -shared $(fPIC) $(SUITESPARSE_INC) SuiteSparse_wrapper.c -o $(BUILD)/lib/libsuitesparse_wrapper.$(SHLIB_EXT) $(SUITESPARSE_LIB) $(INSTALL_NAME_CMD)libsuitesparse_wrapper.$(SHLIB_EXT) $@ - touch $@ -install-suitesparse-wrapper: $(USR)/lib/libsuitesparse_wrapper.$(SHLIB_EXT) + touch -c $@ clean-suitesparse-wrapper: - -rm -f $(SUITESPARSE_OBJ_TARGET) $(USR)/lib/libsuitesparse_wrapper.$(SHLIB_EXT) + -rm -f $(SUITESPARSE_OBJ_TARGET) $(BUILD)/lib/libsuitesparse_wrapper.$(SHLIB_EXT) distclean-suitesparse-wrapper: clean-suitesparse-wrapper -## CLP ## - -CLP_OBJ_TARGET = $(USR)/lib/libClp.$(SHLIB_EXT) - -compile-clp: install-clp -install-clp: $(CLP_OBJ_TARGET) +get-suitesparse-wrapper: +configure-suitesparse-wrapper: +compile-suitesparse-wrapper: +check-suitesparse-wrapper: +install-suitesparse-wrapper: $(BUILD)/lib/libsuitesparse_wrapper.$(SHLIB_EXT) -clp-$(CLP_VER).tar.gz: - $(WGET_DASH_O) $@ http://www.coin-or.org/download/source/Clp/Clp-1.14.5.tgz -clp-$(CLP_VER)/configure: clp-$(CLP_VER).tar.gz - mkdir -p clp-$(CLP_VER) - tar -C clp-$(CLP_VER) --strip-components 1 -zxf $< - touch $@ -clp-$(CLP_VER)/config.status: clp-$(CLP_VER)/configure - cd clp-$(CLP_VER) && \ - ./configure --prefix=$(abspath $(USR)) CC="$(CC)" CXX="$(CXX)" -$(CLP_OBJ_TARGET): clp-$(CLP_VER)/config.status - $(MAKE) -C clp-$(CLP_VER) install - touch $@ - -clean-clp: - -$(MAKE) -C clp-$(CLP_VER) clean - -rm -f $(CLP_OBJ_TARGET) -distclean-clp: - -rm -rf clp-$(CLP_VER).tar.gz clp-$(CLP_VER) ## UNWIND ## -ifeq ($(USE_SYSTEM_LIBUNWIND), 0) -LIBUNWIND_TARGET_OBJ = $(USR)/lib/libunwind.a +LIBUNWIND_TARGET_OBJ = $(BUILD)/lib/libunwind.a LIBUNWIND_TARGET_SOURCE = libunwind-$(UNWIND_VER)/src/.libs/libunwind.a -else -LIBUNWIND_TARGET_OBJ = -LIBUNWIND_TARGET_SOURCE = -endif - LIBUNWIND_CFLAGS = $(CFLAGS) -U_FORTIFY_SOURCE $(fPIC) -ifeq ($(ARCH), ppc64) -LIBUNWIND_CFLAGS += -m64 -endif - -compile-unwind: $(LIBUNWIND_TARGET_SOURCE) -install-unwind: $(LIBUNWIND_TARGET_OBJ) libunwind-$(UNWIND_VER).tar.gz: - $(WGET) http://savannah.spinellicreations.com/libunwind/libunwind-$(UNWIND_VER).tar.gz -libunwind-$(UNWIND_VER)/Makefile: libunwind-$(UNWIND_VER).tar.gz + $(WGET_DASH_O) $@ http://download.savannah.gnu.org/releases/libunwind/$@ +libunwind-$(UNWIND_VER)/configure: libunwind-$(UNWIND_VER).tar.gz tar xfz $< - cd libunwind-$(UNWIND_VER) && ./configure CFLAGS="$(LIBUNWIND_CFLAGS)" --prefix=$(abspath $(USR)) CC="$(CC)" CXX="$(CXX)" - -$(LIBUNWIND_TARGET_SOURCE): libunwind-$(UNWIND_VER)/Makefile - cd libunwind-$(UNWIND_VER) && $(MAKE) - + touch -c $@ +libunwind-$(UNWIND_VER)/config.status: libunwind-$(UNWIND_VER)/configure + cd libunwind-$(UNWIND_VER) && \ + ./configure $(CONFIGURE_COMMON) CFLAGS="$(LIBUNWIND_CFLAGS)" --disable-shared --disable-minidebuginfo + touch -c $@ +$(LIBUNWIND_TARGET_SOURCE): libunwind-$(UNWIND_VER)/config.status + $(MAKE) -C libunwind-$(UNWIND_VER) + touch -c $@ +libunwind-$(UNWIND_VER)/checked: $(LIBUNWIND_TARGET_SOURCE) +ifeq ($(OS),$(BUILD_OS)) + $(MAKE) -C libunwind-$(UNWIND_VER) check +endif + echo 1 > $@ +#todo: libunwind tests known to fail $(LIBUNWIND_TARGET_OBJ): $(LIBUNWIND_TARGET_SOURCE) - cd libunwind-$(UNWIND_VER) && $(MAKE) install + $(MAKE) install -C libunwind-$(UNWIND_VER) +ifeq ($(ARCH), ppc64) + # workaround for configure script bug + mv $(BUILD)/lib64/libunwind*.a $(BUILD)/lib/ +endif clean-unwind: -$(MAKE) -C libunwind-$(UNWIND_VER) clean -rm -f $(LIBUNWIND_TARGET_OBJ) $(LIBUNWIND_TARGET_SOURCE) - distclean-unwind: -rm -rf libunwind-$(UNWIND_VER).tar.gz libunwind-$(UNWIND_VER) -## GNU LIGHTTPD ## - -ifeq ($(USE_SYSTEM_LIGHTTPD), 0) -LIGHTTPD_OBJ_TARGET = $(USR)/sbin/lighttpd -else -LIGHTTPD_OBJ_TARGET = -endif - -compile-lighttpd: install-lighttpd -install-lighttpd: $(LIGHTTPD_OBJ_TARGET) lighttpd.conf - mkdir -p $(USR)/etc - cp -f lighttpd.conf $(USR)/etc/lighttpd.conf +get-unwind: libunwind-$(UNWIND_VER).tar.gz +configure-unwind: libunwind-$(UNWIND_VER)/config.status +compile-unwind: $(LIBUNWIND_TARGET_SOURCE) +check-unwind: libunwind-$(UNWIND_VER)/checked +install-unwind: $(LIBUNWIND_TARGET_OBJ) -lighttpd-$(LIGHTTPD_VER).tar.gz: - $(WGET) http://download.lighttpd.net/lighttpd/releases-1.4.x/lighttpd-$(LIGHTTPD_VER).tar.gz -lighttpd-$(LIGHTTPD_VER)/configure: lighttpd-$(LIGHTTPD_VER).tar.gz - tar zxf $< - touch $@ -lighttpd-$(LIGHTTPD_VER)/config.status: lighttpd-$(LIGHTTPD_VER)/configure - mkdir -p $(USR)/lib/lighttpd && \ - cd lighttpd-$(LIGHTTPD_VER) && \ - ./configure --prefix=$(USR) --libdir=$(USR)/lib/lighttpd --without-pcre --without-zlib --without-bzip2 CC="$(CC)" CXX="$(CXX)" -$(LIGHTTPD_OBJ_TARGET): lighttpd-$(LIGHTTPD_VER)/config.status - $(MAKE) -C lighttpd-$(LIGHTTPD_VER) install - touch $@ - -clean-lighttpd: - -$(MAKE) -C lighttpd-$(LIGHTTPD_VER) clean - -rm -f $(LIGHTTPD_OBJ_TARGET) -distclean-lighttpd: - -rm -rf lighttpd-$(LIGHTTPD_VER).tar.gz lighttpd-$(LIGHTTPD_VER) ## GMP ## -ifeq ($(USE_SYSTEM_GMP), 0) -GMP_OBJ_TARGET = $(USR)/lib/libgmp.$(SHLIB_EXT) -else -GMP_OBJ_TARGET = -endif - -compile-gmp: install-gmp -install-gmp: $(GMP_OBJ_TARGET) +GMP_SRC_TARGET = gmp-$(GMP_VER)/.libs/libgmp.$(SHLIB_EXT) +GMP_OBJ_TARGET = $(BUILD)/lib/libgmp.$(SHLIB_EXT) gmp-$(GMP_VER).tar.bz2: - $(WGET) ftp://ftp.gmplib.org/pub/gmp-$(GMP_VER)/$@ + $(WGET_DASH_O) $@ ftp://ftp.gmplib.org/pub/gmp-$(GMP_VER)/$@ gmp-$(GMP_VER)/configure: gmp-$(GMP_VER).tar.bz2 tar jxf $< - touch $@ + touch -c $@ gmp-$(GMP_VER)/config.status: gmp-$(GMP_VER)/configure cd gmp-$(GMP_VER) && \ - ./configure --prefix=$(abspath $(USR)) CC="$(CC)" CXX="$(CXX)" -$(GMP_OBJ_TARGET): gmp-$(GMP_VER)/config.status - $(MAKE) -C gmp-$(GMP_VER) - $(MAKE) -C gmp-$(GMP_VER) check - $(MAKE) -C gmp-$(GMP_VER) install + ./configure $(CONFIGURE_COMMON) F77= --enable-shared --disable-static + touch -c $@ +$(GMP_SRC_TARGET): gmp-$(GMP_VER)/config.status + $(MAKE) -C gmp-$(GMP_VER) $(LIBTOOL_CCLD) +gmp-$(GMP_VER)/checked: $(GMP_SRC_TARGET) +ifeq ($(OS),$(BUILD_OS)) + $(MAKE) -C gmp-$(GMP_VER) $(LIBTOOL_CCLD) check +endif + echo 1 > $@ +$(GMP_OBJ_TARGET): $(GMP_SRC_TARGET) gmp-$(GMP_VER)/checked + $(MAKE) -C gmp-$(GMP_VER) $(LIBTOOL_CCLD) install $(INSTALL_NAME_CMD)libgmp.dylib $@ - touch $@ + touch -c $@ clean-gmp: -$(MAKE) -C gmp-$(GMP_VER) clean @@ -836,106 +1158,57 @@ clean-gmp: distclean-gmp: -rm -rf gmp-$(GMP_VER).tar.bz2 gmp-$(GMP_VER) -## GMP Wrapper - -ifeq ($(USE_SYSTEM_GMP), 1) -GMPW_INC = -GMPW_LIB = -lgmp -else -GMPW_INC = -I $(USRINC) -GMPW_LIB = -L$(USR)/lib/ -lgmp -endif - -$(USR)/lib/libgmp_wrapper.$(SHLIB_EXT): gmp_wrapper.c $(GMP_OBJ_TARGET) | $(USR)/lib - $(CC) $(CFLAGS) $(LDFLAGS) -O2 -shared $(fPIC) $(GMPW_INC) gmp_wrapper.c -o $(USR)/lib/libgmp_wrapper.$(SHLIB_EXT) $(RPATH_ORIGIN) $(GMPW_LIB) - $(INSTALL_NAME_CMD)libgmp_wrapper.$(SHLIB_EXT) $@ - touch $@ -install-gmp-wrapper: $(USR)/lib/libgmp_wrapper.$(SHLIB_EXT) - -clean-gmp-wrapper: - -rm -f $(GMP_OBJ_TARGET) $(USR)/lib/libgmp_wrapper.$(SHLIB_EXT) -distclean-gmp-wrapper: clean-gmp-wrapper +get-gmp: gmp-$(GMP_VER).tar.bz2 +configure-gmp: gmp-$(GMP_VER)/config.status +compile-gmp: $(GMP_SRC_TARGET) +check-gmp: gmp-$(GMP_VER)/checked +install-gmp: $(GMP_OBJ_TARGET) -## GLPK ## +## ZLIB ## -ifeq ($(USE_SYSTEM_GLPK), 1) -GLPK_OBJ_TARGET = +ifeq ($(OS),WINNT) +ZLIB_SRC_TARGET = zlib-$(ZLIB_VER)/zlib1.$(SHLIB_EXT) else -GLPK_OBJ_TARGET = $(USR)/lib/libglpk.$(SHLIB_EXT) +ZLIB_SRC_TARGET = zlib-$(ZLIB_VER)/libz.$(SHLIB_EXT) endif - -compile-glpk: install-glpk -install-glpk: $(GLPK_OBJ_TARGET) $(USR)/lib/libglpk_wrapper.$(SHLIB_EXT) - -glpk-$(GLPK_VER).tar.gz: - $(WGET) http://ftp.gnu.org/gnu/glpk/$@ - -glpk-$(GLPK_VER)/configure: glpk-$(GLPK_VER).tar.gz - tar zxf $< - touch $@ -glpk-$(GLPK_VER)/config.status: glpk-$(GLPK_VER)/configure - cd glpk-$(GLPK_VER) && \ - ./configure --prefix=$(abspath $(USR)) CC="$(CC)" CXX="$(CXX)" -$(GLPK_OBJ_TARGET): glpk-$(GLPK_VER)/config.status - $(MAKE) -C glpk-$(GLPK_VER) install - $(INSTALL_NAME_CMD)libglpk.dylib $@ - touch $@ - -clean-glpk: - -$(MAKE) -C glpk-$(GLPK_VER) uninstall || true - -$(MAKE) -C glpk-$(GLPK_VER) clean -distclean-glpk: clean-glpk - -rm -rf glpk-$(GLPK_VER).tar.bz2 glpk-$(GLPK_VER) - - -## GLPK Wrapper - -ifeq ($(USE_SYSTEM_GLPK), 1) -GLPKW_INC = -I /usr/include/ -GLPKW_LIB = -lglpk +ZLIB_OBJ_TARGET = $(BUILD)/lib/libz.$(SHLIB_EXT) +ZLIB_CONFIGFLAGS = CFLAGS="-O3 $(CFLAGS) -D_FILE_OFFSET_BITS=64" +ifneq ($(OS),$(BUILD_OS)) +ZLIB_CONFIGFLAGS += CHOST=$(XC_HOST) else -GLPKW_INC = -I $(USRINC) -GLPKW_LIB = -L$(USR)/lib -lglpk +ZLIB_CONFIGFLAGS += CC="$(CC)" endif - -$(USR)/lib/libglpk_wrapper.$(SHLIB_EXT): glpk_wrapper.c $(GLPK_OBJ_TARGET) - $(CC) $(CFLAGS) $(LDFLAGS) -O2 -shared $(fPIC) $(GLPKW_INC) glpk_wrapper.c $(GLPKW_LIB) -o $(USR)/lib/libglpk_wrapper.$(SHLIB_EXT) $(RPATH_ORIGIN) - $(INSTALL_NAME_CMD)libglpk_wrapper.$(SHLIB_EXT) $@ - touch $@ -install-glpk-wrapper: $(USR)/lib/libglpk_wrapper.$(SHLIB_EXT) glpk_wrapper.c - -clean-glpk-wrapper: - -rm -f $(GLPK_OBJ_TARGET) $(USR)/lib/libglpk_wrapper.$(SHLIB_EXT) -distclean-glpk-wrapper: clean-glpk-wrapper - -## ZLIB ## - -ifeq ($(USE_SYSTEM_ZLIB), 1) -ZLIB_OBJ_TARGET = -else -ZLIB_OBJ_TARGET = $(USR)/lib/libz.$(SHLIB_EXT) -ZLIB_CFLAGS = CFLAGS="$(CFLAGS) -D_FILE_OFFSET_BITS=64" -endif - -compile-zlib: install-zlib -install-zlib: $(ZLIB_OBJ_TARGET) - zlib-$(ZLIB_VER).tar.gz: - $(WGET) http://zlib.net/$@ + $(WGET_DASH_O) $@ http://zlib.net/$@ zlib-$(ZLIB_VER)/configure: zlib-$(ZLIB_VER).tar.gz tar zxf $< - touch $@ + touch -c $@ zlib-$(ZLIB_VER)/config.status: zlib-$(ZLIB_VER)/configure +ifeq ($(OS), WINNT) + cd zlib-$(ZLIB_VER) && \ + cp win32/Makefile.gcc Makefile +else cd zlib-$(ZLIB_VER) && \ - CC="$(CC)" $(ZLIB_CFLAGS) ./configure --prefix=$(abspath $(USR)) - touch $@ -$(ZLIB_OBJ_TARGET): zlib-$(ZLIB_VER)/config.status - $(MAKE) -C zlib-$(ZLIB_VER) - $(MAKE) -C zlib-$(ZLIB_VER) check - $(MAKE) -C zlib-$(ZLIB_VER) install + $(ZLIB_CONFIGFLAGS) ./configure --prefix=$(abspath $(BUILD)) #not an autoconf script +endif + echo 1 > $@ +$(ZLIB_SRC_TARGET): zlib-$(ZLIB_VER)/config.status + $(MAKE) -C zlib-$(ZLIB_VER) PREFIX=$(CROSS_COMPILE) + touch -c $@ +zlib-$(ZLIB_VER)/checked: $(ZLIB_SRC_TARGET) +ifneq ($(OS), WINNT) + $(MAKE) -C zlib-$(ZLIB_VER) check PREFIX=$(CROSS_COMPILE) +endif + echo 1 > $@ +$(ZLIB_OBJ_TARGET): $(ZLIB_SRC_TARGET) zlib-$(ZLIB_VER)/checked +ifeq ($(OS), WINNT) + cp zlib-$(ZLIB_VER)/zlib1.dll $@ +else + $(MAKE) -C zlib-$(ZLIB_VER) install PREFIX=$(CROSS_COMPILE) +endif $(INSTALL_NAME_CMD)libz.dylib $@ - touch $@ + touch -c $@ clean-zlib: -$(MAKE) -j$(PARALLEL_BUILD_JOBS) -C zlib-$(ZLIB_VER) clean @@ -943,52 +1216,42 @@ clean-zlib: distclean-zlib: -rm -rf zlib-$(ZLIB_VER).tar.gz zlib-$(ZLIB_VER) -## Tk wrapper ## - -TKW_INC = -I $(USRINC) -I $(JULIAHOME)/src -I $(JULIAHOME)/src/support -TKW_LIB = -ifeq ($(OS), Darwin) - ifneq ($(wildcard /opt/local/bin/port),) - TKW_INC += -I/opt/local/include - TKW_LIB += -L/opt/local/lib - else ifneq ($(wildcard /usr/local/bin/brew),) - TKW_INC += -I/usr/local/include - TKW_LIB += -L/usr/local/lib - endif - TKW_INC += -I/opt/X11/include -I/usr/X11/include -else - TKW_INC += -I/usr/include/tcl -endif -TKW_LIB += -ltcl8.5 -ltk8.5 -L$(USR)/lib/ -ljulia-release - -$(USR)/lib/libtk_wrapper.$(SHLIB_EXT): tk_wrapper.c - $(CC) $(CFLAGS) $(LDFLAGS) -O2 -shared $(fPIC) $(TKW_INC) tk_wrapper.c $(TKW_LIB) -o $(USR)/lib/libtk_wrapper.$(SHLIB_EXT) - $(INSTALL_NAME_CMD)libtk_wrapper.$(SHLIB_EXT) $@ - touch $@ -install-tk-wrapper: $(USR)/lib/libtk_wrapper.$(SHLIB_EXT) tk_wrapper.c +get-zlib: zlib-$(ZLIB_VER).tar.gz +configure-zlib: zlib-$(ZLIB_VER)/config.status +compile-zlib: $(ZLIB_SRC_TARGET) +check-zlib: zlib-$(ZLIB_VER)/checked +install-zlib: $(ZLIB_OBJ_TARGET) -clean-tk-wrapper: - -rm -f $(USR)/lib/libtk_wrapper.$(SHLIB_EXT) -distclean-tk-wrapper: clean-tk-wrapper -## patchelf +## patchelf ## -PATCHELF_TARGET = $(USR)/bin/patchelf +PATCHELF_SOURCE = patchelf-$(PATCHELF_VER)/src/patchelf +PATCHELF_TARGET = $(BUILD)/bin/patchelf compile-patchelf: install-patchelf install-patchelf: $(PATCHELF_TARGET) patchelf-$(PATCHELF_VER).tar.bz2: - $(WGET) http://hydra.nixos.org/build/1524660/download/2/$@ + $(WGET_DASH_O) $@ http://hydra.nixos.org/build/1524660/download/2/$@ patchelf-$(PATCHELF_VER)/configure: patchelf-$(PATCHELF_VER).tar.bz2 tar jxf $< - touch $@ + touch -c $@ patchelf-$(PATCHELF_VER)/config.status: patchelf-$(PATCHELF_VER)/configure cd patchelf-$(PATCHELF_VER) && \ - ./configure --prefix=$(abspath $(USR)) CC="$(CC)" CXX="$(CXX)" -$(PATCHELF_TARGET): patchelf-$(PATCHELF_VER)/config.status + ./configure $(CONFIGURE_COMMON) + touch -c $@ +$(PATCHELF_SOURCE): patchelf-$(PATCHELF_VER)/config.status + $(MAKE) -C patchelf-$(PATCHELF_VER) + touch -c $@ +patchelf-$(PATCHELF_VER)/checked: $(PATCHELF_SOURCE) +ifeq ($(OS),$(BUILD_OS)) + # disabled due to bug in v0.6 + #$(MAKE) -C patchelf-$(PATCHELF_VER) check +endif + echo 1 > $@ +$(PATCHELF_TARGET): $(PATCHELF_SOURCE) patchelf-$(PATCHELF_VER)/checked $(MAKE) -C patchelf-$(PATCHELF_VER) install - touch $@ + touch -c $@ clean-patchelf: -$(MAKE) -C patchelf-$(PATCHELF_VER) clean @@ -996,8 +1259,51 @@ clean-patchelf: distclean-patchelf: -rm -rf patchelf-$(PATCHELF_VER).tar.bz2 patchelf-$(PATCHELF_VER) +get-patchelf: patchelf-$(PATCHELF_VER).tar.bz2 +configure-patchelf: patchelf-$(PATCHELF_VER)/config.status +compile-patchelf: $(PATCHELF_SOURCE) +check-patchelf: patchelf-$(PATCHELF_VER)/checked +install-patchelf: $(PATCHELF_TARGET) + +## Git + +GIT_SOURCE = git-$(GIT_VER)/src/git +GIT_TARGET = $(BUILD)/git + +git-$(GIT_VER).tar.gz: + $(WGET_DASH_O) $@ http://git-core.googlecode.com/files/$@ +git-$(GIT_VER)/configure: git-$(GIT_VER).tar.gz + tar zxf $< + touch -c $@ +git-$(GIT_VER)/config.status: git-$(GIT_VER)/configure + cd git-$(GIT_VER) && \ + ./configure $(CONFIGURE_COMMON) + touch -c $@ +$(GIT_SOURCE): git-$(GIT_VER)/config.status + $(MAKE) -C git-$(GIT_VER) + touch -c $@ +git-$(GIT_VER)/checked: $(GIT_SOURCE) + echo 1 > $@ +$(GIT_TARGET): $(GIT_SOURCE) git-$(GIT_VER)/checked + $(MAKE) -C git-$(GIT_VER) install NO_INSTALL_HARDLINKS=1 + touch -c $@ + +clean-git: + -$(MAKE) -C git-$(GIT_VER) clean + -rm -f $(GIT_OBJ_TARGET) +distclean-git: + -rm -rf git-$(GIT_VER).tar.gz git-$(GIT_VER) + +get-git: git-$(GIT_VER).tar.gz +configure-git: git-$(GIT_VER)/config.status +compile-git: $(GIT_SOURCE) +check-git: git-$(GIT_VER)/checked +install-git: $(GIT_TARGET) + ## phony targets ## .PHONY: \ default compile install cleanall distclean \ - compile-* install-* clean-* distclean-* + get-* configure-* compile-* check-* install-* \ + clean-* distclean-* + diff --git a/deps/Rmath b/deps/Rmath new file mode 160000 index 0000000000000..85dee98a799c1 --- /dev/null +++ b/deps/Rmath @@ -0,0 +1 @@ +Subproject commit 85dee98a799c193bedf6af35c839de08c2d233f6 diff --git a/deps/Rmath/include/R_ext/Arith.h b/deps/Rmath/include/R_ext/Arith.h deleted file mode 100644 index bcb1f4a7789ea..0000000000000 --- a/deps/Rmath/include/R_ext/Arith.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * R : A Computer Language for Statistical Data Analysis - * Copyright (C) 1995, 1996 Robert Gentleman and Ross Ihaka - * Copyright (C) 1998--2007 The R Development Core Team. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - */ - -#ifndef R_ARITH_H_ -#define R_ARITH_H_ - -/* Only for use where config.h has not already been included */ -#if defined(HAVE_GLIBC2) && !defined(_BSD_SOURCE) -/* ensure that finite and isnan are declared */ -# define _BSD_SOURCE 1 -#endif - -#include -#ifdef __cplusplus -extern "C" { -#elif !defined(NO_C_HEADERS) -/* needed for isnan and isfinite, neither of which are used under C++ */ -# include -#endif - -/* implementation of these : ../../main/arithmetic.c */ -LibExtern double R_NaN; /* IEEE NaN */ -LibExtern double R_PosInf; /* IEEE Inf */ -LibExtern double R_NegInf; /* IEEE -Inf */ -LibExtern double R_NaReal; /* NA_REAL: IEEE */ -LibExtern int R_NaInt; /* NA_INTEGER:= INT_MIN currently */ -#ifdef __MAIN__ -#undef extern -#undef LibExtern -#endif - -#define NA_LOGICAL R_NaInt -#define NA_INTEGER R_NaInt -/* #define NA_FACTOR R_NaInt unused */ -#define NA_REAL R_NaReal -/* NA_STRING is a SEXP, so defined in Rinternals.h */ - -int R_IsNA(double); /* True for R's NA only */ -int R_IsNaN(double); /* True for special NaN, *not* for NA */ -int R_finite(double); /* True if none of NA, NaN, +/-Inf */ -#define ISNA(x) R_IsNA(x) - -/* ISNAN(): True for *both* NA and NaN. - NOTE: some systems do not return 1 for TRUE. - Also note that C++ math headers specifically undefine - isnan if it is a macro (it is on OS X and in C99), - hence the workaround. This code also appears in Rmath.h -*/ -#ifdef __cplusplus - int R_isnancpp(double); /* in arithmetic.c */ -# define ISNAN(x) R_isnancpp(x) -#else -# define ISNAN(x) (isnan(x)!=0) -#endif - -/* The following is only defined inside R */ -#ifdef HAVE_WORKING_ISFINITE -/* isfinite is defined in according to C99 */ -# define R_FINITE(x) isfinite(x) -#else -# define R_FINITE(x) R_finite(x) -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* R_ARITH_H_ */ diff --git a/deps/Rmath/include/R_ext/Boolean.h b/deps/Rmath/include/R_ext/Boolean.h deleted file mode 100644 index 007f5ca2f3716..0000000000000 --- a/deps/Rmath/include/R_ext/Boolean.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * R : A Computer Language for Statistical Data Analysis - * Copyright (C) 2000, 2001 The R Development Core Team. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - */ - -#ifndef R_EXT_BOOLEAN_H_ -#define R_EXT_BOOLEAN_H_ - -#undef FALSE -#undef TRUE - -#ifdef __cplusplus -extern "C" { -#endif -typedef enum { FALSE = 0, TRUE /*, MAYBE */ } Rboolean; - -#ifdef __cplusplus -} -#endif - -#endif /* R_EXT_BOOLEAN_H_ */ diff --git a/deps/Rmath/include/R_ext/Error.h b/deps/Rmath/include/R_ext/Error.h deleted file mode 100644 index e76643c97ea66..0000000000000 --- a/deps/Rmath/include/R_ext/Error.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * R : A Computer Language for Statistical Data Analysis - * Copyright (C) 1998-2005 Robert Gentleman, Ross Ihaka - * and the R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - */ - -#ifndef R_ERROR_H_ -#define R_ERROR_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -void Rf_error(const char *, ...); -void Rf_warning(const char *, ...); -void WrongArgCount(const char *); -void UNIMPLEMENTED(const char *); -void R_ShowMessage(const char *s); - - -#ifdef __cplusplus -} -#endif - -#ifndef R_NO_REMAP -#define error Rf_error -#define warning Rf_warning -#endif - - -#endif /* R_ERROR_H_ */ diff --git a/deps/Rmath/include/R_ext/Print.h b/deps/Rmath/include/R_ext/Print.h deleted file mode 100644 index 9516f125c4fd0..0000000000000 --- a/deps/Rmath/include/R_ext/Print.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * R : A Computer Language for Statistical Data Analysis - * Copyright (C) 1998-2010 Robert Gentleman, Ross Ihaka - * and the R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - */ -#ifndef R_EXT_PRINT_H_ -#define R_EXT_PRINT_H_ - -#ifdef __cplusplus -/* If the vprintf interface is defined at all in C++ it may only be - defined in namespace std. */ -# ifdef R_USE_C99_IN_CXX -# include -# ifdef __SUNPRO_CC -using _STLP_VENDOR_CSTD::va_list; -# endif -# endif -extern "C" { -#else -# include -#endif - -void Rprintf(const char *, ...); -void REprintf(const char *, ...); -#if !defined(__cplusplus) || defined R_USE_C99_IN_CXX -void Rvprintf(const char *, va_list); -void REvprintf(const char *, va_list); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* R_EXT_PRINT_H_ */ diff --git a/deps/Rmath/include/R_ext/RS.h b/deps/Rmath/include/R_ext/RS.h deleted file mode 100644 index 609f86d6e5ed8..0000000000000 --- a/deps/Rmath/include/R_ext/RS.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * R : A Computer Language for Statistical Data Analysis - * Copyright (C) 1999-2007 The R Development Core Team. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - */ - -#ifndef R_RS_H -#define R_RS_H - -#ifndef NO_C_HEADERS -# include /* for memcpy */ -#endif - -#include /* for F77_APPEND_UNDERSCORE */ - -#ifdef __cplusplus -extern "C" { -#endif - -/* S Like Error Handling */ - -#include /* for error and warning */ - -#ifndef STRICT_R_HEADERS - -#define R_PROBLEM_BUFSIZE 4096 -/* Parentheses added for FC4 with gcc4 and -D_FORTIFY_SOURCE=2 */ -#define PROBLEM {char R_problem_buf[R_PROBLEM_BUFSIZE];(sprintf)(R_problem_buf, -#define MESSAGE {char R_problem_buf[R_PROBLEM_BUFSIZE];(sprintf)(R_problem_buf, -#define ERROR ),error(R_problem_buf);} -#define RECOVER(x) ),error(R_problem_buf);} -#define WARNING(x) ),warning(R_problem_buf);} -#define LOCAL_EVALUATOR /**/ -#define NULL_ENTRY /**/ -#define WARN WARNING(NULL) - -#endif - -/* S Like Memory Management */ - -extern void *R_chk_calloc(size_t, size_t); -extern void *R_chk_realloc(void *, size_t); -extern void R_chk_free(void *); - -#ifndef STRICT_R_HEADERS -/* S-PLUS 3.x but not 5.x NULLs the pointer in the following */ -#define Calloc(n, t) (t *) R_chk_calloc( (size_t) (n), sizeof(t) ) -#define Realloc(p,n,t) (t *) R_chk_realloc( (void *)(p), (size_t)((n) * sizeof(t)) ) -#define Free(p) (R_chk_free( (void *)(p) ), (p) = NULL) -#endif -#define R_Calloc(n, t) (t *) R_chk_calloc( (size_t) (n), sizeof(t) ) -#define R_Realloc(p,n,t) (t *) R_chk_realloc( (void *)(p), (size_t)((n) * sizeof(t)) ) -#define R_Free(p) (R_chk_free( (void *)(p) ), (p) = NULL) - -#define Memcpy(p,q,n) memcpy( p, q, (size_t)( (n) * sizeof(*p) ) ) - -#define CallocCharBuf(n) (char *) R_chk_calloc((size_t) ((n)+1), sizeof(char)) - -/* S Like Fortran Interface */ -/* These may not be adequate everywhere. Convex had _ prepending common - blocks, and some compilers may need to specify Fortran linkage */ - -#ifdef HAVE_F77_UNDERSCORE -# define F77_CALL(x) x ## _ -#else -# define F77_CALL(x) x -#endif -#define F77_NAME(x) F77_CALL(x) -#define F77_SUB(x) F77_CALL(x) -#define F77_COM(x) F77_CALL(x) -#define F77_COMDECL(x) F77_CALL(x) - -void call_R(char*, long, void**, char**, long*, char**, long, char**); - -#ifdef __cplusplus -} -#endif - -#endif /* R_RS_H */ diff --git a/deps/Rmath/include/R_ext/Random.h b/deps/Rmath/include/R_ext/Random.h deleted file mode 100644 index 7e5e8e84ab1fb..0000000000000 --- a/deps/Rmath/include/R_ext/Random.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * R : A Computer Language for Statistical Data Analysis - * Copyright (C) 1998-2011 Robert Gentleman, Ross Ihaka - * and the R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - */ - -#ifndef R_RANDOM_H -#define R_RANDOM_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -typedef enum { - WICHMANN_HILL, - MARSAGLIA_MULTICARRY, - SUPER_DUPER, - MERSENNE_TWISTER, - KNUTH_TAOCP, - USER_UNIF, - KNUTH_TAOCP2, - LECUYER_CMRG -} RNGtype; - -/* Different kinds of "N(0,1)" generators :*/ -typedef enum { - BUGGY_KINDERMAN_RAMAGE, - AHRENS_DIETER, - BOX_MULLER, - USER_NORM, - INVERSION, - KINDERMAN_RAMAGE -} N01type; - - -void GetRNGstate(void); -void PutRNGstate(void); - -double unif_rand(void); -/* These are also defined in Rmath.h */ -double norm_rand(void); -double exp_rand(void); - -typedef unsigned int Int32; -double * user_unif_rand(void); -void user_unif_init(Int32); -int * user_unif_nseed(void); -int * user_unif_seedloc(void); - -double * user_norm_rand(void); - -void FixupProb(double *, int, int, Rboolean); - -#ifdef __cplusplus -} -#endif - -#endif /* R_RANDOM_H */ diff --git a/deps/Rmath/include/R_ext/libextern.h b/deps/Rmath/include/R_ext/libextern.h deleted file mode 100644 index 5f3b6ced72fd3..0000000000000 --- a/deps/Rmath/include/R_ext/libextern.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * R : A Computer Language for Statistical Data Analysis - * Copyright (C) 2001, 2004 The R Development Core Team. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - */ - -/* don't disallow including this one more than once */ - -/* This is intended to be called from other header files, so not callable - from C++ */ - -#undef LibExtern -#undef LibImport -#undef LibExport - -/* Don't try to include CYGWIN here: decorating some symbols breaks - the auto-export that it relies on, even if R_DLL_BUILD were set. */ -#ifdef WIN32 /* WIN32 as does not depend on config.h */ -#define LibImport __declspec(dllimport) -#define LibExport __declspec(dllexport) -#else -#define LibImport -#define LibExport -#endif - -#ifdef __MAIN__ -#define LibExtern LibExport -#define extern -#elif defined(R_DLL_BUILD) -#define LibExtern extern -#else -#define LibExtern extern LibImport -#endif diff --git a/deps/Rmath/include/Rconfig.h b/deps/Rmath/include/Rconfig.h deleted file mode 100644 index 1512cee611259..0000000000000 --- a/deps/Rmath/include/Rconfig.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Rconfig.h. Generated automatically */ -#ifndef R_RCONFIG_H -#define R_RCONFIG_H - -#ifndef R_CONFIG_H - -#define HAVE_F77_UNDERSCORE 1 -#define IEEE_754 1 -/* #undef WORDS_BIGENDIAN */ -#define R_INLINE inline -/* #undef HAVE_VISIBILITY_ATTRIBUTE */ -#define SUPPORT_UTF8 1 -#define SUPPORT_MBCS 1 -#define ENABLE_NLS 1 -#define HAVE_AQUA 1 -#define SUPPORT_OPENMP 1 - -#endif /* not R_CONFIG_H */ - -#endif /* not R_RCONFIG_H */ diff --git a/deps/Rmath/include/Rmath.h b/deps/Rmath/include/Rmath.h deleted file mode 100644 index 0ecbbde2c2eb1..0000000000000 --- a/deps/Rmath/include/Rmath.h +++ /dev/null @@ -1,653 +0,0 @@ -/* -*- C -*- - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998-2011 The R Development Core Team - * Copyright (C) 2004 The R Foundation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - - * Rmath.h should contain ALL headers from R's C code in `src/nmath' - ------- such that ``the Math library'' can be used by simply - - ``#include '' - - and nothing else. -*/ -#ifndef RMATH_H -#define RMATH_H - -/* Note that on some systems we need to include math.h before the - defines below, to avoid redefining ftrunc */ -#ifndef NO_C_HEADERS -# include -#endif - -/*-- Mathlib as part of R -- define this for standalone : */ -/* #undef MATHLIB_STANDALONE */ - -#define R_VERSION_STRING "2.14.2" - -#ifndef HAVE_EXPM1 -# define HAVE_EXPM1 1 -#endif - -#ifndef HAVE_HYPOT -# define HAVE_HYPOT 1 -#endif - -#ifndef HAVE_LOG1P -# define HAVE_LOG1P 1 -#endif - -#ifndef HAVE_WORKING_LOG1P -# define HAVE_WORKING_LOG1P 1 -#endif - -#if defined(HAVE_LOG1P) && !defined(HAVE_WORKING_LOG1P) -/* remap to avoid problems with getting the right entry point */ -double Rlog1p(double); -#define log1p Rlog1p -#endif - - - /* Undo SGI Madness */ - -#ifdef ftrunc -# undef ftrunc -#endif -#ifdef qexp -# undef qexp -#endif -#ifdef qgamma -# undef qgamma -#endif - - -/* ----- The following constants and entry points are part of the R API ---- */ - -/* 30 Decimal-place constants */ -/* Computed with bc -l (scale=32; proper round) */ - -/* SVID & X/Open Constants */ -/* Names from Solaris math.h */ - -#ifndef M_E -#define M_E 2.718281828459045235360287471353 /* e */ -#endif - -#ifndef M_LOG2E -#define M_LOG2E 1.442695040888963407359924681002 /* log2(e) */ -#endif - -#ifndef M_LOG10E -#define M_LOG10E 0.434294481903251827651128918917 /* log10(e) */ -#endif - -#ifndef M_LN2 -#define M_LN2 0.693147180559945309417232121458 /* ln(2) */ -#endif - -#ifndef M_LN10 -#define M_LN10 2.302585092994045684017991454684 /* ln(10) */ -#endif - -#ifndef M_PI -#define M_PI 3.141592653589793238462643383280 /* pi */ -#endif - -#ifndef M_2PI -#define M_2PI 6.283185307179586476925286766559 /* 2*pi */ -#endif - -#ifndef M_PI_2 -#define M_PI_2 1.570796326794896619231321691640 /* pi/2 */ -#endif - -#ifndef M_PI_4 -#define M_PI_4 0.785398163397448309615660845820 /* pi/4 */ -#endif - -#ifndef M_1_PI -#define M_1_PI 0.318309886183790671537767526745 /* 1/pi */ -#endif - -#ifndef M_2_PI -#define M_2_PI 0.636619772367581343075535053490 /* 2/pi */ -#endif - -#ifndef M_2_SQRTPI -#define M_2_SQRTPI 1.128379167095512573896158903122 /* 2/sqrt(pi) */ -#endif - -#ifndef M_SQRT2 -#define M_SQRT2 1.414213562373095048801688724210 /* sqrt(2) */ -#endif - -#ifndef M_SQRT1_2 -#define M_SQRT1_2 0.707106781186547524400844362105 /* 1/sqrt(2) */ -#endif - -/* R-Specific Constants */ - -#ifndef M_SQRT_3 -#define M_SQRT_3 1.732050807568877293527446341506 /* sqrt(3) */ -#endif - -#ifndef M_SQRT_32 -#define M_SQRT_32 5.656854249492380195206754896838 /* sqrt(32) */ -#endif - -#ifndef M_LOG10_2 -#define M_LOG10_2 0.301029995663981195213738894724 /* log10(2) */ -#endif - -#ifndef M_SQRT_PI -#define M_SQRT_PI 1.772453850905516027298167483341 /* sqrt(pi) */ -#endif - -#ifndef M_1_SQRT_2PI -#define M_1_SQRT_2PI 0.398942280401432677939946059934 /* 1/sqrt(2pi) */ -#endif - -#ifndef M_SQRT_2dPI -#define M_SQRT_2dPI 0.797884560802865355879892119869 /* sqrt(2/pi) */ -#endif - - -#ifndef M_LN_SQRT_PI -#define M_LN_SQRT_PI 0.572364942924700087071713675677 /* log(sqrt(pi)) - == log(pi)/2 */ -#endif - -#ifndef M_LN_SQRT_2PI -#define M_LN_SQRT_2PI 0.918938533204672741780329736406 /* log(sqrt(2*pi)) - == log(2*pi)/2 */ -#endif - -#ifndef M_LN_SQRT_PId2 -#define M_LN_SQRT_PId2 0.225791352644727432363097614947 /* log(sqrt(pi/2)) */ -#endif - - -#ifdef MATHLIB_STANDALONE -# ifndef R_EXT_BOOLEAN_H_ -/* "copy-paste" R_ext/Boolean.h if not already included: */ - #define R_EXT_BOOLEAN_H_ - #undef FALSE - #undef TRUE - typedef enum { FALSE = 0, TRUE } Rboolean; -# endif -#else -# include -#endif - - -#ifndef MATHLIB_STANDALONE -#define bessel_i Rf_bessel_i -#define bessel_j Rf_bessel_j -#define bessel_k Rf_bessel_k -#define bessel_y Rf_bessel_y -#define bessel_i_ex Rf_bessel_i_ex -#define bessel_j_ex Rf_bessel_j_ex -#define bessel_k_ex Rf_bessel_k_ex -#define bessel_y_ex Rf_bessel_y_ex -#define beta Rf_beta -#define choose Rf_choose -#define dbeta Rf_dbeta -#define dbinom Rf_dbinom -#define dcauchy Rf_dcauchy -#define dchisq Rf_dchisq -#define dexp Rf_dexp -#define df Rf_df -#define dgamma Rf_dgamma -#define dgeom Rf_dgeom -#define dhyper Rf_dhyper -#define digamma Rf_digamma -#define dlnorm Rf_dlnorm -#define dlogis Rf_dlogis -#define dnbeta Rf_dnbeta -#define dnbinom Rf_dnbinom -#define dnchisq Rf_dnchisq -#define dnf Rf_dnf -#define dnorm4 Rf_dnorm4 -#define dnt Rf_dnt -#define dpois Rf_dpois -#define dpsifn Rf_dpsifn -#define dsignrank Rf_dsignrank -#define dt Rf_dt -#define dtukey Rf_dtukey -#define dunif Rf_dunif -#define dweibull Rf_dweibull -#define dwilcox Rf_dwilcox -#define fmax2 Rf_fmax2 -#define fmin2 Rf_fmin2 -#define fprec Rf_fprec -#define fround Rf_fround -#define ftrunc Rf_ftrunc -#define fsign Rf_fsign -#define gammafn Rf_gammafn -#define imax2 Rf_imax2 -#define imin2 Rf_imin2 -#define lbeta Rf_lbeta -#define lchoose Rf_lchoose -#define lgammafn Rf_lgammafn -#define lgammafn_sign Rf_lgammafn_sign -#define lgamma1p Rf_lgamma1p -#define log1pmx Rf_log1pmx -#define logspace_add Rf_logspace_add -#define logspace_sub Rf_logspace_sub -#define pbeta Rf_pbeta -#define pbeta_raw Rf_pbeta_raw -#define pbinom Rf_pbinom -#define pcauchy Rf_pcauchy -#define pchisq Rf_pchisq -#define pentagamma Rf_pentagamma -#define pexp Rf_pexp -#define pf Rf_pf -#define pgamma Rf_pgamma -#define pgeom Rf_pgeom -#define phyper Rf_phyper -#define plnorm Rf_plnorm -#define plogis Rf_plogis -#define pnbeta Rf_pnbeta -#define pnbinom Rf_pnbinom -#define pnchisq Rf_pnchisq -#define pnf Rf_pnf -#define pnorm5 Rf_pnorm5 -#define pnorm_both Rf_pnorm_both -#define pnt Rf_pnt -#define ppois Rf_ppois -#define psignrank Rf_psignrank -#define psigamma Rf_psigamma -#define pt Rf_pt -#define ptukey Rf_ptukey -#define punif Rf_punif -#define pythag Rf_pythag -#define pweibull Rf_pweibull -#define pwilcox Rf_pwilcox -#define qbeta Rf_qbeta -#define qbinom Rf_qbinom -#define qcauchy Rf_qcauchy -#define qchisq Rf_qchisq -#define qchisq_appr Rf_qchisq_appr -#define qexp Rf_qexp -#define qf Rf_qf -#define qgamma Rf_qgamma -#define qgeom Rf_qgeom -#define qhyper Rf_qhyper -#define qlnorm Rf_qlnorm -#define qlogis Rf_qlogis -#define qnbeta Rf_qnbeta -#define qnbinom Rf_qnbinom -#define qnchisq Rf_qnchisq -#define qnf Rf_qnf -#define qnorm5 Rf_qnorm5 -#define qnt Rf_qnt -#define qpois Rf_qpois -#define qsignrank Rf_qsignrank -#define qt Rf_qt -#define qtukey Rf_qtukey -#define qunif Rf_qunif -#define qweibull Rf_qweibull -#define qwilcox Rf_qwilcox -#define rbeta Rf_rbeta -#define rbinom Rf_rbinom -#define rcauchy Rf_rcauchy -#define rchisq Rf_rchisq -#define rexp Rf_rexp -#define rf Rf_rf -#define rgamma Rf_rgamma -#define rgeom Rf_rgeom -#define rhyper Rf_rhyper -#define rlnorm Rf_rlnorm -#define rlogis Rf_rlogis -#define rnbeta Rf_rnbeta -#define rnbinom Rf_rnbinom -#define rnchisq Rf_rnchisq -#define rnf Rf_rnf -#define rnorm Rf_rnorm -#define rnt Rf_rnt -#define rpois Rf_rpois -#define rsignrank Rf_rsignrank -#define rt Rf_rt -#define rtukey Rf_rtukey -#define runif Rf_runif -#define rweibull Rf_rweibull -#define rwilcox Rf_rwilcox -#define sign Rf_sign -#define tetragamma Rf_tetragamma -#define trigamma Rf_trigamma -#endif - -#define rround fround -#define prec fprec -#undef trunc -#define trunc ftrunc - -#ifdef __cplusplus -extern "C" { -#endif - /* R's versions with !R_FINITE checks */ - -double R_pow(double x, double y); -double R_pow_di(double, int); - - /* Random Number Generators */ - -double norm_rand(void); -double unif_rand(void); -double exp_rand(void); -#ifdef MATHLIB_STANDALONE -void set_seed(unsigned int, unsigned int); -void get_seed(unsigned int *, unsigned int *); -#endif - - /* Normal Distribution */ - -#define pnorm pnorm5 -#define qnorm qnorm5 -#define dnorm dnorm4 - -double dnorm(double, double, double, int); -double pnorm(double, double, double, int, int); -double qnorm(double, double, double, int, int); -double rnorm(double, double); -void pnorm_both(double, double *, double *, int, int);/* both tails */ - - /* Uniform Distribution */ - -double dunif(double, double, double, int); -double punif(double, double, double, int, int); -double qunif(double, double, double, int, int); -double runif(double, double); - - /* Gamma Distribution */ - -double dgamma(double, double, double, int); -double pgamma(double, double, double, int, int); -double qgamma(double, double, double, int, int); -double rgamma(double, double); - -double log1pmx(double); -double lgamma1p(double); -double logspace_add(double, double); -double logspace_sub(double, double); - - /* Beta Distribution */ - -double dbeta(double, double, double, int); -double pbeta(double, double, double, int, int); -double qbeta(double, double, double, int, int); -double rbeta(double, double); - - /* Lognormal Distribution */ - -double dlnorm(double, double, double, int); -double plnorm(double, double, double, int, int); -double qlnorm(double, double, double, int, int); -double rlnorm(double, double); - - /* Chi-squared Distribution */ - -double dchisq(double, double, int); -double pchisq(double, double, int, int); -double qchisq(double, double, int, int); -double rchisq(double); - - /* Non-central Chi-squared Distribution */ - -double dnchisq(double, double, double, int); -double pnchisq(double, double, double, int, int); -double qnchisq(double, double, double, int, int); -double rnchisq(double, double); - - /* F Distibution */ - -double df(double, double, double, int); -double pf(double, double, double, int, int); -double qf(double, double, double, int, int); -double rf(double, double); - - /* Student t Distibution */ - -double dt(double, double, int); -double pt(double, double, int, int); -double qt(double, double, int, int); -double rt(double); - - /* Binomial Distribution */ - -double dbinom(double, double, double, int); -double pbinom(double, double, double, int, int); -double qbinom(double, double, double, int, int); -double rbinom(double, double); - - /* Multnomial Distribution */ - -void rmultinom(int, double*, int, int*); - - /* Cauchy Distribution */ - -double dcauchy(double, double, double, int); -double pcauchy(double, double, double, int, int); -double qcauchy(double, double, double, int, int); -double rcauchy(double, double); - - /* Exponential Distribution */ - -double dexp(double, double, int); -double pexp(double, double, int, int); -double qexp(double, double, int, int); -double rexp(double); - - /* Geometric Distribution */ - -double dgeom(double, double, int); -double pgeom(double, double, int, int); -double qgeom(double, double, int, int); -double rgeom(double); - - /* Hypergeometric Distibution */ - -double dhyper(double, double, double, double, int); -double phyper(double, double, double, double, int, int); -double qhyper(double, double, double, double, int, int); -double rhyper(double, double, double); - - /* Negative Binomial Distribution */ - -double dnbinom(double, double, double, int); -double pnbinom(double, double, double, int, int); -double qnbinom(double, double, double, int, int); -double rnbinom(double, double); - -double dnbinom_mu(double, double, double, int); -double pnbinom_mu(double, double, double, int, int); -double qnbinom_mu(double, double, double, int, int); -double rnbinom_mu(double, double); - - /* Poisson Distribution */ - -double dpois(double, double, int); -double ppois(double, double, int, int); -double qpois(double, double, int, int); -double rpois(double); - - /* Weibull Distribution */ - -double dweibull(double, double, double, int); -double pweibull(double, double, double, int, int); -double qweibull(double, double, double, int, int); -double rweibull(double, double); - - /* Logistic Distribution */ - -double dlogis(double, double, double, int); -double plogis(double, double, double, int, int); -double qlogis(double, double, double, int, int); -double rlogis(double, double); - - /* Non-central Beta Distribution */ - -double dnbeta(double, double, double, double, int); -double pnbeta(double, double, double, double, int, int); -double qnbeta(double, double, double, double, int, int); -double rnbeta(double, double, double); - - /* Non-central F Distribution */ - -double dnf(double, double, double, double, int); -double pnf(double, double, double, double, int, int); -double qnf(double, double, double, double, int, int); - - /* Non-central Student t Distribution */ - -double dnt(double, double, double, int); -double pnt(double, double, double, int, int); -double qnt(double, double, double, int, int); - - /* Studentized Range Distribution */ - -double ptukey(double, double, double, double, int, int); -double qtukey(double, double, double, double, int, int); - - /* Wilcoxon Rank Sum Distribution */ - -double dwilcox(double, double, double, int); -double pwilcox(double, double, double, int, int); -double qwilcox(double, double, double, int, int); -double rwilcox(double, double); - - /* Wilcoxon Signed Rank Distribution */ - -double dsignrank(double, double, int); -double psignrank(double, double, int, int); -double qsignrank(double, double, int, int); -double rsignrank(double); - - /* Gamma and Related Functions */ -double gammafn(double); -double lgammafn(double); -double lgammafn_sign(double, int*); -void dpsifn(double, int, int, int, double*, int*, int*); -double psigamma(double, double); -double digamma(double); -double trigamma(double); -double tetragamma(double); -double pentagamma(double); - -double beta(double, double); -double lbeta(double, double); - -double choose(double, double); -double lchoose(double, double); - - /* Bessel Functions */ - -double bessel_i(double, double, double); -double bessel_j(double, double); -double bessel_k(double, double, double); -double bessel_y(double, double); -double bessel_i_ex(double, double, double, double *); -double bessel_j_ex(double, double, double *); -double bessel_k_ex(double, double, double, double *); -double bessel_y_ex(double, double, double *); - - - /* General Support Functions */ - -#ifndef HAVE_HYPOT -double hypot(double, double); -#endif -double pythag(double, double); -#ifndef HAVE_EXPM1 -double expm1(double); /* = exp(x)-1 {care for small x} */ -#endif -#ifndef HAVE_LOG1P -double log1p(double); /* = log(1+x) {care for small x} */ -#endif -int imax2(int, int); -int imin2(int, int); -double fmax2(double, double); -double fmin2(double, double); -double sign(double); -double fprec(double, double); -double fround(double, double); -double fsign(double, double); -double ftrunc(double); - -double log1pmx(double); /* Accurate log(1+x) - x, {care for small x} */ -double lgamma1p(double);/* accurate log(gamma(x+1)), small x (0 < x < 0.5) */ - -/* Compute the log of a sum or difference from logs of terms, i.e., - * - * log (exp (logx) + exp (logy)) - * or log (exp (logx) - exp (logy)) - * - * without causing overflows or throwing away too much accuracy: - */ -double logspace_add(double logx, double logy); -double logspace_sub(double logx, double logy); - - - - -/* ----------------- Private part of the header file ------------------- */ - - /* old-R Compatibility */ - -#ifdef OLD_RMATH_COMPAT -# define snorm norm_rand -# define sunif unif_rand -# define sexp exp_rand -#endif - -#if defined(MATHLIB_STANDALONE) && !defined(MATHLIB_PRIVATE_H) -/* second is defined by nmath.h */ - -/* If isnan is a macro, as C99 specifies, the C++ - math header will undefine it. This happens on OS X */ -# ifdef __cplusplus - int R_isnancpp(double); /* in mlutils.c */ -# define ISNAN(x) R_isnancpp(x) -# else -# define ISNAN(x) (isnan(x)!=0) -# endif - -# define R_FINITE(x) R_finite(x) -int R_finite(double); - -# ifdef WIN32 /* not Win32 as no config information */ -# ifdef RMATH_DLL -# define R_EXTERN extern __declspec(dllimport) -# else -# define R_EXTERN extern -# endif -R_EXTERN double NA_REAL; -R_EXTERN double R_PosInf; -R_EXTERN double R_NegInf; -R_EXTERN int N01_kind; -# undef R_EXTERN -#else -extern int N01_kind; -# endif - -#endif /* MATHLIB_STANDALONE */ - -#ifdef __cplusplus -} -#endif - -#endif /* RMATH_H */ diff --git a/deps/Rmath/include/Rmath.h0 b/deps/Rmath/include/Rmath.h0 deleted file mode 100644 index 0ecbbde2c2eb1..0000000000000 --- a/deps/Rmath/include/Rmath.h0 +++ /dev/null @@ -1,653 +0,0 @@ -/* -*- C -*- - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998-2011 The R Development Core Team - * Copyright (C) 2004 The R Foundation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - - * Rmath.h should contain ALL headers from R's C code in `src/nmath' - ------- such that ``the Math library'' can be used by simply - - ``#include '' - - and nothing else. -*/ -#ifndef RMATH_H -#define RMATH_H - -/* Note that on some systems we need to include math.h before the - defines below, to avoid redefining ftrunc */ -#ifndef NO_C_HEADERS -# include -#endif - -/*-- Mathlib as part of R -- define this for standalone : */ -/* #undef MATHLIB_STANDALONE */ - -#define R_VERSION_STRING "2.14.2" - -#ifndef HAVE_EXPM1 -# define HAVE_EXPM1 1 -#endif - -#ifndef HAVE_HYPOT -# define HAVE_HYPOT 1 -#endif - -#ifndef HAVE_LOG1P -# define HAVE_LOG1P 1 -#endif - -#ifndef HAVE_WORKING_LOG1P -# define HAVE_WORKING_LOG1P 1 -#endif - -#if defined(HAVE_LOG1P) && !defined(HAVE_WORKING_LOG1P) -/* remap to avoid problems with getting the right entry point */ -double Rlog1p(double); -#define log1p Rlog1p -#endif - - - /* Undo SGI Madness */ - -#ifdef ftrunc -# undef ftrunc -#endif -#ifdef qexp -# undef qexp -#endif -#ifdef qgamma -# undef qgamma -#endif - - -/* ----- The following constants and entry points are part of the R API ---- */ - -/* 30 Decimal-place constants */ -/* Computed with bc -l (scale=32; proper round) */ - -/* SVID & X/Open Constants */ -/* Names from Solaris math.h */ - -#ifndef M_E -#define M_E 2.718281828459045235360287471353 /* e */ -#endif - -#ifndef M_LOG2E -#define M_LOG2E 1.442695040888963407359924681002 /* log2(e) */ -#endif - -#ifndef M_LOG10E -#define M_LOG10E 0.434294481903251827651128918917 /* log10(e) */ -#endif - -#ifndef M_LN2 -#define M_LN2 0.693147180559945309417232121458 /* ln(2) */ -#endif - -#ifndef M_LN10 -#define M_LN10 2.302585092994045684017991454684 /* ln(10) */ -#endif - -#ifndef M_PI -#define M_PI 3.141592653589793238462643383280 /* pi */ -#endif - -#ifndef M_2PI -#define M_2PI 6.283185307179586476925286766559 /* 2*pi */ -#endif - -#ifndef M_PI_2 -#define M_PI_2 1.570796326794896619231321691640 /* pi/2 */ -#endif - -#ifndef M_PI_4 -#define M_PI_4 0.785398163397448309615660845820 /* pi/4 */ -#endif - -#ifndef M_1_PI -#define M_1_PI 0.318309886183790671537767526745 /* 1/pi */ -#endif - -#ifndef M_2_PI -#define M_2_PI 0.636619772367581343075535053490 /* 2/pi */ -#endif - -#ifndef M_2_SQRTPI -#define M_2_SQRTPI 1.128379167095512573896158903122 /* 2/sqrt(pi) */ -#endif - -#ifndef M_SQRT2 -#define M_SQRT2 1.414213562373095048801688724210 /* sqrt(2) */ -#endif - -#ifndef M_SQRT1_2 -#define M_SQRT1_2 0.707106781186547524400844362105 /* 1/sqrt(2) */ -#endif - -/* R-Specific Constants */ - -#ifndef M_SQRT_3 -#define M_SQRT_3 1.732050807568877293527446341506 /* sqrt(3) */ -#endif - -#ifndef M_SQRT_32 -#define M_SQRT_32 5.656854249492380195206754896838 /* sqrt(32) */ -#endif - -#ifndef M_LOG10_2 -#define M_LOG10_2 0.301029995663981195213738894724 /* log10(2) */ -#endif - -#ifndef M_SQRT_PI -#define M_SQRT_PI 1.772453850905516027298167483341 /* sqrt(pi) */ -#endif - -#ifndef M_1_SQRT_2PI -#define M_1_SQRT_2PI 0.398942280401432677939946059934 /* 1/sqrt(2pi) */ -#endif - -#ifndef M_SQRT_2dPI -#define M_SQRT_2dPI 0.797884560802865355879892119869 /* sqrt(2/pi) */ -#endif - - -#ifndef M_LN_SQRT_PI -#define M_LN_SQRT_PI 0.572364942924700087071713675677 /* log(sqrt(pi)) - == log(pi)/2 */ -#endif - -#ifndef M_LN_SQRT_2PI -#define M_LN_SQRT_2PI 0.918938533204672741780329736406 /* log(sqrt(2*pi)) - == log(2*pi)/2 */ -#endif - -#ifndef M_LN_SQRT_PId2 -#define M_LN_SQRT_PId2 0.225791352644727432363097614947 /* log(sqrt(pi/2)) */ -#endif - - -#ifdef MATHLIB_STANDALONE -# ifndef R_EXT_BOOLEAN_H_ -/* "copy-paste" R_ext/Boolean.h if not already included: */ - #define R_EXT_BOOLEAN_H_ - #undef FALSE - #undef TRUE - typedef enum { FALSE = 0, TRUE } Rboolean; -# endif -#else -# include -#endif - - -#ifndef MATHLIB_STANDALONE -#define bessel_i Rf_bessel_i -#define bessel_j Rf_bessel_j -#define bessel_k Rf_bessel_k -#define bessel_y Rf_bessel_y -#define bessel_i_ex Rf_bessel_i_ex -#define bessel_j_ex Rf_bessel_j_ex -#define bessel_k_ex Rf_bessel_k_ex -#define bessel_y_ex Rf_bessel_y_ex -#define beta Rf_beta -#define choose Rf_choose -#define dbeta Rf_dbeta -#define dbinom Rf_dbinom -#define dcauchy Rf_dcauchy -#define dchisq Rf_dchisq -#define dexp Rf_dexp -#define df Rf_df -#define dgamma Rf_dgamma -#define dgeom Rf_dgeom -#define dhyper Rf_dhyper -#define digamma Rf_digamma -#define dlnorm Rf_dlnorm -#define dlogis Rf_dlogis -#define dnbeta Rf_dnbeta -#define dnbinom Rf_dnbinom -#define dnchisq Rf_dnchisq -#define dnf Rf_dnf -#define dnorm4 Rf_dnorm4 -#define dnt Rf_dnt -#define dpois Rf_dpois -#define dpsifn Rf_dpsifn -#define dsignrank Rf_dsignrank -#define dt Rf_dt -#define dtukey Rf_dtukey -#define dunif Rf_dunif -#define dweibull Rf_dweibull -#define dwilcox Rf_dwilcox -#define fmax2 Rf_fmax2 -#define fmin2 Rf_fmin2 -#define fprec Rf_fprec -#define fround Rf_fround -#define ftrunc Rf_ftrunc -#define fsign Rf_fsign -#define gammafn Rf_gammafn -#define imax2 Rf_imax2 -#define imin2 Rf_imin2 -#define lbeta Rf_lbeta -#define lchoose Rf_lchoose -#define lgammafn Rf_lgammafn -#define lgammafn_sign Rf_lgammafn_sign -#define lgamma1p Rf_lgamma1p -#define log1pmx Rf_log1pmx -#define logspace_add Rf_logspace_add -#define logspace_sub Rf_logspace_sub -#define pbeta Rf_pbeta -#define pbeta_raw Rf_pbeta_raw -#define pbinom Rf_pbinom -#define pcauchy Rf_pcauchy -#define pchisq Rf_pchisq -#define pentagamma Rf_pentagamma -#define pexp Rf_pexp -#define pf Rf_pf -#define pgamma Rf_pgamma -#define pgeom Rf_pgeom -#define phyper Rf_phyper -#define plnorm Rf_plnorm -#define plogis Rf_plogis -#define pnbeta Rf_pnbeta -#define pnbinom Rf_pnbinom -#define pnchisq Rf_pnchisq -#define pnf Rf_pnf -#define pnorm5 Rf_pnorm5 -#define pnorm_both Rf_pnorm_both -#define pnt Rf_pnt -#define ppois Rf_ppois -#define psignrank Rf_psignrank -#define psigamma Rf_psigamma -#define pt Rf_pt -#define ptukey Rf_ptukey -#define punif Rf_punif -#define pythag Rf_pythag -#define pweibull Rf_pweibull -#define pwilcox Rf_pwilcox -#define qbeta Rf_qbeta -#define qbinom Rf_qbinom -#define qcauchy Rf_qcauchy -#define qchisq Rf_qchisq -#define qchisq_appr Rf_qchisq_appr -#define qexp Rf_qexp -#define qf Rf_qf -#define qgamma Rf_qgamma -#define qgeom Rf_qgeom -#define qhyper Rf_qhyper -#define qlnorm Rf_qlnorm -#define qlogis Rf_qlogis -#define qnbeta Rf_qnbeta -#define qnbinom Rf_qnbinom -#define qnchisq Rf_qnchisq -#define qnf Rf_qnf -#define qnorm5 Rf_qnorm5 -#define qnt Rf_qnt -#define qpois Rf_qpois -#define qsignrank Rf_qsignrank -#define qt Rf_qt -#define qtukey Rf_qtukey -#define qunif Rf_qunif -#define qweibull Rf_qweibull -#define qwilcox Rf_qwilcox -#define rbeta Rf_rbeta -#define rbinom Rf_rbinom -#define rcauchy Rf_rcauchy -#define rchisq Rf_rchisq -#define rexp Rf_rexp -#define rf Rf_rf -#define rgamma Rf_rgamma -#define rgeom Rf_rgeom -#define rhyper Rf_rhyper -#define rlnorm Rf_rlnorm -#define rlogis Rf_rlogis -#define rnbeta Rf_rnbeta -#define rnbinom Rf_rnbinom -#define rnchisq Rf_rnchisq -#define rnf Rf_rnf -#define rnorm Rf_rnorm -#define rnt Rf_rnt -#define rpois Rf_rpois -#define rsignrank Rf_rsignrank -#define rt Rf_rt -#define rtukey Rf_rtukey -#define runif Rf_runif -#define rweibull Rf_rweibull -#define rwilcox Rf_rwilcox -#define sign Rf_sign -#define tetragamma Rf_tetragamma -#define trigamma Rf_trigamma -#endif - -#define rround fround -#define prec fprec -#undef trunc -#define trunc ftrunc - -#ifdef __cplusplus -extern "C" { -#endif - /* R's versions with !R_FINITE checks */ - -double R_pow(double x, double y); -double R_pow_di(double, int); - - /* Random Number Generators */ - -double norm_rand(void); -double unif_rand(void); -double exp_rand(void); -#ifdef MATHLIB_STANDALONE -void set_seed(unsigned int, unsigned int); -void get_seed(unsigned int *, unsigned int *); -#endif - - /* Normal Distribution */ - -#define pnorm pnorm5 -#define qnorm qnorm5 -#define dnorm dnorm4 - -double dnorm(double, double, double, int); -double pnorm(double, double, double, int, int); -double qnorm(double, double, double, int, int); -double rnorm(double, double); -void pnorm_both(double, double *, double *, int, int);/* both tails */ - - /* Uniform Distribution */ - -double dunif(double, double, double, int); -double punif(double, double, double, int, int); -double qunif(double, double, double, int, int); -double runif(double, double); - - /* Gamma Distribution */ - -double dgamma(double, double, double, int); -double pgamma(double, double, double, int, int); -double qgamma(double, double, double, int, int); -double rgamma(double, double); - -double log1pmx(double); -double lgamma1p(double); -double logspace_add(double, double); -double logspace_sub(double, double); - - /* Beta Distribution */ - -double dbeta(double, double, double, int); -double pbeta(double, double, double, int, int); -double qbeta(double, double, double, int, int); -double rbeta(double, double); - - /* Lognormal Distribution */ - -double dlnorm(double, double, double, int); -double plnorm(double, double, double, int, int); -double qlnorm(double, double, double, int, int); -double rlnorm(double, double); - - /* Chi-squared Distribution */ - -double dchisq(double, double, int); -double pchisq(double, double, int, int); -double qchisq(double, double, int, int); -double rchisq(double); - - /* Non-central Chi-squared Distribution */ - -double dnchisq(double, double, double, int); -double pnchisq(double, double, double, int, int); -double qnchisq(double, double, double, int, int); -double rnchisq(double, double); - - /* F Distibution */ - -double df(double, double, double, int); -double pf(double, double, double, int, int); -double qf(double, double, double, int, int); -double rf(double, double); - - /* Student t Distibution */ - -double dt(double, double, int); -double pt(double, double, int, int); -double qt(double, double, int, int); -double rt(double); - - /* Binomial Distribution */ - -double dbinom(double, double, double, int); -double pbinom(double, double, double, int, int); -double qbinom(double, double, double, int, int); -double rbinom(double, double); - - /* Multnomial Distribution */ - -void rmultinom(int, double*, int, int*); - - /* Cauchy Distribution */ - -double dcauchy(double, double, double, int); -double pcauchy(double, double, double, int, int); -double qcauchy(double, double, double, int, int); -double rcauchy(double, double); - - /* Exponential Distribution */ - -double dexp(double, double, int); -double pexp(double, double, int, int); -double qexp(double, double, int, int); -double rexp(double); - - /* Geometric Distribution */ - -double dgeom(double, double, int); -double pgeom(double, double, int, int); -double qgeom(double, double, int, int); -double rgeom(double); - - /* Hypergeometric Distibution */ - -double dhyper(double, double, double, double, int); -double phyper(double, double, double, double, int, int); -double qhyper(double, double, double, double, int, int); -double rhyper(double, double, double); - - /* Negative Binomial Distribution */ - -double dnbinom(double, double, double, int); -double pnbinom(double, double, double, int, int); -double qnbinom(double, double, double, int, int); -double rnbinom(double, double); - -double dnbinom_mu(double, double, double, int); -double pnbinom_mu(double, double, double, int, int); -double qnbinom_mu(double, double, double, int, int); -double rnbinom_mu(double, double); - - /* Poisson Distribution */ - -double dpois(double, double, int); -double ppois(double, double, int, int); -double qpois(double, double, int, int); -double rpois(double); - - /* Weibull Distribution */ - -double dweibull(double, double, double, int); -double pweibull(double, double, double, int, int); -double qweibull(double, double, double, int, int); -double rweibull(double, double); - - /* Logistic Distribution */ - -double dlogis(double, double, double, int); -double plogis(double, double, double, int, int); -double qlogis(double, double, double, int, int); -double rlogis(double, double); - - /* Non-central Beta Distribution */ - -double dnbeta(double, double, double, double, int); -double pnbeta(double, double, double, double, int, int); -double qnbeta(double, double, double, double, int, int); -double rnbeta(double, double, double); - - /* Non-central F Distribution */ - -double dnf(double, double, double, double, int); -double pnf(double, double, double, double, int, int); -double qnf(double, double, double, double, int, int); - - /* Non-central Student t Distribution */ - -double dnt(double, double, double, int); -double pnt(double, double, double, int, int); -double qnt(double, double, double, int, int); - - /* Studentized Range Distribution */ - -double ptukey(double, double, double, double, int, int); -double qtukey(double, double, double, double, int, int); - - /* Wilcoxon Rank Sum Distribution */ - -double dwilcox(double, double, double, int); -double pwilcox(double, double, double, int, int); -double qwilcox(double, double, double, int, int); -double rwilcox(double, double); - - /* Wilcoxon Signed Rank Distribution */ - -double dsignrank(double, double, int); -double psignrank(double, double, int, int); -double qsignrank(double, double, int, int); -double rsignrank(double); - - /* Gamma and Related Functions */ -double gammafn(double); -double lgammafn(double); -double lgammafn_sign(double, int*); -void dpsifn(double, int, int, int, double*, int*, int*); -double psigamma(double, double); -double digamma(double); -double trigamma(double); -double tetragamma(double); -double pentagamma(double); - -double beta(double, double); -double lbeta(double, double); - -double choose(double, double); -double lchoose(double, double); - - /* Bessel Functions */ - -double bessel_i(double, double, double); -double bessel_j(double, double); -double bessel_k(double, double, double); -double bessel_y(double, double); -double bessel_i_ex(double, double, double, double *); -double bessel_j_ex(double, double, double *); -double bessel_k_ex(double, double, double, double *); -double bessel_y_ex(double, double, double *); - - - /* General Support Functions */ - -#ifndef HAVE_HYPOT -double hypot(double, double); -#endif -double pythag(double, double); -#ifndef HAVE_EXPM1 -double expm1(double); /* = exp(x)-1 {care for small x} */ -#endif -#ifndef HAVE_LOG1P -double log1p(double); /* = log(1+x) {care for small x} */ -#endif -int imax2(int, int); -int imin2(int, int); -double fmax2(double, double); -double fmin2(double, double); -double sign(double); -double fprec(double, double); -double fround(double, double); -double fsign(double, double); -double ftrunc(double); - -double log1pmx(double); /* Accurate log(1+x) - x, {care for small x} */ -double lgamma1p(double);/* accurate log(gamma(x+1)), small x (0 < x < 0.5) */ - -/* Compute the log of a sum or difference from logs of terms, i.e., - * - * log (exp (logx) + exp (logy)) - * or log (exp (logx) - exp (logy)) - * - * without causing overflows or throwing away too much accuracy: - */ -double logspace_add(double logx, double logy); -double logspace_sub(double logx, double logy); - - - - -/* ----------------- Private part of the header file ------------------- */ - - /* old-R Compatibility */ - -#ifdef OLD_RMATH_COMPAT -# define snorm norm_rand -# define sunif unif_rand -# define sexp exp_rand -#endif - -#if defined(MATHLIB_STANDALONE) && !defined(MATHLIB_PRIVATE_H) -/* second is defined by nmath.h */ - -/* If isnan is a macro, as C99 specifies, the C++ - math header will undefine it. This happens on OS X */ -# ifdef __cplusplus - int R_isnancpp(double); /* in mlutils.c */ -# define ISNAN(x) R_isnancpp(x) -# else -# define ISNAN(x) (isnan(x)!=0) -# endif - -# define R_FINITE(x) R_finite(x) -int R_finite(double); - -# ifdef WIN32 /* not Win32 as no config information */ -# ifdef RMATH_DLL -# define R_EXTERN extern __declspec(dllimport) -# else -# define R_EXTERN extern -# endif -R_EXTERN double NA_REAL; -R_EXTERN double R_PosInf; -R_EXTERN double R_NegInf; -R_EXTERN int N01_kind; -# undef R_EXTERN -#else -extern int N01_kind; -# endif - -#endif /* MATHLIB_STANDALONE */ - -#ifdef __cplusplus -} -#endif - -#endif /* RMATH_H */ diff --git a/deps/Rmath/include/config.h b/deps/Rmath/include/config.h deleted file mode 100644 index f9ccf515b334d..0000000000000 --- a/deps/Rmath/include/config.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _CONFIG_H_ - -#define _CONFIG_H_ - -#include - -#endif /* _CONFIG_H_ */ diff --git a/deps/Rmath/src/.gitignore b/deps/Rmath/src/.gitignore deleted file mode 100644 index 945fb3e8e313e..0000000000000 --- a/deps/Rmath/src/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -*.o -*.dylib -*.so diff --git a/deps/Rmath/src/Makefile b/deps/Rmath/src/Makefile deleted file mode 100644 index 3552b1887a732..0000000000000 --- a/deps/Rmath/src/Makefile +++ /dev/null @@ -1,48 +0,0 @@ -JULIAHOME = $(abspath ../../..) -include $(JULIAHOME)/Make.inc - -SRCS = bd0.c dnbeta.c i1mach.c pnbinom.c qlnorm.c rgeom.c \ - bessel_i.c dnbinom.c imax2.c pnchisq.c qlogis.c rhyper.c \ - bessel_j.c dnchisq.c imin2.c pnf.c qnbeta.c rlnorm.c \ - bessel_k.c dnf.c lbeta.c pnorm.c qnbinom.c rlogis.c \ - bessel_y.c dnorm.c lgamma.c pnt.c qnchisq.c rmultinom.c \ - beta.c dnt.c lgammacor.c polygamma.c qnf.c rnbinom.c \ - chebyshev.c dpois.c log1p.c ppois.c qnorm.c rnchisq.c \ - choose.c dt.c mlutils.c pt.c qnt.c rnorm.c \ - d1mach.c dunif.c pbeta.c ptukey.c qpois.c rpois.c \ - dbeta.c dweibull.c pbinom.c punif.c qt.c rt.c \ - dbinom.c expm1.c pcauchy.c pweibull.c qtukey.c runif.c \ - dcauchy.c fmax2.c pchisq.c qbeta.c qunif.c rweibull.c \ - dchisq.c fmin2.c pexp.c qbinom.c qweibull.c sexp.c \ - dexp.c fprec.c pf.c qcauchy.c rbeta.c sign.c \ - df.c fround.c pgamma.c qchisq.c rbinom.c signrank.c \ - dgamma.c fsign.c pgeom.c qexp.c rcauchy.c snorm.c \ - dgeom.c ftrunc.c phyper.c qf.c rchisq.c stirlerr.c \ - dhyper.c gamma.c plnorm.c qgamma.c rexp.c toms708.c \ - dlnorm.c gamma_cody.c plogis.c qgeom.c rf.c wilcox.c \ - dlogis.c gammalims.c pnbeta.c qhyper.c rgamma.c sunif.c - -OBJS = $(SRCS:%.c=%.o) -DOBJS = $(SRCS:%.c=%.do) - -ifneq ($(MAKECMDGOALS),debug) -XOBJS = $(OBJS) -else -XOBJS = $(DOBJS) -endif - -default: release - -%.o: %.c - $(QUIET_CC) $(CC) $(fPIC) -std=gnu99 -I../include -DMATHLIB_STANDALONE -DNDEBUG -O3 -c $< -o $@ -%.do: %.c - $(QUIET_CC) $(CC) $(fPIC) -std=gnu99 -I../include -DMATHLIB_STANDALONE -g -c $< -o $@ - -release debug: libRmath.$(SHLIB_EXT) - -libRmath.$(SHLIB_EXT): $(XOBJS) - rm -rf $@ - $(QUIET_LINK) $(CC) -shared -o $@ $^ -L$(USR)/lib -lrandom $(RPATH_ORIGIN) - -clean: - rm -f *.o *.do *.a *.$(SHLIB_EXT) core* *~ *# diff --git a/deps/Rmath/src/bd0.c b/deps/Rmath/src/bd0.c deleted file mode 100644 index d6a2b3b0a9798..0000000000000 --- a/deps/Rmath/src/bd0.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * AUTHOR - * Catherine Loader, catherine@research.bell-labs.com. - * October 23, 2000. - * - * Merge in to R: - * Copyright (C) 2000, The R Core Development Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * - * DESCRIPTION - * Evaluates the "deviance part" - * bd0(x,M) := M * D0(x/M) = M*[ x/M * log(x/M) + 1 - (x/M) ] = - * = x * log(x/M) + M - x - * where M = E[X] = n*p (or = lambda), for x, M > 0 - * - * in a manner that should be stable (with small relative error) - * for all x and M=np. In particular for x/np close to 1, direct - * evaluation fails, and evaluation is based on the Taylor series - * of log((1+v)/(1-v)) with v = (x-np)/(x+np). - */ -#include "nmath.h" - -double attribute_hidden bd0(double x, double np) -{ - double ej, s, s1, v; - int j; - - if(!R_FINITE(x) || !R_FINITE(np) || np == 0.0) ML_ERR_return_NAN; - - if (fabs(x-np) < 0.1*(x+np)) { - v = (x-np)/(x+np); - s = (x-np)*v;/* s using v -- change by MM */ - ej = 2*x*v; - v = v*v; - for (j=1; ; j++) { /* Taylor series */ - ej *= v; - s1 = s+ej/((j<<1)+1); - if (s1==s) /* last term was effectively 0 */ - return(s1); - s = s1; - } - } - /* else: | x - np | is not too small */ - return(x*log(x/np)+np-x); -} diff --git a/deps/Rmath/src/bessel.h b/deps/Rmath/src/bessel.h deleted file mode 100644 index ff3f6f2b4ce29..0000000000000 --- a/deps/Rmath/src/bessel.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * R : A Computer Language for Statistical Data Analysis - * Copyright (C) 2001 R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - */ - -/* Constants und Documentation that apply to several of the - * ./bessel_[ijky].c files */ - -/* ******************************************************************* - - Explanation of machine-dependent constants - - beta = Radix for the floating-point system - minexp = Smallest representable power of beta - maxexp = Smallest power of beta that overflows - it = p = Number of bits (base-beta digits) in the mantissa - (significand) of a working precision (floating-point) variable - NSIG = Decimal significance desired. Should be set to - INT(LOG10(2)*it+1). Setting NSIG lower will result - in decreased accuracy while setting NSIG higher will - increase CPU time without increasing accuracy. The - truncation error is limited to a relative error of - T=.5*10^(-NSIG). - ENTEN = 10 ^ K, where K is the largest long such that - ENTEN is machine-representable in working precision - ENSIG = 10 ^ NSIG - RTNSIG = 10 ^ (-K) for the smallest long K such that - K >= NSIG/4 - ENMTEN = Smallest ABS(X) such that X/4 does not underflow - XINF = Largest positive machine number; approximately beta ^ maxexp - == DBL_MAX (defined in #include ) - SQXMIN = Square root of beta ^ minexp = sqrt(DBL_MIN) - - EPS = The smallest positive floating-point number such that 1.0+EPS > 1.0 - = beta ^ (-p) == DBL_EPSILON - - - For I : - - EXPARG = Largest working precision argument that the library - EXP routine can handle and upper limit on the - magnitude of X when IZE=1; approximately LOG(beta ^ maxexp) - - For I and J : - - xlrg_IJ = xlrg_BESS_IJ (was = XLARGE). Upper limit on the magnitude of X - (when IZE=2 for I()). Bear in mind that if floor(abs(x)) =: N, then - at least N iterations of the backward recursion will be executed. - The value of 10 ^ 4 was used till Feb.2009, when it was increased - to 10 ^ 5 (= 1e5). - - For j : - XMIN_J = Smallest acceptable argument for RBESY; approximately - max(2*beta ^ minexp, 2/XINF), rounded up - - For Y : - - xlrg_Y = (was = XLARGE). Upper bound on X; - approximately 1/DEL, because the sine and cosine functions - have lost about half of their precision at that point. - - EPS_SINC = Machine number below which sin(x)/x = 1; approximately SQRT(EPS). - THRESH = Lower bound for use of the asymptotic form; - approximately AINT(-LOG10(EPS/2.0))+1.0 - - - For K : - - xmax_k = (was = XMAX). Upper limit on the magnitude of X when ize = 1; - i.e. maximal x for UNscaled answer. - - Solution to equation: - W(X) * (1 -1/8 X + 9/128 X^2) = beta ^ minexp - where W(X) = EXP(-X)*SQRT(PI/2X) - - -------------------------------------------------------------------- - - Approximate values for some important machines are: - - beta minexp maxexp it NSIG ENTEN ENSIG RTNSIG ENMTEN EXPARG - IEEE (IBM/XT, - SUN, etc.) (S.P.) 2 -126 128 24 8 1e38 1e8 1e-2 4.70e-38 88 - IEEE (...) (D.P.) 2 -1022 1024 53 16 1e308 1e16 1e-4 8.90e-308 709 - CRAY-1 (S.P.) 2 -8193 8191 48 15 1e2465 1e15 1e-4 1.84e-2466 5677 - Cyber 180/855 - under NOS (S.P.) 2 -975 1070 48 15 1e322 1e15 1e-4 1.25e-293 741 - IBM 3033 (D.P.) 16 -65 63 14 5 1e75 1e5 1e-2 2.16e-78 174 - VAX (S.P.) 2 -128 127 24 8 1e38 1e8 1e-2 1.17e-38 88 - VAX D-Format (D.P.) 2 -128 127 56 17 1e38 1e17 1e-5 1.17e-38 88 - VAX G-Format (D.P.) 2 -1024 1023 53 16 1e307 1e16 1e-4 2.22e-308 709 - - -And routine specific : - - xlrg_IJ xlrg_Y xmax_k EPS_SINC XMIN_J XINF THRESH - IEEE (IBM/XT, - SUN, etc.) (S.P.) 1e4 1e4 85.337 1e-4 2.36e-38 3.40e38 8. - IEEE (...) (D.P.) 1e4 1e8 705.342 1e-8 4.46e-308 1.79e308 16. - CRAY-1 (S.P.) 1e4 2e7 5674.858 5e-8 3.67e-2466 5.45e2465 15. - Cyber 180/855 - under NOS (S.P.) 1e4 2e7 672.788 5e-8 6.28e-294 1.26e322 15. - IBM 3033 (D.P.) 1e4 1e8 177.852 1e-8 2.77e-76 7.23e75 17. - VAX (S.P.) 1e4 1e4 86.715 1e-4 1.18e-38 1.70e38 8. - VAX e-Format (D.P.) 1e4 1e9 86.715 1e-9 1.18e-38 1.70e38 17. - VAX G-Format (D.P.) 1e4 1e8 706.728 1e-8 2.23e-308 8.98e307 16. - -*/ -#define nsig_BESS 16 -#define ensig_BESS 1e16 -#define rtnsig_BESS 1e-4 -#define enmten_BESS 8.9e-308 -#define enten_BESS 1e308 - -#define exparg_BESS 709. -#define xlrg_BESS_IJ 1e5 -#define xlrg_BESS_Y 1e8 -#define thresh_BESS_Y 16. - -#define xmax_BESS_K 705.342/* maximal x for UNscaled answer */ - - -/* sqrt(DBL_MIN) = 1.491668e-154 */ -#define sqxmin_BESS_K 1.49e-154 - -/* x < eps_sinc <==> sin(x)/x == 1 (particularly "==>"); - Linux (around 2001-02) gives 2.14946906753213e-08 - Solaris 2.5.1 gives 2.14911933289084e-08 -*/ -#define M_eps_sinc 2.149e-8 diff --git a/deps/Rmath/src/bessel_i.c b/deps/Rmath/src/bessel_i.c deleted file mode 100644 index 762dca9172d21..0000000000000 --- a/deps/Rmath/src/bessel_i.c +++ /dev/null @@ -1,531 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998-2001 Ross Ihaka and the R Development Core team. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - */ - -/* DESCRIPTION --> see below */ - - -/* From http://www.netlib.org/specfun/ribesl Fortran translated by f2c,... - * ------------------------------=#---- Martin Maechler, ETH Zurich - */ -#include "nmath.h" -#include "bessel.h" - -#ifndef MATHLIB_STANDALONE -#include -#endif - -static void I_bessel(double *x, double *alpha, long *nb, - long *ize, double *bi, long *ncalc); - -/* .Internal(besselI(*)) : */ -double bessel_i(double x, double alpha, double expo) -{ - long nb, ncalc, ize; - double na, *bi; -#ifndef MATHLIB_STANDALONE - const void *vmax; -#endif - -#ifdef IEEE_754 - /* NaNs propagated correctly */ - if (ISNAN(x) || ISNAN(alpha)) return x + alpha; -#endif - if (x < 0) { - ML_ERROR(ME_RANGE, "bessel_i"); - return ML_NAN; - } - ize = (long)expo; - na = floor(alpha); - if (alpha < 0) { - /* Using Abramowitz & Stegun 9.6.2 & 9.6.6 - * this may not be quite optimal (CPU and accuracy wise) */ - return(bessel_i(x, -alpha, expo) + - ((alpha == na) ? /* sin(pi * alpha) = 0 */ 0 : - bessel_k(x, -alpha, expo) * - ((ize == 1)? 2. : 2.*exp(-2.*x))/M_PI * sin(-M_PI * alpha))); - } - nb = 1 + (long)na;/* nb-1 <= alpha < nb */ - alpha -= (nb-1); -#ifdef MATHLIB_STANDALONE - bi = (double *) calloc(nb, sizeof(double)); - if (!bi) MATHLIB_ERROR("%s", _("bessel_i allocation error")); -#else - vmax = vmaxget(); - bi = (double *) R_alloc((size_t) nb, sizeof(double)); -#endif - I_bessel(&x, &alpha, &nb, &ize, bi, &ncalc); - if(ncalc != nb) {/* error input */ - if(ncalc < 0) - MATHLIB_WARNING4(_("bessel_i(%g): ncalc (=%ld) != nb (=%ld); alpha=%g. Arg. out of range?\n"), - x, ncalc, nb, alpha); - else - MATHLIB_WARNING2(_("bessel_i(%g,nu=%g): precision lost in result\n"), - x, alpha+nb-1); - } - x = bi[nb-1]; -#ifdef MATHLIB_STANDALONE - free(bi); -#else - vmaxset(vmax); -#endif - return x; -} - -/* modified version of bessel_i that accepts a work array instead of - allocating one. */ -double bessel_i_ex(double x, double alpha, double expo, double *bi) -{ - long nb, ncalc, ize; - double na; - -#ifdef IEEE_754 - /* NaNs propagated correctly */ - if (ISNAN(x) || ISNAN(alpha)) return x + alpha; -#endif - if (x < 0) { - ML_ERROR(ME_RANGE, "bessel_i"); - return ML_NAN; - } - ize = (long)expo; - na = floor(alpha); - if (alpha < 0) { - /* Using Abramowitz & Stegun 9.6.2 & 9.6.6 - * this may not be quite optimal (CPU and accuracy wise) */ - return(bessel_i_ex(x, -alpha, expo, bi) + - ((alpha == na) ? 0 : - bessel_k_ex(x, -alpha, expo, bi) * - ((ize == 1)? 2. : 2.*exp(-2.*x))/M_PI * sin(-M_PI * alpha))); - } - nb = 1 + (long)na;/* nb-1 <= alpha < nb */ - alpha -= (nb-1); - I_bessel(&x, &alpha, &nb, &ize, bi, &ncalc); - if(ncalc != nb) {/* error input */ - if(ncalc < 0) - MATHLIB_WARNING4(_("bessel_i(%g): ncalc (=%ld) != nb (=%ld); alpha=%g. Arg. out of range?\n"), - x, ncalc, nb, alpha); - else - MATHLIB_WARNING2(_("bessel_i(%g,nu=%g): precision lost in result\n"), - x, alpha+nb-1); - } - x = bi[nb-1]; - return x; -} - -static void I_bessel(double *x, double *alpha, long *nb, - long *ize, double *bi, long *ncalc) -{ -/* ------------------------------------------------------------------- - - This routine calculates Bessel functions I_(N+ALPHA) (X) - for non-negative argument X, and non-negative order N+ALPHA, - with or without exponential scaling. - - - Explanation of variables in the calling sequence - - X - Non-negative argument for which - I's or exponentially scaled I's (I*EXP(-X)) - are to be calculated. If I's are to be calculated, - X must be less than exparg_BESS (IZE=1) or xlrg_BESS_IJ (IZE=2), - (see bessel.h). - ALPHA - Fractional part of order for which - I's or exponentially scaled I's (I*EXP(-X)) are - to be calculated. 0 <= ALPHA < 1.0. - NB - Number of functions to be calculated, NB > 0. - The first function calculated is of order ALPHA, and the - last is of order (NB - 1 + ALPHA). - IZE - Type. IZE = 1 if unscaled I's are to be calculated, - = 2 if exponentially scaled I's are to be calculated. - BI - Output vector of length NB. If the routine - terminates normally (NCALC=NB), the vector BI contains the - functions I(ALPHA,X) through I(NB-1+ALPHA,X), or the - corresponding exponentially scaled functions. - NCALC - Output variable indicating possible errors. - Before using the vector BI, the user should check that - NCALC=NB, i.e., all orders have been calculated to - the desired accuracy. See error returns below. - - - ******************************************************************* - ******************************************************************* - - Error returns - - In case of an error, NCALC != NB, and not all I's are - calculated to the desired accuracy. - - NCALC < 0: An argument is out of range. For example, - NB <= 0, IZE is not 1 or 2, or IZE=1 and ABS(X) >= EXPARG_BESS. - In this case, the BI-vector is not calculated, and NCALC is - set to MIN0(NB,0)-1 so that NCALC != NB. - - NB > NCALC > 0: Not all requested function values could - be calculated accurately. This usually occurs because NB is - much larger than ABS(X). In this case, BI[N] is calculated - to the desired accuracy for N <= NCALC, but precision - is lost for NCALC < N <= NB. If BI[N] does not vanish - for N > NCALC (because it is too small to be represented), - and BI[N]/BI[NCALC] = 10**(-K), then only the first NSIG-K - significant figures of BI[N] can be trusted. - - - Intrinsic functions required are: - - DBLE, EXP, gamma_cody, INT, MAX, MIN, REAL, SQRT - - - Acknowledgement - - This program is based on a program written by David J. - Sookne (2) that computes values of the Bessel functions J or - I of float argument and long order. Modifications include - the restriction of the computation to the I Bessel function - of non-negative float argument, the extension of the computation - to arbitrary positive order, the inclusion of optional - exponential scaling, and the elimination of most underflow. - An earlier version was published in (3). - - References: "A Note on Backward Recurrence Algorithms," Olver, - F. W. J., and Sookne, D. J., Math. Comp. 26, 1972, - pp 941-947. - - "Bessel Functions of Real Argument and Integer Order," - Sookne, D. J., NBS Jour. of Res. B. 77B, 1973, pp - 125-132. - - "ALGORITHM 597, Sequence of Modified Bessel Functions - of the First Kind," Cody, W. J., Trans. Math. Soft., - 1983, pp. 242-245. - - Latest modification: May 30, 1989 - - Modified by: W. J. Cody and L. Stoltz - Applied Mathematics Division - Argonne National Laboratory - Argonne, IL 60439 -*/ - - /*------------------------------------------------------------------- - Mathematical constants - -------------------------------------------------------------------*/ - const static double const__ = 1.585; - - /* Local variables */ - long nend, intx, nbmx, k, l, n, nstart; - double pold, test, p, em, en, empal, emp2al, halfx, - aa, bb, cc, psave, plast, tover, psavel, sum, nu, twonu; - - /*Parameter adjustments */ - --bi; - nu = *alpha; - twonu = nu + nu; - - /*------------------------------------------------------------------- - Check for X, NB, OR IZE out of range. - ------------------------------------------------------------------- */ - if (*nb > 0 && *x >= 0. && (0. <= nu && nu < 1.) && - (1 <= *ize && *ize <= 2) ) { - - *ncalc = *nb; - if(*ize == 1 && *x > exparg_BESS) { - for(k=1; k <= *nb; k++) - bi[k]=ML_POSINF; /* the limit *is* = Inf */ - return; - } - if(*ize == 2 && *x > xlrg_BESS_IJ) { - for(k=1; k <= *nb; k++) - bi[k]= 0.; /* The limit exp(-x) * I_nu(x) --> 0 : */ - return; - } - intx = (long) (*x);/* fine, since *x <= xlrg_BESS_IJ <<< LONG_MAX */ - if (*x >= rtnsig_BESS) { /* "non-small" x ( >= 1e-4 ) */ -/* ------------------------------------------------------------------- - Initialize the forward sweep, the P-sequence of Olver - ------------------------------------------------------------------- */ - nbmx = *nb - intx; - n = intx + 1; - en = (double) (n + n) + twonu; - plast = 1.; - p = en / *x; - /* ------------------------------------------------ - Calculate general significance test - ------------------------------------------------ */ - test = ensig_BESS + ensig_BESS; - if (intx << 1 > nsig_BESS * 5) { - test = sqrt(test * p); - } else { - test /= pow(const__, (double)intx); - } - if (nbmx >= 3) { - /* -------------------------------------------------- - Calculate P-sequence until N = NB-1 - Check for possible overflow. - ------------------------------------------------ */ - tover = enten_BESS / ensig_BESS; - nstart = intx + 2; - nend = *nb - 1; - for (k = nstart; k <= nend; ++k) { - n = k; - en += 2.; - pold = plast; - plast = p; - p = en * plast / *x + pold; - if (p > tover) { - /* ------------------------------------------------ - To avoid overflow, divide P-sequence by TOVER. - Calculate P-sequence until ABS(P) > 1. - ---------------------------------------------- */ - tover = enten_BESS; - p /= tover; - plast /= tover; - psave = p; - psavel = plast; - nstart = n + 1; - do { - ++n; - en += 2.; - pold = plast; - plast = p; - p = en * plast / *x + pold; - } - while (p <= 1.); - - bb = en / *x; - /* ------------------------------------------------ - Calculate backward test, and find NCALC, - the highest N such that the test is passed. - ------------------------------------------------ */ - test = pold * plast / ensig_BESS; - test *= .5 - .5 / (bb * bb); - p = plast * tover; - --n; - en -= 2.; - nend = imin2(*nb,n); - for (l = nstart; l <= nend; ++l) { - *ncalc = l; - pold = psavel; - psavel = psave; - psave = en * psavel / *x + pold; - if (psave * psavel > test) { - goto L90; - } - } - *ncalc = nend + 1; -L90: - --(*ncalc); - goto L120; - } - } - n = nend; - en = (double)(n + n) + twonu; - /*--------------------------------------------------- - Calculate special significance test for NBMX > 2. - --------------------------------------------------- */ - test = fmax2(test,sqrt(plast * ensig_BESS) * sqrt(p + p)); - } - /* -------------------------------------------------------- - Calculate P-sequence until significance test passed. - -------------------------------------------------------- */ - do { - ++n; - en += 2.; - pold = plast; - plast = p; - p = en * plast / *x + pold; - } while (p < test); - -L120: -/* ------------------------------------------------------------------- - Initialize the backward recursion and the normalization sum. - ------------------------------------------------------------------- */ - ++n; - en += 2.; - bb = 0.; - aa = 1. / p; - em = (double) n - 1.; - empal = em + nu; - emp2al = em - 1. + twonu; - sum = aa * empal * emp2al / em; - nend = n - *nb; - if (nend < 0) { - /* ----------------------------------------------------- - N < NB, so store BI[N] and set higher orders to 0.. - ----------------------------------------------------- */ - bi[n] = aa; - nend = -nend; - for (l = 1; l <= nend; ++l) { - bi[n + l] = 0.; - } - } else { - if (nend > 0) { - /* ----------------------------------------------------- - Recur backward via difference equation, - calculating (but not storing) BI[N], until N = NB. - --------------------------------------------------- */ - - for (l = 1; l <= nend; ++l) { - --n; - en -= 2.; - cc = bb; - bb = aa; - /* for x ~= 1500, sum would overflow to 'inf' here, - * and the final bi[] /= sum would give 0 wrongly; - * RE-normalize (aa, sum) here -- no need to undo */ - if(nend > 100 && aa > 1e200) { - /* multiply by 2^-900 = 1.18e-271 */ - cc = ldexp(cc, -900); - bb = ldexp(bb, -900); - sum = ldexp(sum,-900); - } - aa = en * bb / *x + cc; - em -= 1.; - emp2al -= 1.; - if (n == 1) { - break; - } - if (n == 2) { - emp2al = 1.; - } - empal -= 1.; - sum = (sum + aa * empal) * emp2al / em; - } - } - /* --------------------------------------------------- - Store BI[NB] - --------------------------------------------------- */ - bi[n] = aa; - if (*nb <= 1) { - sum = sum + sum + aa; - goto L230; - } - /* ------------------------------------------------- - Calculate and Store BI[NB-1] - ------------------------------------------------- */ - --n; - en -= 2.; - bi[n] = en * aa / *x + bb; - if (n == 1) { - goto L220; - } - em -= 1.; - if (n == 2) - emp2al = 1.; - else - emp2al -= 1.; - - empal -= 1.; - sum = (sum + bi[n] * empal) * emp2al / em; - } - nend = n - 2; - if (nend > 0) { - /* -------------------------------------------- - Calculate via difference equation - and store BI[N], until N = 2. - ------------------------------------------ */ - for (l = 1; l <= nend; ++l) { - --n; - en -= 2.; - bi[n] = en * bi[n + 1] / *x + bi[n + 2]; - em -= 1.; - if (n == 2) - emp2al = 1.; - else - emp2al -= 1.; - empal -= 1.; - sum = (sum + bi[n] * empal) * emp2al / em; - } - } - /* ---------------------------------------------- - Calculate BI[1] - -------------------------------------------- */ - bi[1] = 2. * empal * bi[2] / *x + bi[3]; -L220: - sum = sum + sum + bi[1]; - -L230: - /* --------------------------------------------------------- - Normalize. Divide all BI[N] by sum. - --------------------------------------------------------- */ - if (nu != 0.) - sum *= (gamma_cody(1. + nu) * pow(*x * .5, -nu)); - if (*ize == 1) - sum *= exp(-(*x)); - aa = enmten_BESS; - if (sum > 1.) - aa *= sum; - for (n = 1; n <= *nb; ++n) { - if (bi[n] < aa) - bi[n] = 0.; - else - bi[n] /= sum; - } - return; - } else { /* small x < 1e-4 */ - /* ----------------------------------------------------------- - Two-term ascending series for small X. - -----------------------------------------------------------*/ - aa = 1.; - empal = 1. + nu; -#ifdef IEEE_754 - /* No need to check for underflow */ - halfx = .5 * *x; -#else - if (*x > enmten_BESS) */ - halfx = .5 * *x; - else - halfx = 0.; -#endif - if (nu != 0.) - aa = pow(halfx, nu) / gamma_cody(empal); - if (*ize == 2) - aa *= exp(-(*x)); - bb = halfx * halfx; - bi[1] = aa + aa * bb / empal; - if (*x != 0. && bi[1] == 0.) - *ncalc = 0; - if (*nb > 1) { - if (*x == 0.) { - for (n = 2; n <= *nb; ++n) - bi[n] = 0.; - } else { - /* ------------------------------------------------- - Calculate higher-order functions. - ------------------------------------------------- */ - cc = halfx; - tover = (enmten_BESS + enmten_BESS) / *x; - if (bb != 0.) - tover = enmten_BESS / bb; - for (n = 2; n <= *nb; ++n) { - aa /= empal; - empal += 1.; - aa *= cc; - if (aa <= tover * empal) - bi[n] = aa = 0.; - else - bi[n] = aa + aa * bb / empal; - if (bi[n] == 0. && *ncalc > n) - *ncalc = n - 1; - } - } - } - } - } else { /* argument out of range */ - *ncalc = imin2(*nb,0) - 1; - } -} diff --git a/deps/Rmath/src/bessel_j.c b/deps/Rmath/src/bessel_j.c deleted file mode 100644 index ce0eaf4d14918..0000000000000 --- a/deps/Rmath/src/bessel_j.c +++ /dev/null @@ -1,575 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998-2005 Ross Ihaka and the R Development Core team. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - */ - -/* DESCRIPTION --> see below */ - - -/* From http://www.netlib.org/specfun/rjbesl Fortran translated by f2c,... - * ------------------------------=#---- Martin Maechler, ETH Zurich - * Additional code for nu == alpha < 0 MM - */ -#include "nmath.h" -#include "bessel.h" - -#ifndef MATHLIB_STANDALONE -#include -#endif - -static void J_bessel(double *x, double *alpha, long *nb, - double *b, long *ncalc); - -double bessel_j(double x, double alpha) -{ - long nb, ncalc; - double na, *bj; -#ifndef MATHLIB_STANDALONE - const void *vmax; -#endif - -#ifdef IEEE_754 - /* NaNs propagated correctly */ - if (ISNAN(x) || ISNAN(alpha)) return x + alpha; -#endif - if (x < 0) { - ML_ERROR(ME_RANGE, "bessel_j"); - return ML_NAN; - } - na = floor(alpha); - if (alpha < 0) { - /* Using Abramowitz & Stegun 9.1.2 - * this may not be quite optimal (CPU and accuracy wise) */ - return(bessel_j(x, -alpha) * cos(M_PI * alpha) + - ((alpha == na) ? 0 : - bessel_y(x, -alpha) * sin(M_PI * alpha))); - } - nb = 1 + (long)na; /* nb-1 <= alpha < nb */ - alpha -= (nb-1); -#ifdef MATHLIB_STANDALONE - bj = (double *) calloc(nb, sizeof(double)); - if (!bj) MATHLIB_ERROR("%s", _("bessel_j allocation error")); -#else - vmax = vmaxget(); - bj = (double *) R_alloc((size_t) nb, sizeof(double)); -#endif - J_bessel(&x, &alpha, &nb, bj, &ncalc); - if(ncalc != nb) {/* error input */ - if(ncalc < 0) - MATHLIB_WARNING4(_("bessel_j(%g): ncalc (=%ld) != nb (=%ld); alpha=%g. Arg. out of range?\n"), - x, ncalc, nb, alpha); - else - MATHLIB_WARNING2(_("bessel_j(%g,nu=%g): precision lost in result\n"), - x, alpha+nb-1); - } - x = bj[nb-1]; -#ifdef MATHLIB_STANDALONE - free(bj); -#else - vmaxset(vmax); -#endif - return x; -} - -/* modified version of bessel_j that accepts a work array instead of - allocating one. */ -double bessel_j_ex(double x, double alpha, double *bj) -{ - long nb, ncalc; - double na; - -#ifdef IEEE_754 - /* NaNs propagated correctly */ - if (ISNAN(x) || ISNAN(alpha)) return x + alpha; -#endif - if (x < 0) { - ML_ERROR(ME_RANGE, "bessel_j"); - return ML_NAN; - } - na = floor(alpha); - if (alpha < 0) { - /* Using Abramowitz & Stegun 9.1.2 - * this may not be quite optimal (CPU and accuracy wise) */ - return(bessel_j_ex(x, -alpha, bj) * cos(M_PI * alpha) + - ((alpha == na) ? 0 : - bessel_y_ex(x, -alpha, bj) * sin(M_PI * alpha))); - } - nb = 1 + (long)na; /* nb-1 <= alpha < nb */ - alpha -= (nb-1); - J_bessel(&x, &alpha, &nb, bj, &ncalc); - if(ncalc != nb) {/* error input */ - if(ncalc < 0) - MATHLIB_WARNING4(_("bessel_j(%g): ncalc (=%ld) != nb (=%ld); alpha=%g. Arg. out of range?\n"), - x, ncalc, nb, alpha); - else - MATHLIB_WARNING2(_("bessel_j(%g,nu=%g): precision lost in result\n"), - x, alpha+nb-1); - } - x = bj[nb-1]; - return x; -} - -static void J_bessel(double *x, double *alpha, long *nb, - double *b, long *ncalc) -{ -/* - Calculates Bessel functions J_{n+alpha} (x) - for non-negative argument x, and non-negative order n+alpha, n = 0,1,..,nb-1. - - Explanation of variables in the calling sequence. - - X - Non-negative argument for which J's are to be calculated. - ALPHA - Fractional part of order for which - J's are to be calculated. 0 <= ALPHA < 1. - NB - Number of functions to be calculated, NB >= 1. - The first function calculated is of order ALPHA, and the - last is of order (NB - 1 + ALPHA). - B - Output vector of length NB. If RJBESL - terminates normally (NCALC=NB), the vector B contains the - functions J/ALPHA/(X) through J/NB-1+ALPHA/(X). - NCALC - Output variable indicating possible errors. - Before using the vector B, the user should check that - NCALC=NB, i.e., all orders have been calculated to - the desired accuracy. See the following - - **************************************************************** - - Error return codes - - In case of an error, NCALC != NB, and not all J's are - calculated to the desired accuracy. - - NCALC < 0: An argument is out of range. For example, - NBES <= 0, ALPHA < 0 or > 1, or X is too large. - In this case, b[1] is set to zero, the remainder of the - B-vector is not calculated, and NCALC is set to - MIN(NB,0)-1 so that NCALC != NB. - - NB > NCALC > 0: Not all requested function values could - be calculated accurately. This usually occurs because NB is - much larger than ABS(X). In this case, b[N] is calculated - to the desired accuracy for N <= NCALC, but precision - is lost for NCALC < N <= NB. If b[N] does not vanish - for N > NCALC (because it is too small to be represented), - and b[N]/b[NCALC] = 10^(-K), then only the first NSIG - K - significant figures of b[N] can be trusted. - - - Acknowledgement - - This program is based on a program written by David J. Sookne - (2) that computes values of the Bessel functions J or I of float - argument and long order. Modifications include the restriction - of the computation to the J Bessel function of non-negative float - argument, the extension of the computation to arbitrary positive - order, and the elimination of most underflow. - - References: - - Olver, F.W.J., and Sookne, D.J. (1972) - "A Note on Backward Recurrence Algorithms"; - Math. Comp. 26, 941-947. - - Sookne, D.J. (1973) - "Bessel Functions of Real Argument and Integer Order"; - NBS Jour. of Res. B. 77B, 125-132. - - Latest modification: March 19, 1990 - - Author: W. J. Cody - Applied Mathematics Division - Argonne National Laboratory - Argonne, IL 60439 - ******************************************************************* - */ - -/* --------------------------------------------------------------------- - Mathematical constants - - PI2 = 2 / PI - TWOPI1 = first few significant digits of 2 * PI - TWOPI2 = (2*PI - TWOPI1) to working precision, i.e., - TWOPI1 + TWOPI2 = 2 * PI to extra precision. - --------------------------------------------------------------------- */ - const static double pi2 = .636619772367581343075535; - const static double twopi1 = 6.28125; - const static double twopi2 = .001935307179586476925286767; - -/*--------------------------------------------------------------------- - * Factorial(N) - *--------------------------------------------------------------------- */ - const static double fact[25] = { 1.,1.,2.,6.,24.,120.,720.,5040.,40320., - 362880.,3628800.,39916800.,479001600.,6227020800.,87178291200., - 1.307674368e12,2.0922789888e13,3.55687428096e14,6.402373705728e15, - 1.21645100408832e17,2.43290200817664e18,5.109094217170944e19, - 1.12400072777760768e21,2.585201673888497664e22, - 6.2044840173323943936e23 }; - - /* Local variables */ - long nend, intx, nbmx, i, j, k, l, m, n, nstart; - - double nu, twonu, capp, capq, pold, vcos, test, vsin; - double p, s, t, z, alpem, halfx, aa, bb, cc, psave, plast; - double tover, t1, alp2em, em, en, xc, xk, xm, psavel, gnu, xin, sum; - - - /* Parameter adjustment */ - --b; - - nu = *alpha; - twonu = nu + nu; - - /*------------------------------------------------------------------- - Check for out of range arguments. - -------------------------------------------------------------------*/ - if (*nb > 0 && *x >= 0. && 0. <= nu && nu < 1.) { - - *ncalc = *nb; - if(*x > xlrg_BESS_IJ) { - ML_ERROR(ME_RANGE, "J_bessel"); - /* indeed, the limit is 0, - * but the cutoff happens too early */ - for(i=1; i <= *nb; i++) - b[i] = 0.; /*was ML_POSINF (really nonsense) */ - return; - } - intx = (long) (*x); - /* Initialize result array to zero. */ - for (i = 1; i <= *nb; ++i) - b[i] = 0.; - - /*=================================================================== - Branch into 3 cases : - 1) use 2-term ascending series for small X - 2) use asymptotic form for large X when NB is not too large - 3) use recursion otherwise - ===================================================================*/ - - if (*x < rtnsig_BESS) { - /* --------------------------------------------------------------- - Two-term ascending series for small X. - --------------------------------------------------------------- */ - alpem = 1. + nu; - - halfx = (*x > enmten_BESS) ? .5 * *x : 0.; - aa = (nu != 0.) ? pow(halfx, nu) / (nu * gamma_cody(nu)) : 1.; - bb = (*x + 1. > 1.)? -halfx * halfx : 0.; - b[1] = aa + aa * bb / alpem; - if (*x != 0. && b[1] == 0.) - *ncalc = 0; - - if (*nb != 1) { - if (*x <= 0.) { - for (n = 2; n <= *nb; ++n) - b[n] = 0.; - } - else { - /* ---------------------------------------------- - Calculate higher order functions. - ---------------------------------------------- */ - if (bb == 0.) - tover = (enmten_BESS + enmten_BESS) / *x; - else - tover = enmten_BESS / bb; - cc = halfx; - for (n = 2; n <= *nb; ++n) { - aa /= alpem; - alpem += 1.; - aa *= cc; - if (aa <= tover * alpem) - aa = 0.; - - b[n] = aa + aa * bb / alpem; - if (b[n] == 0. && *ncalc > n) - *ncalc = n - 1; - } - } - } - } else if (*x > 25. && *nb <= intx + 1) { - /* ------------------------------------------------------------ - Asymptotic series for X > 25 (and not too large nb) - ------------------------------------------------------------ */ - xc = sqrt(pi2 / *x); - xin = 1 / (64 * *x * *x); - if (*x >= 130.) m = 4; - else if (*x >= 35.) m = 8; - else m = 11; - xm = 4. * (double) m; - /* ------------------------------------------------ - Argument reduction for SIN and COS routines. - ------------------------------------------------ */ - t = ftrunc(*x / (twopi1 + twopi2) + .5); - z = (*x - t * twopi1) - t * twopi2 - (nu + .5) / pi2; - vsin = sin(z); - vcos = cos(z); - gnu = twonu; - for (i = 1; i <= 2; ++i) { - s = (xm - 1. - gnu) * (xm - 1. + gnu) * xin * .5; - t = (gnu - (xm - 3.)) * (gnu + (xm - 3.)); - t1= (gnu - (xm + 1.)) * (gnu + (xm + 1.)); - k = m + m; - capp = s * t / fact[k]; - capq = s * t1/ fact[k + 1]; - xk = xm; - for (; k >= 4; k -= 2) {/* k + 2(j-2) == 2m */ - xk -= 4.; - s = (xk - 1. - gnu) * (xk - 1. + gnu); - t1 = t; - t = (gnu - (xk - 3.)) * (gnu + (xk - 3.)); - capp = (capp + 1. / fact[k - 2]) * s * t * xin; - capq = (capq + 1. / fact[k - 1]) * s * t1 * xin; - - } - capp += 1.; - capq = (capq + 1.) * (gnu * gnu - 1.) * (.125 / *x); - b[i] = xc * (capp * vcos - capq * vsin); - if (*nb == 1) - return; - - /* vsin <--> vcos */ t = vsin; vsin = -vcos; vcos = t; - gnu += 2.; - } - /* ----------------------------------------------- - If NB > 2, compute J(X,ORDER+I) for I = 2, NB-1 - ----------------------------------------------- */ - if (*nb > 2) - for (gnu = twonu + 2., j = 3; j <= *nb; j++, gnu += 2.) - b[j] = gnu * b[j - 1] / *x - b[j - 2]; - } - else { - /* rtnsig_BESS <= x && ( x <= 25 || intx+1 < *nb ) : - -------------------------------------------------------- - Use recurrence to generate results. - First initialize the calculation of P*S. - -------------------------------------------------------- */ - nbmx = *nb - intx; - n = intx + 1; - en = (double)(n + n) + twonu; - plast = 1.; - p = en / *x; - /* --------------------------------------------------- - Calculate general significance test. - --------------------------------------------------- */ - test = ensig_BESS + ensig_BESS; - if (nbmx >= 3) { - /* ------------------------------------------------------------ - Calculate P*S until N = NB-1. Check for possible overflow. - ---------------------------------------------------------- */ - tover = enten_BESS / ensig_BESS; - nstart = intx + 2; - nend = *nb - 1; - en = (double) (nstart + nstart) - 2. + twonu; - for (k = nstart; k <= nend; ++k) { - n = k; - en += 2.; - pold = plast; - plast = p; - p = en * plast / *x - pold; - if (p > tover) { - /* ------------------------------------------- - To avoid overflow, divide P*S by TOVER. - Calculate P*S until ABS(P) > 1. - -------------------------------------------*/ - tover = enten_BESS; - p /= tover; - plast /= tover; - psave = p; - psavel = plast; - nstart = n + 1; - do { - ++n; - en += 2.; - pold = plast; - plast = p; - p = en * plast / *x - pold; - } while (p <= 1.); - - bb = en / *x; - /* ----------------------------------------------- - Calculate backward test and find NCALC, - the highest N such that the test is passed. - ----------------------------------------------- */ - test = pold * plast * (.5 - .5 / (bb * bb)); - test /= ensig_BESS; - p = plast * tover; - --n; - en -= 2.; - nend = imin2(*nb,n); - for (l = nstart; l <= nend; ++l) { - pold = psavel; - psavel = psave; - psave = en * psavel / *x - pold; - if (psave * psavel > test) { - *ncalc = l - 1; - goto L190; - } - } - *ncalc = nend; - goto L190; - } - } - n = nend; - en = (double) (n + n) + twonu; - /* ----------------------------------------------------- - Calculate special significance test for NBMX > 2. - -----------------------------------------------------*/ - test = fmax2(test, sqrt(plast * ensig_BESS) * sqrt(p + p)); - } - /* ------------------------------------------------ - Calculate P*S until significance test passes. */ - do { - ++n; - en += 2.; - pold = plast; - plast = p; - p = en * plast / *x - pold; - } while (p < test); - -L190: - /*--------------------------------------------------------------- - Initialize the backward recursion and the normalization sum. - --------------------------------------------------------------- */ - ++n; - en += 2.; - bb = 0.; - aa = 1. / p; - m = n / 2; - em = (double)m; - m = (n << 1) - (m << 2);/* = 2 n - 4 (n/2) - = 0 for even, 2 for odd n */ - if (m == 0) - sum = 0.; - else { - alpem = em - 1. + nu; - alp2em = em + em + nu; - sum = aa * alpem * alp2em / em; - } - nend = n - *nb; - /* if (nend > 0) */ - /* -------------------------------------------------------- - Recur backward via difference equation, calculating - (but not storing) b[N], until N = NB. - -------------------------------------------------------- */ - for (l = 1; l <= nend; ++l) { - --n; - en -= 2.; - cc = bb; - bb = aa; - aa = en * bb / *x - cc; - m = m ? 0 : 2; /* m = 2 - m failed on gcc4-20041019 */ - if (m != 0) { - em -= 1.; - alp2em = em + em + nu; - if (n == 1) - break; - - alpem = em - 1. + nu; - if (alpem == 0.) - alpem = 1.; - sum = (sum + aa * alp2em) * alpem / em; - } - } - /*-------------------------------------------------- - Store b[NB]. - --------------------------------------------------*/ - b[n] = aa; - if (nend >= 0) { - if (*nb <= 1) { - if (nu + 1. == 1.) - alp2em = 1.; - else - alp2em = nu; - sum += b[1] * alp2em; - goto L250; - } - else {/*-- nb >= 2 : --------------------------- - Calculate and store b[NB-1]. - ----------------------------------------*/ - --n; - en -= 2.; - b[n] = en * aa / *x - bb; - if (n == 1) - goto L240; - - m = m ? 0 : 2; /* m = 2 - m failed on gcc4-20041019 */ - if (m != 0) { - em -= 1.; - alp2em = em + em + nu; - alpem = em - 1. + nu; - if (alpem == 0.) - alpem = 1.; - sum = (sum + b[n] * alp2em) * alpem / em; - } - } - } - - /* if (n - 2 != 0) */ - /* -------------------------------------------------------- - Calculate via difference equation and store b[N], - until N = 2. - -------------------------------------------------------- */ - for (n = n-1; n >= 2; n--) { - en -= 2.; - b[n] = en * b[n + 1] / *x - b[n + 2]; - m = m ? 0 : 2; /* m = 2 - m failed on gcc4-20041019 */ - if (m != 0) { - em -= 1.; - alp2em = em + em + nu; - alpem = em - 1. + nu; - if (alpem == 0.) - alpem = 1.; - sum = (sum + b[n] * alp2em) * alpem / em; - } - } - /* --------------------------------------- - Calculate b[1]. - -----------------------------------------*/ - b[1] = 2. * (nu + 1.) * b[2] / *x - b[3]; - -L240: - em -= 1.; - alp2em = em + em + nu; - if (alp2em == 0.) - alp2em = 1.; - sum += b[1] * alp2em; - -L250: - /* --------------------------------------------------- - Normalize. Divide all b[N] by sum. - ---------------------------------------------------*/ -/* if (nu + 1. != 1.) poor test */ - if(fabs(nu) > 1e-15) - sum *= (gamma_cody(nu) * pow(.5* *x, -nu)); - - aa = enmten_BESS; - if (sum > 1.) - aa *= sum; - for (n = 1; n <= *nb; ++n) { - if (fabs(b[n]) < aa) - b[n] = 0.; - else - b[n] /= sum; - } - } - - } - else { - /* Error return -- X, NB, or ALPHA is out of range : */ - b[1] = 0.; - *ncalc = imin2(*nb,0) - 1; - } -} diff --git a/deps/Rmath/src/bessel_k.c b/deps/Rmath/src/bessel_k.c deleted file mode 100644 index 789be18bbd611..0000000000000 --- a/deps/Rmath/src/bessel_k.c +++ /dev/null @@ -1,558 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998-2001 Ross Ihaka and the R Development Core team. - * Copyright (C) 2002-3 The R Foundation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - */ - -/* DESCRIPTION --> see below */ - - -/* From http://www.netlib.org/specfun/rkbesl Fortran translated by f2c,... - * ------------------------------=#---- Martin Maechler, ETH Zurich - */ -#include "nmath.h" -#include "bessel.h" - -#ifndef MATHLIB_STANDALONE -#include -#endif - -static void K_bessel(double *x, double *alpha, long *nb, - long *ize, double *bk, long *ncalc); - -double bessel_k(double x, double alpha, double expo) -{ - long nb, ncalc, ize; - double *bk; -#ifndef MATHLIB_STANDALONE - const void *vmax; -#endif - -#ifdef IEEE_754 - /* NaNs propagated correctly */ - if (ISNAN(x) || ISNAN(alpha)) return x + alpha; -#endif - if (x < 0) { - ML_ERROR(ME_RANGE, "bessel_k"); - return ML_NAN; - } - ize = (long)expo; - if(alpha < 0) - alpha = -alpha; - nb = 1+ (long)floor(alpha);/* nb-1 <= |alpha| < nb */ - alpha -= (nb-1); -#ifdef MATHLIB_STANDALONE - bk = (double *) calloc(nb, sizeof(double)); - if (!bk) MATHLIB_ERROR("%s", _("bessel_k allocation error")); -#else - vmax = vmaxget(); - bk = (double *) R_alloc((size_t) nb, sizeof(double)); -#endif - K_bessel(&x, &alpha, &nb, &ize, bk, &ncalc); - if(ncalc != nb) {/* error input */ - if(ncalc < 0) - MATHLIB_WARNING4(_("bessel_k(%g): ncalc (=%ld) != nb (=%ld); alpha=%g. Arg. out of range?\n"), - x, ncalc, nb, alpha); - else - MATHLIB_WARNING2(_("bessel_k(%g,nu=%g): precision lost in result\n"), - x, alpha+nb-1); - } - x = bk[nb-1]; -#ifdef MATHLIB_STANDALONE - free(bk); -#else - vmaxset(vmax); -#endif - return x; -} - -/* modified version of bessel_k that accepts a work array instead of - allocating one. */ -double bessel_k_ex(double x, double alpha, double expo, double *bk) -{ - long nb, ncalc, ize; - -#ifdef IEEE_754 - /* NaNs propagated correctly */ - if (ISNAN(x) || ISNAN(alpha)) return x + alpha; -#endif - if (x < 0) { - ML_ERROR(ME_RANGE, "bessel_k"); - return ML_NAN; - } - ize = (long)expo; - if(alpha < 0) - alpha = -alpha; - nb = 1+ (long)floor(alpha);/* nb-1 <= |alpha| < nb */ - alpha -= (nb-1); - K_bessel(&x, &alpha, &nb, &ize, bk, &ncalc); - if(ncalc != nb) {/* error input */ - if(ncalc < 0) - MATHLIB_WARNING4(_("bessel_k(%g): ncalc (=%ld) != nb (=%ld); alpha=%g. Arg. out of range?\n"), - x, ncalc, nb, alpha); - else - MATHLIB_WARNING2(_("bessel_k(%g,nu=%g): precision lost in result\n"), - x, alpha+nb-1); - } - x = bk[nb-1]; - return x; -} - -static void K_bessel(double *x, double *alpha, long *nb, - long *ize, double *bk, long *ncalc) -{ -/*------------------------------------------------------------------- - - This routine calculates modified Bessel functions - of the third kind, K_(N+ALPHA) (X), for non-negative - argument X, and non-negative order N+ALPHA, with or without - exponential scaling. - - Explanation of variables in the calling sequence - - X - Non-negative argument for which - K's or exponentially scaled K's (K*EXP(X)) - are to be calculated. If K's are to be calculated, - X must not be greater than XMAX_BESS_K. - ALPHA - Fractional part of order for which - K's or exponentially scaled K's (K*EXP(X)) are - to be calculated. 0 <= ALPHA < 1.0. - NB - Number of functions to be calculated, NB > 0. - The first function calculated is of order ALPHA, and the - last is of order (NB - 1 + ALPHA). - IZE - Type. IZE = 1 if unscaled K's are to be calculated, - = 2 if exponentially scaled K's are to be calculated. - BK - Output vector of length NB. If the - routine terminates normally (NCALC=NB), the vector BK - contains the functions K(ALPHA,X), ... , K(NB-1+ALPHA,X), - or the corresponding exponentially scaled functions. - If (0 < NCALC < NB), BK(I) contains correct function - values for I <= NCALC, and contains the ratios - K(ALPHA+I-1,X)/K(ALPHA+I-2,X) for the rest of the array. - NCALC - Output variable indicating possible errors. - Before using the vector BK, the user should check that - NCALC=NB, i.e., all orders have been calculated to - the desired accuracy. See error returns below. - - - ******************************************************************* - - Error returns - - In case of an error, NCALC != NB, and not all K's are - calculated to the desired accuracy. - - NCALC < -1: An argument is out of range. For example, - NB <= 0, IZE is not 1 or 2, or IZE=1 and ABS(X) >= XMAX_BESS_K. - In this case, the B-vector is not calculated, - and NCALC is set to MIN0(NB,0)-2 so that NCALC != NB. - NCALC = -1: Either K(ALPHA,X) >= XINF or - K(ALPHA+NB-1,X)/K(ALPHA+NB-2,X) >= XINF. In this case, - the B-vector is not calculated. Note that again - NCALC != NB. - - 0 < NCALC < NB: Not all requested function values could - be calculated accurately. BK(I) contains correct function - values for I <= NCALC, and contains the ratios - K(ALPHA+I-1,X)/K(ALPHA+I-2,X) for the rest of the array. - - - Intrinsic functions required are: - - ABS, AINT, EXP, INT, LOG, MAX, MIN, SINH, SQRT - - - Acknowledgement - - This program is based on a program written by J. B. Campbell - (2) that computes values of the Bessel functions K of float - argument and float order. Modifications include the addition - of non-scaled functions, parameterization of machine - dependencies, and the use of more accurate approximations - for SINH and SIN. - - References: "On Temme's Algorithm for the Modified Bessel - Functions of the Third Kind," Campbell, J. B., - TOMS 6(4), Dec. 1980, pp. 581-586. - - "A FORTRAN IV Subroutine for the Modified Bessel - Functions of the Third Kind of Real Order and Real - Argument," Campbell, J. B., Report NRC/ERB-925, - National Research Council, Canada. - - Latest modification: May 30, 1989 - - Modified by: W. J. Cody and L. Stoltz - Applied Mathematics Division - Argonne National Laboratory - Argonne, IL 60439 - - ------------------------------------------------------------------- -*/ - /*--------------------------------------------------------------------- - * Mathematical constants - * A = LOG(2) - Euler's constant - * D = SQRT(2/PI) - ---------------------------------------------------------------------*/ - const static double a = .11593151565841244881; - - /*--------------------------------------------------------------------- - P, Q - Approximation for LOG(GAMMA(1+ALPHA))/ALPHA + Euler's constant - Coefficients converted from hex to decimal and modified - by W. J. Cody, 2/26/82 */ - const static double p[8] = { .805629875690432845,20.4045500205365151, - 157.705605106676174,536.671116469207504,900.382759291288778, - 730.923886650660393,229.299301509425145,.822467033424113231 }; - const static double q[7] = { 29.4601986247850434,277.577868510221208, - 1206.70325591027438,2762.91444159791519,3443.74050506564618, - 2210.63190113378647,572.267338359892221 }; - /* R, S - Approximation for (1-ALPHA*PI/SIN(ALPHA*PI))/(2.D0*ALPHA) */ - const static double r[5] = { -.48672575865218401848,13.079485869097804016, - -101.96490580880537526,347.65409106507813131, - 3.495898124521934782e-4 }; - const static double s[4] = { -25.579105509976461286,212.57260432226544008, - -610.69018684944109624,422.69668805777760407 }; - /* T - Approximation for SINH(Y)/Y */ - const static double t[6] = { 1.6125990452916363814e-10, - 2.5051878502858255354e-8,2.7557319615147964774e-6, - 1.9841269840928373686e-4,.0083333333333334751799, - .16666666666666666446 }; - /*---------------------------------------------------------------------*/ - const static double estm[6] = { 52.0583,5.7607,2.7782,14.4303,185.3004, 9.3715 }; - const static double estf[7] = { 41.8341,7.1075,6.4306,42.511,1.35633,84.5096,20.}; - - /* Local variables */ - long iend, i, j, k, m, ii, mplus1; - double x2by4, twox, c, blpha, ratio, wminf; - double d1, d2, d3, f0, f1, f2, p0, q0, t1, t2, twonu; - double dm, ex, bk1, bk2, nu; - - ii = 0; /* -Wall */ - - ex = *x; - nu = *alpha; - *ncalc = imin2(*nb,0) - 2; - if (*nb > 0 && (0. <= nu && nu < 1.) && (1 <= *ize && *ize <= 2)) { - if(ex <= 0 || (*ize == 1 && ex > xmax_BESS_K)) { - if(ex <= 0) { - if(ex < 0) ML_ERROR(ME_RANGE, "K_bessel"); - for(i=0; i < *nb; i++) - bk[i] = ML_POSINF; - } else /* would only have underflow */ - for(i=0; i < *nb; i++) - bk[i] = 0.; - *ncalc = *nb; - return; - } - k = 0; - if (nu < sqxmin_BESS_K) { - nu = 0.; - } else if (nu > .5) { - k = 1; - nu -= 1.; - } - twonu = nu + nu; - iend = *nb + k - 1; - c = nu * nu; - d3 = -c; - if (ex <= 1.) { - /* ------------------------------------------------------------ - Calculation of P0 = GAMMA(1+ALPHA) * (2/X)**ALPHA - Q0 = GAMMA(1-ALPHA) * (X/2)**ALPHA - ------------------------------------------------------------ */ - d1 = 0.; d2 = p[0]; - t1 = 1.; t2 = q[0]; - for (i = 2; i <= 7; i += 2) { - d1 = c * d1 + p[i - 1]; - d2 = c * d2 + p[i]; - t1 = c * t1 + q[i - 1]; - t2 = c * t2 + q[i]; - } - d1 = nu * d1; - t1 = nu * t1; - f1 = log(ex); - f0 = a + nu * (p[7] - nu * (d1 + d2) / (t1 + t2)) - f1; - q0 = exp(-nu * (a - nu * (p[7] + nu * (d1-d2) / (t1-t2)) - f1)); - f1 = nu * f0; - p0 = exp(f1); - /* ----------------------------------------------------------- - Calculation of F0 = - ----------------------------------------------------------- */ - d1 = r[4]; - t1 = 1.; - for (i = 0; i < 4; ++i) { - d1 = c * d1 + r[i]; - t1 = c * t1 + s[i]; - } - /* d2 := sinh(f1)/ nu = sinh(f1)/(f1/f0) - * = f0 * sinh(f1)/f1 */ - if (fabs(f1) <= .5) { - f1 *= f1; - d2 = 0.; - for (i = 0; i < 6; ++i) { - d2 = f1 * d2 + t[i]; - } - d2 = f0 + f0 * f1 * d2; - } else { - d2 = sinh(f1) / nu; - } - f0 = d2 - nu * d1 / (t1 * p0); - if (ex <= 1e-10) { - /* --------------------------------------------------------- - X <= 1.0E-10 - Calculation of K(ALPHA,X) and X*K(ALPHA+1,X)/K(ALPHA,X) - --------------------------------------------------------- */ - bk[0] = f0 + ex * f0; - if (*ize == 1) { - bk[0] -= ex * bk[0]; - } - ratio = p0 / f0; - c = ex * DBL_MAX; - if (k != 0) { - /* --------------------------------------------------- - Calculation of K(ALPHA,X) - and X*K(ALPHA+1,X)/K(ALPHA,X), ALPHA >= 1/2 - --------------------------------------------------- */ - *ncalc = -1; - if (bk[0] >= c / ratio) { - return; - } - bk[0] = ratio * bk[0] / ex; - twonu += 2.; - ratio = twonu; - } - *ncalc = 1; - if (*nb == 1) - return; - - /* ----------------------------------------------------- - Calculate K(ALPHA+L,X)/K(ALPHA+L-1,X), - L = 1, 2, ... , NB-1 - ----------------------------------------------------- */ - *ncalc = -1; - for (i = 1; i < *nb; ++i) { - if (ratio >= c) - return; - - bk[i] = ratio / ex; - twonu += 2.; - ratio = twonu; - } - *ncalc = 1; - goto L420; - } else { - /* ------------------------------------------------------ - 10^-10 < X <= 1.0 - ------------------------------------------------------ */ - c = 1.; - x2by4 = ex * ex / 4.; - p0 = .5 * p0; - q0 = .5 * q0; - d1 = -1.; - d2 = 0.; - bk1 = 0.; - bk2 = 0.; - f1 = f0; - f2 = p0; - do { - d1 += 2.; - d2 += 1.; - d3 = d1 + d3; - c = x2by4 * c / d2; - f0 = (d2 * f0 + p0 + q0) / d3; - p0 /= d2 - nu; - q0 /= d2 + nu; - t1 = c * f0; - t2 = c * (p0 - d2 * f0); - bk1 += t1; - bk2 += t2; - } while (fabs(t1 / (f1 + bk1)) > DBL_EPSILON || - fabs(t2 / (f2 + bk2)) > DBL_EPSILON); - bk1 = f1 + bk1; - bk2 = 2. * (f2 + bk2) / ex; - if (*ize == 2) { - d1 = exp(ex); - bk1 *= d1; - bk2 *= d1; - } - wminf = estf[0] * ex + estf[1]; - } - } else if (DBL_EPSILON * ex > 1.) { - /* ------------------------------------------------- - X > 1./EPS - ------------------------------------------------- */ - *ncalc = *nb; - bk1 = 1. / (M_SQRT_2dPI * sqrt(ex)); - for (i = 0; i < *nb; ++i) - bk[i] = bk1; - return; - - } else { - /* ------------------------------------------------------- - X > 1.0 - ------------------------------------------------------- */ - twox = ex + ex; - blpha = 0.; - ratio = 0.; - if (ex <= 4.) { - /* ---------------------------------------------------------- - Calculation of K(ALPHA+1,X)/K(ALPHA,X), 1.0 <= X <= 4.0 - ----------------------------------------------------------*/ - d2 = ftrunc(estm[0] / ex + estm[1]); - m = (long) d2; - d1 = d2 + d2; - d2 -= .5; - d2 *= d2; - for (i = 2; i <= m; ++i) { - d1 -= 2.; - d2 -= d1; - ratio = (d3 + d2) / (twox + d1 - ratio); - } - /* ----------------------------------------------------------- - Calculation of I(|ALPHA|,X) and I(|ALPHA|+1,X) by backward - recurrence and K(ALPHA,X) from the wronskian - -----------------------------------------------------------*/ - d2 = ftrunc(estm[2] * ex + estm[3]); - m = (long) d2; - c = fabs(nu); - d3 = c + c; - d1 = d3 - 1.; - f1 = DBL_MIN; - f0 = (2. * (c + d2) / ex + .5 * ex / (c + d2 + 1.)) * DBL_MIN; - for (i = 3; i <= m; ++i) { - d2 -= 1.; - f2 = (d3 + d2 + d2) * f0; - blpha = (1. + d1 / d2) * (f2 + blpha); - f2 = f2 / ex + f1; - f1 = f0; - f0 = f2; - } - f1 = (d3 + 2.) * f0 / ex + f1; - d1 = 0.; - t1 = 1.; - for (i = 1; i <= 7; ++i) { - d1 = c * d1 + p[i - 1]; - t1 = c * t1 + q[i - 1]; - } - p0 = exp(c * (a + c * (p[7] - c * d1 / t1) - log(ex))) / ex; - f2 = (c + .5 - ratio) * f1 / ex; - bk1 = p0 + (d3 * f0 - f2 + f0 + blpha) / (f2 + f1 + f0) * p0; - if (*ize == 1) { - bk1 *= exp(-ex); - } - wminf = estf[2] * ex + estf[3]; - } else { - /* --------------------------------------------------------- - Calculation of K(ALPHA,X) and K(ALPHA+1,X)/K(ALPHA,X), by - backward recurrence, for X > 4.0 - ----------------------------------------------------------*/ - dm = ftrunc(estm[4] / ex + estm[5]); - m = (long) dm; - d2 = dm - .5; - d2 *= d2; - d1 = dm + dm; - for (i = 2; i <= m; ++i) { - dm -= 1.; - d1 -= 2.; - d2 -= d1; - ratio = (d3 + d2) / (twox + d1 - ratio); - blpha = (ratio + ratio * blpha) / dm; - } - bk1 = 1. / ((M_SQRT_2dPI + M_SQRT_2dPI * blpha) * sqrt(ex)); - if (*ize == 1) - bk1 *= exp(-ex); - wminf = estf[4] * (ex - fabs(ex - estf[6])) + estf[5]; - } - /* --------------------------------------------------------- - Calculation of K(ALPHA+1,X) - from K(ALPHA,X) and K(ALPHA+1,X)/K(ALPHA,X) - --------------------------------------------------------- */ - bk2 = bk1 + bk1 * (nu + .5 - ratio) / ex; - } - /*-------------------------------------------------------------------- - Calculation of 'NCALC', K(ALPHA+I,X), I = 0, 1, ... , NCALC-1, - & K(ALPHA+I,X)/K(ALPHA+I-1,X), I = NCALC, NCALC+1, ... , NB-1 - -------------------------------------------------------------------*/ - *ncalc = *nb; - bk[0] = bk1; - if (iend == 0) - return; - - j = 1 - k; - if (j >= 0) - bk[j] = bk2; - - if (iend == 1) - return; - - m = imin2((long) (wminf - nu),iend); - for (i = 2; i <= m; ++i) { - t1 = bk1; - bk1 = bk2; - twonu += 2.; - if (ex < 1.) { - if (bk1 >= DBL_MAX / twonu * ex) - break; - } else { - if (bk1 / ex >= DBL_MAX / twonu) - break; - } - bk2 = twonu / ex * bk1 + t1; - ii = i; - ++j; - if (j >= 0) { - bk[j] = bk2; - } - } - - m = ii; - if (m == iend) { - return; - } - ratio = bk2 / bk1; - mplus1 = m + 1; - *ncalc = -1; - for (i = mplus1; i <= iend; ++i) { - twonu += 2.; - ratio = twonu / ex + 1./ratio; - ++j; - if (j >= 1) { - bk[j] = ratio; - } else { - if (bk2 >= DBL_MAX / ratio) - return; - - bk2 *= ratio; - } - } - *ncalc = imax2(1, mplus1 - k); - if (*ncalc == 1) - bk[0] = bk2; - if (*nb == 1) - return; - -L420: - for (i = *ncalc; i < *nb; ++i) { /* i == *ncalc */ -#ifndef IEEE_754 - if (bk[i-1] >= DBL_MAX / bk[i]) - return; -#endif - bk[i] *= bk[i-1]; - (*ncalc)++; - } - } -} diff --git a/deps/Rmath/src/bessel_y.c b/deps/Rmath/src/bessel_y.c deleted file mode 100644 index ee23eda1f263f..0000000000000 --- a/deps/Rmath/src/bessel_y.c +++ /dev/null @@ -1,501 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998-2003 Ross Ihaka and the R Development Core team. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - */ - -/* DESCRIPTION --> see below */ - - -/* From http://www.netlib.org/specfun/rybesl Fortran translated by f2c,... - * ------------------------------=#---- Martin Maechler, ETH Zurich - */ -#include "nmath.h" -#include "bessel.h" - -#ifndef MATHLIB_STANDALONE -#include -#endif - -static void Y_bessel(double *x, double *alpha, long *nb, - double *by, long *ncalc); - -double bessel_y(double x, double alpha) -{ - long nb, ncalc; - double na, *by; -#ifndef MATHLIB_STANDALONE - const void *vmax; -#endif - -#ifdef IEEE_754 - /* NaNs propagated correctly */ - if (ISNAN(x) || ISNAN(alpha)) return x + alpha; -#endif - if (x < 0) { - ML_ERROR(ME_RANGE, "bessel_y"); - return ML_NAN; - } - na = floor(alpha); - if (alpha < 0) { - /* Using Abramowitz & Stegun 9.1.2 - * this may not be quite optimal (CPU and accuracy wise) */ - return(bessel_y(x, -alpha) * cos(M_PI * alpha) - - ((alpha == na) ? 0 : - bessel_j(x, -alpha) * sin(M_PI * alpha))); - } - nb = 1+ (long)na;/* nb-1 <= alpha < nb */ - alpha -= (nb-1); -#ifdef MATHLIB_STANDALONE - by = (double *) calloc(nb, sizeof(double)); - if (!by) MATHLIB_ERROR("%s", _("bessel_y allocation error")); -#else - vmax = vmaxget(); - by = (double *) R_alloc((size_t) nb, sizeof(double)); -#endif - Y_bessel(&x, &alpha, &nb, by, &ncalc); - if(ncalc != nb) {/* error input */ - if(ncalc == -1) - return ML_POSINF; - else if(ncalc < -1) - MATHLIB_WARNING4(_("bessel_y(%g): ncalc (=%ld) != nb (=%ld); alpha=%g. Arg. out of range?\n"), - x, ncalc, nb, alpha); - else /* ncalc >= 0 */ - MATHLIB_WARNING2(_("bessel_y(%g,nu=%g): precision lost in result\n"), - x, alpha+nb-1); - } - x = by[nb-1]; -#ifdef MATHLIB_STANDALONE - free(by); -#else - vmaxset(vmax); -#endif - return x; -} - -/* modified version of bessel_y that accepts a work array instead of - allocating one. */ -double bessel_y_ex(double x, double alpha, double *by) -{ - long nb, ncalc; - double na; - -#ifdef IEEE_754 - /* NaNs propagated correctly */ - if (ISNAN(x) || ISNAN(alpha)) return x + alpha; -#endif - if (x < 0) { - ML_ERROR(ME_RANGE, "bessel_y"); - return ML_NAN; - } - na = floor(alpha); - if (alpha < 0) { - /* Using Abramowitz & Stegun 9.1.2 - * this may not be quite optimal (CPU and accuracy wise) */ - return(bessel_y_ex(x, -alpha, by) * cos(M_PI * alpha) - - ((alpha == na) ? 0 : - bessel_j_ex(x, -alpha, by) * sin(M_PI * alpha))); - } - nb = 1+ (long)na;/* nb-1 <= alpha < nb */ - alpha -= (nb-1); - Y_bessel(&x, &alpha, &nb, by, &ncalc); - if(ncalc != nb) {/* error input */ - if(ncalc == -1) - return ML_POSINF; - else if(ncalc < -1) - MATHLIB_WARNING4(_("bessel_y(%g): ncalc (=%ld) != nb (=%ld); alpha=%g. Arg. out of range?\n"), - x, ncalc, nb, alpha); - else /* ncalc >= 0 */ - MATHLIB_WARNING2(_("bessel_y(%g,nu=%g): precision lost in result\n"), - x, alpha+nb-1); - } - x = by[nb-1]; - return x; -} - -static void Y_bessel(double *x, double *alpha, long *nb, - double *by, long *ncalc) -{ -/* ---------------------------------------------------------------------- - - This routine calculates Bessel functions Y_(N+ALPHA) (X) - for non-negative argument X, and non-negative order N+ALPHA. - - - Explanation of variables in the calling sequence - - X - Non-negative argument for which - Y's are to be calculated. - ALPHA - Fractional part of order for which - Y's are to be calculated. 0 <= ALPHA < 1.0. - NB - Number of functions to be calculated, NB > 0. - The first function calculated is of order ALPHA, and the - last is of order (NB - 1 + ALPHA). - BY - Output vector of length NB. If the - routine terminates normally (NCALC=NB), the vector BY - contains the functions Y(ALPHA,X), ... , Y(NB-1+ALPHA,X), - If (0 < NCALC < NB), BY(I) contains correct function - values for I <= NCALC, and contains the ratios - Y(ALPHA+I-1,X)/Y(ALPHA+I-2,X) for the rest of the array. - NCALC - Output variable indicating possible errors. - Before using the vector BY, the user should check that - NCALC=NB, i.e., all orders have been calculated to - the desired accuracy. See error returns below. - - - ******************************************************************* - - Error returns - - In case of an error, NCALC != NB, and not all Y's are - calculated to the desired accuracy. - - NCALC < -1: An argument is out of range. For example, - NB <= 0, IZE is not 1 or 2, or IZE=1 and ABS(X) >= - XMAX. In this case, BY[0] = 0.0, the remainder of the - BY-vector is not calculated, and NCALC is set to - MIN0(NB,0)-2 so that NCALC != NB. - NCALC = -1: Y(ALPHA,X) >= XINF. The requested function - values are set to 0.0. - 1 < NCALC < NB: Not all requested function values could - be calculated accurately. BY(I) contains correct function - values for I <= NCALC, and and the remaining NB-NCALC - array elements contain 0.0. - - - Intrinsic functions required are: - - DBLE, EXP, INT, MAX, MIN, REAL, SQRT - - - Acknowledgement - - This program draws heavily on Temme's Algol program for Y(a,x) - and Y(a+1,x) and on Campbell's programs for Y_nu(x). Temme's - scheme is used for x < THRESH, and Campbell's scheme is used - in the asymptotic region. Segments of code from both sources - have been translated into Fortran 77, merged, and heavily modified. - Modifications include parameterization of machine dependencies, - use of a new approximation for ln(gamma(x)), and built-in - protection against over/underflow. - - References: "Bessel functions J_nu(x) and Y_nu(x) of float - order and float argument," Campbell, J. B., - Comp. Phy. Comm. 18, 1979, pp. 133-142. - - "On the numerical evaluation of the ordinary - Bessel function of the second kind," Temme, - N. M., J. Comput. Phys. 21, 1976, pp. 343-350. - - Latest modification: March 19, 1990 - - Modified by: W. J. Cody - Applied Mathematics Division - Argonne National Laboratory - Argonne, IL 60439 - ----------------------------------------------------------------------*/ - - -/* ---------------------------------------------------------------------- - Mathematical constants - FIVPI = 5*PI - PIM5 = 5*PI - 15 - ----------------------------------------------------------------------*/ - const static double fivpi = 15.707963267948966192; - const static double pim5 = .70796326794896619231; - - /*---------------------------------------------------------------------- - Coefficients for Chebyshev polynomial expansion of - 1/gamma(1-x), abs(x) <= .5 - ----------------------------------------------------------------------*/ - const static double ch[21] = { -6.7735241822398840964e-24, - -6.1455180116049879894e-23,2.9017595056104745456e-21, - 1.3639417919073099464e-19,2.3826220476859635824e-18, - -9.0642907957550702534e-18,-1.4943667065169001769e-15, - -3.3919078305362211264e-14,-1.7023776642512729175e-13, - 9.1609750938768647911e-12,2.4230957900482704055e-10, - 1.7451364971382984243e-9,-3.3126119768180852711e-8, - -8.6592079961391259661e-7,-4.9717367041957398581e-6, - 7.6309597585908126618e-5,.0012719271366545622927, - .0017063050710955562222,-.07685284084478667369, - -.28387654227602353814,.92187029365045265648 }; - - /* Local variables */ - long i, k, na; - - double alfa, div, ddiv, even, gamma, term, cosmu, sinmu, - b, c, d, e, f, g, h, p, q, r, s, d1, d2, q0, pa,pa1, qa,qa1, - en, en1, nu, ex, ya,ya1, twobyx, den, odd, aye, dmu, x2, xna; - - en1 = ya = ya1 = 0; /* -Wall */ - - ex = *x; - nu = *alpha; - if (*nb > 0 && 0. <= nu && nu < 1.) { - if(ex < DBL_MIN || ex > xlrg_BESS_Y) { - /* Warning is not really appropriate, give - * proper limit: - * ML_ERROR(ME_RANGE, "Y_bessel"); */ - *ncalc = *nb; - if(ex > xlrg_BESS_Y) by[0]= 0.; /*was ML_POSINF */ - else if(ex < DBL_MIN) by[0]=ML_NEGINF; - for(i=0; i < *nb; i++) - by[i] = by[0]; - return; - } - xna = ftrunc(nu + .5); - na = (long) xna; - if (na == 1) {/* <==> .5 <= *alpha < 1 <==> -5. <= nu < 0 */ - nu -= xna; - } - if (nu == -.5) { - p = M_SQRT_2dPI / sqrt(ex); - ya = p * sin(ex); - ya1 = -p * cos(ex); - } else if (ex < 3.) { - /* ------------------------------------------------------------- - Use Temme's scheme for small X - ------------------------------------------------------------- */ - b = ex * .5; - d = -log(b); - f = nu * d; - e = pow(b, -nu); - if (fabs(nu) < M_eps_sinc) - c = M_1_PI; - else - c = nu / sin(nu * M_PI); - - /* ------------------------------------------------------------ - Computation of sinh(f)/f - ------------------------------------------------------------ */ - if (fabs(f) < 1.) { - x2 = f * f; - en = 19.; - s = 1.; - for (i = 1; i <= 9; ++i) { - s = s * x2 / en / (en - 1.) + 1.; - en -= 2.; - } - } else { - s = (e - 1. / e) * .5 / f; - } - /* -------------------------------------------------------- - Computation of 1/gamma(1-a) using Chebyshev polynomials */ - x2 = nu * nu * 8.; - aye = ch[0]; - even = 0.; - alfa = ch[1]; - odd = 0.; - for (i = 3; i <= 19; i += 2) { - even = -(aye + aye + even); - aye = -even * x2 - aye + ch[i - 1]; - odd = -(alfa + alfa + odd); - alfa = -odd * x2 - alfa + ch[i]; - } - even = (even * .5 + aye) * x2 - aye + ch[20]; - odd = (odd + alfa) * 2.; - gamma = odd * nu + even; - /* End of computation of 1/gamma(1-a) - ----------------------------------------------------------- */ - g = e * gamma; - e = (e + 1. / e) * .5; - f = 2. * c * (odd * e + even * s * d); - e = nu * nu; - p = g * c; - q = M_1_PI / g; - c = nu * M_PI_2; - if (fabs(c) < M_eps_sinc) - r = 1.; - else - r = sin(c) / c; - - r = M_PI * c * r * r; - c = 1.; - d = -b * b; - h = 0.; - ya = f + r * q; - ya1 = p; - en = 1.; - - while (fabs(g / (1. + fabs(ya))) + - fabs(h / (1. + fabs(ya1))) > DBL_EPSILON) { - f = (f * en + p + q) / (en * en - e); - c *= (d / en); - p /= en - nu; - q /= en + nu; - g = c * (f + r * q); - h = c * p - en * g; - ya += g; - ya1+= h; - en += 1.; - } - ya = -ya; - ya1 = -ya1 / b; - } else if (ex < thresh_BESS_Y) { - /* -------------------------------------------------------------- - Use Temme's scheme for moderate X : 3 <= x < 16 - -------------------------------------------------------------- */ - c = (.5 - nu) * (.5 + nu); - b = ex + ex; - e = ex * M_1_PI * cos(nu * M_PI) / DBL_EPSILON; - e *= e; - p = 1.; - q = -ex; - r = 1. + ex * ex; - s = r; - en = 2.; - while (r * en * en < e) { - en1 = en + 1.; - d = (en - 1. + c / en) / s; - p = (en + en - p * d) / en1; - q = (-b + q * d) / en1; - s = p * p + q * q; - r *= s; - en = en1; - } - f = p / s; - p = f; - g = -q / s; - q = g; -L220: - en -= 1.; - if (en > 0.) { - r = en1 * (2. - p) - 2.; - s = b + en1 * q; - d = (en - 1. + c / en) / (r * r + s * s); - p = d * r; - q = d * s; - e = f + 1.; - f = p * e - g * q; - g = q * e + p * g; - en1 = en; - goto L220; - } - f = 1. + f; - d = f * f + g * g; - pa = f / d; - qa = -g / d; - d = nu + .5 - p; - q += ex; - pa1 = (pa * q - qa * d) / ex; - qa1 = (qa * q + pa * d) / ex; - b = ex - M_PI_2 * (nu + .5); - c = cos(b); - s = sin(b); - d = M_SQRT_2dPI / sqrt(ex); - ya = d * (pa * s + qa * c); - ya1 = d * (qa1 * s - pa1 * c); - } else { /* x > thresh_BESS_Y */ - /* ---------------------------------------------------------- - Use Campbell's asymptotic scheme. - ---------------------------------------------------------- */ - na = 0; - d1 = ftrunc(ex / fivpi); - i = (long) d1; - dmu = ex - 15. * d1 - d1 * pim5 - (*alpha + .5) * M_PI_2; - if (i - (i / 2 << 1) == 0) { - cosmu = cos(dmu); - sinmu = sin(dmu); - } else { - cosmu = -cos(dmu); - sinmu = -sin(dmu); - } - ddiv = 8. * ex; - dmu = *alpha; - den = sqrt(ex); - for (k = 1; k <= 2; ++k) { - p = cosmu; - cosmu = sinmu; - sinmu = -p; - d1 = (2. * dmu - 1.) * (2. * dmu + 1.); - d2 = 0.; - div = ddiv; - p = 0.; - q = 0.; - q0 = d1 / div; - term = q0; - for (i = 2; i <= 20; ++i) { - d2 += 8.; - d1 -= d2; - div += ddiv; - term = -term * d1 / div; - p += term; - d2 += 8.; - d1 -= d2; - div += ddiv; - term *= (d1 / div); - q += term; - if (fabs(term) <= DBL_EPSILON) { - break; - } - } - p += 1.; - q += q0; - if (k == 1) - ya = M_SQRT_2dPI * (p * cosmu - q * sinmu) / den; - else - ya1 = M_SQRT_2dPI * (p * cosmu - q * sinmu) / den; - dmu += 1.; - } - } - if (na == 1) { - h = 2. * (nu + 1.) / ex; - if (h > 1.) { - if (fabs(ya1) > DBL_MAX / h) { - h = 0.; - ya = 0.; - } - } - h = h * ya1 - ya; - ya = ya1; - ya1 = h; - } - - /* --------------------------------------------------------------- - Now have first one or two Y's - --------------------------------------------------------------- */ - by[0] = ya; - *ncalc = 1; - if(*nb > 1) { - by[1] = ya1; - if (ya1 != 0.) { - aye = 1. + *alpha; - twobyx = 2. / ex; - *ncalc = 2; - for (i = 2; i < *nb; ++i) { - if (twobyx < 1.) { - if (fabs(by[i - 1]) * twobyx >= DBL_MAX / aye) - goto L450; - } else { - if (fabs(by[i - 1]) >= DBL_MAX / aye / twobyx) - goto L450; - } - by[i] = twobyx * aye * by[i - 1] - by[i - 2]; - aye += 1.; - ++(*ncalc); - } - } - } -L450: - for (i = *ncalc; i < *nb; ++i) - by[i] = ML_NEGINF;/* was 0 */ - - } else { - by[0] = 0.; - *ncalc = imin2(*nb,0) - 1; - } -} - diff --git a/deps/Rmath/src/beta.c b/deps/Rmath/src/beta.c deleted file mode 100644 index 169b80d7ce359..0000000000000 --- a/deps/Rmath/src/beta.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000-2001 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * double beta(double a, double b); - * - * DESCRIPTION - * - * This function returns the value of the beta function - * evaluated with arguments a and b. - * - * NOTES - * - * This routine is a translation into C of a Fortran subroutine - * by W. Fullerton of Los Alamos Scientific Laboratory. - * Some modifications have been made so that the routines - * conform to the IEEE 754 standard. - */ - -#include "nmath.h" - -double beta(double a, double b) -{ -#ifdef NOMORE_FOR_THREADS - static double xmin, xmax = 0;/*-> typically = 171.61447887 for IEEE */ - static double lnsml = 0;/*-> typically = -708.3964185 */ - - if (xmax == 0) { - gammalims(&xmin, &xmax); - lnsml = log(d1mach(1)); - } -#else -/* For IEEE double precision DBL_EPSILON = 2^-52 = 2.220446049250313e-16 : - * xmin, xmax : see ./gammalims.c - * lnsml = log(DBL_MIN) = log(2 ^ -1022) = -1022 * log(2) -*/ -# define xmin -170.5674972726612 -# define xmax 171.61447887182298 -# define lnsml -708.39641853226412 -#endif - - -#ifdef IEEE_754 - /* NaNs propagated correctly */ - if(ISNAN(a) || ISNAN(b)) return a + b; -#endif - - if (a < 0 || b < 0) - ML_ERR_return_NAN - else if (a == 0 || b == 0) { - return ML_POSINF; - } - else if (!R_FINITE(a) || !R_FINITE(b)) { - return 0; - } - - if (a + b < xmax) /* ~= 171.61 for IEEE */ - return gammafn(a) * gammafn(b) / gammafn(a+b); - else { - double val = lbeta(a, b); - if (val < lnsml) { - /* a and/or b so big that beta underflows */ - ML_ERROR(ME_UNDERFLOW, "beta"); - /* return ML_UNDERFLOW; pointless giving incorrect value */ - } - return exp(val); - } -} diff --git a/deps/Rmath/src/chebyshev.c b/deps/Rmath/src/chebyshev.c deleted file mode 100644 index 8e85f1c6fa5ae..0000000000000 --- a/deps/Rmath/src/chebyshev.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * int chebyshev_init(double *dos, int nos, double eta) - * double chebyshev_eval(double x, double *a, int n) - * - * DESCRIPTION - * - * "chebyshev_init" determines the number of terms for the - * double precision orthogonal series "dos" needed to insure - * the error is no larger than "eta". Ordinarily eta will be - * chosen to be one-tenth machine precision. - * - * "chebyshev_eval" evaluates the n-term Chebyshev series - * "a" at "x". - * - * NOTES - * - * These routines are translations into C of Fortran routines - * by W. Fullerton of Los Alamos Scientific Laboratory. - * - * Based on the Fortran routine dcsevl by W. Fullerton. - * Adapted from R. Broucke, Algorithm 446, CACM., 16, 254 (1973). - */ - -#include "nmath.h" - -/* NaNs propagated correctly */ - - -int attribute_hidden chebyshev_init(double *dos, int nos, double eta) -{ - int i, ii; - double err; - - if (nos < 1) - return 0; - - err = 0.0; - i = 0; /* just to avoid compiler warnings */ - for (ii=1; ii<=nos; ii++) { - i = nos - ii; - err += fabs(dos[i]); - if (err > eta) { - return i; - } - } - return i; -} - - -double attribute_hidden chebyshev_eval(double x, const double *a, const int n) -{ - double b0, b1, b2, twox; - int i; - - if (n < 1 || n > 1000) ML_ERR_return_NAN; - - if (x < -1.1 || x > 1.1) ML_ERR_return_NAN; - - twox = x * 2; - b2 = b1 = 0; - b0 = 0; - for (i = 1; i <= n; i++) { - b2 = b1; - b1 = b0; - b0 = twox * b1 - b2 + a[n - i]; - } - return (b0 - b2) * 0.5; -} diff --git a/deps/Rmath/src/choose.c b/deps/Rmath/src/choose.c deleted file mode 100644 index 97bc3c5ffd216..0000000000000 --- a/deps/Rmath/src/choose.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2004-2009 The R Foundation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * double choose(double n, double k); - * double lchoose(double n, double k); - * (and private) - * double lfastchoose(double n, double k); - * - * DESCRIPTION - * - * Binomial coefficients. - * choose(n, k) and lchoose(n,k) := log(abs(choose(n,k)) - * - * These work for the *generalized* binomial theorem, - * i.e., are also defined for non-integer n (integer k). - * - * We use the simple explicit product formula for k <= k_small_max - * and also have added statements to make sure that the symmetry - * (n \\ k ) == (n \\ n-k) is preserved for non-negative integer n. - */ - -#include "nmath.h" - -double attribute_hidden lfastchoose(double n, double k) -{ - return -log(n + 1.) - lbeta(n - k + 1., k + 1.); -} -/* mathematically the same: - less stable typically, but useful if n-k+1 < 0 : */ -static -double lfastchoose2(double n, double k, int *s_choose) -{ - double r; - r = lgammafn_sign(n - k + 1., s_choose); - return lgammafn(n + 1.) - lgammafn(k + 1.) - r; -} - -#define ODD(_K_) ((_K_) != 2 * floor((_K_) / 2.)) -/* matching R_D_nonint() in ./dpq.h : */ -#define R_IS_INT(x) (fabs((x) - floor((x)+0.5)) <= 1e-7) - -double lchoose(double n, double k) -{ - double k0 = k; - k = floor(k + 0.5); -#ifdef IEEE_754 - /* NaNs propagated correctly */ - if(ISNAN(n) || ISNAN(k)) return n + k; -#endif - if (fabs(k - k0) > 1e-7) - MATHLIB_WARNING2(_("'k' (%.2f) must be integer, rounded to %.0f"), k0, k); - if (k < 2) { - if (k < 0) return ML_NEGINF; - if (k == 0) return 0.; - /* else: k == 1 */ - return log(fabs(n)); - } - /* else: k >= 2 */ - if (n < 0) { - return lchoose(-n+ k-1, k); - } - else if (R_IS_INT(n)) { - if(n < k) return ML_NEGINF; - /* k <= n :*/ - if(n - k < 2) return lchoose(n, n-k); /* <- Symmetry */ - /* else: n >= k+2 */ - return lfastchoose(n, k); - } - /* else non-integer n >= 0 : */ - if (n < k-1) { - int s; - return lfastchoose2(n, k, &s); - } - return lfastchoose(n, k); -} - -#define k_small_max 30 -/* 30 is somewhat arbitrary: it is on the *safe* side: - * both speed and precision are clearly improved for k < 30. -*/ -double choose(double n, double k) -{ - double r, k0 = k; - k = floor(k + 0.5); -#ifdef IEEE_754 - /* NaNs propagated correctly */ - if(ISNAN(n) || ISNAN(k)) return n + k; -#endif - if (fabs(k - k0) > 1e-7) - MATHLIB_WARNING2(_("'k' (%.2f) must be integer, rounded to %.0f"), k0, k); - if (k < k_small_max) { - int j; - if(n-k < k && n >= 0 && R_IS_INT(n)) k = n-k; /* <- Symmetry */ - if (k < 0) return 0.; - if (k == 0) return 1.; - /* else: k >= 1 */ - r = n; - for(j = 2; j <= k; j++) - r *= (n-j+1)/j; - return R_IS_INT(n) ? floor(r + 0.5) : r; - /* might have got rounding errors */ - } - /* else: k >= k_small_max */ - if (n < 0) { - r = choose(-n+ k-1, k); - if (ODD(k)) r = -r; - return r; - } - else if (R_IS_INT(n)) { - if(n < k) return 0.; - if(n - k < k_small_max) return choose(n, n-k); /* <- Symmetry */ - return floor(exp(lfastchoose(n, k)) + 0.5); - } - /* else non-integer n >= 0 : */ - if (n < k-1) { - int s_choose; - r = lfastchoose2(n, k, /* -> */ &s_choose); - return s_choose * exp(r); - } - return exp(lfastchoose(n, k)); -} - -#undef ODD -#undef R_IS_INT -#undef k_small_max diff --git a/deps/Rmath/src/d1mach.c b/deps/Rmath/src/d1mach.c deleted file mode 100644 index 4369d2ddb7e68..0000000000000 --- a/deps/Rmath/src/d1mach.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Mathlib - A Mathematical Function Library - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000-7 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - */ - -/* NaNs propagated correctly */ - - -/*-- FIXME: Eliminate calls to these - * ===== o from C code when - * o it is only used to initialize "static" variables (threading) - * and use the DBL_... constants instead - */ - -#include "nmath.h" - -attribute_hidden double Rf_d1mach(int i) -{ - switch(i) { - case 1: return DBL_MIN; - case 2: return DBL_MAX; - - case 3: /* = FLT_RADIX ^ - DBL_MANT_DIG - for IEEE: = 2^-53 = 1.110223e-16 = .5*DBL_EPSILON */ - return 0.5*DBL_EPSILON; - - case 4: /* = FLT_RADIX ^ (1- DBL_MANT_DIG) = - for IEEE: = 2^-52 = DBL_EPSILON */ - return DBL_EPSILON; - - case 5: return M_LOG10_2; - - default: return 0.0; - } -} - -#ifdef __cplusplus -extern "C" -#endif - -double F77_NAME(d1mach)(int *i) -{ - return Rf_d1mach(*i); -} diff --git a/deps/Rmath/src/dbeta.c b/deps/Rmath/src/dbeta.c deleted file mode 100644 index ddbe2196d3f72..0000000000000 --- a/deps/Rmath/src/dbeta.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * AUTHOR - * Catherine Loader, catherine@research.bell-labs.com. - * October 23, 2000. - * - * Merge in to R: - * Copyright (C) 2000, The R Core Development Team - * Changes to case a, b < 2, use logs to avoid underflow - * Copyright (C) 2006, The R Core Development Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * - * DESCRIPTION - * Beta density, - * (a+b-1)! a-1 b-1 - * p(x;a,b) = ------------ x (1-x) - * (a-1)!(b-1)! - * - * = (a+b-1) dbinom(a-1; a+b-2,x) - * - * The basic formula for the log density is thus - * (a-1) log x + (b-1) log (1-x) - lbeta(a, b) - * If either a or b <= 2 then 0 < lbeta(a, b) < 710 and so no - * term is large. We use Loader's code only if both a and b > 2. - */ - -#include "nmath.h" -#include "dpq.h" - -double dbeta(double x, double a, double b, int give_log) -{ - double lval; - -#ifdef IEEE_754 - /* NaNs propagated correctly */ - if (ISNAN(x) || ISNAN(a) || ISNAN(b)) return x + a + b; -#endif - - if (a <= 0 || b <= 0) ML_ERR_return_NAN; - if (x < 0 || x > 1) return(R_D__0); - if (x == 0) { - if(a > 1) return(R_D__0); - if(a < 1) return(ML_POSINF); - /* a == 1 : */ return(R_D_val(b)); - } - if (x == 1) { - if(b > 1) return(R_D__0); - if(b < 1) return(ML_POSINF); - /* b == 1 : */ return(R_D_val(a)); - } - if (a <= 2 || b <= 2) - lval = (a-1)*log(x) + (b-1)*log1p(-x) - lbeta(a, b); - else - lval = log(a+b-1) + dbinom_raw(a-1, a+b-2, x, 1-x, TRUE); - - return R_D_exp(lval); -} diff --git a/deps/Rmath/src/dbinom.c b/deps/Rmath/src/dbinom.c deleted file mode 100644 index 6e2f4ec8b0d1c..0000000000000 --- a/deps/Rmath/src/dbinom.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - * AUTHOR - * Catherine Loader, catherine@research.bell-labs.com. - * October 23, 2000. - * - * Merge in to R and further tweaks : - * Copyright (C) 2000, The R Core Development Team - * Copyright (C) 2008, The R Foundation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * - * DESCRIPTION - * - * To compute the binomial probability, call dbinom(x,n,p). - * This checks for argument validity, and calls dbinom_raw(). - * - * dbinom_raw() does the actual computation; note this is called by - * other functions in addition to dbinom(). - * (1) dbinom_raw() has both p and q arguments, when one may be represented - * more accurately than the other (in particular, in df()). - * (2) dbinom_raw() does NOT check that inputs x and n are integers. This - * should be done in the calling function, where necessary. - * -- but is not the case at all when called e.g., from df() or dbeta() ! - * (3) Also does not check for 0 <= p <= 1 and 0 <= q <= 1 or NaN's. - * Do this in the calling function. - */ - -#include "nmath.h" -#include "dpq.h" - -double attribute_hidden -dbinom_raw(double x, double n, double p, double q, int give_log) -{ - double lf, lc; - - if (p == 0) return((x == 0) ? R_D__1 : R_D__0); - if (q == 0) return((x == n) ? R_D__1 : R_D__0); - - if (x == 0) { - if(n == 0) return R_D__1; - lc = (p < 0.1) ? -bd0(n,n*q) - n*p : n*log(q); - return( R_D_exp(lc) ); - } - if (x == n) { - lc = (q < 0.1) ? -bd0(n,n*p) - n*q : n*log(p); - return( R_D_exp(lc) ); - } - if (x < 0 || x > n) return( R_D__0 ); - - /* n*p or n*q can underflow to zero if n and p or q are small. This - used to occur in dbeta, and gives NaN as from R 2.3.0. */ - lc = stirlerr(n) - stirlerr(x) - stirlerr(n-x) - bd0(x,n*p) - bd0(n-x,n*q); - - /* f = (M_2PI*x*(n-x))/n; could overflow or underflow */ - /* Upto R 2.7.1: - * lf = log(M_2PI) + log(x) + log(n-x) - log(n); - * -- following is much better for x << n : */ - lf = log(M_2PI) + log(x) + log1p(- x/n); - - return R_D_exp(lc - 0.5*lf); -} - -double dbinom(double x, double n, double p, int give_log) -{ -#ifdef IEEE_754 - /* NaNs propagated correctly */ - if (ISNAN(x) || ISNAN(n) || ISNAN(p)) return x + n + p; -#endif - - if (p < 0 || p > 1 || R_D_negInonint(n)) - ML_ERR_return_NAN; - R_D_nonint_check(x); - if (x < 0 || !R_FINITE(x)) return R_D__0; - - n = R_D_forceint(n); - x = R_D_forceint(x); - - return dbinom_raw(x, n, p, 1-p, give_log); -} diff --git a/deps/Rmath/src/dcauchy.c b/deps/Rmath/src/dcauchy.c deleted file mode 100644 index 125778df8aa27..0000000000000 --- a/deps/Rmath/src/dcauchy.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * DESCRIPTION - * - * The density of the Cauchy distribution. - */ - -#include "nmath.h" -#include "dpq.h" - -double dcauchy(double x, double location, double scale, int give_log) -{ - double y; -#ifdef IEEE_754 - /* NaNs propagated correctly */ - if (ISNAN(x) || ISNAN(location) || ISNAN(scale)) - return x + location + scale; -#endif - if (scale <= 0) ML_ERR_return_NAN; - - y = (x - location) / scale; - return give_log ? - - log(M_PI * scale * (1. + y * y)) : - 1. / (M_PI * scale * (1. + y * y)); -} diff --git a/deps/Rmath/src/dchisq.c b/deps/Rmath/src/dchisq.c deleted file mode 100644 index cc3a0f87ab3b3..0000000000000 --- a/deps/Rmath/src/dchisq.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * DESCRIPTION - * - * The density of the chi-squared distribution. - */ - -#include "nmath.h" -#include "dpq.h" - -double dchisq(double x, double df, int give_log) -{ - return dgamma(x, df / 2., 2., give_log); -} diff --git a/deps/Rmath/src/dexp.c b/deps/Rmath/src/dexp.c deleted file mode 100644 index 7cd27f85fc6c8..0000000000000 --- a/deps/Rmath/src/dexp.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * DESCRIPTION - * - * The density of the exponential distribution. - */ - -#include "nmath.h" -#include "dpq.h" - -double dexp(double x, double scale, int give_log) -{ -#ifdef IEEE_754 - /* NaNs propagated correctly */ - if (ISNAN(x) || ISNAN(scale)) return x + scale; -#endif - if (scale <= 0.0) ML_ERR_return_NAN; - - if (x < 0.) - return R_D__0; - return (give_log ? - (-x / scale) - log(scale) : - exp(-x / scale) / scale); -} diff --git a/deps/Rmath/src/df.c b/deps/Rmath/src/df.c deleted file mode 100644 index e5056904f04bd..0000000000000 --- a/deps/Rmath/src/df.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * AUTHOR - * Catherine Loader, catherine@research.bell-labs.com. - * October 23, 2000. - * - * Merge in to R: - * Copyright (C) 2000, 2005 The R Core Development Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * - * DESCRIPTION - * - * The density function of the F distribution. - * To evaluate it, write it as a Binomial probability with p = x*m/(n+x*m). - * For m >= 2, we use the simplest conversion. - * For m < 2, (m-2)/2 < 0 so the conversion will not work, and we must use - * a second conversion. - * Note the division by p; this seems unavoidable - * for m < 2, since the F density has a singularity as x (or p) -> 0. - */ - -#include "nmath.h" -#include "dpq.h" - -double df(double x, double m, double n, int give_log) -{ - double p, q, f, dens; - -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(m) || ISNAN(n)) - return x + m + n; -#endif - if (m <= 0 || n <= 0) ML_ERR_return_NAN; - if (x < 0.) return(R_D__0); - if (x == 0.) return(m > 2 ? R_D__0 : (m == 2 ? R_D__1 : ML_POSINF)); - if (!R_FINITE(m) && !R_FINITE(n)) { /* both +Inf */ - if(x == 1.) return ML_POSINF; - /* else */ return R_D__0; - } - if (!R_FINITE(n)) /* must be +Inf by now */ - return(dgamma(x, m/2, 2./m, give_log)); - if (m > 1e14) {/* includes +Inf: code below is inaccurate there */ - dens = dgamma(1./x, n/2, 2./n, give_log); - return give_log ? dens - 2*log(x): dens/(x*x); - } - - f = 1./(n+x*m); - q = n*f; - p = x*m*f; - - if (m >= 2) { - f = m*q/2; - dens = dbinom_raw((m-2)/2, (m+n-2)/2, p, q, give_log); - } - else { - f = m*m*q / (2*p*(m+n)); - dens = dbinom_raw(m/2, (m+n)/2, p, q, give_log); - } - return(give_log ? log(f)+dens : f*dens); -} diff --git a/deps/Rmath/src/dgamma.c b/deps/Rmath/src/dgamma.c deleted file mode 100644 index 69d96d06b5ab9..0000000000000 --- a/deps/Rmath/src/dgamma.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * AUTHOR - * Catherine Loader, catherine@research.bell-labs.com. - * October 23, 2000. - * - * Merge in to R: - * Copyright (C) 2000 The R Core Development Team - * Copyright (C) 2004 The R Foundation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * - * DESCRIPTION - * - * Computes the density of the gamma distribution, - * - * 1/s (x/s)^{a-1} exp(-x/s) - * p(x;a,s) = ----------------------- - * (a-1)! - * - * where `s' is the scale (= 1/lambda in other parametrizations) - * and `a' is the shape parameter ( = alpha in other contexts). - * - * The old (R 1.1.1) version of the code is available via `#define D_non_pois' - */ - -#include "nmath.h" -#include "dpq.h" - -double dgamma(double x, double shape, double scale, int give_log) -{ - double pr; -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(shape) || ISNAN(scale)) - return x + shape + scale; -#endif - if (shape < 0 || scale <= 0) ML_ERR_return_NAN; - if (x < 0) - return R_D__0; - if (shape == 0) /* point mass at 0 */ - return (x == 0)? ML_POSINF : R_D__0; - if (x == 0) { - if (shape < 1) return ML_POSINF; - if (shape > 1) return R_D__0; - /* else */ - return give_log ? -log(scale) : 1 / scale; - } - - if (shape < 1) { - pr = dpois_raw(shape, x/scale, give_log); - return give_log ? pr + log(shape/x) : pr*shape/x; - } - /* else shape >= 1 */ - pr = dpois_raw(shape-1, x/scale, give_log); - return give_log ? pr - log(scale) : pr/scale; -} diff --git a/deps/Rmath/src/dgeom.c b/deps/Rmath/src/dgeom.c deleted file mode 100644 index 3f61e0b844282..0000000000000 --- a/deps/Rmath/src/dgeom.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * AUTHOR - * Catherine Loader, catherine@research.bell-labs.com. - * October 23, 2000. - * - * Merge in to R: - * Copyright (C) 2000, 2001, 2006 The R Core Development Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * - * DESCRIPTION - * - * Computes the geometric probabilities, Pr(X=x) = p(1-p)^x. - */ - -#include "nmath.h" -#include "dpq.h" - -double dgeom(double x, double p, int give_log) -{ - double prob; - -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(p)) return x + p; -#endif - - if (p <= 0 || p > 1) ML_ERR_return_NAN; - - R_D_nonint_check(x); - if (x < 0 || !R_FINITE(x) || p == 0) return R_D__0; - x = R_D_forceint(x); - - /* prob = (1-p)^x, stable for small p */ - prob = dbinom_raw(0.,x, p,1-p, give_log); - - return((give_log) ? log(p) + prob : p*prob); -} diff --git a/deps/Rmath/src/dhyper.c b/deps/Rmath/src/dhyper.c deleted file mode 100644 index 61628eec5e57f..0000000000000 --- a/deps/Rmath/src/dhyper.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * AUTHOR - * Catherine Loader, catherine@research.bell-labs.com. - * October 23, 2000. - * - * Merge in to R: - * Copyright (C) 2000, 2001 The R Core Development Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * - * DESCRIPTION - * - * Given a sequence of r successes and b failures, we sample n (\le b+r) - * items without replacement. The hypergeometric probability is the - * probability of x successes: - * - * choose(r, x) * choose(b, n-x) - * p(x; r,b,n) = ----------------------------- = - * choose(r+b, n) - * - * dbinom(x,r,p) * dbinom(n-x,b,p) - * = -------------------------------- - * dbinom(n,r+b,p) - * - * for any p. For numerical stability, we take p=n/(r+b); with this choice, - * the denominator is not exponentially small. - */ - -#include "nmath.h" -#include "dpq.h" - -double dhyper(double x, double r, double b, double n, int give_log) -{ - double p, q, p1, p2, p3; - -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(r) || ISNAN(b) || ISNAN(n)) - return x + r + b + n; -#endif - - if (R_D_negInonint(r) || R_D_negInonint(b) || R_D_negInonint(n) || n > r+b) - ML_ERR_return_NAN; - if (R_D_negInonint(x)) - return(R_D__0); - - x = R_D_forceint(x); - r = R_D_forceint(r); - b = R_D_forceint(b); - n = R_D_forceint(n); - - if (n < x || r < x || n - x > b) return(R_D__0); - if (n == 0) return((x == 0) ? R_D__1 : R_D__0); - - p = ((double)n)/((double)(r+b)); - q = ((double)(r+b-n))/((double)(r+b)); - - p1 = dbinom_raw(x, r, p,q,give_log); - p2 = dbinom_raw(n-x,b, p,q,give_log); - p3 = dbinom_raw(n,r+b, p,q,give_log); - - return( (give_log) ? p1 + p2 - p3 : p1*p2/p3 ); -} diff --git a/deps/Rmath/src/dlnorm.c b/deps/Rmath/src/dlnorm.c deleted file mode 100644 index ad0694255e05a..0000000000000 --- a/deps/Rmath/src/dlnorm.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000-8 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * DESCRIPTION - * - * The density of the lognormal distribution. - */ - -#include "nmath.h" -#include "dpq.h" - -double dlnorm(double x, double meanlog, double sdlog, int give_log) -{ - double y; - -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(meanlog) || ISNAN(sdlog)) - return x + meanlog + sdlog; -#endif - if(sdlog <= 0) ML_ERR_return_NAN; - - if(x <= 0) return R_D__0; - - y = (log(x) - meanlog) / sdlog; - return (give_log ? - -(M_LN_SQRT_2PI + 0.5 * y * y + log(x * sdlog)) : - M_1_SQRT_2PI * exp(-0.5 * y * y) / (x * sdlog)); - /* M_1_SQRT_2PI = 1 / sqrt(2 * pi) */ - -} diff --git a/deps/Rmath/src/dlogis.c b/deps/Rmath/src/dlogis.c deleted file mode 100644 index d174cf2f7fc18..0000000000000 --- a/deps/Rmath/src/dlogis.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * R : A Computer Language for Statistical Data Analysis - * Copyright (C) 1995, 1996 Robert Gentleman and Ross Ihaka - * Copyright (C) 2000 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - */ - -#include "nmath.h" -#include "dpq.h" - -double dlogis(double x, double location, double scale, int give_log) -{ - double e, f; -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(location) || ISNAN(scale)) - return x + location + scale; -#endif - if (scale <= 0.0) - ML_ERR_return_NAN; - - x = fabs((x - location) / scale); - e = exp(-x); - f = 1.0 + e; - return give_log ? -(x + log(scale * f * f)) : e / (scale * f * f); -} diff --git a/deps/Rmath/src/dnbeta.c b/deps/Rmath/src/dnbeta.c deleted file mode 100644 index 3ee2b21cb2f75..0000000000000 --- a/deps/Rmath/src/dnbeta.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000-8 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * double dnbeta(double x, double a, double b, double ncp, int give_log); - * - * DESCRIPTION - * - * Computes the density of the noncentral beta distribution with - * noncentrality parameter ncp. The noncentral beta distribution - * has density: - * - * Inf - * f(x|a,b,ncp) = SUM p(i) * x^(a+i-1) * (1-x)^(b-1) / B(a+i,b) - * i=0 - * - * where: - * - * p(k) = exp(-ncp/2) (ncp/2)^k / k! - * - * B(a,b) = Gamma(a) * Gamma(b) / Gamma(a+b) - * - * - * This can be computed efficiently by using the recursions: - * - * p(k+1) = ncp/2 / (k+1) * p(k) - * - * B(a+k+1,b) = (a+k)/(a+b+k) * B(a+k,b) - * - * The new algorithm first determines for which k the k-th term is maximal, - * and then sums outwards to both sides from the 'mid'. - */ - -#include "nmath.h" -#include "dpq.h" - -double dnbeta(double x, double a, double b, double ncp, int give_log) -{ - const static double eps = 1.e-15; - - int kMax; - double k, ncp2, dx2, d, D; - long double sum, term, p_k, q; - -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(a) || ISNAN(b) || ISNAN(ncp)) - return x + a + b + ncp; -#endif - if (ncp < 0 || a <= 0 || b <= 0) - ML_ERR_return_NAN; - - if (!R_FINITE(a) || !R_FINITE(b) || !R_FINITE(ncp)) - ML_ERR_return_NAN; - - if (x < 0 || x > 1) return(R_D__0); - if(ncp == 0) - return dbeta(x, a, b, give_log); - - /* New algorithm, starting with *largest* term : */ - ncp2 = 0.5 * ncp; - dx2 = ncp2*x; - d = (dx2 - a - 1)/2; - D = d*d + dx2 * (a + b) - a; - if(D <= 0) { - kMax = 0; - } else { - D = ceil(d + sqrt(D)); - kMax = (D > 0) ? (int)D : 0; - } - - /* The starting "middle term" --- first look at it's log scale: */ - term = dbeta(x, a + kMax, b, /* log = */ TRUE); - p_k = dpois_raw(kMax, ncp2, TRUE); - if(x == 0. || !R_FINITE(term) || !R_FINITE(p_k)) /* if term = +Inf */ - return R_D_exp(p_k + term); - - /* Now if s_k := p_k * t_k {here = exp(p_k + term)} would underflow, - * we should rather scale everything and re-scale at the end:*/ - - p_k += term; /* = log(p_k) + log(t_k) == log(s_k) -- used at end to rescale */ - /* mid = 1 = the rescaled value, instead of mid = exp(p_k); */ - - /* Now sum from the inside out */ - sum = term = 1. /* = mid term */; - /* middle to the left */ - k = kMax; - while(k > 0 && term > sum * eps) { - k--; - q = /* 1 / r_k = */ (k+1)*(k+a) / (k+a+b) / dx2; - term *= q; - sum += term; - } - /* middle to the right */ - term = 1.; - k = kMax; - do { - q = /* r_{old k} = */ dx2 * (k+a+b) / (k+a) / (k+1); - k++; - term *= q; - sum += term; - } while (term > sum * eps); - - return R_D_exp(p_k + log(sum)); -} diff --git a/deps/Rmath/src/dnbinom.c b/deps/Rmath/src/dnbinom.c deleted file mode 100644 index dd8148a2a001e..0000000000000 --- a/deps/Rmath/src/dnbinom.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * AUTHOR - * Catherine Loader, catherine@research.bell-labs.com. - * October 23, 2000 and Feb, 2001. - * - * dnbinom_mu(): Martin Maechler, June 2008 - * - * Merge in to R: - * Copyright (C) 2000--2008, The R Core Development Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * - * DESCRIPTION - * - * Computes the negative binomial distribution. For integer n, - * this is probability of x failures before the nth success in a - * sequence of Bernoulli trials. We do not enforce integer n, since - * the distribution is well defined for non-integers, - * and this can be useful for e.g. overdispersed discrete survival times. - */ - -#include "nmath.h" -#include "dpq.h" - -double dnbinom(double x, double size, double prob, int give_log) -{ - double ans, p; - -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(size) || ISNAN(prob)) - return x + size + prob; -#endif - - if (prob <= 0 || prob > 1 || size < 0) ML_ERR_return_NAN; - R_D_nonint_check(x); - if (x < 0 || !R_FINITE(x)) return R_D__0; - x = R_D_forceint(x); - - ans = dbinom_raw(size, x+size, prob, 1-prob, give_log); - p = ((double)size)/(size+x); - return((give_log) ? log(p) + ans : p * ans); -} - -double dnbinom_mu(double x, double size, double mu, int give_log) -{ - /* originally, just set prob := size / (size + mu) and called dbinom_raw(), - * but that suffers from cancellation when mu << size */ - double ans, p; - -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(size) || ISNAN(mu)) - return x + size + mu; -#endif - - if (mu < 0 || size < 0) ML_ERR_return_NAN; - R_D_nonint_check(x); - if (x < 0 || !R_FINITE(x)) return R_D__0; - x = R_D_forceint(x); - if(x == 0)/* be accurate, both for n << mu, and n >> mu :*/ - return R_D_exp(size * (size < mu ? log(size/(size+mu)) : log1p(- mu/(size+mu)))); - if(x < 1e-10 * size) { /* don't use dbinom_raw() but MM's formula: */ - /* FIXME --- 1e-8 shows problem; rather use algdiv() from ./toms708.c */ - return R_D_exp(x * log(size*mu / (size+mu)) - mu - lgamma(x+1) + - log1p(x*(x-1)/(2*size))); - } - /* else: no unnecessary cancellation inside dbinom_raw, when - * x_ = size and n_ = x+size are so close that n_ - x_ loses accuracy - */ - ans = dbinom_raw(size, x+size, size/(size+mu), mu/(size+mu), give_log); - p = ((double)size)/(size+x); - return((give_log) ? log(p) + ans : p * ans); -} diff --git a/deps/Rmath/src/dnchisq.c b/deps/Rmath/src/dnchisq.c deleted file mode 100644 index 881269d7cb09c..0000000000000 --- a/deps/Rmath/src/dnchisq.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000-8 The R Development Core Team - * Copyright (C) 2004-8 The R Foundation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * DESCRIPTION - * - * The density of the noncentral chi-squared distribution with "df" - * degrees of freedom and noncentrality parameter "ncp". - */ - -#include "nmath.h" -#include "dpq.h" - -double dnchisq(double x, double df, double ncp, int give_log) -{ - const static double eps = 5e-15; - - double i, ncp2, q, mid, dfmid, imax; - long double sum, term; - -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(df) || ISNAN(ncp)) - return x + df + ncp; -#endif - if (ncp < 0 || df <= 0) ML_ERR_return_NAN; - - if (!R_FINITE(df) || !R_FINITE(ncp)) - ML_ERR_return_NAN; - - if(x < 0) return R_D__0; - if(x == 0 && df < 2.) - return ML_POSINF; - if(ncp == 0) - return dchisq(x, df, give_log); - if(x == ML_POSINF) return R_D__0; - - ncp2 = 0.5 * ncp; - - /* find max element of sum */ - imax = ceil((-(2+df) +sqrt((2-df) * (2-df) + 4 * ncp * x))/4); - if (imax < 0) imax = 0; - if(R_FINITE(imax)) { - dfmid = df + 2 * imax; - mid = dpois_raw(imax, ncp2, FALSE) * dchisq(x, dfmid, FALSE); - } else /* imax = Inf */ - mid = 0; - - if(mid == 0) { - /* underflow to 0 -- maybe numerically correct; maybe can be more accurate, - * particularly when give_log = TRUE */ - /* Use central-chisq approximation formula when appropriate; - * ((FIXME: the optimal cutoff also depends on (x,df); use always here? )) */ - if(give_log || ncp > 1000.) { - double nl = df + ncp, ic = nl/(nl + ncp);/* = "1/(1+b)" Abramowitz & St.*/ - return dchisq(x*ic, nl*ic, give_log); - } else - return R_D__0; - } - - sum = mid; - - /* errorbound := term * q / (1-q) now subsumed in while() / if() below: */ - - /* upper tail */ - term = mid; df = dfmid; i = imax; - double x2 = x * ncp2; - do { - i++; - q = x2 / i / df; - df += 2; - term *= q; - sum += term; - } while (q >= 1 || term * q > (1-q)*eps || term > 1e-10*sum); - /* lower tail */ - term = mid; df = dfmid; i = imax; - while (i) { - df -= 2; - q = i * df / x2; - i--; - term *= q; - sum += term; - if (q < 1 && term * q <= (1-q)*eps) break; - } - return R_D_val(sum); -} diff --git a/deps/Rmath/src/dnf.c b/deps/Rmath/src/dnf.c deleted file mode 100644 index c06e97d056cd8..0000000000000 --- a/deps/Rmath/src/dnf.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * AUTHOR - * Peter Ruckdeschel, peter.ruckdeschel@uni-bayreuth.de. - * April 13, 2006. - * - * Merge in to R: - * Copyright (C) 2006 The R Core Development Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * - * DESCRIPTION - * - * The density function of the non-central F distribution --- - * obtained by differentiating the corresp. cumulative distribution function - * using dnbeta. - * For df1 < 2, since the F density has a singularity as x -> Inf. - */ - -#include "nmath.h" -#include "dpq.h" - -double dnf(double x, double df1, double df2, double ncp, int give_log) -{ - double y, z, f; - -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(df1) || ISNAN(df2) || ISNAN(ncp)) - return x + df2 + df1 + ncp; -#endif - - /* want to compare dnf(ncp=0) behavior with df() one, hence *NOT* : - * if (ncp == 0) - * return df(x, df1, df2, give_log); */ - - if (df1 <= 0. || df2 <= 0. || ncp < 0) ML_ERR_return_NAN; - if (x < 0.) return(R_D__0); - if (!R_FINITE(ncp)) /* ncp = +Inf -- FIXME?: in some cases, limit exists */ - ML_ERR_return_NAN; - - /* This is not correct for df1 == 2, ncp > 0 - and seems unneeded: - * if (x == 0.) return(df1 > 2 ? R_D__0 : (df1 == 2 ? R_D__1 : ML_POSINF)); - */ - if (!R_FINITE(df1) && !R_FINITE(df2)) { /* both +Inf */ - /* PR: not sure about this (taken from ncp==0) -- FIXME ? */ - if(x == 1.) return ML_POSINF; - /* else */ return R_D__0; - } - if (!R_FINITE(df2)) /* i.e. = +Inf */ - return df1* dnchisq(x*df1, df1, ncp, give_log); - /* == dngamma(x, df1/2, 2./df1, ncp, give_log) -- but that does not exist */ - if (df1 > 1e14 && ncp < 1e7) { - /* includes df1 == +Inf: code below is inaccurate there */ - f = 1 + ncp/df1; /* assumes ncp << df1 [ignores 2*ncp^(1/2)/df1*x term] */ - z = dgamma(1./x/f, df2/2, 2./df2, give_log); - return give_log ? z - 2*log(x) - log(f) : z / (x*x) / f; - } - - y = (df1 / df2) * x; - z = dnbeta(y/(1 + y), df1 / 2., df2 / 2., ncp, give_log); - return give_log ? - z + log(df1) - log(df2) - 2 * log1p(y) : - z * (df1 / df2) /(1 + y) / (1 + y); -} - - - diff --git a/deps/Rmath/src/dnorm.c b/deps/Rmath/src/dnorm.c deleted file mode 100644 index 0a8c43b5fca33..0000000000000 --- a/deps/Rmath/src/dnorm.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000 The R Development Core Team - * Copyright (C) 2003 The R Foundation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * double dnorm4(double x, double mu, double sigma, int give_log) - * {dnorm (..) is synonymous and preferred inside R} - * - * DESCRIPTION - * - * Compute the density of the normal distribution. - */ - -#include "nmath.h" -#include "dpq.h" - -double dnorm4(double x, double mu, double sigma, int give_log) -{ -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(mu) || ISNAN(sigma)) - return x + mu + sigma; -#endif - if(!R_FINITE(sigma)) return R_D__0; - if(!R_FINITE(x) && mu == x) return ML_NAN;/* x-mu is NaN */ - if (sigma <= 0) { - if (sigma < 0) ML_ERR_return_NAN; - /* sigma == 0 */ - return (x == mu) ? ML_POSINF : R_D__0; - } - x = (x - mu) / sigma; - - if(!R_FINITE(x)) return R_D__0; - return (give_log ? - -(M_LN_SQRT_2PI + 0.5 * x * x + log(sigma)) : - M_1_SQRT_2PI * exp(-0.5 * x * x) / sigma); - /* M_1_SQRT_2PI = 1 / sqrt(2 * pi) */ -} diff --git a/deps/Rmath/src/dnt.c b/deps/Rmath/src/dnt.c deleted file mode 100644 index 2630573874331..0000000000000 --- a/deps/Rmath/src/dnt.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * AUTHOR - * Claus Ekstrøm, ekstrom@dina.kvl.dk - * July 15, 2003. - * - * Merge in to R: - * Copyright (C) 2003 The R Foundation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * - * NOTE - * - * Requires the following auxiliary routines: - * - * lgammafn(x) - log gamma function - * pnt(x, df, ncp) - the distribution function for - * the non-central t distribution - * - * - * DESCRIPTION - * - * The non-central t density is - * - * f(x, df, ncp) = - * df^(df/2) * exp(-.5*ncp^2) / - * (sqrt(pi)*gamma(df/2)*(df+x^2)^((df+1)/2)) * - * sum_{k=0}^Inf gamma((df + k + df)/2)*ncp^k / - * prod(1:k)*(2*x^2/(df+x^2))^(k/2) - * - * The functional relationship - * - * f(x, df, ncp) = df/x * - * (F(sqrt((df+2)/df)*x, df+2, ncp) - F(x, df, ncp)) - * - * is used to evaluate the density at x != 0 and - * - * f(0, df, ncp) = exp(-.5*ncp^2) / - * (sqrt(pi)*sqrt(df)*gamma(df/2))*gamma((df+1)/2) - * - * is used for x=0. - * - * All calculations are done on log-scale to increase stability. - * - */ - -#include "nmath.h" -#include "dpq.h" - -double dnt(double x, double df, double ncp, int give_log) -{ - double u; -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(df)) - return x + df; -#endif - - /* If non-positive df then error */ - if (df <= 0.0) ML_ERR_return_NAN; - - if(ncp == 0.0) return dt(x, df, give_log); - - /* If x is infinite then return 0 */ - if(!R_FINITE(x)) - return R_D__0; - - /* If infinite df then the density is identical to a - normal distribution with mean = ncp. However, the formula - loses a lot of accuracy around df=1e9 - */ - if(!R_FINITE(df) || df > 1e8) - return dnorm(x, ncp, 1., give_log); - - /* Do calculations on log scale to stabilize */ - - /* Consider two cases: x ~= 0 or not */ - if (fabs(x) > sqrt(df * DBL_EPSILON)) { - u = log(df) - log(fabs(x)) + - log(fabs(pnt(x*sqrt((df+2)/df), df+2, ncp, 1, 0) - - pnt(x, df, ncp, 1, 0))); - /* FIXME: the above still suffers from cancellation (but not horribly) */ - } - else { /* x ~= 0 : -> same value as for x = 0 */ - u = lgammafn((df+1)/2) - lgammafn(df/2) - - .5*(log(M_PI) + log(df) + ncp*ncp); - } - - return (give_log ? u : exp(u)); -} diff --git a/deps/Rmath/src/dpois.c b/deps/Rmath/src/dpois.c deleted file mode 100644 index 6b60849f65940..0000000000000 --- a/deps/Rmath/src/dpois.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * AUTHOR - * Catherine Loader, catherine@research.bell-labs.com. - * October 23, 2000. - * - * Merge in to R: - * Copyright (C) 2000, The R Core Development Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * - * DESCRIPTION - * - * dpois() checks argument validity and calls dpois_raw(). - * - * dpois_raw() computes the Poisson probability lb^x exp(-lb) / x!. - * This does not check that x is an integer, since dgamma() may - * call this with a fractional x argument. Any necessary argument - * checks should be done in the calling function. - * - */ - -#include "nmath.h" -#include "dpq.h" - -double attribute_hidden dpois_raw(double x, double lambda, int give_log) -{ - /* x >= 0 ; integer for dpois(), but not e.g. for pgamma()! - lambda >= 0 - */ - if (lambda == 0) return( (x == 0) ? R_D__1 : R_D__0 ); - if (!R_FINITE(lambda)) return R_D__0; - if (x < 0) return( R_D__0 ); - if (x <= lambda * DBL_MIN) return(R_D_exp(-lambda) ); - if (lambda < x * DBL_MIN) return(R_D_exp(-lambda + x*log(lambda) -lgammafn(x+1))); - return(R_D_fexp( M_2PI*x, -stirlerr(x)-bd0(x,lambda) )); -} - -double dpois(double x, double lambda, int give_log) -{ -#ifdef IEEE_754 - if(ISNAN(x) || ISNAN(lambda)) - return x + lambda; -#endif - - if (lambda < 0) ML_ERR_return_NAN; - R_D_nonint_check(x); - if (x < 0 || !R_FINITE(x)) - return R_D__0; - - x = R_D_forceint(x); - - return( dpois_raw(x,lambda,give_log) ); -} diff --git a/deps/Rmath/src/dpq.h b/deps/Rmath/src/dpq.h deleted file mode 100644 index 1b9cbda45aab8..0000000000000 --- a/deps/Rmath/src/dpq.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * R : A Computer Language for Statistical Data Analysis - * Copyright (C) 2000--2007 R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - */ - /* Utilities for `dpq' handling (density/probability/quantile) */ - -/* give_log in "d"; log_p in "p" & "q" : */ -#define give_log log_p - /* "DEFAULT" */ - /* --------- */ -#define R_D__0 (log_p ? ML_NEGINF : 0.) /* 0 */ -#define R_D__1 (log_p ? 0. : 1.) /* 1 */ -#define R_DT_0 (lower_tail ? R_D__0 : R_D__1) /* 0 */ -#define R_DT_1 (lower_tail ? R_D__1 : R_D__0) /* 1 */ - -/* Use 0.5 - p + 0.5 to perhaps gain 1 bit of accuracy */ -#define R_D_Lval(p) (lower_tail ? (p) : (0.5 - (p) + 0.5)) /* p */ -#define R_D_Cval(p) (lower_tail ? (0.5 - (p) + 0.5) : (p)) /* 1 - p */ - -#define R_D_val(x) (log_p ? log(x) : (x)) /* x in pF(x,..) */ -#define R_D_qIv(p) (log_p ? exp(p) : (p)) /* p in qF(p,..) */ -#define R_D_exp(x) (log_p ? (x) : exp(x)) /* exp(x) */ -#define R_D_log(p) (log_p ? (p) : log(p)) /* log(p) */ -#define R_D_Clog(p) (log_p ? log1p(-(p)) : (0.5 - (p) + 0.5)) /* [log](1-p) */ - -/* log(1 - exp(x)) in more stable form than log1p(- R_D_qIv(x))) : */ -#define R_Log1_Exp(x) ((x) > -M_LN2 ? log(-expm1(x)) : log1p(-exp(x))) - -/* log(1-exp(x)): R_D_LExp(x) == (log1p(- R_D_qIv(x))) but even more stable:*/ -#define R_D_LExp(x) (log_p ? R_Log1_Exp(x) : log1p(-x)) - -#define R_DT_val(x) (lower_tail ? R_D_val(x) : R_D_Clog(x)) -#define R_DT_Cval(x) (lower_tail ? R_D_Clog(x) : R_D_val(x)) - -/*#define R_DT_qIv(p) R_D_Lval(R_D_qIv(p)) * p in qF ! */ -#define R_DT_qIv(p) (log_p ? (lower_tail ? exp(p) : - expm1(p)) \ - : R_D_Lval(p)) - -/*#define R_DT_CIv(p) R_D_Cval(R_D_qIv(p)) * 1 - p in qF */ -#define R_DT_CIv(p) (log_p ? (lower_tail ? -expm1(p) : exp(p)) \ - : R_D_Cval(p)) - -#define R_DT_exp(x) R_D_exp(R_D_Lval(x)) /* exp(x) */ -#define R_DT_Cexp(x) R_D_exp(R_D_Cval(x)) /* exp(1 - x) */ - -#define R_DT_log(p) (lower_tail? R_D_log(p) : R_D_LExp(p))/* log(p) in qF */ -#define R_DT_Clog(p) (lower_tail? R_D_LExp(p): R_D_log(p))/* log(1-p) in qF*/ -#define R_DT_Log(p) (lower_tail? (p) : R_Log1_Exp(p)) -/* == R_DT_log when we already "know" log_p == TRUE :*/ - - -#define R_Q_P01_check(p) \ - if ((log_p && p > 0) || \ - (!log_p && (p < 0 || p > 1)) ) \ - ML_ERR_return_NAN - -/* Do the boundaries exactly for q*() functions : - * Often _LEFT_ = ML_NEGINF , and very often _RIGHT_ = ML_POSINF; - * - * R_Q_P01_boundaries(p, _LEFT_, _RIGHT_) :<==> - * - * R_Q_P01_check(p); - * if (p == R_DT_0) return _LEFT_ ; - * if (p == R_DT_1) return _RIGHT_; - * - * the following implementation should be more efficient (less tests): - */ -#define R_Q_P01_boundaries(p, _LEFT_, _RIGHT_) \ - if (log_p) { \ - if(p > 0) \ - ML_ERR_return_NAN; \ - if(p == 0) /* upper bound*/ \ - return lower_tail ? _RIGHT_ : _LEFT_; \ - if(p == ML_NEGINF) \ - return lower_tail ? _LEFT_ : _RIGHT_; \ - } \ - else { /* !log_p */ \ - if(p < 0 || p > 1) \ - ML_ERR_return_NAN; \ - if(p == 0) \ - return lower_tail ? _LEFT_ : _RIGHT_; \ - if(p == 1) \ - return lower_tail ? _RIGHT_ : _LEFT_; \ - } - -#define R_P_bounds_01(x, x_min, x_max) \ - if(x <= x_min) return R_DT_0; \ - if(x >= x_max) return R_DT_1 -/* is typically not quite optimal for (-Inf,Inf) where - * you'd rather have */ -#define R_P_bounds_Inf_01(x) \ - if(!R_FINITE(x)) { \ - if (x > 0) return R_DT_1; \ - /* x < 0 */return R_DT_0; \ - } - - - -/* additions for density functions (C.Loader) */ -#define R_D_fexp(f,x) (give_log ? -0.5*log(f)+(x) : exp(x)/sqrt(f)) -#define R_D_forceint(x) floor((x) + 0.5) -#define R_D_nonint(x) (fabs((x) - floor((x)+0.5)) > 1e-7) -/* [neg]ative or [non int]eger : */ -#define R_D_negInonint(x) (x < 0. || R_D_nonint(x)) - -#define R_D_nonint_check(x) \ - if(R_D_nonint(x)) { \ - MATHLIB_WARNING("non-integer x = %f", x); \ - return R_D__0; \ - } diff --git a/deps/Rmath/src/dt.c b/deps/Rmath/src/dt.c deleted file mode 100644 index 273adc6b288a0..0000000000000 --- a/deps/Rmath/src/dt.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * AUTHOR - * Catherine Loader, catherine@research.bell-labs.com. - * October 23, 2000. - * - * Merge in to R: - * Copyright (C) 2000, The R Core Development Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * - * DESCRIPTION - * - * The t density is evaluated as - * sqrt(n/2) / ((n+1)/2) * Gamma((n+3)/2) / Gamma((n+2)/2). - * * (1+x^2/n)^(-n/2) - * / sqrt( 2 pi (1+x^2/n) ) - * - * This form leads to a stable computation for all - * values of n, including n -> 0 and n -> infinity. - */ - -#include "nmath.h" -#include "dpq.h" - -double dt(double x, double n, int give_log) -{ - double t, u; -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(n)) - return x + n; -#endif - - if (n <= 0) ML_ERR_return_NAN; - if(!R_FINITE(x)) - return R_D__0; - if(!R_FINITE(n)) - return dnorm(x, 0., 1., give_log); - - t = -bd0(n/2.,(n+1)/2.) + stirlerr((n+1)/2.) - stirlerr(n/2.); - if ( x*x > 0.2*n ) - u = log( 1+ x*x/n ) * n/2; - else - u = -bd0(n/2.,(n+x*x)/2.) + x*x/2.; - - return R_D_fexp(M_2PI*(1+x*x/n), t-u); -} diff --git a/deps/Rmath/src/dunif.c b/deps/Rmath/src/dunif.c deleted file mode 100644 index 9b551c9c463ec..0000000000000 --- a/deps/Rmath/src/dunif.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * DESCRIPTION - * - * The density of the uniform distribution. - */ - -#include "nmath.h" -#include "dpq.h" - -double dunif(double x, double a, double b, int give_log) -{ -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(a) || ISNAN(b)) - return x + a + b; -#endif - if (b <= a) ML_ERR_return_NAN; - - if (a <= x && x <= b) - return give_log ? -log(b - a) : 1. / (b - a); - return R_D__0; -} diff --git a/deps/Rmath/src/dweibull.c b/deps/Rmath/src/dweibull.c deleted file mode 100644 index 274094f6ef36a..0000000000000 --- a/deps/Rmath/src/dweibull.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000-6 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * DESCRIPTION - * - * The density function of the Weibull distribution. - */ - -#include "nmath.h" -#include "dpq.h" - -double dweibull(double x, double shape, double scale, int give_log) -{ - double tmp1, tmp2; -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(shape) || ISNAN(scale)) - return x + shape + scale; -#endif - if (shape <= 0 || scale <= 0) ML_ERR_return_NAN; - - if (x < 0) return R_D__0; - if (!R_FINITE(x)) return R_D__0; - /* need to handle x == 0 separately */ - if(x == 0 && shape < 1) return ML_POSINF; - tmp1 = pow(x / scale, shape - 1); - tmp2 = tmp1 * (x / scale); - /* These are incorrect if tmp1 == 0 */ - return give_log ? - -tmp2 + log(shape * tmp1 / scale) : - shape * tmp1 * exp(-tmp2) / scale; -} diff --git a/deps/Rmath/src/expm1.c b/deps/Rmath/src/expm1.c deleted file mode 100644 index a74a5c8cf17f3..0000000000000 --- a/deps/Rmath/src/expm1.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 2002 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * double expm1(double x); - * - * DESCRIPTION - * - * Compute the Exponential minus 1 - * - * exp(x) - 1 - * - * accurately also when x is close to zero, i.e. |x| << 1 - * - * NOTES - * - * As log1p(), this is a standard function in some C libraries, - * particularly GNU and BSD (but is neither ISO/ANSI C nor POSIX). - * - * We supply a substitute for the case when there is no system one. - */ - -#ifdef HAVE_CONFIG_H -# include -#endif -#include "nmath.h" - - -#ifndef HAVE_EXPM1 -double expm1(double x) -{ - double y, a = fabs(x); - - if (a < DBL_EPSILON) return x; - if (a > 0.697) return exp(x) - 1; /* negligible cancellation */ - - if (a > 1e-8) - y = exp(x) - 1; - else /* Taylor expansion, more accurate in this range */ - y = (x / 2 + 1) * x; - - /* Newton step for solving log(1 + y) = x for y : */ - /* WARNING: does not work for y ~ -1: bug in 1.5.0 */ - y -= (1 + y) * (log1p (y) - x); - return y; -} -#endif diff --git a/deps/Rmath/src/fmax2.c b/deps/Rmath/src/fmax2.c deleted file mode 100644 index c4b61ee4a9b4d..0000000000000 --- a/deps/Rmath/src/fmax2.c +++ /dev/null @@ -1,29 +0,0 @@ -/* - * R : A Computer Language for Statistical Data Analysis - * Copyright (C) 1995, 1996 Robert Gentleman and Ross Ihaka - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - */ - -#include "nmath.h" - -double fmax2(double x, double y) -{ -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(y)) - return x + y; -#endif - return (x < y) ? y : x; -} diff --git a/deps/Rmath/src/fmin2.c b/deps/Rmath/src/fmin2.c deleted file mode 100644 index bc67f094cb1b7..0000000000000 --- a/deps/Rmath/src/fmin2.c +++ /dev/null @@ -1,29 +0,0 @@ -/* - * R : A Computer Language for Statistical Data Analysis - * Copyright (C) 1995, 1996 Robert Gentleman and Ross Ihaka - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - */ - -#include "nmath.h" - -double fmin2(double x, double y) -{ -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(y)) - return x + y; -#endif - return (x < y) ? x : y; -} diff --git a/deps/Rmath/src/fprec.c b/deps/Rmath/src/fprec.c deleted file mode 100644 index b42a4e35af500..0000000000000 --- a/deps/Rmath/src/fprec.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000-11 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * double fprec(double x, double digits); - * - * DESCRIPTION - * - * Returns the value of x rounded to "digits" significant - * decimal digits. - * - * NOTES - * - * This routine is a translation into C of a Fortran subroutine - * by W. Fullerton of Los Alamos Scientific Laboratory. - * Some modifications have been made so that the routines - * conform to the IEEE 754 standard. - */ - -#include -#include "nmath.h" - - -/* nearbyint is C99, so all platforms should have it (and AFAIK, all do) */ -#ifdef HAVE_NEARBYINT -# define R_rint nearbyint -#elif defined(HAVE_RINT) -# define R_rint rint -#else -# define R_rint private_rint -extern double private_rint(double x); -#endif - -/* Improvements by Martin Maechler, May 1997; - further ones, Feb.2000: - Replace pow(x, (double)i) by R_pow_di(x, i) {and use int dig} */ - -#define MAX_DIGITS 22 -/* was till R 0.99: DBL_DIG := digits of precision of a double, usually 15 */ -/* FIXME: Hmm, have quite a host of these: - - 1) ./fround.c uses much more (sensibly!) ``instead'' - 2) ../main/coerce.c & ../main/deparse.c have DBL_DIG directly - 3) ../main/options.c has #define MAX_DIGITS 22 for options(digits) - - Really should decide on a (config.h dependent?) global MAX_DIGITS. - --MM-- - */ - - -double fprec(double x, double digits) -{ - double l10, pow10, sgn, p10, P10; - int e10, e2, do_round, dig; - /* Max.expon. of 10 (=308.2547) */ - const static int max10e = DBL_MAX_EXP * M_LOG10_2; - - if (ISNAN(x) || ISNAN(digits)) - return x + digits; - if (!R_FINITE(x)) return x; - if (!R_FINITE(digits)) { - if(digits > 0.0) return x; - else digits = 1.0; - } - if(x == 0) return x; - dig = (int)floor(digits+0.5); - if (dig > MAX_DIGITS) { - return x; - } else if (dig < 1) - dig = 1; - - sgn = 1.0; - if(x < 0.0) { - sgn = -sgn; - x = -x; - } - l10 = log10(x); - e10 = (int)(dig-1-floor(l10)); - if(fabs(l10) < max10e - 2) { - p10 = 1.0; - if(e10 > max10e) { /* numbers less than 10^(dig-1) * 1e-308 */ - p10 = R_pow_di(10., e10-max10e); - e10 = max10e; - } - if(e10 > 0) { /* Try always to have pow >= 1 - and so exactly representable */ - pow10 = R_pow_di(10., e10); - return(sgn*(R_rint((x*pow10)*p10)/pow10)/p10); - } else { - pow10 = R_pow_di(10., -e10); - return(sgn*(R_rint((x/pow10))*pow10)); - } - } else { /* -- LARGE or small -- */ - do_round = max10e - l10 >= R_pow_di(10., -dig); - e2 = dig + ((e10>0)? 1 : -1) * MAX_DIGITS; - p10 = R_pow_di(10., e2); x *= p10; - P10 = R_pow_di(10., e10-e2); x *= P10; - /*-- p10 * P10 = 10 ^ e10 */ - if(do_round) x += 0.5; - x = floor(x) / p10; - return(sgn*x/P10); - } -} diff --git a/deps/Rmath/src/fround.c b/deps/Rmath/src/fround.c deleted file mode 100644 index 88df1a9d35138..0000000000000 --- a/deps/Rmath/src/fround.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000-11 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * double fround(double x, double digits); - * - * DESCRIPTION - * - * Rounds "x" to "digits" decimal digits. - * - */ - -#include /* needed for HAVE_*, IEEE_754 */ -#include "nmath.h" - - -/* nearbyint is C99, so all platforms should have it (and AFAIK, all do) */ -#ifdef HAVE_NEARBYINT -# define R_rint nearbyint -#elif defined(HAVE_RINT) -# define R_rint rint -#else -# define R_rint private_rint -extern double private_rint(double x); - -/* also used potentially in fprec.c and main/format.c */ -double attribute_hidden private_rint(double x) -{ - double tmp, sgn = 1.0; - long ltmp; - - if (x != x) return x; /* NaN */ - - if (x < 0.0) { - x = -x; - sgn = -1.0; - } - - if(x < (double) LONG_MAX) { /* in is architecture dependent */ - ltmp = x + 0.5; - /* implement round to even */ - if(fabs(x + 0.5 - ltmp) < 10*DBL_EPSILON - && (ltmp % 2 == 1)) ltmp--; - tmp = ltmp; - } else { - /* ignore round to even: too small a point to bother */ - tmp = floor(x + 0.5); - } - return sgn * tmp; -} -#endif - -double fround(double x, double digits) { -#define MAX_DIGITS DBL_MAX_10_EXP - /* = 308 (IEEE); was till R 0.99: (DBL_DIG - 1) */ - /* Note that large digits make sense for very small numbers */ - long double pow10, sgn, intx; - int dig; - - if (ISNAN(x) || ISNAN(digits)) - return x + digits; - if(!R_FINITE(x)) return x; - - if(digits == ML_POSINF) return x; - else if(digits == ML_NEGINF) return 0.0; - - if (digits > MAX_DIGITS) digits = MAX_DIGITS; - dig = (int)floor(digits + 0.5); - if(x < 0.) { - sgn = -1.; - x = -x; - } else - sgn = 1.; - if (dig == 0) { - return sgn * R_rint(x); - } else if (dig > 0) { - pow10 = R_pow_di(10., dig); - intx = floor(x); - return sgn * (intx + R_rint((x-intx) * pow10) / pow10); - } else { - pow10 = R_pow_di(10., -dig); - return sgn * R_rint(x/pow10) * pow10; - } -} diff --git a/deps/Rmath/src/fsign.c b/deps/Rmath/src/fsign.c deleted file mode 100644 index f2fcd6d09d9ed..0000000000000 --- a/deps/Rmath/src/fsign.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * double fsign(double x, double y); - * - * DESCRIPTION - * - * This function performs transfer of sign. The result is: - * - * |x| * signum(y) - */ - -#include "nmath.h" - -double fsign(double x, double y) -{ -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(y)) - return x + y; -#endif - return ((y >= 0) ? fabs(x) : -fabs(x)); -} diff --git a/deps/Rmath/src/ftrunc.c b/deps/Rmath/src/ftrunc.c deleted file mode 100644 index 55e14da758daf..0000000000000 --- a/deps/Rmath/src/ftrunc.c +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * double ftrunc(double x); - * - * DESCRIPTION - * - * Truncation toward zero. - */ - -#include "nmath.h" - -double ftrunc(double x) -{ - if(x >= 0) return floor(x); - else return ceil(x); -} diff --git a/deps/Rmath/src/gamma.c b/deps/Rmath/src/gamma.c deleted file mode 100644 index 692e47a389099..0000000000000 --- a/deps/Rmath/src/gamma.c +++ /dev/null @@ -1,221 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000-2001 The R Development Core Team - * Copyright (C) 2002-2004 The R Foundation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * double gammafn(double x); - * - * DESCRIPTION - * - * This function computes the value of the gamma function. - * - * NOTES - * - * This function is a translation into C of a Fortran subroutine - * by W. Fullerton of Los Alamos Scientific Laboratory. - * (e.g. http://www.netlib.org/slatec/fnlib/gamma.f) - * - * The accuracy of this routine compares (very) favourably - * with those of the Sun Microsystems portable mathematical - * library. - * - * MM specialized the case of n! for n < 50 - for even better precision - */ - -#include "nmath.h" - -double gammafn(double x) -{ - const static double gamcs[42] = { - +.8571195590989331421920062399942e-2, - +.4415381324841006757191315771652e-2, - +.5685043681599363378632664588789e-1, - -.4219835396418560501012500186624e-2, - +.1326808181212460220584006796352e-2, - -.1893024529798880432523947023886e-3, - +.3606925327441245256578082217225e-4, - -.6056761904460864218485548290365e-5, - +.1055829546302283344731823509093e-5, - -.1811967365542384048291855891166e-6, - +.3117724964715322277790254593169e-7, - -.5354219639019687140874081024347e-8, - +.9193275519859588946887786825940e-9, - -.1577941280288339761767423273953e-9, - +.2707980622934954543266540433089e-10, - -.4646818653825730144081661058933e-11, - +.7973350192007419656460767175359e-12, - -.1368078209830916025799499172309e-12, - +.2347319486563800657233471771688e-13, - -.4027432614949066932766570534699e-14, - +.6910051747372100912138336975257e-15, - -.1185584500221992907052387126192e-15, - +.2034148542496373955201026051932e-16, - -.3490054341717405849274012949108e-17, - +.5987993856485305567135051066026e-18, - -.1027378057872228074490069778431e-18, - +.1762702816060529824942759660748e-19, - -.3024320653735306260958772112042e-20, - +.5188914660218397839717833550506e-21, - -.8902770842456576692449251601066e-22, - +.1527474068493342602274596891306e-22, - -.2620731256187362900257328332799e-23, - +.4496464047830538670331046570666e-24, - -.7714712731336877911703901525333e-25, - +.1323635453126044036486572714666e-25, - -.2270999412942928816702313813333e-26, - +.3896418998003991449320816639999e-27, - -.6685198115125953327792127999999e-28, - +.1146998663140024384347613866666e-28, - -.1967938586345134677295103999999e-29, - +.3376448816585338090334890666666e-30, - -.5793070335782135784625493333333e-31 - }; - - int i, n; - double y; - double sinpiy, value; - -#ifdef NOMORE_FOR_THREADS - static int ngam = 0; - static double xmin = 0, xmax = 0., xsml = 0., dxrel = 0.; - - /* Initialize machine dependent constants, the first time gamma() is called. - FIXME for threads ! */ - if (ngam == 0) { - ngam = chebyshev_init(gamcs, 42, DBL_EPSILON/20);/*was .1*d1mach(3)*/ - gammalims(&xmin, &xmax);/*-> ./gammalims.c */ - xsml = exp(fmax2(log(DBL_MIN), -log(DBL_MAX)) + 0.01); - /* = exp(.01)*DBL_MIN = 2.247e-308 for IEEE */ - dxrel = sqrt(DBL_EPSILON);/*was sqrt(d1mach(4)) */ - } -#else -/* For IEEE double precision DBL_EPSILON = 2^-52 = 2.220446049250313e-16 : - * (xmin, xmax) are non-trivial, see ./gammalims.c - * xsml = exp(.01)*DBL_MIN - * dxrel = sqrt(DBL_EPSILON) = 2 ^ -26 -*/ -# define ngam 22 -# define xmin -170.5674972726612 -# define xmax 171.61447887182298 -# define xsml 2.2474362225598545e-308 -# define dxrel 1.490116119384765696e-8 -#endif - - if(ISNAN(x)) return x; - - /* If the argument is exactly zero or a negative integer - * then return NaN. */ - if (x == 0 || (x < 0 && x == (long)x)) { - ML_ERROR(ME_DOMAIN, "gammafn"); - return ML_NAN; - } - - y = fabs(x); - - if (y <= 10) { - - /* Compute gamma(x) for -10 <= x <= 10 - * Reduce the interval and find gamma(1 + y) for 0 <= y < 1 - * first of all. */ - - n = x; - if(x < 0) --n; - y = x - n;/* n = floor(x) ==> y in [ 0, 1 ) */ - --n; - value = chebyshev_eval(y * 2 - 1, gamcs, ngam) + .9375; - if (n == 0) - return value;/* x = 1.dddd = 1+y */ - - if (n < 0) { - /* compute gamma(x) for -10 <= x < 1 */ - - /* exact 0 or "-n" checked already above */ - - /* The answer is less than half precision */ - /* because x too near a negative integer. */ - if (x < -0.5 && fabs(x - (int)(x - 0.5) / x) < dxrel) { - ML_ERROR(ME_PRECISION, "gammafn"); - } - - /* The argument is so close to 0 that the result would overflow. */ - if (y < xsml) { - ML_ERROR(ME_RANGE, "gammafn"); - if(x > 0) return ML_POSINF; - else return ML_NEGINF; - } - - n = -n; - - for (i = 0; i < n; i++) { - value /= (x + i); - } - return value; - } - else { - /* gamma(x) for 2 <= x <= 10 */ - - for (i = 1; i <= n; i++) { - value *= (y + i); - } - return value; - } - } - else { - /* gamma(x) for y = |x| > 10. */ - - if (x > xmax) { /* Overflow */ - ML_ERROR(ME_RANGE, "gammafn"); - return ML_POSINF; - } - - if (x < xmin) { /* Underflow */ - ML_ERROR(ME_UNDERFLOW, "gammafn"); - return 0.; - } - - if(y <= 50 && y == (int)y) { /* compute (n - 1)! */ - value = 1.; - for (i = 2; i < y; i++) value *= i; - } - else { /* normal case */ - value = exp((y - 0.5) * log(y) - y + M_LN_SQRT_2PI + - ((2*y == (int)2*y)? stirlerr(y) : lgammacor(y))); - } - if (x > 0) - return value; - - if (fabs((x - (int)(x - 0.5))/x) < dxrel){ - - /* The answer is less than half precision because */ - /* the argument is too near a negative integer. */ - - ML_ERROR(ME_PRECISION, "gammafn"); - } - - sinpiy = sin(M_PI * y); - if (sinpiy == 0) { /* Negative integer arg - overflow */ - ML_ERROR(ME_RANGE, "gammafn"); - return ML_POSINF; - } - - return -M_PI / (y * sinpiy * value); - } -} diff --git a/deps/Rmath/src/gamma_cody.c b/deps/Rmath/src/gamma_cody.c deleted file mode 100644 index 0efbaff445ce3..0000000000000 --- a/deps/Rmath/src/gamma_cody.c +++ /dev/null @@ -1,241 +0,0 @@ -/* From http://www.netlib.org/specfun/gamma Fortran translated by f2c,... - * ------------------------------##### Martin Maechler, ETH Zurich - * - *=========== was part of ribesl (Bessel I(.)) - *=========== ~~~~~~ - */ -#include "nmath.h" - -double attribute_hidden gamma_cody(double x) -{ -/* ---------------------------------------------------------------------- - - This routine calculates the GAMMA function for a float argument X. - Computation is based on an algorithm outlined in reference [1]. - The program uses rational functions that approximate the GAMMA - function to at least 20 significant decimal digits. Coefficients - for the approximation over the interval (1,2) are unpublished. - Those for the approximation for X >= 12 are from reference [2]. - The accuracy achieved depends on the arithmetic system, the - compiler, the intrinsic functions, and proper selection of the - machine-dependent constants. - - ******************************************************************* - - Error returns - - The program returns the value XINF for singularities or - when overflow would occur. The computation is believed - to be free of underflow and overflow. - - Intrinsic functions required are: - - INT, DBLE, EXP, LOG, REAL, SIN - - - References: - [1] "An Overview of Software Development for Special Functions", - W. J. Cody, Lecture Notes in Mathematics, 506, - Numerical Analysis Dundee, 1975, G. A. Watson (ed.), - Springer Verlag, Berlin, 1976. - - [2] Computer Approximations, Hart, Et. Al., Wiley and sons, New York, 1968. - - Latest modification: October 12, 1989 - - Authors: W. J. Cody and L. Stoltz - Applied Mathematics Division - Argonne National Laboratory - Argonne, IL 60439 - ----------------------------------------------------------------------*/ - -/* ---------------------------------------------------------------------- - Mathematical constants - ----------------------------------------------------------------------*/ - const static double sqrtpi = .9189385332046727417803297; /* == ??? */ - -/* ******************************************************************* - - Explanation of machine-dependent constants - - beta - radix for the floating-point representation - maxexp - the smallest positive power of beta that overflows - XBIG - the largest argument for which GAMMA(X) is representable - in the machine, i.e., the solution to the equation - GAMMA(XBIG) = beta**maxexp - XINF - the largest machine representable floating-point number; - approximately beta**maxexp - EPS - the smallest positive floating-point number such that 1.0+EPS > 1.0 - XMININ - the smallest positive floating-point number such that - 1/XMININ is machine representable - - Approximate values for some important machines are: - - beta maxexp XBIG - - CRAY-1 (S.P.) 2 8191 966.961 - Cyber 180/855 - under NOS (S.P.) 2 1070 177.803 - IEEE (IBM/XT, - SUN, etc.) (S.P.) 2 128 35.040 - IEEE (IBM/XT, - SUN, etc.) (D.P.) 2 1024 171.624 - IBM 3033 (D.P.) 16 63 57.574 - VAX D-Format (D.P.) 2 127 34.844 - VAX G-Format (D.P.) 2 1023 171.489 - - XINF EPS XMININ - - CRAY-1 (S.P.) 5.45E+2465 7.11E-15 1.84E-2466 - Cyber 180/855 - under NOS (S.P.) 1.26E+322 3.55E-15 3.14E-294 - IEEE (IBM/XT, - SUN, etc.) (S.P.) 3.40E+38 1.19E-7 1.18E-38 - IEEE (IBM/XT, - SUN, etc.) (D.P.) 1.79D+308 2.22D-16 2.23D-308 - IBM 3033 (D.P.) 7.23D+75 2.22D-16 1.39D-76 - VAX D-Format (D.P.) 1.70D+38 1.39D-17 5.88D-39 - VAX G-Format (D.P.) 8.98D+307 1.11D-16 1.12D-308 - - ******************************************************************* - - ---------------------------------------------------------------------- - Machine dependent parameters - ---------------------------------------------------------------------- - */ - - - const static double xbig = 171.624; - /* ML_POSINF == const double xinf = 1.79e308;*/ - /* DBL_EPSILON = const double eps = 2.22e-16;*/ - /* DBL_MIN == const double xminin = 2.23e-308;*/ - - /*---------------------------------------------------------------------- - Numerator and denominator coefficients for rational minimax - approximation over (1,2). - ----------------------------------------------------------------------*/ - const static double p[8] = { - -1.71618513886549492533811, - 24.7656508055759199108314,-379.804256470945635097577, - 629.331155312818442661052,866.966202790413211295064, - -31451.2729688483675254357,-36144.4134186911729807069, - 66456.1438202405440627855 }; - const static double q[8] = { - -30.8402300119738975254353, - 315.350626979604161529144,-1015.15636749021914166146, - -3107.77167157231109440444,22538.1184209801510330112, - 4755.84627752788110767815,-134659.959864969306392456, - -115132.259675553483497211 }; - /*---------------------------------------------------------------------- - Coefficients for minimax approximation over (12, INF). - ----------------------------------------------------------------------*/ - const static double c[7] = { - -.001910444077728,8.4171387781295e-4, - -5.952379913043012e-4,7.93650793500350248e-4, - -.002777777777777681622553,.08333333333333333331554247, - .0057083835261 }; - - /* Local variables */ - long i, n; - long int parity;/*logical*/ - double fact, xden, xnum, y, z, yi, res, sum, ysq; - - parity = (0); - fact = 1.; - n = 0; - y = x; - if (y <= 0.) { - /* ------------------------------------------------------------- - Argument is negative - ------------------------------------------------------------- */ - y = -x; - yi = ftrunc(y); - res = y - yi; - if (res != 0.) { - if (yi != ftrunc(yi * .5) * 2.) - parity = (1); - fact = -M_PI / sin(M_PI * res); - y += 1.; - } else { - return(ML_POSINF); - } - } - /* ----------------------------------------------------------------- - Argument is positive - -----------------------------------------------------------------*/ - if (y < DBL_EPSILON) { - /* -------------------------------------------------------------- - Argument < EPS - -------------------------------------------------------------- */ - if (y >= DBL_MIN) { - res = 1. / y; - } else { - return(ML_POSINF); - } - } else if (y < 12.) { - yi = y; - if (y < 1.) { - /* --------------------------------------------------------- - EPS < argument < 1 - --------------------------------------------------------- */ - z = y; - y += 1.; - } else { - /* ----------------------------------------------------------- - 1 <= argument < 12, reduce argument if necessary - ----------------------------------------------------------- */ - n = (long) y - 1; - y -= (double) n; - z = y - 1.; - } - /* --------------------------------------------------------- - Evaluate approximation for 1. < argument < 2. - ---------------------------------------------------------*/ - xnum = 0.; - xden = 1.; - for (i = 0; i < 8; ++i) { - xnum = (xnum + p[i]) * z; - xden = xden * z + q[i]; - } - res = xnum / xden + 1.; - if (yi < y) { - /* -------------------------------------------------------- - Adjust result for case 0. < argument < 1. - -------------------------------------------------------- */ - res /= yi; - } else if (yi > y) { - /* ---------------------------------------------------------- - Adjust result for case 2. < argument < 12. - ---------------------------------------------------------- */ - for (i = 0; i < n; ++i) { - res *= y; - y += 1.; - } - } - } else { - /* ------------------------------------------------------------- - Evaluate for argument >= 12., - ------------------------------------------------------------- */ - if (y <= xbig) { - ysq = y * y; - sum = c[6]; - for (i = 0; i < 6; ++i) { - sum = sum / ysq + c[i]; - } - sum = sum / y - y + sqrtpi; - sum += (y - .5) * log(y); - res = exp(sum); - } else { - return(ML_POSINF); - } - } - /* ---------------------------------------------------------------------- - Final adjustments and return - ----------------------------------------------------------------------*/ - if (parity) - res = -res; - if (fact != 1.) - res = fact / res; - return res; -} - diff --git a/deps/Rmath/src/gammalims.c b/deps/Rmath/src/gammalims.c deleted file mode 100644 index b1a2227a196e8..0000000000000 --- a/deps/Rmath/src/gammalims.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 1999-2000 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * void gammalims(double *xmin, double *xmax); - * - * DESCRIPTION - * - * This function calculates the minimum and maximum legal bounds - * for x in gammafn(x). These are not the only bounds, but they - * are the only non-trivial ones to calculate. - * - * NOTES - * - * This routine is a translation into C of a Fortran subroutine - * by W. Fullerton of Los Alamos Scientific Laboratory. - */ - -#include "nmath.h" - -void attribute_hidden gammalims(double *xmin, double *xmax) -{ -/* FIXME: Even better: If IEEE, #define these in nmath.h - and don't call gammalims() at all -*/ -#ifdef IEEE_754 - *xmin = -170.5674972726612; - *xmax = 171.61447887182298;/*(3 Intel/Sparc architectures)*/ -#else - double alnbig, alnsml, xln, xold; - int i; - - alnsml = log(d1mach(1)); - *xmin = -alnsml; - for (i=1; i<=10; ++i) { - xold = *xmin; - xln = log(*xmin); - *xmin -= *xmin * ((*xmin + .5) * xln - *xmin - .2258 + alnsml) / - (*xmin * xln + .5); - if (fabs(*xmin - xold) < .005) { - *xmin = -(*xmin) + .01; - goto find_xmax; - } - } - - /* unable to find xmin */ - - ML_ERROR(ME_NOCONV, "gammalims"); - *xmin = *xmax = ML_NAN; - -find_xmax: - - alnbig = log(d1mach(2)); - *xmax = alnbig; - for (i=1; i<=10; ++i) { - xold = *xmax; - xln = log(*xmax); - *xmax -= *xmax * ((*xmax - .5) * xln - *xmax + .9189 - alnbig) / - (*xmax * xln - .5); - if (fabs(*xmax - xold) < .005) { - *xmax += -.01; - goto done; - } - } - - /* unable to find xmax */ - - ML_ERROR(ME_NOCONV, "gammalims"); - *xmin = *xmax = ML_NAN; - -done: - *xmin = fmax2(*xmin, -(*xmax) + 1); -#endif -} - diff --git a/deps/Rmath/src/i1mach.c b/deps/Rmath/src/i1mach.c deleted file mode 100644 index 07fc134c18a9e..0000000000000 --- a/deps/Rmath/src/i1mach.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Mathlib - A Mathematical Function Library - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000-7 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - */ - -#include "nmath.h" -#include - -attribute_hidden int Rf_i1mach(int i) -{ - switch(i) { - - case 1: return 5; - case 2: return 6; - case 3: return 0; - case 4: return 0; - - case 5: return CHAR_BIT * sizeof(int); - case 6: return sizeof(int)/sizeof(char); - - case 7: return 2; - case 8: return CHAR_BIT * sizeof(int) - 1; - case 9: return INT_MAX; - - case 10: return FLT_RADIX; - - case 11: return FLT_MANT_DIG; - case 12: return FLT_MIN_EXP; - case 13: return FLT_MAX_EXP; - - case 14: return DBL_MANT_DIG; - case 15: return DBL_MIN_EXP; - case 16: return DBL_MAX_EXP; - - default: return 0; - } -} - -int F77_NAME(i1mach)(int *i) -{ - return Rf_i1mach(*i); -} diff --git a/deps/Rmath/src/imax2.c b/deps/Rmath/src/imax2.c deleted file mode 100644 index f039459d58036..0000000000000 --- a/deps/Rmath/src/imax2.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * int imax2(int x, int y); - * - * DESCRIPTION - * - * Compute maximum of two integers. - */ - -#include "nmath.h" - -int imax2(int x, int y) -{ - return (x < y) ? y : x; -} diff --git a/deps/Rmath/src/imin2.c b/deps/Rmath/src/imin2.c deleted file mode 100644 index a8b42967ba10b..0000000000000 --- a/deps/Rmath/src/imin2.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * int imin2(int x, int y); - * - * DESCRIPTION - * - * Compute minimum of two integers. - */ - -#include "nmath.h" - -int imin2(int x, int y) -{ - return (x < y) ? x : y; -} diff --git a/deps/Rmath/src/lbeta.c b/deps/Rmath/src/lbeta.c deleted file mode 100644 index 3ef6d6deb381a..0000000000000 --- a/deps/Rmath/src/lbeta.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000 The R Development Core Team - * Copyright (C) 2003 The R Foundation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * double lbeta(double a, double b); - * - * DESCRIPTION - * - * This function returns the value of the log beta function. - * - * NOTES - * - * This routine is a translation into C of a Fortran subroutine - * by W. Fullerton of Los Alamos Scientific Laboratory. - */ - -#include "nmath.h" - -double lbeta(double a, double b) -{ - double corr, p, q; - -#ifdef IEEE_754 - if(ISNAN(a) || ISNAN(b)) - return a + b; -#endif - p = q = a; - if(b < p) p = b;/* := min(a,b) */ - if(b > q) q = b;/* := max(a,b) */ - - /* both arguments must be >= 0 */ - if (p < 0) - ML_ERR_return_NAN - else if (p == 0) { - return ML_POSINF; - } - else if (!R_FINITE(q)) { /* q == +Inf */ - return ML_NEGINF; - } - - if (p >= 10) { - /* p and q are big. */ - corr = lgammacor(p) + lgammacor(q) - lgammacor(p + q); - return log(q) * -0.5 + M_LN_SQRT_2PI + corr - + (p - 0.5) * log(p / (p + q)) + q * log1p(-p / (p + q)); - } - else if (q >= 10) { - /* p is small, but q is big. */ - corr = lgammacor(q) - lgammacor(p + q); - return lgammafn(p) + corr + p - p * log(p + q) - + (q - 0.5) * log1p(-p / (p + q)); - } - else - /* p and q are small: p <= q < 10. */ - return log(gammafn(p) * (gammafn(q) / gammafn(p + q))); -} diff --git a/deps/Rmath/src/lgamma.c b/deps/Rmath/src/lgamma.c deleted file mode 100644 index 53056c97ced9e..0000000000000 --- a/deps/Rmath/src/lgamma.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000-2001 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * double lgammafn_sign(double x, int *sgn); - * double lgammafn(double x); - * - * DESCRIPTION - * - * The function lgammafn computes log|gamma(x)|. The function - * lgammafn_sign in addition assigns the sign of the gamma function - * to the address in the second argument if this is not NULL. - * - * NOTES - * - * This routine is a translation into C of a Fortran subroutine - * by W. Fullerton of Los Alamos Scientific Laboratory. - * - * The accuracy of this routine compares (very) favourably - * with those of the Sun Microsystems portable mathematical - * library. - */ - -#include "nmath.h" - -double lgammafn_sign(double x, int *sgn) -{ - double ans, y, sinpiy; - -#ifdef NOMORE_FOR_THREADS - static double xmax = 0.; - static double dxrel = 0.; - - if (xmax == 0) {/* initialize machine dependent constants _ONCE_ */ - xmax = d1mach(2)/log(d1mach(2));/* = 2.533 e305 for IEEE double */ - dxrel = sqrt (d1mach(4));/* sqrt(Eps) ~ 1.49 e-8 for IEEE double */ - } -#else -/* For IEEE double precision DBL_EPSILON = 2^-52 = 2.220446049250313e-16 : - xmax = DBL_MAX / log(DBL_MAX) = 2^1024 / (1024 * log(2)) = 2^1014 / log(2) - dxrel = sqrt(DBL_EPSILON) = 2^-26 = 5^26 * 1e-26 (is *exact* below !) - */ -#define xmax 2.5327372760800758e+305 -#define dxrel 1.490116119384765696e-8 -#endif - - if (sgn != NULL) *sgn = 1; - -#ifdef IEEE_754 - if(ISNAN(x)) return x; -#endif - - if (x < 0 && fmod(floor(-x), 2.) == 0) - if (sgn != NULL) *sgn = -1; - - if (x <= 0 && x == trunc(x)) { /* Negative integer argument */ - ML_ERROR(ME_RANGE, "lgamma"); - return ML_POSINF;/* +Inf, since lgamma(x) = log|gamma(x)| */ - } - - y = fabs(x); - - if (y <= 10) - return log(fabs(gammafn(x))); - /* - ELSE y = |x| > 10 ---------------------- */ - - if (y > xmax) { - ML_ERROR(ME_RANGE, "lgamma"); - return ML_POSINF; - } - - if (x > 0) { /* i.e. y = x > 10 */ -#ifdef IEEE_754 - if(x > 1e17) - return(x*(log(x) - 1.)); - else if(x > 4934720.) - return(M_LN_SQRT_2PI + (x - 0.5) * log(x) - x); - else -#endif - return M_LN_SQRT_2PI + (x - 0.5) * log(x) - x + lgammacor(x); - } - /* else: x < -10; y = -x */ - sinpiy = fabs(sin(M_PI * y)); - - if (sinpiy == 0) { /* Negative integer argument === - Now UNNECESSARY: caught above */ - MATHLIB_WARNING(" ** should NEVER happen! *** [lgamma.c: Neg.int, y=%g]\n",y); - ML_ERR_return_NAN; - } - - ans = M_LN_SQRT_PId2 + (x - 0.5) * log(y) - x - log(sinpiy) - lgammacor(y); - - if(fabs((x - trunc(x - 0.5)) * ans / x) < dxrel) { - - /* The answer is less than half precision because - * the argument is too near a negative integer. */ - - ML_ERROR(ME_PRECISION, "lgamma"); - } - - return ans; -} - -double lgammafn(double x) -{ - return lgammafn_sign(x, NULL); -} diff --git a/deps/Rmath/src/lgammacor.c b/deps/Rmath/src/lgammacor.c deleted file mode 100644 index 5fda73b86ec6e..0000000000000 --- a/deps/Rmath/src/lgammacor.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000-2001 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * double lgammacor(double x); - * - * DESCRIPTION - * - * Compute the log gamma correction factor for x >= 10 so that - * - * log(gamma(x)) = .5*log(2*pi) + (x-.5)*log(x) -x + lgammacor(x) - * - * [ lgammacor(x) is called Del(x) in other contexts (e.g. dcdflib)] - * - * NOTES - * - * This routine is a translation into C of a Fortran subroutine - * written by W. Fullerton of Los Alamos Scientific Laboratory. - * - * SEE ALSO - * - * Loader(1999)'s stirlerr() {in ./stirlerr.c} is *very* similar in spirit, - * is faster and cleaner, but is only defined "fast" for half integers. - */ - -#include "nmath.h" - -double attribute_hidden lgammacor(double x) -{ - const static double algmcs[15] = { - +.1666389480451863247205729650822e+0, - -.1384948176067563840732986059135e-4, - +.9810825646924729426157171547487e-8, - -.1809129475572494194263306266719e-10, - +.6221098041892605227126015543416e-13, - -.3399615005417721944303330599666e-15, - +.2683181998482698748957538846666e-17, - -.2868042435334643284144622399999e-19, - +.3962837061046434803679306666666e-21, - -.6831888753985766870111999999999e-23, - +.1429227355942498147573333333333e-24, - -.3547598158101070547199999999999e-26, - +.1025680058010470912000000000000e-27, - -.3401102254316748799999999999999e-29, - +.1276642195630062933333333333333e-30 - }; - - double tmp; - -/* For IEEE double precision DBL_EPSILON = 2^-52 = 2.220446049250313e-16 : - * xbig = 2 ^ 26.5 - * xmax = DBL_MAX / 48 = 2^1020 / 3 */ -#define nalgm 5 -#define xbig 94906265.62425156 -#define xmax 3.745194030963158e306 - - if (x < 10) - ML_ERR_return_NAN - else if (x >= xmax) { - ML_ERROR(ME_UNDERFLOW, "lgammacor"); - /* allow to underflow below */ - } - else if (x < xbig) { - tmp = 10 / x; - return chebyshev_eval(tmp * tmp * 2 - 1, algmcs, nalgm) / x; - } - return 1 / (x * 12); -} diff --git a/deps/Rmath/src/log1p.c b/deps/Rmath/src/log1p.c deleted file mode 100644 index 17b9781400b29..0000000000000 --- a/deps/Rmath/src/log1p.c +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000, 2003, 2011 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * double log1p(double x); - * - * DESCRIPTION - * - * Compute the relative error logarithm. - * - * log(1 + x) - * - * NOTES - * - * This code is a translation of the Fortran subroutine `dlnrel' - * written by W. Fullerton of Los Alamos Scientific Laboratory. - */ - -/* Every currently known platform has log1p (which is C99), - but NetBSD/OpenBSD were at least at one time inaccurate */ -#ifdef HAVE_CONFIG_H -# include -#endif -#include "nmath.h" - -/* want to compile log1p as Rlog1p if HAVE_LOG1P && !HAVE_WORKING_LOG1P */ -#if defined(HAVE_LOG1P) && !defined(HAVE_WORKING_LOG1P) -#undef HAVE_LOG1P -#endif - -#ifndef HAVE_LOG1P -double log1p(double x) -{ - /* series for log1p on the interval -.375 to .375 - * with weighted error 6.35e-32 - * log weighted error 31.20 - * significant figures required 30.93 - * decimal places required 32.01 - */ - const static double alnrcs[43] = { - +.10378693562743769800686267719098e+1, - -.13364301504908918098766041553133e+0, - +.19408249135520563357926199374750e-1, - -.30107551127535777690376537776592e-2, - +.48694614797154850090456366509137e-3, - -.81054881893175356066809943008622e-4, - +.13778847799559524782938251496059e-4, - -.23802210894358970251369992914935e-5, - +.41640416213865183476391859901989e-6, - -.73595828378075994984266837031998e-7, - +.13117611876241674949152294345011e-7, - -.23546709317742425136696092330175e-8, - +.42522773276034997775638052962567e-9, - -.77190894134840796826108107493300e-10, - +.14075746481359069909215356472191e-10, - -.25769072058024680627537078627584e-11, - +.47342406666294421849154395005938e-12, - -.87249012674742641745301263292675e-13, - +.16124614902740551465739833119115e-13, - -.29875652015665773006710792416815e-14, - +.55480701209082887983041321697279e-15, - -.10324619158271569595141333961932e-15, - +.19250239203049851177878503244868e-16, - -.35955073465265150011189707844266e-17, - +.67264542537876857892194574226773e-18, - -.12602624168735219252082425637546e-18, - +.23644884408606210044916158955519e-19, - -.44419377050807936898878389179733e-20, - +.83546594464034259016241293994666e-21, - -.15731559416479562574899253521066e-21, - +.29653128740247422686154369706666e-22, - -.55949583481815947292156013226666e-23, - +.10566354268835681048187284138666e-23, - -.19972483680670204548314999466666e-24, - +.37782977818839361421049855999999e-25, - -.71531586889081740345038165333333e-26, - +.13552488463674213646502024533333e-26, - -.25694673048487567430079829333333e-27, - +.48747756066216949076459519999999e-28, - -.92542112530849715321132373333333e-29, - +.17578597841760239233269760000000e-29, - -.33410026677731010351377066666666e-30, - +.63533936180236187354180266666666e-31, - }; - -#ifdef NOMORE_FOR_THREADS - static int nlnrel = 0; - static double xmin = 0.0; - - if (xmin == 0.0) xmin = -1 + sqrt(DBL_EPSILON);/*was sqrt(d1mach(4)); */ - if (nlnrel == 0) /* initialize chebychev coefficients */ - nlnrel = chebyshev_init(alnrcs, 43, DBL_EPSILON/20);/*was .1*d1mach(3)*/ -#else -# define nlnrel 22 - const static double xmin = -0.999999985; -/* 22: for IEEE double precision where DBL_EPSILON = 2.22044604925031e-16 */ -#endif - - if (x == 0.) return 0.;/* speed */ - if (x == -1) return(ML_NEGINF); - if (x < -1) ML_ERR_return_NAN; - - if (fabs(x) <= .375) { - /* Improve on speed (only); - again give result accurate to IEEE double precision: */ - if(fabs(x) < .5 * DBL_EPSILON) - return x; - - if( (0 < x && x < 1e-8) || (-1e-9 < x && x < 0)) - return x * (1 - .5 * x); - /* else */ - return x * (1 - x * chebyshev_eval(x / .375, alnrcs, nlnrel)); - } - /* else */ - if (x < xmin) { - /* answer less than half precision because x too near -1 */ - ML_ERROR(ME_PRECISION, "log1p"); - } - return log(1 + x); -} -#endif - - - -#ifndef HAVE_HYPOT -/* Used as a substitute for the C99 function hypot, which all currently - known platforms have */ - -/* hypot(a,b) finds sqrt(a^2 + b^2) - * without overflow or destructive underflow. - */ - -double hypot(double a, double b) -{ - double p, r, s, t, tmp, u; - - if(ISNAN(a) || ISNAN(b)) /* propagate Na(N)s: */ - return -#ifdef IEEE_754 - a + b; -#else - ML_NAN; -#endif - if (!R_FINITE(a) || !R_FINITE(b)) { - return ML_POSINF; - } - p = fmax2(fabs(a), fabs(b)); - if (p != 0.0) { - - /* r = (min(|a|,|b|) / p) ^2 */ - tmp = fmin2(fabs(a), fabs(b))/p; - r = tmp * tmp; - for(;;) { - t = 4.0 + r; - /* This was a test of 4.0 + r == 4.0, but optimizing - compilers nowadays infinite loop on that. */ - if(fabs(r) < 2*DBL_EPSILON) break; - s = r / t; - u = 1. + 2. * s; - p *= u ; - - /* r = (s / u)^2 * r */ - tmp = s / u; - r *= tmp * tmp; - } - } - return p; -} -#endif diff --git a/deps/Rmath/src/mlutils.c b/deps/Rmath/src/mlutils.c deleted file mode 100644 index a133927c5369f..0000000000000 --- a/deps/Rmath/src/mlutils.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998-2006 Ross Ihaka and the R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - */ - -#ifdef HAVE_CONFIG_H -# include -# undef fprintf -#endif -#include "nmath.h" - -#ifdef MATHLIB_STANDALONE -/* - * based on code in ../main/arithmetic.c - * used only in standalone Rmath lib. - */ - -int R_finite(double x) -{ -#ifdef HAVE_WORKING_ISFINITE - return isfinite(x); -# else - return (!isnan(x) & (x != ML_POSINF) & (x != ML_NEGINF)); -#endif -} - -/* C++ math header undefines any isnan macro. This file - doesn't get C++ headers and so is safe. */ -int R_isnancpp(double x) -{ - return (isnan(x) != 0); -} - -static double myfmod(double x1, double x2) -{ - double q = x1 / x2; - return x1 - floor(q) * x2; -} - -double R_pow(double x, double y) /* = x ^ y */ -{ - if(x == 1. || y == 0.) - return(1.); - if(x == 0.) { - if(y > 0.) return(0.); - /* y < 0 */return(ML_POSINF); - } - if (R_FINITE(x) && R_FINITE(y)) - return(pow(x,y)); - if (ISNAN(x) || ISNAN(y)) { -#ifdef IEEE_754 - return(x + y); -#else - return(ML_NAN); -#endif - } - if(!R_FINITE(x)) { - if(x > 0) /* Inf ^ y */ - return((y < 0.)? 0. : ML_POSINF); - else { /* (-Inf) ^ y */ - if(R_FINITE(y) && y == floor(y)) /* (-Inf) ^ n */ - return((y < 0.) ? 0. : (myfmod(y,2.) ? x : -x)); - } - } - if(!R_FINITE(y)) { - if(x >= 0) { - if(y > 0) /* y == +Inf */ - return((x >= 1)? ML_POSINF : 0.); - else /* y == -Inf */ - return((x < 1) ? ML_POSINF : 0.); - } - } - return(ML_NAN); /* all other cases: (-Inf)^{+-Inf, - non-int}; (neg)^{+-Inf} */ -} - -double R_pow_di(double x, int n) -{ - double pow = 1.0; - - if (ISNAN(x)) return x; - if (n != 0) { - if (!R_FINITE(x)) return R_pow(x, (double)n); - if (n < 0) { n = -n; x = 1/x; } - for(;;) { - if(n & 01) pow *= x; - if(n >>= 1) x *= x; else break; - } - } - return pow; -} - -double NA_REAL = ML_NAN; -double R_PosInf = ML_POSINF, R_NegInf = ML_NEGINF; - -#include -#include -void attribute_hidden REprintf(const char *format, ...) -{ - va_list(ap); - va_start(ap, format); - fprintf(stderr, format, ap); - va_end(ap); -} - -#endif /* MATHLIB_STANDALONE */ diff --git a/deps/Rmath/src/nmath.h b/deps/Rmath/src/nmath.h deleted file mode 100644 index 13aa4e058a6a5..0000000000000 --- a/deps/Rmath/src/nmath.h +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998-2011 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - */ - -/* Private header file for use during compilation of Mathlib */ -#ifndef MATHLIB_PRIVATE_H -#define MATHLIB_PRIVATE_H - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include /* DBL_MIN etc */ - -#include -#include - -double Rf_d1mach(int); -#define gamma_cody Rf_gamma_cody -double gamma_cody(double); - -#include - -/* possibly needed for debugging */ -#include - - -#ifndef MATHLIB_STANDALONE - -#include -# define MATHLIB_ERROR(fmt,x) error(fmt,x); -# define MATHLIB_WARNING(fmt,x) warning(fmt,x) -# define MATHLIB_WARNING2(fmt,x,x2) warning(fmt,x,x2) -# define MATHLIB_WARNING3(fmt,x,x2,x3) warning(fmt,x,x2,x3) -# define MATHLIB_WARNING4(fmt,x,x2,x3,x4) warning(fmt,x,x2,x3,x4) - -#include -#define ML_POSINF R_PosInf -#define ML_NEGINF R_NegInf -#define ML_NAN R_NaN - - -void R_CheckUserInterrupt(void); -/* Ei-ji Nakama reported that AIX 5.2 has calloc as a macro and objected - to redefining it. Tests added for 2.2.1 */ -#ifdef calloc -# undef calloc -#endif -#define calloc R_chk_calloc -#ifdef free -# undef free -#endif -#define free R_chk_free - -#ifdef ENABLE_NLS -#include -#define _(String) gettext (String) -#else -#define _(String) (String) -#endif - -#else -/* Mathlib standalone */ - -#include -#include /* for exit */ -#define MATHLIB_ERROR(fmt,x) { printf(fmt,x); exit(1); } -#define MATHLIB_WARNING(fmt,x) printf(fmt,x) -#define MATHLIB_WARNING2(fmt,x,x2) printf(fmt,x,x2) -#define MATHLIB_WARNING3(fmt,x,x2,x3) printf(fmt,x,x2,x3) -#define MATHLIB_WARNING4(fmt,x,x2,x3,x4) printf(fmt,x,x2,x3,x4) - -#define ISNAN(x) (isnan(x)!=0) -#define R_FINITE(x) R_finite(x) -int R_finite(double); - -#define ML_POSINF (1.0 / 0.0) -#define ML_NEGINF ((-1.0) / 0.0) -#define ML_NAN (0.0 / 0.0) - -#define _(String) String -#endif /* standalone */ - -#define ML_VALID(x) (!ISNAN(x)) - -#define ME_NONE 0 -/* no error */ -#define ME_DOMAIN 1 -/* argument out of domain */ -#define ME_RANGE 2 -/* value out of range */ -#define ME_NOCONV 4 -/* process did not converge */ -#define ME_PRECISION 8 -/* does not have "full" precision */ -#define ME_UNDERFLOW 16 -/* and underflow occured (important for IEEE)*/ - -#define ML_ERR_return_NAN { ML_ERROR(ME_DOMAIN, ""); return ML_NAN; } - -/* For a long time prior to R 2.3.0 ML_ERROR did nothing. - We don't report ME_DOMAIN errors as the callers collect ML_NANs into - a single warning. - */ -#define ML_ERROR(x, s) { \ - if(x > ME_DOMAIN) { \ - char *msg = ""; \ - switch(x) { \ - case ME_DOMAIN: \ - msg = _("argument out of domain in '%s'\n"); \ - break; \ - case ME_RANGE: \ - msg = _("value out of range in '%s'\n"); \ - break; \ - case ME_NOCONV: \ - msg = _("convergence failed in '%s'\n"); \ - break; \ - case ME_PRECISION: \ - msg = _("full precision may not have been achieved in '%s'\n"); \ - break; \ - case ME_UNDERFLOW: \ - msg = _("underflow occurred in '%s'\n"); \ - break; \ - } \ - MATHLIB_WARNING(msg, s); \ - } \ -} - -/* Wilcoxon Rank Sum Distribution */ - -#define WILCOX_MAX 50 - -#ifdef HAVE_VISIBILITY_ATTRIBUTE -# define attribute_hidden __attribute__ ((visibility ("hidden"))) -#else -# define attribute_hidden -#endif - -/* Formerly private part of Mathlib.h */ - -/* always remap internal functions */ -#define bd0 Rf_bd0 -#define chebyshev_eval Rf_chebyshev_eval -#define chebyshev_init Rf_chebyshev_init -#define gammalims Rf_gammalims -#define lfastchoose Rf_lfastchoose -#define lgammacor Rf_lgammacor -#define stirlerr Rf_stirlerr -/* in Rmath.h -#define gamma_cody Rf_gamma_cody -*/ - - /* Chebyshev Series */ - -int attribute_hidden chebyshev_init(double*, int, double); -double attribute_hidden chebyshev_eval(double, const double *, const int); - - /* Gamma and Related Functions */ - -void attribute_hidden gammalims(double*, double*); -double attribute_hidden lgammacor(double); /* log(gamma) correction */ -double attribute_hidden stirlerr(double); /* Stirling expansion "error" */ - -double attribute_hidden lfastchoose(double, double); - -double attribute_hidden bd0(double, double); - -double attribute_hidden dbinom_raw(double, double, double, double, int); -double attribute_hidden dpois_raw (double, double, int); -double attribute_hidden pnchisq_raw(double, double, double, double, double, int, Rboolean); -double attribute_hidden pgamma_raw(double, double, int, int); -double attribute_hidden pbeta_raw(double, double, double, int, int); -double attribute_hidden qchisq_appr(double, double, double, int, int, double tol); -long double attribute_hidden pnbeta_raw(double, double, double, double, double); -double attribute_hidden pnbeta2(double, double, double, double, double, int, int); - -int Rf_i1mach(int); - -/* From toms708.c */ -void attribute_hidden bratio(double a, double b, double x, double y, - double *w, double *w1, int *ierr, int log_p); - - -#endif /* MATHLIB_PRIVATE_H */ diff --git a/deps/Rmath/src/pbeta.c b/deps/Rmath/src/pbeta.c deleted file mode 100644 index 52d5c58312f8a..0000000000000 --- a/deps/Rmath/src/pbeta.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 2006 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * - * double pbeta_raw(double x, double pin, double qin, int lower_tail, int log_p) - * double pbeta (double x, double pin, double qin, int lower_tail, int log_p) - * - * DESCRIPTION - * - * Returns distribution function of the beta distribution. - * ( = The incomplete beta ratio I_x(p,q) ). - * - * NOTES - * - * As from R 2.3.0, a wrapper for TOMS708 - * as from R 2.6.0, 'log_p' partially improved over log(p..) - */ - -#include "nmath.h" -#include "dpq.h" - -attribute_hidden -double pbeta_raw(double x, double pin, double qin, int lower_tail, int log_p) -{ - double x1 = 0.5 - x + 0.5, w, wc; - int ierr; - bratio(pin, qin, x, x1, &w, &wc, &ierr, log_p); /* -> ./toms708.c */ - /* ierr = 8 is about inaccuracy in extreme cases */ - if(ierr && (ierr != 8 || log_p) ) - MATHLIB_WARNING(_("pbeta_raw() -> bratio() gave error code %d"), ierr); - return lower_tail ? w : wc; -} /* pbeta_raw() */ - -double pbeta(double x, double pin, double qin, int lower_tail, int log_p) -{ -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(pin) || ISNAN(qin)) return x + pin + qin; -#endif - - if (pin <= 0 || qin <= 0) ML_ERR_return_NAN; - - if (x <= 0) - return R_DT_0; - if (x >= 1) - return R_DT_1; - return pbeta_raw(x, pin, qin, lower_tail, log_p); -} diff --git a/deps/Rmath/src/pbinom.c b/deps/Rmath/src/pbinom.c deleted file mode 100644 index dc6e837a0087b..0000000000000 --- a/deps/Rmath/src/pbinom.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000-6 The R Development Core Team - * Copyright (C) 2004 The R Foundation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * DESCRIPTION - * - * The distribution function of the binomial distribution. - */ -#include "nmath.h" -#include "dpq.h" - -double pbinom(double x, double n, double p, int lower_tail, int log_p) -{ -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(n) || ISNAN(p)) - return x + n + p; - if (!R_FINITE(n) || !R_FINITE(p)) ML_ERR_return_NAN; - -#endif - if(R_D_nonint(n)) ML_ERR_return_NAN; - n = R_D_forceint(n); - /* PR#8560: n=0 is a valid value */ - if(n < 0 || p < 0 || p > 1) ML_ERR_return_NAN; - - if (x < 0) return R_DT_0; - x = floor(x + 1e-7); - if (n <= x) return R_DT_1; - return pbeta(p, x + 1, n - x, !lower_tail, log_p); -} diff --git a/deps/Rmath/src/pcauchy.c b/deps/Rmath/src/pcauchy.c deleted file mode 100644 index 6b8d3843d2a00..0000000000000 --- a/deps/Rmath/src/pcauchy.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000 The R Development Core Team - * Copyright (C) 2004 The R Foundation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * DESCRIPTION - * - * The distribution function of the Cauchy distribution. - */ - -#include "nmath.h" -#include "dpq.h" - -double pcauchy(double x, double location, double scale, - int lower_tail, int log_p) -{ -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(location) || ISNAN(scale)) - return x + location + scale; -#endif - if (scale <= 0) ML_ERR_return_NAN; - - x = (x - location) / scale; - if (ISNAN(x)) ML_ERR_return_NAN; -#ifdef IEEE_754 - if(!R_FINITE(x)) { - if(x < 0) return R_DT_0; - else return R_DT_1; - } -#endif - if (!lower_tail) - x = -x; - /* for large x, the standard formula suffers from cancellation. - * This is from Morten Welinder thanks to Ian Smith's atan(1/x) : */ - if (fabs(x) > 1) { - double y = atan(1/x) / M_PI; - return (x > 0) ? R_D_Clog(y) : R_D_val(-y); - } else - return R_D_val(0.5 + atan(x) / M_PI); -} diff --git a/deps/Rmath/src/pchisq.c b/deps/Rmath/src/pchisq.c deleted file mode 100644 index 7025e86cbee87..0000000000000 --- a/deps/Rmath/src/pchisq.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * DESCRIPTION - * - * The distribution function of the chi-squared distribution. - */ - -#include "nmath.h" -#include "dpq.h" - -double pchisq(double x, double df, int lower_tail, int log_p) -{ - return pgamma(x, df/2., 2., lower_tail, log_p); -} diff --git a/deps/Rmath/src/pexp.c b/deps/Rmath/src/pexp.c deleted file mode 100644 index 2345a9963c665..0000000000000 --- a/deps/Rmath/src/pexp.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000-2002 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * DESCRIPTION - * - * The distribution function of the exponential distribution. - */ -#include "nmath.h" -#include "dpq.h" - -double pexp(double x, double scale, int lower_tail, int log_p) -{ -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(scale)) - return x + scale; - if (scale < 0) ML_ERR_return_NAN; -#else - if (scale <= 0) ML_ERR_return_NAN; -#endif - - if (x <= 0.) - return R_DT_0; - /* same as weibull( shape = 1): */ - x = -(x / scale); - if (lower_tail) - return (log_p - /* log(1 - exp(x)) for x < 0 : */ - ? (x > -M_LN2 ? log(-expm1(x)) : log1p(-exp(x))) - : -expm1(x)); - /* else: !lower_tail */ - return R_D_exp(x); -} diff --git a/deps/Rmath/src/pf.c b/deps/Rmath/src/pf.c deleted file mode 100644 index 6bfbfb57746b3..0000000000000 --- a/deps/Rmath/src/pf.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000-8 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * DESCRIPTION - * - * The distribution function of the F distribution. - */ - -#include "nmath.h" -#include "dpq.h" - -double pf(double x, double df1, double df2, int lower_tail, int log_p) -{ -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(df1) || ISNAN(df2)) - return x + df2 + df1; -#endif - if (df1 <= 0. || df2 <= 0.) ML_ERR_return_NAN; - - R_P_bounds_01(x, 0., ML_POSINF); - - /* move to pchisq for very large values - was 'df1 > 4e5' in 2.0.x, - now only needed for df1 = Inf or df2 = Inf {since pbeta(0,*)=0} : */ - if (df2 == ML_POSINF) { - if (df1 == ML_POSINF) { - if(x < 1.) return R_DT_0; - if(x == 1.) return (log_p ? -M_LN2 : 0.5); - if(x > 1.) return R_DT_1; - } - - return pchisq(x * df1, df1, lower_tail, log_p); - } - - if (df1 == ML_POSINF)/* was "fudge" 'df1 > 4e5' in 2.0.x */ - return pchisq(df2 / x , df2, !lower_tail, log_p); - - /* Avoid squeezing pbeta's first parameter against 1 : */ - if (df1 * x > df2) - x = pbeta(df2 / (df2 + df1 * x), df2 / 2., df1 / 2., - !lower_tail, log_p); - else - x = pbeta(df1 * x / (df2 + df1 * x), df1 / 2., df2 / 2., - lower_tail, log_p); - - return ML_VALID(x) ? x : ML_NAN; -} diff --git a/deps/Rmath/src/pgamma.c b/deps/Rmath/src/pgamma.c deleted file mode 100644 index 8083b7fcc3db8..0000000000000 --- a/deps/Rmath/src/pgamma.c +++ /dev/null @@ -1,881 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 2005-6 Morten Welinder - * Copyright (C) 2005-10 The R Foundation - * Copyright (C) 2006-10 The R Core Development Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * - * double pgamma (double x, double alph, double scale, - * int lower_tail, int log_p) - * - * double log1pmx (double x) - * double lgamma1p (double a) - * - * double logspace_add (double logx, double logy) - * double logspace_sub (double logx, double logy) - * - * - * DESCRIPTION - * - * This function computes the distribution function for the - * gamma distribution with shape parameter alph and scale parameter - * scale. This is also known as the incomplete gamma function. - * See Abramowitz and Stegun (6.5.1) for example. - * - * NOTES - * - * Complete redesign by Morten Welinder, originally for Gnumeric. - * Improvements (e.g. "while NEEDED_SCALE") by Martin Maechler - * The old version can be activated by compiling with -DR_USE_OLD_PGAMMA - * - * REFERENCES - * - */ - -#include "nmath.h" -#include "dpq.h" -/*----------- DEBUGGING ------------- - * make CFLAGS='-DDEBUG_p -g -I/usr/local/include -I../include' - * (cd ~/R/D/r-devel/Linux-inst/src/nmath; gcc -std=gnu99 -I. -I../../src/include -I../../../R/src/include -I/usr/local/include -DDEBUG_p -g -O2 -c ../../../R/src/nmath/pgamma.c -o pgamma.o) - */ - -/* Scalefactor:= (2^32)^8 = 2^256 = 1.157921e+77 */ -#define SQR(x) ((x)*(x)) -static const double scalefactor = SQR(SQR(SQR(4294967296.0))); -#undef SQR - -/* If |x| > |k| * M_cutoff, then log[ exp(-x) * k^x ] =~= -x */ -static const double M_cutoff = M_LN2 * DBL_MAX_EXP / DBL_EPSILON;/*=3.196577e18*/ - -/* Continued fraction for calculation of - * 1/i + x/(i+d) + x^2/(i+2*d) + x^3/(i+3*d) + ... = sum_{k=0}^Inf x^k/(i+k*d) - * - * auxilary in log1pmx() and lgamma1p() - */ -static double -logcf (double x, double i, double d, - double eps /* ~ relative tolerance */) -{ - double c1 = 2 * d; - double c2 = i + d; - double c4 = c2 + d; - double a1 = c2; - double b1 = i * (c2 - i * x); - double b2 = d * d * x; - double a2 = c4 * c2 - b2; - -#if 0 - assert (i > 0); - assert (d >= 0); -#endif - - b2 = c4 * b1 - i * b2; - - while (fabs(a2 * b1 - a1 * b2) > fabs(eps * b1 * b2)) { - double c3 = c2*c2*x; - c2 += d; - c4 += d; - a1 = c4 * a2 - c3 * a1; - b1 = c4 * b2 - c3 * b1; - - c3 = c1 * c1 * x; - c1 += d; - c4 += d; - a2 = c4 * a1 - c3 * a2; - b2 = c4 * b1 - c3 * b2; - - if (fabs (b2) > scalefactor) { - a1 /= scalefactor; - b1 /= scalefactor; - a2 /= scalefactor; - b2 /= scalefactor; - } else if (fabs (b2) < 1 / scalefactor) { - a1 *= scalefactor; - b1 *= scalefactor; - a2 *= scalefactor; - b2 *= scalefactor; - } - } - - return a2 / b2; -} - -/* Accurate calculation of log(1+x)-x, particularly for small x. */ -double log1pmx (double x) -{ - static const double minLog1Value = -0.79149064; - - if (x > 1 || x < minLog1Value) - return log1p(x) - x; - else { /* -.791 <= x <= 1 -- expand in [x/(2+x)]^2 =: y : - * log(1+x) - x = x/(2+x) * [ 2 * y * S(y) - x], with - * --------------------------------------------- - * S(y) = 1/3 + y/5 + y^2/7 + ... = \sum_{k=0}^\infty y^k / (2k + 3) - */ - double r = x / (2 + x), y = r * r; - if (fabs(x) < 1e-2) { - static const double two = 2; - return r * ((((two / 9 * y + two / 7) * y + two / 5) * y + - two / 3) * y - x); - } else { - static const double tol_logcf = 1e-14; - return r * (2 * y * logcf (y, 3, 2, tol_logcf) - x); - } - } -} - - -/* Compute log(gamma(a+1)) accurately also for small a (0 < a < 0.5). */ -double lgamma1p (double a) -{ - const double eulers_const = 0.5772156649015328606065120900824024; - - /* coeffs[i] holds (zeta(i+2)-1)/(i+2) , i = 0:(N-1), N = 40 : */ - const int N = 40; - static const double coeffs[40] = { - 0.3224670334241132182362075833230126e-0,/* = (zeta(2)-1)/2 */ - 0.6735230105319809513324605383715000e-1,/* = (zeta(3)-1)/3 */ - 0.2058080842778454787900092413529198e-1, - 0.7385551028673985266273097291406834e-2, - 0.2890510330741523285752988298486755e-2, - 0.1192753911703260977113935692828109e-2, - 0.5096695247430424223356548135815582e-3, - 0.2231547584535793797614188036013401e-3, - 0.9945751278180853371459589003190170e-4, - 0.4492623673813314170020750240635786e-4, - 0.2050721277567069155316650397830591e-4, - 0.9439488275268395903987425104415055e-5, - 0.4374866789907487804181793223952411e-5, - 0.2039215753801366236781900709670839e-5, - 0.9551412130407419832857179772951265e-6, - 0.4492469198764566043294290331193655e-6, - 0.2120718480555466586923135901077628e-6, - 0.1004322482396809960872083050053344e-6, - 0.4769810169363980565760193417246730e-7, - 0.2271109460894316491031998116062124e-7, - 0.1083865921489695409107491757968159e-7, - 0.5183475041970046655121248647057669e-8, - 0.2483674543802478317185008663991718e-8, - 0.1192140140586091207442548202774640e-8, - 0.5731367241678862013330194857961011e-9, - 0.2759522885124233145178149692816341e-9, - 0.1330476437424448948149715720858008e-9, - 0.6422964563838100022082448087644648e-10, - 0.3104424774732227276239215783404066e-10, - 0.1502138408075414217093301048780668e-10, - 0.7275974480239079662504549924814047e-11, - 0.3527742476575915083615072228655483e-11, - 0.1711991790559617908601084114443031e-11, - 0.8315385841420284819798357793954418e-12, - 0.4042200525289440065536008957032895e-12, - 0.1966475631096616490411045679010286e-12, - 0.9573630387838555763782200936508615e-13, - 0.4664076026428374224576492565974577e-13, - 0.2273736960065972320633279596737272e-13, - 0.1109139947083452201658320007192334e-13/* = (zeta(40+1)-1)/(40+1) */ - }; - - const double c = 0.2273736845824652515226821577978691e-12;/* zeta(N+2)-1 */ - const double tol_logcf = 1e-14; - double lgam; - int i; - - if (fabs (a) >= 0.5) - return lgammafn (a + 1); - - /* Abramowitz & Stegun 6.1.33 : for |x| < 2, - * <==> log(gamma(1+x)) = -(log(1+x) - x) - gamma*x + x^2 * \sum_{n=0}^\infty c_n (-x)^n - * where c_n := (Zeta(n+2) - 1)/(n+2) = coeffs[n] - * - * Here, another convergence acceleration trick is used to compute - * lgam(x) := sum_{n=0..Inf} c_n (-x)^n - */ - lgam = c * logcf(-a / 2, N + 2, 1, tol_logcf); - for (i = N - 1; i >= 0; i--) - lgam = coeffs[i] - a * lgam; - - return (a * lgam - eulers_const) * a - log1pmx (a); -} /* lgamma1p */ - - - -/* - * Compute the log of a sum from logs of terms, i.e., - * - * log (exp (logx) + exp (logy)) - * - * without causing overflows and without throwing away large handfuls - * of accuracy. - */ -double logspace_add (double logx, double logy) -{ - return fmax2 (logx, logy) + log1p (exp (-fabs (logx - logy))); -} - - -/* - * Compute the log of a difference from logs of terms, i.e., - * - * log (exp (logx) - exp (logy)) - * - * without causing overflows and without throwing away large handfuls - * of accuracy. - */ -double logspace_sub (double logx, double logy) -{ - return logx + R_Log1_Exp(logy - logx); -} - - -#ifndef R_USE_OLD_PGAMMA - -/* dpois_wrap (x_P_1, lambda, g_log) == - * dpois (x_P_1 - 1, lambda, g_log) := exp(-L) L^k / gamma(k+1) , k := x_P_1 - 1 -*/ -static double -dpois_wrap (double x_plus_1, double lambda, int give_log) -{ -#ifdef DEBUG_p - REprintf (" dpois_wrap(x+1=%.14g, lambda=%.14g, log=%d)\n", - x_plus_1, lambda, give_log); -#endif - if (!R_FINITE(lambda)) - return R_D__0; - if (x_plus_1 > 1) - return dpois_raw (x_plus_1 - 1, lambda, give_log); - if (lambda > fabs(x_plus_1 - 1) * M_cutoff) - return R_D_exp(-lambda - lgammafn(x_plus_1)); - else { - double d = dpois_raw (x_plus_1, lambda, give_log); -#ifdef DEBUG_p - REprintf (" -> d=dpois_raw(..)=%.14g\n", d); -#endif - return give_log - ? d + log (x_plus_1 / lambda) - : d * (x_plus_1 / lambda); - } -} - -/* - * Abramowitz and Stegun 6.5.29 [right] - */ -static double -pgamma_smallx (double x, double alph, int lower_tail, int log_p) -{ - double sum = 0, c = alph, n = 0, term; - -#ifdef DEBUG_p - REprintf (" pg_smallx(x=%.12g, alph=%.12g): ", x, alph); -#endif - - /* - * Relative to 6.5.29 all terms have been multiplied by alph - * and the first, thus being 1, is omitted. - */ - - do { - n++; - c *= -x / n; - term = c / (alph + n); - sum += term; - } while (fabs (term) > DBL_EPSILON * fabs (sum)); - -#ifdef DEBUG_p - REprintf (" %d terms --> conv.sum=%g;", n, sum); -#endif - if (lower_tail) { - double f1 = log_p ? log1p (sum) : 1 + sum; - double f2; - if (alph > 1) { - f2 = dpois_raw (alph, x, log_p); - f2 = log_p ? f2 + x : f2 * exp (x); - } else if (log_p) - f2 = alph * log (x) - lgamma1p (alph); - else - f2 = pow (x, alph) / exp (lgamma1p (alph)); -#ifdef DEBUG_p - REprintf (" (f1,f2)= (%g,%g)\n", f1,f2); -#endif - return log_p ? f1 + f2 : f1 * f2; - } else { - double lf2 = alph * log (x) - lgamma1p (alph); -#ifdef DEBUG_p - REprintf (" 1:%.14g 2:%.14g\n", alph * log (x), lgamma1p (alph)); - REprintf (" sum=%.14g log(1+sum)=%.14g lf2=%.14g\n", - sum, log1p (sum), lf2); -#endif - if (log_p) - return R_Log1_Exp (log1p (sum) + lf2); - else { - double f1m1 = sum; - double f2m1 = expm1 (lf2); - return -(f1m1 + f2m1 + f1m1 * f2m1); - } - } -} /* pgamma_smallx() */ - -static double -pd_upper_series (double x, double y, int log_p) -{ - double term = x / y; - double sum = term; - - do { - y++; - term *= x / y; - sum += term; - } while (term > sum * DBL_EPSILON); - - /* sum = \sum_{n=1}^ oo x^n / (y*(y+1)*...*(y+n-1)) - * = \sum_{n=0}^ oo x^(n+1) / (y*(y+1)*...*(y+n)) - * = x/y * (1 + \sum_{n=1}^oo x^n / ((y+1)*...*(y+n))) - * ~ x/y + o(x/y) {which happens when alph -> Inf} - */ - return log_p ? log (sum) : sum; -} - -/* Continued fraction for calculation of - * scaled upper-tail F_{gamma} - * ~= (y / d) * [1 + (1-y)/d + O( ((1-y)/d)^2 ) ] - */ -static double -pd_lower_cf (double y, double d) -{ - double f= 0.0 /* -Wall */, of, f0; - double i, c2, c3, c4, a1, b1, a2, b2; - -#define NEEDED_SCALE \ - (b2 > scalefactor) { \ - a1 /= scalefactor; \ - b1 /= scalefactor; \ - a2 /= scalefactor; \ - b2 /= scalefactor; \ - } - -#define max_it 200000 - -#ifdef DEBUG_p - REprintf("pd_lower_cf(y=%.14g, d=%.14g)", y, d); -#endif - if (y == 0) return 0; - - f0 = y/d; - /* Needed, e.g. for pgamma(10^c(100,295), shape= 1.1, log=TRUE): */ - if(fabs(y - 1) < fabs(d) * DBL_EPSILON) { /* includes y < d = Inf */ -#ifdef DEBUG_p - REprintf(" very small 'y' -> returning (y/d)\n"); -#endif - return (f0); - } - - if(f0 > 1.) f0 = 1.; - c2 = y; - c4 = d; /* original (y,d), *not* potentially scaled ones!*/ - - a1 = 0; b1 = 1; - a2 = y; b2 = d; - - while NEEDED_SCALE - - i = 0; of = -1.; /* far away */ - while (i < max_it) { - - i++; c2--; c3 = i * c2; c4 += 2; - /* c2 = y - i, c3 = i(y - i), c4 = d + 2i, for i odd */ - a1 = c4 * a2 + c3 * a1; - b1 = c4 * b2 + c3 * b1; - - i++; c2--; c3 = i * c2; c4 += 2; - /* c2 = y - i, c3 = i(y - i), c4 = d + 2i, for i even */ - a2 = c4 * a1 + c3 * a2; - b2 = c4 * b1 + c3 * b2; - - if NEEDED_SCALE - - if (b2 != 0) { - f = a2 / b2; - /* convergence check: relative; "absolute" for very small f : */ - if (fabs (f - of) <= DBL_EPSILON * fmax2(f0, fabs(f))) { -#ifdef DEBUG_p - REprintf(" %g iter.\n", i); -#endif - return f; - } - of = f; - } - } - - MATHLIB_WARNING(" ** NON-convergence in pgamma()'s pd_lower_cf() f= %g.\n", - f); - return f;/* should not happen ... */ -} /* pd_lower_cf() */ -#undef NEEDED_SCALE - - -static double -pd_lower_series (double lambda, double y) -{ - double term = 1, sum = 0; - -#ifdef DEBUG_p - REprintf("pd_lower_series(lam=%.14g, y=%.14g) ...", lambda, y); -#endif - while (y >= 1 && term > sum * DBL_EPSILON) { - term *= y / lambda; - sum += term; - y--; - } - /* sum = \sum_{n=0}^ oo y*(y-1)*...*(y - n) / lambda^(n+1) - * = y/lambda * (1 + \sum_{n=1}^Inf (y-1)*...*(y-n) / lambda^n) - * ~ y/lambda + o(y/lambda) - */ -#ifdef DEBUG_p - REprintf(" done: term=%g, sum=%g, y= %g\n", term, sum, y); -#endif - - if (y != floor (y)) { - /* - * The series does not converge as the terms start getting - * bigger (besides flipping sign) for y < -lambda. - */ - double f; -#ifdef DEBUG_p - REprintf(" y not int: add another term "); -#endif - /* FIXME: in quite few cases, adding term*f has no effect (f too small) - * and is unnecessary e.g. for pgamma(4e12, 121.1) */ - f = pd_lower_cf (y, lambda + 1 - y); -#ifdef DEBUG_p - REprintf(" (= %.14g) * term = %.14g to sum %g\n", f, term * f, sum); -#endif - sum += term * f; - } - - return sum; -} /* pd_lower_series() */ - -/* - * Compute the following ratio with higher accuracy that would be had - * from doing it directly. - * - * dnorm (x, 0, 1, FALSE) - * ---------------------------------- - * pnorm (x, 0, 1, lower_tail, FALSE) - * - * Abramowitz & Stegun 26.2.12 - */ -static double -dpnorm (double x, int lower_tail, double lp) -{ - /* - * So as not to repeat a pnorm call, we expect - * - * lp == pnorm (x, 0, 1, lower_tail, TRUE) - * - * but use it only in the non-critical case where either x is small - * or p==exp(lp) is close to 1. - */ - - if (x < 0) { - x = -x; - lower_tail = !lower_tail; - } - - if (x > 10 && !lower_tail) { - double term = 1 / x; - double sum = term; - double x2 = x * x; - double i = 1; - - do { - term *= -i / x2; - sum += term; - i += 2; - } while (fabs (term) > DBL_EPSILON * sum); - - return 1 / sum; - } else { - double d = dnorm (x, 0, 1, FALSE); - return d / exp (lp); - } -} - -/* - * Asymptotic expansion to calculate the probability that Poisson variate - * has value <= x. - * Various assertions about this are made (without proof) at - * http://members.aol.com/iandjmsmith/PoissonApprox.htm - */ -static double -ppois_asymp (double x, double lambda, int lower_tail, int log_p) -{ - static const double coefs_a[8] = { - -1e99, /* placeholder used for 1-indexing */ - 2/3., - -4/135., - 8/2835., - 16/8505., - -8992/12629925., - -334144/492567075., - 698752/1477701225. - }; - - static const double coefs_b[8] = { - -1e99, /* placeholder */ - 1/12., - 1/288., - -139/51840., - -571/2488320., - 163879/209018880., - 5246819/75246796800., - -534703531/902961561600. - }; - - double elfb, elfb_term; - double res12, res1_term, res1_ig, res2_term, res2_ig; - double dfm, pt_, s2pt, f, np; - int i; - - dfm = lambda - x; - /* If lambda is large, the distribution is highly concentrated - about lambda. So representation error in x or lambda can lead - to arbitrarily large values of pt_ and hence divergence of the - coefficients of this approximation. - */ - pt_ = - log1pmx (dfm / x); - s2pt = sqrt (2 * x * pt_); - if (dfm < 0) s2pt = -s2pt; - - res12 = 0; - res1_ig = res1_term = sqrt (x); - res2_ig = res2_term = s2pt; - for (i = 1; i < 8; i++) { - res12 += res1_ig * coefs_a[i]; - res12 += res2_ig * coefs_b[i]; - res1_term *= pt_ / i ; - res2_term *= 2 * pt_ / (2 * i + 1); - res1_ig = res1_ig / x + res1_term; - res2_ig = res2_ig / x + res2_term; - } - - elfb = x; - elfb_term = 1; - for (i = 1; i < 8; i++) { - elfb += elfb_term * coefs_b[i]; - elfb_term /= x; - } - if (!lower_tail) elfb = -elfb; -#ifdef DEBUG_p - REprintf ("res12 = %.14g elfb=%.14g\n", elfb, res12); -#endif - - f = res12 / elfb; - - np = pnorm (s2pt, 0.0, 1.0, !lower_tail, log_p); - - if (log_p) { - double n_d_over_p = dpnorm (s2pt, !lower_tail, np); -#ifdef DEBUG_p - REprintf ("pp*_asymp(): f=%.14g np=e^%.14g nd/np=%.14g f*nd/np=%.14g\n", - f, np, n_d_over_p, f * n_d_over_p); -#endif - return np + log1p (f * n_d_over_p); - } else { - double nd = dnorm (s2pt, 0., 1., log_p); - -#ifdef DEBUG_p - REprintf ("pp*_asymp(): f=%.14g np=%.14g nd=%.14g f*nd=%.14g\n", - f, np, nd, f * nd); -#endif - return np + f * nd; - } -} /* ppois_asymp() */ - - -double pgamma_raw (double x, double alph, int lower_tail, int log_p) -{ -/* Here, assume that (x,alph) are not NA & alph > 0 . */ - - double res; - -#ifdef DEBUG_p - REprintf("pgamma_raw(x=%.14g, alph=%.14g, low=%d, log=%d)\n", - x, alph, lower_tail, log_p); -#endif - R_P_bounds_01(x, 0., ML_POSINF); - - if (x < 1) { - res = pgamma_smallx (x, alph, lower_tail, log_p); - } else if (x <= alph - 1 && x < 0.8 * (alph + 50)) { - /* incl. large alph compared to x */ - double sum = pd_upper_series (x, alph, log_p);/* = x/alph + o(x/alph) */ - double d = dpois_wrap (alph, x, log_p); -#ifdef DEBUG_p - REprintf(" alph 'large': sum=pd_upper*()= %.12g, d=dpois_w(*)= %.12g\n", - sum, d); -#endif - if (!lower_tail) - res = log_p - ? R_Log1_Exp (d + sum) - : 1 - d * sum; - else - res = log_p ? sum + d : sum * d; - } else if (alph - 1 < x && alph < 0.8 * (x + 50)) { - /* incl. large x compared to alph */ - double sum; - double d = dpois_wrap (alph, x, log_p); -#ifdef DEBUG_p - REprintf(" x 'large': d=dpois_w(*)= %.14g ", d); -#endif - if (alph < 1) { - if (x * DBL_EPSILON > 1 - alph) - sum = R_D__1; - else { - double f = pd_lower_cf (alph, x - (alph - 1)) * x / alph; - /* = [alph/(x - alph+1) + o(alph/(x-alph+1))] * x/alph = 1 + o(1) */ - sum = log_p ? log (f) : f; - } - } else { - sum = pd_lower_series (x, alph - 1);/* = (alph-1)/x + o((alph-1)/x) */ - sum = log_p ? log1p (sum) : 1 + sum; - } -#ifdef DEBUG_p - REprintf(", sum= %.14g\n", sum); -#endif - if (!lower_tail) - res = log_p ? sum + d : sum * d; - else - res = log_p - ? R_Log1_Exp (d + sum) - : 1 - d * sum; - } else { /* x >= 1 and x fairly near alph. */ -#ifdef DEBUG_p - REprintf(" using ppois_asymp()\n"); -#endif - res = ppois_asymp (alph - 1, x, !lower_tail, log_p); - } - - /* - * We lose a fair amount of accuracy to underflow in the cases - * where the final result is very close to DBL_MIN. In those - * cases, simply redo via log space. - */ - if (!log_p && res < DBL_MIN / DBL_EPSILON) { - /* with(.Machine, double.xmin / double.eps) #|-> 1.002084e-292 */ -#ifdef DEBUG_p - REprintf(" very small res=%.14g; -> recompute via log\n", res); -#endif - return exp (pgamma_raw (x, alph, lower_tail, 1)); - } else - return res; -} - - -double pgamma(double x, double alph, double scale, int lower_tail, int log_p) -{ -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(alph) || ISNAN(scale)) - return x + alph + scale; -#endif - if(alph < 0. || scale <= 0.) - ML_ERR_return_NAN; - x /= scale; -#ifdef IEEE_754 - if (ISNAN(x)) /* eg. original x = scale = +Inf */ - return x; -#endif - if(alph == 0.) /* limit case; useful e.g. in pnchisq() */ - return (x <= 0) ? R_DT_0: R_DT_1; /* <= assert pgamma(0,0) ==> 0 */ - return pgamma_raw (x, alph, lower_tail, log_p); -} -/* From: terra@gnome.org (Morten Welinder) - * To: R-bugs@biostat.ku.dk - * Cc: maechler@stat.math.ethz.ch - * Subject: Re: [Rd] pgamma discontinuity (PR#7307) - * Date: Tue, 11 Jan 2005 13:57:26 -0500 (EST) - - * this version of pgamma appears to be quite good and certainly a vast - * improvement over current R code. (I last looked at 2.0.1) Apart from - * type naming, this is what I have been using for Gnumeric 1.4.1. - - * This could be included into R as-is, but you might want to benefit from - * making logcf, log1pmx, lgamma1p, and possibly logspace_add/logspace_sub - * available to other parts of R. - - * MM: I've not (yet?) taken logcf(), but the other four - */ - - -#else -/* R_USE_OLD_PGAMMA */ -/* - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 1999-2000 The R Development Core Team - * Copyright (C) 2003-2004 The R Foundation - * based on AS 239 (C) 1988 Royal Statistical Society - * - * ................ - * - * NOTES - * - * This function is an adaptation of Algorithm 239 from the - * Applied Statistics Series. The algorithm is faster than - * those by W. Fullerton in the FNLIB library and also the - * TOMS 542 alorithm of W. Gautschi. It provides comparable - * accuracy to those algorithms and is considerably simpler. - * - * REFERENCES - * - * Algorithm AS 239, Incomplete Gamma Function - * Applied Statistics 37, 1988. - */ - -/* now would need this here: */ -double attribute_hidden pgamma_raw(x, alph, lower_tail, log_p) { - return pgamma(x, alph, 1, lower_tail, log_p); -} - -double pgamma(double x, double alph, double scale, int lower_tail, int log_p) -{ - const static double - xbig = 1.0e+8, - xlarge = 1.0e+37, - - /* normal approx. for alph > alphlimit */ - alphlimit = 1e5;/* was 1000. till R.1.8.x */ - - double pn1, pn2, pn3, pn4, pn5, pn6, arg, a, b, c, an, osum, sum; - long n; - int pearson; - - /* check that we have valid values for x and alph */ - -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(alph) || ISNAN(scale)) - return x + alph + scale; -#endif -#ifdef DEBUG_p - REprintf("pgamma(x=%4g, alph=%4g, scale=%4g): ",x,alph,scale); -#endif - if(alph <= 0. || scale <= 0.) - ML_ERR_return_NAN; - - x /= scale; -#ifdef DEBUG_p - REprintf("-> x=%4g; ",x); -#endif -#ifdef IEEE_754 - if (ISNAN(x)) /* eg. original x = scale = Inf */ - return x; -#endif - if (x <= 0.) - return R_DT_0; - -#define USE_PNORM \ - pn1 = sqrt(alph) * 3. * (pow(x/alph, 1./3.) + 1. / (9. * alph) - 1.); \ - return pnorm(pn1, 0., 1., lower_tail, log_p); - - if (alph > alphlimit) { /* use a normal approximation */ - USE_PNORM; - } - - if (x > xbig * alph) { - if (x > DBL_MAX * alph) - /* if x is extremely large __compared to alph__ then return 1 */ - return R_DT_1; - else { /* this only "helps" when log_p = TRUE */ - USE_PNORM; - } - } - - if (x <= 1. || x < alph) { - - pearson = 1;/* use pearson's series expansion. */ - - arg = alph * log(x) - x - lgammafn(alph + 1.); -#ifdef DEBUG_p - REprintf("Pearson arg=%g ", arg); -#endif - c = 1.; - sum = 1.; - a = alph; - do { - a += 1.; - c *= x / a; - sum += c; - } while (c > DBL_EPSILON * sum); - } - else { /* x >= max( 1, alph) */ - - pearson = 0;/* use a continued fraction expansion */ - - arg = alph * log(x) - x - lgammafn(alph); -#ifdef DEBUG_p - REprintf("Cont.Fract. arg=%g ", arg); -#endif - a = 1. - alph; - b = a + x + 1.; - pn1 = 1.; - pn2 = x; - pn3 = x + 1.; - pn4 = x * b; - sum = pn3 / pn4; - for (n = 1; ; n++) { - a += 1.;/* = n+1 -alph */ - b += 2.;/* = 2(n+1)-alph+x */ - an = a * n; - pn5 = b * pn3 - an * pn1; - pn6 = b * pn4 - an * pn2; - if (fabs(pn6) > 0.) { - osum = sum; - sum = pn5 / pn6; - if (fabs(osum - sum) <= DBL_EPSILON * fmin2(1., sum)) - break; - } - pn1 = pn3; - pn2 = pn4; - pn3 = pn5; - pn4 = pn6; - if (fabs(pn5) >= xlarge) { - /* re-scale the terms in continued fraction if they are large */ -#ifdef DEBUG_p - REprintf(" [r] "); -#endif - pn1 /= xlarge; - pn2 /= xlarge; - pn3 /= xlarge; - pn4 /= xlarge; - } - } - } - - arg += log(sum); - - lower_tail = (lower_tail == pearson); - - if (log_p && lower_tail) - return(arg); - /* else */ - /* sum = exp(arg); and return if(lower_tail) sum else 1-sum : */ - return (lower_tail) ? exp(arg) : (log_p ? R_Log1_Exp(arg) : -expm1(arg)); -} - -#endif -/* R_USE_OLD_PGAMMA */ diff --git a/deps/Rmath/src/pgeom.c b/deps/Rmath/src/pgeom.c deleted file mode 100644 index fb9e83f41bc5d..0000000000000 --- a/deps/Rmath/src/pgeom.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000-2006 The R Development Core Team - * Copyright (C) 2004 The R Foundation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * DESCRIPTION - * - * The distribution function of the geometric distribution. - */ - -#include "nmath.h" -#include "dpq.h" - -double pgeom(double x, double p, int lower_tail, int log_p) -{ -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(p)) - return x + p; -#endif - if(p <= 0 || p > 1) ML_ERR_return_NAN; - - if (x < 0.) return R_DT_0; - if (!R_FINITE(x)) return R_DT_1; - x = floor(x +1e-7); - - if(p == 1.) { /* we cannot assume IEEE */ - x = lower_tail ? 1: 0; - return log_p ? log(x) : x; - } - x = log1p(-p) * (x + 1); - if (log_p) - return R_DT_Clog(x); - else - return lower_tail ? -expm1(x) : exp(x); -} diff --git a/deps/Rmath/src/phyper.c b/deps/Rmath/src/phyper.c deleted file mode 100644 index 860841434f7cc..0000000000000 --- a/deps/Rmath/src/phyper.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 1999-2000 The R Development Core Team - * Copyright (C) 2004 Morten Welinder - * Copyright (C) 2004 The R Foundation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * DESCRIPTION - * - * The distribution function of the hypergeometric distribution. - * - * Current implementation based on posting - * From: Morten Welinder - * Cc: R-bugs@biostat.ku.dk - * Subject: [Rd] phyper accuracy and efficiency (PR#6772) - * Date: Thu, 15 Apr 2004 18:06:37 +0200 (CEST) - ...... - - The current version has very serious cancellation issues. For example, - if you ask for a small right-tail you are likely to get total cancellation. - For example, phyper(59, 150, 150, 60, FALSE, FALSE) gives 6.372680161e-14. - The right answer is dhyper(0, 150, 150, 60, FALSE) which is 5.111204798e-22. - - phyper is also really slow for large arguments. - - Therefore, I suggest using the code below. This is a sniplet from Gnumeric ... - The code isn't perfect. In fact, if x*(NR+NB) is close to n*NR, - then this code can take a while. Not longer than the old code, though. - - -- Thanks to Ian Smith for ideas. -*/ - -#include "nmath.h" -#include "dpq.h" - -static double pdhyper (double x, double NR, double NB, double n, int log_p) -{ -/* - * Calculate - * - * phyper (x, NR, NB, n, TRUE, FALSE) - * [log] ---------------------------------- - * dhyper (x, NR, NB, n, FALSE) - * - * without actually calling phyper. This assumes that - * - * x * (NR + NB) <= n * NR - * - */ - long double sum = 0; - long double term = 1; - - while (x > 0 && term >= DBL_EPSILON * sum) { - term *= x * (NB - n + x) / (n + 1 - x) / (NR + 1 - x); - sum += term; - x--; - } - - return log_p ? log1p(sum) : 1 + sum; -} - - -/* FIXME: The old phyper() code was basically used in ./qhyper.c as well - * ----- We need to sync this again! -*/ -double phyper (double x, double NR, double NB, double n, - int lower_tail, int log_p) -{ -/* Sample of n balls from NR red and NB black ones; x are red */ - - double d, pd; - -#ifdef IEEE_754 - if(ISNAN(x) || ISNAN(NR) || ISNAN(NB) || ISNAN(n)) - return x + NR + NB + n; -#endif - - x = floor (x + 1e-7); - NR = R_D_forceint(NR); - NB = R_D_forceint(NB); - n = R_D_forceint(n); - - if (NR < 0 || NB < 0 || !R_FINITE(NR + NB) || n < 0 || n > NR + NB) - ML_ERR_return_NAN; - - if (x * (NR + NB) > n * NR) { - /* Swap tails. */ - double oldNB = NB; - NB = NR; - NR = oldNB; - x = n - x - 1; - lower_tail = !lower_tail; - } - - if (x < 0) - return R_DT_0; - if (x >= NR || x >= n) - return R_DT_1; - - d = dhyper (x, NR, NB, n, log_p); - pd = pdhyper(x, NR, NB, n, log_p); - - return log_p ? R_DT_Log(d + pd) : R_D_Lval(d * pd); -} diff --git a/deps/Rmath/src/plnorm.c b/deps/Rmath/src/plnorm.c deleted file mode 100644 index 44f871522c5a8..0000000000000 --- a/deps/Rmath/src/plnorm.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000-8 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * DESCRIPTION - * - * The lognormal distribution function. - */ - -#include "nmath.h" -#include "dpq.h" - -double plnorm(double x, double meanlog, double sdlog, int lower_tail, int log_p) -{ -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(meanlog) || ISNAN(sdlog)) - return x + meanlog + sdlog; -#endif - if (sdlog <= 0) ML_ERR_return_NAN; - - if (x > 0) - return pnorm(log(x), meanlog, sdlog, lower_tail, log_p); - return R_DT_0; -} diff --git a/deps/Rmath/src/plogis.c b/deps/Rmath/src/plogis.c deleted file mode 100644 index 27657126b8fe6..0000000000000 --- a/deps/Rmath/src/plogis.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * R : A Computer Language for Statistical Data Analysis - * Copyright (C) 1995, 1996 Robert Gentleman and Ross Ihaka - * Copyright (C) 2000 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - */ -#include "nmath.h" -#include "dpq.h" - -double plogis(double x, double location, double scale, - int lower_tail, int log_p) -{ -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(location) || ISNAN(scale)) - return x + location + scale; -#endif - if (scale <= 0.0) ML_ERR_return_NAN; - - x = (x - location) / scale; - if (ISNAN(x)) ML_ERR_return_NAN; - R_P_bounds_Inf_01(x); - - x = exp(lower_tail ? -x : x); - return (log_p ? -log1p(x) : 1 / (1 + x)); -} - diff --git a/deps/Rmath/src/pnbeta.c b/deps/Rmath/src/pnbeta.c deleted file mode 100644 index 88bedb754bac7..0000000000000 --- a/deps/Rmath/src/pnbeta.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2000-2008 The R Development Core Team - * - * Algorithm AS 226 Appl. Statist. (1987) Vol. 36, No. 2 - * Incorporates modification AS R84 from AS Vol. 39, pp311-2, 1990 - * and AS R95 from AS Vol. 44, pp551-2, 1995 - * original (C) Royal Statistical Society 1987, 1990, 1995 - * - * Returns the cumulative probability of x for the non-central - * beta distribution with parameters a, b and non-centrality ncp. - * - * Auxiliary routines required: - * lgamma - log-gamma function - * pbeta - incomplete-beta function {nowadays: pbeta_raw() -> bratio()} - */ - -#include "nmath.h" -#include "dpq.h" - -long double attribute_hidden -pnbeta_raw(double x, double o_x, double a, double b, double ncp) -{ - /* o_x == 1 - x but maybe more accurate */ - - /* change errmax and itrmax if desired; - * original (AS 226, R84) had (errmax; itrmax) = (1e-6; 100) */ - const static double errmax = 1.0e-9; - const int itrmax = 10000; /* 100 is not enough for pf(ncp=200) - see PR#11277 */ - - double a0, ax, lbeta, c, errbd, temp, x0, tmp_c; - int j, ierr; - - long double ans, gx, q, sumq; - - if (ncp < 0. || a <= 0. || b <= 0.) ML_ERR_return_NAN; - - if(x < 0. || o_x > 1. || (x == 0. && o_x == 1.)) return 0.; - if(x > 1. || o_x < 0. || (x == 1. && o_x == 0.)) return 1.; - - c = ncp / 2.; - - /* initialize the series */ - - x0 = floor(fmax2(c - 7. * sqrt(c), 0.)); - a0 = a + x0; - lbeta = lgammafn(a0) + lgammafn(b) - lgammafn(a0 + b); - /* temp = pbeta_raw(x, a0, b, TRUE, FALSE), but using (x, o_x): */ - bratio(a0, b, x, o_x, &temp, &tmp_c, &ierr, FALSE); - - gx = exp(a0 * log(x) + b * (x < .5 ? log1p(-x) : log(o_x)) - - lbeta - log(a0)); - if (a0 > a) - q = exp(-c + x0 * log(c) - lgammafn(x0 + 1.)); - else - q = exp(-c); - - sumq = 1. - q; - ans = ax = q * temp; - - /* recurse over subsequent terms until convergence is achieved */ - j = x0; - do { - j++; - temp -= gx; - gx *= x * (a + b + j - 1.) / (a + j); - q *= c / j; - sumq -= q; - ax = temp * q; - ans += ax; - errbd = (temp - gx) * sumq; - } - while (errbd > errmax && j < itrmax + x0); - - if (errbd > errmax) - ML_ERROR(ME_PRECISION, "pnbeta"); - if (j >= itrmax + x0) - ML_ERROR(ME_NOCONV, "pnbeta"); - - return ans; -} - -double attribute_hidden -pnbeta2(double x, double o_x, double a, double b, double ncp, - /* o_x == 1 - x but maybe more accurate */ - int lower_tail, int log_p) -{ - long double ans= pnbeta_raw(x, o_x, a,b, ncp); - - /* return R_DT_val(ans), but we want to warn about cancellation here */ - if(lower_tail) return log_p ? log(ans) : ans; - else { - if(ans > 1 - 1e-10) ML_ERROR(ME_PRECISION, "pnbeta"); - ans = fmin2(ans, 1.0); /* Precaution */ - return log_p ? log1p(-ans) : (1 - ans); - } -} - -double pnbeta(double x, double a, double b, double ncp, - int lower_tail, int log_p) -{ -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(a) || ISNAN(b) || ISNAN(ncp)) - return x + a + b + ncp; -#endif - - R_P_bounds_01(x, 0., 1.); - return pnbeta2(x, 1-x, a, b, ncp, lower_tail, log_p); -} diff --git a/deps/Rmath/src/pnbinom.c b/deps/Rmath/src/pnbinom.c deleted file mode 100644 index d894372f46d0f..0000000000000 --- a/deps/Rmath/src/pnbinom.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000-8 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * DESCRIPTION - * - * The distribution function of the negative binomial distribution. - * - * NOTES - * - * x = the number of failures before the n-th success - */ - -#include "nmath.h" -#include "dpq.h" - -double pnbinom(double x, double size, double prob, int lower_tail, int log_p) -{ -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(size) || ISNAN(prob)) - return x + size + prob; - if(!R_FINITE(size) || !R_FINITE(prob)) ML_ERR_return_NAN; -#endif - if (size <= 0 || prob <= 0 || prob > 1) ML_ERR_return_NAN; - - if (x < 0) return R_DT_0; - if (!R_FINITE(x)) return R_DT_1; - x = floor(x + 1e-7); - return pbeta(prob, size, x + 1, lower_tail, log_p); -} - -double pnbinom_mu(double x, double size, double mu, int lower_tail, int log_p) -{ -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(size) || ISNAN(mu)) - return x + size + mu; - if(!R_FINITE(size) || !R_FINITE(mu)) ML_ERR_return_NAN; -#endif - if (size <= 0 || mu < 0) ML_ERR_return_NAN; - - if (x < 0) return R_DT_0; - if (!R_FINITE(x)) return R_DT_1; - x = floor(x + 1e-7); - /* return - * pbeta(pr, size, x + 1, lower_tail, log_p); pr = size/(size + mu), 1-pr = mu/(size+mu) - * - *= pbeta_raw(pr, size, x + 1, lower_tail, log_p) - * x. pin qin - *= bratio (pin, qin, x., 1-x., &w, &wc, &ierr, log_p), and return w or wc .. - *= bratio (size, x+1, pr, 1-pr, &w, &wc, &ierr, log_p) */ - { - int ierr; - double w, wc; - bratio(size, x+1, size/(size+mu), mu/(size+mu), &w, &wc, &ierr, log_p); - if(ierr) - MATHLIB_WARNING(_("pnbinom_mu() -> bratio() gave error code %d"), ierr); - return lower_tail ? w : wc; - } -} diff --git a/deps/Rmath/src/pnchisq.c b/deps/Rmath/src/pnchisq.c deleted file mode 100644 index dacbb1be18f3b..0000000000000 --- a/deps/Rmath/src/pnchisq.c +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Algorithm AS 275 Appl.Statist. (1992), vol.41, no.2 - * original (C) 1992 Royal Statistical Society - * - * Computes the noncentral chi-squared distribution function with - * positive real degrees of freedom df and nonnegative noncentrality - * parameter ncp. pnchisq_raw is based on - * - * Ding, C. G. (1992) - * Algorithm AS275: Computing the non-central chi-squared - * distribution function. Appl.Statist., 41, 478-482. - - * Other parts - * Copyright (C) 2000-2009 The R Development Core Team - * Copyright (C) 2003-2009 The R Foundation - */ - -#include "nmath.h" -#include "dpq.h" - -/*----------- DEBUGGING ------------- - * - * make CFLAGS='-DDEBUG_pnch ....' - - * -- Feb.6, 2000 (R pre0.99); M.Maechler: still have - * bad precision & non-convergence in some cases (x ~= f, both LARGE) - */ - - -double pnchisq(double x, double df, double ncp, int lower_tail, int log_p) -{ - double ans; -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(df) || ISNAN(ncp)) - return x + df + ncp; - if (!R_FINITE(df) || !R_FINITE(ncp)) - ML_ERR_return_NAN; -#endif - - if (df < 0. || ncp < 0.) ML_ERR_return_NAN; - - ans = pnchisq_raw(x, df, ncp, 1e-12, 8*DBL_EPSILON, 1000000, lower_tail); - if(ncp >= 80) { - if(lower_tail) { - ans = fmin2(ans, 1.0); /* e.g., pchisq(555, 1.01, ncp = 80) */ - } else { /* !lower_tail */ - /* since we computed the other tail cancellation is likely */ - if(ans < 1e-10) ML_ERROR(ME_PRECISION, "pnchisq"); - ans = fmax2(ans, 0.0); /* Precaution PR#7099 */ - } - } - if (!log_p) return ans; - /* if ans is near one, we can do better using the other tail */ - if (ncp >= 80 || ans < 1 - 1e-8) return log(ans); - ans = pnchisq_raw(x, df, ncp, 1e-12, 8*DBL_EPSILON, 1000000, !lower_tail); - return log1p(-ans); -} - -double attribute_hidden -pnchisq_raw(double x, double f, double theta, - double errmax, double reltol, int itrmax, Rboolean lower_tail) -{ - double lam, x2, f2, term, bound, f_x_2n, f_2n; - double l_lam = -1., l_x = -1.; /* initialized for -Wall */ - int n; - Rboolean lamSml, tSml, is_r, is_b, is_it; - long double ans, u, v, t, lt, lu =-1; - - static const double _dbl_min_exp = M_LN2 * DBL_MIN_EXP; - /*= -708.3964 for IEEE double precision */ - - if (x <= 0.) { - if(x == 0. && f == 0.) - return lower_tail ? exp(-0.5*theta) : -expm1(-0.5*theta); - /* x < 0 or {x==0, f > 0} */ - return lower_tail ? 0. : 1.; - } - if(!R_FINITE(x)) return lower_tail ? 1. : 0.; - - /* This is principally for use from qnchisq */ -#ifndef MATHLIB_STANDALONE - R_CheckUserInterrupt(); -#endif - - if(theta < 80) { /* use 110 for Inf, as ppois(110, 80/2, lower.tail=FALSE) is 2e-20 */ - long double sum = 0, sum2 = 0, lambda = 0.5*theta, pr = exp(-lambda); - double ans; - int i; - /* we need to renormalize here: the result could be very close to 1 */ - for(i = 0; i < 110; pr *= lambda/++i) { - sum2 += pr; - sum += pr * pchisq(x, f+2*i, lower_tail, FALSE); - if (sum2 >= 1-1e-15) break; - } - ans = sum/sum2; - return ans; - } - - -#ifdef DEBUG_pnch - REprintf("pnchisq(x=%g, f=%g, theta=%g): ",x,f,theta); -#endif - lam = .5 * theta; - lamSml = (-lam < _dbl_min_exp); - if(lamSml) { - /* MATHLIB_ERROR( - "non centrality parameter (= %g) too large for current algorithm", - theta) */ - u = 0; - lu = -lam;/* == ln(u) */ - l_lam = log(lam); - } else { - u = exp(-lam); - } - - /* evaluate the first term */ - v = u; - x2 = .5 * x; - f2 = .5 * f; - f_x_2n = f - x; - -#ifdef DEBUG_pnch - REprintf("-- v=exp(-th/2)=%g, x/2= %g, f/2= %g\n",v,x2,f2); -#endif - - if(f2 * DBL_EPSILON > 0.125 && /* very large f and x ~= f: probably needs */ - fabs(t = x2 - f2) < /* another algorithm anyway */ - sqrt(DBL_EPSILON) * f2) { - /* evade cancellation error */ - /* t = exp((1 - t)*(2 - t/(f2 + 1))) / sqrt(2*M_PI*(f2 + 1));*/ - lt = (1 - t)*(2 - t/(f2 + 1)) - 0.5 * log(2*M_PI*(f2 + 1)); -#ifdef DEBUG_pnch - REprintf(" (case I) ==> "); -#endif - } - else { - /* Usual case 2: careful not to overflow .. : */ - lt = f2*log(x2) -x2 - lgammafn(f2 + 1); - } -#ifdef DEBUG_pnch - REprintf(" lt= %g", lt); -#endif - - tSml = (lt < _dbl_min_exp); - if(tSml) { - if (x > f + theta + 5* sqrt( 2*(f + 2*theta))) { - /* x > E[X] + 5* sigma(X) */ - return lower_tail ? 1. : 0.; /* FIXME: We could be more accurate than 0. */ - } /* else */ - l_x = log(x); - ans = term = t = 0.; - } - else { - t = exp(lt); -#ifdef DEBUG_pnch - REprintf(", t=exp(lt)= %g\n", t); -#endif - ans = term = v * t; - } - - for (n = 1, f_2n = f + 2., f_x_2n += 2.; ; n++, f_2n += 2, f_x_2n += 2) { -#ifdef DEBUG_pnch - REprintf("\n _OL_: n=%d",n); -#endif -#ifndef MATHLIB_STANDALONE - if(n % 1000) R_CheckUserInterrupt(); -#endif - /* f_2n === f + 2*n - * f_x_2n === f - x + 2*n > 0 <==> (f+2n) > x */ - if (f_x_2n > 0) { - /* find the error bound and check for convergence */ - - bound = t * x / f_x_2n; -#ifdef DEBUG_pnch - REprintf("\n L10: n=%d; term= %g; bound= %g",n,term,bound); -#endif - is_r = is_it = FALSE; - /* convergence only if BOTH absolute and relative error < 'bnd' */ - if (((is_b = (bound <= errmax)) && - (is_r = (term <= reltol * ans))) || (is_it = (n > itrmax))) - { -#ifdef DEBUG_pnch - REprintf("BREAK n=%d %s; bound= %g %s, rel.err= %g %s\n", - n, (is_it ? "> itrmax" : ""), - bound, (is_b ? "<= errmax" : ""), - term/ans, (is_r ? "<= reltol" : "")); -#endif - break; /* out completely */ - } - - } - - /* evaluate the next term of the */ - /* expansion and then the partial sum */ - - if(lamSml) { - lu += l_lam - log(n); /* u = u* lam / n */ - if(lu >= _dbl_min_exp) { - /* no underflow anymore ==> change regime */ -#ifdef DEBUG_pnch - REprintf(" n=%d; nomore underflow in u = exp(lu) ==> change\n", - n); -#endif - v = u = exp(lu); /* the first non-0 'u' */ - lamSml = FALSE; - } - } else { - u *= lam / n; - v += u; - } - if(tSml) { - lt += l_x - log(f_2n);/* t <- t * (x / f2n) */ - if(lt >= _dbl_min_exp) { - /* no underflow anymore ==> change regime */ -#ifdef DEBUG_pnch - REprintf(" n=%d; nomore underflow in t = exp(lt) ==> change\n", - n); -#endif - t = exp(lt); /* the first non-0 't' */ - tSml = FALSE; - } - } else { - t *= x / f_2n; - } - if(!lamSml && !tSml) { - term = v * t; - ans += term; - } - - } /* for(n ...) */ - - if (is_it) { - MATHLIB_WARNING2(_("pnchisq(x=%g, ..): not converged in %d iter."), - x, itrmax); - } -#ifdef DEBUG_pnch - REprintf("\n == L_End: n=%d; term= %g; bound=%g\n",n,term,bound); -#endif - return lower_tail ? ans : 1 - ans; -} diff --git a/deps/Rmath/src/pnf.c b/deps/Rmath/src/pnf.c deleted file mode 100644 index f8e3bb043370c..0000000000000 --- a/deps/Rmath/src/pnf.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000-8 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * DESCRIPTION - * - * The distribution function of the non-central F distribution. - */ - -#include "nmath.h" -#include "dpq.h" - -double pnf(double x, double df1, double df2, double ncp, - int lower_tail, int log_p) -{ - double y; -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(df1) || ISNAN(df2) || ISNAN(ncp)) - return x + df2 + df1 + ncp; -#endif - if (df1 <= 0. || df2 <= 0. || ncp < 0) ML_ERR_return_NAN; - if (!R_FINITE(ncp)) ML_ERR_return_NAN; - if (!R_FINITE(df1) && !R_FINITE(df2)) /* both +Inf */ - ML_ERR_return_NAN; - - R_P_bounds_01(x, 0., ML_POSINF); - - if (df2 > 1e8) /* avoid problems with +Inf and loss of accuracy */ - return pnchisq(x * df1, df1, ncp, lower_tail, log_p); - - y = (df1 / df2) * x; - return pnbeta2(y/(1. + y), 1./(1. + y), df1 / 2., df2 / 2., - ncp, lower_tail, log_p); -} diff --git a/deps/Rmath/src/pnorm.c b/deps/Rmath/src/pnorm.c deleted file mode 100644 index bf808d336f855..0000000000000 --- a/deps/Rmath/src/pnorm.c +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000-2010 The R Development Core Team - * Copyright (C) 2003 The R Foundation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * - * double pnorm5(double x, double mu, double sigma, int lower_tail,int log_p); - * {pnorm (..) is synonymous and preferred inside R} - * - * void pnorm_both(double x, double *cum, double *ccum, - * int i_tail, int log_p); - * - * DESCRIPTION - * - * The main computation evaluates near-minimax approximations derived - * from those in "Rational Chebyshev approximations for the error - * function" by W. J. Cody, Math. Comp., 1969, 631-637. This - * transportable program uses rational functions that theoretically - * approximate the normal distribution function to at least 18 - * significant decimal digits. The accuracy achieved depends on the - * arithmetic system, the compiler, the intrinsic functions, and - * proper selection of the machine-dependent constants. - * - * REFERENCE - * - * Cody, W. D. (1993). - * ALGORITHM 715: SPECFUN - A Portable FORTRAN Package of - * Special Function Routines and Test Drivers". - * ACM Transactions on Mathematical Software. 19, 22-32. - * - * EXTENSIONS - * - * The "_both" , lower, upper, and log_p variants were added by - * Martin Maechler, Jan.2000; - * as well as log1p() and similar improvements later on. - * - * James M. Rath contributed bug report PR#699 and patches correcting SIXTEN - * and if() clauses {with a bug: "|| instead of &&" -> PR #2883) more in line - * with the original Cody code. - */ - -#include "nmath.h" -#include "dpq.h" -double pnorm5(double x, double mu, double sigma, int lower_tail, int log_p) -{ - double p, cp; - - /* Note: The structure of these checks has been carefully thought through. - * For example, if x == mu and sigma == 0, we get the correct answer 1. - */ -#ifdef IEEE_754 - if(ISNAN(x) || ISNAN(mu) || ISNAN(sigma)) - return x + mu + sigma; -#endif - if(!R_FINITE(x) && mu == x) return ML_NAN;/* x-mu is NaN */ - if (sigma <= 0) { - if(sigma < 0) ML_ERR_return_NAN; - /* sigma = 0 : */ - return (x < mu) ? R_DT_0 : R_DT_1; - } - p = (x - mu) / sigma; - if(!R_FINITE(p)) - return (x < mu) ? R_DT_0 : R_DT_1; - x = p; - - pnorm_both(x, &p, &cp, (lower_tail ? 0 : 1), log_p); - - return(lower_tail ? p : cp); -} - -#define SIXTEN 16 /* Cutoff allowing exact "*" and "/" */ - -void pnorm_both(double x, double *cum, double *ccum, int i_tail, int log_p) -{ -/* i_tail in {0,1,2} means: "lower", "upper", or "both" : - if(lower) return *cum := P[X <= x] - if(upper) return *ccum := P[X > x] = 1 - P[X <= x] -*/ - const static double a[5] = { - 2.2352520354606839287, - 161.02823106855587881, - 1067.6894854603709582, - 18154.981253343561249, - 0.065682337918207449113 - }; - const static double b[4] = { - 47.20258190468824187, - 976.09855173777669322, - 10260.932208618978205, - 45507.789335026729956 - }; - const static double c[9] = { - 0.39894151208813466764, - 8.8831497943883759412, - 93.506656132177855979, - 597.27027639480026226, - 2494.5375852903726711, - 6848.1904505362823326, - 11602.651437647350124, - 9842.7148383839780218, - 1.0765576773720192317e-8 - }; - const static double d[8] = { - 22.266688044328115691, - 235.38790178262499861, - 1519.377599407554805, - 6485.558298266760755, - 18615.571640885098091, - 34900.952721145977266, - 38912.003286093271411, - 19685.429676859990727 - }; - const static double p[6] = { - 0.21589853405795699, - 0.1274011611602473639, - 0.022235277870649807, - 0.001421619193227893466, - 2.9112874951168792e-5, - 0.02307344176494017303 - }; - const static double q[5] = { - 1.28426009614491121, - 0.468238212480865118, - 0.0659881378689285515, - 0.00378239633202758244, - 7.29751555083966205e-5 - }; - - double xden, xnum, temp, del, eps, xsq, y; -#ifdef NO_DENORMS - double min = DBL_MIN; -#endif - int i, lower, upper; - -#ifdef IEEE_754 - if(ISNAN(x)) { *cum = *ccum = x; return; } -#endif - - /* Consider changing these : */ - eps = DBL_EPSILON * 0.5; - - /* i_tail in {0,1,2} =^= {lower, upper, both} */ - lower = i_tail != 1; - upper = i_tail != 0; - - y = fabs(x); - if (y <= 0.67448975) { /* qnorm(3/4) = .6744.... -- earlier had 0.66291 */ - if (y > eps) { - xsq = x * x; - xnum = a[4] * xsq; - xden = xsq; - for (i = 0; i < 3; ++i) { - xnum = (xnum + a[i]) * xsq; - xden = (xden + b[i]) * xsq; - } - } else xnum = xden = 0.0; - - temp = x * (xnum + a[3]) / (xden + b[3]); - if(lower) *cum = 0.5 + temp; - if(upper) *ccum = 0.5 - temp; - if(log_p) { - if(lower) *cum = log(*cum); - if(upper) *ccum = log(*ccum); - } - } - else if (y <= M_SQRT_32) { - - /* Evaluate pnorm for 0.674.. = qnorm(3/4) < |x| <= sqrt(32) ~= 5.657 */ - - xnum = c[8] * y; - xden = y; - for (i = 0; i < 7; ++i) { - xnum = (xnum + c[i]) * y; - xden = (xden + d[i]) * y; - } - temp = (xnum + c[7]) / (xden + d[7]); - -#define do_del(X) \ - xsq = trunc(X * SIXTEN) / SIXTEN; \ - del = (X - xsq) * (X + xsq); \ - if(log_p) { \ - *cum = (-xsq * xsq * 0.5) + (-del * 0.5) + log(temp); \ - if((lower && x > 0.) || (upper && x <= 0.)) \ - *ccum = log1p(-exp(-xsq * xsq * 0.5) * \ - exp(-del * 0.5) * temp); \ - } \ - else { \ - *cum = exp(-xsq * xsq * 0.5) * exp(-del * 0.5) * temp; \ - *ccum = 1.0 - *cum; \ - } - -#define swap_tail \ - if (x > 0.) {/* swap ccum <--> cum */ \ - temp = *cum; if(lower) *cum = *ccum; *ccum = temp; \ - } - - do_del(y); - swap_tail; - } - -/* else |x| > sqrt(32) = 5.657 : - * the next two case differentiations were really for lower=T, log=F - * Particularly *not* for log_p ! - - * Cody had (-37.5193 < x && x < 8.2924) ; R originally had y < 50 - * - * Note that we do want symmetry(0), lower/upper -> hence use y - */ - else if((log_p && y < 1e170) /* avoid underflow below */ - /* ^^^^^ MM FIXME: can speedup for log_p and much larger |x| ! - * Then, make use of Abramowitz & Stegun, 26.2.13, something like - - xsq = x*x; - - if(xsq * DBL_EPSILON < 1.) - del = (1. - (1. - 5./(xsq+6.)) / (xsq+4.)) / (xsq+2.); - else - del = 0.; - *cum = -.5*xsq - M_LN_SQRT_2PI - log(x) + log1p(-del); - *ccum = log1p(-exp(*cum)); /.* ~ log(1) = 0 *./ - - swap_tail; - - [Yes, but xsq might be infinite.] - - */ - || (lower && -37.5193 < x && x < 8.2924) - || (upper && -8.2924 < x && x < 37.5193) - ) { - - /* Evaluate pnorm for x in (-37.5, -5.657) union (5.657, 37.5) */ - xsq = 1.0 / (x * x); /* (1./x)*(1./x) might be better */ - xnum = p[5] * xsq; - xden = xsq; - for (i = 0; i < 4; ++i) { - xnum = (xnum + p[i]) * xsq; - xden = (xden + q[i]) * xsq; - } - temp = xsq * (xnum + p[4]) / (xden + q[4]); - temp = (M_1_SQRT_2PI - temp) / y; - - do_del(x); - swap_tail; - } else { /* large x such that probs are 0 or 1 */ - if(x > 0) { *cum = R_D__1; *ccum = R_D__0; } - else { *cum = R_D__0; *ccum = R_D__1; } - } - - -#ifdef NO_DENORMS - /* do not return "denormalized" -- we do in R */ - if(log_p) { - if(*cum > -min) *cum = -0.; - if(*ccum > -min)*ccum = -0.; - } - else { - if(*cum < min) *cum = 0.; - if(*ccum < min) *ccum = 0.; - } -#endif - return; -} diff --git a/deps/Rmath/src/pnt.c b/deps/Rmath/src/pnt.c deleted file mode 100644 index 4b534fa9980e1..0000000000000 --- a/deps/Rmath/src/pnt.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka and the R Development Core Team - * Copyright (C) 2000-2008 The R Development Core Team - * based on AS243 (C) 1989 Royal Statistical Society - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - */ - -/* Algorithm AS 243 Lenth,R.V. (1989). Appl. Statist., Vol.38, 185-189. - * ---------------- - * Cumulative probability at t of the non-central t-distribution - * with df degrees of freedom (may be fractional) and non-centrality - * parameter delta. - * - * NOTE - * - * Requires the following auxiliary routines: - * - * lgammafn(x) - log gamma function - * pbeta(x, a, b) - incomplete beta function - * pnorm(x) - normal distribution function - * - * CONSTANTS - * - * M_SQRT_2dPI = 1/ {gamma(1.5) * sqrt(2)} = sqrt(2 / pi) - * M_LN_SQRT_PI = ln(sqrt(pi)) = ln(pi)/2 - */ - -#include "nmath.h" -#include "dpq.h" - -/*----------- DEBUGGING ------------- - * - * make CFLAGS='-DDEBUG_pnt -g' - - * -- Feb.3, 1999; M.Maechler: - - For 't > ncp > 20' (or so) the result is completely WRONG! - */ - -double pnt(double t, double df, double ncp, int lower_tail, int log_p) -{ - double albeta, a, b, del, errbd, lambda, rxb, tt, x; - long double geven, godd, p, q, s, tnc, xeven, xodd; - int it, negdel; - - /* note - itrmax and errmax may be changed to suit one's needs. */ - - const int itrmax = 1000; - const static double errmax = 1.e-12; - - if (df <= 0.0) ML_ERR_return_NAN; - if(ncp == 0.0) return pt(t, df, lower_tail, log_p); - - if(!R_FINITE(t)) - return (t < 0) ? R_DT_0 : R_DT_1; - if (t >= 0.) { - negdel = FALSE; tt = t; del = ncp; - } - else { - /* We deal quickly with left tail if extreme, - since pt(q, df, ncp) <= pt(0, df, ncp) = \Phi(-ncp) */ - if (ncp > 40 && (!log_p || !lower_tail)) return R_DT_0; - negdel = TRUE; tt = -t; del = -ncp; - } - - if (df > 4e5 || del*del > 2*M_LN2*(-(DBL_MIN_EXP))) { - /*-- 2nd part: if del > 37.62, then p=0 below - FIXME: test should depend on `df', `tt' AND `del' ! */ - /* Approx. from Abramowitz & Stegun 26.7.10 (p.949) */ - s = 1./(4.*df); - - return pnorm(tt*(1. - s), del, sqrt(1. + tt*tt*2.*s), - lower_tail != negdel, log_p); - } - - /* initialize twin series */ - /* Guenther, J. (1978). Statist. Computn. Simuln. vol.6, 199. */ - - x = t * t; - rxb = df/(x + df);/* := (1 - x) {x below} -- but more accurately */ - x = x / (x + df);/* in [0,1) */ -#ifdef DEBUG_pnt - REprintf("pnt(t=%7g, df=%7g, ncp=%7g) ==> x= %10g:",t,df,ncp, x); -#endif - if (x > 0.) {/* <==> t != 0 */ - lambda = del * del; - p = .5 * exp(-.5 * lambda); -#ifdef DEBUG_pnt - REprintf("\t p=%10Lg\n",p); -#endif - if(p == 0.) { /* underflow! */ - - /*========== really use an other algorithm for this case !!! */ - ML_ERROR(ME_UNDERFLOW, "pnt"); - ML_ERROR(ME_RANGE, "pnt"); /* |ncp| too large */ - return R_DT_0; - } -#ifdef DEBUG_pnt - REprintf("it 1e5*(godd, geven)| p q s" - /* 1.3 1..4..7.9 1..4..7.9|1..4..7.901 1..4..7.901 1..4..7.901 */ - " pnt(*) errbd\n"); - /* 1..4..7..0..34 1..4..7.9*/ -#endif - q = M_SQRT_2dPI * p * del; - s = .5 - p; - /* s = 0.5 - p = 0.5*(1 - exp(-.5 L)) = -0.5*expm1(-.5 L)) */ - if(s < 1e-7) - s = -0.5 * expm1(-0.5 * lambda); - a = .5; - b = .5 * df; - /* rxb = (1 - x) ^ b [ ~= 1 - b*x for tiny x --> see 'xeven' below] - * where '(1 - x)' =: rxb {accurately!} above */ - rxb = pow(rxb, b); - albeta = M_LN_SQRT_PI + lgammafn(b) - lgammafn(.5 + b); - xodd = pbeta(x, a, b, /*lower*/TRUE, /*log_p*/FALSE); - godd = 2. * rxb * exp(a * log(x) - albeta); - tnc = b * x; - xeven = (tnc < DBL_EPSILON) ? tnc : 1. - rxb; - geven = tnc * rxb; - tnc = p * xodd + q * xeven; - - /* repeat until convergence or iteration limit */ - for(it = 1; it <= itrmax; it++) { - a += 1.; - xodd -= godd; - xeven -= geven; - godd *= x * (a + b - 1.) / a; - geven *= x * (a + b - .5) / (a + .5); - p *= lambda / (2 * it); - q *= lambda / (2 * it + 1); - tnc += p * xodd + q * xeven; - s -= p; - /* R 2.4.0 added test for rounding error here. */ - if(s < -1.e-10) { /* happens e.g. for (t,df,ncp)=(40,10,38.5), after 799 it.*/ - ML_ERROR(ME_PRECISION, "pnt"); -#ifdef DEBUG_pnt - REprintf("s = %#14.7Lg < 0 !!! ---> non-convergence!!\n", s); -#endif - goto finis; - } - if(s <= 0 && it > 1) goto finis; - errbd = 2. * s * (xodd - godd); -#ifdef DEBUG_pnt - REprintf("%3d %#9.4g %#9.4g|%#11.4Lg %#11.4Lg %#11.4Lg %#14.10Lg %#9.4g\n", - it, 1e5*(double)godd, 1e5*(double)geven, p, q, s, tnc, errbd); -#endif - if(fabs(errbd) < errmax) goto finis;/*convergence*/ - } - /* non-convergence:*/ - ML_ERROR(ME_NOCONV, "pnt"); - } - else { /* x = t = 0 */ - tnc = 0.; - } - finis: - tnc += pnorm(- del, 0., 1., /*lower*/TRUE, /*log_p*/FALSE); - - lower_tail = lower_tail != negdel; /* xor */ - if(tnc > 1 - 1e-10 && lower_tail) - ML_ERROR(ME_PRECISION, "pnt{final}"); - - return R_DT_val(fmin2(tnc, 1.) /* Precaution */); -} diff --git a/deps/Rmath/src/polygamma.c b/deps/Rmath/src/polygamma.c deleted file mode 100644 index b44c8e3ed3391..0000000000000 --- a/deps/Rmath/src/polygamma.c +++ /dev/null @@ -1,549 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000-2007 the R Development Core Team - * Copyright (C) 2004-2009 The R Foundation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * void dpsifn(double x, int n, int kode, int m, - * double *ans, int *nz, int *ierr) - * double digamma(double x); - * double trigamma(double x) - * double tetragamma(double x) - * double pentagamma(double x) - * - * DESCRIPTION - * - * Compute the derivatives of the psi function - * and polygamma functions. - * - * The following definitions are used in dpsifn: - * - * Definition 1 - * - * psi(x) = d/dx (ln(gamma(x)), the first derivative of - * the log gamma function. - * - * Definition 2 - * k k - * psi(k,x) = d /dx (psi(x)), the k-th derivative - * of psi(x). - * - * - * "dpsifn" computes a sequence of scaled derivatives of - * the psi function; i.e. for fixed x and m it computes - * the m-member sequence - * - * (-1)^(k+1) / gamma(k+1) * psi(k,x) - * for k = n,...,n+m-1 - * - * where psi(k,x) is as defined above. For kode=1, dpsifn - * returns the scaled derivatives as described. kode=2 is - * operative only when k=0 and in that case dpsifn returns - * -psi(x) + ln(x). That is, the logarithmic behavior for - * large x is removed when kode=2 and k=0. When sums or - * differences of psi functions are computed the logarithmic - * terms can be combined analytically and computed separately - * to help retain significant digits. - * - * Note that dpsifn(x, 0, 1, 1, ans) results in ans = -psi(x). - * - * INPUT - * - * x - argument, x > 0. - * - * n - first member of the sequence, 0 <= n <= 100 - * n == 0 gives ans(1) = -psi(x) for kode=1 - * -psi(x)+ln(x) for kode=2 - * - * kode - selection parameter - * kode == 1 returns scaled derivatives of the - * psi function. - * kode == 2 returns scaled derivatives of the - * psi function except when n=0. In this case, - * ans(1) = -psi(x) + ln(x) is returned. - * - * m - number of members of the sequence, m >= 1 - * - * OUTPUT - * - * ans - a vector of length at least m whose first m - * components contain the sequence of derivatives - * scaled according to kode. - * - * nz - underflow flag - * nz == 0, a normal return - * nz != 0, underflow, last nz components of ans are - * set to zero, ans(m-k+1)=0.0, k=1,...,nz - * - * ierr - error flag - * ierr=0, a normal return, computation completed - * ierr=1, input error, no computation - * ierr=2, overflow, x too small or n+m-1 too - * large or both - * ierr=3, error, n too large. dimensioned - * array trmr(nmax) is not large enough for n - * - * The nominal computational accuracy is the maximum of unit - * roundoff (d1mach(4)) and 1e-18 since critical constants - * are given to only 18 digits. - * - * The basic method of evaluation is the asymptotic expansion - * for large x >= xmin followed by backward recursion on a two - * term recursion relation - * - * w(x+1) + x^(-n-1) = w(x). - * - * this is supplemented by a series - * - * sum( (x+k)^(-n-1) , k=0,1,2,... ) - * - * which converges rapidly for large n. both xmin and the - * number of terms of the series are calculated from the unit - * roundoff of the machine environment. - * - * AUTHOR - * - * Amos, D. E. (Fortran) - * Ross Ihaka (C Translation) - * Martin Maechler (x < 0, and psigamma()) - * - * REFERENCES - * - * Handbook of Mathematical Functions, - * National Bureau of Standards Applied Mathematics Series 55, - * Edited by M. Abramowitz and I. A. Stegun, equations 6.3.5, - * 6.3.18, 6.4.6, 6.4.9 and 6.4.10, pp.258-260, 1964. - * - * D. E. Amos, (1983). "A Portable Fortran Subroutine for - * Derivatives of the Psi Function", Algorithm 610, - * TOMS 9(4), pp. 494-502. - * - * Routines called: Rf_d1mach, Rf_i1mach. - */ - -#include "nmath.h" -#ifdef MATHLIB_STANDALONE -#include -#endif - -#define n_max (100) - -/* From R, currently only used for kode = 1, m = 1, n in {0,1,2,3} : */ -void dpsifn(double x, int n, int kode, int m, double *ans, int *nz, int *ierr) -{ - const static double bvalues[] = { /* Bernoulli Numbers */ - 1.00000000000000000e+00, - -5.00000000000000000e-01, - 1.66666666666666667e-01, - -3.33333333333333333e-02, - 2.38095238095238095e-02, - -3.33333333333333333e-02, - 7.57575757575757576e-02, - -2.53113553113553114e-01, - 1.16666666666666667e+00, - -7.09215686274509804e+00, - 5.49711779448621554e+01, - -5.29124242424242424e+02, - 6.19212318840579710e+03, - -8.65802531135531136e+04, - 1.42551716666666667e+06, - -2.72982310678160920e+07, - 6.01580873900642368e+08, - -1.51163157670921569e+10, - 4.29614643061166667e+11, - -1.37116552050883328e+13, - 4.88332318973593167e+14, - -1.92965793419400681e+16 - }; - - int i, j, k, mm, mx, nn, np, nx, fn; - double arg, den, elim, eps, fln, fx, rln, rxsq, - r1m4, r1m5, s, slope, t, ta, tk, tol, tols, tss, tst, - tt, t1, t2, wdtol, xdmln, xdmy, xinc, xln = 0.0 /* -Wall */, - xm, xmin, xq, yint; - double trm[23], trmr[n_max + 1]; - - *ierr = 0; - if (n < 0 || kode < 1 || kode > 2 || m < 1) { - *ierr = 1; - return; - } - if (x <= 0.) { - /* use Abramowitz & Stegun 6.4.7 "Reflection Formula" - * psi(k, x) = (-1)^k psi(k, 1-x) - pi^{n+1} (d/dx)^n cot(x) - */ - if (x == (long)x) { - /* non-positive integer : +Inf or NaN depends on n */ - for(j=0; j < m; j++) /* k = j + n : */ - ans[j] = ((j+n) % 2) ? ML_POSINF : ML_NAN; - return; - } - /* This could cancel badly */ - dpsifn(1. - x, n, /*kode = */ 1, m, ans, nz, ierr); - /* ans[j] == (-1)^(k+1) / gamma(k+1) * psi(k, 1 - x) - * for j = 0:(m-1) , k = n + j - */ - - /* Cheat for now: only work for m = 1, n in {0,1,2,3} : */ - if(m > 1 || n > 3) {/* doesn't happen for digamma() .. pentagamma() */ - /* not yet implemented */ - *ierr = 4; return; - } - x *= M_PI; /* pi * x */ - if (n == 0) - tt = cos(x)/sin(x); - else if (n == 1) - tt = -1/pow(sin(x),2); - else if (n == 2) - tt = 2*cos(x)/pow(sin(x),3); - else if (n == 3) - tt = -2*(2*pow(cos(x),2) + 1)/pow(sin(x),4); - else /* can not happen! */ - tt = ML_NAN; - /* end cheat */ - - s = (n % 2) ? -1. : 1.;/* s = (-1)^n */ - /* t := pi^(n+1) * d_n(x) / gamma(n+1) , where - * d_n(x) := (d/dx)^n cot(x)*/ - t1 = t2 = s = 1.; - for(k=0, j=k-n; j < m; k++, j++, s = -s) { - /* k == n+j , s = (-1)^k */ - t1 *= M_PI;/* t1 == pi^(k+1) */ - if(k >= 2) - t2 *= k;/* t2 == k! == gamma(k+1) */ - if(j >= 0) /* by cheat above, tt === d_k(x) */ - ans[j] = s*(ans[j] + t1/t2 * tt); - } - if (n == 0 && kode == 2) /* unused from R, but "wrong": xln === 0 :*/ - ans[0] += xln; - return; - } /* x <= 0 */ - - /* else : x > 0 */ - *nz = 0; - xln = log(x); - if(kode == 1 && m == 1) {/* the R case --- for very large x: */ - double lrg = 1/(2. * DBL_EPSILON); - if(n == 0 && x * xln > lrg) { - ans[0] = -xln; - return; - } - else if(n >= 1 && x > n * lrg) { - ans[0] = exp(-n * xln)/n; /* == x^-n / n == 1/(n * x^n) */ - return; - } - } - mm = m; - nx = imin2(-Rf_i1mach(15), Rf_i1mach(16));/* = 1021 */ - r1m5 = Rf_d1mach(5); - r1m4 = Rf_d1mach(4) * 0.5; - wdtol = fmax2(r1m4, 0.5e-18); /* 1.11e-16 */ - - /* elim = approximate exponential over and underflow limit */ - elim = 2.302 * (nx * r1m5 - 3.0);/* = 700.6174... */ - for(;;) { - nn = n + mm - 1; - fn = nn; - t = (fn + 1) * xln; - - /* overflow and underflow test for small and large x */ - - if (fabs(t) > elim) { - if (t <= 0.0) { - *nz = 0; - *ierr = 2; - return; - } - } - else { - if (x < wdtol) { - ans[0] = pow(x, -n-1.0); - if (mm != 1) { - for(k = 1; k < mm ; k++) - ans[k] = ans[k-1] / x; - } - if (n == 0 && kode == 2) - ans[0] += xln; - return; - } - - /* compute xmin and the number of terms of the series, fln+1 */ - - rln = r1m5 * Rf_i1mach(14); - rln = fmin2(rln, 18.06); - fln = fmax2(rln, 3.0) - 3.0; - yint = 3.50 + 0.40 * fln; - slope = 0.21 + fln * (0.0006038 * fln + 0.008677); - xm = yint + slope * fn; - mx = (int)xm + 1; - xmin = mx; - if (n != 0) { - xm = -2.302 * rln - fmin2(0.0, xln); - arg = xm / n; - arg = fmin2(0.0, arg); - eps = exp(arg); - xm = 1.0 - eps; - if (fabs(arg) < 1.0e-3) - xm = -arg; - fln = x * xm / eps; - xm = xmin - x; - if (xm > 7.0 && fln < 15.0) - break; - } - xdmy = x; - xdmln = xln; - xinc = 0.0; - if (x < xmin) { - nx = (int)x; - xinc = xmin - nx; - xdmy = x + xinc; - xdmln = log(xdmy); - } - - /* generate w(n+mm-1, x) by the asymptotic expansion */ - - t = fn * xdmln; - t1 = xdmln + xdmln; - t2 = t + xdmln; - tk = fmax2(fabs(t), fmax2(fabs(t1), fabs(t2))); - if (tk <= elim) /* for all but large x */ - goto L10; - } - nz++; /* underflow */ - mm--; - ans[mm] = 0.; - if (mm == 0) - return; - } /* end{for()} */ - nn = (int)fln + 1; - np = n + 1; - t1 = (n + 1) * xln; - t = exp(-t1); - s = t; - den = x; - for(i=1; i <= nn; i++) { - den += 1.; - trm[i] = pow(den, (double)-np); - s += trm[i]; - } - ans[0] = s; - if (n == 0 && kode == 2) - ans[0] = s + xln; - - if (mm != 1) { /* generate higher derivatives, j > n */ - - tol = wdtol / 5.0; - for(j = 1; j < mm; j++) { - t /= x; - s = t; - tols = t * tol; - den = x; - for(i=1; i <= nn; i++) { - den += 1.; - trm[i] /= den; - s += trm[i]; - if (trm[i] < tols) - break; - } - ans[j] = s; - } - } - return; - - L10: - tss = exp(-t); - tt = 0.5 / xdmy; - t1 = tt; - tst = wdtol * tt; - if (nn != 0) - t1 = tt + 1.0 / fn; - rxsq = 1.0 / (xdmy * xdmy); - ta = 0.5 * rxsq; - t = (fn + 1) * ta; - s = t * bvalues[2]; - if (fabs(s) >= tst) { - tk = 2.0; - for(k = 4; k <= 22; k++) { - t = t * ((tk + fn + 1)/(tk + 1.0))*((tk + fn)/(tk + 2.0)) * rxsq; - trm[k] = t * bvalues[k-1]; - if (fabs(trm[k]) < tst) - break; - s += trm[k]; - tk += 2.; - } - } - s = (s + t1) * tss; - if (xinc != 0.0) { - - /* backward recur from xdmy to x */ - - nx = (int)xinc; - np = nn + 1; - if (nx > n_max) { - *nz = 0; - *ierr = 3; - return; - } - else { - if (nn==0) - goto L20; - xm = xinc - 1.0; - fx = x + xm; - - /* this loop should not be changed. fx is accurate when x is small */ - for(i = 1; i <= nx; i++) { - trmr[i] = pow(fx, (double)-np); - s += trmr[i]; - xm -= 1.; - fx = x + xm; - } - } - } - ans[mm-1] = s; - if (fn == 0) - goto L30; - - /* generate lower derivatives, j < n+mm-1 */ - - for(j = 2; j <= mm; j++) { - fn--; - tss *= xdmy; - t1 = tt; - if (fn!=0) - t1 = tt + 1.0 / fn; - t = (fn + 1) * ta; - s = t * bvalues[2]; - if (fabs(s) >= tst) { - tk = 4 + fn; - for(k=4; k <= 22; k++) { - trm[k] = trm[k] * (fn + 1) / tk; - if (fabs(trm[k]) < tst) - break; - s += trm[k]; - tk += 2.; - } - } - s = (s + t1) * tss; - if (xinc != 0.0) { - if (fn == 0) - goto L20; - xm = xinc - 1.0; - fx = x + xm; - for(i=1 ; i<=nx ; i++) { - trmr[i] = trmr[i] * fx; - s += trmr[i]; - xm -= 1.; - fx = x + xm; - } - } - ans[mm - j] = s; - if (fn == 0) - goto L30; - } - return; - - L20: - for(i = 1; i <= nx; i++) - s += 1. / (x + (nx - i)); /* avoid disastrous cancellation, PR#13714 */ - - L30: - if (kode != 2) /* always */ - ans[0] = s - xdmln; - else if (xdmy != x) { - xq = xdmy / x; - ans[0] = s - log(xq); - } - return; -} /* dpsifn() */ - -#ifdef MATHLIB_STANDALONE -# define ML_TREAT_psigam(_IERR_) \ - if(_IERR_ != 0) { \ - errno = EDOM; \ - return ML_NAN; \ - } -#else -# define ML_TREAT_psigam(_IERR_) \ - if(_IERR_ != 0) \ - return ML_NAN -#endif - -double psigamma(double x, double deriv) -{ - /* n-th derivative of psi(x); e.g., psigamma(x,0) == digamma(x) */ - double ans; - int nz, ierr, k, n; - - if(ISNAN(x)) - return x; - deriv = floor(deriv + 0.5); - n = (int)deriv; - if(n > n_max) { - MATHLIB_WARNING2(_("deriv = %d > %d (= n_max)\n"), n, n_max); - return ML_NAN; - } - dpsifn(x, n, 1, 1, &ans, &nz, &ierr); - ML_TREAT_psigam(ierr); - /* Now, ans == A := (-1)^(n+1) / gamma(n+1) * psi(n, x) */ - ans = -ans; /* = (-1)^(0+1) * gamma(0+1) * A */ - for(k = 1; k <= n; k++) - ans *= (-k);/* = (-1)^(k+1) * gamma(k+1) * A */ - return ans;/* = psi(n, x) */ -} - -double digamma(double x) -{ - double ans; - int nz, ierr; - if(ISNAN(x)) return x; - dpsifn(x, 0, 1, 1, &ans, &nz, &ierr); - ML_TREAT_psigam(ierr); - return -ans; -} - -double trigamma(double x) -{ - double ans; - int nz, ierr; - if(ISNAN(x)) return x; - dpsifn(x, 1, 1, 1, &ans, &nz, &ierr); - ML_TREAT_psigam(ierr); - return ans; -} - -double tetragamma(double x) -{ - double ans; - int nz, ierr; - if(ISNAN(x)) return x; - dpsifn(x, 2, 1, 1, &ans, &nz, &ierr); - ML_TREAT_psigam(ierr); - return -2.0 * ans; -} - -double pentagamma(double x) -{ - double ans; - int nz, ierr; - if(ISNAN(x)) return x; - dpsifn(x, 3, 1, 1, &ans, &nz, &ierr); - ML_TREAT_psigam(ierr); - return 6.0 * ans; -} diff --git a/deps/Rmath/src/ppois.c b/deps/Rmath/src/ppois.c deleted file mode 100644 index f7be0a186d1ce..0000000000000 --- a/deps/Rmath/src/ppois.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * DESCRIPTION - * - * The distribution function of the Poisson distribution. - */ - -#include "nmath.h" -#include "dpq.h" - -double ppois(double x, double lambda, int lower_tail, int log_p) -{ -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(lambda)) - return x + lambda; -#endif - if(lambda < 0.) ML_ERR_return_NAN; - if (x < 0) return R_DT_0; - if (lambda == 0.) return R_DT_1; - if (!R_FINITE(x)) return R_DT_1; - x = floor(x + 1e-7); - - return pgamma(lambda, x + 1, 1., !lower_tail, log_p); -} diff --git a/deps/Rmath/src/pt.c b/deps/Rmath/src/pt.c deleted file mode 100644 index e10aa9351ab7e..0000000000000 --- a/deps/Rmath/src/pt.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * R : A Computer Language for Statistical Data Analysis - * Copyright (C) 1995, 1996 Robert Gentleman and Ross Ihaka - * Copyright (C) 2000-2007 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - */ - -#include "nmath.h" -#include "dpq.h" - -double pt(double x, double n, int lower_tail, int log_p) -{ -/* return P[ T <= x ] where - * T ~ t_{n} (t distrib. with n degrees of freedom). - - * --> ./pnt.c for NON-central - */ - double val, nx; -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(n)) - return x + n; -#endif - if (n <= 0.0) ML_ERR_return_NAN; - - if(!R_FINITE(x)) - return (x < 0) ? R_DT_0 : R_DT_1; - if(!R_FINITE(n)) - return pnorm(x, 0.0, 1.0, lower_tail, log_p); - -#ifdef R_version_le_260 - if (n > 4e5) { /*-- Fixme(?): test should depend on `n' AND `x' ! */ - /* Approx. from Abramowitz & Stegun 26.7.8 (p.949) */ - val = 1./(4.*n); - return pnorm(x*(1. - val)/sqrt(1. + x*x*2.*val), 0.0, 1.0, - lower_tail, log_p); - } -#endif - - nx = 1 + (x/n)*x; - /* FIXME: This test is probably losing rather than gaining precision, - * now that pbeta(*, log_p = TRUE) is much better. - * Note however that a version of this test *is* needed for x*x > D_MAX */ - if(nx > 1e100) { /* <==> x*x > 1e100 * n */ - /* Danger of underflow. So use Abramowitz & Stegun 26.5.4 - pbeta(z, a, b) ~ z^a(1-z)^b / aB(a,b) ~ z^a / aB(a,b), - with z = 1/nx, a = n/2, b= 1/2 : - */ - double lval; - lval = -0.5*n*(2*log(fabs(x)) - log(n)) - - lbeta(0.5*n, 0.5) - log(0.5*n); - val = log_p ? lval : exp(lval); - } else { - val = (n > x * x) - ? pbeta (x * x / (n + x * x), 0.5, n / 2., /*lower_tail*/0, log_p) - : pbeta (1. / nx, n / 2., 0.5, /*lower_tail*/1, log_p); - } - - /* Use "1 - v" if lower_tail and x > 0 (but not both):*/ - if(x <= 0.) - lower_tail = !lower_tail; - - if(log_p) { - if(lower_tail) return log1p(-0.5*exp(val)); - else return val - M_LN2; /* = log(.5* pbeta(....)) */ - } - else { - val /= 2.; - return R_D_Cval(val); - } -} diff --git a/deps/Rmath/src/ptukey.c b/deps/Rmath/src/ptukey.c deleted file mode 100644 index cb5815ac93609..0000000000000 --- a/deps/Rmath/src/ptukey.c +++ /dev/null @@ -1,409 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000--2007 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * double ptukey(q, rr, cc, df, lower_tail, log_p); - * - * DESCRIPTION - * - * Computes the probability that the maximum of rr studentized - * ranges, each based on cc means and with df degrees of freedom - * for the standard error, is less than q. - * - * The algorithm is based on that of the reference. - * - * REFERENCE - * - * Copenhaver, Margaret Diponzio & Holland, Burt S. - * Multiple comparisons of simple effects in - * the two-way analysis of variance with fixed effects. - * Journal of Statistical Computation and Simulation, - * Vol.30, pp.1-15, 1988. - */ - -#include "nmath.h" -#include "dpq.h" - -static double wprob(double w, double rr, double cc) -{ -/* wprob() : - - This function calculates probability integral of Hartley's - form of the range. - - w = value of range - rr = no. of rows or groups - cc = no. of columns or treatments - ir = error flag = 1 if pr_w probability > 1 - pr_w = returned probability integral from (0, w) - - program will not terminate if ir is raised. - - bb = upper limit of legendre integration - iMax = maximum acceptable value of integral - nleg = order of legendre quadrature - ihalf = int ((nleg + 1) / 2) - wlar = value of range above which wincr1 intervals are used to - calculate second part of integral, - else wincr2 intervals are used. - C1, C2, C3 = values which are used as cutoffs for terminating - or modifying a calculation. - - M_1_SQRT_2PI = 1 / sqrt(2 * pi); from abramowitz & stegun, p. 3. - M_SQRT2 = sqrt(2) - xleg = legendre 12-point nodes - aleg = legendre 12-point coefficients - */ -#define nleg 12 -#define ihalf 6 - - /* looks like this is suboptimal for double precision. - (see how C1-C3 are used) - */ - /* const double iMax = 1.; not used if = 1*/ - const static double C1 = -30.; - const static double C2 = -50.; - const static double C3 = 60.; - const static double bb = 8.; - const static double wlar = 3.; - const static double wincr1 = 2.; - const static double wincr2 = 3.; - const static double xleg[ihalf] = { - 0.981560634246719250690549090149, - 0.904117256370474856678465866119, - 0.769902674194304687036893833213, - 0.587317954286617447296702418941, - 0.367831498998180193752691536644, - 0.125233408511468915472441369464 - }; - const static double aleg[ihalf] = { - 0.047175336386511827194615961485, - 0.106939325995318430960254718194, - 0.160078328543346226334652529543, - 0.203167426723065921749064455810, - 0.233492536538354808760849898925, - 0.249147045813402785000562436043 - }; - double a, ac, pr_w, b, binc, blb, c, cc1, - pminus, pplus, qexpo, qsqz, rinsum, wi, wincr, xx; - long double bub, einsum, elsum; - int j, jj; - - - qsqz = w * 0.5; - - /* if w >= 16 then the integral lower bound (occurs for c=20) */ - /* is 0.99999999999995 so return a value of 1. */ - - if (qsqz >= bb) - return 1.0; - - /* find (f(w/2) - 1) ^ cc */ - /* (first term in integral of hartley's form). */ - - pr_w = 2 * pnorm(qsqz, 0.,1., 1,0) - 1.; /* erf(qsqz / M_SQRT2) */ - /* if pr_w ^ cc < 2e-22 then set pr_w = 0 */ - if (pr_w >= exp(C2 / cc)) - pr_w = pow(pr_w, cc); - else - pr_w = 0.0; - - /* if w is large then the second component of the */ - /* integral is small, so fewer intervals are needed. */ - - if (w > wlar) - wincr = wincr1; - else - wincr = wincr2; - - /* find the integral of second term of hartley's form */ - /* for the integral of the range for equal-length */ - /* intervals using legendre quadrature. limits of */ - /* integration are from (w/2, 8). two or three */ - /* equal-length intervals are used. */ - - /* blb and bub are lower and upper limits of integration. */ - - blb = qsqz; - binc = (bb - qsqz) / wincr; - bub = blb + binc; - einsum = 0.0; - - /* integrate over each interval */ - - cc1 = cc - 1.0; - for (wi = 1; wi <= wincr; wi++) { - elsum = 0.0; - a = 0.5 * (bub + blb); - - /* legendre quadrature with order = nleg */ - - b = 0.5 * (bub - blb); - - for (jj = 1; jj <= nleg; jj++) { - if (ihalf < jj) { - j = (nleg - jj) + 1; - xx = xleg[j-1]; - } else { - j = jj; - xx = -xleg[j-1]; - } - c = b * xx; - ac = a + c; - - /* if exp(-qexpo/2) < 9e-14, */ - /* then doesn't contribute to integral */ - - qexpo = ac * ac; - if (qexpo > C3) - break; - - pplus = 2 * pnorm(ac, 0., 1., 1,0); - pminus= 2 * pnorm(ac, w, 1., 1,0); - - /* if rinsum ^ (cc-1) < 9e-14, */ - /* then doesn't contribute to integral */ - - rinsum = (pplus * 0.5) - (pminus * 0.5); - if (rinsum >= exp(C1 / cc1)) { - rinsum = (aleg[j-1] * exp(-(0.5 * qexpo))) * pow(rinsum, cc1); - elsum += rinsum; - } - } - elsum *= (((2.0 * b) * cc) * M_1_SQRT_2PI); - einsum += elsum; - blb = bub; - bub += binc; - } - - /* if pr_w ^ rr < 9e-14, then return 0 */ - pr_w = einsum + pr_w; - if (pr_w <= exp(C1 / rr)) - return 0.; - - pr_w = pow(pr_w, rr); - if (pr_w >= 1.)/* 1 was iMax was eps */ - return 1.; - return pr_w; -} /* wprob() */ - - -double ptukey(double q, double rr, double cc, double df, - int lower_tail, int log_p) -{ -/* function ptukey() [was qprob() ]: - - q = value of studentized range - rr = no. of rows or groups - cc = no. of columns or treatments - df = degrees of freedom of error term - ir[0] = error flag = 1 if wprob probability > 1 - ir[1] = error flag = 1 if qprob probability > 1 - - qprob = returned probability integral over [0, q] - - The program will not terminate if ir[0] or ir[1] are raised. - - All references in wprob to Abramowitz and Stegun - are from the following reference: - - Abramowitz, Milton and Stegun, Irene A. - Handbook of Mathematical Functions. - New York: Dover publications, Inc. (1970). - - All constants taken from this text are - given to 25 significant digits. - - nlegq = order of legendre quadrature - ihalfq = int ((nlegq + 1) / 2) - eps = max. allowable value of integral - eps1 & eps2 = values below which there is - no contribution to integral. - - d.f. <= dhaf: integral is divided into ulen1 length intervals. else - d.f. <= dquar: integral is divided into ulen2 length intervals. else - d.f. <= deigh: integral is divided into ulen3 length intervals. else - d.f. <= dlarg: integral is divided into ulen4 length intervals. - - d.f. > dlarg: the range is used to calculate integral. - - M_LN2 = log(2) - - xlegq = legendre 16-point nodes - alegq = legendre 16-point coefficients - - The coefficients and nodes for the legendre quadrature used in - qprob and wprob were calculated using the algorithms found in: - - Stroud, A. H. and Secrest, D. - Gaussian Quadrature Formulas. - Englewood Cliffs, - New Jersey: Prentice-Hall, Inc, 1966. - - All values matched the tables (provided in same reference) - to 30 significant digits. - - f(x) = .5 + erf(x / sqrt(2)) / 2 for x > 0 - - f(x) = erfc( -x / sqrt(2)) / 2 for x < 0 - - where f(x) is standard normal c. d. f. - - if degrees of freedom large, approximate integral - with range distribution. - */ -#define nlegq 16 -#define ihalfq 8 - -/* const double eps = 1.0; not used if = 1 */ - const static double eps1 = -30.0; - const static double eps2 = 1.0e-14; - const static double dhaf = 100.0; - const static double dquar = 800.0; - const static double deigh = 5000.0; - const static double dlarg = 25000.0; - const static double ulen1 = 1.0; - const static double ulen2 = 0.5; - const static double ulen3 = 0.25; - const static double ulen4 = 0.125; - const static double xlegq[ihalfq] = { - 0.989400934991649932596154173450, - 0.944575023073232576077988415535, - 0.865631202387831743880467897712, - 0.755404408355003033895101194847, - 0.617876244402643748446671764049, - 0.458016777657227386342419442984, - 0.281603550779258913230460501460, - 0.950125098376374401853193354250e-1 - }; - const static double alegq[ihalfq] = { - 0.271524594117540948517805724560e-1, - 0.622535239386478928628438369944e-1, - 0.951585116824927848099251076022e-1, - 0.124628971255533872052476282192, - 0.149595988816576732081501730547, - 0.169156519395002538189312079030, - 0.182603415044923588866763667969, - 0.189450610455068496285396723208 - }; - double ans, f2, f21, f2lf, ff4, otsum, qsqz, rotsum, t1, twa1, ulen, wprb; - int i, j, jj; - -#ifdef IEEE_754 - if (ISNAN(q) || ISNAN(rr) || ISNAN(cc) || ISNAN(df)) - ML_ERR_return_NAN; -#endif - - if (q <= 0) - return R_DT_0; - - /* df must be > 1 */ - /* there must be at least two values */ - - if (df < 2 || rr < 1 || cc < 2) ML_ERR_return_NAN; - - if(!R_FINITE(q)) - return R_DT_1; - - if (df > dlarg) - return R_DT_val(wprob(q, rr, cc)); - - /* calculate leading constant */ - - f2 = df * 0.5; - /* lgammafn(u) = log(gamma(u)) */ - f2lf = ((f2 * log(df)) - (df * M_LN2)) - lgammafn(f2); - f21 = f2 - 1.0; - - /* integral is divided into unit, half-unit, quarter-unit, or */ - /* eighth-unit length intervals depending on the value of the */ - /* degrees of freedom. */ - - ff4 = df * 0.25; - if (df <= dhaf) ulen = ulen1; - else if (df <= dquar) ulen = ulen2; - else if (df <= deigh) ulen = ulen3; - else ulen = ulen4; - - f2lf += log(ulen); - - /* integrate over each subinterval */ - - ans = 0.0; - - for (i = 1; i <= 50; i++) { - otsum = 0.0; - - /* legendre quadrature with order = nlegq */ - /* nodes (stored in xlegq) are symmetric around zero. */ - - twa1 = (2 * i - 1) * ulen; - - for (jj = 1; jj <= nlegq; jj++) { - if (ihalfq < jj) { - j = jj - ihalfq - 1; - t1 = (f2lf + (f21 * log(twa1 + (xlegq[j] * ulen)))) - - (((xlegq[j] * ulen) + twa1) * ff4); - } else { - j = jj - 1; - t1 = (f2lf + (f21 * log(twa1 - (xlegq[j] * ulen)))) - + (((xlegq[j] * ulen) - twa1) * ff4); - - } - - /* if exp(t1) < 9e-14, then doesn't contribute to integral */ - if (t1 >= eps1) { - if (ihalfq < jj) { - qsqz = q * sqrt(((xlegq[j] * ulen) + twa1) * 0.5); - } else { - qsqz = q * sqrt(((-(xlegq[j] * ulen)) + twa1) * 0.5); - } - - /* call wprob to find integral of range portion */ - - wprb = wprob(qsqz, rr, cc); - rotsum = (wprb * alegq[j]) * exp(t1); - otsum += rotsum; - } - /* end legendre integral for interval i */ - /* L200: */ - } - - /* if integral for interval i < 1e-14, then stop. - * However, in order to avoid small area under left tail, - * at least 1 / ulen intervals are calculated. - */ - if (i * ulen >= 1.0 && otsum <= eps2) - break; - - /* end of interval i */ - /* L330: */ - - ans += otsum; - } - - if(otsum > eps2) { /* not converged */ - ML_ERROR(ME_PRECISION, "ptukey"); - } - if (ans > 1.) - ans = 1.; - return R_DT_val(ans); -} diff --git a/deps/Rmath/src/punif.c b/deps/Rmath/src/punif.c deleted file mode 100644 index ec3677dfbe4ec..0000000000000 --- a/deps/Rmath/src/punif.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000-2006 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * DESCRIPTION - * - * The distribution function of the uniform distribution. - */ - -#include "nmath.h" -#include "dpq.h" - -double punif(double x, double a, double b, int lower_tail, int log_p) -{ -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(a) || ISNAN(b)) - return x + a + b; -#endif - if (b < a) ML_ERR_return_NAN; - if (!R_FINITE(a) || !R_FINITE(b)) ML_ERR_return_NAN; - - if (x >= b) - return R_DT_1; - if (x <= a) - return R_DT_0; - if (lower_tail) return R_D_val((x - a) / (b - a)); - else return R_D_val((b - x) / (b - a)); -} diff --git a/deps/Rmath/src/pweibull.c b/deps/Rmath/src/pweibull.c deleted file mode 100644 index 46c379e5e9fcb..0000000000000 --- a/deps/Rmath/src/pweibull.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000-2002 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * DESCRIPTION - * - * The distribution function of the Weibull distribution. - */ - -#include "nmath.h" -#include "dpq.h" - -double pweibull(double x, double shape, double scale, int lower_tail, int log_p) -{ -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(shape) || ISNAN(scale)) - return x + shape + scale; -#endif - if(shape <= 0 || scale <= 0) ML_ERR_return_NAN; - - if (x <= 0) - return R_DT_0; - x = -pow(x / scale, shape); - if (lower_tail) - return (log_p - /* log(1 - exp(x)) for x < 0 : */ - ? R_Log1_Exp(x) : -expm1(x)); - /* else: !lower_tail */ - return R_D_exp(x); -} diff --git a/deps/Rmath/src/qbeta.c b/deps/Rmath/src/qbeta.c deleted file mode 100644 index a6e9ab920fe29..0000000000000 --- a/deps/Rmath/src/qbeta.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * R : A Computer Language for Statistical Data Analysis - * Copyright (C) 1995, 1996 Robert Gentleman and Ross Ihaka - * Copyright (C) 1998--2007 The R Development Core Team - * based on code (C) 1979 and later Royal Statistical Society - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - - * Reference: - * Cran, G. W., K. J. Martin and G. E. Thomas (1977). - * Remark AS R19 and Algorithm AS 109, - * Applied Statistics, 26(1), 111-114. - * Remark AS R83 (v.39, 309-310) and the correction (v.40(1) p.236) - * have been incorporated in this version. - */ - - -#include "nmath.h" -#include "dpq.h" - -/* set the exponent of accu to -2r-2 for r digits of accuracy */ -/*---- NEW ---- -- still fails for p = 1e11, q=.5*/ - -#define fpu 3e-308 -/* acu_min: Minimal value for accuracy 'acu' which will depend on (a,p); - acu_min >= fpu ! */ -#define acu_min 1e-300 -#define lower fpu -#define upper 1-2.22e-16 - -#define const1 2.30753 -#define const2 0.27061 -#define const3 0.99229 -#define const4 0.04481 - - -double qbeta(double alpha, double p, double q, int lower_tail, int log_p) -{ - int swap_tail, i_pb, i_inn; - double a, adj, logbeta, g, h, pp, p_, prev, qq, r, s, t, tx, w, y, yprev; - double acu; - volatile double xinbta; - - /* test for admissibility of parameters */ - -#ifdef IEEE_754 - if (ISNAN(p) || ISNAN(q) || ISNAN(alpha)) - return p + q + alpha; -#endif - if(p < 0. || q < 0.) ML_ERR_return_NAN; - - R_Q_P01_boundaries(alpha, 0, 1); - - p_ = R_DT_qIv(alpha);/* lower_tail prob (in any case) */ - - if(log_p && (p_ == 0. || p_ == 1.)) - return p_; /* better than NaN or infinite loop; - FIXME: suboptimal, since -Inf < alpha ! */ - - /* initialize */ - logbeta = lbeta(p, q); - - /* change tail if necessary; afterwards 0 < a <= 1/2 */ - if (p_ <= 0.5) { - a = p_; pp = p; qq = q; swap_tail = 0; - } else { /* change tail, swap p <-> q :*/ - a = (!lower_tail && !log_p)? alpha : 1 - p_; - pp = q; qq = p; swap_tail = 1; - } - - /* calculate the initial approximation */ - - /* y := {fast approximation of} qnorm(1 - a) :*/ - r = sqrt(-2 * log(a)); - y = r - (const1 + const2 * r) / (1. + (const3 + const4 * r) * r); - if (pp > 1 && qq > 1) { - r = (y * y - 3.) / 6.; - s = 1. / (pp + pp - 1.); - t = 1. / (qq + qq - 1.); - h = 2. / (s + t); - w = y * sqrt(h + r) / h - (t - s) * (r + 5. / 6. - 2. / (3. * h)); - xinbta = pp / (pp + qq * exp(w + w)); - } else { - r = qq + qq; - t = 1. / (9. * qq); - t = r * pow(1. - t + y * sqrt(t), 3.0); - if (t <= 0.) - xinbta = 1. - exp((log1p(-a)+ log(qq) + logbeta) / qq); - else { - t = (4. * pp + r - 2.) / t; - if (t <= 1.) - xinbta = exp((log(a * pp) + logbeta) / pp); - else - xinbta = 1. - 2. / (t + 1.); - } - } - - /* solve for x by a modified newton-raphson method, */ - /* using the function pbeta_raw */ - - r = 1 - pp; - t = 1 - qq; - yprev = 0.; - adj = 1; - /* Sometimes the approximation is negative! */ - if (xinbta < lower) - xinbta = 0.5; - else if (xinbta > upper) - xinbta = 0.5; - - /* Desired accuracy should depend on (a,p) - * This is from Remark .. on AS 109, adapted. - * However, it's not clear if this is "optimal" for IEEE double prec. - - * acu = fmax2(acu_min, pow(10., -25. - 5./(pp * pp) - 1./(a * a))); - - * NEW: 'acu' accuracy NOT for squared adjustment, but simple; - * ---- i.e., "new acu" = sqrt(old acu) - - */ - acu = fmax2(acu_min, pow(10., -13 - 2.5/(pp * pp) - 0.5/(a * a))); - tx = prev = 0.; /* keep -Wall happy */ - - for (i_pb=0; i_pb < 1000; i_pb++) { - y = pbeta_raw(xinbta, pp, qq, /*lower_tail = */ TRUE, FALSE); -#ifdef IEEE_754 - if(!R_FINITE(y)) -#else - if (errno) -#endif - ML_ERR_return_NAN; - - y = (y - a) * - exp(logbeta + r * log(xinbta) + t * log1p(-xinbta)); - if (y * yprev <= 0.) - prev = fmax2(fabs(adj),fpu); - g = 1; - for (i_inn=0; i_inn < 1000;i_inn++) { - adj = g * y; - if (fabs(adj) < prev) { - tx = xinbta - adj; /* trial new x */ - if (tx >= 0. && tx <= 1) { - if (prev <= acu) goto L_converged; - if (fabs(y) <= acu) goto L_converged; - if (tx != 0. && tx != 1) - break; - } - } - g /= 3; - } - if (fabs(tx - xinbta) < 1e-15*xinbta) goto L_converged; - xinbta = tx; - yprev = y; - } - /*-- NOT converged: Iteration count --*/ - ML_ERROR(ME_PRECISION, "qbeta"); - -L_converged: - return swap_tail ? 1 - xinbta : xinbta; -} diff --git a/deps/Rmath/src/qbinom.c b/deps/Rmath/src/qbinom.c deleted file mode 100644 index 38ad845762c95..0000000000000 --- a/deps/Rmath/src/qbinom.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000-2009 The R Development Core Team - * Copyright (C) 2003-2009 The R Foundation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * DESCRIPTION - * - * The quantile function of the binomial distribution. - * - * METHOD - * - * Uses the Cornish-Fisher Expansion to include a skewness - * correction to a normal approximation. This gives an - * initial value which never seems to be off by more than - * 1 or 2. A search is then conducted of values close to - * this initial start point. - */ -#include "nmath.h" -#include "dpq.h" - -static double -do_search(double y, double *z, double p, double n, double pr, double incr) -{ - if(*z >= p) { - /* search to the left */ -#ifdef DEBUG_qbinom - REprintf("\tnew z=%7g >= p = %7g --> search to left (y--) ..\n", z,p); -#endif - for(;;) { - double newz; - if(y == 0 || - (newz = pbinom(y - incr, n, pr, /*l._t.*/TRUE, /*log_p*/FALSE)) < p) - return y; - y = fmax2(0, y - incr); - *z = newz; - } - } - else { /* search to the right */ -#ifdef DEBUG_qbinom - REprintf("\tnew z=%7g < p = %7g --> search to right (y++) ..\n", z,p); -#endif - for(;;) { - y = fmin2(y + incr, n); - if(y == n || - (*z = pbinom(y, n, pr, /*l._t.*/TRUE, /*log_p*/FALSE)) >= p) - return y; - } - } -} - - -double qbinom(double p, double n, double pr, int lower_tail, int log_p) -{ - double q, mu, sigma, gamma, z, y; - -#ifdef IEEE_754 - if (ISNAN(p) || ISNAN(n) || ISNAN(pr)) - return p + n + pr; -#endif - if(!R_FINITE(n) || !R_FINITE(pr)) - ML_ERR_return_NAN; - /* if log_p is true, p = -Inf is a legitimate value */ - if(!R_FINITE(p) && !log_p) - ML_ERR_return_NAN; - - if(n != floor(n + 0.5)) ML_ERR_return_NAN; - if (pr < 0 || pr > 1 || n < 0) - ML_ERR_return_NAN; - - R_Q_P01_boundaries(p, 0, n); - - if (pr == 0. || n == 0) return 0.; - - q = 1 - pr; - if(q == 0.) return n; /* covers the full range of the distribution */ - mu = n * pr; - sigma = sqrt(n * pr * q); - gamma = (q - pr) / sigma; - -#ifdef DEBUG_qbinom - REprintf("qbinom(p=%7g, n=%g, pr=%7g, l.t.=%d, log=%d): sigm=%g, gam=%g\n", - p,n,pr, lower_tail, log_p, sigma, gamma); -#endif - /* Note : "same" code in qpois.c, qbinom.c, qnbinom.c -- - * FIXME: This is far from optimal [cancellation for p ~= 1, etc]: */ - if(!lower_tail || log_p) { - p = R_DT_qIv(p); /* need check again (cancellation!): */ - if (p == 0.) return 0.; - if (p == 1.) return n; - } - /* temporary hack --- FIXME --- */ - if (p + 1.01*DBL_EPSILON >= 1.) return n; - - /* y := approx.value (Cornish-Fisher expansion) : */ - z = qnorm(p, 0., 1., /*lower_tail*/TRUE, /*log_p*/FALSE); - y = floor(mu + sigma * (z + gamma * (z*z - 1) / 6) + 0.5); - - if(y > n) /* way off */ y = n; - -#ifdef DEBUG_qbinom - REprintf(" new (p,1-p)=(%7g,%7g), z=qnorm(..)=%7g, y=%5g\n", p, 1-p, z, y); -#endif - z = pbinom(y, n, pr, /*lower_tail*/TRUE, /*log_p*/FALSE); - - /* fuzz to ensure left continuity: */ - p *= 1 - 64*DBL_EPSILON; - - if(n < 1e5) return do_search(y, &z, p, n, pr, 1); - /* Otherwise be a bit cleverer in the search */ - { - double incr = floor(n * 0.001), oldincr; - do { - oldincr = incr; - y = do_search(y, &z, p, n, pr, incr); - incr = fmax2(1, floor(incr/100)); - } while(oldincr > 1 && incr > n*1e-15); - return y; - } -} diff --git a/deps/Rmath/src/qcauchy.c b/deps/Rmath/src/qcauchy.c deleted file mode 100644 index 084ea6bb124d6..0000000000000 --- a/deps/Rmath/src/qcauchy.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000 The R Development Core Team - * Copyright (C) 2005-6 The R Foundation - * - * This version is based on a suggestion by Morten Welinder. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * http://www.gnu.org/copyleft/gpl.html. - * - * DESCRIPTION - * - * The quantile function of the Cauchy distribution. - */ - -#include "nmath.h" -#include "dpq.h" - -double qcauchy(double p, double location, double scale, - int lower_tail, int log_p) -{ -#ifdef IEEE_754 - if (ISNAN(p) || ISNAN(location) || ISNAN(scale)) - return p + location + scale; -#endif - R_Q_P01_check(p); - if (scale <= 0 || !R_FINITE(scale)) { - if (scale == 0) return location; - /* else */ ML_ERR_return_NAN; - } - -#define my_INF location + (lower_tail ? scale : -scale) * ML_POSINF - if (log_p) { - if (p > -1) { - /* when ep := exp(p), - * tan(pi*ep)= -tan(pi*(-ep))= -tan(pi*(-ep)+pi) = -tan(pi*(1-ep)) = - * = -tan(pi*(-expm1(p)) - * for p ~ 0, exp(p) ~ 1, tan(~0) may be better than tan(~pi). - */ - if (p == 0.) /* needed, since 1/tan(-0) = -Inf for some arch. */ - return my_INF; - lower_tail = !lower_tail; - p = -expm1(p); - } else - p = exp(p); - } else if (p == 1.) - return my_INF; - - return location + (lower_tail ? -scale : scale) / tan(M_PI * p); - /* -1/tan(pi * p) = -cot(pi * p) = tan(pi * (p - 1/2)) */ -} diff --git a/deps/Rmath/src/qchisq.c b/deps/Rmath/src/qchisq.c deleted file mode 100644 index ee7cde1c2c482..0000000000000 --- a/deps/Rmath/src/qchisq.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * DESCRIPTION - * - * The quantile function of the chi-squared distribution. - */ - -#include "nmath.h" -#include "dpq.h" - -double qchisq(double p, double df, int lower_tail, int log_p) -{ - return qgamma(p, 0.5 * df, 2.0, lower_tail, log_p); -} diff --git a/deps/Rmath/src/qexp.c b/deps/Rmath/src/qexp.c deleted file mode 100644 index 8ed25f4760282..0000000000000 --- a/deps/Rmath/src/qexp.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * DESCRIPTION - * - * The quantile function of the exponential distribution. - * - */ - -#include "nmath.h" -#include "dpq.h" - -double qexp(double p, double scale, int lower_tail, int log_p) -{ -#ifdef IEEE_754 - if (ISNAN(p) || ISNAN(scale)) - return p + scale; -#endif - if (scale < 0) ML_ERR_return_NAN; - - R_Q_P01_check(p); - if (p == R_DT_0) - return 0; - - return - scale * R_DT_Clog(p); -} diff --git a/deps/Rmath/src/qf.c b/deps/Rmath/src/qf.c deleted file mode 100644 index edfac0d6b7282..0000000000000 --- a/deps/Rmath/src/qf.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000-8 The R Development Core Team - * Copyright (C) 2005 The R Foundation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * DESCRIPTION - * - * The quantile function of the F distribution. -*/ - -#include "nmath.h" -#include "dpq.h" - -double qf(double p, double df1, double df2, int lower_tail, int log_p) -{ -#ifdef IEEE_754 - if (ISNAN(p) || ISNAN(df1) || ISNAN(df2)) - return p + df1 + df2; -#endif - if (df1 <= 0. || df2 <= 0.) ML_ERR_return_NAN; - - R_Q_P01_boundaries(p, 0, ML_POSINF); - - /* fudge the extreme DF cases -- qbeta doesn't do this well. - But we still need to fudge the infinite ones. - */ - - if (df1 <= df2 && df2 > 4e5) { - if(!R_FINITE(df1)) /* df1 == df2 == Inf : */ - return 1.; - /* else */ - return qchisq(p, df1, lower_tail, log_p) / df1; - } - if (df1 > 4e5) { /* and so df2 < df1 */ - return df2 / qchisq(p, df2, !lower_tail, log_p); - } - - p = (1. / qbeta(p, df2/2, df1/2, !lower_tail, log_p) - 1.) * (df2 / df1); - return ML_VALID(p) ? p : ML_NAN; -} diff --git a/deps/Rmath/src/qgamma.c b/deps/Rmath/src/qgamma.c deleted file mode 100644 index bd07b564d75ad..0000000000000 --- a/deps/Rmath/src/qgamma.c +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000--2011 The R Development Core Team - * Copyright (C) 2004--2009 The R Foundation - * based on AS 91 (C) 1979 Royal Statistical Society - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * DESCRIPTION - * - * Compute the quantile function of the gamma distribution. - * - * NOTES - * - * This function is based on the Applied Statistics - * Algorithm AS 91 ("ppchi2") and via pgamma(.) AS 239. - * - * R core improvements: - * o lower_tail, log_p - * o non-trivial result for p outside [0.000002, 0.999998] - * o p ~ 1 no longer gives +Inf; final Newton step(s) - * - * REFERENCES - * - * Best, D. J. and D. E. Roberts (1975). - * Percentage Points of the Chi-Squared Distribution. - * Applied Statistics 24, page 385. */ - -#include "nmath.h" -#include "dpq.h" - -#ifdef DEBUG_qgamma -# define DEBUG_q -#endif - -attribute_hidden -double qchisq_appr(double p, double nu, double g /* = log Gamma(nu/2) */, - int lower_tail, int log_p, double tol /* EPS1 */) -{ -#define C7 4.67 -#define C8 6.66 -#define C9 6.73 -#define C10 13.32 - - double alpha, a, c, ch, p1; - double p2, q, t, x; - - /* test arguments and initialise */ - -#ifdef IEEE_754 - if (ISNAN(p) || ISNAN(nu)) - return p + nu; -#endif - R_Q_P01_check(p); - if (nu <= 0) ML_ERR_return_NAN; - - alpha = 0.5 * nu;/* = [pq]gamma() shape */ - c = alpha-1; - - if(nu < (-1.24)*(p1 = R_DT_log(p))) { /* for small chi-squared */ - /* log(alpha) + g = log(alpha) + log(gamma(alpha)) = - * = log(alpha*gamma(alpha)) = lgamma(alpha+1) suffers from - * catastrophic cancellation when alpha << 1 - */ - double lgam1pa = (alpha < 0.5) ? lgamma1p(alpha) : (log(alpha) + g); - ch = exp((lgam1pa + p1)/alpha + M_LN2); -#ifdef DEBUG_qgamma - REprintf(" small chi-sq., ch0 = %g\n", ch); -#endif - - } else if(nu > 0.32) { /* using Wilson and Hilferty estimate */ - - x = qnorm(p, 0, 1, lower_tail, log_p); - p1 = 2./(9*nu); - ch = nu*pow(x*sqrt(p1) + 1-p1, 3); - -#ifdef DEBUG_qgamma - REprintf(" nu > .32: Wilson-Hilferty; x = %7g\n", x); -#endif - /* approximation for p tending to 1: */ - if( ch > 2.2*nu + 6 ) - ch = -2*(R_DT_Clog(p) - c*log(0.5*ch) + g); - - } else { /* "small nu" : 1.24*(-log(p)) <= nu <= 0.32 */ - - ch = 0.4; - a = R_DT_Clog(p) + g + c*M_LN2; -#ifdef DEBUG_qgamma - REprintf(" nu <= .32: a = %7g\n", a); -#endif - do { - q = ch; - p1 = 1. / (1+ch*(C7+ch)); - p2 = ch*(C9+ch*(C8+ch)); - t = -0.5 +(C7+2*ch)*p1 - (C9+ch*(C10+3*ch))/p2; - ch -= (1- exp(a+0.5*ch)*p2*p1)/t; - } while(fabs(q - ch) > tol * fabs(ch)); - } - - return ch; -} - -double qgamma(double p, double alpha, double scale, int lower_tail, int log_p) -/* shape = alpha */ -{ -#define EPS1 1e-2 -#define EPS2 5e-7/* final precision of AS 91 */ -#define EPS_N 1e-15/* precision of Newton step / iterations */ -#define LN_EPS -36.043653389117156 /* = log(.Machine$double.eps) iff IEEE_754 */ - -#define MAXIT 1000/* was 20 */ - -#define pMIN 1e-100 /* was 0.000002 = 2e-6 */ -#define pMAX (1-1e-14)/* was (1-1e-12) and 0.999998 = 1 - 2e-6 */ - - const static double - i420 = 1./ 420., - i2520 = 1./ 2520., - i5040 = 1./ 5040; - - double p_, a, b, c, g, ch, ch0, p1; - double p2, q, s1, s2, s3, s4, s5, s6, t, x; - int i, max_it_Newton = 1; - - /* test arguments and initialise */ - -#ifdef IEEE_754 - if (ISNAN(p) || ISNAN(alpha) || ISNAN(scale)) - return p + alpha + scale; -#endif - R_Q_P01_boundaries(p, 0., ML_POSINF); - - if (alpha < 0 || scale <= 0) ML_ERR_return_NAN; - - if (alpha == 0) /* all mass at 0 : */ return 0.; - - if (alpha < 1e-10) { - /* Warning seems unnecessary now: */ -#ifdef _DO_WARN_qgamma_ - MATHLIB_WARNING("value of shape (%g) is extremely small: results may be unreliable", alpha); -#endif - max_it_Newton = 7;/* may still be increased below */ - } - - p_ = R_DT_qIv(p);/* lower_tail prob (in any case) */ - -#ifdef DEBUG_qgamma - REprintf("qgamma(p=%7g, alpha=%7g, scale=%7g, l.t.=%2d, log_p=%2d): ", - p,alpha,scale, lower_tail, log_p); -#endif - g = lgammafn(alpha);/* log Gamma(v/2) */ - - /*----- Phase I : Starting Approximation */ - ch = qchisq_appr(p, /* nu= 'df' = */ 2*alpha, /* lgamma(nu/2)= */ g, - lower_tail, log_p, /* tol= */ EPS1); - if(!R_FINITE(ch)) { - /* forget about all iterations! */ - max_it_Newton = 0; goto END; - } - if(ch < EPS2) {/* Corrected according to AS 91; MM, May 25, 1999 */ - max_it_Newton = 20; - goto END;/* and do Newton steps */ - } - - /* FIXME: This (cutoff to {0, +Inf}) is far from optimal - * ----- when log_p or !lower_tail, but NOT doing it can be even worse */ - if(p_ > pMAX || p_ < pMIN) { - /* did return ML_POSINF or 0.; much better: */ - max_it_Newton = 20; - goto END;/* and do Newton steps */ - } - -#ifdef DEBUG_qgamma - REprintf("\t==> ch = %10g:", ch); -#endif - -/*----- Phase II: Iteration - * Call pgamma() [AS 239] and calculate seven term taylor series - */ - c = alpha-1; - s6 = (120+c*(346+127*c)) * i5040; /* used below, is "const" */ - - ch0 = ch;/* save initial approx. */ - for(i=1; i <= MAXIT; i++ ) { - q = ch; - p1 = 0.5*ch; - p2 = p_ - pgamma_raw(p1, alpha, /*lower_tail*/TRUE, /*log_p*/FALSE); -#ifdef DEBUG_qgamma - if(i == 1) REprintf(" Ph.II iter; ch=%g, p2=%g\n", ch, p2); - if(i >= 2) REprintf(" it=%d, ch=%g, p2=%g\n", i, ch, p2); -#endif -#ifdef IEEE_754 - if(!R_FINITE(p2) || ch <= 0) -#else - if(errno != 0 || ch <= 0) -#endif - { ch = ch0; max_it_Newton = 27; goto END; }/*was return ML_NAN;*/ - - t = p2*exp(alpha*M_LN2+g+p1-c*log(ch)); - b = t/ch; - a = 0.5*t - b*c; - s1 = (210+ a*(140+a*(105+a*(84+a*(70+60*a))))) * i420; - s2 = (420+ a*(735+a*(966+a*(1141+1278*a)))) * i2520; - s3 = (210+ a*(462+a*(707+932*a))) * i2520; - s4 = (252+ a*(672+1182*a) + c*(294+a*(889+1740*a))) * i5040; - s5 = (84+2264*a + c*(1175+606*a)) * i2520; - - ch += t*(1+0.5*t*s1-b*c*(s1-b*(s2-b*(s3-b*(s4-b*(s5-b*s6)))))); - if(fabs(q - ch) < EPS2*ch) - goto END; - if(fabs(q - ch) > 0.1*ch) {/* diverging? -- also forces ch > 0 */ - if(ch < q) ch = 0.9 * q; else ch = 1.1 * q; - } - } -/* no convergence in MAXIT iterations -- but we add Newton now... */ -#ifdef DEBUG_q - MATHLIB_WARNING3("qgamma(%g) not converged in %d iterations; rel.ch=%g\n", - p, MAXIT, ch/fabs(q - ch)); -#endif -/* was - * ML_ERROR(ME_PRECISION, "qgamma"); - * does nothing in R !*/ - -END: -/* PR# 2214 : From: Morten Welinder , Fri, 25 Oct 2002 16:50 - -------- To: R-bugs@biostat.ku.dk Subject: qgamma precision - - * With a final Newton step, double accuracy, e.g. for (p= 7e-4; nu= 0.9) - * - * Improved (MM): - only if rel.Err > EPS_N (= 1e-15); - * - also for lower_tail = FALSE or log_p = TRUE - * - optionally *iterate* Newton - */ - x = 0.5*scale*ch; - if(max_it_Newton) { - /* always use log scale */ - if (!log_p) { - p = log(p); - log_p = TRUE; - } - if(x == 0) { - const double _1_p = 1. + 1e-7; - const double _1_m = 1. - 1e-7; - x = DBL_MIN; - p_ = pgamma(x, alpha, scale, lower_tail, log_p); - if(( lower_tail && p_ > p * _1_p) || - (!lower_tail && p_ < p * _1_m)) - return(0.); - /* else: continue, using x = DBL_MIN instead of 0 */ - } - else - p_ = pgamma(x, alpha, scale, lower_tail, log_p); - if(p_ == ML_NEGINF) return 0; /* PR#14710 */ - for(i = 1; i <= max_it_Newton; i++) { - p1 = p_ - p; -#ifdef DEBUG_qgamma - if(i == 1) REprintf("\n it=%d: p=%g, x = %g, p.=%g; p1=d{p}=%g\n", - i, p, x, p_, p1); - if(i >= 2) REprintf(" x{it= %d} = %g, p.=%g, p1=d{p}=%g\n", - i, x, p_, p1); -#endif - if(fabs(p1) < fabs(EPS_N * p)) - break; - /* else */ - if((g = dgamma(x, alpha, scale, log_p)) == R_D__0) { -#ifdef DEBUG_q - if(i == 1) REprintf("no final Newton step because dgamma(*)== 0!\n"); -#endif - break; - } - /* else : - * delta x = f(x)/f'(x); - * if(log_p) f(x) := log P(x) - p; f'(x) = d/dx log P(x) = P' / P - * ==> f(x)/f'(x) = f*P / P' = f*exp(p_) / P' (since p_ = log P(x)) - */ - t = log_p ? p1*exp(p_ - g) : p1/g ;/* = "delta x" */ - t = lower_tail ? x - t : x + t; - p_ = pgamma (t, alpha, scale, lower_tail, log_p); - if (fabs(p_ - p) > fabs(p1) || - (i > 1 && fabs(p_ - p) == fabs(p1)) /* <- against flip-flop */) { - /* no improvement */ -#ifdef DEBUG_qgamma - if(i == 1 && max_it_Newton > 1) - REprintf("no Newton step done since delta{p} >= last delta\n"); -#endif - break; - } /* else : */ -#ifdef Harmful_notably_if_max_it_Newton_is_1 - /* control step length: this could have started at - the initial approximation */ - if(t > 1.1*x) t = 1.1*x; - else if(t < 0.9*x) t = 0.9*x; -#endif - x = t; - } - } - - return x; -} diff --git a/deps/Rmath/src/qgeom.c b/deps/Rmath/src/qgeom.c deleted file mode 100644 index bea4accf358f9..0000000000000 --- a/deps/Rmath/src/qgeom.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000 The R Development Core Team - * Copyright (C) 2004--2005 The R Foundation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * DESCRIPTION - * - * The quantile function of the geometric distribution. - */ - -#include "nmath.h" -#include "dpq.h" - -double qgeom(double p, double prob, int lower_tail, int log_p) -{ - if (prob <= 0 || prob > 1) ML_ERR_return_NAN; - - R_Q_P01_boundaries(p, 0, ML_POSINF); - -#ifdef IEEE_754 - if (ISNAN(p) || ISNAN(prob)) - return p + prob; -#endif - - if (prob == 1) return(0); -/* add a fuzz to ensure left continuity */ - return ceil(R_DT_Clog(p) / log1p(- prob) - 1 - 1e-7); -} diff --git a/deps/Rmath/src/qhyper.c b/deps/Rmath/src/qhyper.c deleted file mode 100644 index 0e4e5a094fb41..0000000000000 --- a/deps/Rmath/src/qhyper.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * DESCRIPTION - * - * The quantile function of the hypergeometric distribution. - */ - -#include "nmath.h" -#include "dpq.h" - -double qhyper(double p, double NR, double NB, double n, - int lower_tail, int log_p) -{ -/* This is basically the same code as ./phyper.c *used* to be --> FIXME! */ - double N, xstart, xend, xr, xb, sum, term; - int small_N; -#ifdef IEEE_754 - if (ISNAN(p) || ISNAN(NR) || ISNAN(NB) || ISNAN(n)) - return p + NR + NB + n; -#endif - if(!R_FINITE(p) || !R_FINITE(NR) || !R_FINITE(NB) || !R_FINITE(n)) - ML_ERR_return_NAN; - - NR = floor(NR + 0.5); - NB = floor(NB + 0.5); - N = NR + NB; - n = floor(n + 0.5); - if (NR < 0 || NB < 0 || n < 0 || n > N) - ML_ERR_return_NAN; - - /* Goal: Find xr (= #{red balls in sample}) such that - * phyper(xr, NR,NB, n) >= p > phyper(xr - 1, NR,NB, n) - */ - - xstart = fmax2(0, n - NB); - xend = fmin2(n, NR); - - R_Q_P01_boundaries(p, xstart, xend); - - xr = xstart; - xb = n - xr;/* always ( = #{black balls in sample} ) */ - - small_N = (N < 1000); /* won't have underflow in product below */ - /* if N is small, term := product.ratio( bin.coef ); - otherwise work with its logarithm to protect against underflow */ - term = lfastchoose(NR, xr) + lfastchoose(NB, xb) - lfastchoose(N, n); - if(small_N) term = exp(term); - NR -= xr; - NB -= xb; - - if(!lower_tail || log_p) { - p = R_DT_qIv(p); - } - p *= 1 - 1000*DBL_EPSILON; /* was 64, but failed on FreeBSD sometimes */ - sum = small_N ? term : exp(term); - - while(sum < p && xr < xend) { - xr++; - NB++; - if (small_N) term *= (NR / xr) * (xb / NB); - else term += log((NR / xr) * (xb / NB)); - sum += small_N ? term : exp(term); - xb--; - NR--; - } - return xr; -} diff --git a/deps/Rmath/src/qlnorm.c b/deps/Rmath/src/qlnorm.c deleted file mode 100644 index 55a3a027832ae..0000000000000 --- a/deps/Rmath/src/qlnorm.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000-8 The R Development Core Team - * Copyright (C) 2005 The R Foundation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * DESCRIPTION - * - * This the lognormal quantile function. - */ - -#include "nmath.h" -#include "dpq.h" - -double qlnorm(double p, double meanlog, double sdlog, int lower_tail, int log_p) -{ -#ifdef IEEE_754 - if (ISNAN(p) || ISNAN(meanlog) || ISNAN(sdlog)) - return p + meanlog + sdlog; -#endif - R_Q_P01_boundaries(p, 0, ML_POSINF); - - return exp(qnorm(p, meanlog, sdlog, lower_tail, log_p)); -} diff --git a/deps/Rmath/src/qlogis.c b/deps/Rmath/src/qlogis.c deleted file mode 100644 index 72fbf379eeef8..0000000000000 --- a/deps/Rmath/src/qlogis.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * R : A Computer Language for Statistical Data Analysis - * Copyright (C) 1995, 1996 Robert Gentleman and Ross Ihaka - * Copyright (C) 2000 The R Development Core Team - * Copyright (C) 2005 The R Foundation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - */ - -#include "nmath.h" -#include "dpq.h" - -double qlogis(double p, double location, double scale, int lower_tail, int log_p) -{ -#ifdef IEEE_754 - if (ISNAN(p) || ISNAN(location) || ISNAN(scale)) - return p + location + scale; -#endif - R_Q_P01_boundaries(p, ML_NEGINF, ML_POSINF); - - if (scale < 0.) ML_ERR_return_NAN; - if (scale == 0.) return location; - - /* p := logit(p) = log( p / (1-p) ) : */ - if(log_p) { - if(lower_tail) - p = p - R_Log1_Exp(p); - else - p = R_Log1_Exp(p) - p; - } - else - p = log(lower_tail ? (p / (1. - p)) : ((1. - p) / p)); - - return location + scale * p; -} diff --git a/deps/Rmath/src/qnbeta.c b/deps/Rmath/src/qnbeta.c deleted file mode 100644 index 4b22a7a9695f0..0000000000000 --- a/deps/Rmath/src/qnbeta.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * R : A Computer Language for Statistical Data Analysis - * Copyright (C) 2006 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - */ - -#include "nmath.h" -#include "dpq.h" - -double qnbeta(double p, double a, double b, double ncp, - int lower_tail, int log_p) -{ - const static double accu = 1e-15; - const static double Eps = 1e-14; /* must be > accu */ - - double ux, lx, nx, pp; - -#ifdef IEEE_754 - if (ISNAN(p) || ISNAN(a) || ISNAN(b) || ISNAN(ncp)) - return p + a + b + ncp; -#endif - if (!R_FINITE(a)) ML_ERR_return_NAN; - - if (ncp < 0. || a <= 0. || b <= 0.) ML_ERR_return_NAN; - - R_Q_P01_boundaries(p, 0, 1); - - p = R_DT_qIv(p); - - /* Invert pnbeta(.) : - * 1. finding an upper and lower bound */ - if(p > 1 - DBL_EPSILON) return 1.0; - pp = fmin2(1 - DBL_EPSILON, p * (1 + Eps)); - for(ux = 0.5; - ux < 1 - DBL_EPSILON && pnbeta(ux, a, b, ncp, TRUE, FALSE) < pp; - ux = 0.5*(1+ux)); - pp = p * (1 - Eps); - for(lx = 0.5; - lx > DBL_MIN && pnbeta(lx, a, b, ncp, TRUE, FALSE) > pp; - lx *= 0.5); - - /* 2. interval (lx,ux) halving : */ - do { - nx = 0.5 * (lx + ux); - if (pnbeta(nx, a, b, ncp, TRUE, FALSE) > p) ux = nx; else lx = nx; - } - while ((ux - lx) / nx > accu); - - return 0.5 * (ux + lx); -} diff --git a/deps/Rmath/src/qnbinom.c b/deps/Rmath/src/qnbinom.c deleted file mode 100644 index b68141599ec20..0000000000000 --- a/deps/Rmath/src/qnbinom.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000-2008 The R Development Core Team - * Copyright (C) 2005 The R Foundation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * double qnbinom(double p, double size, double prob, - * int lower_tail, int log_p) - * - * DESCRIPTION - * - * The quantile function of the negative binomial distribution. - * - * NOTES - * - * x = the number of failures before the n-th success - * - * METHOD - * - * Uses the Cornish-Fisher Expansion to include a skewness - * correction to a normal approximation. This gives an - * initial value which never seems to be off by more than - * 1 or 2. A search is then conducted of values close to - * this initial start point. - */ - -#include "nmath.h" -#include "dpq.h" - -static double -do_search(double y, double *z, double p, double n, double pr, double incr) -{ - if(*z >= p) { - /* search to the left */ - for(;;) { - if(y == 0 || - (*z = pnbinom(y - incr, n, pr, /*l._t.*/TRUE, /*log_p*/FALSE)) < p) - return y; - y = fmax2(0, y - incr); - } - } - else { /* search to the right */ - - for(;;) { - y = y + incr; - if((*z = pnbinom(y, n, pr, /*l._t.*/TRUE, /*log_p*/FALSE)) >= p) - return y; - } - } -} - - -double qnbinom(double p, double size, double prob, int lower_tail, int log_p) -{ - double P, Q, mu, sigma, gamma, z, y; - -#ifdef IEEE_754 - if (ISNAN(p) || ISNAN(size) || ISNAN(prob)) - return p + size + prob; -#endif - if (prob <= 0 || prob > 1 || size <= 0) ML_ERR_return_NAN; - /* FIXME: size = 0 is well defined ! */ - if (prob == 1) return 0; - - R_Q_P01_boundaries(p, 0, ML_POSINF); - - Q = 1.0 / prob; - P = (1.0 - prob) * Q; - mu = size * P; - sigma = sqrt(size * P * Q); - gamma = (Q + P)/sigma; - - /* Note : "same" code in qpois.c, qbinom.c, qnbinom.c -- - * FIXME: This is far from optimal [cancellation for p ~= 1, etc]: */ - if(!lower_tail || log_p) { - p = R_DT_qIv(p); /* need check again (cancellation!): */ - if (p == R_DT_0) return 0; - if (p == R_DT_1) return ML_POSINF; - } - /* temporary hack --- FIXME --- */ - if (p + 1.01*DBL_EPSILON >= 1.) return ML_POSINF; - - /* y := approx.value (Cornish-Fisher expansion) : */ - z = qnorm(p, 0., 1., /*lower_tail*/TRUE, /*log_p*/FALSE); - y = floor(mu + sigma * (z + gamma * (z*z - 1) / 6) + 0.5); - - z = pnbinom(y, size, prob, /*lower_tail*/TRUE, /*log_p*/FALSE); - - /* fuzz to ensure left continuity: */ - p *= 1 - 64*DBL_EPSILON; - - /* If the C-F value is not too large a simple search is OK */ - if(y < 1e5) return do_search(y, &z, p, size, prob, 1); - /* Otherwise be a bit cleverer in the search */ - { - double incr = floor(y * 0.001), oldincr; - do { - oldincr = incr; - y = do_search(y, &z, p, size, prob, incr); - incr = fmax2(1, floor(incr/100)); - } while(oldincr > 1 && incr > y*1e-15); - return y; - } -} - -double qnbinom_mu(double p, double size, double mu, int lower_tail, int log_p) -{ -/* FIXME! Implement properly!! (not losing accuracy for very large size (prob ~= 1)*/ - return qnbinom(p, size, /* prob = */ size/(size+mu), lower_tail, log_p); -} diff --git a/deps/Rmath/src/qnchisq.c b/deps/Rmath/src/qnchisq.c deleted file mode 100644 index 0563e399571fe..0000000000000 --- a/deps/Rmath/src/qnchisq.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * R : A Computer Language for Statistical Data Analysis - * Copyright (C) 1995, 1996 Robert Gentleman and Ross Ihaka - * Copyright (C) 2000-2008 The R Development Core Team - * Copyright (C) 2004 The R Foundation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - */ - -#include "nmath.h" -#include "dpq.h" - -double qnchisq(double p, double df, double ncp, int lower_tail, int log_p) -{ - const static double accu = 1e-13; - const static double racc = 4*DBL_EPSILON; - /* these two are for the "search" loops, can have less accuracy: */ - const static double Eps = 1e-11; /* must be > accu */ - const static double rEps= 1e-10; /* relative tolerance ... */ - - double ux, lx, ux0, nx, pp; - -#ifdef IEEE_754 - if (ISNAN(p) || ISNAN(df) || ISNAN(ncp)) - return p + df + ncp; -#endif - if (!R_FINITE(df)) ML_ERR_return_NAN; - - /* Was - * df = floor(df + 0.5); - * if (df < 1 || ncp < 0) ML_ERR_return_NAN; - */ - if (df < 0 || ncp < 0) ML_ERR_return_NAN; - - R_Q_P01_boundaries(p, 0, ML_POSINF); - - /* Invert pnchisq(.) : - * 1. finding an upper and lower bound */ - { - /* This is Pearson's (1959) approximation, - which is usually good to 4 figs or so. */ - double b, c, ff; - b = (ncp*ncp)/(df + 3*ncp); - c = (df + 3*ncp)/(df + 2*ncp); - ff = (df + 2 * ncp)/(c*c); - ux = b + c * qchisq(p, ff, lower_tail, log_p); - if(ux < 0) ux = 1; - ux0 = ux; - } - p = R_D_qIv(p); - - if(!lower_tail && ncp >= 80) { - /* pnchisq is only for lower.tail = TRUE */ - if(p < 1e-10) ML_ERROR(ME_PRECISION, "qnchisq"); - p = 1. - p; - lower_tail = TRUE; - } - - if(lower_tail) { - if(p > 1 - DBL_EPSILON) return ML_POSINF; - pp = fmin2(1 - DBL_EPSILON, p * (1 + Eps)); - for(ux = ux; - ux < DBL_MAX && - pnchisq_raw(ux, df, ncp, Eps, rEps, 10000, TRUE) < pp; - ux *= 2); - pp = p * (1 - Eps); - for(lx = fmin2(ux0, DBL_MAX); - lx > DBL_MIN && - pnchisq_raw(lx, df, ncp, Eps, rEps, 10000, TRUE) > pp; - lx *= 0.5); - } - else { - if(p > 1 - DBL_EPSILON) return 0.0; - pp = fmin2(1 - DBL_EPSILON, p * (1 + Eps)); - for(ux = ux; - ux < DBL_MAX && - pnchisq_raw(ux, df, ncp, Eps, rEps, 10000, FALSE) > pp; - ux *= 2); - pp = p * (1 - Eps); - for(lx = fmin2(ux0, DBL_MAX); - lx > DBL_MIN && - pnchisq_raw(lx, df, ncp, Eps, rEps, 10000, FALSE) < pp; - lx *= 0.5); - } - - /* 2. interval (lx,ux) halving : */ - if(lower_tail) { - do { - nx = 0.5 * (lx + ux); - if (pnchisq_raw(nx, df, ncp, accu, racc, 100000, TRUE) > p) - ux = nx; - else - lx = nx; - } - while ((ux - lx) / nx > accu); - } else { - do { - nx = 0.5 * (lx + ux); - if (pnchisq_raw(nx, df, ncp, accu, racc, 100000, FALSE) < p) - ux = nx; - else - lx = nx; - } - while ((ux - lx) / nx > accu); - } - return 0.5 * (ux + lx); -} diff --git a/deps/Rmath/src/qnf.c b/deps/Rmath/src/qnf.c deleted file mode 100644 index 01fe1f48b4786..0000000000000 --- a/deps/Rmath/src/qnf.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * R : A Computer Language for Statistical Data Analysis - * Copyright (C) 2006-8 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - */ - -#include "nmath.h" -#include "dpq.h" - -double qnf(double p, double df1, double df2, double ncp, int lower_tail, - int log_p) -{ - double y; - -#ifdef IEEE_754 - if (ISNAN(p) || ISNAN(df1) || ISNAN(df2) || ISNAN(ncp)) - return p + df1 + df2 + ncp; -#endif - if (df1 <= 0. || df2 <= 0. || ncp < 0) ML_ERR_return_NAN; - if (!R_FINITE(ncp)) ML_ERR_return_NAN; - if (!R_FINITE(df1) && !R_FINITE(df2)) ML_ERR_return_NAN; - R_Q_P01_boundaries(p, 0, ML_POSINF); - - if (df2 > 1e8) /* avoid problems with +Inf and loss of accuracy */ - return qnchisq(p, df1, ncp, lower_tail, log_p)/df1; - - y = qnbeta(p, df1 / 2., df2 / 2., ncp, lower_tail, log_p); - return y/(1-y) * (df2/df1); -} diff --git a/deps/Rmath/src/qnorm.c b/deps/Rmath/src/qnorm.c deleted file mode 100644 index 35636ffde793b..0000000000000 --- a/deps/Rmath/src/qnorm.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000--2005 The R Development Core Team - * based on AS 111 (C) 1977 Royal Statistical Society - * and on AS 241 (C) 1988 Royal Statistical Society - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * double qnorm5(double p, double mu, double sigma, - * int lower_tail, int log_p) - * {qnorm (..) is synonymous and preferred inside R} - * - * DESCRIPTION - * - * Compute the quantile function for the normal distribution. - * - * For small to moderate probabilities, algorithm referenced - * below is used to obtain an initial approximation which is - * polished with a final Newton step. - * - * For very large arguments, an algorithm of Wichura is used. - * - * REFERENCE - * - * Beasley, J. D. and S. G. Springer (1977). - * Algorithm AS 111: The percentage points of the normal distribution, - * Applied Statistics, 26, 118-121. - * - * Wichura, M.J. (1988). - * Algorithm AS 241: The Percentage Points of the Normal Distribution. - * Applied Statistics, 37, 477-484. - */ - -#include "nmath.h" -#include "dpq.h" - -double qnorm5(double p, double mu, double sigma, int lower_tail, int log_p) -{ - double p_, q, r, val; - -#ifdef IEEE_754 - if (ISNAN(p) || ISNAN(mu) || ISNAN(sigma)) - return p + mu + sigma; -#endif - R_Q_P01_boundaries(p, ML_NEGINF, ML_POSINF); - - if(sigma < 0) ML_ERR_return_NAN; - if(sigma == 0) return mu; - - p_ = R_DT_qIv(p);/* real lower_tail prob. p */ - q = p_ - 0.5; - -#ifdef DEBUG_qnorm - REprintf("qnorm(p=%10.7g, m=%g, s=%g, l.t.= %d, log= %d): q = %g\n", - p,mu,sigma, lower_tail, log_p, q); -#endif - - -/*-- use AS 241 --- */ -/* double ppnd16_(double *p, long *ifault)*/ -/* ALGORITHM AS241 APPL. STATIST. (1988) VOL. 37, NO. 3 - - Produces the normal deviate Z corresponding to a given lower - tail area of P; Z is accurate to about 1 part in 10**16. - - (original fortran code used PARAMETER(..) for the coefficients - and provided hash codes for checking them...) -*/ - if (fabs(q) <= .425) {/* 0.075 <= p <= 0.925 */ - r = .180625 - q * q; - val = - q * (((((((r * 2509.0809287301226727 + - 33430.575583588128105) * r + 67265.770927008700853) * r + - 45921.953931549871457) * r + 13731.693765509461125) * r + - 1971.5909503065514427) * r + 133.14166789178437745) * r + - 3.387132872796366608) - / (((((((r * 5226.495278852854561 + - 28729.085735721942674) * r + 39307.89580009271061) * r + - 21213.794301586595867) * r + 5394.1960214247511077) * r + - 687.1870074920579083) * r + 42.313330701600911252) * r + 1.); - } - else { /* closer than 0.075 from {0,1} boundary */ - - /* r = min(p, 1-p) < 0.075 */ - if (q > 0) - r = R_DT_CIv(p);/* 1-p */ - else - r = p_;/* = R_DT_Iv(p) ^= p */ - - r = sqrt(- ((log_p && - ((lower_tail && q <= 0) || (!lower_tail && q > 0))) ? - p : /* else */ log(r))); - /* r = sqrt(-log(r)) <==> min(p, 1-p) = exp( - r^2 ) */ -#ifdef DEBUG_qnorm - REprintf("\t close to 0 or 1: r = %7g\n", r); -#endif - - if (r <= 5.) { /* <==> min(p,1-p) >= exp(-25) ~= 1.3888e-11 */ - r += -1.6; - val = (((((((r * 7.7454501427834140764e-4 + - .0227238449892691845833) * r + .24178072517745061177) * - r + 1.27045825245236838258) * r + - 3.64784832476320460504) * r + 5.7694972214606914055) * - r + 4.6303378461565452959) * r + - 1.42343711074968357734) - / (((((((r * - 1.05075007164441684324e-9 + 5.475938084995344946e-4) * - r + .0151986665636164571966) * r + - .14810397642748007459) * r + .68976733498510000455) * - r + 1.6763848301838038494) * r + - 2.05319162663775882187) * r + 1.); - } - else { /* very close to 0 or 1 */ - r += -5.; - val = (((((((r * 2.01033439929228813265e-7 + - 2.71155556874348757815e-5) * r + - .0012426609473880784386) * r + .026532189526576123093) * - r + .29656057182850489123) * r + - 1.7848265399172913358) * r + 5.4637849111641143699) * - r + 6.6579046435011037772) - / (((((((r * - 2.04426310338993978564e-15 + 1.4215117583164458887e-7)* - r + 1.8463183175100546818e-5) * r + - 7.868691311456132591e-4) * r + .0148753612908506148525) - * r + .13692988092273580531) * r + - .59983220655588793769) * r + 1.); - } - - if(q < 0.0) - val = -val; - /* return (q >= 0.)? r : -r ;*/ - } - return mu + sigma * val; -} - - - diff --git a/deps/Rmath/src/qnt.c b/deps/Rmath/src/qnt.c deleted file mode 100644 index 6e893b724ad5b..0000000000000 --- a/deps/Rmath/src/qnt.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * R : A Computer Language for Statistical Data Analysis - * Copyright (C) 2006-8 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - */ - -#include "nmath.h" -#include "dpq.h" - -double qnt(double p, double df, double ncp, int lower_tail, int log_p) -{ - const static double accu = 1e-13; - const static double Eps = 1e-11; /* must be > accu */ - - double ux, lx, nx, pp; - -#ifdef IEEE_754 - if (ISNAN(p) || ISNAN(df) || ISNAN(ncp)) - return p + df + ncp; -#endif - if (!R_FINITE(df)) ML_ERR_return_NAN; - - /* Was - * df = floor(df + 0.5); - * if (df < 1 || ncp < 0) ML_ERR_return_NAN; - */ - if (df <= 0.0) ML_ERR_return_NAN; - - if(ncp == 0.0 && df >= 1.0) return qt(p, df, lower_tail, log_p); - - R_Q_P01_boundaries(p, ML_NEGINF, ML_POSINF); - - p = R_DT_qIv(p); - - /* Invert pnt(.) : - * 1. finding an upper and lower bound */ - if(p > 1 - DBL_EPSILON) return ML_POSINF; - pp = fmin2(1 - DBL_EPSILON, p * (1 + Eps)); - for(ux = fmax2(1., ncp); - ux < DBL_MAX && pnt(ux, df, ncp, TRUE, FALSE) < pp; - ux *= 2); - pp = p * (1 - Eps); - for(lx = fmin2(-1., -ncp); - lx > -DBL_MAX && pnt(lx, df, ncp, TRUE, FALSE) > pp; - lx *= 2); - - /* 2. interval (lx,ux) halving : */ - do { - nx = 0.5 * (lx + ux); - if (pnt(nx, df, ncp, TRUE, FALSE) > p) ux = nx; else lx = nx; - } - while ((ux - lx) / fabs(nx) > accu); - - return 0.5 * (lx + ux); -} diff --git a/deps/Rmath/src/qpois.c b/deps/Rmath/src/qpois.c deleted file mode 100644 index e5628b6e0cfa1..0000000000000 --- a/deps/Rmath/src/qpois.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000-2009 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * DESCRIPTION - * - * The quantile function of the Poisson distribution. - * - * METHOD - * - * Uses the Cornish-Fisher Expansion to include a skewness - * correction to a normal approximation. This gives an - * initial value which never seems to be off by more than - * 1 or 2. A search is then conducted of values close to - * this initial start point. - */ - -#include "nmath.h" -#include "dpq.h" - -static double -do_search(double y, double *z, double p, double lambda, double incr) -{ - if(*z >= p) { - /* search to the left */ - for(;;) { - if(y == 0 || - (*z = ppois(y - incr, lambda, /*l._t.*/TRUE, /*log_p*/FALSE)) < p) - return y; - y = fmax2(0, y - incr); - } - } - else { /* search to the right */ - - for(;;) { - y = y + incr; - if((*z = ppois(y, lambda, /*l._t.*/TRUE, /*log_p*/FALSE)) >= p) - return y; - } - } -} - -double qpois(double p, double lambda, int lower_tail, int log_p) -{ - double mu, sigma, gamma, z, y; -#ifdef IEEE_754 - if (ISNAN(p) || ISNAN(lambda)) - return p + lambda; -#endif - if(!R_FINITE(lambda)) - ML_ERR_return_NAN; - if(lambda < 0) ML_ERR_return_NAN; - if(lambda == 0) return 0; - - R_Q_P01_boundaries(p, 0, ML_POSINF); - - mu = lambda; - sigma = sqrt(lambda); - /* gamma = sigma; PR#8058 should be kurtosis which is mu^-0.5 */ - gamma = 1.0/sigma; - - /* Note : "same" code in qpois.c, qbinom.c, qnbinom.c -- - * FIXME: This is far from optimal [cancellation for p ~= 1, etc]: */ - if(!lower_tail || log_p) { - p = R_DT_qIv(p); /* need check again (cancellation!): */ - if (p == 0.) return 0; - if (p == 1.) return ML_POSINF; - } - /* temporary hack --- FIXME --- */ - if (p + 1.01*DBL_EPSILON >= 1.) return ML_POSINF; - - /* y := approx.value (Cornish-Fisher expansion) : */ - z = qnorm(p, 0., 1., /*lower_tail*/TRUE, /*log_p*/FALSE); - y = floor(mu + sigma * (z + gamma * (z*z - 1) / 6) + 0.5); - - z = ppois(y, lambda, /*lower_tail*/TRUE, /*log_p*/FALSE); - - /* fuzz to ensure left continuity; 1 - 1e-7 may lose too much : */ - p *= 1 - 64*DBL_EPSILON; - - /* If the mean is not too large a simple search is OK */ - if(lambda < 1e5) return do_search(y, &z, p, lambda, 1); - /* Otherwise be a bit cleverer in the search */ - { - double incr = floor(y * 0.001), oldincr; - do { - oldincr = incr; - y = do_search(y, &z, p, lambda, incr); - incr = fmax2(1, floor(incr/100)); - } while(oldincr > 1 && incr > lambda*1e-15); - return y; - } -} diff --git a/deps/Rmath/src/qt.c b/deps/Rmath/src/qt.c deleted file mode 100644 index fe4921760a5f9..0000000000000 --- a/deps/Rmath/src/qt.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000-2007 The R Development Core Team - * Copyright (C) 2003 The R Foundation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * DESCRIPTION - * - * The "Student" t distribution quantile function. - * - * NOTES - * - * This is a C translation of the Fortran routine given in: - * Hill, G.W (1970) "Algorithm 396: Student's t-quantiles" - * CACM 13(10), 619-620. - * - * Supplemented by inversion for 0 < ndf < 1. - * - * ADDITIONS: - * - lower_tail, log_p - * - using expm1() : takes care of Lozy (1979) "Remark on Algo.", TOMS - * - Apply 2-term Taylor expansion as in - * Hill, G.W (1981) "Remark on Algo.396", ACM TOMS 7, 250-1 - * - Improve the formula decision for 1 < df < 2 - */ - -#include "nmath.h" -#include "dpq.h" - -double qt(double p, double ndf, int lower_tail, int log_p) -{ - const static double eps = 1.e-12; - - double P, q; - Rboolean neg; - -#ifdef IEEE_754 - if (ISNAN(p) || ISNAN(ndf)) - return p + ndf; -#endif - - R_Q_P01_boundaries(p, ML_NEGINF, ML_POSINF); - - if (ndf <= 0) ML_ERR_return_NAN; - - if (ndf < 1) { /* based on qnt */ - const static double accu = 1e-13; - const static double Eps = 1e-11; /* must be > accu */ - - double ux, lx, nx, pp; - - int iter = 0; - - p = R_DT_qIv(p); - - /* Invert pt(.) : - * 1. finding an upper and lower bound */ - if(p > 1 - DBL_EPSILON) return ML_POSINF; - pp = fmin2(1 - DBL_EPSILON, p * (1 + Eps)); - for(ux = 1.; ux < DBL_MAX && pt(ux, ndf, TRUE, FALSE) < pp; ux *= 2); - pp = p * (1 - Eps); - for(lx =-1.; lx > -DBL_MAX && pt(lx, ndf, TRUE, FALSE) > pp; lx *= 2); - - /* 2. interval (lx,ux) halving - regula falsi failed on qt(0.1, 0.1) - */ - do { - nx = 0.5 * (lx + ux); - if (pt(nx, ndf, TRUE, FALSE) > p) ux = nx; else lx = nx; - } while ((ux - lx) / fabs(nx) > accu && ++iter < 1000); - - if(iter >= 1000) ML_ERROR(ME_PRECISION, "qt"); - - return 0.5 * (lx + ux); - } - - /* Old comment: - * FIXME: "This test should depend on ndf AND p !! - * ----- and in fact should be replaced by - * something like Abramowitz & Stegun 26.7.5 (p.949)" - * - * That would say that if the qnorm value is x then - * the result is about x + (x^3+x)/4df + (5x^5+16x^3+3x)/96df^2 - * The differences are tiny even if x ~ 1e5, and qnorm is not - * that accurate in the extreme tails. - */ - if (ndf > 1e20) return qnorm(p, 0., 1., lower_tail, log_p); - - P = R_D_qIv(p); /* if exp(p) underflows, we fix below */ - - neg = (!lower_tail || P < 0.5) && (lower_tail || P > 0.5); - if(neg) - P = 2 * (log_p ? (lower_tail ? P : -expm1(p)) : R_D_Lval(p)); - else - P = 2 * (log_p ? (lower_tail ? -expm1(p) : P) : R_D_Cval(p)); - /* 0 <= P <= 1 ; P = 2*min(P', 1 - P') in all cases */ - -/* Use this if(log_p) only : */ -#define P_is_exp_2p (lower_tail == neg) /* both TRUE or FALSE == !xor */ - - if (fabs(ndf - 2) < eps) { /* df ~= 2 */ - if(P > DBL_MIN) { - if(3* P < DBL_EPSILON) /* P ~= 0 */ - q = 1 / sqrt(P); - else if (P > 0.9) /* P ~= 1 */ - q = (1 - P) * sqrt(2 /(P * (2 - P))); - else /* eps/3 <= P <= 0.9 */ - q = sqrt(2 / (P * (2 - P)) - 2); - } - else { /* P << 1, q = 1/sqrt(P) = ... */ - if(log_p) - q = P_is_exp_2p ? exp(- p/2) / M_SQRT2 : 1/sqrt(-expm1(p)); - else - q = ML_POSINF; - } - } - else if (ndf < 1 + eps) { /* df ~= 1 (df < 1 excluded above): Cauchy */ - if(P > 0) - q = 1/tan(P * M_PI_2);/* == - tan((P+1) * M_PI_2) -- suffers for P ~= 0 */ - - else { /* P = 0, but maybe = 2*exp(p) ! */ - if(log_p) /* 1/tan(e) ~ 1/e */ - q = P_is_exp_2p ? M_1_PI * exp(-p) : -1./(M_PI * expm1(p)); - else - q = ML_POSINF; - } - } - else { /*-- usual case; including, e.g., df = 1.1 */ - double x = 0., y, log_P2 = 0./* -Wall */, - a = 1 / (ndf - 0.5), - b = 48 / (a * a), - c = ((20700 * a / b - 98) * a - 16) * a + 96.36, - d = ((94.5 / (b + c) - 3) / b + 1) * sqrt(a * M_PI_2) * ndf; - - Rboolean P_ok1 = P > DBL_MIN || !log_p, P_ok = P_ok1; - if(P_ok1) { - y = pow(d * P, 2 / ndf); - P_ok = (y >= DBL_EPSILON); - } - if(!P_ok) { /* log_p && P very small */ - log_P2 = P_is_exp_2p ? p : R_Log1_Exp(p); /* == log(P / 2) */ - x = (log(d) + M_LN2 + log_P2) / ndf; - y = exp(2 * x); - } - - if ((ndf < 2.1 && P > 0.5) || y > 0.05 + a) { /* P > P0(df) */ - /* Asymptotic inverse expansion about normal */ - if(P_ok) - x = qnorm(0.5 * P, 0., 1., /*lower_tail*/TRUE, /*log_p*/FALSE); - else /* log_p && P underflowed */ - x = qnorm(log_P2, 0., 1., lower_tail, /*log_p*/ TRUE); - - y = x * x; - if (ndf < 5) - c += 0.3 * (ndf - 4.5) * (x + 0.6); - c = (((0.05 * d * x - 5) * x - 7) * x - 2) * x + b + c; - y = (((((0.4 * y + 6.3) * y + 36) * y + 94.5) / c - - y - 3) / b + 1) * x; - y = expm1(a * y * y); - q = sqrt(ndf * y); - } else { /* re-use 'y' from above */ - - if(!P_ok && x < - M_LN2 * DBL_MANT_DIG) {/* 0.5* log(DBL_EPSILON) */ - /* y above might have underflown */ - q = sqrt(ndf) * exp(-x); - } - else { - y = ((1 / (((ndf + 6) / (ndf * y) - 0.089 * d - 0.822) - * (ndf + 2) * 3) + 0.5 / (ndf + 4)) - * y - 1) * (ndf + 1) / (ndf + 2) + 1 / y; - q = sqrt(ndf * y); - } - } - - - /* Now apply 2-term Taylor expansion improvement (1-term = Newton): - * as by Hill (1981) [ref.above] */ - - /* FIXME: This can be far from optimal when log_p = TRUE - * but is still needed, e.g. for qt(-2, df=1.01, log=TRUE). - * Probably also improvable when lower_tail = FALSE */ - - if(P_ok1) { - int it=0; - while(it++ < 10 && (y = dt(q, ndf, FALSE)) > 0 && - R_FINITE(x = (pt(q, ndf, FALSE, FALSE) - P/2) / y) && - fabs(x) > 1e-14*fabs(q)) - /* Newton (=Taylor 1 term): - * q += x; - * Taylor 2-term : */ - q += x * (1. + x * q * (ndf + 1) / (2 * (q * q + ndf))); - } - } - if(neg) q = -q; - return q; -} diff --git a/deps/Rmath/src/qtukey.c b/deps/Rmath/src/qtukey.c deleted file mode 100644 index 343ad118c3edd..0000000000000 --- a/deps/Rmath/src/qtukey.c +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000--2005 The R Development Core Team - * based in part on AS70 (C) 1974 Royal Statistical Society - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * double qtukey(p, rr, cc, df, lower_tail, log_p); - * - * DESCRIPTION - * - * Computes the quantiles of the maximum of rr studentized - * ranges, each based on cc means and with df degrees of freedom - * for the standard error, is less than q. - * - * The algorithm is based on that of the reference. - * - * REFERENCE - * - * Copenhaver, Margaret Diponzio & Holland, Burt S. - * Multiple comparisons of simple effects in - * the two-way analysis of variance with fixed effects. - * Journal of Statistical Computation and Simulation, - * Vol.30, pp.1-15, 1988. - */ - -#include "nmath.h" -#include "dpq.h" - -/* qinv() : - * this function finds percentage point of the studentized range - * which is used as initial estimate for the secant method. - * function is adapted from portion of algorithm as 70 - * from applied statistics (1974) ,vol. 23, no. 1 - * by odeh, r. e. and evans, j. o. - * - * p = percentage point - * c = no. of columns or treatments - * v = degrees of freedom - * qinv = returned initial estimate - * - * vmax is cutoff above which degrees of freedom - * is treated as infinity. - */ - -static double qinv(double p, double c, double v) -{ - const static double p0 = 0.322232421088; - const static double q0 = 0.993484626060e-01; - const static double p1 = -1.0; - const static double q1 = 0.588581570495; - const static double p2 = -0.342242088547; - const static double q2 = 0.531103462366; - const static double p3 = -0.204231210125; - const static double q3 = 0.103537752850; - const static double p4 = -0.453642210148e-04; - const static double q4 = 0.38560700634e-02; - const static double c1 = 0.8832; - const static double c2 = 0.2368; - const static double c3 = 1.214; - const static double c4 = 1.208; - const static double c5 = 1.4142; - const static double vmax = 120.0; - - double ps, q, t, yi; - - ps = 0.5 - 0.5 * p; - yi = sqrt (log (1.0 / (ps * ps))); - t = yi + (((( yi * p4 + p3) * yi + p2) * yi + p1) * yi + p0) - / (((( yi * q4 + q3) * yi + q2) * yi + q1) * yi + q0); - if (v < vmax) t += (t * t * t + t) / v / 4.0; - q = c1 - c2 * t; - if (v < vmax) q += -c3 / v + c4 * t / v; - return t * (q * log (c - 1.0) + c5); -} - -/* - * Copenhaver, Margaret Diponzio & Holland, Burt S. - * Multiple comparisons of simple effects in - * the two-way analysis of variance with fixed effects. - * Journal of Statistical Computation and Simulation, - * Vol.30, pp.1-15, 1988. - * - * Uses the secant method to find critical values. - * - * p = confidence level (1 - alpha) - * rr = no. of rows or groups - * cc = no. of columns or treatments - * df = degrees of freedom of error term - * - * ir(1) = error flag = 1 if wprob probability > 1 - * ir(2) = error flag = 1 if ptukey probability > 1 - * ir(3) = error flag = 1 if convergence not reached in 50 iterations - * = 2 if df < 2 - * - * qtukey = returned critical value - * - * If the difference between successive iterates is less than eps, - * the search is terminated - */ - - -double qtukey(double p, double rr, double cc, double df, - int lower_tail, int log_p) -{ - const static double eps = 0.0001; - const int maxiter = 50; - - double ans = 0.0, valx0, valx1, x0, x1, xabs; - int iter; - -#ifdef IEEE_754 - if (ISNAN(p) || ISNAN(rr) || ISNAN(cc) || ISNAN(df)) { - ML_ERROR(ME_DOMAIN, "qtukey"); - return p + rr + cc + df; - } -#endif - - /* df must be > 1 ; there must be at least two values */ - if (df < 2 || rr < 1 || cc < 2) ML_ERR_return_NAN; - - R_Q_P01_boundaries(p, 0, ML_POSINF); - - p = R_DT_qIv(p); /* lower_tail,non-log "p" */ - - /* Initial value */ - - x0 = qinv(p, cc, df); - - /* Find prob(value < x0) */ - - valx0 = ptukey(x0, rr, cc, df, /*LOWER*/TRUE, /*LOG_P*/FALSE) - p; - - /* Find the second iterate and prob(value < x1). */ - /* If the first iterate has probability value */ - /* exceeding p then second iterate is 1 less than */ - /* first iterate; otherwise it is 1 greater. */ - - if (valx0 > 0.0) - x1 = fmax2(0.0, x0 - 1.0); - else - x1 = x0 + 1.0; - valx1 = ptukey(x1, rr, cc, df, /*LOWER*/TRUE, /*LOG_P*/FALSE) - p; - - /* Find new iterate */ - - for(iter=1 ; iter < maxiter ; iter++) { - ans = x1 - ((valx1 * (x1 - x0)) / (valx1 - valx0)); - valx0 = valx1; - - /* New iterate must be >= 0 */ - - x0 = x1; - if (ans < 0.0) { - ans = 0.0; - valx1 = -p; - } - /* Find prob(value < new iterate) */ - - valx1 = ptukey(ans, rr, cc, df, /*LOWER*/TRUE, /*LOG_P*/FALSE) - p; - x1 = ans; - - /* If the difference between two successive */ - /* iterates is less than eps, stop */ - - xabs = fabs(x1 - x0); - if (xabs < eps) - return ans; - } - - /* The process did not converge in 'maxiter' iterations */ - ML_ERROR(ME_NOCONV, "qtukey"); - return ans; -} diff --git a/deps/Rmath/src/qunif.c b/deps/Rmath/src/qunif.c deleted file mode 100644 index fc524ada579a1..0000000000000 --- a/deps/Rmath/src/qunif.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000-2006 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * DESCRIPTION - * - * The quantile function of the uniform distribution. - */ - -#include "nmath.h" -#include "dpq.h" - -double qunif(double p, double a, double b, int lower_tail, int log_p) -{ -#ifdef IEEE_754 - if (ISNAN(p) || ISNAN(a) || ISNAN(b)) - return p + a + b; -#endif - R_Q_P01_check(p); - if (!R_FINITE(a) || !R_FINITE(b)) ML_ERR_return_NAN; - if (b < a) ML_ERR_return_NAN; - if (b == a) return a; - - return a + R_DT_qIv(p) * (b - a); -} - - - - diff --git a/deps/Rmath/src/qweibull.c b/deps/Rmath/src/qweibull.c deleted file mode 100644 index d30da65047786..0000000000000 --- a/deps/Rmath/src/qweibull.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000 The R Development Core Team - * Copyright (C) 2005 The R Foundation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * DESCRIPTION - * - * The quantile function of the Weibull distribution. - */ - -#include "nmath.h" -#include "dpq.h" - -double qweibull(double p, double shape, double scale, int lower_tail, int log_p) -{ -#ifdef IEEE_754 - if (ISNAN(p) || ISNAN(shape) || ISNAN(scale)) - return p + shape + scale; -#endif - if (shape <= 0 || scale <= 0) ML_ERR_return_NAN; - - R_Q_P01_boundaries(p, 0, ML_POSINF); - - return scale * pow(- R_DT_Clog(p), 1./shape) ; -} diff --git a/deps/Rmath/src/rbeta.c b/deps/Rmath/src/rbeta.c deleted file mode 100644 index 09a2de75e2c3a..0000000000000 --- a/deps/Rmath/src/rbeta.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * R : A Computer Language for Statistical Data Analysis - * Copyright (C) 1995, 1996 Robert Gentleman and Ross Ihaka - * Copyright (C) 2000--2010 The R Development Core Team - * Copyright (C) 2000, 2010 The R Foundation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - */ - -/* Reference: - * R. C. H. Cheng (1978). - * Generating beta variates with nonintegral shape parameters. - * Communications of the ACM 21, 317-322. - * (Algorithms BB and BC) - */ - -#include "nmath.h" - -#define expmax (DBL_MAX_EXP * M_LN2)/* = log(DBL_MAX) */ - -double rbeta(double aa, double bb) -{ - double a, b, alpha; - double r, s, t, u1, u2, v, w, y, z; - - int qsame; - /* FIXME: Keep Globals (properly) for threading */ - /* Uses these GLOBALS to save time when many rv's are generated : */ - static double beta, gamma, delta, k1, k2; - static double olda = -1.0; - static double oldb = -1.0; - - if (aa <= 0. || bb <= 0. || (!R_FINITE(aa) && !R_FINITE(bb))) - ML_ERR_return_NAN; - - if (!R_FINITE(aa)) - return 1.0; - - if (!R_FINITE(bb)) - return 0.0; - - /* Test if we need new "initializing" */ - qsame = (olda == aa) && (oldb == bb); - if (!qsame) { olda = aa; oldb = bb; } - - a = fmin2(aa, bb); - b = fmax2(aa, bb); /* a <= b */ - alpha = a + b; - -#define v_w_from__u1_bet(AA) \ - v = beta * log(u1 / (1.0 - u1)); \ - if (v <= expmax) { \ - w = AA * exp(v); \ - if(!R_FINITE(w)) w = DBL_MAX; \ - } else \ - w = DBL_MAX - - - if (a <= 1.0) { /* --- Algorithm BC --- */ - - /* changed notation, now also a <= b (was reversed) */ - - if (!qsame) { /* initialize */ - beta = 1.0 / a; - delta = 1.0 + b - a; - k1 = delta * (0.0138889 + 0.0416667 * a) / (b * beta - 0.777778); - k2 = 0.25 + (0.5 + 0.25 / delta) * a; - } - /* FIXME: "do { } while()", but not trivially because of "continue"s:*/ - for(;;) { - u1 = unif_rand(); - u2 = unif_rand(); - if (u1 < 0.5) { - y = u1 * u2; - z = u1 * y; - if (0.25 * u2 + z - y >= k1) - continue; - } else { - z = u1 * u1 * u2; - if (z <= 0.25) { - v_w_from__u1_bet(b); - break; - } - if (z >= k2) - continue; - } - - v_w_from__u1_bet(b); - - if (alpha * (log(alpha / (a + w)) + v) - 1.3862944 >= log(z)) - break; - } - return (aa == a) ? a / (a + w) : w / (a + w); - - } - else { /* Algorithm BB */ - - if (!qsame) { /* initialize */ - beta = sqrt((alpha - 2.0) / (2.0 * a * b - alpha)); - gamma = a + 1.0 / beta; - } - do { - u1 = unif_rand(); - u2 = unif_rand(); - - v_w_from__u1_bet(a); - - z = u1 * u1 * u2; - r = gamma * v - 1.3862944; - s = a + r - w; - if (s + 2.609438 >= 5.0 * z) - break; - t = log(z); - if (s > t) - break; - } - while (r + alpha * log(alpha / (b + w)) < t); - - return (aa != a) ? b / (b + w) : w / (b + w); - } -} diff --git a/deps/Rmath/src/rbinom.c b/deps/Rmath/src/rbinom.c deleted file mode 100644 index 8fabdff1d9fc9..0000000000000 --- a/deps/Rmath/src/rbinom.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000-2002 The R Development Core Team - * Copyright (C) 2007 The R Foundation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * double rbinom(double nin, double pp) - * - * DESCRIPTION - * - * Random variates from the binomial distribution. - * - * REFERENCE - * - * Kachitvichyanukul, V. and Schmeiser, B. W. (1988). - * Binomial random variate generation. - * Communications of the ACM 31, 216-222. - * (Algorithm BTPEC). - */ - -#include "nmath.h" -#include -#include - -#define repeat for(;;) - -double rbinom(double nin, double pp) -{ - /* FIXME: These should become THREAD_specific globals : */ - - static double c, fm, npq, p1, p2, p3, p4, qn; - static double xl, xll, xlr, xm, xr; - - static double psave = -1.0; - static int nsave = -1; - static int m; - - double f, f1, f2, u, v, w, w2, x, x1, x2, z, z2; - double p, q, np, g, r, al, alv, amaxp, ffm, ynorm; - int i,ix,k, n; - - if (!R_FINITE(nin)) ML_ERR_return_NAN; - r = floor(nin + 0.5); - if (r != nin) ML_ERR_return_NAN; - if (!R_FINITE(pp) || - /* n=0, p=0, p=1 are not errors */ - r < 0 || pp < 0. || pp > 1.) ML_ERR_return_NAN; - - if (r == 0 || pp == 0.) return 0; - if (pp == 1.) return r; - - if (r >= INT_MAX)/* evade integer overflow, - and r == INT_MAX gave only even values */ - return qbinom(unif_rand(), r, pp, /*lower_tail*/ 0, /*log_p*/ 0); - /* else */ - n = r; - - p = fmin2(pp, 1. - pp); - q = 1. - p; - np = n * p; - r = p / q; - g = r * (n + 1); - - /* Setup, perform only when parameters change [using static (globals): */ - - /* FIXING: Want this thread safe - -- use as little (thread globals) as possible - */ - if (pp != psave || n != nsave) { - psave = pp; - nsave = n; - if (np < 30.0) { - /* inverse cdf logic for mean less than 30 */ - qn = pow(q, (double) n); - goto L_np_small; - } else { - ffm = np + p; - m = ffm; - fm = m; - npq = np * q; - p1 = (int)(2.195 * sqrt(npq) - 4.6 * q) + 0.5; - xm = fm + 0.5; - xl = xm - p1; - xr = xm + p1; - c = 0.134 + 20.5 / (15.3 + fm); - al = (ffm - xl) / (ffm - xl * p); - xll = al * (1.0 + 0.5 * al); - al = (xr - ffm) / (xr * q); - xlr = al * (1.0 + 0.5 * al); - p2 = p1 * (1.0 + c + c); - p3 = p2 + c / xll; - p4 = p3 + c / xlr; - } - } else if (n == nsave) { - if (np < 30.0) - goto L_np_small; - } - - /*-------------------------- np = n*p >= 30 : ------------------- */ - repeat { - u = unif_rand() * p4; - v = unif_rand(); - /* triangular region */ - if (u <= p1) { - ix = xm - p1 * v + u; - goto finis; - } - /* parallelogram region */ - if (u <= p2) { - x = xl + (u - p1) / c; - v = v * c + 1.0 - fabs(xm - x) / p1; - if (v > 1.0 || v <= 0.) - continue; - ix = x; - } else { - if (u > p3) { /* right tail */ - ix = xr - log(v) / xlr; - if (ix > n) - continue; - v = v * (u - p3) * xlr; - } else {/* left tail */ - ix = xl + log(v) / xll; - if (ix < 0) - continue; - v = v * (u - p2) * xll; - } - } - /* determine appropriate way to perform accept/reject test */ - k = abs(ix - m); - if (k <= 20 || k >= npq / 2 - 1) { - /* explicit evaluation */ - f = 1.0; - if (m < ix) { - for (i = m + 1; i <= ix; i++) - f *= (g / i - r); - } else if (m != ix) { - for (i = ix + 1; i <= m; i++) - f /= (g / i - r); - } - if (v <= f) - goto finis; - } else { - /* squeezing using upper and lower bounds on log(f(x)) */ - amaxp = (k / npq) * ((k * (k / 3. + 0.625) + 0.1666666666666) / npq + 0.5); - ynorm = -k * k / (2.0 * npq); - alv = log(v); - if (alv < ynorm - amaxp) - goto finis; - if (alv <= ynorm + amaxp) { - /* stirling's formula to machine accuracy */ - /* for the final acceptance/rejection test */ - x1 = ix + 1; - f1 = fm + 1.0; - z = n + 1 - fm; - w = n - ix + 1.0; - z2 = z * z; - x2 = x1 * x1; - f2 = f1 * f1; - w2 = w * w; - if (alv <= xm * log(f1 / x1) + (n - m + 0.5) * log(z / w) + (ix - m) * log(w * p / (x1 * q)) + (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / f2) / f2) / f2) / f2) / f1 / 166320.0 + (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / z2) / z2) / z2) / z2) / z / 166320.0 + (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / x2) / x2) / x2) / x2) / x1 / 166320.0 + (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / w2) / w2) / w2) / w2) / w / 166320.) - goto finis; - } - } - } - - L_np_small: - /*---------------------- np = n*p < 30 : ------------------------- */ - - repeat { - ix = 0; - f = qn; - u = unif_rand(); - repeat { - if (u < f) - goto finis; - if (ix > 110) - break; - u -= f; - ix++; - f *= (g / ix - r); - } - } - finis: - if (psave > 0.5) - ix = n - ix; - return (double)ix; -} diff --git a/deps/Rmath/src/rcauchy.c b/deps/Rmath/src/rcauchy.c deleted file mode 100644 index 079d97df33428..0000000000000 --- a/deps/Rmath/src/rcauchy.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000--2008 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * double rcauchy(double location, double scale); - * - * DESCRIPTION - * - * Random variates from the Cauchy distribution. - */ - -#include "nmath.h" - -double rcauchy(double location, double scale) -{ - if (ISNAN(location) || !R_FINITE(scale) || scale < 0) - ML_ERR_return_NAN; - if (scale == 0. || !R_FINITE(location)) - return location; - else - return location + scale * tan(M_PI * unif_rand()); -} diff --git a/deps/Rmath/src/rchisq.c b/deps/Rmath/src/rchisq.c deleted file mode 100644 index 3a23dd2fe9a3b..0000000000000 --- a/deps/Rmath/src/rchisq.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * double rchisq(double df); - * - * DESCRIPTION - * - * Random variates from the chi-squared distribution. - * - * NOTES - * - * Calls rgamma to do the real work. - */ - -#include "nmath.h" - -double rchisq(double df) -{ - if (!R_FINITE(df) || df < 0.0) ML_ERR_return_NAN; - - return rgamma(df / 2.0, 2.0); -} diff --git a/deps/Rmath/src/rexp.c b/deps/Rmath/src/rexp.c deleted file mode 100644 index 388f506f4dc8f..0000000000000 --- a/deps/Rmath/src/rexp.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000--2008 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * double rexp(double scale) - * - * DESCRIPTION - * - * Random variates from the exponential distribution. - * - */ - -#include "nmath.h" - -double rexp(double scale) -{ - if (!R_FINITE(scale) || scale <= 0.0) { - if(scale == 0.) return 0.; - /* else */ - ML_ERR_return_NAN; - } - return scale * exp_rand(); -} diff --git a/deps/Rmath/src/rf.c b/deps/Rmath/src/rf.c deleted file mode 100644 index 9968d1010909a..0000000000000 --- a/deps/Rmath/src/rf.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include "mathlib.h" - * double rf(double dfn, double dfd); - * - * DESCRIPTION - * - * Pseudo-random variates from an F distribution. - * - * NOTES - * - * This function calls rchisq to do the real work - */ - -#include "nmath.h" - -double rf(double n1, double n2) -{ - double v1, v2; - if (ISNAN(n1) || ISNAN(n2) || n1 <= 0. || n2 <= 0.) - ML_ERR_return_NAN; - - v1 = R_FINITE(n1) ? (rchisq(n1) / n1) : 1; - v2 = R_FINITE(n2) ? (rchisq(n2) / n2) : 1; - return v1 / v2; -} diff --git a/deps/Rmath/src/rgamma.c b/deps/Rmath/src/rgamma.c deleted file mode 100644 index 167fbc3b2e88b..0000000000000 --- a/deps/Rmath/src/rgamma.c +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000--2008 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * double rgamma(double a, double scale); - * - * DESCRIPTION - * - * Random variates from the gamma distribution. - * - * REFERENCES - * - * [1] Shape parameter a >= 1. Algorithm GD in: - * - * Ahrens, J.H. and Dieter, U. (1982). - * Generating gamma variates by a modified - * rejection technique. - * Comm. ACM, 25, 47-54. - * - * - * [2] Shape parameter 0 < a < 1. Algorithm GS in: - * - * Ahrens, J.H. and Dieter, U. (1974). - * Computer methods for sampling from gamma, beta, - * poisson and binomial distributions. - * Computing, 12, 223-246. - * - * Input: a = parameter (mean) of the standard gamma distribution. - * Output: a variate from the gamma(a)-distribution - */ - -#include "nmath.h" - -#define repeat for(;;) - -double rgamma(double a, double scale) -{ -/* Constants : */ - const static double sqrt32 = 5.656854; - const static double exp_m1 = 0.36787944117144232159;/* exp(-1) = 1/e */ - - /* Coefficients q[k] - for q0 = sum(q[k]*a^(-k)) - * Coefficients a[k] - for q = q0+(t*t/2)*sum(a[k]*v^k) - * Coefficients e[k] - for exp(q)-1 = sum(e[k]*q^k) - */ - const static double q1 = 0.04166669; - const static double q2 = 0.02083148; - const static double q3 = 0.00801191; - const static double q4 = 0.00144121; - const static double q5 = -7.388e-5; - const static double q6 = 2.4511e-4; - const static double q7 = 2.424e-4; - - const static double a1 = 0.3333333; - const static double a2 = -0.250003; - const static double a3 = 0.2000062; - const static double a4 = -0.1662921; - const static double a5 = 0.1423657; - const static double a6 = -0.1367177; - const static double a7 = 0.1233795; - - /* State variables [FIXME for threading!] :*/ - static double aa = 0.; - static double aaa = 0.; - static double s, s2, d; /* no. 1 (step 1) */ - static double q0, b, si, c;/* no. 2 (step 4) */ - - double e, p, q, r, t, u, v, w, x, ret_val; - - if (!R_FINITE(a) || !R_FINITE(scale) || a < 0.0 || scale <= 0.0) { - if(scale == 0.) return 0.; - ML_ERR_return_NAN; - } - - if (a < 1.) { /* GS algorithm for parameters a < 1 */ - if(a == 0) - return 0.; - e = 1.0 + exp_m1 * a; - repeat { - p = e * unif_rand(); - if (p >= 1.0) { - x = -log((e - p) / a); - if (exp_rand() >= (1.0 - a) * log(x)) - break; - } else { - x = exp(log(p) / a); - if (exp_rand() >= x) - break; - } - } - return scale * x; - } - - /* --- a >= 1 : GD algorithm --- */ - - /* Step 1: Recalculations of s2, s, d if a has changed */ - if (a != aa) { - aa = a; - s2 = a - 0.5; - s = sqrt(s2); - d = sqrt32 - s * 12.0; - } - /* Step 2: t = standard normal deviate, - x = (s,1/2) -normal deviate. */ - - /* immediate acceptance (i) */ - t = norm_rand(); - x = s + 0.5 * t; - ret_val = x * x; - if (t >= 0.0) - return scale * ret_val; - - /* Step 3: u = 0,1 - uniform sample. squeeze acceptance (s) */ - u = unif_rand(); - if (d * u <= t * t * t) - return scale * ret_val; - - /* Step 4: recalculations of q0, b, si, c if necessary */ - - if (a != aaa) { - aaa = a; - r = 1.0 / a; - q0 = ((((((q7 * r + q6) * r + q5) * r + q4) * r + q3) * r - + q2) * r + q1) * r; - - /* Approximation depending on size of parameter a */ - /* The constants in the expressions for b, si and c */ - /* were established by numerical experiments */ - - if (a <= 3.686) { - b = 0.463 + s + 0.178 * s2; - si = 1.235; - c = 0.195 / s - 0.079 + 0.16 * s; - } else if (a <= 13.022) { - b = 1.654 + 0.0076 * s2; - si = 1.68 / s + 0.275; - c = 0.062 / s + 0.024; - } else { - b = 1.77; - si = 0.75; - c = 0.1515 / s; - } - } - /* Step 5: no quotient test if x not positive */ - - if (x > 0.0) { - /* Step 6: calculation of v and quotient q */ - v = t / (s + s); - if (fabs(v) <= 0.25) - q = q0 + 0.5 * t * t * ((((((a7 * v + a6) * v + a5) * v + a4) * v - + a3) * v + a2) * v + a1) * v; - else - q = q0 - s * t + 0.25 * t * t + (s2 + s2) * log(1.0 + v); - - - /* Step 7: quotient acceptance (q) */ - if (log(1.0 - u) <= q) - return scale * ret_val; - } - - repeat { - /* Step 8: e = standard exponential deviate - * u = 0,1 -uniform deviate - * t = (b,si)-double exponential (laplace) sample */ - e = exp_rand(); - u = unif_rand(); - u = u + u - 1.0; - if (u < 0.0) - t = b - si * e; - else - t = b + si * e; - /* Step 9: rejection if t < tau(1) = -0.71874483771719 */ - if (t >= -0.71874483771719) { - /* Step 10: calculation of v and quotient q */ - v = t / (s + s); - if (fabs(v) <= 0.25) - q = q0 + 0.5 * t * t * - ((((((a7 * v + a6) * v + a5) * v + a4) * v + a3) * v - + a2) * v + a1) * v; - else - q = q0 - s * t + 0.25 * t * t + (s2 + s2) * log(1.0 + v); - /* Step 11: hat acceptance (h) */ - /* (if q not positive go to step 8) */ - if (q > 0.0) { - w = expm1(q); - /* ^^^^^ original code had approximation with rel.err < 2e-7 */ - /* if t is rejected sample again at step 8 */ - if (c * fabs(u) <= w * exp(e - 0.5 * t * t)) - break; - } - } - } /* repeat .. until `t' is accepted */ - x = s + 0.5 * t; - return scale * x * x; -} diff --git a/deps/Rmath/src/rgeom.c b/deps/Rmath/src/rgeom.c deleted file mode 100644 index 439f604fd229d..0000000000000 --- a/deps/Rmath/src/rgeom.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka and the R Development Core Team. - * Copyright (C) 2000 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * double rgeom(double p); - * - * DESCRIPTION - * - * Random variates from the geometric distribution. - * - * NOTES - * - * We generate lambda as exponential with scale parameter - * p / (1 - p). Return a Poisson deviate with mean lambda. - * - * REFERENCE - * - * Devroye, L. (1986). - * Non-Uniform Random Variate Generation. - * New York: Springer-Verlag. - * Page 480. - */ - -#include "nmath.h" - -double rgeom(double p) -{ - if (!R_FINITE(p) || p <= 0 || p > 1) ML_ERR_return_NAN; - - return rpois(exp_rand() * ((1 - p) / p)); -} diff --git a/deps/Rmath/src/rhyper.c b/deps/Rmath/src/rhyper.c deleted file mode 100644 index 9e17b1d230015..0000000000000 --- a/deps/Rmath/src/rhyper.c +++ /dev/null @@ -1,339 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000-2001 The R Development Core Team - * Copyright (C) 2005 The R Foundation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * double rhyper(double NR, double NB, double n); - * - * DESCRIPTION - * - * Random variates from the hypergeometric distribution. - * Returns the number of white balls drawn when kk balls - * are drawn at random from an urn containing nn1 white - * and nn2 black balls. - * - * REFERENCE - * - * V. Kachitvichyanukul and B. Schmeiser (1985). - * ``Computer generation of hypergeometric random variates,'' - * Journal of Statistical Computation and Simulation 22, 127-145. - * - * The original algorithm had a bug -- R bug report PR#7314 -- - * giving numbers slightly too small in case III h2pe - * where (m < 100 || ix <= 50) , see below. - */ - -#include "nmath.h" - -/* afc(i) := ln( i! ) [logarithm of the factorial i. - * If (i > 7), use Stirling's approximation, otherwise use table lookup. -*/ - -static double afc(int i) -{ - const static double al[9] = - { - 0.0, - 0.0,/*ln(0!)=ln(1)*/ - 0.0,/*ln(1!)=ln(1)*/ - 0.69314718055994530941723212145817,/*ln(2) */ - 1.79175946922805500081247735838070,/*ln(6) */ - 3.17805383034794561964694160129705,/*ln(24)*/ - 4.78749174278204599424770093452324, - 6.57925121201010099506017829290394, - 8.52516136106541430016553103634712 - /*, 10.60460290274525022841722740072165*/ - }; - double di, value; - - if (i < 0) { - MATHLIB_WARNING(("rhyper.c: afc(i), i=%d < 0 -- SHOULD NOT HAPPEN!\n"), - i); - return -1;/* unreached (Wall) */ - } else if (i <= 7) { - value = al[i + 1]; - } else { - di = i; - value = (di + 0.5) * log(di) - di + 0.08333333333333 / di - - 0.00277777777777 / di / di / di + 0.9189385332; - } - return value; -} - -double rhyper(double nn1in, double nn2in, double kkin) -{ - const static double con = 57.56462733; - const static double deltal = 0.0078; - const static double deltau = 0.0034; - const static double scale = 1e25; - - /* extern double afc(int); */ - - int nn1, nn2, kk; - int i, ix; - Rboolean reject, setup1, setup2; - - double e, f, g, p, r, t, u, v, y; - double de, dg, dr, ds, dt, gl, gu, nk, nm, ub; - double xk, xm, xn, y1, ym, yn, yk, alv; - - /* These should become `thread_local globals' : */ - static int ks = -1; - static int n1s = -1, n2s = -1; - - static int k, m; - static int minjx, maxjx, n1, n2; - - static double a, d, s, w; - static double tn, xl, xr, kl, kr, lamdl, lamdr, p1, p2, p3; - - - /* check parameter validity */ - - if(!R_FINITE(nn1in) || !R_FINITE(nn2in) || !R_FINITE(kkin)) - ML_ERR_return_NAN; - - nn1 = floor(nn1in+0.5); - nn2 = floor(nn2in+0.5); - kk = floor(kkin +0.5); - - if (nn1 < 0 || nn2 < 0 || kk < 0 || kk > nn1 + nn2) - ML_ERR_return_NAN; - - /* if new parameter values, initialize */ - reject = TRUE; - if (nn1 != n1s || nn2 != n2s) { - setup1 = TRUE; setup2 = TRUE; - } else if (kk != ks) { - setup1 = FALSE; setup2 = TRUE; - } else { - setup1 = FALSE; setup2 = FALSE; - } - if (setup1) { - n1s = nn1; - n2s = nn2; - tn = nn1 + nn2; - if (nn1 <= nn2) { - n1 = nn1; - n2 = nn2; - } else { - n1 = nn2; - n2 = nn1; - } - } - if (setup2) { - ks = kk; - if (kk + kk >= tn) { - k = tn - kk; - } else { - k = kk; - } - } - if (setup1 || setup2) { - m = (k + 1.0) * (n1 + 1.0) / (tn + 2.0); - minjx = imax2(0, k - n2); - maxjx = imin2(n1, k); - } - /* generate random variate --- Three basic cases */ - - if (minjx == maxjx) { /* I: degenerate distribution ---------------- */ - ix = maxjx; - /* return ix; - No, need to unmangle */ - /* return appropriate variate */ - - if (kk + kk >= tn) { - if (nn1 > nn2) { - ix = kk - nn2 + ix; - } else { - ix = nn1 - ix; - } - } else { - if (nn1 > nn2) - ix = kk - ix; - } - return ix; - - } else if (m - minjx < 10) { /* II: inverse transformation ---------- */ - if (setup1 || setup2) { - if (k < n2) { - w = exp(con + afc(n2) + afc(n1 + n2 - k) - - afc(n2 - k) - afc(n1 + n2)); - } else { - w = exp(con + afc(n1) + afc(k) - - afc(k - n2) - afc(n1 + n2)); - } - } - L10: - p = w; - ix = minjx; - u = unif_rand() * scale; - L20: - if (u > p) { - u -= p; - p *= (n1 - ix) * (k - ix); - ix++; - p = p / ix / (n2 - k + ix); - if (ix > maxjx) - goto L10; - goto L20; - } - } else { /* III : h2pe --------------------------------------------- */ - - if (setup1 || setup2) { - s = sqrt((tn - k) * k * n1 * n2 / (tn - 1) / tn / tn); - - /* remark: d is defined in reference without int. */ - /* the truncation centers the cell boundaries at 0.5 */ - - d = (int) (1.5 * s) + .5; - xl = m - d + .5; - xr = m + d + .5; - a = afc(m) + afc(n1 - m) + afc(k - m) + afc(n2 - k + m); - kl = exp(a - afc((int) (xl)) - afc((int) (n1 - xl)) - - afc((int) (k - xl)) - - afc((int) (n2 - k + xl))); - kr = exp(a - afc((int) (xr - 1)) - - afc((int) (n1 - xr + 1)) - - afc((int) (k - xr + 1)) - - afc((int) (n2 - k + xr - 1))); - lamdl = -log(xl * (n2 - k + xl) / (n1 - xl + 1) / (k - xl + 1)); - lamdr = -log((n1 - xr + 1) * (k - xr + 1) / xr / (n2 - k + xr)); - p1 = d + d; - p2 = p1 + kl / lamdl; - p3 = p2 + kr / lamdr; - } - L30: - u = unif_rand() * p3; - v = unif_rand(); - if (u < p1) { /* rectangular region */ - ix = xl + u; - } else if (u <= p2) { /* left tail */ - ix = xl + log(v) / lamdl; - if (ix < minjx) - goto L30; - v = v * (u - p1) * lamdl; - } else { /* right tail */ - ix = xr - log(v) / lamdr; - if (ix > maxjx) - goto L30; - v = v * (u - p2) * lamdr; - } - - /* acceptance/rejection test */ - - if (m < 100 || ix <= 50) { - /* explicit evaluation */ - /* The original algorithm (and TOMS 668) have - f = f * i * (n2 - k + i) / (n1 - i) / (k - i); - in the (m > ix) case, but the definition of the - recurrence relation on p134 shows that the +1 is - needed. */ - f = 1.0; - if (m < ix) { - for (i = m + 1; i <= ix; i++) - f = f * (n1 - i + 1) * (k - i + 1) / (n2 - k + i) / i; - } else if (m > ix) { - for (i = ix + 1; i <= m; i++) - f = f * i * (n2 - k + i) / (n1 - i + 1) / (k - i + 1); - } - if (v <= f) { - reject = FALSE; - } - } else { - /* squeeze using upper and lower bounds */ - y = ix; - y1 = y + 1.0; - ym = y - m; - yn = n1 - y + 1.0; - yk = k - y + 1.0; - nk = n2 - k + y1; - r = -ym / y1; - s = ym / yn; - t = ym / yk; - e = -ym / nk; - g = yn * yk / (y1 * nk) - 1.0; - dg = 1.0; - if (g < 0.0) - dg = 1.0 + g; - gu = g * (1.0 + g * (-0.5 + g / 3.0)); - gl = gu - .25 * (g * g * g * g) / dg; - xm = m + 0.5; - xn = n1 - m + 0.5; - xk = k - m + 0.5; - nm = n2 - k + xm; - ub = y * gu - m * gl + deltau - + xm * r * (1. + r * (-0.5 + r / 3.0)) - + xn * s * (1. + s * (-0.5 + s / 3.0)) - + xk * t * (1. + t * (-0.5 + t / 3.0)) - + nm * e * (1. + e * (-0.5 + e / 3.0)); - /* test against upper bound */ - alv = log(v); - if (alv > ub) { - reject = TRUE; - } else { - /* test against lower bound */ - dr = xm * (r * r * r * r); - if (r < 0.0) - dr /= (1.0 + r); - ds = xn * (s * s * s * s); - if (s < 0.0) - ds /= (1.0 + s); - dt = xk * (t * t * t * t); - if (t < 0.0) - dt /= (1.0 + t); - de = nm * (e * e * e * e); - if (e < 0.0) - de /= (1.0 + e); - if (alv < ub - 0.25 * (dr + ds + dt + de) - + (y + m) * (gl - gu) - deltal) { - reject = FALSE; - } - else { - /* * Stirling's formula to machine accuracy - */ - if (alv <= (a - afc(ix) - afc(n1 - ix) - - afc(k - ix) - afc(n2 - k + ix))) { - reject = FALSE; - } else { - reject = TRUE; - } - } - } - } - if (reject) - goto L30; - } - - /* return appropriate variate */ - - if (kk + kk >= tn) { - if (nn1 > nn2) { - ix = kk - nn2 + ix; - } else { - ix = nn1 - ix; - } - } else { - if (nn1 > nn2) - ix = kk - ix; - } - return ix; -} diff --git a/deps/Rmath/src/rlnorm.c b/deps/Rmath/src/rlnorm.c deleted file mode 100644 index 9d24b5cef9b09..0000000000000 --- a/deps/Rmath/src/rlnorm.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000--2001 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * double rlnorm(double logmean, double logsd); - * - * DESCRIPTION - * - * Random variates from the lognormal distribution. - */ - -#include "nmath.h" - -double rlnorm(double meanlog, double sdlog) -{ - if(ISNAN(meanlog) || !R_FINITE(sdlog) || sdlog < 0.) - ML_ERR_return_NAN; - - return exp(rnorm(meanlog, sdlog)); -} diff --git a/deps/Rmath/src/rlogis.c b/deps/Rmath/src/rlogis.c deleted file mode 100644 index ae5e821a54512..0000000000000 --- a/deps/Rmath/src/rlogis.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * R : A Computer Language for Statistical Data Analysis - * Copyright (C) 1995, 1996 Robert Gentleman and Ross Ihaka - * Copyright (C) 2000--2008 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - */ - -#include "nmath.h" - -double rlogis(double location, double scale) -{ - if (ISNAN(location) || !R_FINITE(scale)) - ML_ERR_return_NAN; - - if (scale == 0. || !R_FINITE(location)) - return location; - else { - double u = unif_rand(); - return location + scale * log(u / (1. - u)); - } -} diff --git a/deps/Rmath/src/rmultinom.c b/deps/Rmath/src/rmultinom.c deleted file mode 100644 index 75a907bb06d71..0000000000000 --- a/deps/Rmath/src/rmultinom.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 2003-2007 The R Foundation - * - * This program is free software; you can redistribute 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 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, a copy is available at - * http://www.r-project.org/Licenses/ - * - * - * SYNOPSIS - * - * #include - * void rmultinom(int n, double* prob, int K, int* rN); - * - * DESCRIPTION - * - * Random Vector from the multinomial distribution. - * ~~~~~~ - * NOTE - * Because we generate random _vectors_ this doesn't fit easily - * into the do_random[1-4](.) framework setup in ../main/random.c - * as that is used only for the univariate random generators. - * Multivariate distributions typically have too complex parameter spaces - * to be treated uniformly. - * => Hence also can have int arguments. - */ - -#include "nmath.h" -#include - -#ifdef MATHLIB_STANDALONE -#define ML_ERR_ret_NAN(_k_) {ML_ERROR(ME_DOMAIN, "rmultinom"); rN[_k_]=-1; return;} -#else -#define ML_ERR_ret_NAN(_k_) {ML_ERROR(ME_DOMAIN, "rmultinom"); rN[_k_]=NA_INTEGER; return;} -#endif - -void rmultinom(int n, double* prob, int K, int* rN) -/* `Return' vector rN[1:K] {K := length(prob)} - * where rN[j] ~ Bin(n, prob[j]) , sum_j rN[j] == n, sum_j prob[j] == 1, - */ -{ - int k; - double pp; - long double p_tot = 0.; - /* This calculation is sensitive to exact values, so we try to - ensure that the calculations are as accurate as possible - so different platforms are more likely to give the same - result. */ - -#ifdef MATHLIB_STANDALONE - if (K < 1) { ML_ERROR(ME_DOMAIN, "rmultinom"); return;} - if (n < 0) ML_ERR_ret_NAN(0); -#else - if (K == NA_INTEGER || K < 1) { ML_ERROR(ME_DOMAIN, "rmultinom"); return;} - if (n == NA_INTEGER || n < 0) ML_ERR_ret_NAN(0); -#endif - - /* Note: prob[K] is only used here for checking sum_k prob[k] = 1 ; - * Could make loop one shorter and drop that check ! - */ - for(k = 0; k < K; k++) { - pp = prob[k]; - if (!R_FINITE(pp) || pp < 0. || pp > 1.) ML_ERR_ret_NAN(k); - p_tot += pp; - rN[k] = 0; - } - if(fabs(p_tot - 1.) > 1e-7) - MATHLIB_ERROR(_("rbinom: probability sum should be 1, but is %g"), - (double) p_tot); - if (n == 0) return; - if (K == 1 && p_tot == 0.) return;/* trivial border case: do as rbinom */ - - /* Generate the first K-1 obs. via binomials */ - - for(k = 0; k < K-1; k++) { /* (p_tot, n) are for "remaining binomial" */ - if(prob[k]) { - pp = prob[k] / p_tot; - /* printf("[%d] %.17f\n", k+1, pp); */ - rN[k] = ((pp < 1.) ? (int) rbinom((double) n, pp) : - /*>= 1; > 1 happens because of rounding */ - n); - n -= rN[k]; - } - else rN[k] = 0; - if(n <= 0) /* we have all*/ return; - p_tot -= prob[k]; /* i.e. = sum(prob[(k+1):K]) */ - } - rN[K-1] = n; - return; -} -#undef ML_ERR_ret_NAN diff --git a/deps/Rmath/src/rnbinom.c b/deps/Rmath/src/rnbinom.c deleted file mode 100644 index 5bcde27a8bf62..0000000000000 --- a/deps/Rmath/src/rnbinom.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000--2006 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * double rnbinom(double n, double p) - * - * DESCRIPTION - * - * Random variates from the negative binomial distribution. - * - * NOTES - * - * x = the number of failures before the n-th success - * - * REFERENCE - * - * Devroye, L. (1986). - * Non-Uniform Random Variate Generation. - * New York:Springer-Verlag. Page 480. - * - * METHOD - * - * Generate lambda as gamma with shape parameter n and scale - * parameter p/(1-p). Return a Poisson deviate with mean lambda. - */ - -#include "nmath.h" - -double rnbinom(double size, double prob) -{ - if(!R_FINITE(size) || !R_FINITE(prob) || size <= 0 || prob <= 0 || prob > 1) - /* prob = 1 is ok, PR#1218 */ - ML_ERR_return_NAN; - return (prob == 1) ? 0 : rpois(rgamma(size, (1 - prob) / prob)); -} - -double rnbinom_mu(double size, double mu) -{ - if(!R_FINITE(size) || !R_FINITE(mu) || size <= 0 || mu < 0) - ML_ERR_return_NAN; - return (mu == 0) ? 0 : rpois(rgamma(size, mu / size)); -} diff --git a/deps/Rmath/src/rnchisq.c b/deps/Rmath/src/rnchisq.c deleted file mode 100644 index 07c8c2ac46049..0000000000000 --- a/deps/Rmath/src/rnchisq.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 2003 The R Foundation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * double rnchisq(double df, double lambda); - * - * DESCRIPTION - * - * Random variates from the NON CENTRAL chi-squared distribution. - * - * NOTES - * - According to Hans R. Kuensch's suggestion (30 sep 2002): - - It should be easy to do the general case (ncp > 0) by decomposing it - as the sum of a central chisquare with df degrees of freedom plus a - noncentral chisquare with zero degrees of freedom (which is a Poisson - mixture of central chisquares with integer degrees of freedom), - see Formula (29.5b-c) in Johnson, Kotz, Balakrishnan (1995). - - The noncentral chisquare with arbitary degrees of freedom is of interest - for simulating the Cox-Ingersoll-Ross model for interest rates in - finance. - - R code that works is - - rchisq0 <- function(n, ncp) { - p <- 0 < (K <- rpois(n, lambda = ncp / 2)) - r <- numeric(n) - r[p] <- rchisq(sum(p), df = 2*K[p]) - r - } - - rchisq <- function(n, df, ncp=0) { - if(missing(ncp)) .Internal(rchisq(n, df)) - else rchisq0(n, ncp) + .Internal(rchisq(n, df)) - } - */ - -#include "nmath.h" - -double rnchisq(double df, double lambda) -{ - if (!R_FINITE(df) || !R_FINITE(lambda) || df < 0. || lambda < 0.) - ML_ERR_return_NAN; - - if(lambda == 0.) { - if (df == 0.) ML_ERR_return_NAN; - return rgamma(df / 2., 2.); - } - else { - double r = rpois( lambda / 2.); - if (r > 0.) r = rchisq(2. * r); - if (df > 0.) r += rgamma(df / 2., 2.); - return r; - } -} diff --git a/deps/Rmath/src/rnorm.c b/deps/Rmath/src/rnorm.c deleted file mode 100644 index ef800df511cd0..0000000000000 --- a/deps/Rmath/src/rnorm.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include "Rnorm.h" - * double rnorm(double mu, double sigma); - * - * DESCRIPTION - * - * Random variates from the normal distribution. - * - */ - -#include "nmath.h" - -double rnorm(double mu, double sigma) -{ - if (ISNAN(mu) || !R_FINITE(sigma) || sigma < 0.) - ML_ERR_return_NAN; - if (sigma == 0. || !R_FINITE(mu)) - return mu; /* includes mu = +/- Inf with finite sigma */ - else - return mu + sigma * norm_rand(); -} diff --git a/deps/Rmath/src/rpois.c b/deps/Rmath/src/rpois.c deleted file mode 100644 index 0c22043a49523..0000000000000 --- a/deps/Rmath/src/rpois.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000-2011 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * double rpois(double lambda) - * - * DESCRIPTION - * - * Random variates from the Poisson distribution. - * - * REFERENCE - * - * Ahrens, J.H. and Dieter, U. (1982). - * Computer generation of Poisson deviates - * from modified normal distributions. - * ACM Trans. Math. Software 8, 163-179. - */ - -#include "nmath.h" - -#define a0 -0.5 -#define a1 0.3333333 -#define a2 -0.2500068 -#define a3 0.2000118 -#define a4 -0.1661269 -#define a5 0.1421878 -#define a6 -0.1384794 -#define a7 0.1250060 - -#define one_7 0.1428571428571428571 -#define one_12 0.0833333333333333333 -#define one_24 0.0416666666666666667 - -#define repeat for(;;) - -double rpois(double mu) -{ - /* Factorial Table (0:9)! */ - const static double fact[10] = - { - 1., 1., 2., 6., 24., 120., 720., 5040., 40320., 362880. - }; - - /* These are static --- persistent between calls for same mu : */ - static int l, m; - - static double b1, b2, c, c0, c1, c2, c3; - static double pp[36], p0, p, q, s, d, omega; - static double big_l;/* integer "w/o overflow" */ - static double muprev = 0., muprev2 = 0.;/*, muold = 0.*/ - - /* Local Vars [initialize some for -Wall]: */ - double del, difmuk= 0., E= 0., fk= 0., fx, fy, g, px, py, t, u= 0., v, x; - double pois = -1.; - int k, kflag, big_mu, new_big_mu = FALSE; - - if (!R_FINITE(mu) || mu < 0) - ML_ERR_return_NAN; - - if (mu <= 0.) - return 0.; - - big_mu = mu >= 10.; - if(big_mu) - new_big_mu = FALSE; - - if (!(big_mu && mu == muprev)) {/* maybe compute new persistent par.s */ - - if (big_mu) { - new_big_mu = TRUE; - /* Case A. (recalculation of s,d,l because mu has changed): - * The poisson probabilities pk exceed the discrete normal - * probabilities fk whenever k >= m(mu). - */ - muprev = mu; - s = sqrt(mu); - d = 6. * mu * mu; - big_l = floor(mu - 1.1484); - /* = an upper bound to m(mu) for all mu >= 10.*/ - } - else { /* Small mu ( < 10) -- not using normal approx. */ - - /* Case B. (start new table and calculate p0 if necessary) */ - - /*muprev = 0.;-* such that next time, mu != muprev ..*/ - if (mu != muprev) { - muprev = mu; - m = imax2(1, (int) mu); - l = 0; /* pp[] is already ok up to pp[l] */ - q = p0 = p = exp(-mu); - } - - repeat { - /* Step U. uniform sample for inversion method */ - u = unif_rand(); - if (u <= p0) - return 0.; - - /* Step T. table comparison until the end pp[l] of the - pp-table of cumulative poisson probabilities - (0.458 > ~= pp[9](= 0.45792971447) for mu=10 ) */ - if (l != 0) { - for (k = (u <= 0.458) ? 1 : imin2(l, m); k <= l; k++) - if (u <= pp[k]) - return (double)k; - if (l == 35) /* u > pp[35] */ - continue; - } - /* Step C. creation of new poisson - probabilities p[l..] and their cumulatives q =: pp[k] */ - l++; - for (k = l; k <= 35; k++) { - p *= mu / k; - q += p; - pp[k] = q; - if (u <= q) { - l = k; - return (double)k; - } - } - l = 35; - } /* end(repeat) */ - }/* mu < 10 */ - - } /* end {initialize persistent vars} */ - -/* Only if mu >= 10 : ----------------------- */ - - /* Step N. normal sample */ - g = mu + s * norm_rand();/* norm_rand() ~ N(0,1), standard normal */ - - if (g >= 0.) { - pois = floor(g); - /* Step I. immediate acceptance if pois is large enough */ - if (pois >= big_l) - return pois; - /* Step S. squeeze acceptance */ - fk = pois; - difmuk = mu - fk; - u = unif_rand(); /* ~ U(0,1) - sample */ - if (d * u >= difmuk * difmuk * difmuk) - return pois; - } - - /* Step P. preparations for steps Q and H. - (recalculations of parameters if necessary) */ - - if (new_big_mu || mu != muprev2) { - /* Careful! muprev2 is not always == muprev - because one might have exited in step I or S - */ - muprev2 = mu; - omega = M_1_SQRT_2PI / s; - /* The quantities b1, b2, c3, c2, c1, c0 are for the Hermite - * approximations to the discrete normal probabilities fk. */ - - b1 = one_24 / mu; - b2 = 0.3 * b1 * b1; - c3 = one_7 * b1 * b2; - c2 = b2 - 15. * c3; - c1 = b1 - 6. * b2 + 45. * c3; - c0 = 1. - b1 + 3. * b2 - 15. * c3; - c = 0.1069 / mu; /* guarantees majorization by the 'hat'-function. */ - } - - if (g >= 0.) { - /* 'Subroutine' F is called (kflag=0 for correct return) */ - kflag = 0; - goto Step_F; - } - - - repeat { - /* Step E. Exponential Sample */ - - E = exp_rand(); /* ~ Exp(1) (standard exponential) */ - - /* sample t from the laplace 'hat' - (if t <= -0.6744 then pk < fk for all mu >= 10.) */ - u = 2 * unif_rand() - 1.; - t = 1.8 + fsign(E, u); - if (t > -0.6744) { - pois = floor(mu + s * t); - fk = pois; - difmuk = mu - fk; - - /* 'subroutine' F is called (kflag=1 for correct return) */ - kflag = 1; - - Step_F: /* 'subroutine' F : calculation of px,py,fx,fy. */ - - if (pois < 10) { /* use factorials from table fact[] */ - px = -mu; - py = pow(mu, pois) / fact[(int)pois]; - } - else { - /* Case pois >= 10 uses polynomial approximation - a0-a7 for accuracy when advisable */ - del = one_12 / fk; - del = del * (1. - 4.8 * del * del); - v = difmuk / fk; - if (fabs(v) <= 0.25) - px = fk * v * v * (((((((a7 * v + a6) * v + a5) * v + a4) * - v + a3) * v + a2) * v + a1) * v + a0) - - del; - else /* |v| > 1/4 */ - px = fk * log(1. + v) - difmuk - del; - py = M_1_SQRT_2PI / sqrt(fk); - } - x = (0.5 - difmuk) / s; - x *= x;/* x^2 */ - fx = -0.5 * x; - fy = omega * (((c3 * x + c2) * x + c1) * x + c0); - if (kflag > 0) { - /* Step H. Hat acceptance (E is repeated on rejection) */ - if (c * fabs(u) <= py * exp(px + E) - fy * exp(fx + E)) - break; - } else - /* Step Q. Quotient acceptance (rare case) */ - if (fy - u * fy <= py * exp(px - fx)) - break; - }/* t > -.67.. */ - } - return pois; -} diff --git a/deps/Rmath/src/rt.c b/deps/Rmath/src/rt.c deleted file mode 100644 index 7fd0bab945571..0000000000000 --- a/deps/Rmath/src/rt.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000-2008 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * DESCRIPTION - * - * Pseudo-random variates from a t distribution. - * - * NOTES - * - * This function calls rchisq and rnorm to do the real work. - */ - -#include "nmath.h" - -double rt(double df) -{ - if (ISNAN(df) || df <= 0.0) ML_ERR_return_NAN; - - if(!R_FINITE(df)) - return norm_rand(); - else { -/* Some compilers (including MW6) evaluated this from right to left - return norm_rand() / sqrt(rchisq(df) / df); */ - double num = norm_rand(); - return num / sqrt(rchisq(df) / df); - } -} diff --git a/deps/Rmath/src/runif.c b/deps/Rmath/src/runif.c deleted file mode 100644 index efb8dd1ab3083..0000000000000 --- a/deps/Rmath/src/runif.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * DESCRIPTION - * - * Random variates from the uniform distribution. - */ -#include "nmath.h" - -double runif(double a, double b) -{ - if (!R_FINITE(a) || !R_FINITE(b) || b < a) ML_ERR_return_NAN; - - if (a == b) - return a; - else { - double u; - /* This is true of all builtin generators, but protect against - user-supplied ones */ - do {u = unif_rand();} while (u <= 0 || u >= 1); - return a + (b - a) * u; - } -} diff --git a/deps/Rmath/src/rweibull.c b/deps/Rmath/src/rweibull.c deleted file mode 100644 index bd280239f2b23..0000000000000 --- a/deps/Rmath/src/rweibull.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * DESCRIPTION - * - * Random variates from the Weibull distribution. - */ - -#include "nmath.h" - -double rweibull(double shape, double scale) -{ - if (!R_FINITE(shape) || !R_FINITE(scale) || shape <= 0. || scale <= 0.) { - if(scale == 0.) return 0.; - /* else */ - ML_ERR_return_NAN; - } - - return scale * pow(-log(unif_rand()), 1.0 / shape); -} diff --git a/deps/Rmath/src/sexp.c b/deps/Rmath/src/sexp.c deleted file mode 100644 index dc90701a6dbeb..0000000000000 --- a/deps/Rmath/src/sexp.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000-2002 the R Development Core Team - * Copyright (C) 2012 Viral B. Shah (randmtzig) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * double exp_rand(void); - * - * DESCRIPTION - * - * Random variates from the standard exponential distribution. - * - * REFERENCE - * - * Ahrens, J.H. and Dieter, U. (1972). - * Computer methods for sampling from the exponential and - * normal distributions. - * Comm. ACM, 15, 873-882. - */ - -extern double randmtzig_exprnd (void); - -double exp_rand(void) { - return randmtzig_exprnd(); -} - -#include "nmath.h" - -double exp_rand_rmath(void) -{ - /* q[k-1] = sum(log(2)^k / k!) k=1,..,n, */ - /* The highest n (here 16) is determined by q[n-1] = 1.0 */ - /* within standard precision */ - const static double q[] = - { - 0.6931471805599453, - 0.9333736875190459, - 0.9888777961838675, - 0.9984959252914960, - 0.9998292811061389, - 0.9999833164100727, - 0.9999985691438767, - 0.9999998906925558, - 0.9999999924734159, - 0.9999999995283275, - 0.9999999999728814, - 0.9999999999985598, - 0.9999999999999289, - 0.9999999999999968, - 0.9999999999999999, - 1.0000000000000000 - }; - - double a = 0.; - double u = unif_rand(); /* precaution if u = 0 is ever returned */ - while(u <= 0. || u >= 1.) u = unif_rand(); - for (;;) { - u += u; - if (u > 1.) - break; - a += q[0]; - } - u -= 1.; - - if (u <= q[0]) - return a + u; - - int i = 0; - double ustar = unif_rand(), umin = ustar; - do { - ustar = unif_rand(); - if (umin > ustar) - umin = ustar; - i++; - } while (u > q[i]); - return a + umin * q[0]; -} diff --git a/deps/Rmath/src/sign.c b/deps/Rmath/src/sign.c deleted file mode 100644 index 2bbdcce34cde3..0000000000000 --- a/deps/Rmath/src/sign.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * double sign(double x); - * - * DESCRIPTION - * - * This function computes the 'signum(.)' function: - * - * sign(x) = 1 if x > 0 - * sign(x) = 0 if x == 0 - * sign(x) = -1 if x < 0 - */ - -#include "nmath.h" - -double sign(double x) -{ - if (ISNAN(x)) - return x; - return ((x > 0) ? 1 : ((x == 0)? 0 : -1)); -} diff --git a/deps/Rmath/src/signrank.c b/deps/Rmath/src/signrank.c deleted file mode 100644 index 5d4ada6672fb7..0000000000000 --- a/deps/Rmath/src/signrank.c +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1999-2007 The R Development Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * double dsignrank(double x, double n, int give_log) - * double psignrank(double x, double n, int lower_tail, int log_p) - * double qsignrank(double x, double n, int lower_tail, int log_p) - * double rsignrank(double n) - * - * DESCRIPTION - * - * dsignrank The density of the Wilcoxon Signed Rank distribution. - * psignrank The distribution function of the Wilcoxon Signed Rank - * distribution. - * qsignrank The quantile function of the Wilcoxon Signed Rank - * distribution. - * rsignrank Random variates from the Wilcoxon Signed Rank - * distribution. - */ - -#include "nmath.h" -#include "dpq.h" - -static double *w; -static int allocated_n; - -static void -w_free(void) -{ - if (!w) return; - - free((void *) w); - w = 0; - allocated_n = 0; -} - -void signrank_free(void) -{ - w_free(); -} - -static void -w_init_maybe(int n) -{ - int u, c; - - u = n * (n + 1) / 2; - c = (u / 2); - - if (w) { - if(n != allocated_n) { - w_free(); - } - else return; - } - - if(!w) { - w = (double *) calloc((size_t) c + 1, sizeof(double)); -#ifdef MATHLIB_STANDALONE - if (!w) MATHLIB_ERROR("%s", _("signrank allocation error")); -#endif - allocated_n = n; - } -} - -static double -csignrank(int k, int n) -{ - int c, u, j; - -#ifndef MATHLIB_STANDALONE - R_CheckUserInterrupt(); -#endif - - u = n * (n + 1) / 2; - c = (u / 2); - - if (k < 0 || k > u) - return 0; - if (k > c) - k = u - k; - - if (n == 1) - return 1.; - if (w[0] == 1.) - return w[k]; - - w[0] = w[1] = 1.; - for(j=2; j < n+1; ++j) { - int i, end = imin2(j*(j+1)/2, c); - for(i=end; i >= j; --i) { - w[i] += w[i-j]; - } - } - - return w[k]; -} - -double dsignrank(double x, double n, int give_log) -{ - double d; - -#ifdef IEEE_754 - /* NaNs propagated correctly */ - if (ISNAN(x) || ISNAN(n)) return(x + n); -#endif - n = floor(n + 0.5); - if (n <= 0) - ML_ERR_return_NAN; - - if (fabs(x - floor(x + 0.5)) > 1e-7) - return(R_D__0); - x = floor(x + 0.5); - if ((x < 0) || (x > (n * (n + 1) / 2))) - return(R_D__0); - - w_init_maybe(n); - d = R_D_exp(log(csignrank(x, n)) - n * M_LN2); - - return(d); -} - -double psignrank(double x, double n, int lower_tail, int log_p) -{ - int i; - double f, p; - -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(n)) - return(x + n); -#endif - if (!R_FINITE(n)) ML_ERR_return_NAN; - n = floor(n + 0.5); - if (n <= 0) ML_ERR_return_NAN; - - x = floor(x + 1e-7); - if (x < 0.0) - return(R_DT_0); - if (x >= n * (n + 1) / 2) - return(R_DT_1); - - w_init_maybe(n); - f = exp(- n * M_LN2); - p = 0; - if (x <= (n * (n + 1) / 4)) { - for (i = 0; i <= x; i++) - p += csignrank(i, n) * f; - } - else { - x = n * (n + 1) / 2 - x; - for (i = 0; i < x; i++) - p += csignrank(i, n) * f; - lower_tail = !lower_tail; /* p = 1 - p; */ - } - - return(R_DT_val(p)); -} /* psignrank() */ - -double qsignrank(double x, double n, int lower_tail, int log_p) -{ - double f, p, q; - -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(n)) - return(x + n); -#endif - if (!R_FINITE(x) || !R_FINITE(n)) - ML_ERR_return_NAN; - R_Q_P01_check(x); - - n = floor(n + 0.5); - if (n <= 0) - ML_ERR_return_NAN; - - if (x == R_DT_0) - return(0); - if (x == R_DT_1) - return(n * (n + 1) / 2); - - if(log_p || !lower_tail) - x = R_DT_qIv(x); /* lower_tail,non-log "p" */ - - w_init_maybe(n); - f = exp(- n * M_LN2); - p = 0; - q = 0; - if (x <= 0.5) { - x = x - 10 * DBL_EPSILON; - for (;;) { - p += csignrank(q, n) * f; - if (p >= x) - break; - q++; - } - } - else { - x = 1 - x + 10 * DBL_EPSILON; - for (;;) { - p += csignrank(q, n) * f; - if (p > x) { - q = n * (n + 1) / 2 - q; - break; - } - q++; - } - } - - return(q); -} - -double rsignrank(double n) -{ - int i, k; - double r; - -#ifdef IEEE_754 - /* NaNs propagated correctly */ - if (ISNAN(n)) return(n); -#endif - n = floor(n + 0.5); - if (n < 0) ML_ERR_return_NAN; - - if (n == 0) - return(0); - r = 0.0; - k = (int) n; - for (i = 0; i < k; ) { - r += (++i) * floor(unif_rand() + 0.5); - } - return(r); -} diff --git a/deps/Rmath/src/snorm.c b/deps/Rmath/src/snorm.c deleted file mode 100644 index 1be292137b2e8..0000000000000 --- a/deps/Rmath/src/snorm.c +++ /dev/null @@ -1,336 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 1998 Ross Ihaka - * Copyright (C) 2000-9 The R Development Core Team - * Copyright (C) 2012 Viral B. Shah (randmtzig) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - * SYNOPSIS - * - * #include - * double norm_rand(void); - * - * DESCRIPTION - * - * Random variates from the STANDARD normal distribution N(0,1). - * - * Is called from rnorm(..), but also rt(), rf(), rgamma(), ... - */ - -extern double randmtzig_randn (void); - -double norm_rand(void) { - return randmtzig_randn(); -} - -#include -#include "nmath.h" - -#define repeat for(;;) - -#ifdef MATHLIB_STANDALONE -static -#else -attribute_hidden -#endif -double BM_norm_keep = 0.0; - -N01type N01_kind = INVERSION; - -#ifndef MATHLIB_STANDALONE -typedef void * (*DL_FUNC)(); -extern DL_FUNC User_norm_fun; /* declared and set in ../main/RNG.c */ -#endif - -/* - * REFERENCE - * - * Ahrens, J.H. and Dieter, U. - * Extensions of Forsythe's method for random sampling from - * the normal distribution. - * Math. Comput. 27, 927-937. - * - * The definitions of the constants a[k], d[k], t[k] and - * h[k] are according to the abovementioned article - */ -double norm_rand_rmath(void) -{ - - const static double a[32] = - { - 0.0000000, 0.03917609, 0.07841241, 0.1177699, - 0.1573107, 0.19709910, 0.23720210, 0.2776904, - 0.3186394, 0.36012990, 0.40225010, 0.4450965, - 0.4887764, 0.53340970, 0.57913220, 0.6260990, - 0.6744898, 0.72451440, 0.77642180, 0.8305109, - 0.8871466, 0.94678180, 1.00999000, 1.0775160, - 1.1503490, 1.22985900, 1.31801100, 1.4177970, - 1.5341210, 1.67594000, 1.86273200, 2.1538750 - }; - - const static double d[31] = - { - 0.0000000, 0.0000000, 0.0000000, 0.0000000, - 0.0000000, 0.2636843, 0.2425085, 0.2255674, - 0.2116342, 0.1999243, 0.1899108, 0.1812252, - 0.1736014, 0.1668419, 0.1607967, 0.1553497, - 0.1504094, 0.1459026, 0.1417700, 0.1379632, - 0.1344418, 0.1311722, 0.1281260, 0.1252791, - 0.1226109, 0.1201036, 0.1177417, 0.1155119, - 0.1134023, 0.1114027, 0.1095039 - }; - - const static double t[31] = - { - 7.673828e-4, 0.002306870, 0.003860618, 0.005438454, - 0.007050699, 0.008708396, 0.010423570, 0.012209530, - 0.014081250, 0.016055790, 0.018152900, 0.020395730, - 0.022811770, 0.025434070, 0.028302960, 0.031468220, - 0.034992330, 0.038954830, 0.043458780, 0.048640350, - 0.054683340, 0.061842220, 0.070479830, 0.081131950, - 0.094624440, 0.112300100, 0.136498000, 0.171688600, - 0.227624100, 0.330498000, 0.584703100 - }; - - const static double h[31] = - { - 0.03920617, 0.03932705, 0.03950999, 0.03975703, - 0.04007093, 0.04045533, 0.04091481, 0.04145507, - 0.04208311, 0.04280748, 0.04363863, 0.04458932, - 0.04567523, 0.04691571, 0.04833487, 0.04996298, - 0.05183859, 0.05401138, 0.05654656, 0.05953130, - 0.06308489, 0.06737503, 0.07264544, 0.07926471, - 0.08781922, 0.09930398, 0.11555990, 0.14043440, - 0.18361420, 0.27900160, 0.70104740 - }; - - /*----------- Constants and definitions for Kinderman - Ramage --- */ - /* - * REFERENCE - * - * Kinderman A. J. and Ramage J. G. (1976). - * Computer generation of normal random variables. - * JASA 71, 893-896. - */ - -#define C1 0.398942280401433 -#define C2 0.180025191068563 -#define g(x) (C1*exp(-x*x/2.0)-C2*(A-x)) - - const static double A = 2.216035867166471; - - double s, u1, w, y, u2, u3, aa, tt, theta, R; - int i; - - switch(N01_kind) { - - case AHRENS_DIETER: /* see Reference above */ - - u1 = unif_rand(); - s = 0.0; - if (u1 > 0.5) - s = 1.0; - u1 = u1 + u1 - s; - u1 *= 32.0; - i = (int) u1; - if (i == 32) - i = 31; - if (i != 0) { - u2 = u1 - i; - aa = a[i - 1]; - while (u2 <= t[i - 1]) { - u1 = unif_rand(); - w = u1 * (a[i] - aa); - tt = (w * 0.5 + aa) * w; - repeat { - if (u2 > tt) - goto deliver; - u1 = unif_rand(); - if (u2 < u1) - break; - tt = u1; - u2 = unif_rand(); - } - u2 = unif_rand(); - } - w = (u2 - t[i - 1]) * h[i - 1]; - } - else { - i = 6; - aa = a[31]; - repeat { - u1 = u1 + u1; - if (u1 >= 1.0) - break; - aa = aa + d[i - 1]; - i = i + 1; - } - u1 = u1 - 1.0; - repeat { - w = u1 * d[i - 1]; - tt = (w * 0.5 + aa) * w; - repeat { - u2 = unif_rand(); - if (u2 > tt) - goto jump; - u1 = unif_rand(); - if (u2 < u1) - break; - tt = u1; - } - u1 = unif_rand(); - } - jump:; - } - - deliver: - y = aa + w; - return (s == 1.0) ? -y : y; - - /*-----------------------------------------------------------*/ - - case BUGGY_KINDERMAN_RAMAGE: /* see Reference above */ - /* note: this has problems, but is retained for - * reproducibility of older codes, with the same - * numeric code */ - u1 = unif_rand(); - if(u1 < 0.884070402298758) { - u2 = unif_rand(); - return A*(1.13113163544180*u1+u2-1); - } - - if(u1 >= 0.973310954173898) { /* tail: */ - repeat { - u2 = unif_rand(); - u3 = unif_rand(); - tt = (A*A-2*log(u3)); - if( u2*u2<(A*A)/tt ) - return (u1 < 0.986655477086949) ? sqrt(tt) : -sqrt(tt); - } - } - - if(u1 >= 0.958720824790463) { /* region3: */ - repeat { - u2 = unif_rand(); - u3 = unif_rand(); - tt = A - 0.630834801921960* fmin2(u2,u3); - if(fmax2(u2,u3) <= 0.755591531667601) - return (u2= 0.911312780288703) { /* region2: */ - repeat { - u2 = unif_rand(); - u3 = unif_rand(); - tt = 0.479727404222441+1.105473661022070*fmin2(u2,u3); - if( fmax2(u2,u3)<=0.872834976671790 ) - return (u2= 0.973310954173898) { /* tail: */ - repeat { - u2 = unif_rand(); - u3 = unif_rand(); - tt = (A*A-2*log(u3)); - if( u2*u2<(A*A)/tt ) - return (u1 < 0.986655477086949) ? sqrt(tt) : -sqrt(tt); - } - } - - if(u1 >= 0.958720824790463) { /* region3: */ - repeat { - u2 = unif_rand(); - u3 = unif_rand(); - tt = A - 0.630834801921960* fmin2(u2,u3); - if(fmax2(u2,u3) <= 0.755591531667601) - return (u2= 0.911312780288703) { /* region2: */ - repeat { - u2 = unif_rand(); - u3 = unif_rand(); - tt = 0.479727404222441+1.105473661022070*fmin2(u2,u3); - if( fmax2(u2,u3)<=0.872834976671790 ) - return (u2 15, uses the series 1/12n - 1/360n^3 + ... - * For n <=15, integers or half-integers, uses stored values. - * For other n < 15, uses lgamma directly (don't use this to - * write lgamma!) - * - * Merge in to R: - * Copyright (C) 2000, The R Core Development Team - * R has lgammafn, and lgamma is not part of ISO C - */ - -#include "nmath.h" - -/* stirlerr(n) = log(n!) - log( sqrt(2*pi*n)*(n/e)^n ) - * = log Gamma(n+1) - 1/2 * [log(2*pi) + log(n)] - n*[log(n) - 1] - * = log Gamma(n+1) - (n + 1/2) * log(n) + n - log(2*pi)/2 - * - * see also lgammacor() in ./lgammacor.c which computes almost the same! - */ - -double attribute_hidden stirlerr(double n) -{ - -#define S0 0.083333333333333333333 /* 1/12 */ -#define S1 0.00277777777777777777778 /* 1/360 */ -#define S2 0.00079365079365079365079365 /* 1/1260 */ -#define S3 0.000595238095238095238095238 /* 1/1680 */ -#define S4 0.0008417508417508417508417508/* 1/1188 */ - -/* - error for 0, 0.5, 1.0, 1.5, ..., 14.5, 15.0. -*/ - const static double sferr_halves[31] = { - 0.0, /* n=0 - wrong, place holder only */ - 0.1534264097200273452913848, /* 0.5 */ - 0.0810614667953272582196702, /* 1.0 */ - 0.0548141210519176538961390, /* 1.5 */ - 0.0413406959554092940938221, /* 2.0 */ - 0.03316287351993628748511048, /* 2.5 */ - 0.02767792568499833914878929, /* 3.0 */ - 0.02374616365629749597132920, /* 3.5 */ - 0.02079067210376509311152277, /* 4.0 */ - 0.01848845053267318523077934, /* 4.5 */ - 0.01664469118982119216319487, /* 5.0 */ - 0.01513497322191737887351255, /* 5.5 */ - 0.01387612882307074799874573, /* 6.0 */ - 0.01281046524292022692424986, /* 6.5 */ - 0.01189670994589177009505572, /* 7.0 */ - 0.01110455975820691732662991, /* 7.5 */ - 0.010411265261972096497478567, /* 8.0 */ - 0.009799416126158803298389475, /* 8.5 */ - 0.009255462182712732917728637, /* 9.0 */ - 0.008768700134139385462952823, /* 9.5 */ - 0.008330563433362871256469318, /* 10.0 */ - 0.007934114564314020547248100, /* 10.5 */ - 0.007573675487951840794972024, /* 11.0 */ - 0.007244554301320383179543912, /* 11.5 */ - 0.006942840107209529865664152, /* 12.0 */ - 0.006665247032707682442354394, /* 12.5 */ - 0.006408994188004207068439631, /* 13.0 */ - 0.006171712263039457647532867, /* 13.5 */ - 0.005951370112758847735624416, /* 14.0 */ - 0.005746216513010115682023589, /* 14.5 */ - 0.005554733551962801371038690 /* 15.0 */ - }; - double nn; - - if (n <= 15.0) { - nn = n + n; - if (nn == (int)nn) return(sferr_halves[(int)nn]); - return(lgammafn(n + 1.) - (n + 0.5)*log(n) + n - M_LN_SQRT_2PI); - } - - nn = n*n; - if (n>500) return((S0-S1/nn)/n); - if (n> 80) return((S0-(S1-S2/nn)/nn)/n); - if (n> 35) return((S0-(S1-(S2-S3/nn)/nn)/nn)/n); - /* 15 < n <= 35 : */ - return((S0-(S1-(S2-(S3-S4/nn)/nn)/nn)/nn)/n); -} diff --git a/deps/Rmath/src/sunif.c b/deps/Rmath/src/sunif.c deleted file mode 100644 index b1db5a47cc126..0000000000000 --- a/deps/Rmath/src/sunif.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Mathlib : A C Library of Special Functions - * Copyright (C) 2000, 2003 The R Development Core Team - * Copyright (C) 2012 Viral B. Shah (DSFMT) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, a copy is available at - * http://www.r-project.org/Licenses/ - * - */ - -/* A version of Marsaglia-MultiCarry */ - -/* -static unsigned int I1=1234, I2=5678; - -void set_seed(unsigned int i1, unsigned int i2) -{ - I1 = i1; I2 = i2; -} - -void get_seed(unsigned int *i1, unsigned int *i2) -{ - *i1 = I1; *i2 = I2; -} - - -double unif_rand(void) -{ - I1= 36969*(I1 & 0177777) + (I1>>16); - I2= 18000*(I2 & 0177777) + (I2>>16); - return ((I1 << 16)^(I2 & 0177777)) * 2.328306437080797e-10; // in [0,1) -} -*/ - -extern double dsfmt_gv_genrand_close_open(); - -double unif_rand(void) -{ - return dsfmt_gv_genrand_close_open(); -} - diff --git a/deps/Rmath/src/toms708.c b/deps/Rmath/src/toms708.c deleted file mode 100644 index daffccb84d5d4..0000000000000 --- a/deps/Rmath/src/toms708.c +++ /dev/null @@ -1,2313 +0,0 @@ -/* Based on C translation of ACM TOMS 708 - Please do not change this, e.g. to use R's versions of the - ancillary routines, without investigating the error analysis as we - do need very high relative accuracy. This version has about - 14 digits accuracy. -*/ - -#undef min -#define min(a,b) ((a < b)?a:b) -#undef max -#define max(a,b) ((a > b)?a:b) - -#include "nmath.h" -#include "dpq.h" -/* after config.h to avoid warning on Solaris */ -#include -/* is included by above, with suitable defines in glibc systems - to make log1p and expm1 declared */ - -/**----------- DEBUGGING ------------- - * - * make CFLAGS='-DDEBUG_bratio ...' - *MM: (cd `R-devel RHOME`/src/nmath ; gcc -std=gnu99 -I. -I../../src/include -I../../../R/src/include -I/usr/local/include -DHAVE_CONFIG_H -DDEBUG_bratio -g -c ../../../R/src/nmath/toms708.c -o toms708.o; cd ../..; make R) -*/ -#ifdef DEBUG_bratio -# include -#endif - -/* MM added R_D_LExp, so redefine here in terms of rexpm1 */ -#undef R_Log1_Exp -#define R_Log1_Exp(x) ((x) > -M_LN2 ? log(-rexpm1(x)) : log1p(-exp(x))) - - -static double bfrac(double, double, double, double, double, double, int log_p); -static void bgrat(double, double, double, double, double *, double, int *); -static void grat1(double, double, double, double *, double *, double); -static double apser(double, double, double, double); -static double bpser(double, double, double, double, int log_p); -static double basym(double, double, double, double, int log_p); -static double fpser(double, double, double, double, int log_p); -static double bup(double, double, double, double, int, double); -static double exparg(int); -static double psi(double); -static double gam1(double); -static double gamln1(double); -static double betaln(double, double); -static double algdiv(double, double); -static double brcmp1(int, double, double, double, double); -static double brcomp(double, double, double, double, int log_p); -static double rlog1(double); -static double bcorr(double, double); -static double gamln(double); -static double alnrel(double); -static double esum(int, double); -static double erf__(double); -static double rexpm1(double); -static double erfc1(int, double); -static double gsumln(double, double); - -/* ALGORITHM 708, COLLECTED ALGORITHMS FROM ACM. - * This work published in Transactions On Mathematical Software, - * vol. 18, no. 3, September 1992, pp. 360-373z. - */ - -/* Changes by R Core Team : - * add log_p and work towards gaining precision in that case - */ - -void attribute_hidden -bratio(double a, double b, double x, double y, double *w, double *w1, - int *ierr, int log_p) -{ -/* ----------------------------------------------------------------------- - - * Evaluation of the Incomplete Beta function I_x(a,b) - - * -------------------- - - * It is assumed that a and b are nonnegative, and that x <= 1 - * and y = 1 - x. Bratio assigns w and w1 the values - - * w = I_x(a,b) - * w1 = 1 - I_x(a,b) - - * ierr is a variable that reports the status of the results. - * If no input errors are detected then ierr is set to 0 and - * w and w1 are computed. otherwise, if an error is detected, - * then w and w1 are assigned the value 0 and ierr is set to - * one of the following values ... - - * ierr = 1 if a or b is negative - * ierr = 2 if a = b = 0 - * ierr = 3 if x < 0 or x > 1 - * ierr = 4 if y < 0 or y > 1 - * ierr = 5 if x + y != 1 - * ierr = 6 if x = a = 0 - * ierr = 7 if y = b = 0 - * ierr = 8 "error" in bgrat() - - * -------------------- - * Written by Alfred H. Morris, Jr. - * Naval Surface Warfare Center - * Dahlgren, Virginia - * Revised ... Nov 1991 -* ----------------------------------------------------------------------- */ - - Rboolean do_swap; - int n, ierr1 = 0; - double z, a0, b0, x0, y0, eps, lambda; - -/* eps is a machine dependent constant: the smallest - * floating point number for which 1.0 + eps > 1.0 */ - eps = 2.0 * Rf_d1mach(3); /* == DBL_EPSILON (in R, Rmath) */ - -/* ----------------------------------------------------------------------- */ - *w = R_D__0; - *w1 = R_D__0; - - if (a < 0.0 || b < 0.0) { *ierr = 1; return; } - if (a == 0.0 && b == 0.0) { *ierr = 2; return; } - if (x < 0.0 || x > 1.0) { *ierr = 3; return; } - if (y < 0.0 || y > 1.0) { *ierr = 4; return; } - - /* check that 'y == 1 - x' : */ - z = x + y - 0.5 - 0.5; - - if (fabs(z) > eps * 3.0) { *ierr = 5; return; } - -#ifdef DEBUG_bratio - REprintf("bratio(a=%g, b=%g, x=%9g, y=%9g, .., log_p=%d): ", a,b,x,y, log_p); -#endif - - *ierr = 0; - if (x == 0.0) goto L200; - if (y == 0.0) goto L210; - - if (a == 0.0) goto L211; - if (b == 0.0) goto L201; - - eps = max(eps, 1e-15); - if (max(a,b) < eps * .001) { /* procedure for a and b < 0.001 * eps */ - /* L230: */ - if(log_p) { - z = log(a + b); - *w = log(b) - z; - *w1 = log(a) - z; - } else { - *w = b / (a + b); - *w1 = a / (a + b); - } - return; - } - -#define SET_0_noswap \ - a0 = a; x0 = x; \ - b0 = b; y0 = y; - -#define SET_0_swap \ - a0 = b; x0 = y; \ - b0 = a; y0 = x; - - if (min(a,b) <= 1.) { /*------------------------ a <= 1 or b <= 1 ---- */ - - do_swap = (x > 0.5); - if (do_swap) { - SET_0_swap; - } else { - SET_0_noswap; - } - /* now have x0 <= 1/2 <= y0 (still x0+y0 == 1) */ - -#ifdef DEBUG_bratio - REprintf(" min(a,b) <= 1 : do_swap = %d; ", do_swap); -#endif - - if (b0 < min(eps, eps * a0)) { /* L80: */ - *w = fpser(a0, b0, x0, eps, log_p); - *w1 = log_p ? R_Log1_Exp(*w) : 0.5 - *w + 0.5; -#ifdef DEBUG_bratio - REprintf(" b0 small -> w := fpser(*) = %15g\n", *w); -#endif - goto L_end_after_log; - } - - if (a0 < min(eps, eps * b0) && b0 * x0 <= 1.0) { /* L90: */ - *w1 = apser(a0, b0, x0, eps); -#ifdef DEBUG_bratio - REprintf(" a0 small -> w1 := apser(*) = %15g\n", *w1); -#endif - goto L_end_from_w1; - } - - if (max(a0,b0) > 1.0) { /* L20: min(a,b) <= 1 < max(a,b) */ -#ifdef DEBUG_bratio - REprintf(" L20: min(a,b) <= 1 < max(a,b); "); -#endif - if (b0 <= 1.0) goto L100; - - if (x0 >= 0.29) /* was 0.3, PR#13786 */ goto L110; - - if (x0 < 0.1) { - if (pow(x0*b0, a0) <= 0.7) { - goto L100; - } - } - if (b0 > 15.0) { - *w1 = 0.; - goto L131; - } - } else { /* a, b <= 1 */ -#ifdef DEBUG_bratio - REprintf(" both a,b <= 1; "); -#endif - if (a0 >= min(0.2, b0)) goto L100; - - if (pow(x0, a0) <= 0.9) goto L100; - - if (x0 >= 0.3) goto L110; - } - n = 20; /* goto L130; */ - *w1 = bup(b0, a0, y0, x0, n, eps); -#ifdef DEBUG_bratio - REprintf(" ... n=20 and *w1 := bup(*) = %15g; "); -#endif - b0 += n; - L131: - bgrat(b0, a0, y0, x0, w1, 15*eps, &ierr1); - -#ifdef DEBUG_bratio - REprintf(" L131: bgrat(*, w1) ==> w1 = %15g\n", *w1); -#endif - goto L_end_from_w1; - } - else { /* L30: -------------------- both a, b > 1 {a0 > 1 & b0 > 1} ---*/ - - if (a > b) - lambda = (a + b) * y - b; - else - lambda = a - (a + b) * x; - - do_swap = (lambda < 0.0); - if (do_swap) { - lambda = -lambda; - SET_0_swap; - } else { - SET_0_noswap; - } - -#ifdef DEBUG_bratio - REprintf(" L30: both a, b > 1; |lambda| = %#g, do_swap = %d\n", - lambda, do_swap); -#endif - - if (b0 < 40.0) { -#ifdef DEBUG_bratio - REprintf(" b0 < 40; "); -#endif - if (b0 * x0 <= 0.7 - || (log_p && lambda > 650.)) /* << added 2010-03-18 */ - goto L100; - else - goto L140; - } - else if (a0 > b0) { /* ---- a0 > b0 >= 40 ---- */ -#ifdef DEBUG_bratio - REprintf(" a0 > b0 >= 40; "); -#endif - if (b0 <= 100.0 || lambda > b0 * 0.03) - goto L120; - - } else if (a0 <= 100.0) { -#ifdef DEBUG_bratio - REprintf(" a0 <= 100; a0 <= b0 >= 40; "); -#endif - goto L120; - } - else if (lambda > a0 * 0.03) { -#ifdef DEBUG_bratio - REprintf(" b0 >= a0 > 100; lambda > a0 * 0.03 "); -#endif - goto L120; - } - - /* else if none of the above L180: */ - *w = basym(a0, b0, lambda, eps * 100.0, log_p); - *w1 = log_p ? R_Log1_Exp(*w) : 0.5 - *w + 0.5; -#ifdef DEBUG_bratio - REprintf(" b0 >= a0 > 100; lambda <= a0 * 0.03: *w := basym(*) = %15g\n", - *w); -#endif - goto L_end_after_log; - - } /* else: a, b > 1 */ - -/* EVALUATION OF THE APPROPRIATE ALGORITHM */ - -L100: - *w = bpser(a0, b0, x0, eps, log_p); - *w1 = log_p ? R_Log1_Exp(*w) : 0.5 - *w + 0.5; -#ifdef DEBUG_bratio - REprintf(" L100: *w := bpser(*) = %15g\n", *w); -#endif - goto L_end_after_log; - -L110: - *w1 = bpser(b0, a0, y0, eps, log_p); - *w = log_p ? R_Log1_Exp(*w1) : 0.5 - *w1 + 0.5; -#ifdef DEBUG_bratio - REprintf(" L110: *w1 := bpser(*) = %15g\n", *w1); -#endif - goto L_end_after_log; - -L120: - *w = bfrac(a0, b0, x0, y0, lambda, eps * 15.0, log_p); - *w1 = log_p ? R_Log1_Exp(*w) : 0.5 - *w + 0.5; -#ifdef DEBUG_bratio - REprintf(" L120: *w := bfrac(*) = %g\n", *w); -#endif - goto L_end_after_log; - -L140: - /* b0 := fractional_part( b0 ) in (0, 1] */ - n = (int) b0; - b0 -= n; - if (b0 == 0.) { - --n; b0 = 1.; - } - - *w = bup(b0, a0, y0, x0, n, eps); - -#ifdef DEBUG_bratio - REprintf(" L140: *w := bup(b0=%g, *) = %15g; ", b0, *w); -#endif - if(*w < DBL_MIN && log_p) { /* do not believe it; try bpser() : */ - /*revert: */ b0 += n; - /* which is only valid if b0 <= 1 || b0*x0 <= 0.7 */ - goto L100; - } - if (x0 <= 0.7) { - /* log_p : TODO: w = bup(.) + bpser(.) -- not so easy to use log-scale */ - *w += bpser(a0, b0, x0, eps, /* log_p = */ FALSE); -#ifdef DEBUG_bratio - REprintf(" x0 <= 0.7: *w := *w + bpser(*) = %15g\n", *w); -#endif - goto L_end_from_w; - } - /* L150: */ - if (a0 <= 15.0) { - n = 20; - *w += bup(a0, b0, x0, y0, n, eps); -#ifdef DEBUG_bratio - REprintf("\n a0 <= 15: *w := *w + bup(*) = %15g;", *w); -#endif - a0 += n; - } - bgrat(a0, b0, x0, y0, w, 15*eps, &ierr1); -#ifdef DEBUG_bratio - REprintf(" bgrat(*) ==> *w = %g\n", *w); -#endif - goto L_end_from_w; - - -/* TERMINATION OF THE PROCEDURE */ - -L200: - if (a == 0.0) { *ierr = 6; return; } -L201: - *w = R_D__0; - *w1 = R_D__1; - return; - -L210: - if (b == 0.0) { *ierr = 7; return; } -L211: - *w = R_D__1; - *w1 = R_D__0; - return; - -L_end_from_w: - if(log_p) { - *w1 = log1p(-*w); - *w = log(*w); - } else { - *w1 = 0.5 - *w + 0.5; - } - goto L_end_after_log; - -L_end_from_w1: - if(log_p) { - *w = log1p(-*w1); - *w1 = log(*w1); - } else { - *w = 0.5 - *w1 + 0.5; - } - -L_end_after_log: - if (do_swap) { /* swap */ - double t = *w; *w = *w1; *w1 = t; - } - return; - -} /* bratio */ - -#undef SET_0_noswap -#undef SET_0_swap - -double fpser(double a, double b, double x, double eps, int log_p) -{ -/* ----------------------------------------------------------------------- * - - * EVALUATION OF I (A,B) - * X - - * FOR B < MIN(EPS, EPS*A) AND X <= 0.5 - - * ----------------------------------------------------------------------- */ - - double ans, c, s, t, an, tol; - - /* SET ans := x^a : */ - if (log_p) { - ans = a * log(x); - } else if (a > eps * 0.001) { - t = a * log(x); - if (t < exparg(1)) { /* exp(t) would underflow */ - return 0.0; - } - ans = exp(t); - } else - ans = 1.; - -/* NOTE THAT 1/B(A,B) = B */ - - if (log_p) - ans += log(b) - log(a); - else - ans *= b / a; - - tol = eps / a; - an = a + 1.0; - t = x; - s = t / an; - do { - an += 1.0; - t = x * t; - c = t / an; - s += c; - } while (fabs(c) > tol); - - if (log_p) - ans += log1p(a * s); - else - ans *= a * s + 1.0; - return ans; -} /* fpser */ - -static double apser(double a, double b, double x, double eps) -{ -/* ----------------------------------------------------------------------- - * apser() yields the incomplete beta ratio I_{1-x}(b,a) for - * a <= min(eps,eps*b), b*x <= 1, and x <= 0.5, i.e., a is very small. - * Use only if above inequalities are satisfied. - * ----------------------------------------------------------------------- */ - - static double const g = .577215664901533; - - double tol, c, j, s, t, aj; - double bx = b * x; - - t = x - bx; - if (b * eps <= 0.02) - c = log(x) + psi(b) + g + t; - else - c = log(bx) + g + t; - - tol = eps * 5.0 * fabs(c); - j = 1.; - s = 0.; - do { - j += 1.0; - t *= x - bx / j; - aj = t / j; - s += aj; - } while (fabs(aj) > tol); - - return -a * (c + s); -} /* apser */ - -static double bpser(double a, double b, double x, double eps, int log_p) -{ -/* ----------------------------------------------------------------------- - * Power SERies expansion for evaluating I_x(a,b) when - * b <= 1 or b*x <= 0.7. eps is the tolerance used. - * ----------------------------------------------------------------------- */ - - int i, m; - double ans, c, n, t, u, w, z, a0, b0, apb, tol, sum; - - if (x == 0.) { - return R_D__0; - } -/* ----------------------------------------------------------------------- */ -/* compute the factor x^a/(a*Beta(a,b)) */ -/* ----------------------------------------------------------------------- */ - a0 = min(a,b); - if (a0 >= 1.0) { /* ------ 1 <= a0 <= b0 ------ */ - z = a * log(x) - betaln(a, b); - ans = log_p ? z - log(a) : exp(z) / a; - } - else { - b0 = max(a,b); - - if (b0 < 8.0) { - - if (b0 <= 1.0) { /* ------ a0 < 1 and b0 <= 1 ------ */ - - if(log_p) { - ans = a * log(x); - } else { - ans = pow(x, a); - if (ans == 0.) /* once underflow, always underflow .. */ - return ans; - } - apb = a + b; - if (apb > 1.0) { - u = a + b - 1.; - z = (gam1(u) + 1.0) / apb; - } else { - z = gam1(apb) + 1.0; - } - c = (gam1(a) + 1.0) * (gam1(b) + 1.0) / z; - - if(log_p) /* FIXME ? -- improve quite a bit for c ~= 1 */ - ans += log(c * (b / apb)); - else - ans *= c * (b / apb); - - } else { /* ------ a0 < 1 < b0 < 8 ------ */ - - u = gamln1(a0); - m = b0 - 1.0; - if (m >= 1) { - c = 1.0; - for (i = 1; i <= m; ++i) { - b0 += -1.0; - c *= b0 / (a0 + b0); - } - u += log(c); - } - - z = a * log(x) - u; - b0 += -1.0; - apb = a0 + b0; - if (apb > 1.0) { - u = a0 + b0 - 1.; - t = (gam1(u) + 1.0) / apb; - } else { - t = gam1(apb) + 1.0; - } - - if(log_p) /* FIXME? potential for improving log(t) */ - ans = z + log(a0 / a) + log1p(gam1(b0)) - log(t); - else - ans = exp(z) * (a0 / a) * (gam1(b0) + 1.0) / t; - } - - } else { /* ------ a0 < 1 < 8 <= b0 ------ */ - - u = gamln1(a0) + algdiv(a0, b0); - z = a * log(x) - u; - - if(log_p) - ans = z + log(a0 / a); - else - ans = a0 / a * exp(z); - } - } - - if (!log_p && (ans == 0.0 || a <= eps * 0.1)) { - return ans; - } - -/* ----------------------------------------------------------------------- */ -/* COMPUTE THE SERIES */ -/* ----------------------------------------------------------------------- */ - sum = 0.; - n = 0.; - c = 1.; - tol = eps / a; - - do { - n += 1.; - c *= (0.5 - b / n + 0.5) * x; - w = c / (a + n); - sum += w; - } while (fabs(w) > tol); - - if(log_p) { - if (a*sum > -1.0) ans += log1p(a * sum); - else ans = ML_NEGINF; - } else - ans *= a * sum + 1.0; - return ans; -} /* bpser */ - -static double bup(double a, double b, double x, double y, int n, double eps) -{ -/* ----------------------------------------------------------------------- */ -/* EVALUATION OF I_x(A,B) - I_x(A+N,B) WHERE N IS A POSITIVE INT. */ -/* EPS IS THE TOLERANCE USED. */ -/* ----------------------------------------------------------------------- */ - - /* System generated locals */ - double ret_val; - - /* Local variables */ - int i, k, mu, nm1; - double d, l, r, t, w; - double ap1, apb; - -/* OBTAIN THE SCALING FACTOR EXP(-MU) AND */ -/* EXP(MU)*(X^A * Y^B / BETA(A,B))/A */ - - apb = a + b; - ap1 = a + 1.0; - if (n > 1 && a >= 1. && apb >= ap1 * 1.1) { - mu = fabs(exparg(1)); - k = (int) exparg(0); - if (k < mu) { - mu = k; - } - t = (double) mu; - d = exp(-t); - } - else { - mu = 0; - d = 1.0; - } - - /* L10: */ - ret_val = brcmp1(mu, a, b, x, y) / a; - if (n == 1 || ret_val == 0.0) { - return ret_val; - } - nm1 = n - 1; - w = d; - -/* LET K BE THE INDEX OF THE MAXIMUM TERM */ - - k = 0; - if (b <= 1.0) { - goto L40; - } - if (y > 1e-4) { - r = (b - 1.0) * x / y - a; - if (r < 1.0) { - goto L40; - } - k = nm1; - t = (double) nm1; - if (r < t) { - k = (int) r; - } - } else { - k = nm1; - } - -/* ADD THE INCREASING TERMS OF THE SERIES */ - -/* L30: */ - for (i = 1; i <= k; ++i) { - l = (double) (i - 1); - d = (apb + l) / (ap1 + l) * x * d; - w += d; -/* L31: */ - } - if (k == nm1) { - goto L50; - } - -/* ADD THE REMAINING TERMS OF THE SERIES */ - -L40: - for (i = k+1; i <= nm1; ++i) { - l = (double) (i - 1); - d = (apb + l) / (ap1 + l) * x * d; - w += d; - if (d <= eps * w) /* relativ convergence (eps) */ - break; - } - -/* TERMINATE THE PROCEDURE */ - -L50: - ret_val *= w; - return ret_val; -} /* bup */ - -static double bfrac(double a, double b, double x, double y, double lambda, - double eps, int log_p) -{ -/* ----------------------------------------------------------------------- - Continued fraction expansion for I_x(a,b) when a, b > 1. - It is assumed that lambda = (a + b)*y - b. - -----------------------------------------------------------------------*/ - - double c, e, n, p, r, s, t, w, c0, c1, r0, an, bn, yp1, anp1, bnp1, - beta, alpha; - - double brc = brcomp(a, b, x, y, log_p); - - if (!log_p && brc == 0.) /* already underflowed to 0 */ - return 0.; - - c = lambda + 1.0; - c0 = b / a; - c1 = 1.0 / a + 1.0; - yp1 = y + 1.0; - - n = 0.0; - p = 1.0; - s = a + 1.0; - an = 0.0; - bn = 1.0; - anp1 = 1.0; - bnp1 = c / c1; - r = c1 / c; - -/* CONTINUED FRACTION CALCULATION */ - - do { - n += 1.0; - t = n / a; - w = n * (b - n) * x; - e = a / s; - alpha = p * (p + c0) * e * e * (w * x); - e = (t + 1.0) / (c1 + t + t); - beta = n + w / s + e * (c + n * yp1); - p = t + 1.0; - s += 2.0; - - /* update an, bn, anp1, and bnp1 */ - - t = alpha * an + beta * anp1; - an = anp1; - anp1 = t; - t = alpha * bn + beta * bnp1; - bn = bnp1; - bnp1 = t; - - r0 = r; - r = anp1 / bnp1; - if (fabs(r - r0) <= eps * r) { - break; - } - - /* rescale an, bn, anp1, and bnp1 */ - - an /= bnp1; - bn /= bnp1; - anp1 = r; - bnp1 = 1.0; - } while (1); - - return (log_p ? brc + log(r) : brc * r); -} /* bfrac */ - -static double brcomp(double a, double b, double x, double y, int log_p) -{ -/* ----------------------------------------------------------------------- - * Evaluation of x^a * y^b / Beta(a,b) - * ----------------------------------------------------------------------- */ - - static double const__ = .398942280401433; /* == 1/sqrt(2*pi); */ - /* R has M_1_SQRT_2PI , and M_LN_SQRT_2PI = ln(sqrt(2*pi)) = 0.918938.. */ - - int i, n; - double c, e, h, t, u, v, z, a0, b0, x0, y0, apb, lnx, lny; - double lambda; - - - if (x == 0.0 || y == 0.0) { - return R_D__0; - } - a0 = min(a, b); - if (a0 >= 8.0) { - goto L100; - } - - if (x <= .375) { - lnx = log(x); - lny = alnrel(-x); - } - else { - if (y > .375) { - lnx = log(x); - lny = log(y); - } else { - lnx = alnrel(-y); - lny = log(y); - } - } - - z = a * lnx + b * lny; - if (a0 >= 1.) { - z -= betaln(a, b); - return R_D_exp(z); - } - -/* ----------------------------------------------------------------------- */ -/* PROCEDURE FOR a < 1 OR b < 1 */ -/* ----------------------------------------------------------------------- */ - - b0 = max(a, b); - if (b0 >= 8.0) { /* L80: */ - u = gamln1(a0) + algdiv(a0, b0); - - return (log_p ? log(a0) + (z - u) : a0 * exp(z - u)); - } - /* else : */ - - if (b0 <= 1.0) { /* algorithm for max(a,b) = b0 <= 1 */ - - double e_z = R_D_exp(z); - - if (!log_p && e_z == 0.0) /* exp() underflow */ - return 0.; - - apb = a + b; - if (apb > 1.0) { - u = a + b - 1.; - z = (gam1(u) + 1.0) / apb; - } else { - z = gam1(apb) + 1.0; - } - - c = (gam1(a) + 1.0) * (gam1(b) + 1.0) / z; - /* FIXME? log(a0*c)= log(a0)+ log(c) and that is improvable */ - return (log_p - ? e_z + log(a0 * c) - log1p(a0/b0) - : e_z * (a0 * c) / (a0 / b0 + 1.0)); - } - /* else : */ - -/* ALGORITHM FOR 1 < b0 < 8 */ - - u = gamln1(a0); - n = b0 - 1.0; - if (n >= 1) { - c = 1.0; - for (i = 1; i <= n; ++i) { - b0 += -1.0; - c *= b0 / (a0 + b0); - } - u = log(c) + u; - } - z -= u; - b0 += -1.0; - apb = a0 + b0; - if (apb > 1.0) { - u = a0 + b0 - 1.; - t = (gam1(u) + 1.0) / apb; - } else { - t = gam1(apb) + 1.0; - } - - return (log_p - ? log(a0) + z + log1p(gam1(b0)) - log(t) - : a0 * exp(z) * (gam1(b0) + 1.0) / t); - - - -/* ----------------------------------------------------------------------- */ -/* PROCEDURE FOR A >= 8 AND B >= 8 */ -/* ----------------------------------------------------------------------- */ -L100: - if (a <= b) { - h = a / b; - x0 = h / (h + 1.0); - y0 = 1.0 / (h + 1.0); - lambda = a - (a + b) * x; - } else { - h = b / a; - x0 = 1.0 / (h + 1.0); - y0 = h / (h + 1.0); - lambda = (a + b) * y - b; - } - - e = -lambda / a; - if (fabs(e) > .6) - u = e - log(x / x0); - else - u = rlog1(e); - - e = lambda / b; - if (fabs(e) <= .6) - v = rlog1(e); - else - v = e - log(y / y0); - - z = log_p ? -(a * u + b * v) : exp(-(a * u + b * v)); - - return(log_p - ? -M_LN_SQRT_2PI + .5*log(b * x0) + z - bcorr(a,b) - : const__ * sqrt(b * x0) * z * exp(-bcorr(a, b))); -} /* brcomp */ - -static double brcmp1(int mu, double a, double b, double x, double y) -{ -/* ----------------------------------------------------------------------- - * EVALUATION OF EXP(MU) * (X^A * Y^B / BETA(A,B)) - * ----------------------------------------------------------------------- */ - - static double const__ = .398942280401433; /* == 1/sqrt(2*pi); */ - /* R has M_1_SQRT_2PI */ - - /* System generated locals */ - double ret_val, r1; - - /* Local variables */ - double c, e, h; - int i, n; - double t, u, v, z, a0, b0, x0, y0, apb, lnx, lny; - double lambda; - - a0 = min(a,b); - if (a0 >= 8.0) { - goto L100; - } - - if (x > .375) { - goto L10; - } - lnx = log(x); - lny = alnrel(-x); - goto L20; -L10: - if (y > .375) { - goto L11; - } - lnx = alnrel(-y); - lny = log(y); - goto L20; -L11: - lnx = log(x); - lny = log(y); - -L20: - z = a * lnx + b * lny; - if (a0 < 1.0) { - goto L30; - } - z -= betaln(a, b); - ret_val = esum(mu, z); - return ret_val; -/* ----------------------------------------------------------------------- */ -/* PROCEDURE FOR A < 1 OR B < 1 */ -/* ----------------------------------------------------------------------- */ -L30: - b0 = max(a,b); - if (b0 >= 8.0) { - goto L80; - } - if (b0 > 1.0) { - goto L60; - } - -/* ALGORITHM FOR b0 <= 1 */ - - ret_val = esum(mu, z); - if (ret_val == 0.0) { - return ret_val; - } - - apb = a + b; - if (apb > 1.0) { - goto L40; - } - z = gam1(apb) + 1.0; - goto L50; -L40: - u = a + b - 1.; - z = (gam1(u) + 1.0) / apb; - -L50: - c = (gam1(a) + 1.0) * (gam1(b) + 1.0) / z; - ret_val = ret_val * (a0 * c) / (a0 / b0 + 1.0); - return ret_val; - -/* ALGORITHM FOR 1 < b0 < 8 */ - -L60: - u = gamln1(a0); - n = b0 - 1.0; - if (n < 1) { - goto L70; - } - c = 1.0; - for (i = 1; i <= n; ++i) { - b0 += -1.0; - c *= b0 / (a0 + b0); -/* L61: */ - } - u = log(c) + u; - -L70: - z -= u; - b0 += -1.0; - apb = a0 + b0; - if (apb > 1.0) { - goto L71; - } - t = gam1(apb) + 1.0; - goto L72; -L71: - u = a0 + b0 - 1.; - t = (gam1(u) + 1.0) / apb; -L72: - ret_val = a0 * esum(mu, z) * (gam1(b0) + 1.0) / t; - return ret_val; - -/* ALGORITHM FOR b0 >= 8 */ - -L80: - u = gamln1(a0) + algdiv(a0, b0); - ret_val = a0 * esum(mu, z - u); - return ret_val; -/* ----------------------------------------------------------------------- */ -/* PROCEDURE FOR A >= 8 AND B >= 8 */ -/* ----------------------------------------------------------------------- */ -L100: - if (a > b) { - goto L101; - } - h = a / b; - x0 = h / (h + 1.0); - y0 = 1.0 / (h + 1.0); - lambda = a - (a + b) * x; - goto L110; -L101: - h = b / a; - x0 = 1.0 / (h + 1.0); - y0 = h / (h + 1.0); - lambda = (a + b) * y - b; - -L110: - e = -lambda / a; - if (fabs(e) > 0.6) { - goto L111; - } - u = rlog1(e); - goto L120; -L111: - u = e - log(x / x0); - -L120: - e = lambda / b; - if (fabs(e) > 0.6) { - goto L121; - } - v = rlog1(e); - goto L130; -L121: - v = e - log(y / y0); - -L130: - r1 = -(a * u + b * v); - z = esum(mu, r1); - - return const__ * sqrt(b * x0) * z * exp(-bcorr(a, b)); - -} /* brcmp1 */ - -static void bgrat(double a, double b, double x, double y, double *w, - double eps, int *ierr) -{ -/* ----------------------------------------------------------------------- -* Asymptotic Expansion for I_x(a,b) when a is larger than b. -* The result of the expansion is added to w. -* It is assumed a >= 15 and b <= 1. -* eps is the tolerance used. -* ierr is a variable that reports the status of the results. -* ----------------------------------------------------------------------- */ - - double c[30], d[30]; - int i, n, nm1; - double j, l, p, q, r, s, t, u, v, z, n2, t2, dj, cn, nu, bm1; - double lnx, sum, bp2n, coef; - - bm1 = b - 0.5 - 0.5; - nu = a + bm1 * 0.5; - if (y > 0.375) - lnx = log(x); - else - lnx = alnrel(-y); - - z = -nu * lnx; - if (b * z == 0.0) goto L_Error; /* should *never* happen */ - -/* COMPUTATION OF THE EXPANSION */ - -/* set r := exp(-z) * z^b / Gamma(b) */ - r = b * (gam1(b) + 1.0) * exp(b * log(z)); - - r = r * exp(a * lnx) * exp(bm1 * 0.5 * lnx); - u = algdiv(b, a) + b * log(nu); - u = r * exp(-u); - if (u == 0.0) { -#ifdef DEBUG_bratio - REprintf(" bgrat(*) *underflow* r = %g ", r); -#endif - goto L_Error; - } - grat1(b, z, r, &p, &q, eps); /* -> (p,q) {p + q = 1} */ - - v = 0.25 / (nu * nu); - t2 = lnx * 0.25 * lnx; - l = *w / u; - j = q / r; - sum = j; - t = 1.0; - cn = 1.0; - n2 = 0.0; - for (n = 1; n <= 30; ++n) { - bp2n = b + n2; - j = (bp2n * (bp2n + 1.0) * j + (z + bp2n + 1.0) * t) * v; - n2 += 2.0; - t *= t2; - cn /= n2 * (n2 + 1.0); - nm1 = n - 1; - c[nm1] = cn; - s = 0.0; - if (n > 1) { - coef = b - n; - for (i = 1; i <= nm1; ++i) { - s += coef * c[i - 1] * d[nm1 - i]; - coef += b; - } - } - d[nm1] = bm1 * cn + s / n; - dj = d[nm1] * j; - sum += dj; - if (sum <= 0.0) { - goto L_Error; - } - if (fabs(dj) <= eps * (sum + l)) { - break; - } - } - -/* ADD THE RESULTS TO W */ - *ierr = 0; - *w += u * sum; - return; - -/* THE EXPANSION CANNOT BE COMPUTED */ - -L_Error: - *ierr = 1; - return; -} /* bgrat */ - -static void grat1(double a, double x, double r, double *p, double *q, - double eps) -{ -/* ----------------------------------------------------------------------- -* Evaluation of the incomplete gamma ratio functions -* P(a,x) and Q(a,x) - -* It is assumed that a <= 1. eps is the tolerance to be used. -* the input argument r has the value r = e^(-x)* x^a / Gamma(a). -* ----------------------------------------------------------------------- */ - - double c, g, h, j, l, t, w, z, an, am0, an0, a2n, b2n, cma; - double tol, sum, a2nm1, b2nm1; - - if (a * x == 0.0) { /* L130: */ - if (x <= a) - goto L100; - else - goto L110; - } - else if (a == 0.5) { - goto L120; - } - - if (x < 1.1) { /* L10: Taylor series for P(a,x)/x^a */ - - an = 3.0; - c = x; - sum = x / (a + 3.0); - tol = eps * 0.1 / (a + 1.0); - do { - an += 1.0; - c = -c * (x / an); - t = c / (a + an); - sum += t; - } while (fabs(t) > tol); - - j = a * x * ((sum / 6.0 - 0.5 / (a + 2.0)) * x + 1.0 / (a + 1.0)); - - z = a * log(x); - h = gam1(a); - g = h + 1.0; - if (x >= 0.25) { - if (a < x / 2.59) { - goto L40; - } - } - else { - if (z > -0.13394) { - goto L40; - } - } - - w = exp(z); - *p = w * g * (0.5 - j + 0.5); - *q = 0.5 - *p + 0.5; - return; - - L40: - l = rexpm1(z); - w = l + 0.5 + 0.5; - *q = (w * j - l) * g - h; - if (*q < 0.0) { - goto L110; - } - *p = 0.5 - *q + 0.5; - return; - - } - -/* L50: ---- (x >= 1.1) ---- Continued Fraction Expansion */ - - a2nm1 = 1.0; - a2n = 1.0; - b2nm1 = x; - b2n = x + (1.0 - a); - c = 1.0; - - do { - a2nm1 = x * a2n + c * a2nm1; - b2nm1 = x * b2n + c * b2nm1; - am0 = a2nm1 / b2nm1; - c += 1.0; - cma = c - a; - a2n = a2nm1 + cma * a2n; - b2n = b2nm1 + cma * b2n; - an0 = a2n / b2n; - } while (fabs(an0 - am0) >= eps * an0); - - *q = r * an0; - *p = 0.5 - *q + 0.5; - return; - -/* SPECIAL CASES */ - -L100: - *p = 0.0; - *q = 1.0; - return; - -L110: - *p = 1.0; - *q = 0.0; - return; - -L120: - if (x < 0.25) { - *p = erf__(sqrt(x)); - *q = 0.5 - *p + 0.5; - } else { - *q = erfc1(0, sqrt(x)); - *p = 0.5 - *q + 0.5; - } - return; - -} /* grat1 */ - -static double basym(double a, double b, double lambda, double eps, int log_p) -{ -/* ----------------------------------------------------------------------- */ -/* ASYMPTOTIC EXPANSION FOR I_x(A,B) FOR LARGE A AND B. */ -/* LAMBDA = (A + B)*Y - B AND EPS IS THE TOLERANCE USED. */ -/* IT IS ASSUMED THAT LAMBDA IS NONNEGATIVE AND THAT */ -/* A AND B ARE GREATER THAN OR EQUAL TO 15. */ -/* ----------------------------------------------------------------------- */ - - -/* ------------------------ */ -/* ****** NUM IS THE MAXIMUM VALUE THAT N CAN TAKE IN THE DO LOOP */ -/* ENDING AT STATEMENT 50. IT IS REQUIRED THAT NUM BE EVEN. */ -#define num_IT 20 -/* THE ARRAYS A0, B0, C, D HAVE DIMENSION NUM + 1. */ - - static double const e0 = 1.12837916709551;/* e0 == 2/sqrt(pi) */ - static double const e1 = .353553390593274;/* e1 == 2^(-3/2) */ - static double const ln_e0 = 0.120782237635245; /* == ln(e0) */ - - double a0[num_IT + 1], b0[num_IT + 1], c[num_IT + 1], d[num_IT + 1]; - double f, h, r, s, t, u, w, z, j0, j1, h2, r0, r1, t0, t1, w0, z0, z2, hn, zn; - double sum, znm1, bsum, dsum; - - int i, j, m, n, im1, mm1, np1, imj, mmj; - -/* ------------------------ */ - - f = a * rlog1(-lambda/a) + b * rlog1(lambda/b); - if(log_p) - t = -f; - else { - t = exp(-f); - if (t == 0.0) { - return 0; /* once underflow, always underflow .. */ - } - } - z0 = sqrt(f); - z = z0 / e1 * 0.5; - z2 = f + f; - - if (a < b) { - h = a / b; - r0 = 1.0 / (h + 1.0); - r1 = (b - a) / b; - w0 = 1.0 / sqrt(a * (h + 1.0)); - } else { - h = b / a; - r0 = 1.0 / (h + 1.0); - r1 = (b - a) / a; - w0 = 1.0 / sqrt(b * (h + 1.0)); - } - - a0[0] = r1 * .66666666666666663; - c[0] = a0[0] * -0.5; - d[0] = -c[0]; - j0 = 0.5 / e0 * erfc1(1, z0); - j1 = e1; - sum = j0 + d[0] * w0 * j1; - - s = 1.0; - h2 = h * h; - hn = 1.0; - w = w0; - znm1 = z; - zn = z2; - for (n = 2; n <= num_IT; n += 2) { - hn = h2 * hn; - a0[n - 1] = r0 * 2.0 * (h * hn + 1.0) / (n + 2.0); - np1 = n + 1; - s += hn; - a0[np1 - 1] = r1 * 2.0 * s / (n + 3.0); - - for (i = n; i <= np1; ++i) { - r = (i + 1.0) * -0.5; - b0[0] = r * a0[0]; - for (m = 2; m <= i; ++m) { - bsum = 0.0; - mm1 = m - 1; - for (j = 1; j <= mm1; ++j) { - mmj = m - j; - bsum += (j * r - mmj) * a0[j - 1] * b0[mmj - 1]; - } - b0[m - 1] = r * a0[m - 1] + bsum / m; - } - c[i - 1] = b0[i - 1] / (i + 1.0); - - dsum = 0.0; - im1 = i - 1; - for (j = 1; j <= im1; ++j) { - imj = i - j; - dsum += d[imj - 1] * c[j - 1]; - } - d[i - 1] = -(dsum + c[i - 1]); - } - - j0 = e1 * znm1 + (n - 1.0) * j0; - j1 = e1 * zn + n * j1; - znm1 = z2 * znm1; - zn = z2 * zn; - w = w0 * w; - t0 = d[n - 1] * w * j0; - w = w0 * w; - t1 = d[np1 - 1] * w * j1; - sum += t0 + t1; - if (fabs(t0) + fabs(t1) <= eps * sum) { - break; - } - } - - if(log_p) - return ln_e0 + t - bcorr(a, b) + log(sum); - else { - u = exp(-bcorr(a, b)); - return e0 * t * u * sum; - } - -} /* basym_ */ - - -static double exparg(int l) -{ -/* -------------------------------------------------------------------- */ -/* IF L = 0 THEN EXPARG(L) = THE LARGEST POSITIVE W FOR WHICH - * EXP(W) CAN BE COMPUTED. ==> exparg(0) = 709.7827 nowadays. */ - -/* IF L IS NONZERO THEN EXPARG(L) = THE LARGEST NEGATIVE W FOR - * WHICH THE COMPUTED VALUE OF EXP(W) IS NONZERO. - * ==> exparg(1) = -708.3964 nowadays. */ - -/* Note... only an approximate value for exparg(L) is needed. */ -/* -------------------------------------------------------------------- */ - - static double const lnb = .69314718055995; - int m; - - if (l == 0) { - m = Rf_i1mach(16); - return m * lnb * .99999; - } - m = Rf_i1mach(15) - 1; - return m * lnb * .99999; -} /* exparg */ - -static double esum(int mu, double x) -{ -/* ----------------------------------------------------------------------- */ -/* EVALUATION OF EXP(MU + X) */ -/* ----------------------------------------------------------------------- */ - double w; - - if (x > 0.0) { /* L10: */ - if (mu > 0) goto L20; - w = mu + x; - if (w < 0.0) goto L20; - } - else { /* x <= 0 */ - if (mu < 0) goto L20; - w = mu + x; - if (w > 0.0) goto L20; - } - return exp(w); - -L20: - w = (double) (mu); - return exp(w) * exp(x); -} /* esum */ - -double rexpm1(double x) -{ -/* ----------------------------------------------------------------------- */ -/* EVALUATION OF THE FUNCTION EXP(X) - 1 */ -/* ----------------------------------------------------------------------- */ - - static double p1 = 9.14041914819518e-10; - static double p2 = .0238082361044469; - static double q1 = -.499999999085958; - static double q2 = .107141568980644; - static double q3 = -.0119041179760821; - static double q4 = 5.95130811860248e-4; - - if (fabs(x) <= 0.15) { - return x * (((p2 * x + p1) * x + 1.0) / - ((((q4 * x + q3) * x + q2) * x + q1) * x + 1.0)); - } - else { /* |x| > 0.15 : */ - double w = exp(x); - if (x > 0.0) - return w * (0.5 - 1.0 / w + 0.5); - else - return w - 0.5 - 0.5; - } - -} /* rexpm1 */ - -static double alnrel(double a) -{ -/* ----------------------------------------------------------------------- - * Evaluation of the function ln(1 + a) - * ----------------------------------------------------------------------- */ - - static double p1 = -1.29418923021993; - static double p2 = .405303492862024; - static double p3 = -.0178874546012214; - static double q1 = -1.62752256355323; - static double q2 = .747811014037616; - static double q3 = -.0845104217945565; - - if (fabs(a) <= 0.375) { - double t, t2, w; - t = a / (a + 2.0); - t2 = t * t; - w = (((p3 * t2 + p2) * t2 + p1) * t2 + 1.) / - (((q3 * t2 + q2) * t2 + q1) * t2 + 1.); - return t * 2.0 * w; - } else { - double x = a + 1.; - return log(x); - } -} /* alnrel */ - -static double rlog1(double x) -{ -/* ----------------------------------------------------------------------- - * Evaluation of the function x - ln(1 + x) - * ----------------------------------------------------------------------- */ - - static double a = .0566749439387324; - static double b = .0456512608815524; - static double p0 = .333333333333333; - static double p1 = -.224696413112536; - static double p2 = .00620886815375787; - static double q1 = -1.27408923933623; - static double q2 = .354508718369557; - - double h, r, t, w, w1; - - if (x < -0.39 || x > 0.57) { /* direct evaluation */ - w = x + 0.5 + 0.5; - return x - log(w); - } - /* else */ - if (x < -0.18) { /* L10: */ - h = x + .3; - h /= .7; - w1 = a - h * .3; - } - else if (x > 0.18) { /* L20: */ - h = x * .75 - .25; - w1 = b + h / 3.0; - } - else { /* Argument Reduction */ - h = x; - w1 = 0.0; - } - -/* L30: Series Expansion */ - - r = h / (h + 2.0); - t = r * r; - w = ((p2 * t + p1) * t + p0) / ((q2 * t + q1) * t + 1.0); - return t * 2.0 * (1.0 / (1.0 - r) - r * w) + w1; - -} /* rlog1 */ - -static double erf__(double x) -{ -/* ----------------------------------------------------------------------- - * EVALUATION OF THE REAL ERROR FUNCTION - * ----------------------------------------------------------------------- */ - - /* Initialized data */ - - static double c = .564189583547756; - static double a[5] = { 7.7105849500132e-5,-.00133733772997339, - .0323076579225834,.0479137145607681,.128379167095513 }; - static double b[3] = { .00301048631703895,.0538971687740286, - .375795757275549 }; - static double p[8] = { -1.36864857382717e-7,.564195517478974, - 7.21175825088309,43.1622272220567,152.98928504694, - 339.320816734344,451.918953711873,300.459261020162 }; - static double q[8] = { 1.,12.7827273196294,77.0001529352295, - 277.585444743988,638.980264465631,931.35409485061, - 790.950925327898,300.459260956983 }; - static double r[5] = { 2.10144126479064,26.2370141675169, - 21.3688200555087,4.6580782871847,.282094791773523 }; - static double s[4] = { 94.153775055546,187.11481179959, - 99.0191814623914,18.0124575948747 }; - - /* System generated locals */ - double ret_val; - - /* Local variables */ - double t, x2, ax, bot, top; - - ax = fabs(x); - if (ax <= 0.5) { - t = x * x; - top = (((a[0] * t + a[1]) * t + a[2]) * t + a[3]) * t + a[4] + 1.0; - bot = ((b[0] * t + b[1]) * t + b[2]) * t + 1.0; - - return x * (top / bot); - } - /* else: ax > 0.5 */ - - if (ax <= 4.) { /* ax in (0.5, 4] */ - - top = ((((((p[0] * ax + p[1]) * ax + p[2]) * ax + p[3]) * ax + p[4]) * ax - + p[5]) * ax + p[6]) * ax + p[7]; - bot = ((((((q[0] * ax + q[1]) * ax + q[2]) * ax + q[3]) * ax + q[4]) * ax - + q[5]) * ax + q[6]) * ax + q[7]; - ret_val = 0.5 - exp(-x * x) * top / bot + 0.5; - if (x < 0.0) { - ret_val = -ret_val; - } - return ret_val; - } - - /* else: ax > 4 */ - - if (ax >= 5.8) { - return x > 0 ? 1 : -1; - } - x2 = x * x; - t = 1.0 / x2; - top = (((r[0] * t + r[1]) * t + r[2]) * t + r[3]) * t + r[4]; - bot = (((s[0] * t + s[1]) * t + s[2]) * t + s[3]) * t + 1.0; - t = (c - top / (x2 * bot)) / ax; - ret_val = 0.5 - exp(-x2) * t + 0.5; - if (x < 0.0) { - ret_val = -ret_val; - } - return ret_val; - -} /* erf */ - -static double erfc1(int ind, double x) -{ -/* ----------------------------------------------------------------------- */ -/* EVALUATION OF THE COMPLEMENTARY ERROR FUNCTION */ - -/* ERFC1(IND,X) = ERFC(X) IF IND = 0 */ -/* ERFC1(IND,X) = EXP(X*X)*ERFC(X) OTHERWISE */ -/* ----------------------------------------------------------------------- */ - - /* Initialized data */ - - static double c = .564189583547756; - static double a[5] = { 7.7105849500132e-5,-.00133733772997339, - .0323076579225834,.0479137145607681,.128379167095513 }; - static double b[3] = { .00301048631703895,.0538971687740286, - .375795757275549 }; - static double p[8] = { -1.36864857382717e-7,.564195517478974, - 7.21175825088309,43.1622272220567,152.98928504694, - 339.320816734344,451.918953711873,300.459261020162 }; - static double q[8] = { 1.,12.7827273196294,77.0001529352295, - 277.585444743988,638.980264465631,931.35409485061, - 790.950925327898,300.459260956983 }; - static double r[5] = { 2.10144126479064,26.2370141675169, - 21.3688200555087,4.6580782871847,.282094791773523 }; - static double s[4] = { 94.153775055546,187.11481179959, - 99.0191814623914,18.0124575948747 }; - - /* System generated locals */ - double ret_val, d1; - - /* Local variables */ - double e, t, w, ax, bot, top; - -/* ABS(X) <= 0.5 */ - - ax = fabs(x); - if (ax > 0.5) { - goto L10; - } - t = x * x; - top = (((a[0] * t + a[1]) * t + a[2]) * t + a[3]) * t + a[4] + 1.0; - bot = ((b[0] * t + b[1]) * t + b[2]) * t + 1.0; - ret_val = 0.5 - x * (top / bot) + 0.5; - if (ind != 0) { - ret_val = exp(t) * ret_val; - } - return ret_val; - -/* 0.5 < ABS(X) <= 4 */ - -L10: - if (ax > 4.0) { - goto L20; - } - top = ((((((p[0] * ax + p[1]) * ax + p[2]) * ax + p[3]) * ax + p[4]) * ax - + p[5]) * ax + p[6]) * ax + p[7]; - bot = ((((((q[0] * ax + q[1]) * ax + q[2]) * ax + q[3]) * ax + q[4]) * ax - + q[5]) * ax + q[6]) * ax + q[7]; - ret_val = top / bot; - goto L40; - -/* ABS(X) > 4 */ - -L20: - if (x <= -5.6) { - goto L50; - } - if (ind != 0) { - goto L30; - } - if (x > 100.0) { - goto L60; - } - if (x * x > -exparg(1)) { - goto L60; - } - -L30: -/* Computing 2nd power */ - d1 = 1.0 / x; - t = d1 * d1; - top = (((r[0] * t + r[1]) * t + r[2]) * t + r[3]) * t + r[4]; - bot = (((s[0] * t + s[1]) * t + s[2]) * t + s[3]) * t + 1.0; - ret_val = (c - t * top / bot) / ax; - -/* FINAL ASSEMBLY */ - -L40: - if (ind == 0) { - goto L41; - } - if (x < 0.0) { - ret_val = exp(x * x) * 2.0 - ret_val; - } - return ret_val; -L41: - w = x * x; - t = w; - e = w - t; - ret_val = (0.5 - e + 0.5) * exp(-t) * ret_val; - if (x < 0.0) { - ret_val = 2.0 - ret_val; - } - return ret_val; - -/* LIMIT VALUE FOR LARGE NEGATIVE X */ - -L50: - ret_val = 2.0; - if (ind != 0) { - ret_val = exp(x * x) * 2.0; - } - return ret_val; - -/* LIMIT VALUE FOR LARGE POSITIVE X */ -/* WHEN IND = 0 */ - -L60: - ret_val = 0.0; - return ret_val; -} /* erfc1 */ - -static double gam1(double a) -{ -/* ------------------------------------------------------------------ */ -/* COMPUTATION OF 1/GAMMA(A+1) - 1 FOR -0.5 <= A <= 1.5 */ -/* ------------------------------------------------------------------ */ - - double d, t, w, bot, top; - - t = a; - d = a - 0.5; - if (d > 0.0) { - t = d - 0.5; - } - if (t < 0.0) { /* L30: */ - static double - r[9] = { -.422784335098468,-.771330383816272, - -.244757765222226,.118378989872749,9.30357293360349e-4, - -.0118290993445146,.00223047661158249,2.66505979058923e-4, - -1.32674909766242e-4 }, - s1 = .273076135303957, - s2 = .0559398236957378; - - top = (((((((r[8] * t + r[7]) * t + r[6]) * t + r[5]) * t + r[4] - ) * t + r[3]) * t + r[2]) * t + r[1]) * t + r[0]; - bot = (s2 * t + s1) * t + 1.0; - w = top / bot; - if (d > 0.0) - return t * w / a; - else - return a * (w + 0.5 + 0.5); - - } else if (t == 0) { /* L10: */ - return 0.; - - } else { /* t > 0; L20: */ - static double - p[7] = { .577215664901533,-.409078193005776, - -.230975380857675,.0597275330452234,.0076696818164949, - -.00514889771323592,5.89597428611429e-4 }, - q[5] = { 1.,.427569613095214,.158451672430138, - .0261132021441447,.00423244297896961 }; - - top = (((((p[6] * t + p[5]) * t + p[4]) * t + p[3]) * t + p[2] - ) * t + p[1]) * t + p[0]; - bot = (((q[4] * t + q[3]) * t + q[2]) * t + q[1]) * t + 1.0; - w = top / bot; - if (d > 0.0) /* L21: */ - return t / a * (w - 0.5 - 0.5); - else - return a * w; - } -} /* gam1 */ - -static double gamln1(double a) -{ -/* ----------------------------------------------------------------------- */ -/* EVALUATION OF LN(GAMMA(1 + A)) FOR -0.2 <= A <= 1.25 */ -/* ----------------------------------------------------------------------- */ - - double w; - if (a < 0.6) { - static double p0 = .577215664901533; - static double p1 = .844203922187225; - static double p2 = -.168860593646662; - static double p3 = -.780427615533591; - static double p4 = -.402055799310489; - static double p5 = -.0673562214325671; - static double p6 = -.00271935708322958; - static double q1 = 2.88743195473681; - static double q2 = 3.12755088914843; - static double q3 = 1.56875193295039; - static double q4 = .361951990101499; - static double q5 = .0325038868253937; - static double q6 = 6.67465618796164e-4; - w = ((((((p6 * a + p5)* a + p4)* a + p3)* a + p2)* a + p1)* a + p0) / - ((((((q6 * a + q5)* a + q4)* a + q3)* a + q2)* a + q1)* a + 1.); - return -(a) * w; - } - else { /* 0.6 <= a <= 1.25 */ - static double r0 = .422784335098467; - static double r1 = .848044614534529; - static double r2 = .565221050691933; - static double r3 = .156513060486551; - static double r4 = .017050248402265; - static double r5 = 4.97958207639485e-4; - static double s1 = 1.24313399877507; - static double s2 = .548042109832463; - static double s3 = .10155218743983; - static double s4 = .00713309612391; - static double s5 = 1.16165475989616e-4; - double x = a - 0.5 - 0.5; - w = (((((r5 * x + r4) * x + r3) * x + r2) * x + r1) * x + r0) / - (((((s5 * x + s4) * x + s3) * x + s2) * x + s1) * x + 1.0); - return x * w; - } -} /* gamln1 */ - -static double psi(double x) -{ -/* --------------------------------------------------------------------- - - * Evaluation of the Digamma function psi(x) - - * ----------- - - * Psi(xx) is assigned the value 0 when the digamma function cannot - * be computed. - - * The main computation involves evaluation of rational Chebyshev - * approximations published in Math. Comp. 27, 123-127(1973) by - * Cody, Strecok and Thacher. */ - -/* --------------------------------------------------------------------- */ -/* Psi was written at Argonne National Laboratory for the FUNPACK */ -/* package of special function subroutines. Psi was modified by */ -/* A.H. Morris (NSWC). */ -/* --------------------------------------------------------------------- */ - - static double piov4 = .785398163397448; /* == pi / 4 */ -/* dx0 = zero of psi() to extended precision : */ - static double dx0 = 1.461632144968362341262659542325721325; - -/* --------------------------------------------------------------------- */ -/* COEFFICIENTS FOR RATIONAL APPROXIMATION OF */ -/* PSI(X) / (X - X0), 0.5 <= X <= 3.0 */ - static double p1[7] = { .0089538502298197,4.77762828042627, - 142.441585084029,1186.45200713425,3633.51846806499, - 4138.10161269013,1305.60269827897 }; - static double q1[6] = { 44.8452573429826,520.752771467162, - 2210.0079924783,3641.27349079381,1908.310765963, - 6.91091682714533e-6 }; -/* --------------------------------------------------------------------- */ - - -/* --------------------------------------------------------------------- */ -/* COEFFICIENTS FOR RATIONAL APPROXIMATION OF */ -/* PSI(X) - LN(X) + 1 / (2*X), X > 3.0 */ - - static double p2[4] = { -2.12940445131011,-7.01677227766759, - -4.48616543918019,-.648157123766197 }; - static double q2[4] = { 32.2703493791143,89.2920700481861, - 54.6117738103215,7.77788548522962 }; -/* --------------------------------------------------------------------- */ - - int i, m, n, nq; - double d2; - double w, z; - double den, aug, sgn, xmx0, xmax1, upper, xsmall; - -/* --------------------------------------------------------------------- */ - - -/* MACHINE DEPENDENT CONSTANTS ... */ - -/* --------------------------------------------------------------------- */ -/* XMAX1 = THE SMALLEST POSITIVE FLOATING POINT CONSTANT - WITH ENTIRELY INT REPRESENTATION. ALSO USED - AS NEGATIVE OF LOWER BOUND ON ACCEPTABLE NEGATIVE - ARGUMENTS AND AS THE POSITIVE ARGUMENT BEYOND WHICH - PSI MAY BE REPRESENTED AS LOG(X). - * Originally: xmax1 = amin1(ipmpar(3), 1./spmpar(1)) */ - xmax1 = (double) INT_MAX; - d2 = 0.5 / Rf_d1mach(3); /*= 0.5 / (0.5 * DBL_EPS) = 1/DBL_EPSILON = 2^52 */ - if(xmax1 > d2) xmax1 = d2; - -/* --------------------------------------------------------------------- */ -/* XSMALL = ABSOLUTE ARGUMENT BELOW WHICH PI*COTAN(PI*X) */ -/* MAY BE REPRESENTED BY 1/X. */ - xsmall = 1e-9; -/* --------------------------------------------------------------------- */ - aug = 0.0; - if (x < 0.5) { -/* --------------------------------------------------------------------- */ -/* X < 0.5, USE REFLECTION FORMULA */ -/* PSI(1-X) = PSI(X) + PI * COTAN(PI*X) */ -/* --------------------------------------------------------------------- */ - if (fabs(x) <= xsmall) { - - if (x == 0.0) { - goto L_err; - } -/* --------------------------------------------------------------------- */ -/* 0 < ABS(X) <= XSMALL. USE 1/X AS A SUBSTITUTE */ -/* FOR PI*COTAN(PI*X) */ -/* --------------------------------------------------------------------- */ - aug = -1.0 / x; - } else { /* |x| > xsmall */ -/* --------------------------------------------------------------------- */ -/* REDUCTION OF ARGUMENT FOR COTAN */ -/* --------------------------------------------------------------------- */ - /* L100: */ - w = -x; - sgn = piov4; - if (w <= 0.0) { - w = -w; - sgn = -sgn; - } -/* --------------------------------------------------------------------- */ -/* MAKE AN ERROR EXIT IF |X| >= XMAX1 */ -/* --------------------------------------------------------------------- */ - if (w >= xmax1) { - goto L_err; - } - nq = (int) w; - w -= (double) nq; - nq = (int) (w * 4.0); - w = (w - (double) nq * 0.25) * 4.0; -/* --------------------------------------------------------------------- */ -/* W IS NOW RELATED TO THE FRACTIONAL PART OF 4.0 * X. */ -/* ADJUST ARGUMENT TO CORRESPOND TO VALUES IN FIRST */ -/* QUADRANT AND DETERMINE SIGN */ -/* --------------------------------------------------------------------- */ - n = nq / 2; - if (n + n != nq) { - w = 1.0 - w; - } - z = piov4 * w; - m = n / 2; - if (m + m != n) { - sgn = -sgn; - } -/* --------------------------------------------------------------------- */ -/* DETERMINE FINAL VALUE FOR -PI*COTAN(PI*X) */ -/* --------------------------------------------------------------------- */ - n = (nq + 1) / 2; - m = n / 2; - m += m; - if (m == n) { -/* --------------------------------------------------------------------- */ -/* CHECK FOR SINGULARITY */ -/* --------------------------------------------------------------------- */ - if (z == 0.0) { - goto L_err; - } -/* --------------------------------------------------------------------- */ -/* USE COS/SIN AS A SUBSTITUTE FOR COTAN, AND */ -/* SIN/COS AS A SUBSTITUTE FOR TAN */ -/* --------------------------------------------------------------------- */ - aug = sgn * (cos(z) / sin(z) * 4.0); - - } else { /* L140: */ - aug = sgn * (sin(z) / cos(z) * 4.0); - } - } - - x = 1.0 - x; - - } - /* L200: */ - if (x <= 3.0) { -/* --------------------------------------------------------------------- */ -/* 0.5 <= X <= 3.0 */ -/* --------------------------------------------------------------------- */ - den = x; - upper = p1[0] * x; - - for (i = 1; i <= 5; ++i) { - den = (den + q1[i - 1]) * x; - upper = (upper + p1[i]) * x; - } - - den = (upper + p1[6]) / (den + q1[5]); - xmx0 = x - dx0; - return den * xmx0 + aug; - } - -/* --------------------------------------------------------------------- */ -/* IF X >= XMAX1, PSI = LN(X) */ -/* --------------------------------------------------------------------- */ - if (x < xmax1) { -/* --------------------------------------------------------------------- */ -/* 3.0 < X < XMAX1 */ -/* --------------------------------------------------------------------- */ - w = 1.0 / (x * x); - den = w; - upper = p2[0] * w; - - for (i = 1; i <= 3; ++i) { - den = (den + q2[i - 1]) * w; - upper = (upper + p2[i]) * w; - } - - aug = upper / (den + q2[3]) - 0.5 / x + aug; - } - return aug + log(x); - -/* --------------------------------------------------------------------- */ -/* ERROR RETURN */ -/* --------------------------------------------------------------------- */ -L_err: - return 0.; -} /* psi */ - -static double betaln(double a0, double b0) -{ -/* ----------------------------------------------------------------------- - * Evaluation of the logarithm of the beta function ln(beta(a0,b0)) - * ----------------------------------------------------------------------- */ - - static double e = .918938533204673;/* e == 0.5*LN(2*PI) */ - - double a, b, c, h, u, v, w, z; - int i, n; - - a = min(a0 ,b0); - b = max(a0, b0); - if (a >= 8.0) { - goto L60; - } - if (a < 1.0) { -/* ----------------------------------------------------------------------- */ -/* PROCEDURE WHEN A < 1 */ -/* ----------------------------------------------------------------------- */ - if (b < 8.0) - return gamln(a) + (gamln(b) - gamln(a+b)); - else - return gamln(a) + algdiv(a, b); - } - /* else */ -/* ----------------------------------------------------------------------- */ -/* PROCEDURE WHEN 1 <= A < 8 */ -/* ----------------------------------------------------------------------- */ - if (a > 2.0) { - goto L30; - } - if (b <= 2.0) { - return gamln(a) + gamln(b) - gsumln(a, b); - } - /* else */ - - w = 0.0; - if (b < 8.0) { - goto L40; - } - return gamln(a) + algdiv(a, b); - -L30: -/* REDUCTION OF A WHEN B <= 1000 */ - - if (b > 1e3) { - goto L50; - } - n = a - 1.0; - w = 1.0; - for (i = 1; i <= n; ++i) { - a += -1.0; - h = a / b; - w *= h / (h + 1.0); - } - w = log(w); - if (b < 8.0) { - goto L40; - } - return w + gamln(a) + algdiv(a, b); - -L40: -/* REDUCTION OF B WHEN B < 8 */ - - n = b - 1.0; - z = 1.0; - for (i = 1; i <= n; ++i) { - b += -1.0; - z *= b / (a + b); - } - return w + log(z) + (gamln(a) + (gamln(b) - gsumln(a, b))); - -L50: -/* REDUCTION OF A WHEN B > 1000 */ - n = a - 1.0; - w = 1.0; - for (i = 1; i <= n; ++i) { - a += -1.0; - w *= a / (a / b + 1.0); - } - return log(w) - n * log(b) + (gamln(a) + algdiv(a, b)); - -L60: -/* ----------------------------------------------------------------------- */ -/* PROCEDURE WHEN A >= 8 */ -/* ----------------------------------------------------------------------- */ - - w = bcorr(a, b); - h = a / b; - c = h / (h + 1.0); - u = -(a - 0.5) * log(c); - v = b * alnrel(h); - if (u > v) - return log(b) * -0.5 + e + w - v - u; - else - return log(b) * -0.5 + e + w - u - v; - -} /* betaln */ - -static double gsumln(double a, double b) -{ -/* ----------------------------------------------------------------------- */ -/* EVALUATION OF THE FUNCTION LN(GAMMA(A + B)) */ -/* FOR 1 <= A <= 2 AND 1 <= B <= 2 */ -/* ----------------------------------------------------------------------- */ - - double x = a + b - 2.;/* in [0, 2] */ - - if (x <= 0.25) - return gamln1(x + 1.0); - - /* else */ - if (x <= 1.25) - return gamln1(x) + alnrel(x); - /* else x > 1.25 : */ - return gamln1(x - 1.0) + log(x * (x + 1.0)); - -} /* gsumln */ - -static double bcorr(double a0, double b0) -{ -/* ----------------------------------------------------------------------- */ - -/* EVALUATION OF DEL(A0) + DEL(B0) - DEL(A0 + B0) WHERE */ -/* LN(GAMMA(A)) = (A - 0.5)*LN(A) - A + 0.5*LN(2*PI) + DEL(A). */ -/* IT IS ASSUMED THAT A0 >= 8 AND B0 >= 8. */ - -/* ----------------------------------------------------------------------- */ - /* Initialized data */ - - static double c0 = .0833333333333333; - static double c1 = -.00277777777760991; - static double c2 = 7.9365066682539e-4; - static double c3 = -5.9520293135187e-4; - static double c4 = 8.37308034031215e-4; - static double c5 = -.00165322962780713; - - /* System generated locals */ - double ret_val, r1; - - /* Local variables */ - double a, b, c, h, t, w, x, s3, s5, x2, s7, s9, s11; -/* ------------------------ */ - a = min(a0, b0); - b = max(a0, b0); - - h = a / b; - c = h / (h + 1.0); - x = 1.0 / (h + 1.0); - x2 = x * x; - -/* SET SN = (1 - X^N)/(1 - X) */ - - s3 = x + x2 + 1.0; - s5 = x + x2 * s3 + 1.0; - s7 = x + x2 * s5 + 1.0; - s9 = x + x2 * s7 + 1.0; - s11 = x + x2 * s9 + 1.0; - -/* SET W = DEL(B) - DEL(A + B) */ - -/* Computing 2nd power */ - r1 = 1.0 / b; - t = r1 * r1; - w = ((((c5 * s11 * t + c4 * s9) * t + c3 * s7) * t + c2 * s5) * t + c1 * - s3) * t + c0; - w *= c / b; - -/* COMPUTE DEL(A) + W */ - -/* Computing 2nd power */ - r1 = 1.0 / a; - t = r1 * r1; - ret_val = (((((c5 * t + c4) * t + c3) * t + c2) * t + c1) * t + c0) / a + - w; - return ret_val; -} /* bcorr */ - -static double algdiv(double a, double b) -{ -/* ----------------------------------------------------------------------- */ - -/* COMPUTATION OF LN(GAMMA(B)/GAMMA(A+B)) WHEN B >= 8 */ - -/* -------- */ - -/* IN THIS ALGORITHM, DEL(X) IS THE FUNCTION DEFINED BY */ -/* LN(GAMMA(X)) = (X - 0.5)*LN(X) - X + 0.5*LN(2*PI) + DEL(X). */ - -/* ----------------------------------------------------------------------- */ - - /* Initialized data */ - - static double c0 = .0833333333333333; - static double c1 = -.00277777777760991; - static double c2 = 7.9365066682539e-4; - static double c3 = -5.9520293135187e-4; - static double c4 = 8.37308034031215e-4; - static double c5 = -.00165322962780713; - - double c, d, h, t, u, v, w, x, s3, s5, x2, s7, s9, s11; - -/* ------------------------ */ - if (a > b) { - h = b / a; - c = 1.0 / (h + 1.0); - x = h / (h + 1.0); - d = a + (b - 0.5); - } - else { - h = a / b; - c = h / (h + 1.0); - x = 1.0 / (h + 1.0); - d = b + (a - 0.5); - } - -/* Set s = (1 - x^n)/(1 - x) : */ - - x2 = x * x; - s3 = x + x2 + 1.0; - s5 = x + x2 * s3 + 1.0; - s7 = x + x2 * s5 + 1.0; - s9 = x + x2 * s7 + 1.0; - s11 = x + x2 * s9 + 1.0; - -/* w := Del(b) - Del(a + b) */ - - t = 1./ (b * b); - w = ((((c5 * s11 * t + c4 * s9) * t + c3 * s7) * t + c2 * s5) * t + c1 * - s3) * t + c0; - w *= c / b; - -/* COMBINE THE RESULTS */ - - u = d * alnrel(a / b); - v = a * (log(b) - 1.0); - if (u > v) - return w - v - u; - else - return w - u - v; -} /* algdiv */ - -static double gamln(double a) -{ -/* ----------------------------------------------------------------------- - * Evaluation of ln(gamma(a)) for positive a - * ----------------------------------------------------------------------- */ -/* Written by Alfred H. Morris */ -/* Naval Surface Warfare Center */ -/* Dahlgren, Virginia */ -/* ----------------------------------------------------------------------- */ - - static double d = .418938533204673;/* d == 0.5*(LN(2*PI) - 1) */ - - static double c0 = .0833333333333333; - static double c1 = -.00277777777760991; - static double c2 = 7.9365066682539e-4; - static double c3 = -5.9520293135187e-4; - static double c4 = 8.37308034031215e-4; - static double c5 = -.00165322962780713; - - if (a <= 0.8) - return gamln1(a) - log(a); /* ln(G(a+1)) - ln(a) == ln(G(a+1)/a) = ln(G(a)) */ - else if (a <= 2.25) - return gamln1(a - 0.5 - 0.5); - - else if (a < 10.0) { - int i, n = a - 1.25; - double t = a; - double w = 1.0; - for (i = 1; i <= n; ++i) { - t += -1.0; - w *= t; - } - return gamln1(t - 1.) + log(w); - } - else { /* a >= 10 */ - double t = 1. / (a * a); - double w = (((((c5 * t + c4) * t + c3) * t + c2) * t + c1) * t + c0) / a; - return d + w + (a - 0.5) * (log(a) - 1.0); - } -} /* gamln */ diff --git a/deps/Rmath/src/wilcox.c b/deps/Rmath/src/wilcox.c deleted file mode 100644 index 0784b59eef1e2..0000000000000 --- a/deps/Rmath/src/wilcox.c +++ /dev/null @@ -1,326 +0,0 @@ -/* - Mathlib : A C Library of Special Functions - Copyright (C) 1999-2007 The R Development Core Team - - This program is free software; you can redistribute it and/or modify - it under the terms of the 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. - - You should have received a copy of the GNU General Public License - along with this program; if not, a copy is available at - http://www.r-project.org/Licenses/ - - SYNOPSIS - - #include - double dwilcox(double x, double m, double n, int give_log) - double pwilcox(double x, double m, double n, int lower_tail, int log_p) - double qwilcox(double x, double m, double n, int lower_tail, int log_p); - double rwilcox(double m, double n) - - DESCRIPTION - - dwilcox The density of the Wilcoxon distribution. - pwilcox The distribution function of the Wilcoxon distribution. - qwilcox The quantile function of the Wilcoxon distribution. - rwilcox Random variates from the Wilcoxon distribution. - - */ - -/* - Note: the checks here for R_CheckInterrupt also do stack checking. - - calloc/free are remapped for use in R, so allocation checks are done there. - freeing is completed by an on.exit action in the R wrappers. -*/ - -#include "nmath.h" -#include "dpq.h" - -#ifndef MATHLIB_STANDALONE -#include -#endif - -static double ***w; /* to store cwilcox(i,j,k) -> w[i][j][k] */ -static int allocated_m, allocated_n; - -static void -w_free(int m, int n) -{ - int i, j; - - for (i = m; i >= 0; i--) { - for (j = n; j >= 0; j--) { - if (w[i][j] != 0) - free((void *) w[i][j]); - } - free((void *) w[i]); - } - free((void *) w); - w = 0; allocated_m = allocated_n = 0; -} - -static void -w_init_maybe(int m, int n) -{ - int i; - - if (m > n) { - i = n; n = m; m = i; - } - if (w && (m > allocated_m || n > allocated_n)) - w_free(allocated_m, allocated_n); /* zeroes w */ - - if (!w) { /* initialize w[][] */ - m = imax2(m, WILCOX_MAX); - n = imax2(n, WILCOX_MAX); - w = (double ***) calloc((size_t) m + 1, sizeof(double **)); -#ifdef MATHLIB_STANDALONE - if (!w) MATHLIB_ERROR(_("wilcox allocation error %d"), 1); -#endif - for (i = 0; i <= m; i++) { - w[i] = (double **) calloc((size_t) n + 1, sizeof(double *)); -#ifdef MATHLIB_STANDALONE - /* the apparent leak here in the in-R case should be - swept up by the on.exit action */ - if (!w[i]) { - /* first free all earlier allocations */ - w_free(i-1, n); - MATHLIB_ERROR(_("wilcox allocation error %d"), 2); - } -#endif - } - allocated_m = m; allocated_n = n; - } -} - -static void -w_free_maybe(int m, int n) -{ - if (m > WILCOX_MAX || n > WILCOX_MAX) - w_free(m, n); -} - - -/* This counts the number of choices with statistic = k */ -static double -cwilcox(int k, int m, int n) -{ - int c, u, i, j, l; - -#ifndef MATHLIB_STANDALONE - R_CheckUserInterrupt(); -#endif - - u = m * n; - if (k < 0 || k > u) - return(0); - c = (int)(u / 2); - if (k > c) - k = u - k; /* hence k <= floor(u / 2) */ - if (m < n) { - i = m; j = n; - } else { - i = n; j = m; - } /* hence i <= j */ - - if (j == 0) /* and hence i == 0 */ - return (k == 0); - - - /* We can simplify things if k is small. Consider the Mann-Whitney - definition, and sort y. Then if the statistic is k, no more - than k of the y's can be <= any x[i], and since they are sorted - these can only be in the first k. So the count is the same as - if there were just k y's. - */ - if (j > 0 && k < j) return cwilcox(k, i, k); - - if (w[i][j] == 0) { - w[i][j] = (double *) calloc((size_t) c + 1, sizeof(double)); -#ifdef MATHLIB_STANDALONE - if (!w[i][j]) MATHLIB_ERROR(_("wilcox allocation error %d"), 3); -#endif - for (l = 0; l <= c; l++) - w[i][j][l] = -1; - } - if (w[i][j][k] < 0) { - if (j == 0) /* and hence i == 0 */ - w[i][j][k] = (k == 0); - else - w[i][j][k] = cwilcox(k - j, i - 1, j) + cwilcox(k, i, j - 1); - - } - return(w[i][j][k]); -} - -double dwilcox(double x, double m, double n, int give_log) -{ - double d; - -#ifdef IEEE_754 - /* NaNs propagated correctly */ - if (ISNAN(x) || ISNAN(m) || ISNAN(n)) - return(x + m + n); -#endif - m = floor(m + 0.5); - n = floor(n + 0.5); - if (m <= 0 || n <= 0) - ML_ERR_return_NAN; - - if (fabs(x - floor(x + 0.5)) > 1e-7) - return(R_D__0); - x = floor(x + 0.5); - if ((x < 0) || (x > m * n)) - return(R_D__0); - - w_init_maybe(m, n); - d = give_log ? - log(cwilcox(x, m, n)) - lchoose(m + n, n) : - cwilcox(x, m, n) / choose(m + n, n); - - return(d); -} - -/* args have the same meaning as R function pwilcox */ -double pwilcox(double q, double m, double n, int lower_tail, int log_p) -{ - int i; - double c, p; - -#ifdef IEEE_754 - if (ISNAN(q) || ISNAN(m) || ISNAN(n)) - return(q + m + n); -#endif - if (!R_FINITE(m) || !R_FINITE(n)) - ML_ERR_return_NAN; - m = floor(m + 0.5); - n = floor(n + 0.5); - if (m <= 0 || n <= 0) - ML_ERR_return_NAN; - - q = floor(q + 1e-7); - - if (q < 0.0) - return(R_DT_0); - if (q >= m * n) - return(R_DT_1); - - w_init_maybe(m, n); - c = choose(m + n, n); - p = 0; - /* Use summation of probs over the shorter range */ - if (q <= (m * n / 2)) { - for (i = 0; i <= q; i++) - p += cwilcox(i, m, n) / c; - } - else { - q = m * n - q; - for (i = 0; i < q; i++) - p += cwilcox(i, m, n) / c; - lower_tail = !lower_tail; /* p = 1 - p; */ - } - - return(R_DT_val(p)); -} /* pwilcox */ - -/* x is 'p' in R function qwilcox */ - -double qwilcox(double x, double m, double n, int lower_tail, int log_p) -{ - double c, p, q; - -#ifdef IEEE_754 - if (ISNAN(x) || ISNAN(m) || ISNAN(n)) - return(x + m + n); -#endif - if(!R_FINITE(x) || !R_FINITE(m) || !R_FINITE(n)) - ML_ERR_return_NAN; - R_Q_P01_check(x); - - m = floor(m + 0.5); - n = floor(n + 0.5); - if (m <= 0 || n <= 0) - ML_ERR_return_NAN; - - if (x == R_DT_0) - return(0); - if (x == R_DT_1) - return(m * n); - - if(log_p || !lower_tail) - x = R_DT_qIv(x); /* lower_tail,non-log "p" */ - - w_init_maybe(m, n); - c = choose(m + n, n); - p = 0; - q = 0; - if (x <= 0.5) { - x = x - 10 * DBL_EPSILON; - for (;;) { - p += cwilcox(q, m, n) / c; - if (p >= x) - break; - q++; - } - } - else { - x = 1 - x + 10 * DBL_EPSILON; - for (;;) { - p += cwilcox(q, m, n) / c; - if (p > x) { - q = m * n - q; - break; - } - q++; - } - } - - return(q); -} - -double rwilcox(double m, double n) -{ - int i, j, k, *x; - double r; - -#ifdef IEEE_754 - /* NaNs propagated correctly */ - if (ISNAN(m) || ISNAN(n)) - return(m + n); -#endif - m = floor(m + 0.5); - n = floor(n + 0.5); - if ((m < 0) || (n < 0)) - ML_ERR_return_NAN; - - if ((m == 0) || (n == 0)) - return(0); - - r = 0.0; - k = (int) (m + n); - x = (int *) calloc((size_t) k, sizeof(int)); -#ifdef MATHLIB_STANDALONE - if (!x) MATHLIB_ERROR(_("wilcox allocation error %d"), 4); -#endif - for (i = 0; i < k; i++) - x[i] = i; - for (i = 0; i < n; i++) { - j = floor(k * unif_rand()); - r += x[j]; - x[j] = x[--k]; - } - free(x); - return(r - n * (n - 1) / 2); -} - -void wilcox_free(void) -{ - w_free_maybe(allocated_m, allocated_n); -} diff --git a/deps/SuiteSparse_wrapper.c b/deps/SuiteSparse_wrapper.c index e7d8e8bec3c91..ec7e6f2560eb0 100644 --- a/deps/SuiteSparse_wrapper.c +++ b/deps/SuiteSparse_wrapper.c @@ -1,127 +1,28 @@ #include #include -extern void -jl_cholmod_common(void **cm) -{ - cholmod_common *c = (cholmod_common *) malloc (sizeof(cholmod_common)); - *cm = c; +extern size_t jl_cholmod_common_size(size_t x) { + return sizeof(cholmod_common); } -extern void -jl_cholmod_dense( void **cd, /* Store return value in here */ - size_t nrow, /* the matrix is nrow-by-ncol */ - size_t ncol, - size_t nzmax, /* maximum number of entries in the matrix */ - size_t d, /* leading dimension (d >= nrow must hold) */ - void *x, /* size nzmax or 2*nzmax, if present */ - void *z, /* size nzmax, if present */ - int xtype, /* pattern, real, complex, or zomplex */ - int dtype /* x and z double or float */ - ) -{ - cholmod_dense *mat = (cholmod_dense *) malloc (sizeof(cholmod_dense)); - mat->nrow = nrow; - mat->ncol = ncol; - mat->nzmax = nzmax; - mat->d = d; - mat->x = x; - mat->z = z; - mat->xtype = xtype; - mat->dtype = dtype; - - *cd = mat; -} - -extern void -jl_cholmod_dense_copy_out(cholmod_dense *cd, - void *p - ) -{ - size_t elsize = (cd->xtype == CHOLMOD_COMPLEX ? 2 : 1) * - (cd->dtype == CHOLMOD_DOUBLE ? sizeof(double) : sizeof(float)); - - memcpy(p, cd->x, cd->nzmax*elsize); -} - -extern void -jl_cholmod_sparse( void **cs, /* Store return value in here */ - size_t nrow, /* # of rows of A */ - size_t ncol, /* # of columns of A */ - size_t nzmax, /* max # of nonzeros of A */ - void *p, /* p [0..ncol], the column pointers */ - void *i, /* i [0..nzmax-1], the row indices */ - void *nz, /* nz [0..ncol-1], the # of nonzeros in each col if unpacked */ - void *x, /* size nzmax or 2*nzmax, if present */ - void *z, /* size nzmax, if present */ - int stype, /* 0: matrix is unsymmetric and possibly rectangular - >0: matrix is square and upper triangular - <0: matrix is square and lower triangular - */ - int itype, /* CHOLMOD_INT: p, i, and nz are int. - * CHOLMOD_INTLONG: p is UF_long, i and nz are int. - * CHOLMOD_LONG: p, i, and nz are UF_long. */ - int xtype, /* pattern, real, complex, or zomplex */ - int dtype, /* x and z are double or float */ - int sorted, /* TRUE if columns are sorted, FALSE otherwise */ - int packed /* TRUE if packed (nz ignored), FALSE if unpacked - * (nz is required) */ -) -{ - cholmod_sparse *s = (cholmod_sparse *) malloc (sizeof(cholmod_sparse)); - s->nrow = nrow; - s->ncol = ncol; - s->nzmax = nzmax; - s->p = p; - s->i = i; - s->nz = nz; - s->x = x; - s->z = z; - s->stype = stype; - s->itype = itype; - s->xtype = xtype; - s->dtype = dtype; - s->sorted = sorted; - s->packed = packed; - - *cs = s; - return; -} - -extern int -jl_cholmod_sparse_copy_out(cholmod_sparse *cs, - void *cp, /* column pointers */ - void *ri, /* row indices */ - void *nzp, - cholmod_common *cm) /* non-zero values */ -{ - /* error return if cs is not packed */ - if (!cs->packed) return 1; /* FIXME: If non-packed becomes a problem, write code to do packing */ - if (!cs->sorted) /* sort it */ - if (!cholmod_sort(cs, cm)) return 2; - - size_t isize; - switch(cs->itype) { - case CHOLMOD_INT: - case CHOLMOD_INTLONG: - isize = sizeof(int); break; - case CHOLMOD_LONG: - isize = sizeof(SuiteSparse_long); break; - default: - return 3; - } - size_t elsize = (cs->xtype == CHOLMOD_COMPLEX ? 2 : 1) * - (cs->dtype == CHOLMOD_DOUBLE ? sizeof(double) : sizeof(float)); - - if (cs->itype == CHOLMOD_INTLONG) { - int i, *dpt = (int *) cp; - SuiteSparse_long *spt = (SuiteSparse_long *) cs->p; - for (i = 0; i <= cs->ncol; ++i) dpt[i] = spt[i]; - } else { - memcpy(cp, cs->p, (cs->ncol + 1) * isize); - } - - memcpy(ri, cs->i, cs->nzmax * isize); - memcpy(nzp, cs->x, cs->nzmax * elsize); - return 0; +extern void jl_cholmod_common_offsets(size_t *vv) { + vv[0] = offsetof(cholmod_common, dbound); + vv[1] = offsetof(cholmod_common, maxrank); + vv[2] = offsetof(cholmod_common, supernodal_switch); + vv[3] = offsetof(cholmod_common, supernodal); + vv[4] = offsetof(cholmod_common, final_asis); + vv[5] = offsetof(cholmod_common, final_super); + vv[6] = offsetof(cholmod_common, final_ll); + vv[7] = offsetof(cholmod_common, final_pack); + vv[8] = offsetof(cholmod_common, final_monotonic); + vv[9] = offsetof(cholmod_common, final_resymbol); + vv[10] = offsetof(cholmod_common, prefer_zomplex); + vv[11] = offsetof(cholmod_common, prefer_upper); + vv[12] = offsetof(cholmod_common, print); + vv[13] = offsetof(cholmod_common, precise); + vv[14] = offsetof(cholmod_common, nmethods); + vv[15] = offsetof(cholmod_common, selected); + vv[16] = offsetof(cholmod_common, postorder); + vv[17] = offsetof(cholmod_common, itype); + vv[18] = offsetof(cholmod_common, dtype); } diff --git a/deps/Versions.make b/deps/Versions.make index d95a54fb9f433..d2353c8b2d71d 100644 --- a/deps/Versions.make +++ b/deps/Versions.make @@ -1,17 +1,16 @@ -LLVM_VER = 3.1 +LLVM_VER = 3.2 +LLVM_LIB_SUFFIX = svn READLINE_VER = 6.2 PCRE_VER = 8.31 GRISU_VER = 1.1.1 DSFMT_VER = 2.2 -OPENBLAS_VER = v0.2.5 +OPENBLAS_VER = v0.2.6 LAPACK_VER = 3.4.2 -ARPACK_VER = 3.1.2 +ARPACK_VER = 3.1.3 FFTW_VER = 3.3.3 SUITESPARSE_VER = 4.0.2 -CLP_VER = 1.14.5 -UNWIND_VER = 1.0.1 -LIGHTTPD_VER = 1.4.29 -GMP_VER=5.0.5 -GLPK_VER = 4.47 +UNWIND_VER = 1.1 +GMP_VER=5.1.1 ZLIB_VER = 1.2.7 PATCHELF_VER = 0.6 +GIT_VER = 1.8.1.5 diff --git a/deps/cmake/CMakeLists.txt b/deps/cmake/CMakeLists.txt index c3433d62a8855..bfa27667eec75 100644 --- a/deps/cmake/CMakeLists.txt +++ b/deps/cmake/CMakeLists.txt @@ -1,3 +1,5 @@ cmake_minimum_required(VERSION 2.8) add_subdirectory(arpack) -add_subdirectory(fftw-3.3) \ No newline at end of file +add_subdirectory(fftw-3.3) +set(FFTW_SINGLE ON) +add_subdirectory(fftw-3.3 ${CMAKE_CURRENT_BINARY_DIR}/fftw-3.3f) \ No newline at end of file diff --git a/deps/cmake/arpack/CMakeLists.txt b/deps/cmake/arpack/CMakeLists.txt index 6c3bac108ffdd..fa074bd4ecf89 100644 --- a/deps/cmake/arpack/CMakeLists.txt +++ b/deps/cmake/arpack/CMakeLists.txt @@ -106,5 +106,5 @@ prefixlist(arpackutil_STAT_SRCS "${arpackutil_DIR}") ########### next target ############### add_library(arpack SHARED ${arpacksrc_STAT_SRCS} ${arpackutil_STAT_SRCS}) -target_link_libraries(arpack ${LAPACK_TARGET} ${BLAS_LIBRARIES}) +target_link_libraries(arpack ${LapackLIB} ${BLAS_LIBRARIES}) set_target_properties(arpack PROPERTIES VERSION 2.0.0 SOVERSION 2) diff --git a/deps/cmake/fftw-3.3/CMakeLists.txt b/deps/cmake/fftw-3.3/CMakeLists.txt index f24f337a908e4..fbb00b9a5e139 100644 --- a/deps/cmake/fftw-3.3/CMakeLists.txt +++ b/deps/cmake/fftw-3.3/CMakeLists.txt @@ -172,7 +172,7 @@ if(FFTW_QUAD) set(BENCHFFT_QUAD ON) endif() -set(PREC_PREFIX ${PRECISION}) +set(PREC_SUFFIX ${PRECISION}) if(NOT DEFINED PRECISION) set(PRECISION "d") endif() diff --git a/deps/cmake/fftw-3.3/libbench2/CMakeLists.txt b/deps/cmake/fftw-3.3/libbench2/CMakeLists.txt index 8962dba03f599..36a4ded63ccef 100644 --- a/deps/cmake/fftw-3.3/libbench2/CMakeLists.txt +++ b/deps/cmake/fftw-3.3/libbench2/CMakeLists.txt @@ -45,7 +45,7 @@ set(SRCDIR ${CMAKE_CURRENT_SOURCE_DIR}) string(REPLACE "${TOP_CMAKE_SRCDIR}" "" SRCDIR "${SRCDIR}") prefixlist(bench2_STAT_SRCS "${TOP_SRCDIR}/${SRCDIR}/") -add_library(bench2 STATIC ${bench2_STAT_SRCS}) +add_library(bench2${PREC_SUFFIX} STATIC ${bench2_STAT_SRCS}) ########### install files ############### diff --git a/deps/config.guess b/deps/config.guess new file mode 100755 index 0000000000000..f7dd69ecc9c4c --- /dev/null +++ b/deps/config.guess @@ -0,0 +1,1516 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011 Free Software Foundation, Inc. + +timestamp='2011-08-20' + +# 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 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. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner. Please send patches (context +# diff format) to and include a ChangeLog +# entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free +Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + LIBC=gnu + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-gnu + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + i386) + eval $set_cc_for_build + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + UNAME_PROCESSOR="x86_64" + fi + fi ;; + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/deps/fftw-config-nopthreads.patch b/deps/fftw-config-nopthreads.patch new file mode 100644 index 0000000000000..54b66dce0bc41 --- /dev/null +++ b/deps/fftw-config-nopthreads.patch @@ -0,0 +1,11 @@ +--- configure 2013-01-12 06:08:54 +0100 ++++ configure.new 2013-01-12 06:08:51 +0100 +@@ -19500,7 +19500,7 @@ + fi + fi + +-THREADLIBS="" ++THREADLIBS=" " + if test "$enable_threads" = "yes"; then + # POSIX threads, the default choice: + if test -z "$THREADLIBS"; then diff --git a/deps/glpk_wrapper.c b/deps/glpk_wrapper.c deleted file mode 100644 index 5c4c7634782d0..0000000000000 --- a/deps/glpk_wrapper.c +++ /dev/null @@ -1,120 +0,0 @@ -#include -#include -#include - -#define generate_accessors(str, field, type) \ - extern void _jl_glpkw__ ## str ## _set_ ## field(void * v, type val) \ - { \ - glp_ ## str * s = (glp_ ## str *) v; \ - s->field = val; \ - } \ - \ - extern type _jl_glpkw__ ## str ## _get_ ## field(void * v) \ - { \ - glp_ ## str * s = (glp_ ## str *) v; \ - return s->field; \ - } - -extern void* _jl_glpkw__smcp_init() -{ - glp_smcp * smcp = calloc(1, sizeof(glp_smcp)); - glp_init_smcp(smcp); - return (void*) smcp; -} - -extern void _jl_glpkw__smcp_delete(void* smcp) -{ - free((glp_smcp*) smcp); -} - -generate_accessors(smcp, msg_lev, int); -generate_accessors(smcp, meth, int); -generate_accessors(smcp, pricing, int); -generate_accessors(smcp, r_test, int); -generate_accessors(smcp, tol_bnd, double); -generate_accessors(smcp, tol_dj, double); -generate_accessors(smcp, tol_piv, double); -generate_accessors(smcp, obj_ll, double); -generate_accessors(smcp, obj_ul, double); -generate_accessors(smcp, it_lim, int); -generate_accessors(smcp, tm_lim, int); -generate_accessors(smcp, out_frq, int); -generate_accessors(smcp, out_dly, int); -generate_accessors(smcp, presolve, int); - - - -extern void* _jl_glpkw__iptcp_init() -{ - glp_iptcp * iptcp = calloc(1, sizeof(glp_iptcp)); - glp_init_iptcp(iptcp); - return (void*) iptcp; -} - -extern void _jl_glpkw__iptcp_delete(void* iptcp) -{ - free((glp_iptcp*) iptcp); -} - -generate_accessors(iptcp, msg_lev, int); -generate_accessors(iptcp, ord_alg, int); - - - -extern void* _jl_glpkw__iocp_init() -{ - glp_iocp * iocp = calloc(1, sizeof(glp_iocp)); - glp_init_iocp(iocp); - return (void*) iocp; -} - -extern void _jl_glpkw__iocp_delete(void* iocp) -{ - free((glp_iocp*) iocp); -} - -generate_accessors(iocp, msg_lev, int); -generate_accessors(iocp, br_tech, int); -generate_accessors(iocp, bt_tech, int); -generate_accessors(iocp, pp_tech, int); -generate_accessors(iocp, fp_heur, int); -generate_accessors(iocp, gmi_cuts, int); -generate_accessors(iocp, mir_cuts, int); -generate_accessors(iocp, cov_cuts, int); -generate_accessors(iocp, clq_cuts, int); -generate_accessors(iocp, tol_int, double); -generate_accessors(iocp, tol_obj, double); -generate_accessors(iocp, mip_gap, double); -generate_accessors(iocp, tm_lim, int); -generate_accessors(iocp, out_frq, int); -generate_accessors(iocp, out_dly, int); -generate_accessors(iocp, cb_func, void*); -generate_accessors(iocp, cb_info, void*); -generate_accessors(iocp, cb_size, int); -generate_accessors(iocp, presolve, int); -generate_accessors(iocp, binarize, int); - - - -extern void* _jl_glpkw__bfcp_init() -{ - glp_bfcp * bfcp = calloc(1, sizeof(glp_bfcp)); - return (void*) bfcp; -} - -extern void _jl_glpkw__bfcp_delete(void* bfcp) -{ - free((glp_bfcp*) bfcp); -} - -generate_accessors(bfcp, type, int); -generate_accessors(bfcp, lu_size, int); -generate_accessors(bfcp, piv_tol, double); -generate_accessors(bfcp, piv_lim, int); -generate_accessors(bfcp, suhl, int); -generate_accessors(bfcp, eps_tol, double); -generate_accessors(bfcp, max_gro, double); -generate_accessors(bfcp, nfs_max, int); -generate_accessors(bfcp, upd_tol, double); -generate_accessors(bfcp, nrs_max, int); -generate_accessors(bfcp, rs_size, int); diff --git a/deps/gmp_wrapper.c b/deps/gmp_wrapper.c deleted file mode 100644 index 9935e53e3f23c..0000000000000 --- a/deps/gmp_wrapper.c +++ /dev/null @@ -1,212 +0,0 @@ -#include -#include -#include - -void _jl_gmp_free(void *p) -{ - void (*freefunc) (void *, size_t); - mp_get_memory_functions (NULL, NULL, &freefunc); - freefunc(p, 0); -} - -extern void* _jl_mpz_init() -{ - mpz_t* integ = malloc(sizeof(mpz_t)); - mpz_init(*integ); - return integ; -} - -extern void _jl_mpz_clear(mpz_t* rop) { - mpz_clear(*rop); -} - -extern void _jl_mpz_set_string(mpz_t* rop, char* s) { - mpz_set_str(*rop, s, 0); -} - -extern void _jl_mpz_set_ui(mpz_t* rop, unsigned long int op) { - mpz_set_ui(*rop, op); -} - -extern unsigned long _jl_mpz_get_ui(mpz_t* rop) { - return mpz_get_ui(*rop); -} - -extern void _jl_mpz_set_si(mpz_t* rop, long int op) { - mpz_set_si(*rop, op); -} - -extern long _jl_mpz_get_si(mpz_t* rop) { - return mpz_get_si(*rop); -} - -extern void _jl_mpz_add(mpz_t* rop, mpz_t* op1, mpz_t* op2) { - mpz_add(*rop, *op1, *op2); -} - -extern void _jl_mpz_sub(mpz_t* rop, mpz_t* op1, mpz_t* op2) { - mpz_sub(*rop, *op1, *op2); -} - -extern void _jl_mpz_mul(mpz_t* rop, mpz_t* op1, mpz_t* op2) { - mpz_mul(*rop, *op1, *op2); -} - -extern void _jl_mpz_div(mpz_t* rop, mpz_t* op1, mpz_t* op2) { - mpz_fdiv_q(*rop, *op1, *op2); -} - -extern void _jl_mpz_divmod(mpz_t* rop1, mpz_t* rop2, mpz_t* op1, mpz_t* op2) { - mpz_divmod(*rop1, *rop2, *op1, *op2); -} - -extern void _jl_mpz_gcd(mpz_t* rop, mpz_t* op1, mpz_t* op2) { - mpz_gcd(*rop, *op1, *op2); -} - -extern void _jl_mpz_gcdext(mpz_t *g, mpz_t *s, mpz_t *t, mpz_t *a, mpz_t *b) { - mpz_gcdext(*g, *s, *t, *a, *b); -} - -extern void _jl_mpz_rem(mpz_t* rop, mpz_t* op1, mpz_t* op2) { - mpz_fdiv_r(*rop, *op1, *op2); -} - -extern void _jl_mpz_neg(mpz_t* rop, mpz_t* op1) { - mpz_neg(*rop, *op1); -} - -extern void _jl_mpz_abs(mpz_t* rop, mpz_t* op1) { - mpz_abs(*rop, *op1); -} - -extern int _jl_mpz_cmp(mpz_t* op1, mpz_t* op2) { - return mpz_cmp(*op1, *op2); -} - -extern void _jl_mpz_lshift(mpz_t* rop, mpz_t* base, unsigned long int count) { - mpz_mul_2exp(*rop, *base, count); -} - -extern void _jl_mpz_pow_ui(mpz_t* rop, mpz_t* base, unsigned long int exp) { - mpz_pow_ui(*rop, *base, exp); -} - -extern void _jl_mpz_sqrt(mpz_t* rop, mpz_t* op) { - mpz_sqrt(*rop, *op); -} - -extern void _jl_mpz_fac_ui(mpz_t* rop, unsigned long int op) { - mpz_fac_ui(*rop, op); -} - -extern void _jl_mpz_bin_ui(mpz_t* rop, mpz_t* n, unsigned long int k) { - mpz_bin_ui(*rop, *n, k); -} - -extern void _jl_mpz_bin_uiui(mpz_t* rop, unsigned long int n, unsigned long int k) { - mpz_bin_uiui(*rop, n, k); -} - -extern char* _jl_mpz_printf(mpz_t* rop) { - char* pp; - int s = gmp_asprintf(&pp, "%Zd", *rop); - return pp; -} - -//// MPF - -extern void* _jl_mpf_init() -{ - mpf_t* flt = malloc(sizeof(mpf_t)); - mpf_init(*flt); - return flt; -} - -extern void _jl_mpf_clear(mpf_t* rop) { - mpf_clear(*rop); -} - -extern void _jl_mpf_set_string(mpf_t* rop, char* s) { - mpf_set_str(*rop, s, 0); -} - -extern void _jl_mpf_set_ui(mpf_t* rop, unsigned long int op) { - mpf_set_ui(*rop, op); -} - -extern void _jl_mpf_set_si(mpf_t* rop, signed long int op) { - mpf_set_si(*rop, op); -} - -extern void _jl_mpf_set_d(mpf_t* rop, double op) { - mpf_set_d(*rop, op); -} - -extern void _jl_mpf_set_z(mpf_t* rop, mpz_t* op) { - mpf_set_z(*rop, *op); -} - -extern void _jl_mpf_add(mpf_t* rop, mpf_t* op1, mpf_t* op2) { - mpf_add(*rop, *op1, *op2); -} - -extern void _jl_mpf_sub(mpf_t* rop, mpf_t* op1, mpf_t* op2) { - mpf_sub(*rop, *op1, *op2); -} - -extern void _jl_mpf_mul(mpf_t* rop, mpf_t* op1, mpf_t* op2) { - mpf_mul(*rop, *op1, *op2); -} - -extern void _jl_mpf_div(mpf_t* rop, mpf_t* op1, mpf_t* op2) { - mpf_div(*rop, *op1, *op2); -} - -extern void _jl_mpf_neg(mpf_t* rop, mpf_t* op1) { - mpf_neg(*rop, *op1); -} - -extern void _jl_mpf_abs(mpf_t* rop, mpf_t* op1) { - mpf_abs(*rop, *op1); -} - -extern int _jl_mpf_cmp(mpf_t* op1, mpf_t* op2) { - return mpf_cmp(*op1, *op2); -} - -extern void _jl_mpf_pow_ui(mpf_t* rop, mpf_t* base, unsigned long int exp) { - mpf_pow_ui(*rop, *base, exp); -} - -extern void _jl_mpf_sqrt(mpf_t* rop, mpf_t* op) { - mpf_sqrt(*rop, *op); -} - -extern char* _jl_mpf_printf(mpf_t* rop) { - char* pp; - gmp_asprintf(&pp, "%.Ff", *rop); - return pp; -} - - -//Quick and dirty test of the gmp wrapper code -int main( int argc, const char* argv[] ) -{ - void* rop = _jl_mpf_init(); - void* op1 = _jl_mpf_init(); - - _jl_mpf_set_string(op1, "123456789123456789123456789123456789"); - - void* op2 = _jl_mpf_init(); - _jl_mpf_set_string(op2, "12345"); - - _jl_mpf_add(rop, op1, op2); - - printf("The sum is %s\n", _jl_mpf_printf(rop)); - - _jl_mpf_clear(rop); -} - - - diff --git a/deps/ifftw.h.patch b/deps/ifftw.h.patch new file mode 100644 index 0000000000000..bbed3855736d3 --- /dev/null +++ b/deps/ifftw.h.patch @@ -0,0 +1,11 @@ +--- ifftw.h.old 2013-02-05 08:50:34.347507303 -0500 ++++ ifftw.h 2013-02-05 08:50:44.011507796 -0500 +@@ -1026,7 +1026,7 @@ + + double X(measure_execution_time)(const planner *plnr, + plan *pln, const problem *p); +-int X(alignment_of)(R *p); ++IFFTW_EXTERN int X(alignment_of)(R *p); + unsigned X(hash)(const char *s); + INT X(nbuf)(INT n, INT vl, INT maxnbuf); + int X(nbuf_redundant)(INT n, INT vl, int which, diff --git a/deps/jldownload b/deps/jldownload index 07699739c887f..2461b9c913ec2 100755 --- a/deps/jldownload +++ b/deps/jldownload @@ -16,18 +16,18 @@ FETCH_OPTS= if [ $# -eq 1 ]; then CURL_OPTS="$CURL_OPTS -O" URL=$1 - URL_BASENAME=`basename $1` - MIRROR_URL="$MIRROR_HOST/$URL_BASENAME" elif [ $# -eq 2 ]; then WGET_OPTS="$WGET_OPTS -O $1" CURL_OPTS="$CURL_OPTS -o $1" FETCH_OPTS="$FETCH_OPTS -o $1" URL=$2 - MIRROR_URL="$MIRROR_HOST/$1" else exit 1 fi +URL_BASENAME=`basename $URL` +MIRROR_URL="$MIRROR_HOST/$URL_BASENAME" + if [ -x $CURL ]; then GETURL="$CURL $CURL_OPTS" elif [ -x $WGET ]; then diff --git a/deps/libuv b/deps/libuv index 0709538fecef5..d469f03eda6c9 160000 --- a/deps/libuv +++ b/deps/libuv @@ -1 +1 @@ -Subproject commit 0709538fecef54c67c84d446af7edddd3e4a1e99 +Subproject commit d469f03eda6c95f064be3c25b7a9e9a7547c7617 diff --git a/deps/lighttpd.conf b/deps/lighttpd.conf deleted file mode 100644 index b54d40b0e40e7..0000000000000 --- a/deps/lighttpd.conf +++ /dev/null @@ -1,32 +0,0 @@ -server.document-root = "../../ui/website" - -server.port = 2000 - -server.modules = ( - "mod_scgi", - "mod_access", - "mod_alias", - "mod_compress", - "mod_redirect", -) - -mimetype.assign = ( - ".html" => "text/html", - ".htm" => "text/html", - ".txt" => "text/plain", - ".jpg" => "image/jpeg", - ".png" => "image/png", - ".css" => "text/css", - ".js" => "application/javascript", -) - -static-file.exclude-extensions = ( ".fcgi", "~", ".inc" ) - -index-file.names = ( "index.html", "index.htm", "default.htm" ) - -scgi.server = ( - ".scgi" => - (( "host" => "127.0.0.1", - "port" => 2001 - )) -) diff --git a/deps/openlibm b/deps/openlibm index 4ebe327d2457b..c9cf16d2def0a 160000 --- a/deps/openlibm +++ b/deps/openlibm @@ -1 +1 @@ -Subproject commit 4ebe327d2457baa38bb7b457482589f8165bcdf1 +Subproject commit c9cf16d2def0adc51515151612d9b75ceeef162e diff --git a/deps/random/dSFMT.c.patch b/deps/random/dSFMT.c.patch new file mode 100644 index 0000000000000..055483135a789 --- /dev/null +++ b/deps/random/dSFMT.c.patch @@ -0,0 +1,100 @@ +--- dsfmt-2.2/dSFMT.c 2012-06-29 03:24:27.000000000 -0400 ++++ dSFMT-patched.c 2012-12-20 12:45:45.000000000 -0500 +@@ -32,13 +32,13 @@ + 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); ++ ptrdiff_t size); + inline static void gen_rand_array_c0o1(dsfmt_t *dsfmt, w128_t *array, +- int size); ++ ptrdiff_t size); + inline static void gen_rand_array_o0c1(dsfmt_t *dsfmt, w128_t *array, +- int size); ++ ptrdiff_t size); + inline static void gen_rand_array_o0o1(dsfmt_t *dsfmt, w128_t *array, +- int size); ++ ptrdiff_t size); + inline static int idxof(int i); + static void initial_mask(dsfmt_t *dsfmt); + static void period_certification(dsfmt_t *dsfmt); +@@ -142,8 +142,8 @@ + * @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; ++ ptrdiff_t size) { ++ ptrdiff_t i, j; + w128_t lung; + + lung = dsfmt->status[DSFMT_N]; +@@ -180,8 +180,8 @@ + * @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; ++ ptrdiff_t size) { ++ ptrdiff_t i, j; + w128_t lung; + + lung = dsfmt->status[DSFMT_N]; +@@ -223,8 +223,8 @@ + * @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; ++ ptrdiff_t size) { ++ ptrdiff_t i, j; + w128_t lung; + + lung = dsfmt->status[DSFMT_N]; +@@ -266,8 +266,8 @@ + * @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; ++ ptrdiff_t size) { ++ ptrdiff_t i, j; + w128_t lung; + + lung = dsfmt->status[DSFMT_N]; +@@ -453,7 +453,7 @@ + * 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) { ++void dsfmt_fill_array_close1_open2(dsfmt_t *dsfmt, double array[], ptrdiff_t size) { + assert(size % 2 == 0); + assert(size >= DSFMT_N64); + gen_rand_array_c1o2(dsfmt, (w128_t *)array, size / 2); +@@ -471,7 +471,7 @@ + * @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) { ++void dsfmt_fill_array_open_close(dsfmt_t *dsfmt, double array[], ptrdiff_t size) { + assert(size % 2 == 0); + assert(size >= DSFMT_N64); + gen_rand_array_o0c1(dsfmt, (w128_t *)array, size / 2); +@@ -489,7 +489,7 @@ + * @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) { ++void dsfmt_fill_array_close_open(dsfmt_t *dsfmt, double array[], ptrdiff_t size) { + assert(size % 2 == 0); + assert(size >= DSFMT_N64); + gen_rand_array_c0o1(dsfmt, (w128_t *)array, size / 2); +@@ -507,7 +507,7 @@ + * @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) { ++void dsfmt_fill_array_open_open(dsfmt_t *dsfmt, double array[], ptrdiff_t size) { + assert(size % 2 == 0); + assert(size >= DSFMT_N64); + gen_rand_array_o0o1(dsfmt, (w128_t *)array, size / 2); diff --git a/deps/random/dSFMT.h.patch b/deps/random/dSFMT.h.patch index 7a4bfd423113a..72d41d411d055 100644 --- a/deps/random/dSFMT.h.patch +++ b/deps/random/dSFMT.h.patch @@ -1,6 +1,28 @@ ---- dSFMT.h 2012-06-29 12:54:27.000000000 +0530 -+++ dSFMT-julia.h 2012-09-22 23:02:26.000000000 +0530 -@@ -188,6 +188,7 @@ +--- dsfmt-2.2/dSFMT.h 2012-06-29 03:24:27.000000000 -0400 ++++ dSFMT-patched.h 2012-12-20 12:35:44.000000000 -0500 +@@ -40,6 +40,7 @@ + + #include + #include ++#include + + #if !defined(DSFMT_MEXP) + #ifdef __GNUC__ +@@ -178,16 +179,17 @@ + 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_fill_array_open_close(dsfmt_t *dsfmt, double array[], ptrdiff_t size); ++void dsfmt_fill_array_close_open(dsfmt_t *dsfmt, double array[], ptrdiff_t size); ++void dsfmt_fill_array_open_open(dsfmt_t *dsfmt, double array[], ptrdiff_t size); ++void dsfmt_fill_array_close1_open2(dsfmt_t *dsfmt, double array[], ptrdiff_t 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); @@ -8,7 +30,7 @@ #if defined(__GNUC__) # define DSFMT_PRE_INLINE inline static # define DSFMT_PST_INLINE __attribute__((always_inline)) -@@ -198,6 +199,10 @@ +@@ -198,6 +200,10 @@ # define DSFMT_PRE_INLINE inline static # define DSFMT_PST_INLINE #endif @@ -19,7 +41,25 @@ 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; -@@ -236,7 +241,7 @@ +@@ -212,13 +218,13 @@ + 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_PRE_INLINE void dsfmt_gv_fill_array_open_close(double array[], ptrdiff_t size) + DSFMT_PST_INLINE; +-DSFMT_PRE_INLINE void dsfmt_gv_fill_array_close_open(double array[], int size) ++DSFMT_PRE_INLINE void dsfmt_gv_fill_array_close_open(double array[], ptrdiff_t size) + DSFMT_PST_INLINE; +-DSFMT_PRE_INLINE void dsfmt_gv_fill_array_open_open(double array[], int size) ++DSFMT_PRE_INLINE void dsfmt_gv_fill_array_open_open(double array[], ptrdiff_t size) + DSFMT_PST_INLINE; +-DSFMT_PRE_INLINE void dsfmt_gv_fill_array_close1_open2(double array[], int size) ++DSFMT_PRE_INLINE void dsfmt_gv_fill_array_close1_open2(double array[], ptrdiff_t 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[], +@@ -236,7 +242,7 @@ * @param dsfmt dsfmt internal state date * @return double precision floating point pseudorandom number */ @@ -28,7 +68,7 @@ uint32_t r; uint64_t *psfmt64 = &dsfmt->status[0].u[0]; -@@ -257,7 +262,7 @@ +@@ -257,7 +263,7 @@ * @param dsfmt dsfmt internal state date * @return double precision floating point pseudorandom number */ @@ -37,7 +77,7 @@ double r; double *psfmt64 = &dsfmt->status[0].d[0]; -@@ -276,7 +281,7 @@ +@@ -276,7 +282,7 @@ * before this function. This function uses \b global variables. * @return double precision floating point pseudorandom number */ @@ -46,7 +86,7 @@ return dsfmt_genrand_uint32(&dsfmt_global_data); } -@@ -287,7 +292,7 @@ +@@ -287,7 +293,7 @@ * before this function. This function uses \b global variables. * @return double precision floating point pseudorandom number */ @@ -55,7 +95,7 @@ return dsfmt_genrand_close1_open2(&dsfmt_global_data); } -@@ -299,7 +304,7 @@ +@@ -299,7 +305,7 @@ * @param dsfmt dsfmt internal state date * @return double precision floating point pseudorandom number */ @@ -64,7 +104,7 @@ return dsfmt_genrand_close1_open2(dsfmt) - 1.0; } -@@ -310,7 +315,7 @@ +@@ -310,7 +316,7 @@ * before this function. This function uses \b global variables. * @return double precision floating point pseudorandom number */ @@ -73,7 +113,7 @@ return dsfmt_gv_genrand_close1_open2() - 1.0; } -@@ -322,7 +327,7 @@ +@@ -322,7 +328,7 @@ * @param dsfmt dsfmt internal state date * @return double precision floating point pseudorandom number */ @@ -82,7 +122,7 @@ return 2.0 - dsfmt_genrand_close1_open2(dsfmt); } -@@ -333,7 +338,7 @@ +@@ -333,7 +339,7 @@ * before this function. This function uses \b global variables. * @return double precision floating point pseudorandom number */ @@ -91,7 +131,7 @@ return 2.0 - dsfmt_gv_genrand_close1_open2(); } -@@ -345,7 +350,7 @@ +@@ -345,7 +351,7 @@ * @param dsfmt dsfmt internal state date * @return double precision floating point pseudorandom number */ @@ -100,7 +140,7 @@ double *dsfmt64 = &dsfmt->status[0].d[0]; union { double d; -@@ -368,7 +373,7 @@ +@@ -368,7 +374,7 @@ * before this function. This function uses \b global variables. * @return double precision floating point pseudorandom number */ @@ -109,43 +149,43 @@ return dsfmt_genrand_open_open(&dsfmt_global_data); } -@@ -383,7 +388,7 @@ +@@ -383,7 +389,7 @@ * @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) { -+void dsfmt_gv_fill_array_close1_open2(double array[], int size) { ++void dsfmt_gv_fill_array_close1_open2(double array[], ptrdiff_t size) { dsfmt_fill_array_close1_open2(&dsfmt_global_data, array, size); } -@@ -399,7 +404,7 @@ +@@ -399,7 +405,7 @@ * 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) { -+void dsfmt_gv_fill_array_open_close(double array[], int size) { ++void dsfmt_gv_fill_array_open_close(double array[], ptrdiff_t size) { dsfmt_fill_array_open_close(&dsfmt_global_data, array, size); } -@@ -415,7 +420,7 @@ +@@ -415,7 +421,7 @@ * 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) { -+void dsfmt_gv_fill_array_close_open(double array[], int size) { ++void dsfmt_gv_fill_array_close_open(double array[], ptrdiff_t size) { dsfmt_fill_array_close_open(&dsfmt_global_data, array, size); } -@@ -431,7 +436,7 @@ +@@ -431,7 +437,7 @@ * 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) { -+void dsfmt_gv_fill_array_open_open(double array[], int size) { ++void dsfmt_gv_fill_array_open_open(double array[], ptrdiff_t size) { dsfmt_fill_array_open_open(&dsfmt_global_data, array, size); } -@@ -441,7 +446,7 @@ +@@ -441,7 +447,7 @@ * @param dsfmt dsfmt state vector. * @param seed a 32-bit integer used as the seed. */ @@ -154,7 +194,7 @@ dsfmt_chk_init_gen_rand(dsfmt, seed, DSFMT_MEXP); } -@@ -451,7 +456,7 @@ +@@ -451,7 +457,7 @@ * @param seed a 32-bit integer used as the seed. * see also \sa dsfmt_init_gen_rand() */ @@ -163,7 +203,7 @@ dsfmt_init_gen_rand(&dsfmt_global_data, seed); } -@@ -462,7 +467,7 @@ +@@ -462,7 +468,7 @@ * @param init_key the array of 32-bit integers, used as a seed. * @param key_length the length of init_key. */ @@ -172,7 +212,7 @@ int key_length) { dsfmt_chk_init_by_array(dsfmt, init_key, key_length, DSFMT_MEXP); } -@@ -475,7 +480,7 @@ +@@ -475,7 +481,7 @@ * @param key_length the length of init_key. * see also \sa dsfmt_init_by_array() */ @@ -181,7 +221,25 @@ dsfmt_init_by_array(&dsfmt_global_data, init_key, key_length); } -@@ -503,7 +508,7 @@ +@@ -489,13 +495,13 @@ + 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_PRE_INLINE void fill_array_open_close(double array[], ptrdiff_t size) + DSFMT_PST_INLINE; +-DSFMT_PRE_INLINE void fill_array_close_open(double array[], int size) ++DSFMT_PRE_INLINE void fill_array_close_open(double array[], ptrdiff_t size) + DSFMT_PST_INLINE; +-DSFMT_PRE_INLINE void fill_array_open_open(double array[], int size) ++DSFMT_PRE_INLINE void fill_array_open_open(double array[], ptrdiff_t size) + DSFMT_PST_INLINE; +-DSFMT_PRE_INLINE void fill_array_close1_open2(double array[], int size) ++DSFMT_PRE_INLINE void fill_array_close1_open2(double array[], ptrdiff_t size) + DSFMT_PST_INLINE; + + /** +@@ -503,7 +509,7 @@ * @return id string. * see also \sa dsfmt_get_idstring() */ @@ -190,7 +248,7 @@ return dsfmt_get_idstring(); } -@@ -512,7 +517,7 @@ +@@ -512,7 +518,7 @@ * @return minimum size of array used for fill_array functions. * see also \sa dsfmt_get_min_array_size() */ @@ -199,7 +257,7 @@ return dsfmt_get_min_array_size(); } -@@ -521,7 +526,7 @@ +@@ -521,7 +527,7 @@ * @param seed a 32-bit integer used as the seed. * see also \sa dsfmt_gv_init_gen_rand(), \sa dsfmt_init_gen_rand(). */ @@ -208,7 +266,7 @@ dsfmt_gv_init_gen_rand(seed); } -@@ -531,7 +536,7 @@ +@@ -531,7 +537,7 @@ * @param key_length the length of init_key. * see also \sa dsfmt_gv_init_by_array(), \sa dsfmt_init_by_array(). */ @@ -217,7 +275,7 @@ dsfmt_gv_init_by_array(init_key, key_length); } -@@ -541,7 +546,7 @@ +@@ -541,7 +547,7 @@ * see also \sa dsfmt_genrand_close1_open2() \sa * dsfmt_gv_genrand_close1_open2() */ @@ -226,7 +284,7 @@ return dsfmt_gv_genrand_close1_open2(); } -@@ -551,7 +556,7 @@ +@@ -551,7 +557,7 @@ * see also \sa dsfmt_genrand_close_open() \sa * dsfmt_gv_genrand_close_open() */ @@ -235,7 +293,7 @@ return dsfmt_gv_genrand_close_open(); } -@@ -561,7 +566,7 @@ +@@ -561,7 +567,7 @@ * see also \sa dsfmt_genrand_open_close() \sa * dsfmt_gv_genrand_open_close() */ @@ -244,7 +302,7 @@ return dsfmt_gv_genrand_open_close(); } -@@ -571,7 +576,7 @@ +@@ -571,7 +577,7 @@ * see also \sa dsfmt_genrand_open_open() \sa * dsfmt_gv_genrand_open_open() */ @@ -253,39 +311,39 @@ return dsfmt_gv_genrand_open_open(); } -@@ -584,7 +589,7 @@ +@@ -584,7 +590,7 @@ * dsfmt_fill_array_close1_open2(), \sa * dsfmt_gv_fill_array_close1_open2() */ -inline static void fill_array_open_close(double array[], int size) { -+void fill_array_open_close(double array[], int size) { ++void fill_array_open_close(double array[], ptrdiff_t size) { dsfmt_gv_fill_array_open_close(array, size); } -@@ -597,7 +602,7 @@ +@@ -597,7 +603,7 @@ * dsfmt_fill_array_close1_open2(), \sa * dsfmt_gv_fill_array_close1_open2() */ -inline static void fill_array_close_open(double array[], int size) { -+void fill_array_close_open(double array[], int size) { ++void fill_array_close_open(double array[], ptrdiff_t size) { dsfmt_gv_fill_array_close_open(array, size); } -@@ -610,7 +615,7 @@ +@@ -610,7 +616,7 @@ * dsfmt_fill_array_close1_open2(), \sa * dsfmt_gv_fill_array_close1_open2() */ -inline static void fill_array_open_open(double array[], int size) { -+void fill_array_open_open(double array[], int size) { ++void fill_array_open_open(double array[], ptrdiff_t size) { dsfmt_gv_fill_array_open_open(array, size); } -@@ -622,7 +627,7 @@ +@@ -622,7 +628,7 @@ * 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) { -+void fill_array_close1_open2(double array[], int size) { ++void fill_array_close1_open2(double array[], ptrdiff_t size) { dsfmt_gv_fill_array_close1_open2(array, size); } #endif /* DSFMT_DO_NOT_USE_OLD_NAMES */ diff --git a/deps/random/randmtzig.c b/deps/random/randmtzig.c index 226531c689223..adef147fa7186 100644 --- a/deps/random/randmtzig.c +++ b/deps/random/randmtzig.c @@ -55,6 +55,7 @@ #include #include +#include #include #include @@ -66,7 +67,7 @@ #include "dsfmt-2.2/dSFMT.c" #endif -typedef long randmtzig_idx_type; +typedef ptrdiff_t randmtzig_idx_type; typedef signed char randmtzig_int8_t; typedef unsigned char randmtzig_uint8_t; typedef short randmtzig_int16_t; diff --git a/deps/readline-win.h b/deps/readline-win.h index a64ebbc242973..604c2ae979cbc 100644 --- a/deps/readline-win.h +++ b/deps/readline-win.h @@ -1,8 +1,11 @@ #ifndef READLINE_WIN_H #define READLINE_WIN_H +extern void *jl_uv_stderr; #include #define fprintf jl_printf +#undef stderr +#define stderr jl_uv_stderr #define fflush (void) #define putc jl_putc #define fwrite(ptr,size,count,stream) jl_write(stream,ptr,size*count) diff --git a/deps/tk_wrapper.c b/deps/tk_wrapper.c deleted file mode 100644 index 1f5f4513d429d..0000000000000 --- a/deps/tk_wrapper.c +++ /dev/null @@ -1,48 +0,0 @@ -#include -#include -#include -#include -#include "julia.h" - -int jl_tcl_callback(ClientData clientData, Tcl_Interp *interp, - int argc, char *argv[]) -{ - jl_function_t *f = (jl_function_t*)clientData; - jl_value_t **jlargs = alloca(argc * sizeof(void*)); - memset(jlargs, 0, argc * sizeof(void*)); - JL_GC_PUSHARGS(jlargs, argc); - int i; - for(i=0; i < argc; i++) { - jlargs[i] = jl_cstr_to_string(argv[i]); - } - jl_value_t *result = NULL; - JL_TRY { - result = jl_apply(f, jlargs, argc); - } - JL_CATCH { - //jl_show(jl_stdout_obj(), jl_exception_in_transit); - JL_GC_POP(); - return TCL_ERROR; - } - if (jl_is_byte_string(result)) - Tcl_SetResult(interp, jl_string_data(result), TCL_VOLATILE); - else - Tcl_SetResult(interp, "", TCL_STATIC); - JL_GC_POP(); - return TCL_OK; -} - -void *jl_tkwin_display(Tk_Window tkwin) -{ - return Tk_Display(tkwin); -} - -void *jl_tkwin_visual(Tk_Window tkwin) -{ - return Tk_Visual(tkwin); -} - -int jl_tkwin_id(Tk_Window tkwin) -{ - return Tk_WindowId(tkwin); -} diff --git a/doc/Makefile b/doc/Makefile index f4aba11a81206..3c82ec36ea381 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -6,6 +6,7 @@ SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build +JULIA = ../julia # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 @@ -19,7 +20,7 @@ JQUERYURL = http://code.jquery.com/jquery-latest.js WGET = $(abspath ../deps)/jldownload .PHONY: help clean clean-jquery cleanall get-jquery html dirhtml singlehtml pickle json htmlhelp qthelp devhelp \ - epub latex latexpdf text man changes linkcheck doctest gettext + epub latex latexpdf text man changes linkcheck doctest gettext listpkg help: @echo "Please use \`make ' where is one of" @@ -43,9 +44,11 @@ help: @echo " changes to make an overview of all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" + @echo " listpkg to recreate the list of available packages" clean: -rm -rf $(BUILDDIR)/* + -rm -f sphinx/*.pyc clean-jquery: -rm -f $(JQUERYDEST) @@ -171,3 +174,6 @@ doctest: helpdb.jl: stdlib/*.rst sphinx/jlhelp.py sphinx/julia.py $(SPHINXBUILD) -b jlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/jlhelp mv $(BUILDDIR)/jlhelp/jlhelp.jl helpdb.jl + +listpkg: + $(JULIA) listpkg.jl diff --git a/doc/_themes/julia/layout.html b/doc/_themes/julia/layout.html index 822cecd1dae7b..50e92fcce0eb9 100644 --- a/doc/_themes/julia/layout.html +++ b/doc/_themes/julia/layout.html @@ -31,13 +31,15 @@ {% block header %}
-
Julia Documentation
+
Julia Logo
diff --git a/doc/_themes/julia/static/julia.css_t b/doc/_themes/julia/static/julia.css_t index c37be824ef774..3fb847d9a1683 100644 --- a/doc/_themes/julia/static/julia.css_t +++ b/doc/_themes/julia/static/julia.css_t @@ -15,7 +15,7 @@ html, body { body { background-color: {{ theme_bgcolor }}; - font: 11.5pt Georgia, Arial, sans-serif; + font: 11.5pt Georgia, 'DejaVu Serif', serif; width: 100%; text-align: left; line-height: 1.5; @@ -51,7 +51,6 @@ div.header { } div.header .title { font-weight: bold; - margin-bottom: 2em; margin-top: 2.5em; } div.header .links { diff --git a/doc/_themes/julia/static/sidebar.js b/doc/_themes/julia/static/sidebar.js index 573a88cafc2c8..74a4c7f367e0e 100644 --- a/doc/_themes/julia/static/sidebar.js +++ b/doc/_themes/julia/static/sidebar.js @@ -187,4 +187,10 @@ $(function() { $(window).scroll(set_sidebar_pos); sidebarview.scroll(set_button_margin); $(window).resize(set_sidebar_pos); + + $("img[alt]").each(function(){ + $(this).attr('title', $(this).attr('alt')); + }); + }); + diff --git a/doc/conf.py b/doc/conf.py index 0fe41f7afebd5..8b37a432a54cc 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -42,16 +42,16 @@ # General information about the project. project = u'Julia Language' AUTHORS = u"Jeff Bezanson, Stefan Karpinski, Viral Shah, Alan Edelman, et al." -copyright = u'2012, '+AUTHORS +copyright = u'2012-2013, '+AUTHORS # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -version = 'devel' +version = '0.2' # The full version, including alpha/beta/rc tags. -release = 'development' +release = '0.2-dev' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/doc/helpdb.jl b/doc/helpdb.jl index 712106bc8b989..78202b69f7f4b 100644 --- a/doc/helpdb.jl +++ b/doc/helpdb.jl @@ -2,294 +2,131 @@ { -(E"ArgParse",E"ArgParse",E"parse_args",E"parse_args([args], settings) +("Getting Around","Base","exit","exit([code]) - This is the central function of the \"ArgParse\" module. It takes a - \"Vector\" of arguments and an \"ArgParseSettings\" objects (see - *this section*), and returns a \"Dict{String,Any}\". If \"args\" is - not provided, the global variable \"ARGS\" will be used. - - The returned \"Dict\" keys are defined (possibly implicitly) in - \"settings\", and their associated values are parsed from \"args\". - Special keys are used for more advanced purposes; at the moment, - one such key exists: \"%COMMAND%\" (see *this section*). - - Arguments are parsed in sequence and matched against the argument - table in \"settings\" to determine whether they are long options, - short options, option arguments or positional arguments: - - * long options begin with a doule dash \"\"--\"\"; if a \"'='\" - character is found, the remainder is the option argument; - therefore, \"[\"--opt=arg\"]\" and \"[\"--opt\", \"arg\"]\" are - equivalent if \"--opt\" takes at least one argument. Long options - can be abbreviated (e.g. \"--opt\" instead of \"--option\") as - long as there is no ambiguity. - - * short options begin with a single dash \"\"-\"\" and their name - consists of a single character; they can be grouped togheter - (e.g. \"[\"-x\", \"-y\"]\" can become \"[\"-xy\"]\"), but in that - case only the last option in the group can take an argument - (which can also be grouped, e.g. \"[\"-a\", \"-f\", - \"file.txt\"]\" can be passed as \"[\"-affile.txt\"]\" if \"-a\" - does not take an argument and \"-f\" does). The \"'='\" character - can be used to separate option names from option arguments as - well (e.g. \"-af=file.txt\"). - - * positional arguments are anything else; they can appear anywhere. - - The special string \"\"--\"\" can be used to signal the end of all - options; after that, everything is considered as a positional - argument (e.g. if \"args = [\"--opt1\", \"--\", \"--opt2\"]\", the - parser will recognize \"--opt1\" as a long option without argument, - and \"--opt2\" as a positional argument). - - The special string \"\"-\"\" is always parsed as a positional - argument. - - The parsing can stop early if a \":show_help\" or \":show_version\" - action is triggered, or if a parsing error is found. - - Some ambiguities can arise in parsing, see *this section* for a - detailed description of how they're solved. - -"), - -(E"ArgParse",E"ArgParse",E"@add_arg_table",E"@add_arg_table(settings, table...) - - This macro adds a table of arguments and options to the given - \"settings\". It can be invoked multiple times. The arguments - groups are determined automatically, or the current default group - is used if specified (see *this section* for more details). - - The \"table\" is a list in which each element can be either - \"String\", or a tuple or a vector of \"String\", or an assigmment - expression, or a block: - - * a \"String\", a tuple or a vector introduces a new positional - argument or option. Tuples and vectors are only allowed for - options and provide alternative names (e.g. \"[\"--opt\", - \"-o\"]\") - - * assignment expressions (i.e. expressions using \"=\", \":=\" or - \"=>\") describe the previous argument behavior (e.g. \"help = - \"an option\"\" or \"required => false\"). See *this section* - for a complete description - - * blocks (\"begin...end\" or lists of expressions in parentheses - separated by semicolons) are useful to group entries and span - multiple lines. - - These rules allow for a variety usage styles, which are discussed - in *this section*. In the rest of this document, we will mostly use - this style: - - @add_arg_table settings begin - \"--opt1\", \"-o\" - help = \"an option with an argument\" - \"--opt2\" - \"arg1\" - help = \"a positional argument\" - required = true - end - - In the above example, the \"table\" is put in a single - \"begin...end\" block and the line \"\"-opt1\", \"-o\"\" is parsed - as a tuple; indentation is used to help readability. + Quit (or control-D at the prompt). The default exit code is zero, + indicating that the processes completed successfully. "), -(E"ArgParse",E"ArgParse",E"add_arg_table",E"add_arg_table(settings, [arg_name [,arg_options]]...) +("Getting Around","Base","whos","whos([Module,] [pattern::Regex]) - This function is almost equivalent to the macro version. Its syntax - is stricter (tuples and blocks are not allowed and argument options - are explicitly specified as \"Options\" objects) but the - \"arg_name\" entries need not be explicit, they can be anything - which evaluates to a \"String\" or a \"Vector{String}\". - - Example: - - add_arg_table(settings, - [\"--opt1\", \"-o\"], - @options begin - help = \"an option with an argument\" - end, - \"--opt2\", - \"arg1\", - @options begin - help = \"a positional argument\" - required = true - end) - - Note that the \"OptionsMod\" module must be imported in order to - use this function. + Print information about global variables in a module, optionally + restricted to those matching \"pattern\". "), -(E"ArgParse",E"ArgParse",E"add_arg_group",E"add_arg_group(settings, description[, name[, set_as_default]]) - - This function adds an argument group to the argument table in - \"settings\". The \"description\" is a \"String\" used in the help - screen as a title for that group. The \"name\" is a unique name - which can be provided to refer to that group at a later time. - - After invoking this function, all subsequent invocations of the - \"@add_arg_table\" macro and \"add_arg_table\" function will use - the new group as the default, unless \"set_as_default\" is set to - \"false\" (the default is \"true\", and the option can only be set - if providing a \"name\"). Therefore, the most obvious usage pattern - is: for each group, add it and populate the argument table of that - group. Example: - - julia> settings = ArgParseSettings(); - - julia> add_arg_group(settings, \"custom group\"); - - julia> @add_arg_table settings begin - \"--opt\" - \"arg\" - end; - - julia> parse_args([\"--help\"], settings) - usage: [--opt OPT] [-h] [arg] - - optional arguments: - -h, --help show this help message and exit +("Getting Around","Base","edit","edit(file::String[, line]) - custom group: - --opt OPT - arg - - As seen from the example, new groups are always added at the end of - existing ones. - - The \"name\" can also be passed as a \"Symbol\". Forbidden names - are the standard groups names (\"\"command\"\", \"\"positional\"\" - and \"\"optional\"\") and those beginning with a hash character - \"'#'\". + Edit a file optionally providing a line number to edit at. Returns + to the julia prompt when you quit the editor. If the file name ends + in \".jl\" it is reloaded when the editor closes the file. "), -(E"ArgParse",E"ArgParse",E"set_default_arg_group",E"set_default_arg_group(settings[, name]) - - Set the default group for subsequent invocations of the - \"@add_arg_table\" macro and \"add_arg_table\" function. \"name\" - is a \"String\", and must be one of the standard group names - (\"\"command\"\", \"\"positional\"\" or \"\"optional\"\") or one of - the user-defined names given in \"add_arg_group\" (groups with no - assigned name cannot be used with this function). +("Getting Around","Base","edit","edit(function[, types]) - If \"name\" is not provided or is the empty string \"\"\"\", then - the default behavior is reset (i.e. arguments will be automatically - assigned to the standard groups). The \"name\" can also be passed - as a \"Symbol\". + Edit the definition of a function, optionally specifying a tuple of + types to indicate which method to edit. When the editor exits, the + source file containing the definition is reloaded. "), -(E"ArgParse",E"ArgParse",E"import_settings",E"import_settings(settings, other_settings[, args_only]) - - Imports \"other_settings\" into \"settings\", where both are - \"ArgParseSettings\" objects. If \"args_only\" is \"true\" (this is - the default), only the argument table will be imported; otherwise, - the default argument group will also be imported, and all general - settings except \"prog\", \"description\", \"epilog\" and - \"usage\". - - Sub-settings associated with commands will also be imported - recursively; the \"args_only\" setting applies to those as well. If - there are common commands, their sub-settings will be merged. - - While importing, conflicts may arise: if - \"settings.error_on_conflict\" is \"true\", this will result in an - error, otherwise conflicts will be resolved in favor of - \"other_settings\" (see *this section* for a detailed discussion of - how conflicts are handled). +("Getting Around","Base","require","require(file::String...) - Argument groups will also be imported; if two groups in - \"settings\" and \"other_settings\" match, they are merged (groups - match either by name, or, if unnamed, by their description). - - Note that the import will have effect immediately: any subsequent - modification of \"other_settings\" will not have any effect on - \"settings\". - - This function can be used at any time. + Load source files once, in the context of the \"Main\" module, on + every active node, searching the system-wide \"LOAD_PATH\" for + files. \"require\" is considered a top-level operation, so it sets + the current \"include\" path but does not use it to search for + files (see help for \"include\"). This function is typically used + to load library code, and is implicitly called by \"using\" to load + packages. "), -(E"Getting Around",E"Base",E"exit",E"exit([code]) +("Getting Around","Base","reload","reload(file::String) - Quit (or control-D at the prompt). The default exit code is zero, - indicating that the processes completed successfully. + Like \"require\", except forces loading of files regardless of + whether they have been loaded before. Typically used when + interactively developing libraries. "), -(E"Getting Around",E"Base",E"whos",E"whos([Module][, pattern::Regex]) +("Getting Around","Base","include","include(path::String) - Print information about global variables in a module, optionally - restricted to those matching \"pattern\". + Evaluate the contents of a source file in the current context. + During including, a task-local include path is set to the directory + containing the file. Nested calls to \"include\" will search + relative to that path. All paths refer to files on node 1 when + running in parallel, and files will be fetched from node 1. This + function is typically used to load source interactively, or to + combine files in packages that are broken into multiple source + files. "), -(E"Getting Around",E"Base",E"edit",E"edit(\"file\"[, line]) +("Getting Around","Base","include_string","include_string(code::String) - Edit a file optionally providing a line number to edit at. Returns - to the julia prompt when you quit the editor. If the file name ends - in \".jl\" it is reloaded when the editor closes the file. + Like \"include\", except reads code from the given string rather + than from a file. Since there is no file path involved, no path + processing or fetching from node 1 is done. "), -(E"Getting Around",E"Base",E"edit",E"edit(function[, types]) +("Getting Around","Base","evalfile","evalfile(path::String) - Edit the definition of a function, optionally specifying a tuple of - types to indicate which method to edit. When the editor exits, the - source file containing the definition is reloaded. + Evaluate all expressions in the given file, and return the value of + the last one. No other processing (path searching, fetching from + node 1, etc.) is performed. "), -(E"Getting Around",E"Base",E"load",E"load(\"file\") +("Getting Around","Base","help","help(name) - Evaluate the contents of a source file + Get help for a function. \"name\" can be an object or a string. "), -(E"Getting Around",E"Base",E"help",E"help(\"name\" or object) +("Getting Around","Base","apropos","apropos(string) - Get help for a function + Search documentation for functions related to \"string\". "), -(E"Getting Around",E"Base",E"apropos",E"apropos(\"string\") +("Getting Around","Base","which","which(f, args...) - Search help for a substring + Show which method of \"f\" will be called for the given arguments. "), -(E"Getting Around",E"Base",E"which",E"which(f, args...) +("Getting Around","Base","methods","methods(f) - Show which method of \"f\" will be called for the given arguments + Show all methods of \"f\" with their argument types. "), -(E"Getting Around",E"Base",E"methods",E"methods(f) +("Getting Around","Base","methodswith","methodswith(typ[, showparents]) - Show all methods of \"f\" with their argument types + Show all methods with an argument of type \"typ\". If optional + \"showparents\" is \"true\", also show arguments with a parent type + of \"typ\", excluding type \"Any\". "), -(E"All Objects",E"Base",E"is",E"is(x, y) +("All Objects","Base","is","is(x, y) Determine whether \"x\" and \"y\" are identical, in the sense that no program could distinguish them. "), -(E"All Objects",E"Base",E"isa",E"isa(x, type) +("All Objects","Base","isa","isa(x, type) Determine whether \"x\" is of the given type. "), -(E"All Objects",E"Base",E"isequal",E"isequal(x, y) +("All Objects","Base","isequal","isequal(x, y) True if and only if \"x\" and \"y\" have the same contents. Loosely speaking, this means \"x\" and \"y\" would look the same when @@ -297,7 +134,7 @@ "), -(E"All Objects",E"Base",E"isless",E"isless(x, y) +("All Objects","Base","isless","isless(x, y) Test whether \"x\" is less than \"y\". Provides a total order consistent with \"isequal\". Values that are normally unordered, @@ -307,48 +144,48 @@ "), -(E"All Objects",E"Base",E"typeof",E"typeof(x) +("All Objects","Base","typeof","typeof(x) Get the concrete type of \"x\". "), -(E"All Objects",E"Base",E"tuple",E"tuple(xs...) +("All Objects","Base","tuple","tuple(xs...) Construct a tuple of the given objects. "), -(E"All Objects",E"Base",E"ntuple",E"ntuple(n, f::Function) +("All Objects","Base","ntuple","ntuple(n, f::Function) Create a tuple of length \"n\", computing each element as \"f(i)\", where \"i\" is the index of the element. "), -(E"All Objects",E"Base",E"object_id",E"object_id(x) +("All Objects","Base","object_id","object_id(x) Get a unique integer id for \"x\". \"object_id(x)==object_id(y)\" if and only if \"is(x,y)\". "), -(E"All Objects",E"Base",E"hash",E"hash(x) +("All Objects","Base","hash","hash(x) Compute an integer hash code such that \"isequal(x,y)\" implies \"hash(x)==hash(y)\". "), -(E"All Objects",E"Base",E"finalizer",E"finalizer(x, function) +("All Objects","Base","finalizer","finalizer(x, function) - Register a function to be called on \"x\" when there are no + Register a function \"f(x)\" to be called when there are no program-accessible references to \"x\". The behavior of this function is unpredictable if \"x\" is of a bits type. "), -(E"All Objects",E"Base",E"copy",E"copy(x) +("All Objects","Base","copy","copy(x) Create a shallow copy of \"x\": the outer structure is copied, but not all internal values. For example, copying an array produces a @@ -356,7 +193,7 @@ "), -(E"All Objects",E"Base",E"deepcopy",E"deepcopy(x) +("All Objects","Base","deepcopy","deepcopy(x) Create a deep copy of \"x\": everything is copied recursively, resulting in a fully independent object. For example, deep-copying @@ -379,20 +216,20 @@ "), -(E"All Objects",E"Base",E"convert",E"convert(type, x) +("All Objects","Base","convert","convert(type, x) Try to convert \"x\" to the given type. "), -(E"All Objects",E"Base",E"promote",E"promote(xs...) +("All Objects","Base","promote","promote(xs...) Convert all arguments to their common promotion type (if any), and return them all (as a tuple). "), -(E"Types",E"Base",E"subtype",E"subtype(type1, type2) +("Types","Base","subtype","subtype(type1, type2) True if and only if all values of \"type1\" are also of \"type2\". Can also be written using the \"<:\" infix operator as \"type1 <: @@ -400,40 +237,53 @@ "), -(E"Types",E"Base",E"typemin",E"typemin(type) +("Types","Base","<:","<:(T1, T2) + + Subtype operator, equivalent to \"subtype(T1,T2)\". + +"), + +("Types","Base","typemin","typemin(type) The lowest value representable by the given (real) numeric type. "), -(E"Types",E"Base",E"typemax",E"typemax(type) +("Types","Base","typemax","typemax(type) The highest value representable by the given (real) numeric type. "), -(E"Types",E"Base",E"realmin",E"realmin(type) +("Types","Base","realmin","realmin(type) The smallest in absolute value non-denormal value representable by the given floating-point type "), -(E"Types",E"Base",E"realmax",E"realmax(type) +("Types","Base","realmax","realmax(type) The highest finite value representable by the given floating-point type "), -(E"Types",E"Base",E"sizeof",E"sizeof(type) +("Types","Base","maxintfloat","maxintfloat(type) + + The largest integer losslessly representable by the given floating- + point type + +"), + +("Types","Base","sizeof","sizeof(type) Size, in bytes, of the canonical binary representation of the given type, if any. "), -(E"Types",E"Base",E"eps",E"eps([type]) +("Types","Base","eps","eps([type]) The distance between 1.0 and the next larger representable floating-point value of \"type\". The only types that are sensible @@ -442,14 +292,14 @@ "), -(E"Types",E"Base",E"eps",E"eps(x) +("Types","Base","eps","eps(x) The distance between \"x\" and the next larger representable floating-point value of the same type as \"x\". "), -(E"Types",E"Base",E"promote_type",E"promote_type(type1, type2) +("Types","Base","promote_type","promote_type(type1, type2) Determine a type big enough to hold values of each argument type without loss, whenever possible. In some cases, where no type @@ -460,21 +310,46 @@ "), -(E"Generic Functions",E"Base",E"method_exists",E"method_exists(f, tuple) +("Types","Base","getfield","getfield(value, name::Symbol) + + Extract a named field from a value of composite type. The syntax + \"a.b\" calls \"getfield(a, :b)\", and the syntax \"a.(b)\" calls + \"getfield(a, b)\". + +"), + +("Types","Base","setfield","setfield(value, name::Symbol, x) + + Assign \"x\" to a named field in \"value\" of composite type. The + syntax \"a.b = c\" calls \"setfield(a, :b, c)\", and the syntax + \"a.(b) = c\" calls \"setfield(a, b, c)\". + +"), + +("Types","Base","fieldtype","fieldtype(value, name::Symbol) + + Determine the declared type of a named field in a value of + composite type. + +"), + +("Generic Functions","Base","method_exists","method_exists(f, tuple) -> Bool Determine whether the given generic function has a method matching the given tuple of argument types. + **Example**: \"method_exists(length, (Array,)) = true\" + "), -(E"Generic Functions",E"Base",E"applicable",E"applicable(f, args...) +("Generic Functions","Base","applicable","applicable(f, args...) Determine whether the given generic function has a method applicable to the given arguments. "), -(E"Generic Functions",E"Base",E"invoke",E"invoke(f, (types...), args...) +("Generic Functions","Base","invoke","invoke(f, (types...), args...) Invoke a method for the given generic function matching the specified types (as a tuple), on the specified arguments. The @@ -486,46 +361,102 @@ "), -(E"Iteration",E"Base",E"start",E"start(iter) +("Generic Functions","Base","|","|(x, f) + + Applies a function to the preceding argument which allows for easy + function chaining. + + **Example**: \"[1:5] | x->x.^2 | sum | inv\" + +"), + +("Iteration","Base","start","start(iter) -> state Get initial iteration state for an iterable object "), -(E"Iteration",E"Base",E"done",E"done(iter, state) +("Iteration","Base","done","done(iter, state) -> Bool Test whether we are done iterating "), -(E"Iteration",E"Base",E"next",E"next(iter, state) -> item, state +("Iteration","Base","next","next(iter, state) -> item, state For a given iterable object and iteration state, return the current item and the next iteration state "), -(E"General Collections",E"Base",E"isempty",E"isempty(collection) +("Iteration","Base","zip","zip(iters...) + + For a set of iterable objects, returns an iterable of tuples, where + the \"i\"th tuple contains the \"i\"th component of each input + iterable. + + Note that \"zip\" is it's own inverse: \"[zip(zip(a...)...)...] == + [a...]\". + +"), + +("Iteration","Base","enumerate","enumerate(iter) + + Return an iterator that yields \"(i, x)\" where \"i\" is an index + starting at 1, and \"x\" is the \"ith\" value from the given + iterator. + +"), + +("General Collections","Base","isempty","isempty(collection) -> Bool Determine whether a collection is empty (has no elements). "), -(E"General Collections",E"Base",E"length",E"length(collection) +("General Collections","Base","empty!","empty!(collection) -> collection + + Remove all elements from a collection. + +"), + +("General Collections","Base","length","length(collection) -> Integer For ordered, indexable collections, the maximum index \"i\" for - which \"ref(collection, i)\" is valid. For unordered collections, - the number of elements. + which \"getindex(collection, i)\" is valid. For unordered + collections, the number of elements. + +"), + +("General Collections","Base","endof","endof(collection) -> Integer + + Returns the last index of the collection. + + **Example**: \"endof([1,2,4]) = 3\" "), -(E"Iterable Collections",E"Base",E"contains",E"contains(itr, x) +("Iterable Collections","Base","contains","contains(itr, x) -> Bool Determine whether a collection contains the given value, \"x\". "), -(E"Iterable Collections",E"Base",E"reduce",E"reduce(op, v0, itr) +("Iterable Collections","Base","findin","findin(a, b) + + Returns the indices of elements in collection \"a\" that appear in + collection \"b\" + +"), + +("Iterable Collections","Base","unique","unique(itr) + + Returns an array containing only the unique elements of the + iterable \"itr\". + +"), + +("Iterable Collections","Base","reduce","reduce(op, v0, itr) Reduce the given collection with the given operator, i.e. accumulate \"v = op(v,elt)\" for each element, where \"v\" starts @@ -536,603 +467,934 @@ "), -(E"Iterable Collections",E"Base",E"max",E"max(itr) +("Iterable Collections","Base","max","max(itr) - Determine maximum element in a collection + Returns the largest element in a collection "), -(E"Iterable Collections",E"Base",E"min",E"min(itr) +("Iterable Collections","Base","min","min(itr) - Determine minimum element in a collection + Returns the smallest element in a collection "), -(E"Iterable Collections",E"Base",E"indmax",E"indmax(itr) +("Iterable Collections","Base","indmax","indmax(itr) -> Integer Returns the index of the maximum element in a collection "), -(E"Iterable Collections",E"Base",E"indmin",E"indmin(itr) +("Iterable Collections","Base","indmin","indmin(itr) -> Integer Returns the index of the minimum element in a collection "), -(E"Iterable Collections",E"Base",E"findmax",E"findmax(iter) +("Iterable Collections","Base","findmax","findmax(itr) -> (x, index) - Returns a tuple of the maximum element and its index + Returns the maximum element and its index "), -(E"Iterable Collections",E"Base",E"findmin",E"findmin(iter) +("Iterable Collections","Base","findmin","findmin(itr) -> (x, index) - Returns a tuple of the minimum element and its index + Returns the minimum element and its index "), -(E"Iterable Collections",E"Base",E"sum",E"sum(itr) +("Iterable Collections","Base","sum","sum(itr) - Sum elements of a collection + Returns the sum of all elements in a collection "), -(E"Iterable Collections",E"Base",E"prod",E"prod(itr) +("Iterable Collections","Base","prod","prod(itr) - Multiply elements of a collection + Returns the product of all elements of a collection "), -(E"Iterable Collections",E"Base",E"any",E"any(itr) +("Iterable Collections","Base","any","any(itr) -> Bool Test whether any elements of a boolean collection are true "), -(E"Iterable Collections",E"Base",E"all",E"all(itr) +("Iterable Collections","Base","all","all(itr) -> Bool Test whether all elements of a boolean collection are true "), -(E"Iterable Collections",E"Base",E"count",E"count(itr) +("Iterable Collections","Base","count","count(itr) -> Integer - Count the number of boolean elements in \"itr\" which are \"true\" - rather than \"false\". + Count the number of boolean elements in \"itr\" which are true. "), -(E"Iterable Collections",E"Base",E"countp",E"countp(p, itr) +("Iterable Collections","Base","countp","countp(p, itr) -> Integer Count the number of elements in \"itr\" for which predicate \"p\" is true. "), -(E"Iterable Collections",E"Base",E"anyp",E"anyp(p, itr) +("Iterable Collections","Base","any","any(p, itr) -> Bool Determine whether any element of \"itr\" satisfies the given predicate. "), -(E"Iterable Collections",E"Base",E"allp",E"allp(p, itr) +("Iterable Collections","Base","all","all(p, itr) -> Bool Determine whether all elements of \"itr\" satisfy the given predicate. "), -(E"Iterable Collections",E"Base",E"map",E"map(f, c) +("Iterable Collections","Base","map","map(f, c) -> collection + + Transform collection \"c\" by applying \"f\" to each element. + + **Example**: \"map((x) -> x * 2, [1, 2, 3]) = [2, 4, 6]\" + +"), + +("Iterable Collections","Base","map!","map!(function, collection) + + In-place version of \"map()\". + +"), + +("Iterable Collections","Base","mapreduce","mapreduce(f, op, itr) + + Applies function \"f\" to each element in \"itr\" and then reduces + the result using the binary function \"op\". + + **Example**: \"mapreduce(x->x^2, +, [1:3]) == 1 + 4 + 9 == 14\" + +"), + +("Iterable Collections","Base","first","first(coll) + + Get the first element of an ordered collection. + +"), + +("Iterable Collections","Base","last","last(coll) - Transform collection \"c\" by applying \"f\" to each element + Get the last element of an ordered collection. "), -(E"Indexable Collections",E"Base",E"collection[key...]",E"ref(collection, key...) -collection[key...]() +("Indexable Collections","Base","getindex","getindex(collection, key...) Retrieve the value(s) stored at the given key or index within a - collection. + collection. The syntax \"a[i,j,...]\" is converted by the compiler + to \"getindex(a, i, j, ...)\". "), -(E"Indexable Collections",E"",E"collection[key...] = value",E"assign(collection, value, key...) -collection[key...] = value +("Indexable Collections","Base","setindex!","setindex!(collection, value, key...) Store the given value at the given key or index within a - collection. + collection. The syntax \"a[i,j,...] = x\" is converted by the + compiler to \"setindex!(a, x, i, j, ...)\". "), -(E"Associative Collections",E"Base",E"Dict{K,V}",E"Dict{K,V}(n) +("Associative Collections","Base","Dict{K,V}","Dict{K,V}() - Construct a hashtable with keys of type K and values of type V and - intial size of n + Construct a hashtable with keys of type K and values of type V "), -(E"Associative Collections",E"Base",E"has",E"has(collection, key) +("Associative Collections","Base","has","has(collection, key) Determine whether a collection has a mapping for a given key. "), -(E"Associative Collections",E"Base",E"get",E"get(collection, key, default) +("Associative Collections","Base","get","get(collection, key, default) Return the value stored for the given key, or the given default value if no mapping for the key is present. "), -(E"Associative Collections",E"Base",E"del",E"del(collection, key) +("Associative Collections","Base","getkey","getkey(collection, key, default) - Delete the mapping for the given key in a collection. + Return the key matching argument \"key\" if one exists in + \"collection\", otherwise return \"default\". "), -(E"Associative Collections",E"Base",E"del_all",E"del_all(collection) +("Associative Collections","Base","delete!","delete!(collection, key) - Delete all keys from a collection. + Delete the mapping for the given key in a collection. "), -(E"Associative Collections",E"Base",E"keys",E"keys(collection) +("Associative Collections","Base","keys","keys(collection) Return an array of all keys in a collection. "), -(E"Associative Collections",E"Base",E"values",E"values(collection) +("Associative Collections","Base","values","values(collection) Return an array of all values in a collection. "), -(E"Associative Collections",E"Base",E"pairs",E"pairs(collection) +("Associative Collections","Base","collect","collect(collection) - Return an array of all (key, value) tuples in a collection. + Return an array of all items in a collection. For associative + collections, returns (key, value) tuples. "), -(E"Associative Collections",E"Base",E"merge",E"merge(collection, others...) +("Associative Collections","Base","merge","merge(collection, others...) Construct a merged collection from the given collections. "), -(E"Associative Collections",E"Base",E"merge!",E"merge!(collection, others...) +("Associative Collections","Base","merge!","merge!(collection, others...) Update collection with pairs from the other collections "), -(E"Associative Collections",E"Base",E"filter",E"filter(function, collection) +("Associative Collections","Base","filter","filter(function, collection) Return a copy of collection, removing (key, value) pairs for which function is false. "), -(E"Associative Collections",E"Base",E"filter!",E"filter!(function, collection) +("Associative Collections","Base","filter!","filter!(function, collection) Update collection, removing (key, value) pairs for which function is false. "), -(E"Set-Like Collections",E"Base",E"add",E"add(collection, key) +("Associative Collections","Base","eltype","eltype(collection) + + Returns the type tuple of the (key,value) pairs contained in + collection. + +"), + +("Associative Collections","Base","sizehint","sizehint(s, n) + + Suggest that collection \"s\" reserve capacity for at least \"n\" + elements. This can improve performance. + +"), + +("Set-Like Collections","Base","add!","add!(collection, key) Add an element to a set-like collection. "), -(E"Set-Like Collections",E"Base",E"Set",E"Set(x...) +("Set-Like Collections","Base","add_each!","add_each!(collection, iterable) + + Adds each element in iterable to the collection. + +"), + +("Set-Like Collections","Base","Set","Set(x...) Construct a \"Set\" with the given elements. Should be used instead of \"IntSet\" for sparse integer sets. "), -(E"Set-Like Collections",E"Base",E"IntSet",E"IntSet(i...) +("Set-Like Collections","Base","IntSet","IntSet(i...) Construct an \"IntSet\" of the given integers. Implemented as a bit string, and therefore good for dense integer sets. "), -(E"Set-Like Collections",E"Base",E"choose",E"choose(s) +("Set-Like Collections","Base","union","union(s1, s2...) + + Construct the union of two or more sets. Maintains order with + arrays. + +"), + +("Set-Like Collections","Base","union!","union!(s1, s2) + + Constructs the union of IntSets s1 and s2, stores the result in + \"s1\". + +"), + +("Set-Like Collections","Base","intersect","intersect(s1, s2...) + + Construct the intersection of two or more sets. Maintains order + with arrays. + +"), + +("Set-Like Collections","Base","setdiff","setdiff(s1, s2) + + Construct the set of elements in \"s1\" but not \"s2\". Maintains + order with arrays. + +"), + +("Set-Like Collections","Base","symdiff","symdiff(s1, s2...) - Pick an element of a set + Construct the symmetric difference of elements in the passed in + sets or arrays. Maintains order with arrays. "), -(E"Set-Like Collections",E"Base",E"union",E"union(s1, s2) +("Set-Like Collections","Base","symdiff!","symdiff!(s, n) - Construct the union of two sets + IntSet s is destructively modified to toggle the inclusion of + integer \"n\". "), -(E"Dequeues",E"Base",E"push",E"push(collection, item) +("Set-Like Collections","Base","symdiff!","symdiff!(s, itr) + + For each element in \"itr\", destructively toggle its inclusion in + set \"s\". + +"), + +("Set-Like Collections","Base","symdiff!","symdiff!(s1, s2) + + Construct the symmetric difference of IntSets \"s1\" and \"s2\", + storing the result in \"s1\". + +"), + +("Set-Like Collections","Base","complement","complement(s) + + Returns the set-complement of IntSet s. + +"), + +("Set-Like Collections","Base","complement!","complement!(s) + + Mutates IntSet s into its set-complement. + +"), + +("Set-Like Collections","Base","del_each!","del_each!(s, itr) + + Deletes each element of itr in set s in-place. + +"), + +("Set-Like Collections","Base","intersect!","intersect!(s1, s2) + + Intersects IntSets s1 and s2 and overwrites the set s1 with the + result. If needed, s1 will be expanded to the size of s2. + +"), + +("Dequeues","Base","push!","push!(collection, item) -> collection Insert an item at the end of a collection. "), -(E"Dequeues",E"Base",E"pop",E"pop(collection) +("Dequeues","Base","pop!","pop!(collection) -> item Remove the last item in a collection and return it. "), -(E"Dequeues",E"Base",E"enqueue",E"enqueue(collection, item) +("Dequeues","Base","unshift!","unshift!(collection, item) -> collection - Insert an item at the beginning of a collection. Also called - \"unshift\". + Insert an item at the beginning of a collection. "), -(E"Dequeues",E"Base",E"shift",E"shift(collection) +("Dequeues","Base","shift!","shift!(collection) -> item - Remove the first item in a collection and return it. + Remove the first item in a collection. "), -(E"Dequeues",E"Base",E"insert",E"insert(collection, index, item) +("Dequeues","Base","insert!","insert!(collection, index, item) Insert an item at the given index. "), -(E"Dequeues",E"Base",E"del",E"del(collection, index) +("Dequeues","Base","delete!","delete!(collection, index) -> item - Remove the item at the given index. + Remove the item at the given index, and return the deleted item. "), -(E"Dequeues",E"Base",E"grow",E"grow(collection, n) +("Dequeues","Base","delete!","delete!(collection, range) -> items - Add uninitialized space for \"n\" elements at the end of a - collection. + Remove items at specified range, and return a collection containing + the deleted items. "), -(E"Dequeues",E"Base",E"append!",E"append!(collection, items) +("Dequeues","Base","resize!","resize!(collection, n) -> collection - Add the elements of \"items\" to the end of a collection. + Resize collection to contain \"n\" elements. "), -(E"Strings",E"Base",E"strlen",E"strlen(s) +("Dequeues","Base","append!","append!(collection, items) -> collection - The number of characters in string \"s\". + Add the elements of \"items\" to the end of a collection. "), -(E"Strings",E"Base",E"length",E"length(s) +("Strings","Base","length","length(s) - The last valid index for string \"s\". Indexes are byte offsets and - not character numbers. + The number of characters in string \"s\". "), -(E"Strings",E"Base",E"chars",E"chars(string) +("Strings","Base","*","*(s, t) + + Concatenate strings. - Return an array of the characters in \"string\". + **Example**: \"\"Hello \" * \"world\" == \"Hello world\"\" "), -(E"Strings",E"Base",E"strcat",E"strcat(strs...) +("Strings","Base","^","^(s, n) - Concatenate strings. + Repeat string \"s\" \"n\" times. + + **Example**: \"\"Julia \"^3 == \"Julia Julia Julia \"\" "), -(E"Strings",E"Base",E"string",E"string(char...) +("Strings","Base","string","string(xs...) - Create a string with the given characters. + Create a string from any values using the \"print\" function. "), -(E"Strings",E"Base",E"string",E"string(x) +("Strings","Base","repr","repr(x) Create a string from any value using the \"show\" function. "), -(E"Strings",E"Base",E"bytestring",E"bytestring(::Ptr{Uint8}) +("Strings","Base","bytestring","bytestring(::Ptr{Uint8}) - Create a string from the address of a C (0-terminated) string. + Create a string from the address of a C (0-terminated) string. A + copy is made; the ptr can be safely freed. "), -(E"Strings",E"Base",E"bytestring",E"bytestring(s) +("Strings","Base","bytestring","bytestring(s) Convert a string to a contiguous byte array representation appropriate for passing it to C functions. "), -(E"Strings",E"Base",E"ascii",E"ascii(::Array{Uint8, 1}) +("Strings","Base","ascii","ascii(::Array{Uint8, 1}) Create an ASCII string from a byte array. "), -(E"Strings",E"Base",E"ascii",E"ascii(s) +("Strings","Base","ascii","ascii(s) Convert a string to a contiguous ASCII string (all characters must be valid ASCII characters). "), -(E"Strings",E"Base",E"utf8",E"utf8(::Array{Uint8, 1}) +("Strings","Base","utf8","utf8(::Array{Uint8, 1}) Create a UTF-8 string from a byte array. "), -(E"Strings",E"Base",E"utf8",E"utf8(s) +("Strings","Base","utf8","utf8(s) Convert a string to a contiguous UTF-8 string (all characters must be valid UTF-8 characters). "), -(E"Strings",E"Base",E"strchr",E"strchr(string, char[, i]) +("Strings","Base","is_valid_ascii","is_valid_ascii(s) -> Bool + + Returns true if the string or byte vector is valid ASCII, false + otherwise. + +"), + +("Strings","Base","is_valid_utf8","is_valid_utf8(s) -> Bool + + Returns true if the string or byte vector is valid UTF-8, false + otherwise. + +"), + +("Strings","Base","is_valid_char","is_valid_char(c) -> Bool + + Returns true if the given char or integer is a valid Unicode code + point. + +"), + +("Strings","Base","ismatch","ismatch(r::Regex, s::String) - Return the index of \"char\" in \"string\", giving 0 if not found. - The second argument may also be a vector or a set of characters. - The third argument optionally specifies a starting index. + Test whether a string contains a match of the given regular + expression. "), -(E"Strings",E"Base",E"lpad",E"lpad(string, n, p) +("Strings","Base","lpad","lpad(string, n, p) Make a string at least \"n\" characters long by padding on the left with copies of \"p\". "), -(E"Strings",E"Base",E"rpad",E"rpad(string, n, p) +("Strings","Base","rpad","rpad(string, n, p) Make a string at least \"n\" characters long by padding on the right with copies of \"p\". "), -(E"Strings",E"Base",E"search",E"search(string, chars[, start]) +("Strings","Base","search","search(string, chars[, start]) Search for the given characters within the given string. The second argument may be a single character, a vector or a set of - characters, a string, or a regular expression (but regular + characters, a string, or a regular expression (though regular expressions are only allowed on contiguous strings, such as ASCII or UTF-8 strings). The third argument optionally specifies a - starting index. The return value is a tuple with 2 integers: the - index of the match and the first valid index past the match (or an - index beyond the end of the string if the match is at the end); it - returns \"(0,0)\" if no match was found, and \"(start,start)\" if - \"chars\" is empty. + starting index. The return value is a range of indexes where the + matching sequence is found, such that \"s[search(s,x)] == x\". The + return value is \"0:-1\" if there is no match. + +"), + +("Strings","Base","replace","replace(string, pat, r[, n]) + + Search for the given pattern \"pat\", and replace each occurance + with \"r\". If \"n\" is provided, replace at most \"n\" occurances. + As with search, the second argument may be a single character, a + vector or a set of characters, a string, or a regular expression. + If \"r\" is a function, each occurrence is replaced with \"r(s)\" + where \"s\" is the matched substring. "), -(E"Strings",E"Base",E"split",E"split(string, chars[, limit][, include_empty]) +("Strings","Base","split","split(string, [chars, [limit,] [include_empty]]) Return an array of strings by splitting the given string on occurrences of the given character delimiters, which may be specified in any of the formats allowed by \"search\"'s second - argument. The last two arguments are optional; they are are a - maximum size for the result and a flag determining whether empty - fields should be included in the result. + argument (i.e. a single character, collection of characters, + string, or regular expression). If \"chars\" is omitted, it + defaults to the set of all space characters, and \"include_empty\" + is taken to be false. The last two arguments are also optional: + they are are a maximum size for the result and a flag determining + whether empty fields should be included in the result. "), -(E"Strings",E"Base",E"strip",E"strip(string) +("Strings","Base","strip","strip(string[, chars]) Return \"string\" with any leading and trailing whitespace removed. + If a string \"chars\" is provided, instead remove characters + contained in that string. "), -(E"Strings",E"Base",E"lstrip",E"lstrip(string) +("Strings","Base","lstrip","lstrip(string[, chars]) - Return \"string\" with any leading whitespace removed. + Return \"string\" with any leading whitespace removed. If a string + \"chars\" is provided, instead remove characters contained in that + string. "), -(E"Strings",E"Base",E"rstrip",E"rstrip(string) +("Strings","Base","rstrip","rstrip(string[, chars]) - Return \"string\" with any trailing whitespace removed. + Return \"string\" with any trailing whitespace removed. If a string + \"chars\" is provided, instead remove characters contained in that + string. "), -(E"Strings",E"Base",E"begins_with",E"begins_with(string, prefix) +("Strings","Base","beginswith","beginswith(string, prefix) Returns \"true\" if \"string\" starts with \"prefix\". "), -(E"Strings",E"Base",E"ends_with",E"ends_with(string, suffix) +("Strings","Base","endswith","endswith(string, suffix) Returns \"true\" if \"string\" ends with \"suffix\". "), -(E"Strings",E"Base",E"uppercase",E"uppercase(string) +("Strings","Base","uppercase","uppercase(string) Returns \"string\" with all characters converted to uppercase. "), -(E"Strings",E"Base",E"lowercase",E"lowercase(string) +("Strings","Base","lowercase","lowercase(string) Returns \"string\" with all characters converted to lowercase. "), -(E"Strings",E"Base",E"join",E"join(strings, delim) +("Strings","Base","join","join(strings, delim) Join an array of strings into a single string, inserting the given delimiter between adjacent strings. "), -(E"Strings",E"Base",E"chop",E"chop(string) +("Strings","Base","chop","chop(string) Remove the last character from a string "), -(E"Strings",E"Base",E"chomp",E"chomp(string) +("Strings","Base","chomp","chomp(string) Remove a trailing newline from a string "), -(E"Strings",E"Base",E"ind2chr",E"ind2chr(string, i) +("Strings","Base","ind2chr","ind2chr(string, i) Convert a byte index to a character index "), -(E"Strings",E"Base",E"chr2ind",E"chr2ind(string, i) +("Strings","Base","chr2ind","chr2ind(string, i) Convert a character index to a byte index "), -(E"Strings",E"Base",E"randstring",E"randstring(len) +("Strings","Base","isvalid","isvalid(str, i) - Create a random ASCII string of length \"len\", consisting of - upper- and lower-case letters and the digits 0-9 + Tells whether index \"i\" is valid for the given string "), -(E"I/O",E"Base",E"stdout_stream",E"stdout_stream +("Strings","Base","nextind","nextind(str, i) - Global variable referring to the standard out stream. + Get the next valid string index after \"i\". Returns + \"endof(str)+1\" at the end of the string. "), -(E"I/O",E"Base",E"stderr_stream",E"stderr_stream +("Strings","Base","prevind","prevind(str, i) - Global variable referring to the standard error stream. + Get the previous valid string index before \"i\". Returns \"0\" at + the beginning of the string. "), -(E"I/O",E"Base",E"stdin_stream",E"stdin_stream +("Strings","Base","thisind","thisind(str, i) - Global variable referring to the standard input stream. + Adjust \"i\" downwards until it reaches a valid index for the given + string. "), -(E"I/O",E"Base",E"open",E"open(file_name[, read, write, create, truncate, append]) +("Strings","Base","randstring","randstring(len) - Open a file in a mode specified by five boolean arguments. The - default is to open files for reading only. Returns a stream for - accessing the file. + Create a random ASCII string of length \"len\", consisting of + upper- and lower-case letters and the digits 0-9 "), -(E"I/O",E"Base",E"open",E"open(file_name[, mode]) - - Alternate syntax for open, where a string-based mode specifier is - used instead of the five booleans. The values of \"mode\" - correspond to those from \"fopen(3)\" or Perl \"open\", and are - equivalent to setting the following boolean groups: +("Strings","Base","charwidth","charwidth(c) - +------+-----------------------------------+ - | r | read | - +------+-----------------------------------+ - | r+ | read, write | - +------+-----------------------------------+ - | w | write, create, truncate | - +------+-----------------------------------+ - | w+ | read, write, create, truncate | - +------+-----------------------------------+ - | a | write, create, append | - +------+-----------------------------------+ - | a+ | read, write, create, append | - +------+-----------------------------------+ + Gives the number of columns needed to print a character. "), -(E"I/O",E"Base",E"memio",E"memio([size]) +("Strings","Base","strwidth","strwidth(s) - Create an in-memory I/O stream, optionally specifying how much - initial space is needed. + Gives the number of columns needed to print a string. "), -(E"I/O",E"Base",E"fdio",E"fdio(descriptor[, own]) +("Strings","Base","isalnum","isalnum(c::Char) - Create an \"IOStream\" object from an integer file descriptor. If - \"own\" is true, closing this object will close the underlying - descriptor. By default, an \"IOStream\" is closed when it is - garbage collected. + Tests whether a character is alphanumeric. "), -(E"I/O",E"Base",E"flush",E"flush(stream) +("Strings","Base","isalpha","isalpha(c::Char) - Commit all currently buffered writes to the given stream. + Tests whether a character is alphabetic. "), -(E"I/O",E"Base",E"close",E"close(stream) +("Strings","Base","isascii","isascii(c::Char) - Close an I/O stream. Performs a \"flush\" first. + Tests whether a character belongs to the ASCII character set. "), -(E"I/O",E"Base",E"write",E"write(stream, x) +("Strings","Base","isblank","isblank(c::Char) - Write the canonical binary representation of a value to the given - stream. + Tests whether a character is a tab or space. "), -(E"I/O",E"Base",E"read",E"read(stream, type) +("Strings","Base","iscntrl","iscntrl(c::Char) - Read a value of the given type from a stream, in canonical binary - representation. + Tests whether a character is a control character. "), -(E"I/O",E"Base",E"read",E"read(stream, type, dims) +("Strings","Base","isdigit","isdigit(c::Char) - Read a series of values of the given type from a stream, in - canonical binary representation. \"dims\" is either a tuple or a - series of integer arguments specifying the size of \"Array\" to - return. + Tests whether a character is a numeric digit (0-9). "), -(E"I/O",E"Base",E"position",E"position(s) +("Strings","Base","isgraph","isgraph(c::Char) - Get the current position of a stream. + Tests whether a character is printable, and not a space. "), -(E"I/O",E"Base",E"seek",E"seek(s, pos) +("Strings","Base","islower","islower(c::Char) - Seek a stream to the given position. + Tests whether a character is a lowercase letter. "), -(E"I/O",E"Base",E"seek_end",E"seek_end(s) +("Strings","Base","isprint","isprint(c::Char) - Seek a stream to the end. + Tests whether a character is printable, including space. "), -(E"I/O",E"Base",E"skip",E"skip(s, offset) +("Strings","Base","ispunct","ispunct(c::Char) - Seek a stream relative to the current position. + Tests whether a character is printable, and not a space or + alphanumeric. "), -(E"Text I/O",E"Base",E"show",E"show(x) +("Strings","Base","isspace","isspace(c::Char) + + Tests whether a character is any whitespace character. + +"), + +("Strings","Base","isupper","isupper(c::Char) + + Tests whether a character is an uppercase letter. + +"), + +("Strings","Base","isxdigit","isxdigit(c::Char) + + Tests whether a character is a valid hexadecimal digit. + +"), + +("I/O","Base","STDOUT","STDOUT + + Global variable referring to the standard out stream. + +"), + +("I/O","Base","STDERR","STDERR + + Global variable referring to the standard error stream. + +"), + +("I/O","Base","STDIN","STDIN + + Global variable referring to the standard input stream. + +"), + +("I/O","Base","OUTPUT_STREAM","OUTPUT_STREAM + + The default stream used for text output, e.g. in the \"print\" and + \"show\" functions. + +"), + +("I/O","Base","open","open(file_name[, read, write, create, truncate, append]) -> IOStream + + Open a file in a mode specified by five boolean arguments. The + default is to open files for reading only. Returns a stream for + accessing the file. + +"), + +("I/O","Base","open","open(file_name[, mode]) -> IOStream + + Alternate syntax for open, where a string-based mode specifier is + used instead of the five booleans. The values of \"mode\" + correspond to those from \"fopen(3)\" or Perl \"open\", and are + equivalent to setting the following boolean groups: + + +------+-----------------------------------+ + | r | read | + +------+-----------------------------------+ + | r+ | read, write | + +------+-----------------------------------+ + | w | write, create, truncate | + +------+-----------------------------------+ + | w+ | read, write, create, truncate | + +------+-----------------------------------+ + | a | write, create, append | + +------+-----------------------------------+ + | a+ | read, write, create, append | + +------+-----------------------------------+ + +"), + +("I/O","Base","open","open(f::function, args...) + + Apply the function \"f\" to the result of \"open(args...)\" and + close the resulting file descriptor upon completion. + + **Example**: \"open(readall, \"file.txt\")\" + +"), + +("I/O","Base","memio","memio([size[, finalize::Bool]]) -> IOStream + + Create an in-memory I/O stream, optionally specifying how much + initial space is needed. + +"), + +("I/O","Base","fdio","fdio([name::String], fd::Integer[, own::Bool]) -> IOStream + + Create an \"IOStream\" object from an integer file descriptor. If + \"own\" is true, closing this object will close the underlying + descriptor. By default, an \"IOStream\" is closed when it is + garbage collected. \"name\" allows you to associate the descriptor + with a named file. + +"), + +("I/O","Base","flush","flush(stream) + + Commit all currently buffered writes to the given stream. + +"), + +("I/O","Base","close","close(stream) + + Close an I/O stream. Performs a \"flush\" first. + +"), + +("I/O","Base","write","write(stream, x) + + Write the canonical binary representation of a value to the given + stream. + +"), + +("I/O","Base","read","read(stream, type) + + Read a value of the given type from a stream, in canonical binary + representation. + +"), + +("I/O","Base","read","read(stream, type, dims) + + Read a series of values of the given type from a stream, in + canonical binary representation. \"dims\" is either a tuple or a + series of integer arguments specifying the size of \"Array\" to + return. + +"), + +("I/O","Base","position","position(s) + + Get the current position of a stream. + +"), + +("I/O","Base","seek","seek(s, pos) + + Seek a stream to the given position. + +"), + +("I/O","Base","seek_end","seek_end(s) + + Seek a stream to the end. + +"), + +("I/O","Base","skip","skip(s, offset) + + Seek a stream relative to the current position. + +"), + +("I/O","Base","eof","eof(stream) + + Tests whether an I/O stream is at end-of-file. If the stream is not + yet exhausted, this function will block to wait for more data if + necessary, and then return \"false\". Therefore it is always safe + to read one byte after seeing \"eof\" return \"false\". + +"), + +("I/O","Base","ntoh","ntoh(x) + + Converts the endianness of a value from Network byte order (big- + endian) to that used by the Host. + +"), + +("I/O","Base","hton","hton(x) + + Converts the endianness of a value from that used by the Host to + Network byte order (big-endian). + +"), + +("I/O","Base","ltoh","ltoh(x) + + Converts the endianness of a value from Little-endian to that used + by the Host. + +"), + +("I/O","Base","htol","htol(x) + + Converts the endianness of a value from that used by the Host to + Little-endian. + +"), + +("Text I/O","Base","show","show(x) Write an informative text representation of a value to the current output stream. New types should overload \"show(io, x)\" where the @@ -1140,7 +1402,7 @@ collection[key...] = value "), -(E"Text I/O",E"Base",E"print",E"print(x) +("Text I/O","Base","print","print(x) Write (to the default output stream) a canonical (un-decorated) text representation of a value if there is one, otherwise call @@ -1148,57 +1410,71 @@ collection[key...] = value "), -(E"Text I/O",E"Base",E"println",E"println(x) +("Text I/O","Base","println","println(x) + + Print (using \"print()\") \"x\" followed by a newline + +"), + +("Text I/O","Base","@printf","@printf([io::IOStream], \"%Fmt\", args...) - Print (using \"print\") \"x\" followed by a newline + Print arg(s) using C \"printf()\" style format specification + string. Optionally, an IOStream may be passed as the first argument + to redirect output. "), -(E"Text I/O",E"Base",E"showall",E"showall(x) +("Text I/O","Base","@sprintf","@sprintf(\"%Fmt\", args...) + + Return \"@printf\" formatted output as string. + +"), + +("Text I/O","Base","showall","showall(x) Show x, printing all elements of arrays "), -(E"Text I/O",E"Base",E"dump",E"dump(x) +("Text I/O","Base","dump","dump(x) Write a thorough text representation of a value to the current output stream. "), -(E"Text I/O",E"Base",E"readall",E"readall(stream) +("Text I/O","Base","readall","readall(stream) Read the entire contents of an I/O stream as a string. "), -(E"Text I/O",E"Base",E"readline",E"readline(stream) +("Text I/O","Base","readline","readline(stream) Read a single line of text, including a trailing newline character (if one is reached before the end of the input). "), -(E"Text I/O",E"Base",E"readuntil",E"readuntil(stream, delim) +("Text I/O","Base","readuntil","readuntil(stream, delim) Read a string, up to and including the given delimiter byte. "), -(E"Text I/O",E"Base",E"readlines",E"readlines(stream) +("Text I/O","Base","readlines","readlines(stream) Read all lines as an array. "), -(E"Text I/O",E"Base",E"EachLine",E"EachLine(stream) +("Text I/O","Base","eachline","eachline(stream) Create an iterable object that will yield each line from a stream. "), -(E"Text I/O",E"Base",E"dlmread",E"dlmread(filename, delim::Char) +("Text I/O","Base","readdlm","readdlm(filename, delim::Char) Read a matrix from a text file where each line gives one row, with elements separated by the given delimeter. If all data is numeric, @@ -1207,7 +1483,7 @@ collection[key...] = value "), -(E"Text I/O",E"Base",E"dlmread",E"dlmread(filename, delim::Char, T::Type) +("Text I/O","Base","readdlm","readdlm(filename, delim::Char, T::Type) Read a matrix from a text file with a given element type. If \"T\" is a numeric type, the result is an array of that type, with any @@ -1217,26 +1493,26 @@ collection[key...] = value "), -(E"Text I/O",E"Base",E"dlmwrite",E"dlmwrite(filename, array, delim::Char) +("Text I/O","Base","writedlm","writedlm(filename, array, delim::Char) Write an array to a text file using the given delimeter (defaults to comma). "), -(E"Text I/O",E"Base",E"csvread",E"csvread(filename[, T::Type]) +("Text I/O","Base","readcsv","readcsv(filename[, T::Type]) - Equivalent to \"dlmread\" with \"delim\" set to comma. + Equivalent to \"readdlm\" with \"delim\" set to comma. "), -(E"Text I/O",E"Base",E"csvwrite",E"csvwrite(filename, array) +("Text I/O","Base","writecsv","writecsv(filename, array) - Equivalent to \"dlmwrite\" with \"delim\" set to comma. + Equivalent to \"writedlm\" with \"delim\" set to comma. "), -(E"Memory-mapped I/O",E"Base",E"mmap_array",E"mmap_array(type, dims, stream[, offset]) +("Memory-mapped I/O","Base","mmap_array","mmap_array(type, dims, stream[, offset]) Create an array whose values are linked to a file, using memory- mapping. This provides a convenient way of working with data too @@ -1252,14 +1528,14 @@ collection[key...] = value an offset (in bytes) if, for example, you want to skip over a header in the file. - Example: A = mmap_array(Int64, (25,30000), s) + **Example**: A = mmap_array(Int64, (25,30000), s) This would create a 25-by-30000 array of Int64s, linked to the file associated with stream s. "), -(E"Memory-mapped I/O",E"Base",E"msync",E"msync(array) +("Memory-mapped I/O","Base","msync","msync(array) Forces synchronization between the in-memory version of a memory- mapped array and the on-disk version. You may not need to call this @@ -1270,13 +1546,13 @@ collection[key...] = value "), -(E"Memory-mapped I/O",E"Base",E"mmap",E"mmap(len, prot, flags, fd, offset) +("Memory-mapped I/O","Base","mmap","mmap(len, prot, flags, fd, offset) Low-level interface to the mmap system call. See the man page. "), -(E"Memory-mapped I/O",E"Base",E"munmap",E"munmap(pointer, len) +("Memory-mapped I/O","Base","munmap","munmap(pointer, len) Low-level interface for unmapping memory (see the man page). With mmap_array you do not need to call this directly; the memory is @@ -1284,339 +1560,609 @@ collection[key...] = value "), -(E"Mathematical Functions",E"Base",E"-",E"-() +("Mathematical Functions","Base","-","-(x) + + Unary minus operator. + +"), + +("Mathematical Functions","Base","+","+(x, y) + + Binary addition operator. + +"), + +("Mathematical Functions","Base","-","-(x, y) - Unary minus + Binary subtraction operator. "), -(E"Mathematical Functions",E"",E"+ - * / \\ ^",E"+ - * / \\ ^ +("Mathematical Functions","Base","*","*(x, y) - The binary addition, subtraction, multiplication, left division, - right division, and exponentiation operators + Binary multiplication operator. "), -(E"Mathematical Functions",E"",E".* ./ .\\ .^",E".* ./ .\\ .^ +("Mathematical Functions","Base","/","/(x, y) - The element-wise binary addition, subtraction, multiplication, left - division, right division, and exponentiation operators + Binary left-division operator. "), -(E"Mathematical Functions",E"Base",E"div",E"div() +("Mathematical Functions","Base","\\","\\(x, y) - Integer truncating division + Binary right-division operator. "), -(E"Mathematical Functions",E"Base",E"fld",E"fld() +("Mathematical Functions","Base","^","^(x, y) - Integer floor division + Binary exponentiation operator. "), -(E"Mathematical Functions",E"Base",E"mod",E"mod() +("Mathematical Functions","Base",".+",".+(x, y) - Modulus after division + Element-wise binary addition operator. "), -(E"Mathematical Functions",E"",E"rem %",E"rem % +("Mathematical Functions","Base",".-",".-(x, y) + + Element-wise binary subtraction operator. + +"), + +("Mathematical Functions","Base",".*",".*(x, y) + + Element-wise binary multiplication operator. + +"), + +("Mathematical Functions","Base","./","./(x, y) + + Element-wise binary left division operator. + +"), + +("Mathematical Functions","Base",".\\",".\\(x, y) + + Element-wise binary right division operator. + +"), + +("Mathematical Functions","Base",".^",".^(x, y) + + Element-wise binary exponentiation operator. + +"), + +("Mathematical Functions","Base","div","div(a, b) + + Compute a/b, truncating to an integer + +"), + +("Mathematical Functions","Base","fld","fld(a, b) + + Largest integer less than or equal to a/b + +"), + +("Mathematical Functions","Base","mod","mod(x, m) + + Modulus after division, returning in the range [0,m) + +"), + +("Mathematical Functions","Base","rem","rem(x, m) Remainder after division "), -(E"Mathematical Functions",E"Base",E"//",E"//() +("Mathematical Functions","Base","%","%(x, m) + + Remainder after division. The operator form of \"rem\". + +"), + +("Mathematical Functions","Base","mod1","mod1(x, m) + + Modulus after division, returning in the range (0,m] + +"), + +("Mathematical Functions","Base","//","//(num, den) Rational division "), -(E"Mathematical Functions",E"",E"<< >>",E"<< >> +("Mathematical Functions","Base","num","num(x) + + Numerator of the rational representation of \"x\" + +"), + +("Mathematical Functions","Base","den","den(x) + + Denominator of the rational representation of \"x\" + +"), + +("Mathematical Functions","Base","<<","<<(x, n) + + Left shift operator. + +"), + +("Mathematical Functions","Base",">>",">>(x, n) + + Right shift operator. + +"), + +("Mathematical Functions","Base",">>>",">>>(x, n) + + Unsigned right shift operator. + +"), + +("Mathematical Functions","Base",":",":(start[, step], stop) + + Range operator. \"a:b\" constructs a range from \"a\" to \"b\" with + a step size of 1, and \"a:s:b\" is similar but uses a step size of + \"s\". These syntaxes call the function \"colon\". The colon is + also used in indexing to select whole dimensions. + +"), + +("Mathematical Functions","Base","colon","colon(start[, step], stop) + + Called by \":\" syntax for constructing ranges. + +"), + +("Mathematical Functions","Base","==","==(x, y) + + Equality comparison operator. + +"), + +("Mathematical Functions","Base","!=","!=(x, y) + + Not-equals comparison operator. + +"), + +("Mathematical Functions","Base","<","<(x, y) + + Less-than comparison operator. + +"), + +("Mathematical Functions","Base","<=","<=(x, y) + + Less-than-or-equals comparison operator. + +"), + +("Mathematical Functions","Base",">",">(x, y) + + Greater-than comparison operator. + +"), + +("Mathematical Functions","Base",">=",">=(x, y) + + Greater-than-or-equals comparison operator. + +"), + +("Mathematical Functions","Base",".==",".==(x, y) + + Element-wise equality comparison operator. + +"), + +("Mathematical Functions","Base",".!=",".!=(x, y) + + Element-wise not-equals comparison operator. + +"), + +("Mathematical Functions","Base",".<",".<(x, y) + + Element-wise less-than comparison operator. + +"), + +("Mathematical Functions","Base",".<=",".<=(x, y) + + Element-wise less-than-or-equals comparison operator. + +"), + +("Mathematical Functions","Base",".>",".>(x, y) + + Element-wise greater-than comparison operator. + +"), + +("Mathematical Functions","Base",".>=",".>=(x, y) - Left and right shift operators + Element-wise greater-than-or-equals comparison operator. "), -(E"Mathematical Functions",E"",E"== != < <= > >=",E"== != < <= > >= +("Mathematical Functions","Base","cmp","cmp(x, y) - Comparison operators to test equals, not equals, less than, less - than or equals, greater than, and greater than or equals + Return -1, 0, or 1 depending on whether \"xy\", respectively "), -(E"Mathematical Functions",E"Base",E"!",E"!() +("Mathematical Functions","Base","!","!(x) Boolean not "), -(E"Mathematical Functions",E"Base",E"~",E"~() +("Mathematical Functions","Base","~","~(x) - Boolean or bitwise not + Bitwise not "), -(E"Mathematical Functions",E"Base",E"&",E"&() +("Mathematical Functions","Base","&","&(x, y) Bitwise and "), -(E"Mathematical Functions",E"Base",E"|",E"|() +("Mathematical Functions","Base","|","|(x, y) Bitwise or "), -(E"Mathematical Functions",E"Base",E"$",E"$() +("Mathematical Functions","Base","\$","\$(x, y) Bitwise exclusive or "), -(E"Mathematical Functions",E"Base",E"sin",E"sin(x) +("Mathematical Functions","Base","sin","sin(x) - Compute sine of \"x\" + Compute sine of \"x\", where \"x\" is in radians "), -(E"Mathematical Functions",E"Base",E"cos",E"cos(x) +("Mathematical Functions","Base","cos","cos(x) - Compute cosine of \"x\" + Compute cosine of \"x\", where \"x\" is in radians "), -(E"Mathematical Functions",E"Base",E"tan",E"tan(x) +("Mathematical Functions","Base","tan","tan(x) - Compute tangent of \"x\" + Compute tangent of \"x\", where \"x\" is in radians "), -(E"Mathematical Functions",E"Base",E"sinh",E"sinh(x) +("Mathematical Functions","Base","sind","sind(x) - Compute hyperbolic sine of \"x\" specified in radians + Compute sine of \"x\", where \"x\" is in degrees "), -(E"Mathematical Functions",E"Base",E"cosh",E"cosh(x) +("Mathematical Functions","Base","cosd","cosd(x) - Compute hyperbolic cosine of \"x\" specified in radians + Compute cosine of \"x\", where \"x\" is in degrees "), -(E"Mathematical Functions",E"Base",E"tanh",E"tanh(x) +("Mathematical Functions","Base","tand","tand(x) - Compute hyperbolic tangent of \"x\" specified in radians + Compute tangent of \"x\", where \"x\" is in degrees "), -(E"Mathematical Functions",E"Base",E"asin",E"asin(x) +("Mathematical Functions","Base","sinh","sinh(x) - Compute the inverse sine of \"x\" specified in radians + Compute hyperbolic sine of \"x\" "), -(E"Mathematical Functions",E"Base",E"acos",E"acos(x) +("Mathematical Functions","Base","cosh","cosh(x) - Compute the inverse cosine of \"x\" specified in radians + Compute hyperbolic cosine of \"x\" "), -(E"Mathematical Functions",E"Base",E"atan",E"atan(x) +("Mathematical Functions","Base","tanh","tanh(x) - Compute the inverse tangent of \"x\" specified in radians + Compute hyperbolic tangent of \"x\" "), -(E"Mathematical Functions",E"Base",E"atan2",E"atan2(x, y) +("Mathematical Functions","Base","asin","asin(x) + + Compute the inverse sine of \"x\", where the output is in radians + +"), + +("Mathematical Functions","Base","acos","acos(x) + + Compute the inverse cosine of \"x\", where the output is in radians + +"), + +("Mathematical Functions","Base","atan","atan(x) + + Compute the inverse tangent of \"x\", where the output is in + radians + +"), + +("Mathematical Functions","Base","atan2","atan2(y, x) Compute the inverse tangent of \"y/x\", using the signs of both \"x\" and \"y\" to determine the quadrant of the return value. "), -(E"Mathematical Functions",E"Base",E"sec",E"sec(x) +("Mathematical Functions","Base","asind","asind(x) - Compute the secant of \"x\" specified in radians + Compute the inverse sine of \"x\", where the output is in degrees "), -(E"Mathematical Functions",E"Base",E"csc",E"csc(x) +("Mathematical Functions","Base","acosd","acosd(x) - Compute the cosecant of \"x\" specified in radians + Compute the inverse cosine of \"x\", where the output is in degrees "), -(E"Mathematical Functions",E"Base",E"cot",E"cot(x) +("Mathematical Functions","Base","atand","atand(x) - Compute the cotangent of \"x\" specified in radians + Compute the inverse tangent of \"x\", where the output is in + degrees "), -(E"Mathematical Functions",E"Base",E"asec",E"asec(x) +("Mathematical Functions","Base","sec","sec(x) - Compute the inverse secant of \"x\" specified in radians + Compute the secant of \"x\", where \"x\" is in radians "), -(E"Mathematical Functions",E"Base",E"acsc",E"acsc(x) +("Mathematical Functions","Base","csc","csc(x) - Compute the inverse cosecant of \"x\" specified in radians + Compute the cosecant of \"x\", where \"x\" is in radians "), -(E"Mathematical Functions",E"Base",E"acot",E"acot(x) +("Mathematical Functions","Base","cot","cot(x) - Compute the inverse cotangent of \"x\" specified in radians + Compute the cotangent of \"x\", where \"x\" is in radians "), -(E"Mathematical Functions",E"Base",E"sech",E"sech(x) +("Mathematical Functions","Base","secd","secd(x) - Compute the hyperbolic secant of \"x\" specified in radians + Compute the secant of \"x\", where \"x\" is in degrees "), -(E"Mathematical Functions",E"Base",E"csch",E"csch(x) +("Mathematical Functions","Base","cscd","cscd(x) - Compute the hyperbolic cosecant of \"x\" specified in radians + Compute the cosecant of \"x\", where \"x\" is in degrees "), -(E"Mathematical Functions",E"Base",E"coth",E"coth(x) +("Mathematical Functions","Base","cotd","cotd(x) - Compute the hyperbolic cotangent of \"x\" specified in radians + Compute the cotangent of \"x\", where \"x\" is in degrees "), -(E"Mathematical Functions",E"Base",E"asinh",E"asinh(x) +("Mathematical Functions","Base","asec","asec(x) - Compute the inverse hyperbolic sine of \"x\" specified in radians + Compute the inverse secant of \"x\", where the output is in radians "), -(E"Mathematical Functions",E"Base",E"acosh",E"acosh(x) +("Mathematical Functions","Base","acsc","acsc(x) - Compute the inverse hyperbolic cosine of \"x\" specified in radians + Compute the inverse cosecant of \"x\", where the output is in + radians "), -(E"Mathematical Functions",E"Base",E"atanh",E"atanh(x) +("Mathematical Functions","Base","acot","acot(x) - Compute the inverse hyperbolic cotangent of \"x\" specified in + Compute the inverse cotangent of \"x\", where the output is in radians "), -(E"Mathematical Functions",E"Base",E"asech",E"asech(x) +("Mathematical Functions","Base","asecd","asecd(x) - Compute the inverse hyperbolic secant of \"x\" specified in radians + Compute the inverse secant of \"x\", where the output is in degrees "), -(E"Mathematical Functions",E"Base",E"acsch",E"acsch(x) +("Mathematical Functions","Base","acscd","acscd(x) - Compute the inverse hyperbolic cosecant of \"x\" specified in - radians + Compute the inverse cosecant of \"x\", where the output is in + degrees "), -(E"Mathematical Functions",E"Base",E"acoth",E"acoth(x) +("Mathematical Functions","Base","acotd","acotd(x) - Compute the inverse hyperbolic cotangent of \"x\" specified in - radians + Compute the inverse cotangent of \"x\", where the output is in + degrees "), -(E"Mathematical Functions",E"Base",E"sinc",E"sinc(x) +("Mathematical Functions","Base","sech","sech(x) - Compute sin(\\pi x) / x + Compute the hyperbolic secant of \"x\" "), -(E"Mathematical Functions",E"Base",E"cosc",E"cosc(x) +("Mathematical Functions","Base","csch","csch(x) - Compute cos(\\pi x) / x + Compute the hyperbolic cosecant of \"x\" "), -(E"Mathematical Functions",E"Base",E"hypot",E"hypot(x, y) +("Mathematical Functions","Base","coth","coth(x) - Compute the \\sqrt{(x^2+y^2)} without undue overflow or underflow + Compute the hyperbolic cotangent of \"x\" "), -(E"Mathematical Functions",E"Base",E"log",E"log(x) +("Mathematical Functions","Base","asinh","asinh(x) - Compute the natural logarithm of \"x\" + Compute the inverse hyperbolic sine of \"x\" "), -(E"Mathematical Functions",E"Base",E"log2",E"log2(x) +("Mathematical Functions","Base","acosh","acosh(x) - Compute the natural logarithm of \"x\" to base 2 + Compute the inverse hyperbolic cosine of \"x\" "), -(E"Mathematical Functions",E"Base",E"log10",E"log10(x) +("Mathematical Functions","Base","atanh","atanh(x) - Compute the natural logarithm of \"x\" to base 10 + Compute the inverse hyperbolic cotangent of \"x\" "), -(E"Mathematical Functions",E"Base",E"log1p",E"log1p(x) +("Mathematical Functions","Base","asech","asech(x) - Accurate natural logarithm of \"1+x\" + Compute the inverse hyperbolic secant of \"x\" + +"), + +("Mathematical Functions","Base","acsch","acsch(x) + + Compute the inverse hyperbolic cosecant of \"x\" + +"), + +("Mathematical Functions","Base","acoth","acoth(x) + + Compute the inverse hyperbolic cotangent of \"x\" + +"), + +("Mathematical Functions","Base","sinc","sinc(x) + + Compute \\sin(\\pi x) / (\\pi x) if x \\neq 0, and 1 if x = 0. + +"), + +("Mathematical Functions","Base","cosc","cosc(x) + + Compute \\cos(\\pi x) / x - \\sin(\\pi x) / (\\pi x^2) if x \\neq + 0, and 0 if x = 0. This is the derivative of \"sinc(x)\". + +"), + +("Mathematical Functions","Base","degrees2radians","degrees2radians(x) + + Convert \"x\" from degrees to radians + +"), + +("Mathematical Functions","Base","radians2degrees","radians2degrees(x) + + Convert \"x\" from radians to degrees + +"), + +("Mathematical Functions","Base","hypot","hypot(x, y) + + Compute the \\sqrt{x^2+y^2} without undue overflow or underflow + +"), + +("Mathematical Functions","Base","log","log(x) + + Compute the natural logarithm of \"x\" + +"), + +("Mathematical Functions","Base","log2","log2(x) + + Compute the natural logarithm of \"x\" to base 2 "), -(E"Mathematical Functions",E"Base",E"logb",E"logb(x) +("Mathematical Functions","Base","log10","log10(x) - Return the exponent of x, represented as a floating-point number + Compute the natural logarithm of \"x\" to base 10 "), -(E"Mathematical Functions",E"Base",E"ilogb",E"ilogb(x) +("Mathematical Functions","Base","log1p","log1p(x) - Return the exponent of x, represented as a signed integer value + Accurate natural logarithm of \"1+x\" "), -(E"Mathematical Functions",E"Base",E"frexp",E"frexp(val, exp) +("Mathematical Functions","Base","frexp","frexp(val, exp) Return a number \"x\" such that it has a magnitude in the interval \"[1/2, 1)\" or 0, and val = x \\times 2^{exp}. "), -(E"Mathematical Functions",E"Base",E"exp",E"exp(x) +("Mathematical Functions","Base","exp","exp(x) Compute e^x "), -(E"Mathematical Functions",E"Base",E"exp2",E"exp2(x) +("Mathematical Functions","Base","exp2","exp2(x) Compute 2^x "), -(E"Mathematical Functions",E"Base",E"ldexp",E"ldexp(x, n) +("Mathematical Functions","Base","ldexp","ldexp(x, n) Compute x \\times 2^n "), -(E"Mathematical Functions",E"Base",E"expm1",E"expm1(x) +("Mathematical Functions","Base","modf","modf(x) + + Return a tuple (fpart,ipart) of the fractional and integral parts + of a number. Both parts have the same sign as the argument. + +"), + +("Mathematical Functions","Base","expm1","expm1(x) Accurately compute e^x-1 "), -(E"Mathematical Functions",E"Base",E"round",E"round(x[, digits[, base]]) -> FloatingPoint +("Mathematical Functions","Base","square","square(x) + + Compute x^2 + +"), + +("Mathematical Functions","Base","round","round(x[, digits[, base]]) -> FloatingPoint \"round(x)\" returns the nearest integer to \"x\". \"round(x, digits)\" rounds to the specified number of digits after the @@ -1626,52 +2172,52 @@ collection[key...] = value "), -(E"Mathematical Functions",E"Base",E"ceil",E"ceil(x[, digits[, base]]) -> FloatingPoint +("Mathematical Functions","Base","ceil","ceil(x[, digits[, base]]) -> FloatingPoint Returns the nearest integer not less than \"x\". \"digits\" and \"base\" work as above. "), -(E"Mathematical Functions",E"Base",E"floor",E"floor(x[, digits[, base]]) -> FloatingPoint +("Mathematical Functions","Base","floor","floor(x[, digits[, base]]) -> FloatingPoint Returns the nearest integer not greater than \"x\". \"digits\" and \"base\" work as above. "), -(E"Mathematical Functions",E"Base",E"trunc",E"trunc(x[, digits[, base]]) -> FloatingPoint +("Mathematical Functions","Base","trunc","trunc(x[, digits[, base]]) -> FloatingPoint Returns the nearest integer not greater in magnitude than \"x\". \"digits\" and \"base\" work as above. "), -(E"Mathematical Functions",E"Base",E"iround",E"iround(x) -> Integer +("Mathematical Functions","Base","iround","iround(x) -> Integer Returns the nearest integer to \"x\". "), -(E"Mathematical Functions",E"Base",E"iceil",E"iceil(x) -> Integer +("Mathematical Functions","Base","iceil","iceil(x) -> Integer Returns the nearest integer not less than \"x\". "), -(E"Mathematical Functions",E"Base",E"ifloor",E"ifloor(x) -> Integer +("Mathematical Functions","Base","ifloor","ifloor(x) -> Integer Returns the nearest integer not greater than \"x\". "), -(E"Mathematical Functions",E"Base",E"itrunc",E"itrunc(x) -> Integer +("Mathematical Functions","Base","itrunc","itrunc(x) -> Integer Returns the nearest integer not greater in magnitude than \"x\". "), -(E"Mathematical Functions",E"Base",E"signif",E"signif(x, digits[, base]) -> FloatingPoint +("Mathematical Functions","Base","signif","signif(x, digits[, base]) -> FloatingPoint Rounds (in the sense of \"round\") \"x\" so that there are \"digits\" significant digits, under a base \"base\" @@ -1680,3796 +2226,3627 @@ collection[key...] = value "), -(E"Mathematical Functions",E"Base",E"min",E"min(x, y) +("Mathematical Functions","Base","min","min(x, y) Return the minimum of \"x\" and \"y\" "), -(E"Mathematical Functions",E"Base",E"max",E"max(x, y) +("Mathematical Functions","Base","max","max(x, y) Return the maximum of \"x\" and \"y\" "), -(E"Mathematical Functions",E"Base",E"clamp",E"clamp(x, lo, hi) +("Mathematical Functions","Base","clamp","clamp(x, lo, hi) Return x if \"lo <= x <= y\". If \"x < lo\", return \"lo\". If \"x > hi\", return \"hi\". "), -(E"Mathematical Functions",E"Base",E"abs",E"abs(x) +("Mathematical Functions","Base","abs","abs(x) Absolute value of \"x\" "), -(E"Mathematical Functions",E"Base",E"abs2",E"abs2(x) +("Mathematical Functions","Base","abs2","abs2(x) Squared absolute value of \"x\" "), -(E"Mathematical Functions",E"Base",E"copysign",E"copysign(x, y) +("Mathematical Functions","Base","copysign","copysign(x, y) Return \"x\" such that it has the same sign as \"y\" "), -(E"Mathematical Functions",E"Base",E"sign",E"sign(x) +("Mathematical Functions","Base","sign","sign(x) Return \"+1\" if \"x\" is positive, \"0\" if \"x == 0\", and \"-1\" if \"x\" is negative. "), -(E"Mathematical Functions",E"Base",E"signbit",E"signbit(x) +("Mathematical Functions","Base","signbit","signbit(x) - Returns non-zero if the value of the sign of \"x\" is negative, + Returns \"1\" if the value of the sign of \"x\" is negative, otherwise \"0\". "), -(E"Mathematical Functions",E"Base",E"sqrt",E"sqrt(x) - - Return \\sqrt{x} - -"), - -(E"Mathematical Functions",E"Base",E"cbrt",E"cbrt(x) - - Return x^{1/3} - -"), - -(E"Mathematical Functions",E"Base",E"erf",E"erf(x) - - Compute the error function of \"x\" - -"), - -(E"Mathematical Functions",E"Base",E"erfc",E"erfc(x) - - Compute the complementary error function of \"x\" - -"), - -(E"Mathematical Functions",E"Base",E"real",E"real(z) - - Return the real part of the complex number \"z\" - -"), - -(E"Mathematical Functions",E"Base",E"imag",E"imag(z) - - Return the imaginary part of the complex number \"z\" - -"), - -(E"Mathematical Functions",E"Base",E"conj",E"conj(z) +("Mathematical Functions","Base","flipsign","flipsign(x, y) - Compute the complex conjugate of a complex number \"z\" + Return \"x\" with its sign flipped if \"y\" is negative. For + example \"abs(x) = flipsign(x,x)\". "), -(E"Mathematical Functions",E"Base",E"angle",E"angle(z) +("Mathematical Functions","Base","sqrt","sqrt(x) - Compute the phase angle of a complex number \"z\" + Return \\sqrt{x} "), -(E"Mathematical Functions",E"Base",E"cis",E"cis(z) +("Mathematical Functions","Base","cbrt","cbrt(x) - Return \"cos(z) + i*sin(z)\" if z is real. Return \"(cos(real(z)) + - i*sin(real(z)))/exp(imag(z))\" if \"z\" is complex + Return x^{1/3} "), -(E"Mathematical Functions",E"Base",E"binomial",E"binomial(n, k) +("Mathematical Functions","Base","erf","erf(x) - Number of ways to choose \"k\" out of \"n\" items + Compute the error function of \"x\", defined by + \\frac{2}{\\sqrt{\\pi}} \\int_0^x e^{-t^2} dt for arbitrary complex + \"x\". "), -(E"Mathematical Functions",E"Base",E"factorial",E"factorial(n) +("Mathematical Functions","Base","erfc","erfc(x) - Factorial of n + Compute the complementary error function of \"x\", defined by 1 - + \\operatorname{erf}(x). "), -(E"Mathematical Functions",E"Base",E"factorial",E"factorial(n, k) +("Mathematical Functions","Base","erfcx","erfcx(x) - Compute \"factorial(n)/factorial(k)\" + Compute the scaled complementary error function of \"x\", defined + by e^{x^2} \\operatorname{erfc}(x). Note also that + \\operatorname{erfcx}(-ix) computes the Faddeeva function w(x). "), -(E"Mathematical Functions",E"Base",E"gcd",E"gcd(x, y) +("Mathematical Functions","Base","erfi","erfi(x) - Greatest common divisor + Compute the imaginary error function of \"x\", defined by -i + \\operatorname{erf}(ix). "), -(E"Mathematical Functions",E"Base",E"lcm",E"lcm(x, y) +("Mathematical Functions","Base","dawson","dawson(x) - Least common multiple + Compute the Dawson function (scaled imaginary error function) of + \"x\", defined by \\frac{\\sqrt{\\pi}}{2} e^{-x^2} + \\operatorname{erfi}(x). "), -(E"Mathematical Functions",E"Base",E"nextpow2",E"nextpow2(n) +("Mathematical Functions","Base","real","real(z) - Next power of two not less than \"n\" + Return the real part of the complex number \"z\" "), -(E"Mathematical Functions",E"Base",E"nextpow",E"nextpow(a, n) +("Mathematical Functions","Base","imag","imag(z) - Next power of \"a\" not less than \"n\" + Return the imaginary part of the complex number \"z\" "), -(E"Mathematical Functions",E"Base",E"prevpow",E"prevpow(a, n) +("Mathematical Functions","Base","reim","reim(z) - Previous power of \"a\" not greater than \"n\" + Return both the real and imaginary parts of the complex number + \"z\" "), -(E"Mathematical Functions",E"Base",E"nextprod",E"nextprod([a, b, c], n) +("Mathematical Functions","Base","conj","conj(z) - Next integer not less than \"n\" that can be written \"a^i1 * b^i2 - * c^i3\" for integers \"i1\", \"i2\", \"i3\". + Compute the complex conjugate of a complex number \"z\" "), -(E"Mathematical Functions",E"Base",E"prevprod",E"prevprod([a, b, c], n) +("Mathematical Functions","Base","angle","angle(z) - Previous integer not greater than \"n\" that can be written \"a^i1 - * b^i2 * c^i3\" for integers \"i1\", \"i2\", \"i3\". + Compute the phase angle of a complex number \"z\" "), -(E"Mathematical Functions",E"Base",E"powermod",E"powermod(x, p, m) - - Compute \"mod(x^p, m)\" - -"), +("Mathematical Functions","Base","cis","cis(z) -(E"Mathematical Functions",E"Base",E"gamma",E"gamma(x) + Return \"cos(z) + i*sin(z)\" if z is real. Return \"(cos(real(z)) + + i*sin(real(z)))/exp(imag(z))\" if \"z\" is complex "), -(E"Mathematical Functions",E"Base",E"lgamma",E"lgamma(x) +("Mathematical Functions","Base","binomial","binomial(n, k) -"), - -(E"Mathematical Functions",E"Base",E"lfact",E"lfact(x) + Number of ways to choose \"k\" out of \"n\" items "), -(E"Mathematical Functions",E"Base",E"airyai",E"airy(x) -airyai(x) +("Mathematical Functions","Base","factorial","factorial(n) - Airy function \\operatorname{Ai}(x). + Factorial of n "), -(E"Mathematical Functions",E"Base",E"airyaiprime",E"airyprime(x) -airyaiprime(x) +("Mathematical Functions","Base","factorial","factorial(n, k) - Airy function derivative \\operatorname{Ai}'(x). + Compute \"factorial(n)/factorial(k)\" "), -(E"Mathematical Functions",E"Base",E"airybi",E"airybi(x) - - Airy function \\operatorname{Bi}(x). - -"), +("Mathematical Functions","Base","factor","factor(n) -(E"Mathematical Functions",E"Base",E"airybiprime",E"airybiprime(x) + Compute the prime factorization of an integer \"n\". Returns a + dictionary. The keys of the dictionary correspond to the factors, + and hence are of the same type as \"n\". The value associated with + each key indicates the number of times the factor appears in the + factorization. - Airy function derivative \\operatorname{Bi}'(x). + **Example**: 100=2*2*5*5; then, \"factor(100) -> [5=>2,2=>2]\" "), -(E"Mathematical Functions",E"Base",E"besselj0",E"besselj0(x) +("Mathematical Functions","Base","gcd","gcd(x, y) - Bessel function of the first kind of order 0, J_0(x). + Greatest common divisor "), -(E"Mathematical Functions",E"Base",E"besselj1",E"besselj1(x) +("Mathematical Functions","Base","lcm","lcm(x, y) - Bessel function of the first kind of order 1, J_1(x). + Least common multiple "), -(E"Mathematical Functions",E"Base",E"besselj",E"besselj(nu, x) +("Mathematical Functions","Base","gcdx","gcdx(x, y) - Bessel function of the first kind of order \"nu\", J_\\nu(x). + Greatest common divisor, also returning integer coefficients \"u\" + and \"v\" that solve \"ux+vy == gcd(x,y)\" "), -(E"Mathematical Functions",E"Base",E"bessely0",E"bessely0(x) +("Mathematical Functions","Base","ispow2","ispow2(n) - Bessel function of the second kind of order 0, Y_0(x). + Test whether \"n\" is a power of two "), -(E"Mathematical Functions",E"Base",E"bessely1",E"bessely1(x) +("Mathematical Functions","Base","nextpow2","nextpow2(n) - Bessel function of the second kind of order 1, Y_1(x). + Next power of two not less than \"n\" "), -(E"Mathematical Functions",E"Base",E"bessely",E"bessely(nu, x) +("Mathematical Functions","Base","prevpow2","prevpow2(n) - Bessel function of the second kind of order \"nu\", Y_\\nu(x). + Previous power of two not greater than \"n\" "), -(E"Mathematical Functions",E"Base",E"hankelh1",E"hankelh1(nu, x) +("Mathematical Functions","Base","nextpow","nextpow(a, n) - Bessel function of the third kind of order \"nu\", H^{(1)}_\\nu(x). + Next power of \"a\" not less than \"n\" "), -(E"Mathematical Functions",E"Base",E"hankelh2",E"hankelh2(nu, x) +("Mathematical Functions","Base","prevpow","prevpow(a, n) - Bessel function of the third kind of order \"nu\", H^{(2)}_\\nu(x). + Previous power of \"a\" not greater than \"n\" "), -(E"Mathematical Functions",E"Base",E"besseli",E"besseli(nu, x) +("Mathematical Functions","Base","nextprod","nextprod([a, b, c], n) - Modified Bessel function of the first kind of order \"nu\", - I_\\nu(x). + Next integer not less than \"n\" that can be written \"a^i1 * b^i2 + * c^i3\" for integers \"i1\", \"i2\", \"i3\". "), -(E"Mathematical Functions",E"Base",E"besselk",E"besselk(nu, x) +("Mathematical Functions","Base","prevprod","prevprod([a, b, c], n) - Modified Bessel function of the second kind of order \"nu\", - K_\\nu(x). + Previous integer not greater than \"n\" that can be written \"a^i1 + * b^i2 * c^i3\" for integers \"i1\", \"i2\", \"i3\". "), -(E"Mathematical Functions",E"Base",E"beta",E"beta(x, y) +("Mathematical Functions","Base","invmod","invmod(x, m) - Euler integral of the first kind \\operatorname{B}(x,y) = - \\Gamma(x)\\Gamma(y)/\\Gamma(x+y). + Inverse of \"x\", modulo \"m\" "), -(E"Mathematical Functions",E"Base",E"lbeta",E"lbeta(x, y) +("Mathematical Functions","Base","powermod","powermod(x, p, m) - Natural logarithm of the beta function - \\log(\\operatorname{B}(x,y)). + Compute \"mod(x^p, m)\" "), -(E"Mathematical Functions",E"Base",E"eta",E"eta(x) +("Mathematical Functions","Base","gamma","gamma(x) - Dirichlet eta function \\eta(s) = - \\sum^\\infty_{n=1}(-)^{n-1}/n^{s}. + Compute the gamma function of \"x\" "), -(E"Mathematical Functions",E"Base",E"zeta",E"zeta(x) +("Mathematical Functions","Base","lgamma","lgamma(x) - Riemann zeta function \\zeta(s). + Compute the logarithm of \"gamma(x)\" "), -(E"Data Formats",E"Base",E"bin",E"bin(n[, pad]) +("Mathematical Functions","Base","lfact","lfact(x) - Convert an integer to a binary string, optionally specifying a - number of digits to pad to. + Compute the logarithmic factorial of \"x\" "), -(E"Data Formats",E"Base",E"hex",E"hex(n[, pad]) +("Mathematical Functions","Base","digamma","digamma(x) - Convert an integer to a hexadecimal string, optionally specifying a - number of digits to pad to. + Compute the digamma function of \"x\" (the logarithmic derivative + of \"gamma(x)\") "), -(E"Data Formats",E"Base",E"dec",E"dec(n[, pad]) +("Mathematical Functions","Base","airy","airy(k, x) - Convert an integer to a decimal string, optionally specifying a - number of digits to pad to. + kth derivative of the Airy function \\operatorname{Ai}(x). "), -(E"Data Formats",E"Base",E"oct",E"oct(n[, pad]) +("Mathematical Functions","Base","airyai","airyai(x) - Convert an integer to an octal string, optionally specifying a - number of digits to pad to. + Airy function \\operatorname{Ai}(x). "), -(E"Data Formats",E"Base",E"base",E"base(b, n[, pad]) +("Mathematical Functions","Base","airyprime","airyprime(x) - Convert an integer to a string in the given base, optionally - specifying a number of digits to pad to. + Airy function derivative \\operatorname{Ai}'(x). "), -(E"Data Formats",E"Base",E"parse_int",E"parse_int(type, str, base) +("Mathematical Functions","Base","airyaiprime","airyaiprime(x) - Parse a string as an integer in the given base, yielding a number - of the specified type. + Airy function derivative \\operatorname{Ai}'(x). "), -(E"Data Formats",E"Base",E"bool",E"bool(x) +("Mathematical Functions","Base","airybi","airybi(x) - Convert a number or numeric array to boolean + Airy function \\operatorname{Bi}(x). "), -(E"Data Formats",E"Base",E"int8",E"int8(x) +("Mathematical Functions","Base","airybiprime","airybiprime(x) - Convert a number or array to \"Int8\" data type + Airy function derivative \\operatorname{Bi}'(x). "), -(E"Data Formats",E"Base",E"int16",E"int16(x) +("Mathematical Functions","Base","besselj0","besselj0(x) - Convert a number or array to \"Int16\" data type + Bessel function of the first kind of order 0, J_0(x). "), -(E"Data Formats",E"Base",E"int32",E"int32(x) +("Mathematical Functions","Base","besselj1","besselj1(x) - Convert a number or array to \"Int32\" data type + Bessel function of the first kind of order 1, J_1(x). "), -(E"Data Formats",E"Base",E"int64",E"int64(x) +("Mathematical Functions","Base","besselj","besselj(nu, x) - Convert a number or array to \"Int64\" data type + Bessel function of the first kind of order \"nu\", J_\\nu(x). "), -(E"Data Formats",E"Base",E"uint8",E"uint8(x) +("Mathematical Functions","Base","bessely0","bessely0(x) - Convert a number or array to \"Uint8\" data type + Bessel function of the second kind of order 0, Y_0(x). "), -(E"Data Formats",E"Base",E"uint16",E"uint16(x) +("Mathematical Functions","Base","bessely1","bessely1(x) - Convert a number or array to \"Uint16\" data type + Bessel function of the second kind of order 1, Y_1(x). "), -(E"Data Formats",E"Base",E"uint32",E"uint32(x) +("Mathematical Functions","Base","bessely","bessely(nu, x) - Convert a number or array to \"Uint32\" data type + Bessel function of the second kind of order \"nu\", Y_\\nu(x). "), -(E"Data Formats",E"Base",E"uint64",E"uint64(x) +("Mathematical Functions","Base","hankelh1","hankelh1(nu, x) - Convert a number or array to \"Uint64\" data type + Bessel function of the third kind of order \"nu\", H^{(1)}_\\nu(x). "), -(E"Data Formats",E"Base",E"float32",E"float32(x) +("Mathematical Functions","Base","hankelh2","hankelh2(nu, x) - Convert a number or array to \"Float32\" data type + Bessel function of the third kind of order \"nu\", H^{(2)}_\\nu(x). "), -(E"Data Formats",E"Base",E"float64",E"float64(x) +("Mathematical Functions","Base","besseli","besseli(nu, x) - Convert a number or array to \"Float64\" data type + Modified Bessel function of the first kind of order \"nu\", + I_\\nu(x). "), -(E"Data Formats",E"Base",E"char",E"char(x) +("Mathematical Functions","Base","besselk","besselk(nu, x) - Convert a number or array to \"Char\" data type + Modified Bessel function of the second kind of order \"nu\", + K_\\nu(x). "), -(E"Data Formats",E"Base",E"safe_char",E"safe_char(x) +("Mathematical Functions","Base","beta","beta(x, y) - Convert to \"Char\", checking for invalid code points + Euler integral of the first kind \\operatorname{B}(x,y) = + \\Gamma(x)\\Gamma(y)/\\Gamma(x+y). "), -(E"Data Formats",E"Base",E"complex",E"complex(r, i) +("Mathematical Functions","Base","lbeta","lbeta(x, y) - Convert real numbers or arrays to complex + Natural logarithm of the beta function + \\log(\\operatorname{B}(x,y)). "), -(E"Data Formats",E"Base",E"iscomplex",E"iscomplex(x) +("Mathematical Functions","Base","eta","eta(x) - Test whether a number or array is of a complex type + Dirichlet eta function \\eta(s) = + \\sum^\\infty_{n=1}(-)^{n-1}/n^{s}. "), -(E"Data Formats",E"Base",E"isreal",E"isreal(x) +("Mathematical Functions","Base","zeta","zeta(x) - Test whether a number or array is of a real type + Riemann zeta function \\zeta(s). "), -(E"Data Formats",E"Base",E"bswap",E"bswap(n) +("Mathematical Functions","Base","bitmix","bitmix(x, y) - Byte-swap an integer + Hash two integers into a single integer. Useful for constructing + hash functions. "), -(E"Data Formats",E"Base",E"num2hex",E"num2hex(f) +("Mathematical Functions","Base","ndigits","ndigits(n, b) - Get a hexadecimal string of the binary representation of a floating - point number + Compute the number of digits in number \"n\" written in base \"b\". "), -(E"Data Formats",E"Base",E"hex2num",E"hex2num(str) +("Data Formats","Base","bin","bin(n[, pad]) - Convert a hexadecimal string to the floating point number it - represents + Convert an integer to a binary string, optionally specifying a + number of digits to pad to. "), -(E"Numbers",E"Base",E"one",E"one(x) +("Data Formats","Base","hex","hex(n[, pad]) - Get the multiplicative identity element for the type of x (x can - also specify the type itself). For matrices, returns an identity - matrix of the appropriate size and type. + Convert an integer to a hexadecimal string, optionally specifying a + number of digits to pad to. "), -(E"Numbers",E"Base",E"zero",E"zero(x) +("Data Formats","Base","dec","dec(n[, pad]) - Get the additive identity element for the type of x (x can also - specify the type itself). + Convert an integer to a decimal string, optionally specifying a + number of digits to pad to. "), -(E"Numbers",E"Base",E"pi",E"pi +("Data Formats","Base","oct","oct(n[, pad]) - The constant pi + Convert an integer to an octal string, optionally specifying a + number of digits to pad to. "), -(E"Numbers",E"Base",E"isdenormal",E"isdenormal(f) +("Data Formats","Base","base","base(base, n[, pad]) - Test whether a floating point number is denormal + Convert an integer to a string in the given base, optionally + specifying a number of digits to pad to. The base can be specified + as either an integer, or as a \"Uint8\" array of character values + to use as digit symbols. "), -(E"Numbers",E"Base",E"isfinite",E"isfinite(f) +("Data Formats","Base","bits","bits(n) - Test whether a number is finite + A string giving the literal bit representation of a number. "), -(E"Numbers",E"Base",E"isnan",E"isnan(f) +("Data Formats","Base","parseint","parseint([type], str[, base]) - Test whether a floating point number is not a number (NaN) + Parse a string as an integer in the given base (default 10), + yielding a number of the specified type (default \"Int\"). "), -(E"Numbers",E"Base",E"nextfloat",E"nextfloat(f) +("Data Formats","Base","parsefloat","parsefloat([type], str) - Get the next floating point number in lexicographic order + Parse a string as a decimal floating point number, yielding a + number of the specified type. "), -(E"Numbers",E"Base",E"prevfloat",E"prevfloat(f) +("Data Formats","Base","bool","bool(x) - Get the previous floating point number in lexicographic order + Convert a number or numeric array to boolean "), -(E"Numbers",E"Base",E"integer_valued",E"integer_valued(x) +("Data Formats","Base","isbool","isbool(x) - Test whether \"x\" is numerically equal to some integer + Test whether number or array is boolean "), -(E"Numbers",E"Base",E"real_valued",E"real_valued(x) +("Data Formats","Base","int","int(x) - Test whether \"x\" is numerically equal to some real number + Convert a number or array to the default integer type on your + platform. Alternatively, \"x\" can be a string, which is parsed as + an integer. "), -(E"Numbers",E"Base",E"exponent",E"exponent(f) +("Data Formats","Base","uint","uint(x) - Get the exponent of a floating-point number + Convert a number or array to the default unsigned integer type on + your platform. Alternatively, \"x\" can be a string, which is + parsed as an unsigned integer. "), -(E"Numbers",E"Base",E"mantissa",E"mantissa(f) +("Data Formats","Base","integer","integer(x) - Get the mantissa of a floating-point number + Convert a number or array to integer type. If \"x\" is already of + integer type it is unchanged, otherwise it converts it to the + default integer type on your platform. "), -(E"Random Numbers",E"Base",E"rand",E"rand() +("Data Formats","Base","isinteger","isinteger(x) - Generate a \"Float64\" random number in (0,1) + Test whether a number or array is of integer type "), -(E"Random Numbers",E"Base",E"randf",E"randf() +("Data Formats","Base","signed","signed(x) - Generate a \"Float32\" random number in (0,1) + Convert a number to a signed integer "), -(E"Random Numbers",E"Base",E"randi",E"randi(Int32|Uint32|Int64|Uint64) +("Data Formats","Base","unsigned","unsigned(x) - Generate a random integer of the given type + Convert a number to an unsigned integer "), -(E"Random Numbers",E"Base",E"randi",E"randi(n) +("Data Formats","Base","int8","int8(x) - Generate a random integer from 1 to \"n\" inclusive + Convert a number or array to \"Int8\" data type "), -(E"Random Numbers",E"Base",E"randi",E"randi(n, dims...) +("Data Formats","Base","int16","int16(x) - Generate an array of random integers from 1 to \"n\" inclusive + Convert a number or array to \"Int16\" data type "), -(E"Random Numbers",E"Base",E"randi",E"randi((a, b)) +("Data Formats","Base","int32","int32(x) - Generate a random integer in the interval from \"a\" to \"b\" - inclusive. The argument is a tuple. + Convert a number or array to \"Int32\" data type "), -(E"Random Numbers",E"Base",E"randi",E"randi((a, b), dims...) +("Data Formats","Base","int64","int64(x) - Generate an array of random integers in the interval from \"a\" to - \"b\" inclusive. The first argument is a tuple. + Convert a number or array to \"Int64\" data type "), -(E"Random Numbers",E"Base",E"randbit",E"randbit() +("Data Formats","Base","int128","int128(x) - Generate \"1\" or \"0\" at random + Convert a number or array to \"Int128\" data type "), -(E"Random Numbers",E"Base",E"randbool",E"randbool() +("Data Formats","Base","uint8","uint8(x) - Generate a random boolean value + Convert a number or array to \"Uint8\" data type "), -(E"Random Numbers",E"Base",E"randn",E"randn() +("Data Formats","Base","uint16","uint16(x) - Generate a normally-distributed random number with mean 0 and - standard deviation 1 + Convert a number or array to \"Uint16\" data type "), -(E"Random Numbers",E"Base",E"randg",E"randg(a) +("Data Formats","Base","uint32","uint32(x) - Generate a sample from the gamma distribution with shape parameter - \"a\" + Convert a number or array to \"Uint32\" data type "), -(E"Random Numbers",E"Base",E"randchi2",E"randchi2(n) +("Data Formats","Base","uint64","uint64(x) - Generate a sample from the chi-squared distribution with \"n\" - degrees of freedom (also available as \"chi2rnd\") + Convert a number or array to \"Uint64\" data type "), -(E"Random Numbers",E"Base",E"randexp",E"randexp() +("Data Formats","Base","uint128","uint128(x) - Generate samples from the exponential distribution + Convert a number or array to \"Uint128\" data type "), -(E"Random Numbers",E"Base",E"srand",E"srand() +("Data Formats","Base","float32","float32(x) - Seed the RNG + Convert a number or array to \"Float32\" data type "), -(E"Arrays",E"Base",E"ndims",E"ndims(A) +("Data Formats","Base","float64","float64(x) - Returns the number of dimensions of A + Convert a number or array to \"Float64\" data type "), -(E"Arrays",E"Base",E"size",E"size(A) +("Data Formats","Base","float","float(x) - Returns a tuple containing the dimensions of A + Convert a number, array, or string to a \"FloatingPoint\" data + type. For numeric data, the smallest suitable \"FloatingPoint\" + type is used. For strings, it converts to \"Float64\". "), -(E"Arrays",E"Base",E"eltype",E"eltype(A) - - Returns the type of the elements contained in A - -"), +("Data Formats","Base","significand","significand(x) -(E"Arrays",E"Base",E"numel",E"numel(A) + Extract the significand(s) (a.k.a. mantissa), in binary + representation, of a floating-point number or array. - Returns the number of elements in A + For example, \"significand(15.2)/15.2 == 0.125\", and + \"significand(15.2)*8 == 15.2\" "), -(E"Arrays",E"Base",E"length",E"length(A) +("Data Formats","Base","exponent","exponent(x) -> Int - Returns the number of elements in A (note that this differs from - Matlab where \"length(A)\" is the largest dimension of \"A\") + Get the exponent of a normalized floating-point number. "), -(E"Arrays",E"Base",E"nnz",E"nnz(A) +("Data Formats","Base","float64_valued","float64_valued(x::Rational) - Counts the number of nonzero values in A + True if \"x\" can be losslessly represented as a \"Float64\" data + type "), -(E"Arrays",E"Base",E"stride",E"stride(A, k) +("Data Formats","Base","complex64","complex64(r, i) - Returns the distance in memory (in number of elements) between - adjacent elements in dimension k + Convert to \"r+i*im\" represented as a \"Complex64\" data type "), -(E"Arrays",E"Base",E"strides",E"strides(A) +("Data Formats","Base","complex128","complex128(r, i) - Returns a tuple of the memory strides in each dimension + Convert to \"r+i*im\" represented as a \"Complex128\" data type "), -(E"Arrays",E"Base",E"Array",E"Array(type, dims) +("Data Formats","Base","char","char(x) - Construct an uninitialized dense array. \"dims\" may be a tuple or - a series of integer arguments. + Convert a number or array to \"Char\" data type "), -(E"Arrays",E"Base",E"ref",E"ref(type) +("Data Formats","Base","complex","complex(r, i) - Construct an empty 1-d array of the specified type. This is usually - called with the syntax \"Type[]\". Element values can be specified - using \"Type[a,b,c,...]\". + Convert real numbers or arrays to complex "), -(E"Arrays",E"Base",E"cell",E"cell(dims) +("Data Formats","Base","iscomplex","iscomplex(x) -> Bool - Construct an uninitialized cell array (heterogeneous array). - \"dims\" can be either a tuple or a series of integer arguments. + Test whether a number or array is of a complex type "), -(E"Arrays",E"Base",E"zeros",E"zeros(type, dims) +("Data Formats","Base","isreal","isreal(x) -> Bool - Create an array of all zeros of specified type + Test whether a number or array is of a real type "), -(E"Arrays",E"Base",E"ones",E"ones(type, dims) +("Data Formats","Base","bswap","bswap(n) - Create an array of all ones of specified type + Byte-swap an integer "), -(E"Arrays",E"Base",E"trues",E"trues(dims) +("Data Formats","Base","num2hex","num2hex(f) - Create a Bool array with all values set to true + Get a hexadecimal string of the binary representation of a floating + point number "), -(E"Arrays",E"Base",E"falses",E"falses(dims) +("Data Formats","Base","hex2num","hex2num(str) - Create a Bool array with all values set to false + Convert a hexadecimal string to the floating point number it + represents "), -(E"Arrays",E"Base",E"fill",E"fill(v, dims) +("Numbers","Base","one","one(x) - Create an array filled with \"v\" + Get the multiplicative identity element for the type of x (x can + also specify the type itself). For matrices, returns an identity + matrix of the appropriate size and type. "), -(E"Arrays",E"Base",E"fill!",E"fill!(A, x) +("Numbers","Base","zero","zero(x) - Fill array \"A\" with value \"x\" + Get the additive identity element for the type of x (x can also + specify the type itself). "), -(E"Arrays",E"Base",E"reshape",E"reshape(A, dims) +("Numbers","Base","pi","pi - Create an array with the same data as the given array, but with - different dimensions. An implementation for a particular type of - array may choose whether the data is copied or shared. + The constant pi "), -(E"Arrays",E"Base",E"copy",E"copy(A) +("Numbers","Base","im","im - Create a copy of \"A\" + The imaginary unit "), -(E"Arrays",E"Base",E"similar",E"similar(array, element_type, dims) +("Numbers","Base","e","e - Create an uninitialized array of the same type as the given array, - but with the specified element type and dimensions. The second and - third arguments are both optional. The \"dims\" argument may be a - tuple or a series of integer arguments. + The constant e "), -(E"Arrays",E"Base",E"reinterpret",E"reinterpret(type, A) +("Numbers","Base","Inf","Inf - Construct an array with the same binary data as the given array, - but with the specified element type + Positive infinity of type Float64 "), -(E"Arrays",E"Base",E"rand",E"rand(dims) +("Numbers","Base","Inf32","Inf32 - Create a random array with Float64 random values in (0,1) + Positive infinity of type Float32 "), -(E"Arrays",E"Base",E"randf",E"randf(dims) +("Numbers","Base","NaN","NaN - Create a random array with Float32 random values in (0,1) + A not-a-number value of type Float64 "), -(E"Arrays",E"Base",E"randn",E"randn(dims) +("Numbers","Base","NaN32","NaN32 - Create a random array with Float64 normally-distributed random - values with a mean of 0 and standard deviation of 1 + A not-a-number value of type Float32 "), -(E"Arrays",E"Base",E"eye",E"eye(n) +("Numbers","Base","isdenormal","isdenormal(f) -> Bool - n-by-n identity matrix + Test whether a floating point number is denormal "), -(E"Arrays",E"Base",E"eye",E"eye(m, n) +("Numbers","Base","isfinite","isfinite(f) -> Bool - m-by-n identity matrix + Test whether a number is finite "), -(E"Arrays",E"Base",E"linspace",E"linspace(start, stop, n) +("Numbers","Base","isinf","isinf(f) - Construct a vector of \"n\" linearly-spaced elements from \"start\" - to \"stop\". + Test whether a number is infinite "), -(E"Arrays",E"Base",E"logspace",E"logspace(start, stop, n) +("Numbers","Base","isnan","isnan(f) - Construct a vector of \"n\" logarithmically-spaced numbers from - \"10^start\" to \"10^stop\". + Test whether a floating point number is not a number (NaN) "), -(E"Arrays",E"Base",E"ref",E"ref(A, ind) +("Numbers","Base","inf","inf(f) - Returns a subset of \"A\" as specified by \"ind\", which may be an - \"Int\", a \"Range\", or a \"Vector\". + Returns infinity in the same floating point type as \"f\" (or \"f\" + can by the type itself) "), -(E"Arrays",E"Base",E"sub",E"sub(A, ind) +("Numbers","Base","nan","nan(f) - Returns a SubArray, which stores the input \"A\" and \"ind\" rather - than computing the result immediately. Calling \"ref\" on a - SubArray computes the indices on the fly. + Returns NaN in the same floating point type as \"f\" (or \"f\" can + by the type itself) "), -(E"Arrays",E"Base",E"slicedim",E"slicedim(A, d, i) - - Return all the data of \"A\" where the index for dimension \"d\" - equals \"i\". Equivalent to \"A[:,:,...,i,:,:,...]\" where \"i\" is - in position \"d\". +("Numbers","Base","nextfloat","nextfloat(f) + + Get the next floating point number in lexicographic order "), -(E"Arrays",E"Base",E"assign",E"assign(A, X, ind) +("Numbers","Base","prevfloat","prevfloat(f) -> Float - Store an input array \"X\" within some subset of \"A\" as specified - by \"ind\". + Get the previous floating point number in lexicographic order "), -(E"Arrays",E"Base",E"cat",E"cat(dim, A...) +("Numbers","Base","integer_valued","integer_valued(x) - Concatenate the input arrays along the specified dimension + Test whether \"x\" is numerically equal to some integer "), -(E"Arrays",E"Base",E"vcat",E"vcat(A...) +("Numbers","Base","real_valued","real_valued(x) - Concatenate along dimension 1 + Test whether \"x\" is numerically equal to some real number "), -(E"Arrays",E"Base",E"hcat",E"hcat(A...) +("Numbers","Base","BigInt","BigInt(x) - Concatenate along dimension 2 + Create an arbitrary precision integer. \"x\" may be an \"Int\" (or + anything that can be converted to an \"Int\") or a \"String\". The + usual mathematical operators are defined for this type, and results + are promoted to a \"BigInt\". "), -(E"Arrays",E"Base",E"hvcat",E"hvcat() +("Numbers","Base","BigFloat","BigFloat(x) - Horizontal and vertical concatenation in one call + Create an arbitrary precision floating point number. \"x\" may be + an \"Integer\", a \"Float64\", a \"String\" or a \"BigInt\". The + usual mathematical operators are defined for this type, and results + are promoted to a \"BigFloat\". "), -(E"Arrays",E"Base",E"flipdim",E"flipdim(A, d) +("Numbers","Base","count_ones","count_ones(x::Integer) -> Integer - Reverse \"A\" in dimension \"d\". + Number of ones in the binary representation of \"x\". + + **Example**: \"count_ones(7) -> 3\" "), -(E"Arrays",E"Base",E"flipud",E"flipud(A) +("Numbers","Base","count_zeros","count_zeros(x::Integer) -> Integer - Equivalent to \"flipdim(A,1)\". + Number of zeros in the binary representation of \"x\". + + **Example**: \"count_zeros(int32(2 ^ 16 - 1)) -> 16\" "), -(E"Arrays",E"Base",E"fliplr",E"fliplr(A) +("Numbers","Base","leading_zeros","leading_zeros(x::Integer) -> Integer - Equivalent to \"flipdim(A,2)\". + Number of zeros leading the binary representation of \"x\". + + **Example**: \"leading_zeros(int32(1)) -> 31\" "), -(E"Arrays",E"Base",E"circshift",E"circshift(A, shifts) +("Numbers","Base","leading_ones","leading_ones(x::Integer) -> Integer - Circularly shift the data in an array. The second argument is a - vector giving the amount to shift in each dimension. + Number of ones leading the binary representation of \"x\". + + **Example**: \"leading_ones(int32(2 ^ 32 - 2)) -> 31\" "), -(E"Arrays",E"Base",E"find",E"find(A) +("Numbers","Base","trailing_zeros","trailing_zeros(x::Integer) -> Integer - Return a vector of the linear indexes of the non-zeros in \"A\". + Number of zeros trailing the binary representation of \"x\". + + **Example**: \"trailing_zeros(2) -> 1\" "), -(E"Arrays",E"Base",E"findn",E"findn(A) +("Numbers","Base","trailing_ones","trailing_ones(x::Integer) -> Integer - Return a vector of indexes for each dimension giving the locations - of the non-zeros in \"A\". + Number of ones trailing the binary representation of \"x\". + + **Example**: \"trailing_ones(3) -> 2\" "), -(E"Arrays",E"Base",E"permute",E"permute(A, perm) +("Numbers","Base","isprime","isprime(x::Integer) -> Bool - Permute the dimensions of array \"A\". \"perm\" is a vector - specifying a permutation of length \"ndims(A)\". This is a - generalization of transpose for multi-dimensional arrays. Transpose - is equivalent to \"permute(A,[2,1])\". + Returns \"true\" if \"x\" is prime, and \"false\" otherwise. + + **Example**: \"isprime(3) -> true\" "), -(E"Arrays",E"Base",E"ipermute",E"ipermute(A, perm) +("Numbers","Base","isodd","isodd(x::Integer) -> Bool + + Returns \"true\" if \"x\" is odd (that is, not divisible by 2), and + \"false\" otherwise. - Like \"permute\", except the inverse of the given permutation is - applied. + **Example**: \"isodd(9) -> false\" "), -(E"Arrays",E"Base",E"squeeze",E"squeeze(A) +("Numbers","Base","iseven","iseven(x::Integer) -> Bool - Remove singleton dimensions from the shape of array \"A\" + Returns \"true\" is \"x\" is even (that is, divisible by 2), and + \"false\" otherwise. + + **Example**: \"iseven(1) -> false\" "), -(E"Arrays",E"Base",E"vec",E"vec(A) +("Random Numbers","Base","srand","srand([rng], seed) - Make a vector out of an array with only one non-singleton - dimension. + Seed the RNG with a \"seed\", which may be an unsigned integer or a + vector of unsigned integers. \"seed\" can even be a filename, in + which case the seed is read from a file. If the argument \"rng\" is + not provided, the default global RNG is seeded. "), -(E"Linear Algebra",E"Base",E"*",E"*() +("Random Numbers","Base","MersenneTwister","MersenneTwister([seed]) - Matrix multiplication + Create a \"MersenneTwister\" RNG object. Different RNG objects can + have their own seeds, which may be useful for generating different + streams of random numbers. "), -(E"Linear Algebra",E"Base",E"\\",E"\\() +("Random Numbers","Base","rand","rand() - Matrix division using a polyalgorithm. For input matrices \"A\" and - \"B\", the result \"X\" is such that \"A*X == B\". For rectangular - \"A\", QR factorization is used. For triangular \"A\", a triangular - solve is performed. For square \"A\", Cholesky factorization is - tried if the input is symmetric with a heavy diagonal. LU - factorization is used in case Cholesky factorization fails or for - general square inputs. If \"size(A,1) > size(A,2)\", the result is - a least squares solution of \"A*X+eps=B\" using the singular value - decomposition. \"A\" does not need to have full rank. + Generate a \"Float64\" random number uniformly in [0,1) "), -(E"Linear Algebra",E"Base",E"dot",E"dot() +("Random Numbers","Base","rand!","rand!([rng], A) - Compute the dot product + Populate the array A with random number generated from the + specified RNG. "), -(E"Linear Algebra",E"Base",E"cross",E"cross() +("Random Numbers","Base","rand","rand(rng::AbstractRNG[, dims...]) - Compute the cross product of two 3-vectors + Generate a random \"Float64\" number or array of the size specified + by dims, using the specified RNG object. Currently, + \"MersenneTwister\" is the only available Random Number Generator + (RNG), which may be seeded using srand. "), -(E"Linear Algebra",E"Base",E"norm",E"norm() +("Random Numbers","Base","rand","rand(dims or [dims...]) - Compute the norm of a \"Vector\" or a \"Matrix\" + Generate a random \"Float64\" array of the size specified by dims "), -(E"Linear Algebra",E"Base",E"lu",E"lu(A) -> LU +("Random Numbers","Base","rand","rand(Int32|Uint32|Int64|Uint64|Int128|Uint128[, dims...]) - Compute LU factorization. LU is an \"LU factorization\" type that - can be used as an ordinary matrix. + Generate a random integer of the given type. Optionally, generate + an array of random integers of the given type by specifying dims. "), -(E"Linear Algebra",E"Base",E"chol",E"chol(A) +("Random Numbers","Base","rand","rand(r[, dims...]) - Compute Cholesky factorization + Generate a random integer from the inclusive interval specified by + \"Range1 r\" (for example, \"1:n\"). Optionally, generate a random + integer array. "), -(E"Linear Algebra",E"Base",E"qr",E"qr(A) +("Random Numbers","Base","randbool","randbool([dims...]) - Compute QR factorization + Generate a random boolean value. Optionally, generate an array of + random boolean values. "), -(E"Linear Algebra",E"Base",E"qrp",E"qrp(A) +("Random Numbers","Base","randbool!","randbool!(A) - Compute QR factorization with pivoting + Fill an array with random boolean values. A may be an \"Array\" or + a \"BitArray\". "), -(E"Linear Algebra",E"Base",E"factors",E"factors(D) +("Random Numbers","Base","randn","randn(dims or [dims...]) - Return the factors of a decomposition D. For an LU decomposition, - factors(LU) -> L, U, p + Generate a normally-distributed random number with mean 0 and + standard deviation 1. Optionally generate an array of normally- + distributed random numbers. "), -(E"Linear Algebra",E"Base",E"eig",E"eig(A) -> D, V +("Arrays","Base","ndims","ndims(A) -> Integer - Compute eigenvalues and eigenvectors of A + Returns the number of dimensions of A "), -(E"Linear Algebra",E"Base",E"eigvals",E"eigvals(A) +("Arrays","Base","size","size(A) - Returns the eigenvalues of \"A\". + Returns a tuple containing the dimensions of A "), -(E"Linear Algebra",E"Base",E"svd",E"svd(A) -> U, S, V' +("Arrays","Base","eltype","eltype(A) - Compute the SVD of A + Returns the type of the elements contained in A "), -(E"Linear Algebra",E"Base",E"svdvals",E"svdvals(A) +("Arrays","Base","length","length(A) -> Integer - Returns the singular values of \"A\". + Returns the number of elements in A (note that this differs from + MATLAB where \"length(A)\" is the largest dimension of \"A\") "), -(E"Linear Algebra",E"Base",E"triu",E"triu(M) +("Arrays","Base","nnz","nnz(A) - Upper triangle of a matrix + Counts the number of nonzero values in array A (dense or sparse) "), -(E"Linear Algebra",E"Base",E"tril",E"tril(M) +("Arrays","Base","scale!","scale!(A, k) - Lower triangle of a matrix + Scale the contents of an array A with k (in-place) "), -(E"Linear Algebra",E"Base",E"diag",E"diag(M) +("Arrays","Base","conj!","conj!(A) - The diagonal of a matrix, as a vector + Convert an array to its complex conjugate in-place "), -(E"Linear Algebra",E"Base",E"diagm",E"diagm(v) +("Arrays","Base","stride","stride(A, k) - Construct a diagonal matrix from a vector + Returns the distance in memory (in number of elements) between + adjacent elements in dimension k "), -(E"Linear Algebra",E"Base",E"Tridiagonal",E"Tridiagonal(dl, d, du) +("Arrays","Base","strides","strides(A) - Construct a tridiagonal matrix from the lower diagonal, diagonal, - and upper diagonal + Returns a tuple of the memory strides in each dimension "), -(E"Linear Algebra",E"Base",E"Woodbury",E"Woodbury(A, U, C, V) +("Arrays","Base","Array","Array(type, dims) - Construct a matrix in a form suitable for applying the Woodbury - matrix identity + Construct an uninitialized dense array. \"dims\" may be a tuple or + a series of integer arguments. "), -(E"Linear Algebra",E"Base",E"rank",E"rank(M) +("Arrays","Base","getindex","getindex(type[, elements...]) - Compute the rank of a matrix + Construct a 1-d array of the specified type. This is usually called + with the syntax \"Type[]\". Element values can be specified using + \"Type[a,b,c,...]\". "), -(E"Linear Algebra",E"Base",E"cond",E"cond(M) +("Arrays","Base","cell","cell(dims) - Matrix condition number + Construct an uninitialized cell array (heterogeneous array). + \"dims\" can be either a tuple or a series of integer arguments. "), -(E"Linear Algebra",E"Base",E"trace",E"trace(M) +("Arrays","Base","zeros","zeros(type, dims) - Matrix trace + Create an array of all zeros of specified type "), -(E"Linear Algebra",E"Base",E"det",E"det(M) +("Arrays","Base","ones","ones(type, dims) - Matrix determinant + Create an array of all ones of specified type "), -(E"Linear Algebra",E"Base",E"inv",E"inv(M) +("Arrays","Base","trues","trues(dims) - Matrix inverse + Create a Bool array with all values set to true "), -(E"Linear Algebra",E"Base",E"pinv",E"pinv(M) +("Arrays","Base","falses","falses(dims) - Moore-Penrose inverse + Create a Bool array with all values set to false "), -(E"Linear Algebra",E"Base",E"null",E"null(M) +("Arrays","Base","fill","fill(v, dims) - Basis for null space of M + Create an array filled with \"v\" "), -(E"Linear Algebra",E"Base",E"repmat",E"repmat(A, n, m) +("Arrays","Base","fill!","fill!(A, x) - Construct a matrix by repeating the given matrix \"n\" times in - dimension 1 and \"m\" times in dimension 2. + Fill array \"A\" with value \"x\" "), -(E"Linear Algebra",E"Base",E"kron",E"kron(A, B) +("Arrays","Base","reshape","reshape(A, dims) - Kronecker tensor product of two vectors or two matrices. + Create an array with the same data as the given array, but with + different dimensions. An implementation for a particular type of + array may choose whether the data is copied or shared. "), -(E"Linear Algebra",E"Base",E"linreg",E"linreg(x, y) +("Arrays","Base","similar","similar(array, element_type, dims) - Determine parameters \"[a, b]\" that minimize the squared error - between \"y\" and \"a+b*x\". + Create an uninitialized array of the same type as the given array, + but with the specified element type and dimensions. The second and + third arguments are both optional. The \"dims\" argument may be a + tuple or a series of integer arguments. "), -(E"Linear Algebra",E"Base",E"linreg",E"linreg(x, y, w) +("Arrays","Base","reinterpret","reinterpret(type, A) - Weighted least-squares linear regression + Construct an array with the same binary data as the given array, + but with the specified element type "), -(E"Combinatorics",E"Base",E"sort",E"sort(v) +("Arrays","Base","eye","eye(n) - Sort a vector in ascending order, according to \"isless\". + n-by-n identity matrix "), -(E"Combinatorics",E"Base",E"sort!",E"sort!(v) +("Arrays","Base","eye","eye(m, n) - In-place sort + m-by-n identity matrix "), -(E"Combinatorics",E"Base",E"sortr",E"sortr(v) +("Arrays","Base","linspace","linspace(start, stop, n) - Sort a vector in descending order + Construct a vector of \"n\" linearly-spaced elements from \"start\" + to \"stop\". "), -(E"Combinatorics",E"Base",E"sortr!",E"sortr!(v) +("Arrays","Base","logspace","logspace(start, stop, n) - In-place descending-order sort + Construct a vector of \"n\" logarithmically-spaced numbers from + \"10^start\" to \"10^stop\". "), -(E"Combinatorics",E"Base",E"sort",E"sort(a, dim) +("Arrays","Base","bsxfun","bsxfun(fn, A, B[, C...]) - Sort an array along the given dimension + Apply binary function \"fn\" to two or more arrays, with singleton + dimensions expanded. "), -(E"Combinatorics",E"Base",E"sort",E"sort(lessthan, a[, dim]) +("Arrays","Base","getindex","getindex(A, ind) - Sort with a custom comparison function + Returns a subset of array \"A\" as specified by \"ind\", which may + be an \"Int\", a \"Range\", or a \"Vector\". "), -(E"Combinatorics",E"Base",E"sortperm",E"sortperm(v) -> s,p +("Arrays","Base","sub","sub(A, ind) - Sort a vector in ascending order, also constructing the permutation - that sorts the vector + Returns a SubArray, which stores the input \"A\" and \"ind\" rather + than computing the result immediately. Calling \"getindex\" on a + SubArray computes the indices on the fly. "), -(E"Combinatorics",E"Base",E"issorted",E"issorted(v) +("Arrays","Base","slicedim","slicedim(A, d, i) - Test whether a vector is in ascending sorted order + Return all the data of \"A\" where the index for dimension \"d\" + equals \"i\". Equivalent to \"A[:,:,...,i,:,:,...]\" where \"i\" is + in position \"d\". "), -(E"Combinatorics",E"Base",E"nthperm",E"nthperm(v, k) +("Arrays","Base","setindex!","setindex!(A, X, ind) - Compute the kth lexicographic permutation of a vector + Store values from array \"X\" within some subset of \"A\" as + specified by \"ind\". "), -(E"Combinatorics",E"Base",E"nthperm!",E"nthperm!(v, k) +("Arrays","Base","cat","cat(dim, A...) - In-place version of \"nthperm\" + Concatenate the input arrays along the specified dimension "), -(E"Combinatorics",E"Base",E"randperm",E"randperm(n) +("Arrays","Base","vcat","vcat(A...) - Construct a random permutation of the given length + Concatenate along dimension 1 "), -(E"Combinatorics",E"Base",E"randcycle",E"randcycle(n) +("Arrays","Base","hcat","hcat(A...) - Construct a random cyclic permutation of the given length + Concatenate along dimension 2 "), -(E"Combinatorics",E"Base",E"shuffle",E"shuffle(v) +("Arrays","Base","hvcat","hvcat(rows::(Int...), values...) - Randomly rearrange the elements of a vector + Horizontal and vertical concatenation in one call. This function is + called for block matrix syntax. The first argument specifies the + number of arguments to concatenate in each block row. For example, + \"[a b;c d e]\" calls \"hvcat((2,3),a,b,c,d,e)\". "), -(E"Combinatorics",E"Base",E"shuffle!",E"shuffle!(v) +("Arrays","Base","flipdim","flipdim(A, d) - In-place version of \"shuffle\" + Reverse \"A\" in dimension \"d\". "), -(E"Combinatorics",E"Base",E"reverse",E"reverse(v) +("Arrays","Base","flipud","flipud(A) - Reverse vector \"v\" + Equivalent to \"flipdim(A,1)\". "), -(E"Combinatorics",E"Base",E"reverse!",E"reverse!(v) +("Arrays","Base","fliplr","fliplr(A) - Reverse vector \"v\" in-place + Equivalent to \"flipdim(A,2)\". "), -(E"Combinatorics",E"Base",E"select",E"select(v, k) +("Arrays","Base","circshift","circshift(A, shifts) - Find the element in position \"k\" in the sorted vector \"v\" - without sorting + Circularly shift the data in an array. The second argument is a + vector giving the amount to shift in each dimension. "), -(E"Combinatorics",E"Base",E"select!",E"select!(v, k) +("Arrays","Base","find","find(A) - In-place version of \"select\" + Return a vector of the linear indexes of the non-zeros in \"A\". "), -(E"Statistics",E"Base",E"mean",E"mean(v[, dim]) +("Arrays","Base","findn","findn(A) - Compute the mean of whole array \"v\", or optionally along - dimension \"dim\" + Return a vector of indexes for each dimension giving the locations + of the non-zeros in \"A\". "), -(E"Statistics",E"Base",E"std",E"std(v) +("Arrays","Base","nonzeros","nonzeros(A) - Compute the standard deviation of a vector \"v\" + Return a vector of the non-zero values in array \"A\". "), -(E"Statistics",E"Base",E"median",E"median(v) +("Arrays","Base","findfirst","findfirst(A) - Compute the median of a vector \"v\" + Return the index of the first non-zero value in \"A\". "), -(E"Statistics",E"Base",E"hist",E"hist(v[, n]) +("Arrays","Base","findfirst","findfirst(A, v) - Compute the histogram of \"v\", optionally using \"n\" bins + Return the index of the first element equal to \"v\" in \"A\". "), -(E"Statistics",E"Base",E"histc",E"histc(v, e) +("Arrays","Base","findfirst","findfirst(predicate, A) - Compute the histogram of \"v\" using a vector \"e\" as the edges - for the bins + Return the index of the first element that satisfies the given + predicate in \"A\". "), -(E"Signal Processing",E"Base",E"fft",E"fft(A, dim) +("Arrays","Base","permutedims","permutedims(A, perm) - One dimensional FFT if input is a \"Vector\". For n-d cases, - compute fft of vectors along dimension \"dim\". Most efficient if - \"size(A, dim)\" is a product of small primes; see \"nextprod()\". + Permute the dimensions of array \"A\". \"perm\" is a vector + specifying a permutation of length \"ndims(A)\". This is a + generalization of transpose for multi-dimensional arrays. Transpose + is equivalent to \"permute(A,[2,1])\". "), -(E"Signal Processing",E"Base",E"fft2",E"fft2() +("Arrays","Base","ipermutedims","ipermutedims(A, perm) - 2d FFT + Like \"permutedims()\", except the inverse of the given permutation + is applied. "), -(E"Signal Processing",E"Base",E"fft3",E"fft3() +("Arrays","Base","squeeze","squeeze(A, dims) - 3d FFT + Remove the dimensions specified by \"dims\" from array \"A\" "), -(E"Signal Processing",E"Base",E"fftn",E"fftn() +("Arrays","Base","vec","vec(Array) -> Vector - N-d FFT + Vectorize an array using column-major convention. "), -(E"Signal Processing",E"Base",E"ifft",E"ifft(A, dim) +("Arrays","Base","cumprod","cumprod(A[, dim]) - Inverse FFT. Same arguments as \"fft\". + Cumulative product along a dimension. "), -(E"Signal Processing",E"Base",E"ifft2",E"ifft2() +("Arrays","Base","cumsum","cumsum(A[, dim]) - Inverse 2d FFT + Cumulative sum along a dimension. "), -(E"Signal Processing",E"Base",E"ifft3",E"ifft3() +("Arrays","Base","cumsum_kbn","cumsum_kbn(A[, dim]) - Inverse 3d FFT + Cumulative sum along a dimension, using the Kahan-Babuska-Neumaier + compensated summation algorithm for additional accuracy. "), -(E"Signal Processing",E"Base",E"ifftn",E"ifftn() +("Arrays","Base","cummin","cummin(A[, dim]) - Inverse N-d FFT + Cumulative minimum along a dimension. "), -(E"Signal Processing",E"Base",E"rfft",E"rfft(A[, dim=1]) +("Arrays","Base","cummax","cummax(A[, dim]) - One-dimensional FFT of real array A along dimension dim. If A has - size \"(..., n_dim, ...)\", the result has size \"(..., - floor(n_dim/2)+1, ...)\". + Cumulative maximum along a dimension. "), -(E"Signal Processing",E"Base",E"rfftn",E"rfftn(A) +("Arrays","Base","diff","diff(A[, dim]) - N-d FFT of real array A. If A has size \"(n_1, ..., n_d)\", the - result has size \"(floor(n_1/2)+1, ..., n_d)\". + Finite difference operator of matrix or vector. "), -(E"Signal Processing",E"Base",E"fftshift",E"fftshift(x) +("Arrays","Base","rot180","rot180(A) - Swap the first and second halves of each dimension of \"x\". + Rotate matrix \"A\" 180 degrees. "), -(E"Signal Processing",E"Base",E"fftshift",E"fftshift(x, dim) +("Arrays","Base","rotl90","rotl90(A) - Swap the first and second halves of the given dimension of array - \"x\". + Rotate matrix \"A\" left 90 degrees. "), -(E"Signal Processing",E"Base",E"ifftshift",E"ifftshift(x[, dim]) +("Arrays","Base","rotr90","rotr90(A) - Undoes the effect of \"fftshift\". + Rotate matrix \"A\" right 90 degrees. "), -(E"Signal Processing",E"Base",E"filt",E"filt(b, a, x) +("Arrays","Base","reducedim","reducedim(f, A, dims, initial) - Apply filter described by vectors \"a\" and \"b\" to vector \"x\". + Reduce 2-argument function \"f\" along dimensions of \"A\". + \"dims\" is a vector specifying the dimensions to reduce, and + \"initial\" is the initial value to use in the reductions. "), -(E"Signal Processing",E"Base",E"deconv",E"deconv(b, a) +("Arrays","Base","mapslices","mapslices(f, A, dims) - Construct vector \"c\" such that \"b = conv(a,c) + r\". Equivalent - to polynomial division. + Transform the given dimensions of array \"A\" using function \"f\". + \"f\" is called on each slice of \"A\" of the form + \"A[...,:,...,:,...]\". \"dims\" is an integer vector specifying + where the colons go in this expression. The results are + concatenated along the remaining dimensions. For example, if + \"dims\" is \"[1,2]\" and A is 4-dimensional, \"f\" is called on + \"A[:,:,i,j]\" for all \"i\" and \"j\". "), -(E"Signal Processing",E"Base",E"conv",E"conv(u, v) +("Arrays","Base","sum_kbn","sum_kbn(A) - Convolution of two vectors. Uses FFT algorithm. + Returns the sum of all array elements, using the Kahan-Babuska- + Neumaier compensated summation algorithm for additional accuracy. "), -(E"Signal Processing",E"Base",E"xcorr",E"xcorr(u, v) +("Combinatorics","Base","nthperm","nthperm(v, k) - Compute the cross-correlation of two vectors. + Compute the kth lexicographic permutation of a vector. "), -(E"Parallel Computing",E"Base",E"addprocs_local",E"addprocs_local(n) +("Combinatorics","Base","nthperm!","nthperm!(v, k) - Add processes on the local machine. Can be used to take advantage - of multiple cores. + In-place version of \"nthperm()\". "), -(E"Parallel Computing",E"Base",E"addprocs_ssh",E"addprocs_ssh({\"host1\", \"host2\", ...}) +("Combinatorics","Base","randperm","randperm(n) - Add processes on remote machines via SSH. Requires julia to be - installed in the same location on each node, or to be available via - a shared file system. + Construct a random permutation of the given length. "), -(E"Parallel Computing",E"Base",E"addprocs_sge",E"addprocs_sge(n) +("Combinatorics","Base","invperm","invperm(v) - Add processes via the Sun/Oracle Grid Engine batch queue, using - \"qsub\". + Return the inverse permutation of v. "), -(E"Parallel Computing",E"Base",E"nprocs",E"nprocs() +("Combinatorics","Base","isperm","isperm(v) -> Bool - Get the number of available processors + Returns true if v is a valid permutation. "), -(E"Parallel Computing",E"Base",E"myid",E"myid() +("Combinatorics","Base","permute!","permute!(v, p) + + Permute vector \"v\" in-place, according to permutation \"p\". No + checking is done to verify that \"p\" is a permutation. - Get the id of the current processor + To return a new permutation, use \"v[p]\". Note that this is + generally faster than \"permute!(v,p)\" for large vectors. "), -(E"Parallel Computing",E"Base",E"remote_call",E"remote_call(id, func, args...) +("Combinatorics","Base","ipermute!","ipermute!(v, p) - Call a function asynchronously on the given arguments on the - specified processor. Returns a \"RemoteRef\". + Like permute!, but the inverse of the given permutation is applied. "), -(E"Parallel Computing",E"Base",E"wait",E"wait(RemoteRef) +("Combinatorics","Base","randcycle","randcycle(n) - Wait for a value to become available for the specified remote - reference. + Construct a random cyclic permutation of the given length. "), -(E"Parallel Computing",E"Base",E"fetch",E"fetch(RemoteRef) +("Combinatorics","Base","shuffle","shuffle(v) - Wait for and get the value of a remote reference. + Randomly rearrange the elements of a vector. "), -(E"Parallel Computing",E"Base",E"remote_call_wait",E"remote_call_wait(id, func, args...) +("Combinatorics","Base","shuffle!","shuffle!(v) - Perform \"wait(remote_call(...))\" in one message. + In-place version of \"shuffle()\". "), -(E"Parallel Computing",E"Base",E"remote_call_fetch",E"remote_call_fetch(id, func, args...) +("Combinatorics","Base","reverse","reverse(v) - Perform \"fetch(remote_call(...))\" in one message. + Reverse vector \"v\". "), -(E"Parallel Computing",E"Base",E"put",E"put(RemoteRef, value) +("Combinatorics","Base","reverse!","reverse!(v) -> v - Store a value to a remote reference. Implements \"shared queue of - length 1\" semantics: if a value is already present, blocks until - the value is removed with \"take\". + In-place version of \"reverse()\". "), -(E"Parallel Computing",E"Base",E"take",E"take(RemoteRef) +("Combinatorics","Base","combinations","combinations(array, n) - Fetch the value of a remote reference, removing it so that the - reference is empty again. + Generate all combinations of \"n\" elements from a given array. + Because the number of combinations can be very large, this function + runs inside a Task to produce values on demand. Write \"c = @task + combinations(a,n)\", then iterate \"c\" or call \"consume\" on it. "), -(E"Parallel Computing",E"Base",E"RemoteRef",E"RemoteRef() +("Combinatorics","Base","integer_partitions","integer_partitions(n, m) - Make an uninitialized remote reference on the local machine. + Generate all arrays of \"m\" integers that sum to \"n\". Because + the number of partitions can be very large, this function runs + inside a Task to produce values on demand. Write \"c = @task + integer_partitions(n,m)\", then iterate \"c\" or call \"consume\" + on it. "), -(E"Parallel Computing",E"Base",E"RemoteRef",E"RemoteRef(n) +("Combinatorics","Base","partitions","partitions(array) - Make an uninitialized remote reference on processor \"n\". + Generate all set partitions of the elements of an array, + represented as arrays of arrays. Because the number of partitions + can be very large, this function runs inside a Task to produce + values on demand. Write \"c = @task partitions(a)\", then iterate + \"c\" or call \"consume\" on it. "), -(E"Distributed Arrays",E"Base",E"darray",E"darray(init, type, dims[, distdim, procs, dist]) +("Statistics","Base","mean","mean(v[, region]) - Construct a distributed array. \"init\" is a function of three - arguments that will run on each processor, and should return an - \"Array\" holding the local data for the current processor. Its - arguments are \"(T,d,da)\" where \"T\" is the element type, \"d\" - is the dimensions of the needed local piece, and \"da\" is the new - \"DArray\" being constructed (though, of course, it is not fully - initialized). \"type\" is the element type. \"dims\" is the - dimensions of the entire \"DArray\". \"distdim\" is the dimension - to distribute in. \"procs\" is a vector of processor ids to use. - \"dist\" is a vector giving the first index of each contiguous - distributed piece, such that the nth piece consists of indexes - \"dist[n]\" through \"dist[n+1]-1\". If you have a vector \"v\" of - the sizes of the pieces, \"dist\" can be computed as - \"cumsum([1,v])\". Fortunately, all arguments after \"dims\" are - optional. + Compute the mean of whole array \"v\", or optionally along the + dimensions in \"region\". "), -(E"Distributed Arrays",E"Base",E"darray",E"darray(f, A) +("Statistics","Base","std","std(v[, region]) - Transform \"DArray\" \"A\" to another of the same type and - distribution by applying function \"f\" to each block of \"A\". + Compute the sample standard deviation of a vector or array``v``, + optionally along dimensions in \"region\". The algorithm returns an + estimator of the generative distribution's standard deviation under + the assumption that each entry of \"v\" is an IID draw from that + generative distribution. This computation is equivalent to + calculating \"sqrt(sum((v - mean(v)).^2) / (length(v) - 1))\". "), -(E"Distributed Arrays",E"Base",E"dzeros",E"dzeros([type], dims, ...) +("Statistics","Base","stdm","stdm(v, m) - Construct a distributed array of zeros. Trailing arguments are the - same as those accepted by \"darray\". + Compute the sample standard deviation of a vector \"v\" with known + mean \"m\". "), -(E"Distributed Arrays",E"Base",E"dones",E"dones([type], dims, ...) +("Statistics","Base","var","var(v[, region]) - Construct a distributed array of ones. Trailing arguments are the - same as those accepted by \"darray\". + Compute the sample variance of a vector or array``v``, optionally + along dimensions in \"region\". The algorithm will return an + estimator of the generative distribution's variance under the + assumption that each entry of \"v\" is an IID draw from that + generative distribution. This computation is equivalent to + calculating \"sum((v - mean(v)).^2) / (length(v) - 1)\". "), -(E"Distributed Arrays",E"Base",E"dfill",E"dfill(x, dims, ...) +("Statistics","Base","varm","varm(v, m) - Construct a distributed array filled with value \"x\". Trailing - arguments are the same as those accepted by \"darray\". + Compute the sample variance of a vector \"v\" with known mean + \"m\". "), -(E"Distributed Arrays",E"Base",E"drand",E"drand(dims, ...) +("Statistics","Base","median","median(v) - Construct a distributed uniform random array. Trailing arguments - are the same as those accepted by \"darray\". + Compute the median of a vector \"v\". "), -(E"Distributed Arrays",E"Base",E"drandn",E"drandn(dims, ...) +("Statistics","Base","hist","hist(v[, n]) -> e, counts - Construct a distributed normal random array. Trailing arguments are - the same as those accepted by \"darray\". + Compute the histogram of \"v\", optionally using approximately + \"n\" bins. The return values are a range \"e\", which correspond + to the edges of the bins, and \"counts\" containing the number of + elements of \"v\" in each bin. "), -(E"Distributed Arrays",E"Base",E"dcell",E"dcell(dims, ...) +("Statistics","Base","hist","hist(v, e) -> e, counts - Construct a distributed cell array. Trailing arguments are the same - as those accepted by \"darray\". + Compute the histogram of \"v\" using a vector/range \"e\" as the + edges for the bins. The result will be a vector of length + \"length(e) - 1\", with the \"i``th element being ``sum(e[i] .< v + .<= e[i+1])\". "), -(E"Distributed Arrays",E"Base",E"distribute",E"distribute(a[, distdim]) +("Statistics","Base","histrange","histrange(v, n) - Convert a local array to distributed + Compute *nice* bin ranges for the edges of a histogram of \"v\", + using approximately \"n\" bins. The resulting step sizes will be 1, + 2 or 5 multiplied by a power of 10. "), -(E"Distributed Arrays",E"Base",E"localize",E"localize(d) +("Statistics","Base","midpoints","midpoints(e) - Get the local piece of a distributed array + Compute the midpoints of the bins with edges \"e\". The result is a + vector/range of length \"length(e) - 1\". "), -(E"Distributed Arrays",E"Base",E"changedist",E"changedist(d, distdim) +("Statistics","Base","quantile","quantile(v, p) - Change the distributed dimension of a \"DArray\" + Compute the quantiles of a vector \"v\" at a specified set of + probability values \"p\". "), -(E"Distributed Arrays",E"Base",E"myindexes",E"myindexes(d) +("Statistics","Base","quantile","quantile(v) - A tuple describing the indexes owned by the local processor + Compute the quantiles of a vector \"v\" at the probability values + \"[.0, .2, .4, .6, .8, 1.0]\". "), -(E"Distributed Arrays",E"Base",E"owner",E"owner(d, i) +("Statistics","Base","cov","cov(v1[, v2]) - Get the id of the processor holding index \"i\" in the distributed - dimension + Compute the Pearson covariance between two vectors \"v1\" and + \"v2\". If called with a single element \"v\", then computes + covariance of columns of \"v\". "), -(E"Distributed Arrays",E"Base",E"procs",E"procs(d) +("Statistics","Base","cor","cor(v1[, v2]) - Get the vector of processors storing pieces of \"d\" + Compute the Pearson correlation between two vectors \"v1\" and + \"v2\". If called with a single element \"v\", then computes + correlation of columns of \"v\". "), -(E"Distributed Arrays",E"Base",E"distdim",E"distdim(d) +("Signal Processing","Base","fft","fft(A[, dims]) - Get the distributed dimension of \"d\" + Performs a multidimensional FFT of the array \"A\". The optional + \"dims\" argument specifies an iterable subset of dimensions (e.g. + an integer, range, tuple, or array) to transform along. Most + efficient if the size of \"A\" along the transformed dimensions is + a product of small primes; see \"nextprod()\". See also + \"plan_fft()\" for even greater efficiency. + + A one-dimensional FFT computes the one-dimensional discrete Fourier + transform (DFT) as defined by \\operatorname{DFT}[k] = + \\sum_{n=1}^{\\operatorname{length}(A)} \\exp\\left(-i\\frac{2\\pi + (n-1)(k-1)}{\\operatorname{length}(A)} \\right) A[n]. A + multidimensional FFT simply performs this operation along each + transformed dimension of \"A\". "), -(E"System",E"Base",E"system",E"system(\"command\") +("Signal Processing","Base","fft!","fft!(A[, dims]) - Run a shell command. + Same as \"fft()\", but operates in-place on \"A\", which must be an + array of complex floating-point numbers. "), -(E"System",E"Base",E"gethostname",E"gethostname() +("Signal Processing","Base","ifft","ifft(A[, dims]) - Get the local machine's host name. + Multidimensional inverse FFT. + + A one-dimensional backward FFT computes \\operatorname{BDFT}[k] = + \\sum_{n=1}^{\\operatorname{length}(A)} \\exp\\left(+i\\frac{2\\pi + (n-1)(k-1)}{\\operatorname{length}(A)} \\right) A[n]. A + multidimensional backward FFT simply performs this operation along + each transformed dimension of \"A\". The inverse FFT computes the + same thing divided by the product of the transformed dimensions. "), -(E"System",E"Base",E"getipaddr",E"getipaddr() +("Signal Processing","Base","ifft!","ifft!(A[, dims]) - Get the IP address of the local machine, as a string of the form - \"x.x.x.x\". + Same as \"ifft()\", but operates in-place on \"A\". "), -(E"System",E"Base",E"cwd",E"cwd() +("Signal Processing","Base","bfft","bfft(A[, dims]) - Get the current working directory. + Similar to \"ifft()\", but computes an unnormalized inverse + (backward) transform, which must be divided by the product of the + sizes of the transformed dimensions in order to obtain the inverse. + (This is slightly more efficient than \"ifft()\" because it omits a + scaling step, which in some applications can be combined with other + computational steps elsewhere.) "), -(E"System",E"Base",E"cd",E"cd(\"dir\") +("Signal Processing","Base","bfft!","bfft!(A[, dims]) - Set the current working directory. Returns the new current - directory. + Same as \"bfft()\", but operates in-place on \"A\". "), -(E"System",E"Base",E"mkdir",E"mkdir(path[, mode]) +("Signal Processing","Base","plan_fft","plan_fft(A[, dims[, flags[, timelimit]]]) - Make a new directory with name \"path\" and permissions \"mode\". - \"mode\" defaults to 0o777, modified by the current file creation - mask. + Pre-plan an optimized FFT along given dimensions (\"dims\") of + arrays matching the shape and type of \"A\". (The first two + arguments have the same meaning as for \"fft()\".) Returns a + function \"plan(A)\" that computes \"fft(A, dims)\" quickly. + + The \"flags\" argument is a bitwise-or of FFTW planner flags, + defaulting to \"FFTW.ESTIMATE\". e.g. passing \"FFTW.MEASURE\" or + \"FFTW.PATIENT\" will instead spend several seconds (or more) + benchmarking different possible FFT algorithms and picking the + fastest one; see the FFTW manual for more information on planner + flags. The optional \"timelimit\" argument specifies a rough upper + bound on the allowed planning time, in seconds. Passing + \"FFTW.MEASURE\" or \"FFTW.PATIENT\" may cause the input array + \"A\" to be overwritten with zeros during plan creation. + + \"plan_fft!()\" is the same as \"plan_fft()\" but creates a plan + that operates in-place on its argument (which must be an array of + complex floating-point numbers). \"plan_ifft()\" and so on are + similar but produce plans that perform the equivalent of the + inverse transforms \"ifft()\" and so on. "), -(E"System",E"Base",E"rmdir",E"rmdir(path) +("Signal Processing","Base","plan_ifft","plan_ifft(A[, dims[, flags[, timelimit]]]) - Remove the directory named \"path\". + Same as \"plan_fft()\", but produces a plan that performs inverse + transforms \"ifft()\". "), -(E"System",E"Base",E"getpid",E"getpid() +("Signal Processing","Base","plan_bfft","plan_bfft(A[, dims[, flags[, timelimit]]]) - Get julia's process ID. + Same as \"plan_fft()\", but produces a plan that performs an + unnormalized backwards transform \"bfft()\". "), -(E"System",E"Base",E"time",E"time() +("Signal Processing","Base","plan_fft!","plan_fft!(A[, dims[, flags[, timelimit]]]) - Get the time in seconds since the epoch, with fairly high - (typically, microsecond) resolution. + Same as \"plan_fft()\", but operates in-place on \"A\". "), -(E"System",E"Base",E"time_ns",E"time_ns() +("Signal Processing","Base","plan_ifft!","plan_ifft!(A[, dims[, flags[, timelimit]]]) - Get the time in nanoseconds. The time corresponding to 0 is - undefined, and wraps every 5.8 years. + Same as \"plan_ifft()\", but operates in-place on \"A\". "), -(E"System",E"Base",E"tic",E"tic() +("Signal Processing","Base","plan_bfft!","plan_bfft!(A[, dims[, flags[, timelimit]]]) - Set a timer to be read by the next call to \"toc\" or \"toq\". The - macro call \"@time expr\" can also be used to time evaluation. + Same as \"plan_bfft()\", but operates in-place on \"A\". "), -(E"System",E"Base",E"toc",E"toc() +("Signal Processing","Base","rfft","rfft(A[, dims]) - Print and return the time elapsed since the last \"tic\" + Multidimensional FFT of a real array A, exploiting the fact that + the transform has conjugate symmetry in order to save roughly half + the computational time and storage costs compared with \"fft()\". + If \"A\" has size \"(n_1, ..., n_d)\", the result has size + \"(floor(n_1/2)+1, ..., n_d)\". + + The optional \"dims\" argument specifies an iterable subset of one + or more dimensions of \"A\" to transform, similar to \"fft()\". + Instead of (roughly) halving the first dimension of \"A\" in the + result, the \"dims[1]\" dimension is (roughly) halved in the same + way. "), -(E"System",E"Base",E"toq",E"toq() +("Signal Processing","Base","irfft","irfft(A, d[, dims]) + + Inverse of \"rfft()\": for a complex array \"A\", gives the + corresponding real array whose FFT yields \"A\" in the first half. + As for \"rfft()\", \"dims\" is an optional subset of dimensions to + transform, defaulting to \"1:ndims(A)\". - Return, but do not print, the time elapsed since the last \"tic\" + \"d\" is the length of the transformed real array along the + \"dims[1]\" dimension, which must satisfy \"d == + floor(size(A,dims[1])/2)+1\". (This parameter cannot be inferred + from \"size(A)\" due to the possibility of rounding by the + \"floor\" function here.) "), -(E"System",E"Base",E"EnvHash",E"EnvHash() +("Signal Processing","Base","brfft","brfft(A, d[, dims]) - A singleton of this type, \"ENV\", provides a hash table interface - to environment variables. + Similar to \"irfft()\" but computes an unnormalized inverse + transform (similar to \"bfft()\"), which must be divided by the + product of the sizes of the transformed dimensions (of the real + output array) in order to obtain the inverse transform. "), -(E"System",E"Base",E"dlopen",E"dlopen(libfile) +("Signal Processing","Base","plan_rfft","plan_rfft(A[, dims[, flags[, timelimit]]]) - Load a shared library, returning an opaque handle + Pre-plan an optimized real-input FFT, similar to \"plan_fft()\" + except for \"rfft()\" instead of \"fft()\". The first two + arguments, and the size of the transformed result, are the same as + for \"rfft()\". "), -(E"System",E"Base",E"dlsym",E"dlsym(handle, sym) +("Signal Processing","Base","plan_irfft","plan_irfft(A, d[, dims[, flags[, timelimit]]]) - Look up a symbol from a shared library handle + Pre-plan an optimized inverse real-input FFT, similar to + \"plan_rfft()\" except for \"irfft()\" and \"brfft()\", + respectively. The first three arguments have the same meaning as + for \"irfft()\". "), -(E"Errors",E"Base",E"error",E"error(message) +("Signal Processing","Base","dct","dct(A[, dims]) - Raise an error with the given message + Performs a multidimensional type-II discrete cosine transform (DCT) + of the array \"A\", using the unitary normalization of the DCT. The + optional \"dims\" argument specifies an iterable subset of + dimensions (e.g. an integer, range, tuple, or array) to transform + along. Most efficient if the size of \"A\" along the transformed + dimensions is a product of small primes; see \"nextprod()\". See + also \"plan_dct()\" for even greater efficiency. "), -(E"Errors",E"Base",E"throw",E"throw(e) +("Signal Processing","Base","dct!","dct!(A[, dims]) - Throw an object as an exception + Same as \"dct!()\", except that it operates in-place on \"A\", + which must be an array of real or complex floating-point values. "), -(E"Errors",E"Base",E"errno",E"errno() +("Signal Processing","Base","idct","idct(A[, dims]) - Get the value of the C library's \"errno\" + Computes the multidimensional inverse discrete cosine transform + (DCT) of the array \"A\" (technically, a type-III DCT with the + unitary normalization). The optional \"dims\" argument specifies an + iterable subset of dimensions (e.g. an integer, range, tuple, or + array) to transform along. Most efficient if the size of \"A\" + along the transformed dimensions is a product of small primes; see + \"nextprod()\". See also \"plan_idct()\" for even greater + efficiency. "), -(E"Errors",E"Base",E"strerror",E"strerror(n) +("Signal Processing","Base","idct!","idct!(A[, dims]) - Convert a system call error code to a descriptive string + Same as \"idct!()\", but operates in-place on \"A\". "), -(E"Errors",E"Base",E"assert",E"assert(cond) +("Signal Processing","Base","plan_dct","plan_dct(A[, dims[, flags[, timelimit]]]) - Raise an error if \"cond\" is false. Also available as the macro - \"@assert expr\". + Pre-plan an optimized discrete cosine transform (DCT), similar to + \"plan_fft()\" except producing a function that computes \"dct()\". + The first two arguments have the same meaning as for \"dct()\". "), -(E"Tasks",E"Base",E"Task",E"Task(func) +("Signal Processing","Base","plan_dct!","plan_dct!(A[, dims[, flags[, timelimit]]]) - Create a \"Task\" (i.e. thread, or coroutine) to execute the given - function. The task exits when this function returns. + Same as \"plan_dct()\", but operates in-place on \"A\". "), -(E"Tasks",E"Base",E"yieldto",E"yieldto(task, args...) +("Signal Processing","Base","plan_idct","plan_idct(A[, dims[, flags[, timelimit]]]) - Switch to the given task. The first time a task is switched to, the - task's function is called with \"args\". On subsequent switches, - \"args\" are returned from the task's last call to \"yieldto\". + Pre-plan an optimized inverse discrete cosine transform (DCT), + similar to \"plan_fft()\" except producing a function that computes + \"idct()\". The first two arguments have the same meaning as for + \"idct()\". "), -(E"Tasks",E"Base",E"current_task",E"current_task() +("Signal Processing","Base","plan_idct!","plan_idct!(A[, dims[, flags[, timelimit]]]) - Get the currently running Task. + Same as \"plan_idct()\", but operates in-place on \"A\". "), -(E"Tasks",E"Base",E"istaskdone",E"istaskdone(task) +("Signal Processing","Base","FFTW","FFTW.r2r(A, kind[, dims]) - Tell whether a task has exited. + Performs a multidimensional real-input/real-output (r2r) transform + of type \"kind\" of the array \"A\", as defined in the FFTW manual. + \"kind\" specifies either a discrete cosine transform of various + types (\"FFTW.REDFT00\", \"FFTW.REDFT01\", \"FFTW.REDFT10\", or + \"FFTW.REDFT11\"), a discrete sine transform of various types + (\"FFTW.RODFT00\", \"FFTW.RODFT01\", \"FFTW.RODFT10\", or + \"FFTW.RODFT11\"), a real-input DFT with halfcomplex-format output + (\"FFTW.R2HC\" and its inverse \"FFTW.HC2R\"), or a discrete + Hartley transform (\"FFTW.DHT\"). The \"kind\" argument may be an + array or tuple in order to specify different transform types along + the different dimensions of \"A\"; \"kind[end]\" is used for any + unspecified dimensions. See the FFTW manual for precise + definitions of these transform types, at + **. + + The optional \"dims\" argument specifies an iterable subset of + dimensions (e.g. an integer, range, tuple, or array) to transform + along. \"kind[i]\" is then the transform type for \"dims[i]\", with + \"kind[end]\" being used for \"i > length(kind)\". + + See also \"FFTW.plan_r2r()\" to pre-plan optimized r2r transforms. "), -(E"Tasks",E"Base",E"consume",E"consume(task) +("Signal Processing","Base","FFTW","FFTW.r2r!(A, kind[, dims]) - Receive the next value passed to \"produce\" by the specified task. + \"FFTW.r2r!()\" is the same as \"FFTW.r2r()\", but operates in- + place on \"A\", which must be an array of real or complex floating- + point numbers. "), -(E"Tasks",E"Base",E"produce",E"produce(value) +("Signal Processing","Base","FFTW","FFTW.plan_r2r(A, kind[, dims[, flags[, timelimit]]]) - Send the given value to the last \"consume\" call, switching to the - consumer task. + Pre-plan an optimized r2r transform, similar to \"plan_fft()\" + except that the transforms (and the first three arguments) + correspond to \"FFTW.r2r()\" and \"FFTW.r2r!()\", respectively. "), -(E"Tasks",E"Base",E"make_scheduled",E"make_scheduled(task) +("Signal Processing","Base","FFTW","FFTW.plan_r2r!(A, kind[, dims[, flags[, timelimit]]]) - Register a task with the main event loop, so it will automatically - run when possible. + Similar to \"plan_fft()\", but corresponds to \"FFTW.r2r!()\". "), -(E"Tasks",E"Base",E"yield",E"yield() +("Signal Processing","Base","fftshift","fftshift(x) - For scheduled tasks, switch back to the scheduler to allow another - scheduled task to run. + Swap the first and second halves of each dimension of \"x\". "), -(E"Tasks",E"Base",E"tls",E"tls(symbol) +("Signal Processing","Base","fftshift","fftshift(x, dim) - Look up the value of a symbol in the current task's task-local - storage. + Swap the first and second halves of the given dimension of array + \"x\". "), -(E"Tasks",E"Base",E"tls",E"tls(symbol, value) +("Signal Processing","Base","ifftshift","ifftshift(x[, dim]) - Assign a value to a symbol in the current task's task-local - storage. + Undoes the effect of \"fftshift\". "), -(E"BLAS",E"BLAS",E"copy!",E"copy!(n, X, incx, Y, incy) +("Signal Processing","Base","filt","filt(b, a, x) - Copy \"n\" elements of array \"X\" with stride \"incx\" to array - \"Y\" with stride \"incy\". Returns \"Y\". + Apply filter described by vectors \"a\" and \"b\" to vector \"x\". "), -(E"BLAS",E"BLAS",E"dot",E"dot(n, X, incx, Y, incy) +("Signal Processing","Base","deconv","deconv(b, a) - Dot product of two vectors consisting of \"n\" elements of array - \"X\" with stride \"incx\" and \"n\" elements of array \"Y\" with - stride \"incy\". There are no \"dot\" methods for \"Complex\" - arrays. + Construct vector \"c\" such that \"b = conv(a,c) + r\". Equivalent + to polynomial division. "), -(E"BLAS",E"BLAS",E"nrm2",E"nrm2(n, X, incx) +("Signal Processing","Base","conv","conv(u, v) - 2-norm of a vector consisting of \"n\" elements of array \"X\" with - stride \"incx\". + Convolution of two vectors. Uses FFT algorithm. "), -(E"BLAS",E"BLAS",E"axpy!",E"axpy!(n, a, X, incx, Y, incy) +("Signal Processing","Base","xcorr","xcorr(u, v) - Overwrite \"Y\" with \"a*X + Y\". Returns \"Y\". + Compute the cross-correlation of two vectors. "), -(E"BLAS",E"BLAS",E"syrk!",E"syrk!(uplo, trans, alpha, A, beta, C) +("Parallel Computing","Base","addprocs_local","addprocs_local(n) - Rank-k update of the symmetric matrix \"C\" as \"alpha*A*A.' + - beta*C\" or \"alpha*A.'*A + beta*C\" according to whether \"trans\" - is 'N' or 'T'. When \"uplo\" is 'U' the upper triangle of \"C\" is - updated ('L' for lower triangle). Returns \"C\". + Add processes on the local machine. Can be used to take advantage + of multiple cores. "), -(E"BLAS",E"BLAS",E"syrk",E"syrk(uplo, trans, alpha, A) +("Parallel Computing","Base","addprocs_ssh","addprocs_ssh({\"host1\", \"host2\", ...}) - Returns either the upper triangle or the lower triangle, according - to \"uplo\" ('U' or 'L'), of \"alpha*A*A.'\" or \"alpha*A.'*A\", - according to \"trans\" ('N' or 'T'). + Add processes on remote machines via SSH. Requires julia to be + installed in the same location on each node, or to be available via + a shared file system. "), -(E"BLAS",E"BLAS",E"herk!",E"herk!(uplo, trans, alpha, A, beta, C) +("Parallel Computing","Base","addprocs_sge","addprocs_sge(n) - Methods for complex arrays only. Rank-k update of the Hermitian - matrix \"C\" as \"alpha*A*A' + beta*C\" or \"alpha*A'*A + beta*C\" - according to whether \"trans\" is 'N' or 'T'. When \"uplo\" is 'U' - the upper triangle of \"C\" is updated ('L' for lower triangle). - Returns \"C\". + Add processes via the Sun/Oracle Grid Engine batch queue, using + \"qsub\". "), -(E"BLAS",E"BLAS",E"herk",E"herk(uplo, trans, alpha, A) +("Parallel Computing","Base","nprocs","nprocs() - Methods for complex arrays only. Returns either the upper triangle - or the lower triangle, according to \"uplo\" ('U' or 'L'), of - \"alpha*A*A'\" or \"alpha*A'*A\", according to \"trans\" ('N' or - 'T'). + Get the number of available processors. "), -(E"BLAS",E"BLAS",E"gbmv!",E"gbmv!(trans, m, kl, ku, alpha, A, x, beta, y) +("Parallel Computing","Base","myid","myid() - Update vector \"y\" as \"alpha*A*x + beta*y\" or \"alpha*A'*x + - beta*y\" according to \"trans\" ('N' or 'T'). The matrix \"A\" is - a general band matrix of dimension \"m\" by \"size(A,2)\" with - \"kl\" sub-diagonals and \"ku\" super-diagonals. Returns the - updated \"y\". + Get the id of the current processor. "), -(E"BLAS",E"BLAS",E"gbmv",E"gbmv(trans, m, kl, ku, alpha, A, x, beta, y) +("Parallel Computing","Base","pmap","pmap(f, c) - Returns \"alpha*A*x\" or \"alpha*A'*x\" according to \"trans\" ('N' - or 'T'). The matrix \"A\" is a general band matrix of dimension - \"m\" by \"size(A,2)\" with \"kl\" sub-diagonals and \"ku\" super- - diagonals. + Transform collection \"c\" by applying \"f\" to each element in + parallel. "), -(E"BLAS",E"BLAS",E"sbmv!",E"sbmv!(uplo, k, alpha, A, x, beta, y) +("Parallel Computing","Base","remote_call","remote_call(id, func, args...) - Update vector \"y\" as \"alpha*A*x + beta*y\" where \"A\" is a a - symmetric band matrix of order \"size(A,2)\" with \"k\" super- - diagonals stored in the argument \"A\". The storage layout for - \"A\" is described the reference BLAS module, level-2 BLAS at - **. - - Returns the updated \"y\". + Call a function asynchronously on the given arguments on the + specified processor. Returns a \"RemoteRef\". "), -(E"BLAS",E"BLAS",E"sbmv",E"sbmv(uplo, k, alpha, A, x) +("Parallel Computing","Base","wait","wait(RemoteRef) - Returns \"alpha*A*x\" where \"A\" is a symmetric band matrix of - order \"size(A,2)\" with \"k\" super-diagonals stored in the - argument \"A\". + Wait for a value to become available for the specified remote + reference. "), -(E"BLAS",E"BLAS",E"gemm!",E"gemm!(tA, tB, alpha, A, B, beta, C) +("Parallel Computing","Base","fetch","fetch(RemoteRef) - Update \"C\" as \"alpha*A*B + beta*C\" or the other three variants - according to \"tA\" (transpose \"A\") and \"tB\". Returns the - updated \"C\". + Wait for and get the value of a remote reference. "), -(E"BLAS",E"BLAS",E"gemm",E"gemm(tA, tB, alpha, A, B) +("Parallel Computing","Base","remote_call_wait","remote_call_wait(id, func, args...) - Returns \"alpha*A*B\" or the other three variants according to - \"tA\" (transpose \"A\") and \"tB\". + Perform \"wait(remote_call(...))\" in one message. "), -(E"cpp.jl",E"",E"@cpp",E"@cpp(ccall_expression) +("Parallel Computing","Base","remote_call_fetch","remote_call_fetch(id, func, args...) - Suppose you have a C++ shared library, \"libdemo\", which contains - a function \"timestwo\": + Perform \"fetch(remote_call(...))\" in one message. - int timestwo(int x) { - return 2*x; - } +"), - double timestwo(double x) { - return 2*x; - } +("Parallel Computing","Base","put","put(RemoteRef, value) - You can use these functions by placing the \"@cpp\" macro prior to - a ccall, for example: + Store a value to a remote reference. Implements \"shared queue of + length 1\" semantics: if a value is already present, blocks until + the value is removed with \"take\". - mylib = dlopen(\"libdemo\") - x = 3.5 - x2 = @cpp ccall(dlsym(mylib, :timestwo), Float64, (Float64,), x) - y = 3 - y2 = @cpp ccall(dlsym(mylib, :timestwo), Int, (Int,), y) +"), - The macro performs C++ ABI name-mangling (using the types of the - parameters) to determine the correct library symbol. +("Parallel Computing","Base","take","take(RemoteRef) - Like \"ccall\", this performs library calls without overhead. - However, currently it has a number of limitations: + Fetch the value of a remote reference, removing it so that the + reference is empty again. - * It does not support pure-header libraries +"), - * The restrictions of \"ccall\" apply here; for example, there is - no support for \"struct\". Consequently it is not possible to use - C++ objects. +("Parallel Computing","Base","RemoteRef","RemoteRef() - * Currently there is no C++ namespace support + Make an uninitialized remote reference on the local machine. - * Currently there is no support for templated functions +"), - * Currently only g++ is supported +("Parallel Computing","Base","RemoteRef","RemoteRef(n) - The latter three may not be difficult to fix. + Make an uninitialized remote reference on processor \"n\". "), -(E"GLPK",E"GLPK",E"set_prob_name",E"set_prob_name(glp_prob, name) +("Distributed Arrays","Base","DArray","DArray(init, dims[, procs, dist]) - Assigns a name to the problem object (or deletes it if \"name\" is - empty or \"nothing\"). + Construct a distributed array. \"init\" is a function accepting a + tuple of index ranges. This function should return a chunk of the + distributed array for the specified indexes. \"dims\" is the + overall size of the distributed array. \"procs\" optionally + specifies a vector of processor IDs to use. \"dist\" is an integer + vector specifying how many chunks the distributed array should be + divided into in each dimension. "), -(E"GLPK",E"GLPK",E"set_obj_name",E"set_obj_name(glp_prob, name) +("Distributed Arrays","Base","dzeros","dzeros(dims, ...) - Assigns a name to the objective function (or deletes it if \"name\" - is empty or \"nothing\"). + Construct a distributed array of zeros. Trailing arguments are the + same as those accepted by \"darray\". "), -(E"GLPK",E"GLPK",E"set_obj_dir",E"set_obj_dir(glp_prob, dir) +("Distributed Arrays","Base","dones","dones(dims, ...) - Sets the optimization direction, \"GLPK.MIN\" (minimization) or - \"GLPK.MAX\" (maximization). + Construct a distributed array of ones. Trailing arguments are the + same as those accepted by \"darray\". "), -(E"GLPK",E"GLPK",E"add_rows",E"add_rows(glp_prob, rows) +("Distributed Arrays","Base","dfill","dfill(x, dims, ...) - Adds the given number of rows (constraints) to the problem object; - returns the number of the first new row added. + Construct a distributed array filled with value \"x\". Trailing + arguments are the same as those accepted by \"darray\". "), -(E"GLPK",E"GLPK",E"add_cols",E"add_cols(glp_prob, cols) +("Distributed Arrays","Base","drand","drand(dims, ...) - Adds the given number of columns (structural variables) to the - problem object; returns the number of the first new column added. + Construct a distributed uniform random array. Trailing arguments + are the same as those accepted by \"darray\". "), -(E"GLPK",E"GLPK",E"set_row_name",E"set_row_name(glp_prob, row, name) +("Distributed Arrays","Base","drandn","drandn(dims, ...) - Assigns a name to the specified row (or deletes it if \"name\" is - empty or \"nothing\"). + Construct a distributed normal random array. Trailing arguments are + the same as those accepted by \"darray\". "), -(E"GLPK",E"GLPK",E"set_col_name",E"set_col_name(glp_prob, col, name) +("Distributed Arrays","Base","distribute","distribute(a) - Assigns a name to the specified column (or deletes it if \"name\" - is empty or \"nothing\"). + Convert a local array to distributed "), -(E"GLPK",E"GLPK",E"set_row_bnds",E"set_row_bnds(glp_prob, row, bounds_type, lb, ub) +("Distributed Arrays","Base","localize","localize(d) - Sets the type and bounds on a row. \"type\" must be one of - \"GLPK.FR\" (free), \"GLPK.LO\" (lower bounded), \"GLPK.UP\" (upper - bounded), \"GLPK.DB\" (double bounded), \"GLPK.FX\" (fixed). - - At initialization, each row is free. + Get the local piece of a distributed array "), -(E"GLPK",E"GLPK",E"set_col_bnds",E"set_col_bnds(glp_prob, col, bounds_type, lb, ub) +("Distributed Arrays","Base","myindexes","myindexes(d) - Sets the type and bounds on a column. \"type\" must be one of - \"GLPK.FR\" (free), \"GLPK.LO\" (lower bounded), \"GLPK.UP\" (upper - bounded), \"GLPK.DB\" (double bounded), \"GLPK.FX\" (fixed). - - At initialization, each column is fixed at 0. + A tuple describing the indexes owned by the local processor "), -(E"GLPK",E"GLPK",E"set_obj_coef",E"set_obj_coef(glp_prob, col, coef) +("Distributed Arrays","Base","procs","procs(d) - Sets the objective coefficient to a column (\"col\" can be 0 to - indicate the constant term of the objective function). + Get the vector of processors storing pieces of \"d\" "), -(E"GLPK",E"GLPK",E"set_mat_row",E"set_mat_row(glp_prob, row[, len], ind, val) - - Sets (replaces) the content of a row. The content is specified in - sparse format: \"ind\" is a vector of indices, \"val\" is the - vector of corresponding values. \"len\" is the number of vector - elements which will be considered, and must be less or equal to the - length of both \"ind\" and \"val\". If \"len\" is 0, \"ind\" - and/or \"val\" can be \"nothing\". +("System","Base","run","run(command) - In Julia, \"len\" can be omitted, and then it is inferred from - \"ind\" and \"val\" (which need to have the same length in such - case). + Run a command object, constructed with backticks. Throws an error + if anything goes wrong, including the process exiting with a non- + zero status. "), -(E"GLPK",E"GLPK",E"set_mat_col",E"set_mat_col(glp_prob, col[, len], ind, val) +("System","Base","spawn","spawn(command) - Sets (replaces) the content of a column. Everything else is like - \"set_mat_row\". + Run a command object asynchronously, returning the resulting + \"Process\" object. "), -(E"GLPK",E"GLPK",E"load_matrix",E"load_matrix(glp_prob[, numel], ia, ja, ar) -load_matrix(glp_prob, A) +("System","Base","success","success(command) - Sets (replaces) the content matrix (i.e. sets all rows/coluns at - once). The matrix is passed in sparse format. + Run a command object, constructed with backticks, and tell whether + it was successful (exited with a code of 0). - In the first form (original C API), it's passed via 3 vectors: - \"ia\" and \"ja\" are for rows/columns indices, \"ar\" is for - values. \"numel\" is the number of elements which will be read and - must be less or equal to the length of any of the 3 vectors. If - \"numel\" is 0, any of the vectors can be passed as \"nothing\". +"), - In Julia, \"numel\" can be omitted, and then it is inferred from - \"ia\", \"ja\" and \"ar\" (which need to have the same length in - such case). +("System","Base","readsfrom","readsfrom(command) - Also, in Julia there's a second, simpler calling form, in which the - matrix is passed as a \"SparseMatrixCSC\" object. + Starts running a command asynchronously, and returns a tuple + (stream,process). The first value is a stream reading from the + process' standard output. "), -(E"GLPK",E"GLPK",E"check_dup",E"check_dup(rows, cols[, numel], ia, ja) +("System","Base","writesto","writesto(command) - Check for duplicates in the indices vectors \"ia\" and \"ja\". - \"numel\" has the same meaning and (optional) use as in - \"load_matrix\". Returns 0 if no duplicates/out-of-range indices - are found, or a positive number indicating where a duplicate - occurs, or a negative number indicating an out-of-bounds index. + Starts running a command asynchronously, and returns a tuple + (stream,process). The first value is a stream writing to the + process' standard input. "), -(E"GLPK",E"GLPK",E"sort_matrix",E"sort_matrix(glp_prob) +("System","Base","readandwrite","readandwrite(command) - Sorts the elements of the problem object's matrix. + Starts running a command asynchronously, and returns a tuple + (stdout,stdin,process) of the output stream and input stream of the + process, and the process object itself. "), -(E"GLPK",E"GLPK",E"del_rows",E"del_rows(glp_prob[, num_rows], rows_ids) +("System","Base",">",">() + + Redirect standard output of a process. - Deletes rows from the problem object. Rows are specified in the - \"rows_ids\" vector. \"num_rows\" is the number of elements of - \"rows_ids\" which will be considered, and must be less or equal to - the length id \"rows_ids\". If \"num_rows\" is 0, \"rows_ids\" can - be \"nothing\". In Julia, \"num_rows\" is optional (it's inferred - from \"rows_ids\" if not given). + **Example**: \"run(`ls` > \"out.log\")\" "), -(E"GLPK",E"GLPK",E"del_cols",E"del_cols(glp_prob, cols_ids) +("System","Base","<","<() - Deletes columns from the problem object. See \"del_rows\". + Redirect standard input of a process. "), -(E"GLPK",E"GLPK",E"copy_prob",E"copy_prob(glp_prob_dest, glp_prob, copy_names) +("System","Base",">>",">>() - Makes a copy of the problem object. The flag \"copy_names\" - determines if names are copied, and must be either \"GLPK.ON\" or - \"GLPK.OFF\". + Redirect standard output of a process, appending to the destination + file. "), -(E"GLPK",E"GLPK",E"erase_prob",E"erase_prob(glp_prob) +("System","Base",".>",".>() - Resets the problem object. + Redirect the standard error stream of a process. "), -(E"GLPK",E"GLPK",E"get_prob_name",E"get_prob_name(glp_prob) +("System","Base","gethostname","gethostname() -> String - Returns the problem object's name. Unlike the C version, if the - problem has no assigned name, returns an empty string. + Get the local machine's host name. "), -(E"GLPK",E"GLPK",E"get_obj_name",E"get_obj_name(glp_prob) +("System","Base","getipaddr","getipaddr() -> String - Returns the objective function's name. Unlike the C version, if the - objective has no assigned name, returns an empty string. + Get the IP address of the local machine, as a string of the form + \"x.x.x.x\". "), -(E"GLPK",E"GLPK",E"get_obj_dir",E"get_obj_dir(glp_prob) +("System","Base","pwd","pwd() -> String - Returns the optimization direction, \"GLPK.MIN\" (minimization) or - \"GLPK.MAX\" (maximization). + Get the current working directory. "), -(E"GLPK",E"GLPK",E"get_num_rows",E"get_num_rows(glp_prob) +("System","Base","cd","cd(dir::String) - Returns the current number of rows. + Set the current working directory. Returns the new current + directory. "), -(E"GLPK",E"GLPK",E"get_num_cols",E"get_num_cols(glp_prob) +("System","Base","cd","cd(f[, \"dir\"]) - Returns the current number of columns. + Temporarily changes the current working directory (HOME if not + specified) and applies function f before returning. "), -(E"GLPK",E"GLPK",E"get_row_name",E"get_row_name(glp_prob, row) +("System","Base","mkdir","mkdir(path[, mode]) - Returns the name of the specified row. Unlike the C version, if the - row has no assigned name, returns an empty string. + Make a new directory with name \"path\" and permissions \"mode\". + \"mode\" defaults to 0o777, modified by the current file creation + mask. "), -(E"GLPK",E"GLPK",E"get_col_name",E"get_col_name(glp_prob, col) +("System","Base","mkpath","mkpath(path[, mode]) - Returns the name of the specified column. Unlike the C version, if - the column has no assigned name, returns an empty string. + Create all directories in the given \"path\", with permissions + \"mode\". \"mode\" defaults to 0o777, modified by the current file + creation mask. "), -(E"GLPK",E"GLPK",E"get_row_type",E"get_row_type(glp_prob, row) +("System","Base","rmdir","rmdir(path) - Returns the type of the specified row: \"GLPK.FR\" (free), - \"GLPK.LO\" (lower bounded), \"GLPK.UP\" (upper bounded), - \"GLPK.DB\" (double bounded), \"GLPK.FX\" (fixed). + Remove the directory named \"path\". "), -(E"GLPK",E"GLPK",E"get_row_lb",E"get_row_lb(glp_prob, row) +("System","Base","getpid","getpid() -> Int32 - Returns the lower bound of the specified row, \"-DBL_MAX\" if - unbounded. + Get julia's process ID. "), -(E"GLPK",E"GLPK",E"get_row_ub",E"get_row_ub(glp_prob, row) +("System","Base","time","time() - Returns the upper bound of the specified row, \"+DBL_MAX\" if - unbounded. + Get the system time in seconds since the epoch, with fairly high + (typically, microsecond) resolution. "), -(E"GLPK",E"GLPK",E"get_col_type",E"get_col_type(glp_prob, col) +("System","Base","time_ns","time_ns() - Returns the type of the specified column: \"GLPK.FR\" (free), - \"GLPK.LO\" (lower bounded), \"GLPK.UP\" (upper bounded), - \"GLPK.DB\" (double bounded), \"GLPK.FX\" (fixed). + Get the time in nanoseconds. The time corresponding to 0 is + undefined, and wraps every 5.8 years. "), -(E"GLPK",E"GLPK",E"get_col_lb",E"get_col_lb(glp_prob, col) +("System","Base","tic","tic() - Returns the lower bound of the specified column, \"-DBL_MAX\" if - unbounded. + Set a timer to be read by the next call to \"toc()\" or \"toq()\". + The macro call \"@time expr\" can also be used to time evaluation. "), -(E"GLPK",E"GLPK",E"get_col_ub",E"get_col_ub(glp_prob, col) +("System","Base","toc","toc() - Returns the upper bound of the specified column, \"+DBL_MAX\" if - unbounded. + Print and return the time elapsed since the last \"tic()\". "), -(E"GLPK",E"GLPK",E"get_obj_coef",E"get_obj_coef(glp_prob, col) +("System","Base","toq","toq() - Return the objective coefficient to a column (\"col\" can be 0 to - indicate the constant term of the objective function). + Return, but do not print, the time elapsed since the last + \"tic()\". "), -(E"GLPK",E"GLPK",E"get_num_nz",E"get_num_nz(glp_prob) +("System","Base","EnvHash","EnvHash() -> EnvHash - Return the number of non-zero elements in the constraint matrix. + A singleton of this type provides a hash table interface to + environment variables. "), -(E"GLPK",E"GLPK",E"get_mat_row",E"get_mat_row(glp_prob, row, ind, val) -get_mat_row(glp_prob, row) +("System","Base","ENV","ENV - Returns the contents of a row. In the first form (original C API), - it fills the \"ind\" and \"val\" vectors provided, which must be of - type \"Vector{Int32}\" and \"Vector{Float64}\" respectively, and - have a sufficient length to hold the result (or they can be empty - or \"nothing\", and then they're not filled). It returns the length - of the result. - - In Julia, there's a second, simpler calling form which allocates - and returns the two vectors as \"(ind, val)\". + Reference to the singleton \"EnvHash\", providing a dictionary + interface to system environment variables. "), -(E"GLPK",E"GLPK",E"get_mat_col",E"get_mat_col(glp_prob, col, ind, val) -get_mat_col(glp_prob, col) +("C Interface","Base","ccall","ccall((symbol, library) or fptr, RetType, (ArgType1, ...), ArgVar1, ...) - Returns the contents of a column. See \"get_mat_row\". + Call function in C-exported shared library, specified by (function + name, library) tuple (String or :Symbol). Alternatively, ccall may + be used to call a function pointer returned by dlsym, but note that + this usage is generally discouraged to facilitate future static + compilation. "), -(E"GLPK",E"GLPK",E"create_index",E"create_index(glp_prob) +("C Interface","Base","cfunction","cfunction(fun::Function, RetType::Type, (ArgTypes...)) - Creates the name index (used by \"find_row\", \"find_col\") for the - problem object. + Generate C-callable function pointer from Julia function. "), -(E"GLPK",E"GLPK",E"find_row",E"find_row(glp_prob, name) +("C Interface","Base","dlopen","dlopen(libfile::String[, flags::Integer]) + + Load a shared library, returning an opaque handle. - Finds the numeric id of a row by name. Returns 0 if no row with the - given name is found. + The optional flags argument is a bitwise-or of zero or more of + RTLD_LOCAL, RTLD_GLOBAL, RTLD_LAZY, RTLD_NOW, RTLD_NODELETE, + RTLD_NOLOAD, RTLD_DEEPBIND, and RTLD_FIRST. These are converted to + the corresponding flags of the POSIX (and/or GNU libc and/or MacOS) + dlopen command, if possible, or are ignored if the specified + functionality is not available on the current platform. The + default is RTLD_LAZY|RTLD_DEEPBIND|RTLD_LOCAL. An important usage + of these flags, on POSIX platforms, is to specify + RTLD_LAZY|RTLD_DEEPBIND|RTLD_GLOBAL in order for the library's + symbols to be available for usage in other shared libraries, in + situations where there are dependencies between shared libraries. "), -(E"GLPK",E"GLPK",E"find_col",E"find_col(glp_prob, name) +("C Interface","Base","dlsym","dlsym(handle, sym) - Finds the numeric id of a column by name. Returns 0 if no column - with the given name is found. + Look up a symbol from a shared library handle, return callable + function pointer on success. "), -(E"GLPK",E"GLPK",E"delete_index",E"delete_index(glp_prob) +("C Interface","Base","dlsym_e","dlsym_e(handle, sym) - Deletes the name index for the problem object. + Look up a symbol from a shared library handle, silently return NULL + pointer on lookup failure. "), -(E"GLPK",E"GLPK",E"set_rii",E"set_rii(glp_prob, row, rii) +("C Interface","Base","dlclose","dlclose(handle) - Sets the rii scale factor for the specified row. + Close shared library referenced by handle. "), -(E"GLPK",E"GLPK",E"set_sjj",E"set_sjj(glp_prob, col, sjj) +("C Interface","Base","c_free","c_free(addr::Ptr) - Sets the sjj scale factor for the specified column. + Call free() from C standard library. "), -(E"GLPK",E"GLPK",E"get_rii",E"get_rii(glp_prob, row) +("C Interface","Base","unsafe_ref","unsafe_ref(p::Ptr{T}, i::Integer) - Returns the rii scale factor for the specified row. + Dereference the pointer \"p[i]\" or \"*p\", returning a copy of + type T. "), -(E"GLPK",E"GLPK",E"get_sjj",E"get_sjj(glp_prob, col) +("C Interface","Base","unsafe_assign","unsafe_assign(p::Ptr{T}, x, i::Integer) - Returns the sjj scale factor for the specified column. + Assign to the pointer \"p[i] = x\" or \"*p = x\", making a copy of + object x into the memory at p. "), -(E"GLPK",E"GLPK",E"scale_prob",E"scale_prob(glp_prob, flags) +("C Interface","Base","pointer","pointer(a[, index]) - Performs automatic scaling of problem data for the problem object. - The parameter \"flags\" can be \"GLPK.SF_AUTO\" (automatic) or a - bitwise OR of the forllowing: \"GLPK.SF_GM\" (geometric mean), - \"GLPK.SF_EQ\" (equilibration), \"GLPK.SF_2N\" (nearest power of - 2), \"GLPK.SF_SKIP\" (skip if well scaled). + Get the native address of an array element. Be careful to ensure + that a julia reference to \"a\" exists as long as this pointer will + be used. "), -(E"GLPK",E"GLPK",E"unscale_prob",E"unscale_prob(glp_prob) +("C Interface","Base","pointer","pointer(type, int) - Unscale the problem data (cancels the scaling effect). + Convert an integer to a pointer of the specified element type. "), -(E"GLPK",E"GLPK",E"set_row_stat",E"set_row_stat(glp_prob, row, stat) +("C Interface","Base","pointer_to_array","pointer_to_array(p, dims[, own]) - Sets the status of the specified row. \"stat\" must be one of: - \"GLPK.BS\" (basic), \"GLPK.NL\" (non-basic lower bounded), - \"GLPK.NU\" (non-basic upper-bounded), \"GLPK.NF\" (non-basic - free), \"GLPK.NS\" (non-basic fixed). + Wrap a native pointer as a Julia Array object. The pointer element + type determines the array element type. \"own\" optionally + specifies whether Julia should take ownership of the memory, + calling \"free\" on the pointer when the array is no longer + referenced. "), -(E"GLPK",E"GLPK",E"set_col_stat",E"set_col_stat(glp_prob, col, stat) +("Errors","Base","error","error(message::String) - Sets the status of the specified column. \"stat\" must be one of: - \"GLPK.BS\" (basic), \"GLPK.NL\" (non-basic lower bounded), - \"GLPK.NU\" (non-basic upper-bounded), \"GLPK.NF\" (non-basic - free), \"GLPK.NS\" (non-basic fixed). + Raise an error with the given message "), -(E"GLPK",E"GLPK",E"std_basis",E"std_basis(glp_prob) +("Errors","Base","throw","throw(e) - Constructs the standard (trivial) initial LP basis for the problem - object. + Throw an object as an exception "), -(E"GLPK",E"GLPK",E"adv_basis",E"adv_basis(glp_prob[, flags]) +("Errors","Base","errno","errno() - Constructs an advanced initial LP basis for the problem object. The - flag \"flags\" is optional; it must be 0 if given. + Get the value of the C library's \"errno\" "), -(E"GLPK",E"GLPK",E"cpx_basis",E"cpx_basis(glp_prob) +("Errors","Base","strerror","strerror(n) - Constructs an initial LP basis for the problem object with the - algorithm proposed by R. Bixby. + Convert a system call error code to a descriptive string "), -(E"GLPK",E"GLPK",E"simplex",E"simplex(glp_prob[, glp_param]) +("Errors","Base","assert","assert(cond) - The routine \"simplex\" is a driver to the LP solver based on the - simplex method. This routine retrieves problem data from the - specified problem object, calls the solver to solve the problem - instance, and stores results of computations back into the problem - object. + Raise an error if \"cond\" is false. Also available as the macro + \"@assert expr\". - The parameters are specified via the optional \"glp_param\" - argument, which is of type \"GLPK.SimplexParam\" (or \"nothing\" to - use the default settings). +"), - Returns 0 in case of success, or a non-zero flag specifying the - reason for failure: \"GLPK.EBADB\" (invalid base), \"GLPK.ESING\" - (singular matrix), \"GLPK.ECOND\" (ill-conditioned matrix), - \"GLPK.EBOUND\" (incorrect bounds), \"GLPK.EFAIL\" (solver - failure), \"GLPK.EOBJLL\" (lower limit reached), \"GLPK.EOBJUL\" - (upper limit reached), \"GLPK.ITLIM\" (iterations limit exceeded), - \"GLPK.ETLIM\" (time limit exceeded), \"GLPK.ENOPFS\" (no primal - feasible solution), \"GLPK.ENODFS\" (no dual feasible solution). +("Tasks","Base","Task","Task(func) -"), + Create a \"Task\" (i.e. thread, or coroutine) to execute the given + function. The task exits when this function returns. -(E"GLPK",E"GLPK",E"exact",E"exact(glp_prob[, glp_param]) +"), - A tentative implementation of the primal two-phase simplex method - based on exact (rational) arithmetic. Similar to \"simplex\". The - optional \"glp_param\" is of type \"GLPK.SimplexParam\". +("Tasks","Base","yieldto","yieldto(task, args...) - The possible return values are \"0\" (success) or \"GLPK.EBADB\", - \"GLPK.ESING\", \"GLPK.EBOUND\", \"GLPK.EFAIL\", \"GLPK.ITLIM\", - \"GLPK.ETLIM\" (see \"simplex()\"). + Switch to the given task. The first time a task is switched to, the + task's function is called with \"args\". On subsequent switches, + \"args\" are returned from the task's last call to \"yieldto\". "), -(E"GLPK",E"GLPK",E"init_smcp",E"init_smcp(glp_param) +("Tasks","Base","current_task","current_task() - Initializes a \"GLPK.SimplexParam\" object with the default values. - In Julia, this is done at object creation time; this function can - be used to reset the object. + Get the currently running Task. "), -(E"GLPK",E"GLPK",E"get_status",E"get_status(glp_prob) +("Tasks","Base","istaskdone","istaskdone(task) - Returns the generic status of the current basic solution: - \"GLPK.OPT\" (optimal), \"GLPK.FEAS\" (feasible), \"GLPK.INFEAS\" - (infeasible), \"GLPK.NOFEAS\" (no feasible solution), - \"GLPK.UNBND\" (unbounded solution), \"GLPK.UNDEF\" (undefined). + Tell whether a task has exited. "), -(E"GLPK",E"GLPK",E"get_prim_stat",E"get_prim_stat(glp_prob) +("Tasks","Base","consume","consume(task) - Returns the status of the primal basic solution: \"GLPK.FEAS\", - \"GLPK.INFEAS\", \"GLPK.NOFEAS\", \"GLPK.UNDEF\" (see - \"get_status()\"). + Receive the next value passed to \"produce\" by the specified task. "), -(E"GLPK",E"GLPK",E"get_dual_stat",E"get_dual_stat(glp_prob) +("Tasks","Base","produce","produce(value) - Returns the status of the dual basic solution: \"GLPK.FEAS\", - \"GLPK.INFEAS\", \"GLPK.NOFEAS\", \"GLPK.UNDEF\" (see - \"get_status()\"). + Send the given value to the last \"consume\" call, switching to the + consumer task. "), -(E"GLPK",E"GLPK",E"get_obj_val",E"get_obj_val(glp_prob) +("Tasks","Base","make_scheduled","make_scheduled(task) - Returns the current value of the objective function. + Register a task with the main event loop, so it will automatically + run when possible. "), -(E"GLPK",E"GLPK",E"get_row_stat",E"get_row_stat(glp_prob, row) +("Tasks","Base","yield","yield() - Returns the status of the specified row: \"GLPK.BS\", \"GLPK.NL\", - \"GLPK.NU\", \"GLPK.NF\", \"GLPK.NS\" (see \"set_row_stat()\"). + For scheduled tasks, switch back to the scheduler to allow another + scheduled task to run. "), -(E"GLPK",E"GLPK",E"get_row_prim",E"get_row_prim(glp_prob, row) +("Tasks","Base","tls","tls(symbol) - Returns the primal value of the specified row. + Look up the value of a symbol in the current task's task-local + storage. "), -(E"GLPK",E"GLPK",E"get_row_dual",E"get_row_dual(glp_prob, row) +("Tasks","Base","tls","tls(symbol, value) - Returns the dual value (reduced cost) of the specified row. + Assign a value to a symbol in the current task's task-local + storage. "), -(E"GLPK",E"GLPK",E"get_col_stat",E"get_col_stat(glp_prob, col) +("Constants","Base","OS_NAME","OS_NAME - Returns the status of the specified column: \"GLPK.BS\", - \"GLPK.NL\", \"GLPK.NU\", \"GLPK.NF\", \"GLPK.NS\" (see - \"set_row_stat()\"). + A symbol representing the name of the operating system. Possible + values are \":Linux\", \":Darwin\" (OS X), or \":Windows\". "), -(E"GLPK",E"GLPK",E"get_col_prim",E"get_col_prim(glp_prob, col) +("Constants","Base","ARGS","ARGS - Returns the primal value of the specified column. + An array of the command line arguments passed to Julia, as strings. "), -(E"GLPK",E"GLPK",E"get_col_dual",E"get_col_dual(glp_prob, col) +("Constants","Base","C_NULL","C_NULL - Returns the dual value (reduced cost) of the specified column. + The C null pointer constant, sometimes used when calling external + code. "), -(E"GLPK",E"GLPK",E"get_unbnd_ray",E"get_unbnd_ray(glp_prob) +("Constants","Base","CPU_CORES","CPU_CORES - Returns the number k of a variable, which causes primal or dual - unboundedness (if 1 <= k <= rows it's row k; if rows+1 <= k <= - rows+cols it's column k-rows, if k=0 such variable is not defined). + The number of CPU cores in the system. "), -(E"GLPK",E"GLPK",E"interior",E"interior(glp_prob[, glp_param]) +("Constants","Base","WORD_SIZE","WORD_SIZE + + Standard word size on the current machine, in bits. - The routine \"interior\" is a driver to the LP solver based on the - primal-dual interior-point method. This routine retrieves problem - data from the specified problem object, calls the solver to solve - the problem instance, and stores results of computations back into - the problem object. +"), - The parameters are specified via the optional \"glp_param\" - argument, which is of type \"GLPK.InteriorParam\" (or \"nothing\" - to use the default settings). +("Constants","Base","VERSION","VERSION - Returns 0 in case of success, or a non-zero flag specifying the - reason for failure: \"GLPK.EFAIL\" (solver failure), - \"GLPK.ENOCVG\" (very slow convergence, or divergence), - \"GLPK.ITLIM\" (iterations limit exceeded), \"GLPK.EINSTAB\" - (numerical instability). + An object describing which version of Julia is in use. "), -(E"GLPK",E"GLPK",E"init_iptcp",E"init_iptcp(glp_param) +("Constants","Base","LOAD_PATH","LOAD_PATH - Initializes a \"GLPK.InteriorParam\" object with the default - values. In Julia, this is done at object creation time; this - function can be used to reset the object. + An array of paths (as strings) where the \"require\" function looks + for code. "), -(E"GLPK",E"GLPK",E"ipt_status",E"ipt_status(glp_prob) +("Filesystem","Base","isblockdev","isblockdev(path) -> Bool - Returns the status of the interior-point solution: \"GLPK.OPT\" - (optimal), \"GLPK.INFEAS\" (infeasible), \"GLPK.NOFEAS\" (no - feasible solution), \"GLPK.UNDEF\" (undefined). + Returns \"true\" if \"path\" is a block device, \"false\" + otherwise. "), -(E"GLPK",E"GLPK",E"ipt_obj_val",E"ipt_obj_val(glp_prob) +("Filesystem","Base","ischardev","ischardev(path) -> Bool - Returns the current value of the objective function for the - interior-point solution. + Returns \"true\" if \"path\" is a character device, \"false\" + otherwise. "), -(E"GLPK",E"GLPK",E"ipt_row_prim",E"ipt_row_prim(glp_prob, row) +("Filesystem","Base","isdir","isdir(path) -> Bool - Returns the primal value of the specified row for the interior- - point solution. + Returns \"true\" if \"path\" is a directory, \"false\" otherwise. "), -(E"GLPK",E"GLPK",E"ipt_row_dual",E"ipt_row_dual(glp_prob, row) +("Filesystem","Base","isexecutable","isexecutable(path) -> Bool - Returns the dual value (reduced cost) of the specified row for the - interior-point solution. + Returns \"true\" if the current user has permission to execute + \"path\", \"false\" otherwise. "), -(E"GLPK",E"GLPK",E"ipt_col_prim",E"ipt_col_prim(glp_prob, col) +("Filesystem","Base","isfifo","isfifo(path) -> Bool - Returns the primal value of the specified column for the interior- - point solution. + Returns \"true\" if \"path\" is a FIFO, \"false\" otherwise. "), -(E"GLPK",E"GLPK",E"ipt_col_dual",E"ipt_col_dual(glp_prob, col) +("Filesystem","Base","isfile","isfile(path) -> Bool - Returns the dual value (reduced cost) of the specified column for - the interior-point solution. + Returns \"true\" if \"path\" is a regular file, \"false\" + otherwise. "), -(E"GLPK",E"GLPK",E"set_col_kind",E"set_col_kind(glp_prob, col, kind) +("Filesystem","Base","islink","islink(path) -> Bool - Sets the kind for the specified column (for mixed-integer - programming). \"kind\" must be one of: \"GLPK.CV\" (continuous), - \"GLPK.IV\" (integer), \"GLPK.BV\" (binary, 0/1). + Returns \"true\" if \"path\" is a symbolic link, \"false\" + otherwise. "), -(E"GLPK",E"GLPK",E"get_col_kind",E"get_col_kind(glp_prob, col) +("Filesystem","Base","ispath","ispath(path) -> Bool - Returns the kind for the specified column (see \"set_col_kind()\"). + Returns \"true\" if \"path\" is a valid filesystem path, \"false\" + otherwise. "), -(E"GLPK",E"GLPK",E"get_num_int",E"get_num_int(glp_prob) +("Filesystem","Base","isreadable","isreadable(path) -> Bool - Returns the number of columns marked as integer (including binary). + Returns \"true\" if the current user has permission to read + \"path\", \"false\" otherwise. "), -(E"GLPK",E"GLPK",E"get_num_bin",E"get_num_bin(glp_prob) +("Filesystem","Base","issetgid","issetgid(path) -> Bool - Returns the number of columns marked binary. + Returns \"true\" if \"path\" has the setgid flag set, \"false\" + otherwise. "), -(E"GLPK",E"GLPK",E"intopt",E"intopt(glp_prob[, glp_param]) +("Filesystem","Base","issetuid","issetuid(path) -> Bool + + Returns \"true\" if \"path\" has the setuid flag set, \"false\" + otherwise. - The routine \"intopt\" is a driver to the mixed-integer-programming - (MIP) solver based on the branch- and-cut method, which is a hybrid - of branch-and-bound and cutting plane methods. +"), - The parameters are specified via the optional \"glp_param\" - argument, which is of type \"GLPK.IntoptParam\" (or \"nothing\" to - use the default settings). +("Filesystem","Base","issocket","issocket(path) -> Bool - Returns 0 in case of success, or a non-zero flag specifying the - reason for failure: \"GLPK.EBOUND\" (incorrect bounds), - \"GLPK.EROOT\" (no optimal LP basis given), \"GLPK.ENOPFS\" (no - primal feasible LP solution), \"GLPK.ENODFS\" (no dual feasible LP - solution), \"GLPK.EFAIL\" (solver failure), \"GLPK.EMIPGAP\" (mip - gap tolearance reached), \"GLPK.ETLIM\" (time limit exceeded), - \"GLPK.ESTOP\" (terminated by application). + Returns \"true\" if \"path\" is a socket, \"false\" otherwise. "), -(E"GLPK",E"GLPK",E"init_iocp",E"init_iocp(glp_param) +("Filesystem","Base","issticky","issticky(path) -> Bool - Initializes a \"GLPK.IntoptParam\" object with the default values. - In Julia, this is done at object creation time; this function can - be used to reset the object. + Returns \"true\" if \"path\" has the sticky bit set, \"false\" + otherwise. "), -(E"GLPK",E"GLPK",E"mip_status",E"mip_status(glp_prob) +("Filesystem","Base","iswriteable","iswriteable(path) -> Bool - Returns the generic status of the MIP solution: \"GLPK.OPT\" - (optimal), \"GLPK.FEAS\" (feasible), \"GLPK.NOFEAS\" (no feasible - solution), \"GLPK.UNDEF\" (undefined). + Returns \"true\" if the current user has permission to write to + \"path\", \"false\" otherwise. "), -(E"GLPK",E"GLPK",E"mip_obj_val",E"mip_obj_val(glp_prob) +("Filesystem","Base","dirname","dirname(path::String) -> String - Returns the current value of the objective function for the MIP - solution. + Get the directory part of a path. "), -(E"GLPK",E"GLPK",E"mip_row_val",E"mip_row_val(glp_prob, row) +("Filesystem","Base","basename","basename(path::String) -> String - Returns the value of the specified row for the MIP solution. + Get the file name part of a path. "), -(E"GLPK",E"GLPK",E"mip_col_val",E"mip_col_val(glp_prob, col) +("Filesystem","Base","isabspath","isabspath(path::String) -> Bool - Returns the value of the specified column for the MIP solution. + Determines whether a path is absolute (begins at the root + directory). "), -(E"GLPK",E"GLPK",E"read_mps",E"read_mps(glp_prob, format[, param], filename) - - Reads problem data in MPS format from a text file. \"format\" must - be one of \"GLPK.MPS_DECK\" (fixed, old) or \"GLPK.MPS_FILE\" - (free, modern). \"param\" is optional; if given it must be - \"nothing\". +("Filesystem","Base","joinpath","joinpath(parts...) -> String - Returns 0 upon success; throws an error in case of failure. + Join path components into a full path. If some argument is an + absolute path, then prior components are dropped. "), -(E"GLPK",E"GLPK",E"write_mps",E"write_mps(glp_prob, format[, param], filename) +("Filesystem","Base","abspath","abspath(path::String) -> String - Writes problem data in MPS format from a text file. See - \"read_mps\". - - Returns 0 upon success; throws an error in case of failure. + Convert a path to an absolute path by adding the current directory + if necessary. "), -(E"GLPK",E"GLPK",E"read_lp",E"read_lp(glp_prob[, param], filename) - - Reads problem data in CPLEX LP format from a text file. \"param\" - is optional; if given it must be \"nothing\". +("Filesystem","Base","tempname","tempname() - Returns 0 upon success; throws an error in case of failure. + Generate a unique temporary filename. "), -(E"GLPK",E"GLPK",E"write_lp",E"write_lp(glp_prob[, param], filename) +("Filesystem","Base","tempdir","tempdir() - Writes problem data in CPLEX LP format from a text file. See - \"read_lp\". - - Returns 0 upon success; throws an error in case of failure. + Obtain the path of a temporary directory. "), -(E"GLPK",E"GLPK",E"read_prob",E"read_prob(glp_prob[, flags], filename) - - Reads problem data in GLPK LP/MIP format from a text file. - \"flags\" is optional; if given it must be 0. +("Filesystem","Base","mktemp","mktemp() - Returns 0 upon success; throws an error in case of failure. + Returns \"(path, io)\", where \"path\" is the path of a new + temporary file and \"io\" is an open file object for this path. "), -(E"GLPK",E"GLPK",E"write_prob",E"write_prob(glp_prob[, flags], filename) +("Filesystem","Base","mktempdir","mktempdir() - Writes problem data in GLPK LP/MIP format from a text file. See - \"read_prob\". - - Returns 0 upon success; throws an error in case of failure. + Create a temporary directory and return its path. "), -(E"GLPK",E"GLPK",E"mpl_read_model",E"mpl_read_model(glp_tran, filename, skip) - Reads the model section and, optionally, the data section, from a - text file in MathProg format, and stores it in \"glp_tran\", which - is a \"GLPK.MathProgWorkspace\" object. If \"skip\" is nonzero, the - data section is skipped if present. +("Linear Algebra","","*","*(A, B) - Returns 0 upon success; throws an error in case of failure. + Matrix multiplication "), -(E"GLPK",E"GLPK",E"mpl_read_data",E"mpl_read_data(glp_tran, filename) +("Linear Algebra","","\\","\\(A, B) - Reads data section from a text file in MathProg format and stores - it in \"glp_tran\", which is a \"GLPK.MathProgWorkspace\" object. - May be called more than once. - - Returns 0 upon success; throws an error in case of failure. + Matrix division using a polyalgorithm. For input matrices \"A\" and + \"B\", the result \"X\" is such that \"A*X == B\" when \"A\" is + square. The solver that is used depends upon the structure of + \"A\". A direct solver is used for upper- or lower triangular + \"A\". For Hermitian \"A\" (equivalent to symmetric \"A\" for non- + complex \"A\") the BunchKaufman factorization is used. Otherwise + an LU factorization is used. For rectangular \"A\" the result is + the minimum-norm least squares solution computed by reducing \"A\" + to bidiagonal form and solving the bidiagonal least squares + problem. For sparse, square \"A\" the LU factorization (from + UMFPACK) is used. "), -(E"GLPK",E"GLPK",E"mpl_generate",E"mpl_generate(glp_tran[, filename]) +("Linear Algebra","","dot","dot(x, y) - Generates the model using its description stored in the - \"GLPK.MathProgWorkspace\" translator workspace \"glp_tran\". The - optional \"filename\" specifies an output file; if not given or - \"nothing\", the terminal is used. - - Returns 0 upon success; throws an error in case of failure. + Compute the dot product "), -(E"GLPK",E"GLPK",E"mpl_build_prob",E"mpl_build_prob(glp_tran, glp_prob) +("Linear Algebra","","cross","cross(x, y) - Transfer information from the \"GLPK.MathProgWorkspace\" translator - workspace \"glp_tran\" to the \"GLPK.Prob\" problem object - \"glp_prob\". + Compute the cross product of two 3-vectors "), -(E"GLPK",E"GLPK",E"mpl_postsolve",E"mpl_postsolve(glp_tran, glp_prob, sol) +("Linear Algebra","","norm","norm(a) + + Compute the norm of a \"Vector\" or a \"Matrix\" - Copies the solution from the \"GLPK.Prob\" problem object - \"glp_prob\" to the \"GLPK.MathProgWorkspace\" translator workspace - \"glp_tran\" and then executes all the remaining model statements, - which follow the solve statement. +"), - The parameter \"sol\" specifies which solution should be copied - from the problem object to the workspace: \"GLPK.SOL\" (basic), - \"GLPK.IPT\" (interior-point), \"GLPK.MIP\" (MIP). +("Linear Algebra","","lu","lu(A) -> L, U, P - Returns 0 upon success; throws an error in case of failure. + Compute the LU factorization of \"A\", such that \"P*A = L*U\". "), -(E"GLPK",E"GLPK",E"print_sol",E"print_sol(glp_prob, filename) +("Linear Algebra","","lufact","lufact(A) -> LU - Writes the current basic solution to a text file, in printable - format. - - Returns 0 upon success; throws an error in case of failure. + Compute the LU factorization of \"A\", returning an \"LU\" object + for dense \"A\" or an \"UmfpackLU\" object for sparse \"A\". The + individual components of the factorization \"F\" can be accesed by + indexing: \"F[:L]\", \"F[:U]\", and \"F[:P]\" (permutation matrix) + or \"F[:p]\" (permutation vector). An \"UmfpackLU\" object has + additional components \"F[:q]\" (the left permutation vector) and + \"Rs\" the vector of scaling factors. The following functions are + available for both \"LU\" and \"UmfpackLU\" objects: \"size\", + \"\\\" and \"det\". For \"LU\" there is also an \"inv\" method. + The sparse LU factorization is such that \"L*U\" is equal + to``diagmm(Rs,A)[p,q]``. "), -(E"GLPK",E"GLPK",E"read_sol",E"read_sol(glp_prob, filename) - - Reads the current basic solution from a text file, in the format - used by \"write_sol\". +("Linear Algebra","","lufact!","lufact!(A) -> LU - Returns 0 upon success; throws an error in case of failure. + \"lufact!\" is the same as \"lufact\" but saves space by + overwriting the input A, instead of creating a copy. For sparse + \"A\" the \"nzval\" field is not overwritten but the index fields, + \"colptr\" and \"rowval\" are decremented in place, converting from + 1-based indices to 0-based indices. "), -(E"GLPK",E"GLPK",E"write_sol",E"write_sol(glp_prob, filename) +("Linear Algebra","","chol","chol(A[, LU]) -> F - Writes the current basic solution from a text file, in a format - which can be read by \"read_sol\". - - Returns 0 upon success; throws an error in case of failure. + Compute Cholesky factorization of a symmetric positive-definite + matrix \"A\" and return the matrix \"F\". If \"LU\" is \"L\" + (Lower), \"A = L*L'\". If \"LU\" is \"U\" (Upper), \"A = R'*R\". "), -(E"GLPK",E"GLPK",E"print_ipt",E"print_ipt(glp_prob, filename) - - Writes the current interior-point solution to a text file, in - printable format. +("Linear Algebra","","cholfact","cholfact(A[, LU]) -> Cholesky - Returns 0 upon success; throws an error in case of failure. + Compute the Cholesky factorization of a dense symmetric positive- + definite matrix \"A\" and return a \"Cholesky\" object. \"LU\" may + be 'L' for using the lower part or 'U' for the upper part. The + default is to use 'U'. The triangular matrix can be obtained from + the factorization \"F\" with: \"F[:L]\" and \"F[:U]\". The + following functions are available for \"Cholesky\" objects: + \"size\", \"\\\", \"inv\", \"det\". A \"LAPACK.PosDefException\" + error is thrown in case the matrix is not positive definite. "), -(E"GLPK",E"GLPK",E"read_ipt",E"read_ipt(glp_prob, filename) +("Linear Algebra","","cholfact","cholfact(A[, ll]) -> CholmodFactor - Reads the current interior-point solution from a text file, in the - format used by \"write_ipt\". - - Returns 0 upon success; throws an error in case of failure. + Compute the sparse Cholesky factorization of a sparse matrix \"A\". + If \"A\" is Hermitian its Cholesky factor is determined. If \"A\" + is not Hermitian the Cholesky factor of \"A*A'\" is determined. A + fill-reducing permutation is used. Methods for \"size\", + \"solve\", \"\\\", \"findn_nzs\", \"diag\", \"det\" and \"logdet\". + One of the solve methods includes an integer argument that can be + used to solve systems involving parts of the factorization only. + The optional boolean argument, \"ll\" determines whether the + factorization returned is of the \"A[p,p] = L*L'\" form, where + \"L\" is lower triangular or \"A[p,p] = diagmm(L,D)*L'\" form where + \"L\" is unit lower triangular and \"D\" is a non-negative vector. + The default is LDL. "), -(E"GLPK",E"GLPK",E"write_ipt",E"write_ipt(glp_prob, filename) - - Writes the current interior-point solution from a text file, in a - format which can be read by \"read_ipt\". +("Linear Algebra","","cholfact!","cholfact!(A[, LU]) -> Cholesky - Returns 0 upon success; throws an error in case of failure. + \"cholfact!\" is the same as \"cholfact\" but saves space by + overwriting the input A, instead of creating a copy. "), -(E"GLPK",E"GLPK",E"print_mip",E"print_mip(glp_prob, filename) +("Linear Algebra","","cholpfact","cholpfact(A[, LU]) -> CholeskyPivoted - Writes the current MIP solution to a text file, in printable - format. - - Returns 0 upon success; throws an error in case of failure. + Compute the pivoted Cholesky factorization of a symmetric positive + semi-definite matrix \"A\" and return a \"CholeskyPivoted\" object. + \"LU\" may be 'L' for using the lower part or 'U' for the upper + part. The default is to use 'U'. The triangular factors containted + in the factorization \"F\" can be obtained with \"F[:L]\" and + \"F[:U]\", whereas the permutation can be obtained with \"F[:P]\" + or \"F[:p]\". The following functions are available for + \"CholeskyPivoted\" objects: \"size\", \"\\\", \"inv\", \"det\". A + \"LAPACK.RankDeficientException\" error is thrown in case the + matrix is rank deficient. "), -(E"GLPK",E"GLPK",E"read_mip",E"read_mip(glp_prob, filename) - - Reads the current MIP solution from a text file, in the format used - by \"write_mip\". +("Linear Algebra","","cholpfact!","cholpfact!(A[, LU]) -> CholeskyPivoted - Returns 0 upon success; throws an error in case of failure. + \"cholpfact!\" is the same as \"cholpfact\" but saves space by + overwriting the input A, instead of creating a copy. "), -(E"GLPK",E"GLPK",E"write_mip",E"write_mip(glp_prob, filename) +("Linear Algebra","","qr","qr(A[, thin]) -> Q, R - Writes the current MIP solution from a text file, in a format which - can be read by \"read_mip\". - - Returns 0 upon success; throws an error in case of failure. + Compute the QR factorization of \"A\" such that \"A = Q*R\". Also + see \"qrfact\". The default is to compute a thin factorization. "), -(E"GLPK",E"GLPK",E"print_ranges",E"print_ranges(glp_prob, [[len,] list,] [flags,] filename) +("Linear Algebra","","qrfact","qrfact(A) + + Compute the QR factorization of \"A\" and return a \"QR\" object. + The coomponents of the factorization \"F\" can be accessed as + follows: the orthogonal matrix \"Q\" can be extracted with + \"F[:Q]\" and the triangular matrix \"R\" with \"F[:R]\". The + following functions are available for \"QR\" objects: \"size\", + \"\\\". When \"Q\" is extracted, the resulting type is the + \"QRPackedQ\" object, and has the \"*\" operator overloaded to + support efficient multiplication by \"Q\" and \"Q'\". - Performs sensitivity analysis of current optimal basic solution and - writes the analysis report in human-readable format to a text file. - \"list\" is a vector specifying the rows/columns to analyze (if 1 - <= list[i] <= rows, analyzes row list[i]; if rows+1 <= list[i] <= - rows+cols, analyzes column list[i]-rows). \"len\" is the number of - elements of \"list\" which will be consideres, and must be smaller - or equal to the length of the list. In Julia, \"len\" is optional - (it's inferred from \"len\" if not given). \"list\" can be empty of - \"nothing\" or not given at all, implying all indices will be - analyzed. \"flags\" is optional, and must be 0 if given. +"), - To call this function, the current basic solution must be optimal, - and the basis factorization must exist. +("Linear Algebra","","qrfact!","qrfact!(A) - Returns 0 upon success, non-zero otherwise. + \"qrfact!\" is the same as \"qrfact\" but saves space by + overwriting the input A, instead of creating a copy. "), -(E"GLPK",E"GLPK",E"bf_exists",E"bf_exists(glp_prob) +("Linear Algebra","","qrp","qrp(A[, thin]) -> Q, R, P - Returns non-zero if the basis fatorization for the current basis - exists, 0 otherwise. + Compute the QR factorization of \"A\" with pivoting, such that + \"A*P = Q*R\", Also see \"qrpfact\". The default is to compute a + thin factorization. "), -(E"GLPK",E"GLPK",E"factorize",E"factorize(glp_prob) - - Computes the basis factorization for the current basis. +("Linear Algebra","","qrpfact","qrpfact(A) -> QRPivoted - Returns 0 if successful, otherwise: \"GLPK.EBADB\" (invalid - matrix), \"GLPK.ESING\" (singluar matrix), \"GLPK.ECOND\" (ill- - conditioned matrix). + Compute the QR factorization of \"A\" with pivoting and return a + \"QRPivoted\" object. The components of the factorization \"F\" can + be accessed as follows: the orthogonal matrix \"Q\" can be + extracted with \"F[:Q]\", the triangular matrix \"R\" with + \"F[:R]\", and the permutation with \"F[:P]\" or \"F[:p]\". The + following functions are available for \"QRPivoted\" objects: + \"size\", \"\\\". When \"Q\" is extracted, the resulting type is + the \"QRPivotedQ\" object, and has the \"*\" operator overloaded to + support efficient multiplication by \"Q\" and \"Q'\". A + \"QRPivotedQ\" matrix can be converted into a regular matrix with + \"full\". "), -(E"GLPK",E"GLPK",E"bf_updated",E"bf_updated(glp_prob) +("Linear Algebra","","qrpfact!","qrpfact!(A) -> QRPivoted - Returns 0 if the basis factorization was computed from scratch, - non-zero otherwise. + \"qrpfact!\" is the same as \"qrpfact\" but saves space by + overwriting the input A, instead of creating a copy. "), -(E"GLPK",E"GLPK",E"get_bfcp",E"get_bfcp(glp_prob, glp_param) +("Linear Algebra","","sqrtm","sqrtm(A) - Retrieves control parameters, which are used on computing and - updating the basis factorization associated with the problem - object, and stores them in the \"GLPK.BasisFactParam\" object - \"glp_param\". + Compute the matrix square root of \"A\". If \"B = sqrtm(A)\", then + \"B*B == A\" within roundoff error. "), -(E"GLPK",E"GLPK",E"set_bfcp",E"set_bfcp(glp_prob[, glp_param]) +("Linear Algebra","","eig","eig(A) -> D, V - Sets the control parameters stored in the \"GLPK.BasisFactParam\" - object \"glp_param\" into the problem object. If \"glp_param\" is - \"nothing\" or is omitted, resets the parameters to their defaults. - - The \"glp_param\" should always be retreived via \"get_bfcp\" - before changing its values and calling this function. + Compute eigenvalues and eigenvectors of A "), -(E"GLPK",E"GLPK",E"get_bhead",E"get_bhead(glp_prob, k) +("Linear Algebra","","eigvals","eigvals(A) - Returns the basis header information for the current basis. \"k\" - is a row index. - - Returns either i such that 1 <= i <= rows, if \"k\" corresponds to - i-th auxiliary variable, or rows+j such that 1 <= j <= columns, if - \"k\" corresponds to the j-th structural variable. + Returns the eigenvalues of \"A\". "), -(E"GLPK",E"GLPK",E"get_row_bind",E"get_row_bind(glp_prob, row) +("Linear Algebra","","eigmax","eigmax(A) - Returns the index of the basic variable \"k\" which is associated - with the specified row, or \"0\" if the variable is non-basic. If - \"GLPK.get_bhead(glp_prob, k) == row\", then - \"GLPK.get_bind(glp_prob, row) = k\". + Returns the largest eigenvalue of \"A\". "), -(E"GLPK",E"GLPK",E"get_col_bind",E"get_col_bind(glp_prob, col) +("Linear Algebra","","eigmin","eigmin(A) - Returns the index of the basic variable \"k\" which is associated - with the specified column, or \"0\" if the variable is non-basic. - If \"GLPK.get_bhead(glp_prob, k) == rows+col\", then - \"GLPK.get_bind(glp_prob, col) = k\". + Returns the smallest eigenvalue of \"A\". "), -(E"GLPK",E"GLPK",E"ftran",E"ftran(glp_prob, v) +("Linear Algebra","","eigvecs","eigvecs(A[, eigvals]) - Performs forward transformation (FTRAN), i.e. it solves the system - Bx = b, where B is the basis matrix, x is the vector of unknowns to - be computed, b is the vector of right-hand sides. At input, \"v\" - represents the vector b; at output, it contains the vector x. \"v\" - must be a \"Vector{Float64}\" whose length is the number of rows. + Returns the eigenvectors of \"A\". + + For SymTridiagonal matrices, if the optional vector of eigenvalues + \"eigvals\" is specified, returns the specific corresponding + eigenvectors. "), -(E"GLPK",E"GLPK",E"btran",E"btran(glp_prob, v) +("Linear Algebra","","eigfact","eigfact(A) - Performs backward transformation (BTRAN), i.e. it solves the system - \"B'x = b\", where \"B\" is the transposed of the basis matrix, - \"x\" is the vector of unknowns to be computed, \"b\" is the vector - of right-hand sides. At input, \"v\" represents the vector \"b\"; - at output, it contains the vector \"x\". \"v\" must be a - \"Vector{Float64}\" whose length is the number of rows. + Compute the eigenvalue decomposition of \"A\" and return an + \"Eigen\" object. If \"F\" is the factorization object, the + eigenvalues can be accessed with \"F[:values]\" and the + eigenvectors with \"F[:vectors]\". The following functions are + available for \"Eigen\" objects: \"inv\", \"det\". "), -(E"GLPK",E"GLPK",E"warm_up",E"warm_up(glp_prob) - - \"Warms up\" the LP basis using current statuses assigned to rows - and columns, i.e. computes factorization of the basis matrix (if it - does not exist), computes primal and dual components of basic - solution, and determines the solution status. +("Linear Algebra","","eigfact!","eigfact!(A) - Returns 0 if successful, otherwise: \"GLPK.EBADB\" (invalid - matrix), \"GLPK.ESING\" (singluar matrix), \"GLPK.ECOND\" (ill- - conditioned matrix). + \"eigfact!\" is the same as \"eigfact\" but saves space by + overwriting the input A, instead of creating a copy. "), -(E"GLPK",E"GLPK",E"eval_tab_row",E"eval_tab_row(glp_prob, k, ind, val) -eval_tab_row(glp_prob, k) +("Linear Algebra","","hessfact","hessfact(A) - Computes a row of the current simplex tableau which corresponds to - some basic variable specified by the parameter \"k\". If 1 <= \"k\" - <= rows, uses \"k\"-th auxiliary variable; if rows+1 <= \"k\" <= - rows+cols, uses (\"k\"-rows)-th structural variable. The basis - factorization must exist. + Compute the Hessenberg decomposition of \"A\" and return a + \"Hessenberg\" object. If \"F\" is the factorization object, the + unitary matrix can be accessed with \"F[:Q]\" and the Hessenberg + matrix with \"F[:H]\". When \"Q\" is extracted, the resulting type + is the \"HessenbergQ\" object, and may be converted to a regular + matrix with \"full\". - In the first form, stores the result in the provided vectors - \"ind\" and \"val\", which must be of type \"Vector{Int32}\" and - \"Vector{Float64}\", respectively, and returns the length of the - outcome; in Julia, the vectors will be resized as needed to hold - the result. +"), + +("Linear Algebra","","hessfact!","hessfact!(A) - In the second, simpler form, \"ind\" and \"val\" are returned in a - tuple as the output of the function. + \"hessfact!\" is the same as \"hessfact\" but saves space by + overwriting the input A, instead of creating a copy. "), -(E"GLPK",E"GLPK",E"eval_tab_col",E"eval_tab_col(glp_prob, k, ind, val) -eval_tab_col(glp_prob, k) +("Linear Algebra","","schurfact","schurfact(A) -> Schur - Computes a column of the current simplex tableau which corresponds - to some non-basic variable specified by the parameter \"k\". See - \"eval_tab_row\". + Computes the Schur factorization of the matrix \"A\". The (quasi) + triangular Schur factor can be obtained from the \"Schur\" object + \"F\" with either \"F[:Schur]\" or \"F[:T]\" and the + unitary/orthogonal Schur vectors can be obtained with + \"F[:vectors]\" or \"F[:Z]\" such that + \"A=F[:vectors]*F[:Schur]*F[:vectors]'\". The eigenvalues of \"A\" + can be obtained with \"F[:values]\". "), -(E"GLPK",E"GLPK",E"transform_row",E"transform_row(glp_prob[, len], ind, val) +("Linear Algebra","","schur","schur(A) -> Schur[:T], Schur[:Z], Schur[:values] - Performs the same operation as \"eval_tab_row\" with the exception - that the row to be transformed is specified explicitly as a sparse - vector. The parameter \"len\" is the number of elements of \"ind\" - and \"val\" which will be used, and must be smaller or equal to the - length of both vectors; in Julia it is optional (and the \"ind\" - and \"val\" must have the same length). The vectors \"int\" and - \"val\" must be of type \"Vector{Int32}\" and \"Vector{Float64}\", - respectively, since they will also hold the result; in Julia, they - will be resized to the resulting required length. - - Returns the length if the resulting vectors \"ind\" and \"val\". + See schurfact "), -(E"GLPK",E"GLPK",E"transform_col",E"transform_col(glp_prob[, len], ind, val) +("Linear Algebra","","schurfact","schurfact(A, B) -> GeneralizedSchur - Performs the same operation as \"eval_tab_col\" with the exception - that the row to be transformed is specified explicitly as a sparse - vector. See \"transform_row\". + Computes the Generalized Schur (or QZ) factorization of the + matrices \"A\" and \"B\". The (quasi) triangular Schur factors can + be obtained from the \"Schur\" object \"F\" with \"F[:S]\" and + \"F[:T]\", the left unitary/orthogonal Schur vectors can be + obtained with \"F[:left]\" or \"F[:Q]\" and the right + unitary/orthogonal Schur vectors can be obtained with \"F[:right]\" + or \"F[:Z]\" such that \"A=F[:left]*F[:S]*F[:right]'\" and + \"B=F[:left]*F[:T]*F[:right]'\". The generalized eigenvalues of + \"A\" and \"B\" can be obtained with \"F[:alpha]./F[:beta]\". "), -(E"GLPK",E"GLPK",E"prim_rtest",E"prim_rtest(glp_prob[, len], ind, val, dir, eps) - - Performs the primal ratio test using an explicitly specified column - of the simplex table. The current basic solution must be primal - feasible. The column is specified in sparse format by \"len\" - (length of the vector), \"ind\" and \"val\" (indices and values of - the vector). \"len\" is the number of elements which will be - considered and must be smaller or equal to the length of both - \"ind\" and \"val\"; in Julia, it can be omitted (and then \"ind\" - and \"val\" must have the same length). The indices in \"ind\" must - be between 1 and rows+cols; they must correspond to basic - variables. \"dir\" is a direction parameter which must be either +1 - (increasing) or -1 (decreasing). \"eps\" is a tolerance parameter - and must be positive. See the GLPK manual for a detailed - explanation. +("Linear Algebra","","schur","schur(A, B) -> GeneralizedSchur[:S], GeneralizedSchur[:T], GeneralizedSchur[:Q], GeneralizedSchur[:Z] - Returns the position in \"ind\" and \"val\" which corresponds to - the pivot element, or 0 if the choice cannot be made. + See schurfact "), -(E"GLPK",E"GLPK",E"dual_rtest",E"dual_rtest(glp_prob[, len], ind, val, dir, eps) +("Linear Algebra","","svdfact","svdfact(A[, thin]) -> SVD - Performs the dual ratio test using an explicitly specified row of - the simplex table. The current basic solution must be dual - feasible. The indices in \"ind\" must correspond to non-basic - variables. Everything else is like in \"prim_rtest\". + Compute the Singular Value Decomposition (SVD) of \"A\" and return + an \"SVD\" object. \"U\", \"S\", \"V\" and \"Vt\" can be obtained + from the factorization \"F\" with \"F[:U]\", \"F[:S]\", \"F[:V]\" + and \"F[:Vt]\", such that \"A = U*diagm(S)*Vt\". If \"thin\" is + \"true\", an economy mode decomposition is returned. The algorithm + produces \"Vt\" and hence \"Vt\" is more efficient to extract than + \"V\". The default is to produce a thin decomposition. "), -(E"GLPK",E"GLPK",E"analyze_bound",E"analyze_bound(glp_prob, k) +("Linear Algebra","","svdfact!","svdfact!(A[, thin]) -> SVD - Analyzes the effect of varying the active bound of specified non- - basic variable. See the GLPK manual for a detailed explanation. In - Julia, this function has a different API then C. It returns - \"(limit1, var1, limit2, var2)\" rather then taking them as - pointers in the argument list. + \"svdfact!\" is the same as \"svdfact\" but saves space by + overwriting the input A, instead of creating a copy. If \"thin\" is + \"true\", an economy mode decomposition is returned. The default is + to produce a thin decomposition. "), -(E"GLPK",E"GLPK",E"analyze_coef",E"analyze_coef(glp_prob, k) +("Linear Algebra","","svd","svd(A[, thin]) -> U, S, V - Analyzes the effect of varying the objective coefficient at - specified basic variable. See the GLPK manual for a detailed - explanation. In Julia, this function has a different API then C. It - returns \"(coef1, var1, value1, coef2, var2, value2)\" rather then - taking them as pointers in the argument list. + Compute the SVD of A, returning \"U\", vector \"S\", and \"V\" such + that \"A == U*diagm(S)*V'\". If \"thin\" is \"true\", an economy + mode decomposition is returned. "), -(E"GLPK",E"GLPK",E"init_env",E"init_env() +("Linear Algebra","","svdvals","svdvals(A) - Initializes the GLPK environment. Not normally needed. - - Returns 0 (initilization successful), 1 (environment already - initialized), 2 (failed, insufficient memory) or 3 (failed, - unsupported programming model). + Returns the singular values of \"A\". "), -(E"GLPK",E"GLPK",E"version",E"version() +("Linear Algebra","","svdvals!","svdvals!(A) - Returns the GLPK version number. In Julia, instead of returning a - string as in C, it returns a tuple of integer values, containing - the major and the minor number. + Returns the singular values of \"A\", while saving space by + overwriting the input. "), -(E"GLPK",E"GLPK",E"free_env",E"free_env() +("Linear Algebra","","svdfact","svdfact(A, B) -> GeneralizedSVD - Frees all resources used by GLPK routines (memory blocks, etc.) - which are currently still in use. Not normally needed. - - Returns 0 if successful, 1 if envirnoment is inactive. + Compute the generalized SVD of \"A\" and \"B\", returning a + \"GeneralizedSVD\" Factorization object, such that \"A = + U*D1*R0*Q'\" and \"B = V*D2*R0*Q'\". "), -(E"GLPK",E"GLPK",E"term_out",E"term_out(flag) - - Enables/disables the terminal output of glpk routines. \"flag\" is - either \"GLPK.ON\" (output enabled) or \"GLPK.OFF\" (output - disabled). +("Linear Algebra","","svd","svd(A, B) -> U, V, Q, D1, D2, R0 - Returns the previous status of the terminal output. + Compute the generalized SVD of \"A\" and \"B\", returning \"U\", + \"V\", \"Q\", \"D1\", \"D2\", and \"R0\" such that \"A = + U*D1*R0*Q'\" and \"B = V*D2*R0*Q'\". "), -(E"GLPK",E"GLPK",E"open_tee",E"open_tee(filename) +("Linear Algebra","","svdvals","svdvals(A, B) - Starts copying all the terminal output to an output text file. - - Returns 0 if successful, 1 if already active, 2 if it fails - creating the output file. + Return only the singular values from the generalized singular value + decomposition of \"A\" and \"B\". "), -(E"GLPK",E"GLPK",E"close_tee",E"close_tee() - - Stops copying the terminal output to the output text file - previously open by the \"open_tee\". +("Linear Algebra","","triu","triu(M) - Return 0 if successful, 1 if copying terminal output was not - started. + Upper triangle of a matrix "), -(E"GLPK",E"GLPK",E"malloc",E"malloc(size) - - Replacement of standard C \"malloc\". Allocates uninitialized - memeory which must freed with \"free\". +("Linear Algebra","","tril","tril(M) - Returns a pointer to the allocated memory. + Lower triangle of a matrix "), -(E"GLPK",E"GLPK",E"calloc",E"calloc(n, size) - - Replacement of standard C \"calloc\", but does not initialize the - memeory. Allocates uninitialized memeory which must freed with - \"free\". +("Linear Algebra","","diag","diag(M[, k]) - Returns a pointer to the allocated memory. + The \"k\"-th diagonal of a matrix, as a vector "), -(E"GLPK",E"GLPK",E"free",E"free(ptr) +("Linear Algebra","","diagm","diagm(v[, k]) - Deallocates a memory block previously allocated by \"malloc\" or - \"calloc\". + Construct a diagonal matrix and place \"v\" on the \"k\"-th + diagonal "), -(E"GLPK",E"GLPK",E"mem_usage",E"mem_usage() +("Linear Algebra","","diagmm","diagmm(matrix, vector) - Reports some information about utilization of the memory by the - routines \"malloc\", \"calloc\", and \"free\". In Julia, this - function has a different API then C. It returns \"(count, cpeak, - total, tpeak)\" rather then taking them as pointers in the argument - list. + Multiply matrices, interpreting the vector argument as a diagonal + matrix. The arguments may occur in the other order to multiply with + the diagonal matrix on the left. "), -(E"GLPK",E"GLPK",E"mem_limit",E"mem_limit(limit) +("Linear Algebra","","Tridiagonal","Tridiagonal(dl, d, du) - Limits the amount of memory avaliable for dynamic allocation to a - value in megabyes given by the integer parameter \"limit\". + Construct a tridiagonal matrix from the lower diagonal, diagonal, + and upper diagonal "), -(E"GLPK",E"GLPK",E"time",E"time() +("Linear Algebra","","Bidiagonal","Bidiagonal(dv, ev, isupper) - Returns the current universal time (UTC), in milliseconds. + Constructs an upper (isupper=true) or lower (isupper=false) + bidiagonal matrix using the given diagonal (dv) and off-diagonal + (ev) vectors "), -(E"GLPK",E"GLPK",E"difftime",E"difftime(t1, t0) +("Linear Algebra","","Woodbury","Woodbury(A, U, C, V) - Returns the difference between two time values \"t1\" and \"t0\", - expressed in seconds. + Construct a matrix in a form suitable for applying the Woodbury + matrix identity "), -(E"GLPK",E"GLPK",E"sdf_open_file",E"sdf_open_file(filename) +("Linear Algebra","","rank","rank(M) - Opens a plain data file. - - If successful, returns a \"GLPK.Data\" object, otherwise throws an - error. + Compute the rank of a matrix "), -(E"GLPK",E"GLPK",E"sdf_read_int",E"sdf_read_int(glp_data) +("Linear Algebra","","norm","norm(A[, p]) - Reads an integer number from the plain data file specified by the - \"GLPK.Data\" parameter \"glp_data\", skipping initial whitespace. + Compute the \"p\"-norm of a vector or a matrix. \"p\" is \"2\" by + default, if not provided. If \"A\" is a vector, \"norm(A, p)\" + computes the \"p\"-norm. \"norm(A, Inf)\" returns the largest value + in \"abs(A)\", whereas \"norm(A, -Inf)\" returns the smallest. If + \"A\" is a matrix, valid values for \"p\" are \"1\", \"2\", or + \"Inf\". In order to compute the Frobenius norm, use \"normfro\". "), -(E"GLPK",E"GLPK",E"sdf_read_num",E"sdf_read_num(glp_data) +("Linear Algebra","","normfro","normfro(A) - Reads a floating point number from the plain data file specified by - the \"GLPK.Data\" parameter \"glp_data\", skipping initial - whitespace. + Compute the Frobenius norm of a matrix \"A\". "), -(E"GLPK",E"GLPK",E"sdf_read_item",E"sdf_read_item(glp_data) +("Linear Algebra","","cond","cond(M[, p]) - Reads a data item (a String) from the plain data file specified by - the \"GLPK.Data\" parameter \"glp_data\", skipping initial - whitespace. + Matrix condition number, computed using the p-norm. \"p\" is 2 by + default, if not provided. Valid values for \"p\" are \"1\", \"2\", + or \"Inf\". "), -(E"GLPK",E"GLPK",E"sdf_read_text",E"sdf_read_text(glp_data) +("Linear Algebra","","trace","trace(M) - Reads a line of text from the plain data file specified by the - \"GLPK.Data\" parameter \"glp_data\", skipping initial and final - whitespace. + Matrix trace "), -(E"GLPK",E"GLPK",E"sdf_line",E"sdf_line(glp_data) +("Linear Algebra","","det","det(M) - Returns the current line in the \"GLPK.Data\" object \"glp_data\" + Matrix determinant "), -(E"GLPK",E"GLPK",E"sdf_close_file",E"sdf_close_file(glp_data) +("Linear Algebra","","inv","inv(M) - Closes the file associated to \"glp_data\" and frees the resources. + Matrix inverse "), -(E"GLPK",E"GLPK",E"read_cnfsat",E"read_cnfsat(glp_prob, filename) - - Reads the CNF-SAT problem data in DIMACS format from a text file. +("Linear Algebra","","pinv","pinv(M) - Returns 0 upon success; throws an error in case of failure. + Moore-Penrose inverse "), -(E"GLPK",E"GLPK",E"check_cnfsat",E"check_cnfsat(glp_prob) +("Linear Algebra","","null","null(M) - Checks if the problem object encodes a CNF-SAT problem instance, in - which case it returns 0, otherwise returns non-zero. + Basis for null space of M. "), -(E"GLPK",E"GLPK",E"write_cnfsat",E"write_cnfsat(glp_prob, filename) - - Writes the CNF-SAT problem data in DIMACS format into a text file. +("Linear Algebra","","repmat","repmat(A, n, m) - Returns 0 upon success; throws an error in case of failure. + Construct a matrix by repeating the given matrix \"n\" times in + dimension 1 and \"m\" times in dimension 2. "), -(E"GLPK",E"GLPK",E"minisat1",E"minisat1(glp_prob) +("Linear Algebra","","kron","kron(A, B) - The routine \"minisat1\" is a driver to MiniSat, a CNF-SAT solver - developed by Niklas Eén and Niklas Sörensson, Chalmers University - of Technology, Sweden. - - Returns 0 in case of success, or a non-zero flag specifying the - reason for failure: \"GLPK.EDATA\" (problem is not CNF-SAT), - \"GLPK.EFAIL\" (solver failure). + Kronecker tensor product of two vectors or two matrices. "), -(E"GLPK",E"GLPK",E"intfeas1",E"intfeas1(glp_prob, use_bound, obj_bound) +("Linear Algebra","","linreg","linreg(x, y) + + Determine parameters \"[a, b]\" that minimize the squared error + between \"y\" and \"a+b*x\". - The routine \"glp_intfeas1\" is a tentative implementation of an - integer feasibility solver based on a CNF-SAT solver (currently - MiniSat). \"use_bound\" is a flag: if zero, any feasible solution - is seeked, otherwise seraches for an integer feasible solution. - \"obj_bound\" is used only if \"use_bound\" is non-zero, and - specifies an upper/lower bound (for maximization/minimazion - respectively) to the objective function. +"), - All variables (columns) must either be binary or fixed. All - constraint and objective coeffient must be integer. +("Linear Algebra","","linreg","linreg(x, y, w) - Returns 0 in case of success, or a non-zero flag specifying the - reason for failure: \"GLPK.EDATA\" (problem data is not valid), - \"GLPK.ERANGE\" (integer overflow occurred), \"GLPK.EFAIL\" (solver - failure). + Weighted least-squares linear regression. "), -(E"GZip",E"GZip",E"gzopen",E"gzopen(fname[, gzmode[, buf_size]]) +("Linear Algebra","","expm","expm(A) - Opens a file with mode (default \"\"r\"\"), setting internal buffer - size to buf_size (default \"Z_DEFAULT_BUFSIZE=8192\"), and returns - a the file as a \"GZipStream\". + Matrix exponential. - \"gzmode\" must contain one of +"), - +------+-----------------------------------+ - | r | read | - +------+-----------------------------------+ - | w | write, create, truncate | - +------+-----------------------------------+ - | a | write, create, append | - +------+-----------------------------------+ +("Linear Algebra","","issym","issym(A) - In addition, gzmode may also contain + Test whether a matrix is symmetric. - +-------+-----------------------------------+ - | x | create the file exclusively | - +-------+-----------------------------------+ - | 0-9 | compression level | - +-------+-----------------------------------+ +"), - and/or a compression strategy: +("Linear Algebra","","isposdef","isposdef(A) - +------+-----------------------------------+ - | f | filtered data | - +------+-----------------------------------+ - | h | Huffman-only compression | - +------+-----------------------------------+ - | R | run-length encoding | - +------+-----------------------------------+ - | F | fixed code compression | - +------+-----------------------------------+ + Test whether a matrix is positive-definite. - Note that \"+\" is not allowed in gzmode. +"), + +("Linear Algebra","","istril","istril(A) - If an error occurs, \"gzopen\" throws a \"GZError\" + Test whether a matrix is lower-triangular. "), -(E"GZip",E"GZip",E"gzdopen",E"gzdopen(fd[, gzmode[, buf_size]]) +("Linear Algebra","","istriu","istriu(A) - Create a \"GZipStream\" object from an integer file descriptor. See - \"gzopen()\" for \"gzmode\" and \"buf_size\" descriptions. + Test whether a matrix is upper-triangular. "), -(E"GZip",E"GZip",E"gzdopen",E"gzdopen(s[, gzmode[, buf_size]]) +("Linear Algebra","","ishermitian","ishermitian(A) - Create a \"GZipStream\" object from \"IOStream\" \"s\". + Test whether a matrix is hermitian. "), -(E"GZip",E"GZip",E"GZipStream",E"type GZipStream(name, gz_file[, buf_size[, fd[, s]]]) +("Linear Algebra","","transpose","transpose(A) - Subtype of \"IO\" which wraps a gzip stream. Returned by - \"gzopen()\" and \"gzdopen()\". + The transpose operator (.'). "), -(E"GZip",E"GZip",E"GZError",E"type GZError(err, err_str) +("Linear Algebra","","ctranspose","ctranspose(A) - gzip error number and string. Possible error values: - - +-----------------------+------------------------------------------+ - | \\\"Z_OK\\\" | No error | - +-----------------------+------------------------------------------+ - | \\\"Z_ERRNO\\\" | Filesystem error (consult \\\"errno()\\\") | - +-----------------------+------------------------------------------+ - | \\\"Z_STREAM_ERROR\\\" | Inconsistent stream state | - +-----------------------+------------------------------------------+ - | \\\"Z_DATA_ERROR\\\" | Compressed data error | - +-----------------------+------------------------------------------+ - | \\\"Z_MEM_ERROR\\\" | Out of memory | - +-----------------------+------------------------------------------+ - | \\\"Z_BUF_ERROR\\\" | Input buffer full/output buffer empty | - +-----------------------+------------------------------------------+ - | \\\"Z_VERSION_ERROR\\\" | zlib library version is incompatible | - +-----------------------+------------------------------------------+ + The conjugate transpose operator ('). "), +("BLAS Functions","","copy!","copy!(n, X, incx, Y, incy) -(E"OptionsMod",E"OptionsMod",E"@options",E"@options([check_flag], assignments...) + Copy \"n\" elements of array \"X\" with stride \"incx\" to array + \"Y\" with stride \"incy\". Returns \"Y\". - Use the \"@options\" macro to set the value of optional parameters - for a function that has been written to use them (see - \"defaults()\" to learn how to write such functions). The syntax - is: +"), - opts = @options a=5 b=7 +("BLAS Functions","","dot","dot(n, X, incx, Y, incy) - For a function that uses optional parameters \"a\" and \"b\", this - will override the default settings for these parameters. You would - likely call that function in the following way: + Dot product of two vectors consisting of \"n\" elements of array + \"X\" with stride \"incx\" and \"n\" elements of array \"Y\" with + stride \"incy\". There are no \"dot\" methods for \"Complex\" + arrays. - myfunc(requiredarg1, requiredarg2, ..., opts) +"), - Most functions written to use optional arguments will probably - check to make sure that you are not supplying parameters that are - never used by the function or its sub-functions. Typically, - supplying unused parameters will result in an error. You can - control the behavior this way: +("BLAS Functions","","nrm2","nrm2(n, X, incx) - # throw an error if a or b is not used (the default) - opts = @options CheckError a=5 b=2 - # issue a warning if a or b is not used - opts = @options CheckWarn a=5 b=2 - # don't check whether a and b are used - opts = @options CheckNone a=5 b=2 + 2-norm of a vector consisting of \"n\" elements of array \"X\" with + stride \"incx\". - As an alternative to the macro syntax, you can also say: +"), - opts = Options(CheckWarn, :a, 5, :b, 2) +("BLAS Functions","","axpy!","axpy!(n, a, X, incx, Y, incy) - The check flag is optional. + Overwrite \"Y\" with \"a*X + Y\". Returns \"Y\". "), -(E"OptionsMod",E"OptionsMod",E"@set_options",E"@set_options(opts, assigments...) +("BLAS Functions","","syrk!","syrk!(uplo, trans, alpha, A, beta, C) + + Rank-k update of the symmetric matrix \"C\" as \"alpha*A*A.' + + beta*C\" or \"alpha*A.'*A + beta*C\" according to whether \"trans\" + is 'N' or 'T'. When \"uplo\" is 'U' the upper triangle of \"C\" is + updated ('L' for lower triangle). Returns \"C\". - The \"@set_options\" macro lets you add new parameters to an - existing options structure. For example: +"), - @set_options opts d=99 +("BLAS Functions","","syrk","syrk(uplo, trans, alpha, A) - would add \"d\" to the set of parameters in \"opts\", or re-set its - value if it was already supplied. + Returns either the upper triangle or the lower triangle, according + to \"uplo\" ('U' or 'L'), of \"alpha*A*A.'\" or \"alpha*A.'*A\", + according to \"trans\" ('N' or 'T'). "), -(E"OptionsMod",E"OptionsMod",E"@defaults",E"@defaults(opts, assignments...) +("BLAS Functions","","herk!","herk!(uplo, trans, alpha, A, beta, C) + + Methods for complex arrays only. Rank-k update of the Hermitian + matrix \"C\" as \"alpha*A*A' + beta*C\" or \"alpha*A'*A + beta*C\" + according to whether \"trans\" is 'N' or 'T'. When \"uplo\" is 'U' + the upper triangle of \"C\" is updated ('L' for lower triangle). + Returns \"C\". - The \"@defaults\" macro is for writing functions that take optional - parameters. The typical syntax of such functions is: +"), - function myfunc(requiredarg1, requiredarg2, ..., opts::Options) - @defaults opts a=11 b=2a+1 c=a*b d=100 - # The function body. Use a, b, c, and d just as you would - # any other variable. For example, - k = a + b - # You can pass opts down to subfunctions, which might supply - # additional defaults for other variables aa, bb, etc. - y = subfun(k, opts) - # Terminate your function with check_used, then return values - @check_used opts - return y - end +("BLAS Functions","","herk","herk(uplo, trans, alpha, A) - Note the function calls \"@check_used()\" at the end. + Methods for complex arrays only. Returns either the upper triangle + or the lower triangle, according to \"uplo\" ('U' or 'L'), of + \"alpha*A*A'\" or \"alpha*A'*A\", according to \"trans\" ('N' or + 'T'). - It is possible to have more than one Options parameter to a - function, for example: +"), - function twinopts(x, plotopts::Options, calcopts::Options) - @defaults plotopts linewidth=1 - @defaults calcopts n_iter=100 - # Do stuff - @check_used plotopts - @check_used calcopts - end +("BLAS Functions","","gbmv!","gbmv!(trans, m, kl, ku, alpha, A, x, beta, y) - Within a given scope, you should only have one call to - \"@defaults\" per options variable. + Update vector \"y\" as \"alpha*A*x + beta*y\" or \"alpha*A'*x + + beta*y\" according to \"trans\" ('N' or 'T'). The matrix \"A\" is + a general band matrix of dimension \"m\" by \"size(A,2)\" with + \"kl\" sub-diagonals and \"ku\" super-diagonals. Returns the + updated \"y\". "), -(E"OptionsMod",E"OptionsMod",E"@check_used",E"@check_used(opts) +("BLAS Functions","","gbmv","gbmv(trans, m, kl, ku, alpha, A, x, beta, y) + + Returns \"alpha*A*x\" or \"alpha*A'*x\" according to \"trans\" ('N' + or 'T'). The matrix \"A\" is a general band matrix of dimension + \"m\" by \"size(A,2)\" with \"kl\" sub-diagonals and \"ku\" super- + diagonals. - The \"@check_used\" macro tests whether user-supplied parameters - were ever accessed by the \"@defaults()\" macro. The test is - performed at the end of the function body, so that subfunction - handling parameters not used by the parent function may be - \"credited\" for their usage. Each sub-function should also call - \"@check_used\", for example: +"), - function complexfun(x, opts::Options) - @defaults opts parent=3 both=7 - println(parent) - println(both) - subfun1(x, opts) - subfun2(x, opts) - @check_used opts - end +("BLAS Functions","","sbmv!","sbmv!(uplo, k, alpha, A, x, beta, y) - function subfun1(x, opts::Options) - @defaults opts sub1=\"sub1 default\" both=0 - println(sub1) - println(both) - @check_used opts - end + Update vector \"y\" as \"alpha*A*x + beta*y\" where \"A\" is a a + symmetric band matrix of order \"size(A,2)\" with \"k\" super- + diagonals stored in the argument \"A\". The storage layout for + \"A\" is described the reference BLAS module, level-2 BLAS at + **. - function subfun2(x, opts::Options) - @defaults opts sub2=\"sub2 default\" both=22 - println(sub2) - println(both) - @check_used opts - end + Returns the updated \"y\". "), -(E"OptionsMod",E"OptionsMod",E"Options",E"type Options(OptionsChecking, param1, val1, param2, val2, ...) +("BLAS Functions","","sbmv","sbmv(uplo, k, alpha, A, x) - \"Options\" is the central type used for handling optional - arguments. Its fields are briefly described below. + Returns \"alpha*A*x\" where \"A\" is a symmetric band matrix of + order \"size(A,2)\" with \"k\" super-diagonals stored in the + argument \"A\". - key2index +"), - A \"Dict\" that looks up an integer index, given the symbol for - a variable (e.g., \"key2index[:a]\" for the variable \"a\") +("BLAS Functions","","gemm!","gemm!(tA, tB, alpha, A, B, beta, C) - vals + Update \"C\" as \"alpha*A*B + beta*C\" or the other three variants + according to \"tA\" (transpose \"A\") and \"tB\". Returns the + updated \"C\". - \"vals[key2index[:a]]\" is the value to be assigned to the - variable \"a\" +"), - used +("BLAS Functions","","gemm","gemm(tA, tB, alpha, A, B) - A vector of booleans, one per variable, with - \"used[key2index[:a]]\" representing the value for variable - \"a\". These all start as \"false\", but access by a - \"@defaults\" command sets the corresponding value to \"true\". - This marks the variable as having been used in the function. + Returns \"alpha*A*B\" or the other three variants according to + \"tA\" (transpose \"A\") and \"tB\". - check_lock +"), - A vector of booleans, one per variable. This is a \"lock\" that - prevents sub-functions from complaining that they did not access - variables that were intended for the parent function. - \"@defaults()\" sets the lock to true for any options variables - that have already been defined; new variables added through - \"@set_options()\" will start with their \"check_lock\" set to - \"false\", to be handled by a subfunction. +("Punctuation","","punctuation","punctuation + + +-----------+---------------------------------------------------------------------------------------------+ + | symbol | meaning | + +===========+=============================================================================================+ + | \\\"@m\\\" | invoke macro m; followed by space-separated expressions | + +-----------+---------------------------------------------------------------------------------------------+ + | \\\"!\\\" | prefix \\\"not\\\" operator | + +-----------+---------------------------------------------------------------------------------------------+ + | \\\"!\\\" | at the end of a function name, indicates that a function modifies its argument(s) | + +-----------+---------------------------------------------------------------------------------------------+ + | \\\"#\\\" | begin single line comment | + +-----------+---------------------------------------------------------------------------------------------+ + | \\\"\\\$\\\" | xor operator, string and expression interpolation | + +-----------+---------------------------------------------------------------------------------------------+ + | \\\"%\\\" | remainder operator | + +-----------+---------------------------------------------------------------------------------------------+ + | \\\"^\\\" | exponent operator | + +-----------+---------------------------------------------------------------------------------------------+ + | \\\"&\\\" | bitwise and | + +-----------+---------------------------------------------------------------------------------------------+ + | \\\"*\\\" | multiply, or matrix multiply | + +-----------+---------------------------------------------------------------------------------------------+ + | \\\"()\\\" | the empty tuple | + +-----------+---------------------------------------------------------------------------------------------+ + | \\\"~\\\" | bitwise not operator | + +-----------+---------------------------------------------------------------------------------------------+ + | \\\"\\\\\\\" | backslash operator | + +-----------+---------------------------------------------------------------------------------------------+ + | \\\"a[]\\\" | array indexing | + +-----------+---------------------------------------------------------------------------------------------+ + | \\\"[,]\\\" | vertical concatenation | + +-----------+---------------------------------------------------------------------------------------------+ + | \\\"[;]\\\" | also vertical concatenation | + +-----------+---------------------------------------------------------------------------------------------+ + | \\\"[ ]\\\" | with space-separated expressions, horizontal concatenation | + +-----------+---------------------------------------------------------------------------------------------+ + | \\\"T{ }\\\" | parametric type instantiation | + +-----------+---------------------------------------------------------------------------------------------+ + | \\\"{ }\\\" | construct a cell array | + +-----------+---------------------------------------------------------------------------------------------+ + | \\\";\\\" | statement separator | + +-----------+---------------------------------------------------------------------------------------------+ + | \\\",\\\" | separate function arguments or tuple components | + +-----------+---------------------------------------------------------------------------------------------+ + | \\\"?\\\" | 3-argument conditional operator | + +-----------+---------------------------------------------------------------------------------------------+ + | \\\"\\\"\\\"\\\" | delimit string literals | + +-----------+---------------------------------------------------------------------------------------------+ + | \\\"''\\\" | delimit character literals | + +-----------+---------------------------------------------------------------------------------------------+ + | >>``<< | delimit external process (command) specifications | + +-----------+---------------------------------------------------------------------------------------------+ + | \\\"...\\\" | splice arguments into a function call, or declare a varargs function | + +-----------+---------------------------------------------------------------------------------------------+ + | \\\".\\\" | access named fields in objects or names inside modules, also prefixes elementwise operators | + +-----------+---------------------------------------------------------------------------------------------+ + | \\\"a:b\\\" | range | + +-----------+---------------------------------------------------------------------------------------------+ + | \\\"a:s:b\\\" | range | + +-----------+---------------------------------------------------------------------------------------------+ + | \\\":\\\" | index an entire dimension | + +-----------+---------------------------------------------------------------------------------------------+ + | \\\"::\\\" | type annotation | + +-----------+---------------------------------------------------------------------------------------------+ + | \\\":( )\\\" | quoted expression | + +-----------+---------------------------------------------------------------------------------------------+ "), -(E"profile.jl",E"",E"@profile",E"@profile() +("Base.Sort","Base.Sort","sort","sort(v[, alg[, ord]]) - Profiling is controlled via the \"@profile\" macro. Your first step - is to determine which code you want to profile and encapsulate it - inside a \"@profile begin ... end\" block, like this: + Sort a vector in ascending order. Specify \"alg\" to choose a + particular sorting algorithm (\"Sort.InsertionSort\", + \"Sort.QuickSort\", \"Sort.MergeSort\", or \"Sort.TimSort\"), and + \"ord\" to sort with a custom ordering (e.g., Sort.Reverse or a + comparison function). - @profile begin - function f1(x::Int) - z = 0 - for j = 1:x - z += j^2 - end - return z - end +"), - function f1(x::Float64) - return x+2 - end +("Base.Sort","Base.Sort","sort!","sort!(...) - function f1{T}(x::T) - return x+5 - end + In-place sort. - f2(x) = 2*x - end # @profile begin +"), - Now load the file and execute the code you want to profile, e.g.: +("Base.Sort","Base.Sort","sortby","sortby(v, by[, alg]) - f1(215) - for i = 1:100 - f1(3.5) - end - for i = 1:150 - f1(uint8(7)) - end - for i = 1:125 - f2(11) - end + Sort a vector according to \"by(v)\". Specify \"alg\" to choose a + particular sorting algorithm (\"Sort.InsertionSort\", + \"Sort.QuickSort\", \"Sort.MergeSort\", or \"Sort.TimSort\"). - To view the execution times, type \"@profile report\". +"), - Here are the various options you have for controlling profiling: +("Base.Sort","Base.Sort","sortby!","sortby!(...) - * \"@profile report\": display cumulative profiling results + In-place \"sortby\". - * \"@profile clear\": clear all timings accumulated thus far (start - from zero) +"), - * \"@profile off\": turn profiling off (there is no need to remove - \"@profile begin ... end\" blocks) +("Base.Sort","Base.Sort","sortperm","sortperm(v[, alg[, ord]]) - * \"@profile on\": turn profiling back on + Return a permutation vector, which when applied to the input vector + \"v\" will sort it. Specify \"alg\" to choose a particular sorting + algorithm (\"Sort.InsertionSort\", \"Sort.QuickSort\", + \"Sort.MergeSort\", or \"Sort.TimSort\"), and \"ord\" to sort with + a custom ordering (e.g., Sort.Reverse or a comparison function). "), -(E"Sound",E"Sound",E"wavread",E"wavread(io[, options]) +("Base.Sort","Base.Sort","issorted","issorted(v[, ord]) - Reads and returns the samples from a RIFF/WAVE file. The samples - are converted to floating point values in the range from -1.0 to - 1.0 by default. The \"io\" argument accepts either an \"IO\" object - or a filename (\"String\"). The options are passed via an - \"Options\" object (see the \"OptionsMod\" module). + Test whether a vector is in ascending sorted order. If specified, + \"ord\" gives the ordering to test. - The available options, and the default values, are: +"), - * \"format\" (default = \"double\"): changes the format of the - returned samples. The string \"double\" returns double precision - floating point values in the range -1.0 to 1.0. The string - \"native\" returns the values as encoded in the file. The string - \"size\" returns the number of samples in the file, rather than - the actual samples. +("Base.Sort","Base.Sort","searchsorted","searchsorted(a, x[, ord]) - * \"subrange\" (default = \"Any\"): controls which samples are - returned. The default, \"Any\" returns all of the samples. - Passing a number (\"Real\"), \"N\", will return the first \"N\" - samples of each channel. Passing a range (\"Range1{Real}\"), - \"R\", will return the samples in that range of each channel. + Returns the index of the first value of \"a\" equal to or + succeeding \"x\", according to ordering \"ord\" (default: + \"Sort.Forward\"). - The returned values are: + Alias for \"searchsortedfirst()\" - * \"y\": The acoustic samples; A matrix is returned for files that - contain multiple channels. +"), - * \"Fs\": The sampling frequency +("Base.Sort","Base.Sort","searchsortedfirst","searchsortedfirst(a, x[, ord]) - * \"nbits\": The number of bits used to encode each sample + Returns the index of the first value of \"a\" equal to or + succeeding \"x\", according to ordering \"ord\" (default: + \"Sort.Forward\"). - * \"extra\": Any additional bytes used to encode the samples (is - always \"None\") +"), - The following functions are also defined to make this function - compatible with MATLAB: +("Base.Sort","Base.Sort","searchsortedlast","searchsortedlast(a, x[, ord]) - wavread(filename::String) = wavread(filename, @options) - wavread(filename::String, fmt::String) = wavread(filename, @options format=fmt) - wavread(filename::String, N::Int) = wavread(filename, @options subrange=N) - wavread(filename::String, N::Range1{Int}) = wavread(filename, @options subrange=N) - wavread(filename::String, N::Int, fmt::String) = wavread(filename, @options subrange=N format=fmt) - wavread(filename::String, N::Range1{Int}, fmt::String) = wavread(filename, @options subrange=N format=fmt) + Returns the index of the last value of \"a\" preceding or equal to + \"x\", according to ordering \"ord\" (default: \"Sort.Forward\"). "), -(E"Sound",E"Sound",E"wavwrite",E"wavwrite(samples, io[, options]) - - Writes samples to a RIFF/WAVE file io object. The \"io\" - argument accepts either an \"IO\" object or a filename - (\"String\"). The function assumes that the sample rate is 8 kHz - and uses 16 bits to encode each sample. Both of these values can - be changed with the options parameter. Each column of the data - represents a different channel. Stereo files should contain two - columns. The options are passed via an \"Options\" object (see - the \"OptionsMod\" module). +("Base.Sort","Base.Sort","select","select(v, k[, ord]) - The available options, and the default values, are: + Find the element in position \"k\" in the sorted vector \"v\" + without sorting, according to ordering \"ord\" (default: + \"Sort.Forward\"). - * \"sample_rate\" (default = \"8000\"): sampling frequency +"), - * \"nbits\" (default = \"16\"): number of bits used to encode each - sample +("Base.Sort","Base.Sort","select!","select!(v, k[, ord]) - * \"compression\" (default = \"WAVE_FORMAT_PCM\"): The desired - compression technique; accepted values are: WAVE_FORMAT_PCM, - WAVE_FORMAT_IEEE_FLOAT + Version of \"select\" which permutes the input vector in place. - The type of the input array, samples, also affects the generated - file. \"Native\" WAVE files are written when integers are passed - into wavwrite. This means that the literal values are written into - the file. The input ranges are as follows for integer samples. +"), - +--------+-------------+------------------------+---------------+ - | N Bits | y Data Type | y Data Range | Output Format | - +========+=============+========================+===============+ - | 8 | uint8 | 0 <= y <= 255 | uint8 | - +--------+-------------+------------------------+---------------+ - | 16 | int16 | –32768 <= y <= +32767 | int16 | - +--------+-------------+------------------------+---------------+ - | 24 | int32 | –2^23 <= y <= 2^23 – 1 | int32 | - +--------+-------------+------------------------+---------------+ +("Sparse Matrices","","sparse","sparse(I, J, V[, m, n, combine]) - If samples contains floating point values, the input data ranges - are the following. + Create a sparse matrix \"S\" of dimensions \"m x n\" such that + \"S[I[k], J[k]] = V[k]\". The \"combine\" function is used to + combine duplicates. If \"m\" and \"n\" are not specified, they are + set to \"max(I)\" and \"max(J)\" respectively. If the \"combine\" + function is not supplied, duplicates are added by default. - +--------+------------------+-------------------+---------------+ - | N Bits | y Data Type | y Data Range | Output Format | - +========+==================+===================+===============+ - | 8 | single or double | –1.0 <= y < +1.0 | uint8 | - +--------+------------------+-------------------+---------------+ - | 16 | single or double | –1.0 <= y < +1.0 | int16 | - +--------+------------------+-------------------+---------------+ - | 24 | single or double | –1.0 <= y < +1.0 | int32 | - +--------+------------------+-------------------+---------------+ - | 32 | single or double | –1.0 <= y <= +1.0 | single | - +--------+------------------+-------------------+---------------+ +"), - The following functions are also defined to make this function - compatible with MATLAB: +("Sparse Matrices","","sparsevec","sparsevec(I, V[, m, combine]) - wavwrite(y::Array) = wavwrite(y, @options) - wavwrite(y::Array, Fs::Real, filename::String) = wavwrite(y, filename, @options sample_rate=Fs) - wavwrite(y::Array, Fs::Real, N::Real, filename::String) = wavwrite(y, filename, @options sample_rate=Fs nbits=N) + Create a sparse matrix \"S\" of size \"m x 1\" such that \"S[I[k]] + = V[k]\". Duplicates are combined using the \"combine\" function, + which defaults to *+* if it is not provided. In julia, sparse + vectors are really just sparse matrices with one column. Given + Julia's Compressed Sparse Columns (CSC) storage format, a sparse + column matrix with one column is sparse, whereas a sparse row + matrix with one row ends up being dense. "), +("Sparse Matrices","","sparsevec","sparsevec(D::Dict[, m]) -(E"strpack.jl",E"",E"pack",E"pack(io, composite[, strategy]) - - Create a packed buffer representation of \"composite\" in stream - \"io\", using data alignment coded by \"strategy\". This buffer is - suitable to pass as a \"struct\" argument in a \"ccall\". + Create a sparse matrix of size \"m x 1\" where the row values are + keys from the dictionary, and the nonzero values are the values + from the dictionary. "), -(E"strpack.jl",E"",E"unpack",E"unpack(io, T[, strategy]) +("Sparse Matrices","","issparse","issparse(S) - Extract an instance of the Julia composite type \"T\" from the - packed representation in the stream \"io\". \"io\" must be - positioned at the beginning (using \"seek\"). This allows you to - read C \"struct\" outputs from \"ccall\". + Returns \"true\" if \"S\" is sparse, and \"false\" otherwise. "), -(E"TextWrap",E"TextWrap",E"wrap",E"wrap(string[, options]) +("Sparse Matrices","","sparse","sparse(A) - Returns a string in which newlines are inserted as appropriate in - order for each line to fit within a specified width. + Convert a dense matrix \"A\" into a sparse matrix. - The options are passed via an \"Options\" object (provided by the - \"OptionsMod\" module). The available options, and their default - values, are: +"), - * \"width\" (default = \"70\"): the maximum width of the wrapped - text, including indentation. +("Sparse Matrices","","sparsevec","sparsevec(A) - * \"initial_indent\" (default = \"\"\"\"): indentation of the first - line. This can be any string (shorter than \"width\"), or it can - be an integer number (lower than \"width\"). + Convert a dense vector \"A\" into a sparse matrix of size \"m x + 1\". In julia, sparse vectors are really just sparse matrices with + one column. - * \"subsequent_indent\" (default = \"\"\"\"): indentation of all - lines except the first. Works the same as \"initial_indent\". +"), - * \"break_on_hyphens\" (default = \"true\"): this flag determines - whether words can be broken on hyphens, e.g. whether \"high- - precision\" can be split into \"high-\" and \"precision\". +("Sparse Matrices","","dense","dense(S) - * \"break_long_words\" (default = \"true\"): this flag determines - what to do when a word is too long to fit in any line. If - \"true\", the word will be broken, otherwise it will go beyond - the desired text width. + Convert a sparse matrix \"S\" into a dense matrix. - * \"replace_whitespace\" (default = \"true\"): if this flag is - true, all whitespace characters in the original text (including - newlines) will be replaced by spaces. +"), - * \"expand_tabs\" (default = \"true\"): if this flag is true, tabs - will be expanded in-place into spaces. The expansion happens - before whitespace replacement. +("Sparse Matrices","","full","full(S) - * \"fix_sentence_endings\" (default = \"false\"): if this flag is - true, the wrapper will try to recognize sentence endings in the - middle of a paragraph and put two spaces before the next sentence - in case only one is present. + Convert a sparse matrix \"S\" into a dense matrix. "), -(E"TextWrap",E"TextWrap",E"println_wrapped",E"print_wrapped(text...[, options]) -print_wrapped(io, text...[, options]) -println_wrapped(text...[, options]) -println_wrapped(io, text...[, options]) +("Sparse Matrices","","spzeros","spzeros(m, n) - These are just like the standard \"print()\" and \"println()\" - functions (they print multiple arguments and accept an optional - \"IO\" first argument), except that they wrap the result, and - accept an optional last argument with the options to pass to - \"wrap()\". + Create an empty sparse matrix of size \"m x n\". "), -(E"Zlib",E"Zlib",E"compress_bound",E"compress_bound(input_size) +("Sparse Matrices","","speye","speye(type, m[, n]) - Returns the maximum size of the compressed output buffer for a - given uncompressed input size. + Create a sparse identity matrix of specified type of size \"m x + m\". In case \"n\" is supplied, create a sparse identity matrix of + size \"m x n\". "), -(E"Zlib",E"Zlib",E"compress",E"compress(source[, level]) +("Sparse Matrices","","spones","spones(S) - Compresses source using the given compression level, and returns - the compressed buffer (\"Array{Uint8,1}\"). \"level\" is an - integer between 0 and 9, or one of \"Z_NO_COMPRESSION\", - \"Z_BEST_SPEED\", \"Z_BEST_COMPRESSION\", or - \"Z_DEFAULT_COMPRESSION\". It defaults to - \"Z_DEFAULT_COMPRESSION\". - - If an error occurs, \"compress\" throws a \"ZError\" with more - information about the error. + Create a sparse matrix with the same structure as that of \"S\", + but with every nonzero element having the value \"1.0\". "), -(E"Zlib",E"Zlib",E"compress_to_buffer",E"compress_to_buffer(source, dest, level=Z_DEFAULT_COMPRESSION) - - Compresses the source buffer into the destination buffer, and - returns the number of bytes written into dest. +("Sparse Matrices","","sprand","sprand(m, n, density[, rng]) - If an error occurs, \"uncompress\" throws a \"ZError\" with more - information about the error. + Create a random sparse matrix with the specified density. Nonzeros + are sampled from the distribution specified by \"rng\". The uniform + distribution is used in case \"rng\" is not specified. "), -(E"Zlib",E"Zlib",E"uncompress",E"uncompress(source[, uncompressed_size]) +("Sparse Matrices","","sprandn","sprandn(m, n, density) - Allocates a buffer of size \"uncompressed_size\", uncompresses - source to this buffer using the given compression level, and - returns the compressed buffer. If \"uncompressed_size\" is not - given, the size of the output buffer is estimated as - \"2*length(source)\". If the uncompressed_size is larger than - uncompressed_size, the allocated buffer is grown and the - uncompression is retried. - - If an error occurs, \"uncompress\" throws a \"ZError\" with more - information about the error. + Create a random sparse matrix of specified density with nonzeros + sampled from the normal distribution. "), -(E"Zlib",E"Zlib",E"uncompress_to_buffer",E"uncompress_to_buffer(source, dest) - - Uncompresses the source buffer into the destination buffer. Returns - the number of bytes written into dest. An error is thrown if the - destination buffer does not have enough space. +("Sparse Matrices","","sprandbool","sprandbool(m, n, density) - If an error occurs, \"uncompress_to_buffer\" throws a \"ZError\" - with more information about the error. + Create a random sparse boolean matrix with the specified density. "), diff --git a/doc/images/github_metadata_develbranch.png b/doc/images/github_metadata_develbranch.png new file mode 100644 index 0000000000000..e79df04eaa8cc Binary files /dev/null and b/doc/images/github_metadata_develbranch.png differ diff --git a/doc/images/github_metadata_pullrequest.png b/doc/images/github_metadata_pullrequest.png new file mode 100644 index 0000000000000..1a99fb6255c02 Binary files /dev/null and b/doc/images/github_metadata_pullrequest.png differ diff --git a/doc/index.rst b/doc/index.rst index c1303237dfec8..479f27ae5d6b6 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -8,6 +8,12 @@ manual/index stdlib/index + packages/packagelist + +Translations +============ + +* `The Julia Manual (Chinese) `_ Indices and tables ================== diff --git a/doc/listpkg.jl b/doc/listpkg.jl new file mode 100644 index 0000000000000..c62d6a1462150 --- /dev/null +++ b/doc/listpkg.jl @@ -0,0 +1,134 @@ + +require("JSON") +require("Calendar") +using Calendar + +try + global gh_auth + gh_auth = ENV["GH_AUTH"] +catch e + error ("Please provide a Github OAuth Token as environment variable GH_AUTH") +end + +function gen_listpkg() + + Pkg.update() + io=open("packages/packagelist.rst","w+"); + print(io, "********************\n Available Packages \n********************\n\n") + cd(Pkg.dir()) do + for pkg in Pkg.Metadata.each_package() + print(" Processing $(pkg)\n") + url = (Pkg.Metadata.pkg_url(pkg)) + maxv = Pkg.Metadata.versions([pkg])[end] + url_reg = r"^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?" + gh_path_reg_git=r"^/(.*)?/(.*)?.git$" + gh_path_reg_http=r"^/(.*)?/(.*)?$" + m=match(url_reg, url) + host=m.captures[4] + path=m.captures[5] + scheme=m.captures[2] + u=get_user_details_default() + + if ismatch(r"github\.com", host) + m2 = match(gh_path_reg_git, path) + user=m2.captures[1] + repo=m2.captures[2] + u=get_user_details_gh(user) + gh_repo_url = "https://api.github.com/repos/$(user)/$(repo)?access_token=$(gh_auth)" + gh_contrib_url = "https://api.github.com/repos/$(user)/$(repo)/contributors?access_token=$(gh_auth)" + #print("processing $gh_repo_url") + gh_repo=JSON.parse(readall(download_file(gh_repo_url))) + #print("processing $gh_user_url") + gh_contrib=JSON.parse(readall(download_file(gh_contrib_url))) + + + desc = get(gh_repo, "description", "No description provided") + homepage = get(gh_repo, "homepage", nothing) + html_url = gh_repo["html_url"] + end + print(io, "`$(pkg) <$(html_url)>`_\n"); + print(io, "_"^(length("`$(pkg) <$(html_url)>`_")) * "\n\n") + print(io, " .. image:: $(u[:avatar])\n :height: 80px\n :width: 80px\n :align: right\n :alt: $(u[:fullname])\n :target: $(u[:url])\n\n") + print(io, " Current Version: ``$(maxv.version)``\n\n"); + print(io, " $(desc) \n\n") + print(io, " Maintainer: `$(u[:fullname]) <$(u[:url])>`_\n\n") + + if homepage != nothing && length(chomp(homepage)) > 0 + print(io, " Documentation: `<$(homepage)>`_ \n\n") + end + print(io, " Dependencies::\n\n" ) + ver_dir = "METADATA/$pkg/versions/$(maxv.version)/requires" + any_ver = "Any Version" + if isfile(ver_dir) + vset = Pkg.Metadata.parse_requires(ver_dir) + if length(vset) > 0 + for deps in vset + print(io, " $(deps.package)"); print(io, " "^(15-length(deps.package))); print(io, "$(length(deps.versions)>0 ? deps.versions : any_ver)\n") + end + else + print(io, " None\n") + end + else + print(io, " None\n") + end + print(io, "\n") + + if ismatch(r"github\.com", host) + print(io, " Contributors:\n\n") + for contributor in gh_contrib + c_user = get(contributor, "login", "") + u=get_user_details_gh(c_user) + print(io, " .. image:: $(u[:avatar])\n :height: 40px\n :width: 40px\n") + print(io, " :alt: $(u[:fullname])\n :target: $(u[:url])\n\n") + end #for contributor + end + + print(io, "----\n\n") + end #for pkg + print(io, ".. footer: $(length(Pkg.Metadata.packages())) packages, generated $(now()) \n\n") + end #cd + + close(io) +end #function + +global user_cache = Dict{String, Dict}() + +function get_user_details_default() + u=Dict{Symbol, String}() + u[:login] = "Unknown" + u[:fullname] = "Unknown" + u[:avatar] = "Not provided" + u[:url] = "Not provided" + +end + +function get_user_details_gh(user) + + if !has(user_cache, user) + gh_user_url = "https://api.github.com/users/$(user)?access_token=$(gh_auth)" + gh_user=JSON.parse(readall(download_file(gh_user_url))) + fullname = get(gh_user, "name", user) + if fullname == nothing; fullname = user; end + avatar = + user_url = gh_user["html_url"] + + u=Dict{Symbol, String}() + + u[:login] = user + u[:avatar] = gh_user["avatar_url"] + #Sometimes name is missing, sometimes it is null in the JSON + if get(gh_user, "name", user) == nothing + u[:fullname] = user + else + u[:fullname] = get(gh_user, "name", user) + end + u[:url] = gh_user["html_url"] + + user_cache[user] = u + end + + return user_cache[user] + +end #function + +gen_listpkg() diff --git a/doc/manual/arrays.rst b/doc/manual/arrays.rst index da9b5bdd19cc3..cfa0172f4af25 100644 --- a/doc/manual/arrays.rst +++ b/doc/manual/arrays.rst @@ -12,10 +12,10 @@ library is implemented almost completely in Julia itself, and derives its performance from the compiler, just like any other code written in Julia. -An array is a collection of objects stored in a multi-dimensional grid. -In the most general case, an array may contain objects of type ``Any``. -For most computational purposes, arrays should contain objects of a more -specific type, such as ``Float64`` or ``Int32``. +An array is a collection of objects stored in a multi-dimensional +grid. In the most general case, an array may contain objects of type +``Any``. For most computational purposes, arrays should contain +objects of a more specific type, such as ``Float64`` or ``Int32``. In general, unlike many other technical computing languages, Julia does not expect programs to be written in a vectorized style for performance. @@ -166,15 +166,20 @@ where each I\_k may be: 1. A scalar value 2. A ``Range`` of the form ``:``, ``a:b``, or ``a:b:c`` 3. An arbitrary integer vector, including the empty vector ``[]`` +4. A boolean vector -The result X has the dimensions -``(size(I_1), size(I_2), ..., size(I_n))``, with location +The result X generally has dimensions +``(length(I_1), length(I_2), ..., length(I_n))``, with location ``(i_1, i_2, ..., i_n)`` of X containing the value -``A[I_1[i_1], I_2[i_2], ..., I_n[i_n]]``. +``A[I_1[i_1], I_2[i_2], ..., I_n[i_n]]``. Trailing dimensions indexed with +scalars are dropped. For example, the dimensions of ``A[I, 1]`` will be +``(length(I),)``. The size of a dimension indexed by a boolean vector +will be the number of true values in the vector (they behave as if they were +transformed with ``find``). -Indexing syntax is equivalent to a call to ``ref``:: +Indexing syntax is equivalent to a call to ``getindex``:: - X = ref(A, I_1, I_2, ..., I_n) + X = getindex(A, I_1, I_2, ..., I_n) Example:: @@ -202,14 +207,15 @@ where each I\_k may be: 1. A scalar value 2. A ``Range`` of the form ``:``, ``a:b``, or ``a:b:c`` 3. An arbitrary integer vector, including the empty vector ``[]`` +4. A boolean vector -The size of X should be ``(size(I_1), size(I_2), ..., size(I_n))``, and +The size of X should be ``(length(I_1), length(I_2), ..., length(I_n))``, and the value in location ``(i_1, i_2, ..., i_n)`` of A is overwritten with the value ``X[I_1[i_1], I_2[i_2], ..., I_n[i_n]]``. -Index assignment syntax is equivalent to a call to ``assign``:: +Index assignment syntax is equivalent to a call to ``setindex!``:: - A = assign(A, X, I_1, I_2, ..., I_n) + A = setindex!(A, X, I_1, I_2, ..., I_n) Example:: @@ -239,7 +245,7 @@ syntax: Concatenation operators may also be used for concatenating arrays: -1. ``[A B C...]`` — calls ``hcat`` +1. ``[A B C ...]`` — calls ``hcat`` 2. ``[A, B, C, ...]`` — calls ``vcat`` 3. ``[A B; C D; ...]`` — calls ``hvcat`` @@ -262,8 +268,7 @@ one of the inputs is a scalar. ``sec``, ``csc``, ``cot``, ``asec``, ``acsc``, ``acot``, ``sech``, ``csch``, ``coth``, ``asech``, ``acsch``, ``acoth``, ``sinc``, ``cosc``, ``hypot`` -7. Logarithmic functions — ``log``, ``log2``, ``log10``, ``log1p``, - ``logb``, ``ilogb`` +7. Logarithmic functions — ``log``, ``log2``, ``log10``, ``log1p`` 8. Exponential functions — ``exp``, ``expm1``, ``exp2``, ``ldexp`` 9. Rounding functions — ``ceil``, ``floor``, ``trunc``, ``round``, ``ipart``, ``fpart`` @@ -271,6 +276,41 @@ one of the inputs is a scalar. ``sqrt``, ``cbrt``, ``erf``, ``erfc``, ``gamma``, ``lgamma``, ``real``, ``conj``, ``clamp`` +Broadcasting +------------ + +It is sometimes useful to perform element-by-element binary operations +on arrays of different sizes, such as adding a vector to each column +of a matrix. An inefficient way to do this would be to replicate the +vector to the size of the matrix:: + + julia> a = rand(2,1); A = rand(2,3); + + julia> repmat(a,1,3)+A + 2x3 Float64 Array: + 0.848333 1.66714 1.3262 + 1.26743 1.77988 1.13859 + +This is wasteful when dimensions get large, so Julia offers the +MATLAB-inspired ``bsxfun``, which expands singleton dimensions in +array arguments to match the corresponding dimension in the other +array without using extra memory, and applies the given binary +function:: + + julia> bsxfun(+, a, A) + 2x3 Float64 Array: + 0.848333 1.66714 1.3262 + 1.26743 1.77988 1.13859 + + julia> b = rand(1,2) + 1x2 Float64 Array: + 0.629799 0.754948 + + julia> bsxfun(+, a, b) + 2x2 Float64 Array: + 1.31849 1.44364 + 1.56107 1.68622 + Implementation -------------- @@ -293,9 +333,9 @@ generic manner for ``AbstractArray``. ``SubArray`` is a specialization of ``AbstractArray`` that performs indexing by reference rather than by copying. A ``SubArray`` is created -with the ``sub`` function, which is called the same way as ``ref`` (with +with the ``sub`` function, which is called the same way as ``getindex`` (with an array and a series of index arguments). The result of ``sub`` looks -the same as the result of ``ref``, except the data is left in place. +the same as the result of ``getindex``, except the data is left in place. ``sub`` stores the input index vectors in a ``SubArray`` object, which can later be used to index the original array indirectly. @@ -309,27 +349,159 @@ of a larger array, without creating any temporaries, and by calling the appropriate LAPACK function with the right leading dimension size and stride parameters. +.. code-block:: jlcon + + julia> a = rand(10,10) + 10x10 Float64 Array: + 0.763921 0.884854 0.818783 0.519682 … 0.860332 0.882295 0.420202 + 0.190079 0.235315 0.0669517 0.020172 0.902405 0.0024219 0.24984 + 0.823817 0.0285394 0.390379 0.202234 0.516727 0.247442 0.308572 + 0.566851 0.622764 0.0683611 0.372167 0.280587 0.227102 0.145647 + 0.151173 0.179177 0.0510514 0.615746 0.322073 0.245435 0.976068 + 0.534307 0.493124 0.796481 0.0314695 … 0.843201 0.53461 0.910584 + 0.885078 0.891022 0.691548 0.547 0.727538 0.0218296 0.174351 + 0.123628 0.833214 0.0224507 0.806369 0.80163 0.457005 0.226993 + 0.362621 0.389317 0.702764 0.385856 0.155392 0.497805 0.430512 + 0.504046 0.532631 0.477461 0.225632 0.919701 0.0453513 0.505329 + + julia> b = sub(a, 2:2:8,2:2:4) + 4x2 SubArray of 10x10 Float64 Array: + 0.235315 0.020172 + 0.622764 0.372167 + 0.493124 0.0314695 + 0.833214 0.806369 + + julia> (q,r) = qr(b); + + julia> q + 4x2 Float64 Array: + -0.200268 0.331205 + -0.530012 0.107555 + -0.41968 0.720129 + -0.709119 -0.600124 + + julia> r + 2x2 Float64 Array: + -1.175 -0.786311 + 0.0 -0.414549 + +****************** + Sparse Matrices +****************** + +`Sparse matrices `_ are +matrices that contain enough zeros that storing them in a special data +structure leads to savings in space and execution time. Sparse +matrices may be used when operations on the sparse representation of a +matrix lead to considerable gains in either time or space when +compared to performing the same operations on a dense matrix. + +Compressed Sparse Column (CSC) Storage +-------------------------------------- + +In julia, sparse matrices are stored in the `Compressed Sparse Column +(CSC) format +`_. Julia +sparse matrices have the type ``SparseMatrixCSC{Tv,Ti}``, where ``Tv`` +is the type of the nonzero values, and ``Ti`` is the integer type for +storing column pointers and row indices. :: - julia> a = rand(10,10); + type SparseMatrixCSC{Tv,Ti<:Integer} <: AbstractSparseMatrix{Tv,Ti} + m::Int # Number of rows + n::Int # Number of columns + colptr::Vector{Ti} # Column i is in colptr[i]:(colptr[i+1]-1) + rowval::Vector{Ti} # Row values of nonzeros + nzval::Vector{Tv} # Nonzero values + end - julia> b = sub(a, 2:2:8,2:2:4) - 4x2 SubArray of 10x10 Float64 Array - 0.48291296659328276 0.31639301252254248 - 0.11191852765878418 0.80311033863988501 - 0.34377272170384798 0.12998312467801409 - 0.75207724893767547 0.48974544536835718 +The compressed sparse column storage makes it easy and quick to access +the elements in the column of a sparse matrix, whereas accessing the +sparse matrix by rows is considerably slower. Operations such as +insertion of nonzero values one at a time in the CSC structure tend to +be slow. This is because all elements of the sparse matrix that are +beyond the point of insertion have to be moved one place over. - julia> (q,r) = qr(b); +All operations on sparse matrices are carefully implemented to exploit +the CSC data structure for performance, and to avoid expensive operations. - julia> q - 4x2 Float64 Array - -0.31610281030340204 0.38994108897230212 - -0.80237370921615103 -0.5848318975546335 - -0.12986390146593485 0.36571345172816944 - -0.48929624071011685 0.61005841520202764 +Sparse matrix constructors +-------------------------- - julia> r - 2x2 Float64 Array - -1.00091806276211814 -0.65508286752651457 - 0.0 0.70738744643074303 +The simplest way to create sparse matrices are using functions +equivalent to the ``zeros`` and ``eye`` functions that Julia provides +for working with dense matrices. To produce sparse matrices instead, +you can use the same names with an ``sp`` prefix: + +:: + + julia> spzeros(3,5) + 3x5 sparse matrix with 0 nonzeros: + + julia> speye(3,5) + 3x5 sparse matrix with 3 nonzeros: + [1, 1] = 1.0 + [2, 2] = 1.0 + [3, 3] = 1.0 + +The ``sparse`` function is often a handy way to construct sparse +matrices. It takes as its input a vector ``I`` of row indices, a +vector ``J`` of column indices, and a vector ``V`` of nonzero +values. ``sparse(I,J,V)`` constructs a sparse matrix such that +``S[I[k], J[k]] = V[k]``. + +:: + + julia> I = [1, 4, 3, 5]; J = [4, 7, 18, 9]; V = [1, 2, -5, 3]; + + julia> sparse(I,J,V) + 5x18 sparse matrix with 4 nonzeros: + [1 , 4] = 1 + [4 , 7] = 2 + [5 , 9] = 3 + [3 , 18] = -5 + +The inverse of the ``sparse`` function is ``findn``, which +retrieves the inputs used to create the sparse matrix. + +:: + + julia> findn(S) + ([1, 4, 5, 3],[4, 7, 9, 18]) + + julia> findn_nzs(S) + ([1, 4, 5, 3],[4, 7, 9, 18],[1, 2, 3, -5]) + +Another way to create sparse matrices is to convert a dense matrix +into a sparse matrix using the ``sparse`` function: + +:: + + julia> sparse(eye(5)) + 5x5 sparse matrix with 5 nonzeros: + [1, 1] = 1.0 + [2, 2] = 1.0 + [3, 3] = 1.0 + [4, 4] = 1.0 + [5, 5] = 1.0 + +You can go in the other direction using the ``dense`` or the ``full`` +function. The ``issparse`` function can be used to query if a matrix +is sparse. + +:: + + julia> issparse(speye(5)) + true + +Sparse matrix operations +------------------------ + +Arithmetic operations on sparse matrices also work as they do on dense +matrices. Indexing of, assignment into, and concatenation of sparse +matrices work in the same way as dense matrices. Indexing operations, +especially assignment, are expensive, when carried out one element at +a time. In many cases it may be better to convert the sparse matrix +into ``(I,J,V)`` format using ``find_nzs``, manipulate the nonzeros or +the structure in the dense vectors ``(I,J,V)``, and then reconstruct +the sparse matrix. diff --git a/doc/manual/calling-c-and-fortran-code.rst b/doc/manual/calling-c-and-fortran-code.rst index 40ee8075b5b41..d02e8d1b9bd88 100644 --- a/doc/manual/calling-c-and-fortran-code.rst +++ b/doc/manual/calling-c-and-fortran-code.rst @@ -10,11 +10,8 @@ Fortran. To allow easy use of this existing code, Julia makes it simple and efficient to call C and Fortran functions. Julia has a "no boilerplate" philosophy: functions can be called directly from Julia without any "glue" code, code generation, or compilation — even from the -interactive prompt. This is accomplished in three steps: - -1. Load a shared library and create a handle to it. -2. Lookup a library function by name, getting a handle to it. -3. Call the library function using the built-in ``ccall`` function. +interactive prompt. This is accomplished just by making an appropriate call +with ``call`` syntax, which looks like an ordinary function call. The code to be called must be available as a shared library. Most C and Fortran libraries ship compiled as shared libraries already, but if you @@ -29,26 +26,22 @@ possible to perform whole-program optimizations that can even optimize across this boundary, but Julia does not yet support that. In the future, however, it may do so, yielding even greater performance gains.) -Shared libraries are loaded with ``dlopen`` function, which provides -access to the functionality of the POSIX ``dlopen(3)`` call: it locates -a shared library binary and loads it into the process' memory allowing -the program to access functions and variables contained in the library. -The following call loads the standard C library, and stores the -resulting handle in a Julia variable called ``libc``:: - - libc = dlopen("libc") +Shared libraries and functions are referenced by a tuple of the +form ``(:function, "library")`` or ``("function", "library")`` where ``function`` +is the C-exported function name. ``library`` refers to the shared library +name: shared libraries available in the (platform-specific) load path +will be resolved by name, and if necessary a direct path may be specified. -Once a library has been loaded, functions can be looked up by name using -the ``dlsym`` function, which exposes the functionality of the POSIX -``dlsym(3)`` call. This returns a handle to the ``clock`` function from -the standard C library:: - - libc_clock = dlsym(libc, :clock) +A function name may be used alone in place of the tuple (just +``:function`` or ``"function"``). In this case the name is resolved within +the current process. This form can be used to call C library functions, +functions in the Julia runtime, or functions in an application linked to +Julia. Finally, you can use ``ccall`` to actually generate a call to the -library function. Inputs to ``ccall`` are as follows: +library function. Arguments to ``ccall`` are as follows: -1. Function reference from ``dlsym`` — a value of type ``Ptr{Void}``. +1. (:function, "library") pair (must be a constant, but see below). 2. Return type, which may be any bits type, including ``Int32``, ``Int64``, ``Float64``, or ``Ptr{T}`` for any type parameter ``T``, indicating a pointer to values of type ``T``, or just ``Ptr`` for @@ -60,8 +53,11 @@ library function. Inputs to ``ccall`` are as follows: As a complete but simple example, the following calls the ``clock`` function from the standard C library:: - julia> t = ccall(dlsym(libc, :clock), Int32, ()) - 5380445 + julia> t = ccall( (:clock, "libc"), Int32, ()) + 2292761 + + julia> t + 2292761 julia> typeof(ans) Int32 @@ -71,11 +67,11 @@ is that a 1-tuple must be written with with a trailing comma. For example, to call the ``getenv`` function to get a pointer to the value of an environment variable, one makes a call like this:: - julia> path = ccall(dlsym(libc, :getenv), Ptr{Uint8}, (Ptr{Uint8},), "SHELL") - Ptr{Uint8} @0x00007fff5fbfd670 + julia> path = ccall( (:getenv, "libc"), Ptr{Uint8}, (Ptr{Uint8},), "SHELL") + Ptr{Uint8} @0x00007fff5fbffc45 julia> bytestring(path) - "/bin/zsh" + "/bin/bash" Note that the argument type tuple must be written as ``(Ptr{Uint8},)``, rather than ``(Ptr{Uint8})``. This is because ``(Ptr{Uint8})`` is just @@ -98,7 +94,7 @@ in `env.jl `_:: function getenv(var::String) - val = ccall(dlsym(libc, :getenv), + val = ccall( (:getenv, "libc"), Ptr{Uint8}, (Ptr{Uint8},), bytestring(var)) if val == C_NULL error("getenv: undefined variable: ", var) @@ -113,7 +109,7 @@ throws an exception clearly indicating the problem if the caller tries to get a non-existent environment variable:: julia> getenv("SHELL") - "/bin/zsh" + "/bin/bash" julia> getenv("FOOBAR") getenv: undefined variable: FOOBAR @@ -123,8 +119,8 @@ machine's hostname:: function gethostname() hostname = Array(Uint8, 128) - ccall(dlsym(libc, :gethostname), Int32, - (Ptr{Uint8}, Ulong), + ccall( (:gethostname, "libc"), Int32, + (Ptr{Uint8}, Uint), hostname, length(hostname)) return bytestring(convert(Ptr{Uint8}, hostname)) end @@ -146,13 +142,11 @@ example computes a dot product using a BLAS function. :: - libBLAS = dlopen("libLAPACK") - function compute_dot(DX::Vector, DY::Vector) assert(length(DX) == length(DY)) n = length(DX) incx = incy = 1 - product = ccall(dlsym(libBLAS, :ddot_), + product = ccall( (:ddot_, "libLAPACK"), Float64, (Ptr{Int32}, Ptr{Float64}, Ptr{Int32}, Ptr{Float64}, Ptr{Int32}), &n, DX, &incx, DY, &incy) @@ -161,10 +155,11 @@ example computes a dot product using a BLAS function. The meaning of prefix ``&`` is not quite the same as in C. In particular, any changes to the referenced variables will not be visible -in Julia. However, it will not cause any harm for called functions to -attempt such modifications (that is, writing through the passed -pointers). Since this ``&`` is not a real address operator, it may be -used with any syntax, such as ``&0`` or ``&f(x)``. +in Julia. However, it will +never cause any harm for called functions to attempt such modifications +(that is, writing through the passed pointers). Since this ``&`` is not +a real address operator, it may be used with any syntax, such as +``&0`` or ``&f(x)``. Note that no C header files are used anywhere in the process. Currently, it is not possible to pass structs and other non-primitive types from @@ -181,12 +176,12 @@ Mapping C Types to Julia Julia automatically inserts calls to the ``convert`` function to convert each argument to the specified type. For example, the following call:: - ccall(dlsym(libfoo, :foo), Void, (Int32, Float64), + ccall( (:foo, "libfoo"), Void, (Int32, Float64), x, y) will behave as if the following were written:: - ccall(dlsym(libfoo, :foo), Void, (Int32, Float64), + ccall( (:foo, "libfoo"), Void, (Int32, Float64), convert(Int32, x), convert(Float64, y)) When a scalar value is passed with ``&`` as an argument of type @@ -209,22 +204,60 @@ Type correspondences ~~~~~~~~~~~~~~~~~~~~ On all systems we currently support, basic C/C++ value types may be -translated to Julia types as follows. +translated to Julia types as follows. Every C type also has a corresponding +Julia type with the same name, prefixed by C. This can help for writing portable code (and remembering that an int in C is not the same as an Int in Julia). **System-independent:** -- ``bool`` ⟺ ``Bool`` -- ``char`` ⟺ ``Uint8`` -- ``signed char`` ⟺ ``Int8`` -- ``unsigned char`` ⟺ ``Uint8`` -- ``short`` ⟺ ``Int16`` -- ``unsigned short`` ⟺ ``Uint16`` -- ``int`` ⟺ ``Int32`` -- ``unsigned int`` ⟺ ``Uint32`` -- ``long long`` ⟺ ``Int64`` -- ``unsigned long long`` ⟺ ``Uint64`` -- ``float`` ⟺ ``Float32`` -- ``double`` ⟺ ``Float64`` ++------------------------+-------------------+--------------------------------+ +| ``bool`` (8 bits) | ``Cbool`` | ``Bool`` | ++------------------------+-------------------+--------------------------------+ +| ``signed char`` | | ``Int8`` | ++------------------------+-------------------+--------------------------------+ +| ``unsigned char`` | ``Cuchar`` | ``Uint8`` | ++------------------------+-------------------+--------------------------------+ +| ``short`` | ``Cshort`` | ``Int16`` | ++------------------------+-------------------+--------------------------------+ +| ``unsigned short`` | ``Cushort`` | ``Uint16`` | ++------------------------+-------------------+--------------------------------+ +| ``int`` | ``Cint`` | ``Int32`` | ++------------------------+-------------------+--------------------------------+ +| ``unsigned int`` | ``Cuint`` | ``Uint32`` | ++------------------------+-------------------+--------------------------------+ +| ``long long`` | ``Clonglong`` | ``Int64`` | ++------------------------+-------------------+--------------------------------+ +| ``unsigned long long`` | ``Culonglong`` | ``Uint64`` | ++------------------------+-------------------+--------------------------------+ +| ``float`` | ``Cfloat`` | ``Float32`` | ++------------------------+-------------------+--------------------------------+ +| ``double`` | ``Cdouble`` | ``Float64`` | ++------------------------+-------------------+--------------------------------+ +| ``ptrdiff_t`` | ``Cptrdiff_t`` | ``Int`` | ++------------------------+-------------------+--------------------------------+ +| ``size_t`` | ``Csize_t`` | ``Uint`` | ++------------------------+-------------------+--------------------------------+ +| ``complex float`` | ``Ccomplex_float`` (future addition) | ++------------------------+-------------------+--------------------------------+ +| ``complex double`` | ``Ccomplex_double`` (future addition) | ++------------------------+-------------------+--------------------------------+ +| ``void`` | | ``Void`` | ++------------------------+-------------------+--------------------------------+ +| ``void*`` | | ``Ptr{Void}`` | ++------------------------+-------------------+--------------------------------+ +| ``char*`` (or ``char[]``, e.g. a string) | ``Ptr{Uint8}`` | ++------------------------+-------------------+--------------------------------+ +| ``char**`` (or ``*char[]``) | ``Ptr{Ptr{Uint8}}`` | ++------------------------+-------------------+--------------------------------+ +| ``struct T*`` (where T represents an | ``Ptr{T}`` (call using | +| appropriately defined bits type) | &variable_name in the | +| | parameter list) | ++------------------------+-------------------+--------------------------------+ +| ``struct T`` (where T represents an | ``T`` (call using | +| appropriately defined bits type) | &variable_name in the | +| | parameter list) | ++------------------------+-------------------+--------------------------------+ +| ``jl_value_t*`` (any Julia Type) | ``Ptr{Any}`` | ++------------------------+-------------------+--------------------------------+ *Note:* the ``bool`` type is only defined by C++, where it is 8 bits wide. In C, however, ``int`` is often used for boolean values. Since @@ -235,17 +268,26 @@ A C function declared to return ``void`` will give ``nothing`` in Julia. **System-dependent:** -- ``long`` ⟺ ``Int`` -- ``unsigned long`` ⟺ ``Uint`` -- ``size_t`` ⟺ ``Uint`` -- ``wchar_t`` ⟺ ``Char`` +====================== ============== ======= +``char`` ``Cchar`` ``Int8`` (x86, x86_64) + + ``Uint8`` (powerpc, arm) +``long`` ``Clong`` ``Int`` (UNIX) -*Note:* Although ``wchar_t`` is technically system-dependent, on all the -systems we currently support (UNIX), it is a 32 bits. + ``Int32`` (Windows) +``unsigned long`` ``Culong`` ``Uint`` (UNIX) -C functions that take an arguments of the type ``char**`` can be called -by using a ``Ptr{Ptr{Uint8}}`` type within Julia. For example, C -functions of the form:: + ``Int32`` (Windows) +``wchar_t`` ``Char`` Although ``wchar_t`` is technically + system-dependent, on all the + systems we currently support (UNIX), + it is 32-bit. +====================== ============== ======= + +For string arguments (``char*``) the Julia type should be ``Ptr{Uint8}``, +not ``ASCIIString``. C functions that take an argument of the type ``char**`` +can be called by using a ``Ptr{Ptr{Uint8}}`` type within Julia. For example, +C functions of the form:: int main(int argc, char **argv); @@ -255,7 +297,96 @@ can be called via the following Julia code:: ccall(:main, Int32, (Int32, Ptr{Ptr{Uint8}}), length(argv), argv) +Accessing Data through a Pointer +-------------------------------- +The following methods are described as "unsafe" because they can cause Julia +to terminate abruptly or corrupt arbitrary process memory due to a bad pointer +or type declaration. + +Given a ``Ptr{T}``, the contents of type ``T`` can generally be copied from +the referenced memory into a Julia object using ``unsafe_ref(ptr, [index])``. The +index argument is optional (default is 1), and performs 1-based indexing. This +function is intentionally similar to the behavior of ``getindex()`` and ``setindex!()`` +(e.g. ``[]`` access syntax). + +The return value will be a new object initialized +to contain a copy of the contents of the referenced memory. The referenced +memory can safely be freed or released. + +If ``T`` is ``Any``, then the memory is assumed to contain a reference to +a Julia object (a ``jl_value_t*``), the result will be a reference to this object, +and the object will not be copied. You must be careful in this case to ensure +that the object was always visible to the garbage collector (pointers do not +count, but the new reference does) to ensure the memory is not prematurely freed. +Note that if the object was not originally allocated by Julia, the new object +will never be finalized by Julia's garbage collector. If the ``Ptr`` itself +is actually a ``jl_value_t*``, it can be converted back to a Julia object +reference by ``unsafe_pointer_to_objref(ptr)``. (Julia values ``v`` +can be converted to ``jl_value_t*`` pointers, as ``Ptr{Void}``, by calling +``pointer_from_objref(v)``.) + +The reverse operation (writing data to a Ptr{T}), can be performed using +``unsafe_assign(ptr, value, [index])``. Currently, this is only supported +for bitstypes or other pointer-free (``isbits``) immutable types. + +Any operation that throws an error is probably currently unimplemented +and should be posted as a bug so that it can be resolved. + +If the pointer of interest is a plan-data array (bitstype or immutable), the +function ``pointer_to_array(ptr,dims,[own])`` may be more more useful. The final +parameter should be true if Julia should "take ownership" of the underlying +buffer and call ``free(ptr)`` when the returned ``Array`` object is finalized. +If the ``own`` parameter is omitted or false, the caller must ensure the +buffer remains in existence until all access is complete. + + +Garbage Collection Safety +------------------------- +When passing data to a ccall, it is best to avoid using the ``pointer()`` +function. Instead define a convert method and pass the variables directly to +the ccall. ccall automatically arranges that all of its arguments will be +preserved from garbage collection until the call returns. If a C API will +store a reference to memory allocated by Julia, after the ccall returns, you +must arrange that the object remains visible to the garbage collector. The +suggested way to handle this is to make a global variable of type +``Array{Any,1}`` to hold these values, until C interface notifies you that +it is finished with them. + +Whenever you have created a pointer to Julia data, you must ensure the original data +exists until you are done with using the pointer. Many methods in Julia such as +``unsafe_ref()`` and ``bytestring()`` make copies of data instead of taking ownership +of the buffer, so that it is safe to free (or alter) the original data without +affecting Julia. A notable exception is ``pointer_to_array()`` which, for performance +reasons, shares (or can be told to take ownership of) the underlying buffer. + + +Non-constant Function Specifications +------------------------------------ + +A ``(name, library)`` function specification must be a constant expression. +However, it is possible to use computed values as function names by staging +through ``eval`` as follows: + + @eval ccall(($(string("a","b")),"lib"), ... + +This expression constructs a name using ``string``, then substitutes this +name into a new ``ccall`` expression, which is then evaluated. Keep in mind that +``eval`` only operates at the top level, so within this expression local +variables will not be available (unless their values are substituted with +``$``). For this reason, ``eval`` is typically only used to form top-level +definitions, for example when wrapping libraries that contain many +similar functions. + +Indirect calls +-------------- + +The first argument to ``ccall`` can also be an expression evaluated at +run time. In this case, the expression must evaluate to a ``Ptr``, +which will be used as the address of the native function to call. This +behavior occurs when the first ``ccall`` argument contains references +to non-constants, such as local variables or function arguments. + C++ --- -Limited support for C++ is provided by the :mod:`cpp.jl` module. +Limited support for C++ is provided by the `Cpp` package. diff --git a/doc/manual/complex-and-rational-numbers.rst b/doc/manual/complex-and-rational-numbers.rst index c0f807c119db0..1a5e12cce57ac 100644 --- a/doc/manual/complex-and-rational-numbers.rst +++ b/doc/manual/complex-and-rational-numbers.rst @@ -58,7 +58,7 @@ numbers:: julia> 3(2 - 5im)^2 -63 - 60im - julia> 3(2 - 5im)^-1 + julia> 3(2 - 5im)^-1.0 0.20689655172413793 + 0.5172413793103449im The promotion mechanism ensures that combinations of operands of @@ -132,13 +132,14 @@ defined for complex numbers:: julia> sinh(1 + 2im) -0.48905625904129374 + 1.4031192506220407im -Note that mathematical functions always return real values when applied +Note that mathematical functions typically return real values when applied to real numbers and complex values when applied to complex numbers. -Thus, ``sqrt``, for example, behaves differently when applied to ``-1`` +For example, ``sqrt``, for example, behaves differently when applied to ``-1`` versus ``-1 + 0im`` even though ``-1 == -1 + 0im``:: julia> sqrt(-1) - NaN + ERROR: DomainError() + in sqrt at math.jl:111 julia> sqrt(-1 + 0im) 0.0 + 1.0im @@ -150,37 +151,25 @@ the multiplication operation will:: julia> a = 1; b = 2; a + b*im 1 + 2im -Constructing complex numbers from variable values like this, however, is -not recommended. Use the ``complex`` function to construct a complex -value directly from its real and imaginary parts instead:: +Constructing complex numbers from variable values like this, however, +is not recommended. Use the ``complex`` function to construct a +complex value directly from its real and imaginary parts instead. This +construction is preferred for variable arguments because it is more +efficient than the multiplication and addition construct, but also +because certain values of ``b`` can yield unexpected results:: julia> complex(a,b) 1 + 2im -This construction is preferred for variable arguments because it is more -efficient than the multiplication and addition construct, but also -because certain values of ``b`` can yield unexpected results:: +``Inf`` and ``NaN`` propagate through complex numbers in the real +and imaginary parts of a complex number as per IEEE-754 arithmetic:: julia> 1 + Inf*im - NaN + Inf*im - - julia> 1 + NaN*im - NaN + NaN*im - -These results are natural and unavoidable consequences of the -interaction between the rules of complex multiplication and IEEE-754 -floating-point arithmetic. Using the ``complex`` function to construct -complex values directly, however, gives more intuitive results:: - - julia> complex(1,Inf) complex(1.0,Inf) - julia> complex(1,NaN) + julia> 1 + NaN*im complex(1.0,NaN) -On the other hand, it can be argued that these values do not represent -meaningful complex numbers, and are thus not appreciably different from -the results gotten when multiplying explicitly by ``im``. .. _man-rational-numbers: diff --git a/doc/manual/constructors.rst b/doc/manual/constructors.rst index 1e2bd16ba2021..ad281013424b1 100644 --- a/doc/manual/constructors.rst +++ b/doc/manual/constructors.rst @@ -123,11 +123,10 @@ Now ``OrderedPair`` objects can only be constructed such that julia> OrderedPair(2,1) out of order - in OrderedPair at prompt:5 + in OrderedPair at none:5 You can still reach in and directly change the field values to violate -this invariant (support for immutable composites is planned but not yet -implemented), but messing around with an object's internals uninvited is +this invariant, but messing around with an object's internals uninvited is considered poor form. You (or someone else) can also provide additional outer constructor methods at any later point, but once a type is declared, there is no way to add more inner constructor methods. Since @@ -135,8 +134,12 @@ outer constructor methods can only create objects by calling other constructor methods, ultimately, some inner constructor must be called to create an object. This guarantees that all objects of the declared type must come into existence by a call to one of the inner constructor -methods provided with the type, thereby giving some degree of real -enforcement of a type's invariants, at least for object creation. +methods provided with the type, thereby giving some degree of +enforcement of a type's invariants. + +Of course, if the type is declared as ``immutable``, then its +constructor-provided invariants are fully enforced. This is an important +consideration when deciding whether a type should be immutable. If any inner constructor method is defined, no default constructor method is provided: it is presumed that you have supplied yourself with diff --git a/doc/manual/control-flow.rst b/doc/manual/control-flow.rst index a3d1b934820c1..a271b7cf715e7 100644 --- a/doc/manual/control-flow.rst +++ b/doc/manual/control-flow.rst @@ -111,7 +111,7 @@ blocks as desired can be used. The condition expressions in the evaluates to ``true``, after which the associated block is evaluated, and no further condition expressions or blocks are evaluated. -Unlike C, MATLAB®, Perl, Python, and Ruby — but like Java, and a few +Unlike C, MATLAB, Perl, Python, and Ruby — but like Java, and a few other stricter, typed languages — it is an error if the value of a conditional expression is anything but ``true`` or ``false``:: @@ -442,11 +442,11 @@ appropriate action. The ``error`` function is used to indicate that an unexpected condition has occurred which should interrupt the normal flow of control. The -built in ``sqrt`` function returns ``NaN`` if applied to a negative real +built in ``sqrt`` function returns ``DomainError()`` if applied to a negative real value:: julia> sqrt(-1) - NaN + DomainError() Suppose we want to stop execution immediately if the square root of a negative number is taken. To do this, we can define a fussy version of @@ -563,7 +563,7 @@ pass any value back to an enclosing ``try``-``catch``:: end Hello, world. -This example is contrived, of course — the power of the +This example is contrived, of course — the power of the ``try``-``catch`` construct lies in the ability to unwind a deeply nested computation immediately to a much higher level in the stack of calling functions. There are situations where no error has occurred, but diff --git a/doc/manual/conversion-and-promotion.rst b/doc/manual/conversion-and-promotion.rst index 50d87cd069e4b..190d98315034e 100644 --- a/doc/manual/conversion-and-promotion.rst +++ b/doc/manual/conversion-and-promotion.rst @@ -130,7 +130,17 @@ to zero:: false The method signatures for conversion methods are often quite a bit more -involved than this example, especially for parametric types. +involved than this example, especially for parametric types. The example +above is meant to be pedagogical, and is not the actual julia behaviour. +This is the actual implementation in julia:: + + convert{T<:Real}(::Type{T}, z::Complex) = (imag(z)==0 ? convert(T,real(z)) : + throw(InexactError())) + + julia> convert(Bool, 1im) + InexactError() + in convert at complex.jl:40 + Case Study: Rational Conversions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -255,7 +265,7 @@ fields promoted to an appropriate common type. For example, recall that `rational.jl `_ provides the following outer constructor method:: - Rational(n::Int, d::Int) = Rational(promote(n,d)...) + Rational(n::Integere, d::Integer) = Rational(promote(n,d)...) This allows calls like the following to work:: @@ -263,7 +273,7 @@ This allows calls like the following to work:: -3//1 julia> typeof(ans) - Rational{Int32} + Rational{Int64} For most user-defined types, it is better practice to require programmers to supply the expected types to constructor functions @@ -289,20 +299,18 @@ promoted together, they should be promoted to 64-bit floating-point. The promotion type does not need to be one of the argument types, however; the following promotion rules both occur in Julia's standard library:: - promote_rule(::Type{Uint8}, ::Type{Int8}) = Int16 + promote_rule(::Type{Uint8}, ::Type{Int8}) = Int promote_rule(::Type{Char}, ::Type{Uint8}) = Int32 -The former rule expresses that ``Int16`` is the smallest integer type -that contains all the values representable by both ``Uint8`` and -``Int8`` since the former's range extends above 127 while the latter's -range extends below 0. In the latter case, the result type is ``Int32`` -since ``Int32`` is large enough to contain all possible Unicode code -points, and numeric operations on characters always result in plain old -integers unless explicitly cast back to characters (see -:ref:`man-characters`). Also note that one does not need to +As a general rule, Julia promotes integers to `Int` during computation +order to avoid overflow. In the latter case, the result type is +``Int32`` since ``Int32`` is large enough to contain all possible +Unicode code points, and numeric operations on characters always +result in plain old integers unless explicitly cast back to characters +(see :ref:`man-characters`). Also note that one does not need to define both ``promote_rule(::Type{A}, ::Type{B})`` and -``promote_rule(::Type{B}, ::Type{A})`` — the symmetry is implied by the -way ``promote_rule`` is used in the promotion process. +``promote_rule(::Type{B}, ::Type{A})`` — the symmetry is implied by +the way ``promote_rule`` is used in the promotion process. The ``promote_rule`` function is used as a building block to define a second function called ``promote_type``, which, given any number of type @@ -312,7 +320,7 @@ of actual values, what type a collection of values of certain types would promote to, one can use ``promote_type``:: julia> promote_type(Int8, Uint16) - Int32 + Int64 Internally, ``promote_type`` is used inside of ``promote`` to determine what type argument values should be converted to for promotion. It can, diff --git a/doc/manual/functions.rst b/doc/manual/functions.rst index 2935a7039b182..57a0f1e3393d8 100644 --- a/doc/manual/functions.rst +++ b/doc/manual/functions.rst @@ -14,15 +14,15 @@ is:: x + y end -This syntax is similar to MATLAB®, but there are some significant +This syntax is similar to MATLAB, but there are some significant differences: -- In MATLAB®, this definition must be saved in a file, named ``f.m``, +- In MATLAB, this definition must be saved in a file, named ``f.m``, whereas in Julia, this expression can appear anywhere, including in an interactive session. -- In MATLAB®, the closing ``end`` is optional, being implied by the end +- In MATLAB, the closing ``end`` is optional, being implied by the end of the file. In Julia, the terminating ``end`` is required. -- In MATLAB®, this function would print the value ``x + y`` but would +- In MATLAB, this function would print the value ``x + y`` but would not return any value, whereas in Julia, the last expression evaluated is a function's return value. - Expression values are never printed automatically except in @@ -30,7 +30,7 @@ differences: expressions on the same line. In general, while the function definition syntax is reminiscent of -MATLAB®, the similarity is largely superficial. Therefore, rather than +MATLAB, the similarity is largely superficial. Therefore, rather than continually comparing the two, in what follows, we will simply describe the behavior of functions in Julia directly. @@ -184,7 +184,10 @@ which applies a function to each value of an array and returns a new array containing the resulting values:: julia> map(round, [1.2,3.5,1.7]) - [1.0,4.0,2.0] + 3-element Float64 Array: + 1.0 + 4.0 + 2.0 This is fine if a named function effecting the transform one wants already exists to pass as the first argument to ``map``. Often, however, @@ -193,7 +196,10 @@ anonymous function construct allows easy creation of a single-use function object without needing a name:: julia> map(x -> x^2 + 2x - 1, [1,3,-1]) - [2,14,-2] + 3-element Int64 Array: + 2 + 14 + -2 An anonymous function accepting multiple arguments can be written using the syntax ``(x,y,z)->2x+y-z``. A zero-argument anonymous function is @@ -302,13 +308,19 @@ Furthermore, the iterable object spliced into a function call need not be a tuple:: julia> x = [3,4] - [3,4] + 2-element Int64 Array: + 3 + 4 julia> bar(1,2,x...) (1,2,(3,4)) julia> x = [1,2,3,4] - [1,2,3,4] + 4-element Int64 Array: + 1 + 2 + 3 + 4 julia> bar(x...) (1,2,(3,4)) @@ -319,13 +331,18 @@ function (although it often is):: baz(a,b) = a + b julia> args = [1,2] - [1,2] + 2-element Int64 Array: + 1 + 2 julia> baz(args...) 3 julia> args = [1,2,3] - [1,2,3] + 3-element Int64 Array: + 1 + 2 + 3 julia> baz(args...) no method baz(Int64,Int64,Int64) @@ -334,6 +351,75 @@ As you can see, if the wrong number of elements are in the spliced container, then the function call will fail, just as it would if too many arguments were given explicitly. +Optional Arguments +------------------ + +In many cases, function arguments have sensible default values and therefore +might not need to be passed explicitly in every call. For example, the +library function ``parseint(num,base)`` interprets a string as a number +in some base. The ``base`` argument defaults to ``10``. This behavior can be +expressed concisely as:: + + function parseint(num, base=10) + ### + end + +With this definition, the function can be called with either one or two +arguments, and ``10`` is automatically passed when a second argument is not +specified:: + + julia> parseint("12",10) + 12 + + julia> parseint("12",3) + 5 + + julia> parseint("12") + 12 + +Optional arguments are actually just a convenient syntax for writing +multiple method definitions with different numbers of arguments +(see :ref:`man-methods`). + + +Named Arguments +--------------- + +Some functions need a large number of arguments, or have a large number of +behaviors. Remembering how to call such functions can be difficult. Named +arguments, also called keyword arguments, can make these complex interfaces +easier to use and extend by allowing arguments to be identified by name +instead of only by position. + +For example, consider a function ``plot`` that +plots a line. This function might have many options, for controlling line +style, width, color, and so on. If it accepts named arguments, a possible +call might look like ``plot(x, y, width=2)``, where we have chosen to +specify only line width. Notice that this serves two purposes. The call is +easier to read, since we can label an argument with its meaning. It also +becomes possible to pass any subset of a large number of arguments, in +any order. + +Functions with named arguments are defined using a semicolon in the +signature:: + + function plot(x, y; style="solid", width=1, color="black") + ### + end + +Extra named arguments can be collected using ``...``, as in varargs +functions:: + + function f(x; args...) + ### + end + +Inside ``f``, ``args`` will be a collection of ``(key,value)`` tuples, +where each ``key`` is a symbol. Such collections can be passed as named +arguments using a semicolon in a call, ``f(x; k...)``. Dictionaries +can be used for this purpose. + + Block Syntax for Function Arguments ----------------------------------- @@ -387,12 +473,6 @@ code. The function argument to ``open`` receives a handle to the opened file. -Named function arguments (optional parameters) ----------------------------------------------- - -Some complex functions may depend on a large number of parameters. In such cases, it can be inconvenient to have to supply a long argument list in specified order. Such cases can be handled via the :mod:`options.jl` module. - - Further Reading --------------- diff --git a/doc/manual/getting-started.rst b/doc/manual/getting-started.rst index b76a7f6d9f9e4..29697525cb683 100644 --- a/doc/manual/getting-started.rst +++ b/doc/manual/getting-started.rst @@ -4,11 +4,11 @@ Getting Started ***************** -The latest version of Julia can be downloaded and installed by following -the instructions on the `main GitHub -page `_. The easiest way to -learn and experiment with Julia is by starting an interactive session -(also known as a read-eval-print loop or "repl"):: +Julia installation is straightforward, whether using precompiled binaries or compiling from source. Download and install Julia by following the instructions at +`http://julialang.org/downloads/ `_. + +The easiest way to learn and experiment with Julia is by starting an +interactive session (also known as a read-eval-print loop or "repl"):: $ julia _ @@ -26,17 +26,18 @@ learn and experiment with Julia is by starting an interactive session julia> ans 3 - julia> load("file") +To exit the interactive session, type ``^D`` — the control key +together with the ``d`` key or type ``quit()``. When run in interactive +mode, ``julia`` displays a banner and prompts the user for input. Once +the user has entered a complete expression, such as ``1 + 2``, and +hits enter, the interactive session evaluates the expression and shows +its value. If an expression is entered into an interactive session +with a trailing semicolon, its value is not shown. The variable +``ans`` is bound to the value of the last evaluated expression whether +it is shown or not. -To exit the interactive session, type ``^D`` — the control key together -with the ``d`` key. When run in interactive mode, ``julia`` displays a -banner and prompts the user for input. Once the user has entered a -complete expression, such as ``1 + 2``, and hits enter, the interactive -session evaluates the expression and shows its value. If an expression -is entered into an interactive session with a trailing semicolon, its -value is not shown. The variable ``ans`` is bound to the value of the -last evaluated expression whether it is shown or not. The ``load`` -function reads and evaluates the contents of the given file. +To evaluate expressions written in a source file ``file.jl``, write +``include("file.jl")``. To run code in a file non-interactively, you can give it as the first argument to the julia command:: @@ -70,30 +71,39 @@ those available for the ``perl`` and ``ruby`` programs:: -H --home= Load files relative to -T --tab= Set REPL tab width to - -e --eval= Evaluate and don't print - -E --print= Evaluate and print + -e --eval= Evaluate + -E --print= Evaluate and show -P --post-boot= Evaluate right after boot -L --load=file Load right after boot -J --sysimage=file Start up with the given system image file -p n Run n local processes + --machinefile file Run processes on hosts listed in file + + --no-history Don't load or save history + -f --no-startup Don't load ~/.juliarc.jl + -F Load ~/.juliarc.jl, then handle remaining inputs -h --help Print this message -Example Code ------------- +Tutorials +--------- + +A few walkthrough-style tutorials are available online: -At this point it is useful to take a look at some :ref:`man-example-programs`. +- `Forio Julia Tutorials `_ +- `Tutorial for Homer Reid's numerical analysis class `_ -Major Differences From MATLAB® ------------------------------- +Noteworthy differences from MATLAB +---------------------------------- -Julia's syntax is intended to be familiar to users of MATLAB®. However, -Julia is in no way a MATLAB® clone: there are major syntactic and -functional differences. The following are the most significant -differences that may trip up Julia users accustomed to MATLAB®: +MATLAB users may find Julia's syntax familiar. However, +Julia is in no way a MATLAB clone: there are major syntactic and +functional differences. The following are some noteworthy +differences that may trip up Julia users accustomed to MATLAB: - Arrays are indexed with square brackets, ``A[i,j]``. +- The imaginary unit ``sqrt(-1)`` is represented in julia with ``im``. - Multiple values are returned and assigned with parentheses, ``return (a, b)`` and ``(a, b) = f(x)``. - Values are passed and assigned by reference. If a function modifies @@ -132,3 +142,37 @@ differences that may trip up Julia users accustomed to MATLAB®: operators, ``<``, ``>``, ``!=``, etc. - The elements of a collection can be passed as arguments to a function using ``...``, as in ``xs=[1,2]; f(xs...)``. +- Julia's ``svd`` returns singular values as a vector instead of as a + full diagonal matrix. + +Noteworthy differences from R +----------------------------- + +One of Julia's goals is to provide an effective language for data analysis and statistical programming. For users coming to Julia from R, these are some noteworthy differences: + +- Julia uses ``=`` for assignment. Julia does not provide any operator like ``<-`` or ``<-``. +- Julia constructs vectors using brackets. Julia's ``[1, 2, 3]`` is the equivalent of R's ``c(1, 2, 3)``. +- Julia's matrix operations are more like traditional mathematical notation than R's. If ``A`` and ``B`` are matrices, then ``A * B`` defines a matrix multiplication in Julia equivalent to R's ``A %*% B``. In R, this some notation would perform an elementwise Hadamard product. To get the elementwise multiplication operation, you need to write ``A .* B`` in Julia. +- Julia performs matrix transposition using the ``'`` operator. Julia's ``A'`` is therefore equivalent to R's ``t(A)``. +- Julia does not require parentheses when writing ``if`` statements or ``for`` loops: use ``for i in [1, 2, 3]`` instead of ``for (i in c(1, 2, 3))`` and ``if i == 1`` instead of ``if (i == 1)``. +- Julia does not treat the numbers ``0`` and ``1`` as Booleans. You cannot write ``if (1)`` in Julia, because ``if`` statements accept only booleans. Instead, you can write ``if true``. +- Julia does not provide ``nrow`` and ``ncol``. Instead, use ``size(M, 1)`` for ``nrow(M)`` and ``size(M, 2)`` for ``ncol(M)``. +- Julia's SVD is not thinned by default, unlike R. To get results like R's, you will often want to call ``svd(X, true)`` on a matrix ``X``. +- Julia is very careful to distinguish scalars, vectors and matrices. In R, ``1`` and ``c(1)`` are the same. In Julia, they can not be used interchangeably. One potentially confusing result of this is that ``x' * y`` for vectors ``x`` and ``y`` is a 1-element vector, not a scalar. To get a scalar, use ``dot(x, y)``. +- Julia's ``diag()`` and ``diagm()`` are not like R's. +- Julia cannot assign to the results of function calls on the left-hand of an assignment operation: you cannot write ``diag(M) = ones(n)``. +- Julia discourages populating the main namespace with functions. Most statistical functionality for Julia is found in `packages `_ like the DataFrames and Distributions packages: + - Distributions functions are found in the `Distributions package `_ + - The `DataFrames package `_ provides data frames. + - Formulas for GLM's must be escaped: use ``:(y ~ x)`` instead of ``y ~ x``. +- Julia provides tuples and real hash tables, but not R's lists. When returning multiple items, you should typically use a tuple: instead of ``list(a = 1, b = 2)``, use ``(1, 2)``. +- Julia encourages all users to write their own types. Julia's types are much easier to use than S3 or S4 objects in R. Julia's multiple dispatch system means that ``table(x::TypeA)`` and ``table(x::TypeB)`` act like R's ``table.TypeA(x)`` and ``table.TypeB(x)``. +- In Julia, values are passed and assigned by reference. If a function modifies an array, the changes will be visible in the caller. This is very different from R and allows new functions to operate on large data structures much more efficiently. +- Concatenation of vectors and matrices is done using ``hcat`` and ``vcat``, not ``c``, ``rbind`` and ``cbind``. +- A Julia range object like ``a:b`` is not shorthand for a vector like in R, but is a specialized type of object that is used for iteration without high memory overhead. To convert a range into a vector, you need to wrap the range with brackets ``[a:b]``. +- Julia has several functions that can mutate their arguments. For example, it has ``sort(v)`` and ``sort!(v)``. +- ``colMeans()`` and ``rowMeans()``, ``size(m, 1)`` and ``size(m, 2)`` +- In R, performance requires vectorization. In Julia, almost the opposite is true: the best performing code is often achieved by using devectorized loops. +- Unlike R, there is no delayed evaluation in Julia. For most users, this means that there are very few unquoted expressions or column names. +- Julia does not ``NULL`` type. +- There is no equivalent of R's ``assign`` or ``get`` in Julia. diff --git a/doc/manual/index.rst b/doc/manual/index.rst index 0ff56e820f974..5e74508fac93c 100644 --- a/doc/manual/index.rst +++ b/doc/manual/index.rst @@ -24,13 +24,12 @@ methods constructors conversion-and-promotion - arrays - sparse-matrices modules - running-external-programs metaprogramming + arrays parallel-computing + running-external-programs calling-c-and-fortran-code + packages performance-tips - potential-features diff --git a/doc/manual/integers-and-floating-point-numbers.rst b/doc/manual/integers-and-floating-point-numbers.rst index d26e140849685..598208e9f6c4c 100644 --- a/doc/manual/integers-and-floating-point-numbers.rst +++ b/doc/manual/integers-and-floating-point-numbers.rst @@ -25,6 +25,8 @@ them. The following are Julia's primitive numeric types: - ``Uint32`` — unsigned 32-bit integers ranging from 0 to 2^32 - 1. - ``Int64`` — signed 64-bit integers ranging from -2^63 to 2^63 - 1. - ``Uint64`` — unsigned 64-bit integers ranging from 0 to 2^64 - 1. + - ``Int128`` - signed 128-bit integers ranging from -2^127 to 2^127 - 1. + - ``Uint128`` - unsigned 128-bit integers ranging from 0 to 2^128 - 1. - ``Bool`` — either ``true`` or ``false``, which correspond numerically to 1 and 0. - ``Char`` — a 32-bit numeric type representing a `Unicode @@ -67,7 +69,8 @@ system has a 32-bit architecture or a 64-bit architecture:: julia> typeof(1) Int64 -The type ``Int`` is an alias for the system-native integer type:: +Use ``WORD_SIZE`` to figure out whether the target system is 32-bit +or 64-bit. The type ``Int`` is an alias for the system-native integer type:: # 32-bit system: julia> Int @@ -144,17 +147,20 @@ such as integers are given by the ``typemin`` and ``typemax`` functions:: julia> (typemin(Int32), typemax(Int32)) (-2147483648,2147483647) - julia> for T = {Int8,Int16,Int32,Int64,Uint8,Uint16,Uint32,Uint64} + julia> for T = {Int8,Int16,Int32,Int64,Int128,Uint8,Uint16,Uint32,Uint64,Uint128} println("$(lpad(T,6)): [$(typemin(T)),$(typemax(T))]") end - Int8: [-128,127] - Int16: [-32768,32767] - Int32: [-2147483648,2147483647] - Int64: [-9223372036854775808,9223372036854775807] - Uint8: [0x00,0xff] - Uint16: [0x0000,0xffff] - Uint32: [0x00000000,0xffffffff] - Uint64: [0x0000000000000000,0xffffffffffffffff] + + Int8: [-128,127] + Int16: [-32768,32767] + Int32: [-2147483648,2147483647] + Int64: [-9223372036854775808,9223372036854775807] + Int128: [-170141183460469231731687303715884105728,170141183460469231731687303715884105727] + Uint8: [0x00,0xff] + Uint16: [0x0000,0xffff] + Uint32: [0x00000000,0xffffffff] + Uint64: [0x0000000000000000,0xffffffffffffffff] + Uint128: [0x00000000000000000000000000000000,0xffffffffffffffffffffffffffffffff] The values returned by ``typemin`` and ``typemax`` are always of the given argument type. The above expression uses several features we have @@ -200,11 +206,11 @@ for ``Float32``, but you can convert values to ``Float32`` easily:: There are three specified standard floating-point values that do not correspond to a point on the real number line: -- ``Inf`` — positive infinity — a value greater than all finite +- ``Inf`` — positive infinity — a value greater than all finite floating-point values -- ``-Inf`` — negative infinity — a value less than all finite +- ``-Inf`` — negative infinity — a value less than all finite floating-point values -- ``NaN`` — not a number — a value incomparable to all floating-point +- ``NaN`` — not a number — a value incomparable to all floating-point values (including itself). For further discussion of how these non-finite floating-point values are @@ -244,13 +250,12 @@ The ``typemin`` and ``typemax`` functions also apply to floating-point types:: julia> (typemin(Float32),typemax(Float32)) - (-Inf,Inf) + (-Inf32,Inf32) julia> (typemin(Float64),typemax(Float64)) (-Inf,Inf) -Note that ``Float32`` values ``NaN``, ``Inf`` and ``-Inf`` are shown -identically to their ``Float64`` counterparts. +Note that ``Float32`` values have the suffix ``32: ``NaN32``, ``Inf32``, and ``-Inf32``. Floating-point types also support the ``eps`` function, which gives the distance between ``1.0`` and the next larger representable @@ -262,7 +267,7 @@ floating-point value:: julia> eps(Float64) 2.22044604925031308e-16 -These values are ``2^-23`` and ``2^-52`` as ``Float32`` and ``Float64`` +These values are ``2.0^-23`` and ``2.0^-52`` as ``Float32`` and ``Float64`` values, respectively. The ``eps`` function can also take a floating-point value as an argument, and gives the absolute difference between that value and the next representable floating point value. That @@ -280,7 +285,7 @@ than ``x``:: 1.79366203433576585e-43 julia> eps(0.0) - 4.94065645841246544e-324 + 5.0e-324 As you can see, the distance to the next larger representable floating-point value is smaller for smaller values and larger for larger @@ -290,13 +295,6 @@ exponentially as one moves farther away from zero. By definition, ``eps(1.0)`` is the same as ``eps(Float64)`` since ``1.0`` is a 64-bit floating-point value. -.. raw:: html - - Background and References ~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -322,6 +320,35 @@ the "Father of Floating-Point". Of particular interest may be `An Interview with the Old Man of Floating-Point `_. +.. _man_arbitrary_precision_arithmetic: + +Arbitrary Precision Arithmetic +------------------------------ + +To allow computations with arbitrary precision integers and floating point numbers, +Julia wraps the `GNU Multiple Precision Arithmetic Library, GMP `_. +The `BigInt` and `BigFloat` types are available in Julia for arbitrary precision +integer and floating point numbers respectively. + +Constructors exist to create these types from primitive numerical types, or from ``String``. +Once created, they participate in arithmetic with all other numeric types thanks to Julia's +type promotion and conversion mechanism. :: + + julia> BigInt(typemax(Int64)) + 1 + 9223372036854775808 + + julia> BigInt("123456789012345678901234567890") + 1 + 123456789012345678901234567891 + + julia> BigFloat("1.23456789012345678901") + 1.23456789012345678901 + + julia> BigFloat(2.0^66) / 3 + 24595658764946068821.3 + + julia> factorial(BigInt(40)) + 815915283247897734345611269596115894272000000000 + .. _man-numeric-literal-coefficients: Numeric Literal Coefficients diff --git a/doc/manual/introduction.rst b/doc/manual/introduction.rst index cc4285c298397..09cb683b2a15b 100644 --- a/doc/manual/introduction.rst +++ b/doc/manual/introduction.rst @@ -24,10 +24,10 @@ implemented using multi-paradigm, combining features of imperative, functional, and object-oriented programming. The syntax of Julia is similar to `MATLAB® `_ and consequently -MATLAB® programmers should feel immediately comfortable with Julia. -While MATLAB® is quite effective for prototyping and exploring numerical +MATLAB programmers should feel immediately comfortable with Julia. +While MATLAB is quite effective for prototyping and exploring numerical linear algebra, it has limitations for programming tasks outside of this -relatively narrow scope. Julia keeps MATLAB®'s ease and expressiveness +relatively narrow scope. Julia keeps MATLAB's ease and expressiveness for high-level numerical computing, but transcends its general programming limitations. To achieve this, Julia builds upon the lineage of mathematical programming languages, but also borrows much from @@ -92,6 +92,7 @@ advantages of Julia over comparable systems include: - Free and open source (`MIT licensed `_) - User-defined types are as fast and compact as built-ins +- No need to vectorize code for performance; devectorized code is fast - Designed for parallelism and distributed computation - Lightweight "green" threading (`coroutines `_) diff --git a/doc/manual/mathematical-operations.rst b/doc/manual/mathematical-operations.rst index b805d1151f351..b75e68f074572 100644 --- a/doc/manual/mathematical-operations.rst +++ b/doc/manual/mathematical-operations.rst @@ -145,7 +145,7 @@ Here are some simple examples:: julia> 3 < -0.5 false -Integers are compared in the standard manner — by comparison of bits. +Integers are compared in the standard manner — by comparison of bits. Floating-point numbers are compared according to the `IEEE 754 standard `_: @@ -191,8 +191,9 @@ comparisons can be arbitrarily chained:: true Chaining comparisons is often quite convenient in numerical code. -Chained numeric comparisons use the ``&`` operator, which allows them to -work on arrays. For example, ``0 < A < 1`` gives a boolean array whose +Chained comparisons use the ``&&`` operator for scalar comparisons, +and the ``&`` operator for elementwise comparisons, which allows them to +work on arrays. For example, ``0 .< A .< 1`` gives a boolean array whose entries are true where the corresponding elements of ``A`` are between 0 and 1. @@ -200,7 +201,7 @@ Note the evaluation behavior of chained comparisons:: v(x) = (println(x); x) - julia> v(1) > v(2) <= v(3) + julia> v(1) < v(2) <= v(3) 2 1 3 @@ -208,7 +209,7 @@ Note the evaluation behavior of chained comparisons:: The middle expression is only evaluated once, rather than twice as it would be if the expression were written as -``v(1) > v(2) & v(2) <= v(3)``. However, the order of evaluations in a +``v(1) > v(2) && v(2) <= v(3)``. However, the order of evaluations in a chained comparison is undefined. It is strongly recommended not to use expressions with side effects (such as printing) in chained comparisons. If side effects are required, the short-circuit ``&&`` operator should @@ -226,9 +227,11 @@ such definitions make sense. - ``round(x)`` — round ``x`` to the nearest integer. - ``iround(x)`` — round ``x`` to the nearest integer, giving an integer-typed result. -- ``floor(x)`` — round ``x`` towards ``-Inf``. +- ``floor(x)`` — round ``x`` towards ``-Inf``. +- ``ifloor(x)`` — round ``x`` towards ``-Inf``, giving an integer-typed result. - ``ceil(x)`` — round ``x`` towards ``+Inf``. -- ``trunc(x)`` — round ``x`` towards zero. +- ``iceil(x)`` — round ``x`` towards ``+Inf``, giving an integer-typed result. +- ``trunc(x)`` — round ``x`` towards zero. - ``itrunc(x)`` — round ``x`` towards zero, giving an integer-typed result. - ``div(x,y)`` — truncated division; quotient rounded towards zero. @@ -251,12 +254,11 @@ such definitions make sense. of ``x*y``. - ``sqrt(x)`` — the square root of ``x``. - ``cbrt(x)`` — the cube root of ``x``. -- ``hypot(x,y)`` — accurate ``sqrt(x^2 + y^2)`` for all values of ``x`` +- ``hypot(x,y)`` — accurate ``sqrt(x^2 + y^2)`` for all values of ``x`` and ``y``. -- ``pow(x,y)`` — ``x`` raised to the exponent ``y``. - ``exp(x)`` — the natural exponential function at ``x``. - ``expm1(x)`` — accurate ``exp(x)-1`` for ``x`` near zero. -- ``ldexp(x,n)`` — ``x*2^n`` computed efficiently for integer values of +- ``ldexp(x,n)`` — ``x*2^n`` computed efficiently for integer values of ``n``. - ``log(x)`` — the natural logarithm of ``x``. - ``log(b,x)`` — the base ``b`` logarithm of ``x``. @@ -267,9 +269,9 @@ such definitions make sense. - ``erf(x)`` — the `error function `_ at ``x``. - ``erfc(x)`` — accurate ``1-erf(x)`` for large ``x``. -- ``gamma(x)`` — the `gamma +- ``gamma(x)`` — the `gamma function `_ at ``x``. -- ``lgamma(x)`` — accurate ``log(gamma(x))`` for large ``x``. +- ``lgamma(x)`` — accurate ``log(gamma(x))`` for large ``x``. For an overview of why functions like ``hypot``, ``expm1``, ``log1p``, and ``erfc`` are necessary and useful, see John D. Cook's excellent pair @@ -289,21 +291,18 @@ These are all single-argument functions, with the exception of `atan2 `_, which gives the angle in `radians `_ between the *x*-axis and the point specified by its arguments, interpreted as *x* and *y* -coordinates. +coordinates. In order to compute trigonometric functions with degrees +instead of radians, suffix the function with ``d``. For example, ``sind(x)`` +computes the sine of ``x`` where ``x`` is specified in degrees. -For notational convenience, there are equivalent operator forms for the -``rem`` and ``pow`` functions: +For notational convenience, the ``rem`` functions has an operator form: - ``x % y`` is equivalent to ``rem(x,y)``. -- ``x ^ y`` is equivalent to ``pow(x,y)``. -In the former case, the spelled-out ``rem`` operator is the "canonical" -form, and the ``%`` operator form is retained for compatibility with -other systems, whereas in the latter case, the ``^`` operator form is -canonical and the spelled-out ``pow`` form is retained for -compatibility. Like arithmetic and bitwise operators, ``%`` and ``^`` -also have updating forms. As with other operators, ``x %= y`` means -``x = x % y`` and ``x ^= y`` means ``x = x^y``:: +The spelled-out ``rem`` operator is the "canonical" form, while the ``%`` operator +form is retained for compatibility with other systems. Like arithmetic and bitwise +operators, ``%`` and ``^`` also have updating forms. As with other updating forms, +``x %= y`` means ``x = x % y`` and ``x ^= y`` means ``x = x^y``:: julia> x = 2; x ^= 5; x 32 @@ -311,10 +310,3 @@ also have updating forms. As with other operators, ``x %= y`` means julia> x = 7; x %= 4; x 3 -.. raw:: html - - - diff --git a/doc/manual/metaprogramming.rst b/doc/manual/metaprogramming.rst index ac0953229fd70..941f9074dd934 100644 --- a/doc/manual/metaprogramming.rst +++ b/doc/manual/metaprogramming.rst @@ -62,7 +62,11 @@ is an example of the short form used to quote an arithmetic expression:: Symbol julia> ex.args - {+,a,*(b,c),1} + 4-element Any Array: + + + a + :(*(b,c)) + 1 julia> typeof(ex.args[1]) Symbol @@ -160,7 +164,7 @@ dynamically generate arbitrary code which can then be run using julia> a = 1; julia> ex = Expr(:call, {:+,a,:b}, Any) - +(1,b) + :(+(1,b)) julia> a = 0; b = 2; @@ -194,7 +198,7 @@ clearly and concisely using interpolation:: 1 julia> ex = :($a + b) - +(1,b) + :(+(1,b)) This syntax is automatically rewritten to the form above where we explicitly called ``Expr``. The use of ``$`` for expression @@ -264,12 +268,20 @@ in the final syntax tree. Macros are invoked with the following general syntax:: @name expr1 expr2 ... + @name(expr1, expr2, ...) Note the distinguishing ``@`` before the macro name and the lack of -commas between the argument expressions. Before the program runs, this -statement will be replaced with the result of calling an expander -function for ``name`` on the expression arguments. Expanders are defined -with the ``macro`` keyword:: +commas between the argument expressions in the first form, and the +lack of whitespace after ``@name`` in the second form. The two styles +should not be mixed. For example, the following syntax is different +from the examples above; it passes the tuple ``(expr1, expr2, ...)`` as +one argument to the macro:: + + @name (expr1, expr2, ...) + +Before the program runs, this statement will be replaced with the +result of calling an expander function for ``name`` on the expression +arguments. Expanders are defined with the ``macro`` keyword:: macro name(expr1, expr2, ...) ... @@ -280,7 +292,7 @@ macro (see `error.jl `_):: macro assert(ex) - :($ex ? nothing : error("Assertion failed: ", $string(ex))) + :($ex ? nothing : error("Assertion failed: ", $(string(ex)))) end This macro can be used like this:: @@ -291,9 +303,7 @@ This macro can be used like this:: Assertion failed: 1==0 Macro calls are expanded so that the above calls are precisely -equivalent to writing - -:: +equivalent to writing:: 1==1.0 ? nothing : error("Assertion failed: ", "1==1.0") 1==0 ? nothing : error("Assertion failed: ", "1==0") @@ -309,6 +319,11 @@ expression that was false. Notice that it would not be possible to write this as a function, since only the *value* of the condition and not the expression that computed it would be available. +The ``@assert`` example also shows how macros can include a ``quote`` +block, which allows for convenient manipulation of expressions inside +the macro body. + + Hygiene ~~~~~~~ @@ -481,20 +496,14 @@ is, well, invaluable. The mechanism for user-defined string literals is deeply, profoundly powerful. Not only are Julia's non-standard literals implemented using it, but also the command literal syntax (```echo "Hello, $person"```) -and regular string interpolation are implemented using it. These two -powerful facilities are implemented with the following innocuous-looking -pair of macros:: +is implemented with the following innocuous-looking macro:: macro cmd(str) :(cmd_gen($shell_parse(str))) end - macro str(s) - interp_parse(s) - end - Of course, a large amount of complexity is hidden in the functions used -in these macro definitions, but they are just functions, written +in this macro definition, but they are just functions, written entirely in Julia. You can read their source and see precisely what they do — and all they do is construct expression objects to be inserted into your program's syntax tree. diff --git a/doc/manual/methods.rst b/doc/manual/methods.rst index f5e1d2f349879..83d4a3eeb7d2c 100644 --- a/doc/manual/methods.rst +++ b/doc/manual/methods.rst @@ -58,8 +58,8 @@ for structuring and organizing programs. Footnote 1: In C++ or Java, for example, in a method call like obj.meth(arg1,arg2), the object obj "receives" the method call and is -implicitly passed to the method via the this keyword, rather then as an -explicit method argument. When the current this object is the receiver +implicitly passed to the method via the *this* keyword, rather then as an +explicit method argument. When the current *this* object is the receiver of a method call, it can be omitted altogether, writing just meth(arg1,arg2), with this implied as the receiving object. @@ -200,42 +200,52 @@ Julia language. Core operations typically have dozens of methods:: julia> + Methods for generic function + - +(Int8,Int8) - +(Int16,Int16) - +(Int32,Int32) - +(Int64,Int64) - +(Uint8,Uint8) - +(Uint16,Uint16) - +(Uint32,Uint32) - +(Uint64,Uint64) - +(Float32,Float32) - +(Float64,Float64) - +(Char,Char) - +(Int,Ptr{T}) - +(Rational{T<:Int},Rational{T<:Int}) - +(Real,Range{T<:Real}) - +(Real,Range1{T<:Real}) - +(Union(Range{T<:Real},Range1{T<:Real}),Real) - +(Union(Range{T<:Real},Range1{T<:Real}),Union(Range{T<:Real},Range1{T<:Real})) - +(Ptr{T},Int) - +() - +(Complex,Complex) - +(T<:Number,T<:Number) - +(Number,) - +(Number,Number) - +(AbstractArray{T<:Number,N},) - +(SparseMatrixCSC{T1},SparseMatrixCSC{T2}) - +(SparseMatrixCSC{T},Union(Array{T,N},Number)) - +(Number,DArray{T,N,distdim}) - +(Number,AbstractArray{T,N}) - +(Union(Array{T,N},Number),SparseMatrixCSC{T}) - +(AbstractArray{S,N},AbstractArray{T,N}) - +(DArray{T,N,distdim},Number) - +(AbstractArray{T,N},Number) - +(Any,Any,Any) - +(Any,Any,Any,Any) - +(Any,Any,Any,Any,Any) - +(Any,Any,Any,Any...) + +(Real,Range{T<:Real}) at range.jl:136 + +(Real,Range1{T<:Real}) at range.jl:137 + +(Ranges{T<:Real},Real) at range.jl:138 + +(Ranges{T<:Real},Ranges{T<:Real}) at range.jl:150 + +(Bool,) at bool.jl:45 + +(Bool,Bool) at bool.jl:48 + +(Int64,Int64) at int.jl:224 + +(Int128,Int128) at int.jl:226 + +(Union(Array{Bool,N},SubArray{Bool,N,A<:Array{T,N},I<:(Union(Int64,Range1{Int64},Range{Int64})...,)}),Union(Array{Bool,N},SubArray{Bool,N,A<:Array{T,N},I<:(Union(Int64,Range1{Int64},Range{Int64})...,)})) at array.jl:902 + +{T<:Signed}(T<:Signed,T<:Signed) at int.jl:207 + +(Uint64,Uint64) at int.jl:225 + +(Uint128,Uint128) at int.jl:227 + +{T<:Unsigned}(T<:Unsigned,T<:Unsigned) at int.jl:211 + +(Float32,Float32) at float.jl:113 + +(Float64,Float64) at float.jl:114 + +(Complex{T<:Real},Complex{T<:Real}) at complex.jl:207 + +(Rational{T<:Integer},Rational{T<:Integer}) at rational.jl:101 + +(Bool,Union(Array{Bool,N},SubArray{Bool,N,A<:Array{T,N},I<:(Union(Int64,Range1{Int64},Range{Int64})...,)})) at array.jl:896 + +(Union(Array{Bool,N},SubArray{Bool,N,A<:Array{T,N},I<:(Union(Int64,Range1{Int64},Range{Int64})...,)}),Bool) at array.jl:899 + +(Char,Char) at char.jl:46 + +(Char,Int64) at char.jl:47 + +(Int64,Char) at char.jl:48 + +{T<:Number}(T<:Number,T<:Number) at promotion.jl:68 + +(Number,Number) at promotion.jl:40 + +() at operators.jl:30 + +(Number,) at operators.jl:36 + +(Any,Any,Any) at operators.jl:44 + +(Any,Any,Any,Any) at operators.jl:45 + +(Any,Any,Any,Any,Any) at operators.jl:46 + +(Any,Any,Any,Any...) at operators.jl:48 + +{T}(Ptr{T},Integer) at pointer.jl:52 + +(Integer,Ptr{T}) at pointer.jl:54 + +{T<:Number}(AbstractArray{T<:Number,N},) at abstractarray.jl:232 + +{S,T}(Union(Array{S,N},SubArray{S,N,A<:Array{T,N},I<:(Union(Int64,Range1{Int64},Range{Int64})...,)}),Union(Array{T,N},SubArray{T,N,A<:Array{T,N},I<:(Union(Int64,Range1{Int64},Range{Int64})...,)})) at array.jl:850 + +{T}(Number,Union(Array{T,N},SubArray{T,N,A<:Array{T,N},I<:(Union(Int64,Range1{Int64},Range{Int64})...,)})) at array.jl:857 + +{T}(Union(Array{T,N},SubArray{T,N,A<:Array{T,N},I<:(Union(Int64,Range1{Int64},Range{Int64})...,)}),Number) at array.jl:864 + +{S,T<:Real}(Union(Array{S,N},SubArray{S,N,A<:Array{T,N},I<:(Union(Int64,Range1{Int64},Range{Int64})...,)}),Ranges{T<:Real}) at array.jl:872 + +{S<:Real,T}(Ranges{S<:Real},Union(Array{T,N},SubArray{T,N,A<:Array{T,N},I<:(Union(Int64,Range1{Int64},Range{Int64})...,)})) at array.jl:881 + +(BitArray{N},BitArray{N}) at bitarray.jl:922 + +(BitArray{N},Number) at bitarray.jl:923 + +(Number,BitArray{N}) at bitarray.jl:924 + +(BitArray{N},AbstractArray{T,N}) at bitarray.jl:986 + +(AbstractArray{T,N},BitArray{N}) at bitarray.jl:987 + +{Tv,Ti}(SparseMatrixCSC{Tv,Ti},SparseMatrixCSC{Tv,Ti}) at sparse.jl:536 + +(SparseMatrixCSC{Tv,Ti<:Integer},Union(Array{T,N},Number)) at sparse.jl:626 + +(Union(Array{T,N},Number),SparseMatrixCSC{Tv,Ti<:Integer}) at sparse.jl:627 Multiple dispatch together with the flexible parametric type system give Julia its ability to abstractly express high-level algorithms decoupled @@ -261,7 +271,7 @@ arguments:: julia> g(2, 3.0) 8.0 - julia> f(2.0, 3.0) + julia> g(2.0, 3.0) 7.0 Here the call ``g(2.0, 3.0)`` could be handled by either the @@ -283,7 +293,7 @@ the intersection case:: julia> g(2, 3.0) 8.0 - julia> f(2.0, 3.0) + julia> g(2.0, 3.0) 10.0 To suppress Julia's warning, the disambiguating method must be defined @@ -336,7 +346,11 @@ signature:: julia> myappend{T}(v::Vector{T}, x::T) = [v..., x] julia> myappend([1,2,3],4) - [1,2,3,4] + 4-element Int64 Array: + 1 + 2 + 3 + 4 julia> myappend([1,2,3],2.5) no method myappend(Array{Int64,1},Float64) @@ -388,4 +402,24 @@ can also constrain type parameters of methods:: The ``same_type_numeric`` function behaves much like the ``same_type`` function defined above, but is only defined for pairs of numbers. +Note on Optional and Named Arguments +------------------------------------ + +As mentioned briefly in :ref:`man-functions`, optional arguments are +implemented as syntax for multiple method definitions. For example, +this definition:: + + f(a=1,b=2) = a+2b + +translates to the following three methods:: + + f(a,b) = a+2b + f(a) = f(a,2) + f() = f(1,2) + +Named arguments behave quite differently from ordinary positional arguments. +In particular, they do not participate in method dispatch. Methods are +dispatched based only on positional arguments, with named arguments processed +after the matching method is identified. + .. [#] Arthur C. Clarke, *Profiles of the Future* (1961): Clarke's Third Law. diff --git a/doc/manual/modules.rst b/doc/manual/modules.rst index 3e7025f60aa4d..c281098d4e21b 100644 --- a/doc/manual/modules.rst +++ b/doc/manual/modules.rst @@ -4,6 +4,8 @@ Modules ********* +.. index:: module, baremodule, using, import, export, importall + Modules in Julia are separate global variable workspaces. They are delimited syntactically, inside ``module Name ... end``. Modules allow you to create top-level definitions without worrying about name conflicts @@ -11,7 +13,8 @@ when your code is used together with somebody else's. Within a module, you can control which names from other modules are visible (via importing), and specify which of your names are intended to be public (via exporting). -The following example illustrates the major features of modules:: +The following example demonstrates the major features of modules. It is +not meant to be run, but is shown for illustrative purposes:: module MyModule using Lib @@ -29,20 +32,18 @@ The following example illustrates the major features of modules:: show(io, a::MyType) = print(io, "MyType $(a.x)") end -Note that the style is not -to indent the body of the module, since that would typically lead to -whole files being indented. +Note that the style is not to indent the body of the module, since +that would typically lead to whole files being indented. -This module defines a type ``MyType``, and two functions. Function ``foo`` -and type ``MyType`` are -exported, and so will be available for importing into other modules. -Function ``bar`` is private to ``MyModule``. +This module defines a type ``MyType``, and two functions. Function +``foo`` and type ``MyType`` are exported, and so will be available for +importing into other modules. Function ``bar`` is private to +``MyModule``. -The statement ``using Lib`` means that a module called ``Lib`` -will be available for resolving names -as needed. When a global variable is encountered that has no definition in -the current module, the system will search for it in ``Lib`` and import it -if it is found there. +The statement ``using Lib`` means that a module called ``Lib`` will be +available for resolving names as needed. When a global variable is +encountered that has no definition in the current module, the system +will search for it in ``Lib`` and import it if it is found there. This means that all uses of that global within the current module will resolve to the definition of that variable in ``Lib``. @@ -93,9 +94,8 @@ Standard modules There are three important standard modules: Main, Core, and Base. Main is the top-level module, and Julia starts with Main set as the -current module. -Variables defined at the prompt go in Main, and ``whos()`` lists variables -in Main. +current module. Variables defined at the prompt go in Main, and +``whos()`` lists variables in Main. Core contains all identifiers considered "built in" to the language, i.e. part of the core language and not libraries. Every module implicitly @@ -115,7 +115,7 @@ that module. If these definitions are not wanted, modules can be defined using the keyword ``baremodule`` instead. In terms of ``baremodule``, a standard -``module`` looks like this: +``module`` looks like this:: baremodule Mod using Base @@ -132,9 +132,8 @@ If a name is qualified (e.g. ``Base.sin``), then it can be accessed even if it is not exported. This is often useful when debugging. Macros must be exported if they are intended to be used outside their -defining module. -Macro names are written with ``@`` in import and export statements, e.g. -``import Mod.@mac``. +defining module. Macro names are written with ``@`` in import and +export statements, e.g. ``import Mod.@mac``. The syntax ``M.x = y`` does not work to assign a global in another module; global assignment is always module-local. diff --git a/doc/manual/packages.rst b/doc/manual/packages.rst new file mode 100644 index 0000000000000..be3275f88ebf9 --- /dev/null +++ b/doc/manual/packages.rst @@ -0,0 +1,136 @@ +============== +Julia Packages +============== + +Where to find Julia packages +---------------------------- + +- An official list of packages is available, see :ref:`available-packages`. + +- Announcements of new packages can also be found in the `julia-users Google Groups `_. + +Installing a new Julia package +------------------------------ + +The `Pkg` module in julia provides tools for installing and managing third party packages. It also manages the dependencies, while installing packages. Get the updated list of packages with:: + + Pkg.update() + +In order to install a package, use ``Pkg.add()``, where ``MY_PACKAGE_NAME`` is replaced with the actual package name:: + + Pkg.add("MY_PACKAGE_NAME") + +This installs the package to ``$HOME/.julia/MY_PACKAGE_NAME`` . In order to remove a package, do:: + + Pkg.rm("MY_PACKAGE_NAME") + +Internally, every Julia package is a ``git`` repository, and Julia uses ``git`` for its package management. + +Contributing a new Julia package +-------------------------------- + +In the following, replace ``MY_PACKAGE_NAME``, ``MY_GITHUB_USER``, etc. with +the actual desired names. + +Creating a new Julia package +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +1. Initialize your package in Julia by running:: + + Pkg.new("MY_PACKAGE_NAME") + +This will initialize a skeleton for a new package in ``$HOME/.julia/MY_PACKAGE_NAME``. + +.. note:: + This will overwrite any existing files and git repository in ``$HOME/.julia/MY_PACKAGE_NAME``. + +2. If you have already created a repository for your package, overwrite the +skeleton by copying or symlinking over it. For example,:: + + rm -r $HOME/.julia/MY_PACKAGE_NAME + ln -s /path/to/existing/repo/MY_PACKAGE_NAME $HOME/.julia/MY_PACKAGE_NAME + +3. In ``REQUIRE``, list the names of all packages used by your new package. One +package per line. + +4. Populate the package by filling out ``README.md`` and ``LICENSE.md``, source +code in ``src/``, and tests in ``test/``. Ensure that each test file contains these +lines near the beginning:: + + using Test + using MY_PACKAGE_NAME + +5. Add a publicly accessible remote repository URL, if your package doesn't +already have one. For example, create a new repository called +``MY_PACKAGE_NAME.jl`` on Github and then run:: + + cd $HOME/.julia/MY_PACKAGE_NAME + git remote add github https://github.com/MY_GITHUB_USER/MY_PACKAGE_NAME.jl + +6. Add at least one git commit and push it to the remote repository:: + + # Do some stuff + git add -A . #for all changes, or give an explicit file list to avoid checking in binaries and temporary + git commit + git push -u github master + +7. If the previous commands are new to you, this is probably a good time to +go read an explanation of how git works. + +Distributing a Julia package +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +One-time setup (once per user) +------------------------------ +1. Fork a copy of METADATA.jl, if you haven't done so already. The forked +repository URL should look like `https://github.com/MY_GITHUB_USER/METADATA.jl`. + +2. Update the local METADATA with the URL of your forked repository.:: + + cd $HOME/.julia/METADATA + git remote add github https://github.com/MY_GITHUB_USER/METADATA.jl + +Distributing a new package or new version of an existing package +---------------------------------------------------------------- + +0. Ensure that both your forked METADATA.jl on Github and your local METADATA + repository are current. The latter should be checked out to the `devel` + branch.:: + + cd $HOME/.julia/METADATA + git fetch --all + git checkout devel + git rebase origin/devel + git push github devel + +1. Populate the local METADATA by running in Julia: :: + + Pkg.pkg_origin("MY_PACKAGE_NAME") + Pkg.patch("MY_PACKAGE_NAME") + +2. Update the local METADATA with the URL of your forked repository and +create a new branch with your package in it.:: + + cd $HOME/.julia/METADATA + git branch MY_PACKAGE_NAME + git checkout MY_PACKAGE_NAME + git add MY_PACKAGE_NAME #Ensure that only the latest hash is committed + git commit + +3. Push to the remote METADATA repository:: + + git push github MY_PACKAGE_NAME + +4. Go to `https://github.com/MY_GITHUB_USER/METADATA.jl/tree/MY_PACKAGE_NAME` +in your web browser. Click the 'Pull Request' button. + +.. image:: ../images/github_metadata_pullrequest.png + +5. Submit a new pull request. Ensure that the pull request goes to the +devel branch and not master. + +.. image:: ../images/github_metadata_develbranch.png + +6. When the pull request is accepted, announce your new package to the +Julia community on the `julia-users Google Groups `_. + diff --git a/doc/manual/parallel-computing.rst b/doc/manual/parallel-computing.rst index ab7bad344ecfd..d97cd824e3270 100644 --- a/doc/manual/parallel-computing.rst +++ b/doc/manual/parallel-computing.rst @@ -48,29 +48,33 @@ equal the number of CPU cores on the machine. $ ./julia -p 2 julia> r = remote_call(2, rand, 2, 2) - RemoteRef(2,1,0) - - julia> s = remote_call(2, +, 1, r) - RemoteRef(2,1,1) + RemoteRef(2,1,5) julia> fetch(r) - 0.10824216411304866 0.13798233877923116 - 0.12376292706355074 0.18750497916607167 + 2x2 Float64 Array: + 0.60401 0.501111 + 0.174572 0.157411 - julia> fetch(s) - 1.10824216411304866 1.13798233877923116 - 1.12376292706355074 1.18750497916607167 + julia> s = @spawnat 2 1+fetch(r) + RemoteRef(2,1,7) -The first argument to ``remote_call`` is the index of the processor that -will do the work. Most parallel programming in Julia does not reference -specific processors or the number of processors available, but -``remote_call`` is considered a low-level interface providing finer -control. The second argument to ``remote_call`` is the function to call, -and the remaining arguments will be passed to this function. As you can -see, in the first line we asked processor 2 to construct a 2-by-2 random -matrix, and in the second line we asked it to add 1 to it. The result of -both calculations is available in the two remote references, ``r`` and -``s``. + julia> fetch(s) + 2x2 Float64 Array: + 1.60401 1.50111 + 1.17457 1.15741 + +The first argument to ``remote_call`` is the index of the processor +that will do the work. Most parallel programming in Julia does not +reference specific processors or the number of processors available, +but ``remote_call`` is considered a low-level interface providing +finer control. The second argument to ``remote_call`` is the function +to call, and the remaining arguments will be passed to this +function. As you can see, in the first line we asked processor 2 to +construct a 2-by-2 random matrix, and in the second line we asked it +to add 1 to it. The result of both calculations is available in the +two remote references, ``r`` and ``s``. The ``@spawnat`` macro +evaluates the expression in the second argument on the processor +specified by the first argument. Occasionally you might want a remotely-computed value immediately. This typically happens when you read from a remote object to obtain data @@ -80,10 +84,10 @@ but is more efficient. :: - julia> remote_call_fetch(2, ref, r, 1, 1) + julia> remote_call_fetch(2, getindex, r, 1, 1) 0.10824216411304866 -Remember that ``ref(r,1,1)`` is :ref:`equivalent ` to +Remember that ``getindex(r,1,1)`` is :ref:`equivalent ` to ``r[1,1]``, so this call fetches the first element of the remote reference ``r``. @@ -132,10 +136,10 @@ that runs it. For example, type the following into the julia prompt:: julia> exception on 2: in anonymous: rand2 not defined Processor 1 knew about the function ``rand2``, but processor 2 did not. -To make your code available to all processors, the ``load`` function will +To make your code available to all processors, the ``require`` function will automatically load a source file on all currently available processors:: - julia> load("myfile") + julia> require("myfile") In a cluster, the contents of the file (and any files loaded recursively) will be sent over the network. @@ -198,7 +202,7 @@ following function in ``count_heads.jl``:: function count_heads(n) c::Int = 0 for i=1:n - c += randbit() + c += randbool() end c end @@ -207,7 +211,7 @@ The function ``count_heads`` simply adds together ``n`` random bits. Here is how we can perform some trials on two machines, and add together the results:: - load("count_heads") + require("count_heads") a = @spawn count_heads(100000000) b = @spawn count_heads(100000000) @@ -232,7 +236,7 @@ we can use a *parallel for loop*, which can be written in Julia like this:: nheads = @parallel (+) for i=1:200000000 - randbit() + randbool() end This construct implements the pattern of assigning iterations to @@ -287,218 +291,219 @@ a large amount of work. In contrast, ``@parallel for`` can handle situations where each iteration is tiny, perhaps merely summing two numbers. -Distributed Arrays ------------------- - -Large computations are often organized around large arrays of data. In -these cases, a particularly natural way to obtain parallelism is to -distribute arrays among several processors. This combines the memory -resources of multiple machines, allowing use of arrays too large to fit -on one machine. Each processor operates on the part of the array it -owns, providing a ready answer to the question of how a program should -be divided among machines. - -A distributed array (or, more generally, a *global object*) is logically -a single array, but pieces of it are stored on different processors. -This means whole-array operations such as matrix multiply, scalar\*array -multiplication, etc. use the same syntax as with local arrays, and the -parallelism is invisible. In some cases it is possible to obtain useful -parallelism just by changing a local array to a distributed array. - -Julia distributed arrays are implemented by the ``DArray`` type. A -``DArray`` has an element type and dimensions just like an ``Array``, -but it also needs an additional property: the dimension along which data -is distributed. There are many possible ways to distribute data among -processors, but at this time Julia keeps things simple and only allows -distributing along a single dimension. For example, if a 2-d ``DArray`` -is distributed in dimension 1, it means each processor holds a certain -range of rows. If it is distributed in dimension 2, each processor holds -a certain range of columns. - -Common kinds of arrays can be constructed with functions beginning with -``d``:: - - dzeros(100,100,10) - dones(100,100,10) - drand(100,100,10) - drandn(100,100,10) - dcell(100,100,10) - dfill(x, 100,100,10) - -In the last case, each element will be initialized to the specified -value ``x``. These functions automatically pick a distributed dimension -for you. To specify the distributed dimension, other forms are -available:: - - drand((100,100,10), 3) - dzeros(Int64, (100,100), 2) - dzeros((100,100), 2, [7, 8]) - -In the ``drand`` call, we specified that the array should be distributed -across dimension 3. In the first ``dzeros`` call, we specified an -element type as well as the distributed dimension. In the second -``dzeros`` call, we also specified which processors should be used to -store the data. When dividing data among a large number of processors, -one often sees diminishing returns in performance. Placing ``DArray``\ s -on a subset of processors allows multiple ``DArray`` computations to -happen at once, with a higher ratio of work to communication on each -processor. - -``distribute(a::Array, dim)`` can be used to convert a local array to a -distributed array, optionally specifying the distributed dimension. -``localize(a::DArray)`` can be used to obtain the locally-stored portion -of a ``DArray``. ``owner(a::DArray, index)`` gives the id of the -processor storing the given index in the distributed dimension. -``myindexes(a::DArray)`` gives a tuple of the indexes owned by the local -processor. ``convert(Array, a::DArray)`` brings all the data to one -node. - -A ``DArray`` can be stored on a subset of the available processors. -Three properties fully describe the distribution of ``DArray`` ``d``. -``d.pmap[i]`` gives the processor id that owns piece number ``i`` of the -array. Piece ``i`` consists of indexes ``d.dist[i]`` through -``d.dist[i+1]-1``. ``distdim(d)`` gives the distributed dimension. For -convenience, ``d.localpiece`` gives the number of the piece owned by the -local processor (this could also be determined by searching ``d.pmap``). -The array ``d.pmap`` is also available as ``procs(d)``. - -Indexing a ``DArray`` (square brackets) gathers all of the referenced -data to a local ``Array`` object. - -Indexing a ``DArray`` with the ``sub`` function creates a "virtual" -sub-array that leaves all of the data in place. This should be used -where possible, especially for indexing operations that refer to large -pieces of the original array. - -``sub`` itself, naturally, does no communication and so is very -efficient. However, this does not mean it should be viewed as an -optimization in all cases. Many situations require explicitly moving -data to the local processor in order to do a fast serial operation. For -example, functions like matrix multiply perform many accesses to their -input data, so it is better to have all the data available locally up -front. - -Constructing Distributed Arrays -------------------------------- - -The primitive ``DArray`` constructor is the function ``darray``, which -has the following somewhat elaborate signature:: - - darray(init, type, dims, distdim, procs, dist) - -``init`` is a function of three arguments that will run on each -processor, and should return an ``Array`` holding the local data for the -current processor. Its arguments are ``(T,d,da)`` where ``T`` is the -element type, ``d`` is the dimensions of the needed local piece, and -``da`` is the new ``DArray`` being constructed (though, of course, it is -not fully initialized). - -``type`` is the element type. - -``dims`` is the dimensions of the entire ``DArray``. - -``distdim`` is the dimension to distribute in. - -``procs`` is a vector of processor ids to use. - -``dist`` is a vector giving the first index of each contiguous -distributed piece, such that the nth piece consists of indexes -``dist[n]`` through ``dist[n+1]-1``. If you have a vector ``v`` of the -sizes of the pieces, ``dist`` can be computed as ``cumsum([1,v])``. - -The last three arguments are optional, and defaults will be used if they -are omitted. The first argument, the ``init`` function, can also be -omitted, in which case an uninitialized ``DArray`` is constructed. - -As an example, here is how to turn the local array constructor ``rand`` -into a distributed array constructor:: - - drand(args...) = darray((T,d,da)->rand(d), Float64, args...) - -In this case the ``init`` function only needs to call ``rand`` with the -dimensions of the local piece it is creating. ``drand`` accepts the same -trailing arguments as ``darray``. ``darray`` also has definitions that -allow functions like ``drand`` to accept the same arguments as their -local counterparts, so calls like ``drand(m,n)`` will also work. - -The ``changedist`` function, which changes the distribution of a -``DArray``, can be implemented with one call to ``darray`` where the -``init`` function uses indexing to gather data from the existing array:: - - function changedist(A::DArray, to_dist) - return darray((T,sz,da)->A[myindexes(da)...], - eltype(A), size(A), to_dist, procs(A)) - end - -It is particularly easy to construct a ``DArray`` where each block is a -function of a block in an existing ``DArray``. This is done with the -form ``darray(f, A)``. For example, the unary minus function can be -implemented as:: - - -(A::DArray) = darray(-, A) - -Distributed Array Computations ------------------------------- - -Whole-array operations (e.g. elementwise operators) are a convenient way -to use distributed arrays, but they are not always sufficient. To handle -more complex problems, tasks can be spawned to operate on parts of a -``DArray`` and write the results to another ``DArray``. For example, -here is how you could apply a function ``f`` to each 2-d slice of a 3-d -``DArray``:: - - function compute_something(A::DArray) - B = darray(eltype(A), size(A), 3) - for i = 1:size(A,3) - @spawnat owner(B,i) B[:,:,i] = f(A[:,:,i]) - end - B - end - -We used ``@spawnat`` to place each operation near the memory it writes -to. - -This code works in some sense, but trouble stems from the fact that it -performs writes asynchronously. In other words, we don't know when the -result data will be written to the array and become ready for further -processing. This is known as a "race condition", one of the famous -pitfalls of parallel programming. Some form of synchronization is -necessary to wait for the result. As we saw above, ``@spawn`` returns a -remote reference that can be used to wait for its computation. We could -use that feature to wait for specific blocks of work to complete:: - - function compute_something(A::DArray) - B = darray(eltype(A), size(A), 3) - deps = cell(size(A,3)) - for i = 1:size(A,3) - deps[i] = @spawnat owner(B,i) B[:,:,i] = f(A[:,:,i]) - end - (B, deps) - end - -Now a function that needs to access slice ``i`` can perform -``wait(deps[i])`` first to make sure the data is available. - -Another option is to use a ``@sync`` block, as follows:: - - function compute_something(A::DArray) - B = darray(eltype(A), size(A), 3) - @sync begin - for i = 1:size(A,3) - @spawnat owner(B,i) B[:,:,i] = f(A[:,:,i]) - end - end - B - end - -``@sync`` waits for all spawns performed within it to complete. This -makes our ``compute_something`` function easy to use, at the price of -giving up some parallelism (since calls to it cannot overlap with -subsequent operations). - -Still another option is to use the initial, un-synchronized version of -the code, and place a ``@sync`` block around a larger set of operations -in the function calling this one. +.. + Distributed Arrays + ------------------ + + Large computations are often organized around large arrays of data. In + these cases, a particularly natural way to obtain parallelism is to + distribute arrays among several processors. This combines the memory + resources of multiple machines, allowing use of arrays too large to fit + on one machine. Each processor operates on the part of the array it + owns, providing a ready answer to the question of how a program should + be divided among machines. + + A distributed array (or, more generally, a *global object*) is logically + a single array, but pieces of it are stored on different processors. + This means whole-array operations such as matrix multiply, scalar\*array + multiplication, etc. use the same syntax as with local arrays, and the + parallelism is invisible. In some cases it is possible to obtain useful + parallelism just by changing a local array to a distributed array. + + Julia distributed arrays are implemented by the ``DArray`` type. A + ``DArray`` has an element type and dimensions just like an ``Array``, + but it also needs an additional property: the dimension along which data + is distributed. There are many possible ways to distribute data among + processors, but at this time Julia keeps things simple and only allows + distributing along a single dimension. For example, if a 2-d ``DArray`` + is distributed in dimension 1, it means each processor holds a certain + range of rows. If it is distributed in dimension 2, each processor holds + a certain range of columns. + + Common kinds of arrays can be constructed with functions beginning with + ``d``:: + + dzeros(100,100,10) + dones(100,100,10) + drand(100,100,10) + drandn(100,100,10) + dcell(100,100,10) + dfill(x, 100,100,10) + + In the last case, each element will be initialized to the specified + value ``x``. These functions automatically pick a distributed dimension + for you. To specify the distributed dimension, other forms are + available:: + + drand((100,100,10), 3) + dzeros(Int64, (100,100), 2) + dzeros((100,100), 2, [7, 8]) + + In the ``drand`` call, we specified that the array should be distributed + across dimension 3. In the first ``dzeros`` call, we specified an + element type as well as the distributed dimension. In the second + ``dzeros`` call, we also specified which processors should be used to + store the data. When dividing data among a large number of processors, + one often sees diminishing returns in performance. Placing ``DArray``\ s + on a subset of processors allows multiple ``DArray`` computations to + happen at once, with a higher ratio of work to communication on each + processor. + + ``distribute(a::Array, dim)`` can be used to convert a local array to a + distributed array, optionally specifying the distributed dimension. + ``localize(a::DArray)`` can be used to obtain the locally-stored portion + of a ``DArray``. ``owner(a::DArray, index)`` gives the id of the + processor storing the given index in the distributed dimension. + ``myindexes(a::DArray)`` gives a tuple of the indexes owned by the local + processor. ``convert(Array, a::DArray)`` brings all the data to one + node. + + A ``DArray`` can be stored on a subset of the available processors. + Three properties fully describe the distribution of ``DArray`` ``d``. + ``d.pmap[i]`` gives the processor id that owns piece number ``i`` of the + array. Piece ``i`` consists of indexes ``d.dist[i]`` through + ``d.dist[i+1]-1``. ``distdim(d)`` gives the distributed dimension. For + convenience, ``d.localpiece`` gives the number of the piece owned by the + local processor (this could also be determined by searching ``d.pmap``). + The array ``d.pmap`` is also available as ``procs(d)``. + + Indexing a ``DArray`` (square brackets) gathers all of the referenced + data to a local ``Array`` object. + + Indexing a ``DArray`` with the ``sub`` function creates a "virtual" + sub-array that leaves all of the data in place. This should be used + where possible, especially for indexing operations that refer to large + pieces of the original array. + + ``sub`` itself, naturally, does no communication and so is very + efficient. However, this does not mean it should be viewed as an + optimization in all cases. Many situations require explicitly moving + data to the local processor in order to do a fast serial operation. For + example, functions like matrix multiply perform many accesses to their + input data, so it is better to have all the data available locally up + front. + + Constructing Distributed Arrays + ------------------------------- + + The primitive ``DArray`` constructor is the function ``darray``, which + has the following somewhat elaborate signature:: + + darray(init, type, dims, distdim, procs, dist) + + ``init`` is a function of three arguments that will run on each + processor, and should return an ``Array`` holding the local data for the + current processor. Its arguments are ``(T,d,da)`` where ``T`` is the + element type, ``d`` is the dimensions of the needed local piece, and + ``da`` is the new ``DArray`` being constructed (though, of course, it is + not fully initialized). + + ``type`` is the element type. + + ``dims`` is the dimensions of the entire ``DArray``. + + ``distdim`` is the dimension to distribute in. + + ``procs`` is a vector of processor ids to use. + + ``dist`` is a vector giving the first index of each contiguous + distributed piece, such that the nth piece consists of indexes + ``dist[n]`` through ``dist[n+1]-1``. If you have a vector ``v`` of the + sizes of the pieces, ``dist`` can be computed as ``cumsum([1,v])``. + + The last three arguments are optional, and defaults will be used if they + are omitted. The first argument, the ``init`` function, can also be + omitted, in which case an uninitialized ``DArray`` is constructed. + + As an example, here is how to turn the local array constructor ``rand`` + into a distributed array constructor:: + + drand(args...) = darray((T,d,da)->rand(d), Float64, args...) + + In this case the ``init`` function only needs to call ``rand`` with the + dimensions of the local piece it is creating. ``drand`` accepts the same + trailing arguments as ``darray``. ``darray`` also has definitions that + allow functions like ``drand`` to accept the same arguments as their + local counterparts, so calls like ``drand(m,n)`` will also work. + + The ``changedist`` function, which changes the distribution of a + ``DArray``, can be implemented with one call to ``darray`` where the + ``init`` function uses indexing to gather data from the existing array:: + + function changedist(A::DArray, to_dist) + return darray((T,sz,da)->A[myindexes(da)...], + eltype(A), size(A), to_dist, procs(A)) + end + + It is particularly easy to construct a ``DArray`` where each block is a + function of a block in an existing ``DArray``. This is done with the + form ``darray(f, A)``. For example, the unary minus function can be + implemented as:: + + -(A::DArray) = darray(-, A) + + Distributed Array Computations + ------------------------------ + + Whole-array operations (e.g. elementwise operators) are a convenient way + to use distributed arrays, but they are not always sufficient. To handle + more complex problems, tasks can be spawned to operate on parts of a + ``DArray`` and write the results to another ``DArray``. For example, + here is how you could apply a function ``f`` to each 2-d slice of a 3-d + ``DArray``:: + + function compute_something(A::DArray) + B = darray(eltype(A), size(A), 3) + for i = 1:size(A,3) + @spawnat owner(B,i) B[:,:,i] = f(A[:,:,i]) + end + B + end + + We used ``@spawnat`` to place each operation near the memory it writes + to. + + This code works in some sense, but trouble stems from the fact that it + performs writes asynchronously. In other words, we don't know when the + result data will be written to the array and become ready for further + processing. This is known as a "race condition", one of the famous + pitfalls of parallel programming. Some form of synchronization is + necessary to wait for the result. As we saw above, ``@spawn`` returns a + remote reference that can be used to wait for its computation. We could + use that feature to wait for specific blocks of work to complete:: + + function compute_something(A::DArray) + B = darray(eltype(A), size(A), 3) + deps = cell(size(A,3)) + for i = 1:size(A,3) + deps[i] = @spawnat owner(B,i) B[:,:,i] = f(A[:,:,i]) + end + (B, deps) + end + + Now a function that needs to access slice ``i`` can perform + ``wait(deps[i])`` first to make sure the data is available. + + Another option is to use a ``@sync`` block, as follows:: + + function compute_something(A::DArray) + B = darray(eltype(A), size(A), 3) + @sync begin + for i = 1:size(A,3) + @spawnat owner(B,i) B[:,:,i] = f(A[:,:,i]) + end + end + B + end + + ``@sync`` waits for all spawns performed within it to complete. This + makes our ``compute_something`` function easy to use, at the price of + giving up some parallelism (since calls to it cannot overlap with + subsequent operations). + + Still another option is to use the initial, un-synchronized version of + the code, and place a ``@sync`` block around a larger set of operations + in the function calling this one. Synchronization With Remote References -------------------------------------- @@ -569,36 +574,11 @@ are scheduled cooperatively and not preemptively. This means context switches only occur at well-defined points (during the ``fetch`` operation). -Adding Processors ------------------ - -.. raw:: html - - +It is often useful to execute a statement on all processors, particularly +for setup tasks such as loading source files and defining common variables. +This can be done with the ``@everywhere`` macro: + @everywhere include("defs.jl") diff --git a/doc/manual/performance-tips.rst b/doc/manual/performance-tips.rst index c9979f4acba32..b87af3170a264 100644 --- a/doc/manual/performance-tips.rst +++ b/doc/manual/performance-tips.rst @@ -69,6 +69,26 @@ Here, we happened to know that the first element of ``a`` would be an will raise a run-time error if the value is not of the expected type, potentially catching certain bugs earlier. +Declare types of named arguments +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Named arguments can have declared types:: + + function with_named(x; name::Int = 1) + ... + end + +Functions are specialized on the types of named arguments, so these +declarations will not affect performance of code inside the function. +However, they will reduce the overhead of calls to the function that +include named arguments. + +Functions with named arguments have near-zero overhead for call sites +that pass only positional arguments. + +Passing dynamic lists of named arguments, as in ``f(x; names...)``, +can be slow and should be avoided in performance-sensitive code. + Break functions into multiple definitions ----------------------------------------- @@ -156,7 +176,7 @@ randomly-chosen type:: This should be written as:: function fill_twos!(a) - for i=1:numel(a) + for i=1:length(a) a[i] = 2 end end @@ -177,7 +197,7 @@ The second form is also often better style and can lead to more code reuse. This pattern is used in several places in the standard library. For -example, see ``_jl_hvcat_fill`` in +example, see ``hvcat_fill`` in `abstractarray.jl `_, or the ``fill!`` function, which we could have used instead of writing our own ``fill_twos!``. diff --git a/doc/manual/potential-features.rst b/doc/manual/potential-features.rst deleted file mode 100644 index e136a0f57b24b..0000000000000 --- a/doc/manual/potential-features.rst +++ /dev/null @@ -1,30 +0,0 @@ -.. _man-potential-features: - -******************** - Potential Features -******************** - -Julia is still a very young programming language, and there are many -features that have been discussed and planned to various extents, but -not yet implemented. This page documents some of these potential future -features, but is likely to be out of date. See the `mailing -list `_ and `GitHub -issues `_ for the latest -discussion on potential features. - -- `Local goto `_ -- `Abstract multiple - inheritance `_ -- `Enhanced C struct and array - compatibility `_ -- `Const fields in composite - types `_ -- `Multiline quotes using - """ ... """ `_ -- `Multiline comments using - ### ... ### `_ -- `Symbolic - optimization `_ -- `Collaborative cloud-computing - architecture `_ - diff --git a/doc/manual/running-external-programs.rst b/doc/manual/running-external-programs.rst index 2d4c9c8b5b7c6..25aa1dbde5f8c 100644 --- a/doc/manual/running-external-programs.rst +++ b/doc/manual/running-external-programs.rst @@ -35,10 +35,18 @@ Here's a simple example of actually running an external program:: hello true -The ``hello`` is the output of the ``echo`` command, while the ``true`` -is the return value of the command, indicating that it succeeded. (These -are colored differently by the interactive session if your terminal -supports color.) +The ``hello`` is the output of the ``echo`` command, sent to stdout. +The run method itself returns ``Nothing``, and throws an ``ErrorException`` +if the external command fails to run successfully. + +If you want to read the output of the external command, the ``readall`` method +can be used instead:: + + julia> a=readall(`echo hello`) + "hello\n" + + julia> (chomp(a)) == "hello" + true .. _man-command-interpolation: @@ -92,7 +100,10 @@ escaped. But what if you *want* to interpolate multiple words? In that case, just use an array (or any other iterable container):: julia> files = ["/etc/passwd","/Volumes/External HD/data.csv"] - ["/etc/passwd","/Volumes/External HD/data.csv"] + 2-element ASCIIString Array: + "/etc/passwd" + "/Volumes/External HD/data.csv" + julia> `grep foo $files` `grep foo /etc/passwd '/Volumes/External HD/data.csv'` @@ -101,7 +112,10 @@ If you interpolate an array as part of a shell word, Julia emulates the shell's ``{a,b,c}`` argument generation:: julia> names = ["foo","bar","baz"] - ["foo","bar","baz"] + 3-element ASCIIString Array: + "foo" + "bar" + "baz" julia> `grep xylophone $names.txt` `grep xylophone foo.txt bar.txt baz.txt` @@ -110,10 +124,15 @@ Moreover, if you interpolate multiple arrays into the same word, the shell's Cartesian product generation behavior is emulated:: julia> names = ["foo","bar","baz"] - ["foo","bar","baz"] + 3-element ASCIIString Array: + "foo" + "bar" + "baz" julia> exts = ["aux","log"] - ["aux","log"] + 2-element ASCIIString Array: + "aux" + "log" julia> `rm -f $names.$exts` `rm -f foo.aux foo.log bar.aux bar.log baz.aux baz.log` diff --git a/doc/manual/sparse-matrices.rst b/doc/manual/sparse-matrices.rst deleted file mode 100644 index 92d02d08756a4..0000000000000 --- a/doc/manual/sparse-matrices.rst +++ /dev/null @@ -1,121 +0,0 @@ -.. _man-sparse-matrices: - -****************** - Sparse Matrices -****************** - -`Sparse matrices `_ are -matrices that are primarily populated with zeros. Sparse matrices may -be used when operations on the sparse representation of a matrix lead -to considerable gains in either time or space when compared to -performing the same operations on a dense matrix. - -Compressed Sparse Column (CSC) Storage --------------------------------------- - -In julia, sparse matrices are stored in the `Compressed Sparse Column -(CSC) format -`_. Julia -sparse matrices have the type ``SparseMatrixCSC{Tv,Ti}``, where ``Tv`` -is the type of the nonzero values, and ``Ti`` is the integer type for -storing column pointers and row indices. -:: - - type SparseMatrixCSC{Tv,Ti<:Integer} <: AbstractSparseMatrix{Tv,Ti} - m::Int # Number of rows - n::Int # Number of columns - colptr::Vector{Ti} # Column i is in colptr[i]:(colptr[i+1]-1) - rowval::Vector{Ti} # Row values of nonzeros - nzval::Vector{Tv} # Nonzero values - end - -The compressed sparse column storage makes it easy and quick to access -the elements in the column of a sparse matrix, whereas accessing the -sparse matrix by rows is considerably slower. Operations such as -insertion of nonzero values one at a time in the CSC structure tend to -be slow. This is because all elements of the sparse matrix that are -beyond the point of insertion have to be moved one place over. - -All operations on sparse matrices are carefully implemented to exploit -the CSC data structure for performance, and to avoid expensive operations. - -Sparse matrix constructors --------------------------- - -The simplest way to create sparse matrices are using functions -equivalent to the ``zeros`` and ``eye`` functions that Julia provides -for working with dense matrices. To produce sparse matrices instead, -you can use the same names with an ``sp`` prefix: - -:: - - julia> spzeros(3,5) - 3x5 sparse matrix with 0 nonzeros: - - julia> speye(3,5) - 3x5 sparse matrix with 3 nonzeros: - [1, 1] = 1.0 - [2, 2] = 1.0 - [3, 3] = 1.0 - -The ``sparse`` function is often a handy way to construct sparse -matrices. It takes as its input a vector ``I`` of row indices, a -vector ``J`` of column indices, and a vector ``V`` of nonzero -values. ``sparse(I,J,V)`` constructs a sparse matrix such that -``S[I[k], J[k]] = V[k]``. - -:: - - julia> I = [1, 4, 3, 5]; J = [4, 7, 18, 9]; V = [1, 2, -5, 3]; - - julia> sparse(I,J,V) - 5x18 sparse matrix with 4 nonzeros: - [1 , 4] = 1 - [4 , 7] = 2 - [5 , 9] = 3 - [3 , 18] = -5 - -The inverse of the ``sparse`` function is ``findn``, which -retrieves the inputs used to create the sparse matrix. - -:: - - julia> findn(S) - ([1, 4, 5, 3],[4, 7, 9, 18]) - - julia> findn_nzs(S) - ([1, 4, 5, 3],[4, 7, 9, 18],[1, 2, 3, -5]) - -Another way to create sparse matrices is to convert a dense matrix -into a sparse matrix using the ``sparse`` function: - -:: - - julia> sparse(eye(5)) - 5x5 sparse matrix with 5 nonzeros: - [1, 1] = 1.0 - [2, 2] = 1.0 - [3, 3] = 1.0 - [4, 4] = 1.0 - [5, 5] = 1.0 - -You can go in the other direction using the ``dense`` or the ``full`` -function. The ``issparse`` function can be used to query if a matrix -is sparse. - -:: - - julia> issparse(speye(5)) - true - -Sparse matrix operations ------------------------- - -Arithmetic operations on sparse matrices also work as they do on dense -matrices. Indexing of, assignment into, and concatenation of sparse -matrices work in the same way as dense matrices. Indexing operations, -especially assignment, are expensive, when carried out one element at -a time. In many cases it may be better to convert the sparse matrix -into ``(I,J,V)`` format using ``find_nzs``, manipulate the nonzeros or -the structure in the dense vectors ``(I,J,V)``, and then reconstruct -the sparse matrix. diff --git a/doc/manual/strings.rst b/doc/manual/strings.rst index 1b64efe4cd7cf..3091ab3e84761 100644 --- a/doc/manual/strings.rst +++ b/doc/manual/strings.rst @@ -28,7 +28,7 @@ ASCII strings, and they will work as expected, both in terms of performance and semantics. If such code encounters non-ASCII text, it will gracefully fail with a clear error message, rather than silently introducing corrupt results. When this happens, modifying the code to -handle non-ASCII data is straightforward and easy. +handle non-ASCII data is straightforward. There are a few noteworthy high-level features about Julia's strings: @@ -54,8 +54,7 @@ There are a few noteworthy high-level features about Julia's strings: `Unicode `_ characters: literal strings are always `ASCII `_ or `UTF-8 `_ but other encodings for - strings from external sources can be supported easily and - efficiently. + strings from external sources can be supported. .. _man-characters: @@ -81,9 +80,10 @@ easily:: 120 julia> typeof(ans) - Int32 + Int64 -You can convert an integer value back to a ``Char`` just as easily:: +On 32-bit architectures, ``typeof(ans)`` will be Int32. You can convert an integer +value back to a ``Char`` just as easily:: julia> char(120) 'x' @@ -91,13 +91,7 @@ You can convert an integer value back to a ``Char`` just as easily:: Not all integer values are valid Unicode code points, but for performance, the ``char`` conversion does not check that every character value is valid. If you want to check that each converted value is a -value code point, use the ``safe_char`` conversion instead:: - - julia> char(0xd800) - '???' - - julia> safe_char(0xd800) - invalid Unicode code point: U+d800 +valid code point, use the ``safe_char`` conversion instead:: julia> char(0x110000) '\U110000' @@ -155,11 +149,8 @@ also be used:: julia> int('\xff') 255 -Like any integers, you can do arithmetic and comparisons with ``Char`` -values:: - - julia> 'x' - 'a' - 23 +You can do comparisons and a limited amount of arithmetic with +``Char`` values:: julia> 'A' < 'a' true @@ -170,14 +161,10 @@ values:: julia> 'A' <= 'X' <= 'Z' true -Arithmetic with ``Char`` values always yields integer values. To create -a new ``Char`` value, explicit conversion back to the ``Char`` type is -required:: + julia> 'x' - 'a' + 23 julia> 'A' + 1 - 66 - - julia> char(ans) 'B' String Basics @@ -200,13 +187,12 @@ If you want to extract a character from a string, you index into it:: '\n' All indexing in Julia is 1-based: the first element of any -integer-indexed object is found at index 1, not index 0, and the last -element is found at index ``n`` rather than ``n-1``, when the string has +integer-indexed object is found at index 1, and the last +element is found at index ``n``, when the string has a length of ``n``. -In any indexing expression, the keyword, ``end``, can be used as a -shorthand for ``length(x)``, where ``x`` is the object being indexed -into, whether it is a string, an array, or some other indexable object. +In any indexing expression, the keyword ``end`` can be used as a +shorthand for the last index (computed by ``endof(str)``). You can perform arithmetic and other operations with ``end``, just like a normal value:: @@ -225,10 +211,10 @@ a normal value:: Using an index less than 1 or greater than ``end`` raises an error:: julia> str[0] - in next: arrayref: index out of range + BoundsError() julia> str[end+1] - in next: arrayref: index out of range + BoundsError() You can also extract a substring using range indexing:: @@ -286,17 +272,16 @@ such an invalid byte index, an error is thrown:: In this case, the character ``∀`` is a three-byte character, so the indices 2 and 3 are invalid and the next character's index is 4. -Because of variable-length encodings, ``strlen(s)`` and ``length(s)`` -are not always the same: ``strlen(s)`` gives the number of characters in -``s`` while ``length(s)`` gives the maximum valid byte index into ``s``. -If you iterate through the indices 1 through ``length(s)`` and index +Because of variable-length encodings, the number of character in a +string (given by ``length(s)``) is not always the same as the last index. +If you iterate through the indices 1 through ``endof(s)`` and index into ``s``, the sequence of characters returned, when errors aren't -thrown, is the sequence of characters comprising the string, ``s``. -Thus, we do have the identity that ``strlen(s) <= length(s)`` since each +thrown, is the sequence of characters comprising the string ``s``. +Thus, we do have the identity that ``length(s) <= endof(s)`` since each character in a string must have its own index. The following is an inefficient and verbose way to iterate through the characters of ``s``:: - julia> for i = 1:length(s) + julia> for i = 1:endof(s) try println(s[i]) catch @@ -316,7 +301,7 @@ awkward idiom is unnecessary for iterating through the characters in a string, since you can just use the string as an iterable object, no exception handling required:: - julia> for c = s + julia> for c in s println(c) end ∀ @@ -347,11 +332,11 @@ One of the most common and useful string operations is concatenation:: julia> whom = "world" "world" - julia> strcat(greet, ", ", whom, ".\n") + julia> string(greet, ", ", whom, ".\n") "Hello, world.\n" Constructing strings like this can become a bit cumbersome, however. To -reduce the need for these verbose calls to ``strcat``, Julia allows +reduce the need for these verbose calls to ``string``, Julia allows interpolation into string literals using ``$``, as in Perl:: julia> "$greet, $whom.\n" @@ -368,26 +353,19 @@ can interpolate any expression into a string using parentheses:: julia> "1 + 2 = $(1 + 2)" "1 + 2 = 3" -The expression need not be contained in parentheses, however. For -example, since a literal array expression is not complete until the -opening ``[`` is closed by a matching ``]``, you can interpolate an -array like this:: - - julia> x = 2; y = 3; z = 5; - - julia> "x,y,z: $[x,y,z]." - "x,y,z: [2,3,5]." - Both concatenation and string interpolation call the generic ``string`` function to convert objects into ``String`` form. Most non-``String`` objects are converted to strings as they are shown in interactive sessions:: julia> v = [1,2,3] - [1,2,3] + 3-element Int64 Array: + 1 + 2 + 3 julia> "v: $v" - "v: [1,2,3]" + "v: [1, 2, 3]" The ``string`` function is the identity for ``String`` and ``Char`` values, so these are interpolated into strings as themselves, unquoted @@ -454,17 +432,15 @@ Another handy string function is ``repeat``:: Some other useful functions include: -- ``length(str)`` gives the maximal (byte) index that can be used to +- ``endof(str)`` gives the maximal (byte) index that can be used to index into ``str``. -- ``strlen(str)`` the number of characters in ``str``; this is *not* - the same as ``length(str)``. +- ``length(str)`` the number of characters in ``str``. - ``i = start(str)`` gives the first valid index at which a character can be found in ``str`` (typically 1). - ``c, j = next(str,i)`` returns next character at or after the index - ``i`` and the next valid character index following that. With the - ``start`` and ``length``, can be used to iterate through the - characters in ``str``. With ``length`` and ``start`` can be used to - iterate through the characters in ``str`` in reverse. + ``i`` and the next valid character index following that. With + ``start`` and ``endof``, can be used to iterate through the + characters in ``str``. - ``ind2chr(str,i)`` gives the number of characters in ``str`` up to and including any at index ``i``. - ``chr2ind(str,j)`` gives the index at which the ``j``\ th character @@ -482,145 +458,6 @@ quite what is needed. For these kinds of situations, Julia provides a regular double-quoted string literal, but is immediately prefixed by an identifier, and doesn't behave quite like a normal string literal. -Two types of interpretation are performed on normal Julia string -literals: interpolation and unescaping (escaping is the act of -expressing a non-standard character with a sequence like ``\n``, whereas -unescaping is the process of interpreting such escape sequences as -actual characters). There are cases where its convenient to disable -either or both of these behaviors. For such situations, Julia provides -three types of non-standard string literals: - -- ``E"..."`` interpret escape sequences but do not interpolate, thereby - rendering ``$`` a harmless, normal character. -- ``I"..."`` perform interpolation but do not interpret escape - sequences specially. -- ``L"..."`` perform neither unescaping nor interpolation. - -Suppose, for example, you would like to write strings that will contain -many ``$`` characters without interpolation. You can, as described -above, escape the ``$`` characters with a preceding backslash. This can -become tedious, however. Non-standard string literals prefixed with -``E`` do not perform string interpolation:: - - julia> E"I have $100 in my account.\n" - "I have \$100 in my account.\n" - -This allows you to have ``$`` characters inside of string literals -without triggering interpolation and without needing to escape those -``$``\ s by preceding them with a ``\``. Escape sequences, such as the -``\n`` above, still behave as usual, so '' becomes a newline character. - -On the other hand, ``I"..."`` string literals perform interpolation but -no unescaping:: - - julia> I"I have $100 in my account.\n" - "I have 100 in my account.\\n" - -The value of the expression ``100`` is interpolated into the string, -yielding the decimal string representation of the value 100 — namely -``"100"`` (sorry, that might be a bit confusing). The trailing ``\n`` -sequence is taken as literal backslash and ``n`` characters, rather than -being interpreted as a single newline character. - -The third non-standard string form interprets all the characters between -the opening and closing quotes literally: the ``L"..."`` form. Here is -an example usage:: - - julia> L"I have $100 in my account.\n" - "I have \$100 in my account.\\n" - -Neither the ``$`` nor the ``\n`` sequence are specially interpreted. - -Byte Array Literals -~~~~~~~~~~~~~~~~~~~ - -Some string literal forms don't create strings at all. In the `next -section <#regular-expressions>`_, we will see that regular expressions -are written as non-standard string literals. Another useful non-standard -string literal, however, is the byte-array string literal: ``b"..."``. -This form lets you use string notation to express literal byte arrays — -i.e. arrays of ``Uint8`` values. The convention is that non-standard -literals with uppercase prefixes produce actual string objects, while -those with lowercase prefixes produce non-string objects like byte -arrays or compiled regular expressions. The rules for byte array -literals are the following: - -- ASCII characters and ASCII escapes produce a single byte. -- ``\x`` and octal escape sequences produce the *byte* corresponding to - the escape value. -- Unicode escape sequences produce a sequence of bytes encoding that - code point in UTF-8. - -There is some overlap between these rules since the behavior of ``\x`` -and octal escapes less than 0x80 (128) are covered by both of the first -two rules, but here these rules agree. Together, these rules allow one -to easily use ASCII characters, arbitrary byte values, and UTF-8 -sequences to produce arrays of bytes. Here is an example using all -three:: - - julia> b"DATA\xff\u2200" - [68,65,84,65,255,226,136,128] - -The ASCII string "DATA" corresponds to the bytes 68, 65, 84, 65. -``\xff`` produces the single byte 255. The Unicode escape ``\u2200`` is -encoded in UTF-8 as the three bytes 226, 136, 128. Note that the -resulting byte array does not correspond to a valid UTF-8 string — if -you try to use this as a regular string literal, you will get a syntax -error:: - - julia> "DATA\xff\u2200" - syntax error: invalid UTF-8 sequence - -Also observe the significant distinction between ``\xff`` and ``\uff``: -the former escape sequence encodes the *byte 255*, whereas the latter -escape sequence represents the *code point 255*, which is encoded as two -bytes in UTF-8:: - - julia> b"\xff" - [255] - - julia> b"\uff" - [195,191] - -In character literals, this distinction is glossed over and ``\xff`` is -allowed to represent the code point 255, because characters *always* -represent code points. In strings, however, ``\x`` escapes always -represent bytes, not code points, whereas ``\u`` and ``\U`` escapes -always represent code points, which are encoded in one or more bytes. -For code points less than ``\u80``, it happens that the the UTF-8 -encoding of each code point is just the single byte produced by the -corresponding ``\x`` escape, so the distinction can safely be ignored. -For the escapes ``\x80`` through ``\xff`` as compared to ``\u80`` -through ``\uff``, however, there is a major difference: the former -escapes all encode single bytes, which — unless followed by very -specific continuation bytes — do not form valid UTF-8 data, whereas the -latter escapes all represent Unicode code points with two-byte -encodings. - -If this is all extremely confusing, try reading `"The Absolute Minimum -Every Software Developer Absolutely, Positively Must Know About Unicode -and Character -Sets" `_. It's an -excellent introduction to Unicode and UTF-8, and may help alleviate some -confusion regarding the matter. - -In byte array literals, objects interpolate as their binary -representation rather than as their string representation:: - - julia> msg = "Hello." - "Hello." - - julia> len = uint16(length(msg)) - 6 - - julia> b"$len$msg" - [6,0,72,101,108,108,111,46] - -Here the first two bytes are the native (little-endian on x86) binary -representation of the length of the string "Hello.", encoded as a -unsigned 16-bit integer, while the following bytes are the ASCII bytes -of the string "Hello." itself. - Regular Expressions ------------------- @@ -701,13 +538,19 @@ a string is invalid). Here's is a pair of somewhat contrived examples:: "acd" julia> m.captures - ("a","c","d") + 3-element Union(UTF8String,ASCIIString,Nothing) Array: + "a" + "c" + "d" julia> m.offset 1 julia> m.offsets - [1,2,3] + 3-element Int64 Array: + 1 + 2 + 3 julia> m = match(r"(a|b)(c)?(d)", "ad") RegexMatch("ad", 1="a", 2=nothing, 3="d") @@ -716,21 +559,24 @@ a string is invalid). Here's is a pair of somewhat contrived examples:: "ad" julia> m.captures - ("a",nothing,"d") + 3-element Union(UTF8String,ASCIIString,Nothing) Array: + "a" + nothing + "d" julia> m.offset 1 julia> m.offsets - [1,0,2] + 3-element Int64 Array: + 1 + 0 + 2 It is convenient to have captures returned as a tuple so that one can use tuple destructuring syntax to bind them to local variables:: - julia> first, second, third = m.captures - ("a",nothing,"d") - - julia> first + julia> first, second, third = m.captures; first "a" You can modify the behavior of regular expressions by some combination of @@ -775,8 +621,75 @@ For example, the following regex has all three flags turned on:: julia> match(r"a+.*b+.*?d$"ism, "Goodbye,\nOh, angry,\nBad world\n") RegexMatch("angry,\nBad world") -.. raw:: html +Byte Array Literals +~~~~~~~~~~~~~~~~~~~ + +Another useful non-standard string literal is the byte-array string literal: +``b"..."``. This form lets you use string notation to express literal byte +arrays — i.e. arrays of ``Uint8`` values. The convention is that non-standard +literals with uppercase prefixes produce actual string objects, while +those with lowercase prefixes produce non-string objects like byte +arrays or compiled regular expressions. The rules for byte array +literals are the following: + +- ASCII characters and ASCII escapes produce a single byte. +- ``\x`` and octal escape sequences produce the *byte* corresponding to + the escape value. +- Unicode escape sequences produce a sequence of bytes encoding that + code point in UTF-8. + +There is some overlap between these rules since the behavior of ``\x`` +and octal escapes less than 0x80 (128) are covered by both of the first +two rules, but here these rules agree. Together, these rules allow one +to easily use ASCII characters, arbitrary byte values, and UTF-8 +sequences to produce arrays of bytes. Here is an example using all +three:: + + julia> b"DATA\xff\u2200" + [68,65,84,65,255,226,136,128] + +The ASCII string "DATA" corresponds to the bytes 68, 65, 84, 65. +``\xff`` produces the single byte 255. The Unicode escape ``\u2200`` is +encoded in UTF-8 as the three bytes 226, 136, 128. Note that the +resulting byte array does not correspond to a valid UTF-8 string — if +you try to use this as a regular string literal, you will get a syntax +error:: + + julia> "DATA\xff\u2200" + syntax error: invalid UTF-8 sequence + +Also observe the significant distinction between ``\xff`` and ``\uff``: +the former escape sequence encodes the *byte 255*, whereas the latter +escape sequence represents the *code point 255*, which is encoded as two +bytes in UTF-8:: + + julia> b"\xff" + 1-element Uint8 Array: + 0xff + + julia> b"\uff" + 2-element Uint8 Array: + 0xc3 + 0xbf + +In character literals, this distinction is glossed over and ``\xff`` is +allowed to represent the code point 255, because characters *always* +represent code points. In strings, however, ``\x`` escapes always +represent bytes, not code points, whereas ``\u`` and ``\U`` escapes +always represent code points, which are encoded in one or more bytes. +For code points less than ``\u80``, it happens that the the UTF-8 +encoding of each code point is just the single byte produced by the +corresponding ``\x`` escape, so the distinction can safely be ignored. +For the escapes ``\x80`` through ``\xff`` as compared to ``\u80`` +through ``\uff``, however, there is a major difference: the former +escapes all encode single bytes, which — unless followed by very +specific continuation bytes — do not form valid UTF-8 data, whereas the +latter escapes all represent Unicode code points with two-byte +encodings. - +If this is all extremely confusing, try reading `"The Absolute Minimum +Every Software Developer Absolutely, Positively Must Know About Unicode +and Character +Sets" `_. It's an +excellent introduction to Unicode and UTF-8, and may help alleviate some +confusion regarding the matter. diff --git a/doc/manual/types.rst b/doc/manual/types.rst index 5b7f46c26fc91..cb92fa4105ff9 100644 --- a/doc/manual/types.rst +++ b/doc/manual/types.rst @@ -149,7 +149,9 @@ The "declaration" behavior only occurs in specific contexts:: x::Int8 = 10 # as the left-hand side of an assignment In value contexts, such as ``f(x::Int8)``, the ``::`` is a type -assertion again and not a declaration. +assertion again and not a declaration. Note that these declarations +cannot be used in global scope currently, in the REPL, since julia +does not yet have constant-type globals. .. _man-abstract-types: @@ -277,7 +279,7 @@ declaration of ``Bool`` above therefore means that a boolean value takes eight bits to store, and has ``Integer`` as its immediate supertype. Currently, only sizes that are multiples of 8 bits are supported. Therefore, boolean values, although they really need just a single bit, -cannot be declared to be any smaller then eight bits. +cannot be declared to be any smaller than eight bits. The types ``Bool``, ``Int8`` and ``Uint8`` all have identical representations: they are eight-bit chunks of memory. Since Julia's type @@ -289,7 +291,7 @@ All other differences between ``Bool``, ``Int8``, and ``Uint8`` are matters of behavior — the way functions are defined to act when given objects of these types as arguments. This is why a nominative type system is necessary: if structure determined type, which in turn -dictates behavior, it would be impossible to make ``Bool`` behave any +dictates behavior, then it would be impossible to make ``Bool`` behave any differently than ``Int8`` or ``Uint8``. .. _man-composite-types: @@ -302,7 +304,9 @@ are called records, structures ("structs" in C), or objects in various languages. A composite type is a collection of named fields, an instance of which can be treated as a single value. In many languages, composite types are the only kind of user-definable type, and they are by far the -most commonly used user-defined type in Julia as well. In mainstream +most commonly used user-defined type in Julia as well. + +In mainstream object oriented languages, such as C++, Java, Python and Ruby, composite types also have named functions associated with them, and the combination is called an "object". In purer object-oriented languages, @@ -310,15 +314,15 @@ such as Python and Ruby, all values are objects whether they are composites or not. In less pure object oriented languages, including C++ and Java, some values, such as integers and floating-point values, are not objects, while instances of user-defined composite types are true -objects with associated methods. In Julia, all values are objects, as in -Python and Ruby, but functions are not bundled with the objects they +objects with associated methods. In Julia, all values are objects, +but functions are not bundled with the objects they operate on. This is necessary since Julia chooses which method of a function to use by multiple dispatch, meaning that the types of *all* of a function's arguments are considered when selecting a method, rather than just the first one (see :ref:`man-methods` for more information on methods and dispatch). Thus, it would be inappropriate for functions to "belong" to only their first argument. Organizing -methods by association with function objects rather than simply having +methods into function objects rather than having named bags of methods "inside" each object ends up being a highly beneficial aspect of the language design. @@ -392,6 +396,42 @@ Types <#man-parametric-types>`_ and on :ref:`man-methods`, and is sufficiently important to be addressed in its own section: :ref:`man-constructors`. +Immutable Composite Types +------------------------- + +It is also possible to define *immutable* composite types by using +the keyword ``immutable`` instead of ``type``: + + immutable Complex + real::Float64 + imag::Float64 + end + +Such types behave just like other composite types, except that instances +of them cannot be modified. Immutable types have several advantages: + +- They are more efficient in some cases. Types like the ``Complex`` + example above can be packed efficiently into arrays, and in some + cases the compiler is able to avoid allocating immutable objects + entirely. +- It is not possible to violate the invariants provided by the + type's constructors. +- Code using immutable objects can be easier to reason about. + +An immutable object might contain mutable objects, such as arrays, as +fields. Those contained objects will remain mutable; only the fields of the +immutable object itself cannot be changed to point to different objects. + +A useful way to think about immutable composites is that each instance is +associated with specific field values --- the field values alone tell +you everything about the object. In contrast, a mutable object is like a +little container that might contain different values over time, and so is +not identified with specific field values. In deciding whether to make a +type immutable, ask whether two instances with the same field values +would be considered identical, or if they might need to change independently +over time. If they would be considered identical, the type should probably +be immutable. + Type Unions ----------- @@ -421,7 +461,7 @@ union of no types is the "bottom" type, ``None``:: Recall from the `discussion above <#Any+and+None>`_ that ``None`` is the abstract type which is the subtype of all other types, and which no object is an instance of. Since a zero-argument ``Union`` call has no -argument types for objects to be instances of, it should produce the a +argument types for objects to be instances of, it should produce a type which no objects are instances of — i.e. ``None``. Tuple Types @@ -881,9 +921,9 @@ specifying the dimension:: true However, there is no way to equally simply restrict just the dimension -but not the element type. Yet, one often needs to program to just -vectors or matrices. For that reason, the following type aliases are -provided:: +but not the element type. Yet, one often needs to ensure an object +is a vector or a matrix (imposing restrictions on the number of dimensions). For +that reason, the following type aliases are provided:: typealias Vector{T} Array{T,1} typealias Matrix{T} Array{T,2} diff --git a/doc/packages/packagelist.rst b/doc/packages/packagelist.rst new file mode 100644 index 0000000000000..debffd7538a7a --- /dev/null +++ b/doc/packages/packagelist.rst @@ -0,0 +1,4997 @@ +.. _available-packages: + +******************** + Available Packages +******************** + +`ArgParse `_ +__________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/80502de63c1b21d8f3ba663d72ba5be2?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Carlo Baldassi + :target: https://github.com/carlobaldassi + + Current Version: ``0.2.0`` + + Package for parsing command-line arguments to Julia programs. + + Maintainer: `Carlo Baldassi `_ + + Dependencies:: + + Options Any Version + TextWrap Any Version + julia [v"0.2.0-"] + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/80502de63c1b21d8f3ba663d72ba5be2?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Carlo Baldassi + :target: https://github.com/carlobaldassi + + .. image:: https://secure.gravatar.com/avatar/21aeae1f260365557523718bc19640f7?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Stefan Karpinski + :target: https://github.com/StefanKarpinski + + .. image:: https://secure.gravatar.com/avatar/311f28d70bb1de3b0e9bb55e9d5fd26d?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Tim Besard + :target: https://github.com/maleadt + +---- + +`Benchmark `_ +_____________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: John Myles White + :target: https://github.com/johnmyleswhite + + Current Version: ``0.0.0`` + + A package for benchmarking code and packages + + Maintainer: `John Myles White `_ + + Dependencies:: + + DataFrames Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: John Myles White + :target: https://github.com/johnmyleswhite + + .. image:: https://secure.gravatar.com/avatar/16d8443194c380ca93a77fb8530a5aee?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Patrick O'Leary + :target: https://github.com/pao + + .. image:: https://secure.gravatar.com/avatar/fa3b781987ef53c4d3b8397f2239e519?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Diego Javier Zea + :target: https://github.com/diegozea + +---- + +`BinDeps `_ +___________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/ed9f9395e60acde24eb4bb89fe2154aa?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Keno Fischer + :target: https://github.com/loladiro + + Current Version: ``0.0.0`` + + Tool for building binary dependencies for Julia modules + + Maintainer: `Keno Fischer `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/ed9f9395e60acde24eb4bb89fe2154aa?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Keno Fischer + :target: https://github.com/loladiro + + .. image:: https://secure.gravatar.com/avatar/8af4d5971a2308b86a94f58fb98129c5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Jameson Nash + :target: https://github.com/vtjnash + + .. image:: https://secure.gravatar.com/avatar/317e44562dcf11f5164d0a4936696fbc?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: rened + :target: https://github.com/rened + +---- + +`BioSeq `_ +_________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/fa3b781987ef53c4d3b8397f2239e519?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Diego Javier Zea + :target: https://github.com/diegozea + + Current Version: ``0.0.0`` + + Julia's package for working on Bioinformatics with DNA, RNA and Protein Sequences + + Maintainer: `Diego Javier Zea `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/fa3b781987ef53c4d3b8397f2239e519?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Diego Javier Zea + :target: https://github.com/diegozea + + .. image:: https://secure.gravatar.com/avatar/42c8c4ab92de3390bcd2f637ef6ca16c?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Kevin Squire + :target: https://github.com/kmsquire + +---- + +`BloomFilters `_ +___________________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: John Myles White + :target: https://github.com/johnmyleswhite + + Current Version: ``0.0.0`` + + Bloom filters in Julia + + Maintainer: `John Myles White `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: John Myles White + :target: https://github.com/johnmyleswhite + +---- + +`Cairo `_ +________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/d57c99557ab0dc0fa44b4c84447d0f15?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-org-420.png + :height: 80px + :width: 80px + :align: right + :alt: The Julia Language + :target: https://github.com/JuliaLang + + Current Version: ``0.0.0`` + + Bindings to the Cairo graphics library. + + Maintainer: `The Julia Language `_ + + Dependencies:: + + BinDeps Any Version + Color Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/ed9f9395e60acde24eb4bb89fe2154aa?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Keno Fischer + :target: https://github.com/loladiro + + .. image:: https://secure.gravatar.com/avatar/1b65c4698da5f30310e14aaee8f3f24e?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Mike Nolta + :target: https://github.com/nolta + + .. image:: https://secure.gravatar.com/avatar/b4b8db23d8096b722483a57d21b7d65d?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Jeff Bezanson + :target: https://github.com/JeffBezanson + + .. image:: https://secure.gravatar.com/avatar/21aeae1f260365557523718bc19640f7?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Stefan Karpinski + :target: https://github.com/StefanKarpinski + + .. image:: https://secure.gravatar.com/avatar/16d8443194c380ca93a77fb8530a5aee?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Patrick O'Leary + :target: https://github.com/pao + + .. image:: https://secure.gravatar.com/avatar/55e277a715ee2afd0d29c309174eca02?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Viral B. Shah + :target: https://github.com/ViralBShah + + .. image:: https://secure.gravatar.com/avatar/2989a078f4caff6fb86fa30e59bd9aa9?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Tim Holy + :target: https://github.com/timholy + + .. image:: https://secure.gravatar.com/avatar/42c8c4ab92de3390bcd2f637ef6ca16c?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Kevin Squire + :target: https://github.com/kmsquire + + .. image:: https://secure.gravatar.com/avatar/dfc3b0fbb59c9444153823fd35dbd13b?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Westley Argentum Hennigh + :target: https://github.com/WestleyArgentum + +---- + +`Calculus `_ +___________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: John Myles White + :target: https://github.com/johnmyleswhite + + Current Version: ``0.0.0`` + + Calculus functions in Julia + + Maintainer: `John Myles White `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: John Myles White + :target: https://github.com/johnmyleswhite + + .. image:: https://secure.gravatar.com/avatar/2989a078f4caff6fb86fa30e59bd9aa9?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Tim Holy + :target: https://github.com/timholy + + .. image:: https://secure.gravatar.com/avatar/f5c61e85dfa465686adc24e0bffba42a?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Avik Sengupta + :target: https://github.com/aviks + + .. image:: https://secure.gravatar.com/avatar/317e44562dcf11f5164d0a4936696fbc?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: rened + :target: https://github.com/rened + +---- + +`Calendar `_ +__________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/1b65c4698da5f30310e14aaee8f3f24e?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Mike Nolta + :target: https://github.com/nolta + + Current Version: ``0.0.0`` + + Calendar time package for Julia + + Maintainer: `Mike Nolta `_ + + Dependencies:: + + ICU Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/1b65c4698da5f30310e14aaee8f3f24e?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Mike Nolta + :target: https://github.com/nolta + + .. image:: https://secure.gravatar.com/avatar/f5c61e85dfa465686adc24e0bffba42a?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Avik Sengupta + :target: https://github.com/aviks + + .. image:: https://secure.gravatar.com/avatar/21aeae1f260365557523718bc19640f7?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Stefan Karpinski + :target: https://github.com/StefanKarpinski + +---- + +`Catalan `_ +___________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/c928b9b00cbc5133c4ae7a743cf96f10?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Alessandro Andrioni + :target: https://github.com/andrioni + + Current Version: ``0.0.0`` + + Catalan: a combinatorics library for Julia + + Maintainer: `Alessandro Andrioni `_ + + Dependencies:: + + Polynomial Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/c928b9b00cbc5133c4ae7a743cf96f10?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Alessandro Andrioni + :target: https://github.com/andrioni + + .. image:: https://secure.gravatar.com/avatar/6cba33e8e7c69fa63f6ad386b7a958c5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Jiahao Chen + :target: https://github.com/jiahao + +---- + +`Clang `_ +_______________________________________________ + + .. image:: https://secure.gravatar.com/avatar/192f114babcc8c2f53936c145bbc502c?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Isaiah + :target: https://github.com/ihnorton + + Current Version: ``0.0.0`` + + Julia access to the libclang interface of the LLVM Clang compiler. + + Maintainer: `Isaiah `_ + + Dependencies:: + + BinDeps Any Version + julia [v"0.2.0-"] + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/192f114babcc8c2f53936c145bbc502c?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Isaiah + :target: https://github.com/ihnorton + + .. image:: https://secure.gravatar.com/avatar/8af4d5971a2308b86a94f58fb98129c5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Jameson Nash + :target: https://github.com/vtjnash + + .. image:: https://secure.gravatar.com/avatar/313e7a578240d11c97a68c9c6918a90b?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Amit Murthy + :target: https://github.com/amitmurthy + + .. image:: https://secure.gravatar.com/avatar/2989a078f4caff6fb86fa30e59bd9aa9?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Tim Holy + :target: https://github.com/timholy + +---- + +`Clp `_ +_________________________________________ + + .. image:: https://secure.gravatar.com/avatar/b0cf54b8431443687735cb486599ea9c?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Miles Lubin + :target: https://github.com/mlubin + + Current Version: ``0.0.0`` + + Interface to the Coin-OR Linear Programming solver (CLP) + + Maintainer: `Miles Lubin `_ + + Dependencies:: + + BinDeps Any Version + julia [v"0.1.0-"] + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/b0cf54b8431443687735cb486599ea9c?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Miles Lubin + :target: https://github.com/mlubin + +---- + +`Clustering `_ +_______________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: John Myles White + :target: https://github.com/johnmyleswhite + + Current Version: ``0.0.0`` + + Basic functions for clustering data: k-means, dp-means, etc. + + Maintainer: `John Myles White `_ + + Dependencies:: + + Devectorize Any Version + Distance Any Version + MLBase Any Version + Options Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: John Myles White + :target: https://github.com/johnmyleswhite + + .. image:: https://secure.gravatar.com/avatar/3db090e101b916d9256d0d3e043db71d?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Dahua Lin + :target: https://github.com/lindahua + + .. image:: https://secure.gravatar.com/avatar/1af2db0b26142fd0c7ab082f3d445f73?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Ian Fiske + :target: https://github.com/ianfiske + +---- + +`Codecs `_ +________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/fd97b03d16e1aa4c404391216d81c1d5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Daniel Jones + :target: https://github.com/dcjones + + Current Version: ``0.0.0`` + + Common data encoding algorithms + + Maintainer: `Daniel Jones `_ + + Dependencies:: + + Iterators Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/fd97b03d16e1aa4c404391216d81c1d5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Daniel Jones + :target: https://github.com/dcjones + +---- + +`CoinMP `_ +_______________________________________________ + + .. image:: https://secure.gravatar.com/avatar/b0cf54b8431443687735cb486599ea9c?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Miles Lubin + :target: https://github.com/mlubin + + Current Version: ``0.0.0`` + + Interface to the Coin-OR CBC solver for mixed-integer programming + + Maintainer: `Miles Lubin `_ + + Dependencies:: + + BinDeps Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/b0cf54b8431443687735cb486599ea9c?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Miles Lubin + :target: https://github.com/mlubin + +---- + +`Color `_ +________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/d57c99557ab0dc0fa44b4c84447d0f15?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-org-420.png + :height: 80px + :width: 80px + :align: right + :alt: The Julia Language + :target: https://github.com/JuliaLang + + Current Version: ``0.2.0`` + + Basic color manipulation utilities. + + Maintainer: `The Julia Language `_ + + Dependencies:: + + julia [v"0.2.0-"] + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/fd97b03d16e1aa4c404391216d81c1d5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Daniel Jones + :target: https://github.com/dcjones + + .. image:: https://secure.gravatar.com/avatar/2989a078f4caff6fb86fa30e59bd9aa9?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Tim Holy + :target: https://github.com/timholy + + .. image:: https://secure.gravatar.com/avatar/b4b8db23d8096b722483a57d21b7d65d?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Jeff Bezanson + :target: https://github.com/JeffBezanson + + .. image:: https://secure.gravatar.com/avatar/21aeae1f260365557523718bc19640f7?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Stefan Karpinski + :target: https://github.com/StefanKarpinski + +---- + +`Compose `_ +__________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/fd97b03d16e1aa4c404391216d81c1d5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Daniel Jones + :target: https://github.com/dcjones + + Current Version: ``0.0.0`` + + Declarative vector graphics + + Maintainer: `Daniel Jones `_ + + Dependencies:: + + Cairo Any Version + Mustache Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/fd97b03d16e1aa4c404391216d81c1d5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Daniel Jones + :target: https://github.com/dcjones + + .. image:: https://secure.gravatar.com/avatar/ed9f9395e60acde24eb4bb89fe2154aa?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Keno Fischer + :target: https://github.com/loladiro + + .. image:: https://secure.gravatar.com/avatar/2989a078f4caff6fb86fa30e59bd9aa9?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Tim Holy + :target: https://github.com/timholy + + .. image:: https://secure.gravatar.com/avatar/4206b43cb025b0c1fd8cd9fa89dd6086?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: catawbasam + :target: https://github.com/catawbasam + + .. image:: https://secure.gravatar.com/avatar/1af2db0b26142fd0c7ab082f3d445f73?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Ian Fiske + :target: https://github.com/ianfiske + + .. image:: https://secure.gravatar.com/avatar/910a5ad5931aeda034b38c9658eaadf2?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: microtherion + :target: https://github.com/microtherion + + .. image:: https://secure.gravatar.com/avatar/21aeae1f260365557523718bc19640f7?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Stefan Karpinski + :target: https://github.com/StefanKarpinski + + .. image:: https://secure.gravatar.com/avatar/dfc3b0fbb59c9444153823fd35dbd13b?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Westley Argentum Hennigh + :target: https://github.com/WestleyArgentum + +---- + +`ContinuedFractions `_ +_______________________________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: John Myles White + :target: https://github.com/johnmyleswhite + + Current Version: ``0.0.0`` + + Types and functions for working with continued fractions in Julia + + Maintainer: `John Myles White `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: John Myles White + :target: https://github.com/johnmyleswhite + +---- + +`Cpp `_ +__________________________________________ + + .. image:: https://secure.gravatar.com/avatar/2989a078f4caff6fb86fa30e59bd9aa9?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Tim Holy + :target: https://github.com/timholy + + Current Version: ``0.0.0`` + + Utilities for calling C++ from Julia + + Maintainer: `Tim Holy `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/2989a078f4caff6fb86fa30e59bd9aa9?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Tim Holy + :target: https://github.com/timholy + +---- + +`Cubature `_ +_____________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/9563cfcf21df990e570df1dd019bce16?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Steven G. Johnson + :target: https://github.com/stevengj + + Current Version: ``0.0.0`` + + One- and multi-dimensional adaptive integration routines for the Julia language + + Maintainer: `Steven G. Johnson `_ + + Dependencies:: + + BinDeps Any Version + + Contributors: + +---- + +`Curl `_ +__________________________________________ + + .. image:: https://secure.gravatar.com/avatar/bd2a3d33c3dcc6f25e61382f81689f33?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-org-420.png + :height: 80px + :width: 80px + :align: right + :alt: Forio Online Simulations + :target: https://github.com/forio + + Current Version: ``0.0.0`` + + a Julia HTTP curl library + + Maintainer: `Forio Online Simulations `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/d1206b7851de49f51e710c88a15547f4?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: PLHW + :target: https://github.com/pauladam + +---- + +`DICOM `_ +_______________________________________________ + + .. image:: https://secure.gravatar.com/avatar/192f114babcc8c2f53936c145bbc502c?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Isaiah + :target: https://github.com/ihnorton + + Current Version: ``0.0.0`` + + DICOM for Julia + + Maintainer: `Isaiah `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/192f114babcc8c2f53936c145bbc502c?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Isaiah + :target: https://github.com/ihnorton + + .. image:: https://secure.gravatar.com/avatar/21aeae1f260365557523718bc19640f7?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Stefan Karpinski + :target: https://github.com/StefanKarpinski + + .. image:: https://secure.gravatar.com/avatar/b4b8db23d8096b722483a57d21b7d65d?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Jeff Bezanson + :target: https://github.com/JeffBezanson + + .. image:: https://secure.gravatar.com/avatar/80502de63c1b21d8f3ba663d72ba5be2?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Carlo Baldassi + :target: https://github.com/carlobaldassi + + .. image:: https://secure.gravatar.com/avatar/ed9f9395e60acde24eb4bb89fe2154aa?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Keno Fischer + :target: https://github.com/loladiro + +---- + +`DataFrames `_ +________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/9f1a68b9e623be5da422b44e733fa8bc?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Harlan Harris + :target: https://github.com/HarlanH + + Current Version: ``0.2.0`` + + library for working with tabular data in Julia + + Maintainer: `Harlan Harris `_ + + Dependencies:: + + GZip Any Version + Options Any Version + Stats Any Version + julia [v"0.2.0-"] + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: John Myles White + :target: https://github.com/johnmyleswhite + + .. image:: https://secure.gravatar.com/avatar/9f1a68b9e623be5da422b44e733fa8bc?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Harlan Harris + :target: https://github.com/HarlanH + + .. image:: https://secure.gravatar.com/avatar/1a4672a0ae94c24f02517dea26097f58?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Chris DuBois + :target: https://github.com/doobwa + + .. image:: https://secure.gravatar.com/avatar/55e277a715ee2afd0d29c309174eca02?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Viral B. Shah + :target: https://github.com/ViralBShah + + .. image:: https://secure.gravatar.com/avatar/42c8c4ab92de3390bcd2f637ef6ca16c?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Kevin Squire + :target: https://github.com/kmsquire + + .. image:: https://secure.gravatar.com/avatar/903acb22f47a901577ee48d3962d5858?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Tom Short + :target: https://github.com/tshort + + .. image:: https://secure.gravatar.com/avatar/25ce2ab2f5e673e46208c1188a39e6ca?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: milktrader + :target: https://github.com/milktrader + + .. image:: https://secure.gravatar.com/avatar/21aeae1f260365557523718bc19640f7?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Stefan Karpinski + :target: https://github.com/StefanKarpinski + + .. image:: https://secure.gravatar.com/avatar/a27d23ce4c080f3307cc6507f6fdfe87?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: dmbates + :target: https://github.com/dmbates + + .. image:: https://secure.gravatar.com/avatar/2989a078f4caff6fb86fa30e59bd9aa9?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Tim Holy + :target: https://github.com/timholy + + .. image:: https://secure.gravatar.com/avatar/1af2db0b26142fd0c7ab082f3d445f73?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Ian Fiske + :target: https://github.com/ianfiske + + .. image:: https://secure.gravatar.com/avatar/b4b8db23d8096b722483a57d21b7d65d?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Jeff Bezanson + :target: https://github.com/JeffBezanson + + .. image:: https://secure.gravatar.com/avatar/16d8443194c380ca93a77fb8530a5aee?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Patrick O'Leary + :target: https://github.com/pao + + .. image:: https://secure.gravatar.com/avatar/2cbc175271c0dbdaf0aa8f68af6c13d4?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Glen Hertz + :target: https://github.com/GlenHertz + + .. image:: https://secure.gravatar.com/avatar/80502de63c1b21d8f3ba663d72ba5be2?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Carlo Baldassi + :target: https://github.com/carlobaldassi + + .. image:: https://secure.gravatar.com/avatar/8af4d5971a2308b86a94f58fb98129c5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Jameson Nash + :target: https://github.com/vtjnash + + .. image:: https://secure.gravatar.com/avatar/fd97b03d16e1aa4c404391216d81c1d5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Daniel Jones + :target: https://github.com/dcjones + + .. image:: https://secure.gravatar.com/avatar/02abdd20ef026f24d96035a407912df0?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Andreas Noack Jensen + :target: https://github.com/andreasnoackjensen + + .. image:: https://secure.gravatar.com/avatar/4206b43cb025b0c1fd8cd9fa89dd6086?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: catawbasam + :target: https://github.com/catawbasam + + .. image:: https://secure.gravatar.com/avatar/ed9f9395e60acde24eb4bb89fe2154aa?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Keno Fischer + :target: https://github.com/loladiro + + .. image:: https://secure.gravatar.com/avatar/1b65c4698da5f30310e14aaee8f3f24e?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Mike Nolta + :target: https://github.com/nolta + + .. image:: https://secure.gravatar.com/avatar/b0cf54b8431443687735cb486599ea9c?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Miles Lubin + :target: https://github.com/mlubin + + .. image:: https://secure.gravatar.com/avatar/5ac7b1da0f2e9107b5020f88023a15e5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Simon Byrne + :target: https://github.com/simonbyrne + +---- + +`DataStructures `_ +_________________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/3db090e101b916d9256d0d3e043db71d?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Dahua Lin + :target: https://github.com/lindahua + + Current Version: ``0.0.0`` + + Julia implementation of Data structures + + Maintainer: `Dahua Lin `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/3db090e101b916d9256d0d3e043db71d?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Dahua Lin + :target: https://github.com/lindahua + +---- + +`Debug `_ +_____________________________________________ + + .. image:: https://secure.gravatar.com/avatar/8d3d3934c39b52f48c35a0cc536edae7?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: toivoh + :target: https://github.com/toivoh + + Current Version: ``0.0.0`` + + Prototype interactive debugger for Julia + + Maintainer: `toivoh `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/8d3d3934c39b52f48c35a0cc536edae7?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: toivoh + :target: https://github.com/toivoh + + .. image:: https://secure.gravatar.com/avatar/5c06e9faa0d7bd205f81d10e825d7e4a?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: nfoti + :target: https://github.com/nfoti + + .. image:: https://secure.gravatar.com/avatar/317e44562dcf11f5164d0a4936696fbc?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: rened + :target: https://github.com/rened + +---- + +`DecisionTree `_ +_______________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/e0da736cf64e454db46b4446f1f58ed5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Ben Sadeghi + :target: https://github.com/bensadeghi + + Current Version: ``0.0.0`` + + Decision Tree Classifier in Julia + + Maintainer: `Ben Sadeghi `_ + + Dependencies:: + + julia [v"0.1.0-"] + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/e0da736cf64e454db46b4446f1f58ed5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Ben Sadeghi + :target: https://github.com/bensadeghi + +---- + +`Devectorize `_ +___________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/3db090e101b916d9256d0d3e043db71d?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Dahua Lin + :target: https://github.com/lindahua + + Current Version: ``0.2.0`` + + A Julia framework for delayed expression evaluation + + Maintainer: `Dahua Lin `_ + + Dependencies:: + + julia [v"0.2.0-"] + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/3db090e101b916d9256d0d3e043db71d?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Dahua Lin + :target: https://github.com/lindahua + +---- + +`DictViews `_ +__________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/62df30beab9c2a6f3fe3f86995e94387?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: David de Laat + :target: https://github.com/daviddelaat + + Current Version: ``0.0.0`` + + KeysView and ValuesView types for dynamic low-overhead views into the entries of dictionaries + + Maintainer: `David de Laat `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/62df30beab9c2a6f3fe3f86995e94387?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: David de Laat + :target: https://github.com/daviddelaat + +---- + +`DimensionalityReduction `_ +_________________________________________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: John Myles White + :target: https://github.com/johnmyleswhite + + Current Version: ``0.0.0`` + + Methods for dimensionality reduction: PCA, ICA, NMF + + Maintainer: `John Myles White `_ + + Dependencies:: + + DataFrames Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: John Myles White + :target: https://github.com/johnmyleswhite + +---- + +`Distance `_ +_____________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/3db090e101b916d9256d0d3e043db71d?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Dahua Lin + :target: https://github.com/lindahua + + Current Version: ``0.2.0`` + + Julia module for Distance evaluation + + Maintainer: `Dahua Lin `_ + + Dependencies:: + + Devectorize Any Version + julia [v"0.2.0-"] + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/3db090e101b916d9256d0d3e043db71d?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Dahua Lin + :target: https://github.com/lindahua + +---- + +`Distributions `_ +_________________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/d41d8cd98f00b204e9800998ecf8427e?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-org-420.png + :height: 80px + :width: 80px + :align: right + :alt: JuliaStats + :target: https://github.com/JuliaStats + + Current Version: ``0.0.0`` + + A Julia package for probability distributions and associated funtions. + + Maintainer: `JuliaStats `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: John Myles White + :target: https://github.com/johnmyleswhite + + .. image:: https://secure.gravatar.com/avatar/52ec3f52d9c7be45b398b9e8afa4ee8c?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Dan Merl + :target: https://github.com/danmerl + + .. image:: https://secure.gravatar.com/avatar/02abdd20ef026f24d96035a407912df0?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Andreas Noack Jensen + :target: https://github.com/andreasnoackjensen + + .. image:: https://secure.gravatar.com/avatar/a27d23ce4c080f3307cc6507f6fdfe87?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: dmbates + :target: https://github.com/dmbates + + .. image:: https://secure.gravatar.com/avatar/3db090e101b916d9256d0d3e043db71d?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Dahua Lin + :target: https://github.com/lindahua + + .. image:: https://secure.gravatar.com/avatar/6cba33e8e7c69fa63f6ad386b7a958c5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Jiahao Chen + :target: https://github.com/jiahao + + .. image:: https://secure.gravatar.com/avatar/0b41d1f9e580cde53307166a47ae5300?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Sergey Bartunov + :target: https://github.com/sbos + +---- + +`Elliptic `_ +__________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/1b65c4698da5f30310e14aaee8f3f24e?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Mike Nolta + :target: https://github.com/nolta + + Current Version: ``0.0.0`` + + Elliptic integral and Jacobi elliptic special functions + + Maintainer: `Mike Nolta `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/1b65c4698da5f30310e14aaee8f3f24e?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Mike Nolta + :target: https://github.com/nolta + +---- + +`Example `_ +____________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/d57c99557ab0dc0fa44b4c84447d0f15?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-org-420.png + :height: 80px + :width: 80px + :align: right + :alt: The Julia Language + :target: https://github.com/JuliaLang + + Current Version: ``0.0.0`` + + Example Julia package repo. + + Maintainer: `The Julia Language `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/21aeae1f260365557523718bc19640f7?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Stefan Karpinski + :target: https://github.com/StefanKarpinski + +---- + +`FITSIO `_ +______________________________________________ + + .. image:: https://secure.gravatar.com/avatar/1b65c4698da5f30310e14aaee8f3f24e?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Mike Nolta + :target: https://github.com/nolta + + Current Version: ``0.0.0`` + + FITS file package for Julia + + Maintainer: `Mike Nolta `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/1b65c4698da5f30310e14aaee8f3f24e?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Mike Nolta + :target: https://github.com/nolta + +---- + +`FactCheck `_ +_________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/06625cbad0c69f5c2e673a4312e9fd7e?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Zach Allaun + :target: https://github.com/zachallaun + + Current Version: ``0.0.0`` + + Midje-like testing for Julia + + Maintainer: `Zach Allaun `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/06625cbad0c69f5c2e673a4312e9fd7e?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Zach Allaun + :target: https://github.com/zachallaun + +---- + +`FastaRead `_ +____________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/80502de63c1b21d8f3ba663d72ba5be2?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Carlo Baldassi + :target: https://github.com/carlobaldassi + + Current Version: ``0.2.0`` + + A fast FASTA reader for Julia + + Maintainer: `Carlo Baldassi `_ + + Dependencies:: + + GZip Any Version + julia [v"0.2.0-"] + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/80502de63c1b21d8f3ba663d72ba5be2?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Carlo Baldassi + :target: https://github.com/carlobaldassi + + .. image:: https://secure.gravatar.com/avatar/42c8c4ab92de3390bcd2f637ef6ca16c?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Kevin Squire + :target: https://github.com/kmsquire + +---- + +`FileFind `_ +___________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: John Myles White + :target: https://github.com/johnmyleswhite + + Current Version: ``0.0.0`` + + File::Find implementation in Julia + + Maintainer: `John Myles White `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: John Myles White + :target: https://github.com/johnmyleswhite + +---- + +`GLFW `_ +_____________________________________________ + + .. image:: https://secure.gravatar.com/avatar/805857de807ffc1b543e807f727d05c6?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Jay Weisskopf + :target: https://github.com/jayschwa + + Current Version: ``0.0.0`` + + GLFW bindings for Julia. GLFW is a multi-platform library for opening a window, creating an OpenGL context, and managing input. + + Maintainer: `Jay Weisskopf `_ + + Documentation: ``_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/805857de807ffc1b543e807f727d05c6?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Jay Weisskopf + :target: https://github.com/jayschwa + +---- + +`GLM `_ +_____________________________________________ + + .. image:: https://secure.gravatar.com/avatar/d41d8cd98f00b204e9800998ecf8427e?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-org-420.png + :height: 80px + :width: 80px + :align: right + :alt: JuliaStats + :target: https://github.com/JuliaStats + + Current Version: ``0.0.0`` + + Generalized linear models in Julia + + Maintainer: `JuliaStats `_ + + Dependencies:: + + DataFrames Any Version + Distributions Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/a27d23ce4c080f3307cc6507f6fdfe87?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: dmbates + :target: https://github.com/dmbates + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: John Myles White + :target: https://github.com/johnmyleswhite + + .. image:: https://secure.gravatar.com/avatar/1a4672a0ae94c24f02517dea26097f58?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Chris DuBois + :target: https://github.com/doobwa + +---- + +`GLPK `_ +__________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/80502de63c1b21d8f3ba663d72ba5be2?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Carlo Baldassi + :target: https://github.com/carlobaldassi + + Current Version: ``0.0.0`` + + GLPK wrapper module for Julia + + Maintainer: `Carlo Baldassi `_ + + Dependencies:: + + BinDeps Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/80502de63c1b21d8f3ba663d72ba5be2?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Carlo Baldassi + :target: https://github.com/carlobaldassi + + .. image:: https://secure.gravatar.com/avatar/002ccfd8ee9e135f0dfb5650c292052d?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Elliot Saba + :target: https://github.com/staticfloat + +---- + +`GLUT `_ +______________________________________________ + + .. image:: https://secure.gravatar.com/avatar/37cebf4f44a1dbf71ee94aaea166ef00?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Robert Ennis + :target: https://github.com/rennis250 + + Current Version: ``0.0.0`` + + Julia interface to GLUT + + Maintainer: `Robert Ennis `_ + + Dependencies:: + + GetC Any Version + OpenGL Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/37cebf4f44a1dbf71ee94aaea166ef00?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Robert Ennis + :target: https://github.com/rennis250 + +---- + +`GSL `_ +_________________________________________ + + .. image:: https://secure.gravatar.com/avatar/6cba33e8e7c69fa63f6ad386b7a958c5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Jiahao Chen + :target: https://github.com/jiahao + + Current Version: ``0.0.0`` + + Julia interface to the GNU Scientific Library (GSL) + + Maintainer: `Jiahao Chen `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/6cba33e8e7c69fa63f6ad386b7a958c5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Jiahao Chen + :target: https://github.com/jiahao + +---- + +`GZip `_ +_____________________________________________ + + .. image:: https://secure.gravatar.com/avatar/42c8c4ab92de3390bcd2f637ef6ca16c?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Kevin Squire + :target: https://github.com/kmsquire + + Current Version: ``0.0.0`` + + A Julia interface for gzip functions in zlib + + Maintainer: `Kevin Squire `_ + + Documentation: ``_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/42c8c4ab92de3390bcd2f637ef6ca16c?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Kevin Squire + :target: https://github.com/kmsquire + +---- + +`Gadfly `_ +________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/fd97b03d16e1aa4c404391216d81c1d5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Daniel Jones + :target: https://github.com/dcjones + + Current Version: ``0.0.0`` + + Crafty statistical graphics for Julia. + + Maintainer: `Daniel Jones `_ + + Documentation: ``_ + + Dependencies:: + + ArgParse Any Version + Codecs Any Version + Compose Any Version + DataFrames Any Version + Distributions Any Version + Iterators Any Version + JSON Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/fd97b03d16e1aa4c404391216d81c1d5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Daniel Jones + :target: https://github.com/dcjones + + .. image:: https://secure.gravatar.com/avatar/37cebf4f44a1dbf71ee94aaea166ef00?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Robert Ennis + :target: https://github.com/rennis250 + + .. image:: https://secure.gravatar.com/avatar/449044e4f0ed377b21409488cddafc45?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Blake Johnson + :target: https://github.com/blakejohnson + + .. image:: https://secure.gravatar.com/avatar/b1f06f732d86e562563db728b2875eb2?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Jason Merrill + :target: https://github.com/jwmerrill + + .. image:: https://secure.gravatar.com/avatar/f5c61e85dfa465686adc24e0bffba42a?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Avik Sengupta + :target: https://github.com/aviks + + .. image:: https://secure.gravatar.com/avatar/a27d23ce4c080f3307cc6507f6fdfe87?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: dmbates + :target: https://github.com/dmbates + + .. image:: https://secure.gravatar.com/avatar/25ce2ab2f5e673e46208c1188a39e6ca?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: milktrader + :target: https://github.com/milktrader + + .. image:: https://secure.gravatar.com/avatar/2989a078f4caff6fb86fa30e59bd9aa9?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Tim Holy + :target: https://github.com/timholy + +---- + +`Gaston `_ +_____________________________________________ + + .. image:: https://secure.gravatar.com/avatar/ec325e7c3c35e354f2ea5ead5b0ec745?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: mbaz + :target: https://github.com/mbaz + + Current Version: ``0.0.0`` + + A julia front-end for gnuplot. + + Maintainer: `mbaz `_ + + Dependencies:: + + julia [v"0.1.0-", v"0.2.0-"] + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/ec325e7c3c35e354f2ea5ead5b0ec745?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: mbaz + :target: https://github.com/mbaz + + .. image:: https://secure.gravatar.com/avatar/8af4d5971a2308b86a94f58fb98129c5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Jameson Nash + :target: https://github.com/vtjnash + +---- + +`GetC `_ +______________________________________________ + + .. image:: https://secure.gravatar.com/avatar/37cebf4f44a1dbf71ee94aaea166ef00?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Robert Ennis + :target: https://github.com/rennis250 + + Current Version: ``0.0.0`` + + Minimal implementation of Jasper's Julia FFI + + Maintainer: `Robert Ennis `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/37cebf4f44a1dbf71ee94aaea166ef00?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Robert Ennis + :target: https://github.com/rennis250 + +---- + +`GoogleCharts `_ +_____________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/8f514187144b1b19b0205fce41284d32?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: john verzani + :target: https://github.com/jverzani + + Current Version: ``0.0.0`` + + Julia interface to Google Chart Tools + + Maintainer: `john verzani `_ + + Dependencies:: + + Calendar Any Version + DataFrames Any Version + JSON Any Version + Mustache Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/8f514187144b1b19b0205fce41284d32?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: john verzani + :target: https://github.com/jverzani + +---- + +`Graphs `_ +_______________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: John Myles White + :target: https://github.com/johnmyleswhite + + Current Version: ``0.0.0`` + + Working with graphs in Julia + + Maintainer: `John Myles White `_ + + Dependencies:: + + DataFrames Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: John Myles White + :target: https://github.com/johnmyleswhite + + .. image:: https://secure.gravatar.com/avatar/91fa687725c763561519614037bb31a9?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Andrei Formiga + :target: https://github.com/tautologico + +---- + +`Grid `_ +____________________________________________ + + .. image:: https://secure.gravatar.com/avatar/2989a078f4caff6fb86fa30e59bd9aa9?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Tim Holy + :target: https://github.com/timholy + + Current Version: ``0.2.0`` + + Interpolation and related operations on grids + + Maintainer: `Tim Holy `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/2989a078f4caff6fb86fa30e59bd9aa9?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Tim Holy + :target: https://github.com/timholy + +---- + +`Gtk `_ +__________________________________________ + + .. image:: https://secure.gravatar.com/avatar/8af4d5971a2308b86a94f58fb98129c5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Jameson Nash + :target: https://github.com/vtjnash + + Current Version: ``0.0.0`` + + Julia interface to Gtk windowing toolkit. + + Maintainer: `Jameson Nash `_ + + Dependencies:: + + Cairo Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/8af4d5971a2308b86a94f58fb98129c5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Jameson Nash + :target: https://github.com/vtjnash + +---- + +`Gurobi `_ +_________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/3db090e101b916d9256d0d3e043db71d?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Dahua Lin + :target: https://github.com/lindahua + + Current Version: ``0.0.0`` + + Julia Port of Gurobi Optimizer + + Maintainer: `Dahua Lin `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/3db090e101b916d9256d0d3e043db71d?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Dahua Lin + :target: https://github.com/lindahua + +---- + +`HDF5 `_ +____________________________________________ + + .. image:: https://secure.gravatar.com/avatar/2989a078f4caff6fb86fa30e59bd9aa9?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Tim Holy + :target: https://github.com/timholy + + Current Version: ``0.2.0`` + + HDF5 interface for the Julia language + + Maintainer: `Tim Holy `_ + + Dependencies:: + + StrPack Any Version + julia [v"0.2.0-"] + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/2989a078f4caff6fb86fa30e59bd9aa9?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Tim Holy + :target: https://github.com/timholy + + .. image:: https://secure.gravatar.com/avatar/449044e4f0ed377b21409488cddafc45?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Blake Johnson + :target: https://github.com/blakejohnson + + .. image:: https://secure.gravatar.com/avatar/9524ef56c2823a59d54f9226a7ef08ba?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Simon Kornblith + :target: https://github.com/simonster + +---- + +`HDFS `_ +______________________________________________ + + .. image:: https://secure.gravatar.com/avatar/d57c99557ab0dc0fa44b4c84447d0f15?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-org-420.png + :height: 80px + :width: 80px + :align: right + :alt: The Julia Language + :target: https://github.com/JuliaLang + + Current Version: ``0.0.0`` + + A Julia to the Hadoop and Map-R filesystems + + Maintainer: `The Julia Language `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/55e277a715ee2afd0d29c309174eca02?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Viral B. Shah + :target: https://github.com/ViralBShah + +---- + +`HTTP `_ +_________________________________________ + + .. image:: https://secure.gravatar.com/avatar/d9c8c5a29b60871d14846a382d50626a?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Dirk Gadsden + :target: https://github.com/dirk + + Current Version: ``0.0.2`` + + HTTP library (server, client, parser) for the Julia language + + Maintainer: `Dirk Gadsden `_ + + Dependencies:: + + Calendar Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/d9c8c5a29b60871d14846a382d50626a?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Dirk Gadsden + :target: https://github.com/dirk + +---- + +`Hadamard `_ +_____________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/9563cfcf21df990e570df1dd019bce16?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Steven G. Johnson + :target: https://github.com/stevengj + + Current Version: ``0.0.0`` + + Fast Walsh-Hadamard transforms for the Julia language + + Maintainer: `Steven G. Johnson `_ + + Dependencies:: + + None + + Contributors: + +---- + +`HypothesisTests `_ +____________________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/9524ef56c2823a59d54f9226a7ef08ba?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Simon Kornblith + :target: https://github.com/simonster + + Current Version: ``0.2.0`` + + T-tests, Wilcoxon rank sum (Mann-Whitney U), signed rank, and circular statistics in Julia + + Maintainer: `Simon Kornblith `_ + + Dependencies:: + + Distributions Any Version + Rmath Any Version + julia [v"0.2.0-"] + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/9524ef56c2823a59d54f9226a7ef08ba?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Simon Kornblith + :target: https://github.com/simonster + +---- + +`ICU `_ +________________________________________ + + .. image:: https://secure.gravatar.com/avatar/1b65c4698da5f30310e14aaee8f3f24e?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Mike Nolta + :target: https://github.com/nolta + + Current Version: ``0.0.0`` + + Julia wrapper for the International Components for Unicode (ICU) library + + Maintainer: `Mike Nolta `_ + + Dependencies:: + + UTF16 Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/1b65c4698da5f30310e14aaee8f3f24e?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Mike Nolta + :target: https://github.com/nolta + + .. image:: https://secure.gravatar.com/avatar/1af2db0b26142fd0c7ab082f3d445f73?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Ian Fiske + :target: https://github.com/ianfiske + + .. image:: https://secure.gravatar.com/avatar/f5c61e85dfa465686adc24e0bffba42a?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Avik Sengupta + :target: https://github.com/aviks + + .. image:: https://secure.gravatar.com/avatar/21aeae1f260365557523718bc19640f7?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Stefan Karpinski + :target: https://github.com/StefanKarpinski + +---- + +`Images `_ +________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/2989a078f4caff6fb86fa30e59bd9aa9?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Tim Holy + :target: https://github.com/timholy + + Current Version: ``0.0.0`` + + An image library for Julia + + Maintainer: `Tim Holy `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/2989a078f4caff6fb86fa30e59bd9aa9?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Tim Holy + :target: https://github.com/timholy + + .. image:: https://secure.gravatar.com/avatar/d04d5b6e71776eb13d195ba7cc94b995?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Waldir Pimenta + :target: https://github.com/waldir + + .. image:: https://secure.gravatar.com/avatar/b1f06f732d86e562563db728b2875eb2?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Jason Merrill + :target: https://github.com/jwmerrill + + .. image:: https://secure.gravatar.com/avatar/afb7f86706c41da610daf216d60e59b9?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Ron Rock + :target: https://github.com/rsrock + +---- + +`ImmutableArrays `_ +____________________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/9553bee3aa95ce13310db4f5f70acc62?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Tracy Wadleigh + :target: https://github.com/twadleigh + + Current Version: ``0.0.0`` + + Statically-sized immutable vectors and matrices. + + Maintainer: `Tracy Wadleigh `_ + + Dependencies:: + + julia [v"0.2.0-"] + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/9553bee3aa95ce13310db4f5f70acc62?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Tracy Wadleigh + :target: https://github.com/twadleigh + + .. image:: https://secure.gravatar.com/avatar/805857de807ffc1b543e807f727d05c6?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Jay Weisskopf + :target: https://github.com/jayschwa + + .. image:: https://secure.gravatar.com/avatar/cd90bb9515507b0f998f7e5dbccbd238?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Olli Wilkman + :target: https://github.com/dronir + +---- + +`IniFile `_ +____________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/d57c99557ab0dc0fa44b4c84447d0f15?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-org-420.png + :height: 80px + :width: 80px + :align: right + :alt: The Julia Language + :target: https://github.com/JuliaLang + + Current Version: ``0.0.0`` + + Reading and writing Windows-style INI files (writing not yet implemented). + + Maintainer: `The Julia Language `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/62df30beab9c2a6f3fe3f86995e94387?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: David de Laat + :target: https://github.com/daviddelaat + + .. image:: https://secure.gravatar.com/avatar/21aeae1f260365557523718bc19640f7?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Stefan Karpinski + :target: https://github.com/StefanKarpinski + + .. image:: https://secure.gravatar.com/avatar/b4b8db23d8096b722483a57d21b7d65d?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Jeff Bezanson + :target: https://github.com/JeffBezanson + + .. image:: https://secure.gravatar.com/avatar/1b65c4698da5f30310e14aaee8f3f24e?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Mike Nolta + :target: https://github.com/nolta + +---- + +`Iterators `_ +________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/d57c99557ab0dc0fa44b4c84447d0f15?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-org-420.png + :height: 80px + :width: 80px + :align: right + :alt: The Julia Language + :target: https://github.com/JuliaLang + + Current Version: ``0.0.0`` + + Common functional iterator patterns. + + Maintainer: `The Julia Language `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/21aeae1f260365557523718bc19640f7?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Stefan Karpinski + :target: https://github.com/StefanKarpinski + + .. image:: https://secure.gravatar.com/avatar/fd97b03d16e1aa4c404391216d81c1d5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Daniel Jones + :target: https://github.com/dcjones + + .. image:: https://secure.gravatar.com/avatar/b4b8db23d8096b722483a57d21b7d65d?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Jeff Bezanson + :target: https://github.com/JeffBezanson + + .. image:: https://secure.gravatar.com/avatar/1b65c4698da5f30310e14aaee8f3f24e?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Mike Nolta + :target: https://github.com/nolta + +---- + +`Ito `_ +________________________________________ + + .. image:: https://secure.gravatar.com/avatar/f5c61e85dfa465686adc24e0bffba42a?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Avik Sengupta + :target: https://github.com/aviks + + Current Version: ``0.0.0`` + + A Julia package for quantitative finance + + Maintainer: `Avik Sengupta `_ + + Documentation: ``_ + + Dependencies:: + + Calendar Any Version + Distributions Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/f5c61e85dfa465686adc24e0bffba42a?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Avik Sengupta + :target: https://github.com/aviks + + .. image:: https://secure.gravatar.com/avatar/21aeae1f260365557523718bc19640f7?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Stefan Karpinski + :target: https://github.com/StefanKarpinski + +---- + +`JSON `_ +__________________________________________ + + .. image:: https://secure.gravatar.com/avatar/f5c61e85dfa465686adc24e0bffba42a?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Avik Sengupta + :target: https://github.com/aviks + + Current Version: ``0.0.0`` + + JSON parsing and printing + + Maintainer: `Avik Sengupta `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/f5c61e85dfa465686adc24e0bffba42a?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Avik Sengupta + :target: https://github.com/aviks + + .. image:: https://secure.gravatar.com/avatar/21aeae1f260365557523718bc19640f7?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Stefan Karpinski + :target: https://github.com/StefanKarpinski + + .. image:: https://secure.gravatar.com/avatar/62df30beab9c2a6f3fe3f86995e94387?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: David de Laat + :target: https://github.com/daviddelaat + + .. image:: https://secure.gravatar.com/avatar/1b65c4698da5f30310e14aaee8f3f24e?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Mike Nolta + :target: https://github.com/nolta + + .. image:: https://secure.gravatar.com/avatar/dfc3b0fbb59c9444153823fd35dbd13b?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Westley Argentum Hennigh + :target: https://github.com/WestleyArgentum + + .. image:: https://secure.gravatar.com/avatar/b4b8db23d8096b722483a57d21b7d65d?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Jeff Bezanson + :target: https://github.com/JeffBezanson + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: John Myles White + :target: https://github.com/johnmyleswhite + + .. image:: https://secure.gravatar.com/avatar/fa183b064e6ddfafab783d3de300c72a?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: S Wade + :target: https://github.com/swadey + + .. image:: https://secure.gravatar.com/avatar/fd97b03d16e1aa4c404391216d81c1d5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Daniel Jones + :target: https://github.com/dcjones + +---- + +`JudyDicts `_ +_______________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/eea0b193dae8ac47946202ee404a6d7a?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Tanmay Mohapatra + :target: https://github.com/tanmaykm + + Current Version: ``0.0.0`` + + Judy Array for Julia + + Maintainer: `Tanmay Mohapatra `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/eea0b193dae8ac47946202ee404a6d7a?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Tanmay Mohapatra + :target: https://github.com/tanmaykm + +---- + +`JuliaWebRepl `_ +____________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/8af4d5971a2308b86a94f58fb98129c5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Jameson Nash + :target: https://github.com/vtjnash + + Current Version: ``0.0.0`` + + + + Maintainer: `Jameson Nash `_ + + Dependencies:: + + BinDeps Any Version + julia [v"0.2.0-"] + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/8af4d5971a2308b86a94f58fb98129c5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Jameson Nash + :target: https://github.com/vtjnash + +---- + +`Jyacas `_ +_________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/8f514187144b1b19b0205fce41284d32?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: john verzani + :target: https://github.com/jverzani + + Current Version: ``0.0.0`` + + Interface to use yacas from julia + + Maintainer: `john verzani `_ + + Dependencies:: + + JSON Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/8f514187144b1b19b0205fce41284d32?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: john verzani + :target: https://github.com/jverzani + +---- + +`KLDivergence `_ +___________________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: John Myles White + :target: https://github.com/johnmyleswhite + + Current Version: ``0.0.0`` + + KL-divergence estimation in Julia + + Maintainer: `John Myles White `_ + + Dependencies:: + + Distributions Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: John Myles White + :target: https://github.com/johnmyleswhite + +---- + +`LM `_ +___________________________________________ + + .. image:: https://secure.gravatar.com/avatar/d41d8cd98f00b204e9800998ecf8427e?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-org-420.png + :height: 80px + :width: 80px + :align: right + :alt: JuliaStats + :target: https://github.com/JuliaStats + + Current Version: ``0.0.0`` + + Linear models in Julia + + Maintainer: `JuliaStats `_ + + Dependencies:: + + DataFrames Any Version + Distributions Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: John Myles White + :target: https://github.com/johnmyleswhite + + .. image:: https://secure.gravatar.com/avatar/02abdd20ef026f24d96035a407912df0?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Andreas Noack Jensen + :target: https://github.com/andreasnoackjensen + +---- + +`Languages `_ +_____________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: John Myles White + :target: https://github.com/johnmyleswhite + + Current Version: ``0.0.0`` + + A package for working with human languages + + Maintainer: `John Myles White `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: John Myles White + :target: https://github.com/johnmyleswhite + +---- + +`LazySequences `_ +______________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/fd97b03d16e1aa4c404391216d81c1d5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Daniel Jones + :target: https://github.com/dcjones + + Current Version: ``0.0.0`` + + Lazy sequences. + + Maintainer: `Daniel Jones `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/fd97b03d16e1aa4c404391216d81c1d5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Daniel Jones + :target: https://github.com/dcjones + +---- + +`LinProgGLPK `_ +________________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/80502de63c1b21d8f3ba663d72ba5be2?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Carlo Baldassi + :target: https://github.com/carlobaldassi + + Current Version: ``0.0.0`` + + High-level linear programming functionality for Julia via GLPK library (transitional package) + + Maintainer: `Carlo Baldassi `_ + + Dependencies:: + + GLPK Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/80502de63c1b21d8f3ba663d72ba5be2?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Carlo Baldassi + :target: https://github.com/carlobaldassi + +---- + +`Loss `_ +___________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: John Myles White + :target: https://github.com/johnmyleswhite + + Current Version: ``0.0.0`` + + Loss functions + + Maintainer: `John Myles White `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: John Myles White + :target: https://github.com/johnmyleswhite + +---- + +`MAT `_ +____________________________________________ + + .. image:: https://secure.gravatar.com/avatar/9524ef56c2823a59d54f9226a7ef08ba?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Simon Kornblith + :target: https://github.com/simonster + + Current Version: ``0.2.0`` + + Julia module for reading MATLAB files + + Maintainer: `Simon Kornblith `_ + + Dependencies:: + + HDF5 Any Version + julia [v"0.2.0-"] + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/9524ef56c2823a59d54f9226a7ef08ba?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Simon Kornblith + :target: https://github.com/simonster + + .. image:: https://secure.gravatar.com/avatar/2989a078f4caff6fb86fa30e59bd9aa9?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Tim Holy + :target: https://github.com/timholy + + .. image:: https://secure.gravatar.com/avatar/317e44562dcf11f5164d0a4936696fbc?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: rened + :target: https://github.com/rened + + .. image:: https://secure.gravatar.com/avatar/d5eaa24d3d504aebc34d72ed352c344e?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Geoffrey K. Adams + :target: https://github.com/biogeo + +---- + +`MATLAB `_ +_________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/3db090e101b916d9256d0d3e043db71d?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Dahua Lin + :target: https://github.com/lindahua + + Current Version: ``0.0.0`` + + Calling MATLAB in Julia through MATLAB Engine + + Maintainer: `Dahua Lin `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/3db090e101b916d9256d0d3e043db71d?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Dahua Lin + :target: https://github.com/lindahua + +---- + +`MCMC `_ +___________________________________________ + + .. image:: https://secure.gravatar.com/avatar/1a4672a0ae94c24f02517dea26097f58?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Chris DuBois + :target: https://github.com/doobwa + + Current Version: ``0.0.0`` + + MCMC tools for Julia + + Maintainer: `Chris DuBois `_ + + Dependencies:: + + Options Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/1a4672a0ae94c24f02517dea26097f58?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Chris DuBois + :target: https://github.com/doobwa + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: John Myles White + :target: https://github.com/johnmyleswhite + + .. image:: https://secure.gravatar.com/avatar/5c06e9faa0d7bd205f81d10e825d7e4a?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: nfoti + :target: https://github.com/nfoti + +---- + +`MLBase `_ +_________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/3db090e101b916d9256d0d3e043db71d?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Dahua Lin + :target: https://github.com/lindahua + + Current Version: ``0.0.0`` + + A set of functions to support the development of machine learning algorithms + + Maintainer: `Dahua Lin `_ + + Dependencies:: + + Devectorize Any Version + Distance Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/3db090e101b916d9256d0d3e043db71d?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Dahua Lin + :target: https://github.com/lindahua + +---- + +`MarketTechnicals `_ +_______________________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/25ce2ab2f5e673e46208c1188a39e6ca?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: milktrader + :target: https://github.com/milktrader + + Current Version: ``0.0.0`` + + Technical analysis of financial time series in Julia + + Maintainer: `milktrader `_ + + Dependencies:: + + Calendar Any Version + DataFrames Any Version + Stats Any Version + TimeSeries Any Version + UTF16 Any Version + julia [v"0.1.0-", v"0.2.0-"] + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/25ce2ab2f5e673e46208c1188a39e6ca?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: milktrader + :target: https://github.com/milktrader + +---- + +`MathProg `_ +___________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/cc283e3bd2784ad33dfd55afcfef4877?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Iain Dunning + :target: https://github.com/IainNZ + + Current Version: ``0.0.0`` + + Modelling language for Linear, Integer, and Quadratic Programming + + Maintainer: `Iain Dunning `_ + + Dependencies:: + + Clp Any Version + CoinMP Any Version + julia [v"0.2.0-"] + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/cc283e3bd2784ad33dfd55afcfef4877?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Iain Dunning + :target: https://github.com/IainNZ + + .. image:: https://secure.gravatar.com/avatar/b0cf54b8431443687735cb486599ea9c?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Miles Lubin + :target: https://github.com/mlubin + +---- + +`MathProgBase `_ +___________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/b0cf54b8431443687735cb486599ea9c?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Miles Lubin + :target: https://github.com/mlubin + + Current Version: ``0.0.0`` + + Provides standard interface to linear programming solvers, including linprog function. + + Maintainer: `Miles Lubin `_ + + Dependencies:: + + julia [v"0.1.0-"] + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/b0cf54b8431443687735cb486599ea9c?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Miles Lubin + :target: https://github.com/mlubin + +---- + +`Meshes `_ +__________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/9553bee3aa95ce13310db4f5f70acc62?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Tracy Wadleigh + :target: https://github.com/twadleigh + + Current Version: ``0.0.0`` + + Generation and manipulation of triangular meshes. + + Maintainer: `Tracy Wadleigh `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/9553bee3aa95ce13310db4f5f70acc62?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Tracy Wadleigh + :target: https://github.com/twadleigh + + .. image:: https://secure.gravatar.com/avatar/9c8bbd5a306197b461704991872a05b0?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Michel Kuhlmann + :target: https://github.com/michelk + +---- + +`MixedModels `_ +__________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/a27d23ce4c080f3307cc6507f6fdfe87?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: dmbates + :target: https://github.com/dmbates + + Current Version: ``0.0.0`` + + A Julia package for fitting (statistical) mixed-effects models + + Maintainer: `dmbates `_ + + Dependencies:: + + Distributions Any Version + NLopt Any Version + julia [v"0.2.0-"] + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/a27d23ce4c080f3307cc6507f6fdfe87?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: dmbates + :target: https://github.com/dmbates + +---- + +`Monads `_ +____________________________________________ + + .. image:: https://secure.gravatar.com/avatar/16d8443194c380ca93a77fb8530a5aee?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Patrick O'Leary + :target: https://github.com/pao + + Current Version: ``0.0.0`` + + Monadic expressions and sequences for Julia + + Maintainer: `Patrick O'Leary `_ + + Documentation: ``_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/16d8443194c380ca93a77fb8530a5aee?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Patrick O'Leary + :target: https://github.com/pao + +---- + +`Mongo `_ +____________________________________________ + + .. image:: https://secure.gravatar.com/avatar/eabc077018e56904597d150369b4a803?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Brian Smith + :target: https://github.com/Lytol + + Current Version: ``0.0.0`` + + Mongo bindings for the Julia programming language + + Maintainer: `Brian Smith `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/eabc077018e56904597d150369b4a803?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Brian Smith + :target: https://github.com/Lytol + +---- + +`Mongrel2 `_ +__________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/f5c61e85dfa465686adc24e0bffba42a?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Avik Sengupta + :target: https://github.com/aviks + + Current Version: ``0.0.0`` + + Mongrel2 handlers in Julia + + Maintainer: `Avik Sengupta `_ + + Dependencies:: + + JSON Any Version + ZMQ Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/f5c61e85dfa465686adc24e0bffba42a?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Avik Sengupta + :target: https://github.com/aviks + + .. image:: https://secure.gravatar.com/avatar/baff1969663ebce1d743a43a2bbaa00e?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Nathan Wienert + :target: https://github.com/natew + + .. image:: https://secure.gravatar.com/avatar/72ee26065724239b61be271722b682dd?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Nick Collins + :target: https://github.com/ncollins + +---- + +`Mustache `_ +_____________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/8f514187144b1b19b0205fce41284d32?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: john verzani + :target: https://github.com/jverzani + + Current Version: ``0.0.0`` + + Port of mustache.js to julia + + Maintainer: `john verzani `_ + + Dependencies:: + + DataFrames Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/8f514187144b1b19b0205fce41284d32?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: john verzani + :target: https://github.com/jverzani + + .. image:: https://secure.gravatar.com/avatar/72ee26065724239b61be271722b682dd?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Nick Collins + :target: https://github.com/ncollins + + .. image:: https://secure.gravatar.com/avatar/f5c61e85dfa465686adc24e0bffba42a?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Avik Sengupta + :target: https://github.com/aviks + + .. image:: https://secure.gravatar.com/avatar/d9c8c5a29b60871d14846a382d50626a?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Dirk Gadsden + :target: https://github.com/dirk + +---- + +`NHST `_ +___________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: John Myles White + :target: https://github.com/johnmyleswhite + + Current Version: ``0.0.0`` + + Null hypothesis significance tests + + Maintainer: `John Myles White `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: John Myles White + :target: https://github.com/johnmyleswhite + +---- + +`NLopt `_ +_______________________________________________ + + .. image:: https://secure.gravatar.com/avatar/9563cfcf21df990e570df1dd019bce16?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Steven G. Johnson + :target: https://github.com/stevengj + + Current Version: ``0.0.0`` + + Package to call the NLopt nonlinear-optimization library from the Julia language + + Maintainer: `Steven G. Johnson `_ + + Dependencies:: + + julia [v"0.2.0-"] + + Contributors: + +---- + +`Named `_ +______________________________________________ + + .. image:: https://secure.gravatar.com/avatar/9f1a68b9e623be5da422b44e733fa8bc?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Harlan Harris + :target: https://github.com/HarlanH + + Current Version: ``0.0.0`` + + Julia named index and named vector types + + Maintainer: `Harlan Harris `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/9f1a68b9e623be5da422b44e733fa8bc?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Harlan Harris + :target: https://github.com/HarlanH + +---- + +`ODBC `_ +______________________________________________ + + .. image:: https://secure.gravatar.com/avatar/d788bf7fd037ebef5798d8881c5faa2f?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Jacob Quinn + :target: https://github.com/karbarcca + + Current Version: ``0.0.0`` + + A low-level ODBC interface for the Julia programming language + + Maintainer: `Jacob Quinn `_ + + Dependencies:: + + DataFrames Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/d788bf7fd037ebef5798d8881c5faa2f?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Jacob Quinn + :target: https://github.com/karbarcca + + .. image:: https://secure.gravatar.com/avatar/42c8c4ab92de3390bcd2f637ef6ca16c?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Kevin Squire + :target: https://github.com/kmsquire + +---- + +`ODE `_ +__________________________________________ + + .. image:: https://secure.gravatar.com/avatar/8af4d5971a2308b86a94f58fb98129c5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Jameson Nash + :target: https://github.com/vtjnash + + Current Version: ``0.0.0`` + + Assorted basic Ordinary Differential Equation solvers + + Maintainer: `Jameson Nash `_ + + Dependencies:: + + Polynomial Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/8af4d5971a2308b86a94f58fb98129c5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Jameson Nash + :target: https://github.com/vtjnash + +---- + +`OpenGL `_ +__________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/37cebf4f44a1dbf71ee94aaea166ef00?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Robert Ennis + :target: https://github.com/rennis250 + + Current Version: ``0.0.0`` + + Julia interface to OpenGL + + Maintainer: `Robert Ennis `_ + + Dependencies:: + + GetC Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/37cebf4f44a1dbf71ee94aaea166ef00?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Robert Ennis + :target: https://github.com/rennis250 + +---- + +`OpenSSL `_ +_______________________________________________ + + .. image:: https://secure.gravatar.com/avatar/d9c8c5a29b60871d14846a382d50626a?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Dirk Gadsden + :target: https://github.com/dirk + + Current Version: ``0.0.0`` + + WIP OpenSSL bindings for Julia + + Maintainer: `Dirk Gadsden `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/d9c8c5a29b60871d14846a382d50626a?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Dirk Gadsden + :target: https://github.com/dirk + +---- + +`Optim `_ +_____________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: John Myles White + :target: https://github.com/johnmyleswhite + + Current Version: ``0.0.0`` + + Optimization functions for Julia + + Maintainer: `John Myles White `_ + + Documentation: ``_ + + Dependencies:: + + Calculus Any Version + Distributions Any Version + Options Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: John Myles White + :target: https://github.com/johnmyleswhite + + .. image:: https://secure.gravatar.com/avatar/2989a078f4caff6fb86fa30e59bd9aa9?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Tim Holy + :target: https://github.com/timholy + + .. image:: https://secure.gravatar.com/avatar/449044e4f0ed377b21409488cddafc45?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Blake Johnson + :target: https://github.com/blakejohnson + + .. image:: https://secure.gravatar.com/avatar/02abdd20ef026f24d96035a407912df0?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Andreas Noack Jensen + :target: https://github.com/andreasnoackjensen + +---- + +`Options `_ +____________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/d57c99557ab0dc0fa44b4c84447d0f15?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-org-420.png + :height: 80px + :width: 80px + :align: right + :alt: The Julia Language + :target: https://github.com/JuliaLang + + Current Version: ``0.2.0`` + + A framework for providing optional arguments to functions. + + Maintainer: `The Julia Language `_ + + Dependencies:: + + julia [v"0.2.0-"] + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/2989a078f4caff6fb86fa30e59bd9aa9?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Tim Holy + :target: https://github.com/timholy + + .. image:: https://secure.gravatar.com/avatar/80502de63c1b21d8f3ba663d72ba5be2?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Carlo Baldassi + :target: https://github.com/carlobaldassi + + .. image:: https://secure.gravatar.com/avatar/21aeae1f260365557523718bc19640f7?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Stefan Karpinski + :target: https://github.com/StefanKarpinski + + .. image:: https://secure.gravatar.com/avatar/9f1a68b9e623be5da422b44e733fa8bc?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Harlan Harris + :target: https://github.com/HarlanH + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: John Myles White + :target: https://github.com/johnmyleswhite + +---- + +`PLX `_ +____________________________________________ + + .. image:: https://secure.gravatar.com/avatar/9524ef56c2823a59d54f9226a7ef08ba?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Simon Kornblith + :target: https://github.com/simonster + + Current Version: ``0.0.0`` + + Julia module for reading Plexon PLX files + + Maintainer: `Simon Kornblith `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/9524ef56c2823a59d54f9226a7ef08ba?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Simon Kornblith + :target: https://github.com/simonster + +---- + +`PatternDispatch `_ +_________________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/8d3d3934c39b52f48c35a0cc536edae7?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: toivoh + :target: https://github.com/toivoh + + Current Version: ``0.0.0`` + + Method dispatch based on pattern matching for Julia + + Maintainer: `toivoh `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/8d3d3934c39b52f48c35a0cc536edae7?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: toivoh + :target: https://github.com/toivoh + + .. image:: https://secure.gravatar.com/avatar/317e44562dcf11f5164d0a4936696fbc?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: rened + :target: https://github.com/rened + +---- + +`Polynomial `_ +________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/8af4d5971a2308b86a94f58fb98129c5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Jameson Nash + :target: https://github.com/vtjnash + + Current Version: ``0.0.0`` + + Polynomial manipulations + + Maintainer: `Jameson Nash `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/8af4d5971a2308b86a94f58fb98129c5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Jameson Nash + :target: https://github.com/vtjnash + +---- + +`Profile `_ +__________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/2989a078f4caff6fb86fa30e59bd9aa9?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Tim Holy + :target: https://github.com/timholy + + Current Version: ``0.2.0`` + + Profilers for Julia + + Maintainer: `Tim Holy `_ + + Dependencies:: + + julia [v"0.2.0-"] + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/2989a078f4caff6fb86fa30e59bd9aa9?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Tim Holy + :target: https://github.com/timholy + + .. image:: https://secure.gravatar.com/avatar/317e44562dcf11f5164d0a4936696fbc?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: rened + :target: https://github.com/rened + + .. image:: https://secure.gravatar.com/avatar/449044e4f0ed377b21409488cddafc45?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Blake Johnson + :target: https://github.com/blakejohnson + +---- + +`ProjectTemplate `_ +_________________________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: John Myles White + :target: https://github.com/johnmyleswhite + + Current Version: ``0.0.0`` + + ProjectTemplate for Julia + + Maintainer: `John Myles White `_ + + Dependencies:: + + DataFrames Any Version + JSON Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: John Myles White + :target: https://github.com/johnmyleswhite + +---- + +`PyCall `_ +_________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/9563cfcf21df990e570df1dd019bce16?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Steven G. Johnson + :target: https://github.com/stevengj + + Current Version: ``0.0.0`` + + Package to call Python functions from the Julia language + + Maintainer: `Steven G. Johnson `_ + + Dependencies:: + + julia [v"0.2.0-"] + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/9563cfcf21df990e570df1dd019bce16?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Steven G. Johnson + :target: https://github.com/stevengj + + .. image:: https://secure.gravatar.com/avatar/fa3b781987ef53c4d3b8397f2239e519?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Diego Javier Zea + :target: https://github.com/diegozea + + .. image:: https://secure.gravatar.com/avatar/8af4d5971a2308b86a94f58fb98129c5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Jameson Nash + :target: https://github.com/vtjnash + +---- + +`QuickCheck `_ +____________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/16d8443194c380ca93a77fb8530a5aee?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Patrick O'Leary + :target: https://github.com/pao + + Current Version: ``0.0.0`` + + QuickCheck specification-based testing for Julia + + Maintainer: `Patrick O'Leary `_ + + Documentation: ``_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/16d8443194c380ca93a77fb8530a5aee?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Patrick O'Leary + :target: https://github.com/pao + +---- + +`RDatasets `_ +_____________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: John Myles White + :target: https://github.com/johnmyleswhite + + Current Version: ``0.0.0`` + + Julia package for loading many of the data sets available in R + + Maintainer: `John Myles White `_ + + Dependencies:: + + DataFrames Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: John Myles White + :target: https://github.com/johnmyleswhite + + .. image:: https://secure.gravatar.com/avatar/a27d23ce4c080f3307cc6507f6fdfe87?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: dmbates + :target: https://github.com/dmbates + + .. image:: https://secure.gravatar.com/avatar/62df30beab9c2a6f3fe3f86995e94387?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: David de Laat + :target: https://github.com/daviddelaat + +---- + +`RNGTest `_ +_____________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/02abdd20ef026f24d96035a407912df0?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Andreas Noack Jensen + :target: https://github.com/andreasnoackjensen + + Current Version: ``0.0.0`` + + Code for testing of Julia's random numbers + + Maintainer: `Andreas Noack Jensen `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/02abdd20ef026f24d96035a407912df0?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Andreas Noack Jensen + :target: https://github.com/andreasnoackjensen + + .. image:: https://secure.gravatar.com/avatar/55e277a715ee2afd0d29c309174eca02?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Viral B. Shah + :target: https://github.com/ViralBShah + +---- + +`RandomMatrices `_ +_______________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/6cba33e8e7c69fa63f6ad386b7a958c5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Jiahao Chen + :target: https://github.com/jiahao + + Current Version: ``0.0.0`` + + Random matrices package for Julia + + Maintainer: `Jiahao Chen `_ + + Dependencies:: + + Catalan Any Version + Distributions Any Version + GSL Any Version + ODE Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/6cba33e8e7c69fa63f6ad386b7a958c5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Jiahao Chen + :target: https://github.com/jiahao + + .. image:: https://secure.gravatar.com/avatar/b4035aa7c2e4ecf012eed26a63573f5b?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Alan Edelman + :target: https://github.com/alanedelman + +---- + +`Resampling `_ +_______________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: John Myles White + :target: https://github.com/johnmyleswhite + + Current Version: ``0.0.0`` + + Tools for resampling data in Julia + + Maintainer: `John Myles White `_ + + Dependencies:: + + DataFrames Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: John Myles White + :target: https://github.com/johnmyleswhite + +---- + +`Rif `_ +___________________________________________ + + .. image:: https://secure.gravatar.com/avatar/8e5422a173711c086b685140dbc498fe?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Laurent Gautier + :target: https://github.com/lgautier + + Current Version: ``0.0.0`` + + Julia-to-R interface + + Maintainer: `Laurent Gautier `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/8e5422a173711c086b685140dbc498fe?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Laurent Gautier + :target: https://github.com/lgautier + + .. image:: https://secure.gravatar.com/avatar/4fca794da0cf08804f99048d3c8b39c1?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Check your git settings! + :target: https://github.com/invalid-email-address + +---- + +`Rmath `_ +______________________________________________ + + .. image:: https://secure.gravatar.com/avatar/a27d23ce4c080f3307cc6507f6fdfe87?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: dmbates + :target: https://github.com/dmbates + + Current Version: ``0.0.0`` + + Archive of functions that emulate R's d-p-q-r functions for probability distributions + + Maintainer: `dmbates `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/a27d23ce4c080f3307cc6507f6fdfe87?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: dmbates + :target: https://github.com/dmbates + +---- + +`SDE `_ +___________________________________________ + + .. image:: https://secure.gravatar.com/avatar/b3ce82c50576d090da69fc77bc2ee79f?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: M. Schauer + :target: https://github.com/mschauer + + Current Version: ``0.0.0`` + + Simulation and inference for Ito processes and diffusions. + + Maintainer: `M. Schauer `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/b3ce82c50576d090da69fc77bc2ee79f?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: M. Schauer + :target: https://github.com/mschauer + +---- + +`SDL `_ +____________________________________________ + + .. image:: https://secure.gravatar.com/avatar/37cebf4f44a1dbf71ee94aaea166ef00?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Robert Ennis + :target: https://github.com/rennis250 + + Current Version: ``0.0.0`` + + Julia interface to SDL + + Maintainer: `Robert Ennis `_ + + Dependencies:: + + GetC Any Version + OpenGL Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/37cebf4f44a1dbf71ee94aaea166ef00?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Robert Ennis + :target: https://github.com/rennis250 + +---- + +`SemidefiniteProgramming `_ +______________________________________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/62df30beab9c2a6f3fe3f86995e94387?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: David de Laat + :target: https://github.com/daviddelaat + + Current Version: ``0.0.0`` + + Interface to semidefinite programming libraries. + + Maintainer: `David de Laat `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/62df30beab9c2a6f3fe3f86995e94387?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: David de Laat + :target: https://github.com/daviddelaat + +---- + +`SimJulia `_ +_______________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/d90d902f9f64a30155b8a87441615cc2?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Ben Lauwens + :target: https://github.com/BenLauwens + + Current Version: ``0.0.0`` + + Process oriented simulation library written in Julia + + Maintainer: `Ben Lauwens `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/d90d902f9f64a30155b8a87441615cc2?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Ben Lauwens + :target: https://github.com/BenLauwens + +---- + +`Sims `_ +___________________________________________ + + .. image:: https://secure.gravatar.com/avatar/903acb22f47a901577ee48d3962d5858?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Tom Short + :target: https://github.com/tshort + + Current Version: ``0.0.0`` + + Experiments with non-causal, equation-based modeling in Julia + + Maintainer: `Tom Short `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/903acb22f47a901577ee48d3962d5858?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Tom Short + :target: https://github.com/tshort + +---- + +`Stats `_ +_________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/d41d8cd98f00b204e9800998ecf8427e?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-org-420.png + :height: 80px + :width: 80px + :align: right + :alt: JuliaStats + :target: https://github.com/JuliaStats + + Current Version: ``0.2.0`` + + Basic statistics for Julia + + Maintainer: `JuliaStats `_ + + Dependencies:: + + julia [v"0.2.0-"] + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/02abdd20ef026f24d96035a407912df0?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Andreas Noack Jensen + :target: https://github.com/andreasnoackjensen + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: John Myles White + :target: https://github.com/johnmyleswhite + +---- + +`StrPack `_ +______________________________________________ + + .. image:: https://secure.gravatar.com/avatar/16d8443194c380ca93a77fb8530a5aee?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Patrick O'Leary + :target: https://github.com/pao + + Current Version: ``0.0.0`` + + Swiss Army Knife for encoding and decoding binary streams + + Maintainer: `Patrick O'Leary `_ + + Documentation: ``_ + + Dependencies:: + + julia [v"0.2.0-"] + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/16d8443194c380ca93a77fb8530a5aee?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Patrick O'Leary + :target: https://github.com/pao + + .. image:: https://secure.gravatar.com/avatar/ed9f9395e60acde24eb4bb89fe2154aa?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Keno Fischer + :target: https://github.com/loladiro + + .. image:: https://secure.gravatar.com/avatar/2989a078f4caff6fb86fa30e59bd9aa9?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Tim Holy + :target: https://github.com/timholy + +---- + +`Sundials `_ +___________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/903acb22f47a901577ee48d3962d5858?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Tom Short + :target: https://github.com/tshort + + Current Version: ``0.0.0`` + + Julia interface to Sundials, including a nonlinear solver (KINSOL), ODE's (CVODE), and DAE's (IDA). + + Maintainer: `Tom Short `_ + + Dependencies:: + + julia [v"0.2.0-"] + + Contributors: + +---- + +`SymbolicLP `_ +________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/2989a078f4caff6fb86fa30e59bd9aa9?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Tim Holy + :target: https://github.com/timholy + + Current Version: ``0.0.0`` + + Symbolic linear programming and linear constraints + + Maintainer: `Tim Holy `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/2989a078f4caff6fb86fa30e59bd9aa9?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Tim Holy + :target: https://github.com/timholy + +---- + +`TOML `_ +_________________________________________ + + .. image:: https://secure.gravatar.com/avatar/e38cd950767e62fd3250795bbd208cf6?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: pygy + :target: https://github.com/pygy + + Current Version: ``0.0.0`` + + A TOML parser for Julia. + + Maintainer: `pygy `_ + + Dependencies:: + + Calendar Any Version + JSON Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/e38cd950767e62fd3250795bbd208cf6?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: pygy + :target: https://github.com/pygy + +---- + +`TextAnalysis `_ +___________________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: John Myles White + :target: https://github.com/johnmyleswhite + + Current Version: ``0.0.0`` + + Julia package for text analysis + + Maintainer: `John Myles White `_ + + Dependencies:: + + DataFrames Any Version + Languages Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: John Myles White + :target: https://github.com/johnmyleswhite + +---- + +`TextWrap `_ +__________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/80502de63c1b21d8f3ba663d72ba5be2?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Carlo Baldassi + :target: https://github.com/carlobaldassi + + Current Version: ``0.0.0`` + + Package for wrapping text into paragraphs. + + Maintainer: `Carlo Baldassi `_ + + Dependencies:: + + Options Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/80502de63c1b21d8f3ba663d72ba5be2?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Carlo Baldassi + :target: https://github.com/carlobaldassi + + .. image:: https://secure.gravatar.com/avatar/21aeae1f260365557523718bc19640f7?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Stefan Karpinski + :target: https://github.com/StefanKarpinski + +---- + +`TimeModels `_ +___________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/25ce2ab2f5e673e46208c1188a39e6ca?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: milktrader + :target: https://github.com/milktrader + + Current Version: ``0.0.0`` + + Modeling time series in Julia + + Maintainer: `milktrader `_ + + Dependencies:: + + Calendar Any Version + DataFrames Any Version + Stats Any Version + TimeSeries Any Version + UTF16 Any Version + julia [v"0.1.0-", v"0.2.0-"] + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/25ce2ab2f5e673e46208c1188a39e6ca?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: milktrader + :target: https://github.com/milktrader + + .. image:: https://secure.gravatar.com/avatar/ab31fb941184aaef823ddad0f2179c1f?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: João Daniel + :target: https://github.com/jdanielnd + +---- + +`TimeSeries `_ +___________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/25ce2ab2f5e673e46208c1188a39e6ca?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: milktrader + :target: https://github.com/milktrader + + Current Version: ``0.0.0`` + + Time series toolkit for Julia + + Maintainer: `milktrader `_ + + Dependencies:: + + Calendar Any Version + DataFrames Any Version + Stats Any Version + UTF16 Any Version + julia [v"0.1.0-", v"0.2.0-"] + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/25ce2ab2f5e673e46208c1188a39e6ca?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: milktrader + :target: https://github.com/milktrader + + .. image:: https://secure.gravatar.com/avatar/1af2db0b26142fd0c7ab082f3d445f73?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Ian Fiske + :target: https://github.com/ianfiske + +---- + +`Tk `_ +__________________________________________ + + .. image:: https://secure.gravatar.com/avatar/d57c99557ab0dc0fa44b4c84447d0f15?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-org-420.png + :height: 80px + :width: 80px + :align: right + :alt: The Julia Language + :target: https://github.com/JuliaLang + + Current Version: ``0.0.0`` + + Julia interface to Tk windowing toolkit. + + Maintainer: `The Julia Language `_ + + Dependencies:: + + BinDeps Any Version + Cairo Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/ed9f9395e60acde24eb4bb89fe2154aa?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Keno Fischer + :target: https://github.com/loladiro + + .. image:: https://secure.gravatar.com/avatar/8f514187144b1b19b0205fce41284d32?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: john verzani + :target: https://github.com/jverzani + + .. image:: https://secure.gravatar.com/avatar/b4b8db23d8096b722483a57d21b7d65d?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Jeff Bezanson + :target: https://github.com/JeffBezanson + + .. image:: https://secure.gravatar.com/avatar/1b65c4698da5f30310e14aaee8f3f24e?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Mike Nolta + :target: https://github.com/nolta + + .. image:: https://secure.gravatar.com/avatar/55e277a715ee2afd0d29c309174eca02?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Viral B. Shah + :target: https://github.com/ViralBShah + + .. image:: https://secure.gravatar.com/avatar/21aeae1f260365557523718bc19640f7?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Stefan Karpinski + :target: https://github.com/StefanKarpinski + + .. image:: https://secure.gravatar.com/avatar/2989a078f4caff6fb86fa30e59bd9aa9?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Tim Holy + :target: https://github.com/timholy + + .. image:: https://secure.gravatar.com/avatar/449044e4f0ed377b21409488cddafc45?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Blake Johnson + :target: https://github.com/blakejohnson + +---- + +`TkExtras `_ +_____________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/8f514187144b1b19b0205fce41284d32?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: john verzani + :target: https://github.com/jverzani + + Current Version: ``0.0.0`` + + Additions to the Tk.jl pacakge + + Maintainer: `john verzani `_ + + Dependencies:: + + Tk Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/8f514187144b1b19b0205fce41284d32?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: john verzani + :target: https://github.com/jverzani + +---- + +`TopicModels `_ +___________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/34bbe1993f0b1e918539da9a832f8064?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Jonathan Chang + :target: https://github.com/slycoder + + Current Version: ``0.0.0`` + + TopicModels for Julia + + Maintainer: `Jonathan Chang `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/34bbe1993f0b1e918539da9a832f8064?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Jonathan Chang + :target: https://github.com/slycoder + +---- + +`TradingInstrument `_ +_________________________________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/25ce2ab2f5e673e46208c1188a39e6ca?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: milktrader + :target: https://github.com/milktrader + + Current Version: ``0.0.0`` + + Downloading financial time series data and providing financial asset types in Julia + + Maintainer: `milktrader `_ + + Dependencies:: + + Calendar Any Version + DataFrames Any Version + Stats Any Version + TimeSeries Any Version + UTF16 Any Version + julia [v"0.1.0-", v"0.2.0-"] + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/25ce2ab2f5e673e46208c1188a39e6ca?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: milktrader + :target: https://github.com/milktrader + +---- + +`Trie `_ +______________________________________________ + + .. image:: https://secure.gravatar.com/avatar/d57c99557ab0dc0fa44b4c84447d0f15?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-org-420.png + :height: 80px + :width: 80px + :align: right + :alt: The Julia Language + :target: https://github.com/JuliaLang + + Current Version: ``0.0.0`` + + Implementation of the trie data structure. + + Maintainer: `The Julia Language `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/21aeae1f260365557523718bc19640f7?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Stefan Karpinski + :target: https://github.com/StefanKarpinski + +---- + +`UTF16 `_ +____________________________________________ + + .. image:: https://secure.gravatar.com/avatar/1b65c4698da5f30310e14aaee8f3f24e?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Mike Nolta + :target: https://github.com/nolta + + Current Version: ``0.0.0`` + + UTF16 string type for Julia + + Maintainer: `Mike Nolta `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/1b65c4698da5f30310e14aaee8f3f24e?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Mike Nolta + :target: https://github.com/nolta + + .. image:: https://secure.gravatar.com/avatar/21aeae1f260365557523718bc19640f7?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Stefan Karpinski + :target: https://github.com/StefanKarpinski + +---- + +`Units `_ +______________________________________________ + + .. image:: https://secure.gravatar.com/avatar/2989a078f4caff6fb86fa30e59bd9aa9?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Tim Holy + :target: https://github.com/timholy + + Current Version: ``0.0.0`` + + Infrastructure for handling physical units for the Julia programming language + + Maintainer: `Tim Holy `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/2989a078f4caff6fb86fa30e59bd9aa9?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Tim Holy + :target: https://github.com/timholy + +---- + +`WAV `_ +______________________________________________ + + .. image:: https://secure.gravatar.com/avatar/e9c9bece011a5c75918c1dc73a21eaa8?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Daniel Casimiro + :target: https://github.com/dancasimiro + + Current Version: ``0.1.0`` + + Julia package for working with WAV files + + Maintainer: `Daniel Casimiro `_ + + Dependencies:: + + Options Any Version + julia [v"0.1.0-", v"0.2.0-"] + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/e9c9bece011a5c75918c1dc73a21eaa8?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Daniel Casimiro + :target: https://github.com/dancasimiro + +---- + +`Winston `_ +________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/1b65c4698da5f30310e14aaee8f3f24e?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Mike Nolta + :target: https://github.com/nolta + + Current Version: ``0.0.0`` + + 2D plotting for Julia + + Maintainer: `Mike Nolta `_ + + Dependencies:: + + Cairo Any Version + Color Any Version + IniFile Any Version + Tk Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/1b65c4698da5f30310e14aaee8f3f24e?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Mike Nolta + :target: https://github.com/nolta + + .. image:: https://secure.gravatar.com/avatar/b4b8db23d8096b722483a57d21b7d65d?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Jeff Bezanson + :target: https://github.com/JeffBezanson + + .. image:: https://secure.gravatar.com/avatar/42c8c4ab92de3390bcd2f637ef6ca16c?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Kevin Squire + :target: https://github.com/kmsquire + + .. image:: https://secure.gravatar.com/avatar/8af4d5971a2308b86a94f58fb98129c5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Jameson Nash + :target: https://github.com/vtjnash + + .. image:: https://secure.gravatar.com/avatar/449044e4f0ed377b21409488cddafc45?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Blake Johnson + :target: https://github.com/blakejohnson + + .. image:: https://secure.gravatar.com/avatar/55e277a715ee2afd0d29c309174eca02?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Viral B. Shah + :target: https://github.com/ViralBShah + + .. image:: https://secure.gravatar.com/avatar/dfc3b0fbb59c9444153823fd35dbd13b?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Westley Argentum Hennigh + :target: https://github.com/WestleyArgentum + +---- + +`ZMQ `_ +________________________________________ + + .. image:: https://secure.gravatar.com/avatar/f5c61e85dfa465686adc24e0bffba42a?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Avik Sengupta + :target: https://github.com/aviks + + Current Version: ``0.0.0`` + + Julia interface to ZMQ + + Maintainer: `Avik Sengupta `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/f5c61e85dfa465686adc24e0bffba42a?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Avik Sengupta + :target: https://github.com/aviks + + .. image:: https://secure.gravatar.com/avatar/21aeae1f260365557523718bc19640f7?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Stefan Karpinski + :target: https://github.com/StefanKarpinski + + .. image:: https://secure.gravatar.com/avatar/317e44562dcf11f5164d0a4936696fbc?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: rened + :target: https://github.com/rened + +---- + +`Zlib `_ +____________________________________________ + + .. image:: https://secure.gravatar.com/avatar/fd97b03d16e1aa4c404391216d81c1d5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: Daniel Jones + :target: https://github.com/dcjones + + Current Version: ``0.0.0`` + + zlib bindings for Julia + + Maintainer: `Daniel Jones `_ + + Dependencies:: + + None + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/fd97b03d16e1aa4c404391216d81c1d5?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: Daniel Jones + :target: https://github.com/dcjones + +---- + +`kNN `_ +_________________________________________________ + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 80px + :width: 80px + :align: right + :alt: John Myles White + :target: https://github.com/johnmyleswhite + + Current Version: ``0.0.0`` + + The k-nearest neighbors algorithm in Julia + + Maintainer: `John Myles White `_ + + Dependencies:: + + DataFrames Any Version + + Contributors: + + .. image:: https://secure.gravatar.com/avatar/b6b704f26ffe0d91e6317a1c069d4303?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png + :height: 40px + :width: 40px + :alt: John Myles White + :target: https://github.com/johnmyleswhite + +---- + +.. footer: 132 packages, generated 3 Apr 2013 11:25:16 GMT+01:00 + diff --git a/doc/sphinx/jlhelp.py b/doc/sphinx/jlhelp.py index e59310184230f..5690809925d28 100755 --- a/doc/sphinx/jlhelp.py +++ b/doc/sphinx/jlhelp.py @@ -11,7 +11,7 @@ def jl_escape(text): # XXX: crude & fragile - return text.replace('\\',r'\\').replace('"',"\\\"") + return text.replace('\\',r'\\').replace('$',"\\$").replace('"',"\\\"") class JuliaHelpTranslator(TextTranslator): @@ -58,7 +58,7 @@ def depart_desc(self, node): name = self._desc_name if self._current_class: name = self._current_class - self.end_state(first='(E"%s",E"%s",E"%s",E"' % ( \ + self.end_state(first='("%s","%s","%s","' % ( \ jl_escape(category), \ jl_escape(module), \ jl_escape(name))) diff --git a/doc/sphinx/julia.py b/doc/sphinx/julia.py index 6a3f6f2cdafd3..55b8ed3fc8473 100644 --- a/doc/sphinx/julia.py +++ b/doc/sphinx/julia.py @@ -5,7 +5,7 @@ import sphinx.domains.python sphinx.domains.python.py_sig_re = re.compile( - r'''^ ([\w.]*\.)? # class name(s) + r'''^ ([\w.]+\.)? # class name(s) ([^\s(]+) \s* # thing name (?: \((.*)\) # optional: arguments (?:\s* -> \s* (.*))? # return annotation diff --git a/doc/stdlib/argparse.rst b/doc/stdlib/argparse.rst deleted file mode 100644 index 450589338a05f..0000000000000 --- a/doc/stdlib/argparse.rst +++ /dev/null @@ -1,861 +0,0 @@ -:mod:`ArgParse` --- Module for command-line argument parsing -============================================================ - -.. module:: ArgParse - :synopsis: Command line argument parser - -.. note:: located in ``argparse.jl`` - -This module allows the creation of user-friendly command-line interfaces to Julia programs: -the program defines which arguments, options and sub-commands it accepts, and the ``ArgParse`` module -does the actual parsing, issues errors when the input is invalid, and automatically generates help -and usage messages. - -Users familiar with Python's argparse module will find many similarities, but some important differences -as well. - -.. _argparse-overview: - ------------------------------------ -Quick overview and a simple example ------------------------------------ - -First of all, the module needs to be loaded and imported:: - - require("argparse") - using ArgParse - -Note that in the second line we imported all names in the current namespace; this should be completely safe in most cases. - -There are two main steps for defining a command-line interface: creating an ``ArgParseSettings`` object, and -populating it with allowed arguments and options using either the macro ``@add_arg_table`` or the function ``add_arg_table`` -(see :ref:`this section ` for the difference between the two):: - - s = ArgParseSettings() - @add_arg_table s begin - "--opt1" - help = "an option with an argument" - "--opt2", "-o" - help = "another option with an argument" - arg_type = Int - default = 0 - "--flag1" - help = "an option without argument, i.e. a flag" - action = :store_true - "arg1" - help = "a positional argument" - required = true - end - -In the macro, options and positional arguments are specified within a ``begin...end`` block, by one or more names -in a line, optionally followed by a list of settings. -So, in the above example, there are three options: - -* the first one, ``"--opt1"`` takes an argument, but doesn't check for its type, and it doesn't have a default value -* the second one can be invoked in two different forms (``"--opt2"`` and ``"-o"``); it also takes an argument, but - it must be of ``Int`` type (or convertible to it) and its default value is ``0`` -* the third one, ``--flag1``, is a flag, i.e. it doesn't take any argument. - -There is also only one positional argument, ``"arg1"``, which is declared mandatory. - -When the settings are in place, the actual argument parsing is performed via the ``parse_args`` function:: - - parsed_args = parse_args(ARGS, s) - -The parameter ``ARGS`` can be omitted. In case no errors are found, the result will be a ``Dict{String,Any}`` object. -In the above example, it will contain the keys ``"opt1"``, ``"opt2"``, ``"flag1"`` and ``"arg1"``, so that e.g. -``parsed_args["arg1"]`` will yield the value associated with the positional argument. - -Putting all this together in a file, we can see how a basic command-line interface is created:: - - require("argparse") - using ArgParse - - function parse_commandline() - s = ArgParseSettings() - - @add_arg_table s begin - "--opt1" - help = "an option with an argument" - "--opt2", "-o" - help = "another option with an argument" - arg_type = Int - default = 0 - "--flag1" - help = "an option without argument, i.e. a flag" - action = :store_true - "arg1" - help = "a positional argument" - required = true - end - - return parse_args(s) - end - - function main() - parsed_args = parse_commandline() - println("Parsed args:") - for pa in parsed_args - println(" $(pa[1]) => $(pa[2])") - end - end - - main() - -If we save this as a file called ``myprog1.jl``, we can see how a ``--help`` option is added by default, -and a help message is automatically generated and formatted:: - - $ julia myprog1.jl --help - usage: [--opt1 OPT1] [-o OPT2] [--flag1] [-h] arg1 - - positional arguments: - arg1 a positional argument - - optional arguments: - --opt1 OPT1 an option with an argument - -o, --opt2 OPT2 another option with an argument (type: Int64, - default: 0) - --flag1 an option without argument, i.e. a flag - -h, --help show this help message and exit - -Also, we can see how invoking it with the wrong arguments produces errors:: - - $ julia myprog1.jl - required argument arg1 was not provided - usage: [--opt1 OPT1] [-o OPT2] [--flag1] [-h] arg1 - - $ julia myprog1.jl somearg anotherarg - too many arguments - usage: [--opt1 OPT1] [-o OPT2] [--flag1] [-h] arg1 - - $ julia myprog1.jl --opt2 1.5 somearg - invalid argument: 1.5 (must be of type Int64) - usage: [--opt1 OPT1] [-o OPT2] [--flag1] [-h] arg1 - -When everything goes fine instead, our program will print the resulting ``Dict``:: - - $ julia myprog1.jl somearg - Parsed args: - arg1 => somearg - opt2 => 0 - opt1 => nothing - flag1 => false - - $ julia myprog1.jl --opt1 "2+2" --opt2 "2+2" somearg --flag - Parsed args: - arg1 => somearg - opt2 => 4 - opt1 => 2+2 - flag1 => true - -From these examples, a number of things can be noticed: - -* ``opt1`` defaults to ``nothing``, since no ``default`` setting was used for it in ``@add_arg_table`` -* ``opt1`` argument type, begin unspecified, defaults to ``Any``, but in practice it's parsed as a - string (e.g. ``"2+2"``) -* ``opt2`` instead has ``Int`` argument type, so ``"2+2"`` will be parsed as an expression and converted - to an integer -* positional arguments can be passed in between options -* long options can be passed in abbreviated form (e.g. ``--flag`` instead of ``--flag1``) as long as - there's no ambiguity - -.. _argparse-parse_args: - ---------------------------- -The ``parse_args`` function ---------------------------- - -.. function:: parse_args([args,] settings) - - This is the central function of the ``ArgParse`` module. It takes a ``Vector`` of arguments and an ``ArgParseSettings`` - objects (see :ref:`this section `), and returns a ``Dict{String,Any}``. - If ``args`` is not provided, the global variable ``ARGS`` will be used. - - The returned ``Dict`` keys are defined (possibly implicitly) in ``settings``, and their associated values are parsed - from ``args``. Special keys are used for more advanced purposes; at the moment, one such key exists: ``%COMMAND%`` - (see :ref:`this section `). - - Arguments are parsed in sequence and matched against the argument table in ``settings`` to determine whether they are - long options, short options, option arguments or positional arguments: - - * long options begin with a doule dash ``"--"``; if a ``'='`` character is found, the remainder is the option argument; - therefore, ``["--opt=arg"]`` and ``["--opt", "arg"]`` are equivalent if ``--opt`` takes at least one argument. - Long options can be abbreviated (e.g. ``--opt`` instead of ``--option``) as long as there is no ambiguity. - * short options begin with a single dash ``"-"`` and their name consists of a single character; they can be grouped - togheter (e.g. ``["-x", "-y"]`` can become ``["-xy"]``), but in that case only the last option in the group can - take an argument (which can also be grouped, e.g. ``["-a", "-f", "file.txt"]`` can be passed as - ``["-affile.txt"]`` if ``-a`` does not take an argument and ``-f`` does). The ``'='`` character can be used to - separate option names from option arguments as well (e.g. ``-af=file.txt``). - * positional arguments are anything else; they can appear anywhere. - - The special string ``"--"`` can be used to signal the end of all options; after that, everything is considered as a - positional argument (e.g. if ``args = ["--opt1", "--", "--opt2"]``, the parser will recognize ``--opt1`` as a long - option without argument, and ``--opt2`` as a positional argument). - - The special string ``"-"`` is always parsed as a positional argument. - - The parsing can stop early if a ``:show_help`` or ``:show_version`` action is triggered, or if a parsing error is - found. - - Some ambiguities can arise in parsing, see :ref:`this section ` for a detailed description - of how they're solved. - -.. _argparse-settings-overview: - ------------------ -Settings overview ------------------ - -The ``ArgParseSettings`` object contains all the settings to be used during argument parsing. Settings are divided -in two groups: general settings and argument-table-related settings. -While the argument table requires specialized functions such as ``add_arg_table`` to be defined and manipulated, -general settings are simply object fields (most of them are ``Bool`` or ``String``) and can be set directly at any -time. - -.. _argparse-general-settings: - ----------------- -General settings ----------------- - -This is the list of general settings currently available: - -* ``prog`` (default = ``""``): the name of the program, as displayed in the auto-generated help and usage screens. - If left empty, ``""`` will be used. -* ``description`` (default = ``""``): a description of what the program does, to be displayed in the auto-generated - help-screen, between the usage lines and the arguments description. It will be automatically formatted. -* ``epilog`` (default = ``""``): like ``description``, but will be discplayed at the end of the help-screen, after the - arguments description. -* ``usage`` (default = ``""``): the usage line(s) to be displayed in the help screen and when an error is found during parsing. - If left empty, it will be auto-generated. -* ``version`` (default = ``""Unknown version"``): version information. It's used by the ``:show_version`` action. -* ``add_help`` (default = ``true``): if ``true``, a ``--help, -h`` option (triggering the ``:show_help`` action) is added - to the argument table. -* ``add_version`` (default = ``false``): if ``true``, a ``--version`` option (triggering the ``:show_version`` action) is added - to the argument table. -* ``error_on_conflict`` (default = ``true``): if ``true``, throw an error in case conflicting entries are added to the argument table; - if ``false``, later entries will silently take precedence. - See :ref:`this section ` for a detailed description of what conflicts are and what is the exact behavior - when this setting is ``false``. -* ``suppress_warnings`` (default = ``false``): is ``true``, all warnings will be suppressed. -* ``allow_ambiguous_opts`` (default = ``false``): if ``true``, ambiguous options such as ``-1`` will be accepted. -* ``commands_are_required`` (default = ``true``): if ``true``, commands will be mandatory. See :ref:`this section ` - for more information on commands. -* ``exc_handler``: this is a function which is invoked when an error is detected during parsing (e.g. an option is not - recognized, a required argument is not passed etc.). It takes two arguments: the ``settings::ArgParseSettings`` object and the - ``err::ArgParseError`` exception. The default handler prints the error text and the usage screen on standard error and exits. - -Here is a usage example:: - - settings = ArgParseSettings() - settings.prog = "myprogram" - settings.description = "This program does something." - settings.add_version = true - settings.allow_ambiguous_opts = true - -As a shorthand for most common settings, the ``ArgParseSettings`` contructor accepts two optional fields, ``prog`` and -``description``. - -Most settings won't take effect until ``parse_args`` is invoked, but a few will have immediate effects: ``error_on_conflict``, -``suppress_warnings``, ``allow_ambiguous_opts``. - -.. _argparse-argument-table-basics: - ---------------------- -Argument table basics ---------------------- - -The argument table is used to store allowed arguments and options in an ``ArgParseSettings`` object. There are two very similar -methods to populate it: - -.. function:: @add_arg_table(settings, table...) - - This macro adds a table of arguments and options to the given ``settings``. It can be invoked multiple times. The arguments groups - are determined automatically, or the current default group is used if specified (see :ref:`this section ` for - more details). - - The ``table`` is a list in which each element can be either ``String``, or a tuple or a vector of ``String``, or an assigmment - expression, or a block: - - * a ``String``, a tuple or a vector introduces a new positional argument or option. Tuples and vectors are only allowed for options and - provide alternative names (e.g. ``["--opt", "-o"]``) - * assignment expressions (i.e. expressions using ``=``, ``:=`` or ``=>``) describe the previous argument behavior (e.g. - ``help = "an option"`` or ``required => false``). See :ref:`this section ` for a complete description - * blocks (``begin...end`` or lists of expressions in parentheses separated by semicolons) are useful to group entries and span - multiple lines. - - These rules allow for a variety usage styles, which are discussed in :ref:`this section `. - In the rest of this document, we will mostly use this style:: - - @add_arg_table settings begin - "--opt1", "-o" - help = "an option with an argument" - "--opt2" - "arg1" - help = "a positional argument" - required = true - end - - In the above example, the ``table`` is put in a single ``begin...end`` block and the line ``"-opt1", "-o"`` is parsed as a tuple; - indentation is used to help readability. - -.. function:: add_arg_table(settings, [arg_name [,arg_options]]...) - - This function is almost equivalent to the macro version. Its syntax is stricter (tuples and blocks are not allowed and argument options - are explicitly specified as ``Options`` objects) but the ``arg_name`` entries need not be explicit, they can be anything which evaluates - to a ``String`` or a ``Vector{String}``. - - Example:: - - add_arg_table(settings, - ["--opt1", "-o"], - @options begin - help = "an option with an argument" - end, - "--opt2", - "arg1", - @options begin - help = "a positional argument" - required = true - end) - - Note that the :mod:`OptionsMod` module must be imported in order to use this function. - -.. _argparse-argument-table-entries: - ----------------------- -Argument table entries ----------------------- - -Argument table entries consist of an argument name and a list of argument settings, e.g.:: - - "--verbose" - help = "verbose output" - action = :store_true - -.. _argparse-argument-names: - -Argument names --------------- - -Argument names are strings or, in the case of options, lists of strings. An argument is an option if it begins with a ``'-'`` -character, otherwise it'a positional argument. A single ``'-'`` introduces a short option, which must consist of a single -character; long options begin with ``"--"`` instead. - -Positional argument names can be any string, except all-uppercase strings between ``'%'`` characters, which are reserved -(e.g. ``"%COMMAND%"``). -Option names can contain any character except ``'='``, whitespaces and non-breakable spaces. -Depending on the value of the ``add_help`` and ``add_version`` settings, options ``--help``, ``-h`` and ``--version`` may -be reserved. -If the ``allow_ambiguous_opts`` setting is ``false``, some characters are not allowed as short options: all digits, the dot, -the underscore and the opening parethesis (e.g. ``-1``, ``-.``, ``-_``, ``-(``). - -For positional arguments, the argument name will be used as the key in the ``Dict`` object returned by the ``parse_args`` function. -For options, it will be used to produce a default key in case a ``dest_name`` is not explicitly specified in the table entry, using -either the first long option name in the list or the first short option name if no long options are present. For example: - -+--------------------------------+---------------------------+ -| argument name | default ``dest_name`` | -+================================+===========================+ -| ``"--long"`` | ``"long"`` | -+--------------------------------+---------------------------+ -| ``"--long", "-s"`` | ``"long"`` | -+--------------------------------+---------------------------+ -| ``"-s", "--long1", "--long2"`` | ``"long1"`` | -+--------------------------------+---------------------------+ -| ``"-s", "-x"`` | ``"s"`` | -+--------------------------------+---------------------------+ - -The argument name is also used to generate a default metavar in case ``metavar`` is not explicitly set in the table entry. The rules -are the same used to determine the default ``dest_name``, but for options the result will be uppercased (e.g. ``"--long"`` will -become ``LONG``). Note that this poses additional constraints on the positional argument names (e.g. whitespaces are not allowed in -metavars). - -.. _argparse-arg-entry-settings: - -Argument entry settings ------------------------ - -Argument entry settings determine all aspects of an argument's behavior. Some settings combinations are contradictory and will produce -an error (e.g. using both ``action = :store_true`` and ``nargs = 1``, or using ``action = :store_true`` with a positional argument). -Also, some settings are only meaningful under some conditions (e.g. passing a ``metavar`` to a flag-like option does not make sense) -and will be ignored with a warning (unless the ``suppress_warnings`` general setting is ``true``). - -This is the list of all available settings: - -* ``nargs`` (default = ``'A'``): the number of extra command-line tokens parsed with the entry. See - :ref:`this section ` for a complete desctiption. -* ``action``: the action performed when the argument is parsed. It can be passed as a ``String`` or as a ``Symbol`` (e.g. both - ``:store_arg`` and ``"store_arg"`` are accepted). The default action is ``:store_arg`` unless ``nargs`` is ``0``, in which case the - default is ``:store_true``. See :ref:`this section ` for a list of all available actions and a detailed - explanation. -* ``arg_type`` (default = ``Any``): the type of the argument. Makes only sense with non-flag arguments. -* ``default`` (default = ``nothing``): the default value if the option or positional argument is not parsed. Makes only sense with - non-flag arguments, or when the action is ``:store_const`` or ``:append_const``. Unless it's ``nothing``, it must be coherent with - ``arg_type`` and ``range_tester``. -* ``constant`` (default = ``nothing``): this value is used by the ``:store_const`` and ``:append_const`` actions, or when ``nargs = '?'`` - and the option argument is not provided. -* ``required`` (default = ``false``): determines if a positional argument is required (this setting is ignored by options, which are always - optional). -* ``range_tester`` (default = ``x->true``): a function returning a ``Bool`` value which tests whether an argument is allowed (e.g. - you could use ``arg_type = Integer`` and ``range_tester = isodd`` to allow only odd integer values) -* ``dest_name`` (default = auto-generated): the key which will be associated with the argument in the ``Dict`` object returned by - ``parse_args``. The auto-generation rules are explained in :ref:`this section `. Multiple arguments can share - the same destination, provided their actions and types are compatible. -* ``help`` (default = ``""``): the help string which will be shown in the auto-generated help screen. It's a ``String`` which will - be automaticaly formatted; also, ``arg_type`` and ``default`` will be automatically appended to it if provided. -* ``metavar`` (default = auto-generated): a token which will be used in usage and help screens to describe the argument syntax. For - positional arguments, it will also be used as an identifier in all other messages (e.g. in reporting errors), therefore it must - be unique. The auto-generations rules are explained in :ref:`this section `. -* ``force_override``: if ``true``, conflicts are ignored when adding this entry in the argument table (see also :ref:`this section - `). By default, - it follows the general ``error_on_conflict`` settings). -* ``group``: the option group to which the argument will be assigned to (see :ref:`this section `). By default, the - current default group is used if specified, otherwise the assignment is automatic. - -.. _argparse-actions-and-nargs: - -Available actions and nargs values ----------------------------------- - -The ``nargs`` and ``action`` argument entry settings are used together to determine how many tokens will be parsed from the command -line and what action will be performed on them. - -The ``nargs`` setting can be a number or a character; the possible values are: - -* ``'A'``: automatic, i.e. inferred from the action (this is the default). In practice, it means ``0`` for flag-like options and ``1`` - for non-flag-like options (but it's different from using an explicit ``1`` because the result is not stored in a ``Vector``). -* ``0``: this is the only option (besides ``'A'``) for flag-like actions (see below), and it means no extra tokens will be parsed from - the command line. If ``action`` is not specified, setting ``nargs`` to ``0`` will make ``action`` default to ``:store_true``. -* a positive integer number ``N``: exactly ``N`` tokens will be parsed from the command-line, and the result stored into a ``Vector`` - of length ``N`` (even for ``N=1``). -* ``'?'``: optional, i.e. a token will only be parsed if it does not look like an option (see :ref:`this section ` - for a discussion of how exactly this is established), otherwise the ``constant`` argument entry setting will be used instead. - This only makes sense with options. -* ``'*'``: any number, i.e. all subsequent tokens which do not look like an option are stored into a ``Vector``. -* ``'+'``: like ``'*'``, but at least one token is required. -* ``'R'``: all remainder tokens, i.e. like ``'*'`` but it does not stop at options. - -Actions can be categorized in many ways; one prominent distinction is flag vs. non-flag: some actions are for options which take no -argument (i.e. flags), all others (except ``command``, which is special) are for other options and positional arguments: - -* flag actions are only compatible with ``nargs = 0`` or ``nargs = 'A'`` -* non-flag actions are not compatible with ``nargs = 0``. - -This is the list of all available actions (in each examples, suppose we defined ``settings = ArgParseSettings()``): - -* ``store_arg`` (non-flag): store the argument. This is the default unless ``nargs`` is ``0``. Example:: - - julia> @add_arg_table(settings, "arg", action => :store_arg); - - julia> parse_args(["x"], settings) - {"arg"=>"x"} - - The result is a vector if ``nargs`` is a non-zero number, or one of ``'*'``, ``'+'``, ``'R'``:: - - julia> @add_arg_table(settings, "arg", action => :store_arg, nargs => 2); - - julia> parse_args(["x", "y"], settings) - {"arg"=>{"x", "y"}} - -* ``store_true`` (flag): store ``true`` if given, otherwise ``false``. Example:: - - julia> @add_arg_table(settings, "-v", action => :store_true); - - julia> parse_args([], settings) - {"v"=>false} - - julia> parse_args(["-v"], settings) - {"v"=>true} - -* ``store_false`` (flag): store ``false`` if given, otherwise ``true``. Example:: - - julia> @add_arg_table(settings, "-v", action => :store_false); - - julia> parse_args([], settings) - {"v"=>true} - - julia> parse_args(["-v"], settings) - {"v"=>false} - -* ``store_const`` (flag): store the value passed as ``constant`` in the entry settings if given, otherwise ``default``. - Example:: - - julia> @add_arg_table(settings, "-v", action => :store_const, constant => 1, default => 0); - - julia> parse_args([], settings) - {"v"=>0} - - julia> parse_args(["-v"], settings) - {"v"=>1} - -* ``append_arg`` (non-flag): append the argument to the result. Example:: - - julia> @add_arg_table(settings, "-x", action => :append_arg); - - julia> parse_args(["-x", "1", "-x", "2"], settings) - {"x"=>{"1", "2"}} - - The result will be a ``Vector{Vector}`` if ``nargs`` is a non-zero number, or one of ``'*'``, ``'+'``, ``'R'``:: - - julia> @add_arg_table(settings, "-x", action => :append_arg, nargs => '*'); - - julia> parse_args(["-x", "1", "2", "-x", "3"], settings) - {"x"=>{{"1", "2"}, {"3"}} - -* ``append_const`` (flag): append the value passed as ``constant`` in the entry settings. Example:: - - julia> @add_arg_table(settings, "-x", action => :append_const, constant => 1); - - julia> parse_args(["-x", "-x", "-x"], settings) - {"x"=>{1, 1, 1}} - -* ``count_invocations`` (flag): increase a counter; the final result will be the number of times the option was - invoked. Example:: - - julia> @add_arg_table(settings, "-x", action => :count_invocations); - - julia> parse_args(["-x", "-x", "-x"], settings) - {"x"=>3} - -* ``show_help`` (flag): show the help screen and exit. This is useful if the ``add_help`` general setting is - ``false``. Example:: - - julia> settings.add_help = false; - - julia> @add_arg_table(settings, "-x", action => :show_help); - - julia> parse_args(["-x"], settings) - usage: [-x] - - optional arguments: - -x - -* ``show_version`` (flag): show the version information and exit. This is useful if the ``add_version`` general - setting is ``false``. Example:: - - julia> settings.version = "1.0"; - - julia> @add_arg_table(settings, "-x", action => :show_version); - - julia> parse_args(["-v"], settings) - 1.0 - -* ``command`` (special): the argument or option is a command, i.e. it starts a sub-parsing session (see :ref:`this section - `) - -.. _argparse-commands: - -Commands --------- - -Commands are a special kind of arguments which introduce sub-parsing sessions as soon as they are encountered by ``parse_args`` -(and are therefore mutually exclusive). -The ``ArgParse`` module allows commands to look both as positional arguments or as flags, with minor differences between the two. - -Commands are introduced by the ``action = :command`` setting in the argument table. Suppose we save the following script in -a file called ``cmd_example.jl``:: - - require("argparse") - using ArgParse - - function parse_commandline() - s = ArgParseSettings("cmd_example.jl") - - @add_arg_table s begin - "cmd1" - help = "first command" - action = :command - "cmd2" - help = "second command" - action = :command - end - - return parse_args(s) - end - - parsed_args = parse_commandline() - println(parsed_args) - -Invoking the script from the command line, we would get the following help screen:: - - $ julia cmd_example.jl --help - usage: cmd_example.jl [-h] {cmd1|cmd2} - - commands: - cmd1 first command - cmd2 second command - - optional arguments: - -h, --help show this help message and exit - -If commands are present in the argument table, ``parse_args`` will set the special key ``"%COMMAND%"`` in the returned ``Dict`` and -fill it with the invoked command (or ``nothing`` if no command was given):: - - $ julia cmd_example.jl cmd1 - {"%COMMAND%"=>"cmd1", "cmd1"=>{}} - -Since commands introduce sub-parsing sessions, an additional key will be added for the called command (``"cmd1"`` in this case) whose -associated value is another ``Dict{String, Any}`` containing the result of the sub-parsing (in the above case it's empty). In fact, -with the default settings, commands have their own help screens:: - - $ julia cmd_example.jl cmd1 --help - usage: cmd_example.jl cmd1 [-h] - - optional arguments: - -h, --help show this help message and exit - -The argument settings and tables for commands can be accessed by using a dict-like notation, i.e. ``settings["cmd1"]`` is an -``ArgParseSettings`` object specific to the ``"cmd1"`` command. Therefore, to populate a command sub-argument-table, simply -use ``@add_arg_table(settings["cmd1"], table...)`` and similar. - -These sub-settings are created when a command is added to the argument table, and by default they inherit their parent general -settings except for the ``prog`` setting (which is auto-generated, as can be seen in the above example) and the -``description``, ``epilog`` and ``usage`` settings (which are left empty). - -Commands can also have sub-commands. - -By default, if commands exist, they are required; this can be avoided by setting the ``commands_are_required = false`` general setting. - -The only meaningful settings for commands in an argument entry besides ``action`` are ``help``, ``force_override``, ``group`` and -(for flags only) ``dest_name``. - -The only differences between positional-arguments-like and flag-like commands are in the way they are parsed, the fact that flags -accept a ``dest_name`` setting, and that flags can have multiple names (e.g. a long and short form). - -Note that short-form flag-like commands will be still be recognized in the middle of a short options group and trigger a sub-parsing -session: for example, if a flag ``-c`` is associated to a command, then ``-xch`` will parse option ``-x`` according to the parent -settings, and option ``-h`` according to the command sub-settings. - -.. _argparse-groups: - -Argument groups ---------------- - -By default, the auto-generated help screen divides arguments into three groups: commands, positional arguments and optional -arguments, displayed in that order. Example:: - - julia> settings = ArgParseSettings(); - - julia> @add_arg_table settings begin - "--opt" - "arg" - required = true - "cmd1" - action = :command - "cmd2" - action = :command - end; - - julia> parse_args(["--help"], settings) - usage: [--opt OPT] [-h] arg {cmd1|cmd2} - - commands: - cmd1 - cmd2 - - positional arguments: - arg - - optional arguments: - --opt OPT - -h, --help show this help message and exit - -It is possible to partition the arguments differently by defining and using customized argument groups. - -.. function:: add_arg_group(settings, description, [name [, set_as_default]]) - - This function adds an argument group to the argument table in ``settings``. The ``description`` is a ``String`` used in - the help screen as a title for that group. The ``name`` is a unique name which can be provided to refer to that group - at a later time. - - After invoking this function, all subsequent invocations of the ``@add_arg_table`` macro and ``add_arg_table`` function - will use the new group as the default, unless ``set_as_default`` is set to ``false`` (the default is ``true``, and the option - can only be set if providing a ``name``). Therefore, the most obvious usage pattern is: for each group, add it and populate - the argument table of that group. Example:: - - julia> settings = ArgParseSettings(); - - julia> add_arg_group(settings, "custom group"); - - julia> @add_arg_table settings begin - "--opt" - "arg" - end; - - julia> parse_args(["--help"], settings) - usage: [--opt OPT] [-h] [arg] - - optional arguments: - -h, --help show this help message and exit - - custom group: - --opt OPT - arg - - As seen from the example, new groups are always added at the end of existing ones. - - The ``name`` can also be passed as a ``Symbol``. Forbidden names are the standard groups names (``"command"``, - ``"positional"`` and ``"optional"``) and those beginning with a hash character ``'#'``. - -.. function:: set_default_arg_group(settings[, name]) - - Set the default group for subsequent invocations of the ``@add_arg_table`` macro and ``add_arg_table`` function. - ``name`` is a ``String``, and must be one of the standard group names (``"command"``, ``"positional"`` or - ``"optional"``) or one of the user-defined names given in ``add_arg_group`` (groups with no assigned name cannot be - used with this function). - - If ``name`` is not provided or is the empty string ``""``, then the default behavior is reset (i.e. arguments will be - automatically assigned to the standard groups). - The ``name`` can also be passed as a ``Symbol``. - -Besides setting a default group with ``add_arg_group`` and ``set_default_group``, it's also possible to assign individual arguments -to a group by using the ``group`` setting in the argument table entry, which follows the same rules as ``set_default_group``. - -Note that if the ``add_help`` or ``add_version`` general settings are ``true``, the ``--help, -h`` and ``--version`` options -will always be added to the ``optional`` group. - -.. _argparse-import-settings: - ------------------- -Importing settings ------------------- - -It may be useful in some cases to import an argument table into the one which is to be used, for example to create -specialized versions of a common interface. - -.. function:: import_settings(settings, other_settings [,args_only]) - - Imports ``other_settings`` into ``settings``, where both are ``ArgParseSettings`` objects. If ``args_only`` is - ``true`` (this is the default), only the argument table will be imported; otherwise, the default argument group - will also be imported, and all general settings except ``prog``, ``description``, ``epilog`` and ``usage``. - - Sub-settings associated with commands will also be imported recursively; the ``args_only`` setting applies to - those as well. If there are common commands, their sub-settings will be merged. - - While importing, conflicts may arise: if ``settings.error_on_conflict`` is ``true``, this will result in an error, - otherwise conflicts will be resolved in favor of ``other_settings`` (see :ref:`this section ` - for a detailed discussion of how conflicts are handled). - - Argument groups will also be imported; if two groups in ``settings`` and ``other_settings`` match, they are merged - (groups match either by name, or, if unnamed, by their description). - - Note that the import will have effect immediately: any subsequent modification of ``other_settings`` will not have - any effect on ``settings``. - - This function can be used at any time. - -.. _argparse-conflicts: - ------------------------ -Conflicts and overrides ------------------------ - -Conflicts between arguments, be them options, positional arguments or commands, can arise for a variety of reasons: - -* Two options have the same name (either long or short) -* Two arguments have the same destination key, but different types (e.g. one is ``Any`` and the other ``String``) -* Two arguments have the same destination key, but incompatible actions (e.g. one does ``:store_arg`` and the other - ``:append_arg``) -* Two positional arguments have the same metavar (and are therefore indistinguishable in the usage and help screens - and in error messages) -* An argument and a command, or two commands, have the same destination key. - -When the general setting ``error_on_conflict`` is ``true``, or any time the specific ``force_override`` table entry -setting is ``false``, any of the above conditions leads to an error. - -On the other hand, setting ``error_on_conflict`` to ``false``, or ``force_override`` to ``true``, will try to force -the resolution of most of the conflicts in favor of the newest added entry. The general rules are the following: - -* In case of duplicate options, all conflicting forms of the older options are removed; if all forms of an - option are removed, the option is deleted entirely -* In case of duplicate destination key and incompatible types or actions, the older argument is deleted -* In case of duplicate positional arguments metavars, the older argument is deleted -* A command can override an argument with the same destination key -* However, an argument can never override a command if they have the same destination key; neither can - a command override another command when added with ``@add_arg_table`` (compatible commands are merged - by ``import_settings`` though) - -.. _argparse-details: - ---------------- -Parsing details ---------------- - -During parsing, ``parse_args`` must determine whether an argument is an option, an option argument, a positional -argument, or a command. The general rules are explained in :ref:`this section `, but -ambiguities may arise under particular circumstances. In particular, negative numbers like ``-1`` or ``-.1e5`` -may look like options. Under the default settings, such options are forbidden, and therefore those tokens are -always recognized as non-options. However, if the ``allow_ambiguous_opts`` general setting is ``true``, existing -options in the argument table will take precedence: for example, if the option ``-1`` is added, and it takes an -argument, then ``-123`` will be parsed as that option, and ``23`` will be its argument. - -Some ambiguities still remains though, because the ``ArgParse`` module will actually accept and parse expressions, -not only numbers, and therefore one may try to pass arguments like ``-e`` or ``-pi``; in that case, these will -always be at risk of being recognized as options. The easiest workaround is to put them in parentheses, -e.g. ``(-e)``. - -When an option is declared to accept a fixed positive number of arguments or the remainder of the command line -(i.e. if ``nargs`` is a non-zero number, or ``'A'``, or ``'R'``), ``parse_args`` will not try to check if the -argument(s) looks like an option. - -If ``nargs`` is one of ``'?'`` or ``'*'`` or ``'+'``, then ``parse_args`` will take in only arguments which do not -look like options. - -When ``nargs`` is ``'+'`` or ``'*'`` and an option is being parsed, then using the ``'='`` character will mark what -follows as an argument (i.e. not an option); all which follows goes under the rules explained above. The same is true -when short option groups are being parsed. For example, if the option in question is ``-x``, then both -``-y -x=-2 4 -y`` and ``-yx-2 4 -y`` will parse ``"-2"`` and ``"4"`` as the arguments of ``-x``. - -Finally, since expressions may be evaluated during parsing, note that there is no safeguard against passing -things like ``run(`rm -fr ~`)`` and seeing your data evaporate. Be careful. - -.. _argparse-table-styles: - ---------------------- -Argument table styles ---------------------- - -Here are some examples of styles for the ``@add_arg_table`` marco and ``add_arg_table`` function invocation:: - - @add_arg_table settings begin - "--opt", "-o" - help = "an option" - "arg" - help = "a positional argument" - end - - @add_arg_table(settings - , ["--opt", "-o"] - , help => "an option" - , "arg" - , help => "a positional argument" - ) - - @add_arg_table settings begin - (["--opt", "-o"]; help = an option) - ("arg"; help = "a positional argument") - end - - @add_arg_table(settings, - ["-opt", "-o"], - begin - help = "an option" - end, - "arg", - begin - help = "a positional argument" - end) - - add_arg_table(settings, - ["-opt", "-o"], @options(help := "an option"), - "arg" , @options(help := "a positional argument") - ) - -The restrictions are: - -* when using the function-like notation for macros (i.e. passing arguments in a comma-separated list - between parentheses), assignments can only use ``=>`` or ``:=``. In the examples above, this can be seen - both when using ``@add_arg_table`` and ``@options`` -* groups introduced by ``begin...end`` blocks or semicolon-separated list between parentheses cannot introduce - argument names unless the first item in the block is an argument name. diff --git a/doc/stdlib/base.rst b/doc/stdlib/base.rst index be3add9dc9f65..13cb8e5ccc5dd 100644 --- a/doc/stdlib/base.rst +++ b/doc/stdlib/base.rst @@ -7,38 +7,60 @@ Getting Around Quit (or control-D at the prompt). The default exit code is zero, indicating that the processes completed successfully. -.. function:: whos([Module][, pattern::Regex]) +.. function:: whos([Module,] [pattern::Regex]) Print information about global variables in a module, optionally restricted to those matching ``pattern``. -.. function:: edit("file"[, line]) +.. function:: edit(file::String, [line]) Edit a file optionally providing a line number to edit at. Returns to the julia prompt when you quit the editor. If the file name ends in ".jl" it is reloaded when the editor closes the file. -.. function:: edit(function[, types]) +.. function:: edit(function, [types]) Edit the definition of a function, optionally specifying a tuple of types to indicate which method to edit. When the editor exits, the source file containing the definition is reloaded. -.. function:: load("file") +.. function:: require(file::String...) - Evaluate the contents of a source file + Load source files once, in the context of the ``Main`` module, on every active node, searching the system-wide ``LOAD_PATH`` for files. ``require`` is considered a top-level operation, so it sets the current ``include`` path but does not use it to search for files (see help for ``include``). This function is typically used to load library code, and is implicitly called by ``using`` to load packages. -.. function:: help("name" or object) +.. function:: reload(file::String) - Get help for a function + Like ``require``, except forces loading of files regardless of whether they have been loaded before. Typically used when interactively developing libraries. -.. function:: apropos("string") +.. function:: include(path::String) - Search help for a substring + Evaluate the contents of a source file in the current context. During including, a task-local include path is set to the directory containing the file. Nested calls to ``include`` will search relative to that path. All paths refer to files on node 1 when running in parallel, and files will be fetched from node 1. This function is typically used to load source interactively, or to combine files in packages that are broken into multiple source files. + +.. function:: include_string(code::String) + + Like ``include``, except reads code from the given string rather than from a file. Since there is no file path involved, no path processing or fetching from node 1 is done. + +.. function:: evalfile(path::String) + + Evaluate all expressions in the given file, and return the value of the last one. No other processing (path searching, fetching from node 1, etc.) is performed. + +.. function:: help(name) + + Get help for a function. ``name`` can be an object or a string. + +.. function:: apropos(string) + + Search documentation for functions related to ``string``. .. function:: which(f, args...) - Show which method of ``f`` will be called for the given arguments + Show which method of ``f`` will be called for the given arguments. .. function:: methods(f) - Show all methods of ``f`` with their argument types + Show all methods of ``f`` with their argument types. + +.. function:: methodswith(typ[, showparents]) + + Show all methods with an argument of type ``typ``. If optional + ``showparents`` is ``true``, also show arguments with a parent type + of ``typ``, excluding type ``Any``. All Objects ----------- @@ -81,7 +103,7 @@ All Objects .. function:: finalizer(x, function) - Register a function to be called on ``x`` when there are no program-accessible references to ``x``. The behavior of this function is unpredictable if ``x`` is of a bits type. + Register a function ``f(x)`` to be called when there are no program-accessible references to ``x``. The behavior of this function is unpredictable if ``x`` is of a bits type. .. function:: copy(x) @@ -110,6 +132,10 @@ Types True if and only if all values of ``type1`` are also of ``type2``. Can also be written using the ``<:`` infix operator as ``type1 <: type2``. +.. function:: <:(T1, T2) + + Subtype operator, equivalent to ``subtype(T1,T2)``. + .. function:: typemin(type) The lowest value representable by the given (real) numeric type. @@ -126,6 +152,10 @@ Types The highest finite value representable by the given floating-point type +.. function:: maxintfloat(type) + + The largest integer losslessly representable by the given floating-point type + .. function:: sizeof(type) Size, in bytes, of the canonical binary representation of the given type, if any. @@ -142,13 +172,30 @@ Types Determine a type big enough to hold values of each argument type without loss, whenever possible. In some cases, where no type exists which to which both types can be promoted losslessly, some loss is tolerated; for example, ``promote_type(Int64,Float64)`` returns ``Float64`` even though strictly, not all ``Int64`` values can be represented exactly as ``Float64`` values. +.. function:: getfield(value, name::Symbol) + + Extract a named field from a value of composite type. The syntax ``a.b`` calls + ``getfield(a, :b)``, and the syntax ``a.(b)`` calls ``getfield(a, b)``. + +.. function:: setfield(value, name::Symbol, x) + + Assign ``x`` to a named field in ``value`` of composite type. + The syntax ``a.b = c`` calls ``setfield(a, :b, c)``, and the syntax ``a.(b) = c`` + calls ``setfield(a, b, c)``. + +.. function:: fieldtype(value, name::Symbol) + + Determine the declared type of a named field in a value of composite type. + Generic Functions ----------------- -.. function:: method_exists(f, tuple) +.. function:: method_exists(f, tuple) -> Bool Determine whether the given generic function has a method matching the given tuple of argument types. + **Example**: ``method_exists(length, (Array,)) = true`` + .. function:: applicable(f, args...) Determine whether the given generic function has a method applicable to the given arguments. @@ -157,20 +204,23 @@ Generic Functions Invoke a method for the given generic function matching the specified types (as a tuple), on the specified arguments. The arguments must be compatible with the specified types. This allows invoking a method other than the most specific matching method, which is useful when the behavior of a more general definition is explicitly needed (often as part of the implementation of a more specific method of the same function). +.. function:: |(x, f) + + Applies a function to the preceding argument which allows for easy function chaining. + + **Example**: ``[1:5] | x->x.^2 | sum | inv`` + Iteration --------- -Sequential iteration is implemented by the methods ``start``, ``done``, and ``next``. The general ``for`` loop: - -:: +Sequential iteration is implemented by the methods ``start``, ``done``, and +``next``. The general ``for`` loop:: for i = I # body end -is translated to: - -:: +is translated to:: state = start(I) while !done(I, state) @@ -180,11 +230,11 @@ is translated to: The ``state`` object may be anything, and should be chosen appropriately for each iterable type. -.. function:: start(iter) +.. function:: start(iter) -> state Get initial iteration state for an iterable object -.. function:: done(iter, state) +.. function:: done(iter, state) -> Bool Test whether we are done iterating @@ -192,106 +242,159 @@ The ``state`` object may be anything, and should be chosen appropriately for eac For a given iterable object and iteration state, return the current item and the next iteration state +.. function:: zip(iters...) + + For a set of iterable objects, returns an iterable of tuples, where the ``i``\ th tuple contains the ``i``\ th component of each input iterable. + + Note that ``zip`` is it's own inverse: ``[zip(zip(a...)...)...] == [a...]``. + +.. function:: enumerate(iter) + + Return an iterator that yields ``(i, x)`` where ``i`` is an index starting at 1, + and ``x`` is the ``ith`` value from the given iterator. + Fully implemented by: ``Range``, ``Range1``, ``NDRange``, ``Tuple``, ``Real``, ``AbstractArray``, ``IntSet``, ``ObjectIdDict``, ``Dict``, ``WeakKeyDict``, ``EachLine``, ``String``, ``Set``, ``Task``. General Collections ------------------- -.. function:: isempty(collection) +.. function:: isempty(collection) -> Bool Determine whether a collection is empty (has no elements). -.. function:: length(collection) +.. function:: empty!(collection) -> collection - For ordered, indexable collections, the maximum index ``i`` for which ``ref(collection, i)`` is valid. For unordered collections, the number of elements. + Remove all elements from a collection. -Fully implemented by: ``Range``, ``Range1``, ``Tuple``, ``Number``, ``AbstractArray``, ``IntSet``, ``Dict``, ``WeakKeyDict``, ``String``, ``Set``. +.. function:: length(collection) -> Integer + + For ordered, indexable collections, the maximum index ``i`` for which ``getindex(collection, i)`` is valid. For unordered collections, the number of elements. + +.. function:: endof(collection) -> Integer + + Returns the last index of the collection. + + **Example**: ``endof([1,2,4]) = 3`` -Partially implemented by: ``FDSet``. +Fully implemented by: ``Range``, ``Range1``, ``Tuple``, ``Number``, ``AbstractArray``, ``IntSet``, ``Dict``, ``WeakKeyDict``, ``String``, ``Set``. Iterable Collections -------------------- -.. function:: contains(itr, x) +.. function:: contains(itr, x) -> Bool Determine whether a collection contains the given value, ``x``. +.. function:: findin(a, b) + + Returns the indices of elements in collection ``a`` that appear in collection ``b`` + +.. function:: unique(itr) + + Returns an array containing only the unique elements of the iterable ``itr``. + .. function:: reduce(op, v0, itr) Reduce the given collection with the given operator, i.e. accumulate ``v = op(v,elt)`` for each element, where ``v`` starts as ``v0``. Reductions for certain commonly-used operators are available in a more convenient 1-argument form: ``max(itr)``, ``min(itr)``, ``sum(itr)``, ``prod(itr)``, ``any(itr)``, ``all(itr)``. .. function:: max(itr) - Determine maximum element in a collection + Returns the largest element in a collection .. function:: min(itr) - Determine minimum element in a collection + Returns the smallest element in a collection -.. function:: indmax(itr) +.. function:: indmax(itr) -> Integer Returns the index of the maximum element in a collection -.. function:: indmin(itr) +.. function:: indmin(itr) -> Integer Returns the index of the minimum element in a collection -.. function:: findmax(iter) +.. function:: findmax(itr) -> (x, index) - Returns a tuple of the maximum element and its index + Returns the maximum element and its index -.. function:: findmin(iter) +.. function:: findmin(itr) -> (x, index) - Returns a tuple of the minimum element and its index + Returns the minimum element and its index .. function:: sum(itr) - Sum elements of a collection + Returns the sum of all elements in a collection .. function:: prod(itr) - Multiply elements of a collection + Returns the product of all elements of a collection -.. function:: any(itr) +.. function:: any(itr) -> Bool Test whether any elements of a boolean collection are true -.. function:: all(itr) +.. function:: all(itr) -> Bool Test whether all elements of a boolean collection are true -.. function:: count(itr) +.. function:: count(itr) -> Integer - Count the number of boolean elements in ``itr`` which are ``true`` rather than ``false``. + Count the number of boolean elements in ``itr`` which are true. -.. function:: countp(p, itr) +.. function:: countp(p, itr) -> Integer Count the number of elements in ``itr`` for which predicate ``p`` is true. -.. function:: anyp(p, itr) +.. function:: any(p, itr) -> Bool Determine whether any element of ``itr`` satisfies the given predicate. -.. function:: allp(p, itr) +.. function:: all(p, itr) -> Bool Determine whether all elements of ``itr`` satisfy the given predicate. -.. function:: map(f, c) +.. function:: map(f, c) -> collection + + Transform collection ``c`` by applying ``f`` to each element. + + **Example**: ``map((x) -> x * 2, [1, 2, 3]) = [2, 4, 6]`` + +.. function:: map!(function, collection) + + In-place version of :func:`map`. + +.. function:: mapreduce(f, op, itr) - Transform collection ``c`` by applying ``f`` to each element + Applies function ``f`` to each element in ``itr`` and then reduces the result using the binary function ``op``. + + **Example**: ``mapreduce(x->x^2, +, [1:3]) == 1 + 4 + 9 == 14`` + +.. function:: first(coll) + + Get the first element of an ordered collection. + +.. function:: last(coll) + + Get the last element of an ordered collection. + +.. function:: collect(collection) + + Return an array of all items in a collection. For associative collections, returns (key, value) tuples. Indexable Collections --------------------- -.. function:: ref(collection, key...) - collection[key...] +.. function:: getindex(collection, key...) Retrieve the value(s) stored at the given key or index within a collection. + The syntax ``a[i,j,...]`` is converted by the compiler to + ``getindex(a, i, j, ...)``. -.. function:: assign(collection, value, key...) - collection[key...] = value +.. function:: setindex!(collection, value, key...) Store the given value at the given key or index within a collection. + The syntax ``a[i,j,...] = x`` is converted by the compiler to + ``setindex!(a, x, i, j, ...)``. Fully implemented by: ``Array``, ``DArray``, ``AbstractArray``, ``SubArray``, ``ObjectIdDict``, ``Dict``, ``WeakKeyDict``, ``String``. @@ -304,11 +407,14 @@ Associative Collections ``ObjectIdDict`` is a special hash table where the keys are always object identities. ``WeakKeyDict`` is a hash table implementation where the keys are weak references to objects, and thus may be garbage collected even when referenced in a hash table. -Dicts can be created using a literal syntax: ``{"A"=>1, "B"=>2}`` +Dicts can be created using a literal syntax: ``{"A"=>1, "B"=>2}``. Use of curly brackets will create a ``Dict`` of type ``Dict{Any,Any}``. Use of square brackets will attempt to infer type information from the keys and values (i.e. ``["A"=>1, "B"=>2]`` creates a ``Dict{ASCIIString, Int64}``). To explicitly specify types use the syntax: ``(KeyType=>ValueType)[...]``. For example, ``(ASCIIString=>Int32)["A"=>1, "B"=>2]``. + +As with arrays, ``Dicts`` may be created with comprehensions. For example, +``{i => f(i) for i = 1:10}``. -.. function:: Dict{K,V}(n) +.. function:: Dict{K,V}() - Construct a hashtable with keys of type K and values of type V and intial size of n + Construct a hashtable with keys of type K and values of type V .. function:: has(collection, key) @@ -318,13 +424,13 @@ Dicts can be created using a literal syntax: ``{"A"=>1, "B"=>2}`` Return the value stored for the given key, or the given default value if no mapping for the key is present. -.. function:: del(collection, key) +.. function:: getkey(collection, key, default) - Delete the mapping for the given key in a collection. + Return the key matching argument ``key`` if one exists in ``collection``, otherwise return ``default``. -.. function:: del_all(collection) +.. function:: delete!(collection, key) - Delete all keys from a collection. + Delete the mapping for the given key in a collection. .. function:: keys(collection) @@ -334,10 +440,6 @@ Dicts can be created using a literal syntax: ``{"A"=>1, "B"=>2}`` Return an array of all values in a collection. -.. function:: pairs(collection) - - Return an array of all (key, value) tuples in a collection. - .. function:: merge(collection, others...) Construct a merged collection from the given collections. @@ -354,17 +456,29 @@ Dicts can be created using a literal syntax: ``{"A"=>1, "B"=>2}`` Update collection, removing (key, value) pairs for which function is false. +.. function:: eltype(collection) + + Returns the type tuple of the (key,value) pairs contained in collection. + +.. function:: sizehint(s, n) + + Suggest that collection ``s`` reserve capacity for at least ``n`` elements. This can improve performance. + Fully implemented by: ``ObjectIdDict``, ``Dict``, ``WeakKeyDict``. -Partially implemented by: ``IntSet``, ``Set``, ``EnvHash``, ``FDSet``, ``Array``. +Partially implemented by: ``IntSet``, ``Set``, ``EnvHash``, ``Array``. Set-Like Collections -------------------- -.. function:: add(collection, key) +.. function:: add!(collection, key) Add an element to a set-like collection. +.. function:: add_each!(collection, iterable) + + Adds each element in iterable to the collection. + .. function:: Set(x...) Construct a ``Set`` with the given elements. Should be used instead of ``IntSet`` for sparse integer sets. @@ -373,48 +487,94 @@ Set-Like Collections Construct an ``IntSet`` of the given integers. Implemented as a bit string, and therefore good for dense integer sets. -.. function:: choose(s) +.. function:: union(s1,s2...) + + Construct the union of two or more sets. Maintains order with arrays. + +.. function:: union!(s1,s2) + + Constructs the union of IntSets s1 and s2, stores the result in ``s1``. + +.. function:: intersect(s1,s2...) + + Construct the intersection of two or more sets. Maintains order with arrays. + +.. function:: setdiff(s1,s2) + + Construct the set of elements in ``s1`` but not ``s2``. Maintains order with arrays. + +.. function:: symdiff(s1,s2...) + + Construct the symmetric difference of elements in the passed in sets or arrays. Maintains order with arrays. + +.. function:: symdiff!(s, n) + + IntSet s is destructively modified to toggle the inclusion of integer ``n``. + +.. function:: symdiff!(s, itr) - Pick an element of a set + For each element in ``itr``, destructively toggle its inclusion in set ``s``. -.. function:: union(s1,s2) +.. function:: symdiff!(s1, s2) - Construct the union of two sets + Construct the symmetric difference of IntSets ``s1`` and ``s2``, storing the result in ``s1``. -Fully implemented by: ``IntSet``, ``Set``, ``FDSet``. +.. function:: complement(s) + + Returns the set-complement of IntSet s. + +.. function:: complement!(s) + + Mutates IntSet s into its set-complement. + +.. function:: del_each!(s, itr) + + Deletes each element of itr in set s in-place. + +.. function:: intersect!(s1, s2) + + Intersects IntSets s1 and s2 and overwrites the set s1 with the result. If needed, s1 will be expanded to the size of s2. + +Fully implemented by: ``IntSet``, ``Set``. + +Partially implemented by: ``Array``. Dequeues -------- -.. function:: push(collection, item) +.. function:: push!(collection, item) -> collection Insert an item at the end of a collection. -.. function:: pop(collection) +.. function:: pop!(collection) -> item Remove the last item in a collection and return it. -.. function:: enqueue(collection, item) +.. function:: unshift!(collection, item) -> collection - Insert an item at the beginning of a collection. Also called ``unshift``. + Insert an item at the beginning of a collection. -.. function:: shift(collection) +.. function:: shift!(collection) -> item - Remove the first item in a collection and return it. + Remove the first item in a collection. -.. function:: insert(collection, index, item) +.. function:: insert!(collection, index, item) Insert an item at the given index. -.. function:: del(collection, index) +.. function:: delete!(collection, index) -> item + + Remove the item at the given index, and return the deleted item. - Remove the item at the given index. +.. function:: delete!(collection, range) -> items + + Remove items at specified range, and return a collection containing the deleted items. -.. function:: grow(collection, n) +.. function:: resize!(collection, n) -> collection - Add uninitialized space for ``n`` elements at the end of a collection. + Resize collection to contain ``n`` elements. -.. function:: append!(collection, items) +.. function:: append!(collection, items) -> collection Add the elements of ``items`` to the end of a collection. @@ -423,33 +583,33 @@ Fully implemented by: ``Vector`` (aka 1-d ``Array``). Strings ------- -.. function:: strlen(s) +.. function:: length(s) The number of characters in string ``s``. -.. function:: length(s) +.. function:: *(s, t) - The last valid index for string ``s``. Indexes are byte offsets and not character numbers. + Concatenate strings. -.. function:: chars(string) + **Example**: ``"Hello " * "world" == "Hello world"`` - Return an array of the characters in ``string``. +.. function:: ^(s, n) -.. function:: strcat(strs...) + Repeat string ``s`` ``n`` times. - Concatenate strings. + **Example**: ``"Julia "^3 == "Julia Julia Julia "`` -.. function:: string(char...) +.. function:: string(xs...) - Create a string with the given characters. + Create a string from any values using the ``print`` function. -.. function:: string(x) +.. function:: repr(x) Create a string from any value using the ``show`` function. .. function:: bytestring(::Ptr{Uint8}) - Create a string from the address of a C (0-terminated) string. + Create a string from the address of a C (0-terminated) string. A copy is made; the ptr can be safely freed. .. function:: bytestring(s) @@ -471,9 +631,21 @@ Strings Convert a string to a contiguous UTF-8 string (all characters must be valid UTF-8 characters). -.. function:: strchr(string, char[, i]) +.. function:: is_valid_ascii(s) -> Bool - Return the index of ``char`` in ``string``, giving 0 if not found. The second argument may also be a vector or a set of characters. The third argument optionally specifies a starting index. + Returns true if the string or byte vector is valid ASCII, false otherwise. + +.. function:: is_valid_utf8(s) -> Bool + + Returns true if the string or byte vector is valid UTF-8, false otherwise. + +.. function:: is_valid_char(c) -> Bool + + Returns true if the given char or integer is a valid Unicode code point. + +.. function:: ismatch(r::Regex, s::String) + + Test whether a string contains a match of the given regular expression. .. function:: lpad(string, n, p) @@ -483,31 +655,35 @@ Strings Make a string at least ``n`` characters long by padding on the right with copies of ``p``. -.. function:: search(string, chars[, start]) +.. function:: search(string, chars, [start]) + + Search for the given characters within the given string. The second argument may be a single character, a vector or a set of characters, a string, or a regular expression (though regular expressions are only allowed on contiguous strings, such as ASCII or UTF-8 strings). The third argument optionally specifies a starting index. The return value is a range of indexes where the matching sequence is found, such that ``s[search(s,x)] == x``. The return value is ``0:-1`` if there is no match. + +.. function:: replace(string, pat, r[, n]) - Search for the given characters within the given string. The second argument may be a single character, a vector or a set of characters, a string, or a regular expression (but regular expressions are only allowed on contiguous strings, such as ASCII or UTF-8 strings). The third argument optionally specifies a starting index. The return value is a tuple with 2 integers: the index of the match and the first valid index past the match (or an index beyond the end of the string if the match is at the end); it returns ``(0,0)`` if no match was found, and ``(start,start)`` if ``chars`` is empty. + Search for the given pattern ``pat``, and replace each occurance with ``r``. If ``n`` is provided, replace at most ``n`` occurances. As with search, the second argument may be a single character, a vector or a set of characters, a string, or a regular expression. If ``r`` is a function, each occurrence is replaced with ``r(s)`` where ``s`` is the matched substring. -.. function:: split(string, chars[, limit][, include_empty]) +.. function:: split(string, [chars, [limit,] [include_empty]]) - Return an array of strings by splitting the given string on occurrences of the given character delimiters, which may be specified in any of the formats allowed by ``search``'s second argument. The last two arguments are optional; they are are a maximum size for the result and a flag determining whether empty fields should be included in the result. + Return an array of strings by splitting the given string on occurrences of the given character delimiters, which may be specified in any of the formats allowed by ``search``'s second argument (i.e. a single character, collection of characters, string, or regular expression). If ``chars`` is omitted, it defaults to the set of all space characters, and ``include_empty`` is taken to be false. The last two arguments are also optional: they are are a maximum size for the result and a flag determining whether empty fields should be included in the result. -.. function:: strip(string) +.. function:: strip(string, [chars]) - Return ``string`` with any leading and trailing whitespace removed. + Return ``string`` with any leading and trailing whitespace removed. If a string ``chars`` is provided, instead remove characters contained in that string. -.. function:: lstrip(string) +.. function:: lstrip(string, [chars]) - Return ``string`` with any leading whitespace removed. + Return ``string`` with any leading whitespace removed. If a string ``chars`` is provided, instead remove characters contained in that string. -.. function:: rstrip(string) +.. function:: rstrip(string, [chars]) - Return ``string`` with any trailing whitespace removed. + Return ``string`` with any trailing whitespace removed. If a string ``chars`` is provided, instead remove characters contained in that string. -.. function:: begins_with(string, prefix) +.. function:: beginswith(string, prefix) Returns ``true`` if ``string`` starts with ``prefix``. -.. function:: ends_with(string, suffix) +.. function:: endswith(string, suffix) Returns ``true`` if ``string`` ends with ``suffix``. @@ -539,30 +715,112 @@ Strings Convert a character index to a byte index +.. function:: isvalid(str, i) + + Tells whether index ``i`` is valid for the given string + +.. function:: nextind(str, i) + + Get the next valid string index after ``i``. Returns ``endof(str)+1`` at + the end of the string. + +.. function:: prevind(str, i) + + Get the previous valid string index before ``i``. Returns ``0`` at + the beginning of the string. + +.. function:: thisind(str, i) + + Adjust ``i`` downwards until it reaches a valid index for the given string. + .. function:: randstring(len) Create a random ASCII string of length ``len``, consisting of upper- and lower-case letters and the digits 0-9 +.. function:: charwidth(c) + + Gives the number of columns needed to print a character. + +.. function:: strwidth(s) + + Gives the number of columns needed to print a string. + +.. function:: isalnum(c::Char) + + Tests whether a character is alphanumeric. + +.. function:: isalpha(c::Char) + + Tests whether a character is alphabetic. + +.. function:: isascii(c::Char) + + Tests whether a character belongs to the ASCII character set. + +.. function:: isblank(c::Char) + + Tests whether a character is a tab or space. + +.. function:: iscntrl(c::Char) + + Tests whether a character is a control character. + +.. function:: isdigit(c::Char) + + Tests whether a character is a numeric digit (0-9). + +.. function:: isgraph(c::Char) + + Tests whether a character is printable, and not a space. + +.. function:: islower(c::Char) + + Tests whether a character is a lowercase letter. + +.. function:: isprint(c::Char) + + Tests whether a character is printable, including space. + +.. function:: ispunct(c::Char) + + Tests whether a character is printable, and not a space or alphanumeric. + +.. function:: isspace(c::Char) + + Tests whether a character is any whitespace character. + +.. function:: isupper(c::Char) + + Tests whether a character is an uppercase letter. + +.. function:: isxdigit(c::Char) + + Tests whether a character is a valid hexadecimal digit. + I/O --- -.. data:: stdout_stream +.. data:: STDOUT Global variable referring to the standard out stream. -.. data:: stderr_stream +.. data:: STDERR Global variable referring to the standard error stream. -.. data:: stdin_stream +.. data:: STDIN Global variable referring to the standard input stream. -.. function:: open(file_name[, read, write, create, truncate, append]) +.. data:: OUTPUT_STREAM + + The default stream used for text output, e.g. in the ``print`` and ``show`` functions. + +.. function:: open(file_name, [read, write, create, truncate, append]) -> IOStream Open a file in a mode specified by five boolean arguments. The default is to open files for reading only. Returns a stream for accessing the file. -.. function:: open(file_name[, mode]) +.. function:: open(file_name, [mode]) -> IOStream Alternate syntax for open, where a string-based mode specifier is used instead of the five booleans. The values of ``mode`` correspond to those from ``fopen(3)`` or Perl ``open``, and are equivalent to setting the following boolean groups: @@ -575,13 +833,20 @@ I/O a+ read, write, create, append ==== ================================= -.. function:: memio([size]) + +.. function:: open(f::function, args...) + + Apply the function ``f`` to the result of ``open(args...)`` and close the resulting file descriptor upon completion. + + **Example**: ``open(readall, "file.txt")`` + +.. function:: memio([size[, finalize::Bool]]) -> IOStream Create an in-memory I/O stream, optionally specifying how much initial space is needed. -.. function:: fdio(descriptor[, own]) +.. function:: fdio([name::String, ]fd::Integer[, own::Bool]) -> IOStream - Create an ``IOStream`` object from an integer file descriptor. If ``own`` is true, closing this object will close the underlying descriptor. By default, an ``IOStream`` is closed when it is garbage collected. + Create an ``IOStream`` object from an integer file descriptor. If ``own`` is true, closing this object will close the underlying descriptor. By default, an ``IOStream`` is closed when it is garbage collected. ``name`` allows you to associate the descriptor with a named file. .. function:: flush(stream) @@ -619,6 +884,32 @@ I/O Seek a stream relative to the current position. +.. function:: eof(stream) + + Tests whether an I/O stream is at end-of-file. If the stream is not yet + exhausted, this function will block to wait for more data if necessary, and + then return ``false``. Therefore it is always safe to read one byte after + seeing ``eof`` return ``false``. + +.. function:: ntoh(x) + + Converts the endianness of a value from Network byte order (big-endian) to + that used by the Host. + +.. function:: hton(x) + + Converts the endianness of a value from that used by the Host to Network + byte order (big-endian). + +.. function:: ltoh(x) + + Converts the endianness of a value from Little-endian to that used by the + Host. + +.. function:: htol(x) + + Converts the endianness of a value from that used by the Host to + Little-endian. Text I/O -------- @@ -633,7 +924,15 @@ Text I/O .. function:: println(x) - Print (using ``print``) ``x`` followed by a newline + Print (using :func:`print`) ``x`` followed by a newline + +.. function:: @printf([io::IOStream], "%Fmt", args...) + + Print arg(s) using C ``printf()`` style format specification string. Optionally, an IOStream may be passed as the first argument to redirect output. + +.. function:: @sprintf("%Fmt", args...) + + Return ``@printf`` formatted output as string. .. function:: showall(x) @@ -659,34 +958,34 @@ Text I/O Read all lines as an array. -.. function:: EachLine(stream) +.. function:: eachline(stream) Create an iterable object that will yield each line from a stream. -.. function:: dlmread(filename, delim::Char) +.. function:: readdlm(filename, delim::Char) Read a matrix from a text file where each line gives one row, with elements separated by the given delimeter. If all data is numeric, the result will be a numeric array. If some elements cannot be parsed as numbers, a cell array of numbers and strings is returned. -.. function:: dlmread(filename, delim::Char, T::Type) +.. function:: readdlm(filename, delim::Char, T::Type) Read a matrix from a text file with a given element type. If ``T`` is a numeric type, the result is an array of that type, with any non-numeric elements as ``NaN`` for floating-point types, or zero. Other useful values of ``T`` include ``ASCIIString``, ``String``, and ``Any``. -.. function:: dlmwrite(filename, array, delim::Char) +.. function:: writedlm(filename, array, delim::Char) Write an array to a text file using the given delimeter (defaults to comma). -.. function:: csvread(filename[, T::Type]) +.. function:: readcsv(filename, [T::Type]) - Equivalent to ``dlmread`` with ``delim`` set to comma. + Equivalent to ``readdlm`` with ``delim`` set to comma. -.. function:: csvwrite(filename, array) +.. function:: writecsv(filename, array) - Equivalent to ``dlmwrite`` with ``delim`` set to comma. + Equivalent to ``writedlm`` with ``delim`` set to comma. Memory-mapped I/O ----------------- -.. function:: mmap_array(type, dims, stream[, offset]) +.. function:: mmap_array(type, dims, stream, [offset]) Create an array whose values are linked to a file, using memory-mapping. This provides a convenient way of working with data too large to fit in the computer's memory. @@ -694,7 +993,7 @@ Memory-mapped I/O The file is specified via the stream. When you initialize the stream, use "r" for a "read-only" array, and "w+" to create a new array used to write values to disk. Optionally, you can specify an offset (in bytes) if, for example, you want to skip over a header in the file. - Example: A = mmap_array(Int64, (25,30000), s) + **Example**: A = mmap_array(Int64, (25,30000), s) This would create a 25-by-30000 array of Int64s, linked to the file associated with stream s. @@ -718,177 +1017,357 @@ Standard Numeric Types Mathematical Functions ---------------------- -.. function:: - +.. function:: -(x) + + Unary minus operator. + +.. function:: +(x, y) + + Binary addition operator. + +.. function:: -(x, y) + + Binary subtraction operator. + +.. function:: *(x, y) + + Binary multiplication operator. + +.. function:: /(x, y) + + Binary left-division operator. + +.. function:: \\(x, y) + + Binary right-division operator. - Unary minus +.. function:: ^(x, y) -.. function:: + - * / \\ ^ + Binary exponentiation operator. - The binary addition, subtraction, multiplication, left division, right division, and exponentiation operators +.. function:: .+(x, y) -.. function:: .* ./ .\\ .^ + Element-wise binary addition operator. - The element-wise binary addition, subtraction, multiplication, left division, right division, and exponentiation operators +.. function:: .-(x, y) -.. function:: div + Element-wise binary subtraction operator. - Integer truncating division +.. function:: .*(x, y) -.. function:: fld + Element-wise binary multiplication operator. - Integer floor division +.. function:: ./(x, y) -.. function:: mod + Element-wise binary left division operator. - Modulus after division +.. function:: .\\(x, y) -.. function:: rem % + Element-wise binary right division operator. + +.. function:: .^(x, y) + + Element-wise binary exponentiation operator. + +.. function:: div(a,b) + + Compute a/b, truncating to an integer + +.. function:: fld(a,b) + + Largest integer less than or equal to a/b + +.. function:: mod(x,m) + + Modulus after division, returning in the range [0,m) + +.. function:: rem(x, m) Remainder after division -.. function:: // +.. function:: %(x, m) + + Remainder after division. The operator form of ``rem``. + +.. function:: mod1(x,m) + + Modulus after division, returning in the range (0,m] + +.. function:: //(num, den) Rational division -.. function:: << >> +.. function:: num(x) + + Numerator of the rational representation of ``x`` + +.. function:: den(x) - Left and right shift operators + Denominator of the rational representation of ``x`` -.. function:: == != < <= > >= +.. function:: <<(x, n) - Comparison operators to test equals, not equals, less than, less than or equals, greater than, and greater than or equals + Left shift operator. -.. function:: ! +.. function:: >>(x, n) + + Right shift operator. + +.. function:: >>>(x, n) + + Unsigned right shift operator. + +.. function:: :(start, [step], stop) + + Range operator. ``a:b`` constructs a range from ``a`` to ``b`` with a step size of 1, + and ``a:s:b`` is similar but uses a step size of ``s``. These syntaxes call the + function ``colon``. + The colon is also used in indexing to select whole dimensions. + +.. function:: colon(start, [step], stop) + + Called by ``:`` syntax for constructing ranges. + +.. function:: ==(x, y) + + Equality comparison operator. + +.. function:: !=(x, y) + + Not-equals comparison operator. + +.. function:: <(x, y) + + Less-than comparison operator. + +.. function:: <=(x, y) + + Less-than-or-equals comparison operator. + +.. function:: >(x, y) + + Greater-than comparison operator. + +.. function:: >=(x, y) + + Greater-than-or-equals comparison operator. + +.. function:: .==(x, y) + + Element-wise equality comparison operator. + +.. function:: .!=(x, y) + + Element-wise not-equals comparison operator. + +.. function:: .<(x, y) + + Element-wise less-than comparison operator. + +.. function:: .<=(x, y) + + Element-wise less-than-or-equals comparison operator. + +.. function:: .>(x, y) + + Element-wise greater-than comparison operator. + +.. function:: .>=(x, y) + + Element-wise greater-than-or-equals comparison operator. + +.. function:: cmp(x,y) + + Return -1, 0, or 1 depending on whether ``xy``, respectively + +.. function:: !(x) Boolean not -.. function:: ~ +.. function:: ~(x) - Boolean or bitwise not + Bitwise not -.. function:: & +.. function:: &(x, y) Bitwise and -.. function:: | +.. function:: |(x, y) Bitwise or -.. function:: $ +.. function:: $(x, y) Bitwise exclusive or .. function:: sin(x) - Compute sine of ``x`` + Compute sine of ``x``, where ``x`` is in radians .. function:: cos(x) - Compute cosine of ``x`` + Compute cosine of ``x``, where ``x`` is in radians .. function:: tan(x) - Compute tangent of ``x`` + Compute tangent of ``x``, where ``x`` is in radians + +.. function:: sind(x) + + Compute sine of ``x``, where ``x`` is in degrees + +.. function:: cosd(x) + + Compute cosine of ``x``, where ``x`` is in degrees + +.. function:: tand(x) + + Compute tangent of ``x``, where ``x`` is in degrees .. function:: sinh(x) - Compute hyperbolic sine of ``x`` specified in radians + Compute hyperbolic sine of ``x`` .. function:: cosh(x) - Compute hyperbolic cosine of ``x`` specified in radians + Compute hyperbolic cosine of ``x`` .. function:: tanh(x) - Compute hyperbolic tangent of ``x`` specified in radians + Compute hyperbolic tangent of ``x`` .. function:: asin(x) - Compute the inverse sine of ``x`` specified in radians + Compute the inverse sine of ``x``, where the output is in radians .. function:: acos(x) - Compute the inverse cosine of ``x`` specified in radians + Compute the inverse cosine of ``x``, where the output is in radians .. function:: atan(x) - Compute the inverse tangent of ``x`` specified in radians + Compute the inverse tangent of ``x``, where the output is in radians -.. function:: atan2(x, y) +.. function:: atan2(y, x) Compute the inverse tangent of ``y/x``, using the signs of both ``x`` and ``y`` to determine the quadrant of the return value. +.. function:: asind(x) + + Compute the inverse sine of ``x``, where the output is in degrees + +.. function:: acosd(x) + + Compute the inverse cosine of ``x``, where the output is in degrees + +.. function:: atand(x) + + Compute the inverse tangent of ``x``, where the output is in degrees + .. function:: sec(x) - Compute the secant of ``x`` specified in radians + Compute the secant of ``x``, where ``x`` is in radians .. function:: csc(x) - Compute the cosecant of ``x`` specified in radians + Compute the cosecant of ``x``, where ``x`` is in radians .. function:: cot(x) - Compute the cotangent of ``x`` specified in radians + Compute the cotangent of ``x``, where ``x`` is in radians + +.. function:: secd(x) + + Compute the secant of ``x``, where ``x`` is in degrees + +.. function:: cscd(x) + + Compute the cosecant of ``x``, where ``x`` is in degrees + +.. function:: cotd(x) + + Compute the cotangent of ``x``, where ``x`` is in degrees .. function:: asec(x) - Compute the inverse secant of ``x`` specified in radians + Compute the inverse secant of ``x``, where the output is in radians .. function:: acsc(x) - Compute the inverse cosecant of ``x`` specified in radians + Compute the inverse cosecant of ``x``, where the output is in radians .. function:: acot(x) - Compute the inverse cotangent of ``x`` specified in radians + Compute the inverse cotangent of ``x``, where the output is in radians + +.. function:: asecd(x) + + Compute the inverse secant of ``x``, where the output is in degrees + +.. function:: acscd(x) + + Compute the inverse cosecant of ``x``, where the output is in degrees + +.. function:: acotd(x) + + Compute the inverse cotangent of ``x``, where the output is in degrees .. function:: sech(x) - Compute the hyperbolic secant of ``x`` specified in radians + Compute the hyperbolic secant of ``x`` .. function:: csch(x) - Compute the hyperbolic cosecant of ``x`` specified in radians + Compute the hyperbolic cosecant of ``x`` .. function:: coth(x) - Compute the hyperbolic cotangent of ``x`` specified in radians + Compute the hyperbolic cotangent of ``x`` .. function:: asinh(x) - Compute the inverse hyperbolic sine of ``x`` specified in radians + Compute the inverse hyperbolic sine of ``x`` .. function:: acosh(x) - Compute the inverse hyperbolic cosine of ``x`` specified in radians + Compute the inverse hyperbolic cosine of ``x`` .. function:: atanh(x) - Compute the inverse hyperbolic cotangent of ``x`` specified in radians + Compute the inverse hyperbolic cotangent of ``x`` .. function:: asech(x) - Compute the inverse hyperbolic secant of ``x`` specified in radians + Compute the inverse hyperbolic secant of ``x`` .. function:: acsch(x) - Compute the inverse hyperbolic cosecant of ``x`` specified in radians + Compute the inverse hyperbolic cosecant of ``x`` .. function:: acoth(x) - Compute the inverse hyperbolic cotangent of ``x`` specified in radians + Compute the inverse hyperbolic cotangent of ``x`` .. function:: sinc(x) - Compute :math:`sin(\pi x) / x` + Compute :math:`\sin(\pi x) / (\pi x)` if :math:`x \neq 0`, and :math:`1` if :math:`x = 0`. .. function:: cosc(x) - Compute :math:`cos(\pi x) / x` + Compute :math:`\cos(\pi x) / x - \sin(\pi x) / (\pi x^2)` if :math:`x \neq 0`, and :math:`0` + if :math:`x = 0`. This is the derivative of ``sinc(x)``. + +.. function:: degrees2radians(x) + + Convert ``x`` from degrees to radians + +.. function:: radians2degrees(x) + + Convert ``x`` from radians to degrees .. function:: hypot(x, y) - Compute the :math:`\sqrt{(x^2+y^2)}` without undue overflow or underflow + Compute the :math:`\sqrt{x^2+y^2}` without undue overflow or underflow .. function:: log(x) @@ -906,14 +1385,6 @@ Mathematical Functions Accurate natural logarithm of ``1+x`` -.. function:: logb(x) - - Return the exponent of x, represented as a floating-point number - -.. function:: ilogb(x) - - Return the exponent of x, represented as a signed integer value - .. function:: frexp(val, exp) Return a number ``x`` such that it has a magnitude in the interval ``[1/2, 1)`` or 0, @@ -931,23 +1402,32 @@ Mathematical Functions Compute :math:`x \times 2^n` +.. function:: modf(x) + + Return a tuple (fpart,ipart) of the fractional and integral parts of a + number. Both parts have the same sign as the argument. + .. function:: expm1(x) Accurately compute :math:`e^x-1` -.. function:: round(x[, digits[, base]]) -> FloatingPoint +.. function:: square(x) + + Compute :math:`x^2` + +.. function:: round(x, [digits, [base]]) -> FloatingPoint ``round(x)`` returns the nearest integer to ``x``. ``round(x, digits)`` rounds to the specified number of digits after the decimal place, or before if negative, e.g., ``round(pi,2)`` is ``3.14``. ``round(x, digits, base)`` rounds using a different base, defaulting to 10, e.g., ``round(pi, 3, 2)`` is ``3.125``. -.. function:: ceil(x[, digits[, base]]) -> FloatingPoint +.. function:: ceil(x, [digits, [base]]) -> FloatingPoint Returns the nearest integer not less than ``x``. ``digits`` and ``base`` work as above. -.. function:: floor(x[, digits[, base]]) -> FloatingPoint +.. function:: floor(x, [digits, [base]]) -> FloatingPoint Returns the nearest integer not greater than ``x``. ``digits`` and ``base`` work as above. -.. function:: trunc(x[, digits[, base]]) -> FloatingPoint +.. function:: trunc(x, [digits, [base]]) -> FloatingPoint Returns the nearest integer not greater in magnitude than ``x``. ``digits`` and ``base`` work as above. @@ -967,7 +1447,7 @@ Mathematical Functions Returns the nearest integer not greater in magnitude than ``x``. -.. function:: signif(x, digits[, base]) -> FloatingPoint +.. function:: signif(x, digits, [base]) -> FloatingPoint Rounds (in the sense of ``round``) ``x`` so that there are ``digits`` significant digits, under a base ``base`` representation, default 10. E.g., ``signif(123.456, 2)`` is ``120.0``, and ``signif(357.913, 4, 2)`` is ``352.0``. @@ -1001,7 +1481,11 @@ Mathematical Functions .. function:: signbit(x) - Returns non-zero if the value of the sign of ``x`` is negative, otherwise ``0``. + Returns ``1`` if the value of the sign of ``x`` is negative, otherwise ``0``. + +.. function:: flipsign(x, y) + + Return ``x`` with its sign flipped if ``y`` is negative. For example ``abs(x) = flipsign(x,x)``. .. function:: sqrt(x) @@ -1013,11 +1497,31 @@ Mathematical Functions .. function:: erf(x) - Compute the error function of ``x`` + Compute the error function of ``x``, defined by + :math:`\frac{2}{\sqrt{\pi}} \int_0^x e^{-t^2} dt` + for arbitrary complex ``x``. .. function:: erfc(x) - Compute the complementary error function of ``x`` + Compute the complementary error function of ``x``, + defined by :math:`1 - \operatorname{erf}(x)`. + +.. function:: erfcx(x) + + Compute the scaled complementary error function of ``x``, + defined by :math:`e^{x^2} \operatorname{erfc}(x)`. Note + also that :math:`\operatorname{erfcx}(-ix)` computes the + Faddeeva function :math:`w(x)`. + +.. function:: erfi(x) + + Compute the imaginary error function of ``x``, + defined by :math:`-i \operatorname{erf}(ix)`. + +.. function:: dawson(x) + + Compute the Dawson function (scaled imaginary error function) of ``x``, + defined by :math:`\frac{\sqrt{\pi}}{2} e^{-x^2} \operatorname{erfi}(x)`. .. function:: real(z) @@ -1027,6 +1531,10 @@ Mathematical Functions Return the imaginary part of the complex number ``z`` +.. function:: reim(z) + + Return both the real and imaginary parts of the complex number ``z`` + .. function:: conj(z) Compute the complex conjugate of a complex number ``z`` @@ -1051,6 +1559,12 @@ Mathematical Functions Compute ``factorial(n)/factorial(k)`` +.. function:: factor(n) + + Compute the prime factorization of an integer ``n``. Returns a dictionary. The keys of the dictionary correspond to the factors, and hence are of the same type as ``n``. The value associated with each key indicates the number of times the factor appears in the factorization. + + **Example**: :math:`100=2*2*5*5`; then, ``factor(100) -> [5=>2,2=>2]`` + .. function:: gcd(x,y) Greatest common divisor @@ -1059,10 +1573,22 @@ Mathematical Functions Least common multiple +.. function:: gcdx(x,y) + + Greatest common divisor, also returning integer coefficients ``u`` and ``v`` that solve ``ux+vy == gcd(x,y)`` + +.. function:: ispow2(n) + + Test whether ``n`` is a power of two + .. function:: nextpow2(n) Next power of two not less than ``n`` +.. function:: prevpow2(n) + + Previous power of two not greater than ``n`` + .. function:: nextpow(a, n) Next power of ``a`` not less than ``n`` @@ -1079,21 +1605,43 @@ Mathematical Functions Previous integer not greater than ``n`` that can be written ``a^i1 * b^i2 * c^i3`` for integers ``i1``, ``i2``, ``i3``. +.. function:: invmod(x,m) + + Inverse of ``x``, modulo ``m`` + .. function:: powermod(x, p, m) Compute ``mod(x^p, m)`` .. function:: gamma(x) + + Compute the gamma function of ``x`` + .. function:: lgamma(x) + + Compute the logarithm of ``gamma(x)`` + .. function:: lfact(x) -.. function:: airy(x) - airyai(x) + Compute the logarithmic factorial of ``x`` + +.. function:: digamma(x) + + Compute the digamma function of ``x`` (the logarithmic derivative of ``gamma(x)``) + +.. function:: airy(k,x) + + kth derivative of the Airy function :math:`\operatorname{Ai}(x)`. + +.. function:: airyai(x) Airy function :math:`\operatorname{Ai}(x)`. .. function:: airyprime(x) - airyaiprime(x) + + Airy function derivative :math:`\operatorname{Ai}'(x)`. + +.. function:: airyaiprime(x) Airy function derivative :math:`\operatorname{Ai}'(x)`. @@ -1161,38 +1709,82 @@ Mathematical Functions Riemann zeta function :math:`\zeta(s)`. +.. function:: bitmix(x, y) + + Hash two integers into a single integer. Useful for constructing hash + functions. + +.. function:: ndigits(n, b) + + Compute the number of digits in number ``n`` written in base ``b``. Data Formats ------------ -.. function:: bin(n[, pad]) +.. function:: bin(n, [pad]) Convert an integer to a binary string, optionally specifying a number of digits to pad to. -.. function:: hex(n[, pad]) +.. function:: hex(n, [pad]) Convert an integer to a hexadecimal string, optionally specifying a number of digits to pad to. -.. function:: dec(n[, pad]) +.. function:: dec(n, [pad]) Convert an integer to a decimal string, optionally specifying a number of digits to pad to. -.. function:: oct(n[, pad]) +.. function:: oct(n, [pad]) Convert an integer to an octal string, optionally specifying a number of digits to pad to. -.. function:: base(b, n[, pad]) +.. function:: base(base, n, [pad]) + + Convert an integer to a string in the given base, optionally specifying a number of digits to pad to. The base can be specified as either an integer, or as a ``Uint8`` array of character values to use as digit symbols. + +.. function:: bits(n) + + A string giving the literal bit representation of a number. - Convert an integer to a string in the given base, optionally specifying a number of digits to pad to. +.. function:: parseint([type], str, [base]) -.. function:: parse_int(type, str, base) + Parse a string as an integer in the given base (default 10), yielding a number of the specified type (default ``Int``). - Parse a string as an integer in the given base, yielding a number of the specified type. +.. function:: parsefloat([type], str) + + Parse a string as a decimal floating point number, yielding a number of the specified type. .. function:: bool(x) Convert a number or numeric array to boolean +.. function:: isbool(x) + + Test whether number or array is boolean + +.. function:: int(x) + + Convert a number or array to the default integer type on your platform. Alternatively, ``x`` can be a string, which is parsed as an integer. + +.. function:: uint(x) + + Convert a number or array to the default unsigned integer type on your platform. Alternatively, ``x`` can be a string, which is parsed as an unsigned integer. + +.. function:: integer(x) + + Convert a number or array to integer type. If ``x`` is already of integer type it is unchanged, otherwise it converts it to the default integer type on your platform. + +.. function:: isinteger(x) + + Test whether a number or array is of integer type + +.. function:: signed(x) + + Convert a number to a signed integer + +.. function:: unsigned(x) + + Convert a number to an unsigned integer + .. function:: int8(x) Convert a number or array to ``Int8`` data type @@ -1209,6 +1801,10 @@ Data Formats Convert a number or array to ``Int64`` data type +.. function:: int128(x) + + Convert a number or array to ``Int128`` data type + .. function:: uint8(x) Convert a number or array to ``Uint8`` data type @@ -1225,6 +1821,10 @@ Data Formats Convert a number or array to ``Uint64`` data type +.. function:: uint128(x) + + Convert a number or array to ``Uint128`` data type + .. function:: float32(x) Convert a number or array to ``Float32`` data type @@ -1233,23 +1833,45 @@ Data Formats Convert a number or array to ``Float64`` data type -.. function:: char(x) +.. function:: float(x) - Convert a number or array to ``Char`` data type + Convert a number, array, or string to a ``FloatingPoint`` data type. For numeric data, the smallest suitable ``FloatingPoint`` type is used. For strings, it converts to ``Float64``. + +.. function:: significand(x) + + Extract the significand(s) (a.k.a. mantissa), in binary representation, of a floating-point number or array. + + For example, ``significand(15.2)/15.2 == 0.125``, and ``significand(15.2)*8 == 15.2`` + +.. function:: exponent(x) -> Int + + Get the exponent of a normalized floating-point number. -.. function:: safe_char(x) +.. function:: float64_valued(x::Rational) - Convert to ``Char``, checking for invalid code points + True if ``x`` can be losslessly represented as a ``Float64`` data type + +.. function:: complex64(r,i) + + Convert to ``r+i*im`` represented as a ``Complex64`` data type + +.. function:: complex128(r,i) + + Convert to ``r+i*im`` represented as a ``Complex128`` data type + +.. function:: char(x) + + Convert a number or array to ``Char`` data type .. function:: complex(r,i) Convert real numbers or arrays to complex -.. function:: iscomplex(x) +.. function:: iscomplex(x) -> Bool Test whether a number or array is of a complex type -.. function:: isreal(x) +.. function:: isreal(x) -> Bool Test whether a number or array is of a real type @@ -1280,23 +1902,59 @@ Numbers The constant pi -.. function:: isdenormal(f) +.. data:: im + + The imaginary unit + +.. data:: e + + The constant e + +.. data:: Inf + + Positive infinity of type Float64 + +.. data:: Inf32 + + Positive infinity of type Float32 + +.. data:: NaN + + A not-a-number value of type Float64 + +.. data:: NaN32 + + A not-a-number value of type Float32 + +.. function:: isdenormal(f) -> Bool Test whether a floating point number is denormal -.. function:: isfinite(f) +.. function:: isfinite(f) -> Bool Test whether a number is finite +.. function:: isinf(f) + + Test whether a number is infinite + .. function:: isnan(f) Test whether a floating point number is not a number (NaN) +.. function:: inf(f) + + Returns infinity in the same floating point type as ``f`` (or ``f`` can by the type itself) + +.. function:: nan(f) + + Returns NaN in the same floating point type as ``f`` (or ``f`` can by the type itself) + .. function:: nextfloat(f) Get the next floating point number in lexicographic order -.. function:: prevfloat(f) +.. function:: prevfloat(f) -> Float Get the previous floating point number in lexicographic order @@ -1308,74 +1966,122 @@ Numbers Test whether ``x`` is numerically equal to some real number -.. function:: exponent(f) +.. function:: BigInt(x) - Get the exponent of a floating-point number + Create an arbitrary precision integer. ``x`` may be an ``Int`` (or anything that can be converted to an ``Int``) or a ``String``. + The usual mathematical operators are defined for this type, and results are promoted to a ``BigInt``. -.. function:: mantissa(f) +.. function:: BigFloat(x) - Get the mantissa of a floating-point number + Create an arbitrary precision floating point number. ``x`` may be an ``Integer``, a ``Float64``, a ``String`` or a ``BigInt``. The + usual mathematical operators are defined for this type, and results are promoted to a ``BigFloat``. -Random Numbers --------------- +Integers +~~~~~~~~ + +.. function:: count_ones(x::Integer) -> Integer + + Number of ones in the binary representation of ``x``. + + **Example**: ``count_ones(7) -> 3`` + +.. function:: count_zeros(x::Integer) -> Integer + + Number of zeros in the binary representation of ``x``. + + **Example**: ``count_zeros(int32(2 ^ 16 - 1)) -> 16`` + +.. function:: leading_zeros(x::Integer) -> Integer + + Number of zeros leading the binary representation of ``x``. + + **Example**: ``leading_zeros(int32(1)) -> 31`` + +.. function:: leading_ones(x::Integer) -> Integer + + Number of ones leading the binary representation of ``x``. + + **Example**: ``leading_ones(int32(2 ^ 32 - 2)) -> 31`` + +.. function:: trailing_zeros(x::Integer) -> Integer + + Number of zeros trailing the binary representation of ``x``. + + **Example**: ``trailing_zeros(2) -> 1`` + +.. function:: trailing_ones(x::Integer) -> Integer + + Number of ones trailing the binary representation of ``x``. + + **Example**: ``trailing_ones(3) -> 2`` + +.. function:: isprime(x::Integer) -> Bool + + Returns ``true`` if ``x`` is prime, and ``false`` otherwise. + + **Example**: ``isprime(3) -> true`` -Random numbers are generated in Julia by calling functions from the `Mersenne Twister library `_ +.. function:: isodd(x::Integer) -> Bool -.. function:: rand + Returns ``true`` if ``x`` is odd (that is, not divisible by 2), and ``false`` otherwise. - Generate a ``Float64`` random number in (0,1) + **Example**: ``isodd(9) -> false`` -.. function:: randf +.. function:: iseven(x::Integer) -> Bool - Generate a ``Float32`` random number in (0,1) + Returns ``true`` is ``x`` is even (that is, divisible by 2), and ``false`` otherwise. -.. function:: randi(Int32|Uint32|Int64|Uint64) + **Example**: ``iseven(1) -> false`` + + +Random Numbers +-------------- - Generate a random integer of the given type +Random number generateion in Julia uses the `Mersenne Twister library `_. Julia has a global RNG, which is used by default. Multiple RNGs can be plugged in using the ``AbstractRNG`` object, which can then be used to have multiple streams of random numbers. Currently, only ``MersenneTwister`` is supported. -.. function:: randi(n) +.. function:: srand([rng], seed) - Generate a random integer from 1 to ``n`` inclusive + Seed the RNG with a ``seed``, which may be an unsigned integer or a vector of unsigned integers. ``seed`` can even be a filename, in which case the seed is read from a file. If the argument ``rng`` is not provided, the default global RNG is seeded. -.. function:: randi(n, dims...) +.. function:: MersenneTwister([seed]) - Generate an array of random integers from 1 to ``n`` inclusive + Create a ``MersenneTwister`` RNG object. Different RNG objects can have their own seeds, which may be useful for generating different streams of random numbers. -.. function:: randi((a,b)) +.. function:: rand() - Generate a random integer in the interval from ``a`` to ``b`` inclusive. The argument is a tuple. + Generate a ``Float64`` random number uniformly in [0,1) -.. function:: randi((a,b), dims...) +.. function:: rand!([rng], A) - Generate an array of random integers in the interval from ``a`` to ``b`` inclusive. The first argument is a tuple. + Populate the array A with random number generated from the specified RNG. -.. function:: randbit +.. function:: rand(rng::AbstractRNG, [dims...]) - Generate ``1`` or ``0`` at random + Generate a random ``Float64`` number or array of the size specified by dims, using the specified RNG object. Currently, ``MersenneTwister`` is the only available Random Number Generator (RNG), which may be seeded using srand. -.. function:: randbool +.. function:: rand(dims or [dims...]) - Generate a random boolean value + Generate a random ``Float64`` array of the size specified by dims -.. function:: randn +.. function:: rand(Int32|Uint32|Int64|Uint64|Int128|Uint128, [dims...]) - Generate a normally-distributed random number with mean 0 and standard deviation 1 + Generate a random integer of the given type. Optionally, generate an array of random integers of the given type by specifying dims. -.. function:: randg(a) +.. function:: rand(r, [dims...]) - Generate a sample from the gamma distribution with shape parameter ``a`` + Generate a random integer from the inclusive interval specified by ``Range1 r`` (for example, ``1:n``). Optionally, generate a random integer array. -.. function:: randchi2(n) +.. function:: randbool([dims...]) - Generate a sample from the chi-squared distribution with ``n`` degrees of freedom (also available as ``chi2rnd``) + Generate a random boolean value. Optionally, generate an array of random boolean values. -.. function:: randexp +.. function:: randbool!(A) - Generate samples from the exponential distribution + Fill an array with random boolean values. A may be an ``Array`` or a ``BitArray``. -.. function:: srand +.. function:: randn(dims or [dims...]) - Seed the RNG + Generate a normally-distributed random number with mean 0 and standard deviation 1. Optionally generate an array of normally-distributed random numbers. Arrays ------ @@ -1383,7 +2089,7 @@ Arrays Basic functions ~~~~~~~~~~~~~~~ -.. function:: ndims(A) +.. function:: ndims(A) -> Integer Returns the number of dimensions of A @@ -1395,17 +2101,21 @@ Basic functions Returns the type of the elements contained in A -.. function:: numel(A) +.. function:: length(A) -> Integer - Returns the number of elements in A + Returns the number of elements in A (note that this differs from MATLAB where ``length(A)`` is the largest dimension of ``A``) -.. function:: length(A) +.. function:: nnz(A) - Returns the number of elements in A (note that this differs from Matlab where ``length(A)`` is the largest dimension of ``A``) + Counts the number of nonzero values in array A (dense or sparse) -.. function:: nnz(A) +.. function:: scale!(A, k) + + Scale the contents of an array A with k (in-place) + +.. function:: conj!(A) - Counts the number of nonzero values in A + Convert an array to its complex conjugate in-place .. function:: stride(A, k) @@ -1422,9 +2132,9 @@ Constructors Construct an uninitialized dense array. ``dims`` may be a tuple or a series of integer arguments. -.. function:: ref(type) +.. function:: getindex(type[, elements...]) - Construct an empty 1-d array of the specified type. This is usually called with the syntax ``Type[]``. Element values can be specified using ``Type[a,b,c,...]``. + Construct a 1-d array of the specified type. This is usually called with the syntax ``Type[]``. Element values can be specified using ``Type[a,b,c,...]``. .. function:: cell(dims) @@ -1457,10 +2167,6 @@ Constructors Create an array with the same data as the given array, but with different dimensions. An implementation for a particular type of array may choose whether the data is copied or shared. -.. function:: copy(A) - - Create a copy of ``A`` - .. function:: similar(array, element_type, dims) Create an uninitialized array of the same type as the given array, but with the specified element type and dimensions. The second and third arguments are both optional. The ``dims`` argument may be a tuple or a series of integer arguments. @@ -1469,18 +2175,6 @@ Constructors Construct an array with the same binary data as the given array, but with the specified element type -.. function:: rand(dims) - - Create a random array with Float64 random values in (0,1) - -.. function:: randf(dims) - - Create a random array with Float32 random values in (0,1) - -.. function:: randn(dims) - - Create a random array with Float64 normally-distributed random values with a mean of 0 and standard deviation of 1 - .. function:: eye(n) n-by-n identity matrix @@ -1502,24 +2196,28 @@ Mathematical operators and functions All mathematical operations and functions are supported for arrays +.. function:: bsxfun(fn, A, B[, C...]) + + Apply binary function ``fn`` to two or more arrays, with singleton dimensions expanded. + Indexing, Assignment, and Concatenation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. function:: ref(A, ind) +.. function:: getindex(A, ind) - Returns a subset of ``A`` as specified by ``ind``, which may be an ``Int``, a ``Range``, or a ``Vector``. + Returns a subset of array ``A`` as specified by ``ind``, which may be an ``Int``, a ``Range``, or a ``Vector``. .. function:: sub(A, ind) - Returns a SubArray, which stores the input ``A`` and ``ind`` rather than computing the result immediately. Calling ``ref`` on a SubArray computes the indices on the fly. + Returns a SubArray, which stores the input ``A`` and ``ind`` rather than computing the result immediately. Calling ``getindex`` on a SubArray computes the indices on the fly. .. function:: slicedim(A, d, i) Return all the data of ``A`` where the index for dimension ``d`` equals ``i``. Equivalent to ``A[:,:,...,i,:,:,...]`` where ``i`` is in position ``d``. -.. function:: assign(A, X, ind) +.. function:: setindex!(A, X, ind) - Store an input array ``X`` within some subset of ``A`` as specified by ``ind``. + Store values from array ``X`` within some subset of ``A`` as specified by ``ind``. .. function:: cat(dim, A...) @@ -1533,9 +2231,12 @@ Indexing, Assignment, and Concatenation Concatenate along dimension 2 -.. function:: hvcat +.. function:: hvcat(rows::(Int...), values...) - Horizontal and vertical concatenation in one call + Horizontal and vertical concatenation in one call. This function is called for + block matrix syntax. The first argument specifies the number of arguments to + concatenate in each block row. + For example, ``[a b;c d e]`` calls ``hvcat((2,3),a,b,c,d,e)``. .. function:: flipdim(A, d) @@ -1561,349 +2262,475 @@ Indexing, Assignment, and Concatenation Return a vector of indexes for each dimension giving the locations of the non-zeros in ``A``. -.. function:: permute(A,perm) +.. function:: nonzeros(A) - Permute the dimensions of array ``A``. ``perm`` is a vector specifying a permutation of length ``ndims(A)``. This is a generalization of transpose for multi-dimensional arrays. Transpose is equivalent to ``permute(A,[2,1])``. + Return a vector of the non-zero values in array ``A``. -.. function:: ipermute(A,perm) +.. function:: findfirst(A) - Like ``permute``, except the inverse of the given permutation is applied. + Return the index of the first non-zero value in ``A``. -.. function:: squeeze(A) +.. function:: findfirst(A,v) - Remove singleton dimensions from the shape of array ``A`` + Return the index of the first element equal to ``v`` in ``A``. -.. function:: vec(A) +.. function:: findfirst(predicate, A) - Make a vector out of an array with only one non-singleton dimension. + Return the index of the first element that satisfies the given predicate in ``A``. -Sparse Matrices ---------------- +.. function:: permutedims(A,perm) -Sparse matrices support much of the same set of operations as dense matrices. The following functions are specific to sparse matrices. + Permute the dimensions of array ``A``. ``perm`` is a vector specifying a permutation of length ``ndims(A)``. This is a generalization of transpose for multi-dimensional arrays. Transpose is equivalent to ``permute(A,[2,1])``. + +.. function:: ipermutedims(A,perm) -.. function:: sparse(I,J,V[,m,n,combine]) + Like :func:`permutedims`, except the inverse of the given permutation is applied. - Create a sparse matrix ``S`` of dimensions ``m x n`` such that ``S[I[k], J[k]] = V[k]``. The ``combine`` function is used to combine duplicates. If ``m`` and ``n`` are not specified, they are set to ``max(I)`` and ``max(J)`` respectively. If the ``combine`` function is not supplied, duplicates are added by default. +.. function:: squeeze(A, dims) -.. function:: issparse(S) + Remove the dimensions specified by ``dims`` from array ``A`` - Returns ``true`` if ``S`` is sparse, and ``false`` otherwise. +.. function:: vec(Array) -> Vector -.. function:: nnz(S) + Vectorize an array using column-major convention. - Return the number of nonzeros in ``S``. +Array functions +~~~~~~~~~~~~~~~ -.. function:: sparse(A) +.. function:: cumprod(A, [dim]) - Convert a dense matrix ``A`` into a sparse matrix. + Cumulative product along a dimension. -.. function:: dense(S) +.. function:: cumsum(A, [dim]) - Convert a sparse matrix ``S`` into a dense matrix. + Cumulative sum along a dimension. -.. function:: full(S) +.. function:: cumsum_kbn(A, [dim]) - Convert a sparse matrix ``S`` into a dense matrix. + Cumulative sum along a dimension, using the Kahan-Babuska-Neumaier compensated summation algorithm for additional accuracy. -.. function:: spzeros(m,n) +.. function:: cummin(A, [dim]) - Create an empty sparse matrix of size ``m x n``. + Cumulative minimum along a dimension. -.. function:: speye(type,m[,n]) +.. function:: cummax(A, [dim]) - Create a sparse identity matrix of specified type of size ``m x m``. In case ``n`` is supplied, create a sparse identity matrix of size ``m x n``. + Cumulative maximum along a dimension. -.. function:: spones(S) +.. function:: diff(A, [dim]) - Create a sparse matrix with the same structure as that of ``S``, but with every nonzero element having the value ``1.0``. + Finite difference operator of matrix or vector. -.. function:: sprand(m,n,density[,rng]) +.. function:: rot180(A) - Create a random sparse matrix with the specified density. Nonzeros are sampled from the distribution specified by ``rng``. The uniform distribution is used in case ``rng`` is not specified. + Rotate matrix ``A`` 180 degrees. -.. function:: sprandn(m,n,density) +.. function:: rotl90(A) - Create a random sparse matrix of specified density with nonzeros sampled from the normal distribution. + Rotate matrix ``A`` left 90 degrees. -.. function:: sprandbool(m,n,density) +.. function:: rotr90(A) - Create a random sparse boolean matrix with the specified density. + Rotate matrix ``A`` right 90 degrees. +.. function:: reducedim(f, A, dims, initial) -Linear Algebra --------------- + Reduce 2-argument function ``f`` along dimensions of ``A``. ``dims`` is a + vector specifying the dimensions to reduce, and ``initial`` is the initial + value to use in the reductions. -Linear algebra functions in Julia are largely implemented by calling functions from `LAPACK `_. +.. function:: mapslices(f, A, dims) -.. function:: * + Transform the given dimensions of array ``A`` using function ``f``. ``f`` + is called on each slice of ``A`` of the form ``A[...,:,...,:,...]``. + ``dims`` is an integer vector specifying where the colons go in this + expression. The results are concatenated along the remaining dimensions. + For example, if ``dims`` is ``[1,2]`` and A is 4-dimensional, ``f`` is + called on ``A[:,:,i,j]`` for all ``i`` and ``j``. - Matrix multiplication +.. function:: sum_kbn(A) -.. function:: \ + Returns the sum of all array elements, using the Kahan-Babuska-Neumaier compensated summation algorithm for additional accuracy. - Matrix division using a polyalgorithm. For input matrices ``A`` and ``B``, the result ``X`` is such that ``A*X == B``. For rectangular ``A``, QR factorization is used. For triangular ``A``, a triangular solve is performed. For square ``A``, Cholesky factorization is tried if the input is symmetric with a heavy diagonal. LU factorization is used in case Cholesky factorization fails or for general square inputs. If ``size(A,1) > size(A,2)``, the result is a least squares solution of ``A*X+eps=B`` using the singular value decomposition. ``A`` does not need to have full rank. -.. function:: dot +Combinatorics +------------- + +.. function:: nthperm(v, k) - Compute the dot product + Compute the kth lexicographic permutation of a vector. -.. function:: cross +.. function:: nthperm!(v, k) - Compute the cross product of two 3-vectors + In-place version of :func:`nthperm`. -.. function:: norm +.. function:: randperm(n) - Compute the norm of a ``Vector`` or a ``Matrix`` + Construct a random permutation of the given length. -.. function:: lu(A) -> LU +.. function:: invperm(v) - Compute LU factorization. LU is an "LU factorization" type that can be used as an ordinary matrix. + Return the inverse permutation of v. -.. function:: chol(A) +.. function:: isperm(v) -> Bool - Compute Cholesky factorization + Returns true if v is a valid permutation. -.. function:: qr(A) +.. function:: permute!(v, p) - Compute QR factorization + Permute vector ``v`` in-place, according to permutation ``p``. No + checking is done to verify that ``p`` is a permutation. -.. function:: qrp(A) + To return a new permutation, use ``v[p]``. Note that this is + generally faster than ``permute!(v,p)`` for large vectors. - Compute QR factorization with pivoting +.. function:: ipermute!(v, p) -.. function:: factors(D) + Like permute!, but the inverse of the given permutation is applied. - Return the factors of a decomposition D. For an LU decomposition, factors(LU) -> L, U, p +.. function:: randcycle(n) -.. function:: eig(A) -> D, V + Construct a random cyclic permutation of the given length. - Compute eigenvalues and eigenvectors of A +.. function:: shuffle(v) -.. function:: eigvals(A) + Randomly rearrange the elements of a vector. - Returns the eigenvalues of ``A``. +.. function:: shuffle!(v) -.. function:: svd(A) -> U, S, V' + In-place version of :func:`shuffle`. - Compute the SVD of A +.. function:: reverse(v) -.. function:: svdvals(A) + Reverse vector ``v``. - Returns the singular values of ``A``. +.. function:: reverse!(v) -> v -.. function:: triu(M) + In-place version of :func:`reverse`. - Upper triangle of a matrix +.. function:: combinations(array, n) -.. function:: tril(M) + Generate all combinations of ``n`` elements from a given array. Because + the number of combinations can be very large, this function runs inside + a Task to produce values on demand. Write ``c = @task combinations(a,n)``, + then iterate ``c`` or call ``consume`` on it. - Lower triangle of a matrix +.. function:: integer_partitions(n, m) -.. function:: diag(M) + Generate all arrays of ``m`` integers that sum to ``n``. Because + the number of partitions can be very large, this function runs inside + a Task to produce values on demand. Write + ``c = @task integer_partitions(n,m)``, then iterate ``c`` or call + ``consume`` on it. - The diagonal of a matrix, as a vector +.. function:: partitions(array) -.. function:: diagm(v) + Generate all set partitions of the elements of an array, represented as + arrays of arrays. Because the number of partitions can be very large, this + function runs inside a Task to produce values on demand. Write + ``c = @task partitions(a)``, then iterate ``c`` or call ``consume`` on it. - Construct a diagonal matrix from a vector +Statistics +---------- -.. function:: Tridiagonal(dl, d, du) +.. function:: mean(v[, region]) - Construct a tridiagonal matrix from the lower diagonal, diagonal, and upper diagonal + Compute the mean of whole array ``v``, or optionally along the dimensions in ``region``. -.. function:: Woodbury(A, U, C, V) +.. function:: std(v[, region]) - Construct a matrix in a form suitable for applying the Woodbury matrix identity + Compute the sample standard deviation of a vector or array``v``, optionally along dimensions in ``region``. The algorithm returns an estimator of the generative distribution's standard deviation under the assumption that each entry of ``v`` is an IID draw from that generative distribution. This computation is equivalent to calculating ``sqrt(sum((v - mean(v)).^2) / (length(v) - 1))``. -.. function:: rank(M) +.. function:: stdm(v, m) - Compute the rank of a matrix + Compute the sample standard deviation of a vector ``v`` with known mean ``m``. -.. function:: cond(M) +.. function:: var(v[, region]) - Matrix condition number + Compute the sample variance of a vector or array``v``, optionally along dimensions in ``region``. The algorithm will return an estimator of the generative distribution's variance under the assumption that each entry of ``v`` is an IID draw from that generative distribution. This computation is equivalent to calculating ``sum((v - mean(v)).^2) / (length(v) - 1)``. -.. function:: trace(M) +.. function:: varm(v, m) - Matrix trace + Compute the sample variance of a vector ``v`` with known mean ``m``. -.. function:: det(M) +.. function:: median(v) - Matrix determinant + Compute the median of a vector ``v``. -.. function:: inv(M) +.. function:: hist(v[, n]) -> e, counts - Matrix inverse + Compute the histogram of ``v``, optionally using approximately ``n`` + bins. The return values are a range ``e``, which correspond to the + edges of the bins, and ``counts`` containing the number of elements of + ``v`` in each bin. -.. function:: pinv(M) +.. function:: hist(v, e) -> e, counts - Moore-Penrose inverse + Compute the histogram of ``v`` using a vector/range ``e`` as the edges for + the bins. The result will be a vector of length ``length(e) - 1``, with the + ``i``th element being ``sum(e[i] .< v .<= e[i+1])``. -.. function:: null(M) +.. function:: histrange(v, n) - Basis for null space of M + Compute `nice` bin ranges for the edges of a histogram of ``v``, using + approximately ``n`` bins. The resulting step sizes will be 1, 2 or 5 + multiplied by a power of 10. -.. function:: repmat(A, n, m) +.. function:: midpoints(e) - Construct a matrix by repeating the given matrix ``n`` times in dimension 1 and ``m`` times in dimension 2. + Compute the midpoints of the bins with edges ``e``. The result is a + vector/range of length ``length(e) - 1``. -.. function:: kron(A, B) +.. function:: quantile(v, p) - Kronecker tensor product of two vectors or two matrices. + Compute the quantiles of a vector ``v`` at a specified set of probability values ``p``. -.. function:: linreg(x, y) +.. function:: quantile(v) - Determine parameters ``[a, b]`` that minimize the squared error between ``y`` and ``a+b*x``. + Compute the quantiles of a vector ``v`` at the probability values ``[.0, .2, .4, .6, .8, 1.0]``. -.. function:: linreg(x, y, w) +.. function:: cov(v1[, v2]) - Weighted least-squares linear regression + Compute the Pearson covariance between two vectors ``v1`` and ``v2``. If + called with a single element ``v``, then computes covariance of columns of + ``v``. -Combinatorics -------------- +.. function:: cor(v1[, v2]) -.. function:: sort(v) + Compute the Pearson correlation between two vectors ``v1`` and ``v2``. If + called with a single element ``v``, then computes correlation of columns of + ``v``. - Sort a vector in ascending order, according to ``isless``. +Signal Processing +----------------- -.. function:: sort!(v) +FFT functions in Julia are largely implemented by calling functions from `FFTW `_ - In-place sort +.. function:: fft(A [, dims]) -.. function:: sortr(v) + Performs a multidimensional FFT of the array ``A``. The optional ``dims`` + argument specifies an iterable subset of dimensions (e.g. an integer, + range, tuple, or array) to transform along. Most efficient if the + size of ``A`` along the transformed dimensions is a product of small + primes; see :func:`nextprod`. See also :func:`plan_fft` for even + greater efficiency. - Sort a vector in descending order + A one-dimensional FFT computes the one-dimensional discrete Fourier + transform (DFT) as defined by :math:`\operatorname{DFT}[k] = \sum_{n=1}^{\operatorname{length}(A)} \exp\left(-i\frac{2\pi (n-1)(k-1)}{\operatorname{length}(A)} \right) A[n]`. A multidimensional FFT simply performs this operation + along each transformed dimension of ``A``. -.. function:: sortr!(v) +.. function:: fft!(A [, dims]) - In-place descending-order sort + Same as :func:`fft`, but operates in-place on ``A``, + which must be an array of complex floating-point numbers. -.. function:: sort(a, dim) +.. function:: ifft(A [, dims]) - Sort an array along the given dimension + Multidimensional inverse FFT. -.. function:: sort(lessthan, a[, dim]) + A one-dimensional backward FFT computes + :math:`\operatorname{BDFT}[k] = + \sum_{n=1}^{\operatorname{length}(A)} \exp\left(+i\frac{2\pi + (n-1)(k-1)}{\operatorname{length}(A)} \right) A[n]`. A + multidimensional backward FFT simply performs this operation along + each transformed dimension of ``A``. The inverse FFT computes + the same thing divided by the product of the transformed dimensions. - Sort with a custom comparison function +.. function:: ifft!(A [, dims]) -.. function:: sortperm(v) -> s,p + Same as :func:`ifft`, but operates in-place on ``A``. - Sort a vector in ascending order, also constructing the permutation that sorts the vector +.. function:: bfft(A [, dims]) -.. function:: issorted(v) + Similar to :func:`ifft`, but computes an unnormalized inverse + (backward) transform, which must be divided by the product of the sizes + of the transformed dimensions in order to obtain the inverse. (This is + slightly more efficient than :func:`ifft` because it omits a scaling + step, which in some applications can be combined with other + computational steps elsewhere.) - Test whether a vector is in ascending sorted order +.. function:: bfft!(A [, dims]) -.. function:: nthperm(v, k) + Same as :func:`bfft`, but operates in-place on ``A``. - Compute the kth lexicographic permutation of a vector +.. function:: plan_fft(A [, dims [, flags [, timelimit]]]) -.. function:: nthperm!(v, k) + Pre-plan an optimized FFT along given dimensions (``dims``) of arrays + matching the shape and type of ``A``. (The first two arguments have + the same meaning as for :func:`fft`.) Returns a function ``plan(A)`` + that computes ``fft(A, dims)`` quickly. - In-place version of ``nthperm`` + The ``flags`` argument is a bitwise-or of FFTW planner flags, defaulting + to ``FFTW.ESTIMATE``. e.g. passing ``FFTW.MEASURE`` or ``FFTW.PATIENT`` + will instead spend several seconds (or more) benchmarking different + possible FFT algorithms and picking the fastest one; see the FFTW manual + for more information on planner flags. The optional ``timelimit`` argument + specifies a rough upper bound on the allowed planning time, in seconds. + Passing ``FFTW.MEASURE`` or ``FFTW.PATIENT`` may cause the input array ``A`` + to be overwritten with zeros during plan creation. -.. function:: randperm(n) + :func:`plan_fft!` is the same as :func:`plan_fft` but creates a plan + that operates in-place on its argument (which must be an array of + complex floating-point numbers). :func:`plan_ifft` and so on + are similar but produce plans that perform the equivalent of + the inverse transforms :func:`ifft` and so on. - Construct a random permutation of the given length +.. function:: plan_ifft(A [, dims [, flags [, timelimit]]]) -.. function:: randcycle(n) + Same as :func:`plan_fft`, but produces a plan that performs inverse transforms + :func:`ifft`. - Construct a random cyclic permutation of the given length +.. function:: plan_bfft(A [, dims [, flags [, timelimit]]]) -.. function:: shuffle(v) + Same as :func:`plan_fft`, but produces a plan that performs an unnormalized + backwards transform :func:`bfft`. - Randomly rearrange the elements of a vector +.. function:: plan_fft!(A [, dims [, flags [, timelimit]]]) -.. function:: shuffle!(v) + Same as :func:`plan_fft`, but operates in-place on ``A``. - In-place version of ``shuffle`` +.. function:: plan_ifft!(A [, dims [, flags [, timelimit]]]) -.. function:: reverse(v) + Same as :func:`plan_ifft`, but operates in-place on ``A``. - Reverse vector ``v`` +.. function:: plan_bfft!(A [, dims [, flags [, timelimit]]]) -.. function:: reverse!(v) + Same as :func:`plan_bfft`, but operates in-place on ``A``. - Reverse vector ``v`` in-place +.. function:: rfft(A [, dims]) -.. function:: select(v, k) + Multidimensional FFT of a real array A, exploiting the fact that + the transform has conjugate symmetry in order to save roughly half + the computational time and storage costs compared with :func:`fft`. + If ``A`` has size ``(n_1, ..., n_d)``, the result has size + ``(floor(n_1/2)+1, ..., n_d)``. - Find the element in position ``k`` in the sorted vector ``v`` without sorting + The optional ``dims`` argument specifies an iterable subset of one or + more dimensions of ``A`` to transform, similar to :func:`fft`. Instead + of (roughly) halving the first dimension of ``A`` in the result, the + ``dims[1]`` dimension is (roughly) halved in the same way. -.. function:: select!(v, k) +.. function:: irfft(A, d [, dims]) - In-place version of ``select`` + Inverse of :func:`rfft`: for a complex array ``A``, gives the + corresponding real array whose FFT yields ``A`` in the first half. + As for :func:`rfft`, ``dims`` is an optional subset of dimensions + to transform, defaulting to ``1:ndims(A)``. -Statistics ----------- + ``d`` is the length of the transformed real array along the ``dims[1]`` + dimension, which must satisfy ``d == floor(size(A,dims[1])/2)+1``. + (This parameter cannot be inferred from ``size(A)`` due to the + possibility of rounding by the ``floor`` function here.) -.. function:: mean(v[, dim]) +.. function:: brfft(A, d [, dims]) - Compute the mean of whole array ``v``, or optionally along dimension ``dim`` + Similar to :func:`irfft` but computes an unnormalized inverse transform + (similar to :func:`bfft`), which must be divided by the product + of the sizes of the transformed dimensions (of the real output array) + in order to obtain the inverse transform. -.. function:: std(v) +.. function:: plan_rfft(A [, dims [, flags [, timelimit]]]) - Compute the standard deviation of a vector ``v`` + Pre-plan an optimized real-input FFT, similar to :func:`plan_fft` + except for :func:`rfft` instead of :func:`fft`. The first two + arguments, and the size of the transformed result, are the same as + for :func:`rfft`. -.. function:: median(v) +.. function:: plan_irfft(A, d [, dims [, flags [, timelimit]]]) - Compute the median of a vector ``v`` + Pre-plan an optimized inverse real-input FFT, similar to :func:`plan_rfft` + except for :func:`irfft` and :func:`brfft`, respectively. The first + three arguments have the same meaning as for :func:`irfft`. -.. function:: hist(v[, n]) +.. function:: dct(A [, dims]) - Compute the histogram of ``v``, optionally using ``n`` bins + Performs a multidimensional type-II discrete cosine transform (DCT) + of the array ``A``, using the unitary normalization of the DCT. + The optional ``dims`` argument specifies an iterable subset of + dimensions (e.g. an integer, range, tuple, or array) to transform + along. Most efficient if the size of ``A`` along the transformed + dimensions is a product of small primes; see :func:`nextprod`. See + also :func:`plan_dct` for even greater efficiency. -.. function:: histc(v, e) +.. function:: dct!(A [, dims]) - Compute the histogram of ``v`` using a vector ``e`` as the edges for the bins + Same as :func:`dct!`, except that it operates in-place + on ``A``, which must be an array of real or complex floating-point + values. -Signal Processing ------------------ +.. function:: idct(A [, dims]) -FFT functions in Julia are largely implemented by calling functions from `FFTW `_ + Computes the multidimensional inverse discrete cosine transform (DCT) + of the array ``A`` (technically, a type-III DCT with the unitary + normalization). + The optional ``dims`` argument specifies an iterable subset of + dimensions (e.g. an integer, range, tuple, or array) to transform + along. Most efficient if the size of ``A`` along the transformed + dimensions is a product of small primes; see :func:`nextprod`. See + also :func:`plan_idct` for even greater efficiency. -.. function:: fft(A, dim) +.. function:: idct!(A [, dims]) - One dimensional FFT if input is a ``Vector``. For n-d cases, compute fft of vectors along dimension ``dim``. Most efficient if ``size(A, dim)`` is a product of small primes; see :func:`nextprod`. + Same as :func:`idct!`, but operates in-place on ``A``. -.. function:: fft2 +.. function:: plan_dct(A [, dims [, flags [, timelimit]]]) - 2d FFT + Pre-plan an optimized discrete cosine transform (DCT), similar to + :func:`plan_fft` except producing a function that computes :func:`dct`. + The first two arguments have the same meaning as for :func:`dct`. -.. function:: fft3 +.. function:: plan_dct!(A [, dims [, flags [, timelimit]]]) - 3d FFT + Same as :func:`plan_dct`, but operates in-place on ``A``. -.. function:: fftn +.. function:: plan_idct(A [, dims [, flags [, timelimit]]]) - N-d FFT + Pre-plan an optimized inverse discrete cosine transform (DCT), similar to + :func:`plan_fft` except producing a function that computes :func:`idct`. + The first two arguments have the same meaning as for :func:`idct`. -.. function:: ifft(A, dim) +.. function:: plan_idct!(A [, dims [, flags [, timelimit]]]) - Inverse FFT. Same arguments as ``fft``. + Same as :func:`plan_idct`, but operates in-place on ``A``. -.. function:: ifft2 +.. function:: FFTW.r2r(A, kind [, dims]) - Inverse 2d FFT + Performs a multidimensional real-input/real-output (r2r) transform + of type ``kind`` of the array ``A``, as defined in the FFTW manual. + ``kind`` specifies either a discrete cosine transform of various types + (``FFTW.REDFT00``, ``FFTW.REDFT01``, ``FFTW.REDFT10``, or + ``FFTW.REDFT11``), a discrete sine transform of various types + (``FFTW.RODFT00``, ``FFTW.RODFT01``, ``FFTW.RODFT10``, or + ``FFTW.RODFT11``), a real-input DFT with halfcomplex-format output + (``FFTW.R2HC`` and its inverse ``FFTW.HC2R``), or a discrete + Hartley transform (``FFTW.DHT``). The ``kind`` argument may be + an array or tuple in order to specify different transform types + along the different dimensions of ``A``; ``kind[end]`` is used + for any unspecified dimensions. See the FFTW manual for precise + definitions of these transform types, at ``. -.. function:: ifft3 + The optional ``dims`` argument specifies an iterable subset of + dimensions (e.g. an integer, range, tuple, or array) to transform + along. ``kind[i]`` is then the transform type for ``dims[i]``, + with ``kind[end]`` being used for ``i > length(kind)``. - Inverse 3d FFT + See also :func:`FFTW.plan_r2r` to pre-plan optimized r2r transforms. -.. function:: ifftn +.. function:: FFTW.r2r!(A, kind [, dims]) - Inverse N-d FFT + :func:`FFTW.r2r!` is the same as :func:`FFTW.r2r`, but operates + in-place on ``A``, which must be an array of real or complex + floating-point numbers. -.. function:: rfft(A [, dim=1]) +.. function:: FFTW.plan_r2r(A, kind [, dims [, flags [, timelimit]]]) - One-dimensional FFT of real array A along dimension dim. If A has size - ``(..., n_dim, ...)``, the result has size ``(..., floor(n_dim/2)+1, ...)``. + Pre-plan an optimized r2r transform, similar to :func:`plan_fft` + except that the transforms (and the first three arguments) + correspond to :func:`FFTW.r2r` and :func:`FFTW.r2r!`, respectively. -.. function:: rfftn(A) +.. function:: FFTW.plan_r2r!(A, kind [, dims [, flags [, timelimit]]]) - N-d FFT of real array A. If A has size ``(n_1, ..., n_d)``, the result has size - ``(floor(n_1/2)+1, ..., n_d)``. + Similar to :func:`plan_fft`, but corresponds to :func:`FFTW.r2r!`. .. function:: fftshift(x) @@ -1913,7 +2740,7 @@ FFT functions in Julia are largely implemented by calling functions from `FFTW < Swap the first and second halves of the given dimension of array ``x``. -.. function:: ifftshift(x[, dim]) +.. function:: ifftshift(x, [dim]) Undoes the effect of ``fftshift``. @@ -1950,11 +2777,15 @@ Parallel Computing .. function:: nprocs() - Get the number of available processors + Get the number of available processors. .. function:: myid() - Get the id of the current processor + Get the id of the current processor. + +.. function:: pmap(f, c) + + Transform collection ``c`` by applying ``f`` to each element in parallel. .. function:: remote_call(id, func, args...) @@ -1995,19 +2826,15 @@ Parallel Computing Distributed Arrays ------------------ -.. function:: darray(init, type, dims[, distdim, procs, dist]) - - Construct a distributed array. ``init`` is a function of three arguments that will run on each processor, and should return an ``Array`` holding the local data for the current processor. Its arguments are ``(T,d,da)`` where ``T`` is the element type, ``d`` is the dimensions of the needed local piece, and ``da`` is the new ``DArray`` being constructed (though, of course, it is not fully initialized). ``type`` is the element type. ``dims`` is the dimensions of the entire ``DArray``. ``distdim`` is the dimension to distribute in. ``procs`` is a vector of processor ids to use. ``dist`` is a vector giving the first index of each contiguous distributed piece, such that the nth piece consists of indexes ``dist[n]`` through ``dist[n+1]-1``. If you have a vector ``v`` of the sizes of the pieces, ``dist`` can be computed as ``cumsum([1,v])``. Fortunately, all arguments after ``dims`` are optional. - -.. function:: darray(f, A) +.. function:: DArray(init, dims, [procs, dist]) - Transform ``DArray`` ``A`` to another of the same type and distribution by applying function ``f`` to each block of ``A``. + Construct a distributed array. ``init`` is a function accepting a tuple of index ranges. This function should return a chunk of the distributed array for the specified indexes. ``dims`` is the overall size of the distributed array. ``procs`` optionally specifies a vector of processor IDs to use. ``dist`` is an integer vector specifying how many chunks the distributed array should be divided into in each dimension. -.. function:: dzeros([type, ]dims, ...) +.. function:: dzeros(dims, ...) Construct a distributed array of zeros. Trailing arguments are the same as those accepted by ``darray``. -.. function:: dones([type, ]dims, ...) +.. function:: dones(dims, ...) Construct a distributed array of ones. Trailing arguments are the same as those accepted by ``darray``. @@ -2023,11 +2850,7 @@ Distributed Arrays Construct a distributed normal random array. Trailing arguments are the same as those accepted by ``darray``. -.. function:: dcell(dims, ...) - - Construct a distributed cell array. Trailing arguments are the same as those accepted by ``darray``. - -.. function:: distribute(a[, distdim]) +.. function:: distribute(a) Convert a local array to distributed @@ -2035,65 +2858,100 @@ Distributed Arrays Get the local piece of a distributed array -.. function:: changedist(d, distdim) - - Change the distributed dimension of a ``DArray`` - .. function:: myindexes(d) A tuple describing the indexes owned by the local processor -.. function:: owner(d, i) - - Get the id of the processor holding index ``i`` in the distributed dimension - .. function:: procs(d) Get the vector of processors storing pieces of ``d`` -.. function:: distdim(d) - - Get the distributed dimension of ``d`` - System ------ -.. function:: system("command") +.. function:: run(command) + + Run a command object, constructed with backticks. Throws an error if anything goes wrong, including the process exiting with a non-zero status. + +.. function:: spawn(command) + + Run a command object asynchronously, returning the resulting ``Process`` object. + +.. function:: success(command) + + Run a command object, constructed with backticks, and tell whether it was successful (exited with a code of 0). + +.. function:: readsfrom(command) + + Starts running a command asynchronously, and returns a tuple (stream,process). The first value is a stream reading from the process' standard output. + +.. function:: writesto(command) + + Starts running a command asynchronously, and returns a tuple (stream,process). The first value is a stream writing to the process' standard input. + +.. function:: readandwrite(command) + + Starts running a command asynchronously, and returns a tuple (stdout,stdin,process) of the output stream and input stream of the process, and the process object itself. + +.. function:: > + + Redirect standard output of a process. + + **Example**: ``run(`ls` > "out.log")`` + +.. function:: < + + Redirect standard input of a process. + +.. function:: >> + + Redirect standard output of a process, appending to the destination file. - Run a shell command. +.. function:: .> -.. function:: gethostname() + Redirect the standard error stream of a process. + +.. function:: gethostname() -> String Get the local machine's host name. -.. function:: getipaddr() +.. function:: getipaddr() -> String Get the IP address of the local machine, as a string of the form "x.x.x.x". -.. function:: cwd() +.. function:: pwd() -> String Get the current working directory. -.. function:: cd("dir") +.. function:: cd(dir::String) Set the current working directory. Returns the new current directory. -.. function:: mkdir(path[, mode]) +.. function:: cd(f, ["dir"]) + + Temporarily changes the current working directory (HOME if not specified) and applies function f before returning. + +.. function:: mkdir(path, [mode]) Make a new directory with name ``path`` and permissions ``mode``. ``mode`` defaults to 0o777, modified by the current file creation mask. +.. function:: mkpath(path, [mode]) + + Create all directories in the given ``path``, with permissions ``mode``. + ``mode`` defaults to 0o777, modified by the current file creation mask. + .. function:: rmdir(path) Remove the directory named ``path``. -.. function:: getpid() +.. function:: getpid() -> Int32 Get julia's process ID. .. function:: time() - Get the time in seconds since the epoch, with fairly high (typically, microsecond) resolution. + Get the system time in seconds since the epoch, with fairly high (typically, microsecond) resolution. .. function:: time_ns() @@ -2101,32 +2959,95 @@ System .. function:: tic() - Set a timer to be read by the next call to ``toc`` or ``toq``. The macro call ``@time expr`` can also be used to time evaluation. + Set a timer to be read by the next call to :func:`toc` or :func:`toq`. The macro call ``@time expr`` can also be used to time evaluation. .. function:: toc() - Print and return the time elapsed since the last ``tic`` + Print and return the time elapsed since the last :func:`tic`. .. function:: toq() - Return, but do not print, the time elapsed since the last ``tic`` + Return, but do not print, the time elapsed since the last :func:`tic`. + +.. function:: EnvHash() -> EnvHash + + A singleton of this type provides a hash table interface to environment variables. -.. function:: EnvHash() +.. data:: ENV + + Reference to the singleton ``EnvHash``, providing a dictionary interface to system environment variables. + +C Interface +----------- + +.. function:: ccall((symbol, library) or fptr, RetType, (ArgType1, ...), ArgVar1, ...) + + Call function in C-exported shared library, specified by (function name, library) tuple (String or :Symbol). Alternatively, ccall may be used to call a function pointer returned by dlsym, but note that this usage is generally discouraged to facilitate future static compilation. + +.. function:: cfunction(fun::Function, RetType::Type, (ArgTypes...)) + + Generate C-callable function pointer from Julia function. - A singleton of this type, ``ENV``, provides a hash table interface to environment variables. +.. function:: dlopen(libfile::String [, flags::Integer]) -.. function:: dlopen(libfile) + Load a shared library, returning an opaque handle. - Load a shared library, returning an opaque handle + The optional flags argument is a bitwise-or of zero or more of + RTLD_LOCAL, RTLD_GLOBAL, RTLD_LAZY, RTLD_NOW, RTLD_NODELETE, + RTLD_NOLOAD, RTLD_DEEPBIND, and RTLD_FIRST. These are converted to + the corresponding flags of the POSIX (and/or GNU libc and/or MacOS) + dlopen command, if possible, or are ignored if the specified + functionality is not available on the current platform. The + default is RTLD_LAZY|RTLD_DEEPBIND|RTLD_LOCAL. An important usage + of these flags, on POSIX platforms, is to specify + RTLD_LAZY|RTLD_DEEPBIND|RTLD_GLOBAL in order for the library's + symbols to be available for usage in other shared libraries, in + situations where there are dependencies between shared libraries. .. function:: dlsym(handle, sym) - Look up a symbol from a shared library handle + Look up a symbol from a shared library handle, return callable function pointer on success. + +.. function:: dlsym_e(handle, sym) + + Look up a symbol from a shared library handle, silently return NULL pointer on lookup failure. + +.. function:: dlclose(handle) + + Close shared library referenced by handle. + +.. function:: c_free(addr::Ptr) + + Call free() from C standard library. + +.. function:: unsafe_ref(p::Ptr{T},i::Integer) + + Dereference the pointer ``p[i]`` or ``*p``, returning a copy of type T. + +.. function:: unsafe_assign(p::Ptr{T},x,i::Integer) + + Assign to the pointer ``p[i] = x`` or ``*p = x``, making a copy of object x into the memory at p. + +.. function:: pointer(a[, index]) + + Get the native address of an array element. Be careful to ensure that a julia + reference to ``a`` exists as long as this pointer will be used. + +.. function:: pointer(type, int) + + Convert an integer to a pointer of the specified element type. + +.. function:: pointer_to_array(p, dims[, own]) + + Wrap a native pointer as a Julia Array object. The pointer element type determines + the array element type. ``own`` optionally specifies whether Julia should take + ownership of the memory, calling ``free`` on the pointer when the array is no + longer referenced. Errors ------ -.. function:: error(message) +.. function:: error(message::String) Raise an error with the given message diff --git a/doc/stdlib/blas.rst b/doc/stdlib/blas.rst deleted file mode 100644 index 9d951956bdd2a..0000000000000 --- a/doc/stdlib/blas.rst +++ /dev/null @@ -1,106 +0,0 @@ -:mod:`BLAS` --- Basic Linear Algebra Subroutines -=================================================== - -.. module:: BLAS - :synopsis: Wrapper functions for the Basic Linear Algebra Subroutines - -This module provides wrappers for some of the BLAS functions for -linear algebra. Those BLAS functions that overwrite one of the input -arrays have names ending in ``'!'``. - -Usually a function has 4 methods defined, one each for ``Float64``, -``Float32``, ``Complex128`` and ``Complex64`` arrays. - -Utility Functions ------------------ - -.. function:: copy!(n, X, incx, Y, incy) - - Copy ``n`` elements of array ``X`` with stride ``incx`` to array - ``Y`` with stride ``incy``. Returns ``Y``. - -.. function:: dot(n, X, incx, Y, incy) - - Dot product of two vectors consisting of ``n`` elements of array - ``X`` with stride ``incx`` and ``n`` elements of array ``Y`` with - stride ``incy``. There are no ``dot`` methods for ``Complex`` - arrays. - -.. function:: nrm2(n, X, incx) - - 2-norm of a vector consisting of ``n`` elements of array ``X`` with - stride ``incx``. - -.. function:: axpy!(n, a, X, incx, Y, incy) - - Overwrite ``Y`` with ``a*X + Y``. Returns ``Y``. - -.. function:: syrk!(uplo, trans, alpha, A, beta, C) - - Rank-k update of the symmetric matrix ``C`` as ``alpha*A*A.' + - beta*C`` or ``alpha*A.'*A + beta*C`` according to whether ``trans`` - is 'N' or 'T'. When ``uplo`` is 'U' the upper triangle of ``C`` is - updated ('L' for lower triangle). Returns ``C``. - -.. function:: syrk(uplo, trans, alpha, A) - - Returns either the upper triangle or the lower triangle, according - to ``uplo`` ('U' or 'L'), of ``alpha*A*A.'`` or ``alpha*A.'*A``, - according to ``trans`` ('N' or 'T'). - -.. function:: herk!(uplo, trans, alpha, A, beta, C) - - Methods for complex arrays only. Rank-k update of the Hermitian - matrix ``C`` as ``alpha*A*A' + beta*C`` or ``alpha*A'*A + beta*C`` - according to whether ``trans`` is 'N' or 'T'. When ``uplo`` is 'U' - the upper triangle of ``C`` is updated ('L' for lower triangle). - Returns ``C``. - -.. function:: herk(uplo, trans, alpha, A) - - Methods for complex arrays only. Returns either the upper triangle - or the lower triangle, according to ``uplo`` ('U' or 'L'), of - ``alpha*A*A'`` or ``alpha*A'*A``, according to ``trans`` ('N' or 'T'). - -.. function:: gbmv!(trans, m, kl, ku, alpha, A, x, beta, y) - - Update vector ``y`` as ``alpha*A*x + beta*y`` or ``alpha*A'*x + - beta*y`` according to ``trans`` ('N' or 'T'). The matrix ``A`` is - a general band matrix of dimension ``m`` by ``size(A,2)`` with - ``kl`` sub-diagonals and ``ku`` super-diagonals. Returns the - updated ``y``. - -.. function:: gbmv(trans, m, kl, ku, alpha, A, x, beta, y) - - Returns ``alpha*A*x`` or ``alpha*A'*x`` according to ``trans`` ('N' - or 'T'). The matrix ``A`` is a general band matrix of dimension - ``m`` by ``size(A,2)`` with ``kl`` sub-diagonals and - ``ku`` super-diagonals. - -.. function:: sbmv!(uplo, k, alpha, A, x, beta, y) - - Update vector ``y`` as ``alpha*A*x + beta*y`` where ``A`` is a - a symmetric band matrix of order ``size(A,2)`` with - ``k`` super-diagonals stored in the argument ``A``. The storage - layout for ``A`` is described the reference BLAS module, level-2 - BLAS at ``. - - Returns the updated ``y``. - -.. function:: sbmv(uplo, k, alpha, A, x) - - Returns ``alpha*A*x`` where ``A`` is a symmetric band matrix of - order ``size(A,2)`` with ``k`` super-diagonals stored in the - argument ``A``. - -.. function:: gemm!(tA, tB, alpha, A, B, beta, C) - - Update ``C`` as ``alpha*A*B + beta*C`` or the other three variants - according to ``tA`` (transpose ``A``) and ``tB``. Returns the - updated ``C``. - -.. function:: gemm(tA, tB, alpha, A, B) - - Returns ``alpha*A*B`` or the other three variants - according to ``tA`` (transpose ``A``) and ``tB``. - diff --git a/doc/stdlib/constants.rst b/doc/stdlib/constants.rst new file mode 100644 index 0000000000000..01491eee8828a --- /dev/null +++ b/doc/stdlib/constants.rst @@ -0,0 +1,34 @@ + +.. currentmodule:: Base + +Constants +--------- + +.. data:: OS_NAME + + A symbol representing the name of the operating system. Possible values + are ``:Linux``, ``:Darwin`` (OS X), or ``:Windows``. + +.. data:: ARGS + + An array of the command line arguments passed to Julia, as strings. + +.. data:: C_NULL + + The C null pointer constant, sometimes used when calling external code. + +.. data:: CPU_CORES + + The number of CPU cores in the system. + +.. data:: WORD_SIZE + + Standard word size on the current machine, in bits. + +.. data:: VERSION + + An object describing which version of Julia is in use. + +.. data:: LOAD_PATH + + An array of paths (as strings) where the ``require`` function looks for code. diff --git a/doc/stdlib/cpp.rst b/doc/stdlib/cpp.rst deleted file mode 100644 index 2106e24636632..0000000000000 --- a/doc/stdlib/cpp.rst +++ /dev/null @@ -1,39 +0,0 @@ -cpp.jl --- Calling C++ from Julia -================================= - -.. .. module:: cpp.jl - :synopsis: Provides partial support for calling C++ library functions from Julia. - -Provides partial support for calling C++ library functions from Julia. - -.. function:: @cpp(ccall_expression) - - Suppose you have a C++ shared library, ``libdemo``, which contains a function ``timestwo``:: - - int timestwo(int x) { - return 2*x; - } - - double timestwo(double x) { - return 2*x; - } - - You can use these functions by placing the ``@cpp`` macro prior to a ccall, for example:: - - mylib = dlopen("libdemo") - x = 3.5 - x2 = @cpp ccall(dlsym(mylib, :timestwo), Float64, (Float64,), x) - y = 3 - y2 = @cpp ccall(dlsym(mylib, :timestwo), Int, (Int,), y) - - The macro performs C++ ABI name-mangling (using the types of the parameters) to determine the correct library symbol. - - Like ``ccall``, this performs library calls without overhead. However, currently it has a number of limitations: - - * It does not support pure-header libraries - * The restrictions of ``ccall`` apply here; for example, there is no support for ``struct``. Consequently it is not possible to use C++ objects. - * Currently there is no C++ namespace support - * Currently there is no support for templated functions - * Currently only g++ is supported - - The latter three may not be difficult to `fix `_. diff --git a/doc/stdlib/file.rst b/doc/stdlib/file.rst new file mode 100644 index 0000000000000..6b3c2e8c3924a --- /dev/null +++ b/doc/stdlib/file.rst @@ -0,0 +1,103 @@ + +.. currentmodule:: Base + +Filesystem +---------- + +.. function:: isblockdev(path) -> Bool + + Returns ``true`` if ``path`` is a block device, ``false`` otherwise. + +.. function:: ischardev(path) -> Bool + + Returns ``true`` if ``path`` is a character device, ``false`` otherwise. + +.. function:: isdir(path) -> Bool + + Returns ``true`` if ``path`` is a directory, ``false`` otherwise. + +.. function:: isexecutable(path) -> Bool + + Returns ``true`` if the current user has permission to execute ``path``, + ``false`` otherwise. + +.. function:: isfifo(path) -> Bool + + Returns ``true`` if ``path`` is a FIFO, ``false`` otherwise. + +.. function:: isfile(path) -> Bool + + Returns ``true`` if ``path`` is a regular file, ``false`` otherwise. + +.. function:: islink(path) -> Bool + + Returns ``true`` if ``path`` is a symbolic link, ``false`` otherwise. + +.. function:: ispath(path) -> Bool + + Returns ``true`` if ``path`` is a valid filesystem path, ``false`` otherwise. + +.. function:: isreadable(path) -> Bool + + Returns ``true`` if the current user has permission to read ``path``, + ``false`` otherwise. + +.. function:: issetgid(path) -> Bool + + Returns ``true`` if ``path`` has the setgid flag set, ``false`` otherwise. + +.. function:: issetuid(path) -> Bool + + Returns ``true`` if ``path`` has the setuid flag set, ``false`` otherwise. + +.. function:: issocket(path) -> Bool + + Returns ``true`` if ``path`` is a socket, ``false`` otherwise. + +.. function:: issticky(path) -> Bool + + Returns ``true`` if ``path`` has the sticky bit set, ``false`` otherwise. + +.. function:: iswriteable(path) -> Bool + + Returns ``true`` if the current user has permission to write to ``path``, + ``false`` otherwise. + +.. function:: dirname(path::String) -> String + + Get the directory part of a path. + +.. function:: basename(path::String) -> String + + Get the file name part of a path. + +.. function:: isabspath(path::String) -> Bool + + Determines whether a path is absolute (begins at the root directory). + +.. function:: joinpath(parts...) -> String + + Join path components into a full path. If some argument is an absolute + path, then prior components are dropped. + +.. function:: abspath(path::String) -> String + + Convert a path to an absolute path by adding the current directory if + necessary. + +.. function:: tempname() + + Generate a unique temporary filename. + +.. function:: tempdir() + + Obtain the path of a temporary directory. + +.. function:: mktemp() + + Returns ``(path, io)``, where ``path`` is the path of a new temporary file + and ``io`` is an open file object for this path. + +.. function:: mktempdir() + + Create a temporary directory and return its path. diff --git a/doc/stdlib/glpk.rst b/doc/stdlib/glpk.rst deleted file mode 100644 index 916a89768b423..0000000000000 --- a/doc/stdlib/glpk.rst +++ /dev/null @@ -1,1151 +0,0 @@ -:mod:`GLPK` --- Wrapper for the GNU Linear Programming Kit (GLPK) -================================================================= - -.. module:: GLPK - :synopsis: GLPK wrapper - -.. note:: located in ``glpk.jl`` - -This file provides a wrapper for the GNU Linear Programming Kit -(`GLPK `_), which is a C library, in Julia. -It is designed for making it easy to port C code to Julia, while at the same time having the -benefits of the higher level language features of Julia, like the automatic management of memory, the possibility -of returning tuples/strings/vectors etc. - -It's currently based on GLPK version 4.47. - --------- -Preamble --------- - -Almost all GLPK functions can be called in Julia with basically the same syntax as in the original C library, -with some simple translation rules (with very :ref:`few exceptions `). -Some functionality is still missing (see :ref:`this list `); most of it will be -added in the future. - -Let's start with an example. This is an excerpt from the beginning of the :file:`sample.c` example program -which ships with GLPK: - -.. code-block:: c - - /* C code */ - glp_prob *lp = glp_create_prob(); - glp_set_prob_name(lp, "sample"); - glp_set_obj_dir(lp, GLP_MAX); - glp_add_rows(lp, 3); - glp_set_row_name(lp, 1, "p"); - glp_set_row_bnds(lp, 1, GLP_UP, 0.0, 100.0); - -This is the Julia translation of the above:: - - # Julia code - lp = GLPK.Prob() - GLPK.set_prob_name(lp, "sample") - GLPK.set_obj_dir(lp, GLPK.MAX) - GLPK.add_rows(lp, 3) - GLPK.set_row_name(lp, 1, "p") - GLPK.set_row_bnds(lp, 1, GLPK.UP, 0.0, 100.0) - -Apart from the first line, which is different, the translation of subsequent lines follows the very simple -rule that function names and constants drop the prefixes ``glp_`` and ``GLP_``, and take the ``GLPK`` -module prefix instead (at the moment, constants are integer values, like in C, but this may change -in the future). -Note that, as with all Julia modules, the ``GLPK`` prefix could be omitted by adding a ``using GLPK`` -line in the code, but this is not advised in this case due to the very high number of functions with -relatively common names in the library. - -Because of the strict adherence of the Julia functions to their C counterparts, and since the GLPK -documentation is extremely well written and complete, this manual page is not going to document -the whole GLPK library in detail, but rather provide :ref:`the rules ` needed to translate -from C to Julia, detail the :ref:`few exceptions ` to these rules and then -:ref:`list all the available functions ` with a brief description of their -usage. - -Please, refer to the original GLPK manual (available at http://www.gnu.org/software/glpk) for a detailed -description of the library API. - -.. _glpk-translation-rules: - --------------------------------------- -GLPK translation rules from C to Julia --------------------------------------- - -1) functions and constants drop their prefix -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Almost all functions in the C library start with the prefix ``glp_``, and all constants start with -the prefix ``GLP_``. These prefixes are dropped in Julia, and the module prefix ``GLPK.`` is used -instead. For example, the function ``glp_simplex`` becomes ``GLPK.simplex``, and the constant -``GLP_UP`` becomes ``GLPK.UP``. - -2) from C stucts to Julia objects -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -All structs in the original GLPK are wrapped up in composite types, which initialize and destroy themselves -as needed. For example, the ``glp_prob`` C struct becomes the ``GLPK.Prob`` Julia type. -Whenever in C you would pass a pointer to a struct, in Julia you pass a corresponding composite object. -This is the table relating C structs with Julia types: - -+---------------+----------------------------+ -| C | Julia | -+===============+============================+ -| ``glp_prob`` | ``GLPK.Prob`` | -+---------------+----------------------------+ -| ``glp_smcp`` | ``GLPK.SimplexParam`` | -+---------------+----------------------------+ -| ``glp_iptcp`` | ``GLPK.InteriorParam`` | -+---------------+----------------------------+ -| ``glp_iocp`` | ``GLPK.IntoptParam`` | -+---------------+----------------------------+ -| ``glp_bfcp`` | ``GLPK.BasisFactParam`` | -+---------------+----------------------------+ -| ``glp_tran`` | ``GLPK.MathProgWorkspace`` | -+---------------+----------------------------+ -| ``glp_data`` | ``GLPK.Data`` | -+---------------+----------------------------+ - -Therefore, the original C GLPK API: - -.. code-block:: c - - int glp_simplex(glp_prob * lp, glp_smpc * param) - -becomes:: - - GLPK.simplex(lp::GLPK.Prob, param::GLPL.SimplexParam) - -In the C GLPK API, objects are created by functions, such as: - -.. code-block:: c - - glp_prob * lp = glp_create_prob(); - glp_smcp * param = glp_smcp_init(); - -and need to be destroyed when the program is finished: - -.. code-block:: c - - glp_delete_prob(lp); - glp_smcp_delete(smcp); - -In Julia, objects are created by calling the object constructor (without parameters):: - - lp = GLPK.Prob() - param = GLPK.SimplexParam() - -and they are automatically destroyed by the garbage collector when no longer needed. - - -3) setting the parameters to the solvers -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -In all GLPK solver functions, like ``glp_simplex``, options are passed via structs. As stated before, these become -composite object types in Julia; but instead of setting a field, like in C: - -.. code-block:: c - - param = glp_smcp_init(); - param.msg_lev = GLP_MSG_ERR; - param.presolve = GLP_ON; - -in Julia one uses an array-like referencing syntax:: - - param = GLPK.SimplexParam() - param["msg_lev"]= GLPK.MSG_ERR - param["presolve"] = GLPK.ON - -Note that the field names are passed as strings, and that all GLPK constants are available in Julia. -Also note that no test is currently performed at assignment to check that the provided values are valid. - -This part of the API may change in the future. - - -4) scalar and array types translate in a natural way -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The following C-to-Julia type conversion rules apply: - -+--------------+-------------+ -| C | Julia | -+==============+=============+ -| ``int`` | ``Int32`` | -+--------------+-------------+ -| ``double`` | ``Float64`` | -+--------------+-------------+ -| ``char[]`` | ``String`` | -+--------------+-------------+ -| ``glp_long`` | ``Int64`` | -+--------------+-------------+ - -On output, these rules apply exactly. On input, on the other hand, Julia requirements are more relaxed: - -+--------------+-------------+ -| C | Julia | -+==============+=============+ -| ``int`` | ``Integer`` | -+--------------+-------------+ -| ``glp_long`` | ``Integer`` | -+--------------+-------------+ -| ``double`` | ``Real`` | -+--------------+-------------+ - -Whenever the C version expects a pointer to an array, a Julia Array can be passed. In the GLPK API, all indexing -starts from 1 even in the C version, so no special care is required on that side (in C, you would leave an -unused element at the beginning of each array; in Julia you don't). - -The relaxed requirements for inputs are also valid for arrays (e.g. one can pass an ``Array{Int64}`` when an array -of ``int`` is expected, and it will be converted automatically). The only exception is for functions which -return an array of values by filling out an allocated array whose pointer is provided by the user. -In that case, the strict version of the rules applies (i.e. you can only pass an ``Array{Int32}`` if an -array of ``int`` is expected). Those functions almost always have an alternative, more convenient formulation -as well, though. - - -5) optional arguments -^^^^^^^^^^^^^^^^^^^^^ - -Whenever the C version accepts the value ``NULL`` to indicate an optional pointer argument, the Julia version -accepts the constant ``nothing``. In case the optional pointer argument is an array, an empty array is -also accepted (it can be of the expected type, e.g. ``Int32[]``, or even just ``[]``) -Most of the time, alternative ways to call the function are also provided. - - -6) fatal errors become exceptions -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Whenever an invalid condition is detected (e.g. if you pass an invalid parameter, such as a negative length), -the Julia GLPK wrapper throws a ``GLPK.Error`` exception with some message detailing what went wrong. -Ideally, all invalid input combinations should be captured by Julia before being passed -over to the library, so that all errors could be catched via a ``try ... catch`` block; -in practice, it is likely that some conditions exist which will leak to the C API and break Julia: this should be -considered as a bug (and reported as such). - -.. _glpk-not-available: - ---------------------------------------------------- -GLPK functions which are not avaliable yet in Julia ---------------------------------------------------- - -In general, all parts of the GLPK API which rely on callback functions are not avaliable in Julia. -In particular, you should not set the callback fields (``cb_func`` and ``cb_info``) in the ``GLPK.IntoptParam`` -type, unless you *really* know what you're doing. - -There are 5 groups of functions which are not wrapped: - -1. The branch & cut API function for mixed integer programming, because they are supposed to be called from - within a callback (see chapter 5 in the GLPK manual); they all start with this prefix: - - * ``glp_ios_*`` - -2. All graph and network routines (anything involving ``glp_graph`` objects); these will be added in the future) - -3. Some misc functions which either have a variable argument list or involve callbacks (see section 6.1 in the GLPK - manual): - - * ``glp_printf`` - * ``glp_vprintf`` - * ``glp_term_hook`` - * ``glp_error`` - * ``glp_assert`` - * ``glp_error_hook`` - -4. Some plain data file reading routines which involve long jumps / varargs (see section 6.2 in the GLPK manual): - - * ``glp_sdf_set_jump`` - * ``glp_sdf_error`` - * ``glp_sdf_warning`` - - -5. One additional routine, which may be included in the future: - - * ``lpx_check_kkt`` - -.. _glpk-different-than-C: - ------------------------------------------------- -Functions which differ from their C counterparts ------------------------------------------------- - -Some library functions return multiple values; as C cannot do this directly, this is obtained via some "pointer gymnastics". -In Julia, on the other hand, this is not necessary, and providing an exact counterpart to the C version would be awkward and -pointless. There are 3 such functions: - -* ``GLPK.analyze_bound`` -* ``GLPK.analyze_coef`` -* ``GLPK.mem_usage`` - -For example the C declaration for ``glp_analyze_bound`` is: - -.. code-block:: c - - void glp_analyze_bound(glp_prob *lp, int k, int *limit1, int *var1, int *limit2, int *var2) - -In Julia, this becomes:: - - GLPK.analyze_bound(glp_prob::GLPK.Prob, k::Integer) - -which returns a tuple:: - - julia> (limit1, var1, limit2, var2) = GLPK.analyze_bound(glp_prob, k) - -The other 2 functions work in the same way, by just returning the values which in C you would pass -as pointers. - -Some other functions have both a strictly-compatible calling form, for simplifying C code porting, -and some more convenient Julia counterparts. See :ref:`the list below ` for more details. - -One function has a different return value: ``GLPK.version`` returns a tuple of integer with the major and minor -version numbers, rather then a string. - -.. _glpk-function-list: - -------------------------------- -List of GLPK functions in Julia -------------------------------- - -As stated above, this list only offers a brief explanation of what each function does and presents alternative -calling forms when available. Refer to the GLPK manual for a complete description. - -.. function:: set_prob_name(glp_prob, name) - - Assigns a name to the problem object (or deletes it if ``name`` is empty or ``nothing``). - -.. function:: set_obj_name(glp_prob, name) - - Assigns a name to the objective function (or deletes it if ``name`` is empty or ``nothing``). - -.. function:: set_obj_dir(glp_prob, dir) - - Sets the optimization direction, ``GLPK.MIN`` (minimization) or ``GLPK.MAX`` (maximization). - -.. function:: add_rows(glp_prob, rows) - - Adds the given number of rows (constraints) to the problem object; returns the number of - the first new row added. - -.. function:: add_cols(glp_prob, cols) - - Adds the given number of columns (structural variables) to the problem object; returns the number of - the first new column added. - -.. function:: set_row_name(glp_prob, row, name) - - Assigns a name to the specified row (or deletes it if ``name`` is empty or ``nothing``). - -.. function:: set_col_name(glp_prob, col, name) - - Assigns a name to the specified column (or deletes it if ``name`` is empty or ``nothing``). - -.. function:: set_row_bnds(glp_prob, row, bounds_type, lb, ub) - - Sets the type and bounds on a row. ``type`` must be one of ``GLPK.FR`` (free), ``GLPK.LO`` (lower bounded), - ``GLPK.UP`` (upper bounded), ``GLPK.DB`` (double bounded), ``GLPK.FX`` (fixed). - - At initialization, each row is free. - -.. function:: set_col_bnds(glp_prob, col, bounds_type, lb, ub) - - Sets the type and bounds on a column. ``type`` must be one of ``GLPK.FR`` (free), ``GLPK.LO`` (lower bounded), - ``GLPK.UP`` (upper bounded), ``GLPK.DB`` (double bounded), ``GLPK.FX`` (fixed). - - At initialization, each column is fixed at 0. - -.. function:: set_obj_coef(glp_prob, col, coef) - - Sets the objective coefficient to a column (``col`` can be 0 to indicate the constant term of the objective function). - -.. function:: set_mat_row(glp_prob, row, [len,] ind, val) - - Sets (replaces) the content of a row. The content is specified in sparse format: ``ind`` is a vector of indices, - ``val`` is the vector of corresponding values. ``len`` is the number of vector elements which will be considered, - and must be less or equal to the length of both ``ind`` and ``val``. If ``len`` is 0, ``ind`` and/or ``val`` can be ``nothing``. - - In Julia, ``len`` can be omitted, and then it is inferred from ``ind`` and ``val`` (which need to have the same length - in such case). - -.. function:: set_mat_col(glp_prob, col, [len,] ind, val) - - Sets (replaces) the content of a column. Everything else is like ``set_mat_row``. - -.. function:: load_matrix(glp_prob, [numel,] ia, ja, ar) - load_matrix(glp_prob, A) - - Sets (replaces) the content matrix (i.e. sets all rows/coluns at once). The matrix is passed in sparse - format. - - In the first form (original C API), it's passed via 3 vectors: ``ia`` and ``ja`` are for rows/columns - indices, ``ar`` is for values. ``numel`` is the number of elements which will be read and must be less or - equal to the length of any of the 3 vectors. If ``numel`` is 0, any of the vectors can be passed as ``nothing``. - - In Julia, ``numel`` can be omitted, and then it is inferred from ``ia``, ``ja`` and ``ar`` (which need to have the same length - in such case). - - Also, in Julia there's a second, simpler calling form, in which the matrix is passed as a ``SparseMatrixCSC`` object. - -.. function:: check_dup(rows, cols, [numel,] ia, ja) - - Check for duplicates in the indices vectors ``ia`` and ``ja``. ``numel`` has the same meaning and (optional) use as in - ``load_matrix``. Returns 0 if no duplicates/out-of-range indices are found, or a positive number indicating where a duplicate - occurs, or a negative number indicating an out-of-bounds index. - -.. function:: sort_matrix(glp_prob) - - Sorts the elements of the problem object's matrix. - -.. function:: del_rows(glp_prob, [num_rows,] rows_ids) - - Deletes rows from the problem object. Rows are specified in the ``rows_ids`` vector. ``num_rows`` is the number of elements - of ``rows_ids`` which will be considered, and must be less or equal to the length id ``rows_ids``. If ``num_rows`` is 0, ``rows_ids`` - can be ``nothing``. In Julia, ``num_rows`` is optional (it's inferred from ``rows_ids`` if not given). - -.. function:: del_cols(glp_prob, cols_ids) - - Deletes columns from the problem object. See ``del_rows``. - -.. function:: copy_prob(glp_prob_dest, glp_prob, copy_names) - - Makes a copy of the problem object. The flag ``copy_names`` determines if names are copied, and must be either ``GLPK.ON`` or ``GLPK.OFF``. - -.. function:: erase_prob(glp_prob) - - Resets the problem object. - -.. function:: get_prob_name(glp_prob) - - Returns the problem object's name. Unlike the C version, if the problem has no assigned name, returns an empty string. - -.. function:: get_obj_name(glp_prob) - - Returns the objective function's name. Unlike the C version, if the objective has no assigned name, returns an empty string. - -.. function:: get_obj_dir(glp_prob) - - Returns the optimization direction, ``GLPK.MIN`` (minimization) or ``GLPK.MAX`` (maximization). - -.. function:: get_num_rows(glp_prob) - - Returns the current number of rows. - -.. function:: get_num_cols(glp_prob) - - Returns the current number of columns. - -.. function:: get_row_name(glp_prob, row) - - Returns the name of the specified row. Unlike the C version, if the row has no assigned name, returns an empty string. - -.. function:: get_col_name(glp_prob, col) - - Returns the name of the specified column. Unlike the C version, if the column has no assigned name, returns an empty string. - -.. function:: get_row_type(glp_prob, row) - - Returns the type of the specified row: ``GLPK.FR`` (free), ``GLPK.LO`` (lower bounded), - ``GLPK.UP`` (upper bounded), ``GLPK.DB`` (double bounded), ``GLPK.FX`` (fixed). - -.. function:: get_row_lb(glp_prob, row) - - Returns the lower bound of the specified row, ``-DBL_MAX`` if unbounded. - -.. function:: get_row_ub(glp_prob, row) - - Returns the upper bound of the specified row, ``+DBL_MAX`` if unbounded. - -.. function:: get_col_type(glp_prob, col) - - Returns the type of the specified column: ``GLPK.FR`` (free), ``GLPK.LO`` (lower bounded), - ``GLPK.UP`` (upper bounded), ``GLPK.DB`` (double bounded), ``GLPK.FX`` (fixed). - -.. function:: get_col_lb(glp_prob, col) - - Returns the lower bound of the specified column, ``-DBL_MAX`` if unbounded. - -.. function:: get_col_ub(glp_prob, col) - - Returns the upper bound of the specified column, ``+DBL_MAX`` if unbounded. - -.. function:: get_obj_coef(glp_prob, col) - - Return the objective coefficient to a column (``col`` can be 0 to indicate the constant term of the objective function). - -.. function:: get_num_nz(glp_prob) - - Return the number of non-zero elements in the constraint matrix. - -.. function:: get_mat_row(glp_prob, row, ind, val) - get_mat_row(glp_prob, row) - - Returns the contents of a row. In the first form (original C API), it fills the ``ind`` and ``val`` vectors provided, - which must be of type ``Vector{Int32}`` and ``Vector{Float64}`` respectively, and have a sufficient length to hold the result - (or they can be empty or ``nothing``, and then they're not filled). It returns the length of the result. - - In Julia, there's a second, simpler calling form which allocates and returns the two vectors as ``(ind, val)``. - -.. function:: get_mat_col(glp_prob, col, ind, val) - get_mat_col(glp_prob, col) - - Returns the contents of a column. See ``get_mat_row``. - -.. function:: create_index(glp_prob) - - Creates the name index (used by ``find_row``, ``find_col``) for the problem object. - -.. function:: find_row(glp_prob, name) - - Finds the numeric id of a row by name. Returns 0 if no row with the given name is found. - -.. function:: find_col(glp_prob, name) - - Finds the numeric id of a column by name. Returns 0 if no column with the given name is found. - -.. function:: delete_index(glp_prob) - - Deletes the name index for the problem object. - -.. function:: set_rii(glp_prob, row, rii) - - Sets the rii scale factor for the specified row. - -.. function:: set_sjj(glp_prob, col, sjj) - - Sets the sjj scale factor for the specified column. - -.. function:: get_rii(glp_prob, row) - - Returns the rii scale factor for the specified row. - -.. function:: get_sjj(glp_prob, col) - - Returns the sjj scale factor for the specified column. - -.. function:: scale_prob(glp_prob, flags) - - Performs automatic scaling of problem data for the problem object. The parameter ``flags`` can be ``GLPK.SF_AUTO`` (automatic) - or a bitwise OR of the forllowing: ``GLPK.SF_GM`` (geometric mean), ``GLPK.SF_EQ`` (equilibration), ``GLPK.SF_2N`` (nearest power of 2), - ``GLPK.SF_SKIP`` (skip if well scaled). - -.. function:: unscale_prob(glp_prob) - - Unscale the problem data (cancels the scaling effect). - -.. function:: set_row_stat(glp_prob, row, stat) - - Sets the status of the specified row. ``stat`` must be one of: ``GLPK.BS`` (basic), ``GLPK.NL`` (non-basic lower bounded), - ``GLPK.NU`` (non-basic upper-bounded), ``GLPK.NF`` (non-basic free), ``GLPK.NS`` (non-basic fixed). - -.. function:: set_col_stat(glp_prob, col, stat) - - Sets the status of the specified column. ``stat`` must be one of: ``GLPK.BS`` (basic), ``GLPK.NL`` (non-basic lower bounded), - ``GLPK.NU`` (non-basic upper-bounded), ``GLPK.NF`` (non-basic free), ``GLPK.NS`` (non-basic fixed). - -.. function:: std_basis(glp_prob) - - Constructs the standard (trivial) initial LP basis for the problem object. - -.. function:: adv_basis(glp_prob[, flags]) - - Constructs an advanced initial LP basis for the problem object. The flag ``flags`` is optional; it must be 0 if given. - -.. function:: cpx_basis(glp_prob) - - Constructs an initial LP basis for the problem object with the algorithm proposed by R. Bixby. - -.. function:: simplex(glp_prob, [glp_param]) - - The routine ``simplex`` is a driver to the LP solver based on the simplex - method. This routine retrieves problem data from the specified problem - object, calls the solver to solve the problem instance, and stores results of - computations back into the problem object. - - The parameters are specified via the optional ``glp_param`` argument, which is of type ``GLPK.SimplexParam`` - (or ``nothing`` to use the default settings). - - Returns 0 in case of success, or a non-zero flag specifying the reason for failure: ``GLPK.EBADB`` (invalid base), - ``GLPK.ESING`` (singular matrix), ``GLPK.ECOND`` (ill-conditioned matrix), ``GLPK.EBOUND`` (incorrect bounds), - ``GLPK.EFAIL`` (solver failure), ``GLPK.EOBJLL`` (lower limit reached), ``GLPK.EOBJUL`` (upper limit reached), - ``GLPK.ITLIM`` (iterations limit exceeded), ``GLPK.ETLIM`` (time limit exceeded), ``GLPK.ENOPFS`` (no primal feasible - solution), ``GLPK.ENODFS`` (no dual feasible solution). - -.. function:: exact(glp_prob, [glp_param]) - - A tentative implementation of the primal two-phase simplex method based on exact (rational) arithmetic. Similar to - ``simplex``. The optional ``glp_param`` is of type ``GLPK.SimplexParam``. - - The possible return values are ``0`` (success) or ``GLPK.EBADB``, ``GLPK.ESING``, ``GLPK.EBOUND``, - ``GLPK.EFAIL``, ``GLPK.ITLIM``, ``GLPK.ETLIM`` (see :func:`simplex`). - -.. function:: init_smcp(glp_param) - - Initializes a ``GLPK.SimplexParam`` object with the default values. In Julia, this is done at object creation time; this - function can be used to reset the object. - -.. function:: get_status(glp_prob) - - Returns the generic status of the current basic solution: ``GLPK.OPT`` (optimal), - ``GLPK.FEAS`` (feasible), ``GLPK.INFEAS`` (infeasible), ``GLPK.NOFEAS`` (no feasible solution), ``GLPK.UNBND`` - (unbounded solution), ``GLPK.UNDEF`` (undefined). - -.. function:: get_prim_stat(glp_prob) - - Returns the status of the primal basic solution: ``GLPK.FEAS``, ``GLPK.INFEAS``, ``GLPK.NOFEAS``, - ``GLPK.UNDEF`` (see :func:`get_status`). - -.. function:: get_dual_stat(glp_prob) - - Returns the status of the dual basic solution: ``GLPK.FEAS``, ``GLPK.INFEAS``, ``GLPK.NOFEAS``, - ``GLPK.UNDEF`` (see :func:`get_status`). - -.. function:: get_obj_val(glp_prob) - - Returns the current value of the objective function. - -.. function:: get_row_stat(glp_prob, row) - - Returns the status of the specified row: ``GLPK.BS``, ``GLPK.NL``, ``GLPK.NU``, ``GLPK.NF``, - ``GLPK.NS`` (see :func:`set_row_stat`). - -.. function:: get_row_prim(glp_prob, row) - - Returns the primal value of the specified row. - -.. function:: get_row_dual(glp_prob, row) - - Returns the dual value (reduced cost) of the specified row. - -.. function:: get_col_stat(glp_prob, col) - - Returns the status of the specified column: ``GLPK.BS``, ``GLPK.NL``, ``GLPK.NU``, ``GLPK.NF``, - ``GLPK.NS`` (see :func:`set_row_stat`). - -.. function:: get_col_prim(glp_prob, col) - - Returns the primal value of the specified column. - -.. function:: get_col_dual(glp_prob, col) - - Returns the dual value (reduced cost) of the specified column. - -.. function:: get_unbnd_ray(glp_prob) - - Returns the number k of a variable, which causes primal or dual unboundedness (if 1 <= k <= rows - it's row k; if rows+1 <= k <= rows+cols it's column k-rows, if k=0 such variable is not defined). - -.. function:: interior(glp_prob, [glp_param]) - - The routine ``interior`` is a driver to the LP solver based on the primal-dual - interior-point method. This routine retrieves problem data from the - specified problem object, calls the solver to solve the problem instance, and - stores results of computations back into the problem object. - - The parameters are specified via the optional ``glp_param`` argument, which is of type ``GLPK.InteriorParam`` - (or ``nothing`` to use the default settings). - - Returns 0 in case of success, or a non-zero flag specifying the reason for failure: ``GLPK.EFAIL`` (solver failure), - ``GLPK.ENOCVG`` (very slow convergence, or divergence), ``GLPK.ITLIM`` (iterations limit exceeded), - ``GLPK.EINSTAB`` (numerical instability). - -.. function:: init_iptcp(glp_param) - - Initializes a ``GLPK.InteriorParam`` object with the default values. In Julia, this is done at object creation time; this - function can be used to reset the object. - -.. function:: ipt_status(glp_prob) - - Returns the status of the interior-point solution: ``GLPK.OPT`` (optimal), - ``GLPK.INFEAS`` (infeasible), ``GLPK.NOFEAS`` (no feasible solution), ``GLPK.UNDEF`` (undefined). - -.. function:: ipt_obj_val(glp_prob) - - Returns the current value of the objective function for the interior-point solution. - -.. function:: ipt_row_prim(glp_prob, row) - - Returns the primal value of the specified row for the interior-point solution. - -.. function:: ipt_row_dual(glp_prob, row) - - Returns the dual value (reduced cost) of the specified row for the interior-point solution. - -.. function:: ipt_col_prim(glp_prob, col) - - Returns the primal value of the specified column for the interior-point solution. - -.. function:: ipt_col_dual(glp_prob, col) - - Returns the dual value (reduced cost) of the specified column for the interior-point solution. - -.. function:: set_col_kind(glp_prob, col, kind) - - Sets the kind for the specified column (for mixed-integer programming). ``kind`` must be one of: - ``GLPK.CV`` (continuous), ``GLPK.IV`` (integer), ``GLPK.BV`` (binary, 0/1). - -.. function:: get_col_kind(glp_prob, col) - - Returns the kind for the specified column (see :func:`set_col_kind`). - -.. function:: get_num_int(glp_prob) - - Returns the number of columns marked as integer (including binary). - -.. function:: get_num_bin(glp_prob) - - Returns the number of columns marked binary. - -.. function:: intopt(glp_prob, [glp_param]) - - The routine ``intopt`` is a driver to the mixed-integer-programming (MIP) solver - based on the branch- and-cut method, which is a hybrid of branch-and-bound - and cutting plane methods. - - The parameters are specified via the optional ``glp_param`` argument, which is of type ``GLPK.IntoptParam`` - (or ``nothing`` to use the default settings). - - Returns 0 in case of success, or a non-zero flag specifying the reason for failure: ``GLPK.EBOUND`` (incorrect bounds), - ``GLPK.EROOT`` (no optimal LP basis given), ``GLPK.ENOPFS`` (no primal feasible LP solution), ``GLPK.ENODFS`` (no dual - feasible LP solution), ``GLPK.EFAIL`` (solver failure), ``GLPK.EMIPGAP`` (mip gap tolearance reached), ``GLPK.ETLIM`` - (time limit exceeded), ``GLPK.ESTOP`` (terminated by application). - -.. function:: init_iocp(glp_param) - - Initializes a ``GLPK.IntoptParam`` object with the default values. In Julia, this is done at object creation time; this - function can be used to reset the object. - -.. function:: mip_status(glp_prob) - - Returns the generic status of the MIP solution: ``GLPK.OPT`` (optimal), - ``GLPK.FEAS`` (feasible), ``GLPK.NOFEAS`` (no feasible solution), ``GLPK.UNDEF`` (undefined). - -.. function:: mip_obj_val(glp_prob) - - Returns the current value of the objective function for the MIP solution. - -.. function:: mip_row_val(glp_prob, row) - - Returns the value of the specified row for the MIP solution. - -.. function:: mip_col_val(glp_prob, col) - - Returns the value of the specified column for the MIP solution. - -.. function:: read_mps(glp_prob, format, [param,] filename) - - Reads problem data in MPS format from a text file. ``format`` must be one of ``GLPK.MPS_DECK`` (fixed, old) or ``GLPK.MPS_FILE`` - (free, modern). ``param`` is optional; if given it must be ``nothing``. - - Returns 0 upon success; throws an error in case of failure. - -.. function:: write_mps(glp_prob, format, [param,] filename) - - Writes problem data in MPS format from a text file. See ``read_mps``. - - Returns 0 upon success; throws an error in case of failure. - -.. function:: read_lp(glp_prob, [param,] filename) - - Reads problem data in CPLEX LP format from a text file. ``param`` is optional; if given it must be ``nothing``. - - Returns 0 upon success; throws an error in case of failure. - -.. function:: write_lp(glp_prob, [param,] filename) - - Writes problem data in CPLEX LP format from a text file. See ``read_lp``. - - Returns 0 upon success; throws an error in case of failure. - -.. function:: read_prob(glp_prob, [flags,] filename) - - Reads problem data in GLPK LP/MIP format from a text file. ``flags`` is optional; if given it must be 0. - - Returns 0 upon success; throws an error in case of failure. - -.. function:: write_prob(glp_prob, [flags,] filename) - - Writes problem data in GLPK LP/MIP format from a text file. See ``read_prob``. - - Returns 0 upon success; throws an error in case of failure. - -.. function:: mpl_read_model(glp_tran, filename, skip) - - Reads the model section and, optionally, the data section, from a text file in MathProg format, and stores it - in ``glp_tran``, which is a ``GLPK.MathProgWorkspace`` object. If ``skip`` is nonzero, the data section is skipped - if present. - - Returns 0 upon success; throws an error in case of failure. - -.. function:: mpl_read_data(glp_tran, filename) - - Reads data section from a text file in MathProg format and stores it in ``glp_tran``, which is a - ``GLPK.MathProgWorkspace`` object. May be called more than once. - - Returns 0 upon success; throws an error in case of failure. - -.. function:: mpl_generate(glp_tran, [filename]) - - Generates the model using its description stored in the ``GLPK.MathProgWorkspace`` translator workspace ``glp_tran``. - The optional ``filename`` specifies an output file; if not given or ``nothing``, the terminal is used. - - Returns 0 upon success; throws an error in case of failure. - -.. function:: mpl_build_prob(glp_tran, glp_prob) - - Transfer information from the ``GLPK.MathProgWorkspace`` translator workspace ``glp_tran`` to the ``GLPK.Prob`` problem - object ``glp_prob``. - -.. function:: mpl_postsolve(glp_tran, glp_prob, sol) - - Copies the solution from the ``GLPK.Prob`` problem object ``glp_prob`` to the ``GLPK.MathProgWorkspace`` translator workspace - ``glp_tran`` and then executes all the remaining model statements, which follow the solve statement. - - The parameter ``sol`` specifies which solution should be copied from the problem object to the workspace: ``GLPK.SOL`` (basic), - ``GLPK.IPT`` (interior-point), ``GLPK.MIP`` (MIP). - - Returns 0 upon success; throws an error in case of failure. - -.. function:: print_sol(glp_prob, filename) - - Writes the current basic solution to a text file, in printable format. - - Returns 0 upon success; throws an error in case of failure. - -.. function:: read_sol(glp_prob, filename) - - Reads the current basic solution from a text file, in the format used by ``write_sol``. - - Returns 0 upon success; throws an error in case of failure. - -.. function:: write_sol(glp_prob, filename) - - Writes the current basic solution from a text file, in a format which can be read by ``read_sol``. - - Returns 0 upon success; throws an error in case of failure. - -.. function:: print_ipt(glp_prob, filename) - - Writes the current interior-point solution to a text file, in printable format. - - Returns 0 upon success; throws an error in case of failure. - -.. function:: read_ipt(glp_prob, filename) - - Reads the current interior-point solution from a text file, in the format used by ``write_ipt``. - - Returns 0 upon success; throws an error in case of failure. - -.. function:: write_ipt(glp_prob, filename) - - Writes the current interior-point solution from a text file, in a format which can be read by ``read_ipt``. - - Returns 0 upon success; throws an error in case of failure. - -.. function:: print_mip(glp_prob, filename) - - Writes the current MIP solution to a text file, in printable format. - - Returns 0 upon success; throws an error in case of failure. - -.. function:: read_mip(glp_prob, filename) - - Reads the current MIP solution from a text file, in the format used by ``write_mip``. - - Returns 0 upon success; throws an error in case of failure. - -.. function:: write_mip(glp_prob, filename) - - Writes the current MIP solution from a text file, in a format which can be read by ``read_mip``. - - Returns 0 upon success; throws an error in case of failure. - -.. function:: print_ranges(glp_prob, [[len,] list,] [flags,] filename) - - Performs sensitivity analysis of current optimal basic solution and writes the analysis report - in human-readable format to a text file. ``list`` is a vector specifying the rows/columns to analyze - (if 1 <= list[i] <= rows, analyzes row list[i]; if rows+1 <= list[i] <= rows+cols, analyzes column - list[i]-rows). ``len`` is the number of elements of ``list`` which will be consideres, and must be smaller - or equal to the length of the list. In Julia, ``len`` is optional (it's inferred from ``len`` if not given). - ``list`` can be empty of ``nothing`` or not given at all, implying all indices will be analyzed. ``flags`` is - optional, and must be 0 if given. - - To call this function, the current basic solution must be optimal, and the basis factorization must exist. - - Returns 0 upon success, non-zero otherwise. - -.. function:: bf_exists(glp_prob) - - Returns non-zero if the basis fatorization for the current basis exists, 0 otherwise. - -.. function:: factorize(glp_prob) - - Computes the basis factorization for the current basis. - - Returns 0 if successful, otherwise: ``GLPK.EBADB`` (invalid matrix), ``GLPK.ESING`` (singluar matrix), - ``GLPK.ECOND`` (ill-conditioned matrix). - -.. function:: bf_updated(glp_prob) - - Returns 0 if the basis factorization was computed from scratch, non-zero otherwise. - -.. function:: get_bfcp(glp_prob, glp_param) - - Retrieves control parameters, which are used on computing and updating the basis factorization - associated with the problem object, and stores them in the ``GLPK.BasisFactParam`` object ``glp_param``. - -.. function:: set_bfcp(glp_prob[, glp_param]) - - Sets the control parameters stored in the ``GLPK.BasisFactParam`` object ``glp_param`` into the problem - object. If ``glp_param`` is ``nothing`` or is omitted, resets the parameters to their defaults. - - The ``glp_param`` should always be retreived via ``get_bfcp`` before changing its values and calling - this function. - -.. function:: get_bhead(glp_prob, k) - - Returns the basis header information for the current basis. ``k`` is a row index. - - Returns either i such that 1 <= i <= rows, if ``k`` corresponds to i-th auxiliary variable, - or rows+j such that 1 <= j <= columns, if ``k`` corresponds to the j-th structural variable. - -.. function:: get_row_bind(glp_prob, row) - - Returns the index of the basic variable ``k`` which is associated with the specified row, or ``0`` if - the variable is non-basic. If ``GLPK.get_bhead(glp_prob, k) == row``, then ``GLPK.get_bind(glp_prob, row) = k``. - -.. function:: get_col_bind(glp_prob, col) - - Returns the index of the basic variable ``k`` which is associated with the specified column, or ``0`` if - the variable is non-basic. If ``GLPK.get_bhead(glp_prob, k) == rows+col``, then ``GLPK.get_bind(glp_prob, col) = k``. - -.. function:: ftran(glp_prob, v) - - Performs forward transformation (FTRAN), i.e. it solves the system Bx = b, where B is the basis matrix, - x is the vector of unknowns to be computed, b is the vector of right-hand sides. At input, ``v`` represents the - vector b; at output, it contains the vector x. ``v`` must be a ``Vector{Float64}`` whose length is the number of rows. - -.. function:: btran(glp_prob, v) - - Performs backward transformation (BTRAN), i.e. it solves the system ``B'x = b``, where ``B`` is the transposed of the basis - matrix, ``x`` is the vector of unknowns to be computed, ``b`` is the vector of right-hand sides. At input, ``v`` represents the - vector ``b``; at output, it contains the vector ``x``. ``v`` must be a ``Vector{Float64}`` whose length is the number of rows. - -.. function:: warm_up(glp_prob) - - "Warms up" the LP basis using current statuses assigned to rows and columns, i.e. computes factorization of the basis - matrix (if it does not exist), computes primal and dual components of basic solution, and determines the solution status. - - Returns 0 if successful, otherwise: ``GLPK.EBADB`` (invalid matrix), ``GLPK.ESING`` (singluar matrix), - ``GLPK.ECOND`` (ill-conditioned matrix). - -.. function:: eval_tab_row(glp_prob, k, ind, val) - eval_tab_row(glp_prob, k) - - Computes a row of the current simplex tableau which corresponds to some basic variable specified by the parameter ``k``. - If 1 <= ``k`` <= rows, uses ``k``-th auxiliary variable; if rows+1 <= ``k`` <= rows+cols, uses (``k``-rows)-th structural - variable. The basis factorization must exist. - - In the first form, stores the result in the provided vectors ``ind`` and ``val``, which must be of type ``Vector{Int32}`` and - ``Vector{Float64}``, respectively, and returns the length of the outcome; in Julia, the vectors will be resized as needed to hold - the result. - - In the second, simpler form, ``ind`` and ``val`` are returned in a tuple as the output of the function. - -.. function:: eval_tab_col(glp_prob, k, ind, val) - eval_tab_col(glp_prob, k) - - Computes a column of the current simplex tableau which corresponds to some non-basic variable specified by the parameter ``k``. - See ``eval_tab_row``. - -.. function:: transform_row(glp_prob, [len,] ind, val) - - Performs the same operation as ``eval_tab_row`` with the exception that the row to be transformed is specified - explicitly as a sparse vector. The parameter ``len`` is the number of elements of ``ind`` and ``val`` which will be used, - and must be smaller or equal to the length of both vectors; in Julia it is optional (and the ``ind`` and ``val`` must have the - same length). The vectors ``int`` and ``val`` must be of type ``Vector{Int32}`` and ``Vector{Float64}``, respectively, since - they will also hold the result; in Julia, they will be resized to the resulting required length. - - Returns the length if the resulting vectors ``ind`` and ``val``. - -.. function:: transform_col(glp_prob, [len,] ind, val) - - Performs the same operation as ``eval_tab_col`` with the exception that the row to be transformed is specified - explicitly as a sparse vector. See ``transform_row``. - -.. function:: prim_rtest(glp_prob, [len,] ind, val, dir, eps) - - Performs the primal ratio test using an explicitly specified column of the simplex table. - The current basic solution must be primal feasible. - The column is specified in sparse format by ``len`` (length of the vector), ``ind`` and ``val`` (indices and values of - the vector). ``len`` is the number of elements which will be considered and must be smaller or equal to the length of - both ``ind`` and ``val``; in Julia, it can be omitted (and then ``ind`` and ``val`` must have the same length). - The indices in ``ind`` must be between 1 and rows+cols; they must correspond to basic variables. - ``dir`` is a direction parameter which must be either +1 (increasing) or -1 (decreasing). - ``eps`` is a tolerance parameter and must be positive. - See the GLPK manual for a detailed explanation. - - Returns the position in ``ind`` and ``val`` which corresponds to the pivot element, or 0 if the choice cannot be made. - -.. function:: dual_rtest(glp_prob, [len,] ind, val, dir, eps) - - Performs the dual ratio test using an explicitly specified row of the simplex table. - The current basic solution must be dual feasible. - The indices in ``ind`` must correspond to non-basic variables. - Everything else is like in ``prim_rtest``. - -.. function:: analyze_bound(glp_prob, k) - - Analyzes the effect of varying the active bound of specified non-basic variable. See the GLPK manual for a - detailed explanation. - In Julia, this function has a different API then C. It returns ``(limit1, var1, limit2, var2)`` rather - then taking them as pointers in the argument list. - -.. function:: analyze_coef(glp_prob, k) - - Analyzes the effect of varying the objective coefficient at specified basic variable. See the GLPK manual for a - detailed explanation. - In Julia, this function has a different API then C. It returns - ``(coef1, var1, value1, coef2, var2, value2)`` rather then taking them as pointers in the argument list. - -.. function:: init_env() - - Initializes the GLPK environment. Not normally needed. - - Returns 0 (initilization successful), 1 (environment already initialized), 2 (failed, insufficient memory) or - 3 (failed, unsupported programming model). - -.. function:: version() - - Returns the GLPK version number. In Julia, instead of returning a string as in C, it returns a tuple of integer - values, containing the major and the minor number. - -.. function:: free_env() - - Frees all resources used by GLPK routines (memory blocks, etc.) which are currently still in use. Not normally needed. - - Returns 0 if successful, 1 if envirnoment is inactive. - -.. function:: term_out(flag) - - Enables/disables the terminal output of glpk routines. ``flag`` is either ``GLPK.ON`` (output enabled) or ``GLPK.OFF`` - (output disabled). - - Returns the previous status of the terminal output. - -.. function:: open_tee(filename) - - Starts copying all the terminal output to an output text file. - - Returns 0 if successful, 1 if already active, 2 if it fails creating the output file. - -.. function:: close_tee() - - Stops copying the terminal output to the output text file previously open by the ``open_tee``. - - Return 0 if successful, 1 if copying terminal output was not started. - -.. function:: malloc(size) - - Replacement of standard C ``malloc``. Allocates uninitialized memeory which must freed with ``free``. - - Returns a pointer to the allocated memory. - -.. function:: calloc(n, size) - - Replacement of standard C ``calloc``, but does not initialize the memeory. - Allocates uninitialized memeory which must freed with ``free``. - - Returns a pointer to the allocated memory. - -.. function:: free(ptr) - - Deallocates a memory block previously allocated by ``malloc`` or ``calloc``. - -.. function:: mem_usage() - - Reports some information about utilization of the memory by the routines ``malloc``, ``calloc``, - and ``free``. - In Julia, this function has a different API then C. It returns ``(count, cpeak, total, tpeak)`` rather - then taking them as pointers in the argument list. - -.. function:: mem_limit(limit) - - Limits the amount of memory avaliable for dynamic allocation to a value in megabyes given by the integer - parameter ``limit``. - -.. function:: time() - - Returns the current universal time (UTC), in milliseconds. - -.. function:: difftime(t1, t0) - - Returns the difference between two time values ``t1`` and ``t0``, expressed in seconds. - -.. function:: sdf_open_file(filename) - - Opens a plain data file. - - If successful, returns a ``GLPK.Data`` object, otherwise throws an error. - -.. function:: sdf_read_int(glp_data) - - Reads an integer number from the plain data file specified by the ``GLPK.Data`` parameter ``glp_data``, skipping initial - whitespace. - -.. function:: sdf_read_num(glp_data) - - Reads a floating point number from the plain data file specified by the ``GLPK.Data`` parameter ``glp_data``, skipping initial - whitespace. - -.. function:: sdf_read_item(glp_data) - - Reads a data item (a String) from the plain data file specified by the ``GLPK.Data`` parameter ``glp_data``, skipping initial - whitespace. - -.. function:: sdf_read_text(glp_data) - - Reads a line of text from the plain data file specified by the ``GLPK.Data`` parameter ``glp_data``, skipping initial and final - whitespace. - -.. function:: sdf_line(glp_data) - - Returns the current line in the ``GLPK.Data`` object ``glp_data`` - -.. function:: sdf_close_file(glp_data) - - Closes the file associated to ``glp_data`` and frees the resources. - -.. function:: read_cnfsat(glp_prob, filename) - - Reads the CNF-SAT problem data in DIMACS format from a text file. - - Returns 0 upon success; throws an error in case of failure. - -.. function:: check_cnfsat(glp_prob) - - Checks if the problem object encodes a CNF-SAT problem instance, in which case it returns 0, - otherwise returns non-zero. - -.. function:: write_cnfsat(glp_prob, filename) - - Writes the CNF-SAT problem data in DIMACS format into a text file. - - Returns 0 upon success; throws an error in case of failure. - -.. function:: minisat1(glp_prob) - - The routine ``minisat1`` is a driver to MiniSat, a CNF-SAT solver developed by - Niklas Eén and Niklas Sörensson, Chalmers University of Technology, Sweden. - - Returns 0 in case of success, or a non-zero flag specifying the reason for failure: ``GLPK.EDATA`` - (problem is not CNF-SAT), ``GLPK.EFAIL`` (solver failure). - -.. function:: intfeas1(glp_prob, use_bound, obj_bound) - - The routine ``glp_intfeas1`` is a tentative implementation of an integer feasibility solver - based on a CNF-SAT solver (currently MiniSat). ``use_bound`` is a flag: if zero, any feasible solution - is seeked, otherwise seraches for an integer feasible solution. ``obj_bound`` is used only if - ``use_bound`` is non-zero, and specifies an upper/lower bound (for maximization/minimazion respectively) - to the objective function. - - All variables (columns) must either be binary or fixed. All constraint and objective coeffient - must be integer. - - Returns 0 in case of success, or a non-zero flag specifying the reason for failure: ``GLPK.EDATA`` - (problem data is not valid), ``GLPK.ERANGE`` (integer overflow occurred), ``GLPK.EFAIL`` (solver failure). diff --git a/doc/stdlib/gzip.rst b/doc/stdlib/gzip.rst deleted file mode 100644 index 6380255b35e63..0000000000000 --- a/doc/stdlib/gzip.rst +++ /dev/null @@ -1,129 +0,0 @@ -:mod:`GZip` --- Wrapper for gzip functions in zlib -===================================================== - -.. module:: GZip - :synopsis: Wrapper for gzip functions in zlib - -.. note:: located in ``gzip.jl`` - -This module provides a wrapper for the gzip related functions of -(`zlib `_), a free, general-purpose, legally -unencumbered, lossless data-compression library. These functions -allow the reading and writing of gzip files. - -It is currently based on ``zlib`` 1.2.7. - ------ -Notes ------ - - * This interface is only for gzipped files, not the streaming zlib - compression interface. Internally, it depends on/uses the streaming - interface, but the gzip related functions are higher level - functions pertaining to gzip files only. - - * :class:`GZipStream` is an implementation of :class:`IO` and can be used virtually - anywhere :class:`IO` is used. - - * This implementation mimics the :class:`IOStream` implementation, and should - be a drop-in replacement for :class:`IOStream`, with some exceptions: - - * :func:`seek_end` and :func:`truncate` are not available - * :func:`readuntil` is available, but is not very efficient. - (But :func:`readline` works fine.) - -In addition to :func:`gzopen` and :func:`gzfdio`/:func:`gzdopen`, the -following :class:`IO`/:class:`IOStream` functions are supported: - - :func:`close()` - :func:`flush()` - :func:`seek()` - :func:`skip()` - :func:`position()` - :func:`eof()` - :func:`read()` - :func:`readuntil()` - :func:`readline()` - :func:`write()` - -Due to limitations in ``zlib``, :func:`seek_end` and :func:`truncate` are not available. - ---------- -Functions ---------- - -.. function:: gzopen(fname[, gzmode[, buf_size]]) - - Opens a file with mode (default ``"r"``), setting internal buffer size - to buf_size (default ``Z_DEFAULT_BUFSIZE=8192``), and returns a the - file as a :class:`GZipStream`. - - ``gzmode`` must contain one of - - ==== ================================= - r read - w write, create, truncate - a write, create, append - ==== ================================= - - In addition, gzmode may also contain - - ===== ================================= - x create the file exclusively - (fails if file exists) - 0-9 compression level - ===== ================================= - - and/or a compression strategy: - - ==== ================================= - f filtered data - h Huffman-only compression - R run-length encoding - F fixed code compression - ==== ================================= - - Note that ``+`` is not allowed in gzmode. - - If an error occurs, ``gzopen`` throws a :class:`GZError` - - -.. function:: gzdopen(fd[, gzmode[, buf_size]]) - - Create a :class:`GZipStream` object from an integer file descriptor. - See :func:`gzopen` for ``gzmode`` and ``buf_size`` descriptions. - -.. function:: gzdopen(s[, gzmode[, buf_size]]) - - Create a :class:`GZipStream` object from :class:`IOStream` ``s``. - ------ -Types ------ - -.. type:: GZipStream(name, gz_file[, buf_size[, fd[, s]]]) - - Subtype of :class:`IO` which wraps a gzip stream. Returned by - :func:`gzopen` and :func:`gzdopen`. - -.. type:: GZError(err, err_str) - - gzip error number and string. Possible error values: - - +---------------------+----------------------------------------+ - | ``Z_OK`` | No error | - +---------------------+----------------------------------------+ - | ``Z_ERRNO`` | Filesystem error (consult ``errno()``) | - +---------------------+----------------------------------------+ - | ``Z_STREAM_ERROR`` | Inconsistent stream state | - +---------------------+----------------------------------------+ - | ``Z_DATA_ERROR`` | Compressed data error | - +---------------------+----------------------------------------+ - | ``Z_MEM_ERROR`` | Out of memory | - +---------------------+----------------------------------------+ - | ``Z_BUF_ERROR`` | Input buffer full/output buffer empty | - +---------------------+----------------------------------------+ - | ``Z_VERSION_ERROR`` | zlib library version is incompatible | - | | with caller version | - +---------------------+----------------------------------------+ - diff --git a/doc/stdlib/index.rst b/doc/stdlib/index.rst index 9ae98fcc94c48..e9e02479386cc 100644 --- a/doc/stdlib/index.rst +++ b/doc/stdlib/index.rst @@ -16,31 +16,19 @@ Built-ins :maxdepth: 1 base - -****** -Extras -****** - -.. toctree:: - :maxdepth: 1 - - profile - options - cpp - textwrap - zlib - strpack - sound - argparse - gzip + sparse + linalg + constants + file + punctuation **************** -Math & Numerical +Built-in Modules **************** .. toctree:: :maxdepth: 1 - blas - glpk + sort + diff --git a/doc/stdlib/linalg.rst b/doc/stdlib/linalg.rst new file mode 100644 index 0000000000000..1faf8fe1431ee --- /dev/null +++ b/doc/stdlib/linalg.rst @@ -0,0 +1,395 @@ +Linear Algebra +-------------- + +Linear algebra functions in Julia are largely implemented by calling functions from `LAPACK `_. Sparse factorizations call functions from `SuiteSparse `_. + +.. function:: *(A, B) + + Matrix multiplication + +.. function:: \\(A, B) + + Matrix division using a polyalgorithm. For input matrices ``A`` and ``B``, the result ``X`` is such that ``A*X == B`` when ``A`` is square. The solver that is used depends upon the structure of ``A``. A direct solver is used for upper- or lower triangular ``A``. For Hermitian ``A`` (equivalent to symmetric ``A`` for non-complex ``A``) the BunchKaufman factorization is used. Otherwise an LU factorization is used. For rectangular ``A`` the result is the minimum-norm least squares solution computed by reducing ``A`` to bidiagonal form and solving the bidiagonal least squares problem. For sparse, square ``A`` the LU factorization (from UMFPACK) is used. + +.. function:: dot(x, y) + + Compute the dot product + +.. function:: cross(x, y) + + Compute the cross product of two 3-vectors + +.. function:: norm(a) + + Compute the norm of a ``Vector`` or a ``Matrix`` + +.. function:: lu(A) -> L, U, P + + Compute the LU factorization of ``A``, such that ``P*A = L*U``. + +.. function:: lufact(A) -> LU + + Compute the LU factorization of ``A``, returning an ``LU`` object for dense ``A`` or an ``UmfpackLU`` object for sparse ``A``. The individual components of the factorization ``F`` can be accesed by indexing: ``F[:L]``, ``F[:U]``, and ``F[:P]`` (permutation matrix) or ``F[:p]`` (permutation vector). An ``UmfpackLU`` object has additional components ``F[:q]`` (the left permutation vector) and ``Rs`` the vector of scaling factors. The following functions are available for both ``LU`` and ``UmfpackLU`` objects: ``size``, ``\`` and ``det``. For ``LU`` there is also an ``inv`` method. The sparse LU factorization is such that ``L*U`` is equal to``diagmm(Rs,A)[p,q]``. + +.. function:: lufact!(A) -> LU + + ``lufact!`` is the same as ``lufact`` but saves space by overwriting the input A, instead of creating a copy. For sparse ``A`` the ``nzval`` field is not overwritten but the index fields, ``colptr`` and ``rowval`` are decremented in place, converting from 1-based indices to 0-based indices. + +.. function:: chol(A, [LU]) -> F + + Compute Cholesky factorization of a symmetric positive-definite matrix ``A`` and return the matrix ``F``. If ``LU`` is ``L`` (Lower), ``A = L*L'``. If ``LU`` is ``U`` (Upper), ``A = R'*R``. + +.. function:: cholfact(A, [LU]) -> Cholesky + + Compute the Cholesky factorization of a dense symmetric positive-definite matrix ``A`` and return a ``Cholesky`` object. ``LU`` may be 'L' for using the lower part or 'U' for the upper part. The default is to use 'U'. The triangular matrix can be obtained from the factorization ``F`` with: ``F[:L]`` and ``F[:U]``. The following functions are available for ``Cholesky`` objects: ``size``, ``\``, ``inv``, ``det``. A ``LAPACK.PosDefException`` error is thrown in case the matrix is not positive definite. + +.. function:: cholfact(A, [ll]) -> CholmodFactor + + Compute the sparse Cholesky factorization of a sparse matrix ``A``. If ``A`` is Hermitian its Cholesky factor is determined. If ``A`` is not Hermitian the Cholesky factor of ``A*A'`` is determined. A fill-reducing permutation is used. Methods for ``size``, ``solve``, ``\``, ``findn_nzs``, ``diag``, ``det`` and ``logdet``. One of the solve methods includes an integer argument that can be used to solve systems involving parts of the factorization only. The optional boolean argument, ``ll`` determines whether the factorization returned is of the ``A[p,p] = L*L'`` form, where ``L`` is lower triangular or ``A[p,p] = diagmm(L,D)*L'`` form where ``L`` is unit lower triangular and ``D`` is a non-negative vector. The default is LDL. + +.. function:: cholfact!(A, [LU]) -> Cholesky + + ``cholfact!`` is the same as ``cholfact`` but saves space by overwriting the input A, instead of creating a copy. + +.. function:: cholpfact(A, [LU]) -> CholeskyPivoted + + Compute the pivoted Cholesky factorization of a symmetric positive semi-definite matrix ``A`` and return a ``CholeskyPivoted`` object. ``LU`` may be 'L' for using the lower part or 'U' for the upper part. The default is to use 'U'. The triangular factors containted in the factorization ``F`` can be obtained with ``F[:L]`` and ``F[:U]``, whereas the permutation can be obtained with ``F[:P]`` or ``F[:p]``. The following functions are available for ``CholeskyPivoted`` objects: ``size``, ``\``, ``inv``, ``det``. A ``LAPACK.RankDeficientException`` error is thrown in case the matrix is rank deficient. + +.. function:: cholpfact!(A, [LU]) -> CholeskyPivoted + + ``cholpfact!`` is the same as ``cholpfact`` but saves space by overwriting the input A, instead of creating a copy. + +.. function:: qr(A, [thin]) -> Q, R + + Compute the QR factorization of ``A`` such that ``A = Q*R``. Also see ``qrfact``. The default is to compute a thin factorization. + +.. function:: qrfact(A) + + Compute the QR factorization of ``A`` and return a ``QR`` object. The coomponents of the factorization ``F`` can be accessed as follows: the orthogonal matrix ``Q`` can be extracted with ``F[:Q]`` and the triangular matrix ``R`` with ``F[:R]``. The following functions are available for ``QR`` objects: ``size``, ``\``. When ``Q`` is extracted, the resulting type is the ``QRPackedQ`` object, and has the ``*`` operator overloaded to support efficient multiplication by ``Q`` and ``Q'``. + +.. function:: qrfact!(A) + + ``qrfact!`` is the same as ``qrfact`` but saves space by overwriting the input A, instead of creating a copy. + +.. function:: qrp(A, [thin]) -> Q, R, P + + Compute the QR factorization of ``A`` with pivoting, such that ``A*P = Q*R``, Also see ``qrpfact``. The default is to compute a thin factorization. + +.. function:: qrpfact(A) -> QRPivoted + + Compute the QR factorization of ``A`` with pivoting and return a ``QRPivoted`` object. The components of the factorization ``F`` can be accessed as follows: the orthogonal matrix ``Q`` can be extracted with ``F[:Q]``, the triangular matrix ``R`` with ``F[:R]``, and the permutation with ``F[:P]`` or ``F[:p]``. The following functions are available for ``QRPivoted`` objects: ``size``, ``\``. When ``Q`` is extracted, the resulting type is the ``QRPivotedQ`` object, and has the ``*`` operator overloaded to support efficient multiplication by ``Q`` and ``Q'``. A ``QRPivotedQ`` matrix can be converted into a regular matrix with ``full``. + +.. function:: qrpfact!(A) -> QRPivoted + + ``qrpfact!`` is the same as ``qrpfact`` but saves space by overwriting the input A, instead of creating a copy. + +.. function:: sqrtm(A) + + Compute the matrix square root of ``A``. If ``B = sqrtm(A)``, then ``B*B == A`` within roundoff error. + +.. function:: eig(A) -> D, V + + Compute eigenvalues and eigenvectors of A + +.. function:: eigvals(A) + + Returns the eigenvalues of ``A``. + +.. function:: eigmax(A) + + Returns the largest eigenvalue of ``A``. + +.. function:: eigmin(A) + + Returns the smallest eigenvalue of ``A``. + +.. function:: eigvecs(A, [eigvals]) + + Returns the eigenvectors of ``A``. + + For SymTridiagonal matrices, if the optional vector of eigenvalues ``eigvals`` is specified, returns the specific corresponding eigenvectors. + +.. function:: eigfact(A) + + Compute the eigenvalue decomposition of ``A`` and return an ``Eigen`` object. If ``F`` is the factorization object, the eigenvalues can be accessed with ``F[:values]`` and the eigenvectors with ``F[:vectors]``. The following functions are available for ``Eigen`` objects: ``inv``, ``det``. + +.. function:: eigfact!(A) + + ``eigfact!`` is the same as ``eigfact`` but saves space by overwriting the input A, instead of creating a copy. + +.. function:: hessfact(A) + + Compute the Hessenberg decomposition of ``A`` and return a ``Hessenberg`` object. If ``F`` is the factorization object, the unitary matrix can be accessed with ``F[:Q]`` and the Hessenberg matrix with ``F[:H]``. When ``Q`` is extracted, the resulting type is the ``HessenbergQ`` object, and may be converted to a regular matrix with ``full``. + +.. function:: hessfact!(A) + + ``hessfact!`` is the same as ``hessfact`` but saves space by overwriting the input A, instead of creating a copy. + +.. function:: schurfact(A) -> Schur + + Computes the Schur factorization of the matrix ``A``. The (quasi) triangular Schur factor can be obtained from the ``Schur`` object ``F`` with either ``F[:Schur]`` or ``F[:T]`` and the unitary/orthogonal Schur vectors can be obtained with ``F[:vectors]`` or ``F[:Z]`` such that ``A=F[:vectors]*F[:Schur]*F[:vectors]'``. The eigenvalues of ``A`` can be obtained with ``F[:values]``. + +.. function:: schur(A) -> Schur[:T], Schur[:Z], Schur[:values] + + See schurfact + +.. function:: schurfact(A, B) -> GeneralizedSchur + + Computes the Generalized Schur (or QZ) factorization of the matrices ``A`` and ``B``. The (quasi) triangular Schur factors can be obtained from the ``Schur`` object ``F`` with ``F[:S]`` and ``F[:T]``, the left unitary/orthogonal Schur vectors can be obtained with ``F[:left]`` or ``F[:Q]`` and the right unitary/orthogonal Schur vectors can be obtained with ``F[:right]`` or ``F[:Z]`` such that ``A=F[:left]*F[:S]*F[:right]'`` and ``B=F[:left]*F[:T]*F[:right]'``. The generalized eigenvalues of ``A`` and ``B`` can be obtained with ``F[:alpha]./F[:beta]``. + +.. function:: schur(A,B) -> GeneralizedSchur[:S], GeneralizedSchur[:T], GeneralizedSchur[:Q], GeneralizedSchur[:Z] + + See schurfact + +.. function:: svdfact(A, [thin]) -> SVD + + Compute the Singular Value Decomposition (SVD) of ``A`` and return an ``SVD`` object. ``U``, ``S``, ``V`` and ``Vt`` can be obtained from the factorization ``F`` with ``F[:U]``, ``F[:S]``, ``F[:V]`` and ``F[:Vt]``, such that ``A = U*diagm(S)*Vt``. If ``thin`` is ``true``, an economy mode decomposition is returned. The algorithm produces ``Vt`` and hence ``Vt`` is more efficient to extract than ``V``. The default is to produce a thin decomposition. + +.. function:: svdfact!(A, [thin]) -> SVD + + ``svdfact!`` is the same as ``svdfact`` but saves space by overwriting the input A, instead of creating a copy. If ``thin`` is ``true``, an economy mode decomposition is returned. The default is to produce a thin decomposition. + +.. function:: svd(A, [thin]) -> U, S, V + + Compute the SVD of A, returning ``U``, vector ``S``, and ``V`` such that ``A == U*diagm(S)*V'``. If ``thin`` is ``true``, an economy mode decomposition is returned. + +.. function:: svdvals(A) + + Returns the singular values of ``A``. + +.. function:: svdvals!(A) + + Returns the singular values of ``A``, while saving space by overwriting the input. + +.. function:: svdfact(A, B) -> GeneralizedSVD + + Compute the generalized SVD of ``A`` and ``B``, returning a ``GeneralizedSVD`` Factorization object, such that ``A = U*D1*R0*Q'`` and ``B = V*D2*R0*Q'``. + +.. function:: svd(A, B) -> U, V, Q, D1, D2, R0 + + Compute the generalized SVD of ``A`` and ``B``, returning ``U``, ``V``, ``Q``, ``D1``, ``D2``, and ``R0`` such that ``A = U*D1*R0*Q'`` and ``B = V*D2*R0*Q'``. + +.. function:: svdvals(A, B) + + Return only the singular values from the generalized singular value decomposition of ``A`` and ``B``. + +.. function:: triu(M) + + Upper triangle of a matrix + +.. function:: tril(M) + + Lower triangle of a matrix + +.. function:: diag(M, [k]) + + The ``k``-th diagonal of a matrix, as a vector + +.. function:: diagm(v, [k]) + + Construct a diagonal matrix and place ``v`` on the ``k``-th diagonal + +.. function:: diagmm(matrix, vector) + + Multiply matrices, interpreting the vector argument as a diagonal matrix. + The arguments may occur in the other order to multiply with the diagonal + matrix on the left. + +.. function:: Tridiagonal(dl, d, du) + + Construct a tridiagonal matrix from the lower diagonal, diagonal, and upper diagonal + +.. function:: Bidiagonal(dv, ev, isupper) + + Constructs an upper (isupper=true) or lower (isupper=false) bidiagonal matrix + using the given diagonal (dv) and off-diagonal (ev) vectors + +.. function:: Woodbury(A, U, C, V) + + Construct a matrix in a form suitable for applying the Woodbury matrix identity + +.. function:: rank(M) + + Compute the rank of a matrix + +.. function:: norm(A, [p]) + + Compute the ``p``-norm of a vector or a matrix. ``p`` is ``2`` by default, if not provided. If ``A`` is a vector, ``norm(A, p)`` computes the ``p``-norm. ``norm(A, Inf)`` returns the largest value in ``abs(A)``, whereas ``norm(A, -Inf)`` returns the smallest. If ``A`` is a matrix, valid values for ``p`` are ``1``, ``2``, or ``Inf``. In order to compute the Frobenius norm, use ``normfro``. + +.. function:: normfro(A) + + Compute the Frobenius norm of a matrix ``A``. + +.. function:: cond(M, [p]) + + Matrix condition number, computed using the p-norm. ``p`` is 2 by default, if not provided. Valid values for ``p`` are ``1``, ``2``, or ``Inf``. + +.. function:: trace(M) + + Matrix trace + +.. function:: det(M) + + Matrix determinant + +.. function:: inv(M) + + Matrix inverse + +.. function:: pinv(M) + + Moore-Penrose inverse + +.. function:: null(M) + + Basis for null space of M. + +.. function:: repmat(A, n, m) + + Construct a matrix by repeating the given matrix ``n`` times in dimension 1 and ``m`` times in dimension 2. + +.. function:: kron(A, B) + + Kronecker tensor product of two vectors or two matrices. + +.. function:: linreg(x, y) + + Determine parameters ``[a, b]`` that minimize the squared error between ``y`` and ``a+b*x``. + +.. function:: linreg(x, y, w) + + Weighted least-squares linear regression. + +.. function:: expm(A) + + Matrix exponential. + +.. function:: issym(A) + + Test whether a matrix is symmetric. + +.. function:: isposdef(A) + + Test whether a matrix is positive-definite. + +.. function:: istril(A) + + Test whether a matrix is lower-triangular. + +.. function:: istriu(A) + + Test whether a matrix is upper-triangular. + +.. function:: ishermitian(A) + + Test whether a matrix is hermitian. + +.. function:: transpose(A) + + The transpose operator (.'). + +.. function:: ctranspose(A) + + The conjugate transpose operator ('). + + +BLAS Functions +-------------- + +This module provides wrappers for some of the BLAS functions for +linear algebra. Those BLAS functions that overwrite one of the input +arrays have names ending in ``'!'``. + +Usually a function has 4 methods defined, one each for ``Float64``, +``Float32``, ``Complex128`` and ``Complex64`` arrays. + +.. function:: copy!(n, X, incx, Y, incy) + + Copy ``n`` elements of array ``X`` with stride ``incx`` to array + ``Y`` with stride ``incy``. Returns ``Y``. + +.. function:: dot(n, X, incx, Y, incy) + + Dot product of two vectors consisting of ``n`` elements of array + ``X`` with stride ``incx`` and ``n`` elements of array ``Y`` with + stride ``incy``. There are no ``dot`` methods for ``Complex`` + arrays. + +.. function:: nrm2(n, X, incx) + + 2-norm of a vector consisting of ``n`` elements of array ``X`` with + stride ``incx``. + +.. function:: axpy!(n, a, X, incx, Y, incy) + + Overwrite ``Y`` with ``a*X + Y``. Returns ``Y``. + +.. function:: syrk!(uplo, trans, alpha, A, beta, C) + + Rank-k update of the symmetric matrix ``C`` as ``alpha*A*A.' + + beta*C`` or ``alpha*A.'*A + beta*C`` according to whether ``trans`` + is 'N' or 'T'. When ``uplo`` is 'U' the upper triangle of ``C`` is + updated ('L' for lower triangle). Returns ``C``. + +.. function:: syrk(uplo, trans, alpha, A) + + Returns either the upper triangle or the lower triangle, according + to ``uplo`` ('U' or 'L'), of ``alpha*A*A.'`` or ``alpha*A.'*A``, + according to ``trans`` ('N' or 'T'). + +.. function:: herk!(uplo, trans, alpha, A, beta, C) + + Methods for complex arrays only. Rank-k update of the Hermitian + matrix ``C`` as ``alpha*A*A' + beta*C`` or ``alpha*A'*A + beta*C`` + according to whether ``trans`` is 'N' or 'T'. When ``uplo`` is 'U' + the upper triangle of ``C`` is updated ('L' for lower triangle). + Returns ``C``. + +.. function:: herk(uplo, trans, alpha, A) + + Methods for complex arrays only. Returns either the upper triangle + or the lower triangle, according to ``uplo`` ('U' or 'L'), of + ``alpha*A*A'`` or ``alpha*A'*A``, according to ``trans`` ('N' or 'T'). + +.. function:: gbmv!(trans, m, kl, ku, alpha, A, x, beta, y) + + Update vector ``y`` as ``alpha*A*x + beta*y`` or ``alpha*A'*x + + beta*y`` according to ``trans`` ('N' or 'T'). The matrix ``A`` is + a general band matrix of dimension ``m`` by ``size(A,2)`` with + ``kl`` sub-diagonals and ``ku`` super-diagonals. Returns the + updated ``y``. + +.. function:: gbmv(trans, m, kl, ku, alpha, A, x, beta, y) + + Returns ``alpha*A*x`` or ``alpha*A'*x`` according to ``trans`` ('N' + or 'T'). The matrix ``A`` is a general band matrix of dimension + ``m`` by ``size(A,2)`` with ``kl`` sub-diagonals and + ``ku`` super-diagonals. + +.. function:: sbmv!(uplo, k, alpha, A, x, beta, y) + + Update vector ``y`` as ``alpha*A*x + beta*y`` where ``A`` is a + a symmetric band matrix of order ``size(A,2)`` with + ``k`` super-diagonals stored in the argument ``A``. The storage + layout for ``A`` is described the reference BLAS module, level-2 + BLAS at ``. + + Returns the updated ``y``. + +.. function:: sbmv(uplo, k, alpha, A, x) + + Returns ``alpha*A*x`` where ``A`` is a symmetric band matrix of + order ``size(A,2)`` with ``k`` super-diagonals stored in the + argument ``A``. + +.. function:: gemm!(tA, tB, alpha, A, B, beta, C) + + Update ``C`` as ``alpha*A*B + beta*C`` or the other three variants + according to ``tA`` (transpose ``A``) and ``tB``. Returns the + updated ``C``. + +.. function:: gemm(tA, tB, alpha, A, B) + + Returns ``alpha*A*B`` or the other three variants + according to ``tA`` (transpose ``A``) and ``tB``. + diff --git a/doc/stdlib/options.rst b/doc/stdlib/options.rst deleted file mode 100644 index 38a7c23a7d8da..0000000000000 --- a/doc/stdlib/options.rst +++ /dev/null @@ -1,138 +0,0 @@ -:mod:`OptionsMod` --- Optional arguments to functions -===================================================== - -.. module:: OptionsMod - :synopsis: Allows a flexible approach to providing default values for parameters in functions - -.. note:: located in ``options.jl`` - -This module allows a flexible approach to providing default values for parameters in functions. - -.. function:: @options([check_flag,] assignments...) - - Use the ``@options`` macro to set the value of optional parameters for a function that has been written - to use them (see :func:`defaults` to learn how to write such functions). The syntax is:: - - opts = @options a=5 b=7 - - For a function that uses optional parameters ``a`` and ``b``, this will override the default settings - for these parameters. You would likely call that function in the following way:: - - myfunc(requiredarg1, requiredarg2, ..., opts) - - Most functions written to use optional arguments will probably check to make sure that you are not - supplying parameters that are never used by the function or its sub-functions. Typically, supplying - unused parameters will result in an error. You can control the behavior this way:: - - # throw an error if a or b is not used (the default) - opts = @options CheckError a=5 b=2 - # issue a warning if a or b is not used - opts = @options CheckWarn a=5 b=2 - # don't check whether a and b are used - opts = @options CheckNone a=5 b=2 - - As an alternative to the macro syntax, you can also say:: - - opts = Options(CheckWarn, :a, 5, :b, 2) - - The check flag is optional. - -.. function:: @set_options(opts, assigments...) - - The ``@set_options`` macro lets you add new parameters to an existing options structure. For example:: - - @set_options opts d=99 - - would add ``d`` to the set of parameters in ``opts``, or re-set its value if it was already supplied. - -.. function:: @defaults(opts, assignments...) - - The ``@defaults`` macro is for writing functions that take optional parameters. The typical syntax of - such functions is:: - - function myfunc(requiredarg1, requiredarg2, ..., opts::Options) - @defaults opts a=11 b=2a+1 c=a*b d=100 - # The function body. Use a, b, c, and d just as you would - # any other variable. For example, - k = a + b - # You can pass opts down to subfunctions, which might supply - # additional defaults for other variables aa, bb, etc. - y = subfun(k, opts) - # Terminate your function with check_used, then return values - @check_used opts - return y - end - - Note the function calls :func:`@check_used` at the end. - - It is possible to have more than one Options parameter to a function, for example:: - - function twinopts(x, plotopts::Options, calcopts::Options) - @defaults plotopts linewidth=1 - @defaults calcopts n_iter=100 - # Do stuff - @check_used plotopts - @check_used calcopts - end - - Within a given scope, you should only have one call to ``@defaults`` per options variable. - -.. function:: @check_used(opts) - - The ``@check_used`` macro tests whether user-supplied parameters were ever accessed by the :func:`@defaults` - macro. The test is performed at the end of the function body, so that subfunction handling parameters not - used by the parent function may be "credited" for their usage. Each sub-function should also call - ``@check_used``, for example:: - - function complexfun(x, opts::Options) - @defaults opts parent=3 both=7 - println(parent) - println(both) - subfun1(x, opts) - subfun2(x, opts) - @check_used opts - end - - function subfun1(x, opts::Options) - @defaults opts sub1="sub1 default" both=0 - println(sub1) - println(both) - @check_used opts - end - - function subfun2(x, opts::Options) - @defaults opts sub2="sub2 default" both=22 - println(sub2) - println(both) - @check_used opts - end - - -Advanced topics ---------------- - -.. type:: Options(OptionsChecking, param1, val1, param2, val2, ...) - - ``Options`` is the central type used for handling optional arguments. Its fields are briefly described below. - - .. attribute:: key2index - - A ``Dict`` that looks up an integer index, given the symbol for a variable (e.g., ``key2index[:a]`` for - the variable ``a``) - - .. attribute:: vals - - ``vals[key2index[:a]]`` is the value to be assigned to the variable ``a`` - - .. attribute:: used - - A vector of booleans, one per variable, with ``used[key2index[:a]]`` representing the value for variable - ``a``. These all start as ``false``, but access by a ``@defaults`` command sets the corresponding value - to ``true``. This marks the variable as having been used in the function. - - .. attribute:: check_lock - - A vector of booleans, one per variable. This is a "lock" that prevents sub-functions from complaining - that they did not access variables that were intended for the parent function. :func:`@defaults` sets the - lock to true for any options variables that have already been defined; new variables added through - :func:`@set_options` will start with their ``check_lock`` set to ``false``, to be handled by a subfunction. diff --git a/doc/stdlib/profile.rst b/doc/stdlib/profile.rst deleted file mode 100644 index 32e6cb7455e0c..0000000000000 --- a/doc/stdlib/profile.rst +++ /dev/null @@ -1,68 +0,0 @@ -profile.jl --- A simple profiler for Julia -========================================== - -.. .. module:: profile.jl - :synopsis: Allows you to determine running times for each line of code. - -.. function:: @profile - - Profiling is controlled via the ``@profile`` macro. Your first step is to determine which code you want to profile and encapsulate it inside a ``@profile begin ... end`` block, like this:: - - @profile begin - function f1(x::Int) - z = 0 - for j = 1:x - z += j^2 - end - return z - end - - function f1(x::Float64) - return x+2 - end - - function f1{T}(x::T) - return x+5 - end - - f2(x) = 2*x - end # @profile begin - - Now load the file and execute the code you want to profile, e.g.:: - - f1(215) - for i = 1:100 - f1(3.5) - end - for i = 1:150 - f1(uint8(7)) - end - for i = 1:125 - f2(11) - end - - To view the execution times, type ``@profile report``. - - Here are the various options you have for controlling profiling: - - * ``@profile report``: display cumulative profiling results - * ``@profile clear``: clear all timings accumulated thus far (start from zero) - * ``@profile off``: turn profiling off (there is no need to remove ``@profile begin ... end`` blocks) - * ``@profile on``: turn profiling back on - - ----- -Tips ----- - -You should always discard the results of your first run: it may include the overhead needed to JIT-compile some of the subfunctions. - -The primary source of variability is the garbage collector---if it runs between two "instrumentation" lines, its execution time gets added to the time that your own line of code contributes. This can make a fast-running line seem puzzlingly slow. One good way to reduce the variance is to run ``gc()`` before profiling. However, if your code tends to accumulate a bunch of temporaries that need to be cleaned up in the middle of the run, then calling ``gc()`` at the beginning can cause the collector to run at the same point in the code each time, a misleading but consistent result. A different approach is to use multiple runs (without an explicit ``gc()``) and hope that the collector runs at different points in each run. The cost of a given line is probably best reflected in those runs with shortest time for that line. - ------------ -Limitations ------------ - -Profiling adds a performance overhead which can be significant. You can prevent a subsection of your code from being profiled by encapsulating it inside a ``begin ... end`` block; in this case, the block as a whole is profiled, but the individual lines inside the block are not separately timed. - -The profiler tries to compensate for its overhead in the reported times. This naturally leads to some degree of uncertainty about the execution time of individual lines. More significantly, currently the profiler does not compensate for its own instrumentation in profiled *subfunctions*. Consequently, it's recommended that you avoid profiling nested code as a big chunk---you probably want to pick out individual functions or groups of functions to profile separately. diff --git a/doc/stdlib/punctuation.rst b/doc/stdlib/punctuation.rst new file mode 100644 index 0000000000000..e2394646fa807 --- /dev/null +++ b/doc/stdlib/punctuation.rst @@ -0,0 +1,41 @@ + +Punctuation +----------- + +.. data:: punctuation + + ========= ================================================ + symbol meaning + ========= ================================================ + ``@m`` invoke macro m; followed by space-separated expressions + ``!`` prefix "not" operator + ``!`` at the end of a function name, indicates that a function modifies its argument(s) + ``#`` begin single line comment + ``$`` xor operator, string and expression interpolation + ``%`` remainder operator + ``^`` exponent operator + ``&`` bitwise and + ``*`` multiply, or matrix multiply + ``()`` the empty tuple + ``~`` bitwise not operator + ``\`` backslash operator + ``a[]`` array indexing + ``[,]`` vertical concatenation + ``[;]`` also vertical concatenation + ``[ ]`` with space-separated expressions, horizontal concatenation + ``T{ }`` parametric type instantiation + ``{ }`` construct a cell array + ``;`` statement separator + ``,`` separate function arguments or tuple components + ``?`` 3-argument conditional operator + ``""`` delimit string literals + ``''`` delimit character literals + `` delimit external process (command) specifications + ``...`` splice arguments into a function call, or declare a varargs function + ``.`` access named fields in objects or names inside modules, also prefixes elementwise operators + ``a:b`` range + ``a:s:b`` range + ``:`` index an entire dimension + ``::`` type annotation + ``:( )`` quoted expression + ========= ================================================ diff --git a/doc/stdlib/sort.rst b/doc/stdlib/sort.rst new file mode 100644 index 0000000000000..23e1a06c5df84 --- /dev/null +++ b/doc/stdlib/sort.rst @@ -0,0 +1,172 @@ +:mod:`Base.Sort` --- Routines related to sorting +================================================================= + +.. module:: Base.Sort + :synopsis: Sort and related routines + +The `Sort` module contains algorithms and other functions related to +sorting. Default sort functions and standard versions of the various +sort algorithm are available by default. +Specific sort algorithms can be used by importing +`Sort` or using the fully qualified algorithm name, e.g.,:: + + # Julia code + sort(v, Sort.TimSort) + +will sort ``v`` using ``TimSort``. + + +Overview +-------- + +Many users will simply want to use the default sort algorithms, which +allow sorting in ascending or descending order,:: + + # Julia code + julia> sort([2,3,1]) == [1,2,3] + true + + julia> sort([2,3,1], Sort.Reverse) == [3,2,1] + true + +return a permutation,:: + + julia> v = [20,30,10] + 3-element Int64 Array: + 20 + 30 + 10 + + julia> p = sortperm(v) + [3, 1, 2] + + julia> v[p] + 3-element Int64 Array: + 10 + 20 + 30 + +and use a custom extractor function to order inputs:: + + julia> canonicalize(s) = filter(c -> ('A'<=c<='Z' || 'a'<=c<='z'), s) | uppercase + + julia> sortby(["New York", "New Jersey", "Nevada", "Nebraska", "Newark"], canonicalize) + 5-element ASCIIString Array: + "Nebraska" + "Nevada" + "Newark" + "New Jersey" + "New York" + +Note that none of the variants above modify the original arrays. To +sort in-place (which is often more efficient), :func:`sort` and +:func:`sortby` have mutating versions which end with an exclamation +point (:func:`sort!` and :func:`sortby!`). + +These sort functions use reasonable default algorithms, but if you +want more control or want to see if a different sort algorithm will +work better on your data, read on... + + +Sort Algorithms +--------------- + +There are currently four main sorting algorithms available in Julia:: + + InsertionSort + QuickSort + MergeSort + TimSort + +Insertion sort is an O(n^2) stable sorting algorithm. It is +efficient for very small ``n``, and is used internally by +``QuickSort`` and ``TimSort``. + +Quicksort is an O(n log n) sorting algorithm. For efficiency, it +is not stable. It is among the fastest sorting algorithms. + +Mergesort is an O(n log n) stable sorting algorithm. + +Timsort is an O(n log n) stable adaptive sorting algorithm. It +takes advantage of sorted runs which exist in many real world +datasets. + +The sort functions select a reasonable default algorithm, depending on +the type of the target array. To force a specific algorithm to be +used, append ``Sort.`` to the argument list (e.g., use +``sort!(v, Sort.TimSort)`` to force the use of the Timsort algorithm). + + +Functions +--------- + +-------------- +Sort Functions +-------------- +.. function:: sort(v[, alg[, ord]]) + + Sort a vector in ascending order. Specify ``alg`` to choose a + particular sorting algorithm (``Sort.InsertionSort``, + ``Sort.QuickSort``, ``Sort.MergeSort``, or ``Sort.TimSort``), and + ``ord`` to sort with a custom ordering (e.g., Sort.Reverse or a + comparison function). + +.. function:: sort!(...) + + In-place sort. + +.. function:: sortby(v, by[, alg]) + + Sort a vector according to ``by(v)``. Specify ``alg`` to choose a + particular sorting algorithm (``Sort.InsertionSort``, + ``Sort.QuickSort``, ``Sort.MergeSort``, or ``Sort.TimSort``). + +.. function:: sortby!(...) + + In-place ``sortby``. + +.. function:: sortperm(v, [alg[, ord]]) + + Return a permutation vector, which when applied to the input vector + ``v`` will sort it. Specify ``alg`` to choose a particular sorting + algorithm (``Sort.InsertionSort``, ``Sort.QuickSort``, + ``Sort.MergeSort``, or ``Sort.TimSort``), and ``ord`` to sort with + a custom ordering (e.g., Sort.Reverse or a comparison function). + +------------------------- +Sorting-related Functions +------------------------- + +.. function:: issorted(v[, ord]) + + Test whether a vector is in ascending sorted order. If specified, + ``ord`` gives the ordering to test. + +.. function:: searchsorted(a, x[, ord]) + + Returns the index of the first value of ``a`` equal to or + succeeding ``x``, according to ordering ``ord`` (default: + ``Sort.Forward``). + + Alias for ``searchsortedfirst()`` + +.. function:: searchsortedfirst(a, x[, ord]) + + Returns the index of the first value of ``a`` equal to or + succeeding ``x``, according to ordering ``ord`` (default: + ``Sort.Forward``). + +.. function:: searchsortedlast(a, x[, ord]) + + Returns the index of the last value of ``a`` preceding or equal to + ``x``, according to ordering ``ord`` (default: ``Sort.Forward``). + +.. function:: select(v, k[, ord]) + + Find the element in position ``k`` in the sorted vector ``v`` + without sorting, according to ordering ``ord`` (default: + ``Sort.Forward``). + +.. function:: select!(v, k[, ord]) + + Version of ``select`` which permutes the input vector in place. diff --git a/doc/stdlib/sound.rst b/doc/stdlib/sound.rst deleted file mode 100644 index 4aa87df949744..0000000000000 --- a/doc/stdlib/sound.rst +++ /dev/null @@ -1,112 +0,0 @@ -:mod:`Sound` --- Functions for audio -==================================== - -.. module:: Sound - :synopsis: Functions for acoustic processing - -.. note:: located in ``sound.jl`` - -This module contains functions intended to process acoustic samples. - -RIFF/WAVE Functions -------------------- -These functions are used for loading and saving RIFF/WAVE (wav) functions. The API is very similar to -the one found in MATLAB. - -Here is a quick example that copies an existing file:: - - julia> require("sound") - - julia> using Sound - - julia> in_filename = ARGS[1] - - julia> y, Fs, nbits, extra = wavread(in_filename) - - julia> wavwrite(y, Fs, nbits, strcat("out-", in_filename)) - -.. note:: This implementation only supports little endian machines right now. - -.. function:: wavread(io [, options]) - - Reads and returns the samples from a RIFF/WAVE file. The samples are converted to floating - point values in the range from -1.0 to 1.0 by default. The ``io`` argument accepts either an - ``IO`` object or a filename (``String``). The options are passed via an ``Options`` object - (see the :mod:`OptionsMod` module). - - The available options, and the default values, are: - - * ``format`` (default = ``double``): changes the format of the returned samples. The string - ``double`` returns double precision floating point values in the range -1.0 to 1.0. The string - ``native`` returns the values as encoded in the file. The string ``size`` returns the number - of samples in the file, rather than the actual samples. - * ``subrange`` (default = ``Any``): controls which samples are returned. The default, ``Any`` - returns all of the samples. Passing a number (``Real``), ``N``, will return the first ``N`` - samples of each channel. Passing a range (``Range1{Real}``), ``R``, will return the samples - in that range of each channel. - - The returned values are: - - * ``y``: The acoustic samples; A matrix is returned for files that contain multiple channels. - * ``Fs``: The sampling frequency - * ``nbits``: The number of bits used to encode each sample - * ``extra``: Any additional bytes used to encode the samples (is always ``None``) - - The following functions are also defined to make this function compatible with MATLAB:: - - wavread(filename::String) = wavread(filename, @options) - wavread(filename::String, fmt::String) = wavread(filename, @options format=fmt) - wavread(filename::String, N::Int) = wavread(filename, @options subrange=N) - wavread(filename::String, N::Range1{Int}) = wavread(filename, @options subrange=N) - wavread(filename::String, N::Int, fmt::String) = wavread(filename, @options subrange=N format=fmt) - wavread(filename::String, N::Range1{Int}, fmt::String) = wavread(filename, @options subrange=N format=fmt) - -.. function:: wavwrite(samples, io [, options]) - - Writes samples to a RIFF/WAVE file io object. The ``io`` argument - accepts either an ``IO`` object or a filename (``String``). The - function assumes that the sample rate is 8 kHz and uses 16 bits to - encode each sample. Both of these values can be changed with the - options parameter. Each column of the data represents a different - channel. Stereo files should contain two columns. The options are - passed via an ``Options`` object (see the :mod:`OptionsMod` module). - - The available options, and the default values, are: - - * ``sample_rate`` (default = ``8000``): sampling frequency - * ``nbits`` (default = ``16``): number of bits used to encode each - sample - * ``compression`` (default = ``WAVE_FORMAT_PCM``): The desired - compression technique; accepted values are: WAVE_FORMAT_PCM, WAVE_FORMAT_IEEE_FLOAT - - The type of the input array, samples, also affects the generated - file. "Native" WAVE files are written when integers are passed into - wavwrite. This means that the literal values are written into the - file. The input ranges are as follows for integer samples. - - ====== =========== ====================== ============= - N Bits y Data Type y Data Range Output Format - ====== =========== ====================== ============= - 8 uint8 0 <= y <= 255 uint8 - 16 int16 –32768 <= y <= +32767 int16 - 24 int32 –2^23 <= y <= 2^23 – 1 int32 - ====== =========== ====================== ============= - - If samples contains floating point values, the input data ranges - are the following. - - ====== ================ ================= ============= - N Bits y Data Type y Data Range Output Format - ====== ================ ================= ============= - 8 single or double –1.0 <= y < +1.0 uint8 - 16 single or double –1.0 <= y < +1.0 int16 - 24 single or double –1.0 <= y < +1.0 int32 - 32 single or double –1.0 <= y <= +1.0 single - ====== ================ ================= ============= - - The following functions are also defined to make this function - compatible with MATLAB:: - - wavwrite(y::Array) = wavwrite(y, @options) - wavwrite(y::Array, Fs::Real, filename::String) = wavwrite(y, filename, @options sample_rate=Fs) - wavwrite(y::Array, Fs::Real, N::Real, filename::String) = wavwrite(y, filename, @options sample_rate=Fs nbits=N) diff --git a/doc/stdlib/sparse.rst b/doc/stdlib/sparse.rst new file mode 100644 index 0000000000000..3ceb15a75eb9b --- /dev/null +++ b/doc/stdlib/sparse.rst @@ -0,0 +1,62 @@ + +Sparse Matrices +--------------- + +Sparse matrices support much of the same set of operations as dense matrices. The following functions are specific to sparse matrices. + +.. function:: sparse(I,J,V,[m,n,combine]) + + Create a sparse matrix ``S`` of dimensions ``m x n`` such that ``S[I[k], J[k]] = V[k]``. The ``combine`` function is used to combine duplicates. If ``m`` and ``n`` are not specified, they are set to ``max(I)`` and ``max(J)`` respectively. If the ``combine`` function is not supplied, duplicates are added by default. + +.. function:: sparsevec(I, V, [m, combine]) + + Create a sparse matrix ``S`` of size ``m x 1`` such that ``S[I[k]] = V[k]``. Duplicates are combined using the ``combine`` function, which defaults to `+` if it is not provided. In julia, sparse vectors are really just sparse matrices with one column. Given Julia's Compressed Sparse Columns (CSC) storage format, a sparse column matrix with one column is sparse, whereas a sparse row matrix with one row ends up being dense. + +.. function:: sparsevec(D::Dict, [m]) + + Create a sparse matrix of size ``m x 1`` where the row values are keys from the dictionary, and the nonzero values are the values from the dictionary. + +.. function:: issparse(S) + + Returns ``true`` if ``S`` is sparse, and ``false`` otherwise. + +.. function:: sparse(A) + + Convert a dense matrix ``A`` into a sparse matrix. + +.. function:: sparsevec(A) + + Convert a dense vector ``A`` into a sparse matrix of size ``m x 1``. In julia, sparse vectors are really just sparse matrices with one column. + +.. function:: dense(S) + + Convert a sparse matrix ``S`` into a dense matrix. + +.. function:: full(S) + + Convert a sparse matrix ``S`` into a dense matrix. + +.. function:: spzeros(m,n) + + Create an empty sparse matrix of size ``m x n``. + +.. function:: speye(type,m[,n]) + + Create a sparse identity matrix of specified type of size ``m x m``. In case ``n`` is supplied, create a sparse identity matrix of size ``m x n``. + +.. function:: spones(S) + + Create a sparse matrix with the same structure as that of ``S``, but with every nonzero element having the value ``1.0``. + +.. function:: sprand(m,n,density[,rng]) + + Create a random sparse matrix with the specified density. Nonzeros are sampled from the distribution specified by ``rng``. The uniform distribution is used in case ``rng`` is not specified. + +.. function:: sprandn(m,n,density) + + Create a random sparse matrix of specified density with nonzeros sampled from the normal distribution. + +.. function:: sprandbool(m,n,density) + + Create a random sparse boolean matrix with the specified density. + diff --git a/doc/stdlib/strpack.rst b/doc/stdlib/strpack.rst deleted file mode 100644 index 01e01bc7aa4f7..0000000000000 --- a/doc/stdlib/strpack.rst +++ /dev/null @@ -1,84 +0,0 @@ -strpack.jl --- Convert Julia types <--> C structures -==================================================== - -.. .. module:: strpack.jl - :synopsis: Convert Julia types <--> C structures - -This module allows Julia composite types to be converted to a form suitable to pass as a structure input -to a ``ccall``. It can also convert C-structure outputs back into Julia types. - -------- -Example -------- - -Probably the easiest way to see how it works is to try an example. Let's create a C library as follows: - -.. code-block:: c - - struct teststruct { - int int1; - float float1; - }; - - void getvalues(struct teststruct* ts) - { - ts->int1 = 7; - ts->float1 = 3.7; - } - -The ``getvalues`` function just fills the two fields with specified values. Compile this as a shared library, -which on Linux is achieved with ``gcc -fPIC teststruct.c -shared -o libteststruct.so``. - -Let's also create the Julia analog of this structure:: - - type TestStruct - int1::Int32 - float1::Float32 - end - TestStruct(i, f) = TestStruct(convert(Int32, i), convert(Float32, f)) - -Note that C's ``int`` corresponds to ``Int32``. Let's initialize an object of this type:: - - s = TestStruct(-1, 1.2) - -Now we load the strpack "module", ``load("strpack")``, which also brings in ``iostring.jl``. We're going to -pack ``s`` into a form suitable to pass as the input to our C function ``getvalues``, which we do in the -following way:: - - iostr = IOString() - pack(iostr, s) - -It's worth seeing what has happened here:: - - julia> iostr - IOString([0xff, 0xff, 0xff, 0xff, 0x9a, 0x99, 0x99, 0x3f],9) - -The first 4 bytes correspond to the ``Int32`` representation of -1, and the last 4 to the ``Float32`` -representation of 1.2. In other words, this is just a packed memory buffer encoding ``s``. (There are -subtleties such as data alignment, endian status, etc. strpack knows about this stuff, and users who need -to control its behavior manually can do so.) - -Now we load our library and make a ``ccall``:: - - const libtest = dlopen("libteststruct") - ccall(dlsym(libtest, :getvalues), Void, (Ptr{Void},), iostr.data) - -The C function ``getvalues`` stores its output in the buffer we provided as input. We unpack this buffer back -into a Julia type:: - - seek(iostr, 0) # "rewind" to the beginning of the buffer - s2 = unpack(iostr, TestStruct) - -Voila! You have the result back. - -.. function:: pack(io, composite[, strategy]) - - Create a packed buffer representation of ``composite`` in stream ``io``, using data alignment coded by - ``strategy``. This buffer is suitable to pass as a ``struct`` argument in a ``ccall``. - -.. function:: unpack(io, T[, strategy]) - - Extract an instance of the Julia composite type ``T`` from the packed representation in the stream ``io``. - ``io`` must be positioned at the beginning (using ``seek``). This allows you to read C ``struct`` outputs - from ``ccall``. - diff --git a/doc/stdlib/textwrap.rst b/doc/stdlib/textwrap.rst deleted file mode 100644 index 6481992de6dbe..0000000000000 --- a/doc/stdlib/textwrap.rst +++ /dev/null @@ -1,63 +0,0 @@ -:mod:`TextWrap` --- Text wrapping module -======================================== - -.. module:: TextWrap - :synopsis: TextWrap module - -.. note:: located in ``textwrap.jl`` - -This module provides the function ``wrap`` which parses an input text and reorganizes its white space so that -it can be printed with a fixed screen width, optionally indenting it. It also provides the two convenience -functions ``print_wrapped`` and ``println_wrapped``. - -Here is a quick example: - -:: - - julia> require("textwrap") - - julia> using TextWrap - - julia> using OptionsMod - - julia> text = "This text is going to be wrapped around in lines no longer than 20 characters."; - - julia> println_wrapped(text, @options(width=>20)) - This text is going - to be wrapped around - in lines no longer - than 20 characters. - -It's very similar to Python's textwrap module, but the interface is slightly different. - -.. function:: wrap(string [, options]) - - Returns a string in which newlines are inserted as appropriate in order for each line - to fit within a specified width. - - The options are passed via an ``Options`` object (provided by the :mod:`OptionsMod` module). - The available options, and their default values, are: - - * ``width`` (default = ``70``): the maximum width of the wrapped text, including indentation. - * ``initial_indent`` (default = ``""``): indentation of the first line. This can be any string (shorter than ``width``), - or it can be an integer number (lower than ``width``). - * ``subsequent_indent`` (default = ``""``): indentation of all lines except the first. Works the same as ``initial_indent``. - * ``break_on_hyphens`` (default = ``true``): this flag determines whether words can be broken on hyphens, e.g. whether - "high-precision" can be split into "high-" and "precision". - * ``break_long_words`` (default = ``true``): this flag determines what to do when a word is too long to fit in any line. - If ``true``, the word will be broken, otherwise it will go beyond the desired text width. - * ``replace_whitespace`` (default = ``true``): if this flag is true, all whitespace characters in the original text - (including newlines) will be replaced by spaces. - * ``expand_tabs`` (default = ``true``): if this flag is true, tabs will be expanded in-place into spaces. The expansion - happens before whitespace replacement. - * ``fix_sentence_endings`` (default = ``false``): if this flag is true, the wrapper will try to recognize sentence endings - in the middle of a paragraph and put two spaces before the next sentence in case only one is present. - -.. function:: print_wrapped(text... [, options]) - print_wrapped(io, text... [, options]) - println_wrapped(text... [, options]) - println_wrapped(io, text... [, options]) - - These are just like the standard :func:`print` and :func:`println` functions (they print multiple arguments and - accept an optional ``IO`` first argument), except that they wrap the result, and accept an optional - last argument with the options to pass to :func:`wrap`. diff --git a/doc/stdlib/zlib.rst b/doc/stdlib/zlib.rst deleted file mode 100644 index 82a0c261146b7..0000000000000 --- a/doc/stdlib/zlib.rst +++ /dev/null @@ -1,72 +0,0 @@ -:mod:`Zlib` --- Wrapper for zlib compress/uncompress -==================================================== - -.. module:: Zlib - :synopsis: Zlib compress/uncompress wrapper - -.. note:: located in ``zlib.jl`` - -This module provides a wrapper for the compress/uncompress and related -utility functions of (`zlib `_), a free, -general-purpose, legally unencumbered, lossless data-compression -library. These functions allow the compression and decompression of -byte buffers (``Array{Uint8,1}``). - -Note that the zlib stream functions are not yet wrapped. - -It is currently based on zlib 1.2.7. - -Utility Functions ------------------ - -.. function:: compress_bound(input_size) - - Returns the maximum size of the compressed output buffer for a - given uncompressed input size. - - -.. function:: compress(source[, level]) - - Compresses source using the given compression level, and returns - the compressed buffer (``Array{Uint8,1}``). ``level`` is an - integer between 0 and 9, or one of ``Z_NO_COMPRESSION``, - ``Z_BEST_SPEED``, ``Z_BEST_COMPRESSION``, or - ``Z_DEFAULT_COMPRESSION``. It defaults to - ``Z_DEFAULT_COMPRESSION``. - - If an error occurs, ``compress`` throws a :class:`ZError` with more - information about the error. - - -.. function:: compress_to_buffer(source, dest, level=Z_DEFAULT_COMPRESSION) - - Compresses the source buffer into the destination buffer, and - returns the number of bytes written into dest. - - If an error occurs, ``uncompress`` throws a :class:`ZError` with more - information about the error. - - -.. function:: uncompress(source[, uncompressed_size]) - - Allocates a buffer of size ``uncompressed_size``, uncompresses - source to this buffer using the given compression level, and - returns the compressed buffer. If ``uncompressed_size`` is not - given, the size of the output buffer is estimated as - ``2*length(source)``. If the uncompressed_size is larger than - uncompressed_size, the allocated buffer is grown and the - uncompression is retried. - - If an error occurs, ``uncompress`` throws a :class:`ZError` with more - information about the error. - - -.. function:: uncompress_to_buffer(source, dest) - - Uncompresses the source buffer into the destination buffer. - Returns the number of bytes written into dest. An error is thrown - if the destination buffer does not have enough space. - - If an error occurs, ``uncompress_to_buffer`` throws a :class:`ZError` - with more information about the error. - diff --git a/examples/bigfib.jl b/examples/bigfib.jl deleted file mode 100644 index e182fb37efbfb..0000000000000 --- a/examples/bigfib.jl +++ /dev/null @@ -1,45 +0,0 @@ -require("extras/bigint") - -module BigFib -export bigfib -const BigInt = Main.BigInt - -# Large Fibonacci to exercise BigInt -# from Bill Hart, https://groups.google.com/group/julia-dev/browse_frm/thread/798e2d1322daf633 - -function mul(a::Vector{BigInt}, b::Vector{BigInt}) - x = a[2]*b[2] - c = Array(BigInt,3) - c[1] = a[1]*b[1] + x - c[2] = a[1]*b[2] + a[2]*b[3] - c[3] = x + a[3]*b[3] - return c -end - -function bigfib(n) - if n == 0 - BigInt(1) - elseif n == 1 - BigInt(1) - else - r = [BigInt(1), BigInt(1), BigInt(0)] - s = [BigInt(1), BigInt(0), BigInt(1)] - while n != 0 - if (n & 1) == 1 - s = mul(s,r) - end - n >>= 1 - if n != 0 - r = mul(r,r) - end - end - s[1] - end -end - -function test() - @time s = bigfib(100000000) - print("The result contains $(length(string((s)))) decimal digits \n") -end - -end # module diff --git a/examples/bitvector.jl b/examples/bitvector.jl deleted file mode 100644 index 3e818aef65bb8..0000000000000 --- a/examples/bitvector.jl +++ /dev/null @@ -1,129 +0,0 @@ -lomask(n::Integer) = lomask(uint32(n)) -lomask(n::Uint32) = ((1<= s.limit) -function next(s::IntSet, i) - n = bitvector_next(s.bits, uint64(i), uint64(s.limit)) - (n, n+1) -end - - -function bitvector_next(b::Array{Uint32,1}, n0::Uint64, n::Uint64) - local w::Uint32 - i = n0>>5 - nb = n0&31 - nw = (n+31)>>5 - if i < nw-1 || (n&31)==0 - w = b[i+1]>>nb - else - w = (b[i+1]&lomask(n&31))>>nb - end - if w != 0 - nxt = int64(trailing_zeros(w) + n0) - return nxt - end - if i == nw-1 - nxt = int64(n) - return nxt - end - i += 1 - while i < nw-1 - w = b[i+1] - if w != 0 - nxt = int64(trailing_zeros(w) + i<<5) - return nxt - end - i += 1 - end - w = b[i+1] - nb = n & 31 - i = int64(trailing_zeros(w)) - if nb == 0 - nxt = int64(i + (n-32)) - return nxt - end - if i >= nb - nxt = int64(n) - return nxt - end - nxt = int64(i + (n-nb)) - return nxt -end - -function isempty(s::IntSet) - !bitvector_any1(s.bits, uint64(0), uint64(s.limit)) -end - -function bitvector_any1(b::Array{Uint32,1}, offs::Uint64, nbits::Uint64) - local nw::Uint32, tail::Uint32, mask::Uint32 - - if (nbits == 0) - return false; - end - nw = (offs+nbits+31)>>5; - - if (nw == 1) - if (nbits == 32) - mask = (uint32(0xffffffff)<= s.limit - error("choose: set is empty") - end - return n -end - -length(s::IntSet) = numel(s) -numel(s::IntSet) = - int32(ccall(:bitvector_count, Uint64, (Ptr{Uint32}, Uint64, Uint64), - s.bits, 0, s.limit)) - diff --git a/examples/blksvd.jl b/examples/blksvd.jl index f35a55ff22be4..61d051ad2e28b 100644 --- a/examples/blksvd.jl +++ b/examples/blksvd.jl @@ -20,7 +20,7 @@ function bidiag(A::Matrix{Float64}, nb, nargout) X = zeros(m-k+1, nb) Y = zeros(n-k+1, nb) - ccall(dlsym(_jl_libLAPACK, :dlabrd_), Void, + ccall(dlsym(libLAPACK, :dlabrd_), Void, (Ptr{Int32}, Ptr{Int32}, Ptr{Int32}, Ptr{Float64}, Ptr{Int32}, Ptr{Float64}, Ptr{Float64}, Ptr{Float64}, Ptr{Float64}, Ptr{Float64}, @@ -50,7 +50,7 @@ function bidiag(A::Matrix{Float64}, nb, nargout) tauqblk = zeros(s-k+1) taupblk = zeros(s-k+1) - ccall(dlsym(_jl_libLAPACK,:dgebd2_), Void, + ccall(dlsym(libLAPACK,:dgebd2_), Void, (Ptr{Int32}, Ptr{Int32}, Ptr{Float64}, Ptr{Int32}, Ptr{Float64}, Ptr{Float64}, Ptr{Float64}, Ptr{Float64}, Ptr{Float64}, Ptr{Int32}), @@ -77,13 +77,13 @@ function bidiag(A::Matrix{Float64}, nb, nargout) if m >= n Q = copy(A0) - ccall(dlsym(_jl_libLAPACK,:dorgbr_), Void, + ccall(dlsym(libLAPACK,:dorgbr_), Void, (Ptr{Uint8}, Ptr{Int32}, Ptr{Int32}, Ptr{Int32}, Ptr{Float64}, Ptr{Int32}, Ptr{Float64}, Ptr{Float64}, Ptr{Int32}, Ptr{Int32}), "Q", m, n, n, Q, m, tauq, zeros(s), s, 0) PT = A0 - ccall(dlsym(_jl_libLAPACK,:dorgbr_), Void, + ccall(dlsym(libLAPACK,:dorgbr_), Void, (Ptr{Uint8}, Ptr{Int32}, Ptr{Int32}, Ptr{Int32}, Ptr{Float64}, Ptr{Int32}, Ptr{Float64}, Ptr{Float64}, Ptr{Int32}, Ptr{Int32}), @@ -91,14 +91,14 @@ function bidiag(A::Matrix{Float64}, nb, nargout) PT = PT[1:n,:] else Q = copy(A0) - ccall(dlsym(_jl_libLAPACK,:dorgbr_), Void, + ccall(dlsym(libLAPACK,:dorgbr_), Void, (Ptr{Uint8}, Ptr{Int32}, Ptr{Int32}, Ptr{Int32}, Ptr{Float64}, Ptr{Int32}, Ptr{Float64}, Ptr{Float64}, Ptr{Int32}, Ptr{Int32}), "Q", m, m, n, Q, m, tauq, zeros(s), s, 0) Q = Q[:,1:m] PT = A0 - ccall(dlsym(_jl_libLAPACK,:dorgbr_), Void, + ccall(dlsym(libLAPACK,:dorgbr_), Void, (Ptr{Uint8}, Ptr{Int32}, Ptr{Int32}, Ptr{Int32}, Ptr{Float64}, Ptr{Int32}, Ptr{Float64}, Ptr{Float64}, Ptr{Int32}, Ptr{Int32}), @@ -117,7 +117,7 @@ function blksvd(A::Matrix{Float64}, nargout) (Q, D, E, PT) = bidiag(A, nb, 4) if m >= n - ccall(dlsym(_jl_libLAPACK, :dbdsqr_), Void, + ccall(dlsym(libLAPACK, :dbdsqr_), Void, (Ptr{Uint8}, Ptr{Int32}, Ptr{Int32}, Ptr{Int32}, Ptr{Int32}, Ptr{Float64}, Ptr{Float64}, Ptr{Float64}, Ptr{Int32}, Ptr{Float64}, Ptr{Int32}, Ptr{Float64}, Ptr{Int32}, @@ -125,7 +125,7 @@ function blksvd(A::Matrix{Float64}, nargout) "U", n, n, m, 0, D, E, PT, n, Q, m, zeros(1,1), 1, zeros(4*n,1), 0) else - ccall(dlsym(_jl_libLAPACK, :dbdsqr_), Void, + ccall(dlsym(libLAPACK, :dbdsqr_), Void, (Ptr{Uint8}, Ptr{Int32}, Ptr{Int32}, Ptr{Int32}, Ptr{Int32}, Ptr{Float64}, Ptr{Float64}, Ptr{Float64}, Ptr{Int32}, Ptr{Float64}, Ptr{Int32}, Ptr{Float64}, Ptr{Int32}, diff --git a/examples/bubblesort.jl b/examples/bubblesort.jl new file mode 100644 index 0000000000000..05e1a17f554b0 --- /dev/null +++ b/examples/bubblesort.jl @@ -0,0 +1,17 @@ +importall Base + +type BubbleSort <: Sort.Algorithm end + +function sort!(v::AbstractVector, lo::Int, hi::Int, ::BubbleSort, o::Sort.Ordering) + while true + clean = true + for i = lo:hi-1 + if Sort.lt(o, v[i+1], v[i]) + v[i+1], v[i] = v[i], v[i+1] + clean = false + end + end + clean && break + end + return v +end diff --git a/examples/graph.jl b/examples/graph.jl index f3de03cc3b11d..75a52d29dc860 100644 --- a/examples/graph.jl +++ b/examples/graph.jl @@ -101,7 +101,7 @@ type ILVertex <: Vertex end #print(v::ILVertex) = print("Vertex $(v.name): $(v.value)") -show(io,v::ILVertex) = (v.value == 0 ? +show(io::IO,v::ILVertex) = (v.value == 0 ? print(io, "Vertex $(v.name)") : print(io, "Vertex $(v.name): $(v.value)")) @@ -112,7 +112,7 @@ type ILEdge <: Edge end #print(e::ILEdge) = print("Edge: $(e.v1), $(e.v2): $(e.value)") -show(io, e::ILEdge) = (e.value == 0 ? +show(io::IO, e::ILEdge) = (e.value == 0 ? print(io,"Edge $(e.v1.name),$(e.v2.name)") : print(io,"Edge $(e.v1.name),$(e.v2.name): $(e.value)")) @@ -134,7 +134,7 @@ end #print(G::ILGraph) = (for edge = G.edges; println(edge); end) -show(io, G::ILGraph) = (for edge = G.edges; println(io, edge); end) +show(io::IO, G::ILGraph) = (for edge = G.edges; println(io, edge); end) function ILGraph(edges) this = ILGraph() @@ -368,7 +368,7 @@ end sides(side::Bool) = (side ? "A" : "B") #print(v::BVertex) = print("Vertex $(v.name): $(v.value)") -function show(io, v::BVertex) +function show(io::IO, v::BVertex) side = sides(v.side) if v.value == 0 print(io, "Vertex $side/$(v.name)") @@ -384,7 +384,7 @@ type BEdge <: Edge end #print(e::BEdge) = print("Edge: $(e.v1), $(e.v2): $(e.value)") -show(io, e::BEdge) = (e.value == 0 ? +show(io::IO, e::BEdge) = (e.value == 0 ? print(io,"Edge $(e.v1.name),$(e.v2.name)") : print(io,"Edge $(e.v1.name),$(e.v2.name): $(e.value)")) @@ -404,7 +404,7 @@ type BGraph <: Graph end #print(G::BGraph) = (for edge = G.edges; println(edge); end) -show(io, G::BGraph) = (for edge = G.edges; println(io,edge); end) +show(io::IO, G::BGraph) = (for edge = G.edges; println(io,edge); end) function BGraph(edges) this = BGraph() diff --git a/examples/hpl.jl b/examples/hpl.jl index 627b4d875db49..6458037a2c5f7 100644 --- a/examples/hpl.jl +++ b/examples/hpl.jl @@ -218,7 +218,7 @@ function trailing_update_par(L_II, A_IJ, A_KI, A_KJ, row_dep, col_dep) if !isempty(A_KJ) m, k = size(A_KI) n = size(A_IJ,2) - _jl_blas_gemm('N','N',m,n,k,-1.0,A_KI,m,A_IJ,k,1.0,A_KJ,m) + blas_gemm('N','N',m,n,k,-1.0,A_KI,m,A_IJ,k,1.0,A_KJ,m) #A_KJ = A_KJ - A_KI*A_IJ end @@ -361,7 +361,7 @@ function trailing_update_par2(C, L_II, C_KI, i, j, n, flag, dep) if !isempty(C_KJ) cm, ck = size(C_KI) cn = size(C_IJ,2) - _jl_blas_gemm('N','N',cm,cn,ck,-1.0,C_KI,cm,C_IJ,ck,1.0,C_KJ,cm) + blas_gemm('N','N',cm,cn,ck,-1.0,C_KI,cm,C_IJ,ck,1.0,C_KJ,cm) #C_KJ = C_KJ - C_KI*C_IJ C[K,J] = C_KJ end diff --git a/examples/list.jl b/examples/list.jl index 0a1c6033c4b95..220f7abb15427 100644 --- a/examples/list.jl +++ b/examples/list.jl @@ -18,7 +18,7 @@ nil() = nil(Any) head(x::Cons) = x.head tail(x::Cons) = x.tail -function show{T}(io, l::List{T}) +function show{T}(io::IO, l::List{T}) if isa(l,Nil) if is(T,Any) print(io, "nil()") diff --git a/examples/median_MU.jl b/examples/median_MU.jl deleted file mode 100644 index 73d9e286c8dee..0000000000000 --- a/examples/median_MU.jl +++ /dev/null @@ -1,54 +0,0 @@ -function median_MU(S) - n = length(S) - - if n < 1500 - C = sort(S) - half = iround(n/2) - if mod(n,2) == 1 - m = C[half] - else - m = (C[half]+C[half+1])/2 - end - return m - end - - # finds median of set S, a la Mitzenmacher & Upfal, Alg. 3.1 - - n75 = int64(ceil(n^.75)) - R = S[int64(ceil(n*rand(n75)))] - sort!(R) - d = R[max(1.0, floor((n75/2)-sqrt(n)))] - u = R[ceil((n75/2)+sqrt(n))] - - C = similar(S, 0) - Ld = 0 - Lu = 0 - for i = 1:n - if S[i] < d - Ld = Ld + 1 - else - if S[i] > u - Lu = Lu + 1 - else - C = push(C,S[i]) - end - end - end - - if (Ld > n/2) || (Lu > n/2) - m = median(S) - else - if length(C) > 4*n75 - m = median(S) - else - sort!(C) - if mod(n,2) == 1 - m = C[floor(n/2)-Ld+1] - else - m = (C[floor(n/2)-Ld]+C[floor(n/2)-Ld+1])/2 - end - end - end - - return m -end diff --git a/examples/modint.jl b/examples/modint.jl index dd05974f482f0..74a5c3aabd355 100644 --- a/examples/modint.jl +++ b/examples/modint.jl @@ -1,15 +1,17 @@ -type ModInt{N} <: Integer +importall Base + +immutable ModInt{n} <: Integer k::Int - ModInt(k) = new(mod(k,N)) + ModInt(k) = new(mod(k,n)) end --{N}(a::ModInt{N}) = ModInt{N}(-a.k) -+{N}(a::ModInt{N}, b::ModInt{N}) = ModInt{N}(a.k+b.k) --{N}(a::ModInt{N}, b::ModInt{N}) = ModInt{N}(a.k-b.k) -*{N}(a::ModInt{N}, b::ModInt{N}) = ModInt{N}(a.k*b.k) +-{n}(a::ModInt{n}) = ModInt{n}(-a.k) ++{n}(a::ModInt{n}, b::ModInt{n}) = ModInt{n}(a.k+b.k) +-{n}(a::ModInt{n}, b::ModInt{n}) = ModInt{n}(a.k-b.k) +*{n}(a::ModInt{n}, b::ModInt{n}) = ModInt{n}(a.k*b.k) -convert{N}(::Type{ModInt{N}}, i::Int) = ModInt{N}(i) -promote_rule{N}(::Type{ModInt{N}}, ::Type{Int}) = ModInt{N} +convert{n}(::Type{ModInt{n}}, i::Int) = ModInt{n}(i) +promote_rule{n}(::Type{ModInt{n}}, ::Type{Int}) = ModInt{n} -show{n}(io, k::ModInt{n}) = print(io, "$(k.k) mod $n") -showcompact(io, k::ModInt) = print(io, k.k) +show{n}(io::IO, k::ModInt{n}) = print(io, "$(k.k) mod $n") +showcompact(io::IO, k::ModInt) = print(io, k.k) diff --git a/examples/ndgrid.jl b/examples/ndgrid.jl index f6cbca97a1085..35e533fc2326a 100644 --- a/examples/ndgrid.jl +++ b/examples/ndgrid.jl @@ -7,7 +7,7 @@ function ndgrid{T}(v1::AbstractVector{T}, v2::AbstractVector{T}) (repmat(v1, 1, n), repmat(v2, m, 1)) end -function _jl_ndgrid_fill(a, v, s, snext) +function ndgrid_fill(a, v, s, snext) for j = 1:numel(a) a[j] = v[div(rem(j-1, snext), s)+1] end @@ -22,7 +22,7 @@ function ndgrid{T}(vs::AbstractVector{T}...) a = out[i]::Array v = vs[i] snext = s*size(a,i) - _jl_ndgrid_fill(a, v, s, snext) + ndgrid_fill(a, v, s, snext) s = snext end out diff --git a/examples/plife.jl b/examples/plife.jl index fe1eb0b203456..583f75199041b 100644 --- a/examples/plife.jl +++ b/examples/plife.jl @@ -16,7 +16,7 @@ function life_rule(old) end function life_step(d) - DArray(size(d),[2:nprocs()]) do I + DArray(size(d),procs(d)) do I # fetch neighborhood - toroidal boundaries top = mod(first(I[1])-2,size(d,1))+1 bot = mod( last(I[1]) ,size(d,1))+1 @@ -48,12 +48,12 @@ function plife(m, n) c.mouse.button1press = (c,x,y)->(done=true) cr = cairo_context(c) - grid = DArray(I->randbool(map(length,I)), (m, n), [2:nprocs()]) + grid = DArray(I->convert(Array{Bool,2},randbool(map(length,I))), (m, n), [2:nprocs()]) last = time(); f = 1 while !done @async begin - img = convert(Array,grid) .* 0x00ffffff + img = convert(Array{Uint32,2},grid) .* 0x00ffffff set_source_surface(cr, CairoRGBSurface(img), 0, 0) paint(cr) reveal(c) diff --git a/examples/png.jl b/examples/png.jl deleted file mode 100644 index ac24828281675..0000000000000 --- a/examples/png.jl +++ /dev/null @@ -1,29 +0,0 @@ -# Sample of strpack.jl: Reading a .png header - -load("strpack") -fpng = open(ARGS[1]) - -# check the signature -signature = unpack(fpng, s"BcccBBBB") -@assert isequal(signature, struct(s"BcccBBBB", 0x89, 'P', 'N', 'G', 0x0D, 0x0A, 0x1A, 0x0A)) - -# read the header -header = unpack(fpng, s" - > # big endian - i # length of this chunk - cccc # IHDR in this case - [size]2I - bbbbb - ") -close(fpng) - -println("PNG File info for $(ARGS[1]):") -# check we got the header correctly -@assert isequal(header[1], 0x0D) -@assert isequal(header[2:5], ['I', 'H', 'D', 'R']) -println("Width: $(header.size[1]), Height: $(header.size[2])") -println("Bit depth: $(header[7])") -println("Color type: $(header[8])") -println("Compression method: $(header[9])") -println("Filter method: $(header[10])") -println("Interlace method: $(header[11])") diff --git a/examples/preduce.jl b/examples/preduce.jl index 4d90b2b137b08..f0d4cbd45a4d1 100644 --- a/examples/preduce.jl +++ b/examples/preduce.jl @@ -1,3 +1,5 @@ +importall Base + # figure 5.2 from principles of parallel programming, ported to julia. # sum a vector using a tree on top of local reductions. function sum(v::DArray) @@ -9,7 +11,7 @@ function sum(v::DArray) for i=0:np-1 @spawnat P[i+1] begin stride=1 - tally = sum(localize(v)) + tally = sum(localpart(v)) while stride < np if i%(2*stride) == 0 tally = tally + take(nodeval[i+stride]) @@ -28,8 +30,8 @@ function sum(v::DArray) end function reduce(f, v::DArray) - mapreduce(f, fetch, - { @spawnat p reduce(f,localize(v)) for p = procs(v) }) + mapreduce(fetch, f, + { @spawnat p reduce(f,localpart(v)) for p = procs(v) }) end # possibly-useful abstraction: @@ -40,5 +42,5 @@ type RefGroup RefGroup(P) = new([ RemoteRef(p) for p=P ]) end -ref(r::RefGroup, i) = fetch(r.refs[i]) -assign(r::RefGroup, v, i) = put(r.refs[i], v) +getindex(r::RefGroup, i) = fetch(r.refs[i]) +setindex!(r::RefGroup, v, i) = put(r.refs[i], v) diff --git a/examples/quaternion.jl b/examples/quaternion.jl index 8ed0628e3ac30..b670304044e38 100644 --- a/examples/quaternion.jl +++ b/examples/quaternion.jl @@ -21,7 +21,7 @@ promote_rule{S}(::Type{Bool}, ::Type{Quaternion{S}}) = Quaternion{S} promote_rule{T<:Real,S}(::Type{T}, ::Type{Quaternion{S}}) = Quaternion{promote_type(T,S)} -function show(io, z::Quaternion) +function show(io::IO, z::Quaternion) show(io, z.q0) i = z.q1 if sign(i) == -1 diff --git a/examples/shootout/fasta.jl b/examples/shootout/fasta.jl index 31d31d1f94082..f8e4fe9d841f5 100644 --- a/examples/shootout/fasta.jl +++ b/examples/shootout/fasta.jl @@ -1,7 +1,7 @@ const line_width = 60 -const alu = strcat( +const alu = string( "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG", "GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA", "CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT", @@ -37,7 +37,7 @@ end function repeat_fasta(src, n) k = length(src) - s = strcat(src, src, src[1:n % k]) + s = string(src, src, src[1:n % k]) for j = 0:div(n, line_width) - 1 i = j * line_width % k diff --git a/examples/shootout/k-nucleotide.jl b/examples/shootout/k-nucleotide.jl index 62c5047cc2dff..60458d857fd98 100644 --- a/examples/shootout/k-nucleotide.jl +++ b/examples/shootout/k-nucleotide.jl @@ -59,12 +59,12 @@ end function main() three = ">THREE " while true - line = readline(stdin_stream) + line = readline(STDIN) if length(line) >= length(three) && line[1:length(three)] == three break end end - data = chars(readall(stdin_stream)) + data = chars(readall(STDIN)) # delete the newlines and convert to upper case i, j = 1, 1 while i <= length(data) diff --git a/examples/shootout/mandelbrot.jl b/examples/shootout/mandelbrot.jl index a903a91e332b0..d11eb87dfa02d 100644 --- a/examples/shootout/mandelbrot.jl +++ b/examples/shootout/mandelbrot.jl @@ -47,4 +47,4 @@ function main(args, stream) end #main([1600], open("mandel.txt", "w")) -main(ARGS, stdout_stream) +main(ARGS, STDOUT) diff --git a/examples/shootout/meteor-contest.jl b/examples/shootout/meteor-contest.jl index ab3778fe06ed1..e34d040be6bd3 100644 --- a/examples/shootout/meteor-contest.jl +++ b/examples/shootout/meteor-contest.jl @@ -120,7 +120,7 @@ function allBitmasks(piece, color) for x in 0:width-1 isValid, mask = getBitmask(x, y, piece) if isValid && noIslands(uint64(mask)) - push(bitmasks, mask) + push!(bitmasks, mask) end end end @@ -147,7 +147,7 @@ function generateBitmasks() while j >= 0 if (masks[j + 1] & cellMask) == cellMask - push(masksAtCell[cellCounter + 1, color + 1], masks[j + 1]) + push!(masksAtCell[cellCounter + 1, color + 1], masks[j + 1]) j -= 1 else cellMask >>= 1 @@ -166,8 +166,8 @@ function solveCell(cell_, board::Uint64, n) if board == 0x0003FFFFFFFFFFFF # Solved s = stringOfMasks(masks) - push(solutions, s) - push(solutions, reverse(s)) + push!(solutions, s) + push!(solutions, reverse(s)) return end @@ -207,7 +207,7 @@ function stringOfMasks(masks) for x in 0:width-1 for color in 0:9 if (masks[color+1] & mask) != 0 - s = strcat(s, color) + s = string(s, color) break elseif color == 9 s *= "." diff --git a/examples/shootout/nbody.jl b/examples/shootout/nbody.jl index 6a5b76d0616d9..d8ba9328fe6d8 100644 --- a/examples/shootout/nbody.jl +++ b/examples/shootout/nbody.jl @@ -6,7 +6,7 @@ # A straight port from the Java version # -load("timing") +include("timing.jl") # Constants const solar_mass = 4 * pi * pi diff --git a/examples/shootout/nbody_vec.jl b/examples/shootout/nbody_vec.jl index 481765f6e7d31..82ca4baa2325a 100644 --- a/examples/shootout/nbody_vec.jl +++ b/examples/shootout/nbody_vec.jl @@ -6,7 +6,7 @@ # A vectorized version of the Java port from nbody.jl # -load("timing") +include("timing.jl") # Constants const solar_mass = 4 * pi * pi diff --git a/examples/shootout/pidigits.jl b/examples/shootout/pidigits.jl index f1c88ee178c21..20dbe02ecf19b 100644 --- a/examples/shootout/pidigits.jl +++ b/examples/shootout/pidigits.jl @@ -1,5 +1,4 @@ -load("timing") -load("bigint") +include("timing.jl") function pidigits(N::Int, printOut::Bool) """ @@ -28,7 +27,7 @@ function pidigits(N::Int, printOut::Bool) while true k += 1 - t = lshift(n,uint(1)) + t = n << 1 n *= k a += t k1 += 2 @@ -36,14 +35,14 @@ function pidigits(N::Int, printOut::Bool) d *= k1 if a >= n - t,u = divmod(n*3 +a, d) + t,u = Base.GMP.divrem(n*3 +a, d) u += n if d > u ns = ns*10 + t i += 1 if mod(i,10) == 0 if printOut - show(ns) + print(ns) @printf("\t:%d\n", i) end if i >= N @@ -74,4 +73,3 @@ else end @timeit pidigits(N) "pidigits" - diff --git a/examples/shootout/regex-dna.jl b/examples/shootout/regex-dna.jl index 3869e4e9b504b..02290ca5c63ca 100644 --- a/examples/shootout/regex-dna.jl +++ b/examples/shootout/regex-dna.jl @@ -31,7 +31,7 @@ const subs = [ ] function main() - seq = readall(stdin_stream) + seq = readall(STDIN) l1 = length(seq) seq = replace(seq, r">.*\n|\n", "") diff --git a/examples/shootout/revcomp.jl b/examples/shootout/revcomp.jl index 0454cacf046e2..283b2ba78d0bb 100644 --- a/examples/shootout/revcomp.jl +++ b/examples/shootout/revcomp.jl @@ -40,7 +40,7 @@ end function main() buff = Uint8[] while true - line = readline(stdin_stream).data + line = readline(STDIN).data if isempty(line) print_buff(buff) return diff --git a/examples/shootout/timing.jl b/examples/shootout/timing.jl index 514d4cbefdfc5..96a3b0dd1c41a 100644 --- a/examples/shootout/timing.jl +++ b/examples/shootout/timing.jl @@ -1,5 +1,5 @@ macro timeit(ex,name) - t, i = gensym(2) + @gensym t i quote $t = Inf for $i=1:5 diff --git a/examples/staged.jl b/examples/staged.jl index b8a19d5d39246..69cc98a7f642e 100644 --- a/examples/staged.jl +++ b/examples/staged.jl @@ -1,5 +1,5 @@ -function _jl_add_method(gf, an, at, body) - argexs = { expr(symbol("::"), an[i], at[i]) for i=1:length(an) } +function add_method(gf, an, at, body) + argexs = { Expr(symbol("::"), an[i], at[i]) for i=1:length(an) } def = quote let __F__=($gf) function __F__($(argexs...)) @@ -17,7 +17,7 @@ macro staged(fdef) fname = fdef.args[1].args[1] argspec = fdef.args[1].args[2:] argnames = map(x->(isa(x,Expr) ? x.args[1] : x), argspec) - qargnames = map(x->expr(:quote,{x}), argnames) + qargnames = map(x->Expr(:quote,x), argnames) fbody = fdef.args[2] @gensym gengf argtypes expander genbody quote @@ -32,7 +32,7 @@ macro staged(fdef) ($argtypes) = typeof(tuple($(argnames...))) if !method_exists($gengf, $argtypes) ($genbody) = apply(($expander), ($argtypes)) - _jl_add_method($gengf, {$(qargnames...)}, + add_method($gengf, {$(qargnames...)}, $argtypes, $genbody) end return ($gengf)($(argnames...)) diff --git a/examples/tk_examples.jl b/examples/tk_examples.jl deleted file mode 100644 index 6f57b42efb607..0000000000000 --- a/examples/tk_examples.jl +++ /dev/null @@ -1,27 +0,0 @@ -require("Tk") -using Tk -using Cairo - -function sketch_window() - w = Window("drawing", 400, 300) - c = Canvas(w) - pack(c) - lastx = 0 - lasty = 0 - cr = cairo_context(c) - set_source_rgb(cr, 1, 1, 1) - paint(cr) - reveal(c) - set_source_rgb(cr, 0, 0, 0.85) - c.mouse.button1press = function (c, x, y) - lastx = x; lasty = y - end - c.mouse.button1motion = function (c, x, y) - move_to(cr, lastx, lasty) - line_to(cr, x, y) - stroke(cr) - reveal(c) - lastx = x; lasty = y - end - c -end diff --git a/examples/tree.jl b/examples/tree.jl index 0646647b1b876..ec0c566475fea 100644 --- a/examples/tree.jl +++ b/examples/tree.jl @@ -29,10 +29,10 @@ function has(t::TreeNode, key) end end -ref(t::EmptyTree, k) = throw(KeyError(k)) -ref(t::BTree, k) = t.root[k] +getindex(t::EmptyTree, k) = throw(KeyError(k)) +getindex(t::BTree, k) = t.root[k] -function ref(t::TreeNode, key) +function getindex(t::TreeNode, key) if t.key == key t.data elseif key < t.key diff --git a/examples/typetree.jl b/examples/typetree.jl index 9314ac0a00064..c4f9940a29170 100644 --- a/examples/typetree.jl +++ b/examples/typetree.jl @@ -11,7 +11,7 @@ function list_all(T::Type, modules::Array{Module}, f::Function) sm = string(m) for s = names(m,true) try - t = eval(s) + t = eval(m,s) if f(t) a[string(s)] = t end @@ -40,7 +40,7 @@ extra = Dict{String, String}() function insert_type(m,s,x,ex) try ms = m[s] - add(ms, x) + add!(ms, x) catch m[s] = Set{String}(x) end @@ -48,9 +48,7 @@ function insert_type(m,s,x,ex) end function add_type(x,t,sup) - if isa(t, AbstractKind) || - isa(t, BitsKind) || - isa(t, CompositeKind) + if isa(t, DataType) s = sup ? super(t) : t s_param = "" if x != string(t.name) @@ -59,11 +57,11 @@ function add_type(x,t,sup) s_param *= " (=" * string(s.name) * "{" * join(s.parameters, ", ") * "})" end insert_type(children_map, string(s.name), x, s_param) - elseif isa(t, UnionKind) + elseif isa(t, UnionType) for c in t.types add_type(x, c, false) end - insert_type(children_map, "UnionKind", x, " = " * string(t)) + insert_type(children_map, "UnionType", x, " = " * string(t)) elseif isa(t, TypeConstructor) add_type(x, t.body, false) #println(typeof(t.body)) @@ -118,8 +116,8 @@ end show_tree(root) = show_tree(root, "", "") ## main ## -all_types = list_all(Type, [Core, Base], (x)->isa(x, Type)) -children_map = Dict{String, Set{String}}(length(all_types)) +all_types = list_all(Type, [Core, Base, Main], (x)->isa(x, Type)) +children_map = Dict{String, Set{String}}() mk_tree() println("\n\nType Tree:") show_tree("Any") #todo: generalize this to be every item without a parent in all_types diff --git a/examples/wav.jl b/examples/wav.jl deleted file mode 100644 index 2698dede28800..0000000000000 --- a/examples/wav.jl +++ /dev/null @@ -1,7 +0,0 @@ -require("sound") -using Sound - -in_filename = ARGS[1] - -y, Fs, nbits, opts = wavread(in_filename) -wavwrite(y, Fs, nbits, strcat("out-", in_filename)) diff --git a/examples/wordcount.jl b/examples/wordcount.jl index 3c26895666e0c..ca525eba75211 100644 --- a/examples/wordcount.jl +++ b/examples/wordcount.jl @@ -82,6 +82,6 @@ function wordcount_files(result_file,input_file_names...) wc=parallel_wordcount(text) fo=open(result_file,"w") for (k,v) = wc - with_output_stream(fo,println,k,"=",v) + println(fo,k,"=",v) end end diff --git a/extras/.gitignore b/extras/.gitignore deleted file mode 100644 index 37945b1d9259b..0000000000000 --- a/extras/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/glpk-* -/glpk_h.jl -/webrepl_msgtypes_h.jl diff --git a/extras/Makefile b/extras/Makefile deleted file mode 100644 index 1ec88005c62a5..0000000000000 --- a/extras/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -JULIAHOME = $(abspath ..) -include $(JULIAHOME)/Make.inc - -all: glpk_h.jl webrepl_msgtypes_h.jl - -GLPK_VER = 4.47 - -GLPK_CONST = 0x[0-9a-fA-F]+|[-+]?\s*[0-9]+ - -ifeq ($(USE_SYSTEM_GLPK), 1) -GLPK_PREFIX = /usr/include -else -GLPK_PREFIX = $(JULIAHOME)/deps/glpk-$(GLPK_VER)/src -endif - -glpk_h.jl: - $(QUIET_PERL) $(CC) -E -dM $(GLPK_PREFIX)/glpk.h | perl -nle '/^\s*#define\s+GLP_(\w*)\s*\(?($(GLPK_CONST))\)?\s*$$/ and print "const $$1 = int32($$2)"' | sort > $@ - -webrepl_msgtypes_h.jl: ../ui/webserver/message_types.h - $(QUIET_PERL) $(CC) -E -Dnotdefined $^ > $@ - -clean: - rm -f glpk_h.jl julia_message_types_h.jl diff --git a/extras/Rmath.jl b/extras/Rmath.jl deleted file mode 100644 index bf73e4b0dd68d..0000000000000 --- a/extras/Rmath.jl +++ /dev/null @@ -1,559 +0,0 @@ -## Interface to the Rmath library ## -_jl_libRmath = dlopen("libRmath") - -macro _jl_libRmath_vectorize_3arg(f) - quote - global $f - ($f){T1<:Number, T2<:Number, T3<:Number}(x::AbstractArray{T1}, y::T2, z::T3) = - reshape([ ($f)(x[i], y, z) for i=1:numel(x) ], size(x)) - ($f){T1<:Number, T2<:Number, T3<:Number}(x::T1, y::AbstractArray{T2}, z::T3) = - reshape([ ($f)(x, y[i], z) for i=1:numel(y) ], size(y)) - ($f){T1<:Number, T2<:Number, T3<:Number}(x::T1, y::T2, z::AbstractArray{T3}) = - reshape([ ($f)(x, y, z[i]) for i=1:numel(z) ], size(z)) - function ($f){T1<:Number, T2<:Number, T3<:Number}(x::AbstractArray{T1}, y::AbstractArray{T2}, z::T3) - shp = promote_shape(size(x), size(y)) - reshape([ ($f)(x[i], y[i], z) for i=1:numel(x) ], shp) - end - function ($f){T1<:Number, T2<:Number, T3<:Number}(x::T1, y::AbstractArray{T2}, z::AbstractArray{T3}) - shp = promote_shape(size(y), size(z)) - reshape([ ($f)(x, y[i], z[i]) for i=1:numel(y) ], shp) - end - function ($f){T1<:Number, T2<:Number, T3<:Number}(x::AbstractArray{T1}, y::T2, z::AbstractArray{T3}) - shp = promote_shape(size(x), size(z)) - reshape([ ($f)(x[i], y, z[i]) for i=1:numel(x) ], shp) - end - function ($f){T1<:Number, T2<:Number, T3<:Number}(x::AbstractArray{T1}, y::T2, z::AbstractArray{T3}) - shp = promote_shape(size(x), size(z)) - reshape([ ($f)(x[i], y, z[i]) for i=1:numel(x) ], shp) - end - function ($f){T1<:Number, T2<:Number, T3<:Number}(x::AbstractArray{T1}, y::AbstractArray{T2}, z::AbstractArray{T3}) - shp = promote_shape(promote_shape(size(x), size(y)), size(z)) - reshape([ ($f)(x[i], y, z[i]) for i=1:numel(x) ], shp) - end - end -end - -## Is this version still needed? -set_seed(a1::Integer, a2::Integer) = - ccall(dlsym(_jl_libRmath,:set_seed), Void, (Int32,Int32), a1, a2) - -## Vectorize over four numeric arguments -macro _jl_libRmath_vectorize_4arg(f) - quote - global $f - ($f){T1<:Number, T2<:Number, T3<:Number, T4<:Number}(a1::AbstractArray{T1}, a2::T2, a3::T3, a4::T4) = - reshape([ ($f)(a1[i], a2, a3, a4) for i=1:numel(a1) ], size(a1)) - ($f){T1<:Number, T2<:Number, T3<:Number, T4<:Number}(a1::T1, a2::AbstractArray{T2}, a3::T3, a4::T4) = - reshape([ ($f)(a1, a2[i], a3, a4) for i=1:numel(a2) ], size(a2)) - ($f){T1<:Number, T2<:Number, T3<:Number, T4<:Number}(a1::T1, a2::T2, a3::AbstractArray{T3}, a4::T4) = - reshape([ ($f)(a1, a2, a3[i], a4) for i=1:numel(a3) ], size(a3)) - ($f){T1<:Number, T2<:Number, T3<:Number, T4<:Number}(a1::T1, a2::T2, a3::T3, a4::AbstractArray{T4}) = - reshape([ ($f)(a1, a2, a3, a4[i]) for i=1:numel(a4) ], size(a4)) - function ($f){T1<:Number, T2<:Number, T3<:Number, T4<:Number}(a1::AbstractArray{T1}, a2::AbstractArray{T2}, a3::T3, a4::T4) - shp = promote_shape(size(a1), size(a2)) - reshape([ ($f)(a1[i], a2[i], a3, a4) for i=1:numel(a1) ], shp) - end - function ($f){T1<:Number, T2<:Number, T3<:Number, T4<:Number}(a1::AbstractArray{T1}, a2::T2, a3::AbstractArray{T3}, a4::T4) - shp = promote_shape(size(a1), size(a3)) - reshape([ ($f)(a1[i], a2, a3[i], a4) for i=1:numel(a1) ], shp) - end - function ($f){T1<:Number, T2<:Number, T3<:Number, T4<:Number}(a1::AbstractArray{T1}, a2::T2, a3::T3, a4::AbstractArray{T4}) - shp = promote_shape(size(a1), size(a4)) - reshape([ ($f)(a1[i], a2, a3, a4[i]) for i=1:numel(a1) ], shp) - end - function ($f){T1<:Number, T2<:Number, T3<:Number, T4<:Number}(a1::T1, a2::AbstractArray{T2}, a3::AbstractArray{T3}, a4::T4) - shp = promote_shape(size(a2), size(a3)) - reshape([ ($f)(a1, a2[i], a3[i], a4) for i=1:numel(a2) ], shp) - end - function ($f){T1<:Number, T2<:Number, T3<:Number, T4<:Number}(a1::T1, a2::AbstractArray{T2}, a3::T3, a4::AbstractArray{T4}) - shp = promote_shape(size(a2), size(a4)) - reshape([ ($f)(a1, a2[i], a3, a4[i]) for i=1:numel(a2) ], shp) - end - function ($f){T1<:Number, T2<:Number, T3<:Number, T4<:Number}(a1::T1, a2::T2, a3::AbstractArray{T3}, a4::AbstractArray{T4}) - shp = promote_shape(size(a3), size(a4)) - reshape([ ($f)(a1, a2, a3[i], a4[i]) for i=1:numel(a3) ], shp) - end - function ($f){T1<:Number, T2<:Number, T3<:Number, T4<:Number}(a1::AbstractArray{T1}, a2::AbstractArray{T2}, a3::AbstractArray{T3}, a4::T4) - shp = promote_shape(promote_shape(size(a1), size(a2)), size(a3)) - reshape([ ($f)(a1[i], a2[i], a3[i], a4) for i=1:numel(a1) ], shp) - end - function ($f){T1<:Number, T2<:Number, T3<:Number, T4<:Number}(a1::AbstractArray{T1}, a2::AbstractArray{T2}, a3::T3, a4::AbstractArray{T4}) - shp = promote_shape(promote_shape(size(a1), size(a2)), size(a4)) - reshape([ ($f)(a1[i], a2[i], a3, a4[i]) for i=1:numel(a1) ], shp) - end - function ($f){T1<:Number, T2<:Number, T3<:Number, T4<:Number}(a1::AbstractArray{T1}, a2::T2, a3::AbstractArray{T3}, a4::AbstractArray{T4}) - shp = promote_shape(promote_shape(size(a1), size(a3)), size(a4)) - reshape([ ($f)(a1[i], a2, a3[i], a4[i]) for i=1:numel(a1) ], shp) - end - function ($f){T1<:Number, T2<:Number, T3<:Number, T4<:Number}(a1::T1, a2::AbstractArray{T2}, a3::AbstractArray{T3}, a4::AbstractArray{T4}) - shp = promote_shape(promote_shape(size(a2), size(a3)), size(a4)) - reshape([ ($f)(a1, a2[i], a3[i], a4[i]) for i=1:numel(a2) ], shp) - end - function ($f){T1<:Number, T2<:Number, T3<:Number, T4<:Number}(a1::AbstractArray{T1}, a2::AbstractArray{T2}, a3::AbstractArray{T3}, a4::AbstractArray{T4}) - shp = promote_shape(promote_shape(promote_shape(size(a1), size(a2)), size(a3)), size(a4)) - reshape([ ($f)(a1[i], a2[i], a3[i], a4[i]) for i=1:numel(a2) ], shp) - end - end -end - -## Macro for deferring freeing data until GC for wilcox and signrank -macro _jl_libRmath_deferred_free(base) - libcall = symbol(strcat(string(base), "_free")) - func = symbol(strcat(string(base), "_deferred_free")) - quote - let gc_tracking_obj = [] - global $func - function $libcall(x::Vector{None}) - gc_tracking_obj = [] - ccall(dlsym(_jl_libRmath, $(string(libcall))), Void, ()) - end - function $func() - if !isa(gc_tracking_obj, Bool) - finalizer(gc_tracking_obj, $libcall) - gc_tracking_obj = false - end - end - end - end -end - -## Non-ccall functions for distributions with 1 parameter and no defaults -macro _jl_libRmath_1par_0d_aliases(base) - dd = symbol(strcat("d", string(base))) - pp = symbol(strcat("p", string(base))) - qq = symbol(strcat("q", string(base))) - quote - global $dd, $pp, $qq - ($dd){T<:Number}(x::AbstractArray{T}, p1::Number, give_log::Bool) = - reshape([ ($dd)(x[i], p1, give_log) for i=1:numel(x) ], size(x)) - ($dd)(x::Number, p1::Number) = ($dd)(x, p1, false) - @vectorize_2arg Number $dd - - ($pp){T<:Number}(q::AbstractArray{T}, p1::Number, lower_tail::Bool, log_p::Bool) = - reshape([ ($pp)(q[i], p1, lower_tail, log_p) for i=1:numel(q) ], size(q)) - ($pp)(q::Number, p1::Number, lower_tail::Bool) = ($pp)(q, p1, lower_tail, false) - ($pp){T<:Number}(q::AbstractArray{T}, p1::Number, lower_tail::Bool) = ($pp)(q, p1, lower_tail, false) - ($pp)(q::Number, p1::Number) = ($pp)(q, p1, true, false) - @vectorize_2arg Number $pp - - ($qq){T<:Number}(p::AbstractArray{T}, p1::Number, lower_tail::Bool, log_p::Bool) = - reshape([ ($qq)(p[i], p1, lower_tail, log_p) for i=1:numel(p) ], size(p)) - ($qq)(p::Number, p1::Number, lower_tail::Bool) = ($qq)(p, p1, lower_tail, false) - ($qq){T<:Number}(p::AbstractArray{T}, p1::Number, lower_tail::Bool) = ($qq)(p, p1, lower_tail, false) - ($qq)(p::Number, p1::Number) = ($qq)(p, p1, true, false) - @vectorize_2arg Number $qq - end -end - -## Distributions with 1 parameter and no default -macro _jl_libRmath_1par_0d(base) - dd = symbol(strcat("d", string(base))) - pp = symbol(strcat("p", string(base))) - qq = symbol(strcat("q", string(base))) - rr = symbol(strcat("r", string(base))) - quote - global $dd, $pp, $qq, $rr - ($dd)(x::Number, p1::Number, give_log::Bool) = - ccall(dlsym(_jl_libRmath,$(string(dd))), Float64, (Float64,Float64,Int32), x, p1, give_log) - ($pp)(q::Number, p1::Number, lower_tail::Bool, log_p::Bool) = - ccall(dlsym(_jl_libRmath,$(string(pp))), Float64, (Float64,Float64,Int32,Int32), q, p1, lower_tail, log_p) - ($qq)(p::Number, p1::Number, lower_tail::Bool, log_p::Bool) = - ccall(dlsym(_jl_libRmath,$(string(qq))), Float64, (Float64,Float64,Int32,Int32), p, p1, lower_tail, log_p) - ($rr)(nn::Integer, p1::Number) = - [ ccall(dlsym(_jl_libRmath,$(string(rr))), Float64, (Float64,), p1) for i=1:nn ] - @_jl_libRmath_1par_0d_aliases $base - end -end - -@_jl_libRmath_1par_0d t # Student's t distribution (df) -@_jl_libRmath_1par_0d chisq # Central Chi-squared distribution (df) -@_jl_libRmath_1par_0d pois # Poisson distribution (lambda) -@_jl_libRmath_1par_0d geom # Geometric distribution (prob) - -## The d-p-q functions in Rmath for signrank allocate storage that must be freed -## Signrank - Wilcoxon Signed Rank statistic -@_jl_libRmath_deferred_free signrank -function dsignrank(x::Number, p1::Number, give_log::Bool) - signrank_deferred_free() - ccall(dlsym(_jl_libRmath, "dsignrank"), Float64, (Float64,Float64,Int32), x, p1, give_log) -end -function psignrank(q::Number, p1::Number, lower_tail::Bool, log_p::Bool) - signrank_deferred_free() - ccall(dlsym(_jl_libRmath, "psignrank"), Float64, (Float64,Float64,Int32,Int32), q, p1, lower_tail, log_p) -end -function qsignrank(p::Number, p1::Number, lower_tail::Bool, log_p::Bool) - signrank_deferred_free() - ccall(dlsym(_jl_libRmath, "qsignrank"), Float64, (Float64,Float64,Int32,Int32), p, p1, lower_tail, log_p) -end -@_jl_libRmath_1par_0d_aliases signrank -rsignrank(nn::Integer, p1::Number) = - [ ccall(dlsym(_jl_libRmath, "rsignrank"), Float64, (Float64,), p1) for i=1:nn ] - -## Distributions with 1 parameter and a default -macro _jl_libRmath_1par_1d(base, d1) - dd = symbol(strcat("d", string(base))) - pp = symbol(strcat("p", string(base))) - qq = symbol(strcat("q", string(base))) - rr = symbol(strcat("r", string(base))) - quote - global $dd, $pp, $qq, $rr - ($dd)(x::Number, p1::Number, give_log::Bool) = - ccall(dlsym(_jl_libRmath,$(string(dd))), Float64, (Float64,Float64,Int32), x, p1, give_log) - ($dd){T<:Number}(x::AbstractArray{T}, p1::Number, give_log::Bool) = - reshape([ ($dd)(x[i], p1, give_log) for i=1:numel(x) ], size(x)) - ($dd)(x::Number, give_log::Bool) = ($dd)(x, $d1, give_log) - ($dd){T<:Number}(x::AbstractArray{T}, give_log::Bool) = ($dd)(x, $d1, give_log) - ($dd)(x::Number, p1::Number) = ($dd)(x, p1, false) - @vectorize_2arg Number $dd - ($dd)(x::Number) = ($dd)(x, $d1, false) - ($dd){T<:Number}(x::AbstractArray{T}) = ($dd)(x, $d1, false) - - ($pp)(q::Number, p1::Number, lower_tail::Bool, log_p::Bool) = - ccall(dlsym(_jl_libRmath,$(string(pp))), Float64, (Float64,Float64,Int32,Int32), q, p1, lower_tail, log_p) - ($pp){T<:Number}(q::AbstractArray{T}, p1::Number, lower_tail::Bool, log_p::Bool) = - reshape([ ($pp)(q[i], p1, lower_tail, log_p) for i=1:numel(q) ], size(q)) - ($pp)(q::Number, lower_tail::Bool, log_p::Bool) = ($pp)(q, $d1, lower_tail, log_p) - ($pp){T<:Number}(q::AbstractArray{T}, lower_tail::Bool, log_p::Bool) = ($pp)(q, $d1, lower_tail, log_p) - ($pp)(q::Number, p1::Number, lower_tail::Bool) = ($pp)(q, p1, lower_tail, false) - ($pp){T<:Number}(q::AbstractArray{T}, p1::Number, lower_tail::Bool) = ($pp)(q, p1, lower_tail, false) - ($pp)(q::Number, lower_tail::Bool) = ($pp)(q, $d1, lower_tail, false) - ($pp){T<:Number}(q::AbstractArray{T}, lower_tail::Bool) = ($pp)(q, $d1, lower_tail, false) - ($pp)(q::Number, p1::Number) = ($pp)(q, p1, true, false) - @vectorize_2arg Number $pp - ($pp)(q::Number) = ($pp)(q, $d1, true, false) - ($pp){T<:Number}(q::AbstractArray{T}) = ($pp)(q, $d1, true, false) - - ($qq)(p::Number, p1::Number, lower_tail::Bool, log_p::Bool) = - ccall(dlsym(_jl_libRmath,$(string(qq))), Float64, (Float64,Float64,Int32,Int32), p, p1, lower_tail, log_p) - ($qq){T<:Number}(p::AbstractArray{T}, p1::Number, lower_tail::Bool, log_p::Bool) = - reshape([ ($qq)(p[i], p1, lower_tail, log_p) for i=1:numel(p) ], size(p)) - ($qq)(p::Number, lower_tail::Bool, log_p::Bool) = ($qq)(p, $d1, lower_tail, log_p) - ($qq){T<:Number}(p::AbstractArray{T}, lower_tail::Bool, log_p::Bool) = ($qq)(p, $d1, lower_tail, log_p) - ($qq)(p::Number, p1::Number, lower_tail::Bool) = ($qq)(p, p1, lower_tail, false) - ($qq){T<:Number}(p::AbstractArray{T}, p1::Number, lower_tail::Bool) = ($qq)(p, p1, lower_tail, false) - ($qq)(p::Number, lower_tail::Bool) = ($qq)(p, $d1, lower_tail, false) - ($qq){T<:Number}(p::AbstractArray{T}, lower_tail::Bool) = ($qq)(p, $d1, lower_tail, false) - ($qq)(p::Number, p1::Number) = ($qq)(p, p1, true, false) - @vectorize_2arg Number $qq - ($qq)(p::Number) = ($qq)(p, $d1, true, false) - ($qq){T<:Number}(p::AbstractArray{T}) = ($qq)(p, $d1, true, false) - - ($rr)(nn::Integer, p1::Number) = - [ ccall(dlsym(_jl_libRmath,$(string(rr))), Float64, (Float64,), p1) for i=1:nn ] - ($rr)(nn::Integer) = ($rr)(nn, $d1) - end -end - -## May need to handle this as a special case. The Rmath library uses 1/rate, not rate -@_jl_libRmath_1par_1d exp 1 # Exponential distribution (rate) - -## Non-ccall functions for distributions with 2 parameters and no defaults -macro _jl_libRmath_2par_0d_aliases(base) - dd = symbol(strcat("d", string(base))) - pp = symbol(strcat("p", string(base))) - qq = symbol(strcat("q", string(base))) - quote - global $dd, $pp, $qq - ($dd){T<:Number}(x::AbstractArray{T}, p1::Number, p2::Number, give_log::Bool) = - reshape([ ($dd)(x[i], p1, p2, give_log) for i=1:numel(x) ], size(x)) - ($dd)(x::Number, p1::Number, p2::Number) = ($dd)(x, p1, p2, false) - @_jl_libRmath_vectorize_3arg $dd - - ($pp){T<:Number}(q::AbstractArray{T}, p1::Number, p2::Number, lower_tail::Bool, log_p::Bool) = - reshape([ ($pp)(q[i], p1, p2, lower_tail, log_p) for i=1:numel(q) ], size(q)) - ($pp)(q::Number, p1::Number, p2::Number, lower_tail::Bool) = ($pp)(q, p1, p2, lower_tail, false) - ($pp){T<:Number}(q::AbstractArray{T}, p1::Number, p2::Number, lower_tail::Bool) = - reshape([ ($pp)(q[i], p1, p2, lower_tail, false) for i=1:numel(q) ], size(q)) - ($pp)(q::Number, p1::Number, p2::Number) = ($pp)(q, p1, p2, true, false) - @_jl_libRmath_vectorize_3arg $pp - - ($qq){T<:Number}(p::AbstractArray{T}, p1::Number, p2::Number, lower_tail::Bool, log_p::Bool) = - reshape([ ($qq)(p[i], p1, p2, lower_tail, log_p) for i=1:numel(p) ], size(p)) - ($qq)(p::Number, p1::Number, p2::Number, lower_tail::Bool) = ($qq)(p, p1, p2, lower_tail, false) - ($qq){T<:Number}(p::AbstractArray{T}, p1::Number, p2::Number, lower_tail::Bool) = - reshape([ ($qq)(p[i], p1, p2, lower_tail, false) for i=1:numel(p) ], size(p)) - ($qq)(p::Number, p1::Number, p2::Number) = ($qq)(p, p1, p2, true, false) - @_jl_libRmath_vectorize_3arg $qq - end -end - -## Distributions with 2 parameters and no defaults -macro _jl_libRmath_2par_0d(base) - dd = symbol(strcat("d", string(base))) - pp = symbol(strcat("p", string(base))) - qq = symbol(strcat("q", string(base))) - rr = symbol(strcat("r", string(base))) - quote - global $dd, $pp, $qq, $rr - ($dd)(x::Number, p1::Number, p2::Number, give_log::Bool) = - ccall(dlsym(_jl_libRmath,$(string(dd))), Float64, (Float64,Float64,Float64,Int32), x, p1, p2, give_log) - ($pp)(q::Number, p1::Number, p2::Number, lower_tail::Bool, log_p::Bool) = - ccall(dlsym(_jl_libRmath,$(string(pp))), Float64, (Float64,Float64,Float64,Int32,Int32), q, p1, p2, lower_tail, log_p) - ($qq)(p::Number, p1::Number, p2::Number, lower_tail::Bool, log_p::Bool) = - ccall(dlsym(_jl_libRmath,$(string(qq))), Float64, (Float64,Float64,Float64,Int32,Int32), p, p1, p2, lower_tail, log_p) - ($rr)(nn::Integer, p1::Number, p2::Number) = - [ ccall(dlsym(_jl_libRmath,$(string(rr))), Float64, (Float64,Float64), p1, p2) for i=1:nn ] - @_jl_libRmath_2par_0d_aliases $base - end -end - -@_jl_libRmath_2par_0d f # Central F distribution (df1, df2) -@_jl_libRmath_2par_0d binom # Binomial distribution (size, prob) -@_jl_libRmath_2par_0d nbinom # Negative binomial distribution (size, prob) -@_jl_libRmath_2par_0d nbinom_mu # Negative binomial distribution (size, mu) -@_jl_libRmath_2par_0d beta # Beta distribution (shape1, shape2) -@_jl_libRmath_2par_0d nchisq # Noncentral Chi-squared distribution (df, ncp) - -## Need to handle the d-p-q for Wilcox separately because the Rmath functions allocate storage that must be freed. -## Wilcox - Wilcox's Rank Sum statistic (m, n) - probably only makes sense for positive integers -@_jl_libRmath_deferred_free wilcox -function dwilcox(x::Number, p1::Number, p2::Number, give_log::Bool) - wilcox_deferred_free() - ccall(dlsym(_jl_libRmath,"dwilcox"), Float64, (Float64,Float64,Float64,Int32), x, p1, p2, give_log) -end -function pwilcox(q::Number, p1::Number, p2::Number, lower_tail::Bool, log_p::Bool) - wilcox_deferred_free() - ccall(dlsym(_jl_libRmath, "pwilcox"), Float64, (Float64,Float64,Float64,Int32,Int32), q, p1, p2, lower_tail, log_p) -end -function qwilcox(p::Number, p1::Number, p2::Number, lower_tail::Bool, log_p::Bool) - wilcox_deferred_free() - ccall(dlsym(_jl_libRmath, "qwilcox"), Float64, (Float64,Float64,Float64,Int32,Int32), p, p1, p2, lower_tail, log_p) -end -rwilcox(nn::Integer, p1::Number, p2::Number) = - [ ccall(dlsym(_jl_libRmath, "rwilcox"), Float64, (Float64,Float64), p1, p2) for i=1:nn ] -@_jl_libRmath_2par_0d_aliases wilcox - -## Distributions with 2 parameters and 1 default -macro _jl_libRmath_2par_1d(base, d2) - dd = symbol(strcat("d", string(base))) - pp = symbol(strcat("p", string(base))) - qq = symbol(strcat("q", string(base))) - rr = symbol(strcat("r", string(base))) - quote - global $dd, $pp, $qq, $rr - ($dd)(x::Number, p1::Number, p2::Number, give_log::Bool) = - ccall(dlsym(_jl_libRmath,$(string(dd))), Float64, (Float64,Float64,Float64,Int32), x, p1, p2, give_log) - ($dd){T<:Number}(x::AbstractArray{T}, p1::Number, p2::Number, give_log::Bool) = - reshape([ ($dd)(x[i], p1, p2, give_log) for i=1:numel(x) ], size(x)) - ($dd)(x::Number, p1::Number, give_log::Bool) = ($dd)(x, p1, $d2, give_log) - ($dd){T<:Number}(x::AbstractArray{T}, p1::Number, give_log::Bool) = ($dd)(x, p1, $d2, give_log) - ($dd)(x::Number, p1::Number, p2::Number) = ($dd)(x, p1, p2, false) - @_jl_libRmath_vectorize_3arg $dd - ($dd)(x::Number, p1::Number) = ($dd)(x, p1, $d2, false) - @vectorize_2arg Number $dd - - ($pp)(q::Number, p1::Number, p2::Number, lower_tail::Bool, log_p::Bool) = - ccall(dlsym(_jl_libRmath,$(string(pp))), Float64, (Float64,Float64,Float64,Int32,Int32), q, p1, p2, lower_tail, log_p) - ($pp)(q::Number, p1::Number, lower_tail::Bool, log_p::Bool) = ($pp)(q, p1, $d2, lower_tail, log_p) - ($pp){T<:Number}(q::AbstractArray{T}, p1::Number, p2::Number, lower_tail::Bool, log_p::Bool) = - reshape([ ($pp)(q[i], p1, p2, lower_tail, log_p) for i=1:numel(q) ], size(q)) - ($pp){T<:Number}(q::AbstractArray{T}, p1::Number, lower_tail::Bool, log_p::Bool) = ($pp)(q, p1, $d2, lower_tail, log_p) - ($pp)(q::Number, p1::Number, p2::Number, lower_tail::Bool) = ($pp)(q, p1, p2, lower_tail, false) - ($pp)(q::Number, p1::Number, lower_tail::Bool) = ($pp)(q, p1, $d2, lower_tail, false) - ($pp){T<:Number}(q::AbstractArray{T}, p1::Number, p2::Number, lower_tail::Bool) = ($pp)(q, p1, p2, lower_tail, false) - ($pp){T<:Number}(q::AbstractArray{T}, p1::Number, lower_tail::Bool) = ($pp)(q, p1, $d2, lower_tail, false) - ($pp)(q::Number, p1::Number, p2::Number) = ($pp)(q, p1, p2, true, false) - @_jl_libRmath_vectorize_3arg $pp - ($pp)(q::Number, p1::Number) = ($pp)(q, p1, $d2, true, false) - @vectorize_2arg Number $pp - - ($qq)(p::Number, p1::Number, p2::Number, lower_tail::Bool, log_p::Bool) = - ccall(dlsym(_jl_libRmath,$(string(qq))), Float64, (Float64,Float64,Float64,Int32,Int32), p, p1, p2, lower_tail, log_p) - ($qq)(p::Number, p1::Number, lower_tail::Bool, log_p::Bool) = ($qq)(p, p1, $d2, lower_tail, log_p) - ($qq){T<:Number}(p::AbstractArray{T}, p1::Number, p2::Number, lower_tail::Bool, log_p::Bool) = - reshape([ ($qq)(p[i], p1, p2, lower_tail, log_p) for i=1:numel(p) ], size(p)) - ($qq){T<:Number}(p::AbstractArray{T}, p1::Number, lower_tail::Bool, log_p::Bool) = ($qq)(p, p1, $d2, lower_tail, log_p) - ($qq)(p::Number, p1::Number, p2::Number, lower_tail::Bool) = ($qq)(p, p1, p2, lower_tail, false) - ($qq)(p::Number, p1::Number, lower_tail::Bool) = ($qq)(p, p1, $d2, lower_tail, false) - ($qq){T<:Number}(p::AbstractArray{T}, p1::Number, p2::Number, lower_tail::Bool) = ($qq)(p, p1, p2, lower_tail, false) - ($qq){T<:Number}(p::AbstractArray{T}, p1::Number, lower_tail::Bool) = ($qq)(p, p1, $d2, lower_tail, false) - ($qq)(p::Number, p1::Number, p2::Number) = ($qq)(p, p1, p2, true, false) - @_jl_libRmath_vectorize_3arg $qq - ($qq)(p::Number, p1::Number) = ($qq)(p, p1, $d2, true, false) - @vectorize_2arg Number $qq - - ($rr)(nn::Integer, p1::Number, p2::Number) = - [ ccall(dlsym(_jl_libRmath,$(string(rr))), Float64, (Float64,Float64), p1, p2) for i=1:nn ] - ($rr)(nn::Integer, p1::Number) = ($rr)(nn, p1, $d2) - end -end - -@_jl_libRmath_2par_1d gamma 1 # Gamma distribution (shape, scale) -@_jl_libRmath_2par_1d weibull 1 # Weibull distribution (shape, scale) - -## Distributions with 2 parameters and 2 defaults -macro _jl_libRmath_2par_2d(base, d1, d2) - ddsym = dd = symbol(strcat("d", string(base))) - ppsym = pp = symbol(strcat("p", string(base))) - qqsym = qq = symbol(strcat("q", string(base))) - rr = symbol(strcat("r", string(base))) - if (string(base) == "norm") - ddsym = :dnorm4 - ppsym = :pnorm5 - qqsym = :qnorm5 - end - quote - global $dd, $pp, $qq, $rr - ($dd)(x::Number, p1::Number, p2::Number, give_log::Bool) = - ccall(dlsym(_jl_libRmath,$(string(ddsym))), Float64, (Float64,Float64,Float64,Int32), x, p1, p2, give_log) - ($dd){T<:Number}(x::AbstractArray{T}, p1::Number, p2::Number, give_log::Bool) = - reshape([ ($dd)(x[i], p1, p2, give_log) for i=1:numel(x) ], size(x)) - ($dd)(x::Number, p1::Number, give_log::Bool) = ($dd)(x, p1, $d2, give_log) - ($dd){T<:Number}(x::AbstractArray{T}, p1::Number, give_log::Bool) = ($dd)(x, p1, $d2, give_log) - ($dd)(x::Number, give_log::Bool) = ($dd)(x, $d1, $d2, give_log) - ($dd){T<:Number}(x::AbstractArray{T}, give_log::Bool) = ($dd)(x, $d1, $d2, give_log) - ($dd)(x::Number, p1::Number, p2::Number) = ($dd)(x, p1, p2, false) - @_jl_libRmath_vectorize_3arg $dd - ($dd)(x::Number, p1::Number) = ($dd)(x, p1, $d2, false) - @vectorize_2arg Number $dd - ($dd)(x::Number) = ($dd)(x, $d1, $d2, false) - ($dd){T<:Number}(x::AbstractArray{T}) = ($dd)(x, $d1, $d2, give_log) - - - ($pp)(q::Number, p1::Number, p2::Number, lower_tail::Bool, log_p::Bool) = - ccall(dlsym(_jl_libRmath,$(string(ppsym))), Float64, (Float64,Float64,Float64,Int32,Int32), q, p1, p2, lower_tail, log_p) - ($pp){T<:Number}(q::AbstractArray{T}, p1::Number, p2::Number, lower_tail::Bool, log_p::Bool) = - reshape([ ($pp)(q[i], p1, p2, lower_tail, log_p) for i=1:numel(q) ], size(q)) - ($pp)(q::Number, p1::Number, lower_tail::Bool, log_p::Bool) = ($pp)(q, p1, $d2, lower_tail, log_p) - ($pp){T<:Number}(q::AbstractArray{T}, p1::Number, lower_tail::Bool, log_p::Bool) = ($pp)(q, p1, $d2, lower_tail, log_p) - ($pp)(q::Number, lower_tail::Bool, log_p::Bool) = ($pp)(q, $d1, $d2, lower_tail, log_p) - ($pp){T<:Number}(q::AbstractArray{T}, lower_tail::Bool, log_p::Bool) = ($pp)(q, $d1, $d2, lower_tail, log_p) - ($pp)(q::Number, p1::Number, p2::Number, lower_tail::Bool) = ($pp)(q, p1, p2, lower_tail, false) - ($pp){T<:Number}(q::AbstractArray{T}, p1::Number, p2::Number, lower_tail::Bool) = ($pp)(q, p1, p2, lower_tail, false) - ($pp)(q::Number, p1::Number, lower_tail::Bool) = ($pp)(q, p1, $d2, lower_tail, false) - ($pp){T<:Number}(q::AbstractArray{T}, p1::Number, lower_tail::Bool) = ($pp)(q, p1, $d2, lower_tail, false) - ($pp)(q::Number, lower_tail::Bool) = ($pp)(q, $d1, $d2, lower_tail, false) - ($pp){T<:Number}(q::AbstractArray{T}, lower_tail::Bool) = ($pp)(q, $d1, $d2, lower_tail, false) - ($pp)(q::Number, p1::Number, p2::Number) = ($pp)(q, p1, p2, true, false) - @_jl_libRmath_vectorize_3arg $pp - ($pp)(q::Number, p1::Number) = ($pp)(q, p1, $d2, true, false) - @vectorize_2arg Number $pp - ($pp)(q::Number) = ($pp)(q, $d1, $d2, true, false) - ($pp){T<:Number}(q::AbstractArray{T}) = ($pp)(q, $d1, $d2, true, false) - - ($qq)(p::Number, p1::Number, p2::Number, lower_tail::Bool, log_p::Bool) = - ccall(dlsym(_jl_libRmath,$(string(qqsym))), Float64, (Float64,Float64,Float64,Int32,Int32), p, p1, p2, lower_tail, log_p) - ($qq){T<:Number}(p::AbstractArray{T}, p1::Number, p2::Number, lower_tail::Bool, log_p::Bool) = - reshape([ ($qq)(p[i], p1, p2, lower_tail, log_p) for i=1:numel(p) ], size(p)) - ($qq)(p::Number, p1::Number, lower_tail::Bool, log_p::Bool) = ($qq)(p, p1, $d2, lower_tail, log_p) - ($qq){T<:Number}(p::AbstractArray{T}, p1::Number, lower_tail::Bool, log_p::Bool) = ($qq)(p, p1, $d2, lower_tail, log_p) - ($qq)(p::Number, lower_tail::Bool, log_p::Bool) = ($qq)(p, $d1, $d2, lower_tail, log_p) - ($qq){T<:Number}(p::AbstractArray{T}, lower_tail::Bool, log_p::Bool) = ($qq)(p, $d1, $d2, lower_tail, log_p) - ($qq)(p::Number, p1::Number, p2::Number, lower_tail::Bool) = ($qq)(p, p1, p2, lower_tail, false) - ($qq){T<:Number}(p::AbstractArray{T}, p1::Number, p2::Number, lower_tail::Bool) = ($qq)(p, p1, p2, lower_tail, false) - ($qq)(p::Number, p1::Number, lower_tail::Bool) = ($qq)(p, p1, $d2, lower_tail, false) - ($qq){T<:Number}(p::AbstractArray{T}, p1::Number, lower_tail::Bool) = ($qq)(p, p1, $d2, lower_tail, false) - ($qq)(p::Number, lower_tail::Bool) = ($qq)(p, $d1, $d2, lower_tail, false) - ($qq){T<:Number}(p::AbstractArray{T}, lower_tail::Bool) = ($qq)(p, $d1, $d2, lower_tail, false) - ($qq)(p::Number, p1::Number, p2::Number) = ($qq)(p, p1, p2, true, false) - @_jl_libRmath_vectorize_3arg $qq - ($qq)(p::Number, p1::Number) = ($qq)(p, p1, $d2, true, false) - @vectorize_2arg Number $qq - ($qq)(p::Number) = ($qq)(p, $d1, $d2, true, false) - ($qq){T<:Number}(p::AbstractArray{T}) = ($qq)(p, $d1, $d2, true, false) - - ($rr)(nn::Integer, p1::Number, p2::Number) = - [ ccall(dlsym(_jl_libRmath,$(string(rr))), Float64, (Float64,Float64), p1, p2) for i=1:nn ] - ($rr)(nn::Integer, p1::Number) = ($rr)(nn, p1, $d2) - ($rr)(nn::Integer) = ($rr)(nn, $d1, $d2) - end -end - -@_jl_libRmath_2par_2d cauchy 0 1 # Cauchy distribution (location, scale) -@_jl_libRmath_2par_2d lnorm 0 1 # Log-normal distribution (meanlog, sdlog) -@_jl_libRmath_2par_2d logis 0 1 # Logistic distribution (location, scale) -@_jl_libRmath_2par_2d norm 0 1 # Normal (Gaussian) distribution (mu, sd) -@_jl_libRmath_2par_2d unif 0 1 # Uniform distribution (min, max) - -## Distributions with 3 parameters and no defaults -macro _jl_libRmath_3par_0d(base) - dd = symbol(strcat("d", string(base))) - pp = symbol(strcat("p", string(base))) - qq = symbol(strcat("q", string(base))) - rr = symbol(strcat("r", string(base))) - quote - global $dd, $pp, $qq, $rr - ($dd)(x::Number, p1::Number, p2::Number, p3::Number, give_log::Bool) = - ccall(dlsym(_jl_libRmath,$(string(dd))), Float64, (Float64,Float64,Float64,Float64,Int32), x, p1, p2, p3, give_log) - ($dd){T<:Number}(x::AbstractArray{T}, p1::Number, p2::Number, p3::Number, give_log::Bool) = - reshape([ ($dd)(x[i], p1, p2, p3, give_log) for i=1:numel(x) ], size(x)) - ($dd)(x::Number, p1::Number, p2::Number, p3::Number) = ($dd)(x, p1, p2, p3, false) - @_jl_libRmath_vectorize_4arg $dd - - ($pp)(q::Number, p1::Number, p2::Number, p3::Number, lower_tail::Bool, log_p::Bool) = - ccall(dlsym(_jl_libRmath,$(string(pp))), Float64, (Float64,Float64,Float64,Float64,Int32,Int32), q, p1, p2, p3, lower_tail, log_p) - ($pp){T<:Number}(q::AbstractArray{T}, p1::Number, p2::Number, p3::Number, lower_tail::Bool, log_p::Bool) = - reshape([ ($pp)(q[i], p1, p2, p3, lower_tail, log_p) for i=1:numel(q) ], size(q)) - ($pp)(q::Number, p1::Number, p2::Number, p3::Number, lower_tail::Bool) = ($pp)(q, p1, p2, p3, lower_tail, false) - ($pp){T<:Number}(q::AbstractArray{T}, p1::Number, p2::Number, p3::Number, lower_tail::Bool) = - reshape([ ($pp)(q[i], p1, p2, p3, lower_tail, false) for i=1:numel(q) ], size(q)) - ($pp)(q::Number, p1::Number, p2::Number, p3::Number) = ($pp)(q, p1, p2, p3, true, false) - @_jl_libRmath_vectorize_4arg $pp - - ($qq)(p::Number, p1::Number, p2::Number, p3::Number, lower_tail::Bool, log_p::Bool) = - ccall(dlsym(_jl_libRmath,$(string(qq))), Float64, (Float64,Float64,Float64,Float64,Int32,Int32), p, p1, p2, p3, lower_tail, log_p) - ($qq){T<:Number}(p::AbstractArray{T}, p1::Number, p2::Number, p3::Number, lower_tail::Bool, log_p::Bool) = - reshape([ ($qq)(p[i], p1, p2, p3, lower_tail, log_p) for i=1:numel(p) ], size(p)) - ($qq)(p::Number, p1::Number, p2::Number, p3::Number, lower_tail::Bool) = ($qq)(p, p1, p2, p3, lower_tail, false) - ($qq){T<:Number}(p::AbstractArray{T}, p1::Number, p2::Number, p3::Number, lower_tail::Bool) = - reshape([ ($qq)(p[i], p1, p2, p3, lower_tail, false) for i=1:numel(p) ], size(p)) - ($qq)(p::Number, p1::Number, p2::Number, p3::Number) = ($qq)(p, p1, p2, p3, true, false) - @_jl_libRmath_vectorize_4arg $qq - - ($rr)(nn::Integer, p1::Number, p2::Number, p3::Number) = - [ ccall(dlsym(_jl_libRmath,$(string(rr))), Float64, (Float64,Float64,Float64), p1, p2, p3) for i=1:nn ] - end -end - -@_jl_libRmath_3par_0d hyper # Hypergeometric (m, n, k) -@_jl_libRmath_3par_0d nbeta # Non-central beta (shape1, shape2, ncp) -@_jl_libRmath_3par_0d nf # Non-central F (df1, df2, ncp) - -## tukey (Studentized Range Distribution - p and q only - 3pars) -ptukey(q::Number, nmeans::Number, df::Number, nranges::Number, lower_tail::Bool, log_p::Bool) = - ccall(dlsym(_jl_libRmath, :ptukey), Float64, (Float64,Float64,Float64,Int32,Int32),q,nranges,nmeans,df,lower_tail,log_p) -ptukey(q::Number, nmeans::Number, df::Number, nranges::Number, lower_tail::Bool) = - ccall(dlsym(_jl_libRmath, :ptukey), Float64, (Float64,Float64,Float64,Int32,Int32),q,nranges,nmeans,df,lower_tail,false) -ptukey(q::Number, nmeans::Number, df::Number, nranges::Number) = - ccall(dlsym(_jl_libRmath, :ptukey), Float64, (Float64,Float64,Float64,Int32,Int32),q,nranges,nmeans,df,true,false) -ptukey{T<:Number}(q::AbstractArray{T}, nmeans::Number, df::Number, nranges::Number, lower_tail::Bool, log_p::Bool) = - reshape([ptukey(q[i],nmeans,df,nranges,lower_tail,log_p) for i=1:numel(q)], size(q)) -ptukey{T<:Number}(q::AbstractArray{T}, nmeans::Number, df::Number, nranges::Number, lower_tail::Bool) = - reshape([ptukey(q[i],nmeans,df,nranges,lower_tail,false) for i=1:numel(q)], size(q)) -ptukey{T<:Number}(q::AbstractArray{T}, nmeans::Number, df::Number, nranges::Number) = - reshape([ptukey(q[i],nmeans,df,nranges,true,false) for i=1:numel(q)], size(q)) - -## tukey (Studentized Range Distribution - p and q only - 3pars) -ptukey(q::Number, nmeans::Number, df::Number, nranges::Number, lower_tail::Bool, log_p::Bool) = - ccall(dlsym(_jl_libRmath, :ptukey), Float64, (Float64,Float64,Float64,Int32,Int32),q,nranges,nmeans,df,lower_tail,log_p) -ptukey(q::Number, nmeans::Number, df::Number, nranges::Number, lower_tail::Bool) = - ccall(dlsym(_jl_libRmath, :ptukey), Float64, (Float64,Float64,Float64,Int32,Int32),q,nranges,nmeans,df,lower_tail,false) -ptukey(q::Number, nmeans::Number, df::Number, nranges::Number) = - ccall(dlsym(_jl_libRmath, :ptukey), Float64, (Float64,Float64,Float64,Int32,Int32),q,nranges,nmeans,df,true,false) -ptukey(q::Number, nmeans::Number, df::Number, nranges::Number) = - ccall(dlsym(_jl_libRmath, :ptukey), Float64, (Float64,Float64,Float64,Int32,Int32),q,nranges,1.,df,true,false) -ptukey{T<:Number}(q::AbstractArray{T}, nmeans::Number, df::Number, nranges::Number, lower_tail::Bool, log_p::Bool) = - reshape([ptukey(q[i],nmeans,df,nranges,lower_tail,log_p) for i=1:numel(q)], size(q)) -ptukey{T<:Number}(q::AbstractArray{T}, nmeans::Number, df::Number, nranges::Number, lower_tail::Bool) = - reshape([ptukey(q[i],nmeans,df,nranges,lower_tail,false) for i=1:numel(q)], size(q)) -ptukey{T<:Number}(q::AbstractArray{T}, nmeans::Number, df::Number, nranges::Number) = - reshape([ptukey(q[i],nmeans,df,nranges,true,false) for i=1:numel(q)], size(q)) -ptukey{T<:Number}(q::AbstractArray{T}, nmeans::Number, df::Number) = - reshape([ptukey(q[i],nmeans,df,1.,true,false) for i=1:numel(q)], size(q)) - -qtukey(q::Number, nmeans::Number, df::Number, nranges::Number, lower_tail::Bool, log_p::Bool) = - ccall(dlsym(_jl_libRmath, :qtukey), Float64, (Float64,Float64,Float64,Int32,Int32),p,nranges,nmeans,df,lower_tail,log_p) -qtukey(p::Number, nmeans::Number, df::Number, nranges::Number, lower_tail::Bool) = - ccall(dlsym(_jl_libRmath, :qtukey), Float64, (Float64,Float64,Float64,Int32,Int32),p,nranges,nmeans,df,lower_tail,false) -qtukey(p::Number, nmeans::Number, df::Number, nranges::Number) = - ccall(dlsym(_jl_libRmath, :qtukey), Float64, (Float64,Float64,Float64,Int32,Int32),p,nranges,nmeans,df,true,false) -qtukey(p::Number, nmeans::Number, df::Number) = - ccall(dlsym(_jl_libRmath, :qtukey), Float64, (Float64,Float64,Float64,Int32,Int32),p,nranges,1.,df,true,false) -qtukey{T<:Number}(p::AbstractArray{T}, nmeans::Number, df::Number, nranges::Number, lower_tail::Bool, log_p::Bool) = - reshape([qtukey(p[i],nmeans,df,nranges,lower_tail,log_p) for i=1:numel(p)], size(p)) -qtukey{T<:Number}(p::AbstractArray{T}, nmeans::Number, df::Number, nranges::Number, lower_tail::Bool) = - reshape([qtukey(p[i],nmeans,df,nranges,lower_tail,false) for i=1:numel(p)], size(p)) -qtukey{T<:Number}(p::AbstractArray{T}, nmeans::Number, df::Number, nranges::Number) = - reshape([qtukey(p[i],nmeans,df,nranges,true,false) for i=1:numel(p)], size(p)) -qtukey{T<:Number}(p::AbstractArray{T}, nmeans::Number, df::Number) = - reshape([qtukey(p[i],nmeans,df,1.,true,false) for i=1:numel(p)], size(p)) diff --git a/extras/arpack.jl b/extras/arpack.jl deleted file mode 100644 index e834bf083158d..0000000000000 --- a/extras/arpack.jl +++ /dev/null @@ -1,259 +0,0 @@ -module ARPACK - -export eigs, svds - -libarpack = dlopen("libarpack") - -# For a dense matrix A is ignored and At is actually A'*A -_jl_sarupdate{T}(A::StridedMatrix{T}, At::StridedMatrix{T}, X::StridedVector{T}) = BLAS.symv('U', one(T), At, X) -_jl_sarupdate{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, At::SparseMatrixCSC{Tv,Ti}, X::StridedVector{Tv}) = At*(A*X) - -for (T, saupd, seupd, naupd, neupd) in - ((:Float64, :dsaupd_, :dseupd_, :dnaupd_, :dneupd_), - (:Float32, :ssaupd_, :sseupd_, :snaupd_, :sneupd_)) - @eval begin - function eigs(A::AbstractMatrix{$T}, nev::Integer, evtype::ASCIIString, rvec::Bool) - (m, n) = size(A) - if m != n error("eigs: matrix A is $m by $n but must be square") end - sym = issym(A) - if n <= nev nev = n - 1 end - - ncv = min(max(nev*2, 20), n) -# if ncv-nev < 2 || ncv > n error("Compute fewer eigenvalues using eigs(A, k)") end - - bmat = "I" - lworkl = sym ? ncv * (ncv + 8) : ncv * (3*ncv + 6) - - v = Array($T, n, ncv) - workd = Array($T, 3*n) - workl = Array($T, lworkl) - resid = Array($T, n) - select = Array(Int32, ncv) - iparam = zeros(Int32, 11) - ipntr = zeros(Int32, 14) - - tol = zeros($T, 1) - ido = zeros(Int32, 1) - info = zeros(Int32, 1) - - iparam[1] = int32(1) # ishifts - iparam[3] = int32(1000) # maxitr - iparam[7] = int32(1) # mode 1 - - zernm1 = 0:(n-1) - - while true - if sym - ccall(dlsym(libarpack, $(string(saupd))), Void, - (Ptr{Int32}, Ptr{Uint8}, Ptr{Int32}, Ptr{Uint8}, Ptr{Int32}, - Ptr{$T}, Ptr{$T}, Ptr{Int32}, Ptr{$T}, Ptr{Int32}, - Ptr{Int32}, Ptr{Int32}, Ptr{$T}, Ptr{$T}, Ptr{Int32}, Ptr{Int32}), - ido, bmat, &n, evtype, &nev, tol, resid, &ncv, v, &n, - iparam, ipntr, workd, workl, &lworkl, info) - else - ccall(dlsym(libarpack, $(string(naupd))), Void, - (Ptr{Int32}, Ptr{Uint8}, Ptr{Int32}, Ptr{Uint8}, Ptr{Int32}, - Ptr{$T}, Ptr{$T}, Ptr{Int32}, Ptr{$T}, Ptr{Int32}, - Ptr{Int32}, Ptr{Int32}, Ptr{$T}, Ptr{$T}, Ptr{Int32}, Ptr{Int32}), - ido, bmat, &n, evtype, &nev, tol, resid, &ncv, v, &n, - iparam, ipntr, workd, workl, &lworkl, info) - end - if info[1] != 0 error("error code $(info[1]) from ARPACK aupd") end - if (ido[1] != -1 && ido[1] != 1) break end - workd[ipntr[2]+zernm1] = A*ref(workd, ipntr[1]+zernm1) - end - - howmny = "A" - - if sym - d = Array($T, nev) - sigma = zeros($T, 1) - ccall(dlsym(libarpack, $(string(seupd))), Void, - (Ptr{Int32}, Ptr{Uint8}, Ptr{Int32}, Ptr{$T}, Ptr{$T}, Ptr{Int32}, - Ptr{$T}, Ptr{Uint8}, Ptr{Int32}, Ptr{Uint8}, Ptr{Int32}, - Ptr{$T}, Ptr{$T}, Ptr{Int32}, Ptr{$T}, Ptr{Int32}, Ptr{Int32}, - Ptr{Int32}, Ptr{$T}, Ptr{$T}, Ptr{Int32}, Ptr{Int32}), - &rvec, howmny, select, d, v, &n, sigma, - bmat, &n, evtype, &nev, tol, resid, &ncv, v, &n, - iparam, ipntr, workd, workl, &lworkl, info) - if info[1] != 0 error("error code $(info[1]) from ARPACK eupd") end - return rvec ? (d, v[1:n, 1:nev]) : d - end - dr = Array($T, nev+1) - di = Array($T, nev+1) - sigmar = zeros($T, 1) - sigmai = zeros($T, 1) - workev = Array($T, 3*ncv) - ccall(dlsym(libarpack, $(string(neupd))), Void, - (Ptr{Int32}, Ptr{Uint8}, Ptr{Int32}, Ptr{$T}, Ptr{$T}, Ptr{$T}, - Ptr{Int32}, Ptr{$T}, Ptr{$T}, Ptr{$T}, Ptr{Uint8}, Ptr{Int32}, - Ptr{Uint8}, Ptr{Int32}, Ptr{$T}, Ptr{$T}, Ptr{Int32}, Ptr{$T}, - Ptr{Int32}, Ptr{Int32}, Ptr{Int32}, Ptr{$T}, Ptr{$T}, - Ptr{Int32}, Ptr{Int32}), - &rvec, howmny, select, dr, di, v, &n, sigmar, sigmai, - workev, bmat, &n, evtype, &nev, tol, resid, &ncv, v, &n, - iparam, ipntr, workd, workl, &lworkl, info) - if info[1] != 0 error("error code $(info[1]) from ARPACK eupd") end - evec = complex(zeros($T, n, nev+1), zeros($T, n, nev+1)) - j = 1 - while j <= nev - if di[j] == 0.0 - evec[:,j] = v[:,j] - else - evec[:,j] = v[:,j] + im*v[:,j+1] - evec[:,j+1] = v[:,j] - im*v[:,j+1] - j += 1 - end - j += 1 - end - complex(dr[1:nev],di[1:nev]), evec[1:n, 1:nev] - end - end -end - -for (T, TR, naupd, neupd) in - ((:Complex128, :Float64, :znaupd_, :zneupd_), - (:Complex64, :Float32, :cnaupd_, :cneupd_)) - @eval begin - function eigs(A::AbstractMatrix{$T}, nev::Integer, evtype::ASCIIString, rvec::Bool) - (m, n) = size(A) - if m != n error("eigs: matrix A is $m by $n but must be square") end - if n <= nev nev = n - 1 end - - ncv = min(max(nev*2, 20), n) -# if ncv-nev < 2 || ncv > n error("Compute fewer eigenvalues using eigs(A, k)") end - - bmat = "I" - lworkl = ncv * (3*ncv + 5) - - v = Array($T, n, ncv) - workd = Array($T, 3*n) - workl = Array($T, lworkl) - rwork = Array($TR, ncv) - resid = Array($T, n) - select = Array(Int32, ncv) - iparam = zeros(Int32, 11) - ipntr = zeros(Int32, 14) - - tol = zeros($TR, 1) - ido = zeros(Int32, 1) - info = zeros(Int32, 1) - - iparam[1] = int32(1) # ishifts - iparam[3] = int32(1000) # maxitr - iparam[7] = int32(1) # mode 1 - - zernm1 = 0:(n-1) - - while true - ccall(dlsym(libarpack, $(string(naupd))), Void, - (Ptr{Int32}, Ptr{Uint8}, Ptr{Int32}, Ptr{Uint8}, Ptr{Int32}, - Ptr{$TR}, Ptr{$T}, Ptr{Int32}, Ptr{$T}, Ptr{Int32}, - Ptr{Int32}, Ptr{Int32}, Ptr{$T}, Ptr{$T}, Ptr{Int32}, - Ptr{$TR}, Ptr{Int32}), - ido, bmat, &n, evtype, &nev, tol, resid, &ncv, v, &n, - iparam, ipntr, workd, workl, &lworkl, rwork, info) - if info[1] != 0 error("error code $(info[1]) from ARPACK aupd") end - if (ido[1] != -1 && ido[1] != 1) break end - workd[ipntr[2]+zernm1] = A*ref(workd, ipntr[1]+zernm1) - end - - howmny = "A" - - d = Array($T, nev+1) - sigma = zeros($T, 1) - workev = Array($T, 2ncv) - ccall(dlsym(libarpack, $(string(neupd))), Void, - (Ptr{Int32}, Ptr{Uint8}, Ptr{Int32}, Ptr{$T}, Ptr{$T}, Ptr{Int32}, - Ptr{$T}, Ptr{$T}, Ptr{Uint8}, Ptr{Int32}, Ptr{Uint8}, Ptr{Int32}, - Ptr{$TR}, Ptr{$T}, Ptr{Int32}, Ptr{$T}, Ptr{Int32}, Ptr{Int32}, - Ptr{Int32}, Ptr{$T}, Ptr{$T}, Ptr{Int32}, Ptr{$TR}, Ptr{Int32}), - &rvec, howmny, select, d, v, &n, workev, sigma, - bmat, &n, evtype, &nev, tol, resid, &ncv, v, &n, - iparam, ipntr, workd, workl, &lworkl, rwork, info) - if info[1] != 0 error("error code $(info[1]) from ARPACK eupd") end - rvec ? (d, v[1:n, 1:nev]) : d - end - end -end - -eigs(A::AbstractMatrix, nev::Integer, typ::ASCIIString) = eigs(A, nev, which, true) -eigs(A::AbstractMatrix, nev::Integer, rvec::Bool) = eigs(A, nev, "LM", rvec) -eigs(A::AbstractMatrix, rvec::Bool) = eigs(A, 6, "LM", rvec) -eigs(A::AbstractMatrix, nev::Integer) = eigs(A, nev, "LM", true) -eigs(A::AbstractMatrix) = eigs(A, 6, "LM", true) - - -# For a dense matrix A is ignored and At is actually A'*A -_jl_sarupdate{T}(A::StridedMatrix{T}, At::StridedMatrix{T}, X::StridedVector{T}) = BLAS.symv('U', one(T), At, X) -_jl_sarupdate{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, At::SparseMatrixCSC{Tv,Ti}, X::StridedVector{Tv}) = At*(A*X) - -for (T, saupd, seupd) in ((:Float64, :dsaupd_, :dseupd_), (:Float32, :ssaupd_, :sseupd_)) - @eval begin - function svds(A::AbstractMatrix{$T}, nev::Integer, which::ASCIIString, rvec::Bool) - (m, n) = size(A) - if m < n error("m = $m, n = $n and only the m >= n case is implemented") end - if n <= nev nev = n - 1 end - - At = isa(A, StridedMatrix) ? BLAS.syrk('U','T',1.,A) : A' - - ncv = min(max(nev*2, 20), n) - lworkl = ncv*(ncv+8) - - v = Array($T, n, ncv) - workd = Array($T, 3n) - workl = Array($T, lworkl) - resid = Array($T, n) - select = Array(Int32, ncv) - iparam = zeros(Int32, 11) - iparam[1] = 1 # ishifts - iparam[3] = 1000 # maxitr - iparam[7] = 1 # mode 1 - ipntr = zeros(Int32, 14) - - tol = zeros($T, 1) - sigma = zeros($T, 1) - ido = zeros(Int32, 1) - info = Array(Int32, 1) - bmat = "I" - zernm1 = 0:(n-1) - - while true - ccall(dlsym(libarpack, $(string(saupd))), Void, - (Ptr{Int32}, Ptr{Uint8}, Ptr{Int32}, Ptr{Uint8}, Ptr{Int32}, - Ptr{$T}, Ptr{$T}, Ptr{Int32}, Ptr{$T}, Ptr{Int32}, - Ptr{Int32}, Ptr{Int32}, Ptr{$T}, Ptr{$T}, Ptr{Int32}, Ptr{Int32}), - ido, bmat, &n, which, &nev, tol, resid, &ncv, v, &n, - iparam, ipntr, workd, workl, &lworkl, info) - if (info[1] < 0) error("error code $(info[1]) from ARPACK saupd") end - if (ido[1] != -1 && ido[1] != 1) break end - workd[ipntr[2]+zernm1] = _jl_sarupdate(A, At, ref(workd, ipntr[1]+zernm1)) - end - - d = Array($T, nev) - howmny = "A" - - ccall(dlsym(libarpack, $(string(seupd))), Void, - (Ptr{Int32}, Ptr{Uint8}, Ptr{Int32}, Ptr{$T}, Ptr{$T}, Ptr{Int32}, Ptr{$T}, - Ptr{Uint8}, Ptr{Int32}, Ptr{Uint8}, Ptr{Int32}, - Ptr{$T}, Ptr{$T}, Ptr{Int32}, Ptr{$T}, Ptr{Int32}, Ptr{Int32}, - Ptr{Int32}, Ptr{$T}, Ptr{$T}, Ptr{Int32}, Ptr{Int32}), - &rvec, howmny, select, d, v, &n, sigma, - bmat, &n, which, &nev, tol, resid, &ncv, v, &n, - iparam, ipntr, workd, workl, &lworkl, info) - if info[1] != 0 error("error code $(info[1]) from ARPACK eupd") end - d = sqrt(d) - if !rvec return d end - v = v[1:n, 1:nev] - A*v*diagm(1./d), d, v.' - end - end -end - -svds(A::AbstractMatrix, nev::Integer, which::ASCIIString) = svds(A, nev, which, true) -svds(A::AbstractMatrix, nev::Integer, rvec::Bool) = svds(A, nev, "LA", rvec) -svds(A::AbstractMatrix, rvec::Bool) = svds(A, 6, "LA", rvec) -svds(A::AbstractMatrix, nev::Integer) = svds(A, nev, "LA", true) -svds(A::AbstractMatrix) = svds(A, 6, "LA", true) - -end #module ARPACK diff --git a/extras/bigfloat.jl b/extras/bigfloat.jl deleted file mode 100644 index 28554ad29f0bf..0000000000000 --- a/extras/bigfloat.jl +++ /dev/null @@ -1,158 +0,0 @@ -import Base.convert, Base.promote_rule, Base.+, Base.-, Base.*, Base./ -import Base.isnan, Base.isinf, Base.^, Base.cmp, Base.sqrt -import Base.==, Base.<=, Base.>=, Base.<, Base.>, Base.string, Base.show -import Base.showcompact - -_jl_libgmp_wrapper = dlopen("libgmp_wrapper") - -require("bigint") - -type BigFloat <: FloatingPoint - mpf::Ptr{Void} - - function BigFloat(x::String) - z = _jl_BigFloat_init() - ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpf_set_string), Void, (Ptr{Void}, Ptr{Uint8}), z, bytestring(x)) - b = new(z) - finalizer(b, _jl_BigFloat_clear) - b - end - - function BigFloat(x::Float64) - z = _jl_BigFloat_init() - ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpf_set_d), Void, (Ptr{Void}, Float64), z, x) - b = new(z) - finalizer(b, _jl_BigFloat_clear) - b - end - - function BigFloat(x::Uint) - z = _jl_BigFloat_init() - ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpf_set_ui), Void, (Ptr{Void}, Uint), z, x) - b = new(z) - finalizer(b, _jl_BigFloat_clear) - b - end - - function BigFloat(x::Int) - z = _jl_BigFloat_init() - ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpf_set_si), Void, (Ptr{Void}, Int), z, x) - b = new(z) - finalizer(b, _jl_BigFloat_clear) - b - end - - function BigFloat(x::BigInt) - z = _jl_BigFloat_init() - ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpf_set_z), Void, (Ptr{Void}, Ptr{Void}), z, x.mpz) - b = new(z) - finalizer(b, _jl_BigFloat_clear) - b - end - - function BigFloat(z::Ptr{Void}) - b = new(z) - finalizer(b, _jl_BigFloat_clear) - b - end -end - -convert(::Type{BigFloat}, x::Int8) = BigFloat(int(x)) -convert(::Type{BigFloat}, x::Int16) = BigFloat(int(x)) -convert(::Type{BigFloat}, x::Int) = BigFloat(x) -if WORD_SIZE == 64 - convert(::Type{BigFloat}, x::Int32) = BigFloat(int(x)) - convert(::Type{BigFloat}, x::Uint32) = BigFloat(int(x)) -else - convert(::Type{BigFloat}, x::Int64) = BigFloat(string(x)) - convert(::Type{BigFloat}, x::Uint64) = BigFloat(string(x)) -end -convert(::Type{BigFloat}, x::Uint8) = BigFloat(int(x)) -convert(::Type{BigFloat}, x::Uint16) = BigFloat(int(x)) -convert(::Type{BigFloat}, x::Float64) = BigFloat(x) -convert(::Type{BigFloat}, x::Float32) = BigFloat(float64(x)) - -promote_rule(::Type{BigFloat}, ::Type{Float32}) = BigFloat -promote_rule(::Type{BigFloat}, ::Type{Float64}) = BigFloat -promote_rule(::Type{BigFloat}, ::Type{Int8}) = BigFloat -promote_rule(::Type{BigFloat}, ::Type{Int16}) = BigFloat -promote_rule(::Type{BigFloat}, ::Type{Int32}) = BigFloat -promote_rule(::Type{BigFloat}, ::Type{Int64}) = BigFloat -promote_rule(::Type{BigFloat}, ::Type{Uint8}) = BigFloat -promote_rule(::Type{BigFloat}, ::Type{Uint16}) = BigFloat -promote_rule(::Type{BigFloat}, ::Type{Uint32}) = BigFloat -promote_rule(::Type{BigFloat}, ::Type{Uint64}) = BigFloat - -# mpf doesn't have inf or nan -isnan(x::BigFloat) = false -isinf(x::BigFloat) = false - -function +(x::BigFloat, y::BigFloat) - z= _jl_BigFloat_init() - ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpf_add), Void, (Ptr{Void}, Ptr{Void}, Ptr{Void}), z, x.mpf, y.mpf) - BigFloat(z) -end - -function -(x::BigFloat) - z= _jl_BigFloat_init() - ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpf_neg), Void, (Ptr{Void}, Ptr{Void}), z, x.mpf) - BigFloat(z) -end - -function -(x::BigFloat, y::BigFloat) - z= _jl_BigFloat_init() - ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpf_sub), Void, (Ptr{Void}, Ptr{Void}, Ptr{Void}), z, x.mpf, y.mpf) - BigFloat(z) -end - -function *(x::BigFloat, y::BigFloat) - z= _jl_BigFloat_init() - ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpf_mul), Void, (Ptr{Void}, Ptr{Void}, Ptr{Void}), z, x.mpf, y.mpf) - BigFloat(z) -end - -function /(x::BigFloat, y::BigFloat) - z= _jl_BigFloat_init() - ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpf_div), Void, (Ptr{Void}, Ptr{Void}, Ptr{Void}), z, x.mpf, y.mpf) - BigFloat(z) -end - -function cmp(x::BigFloat, y::BigFloat) - ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpf_cmp), Int32, (Ptr{Void}, Ptr{Void}), x.mpf, y.mpf) -end - -function sqrt(x::BigFloat) - z = _jl_BigFloat_init() - ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpf_sqrt), Void, (Ptr{Void}, Ptr{Void}), z, x.mpf) - BigFloat(z) -end - -function ^(x::BigFloat, y::Uint) - z = _jl_BigFloat_init() - ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpf_pow_ui), Void, (Ptr{Void}, Ptr{Void}, Uint), z, x.mpf, y) - BigFloat(z) -end - -==(x::BigFloat, y::BigFloat) = cmp(x,y) == 0 -<=(x::BigFloat, y::BigFloat) = cmp(x,y) <= 0 ->=(x::BigFloat, y::BigFloat) = cmp(x,y) >= 0 -<(x::BigFloat, y::BigFloat) = cmp(x,y) < 0 ->(x::BigFloat, y::BigFloat) = cmp(x,y) > 0 - -function string(x::BigFloat) - s=ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpf_printf), Ptr{Uint8}, (Ptr{Void},), x.mpf) - ret = bytestring(s) #This copies s. - ccall(dlsym(_jl_libgmp_wrapper,:_jl_gmp_free), Void, (Ptr{Void},), s) - ret -end - -show(io, b::BigFloat) = print(io, string(b)) -showcompact(io, b::BigFloat) = print(io, string(b)) - -function _jl_BigFloat_clear(x::BigFloat) - ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpf_clear), Void, (Ptr{Void},), x.mpf) -end - -function _jl_BigFloat_init() - return ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpf_init), Ptr{Void}, ()) -end diff --git a/extras/bigint.jl b/extras/bigint.jl deleted file mode 100644 index 8d780571f7983..0000000000000 --- a/extras/bigint.jl +++ /dev/null @@ -1,211 +0,0 @@ -import Base.convert, Base.promote_rule, Base.+, Base.-, Base.*, Base.<< -import Base.^, Base.div, Base.rem, Base.cmp, Base.sqrt -import Base.gcd, Base.gcdx, Base.factorial, Base.binomial -import Base.==, Base.<=, Base.>=, Base.<, Base.>, Base.string, Base.show - -_jl_libgmp_wrapper = dlopen("libgmp_wrapper") - -type BigInt <: Integer - mpz::Ptr{Void} - - function BigInt(x::String) - z = _jl_bigint_init() - ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpz_set_string), Void, (Ptr{Void}, Ptr{Uint8}),z,bytestring(x)) - b = new(z) - finalizer(b, _jl_bigint_clear) - b - end - - function BigInt(x::Int) - z = _jl_bigint_init() - ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpz_set_si), Void, (Ptr{Void}, Int),z,x) - b = new(z) - finalizer(b, _jl_bigint_clear) - b - end - BigInt{T<:Signed}(x::T) = BigInt(int(x)) - BigInt(x::Int128) = BigInt(string(x)) - - function BigInt(x::Uint) - z = _jl_bigint_init() - ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpz_set_ui), Void, - (Ptr{Void}, Uint), z, x) - b = new(z) - finalizer(b, _jl_bigint_clear) - b - end - BigInt{T<:Unsigned}(x::T) = BigInt(uint(x)) - BigInt(x::Uint128) = BigInt(string(x)) - - function BigInt(z::Ptr{Void}) - b = new(z) - finalizer(b, _jl_bigint_clear) - b - end -end - -convert(::Type{BigInt}, x::Int8) = BigInt(int(x)) -convert(::Type{BigInt}, x::Int16) = BigInt(int(x)) -convert(::Type{BigInt}, x::Int) = BigInt(x) - -convert(::Type{BigInt}, x::Uint8) = BigInt(uint(x)) -convert(::Type{BigInt}, x::Uint16) = BigInt(uint(x)) -convert(::Type{BigInt}, x::Uint) = BigInt(x) - -if WORD_SIZE == 64 - convert(::Type{BigInt}, x::Int32) = BigInt(int(x)) - convert(::Type{BigInt}, x::Uint32) = BigInt(uint(x)) -else - BigInt(l::Int64) = BigInt(string(l)) - BigInt(l::Uint64) = BigInt(string(l)) - convert(::Type{BigInt}, x::Int64) = BigInt(string(x)) - convert(::Type{BigInt}, x::Uint64) = BigInt(string(x)) -end - -convert(::Type{Int}, n::BigInt) = - ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpz_get_si), Int, (Ptr{Void},), n.mpz) - -convert(::Type{Uint}, n::BigInt) = - ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpz_get_ui), Uint, (Ptr{Void},), n.mpz) - -promote_rule(::Type{BigInt}, ::Type{Int8}) = BigInt -promote_rule(::Type{BigInt}, ::Type{Int16}) = BigInt -promote_rule(::Type{BigInt}, ::Type{Int32}) = BigInt -promote_rule(::Type{BigInt}, ::Type{Int64}) = BigInt -promote_rule(::Type{BigInt}, ::Type{Int128}) = BigInt - -promote_rule(::Type{BigInt}, ::Type{Uint8}) = BigInt -promote_rule(::Type{BigInt}, ::Type{Uint16}) = BigInt -promote_rule(::Type{BigInt}, ::Type{Uint32}) = BigInt -promote_rule(::Type{BigInt}, ::Type{Uint64}) = BigInt -promote_rule(::Type{BigInt}, ::Type{Uint128}) = BigInt - -function +(x::BigInt, y::BigInt) - z= _jl_bigint_init() - ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpz_add), Void, (Ptr{Void}, Ptr{Void}, Ptr{Void}),z,x.mpz,y.mpz) - BigInt(z) -end - -function -(x::BigInt) - z= _jl_bigint_init() - ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpz_neg), Void, (Ptr{Void}, Ptr{Void}),z,x.mpz) - BigInt(z) -end - -function -(x::BigInt, y::BigInt) - z= _jl_bigint_init() - ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpz_sub), Void, (Ptr{Void}, Ptr{Void}, Ptr{Void}),z,x.mpz,y.mpz) - BigInt(z) -end - -function *(x::BigInt, y::BigInt) - z= _jl_bigint_init() - ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpz_mul), Void, (Ptr{Void}, Ptr{Void}, Ptr{Void}),z,x.mpz,y.mpz) - BigInt(z) -end - -function <<(x::BigInt, c::Uint) - z= _jl_bigint_init() - ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpz_lshift), Void, (Ptr{Void}, Ptr{Void}, Uint), z, x.mpz, c) - BigInt(z) -end -<<(x::BigInt, c::Int32) = c<0 ? throw(DomainError()) : x<=(x::BigInt, y::BigInt) = cmp(x,y) >= 0 -<(x::BigInt, y::BigInt) = cmp(x,y) < 0 ->(x::BigInt, y::BigInt) = cmp(x,y) > 0 - -function string(x::BigInt) - s=ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpz_printf), Ptr{Uint8}, (Ptr{Void},),x.mpz) - ret = bytestring(s) #This copies s. - ccall(dlsym(_jl_libgmp_wrapper,:_jl_gmp_free), Void, (Ptr{Void},), s) - ret -end - -function show(io, x::BigInt) - print(io, string(x)) -end - -function _jl_bigint_clear(x::BigInt) - ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpz_clear), Void, (Ptr{Void},),x.mpz) -end - -function _jl_bigint_init() - return ccall(dlsym(_jl_libgmp_wrapper, :_jl_mpz_init), Ptr{Void}, ()) -end diff --git a/extras/cpp.jl b/extras/cpp.jl deleted file mode 100644 index 1f728862b8bda..0000000000000 --- a/extras/cpp.jl +++ /dev/null @@ -1,61 +0,0 @@ -# Allow calling of functions in C++ shared libraries. -# Usage: a = @cpp ccall(dlsym(mylib,:mysymbol),...) -macro cpp(ex) - # If you get "undefined symbol" errors, use nm or readelf to view - # the names of the symbols in the library. Then use the resulting - # information to help improve this macro! - # Note: for global objects without class or namespace qualifiers - # (e.g., global consts), you do not need to use this macro (it - # will work with a plain ccall, even though it is a C++ library) - msg = "@cpp requires a ccall(dlsym(mylib,:mysymbol),...) expression" - if !isa(ex,Expr) || ex.head != :ccall - error(msg) - end - # Parse the library symbol's name - extmp = ex.args[1] - if isa(extmp,Expr) && extmp.head == :call && extmp.args[1] == :dlsym - sym = extmp.args[3] - else - error(msg) - end - fstr = string(sym) - fstr = fstr[2:end] # strip the : - #GNU3-4 ABI - fstr = string("_Z",strlen(fstr),fstr) - # Parse the arguments to ccall and construct the parameter type string - extmp = ex.args[3] - if extmp.head != :tuple - error(msg) - end - exargs = extmp.args - pstr = "" - symtable = (:Void,:Bool,:Cchar,:Char,:ASCIIString,:Int,:Int8,:Uint8,:Int16,:Uint16,:Int32,:Uint32,:Int64,:Uint64,:Float32,:Float64) - # GNU3-4 ABI v.3 and v.4 - ptable = ('v','b','c','w',"Pc",'i','a','h','s','t','i','j','l','m','f','d') - for iarg = 1:length(exargs) - thisarg = exargs[iarg] - if isa(thisarg,Expr) && thisarg.head == :curly && thisarg.args[1] == :Ptr - pstr = string(pstr,'P') - thisarg = thisarg.args[2] - end - matched = false - for isym = 1:length(symtable) - if thisarg == symtable[isym] - matched = true - pstr = string(pstr,ptable[isym]) - # Cchar is a special notation just for name mangling, - # convert back to :Int8 - if thisarg == :Cchar - ex.args[3].args[iarg] = :Int8 - end - break - end - end - if !matched - println(thisarg) - error("Argument not recognized") - end - end - ex.args[1].args[3] = strcat(fstr,pstr) - ex -end diff --git a/extras/dcm_dict.jl b/extras/dcm_dict.jl deleted file mode 100644 index b0b370118b8ca..0000000000000 --- a/extras/dcm_dict.jl +++ /dev/null @@ -1,1952 +0,0 @@ -_dcmdict_data_ = -{{{8, 5}, "Specific Character Set", "CS", "1-n"}, -{{8, 8}, "Image Type", "CS", "1-n"}, -{{8, 18}, "Instance Creation Date", "DA", "1"}, -{{8, 19}, "Instance Creation Time", "TM", "1"}, -{{8, 20}, "Instance Creator UID", "UI", "1"}, -{{8, 22}, "SOP Class UID", "UI", "1"}, -{{8, 24}, "SOP Instance UID", "UI", "1"}, -{{8, 26}, "Related General SOP Class UID", "UI", "1-n"}, -{{8, 27}, "Original Specialized SOP Class UID", "UI", "1"}, -{{8, 32}, "Study Date", "DA", "1"}, -{{8, 33}, "Series Date", "DA", "1"}, -{{8, 34}, "Acquisition Date", "DA", "1"}, -{{8, 35}, "Content Date", "DA", "1"}, -{{8, 36}, "Overlay Date", "DA", "1"}, -{{8, 37}, "Curve Date", "DA", "1"}, -{{8, 42}, "Acquisition Datetime", "DT", "1"}, -{{8, 48}, "Study Time", "TM", "1"}, -{{8, 49}, "Series Time", "TM", "1"}, -{{8, 50}, "Acquisition Time", "TM", "1"}, -{{8, 51}, "Content Time", "TM", "1"}, -{{8, 52}, "Overlay Time", "TM", "1"}, -{{8, 53}, "Curve Time", "TM", "1"}, -{{8, 80}, "Accession Number", "SH", "1"}, -{{8, 82}, "Query/Retrieve Level", "CS", "1"}, -{{8, 84}, "Retrieve AE Title", "AE", "1-n"}, -{{8, 86}, "Instance Availability", "CS", "1"}, -{{8, 88}, "Failed SOP Instance UID List", "UI", "1-n"}, -{{8, 96}, "Modality", "CS", "1"}, -{{8, 97}, "Modalities in Study", "CS", "1-n"}, -{{8, 98}, "SOP Classes in Study", "UI", "1-n"}, -{{8, 100}, "Conversion Type", "CS", "1"}, -{{8, 104}, "Presentation Intent Type", "CS", "1"}, -{{8, 112}, "Manufacturer", "LO", "1"}, -{{8, 128}, "Institution Name", "LO", "1"}, -{{8, 129}, "Institution Address", "ST", "1"}, -{{8, 130}, "Institution Code Sequence", "SQ", "1"}, -{{8, 144}, "Referring Physician's Name", "PN", "1"}, -{{8, 146}, "Referring Physician's Address", "ST", "1"}, -{{8, 148}, "Referring Physician's Telephone Numbers", "SH", "1-n"}, -{{8, 150}, "Referring Physician Identification Sequence", "SQ", "1"}, -{{8, 256}, "Code Value", "SH", "1"}, -{{8, 258}, "Coding Scheme Designator", "SH", "1"}, -{{8, 259}, "Coding Scheme Version", "SH", "1"}, -{{8, 260}, "Code Meaning", "LO", "1"}, -{{8, 261}, "Mapping Resource", "CS", "1"}, -{{8, 262}, "Context Group Version", "DT", "1"}, -{{8, 263}, "Context Group Local Version", "DT", "1"}, -{{8, 267}, "Context Group Extension Flag", "CS", "1"}, -{{8, 268}, "Coding Scheme UID", "UI", "1"}, -{{8, 269}, "Context Group Extension Creator UID", "UI", "1"}, -{{8, 271}, "Context Identifier", "CS", "1"}, -{{8, 272}, "Coding Scheme Identification Sequence", "SQ", "1"}, -{{8, 274}, "Coding Scheme Registry", "LO", "1"}, -{{8, 276}, "Coding Scheme External ID", "ST", "1"}, -{{8, 277}, "Coding Scheme Name", "ST", "1"}, -{{8, 278}, "Responsible Organization", "ST", "1"}, -{{8, 513}, "Timezone Offset From UTC", "SH", "1"}, -{{8, 4112}, "Station Name", "SH", "1"}, -{{8, 4144}, "Study Description", "LO", "1"}, -{{8, 4146}, "Procedure Code Sequence", "SQ", "1"}, -{{8, 4158}, "Series Description", "LO", "1"}, -{{8, 4160}, "Institutional Department Name", "LO", "1"}, -{{8, 4168}, "Physician(s) of Record", "PN", "1-n"}, -{{8, 4169}, "Physician(s) of Record Identification Sequence", "SQ", "1"}, -{{8, 4176}, "Performing Physician's Name", "PN", "1-n"}, -{{8, 4178}, "Performing Physician Identification Sequence", "SQ", "1"}, -{{8, 4192}, "Name of Physician(s) Reading Study", "PN", "1-n"}, -{{8, 4194}, "Physician(s) Reading Study Identification Sequence", "SQ", "1"}, -{{8, 4208}, "Operators' Name", "PN", "1-n"}, -{{8, 4210}, "Operator Identification Sequence", "SQ", "1"}, -{{8, 4224}, "Admitting Diagnoses Description", "LO", "1-n"}, -{{8, 4228}, "Admitting Diagnoses Code Sequence", "SQ", "1"}, -{{8, 4240}, "Manufacturer's Model Name", "LO", "1"}, -{{8, 4352}, "Referenced Results Sequence", "SQ", "1"}, -{{8, 4368}, "Referenced Study Sequence", "SQ", "1"}, -{{8, 4369}, "Referenced Performed Procedure Step Sequence", "SQ", "1"}, -{{8, 4373}, "Referenced Series Sequence", "SQ", "1"}, -{{8, 4384}, "Referenced Patient Sequence", "SQ", "1"}, -{{8, 4389}, "Referenced Visit Sequence", "SQ", "1"}, -{{8, 4400}, "Referenced Overlay Sequence", "SQ", "1"}, -{{8, 4410}, "Referenced Waveform Sequence", "SQ", "1"}, -{{8, 4416}, "Referenced Image Sequence", "SQ", "1"}, -{{8, 4421}, "Referenced Curve Sequence", "SQ", "1"}, -{{8, 4426}, "Referenced Instance Sequence", "SQ", "1"}, -{{8, 4432}, "Referenced SOP Class UID", "UI", "1"}, -{{8, 4437}, "Referenced SOP Instance UID", "UI", "1"}, -{{8, 4442}, "SOP Classes Supported", "UI", "1-n"}, -{{8, 4448}, "Referenced Frame Number", "IS", "1-n"}, -{{8, 4501}, "Transaction UID", "UI", "1"}, -{{8, 4503}, "Failure Reason", "US", "1"}, -{{8, 4504}, "Failed SOP Sequence", "SQ", "1"}, -{{8, 4505}, "Referenced SOP Sequence", "SQ", "1"}, -{{8, 4608}, "Studies Containing Other Referenced Instances Sequence", "SQ", "1"}, -{{8, 4688}, "Related Series Sequence", "SQ", "1"}, -{{8, 8464}, "Lossy Image Compression", "CS", "1"}, -{{8, 8465}, "Derivation Description", "ST", "1"}, -{{8, 8466}, "Source Image Sequence", "SQ", "1"}, -{{8, 8480}, "Stage Name", "SH", "1"}, -{{8, 8482}, "Stage Number", "IS", "1"}, -{{8, 8484}, "Number of Stages", "IS", "1"}, -{{8, 8487}, "View Name", "SH", "1"}, -{{8, 8488}, "View Number", "IS", "1"}, -{{8, 8489}, "Number of Event Timers", "IS", "1"}, -{{8, 8490}, "Number of Views in Stage", "IS", "1"}, -{{8, 8496}, "Event Elapsed Time(s)", "DS", "1-n"}, -{{8, 8498}, "Event Timer Name(s)", "LO", "1-n"}, -{{8, 8514}, "Start Trim", "IS", "1"}, -{{8, 8515}, "Stop Trim", "IS", "1"}, -{{8, 8516}, "Recommended Display Frame Rate", "IS", "1"}, -{{8, 8728}, "Anatomic Region Sequence", "SQ", "1"}, -{{8, 8736}, "Anatomic Region Modifier Sequence", "SQ", "1"}, -{{8, 8744}, "Primary Anatomic Structure Sequence", "SQ", "1"}, -{{8, 8745}, "Anatomic Structure, Space or Region Sequence", "SQ", "1"}, -{{8, 8752}, "Primary Anatomic Structure Modifier Sequence", "SQ", "1"}, -{{8, 8768}, "Transducer Position Sequence", "SQ", "1"}, -{{8, 8770}, "Transducer Position Modifier Sequence", "SQ", "1"}, -{{8, 8772}, "Transducer Orientation Sequence", "SQ", "1"}, -{{8, 8774}, "Transducer Orientation Modifier Sequence", "SQ", "1"}, -{{8, 12289}, "Alternate Representation Sequence", "SQ", "1"}, -{{8, 36871}, "Frame Type", "CS", "4"}, -{{8, 37010}, "Referenced Image Evidence Sequence", "SQ", "1"}, -{{8, 37153}, "Referenced Raw Data Sequence", "SQ", "1"}, -{{8, 37155}, "Creator-Version UID", "UI", "1"}, -{{8, 37156}, "Derivation Image Sequence", "SQ", "1"}, -{{8, 37204}, "Source Image Evidence Sequence", "SQ", "1"}, -{{8, 37381}, "Pixel Presentation", "CS", "1"}, -{{8, 37382}, "Volumetric Properties", "CS", "1"}, -{{8, 37383}, "Volume Based Calculation Technique", "CS", "1"}, -{{8, 37384}, "Complex Image Component", "CS", "1"}, -{{8, 37385}, "Acquisition Contrast", "CS", "1"}, -{{8, 37397}, "Derivation Code Sequence", "SQ", "1"}, -{{8, 37431}, "Referenced Grayscale Presentation State Sequence", "SQ", "1"}, -{{16, 16}, "Patient's Name", "PN", "1"}, -{{16, 32}, "Patient ID", "LO", "1"}, -{{16, 33}, "Issuer of Patient ID", "LO", "1"}, -{{16, 48}, "Patient's Birth Date", "DA", "1"}, -{{16, 50}, "Patient's Birth Time", "TM", "1"}, -{{16, 64}, "Patient's Sex", "CS", "1"}, -{{16, 80}, "Patient's Insurance Plan Code Sequence", "SQ", "1"}, -{{16, 257}, "Patient's Primary Language Code Sequence", "SQ", "1"}, -{{16, 258}, "Patient's Primary Language Code Modifier Sequence", "SQ", "1"}, -{{16, 4096}, "Other Patient IDs", "LO", "1-n"}, -{{16, 4097}, "Other Patient Names", "PN", "1-n"}, -{{16, 4101}, "Patient's Birth Name", "PN", "1"}, -{{16, 4112}, "Patient's Age", "AS", "1"}, -{{16, 4128}, "Patient's Size", "DS", "1"}, -{{16, 4144}, "Patient's Weight", "DS", "1"}, -{{16, 4160}, "Patient's Address", "LO", "1"}, -{{16, 4192}, "Patient's Mother's Birth Name", "PN", "1"}, -{{16, 4224}, "Military Rank", "LO", "1"}, -{{16, 4225}, "Branch of Service", "LO", "1"}, -{{16, 4240}, "Medical Record Locator", "LO", "1"}, -{{16, 8192}, "Medical Alerts", "LO", "1-n"}, -{{16, 8464}, "Contrast Allergies", "LO", "1-n"}, -{{16, 8528}, "Country of Residence", "LO", "1"}, -{{16, 8530}, "Region of Residence", "LO", "1"}, -{{16, 8532}, "Patient's Telephone Numbers", "SH", "1-n"}, -{{16, 8544}, "Ethnic Group", "SH", "1"}, -{{16, 8576}, "Occupation", "SH", "1"}, -{{16, 8608}, "Smoking Status", "CS", "1"}, -{{16, 8624}, "Additional Patient History", "LT", "1"}, -{{16, 8640}, "Pregnancy Status", "US", "1"}, -{{16, 8656}, "Last Menstrual Date", "DA", "1"}, -{{16, 8688}, "Patient's Religious Preference", "LO", "1"}, -{{16, 16384}, "Patient Comments", "LT", "1"}, -{{18, 16}, "Clinical Trial Sponsor Name", "LO", "1"}, -{{18, 32}, "Clinical Trial Protocol ID", "LO", "1"}, -{{18, 33}, "Clinical Trial Protocol Name", "LO", "1"}, -{{18, 48}, "Clinical Trial Site ID", "LO", "1"}, -{{18, 49}, "Clinical Trial Site Name", "LO", "1"}, -{{18, 64}, "Clinical Trial Subject ID", "LO", "1"}, -{{18, 66}, "Clinical Trial Subject Reading ID", "LO", "1"}, -{{18, 80}, "Clinical Trial Time Point ID", "LO", "1"}, -{{18, 81}, "Clinical Trial Time Point Description", "ST", "1"}, -{{18, 96}, "Clinical Trial Coordinating Center Name", "LO", "1"}, -{{24, 16}, "Contrast/Bolus Agent", "LO", "1"}, -{{24, 18}, "Contrast/Bolus Agent Sequence", "SQ", "1"}, -{{24, 20}, "Contrast/Bolus Administration Route Sequence", "SQ", "1"}, -{{24, 21}, "Body Part Examined", "CS", "1"}, -{{24, 32}, "Scanning Sequence", "CS", "1-n"}, -{{24, 33}, "Sequence Variant", "CS", "1-n"}, -{{24, 34}, "Scan Options", "CS", "1-n"}, -{{24, 35}, "MR Acquisition Type", "CS", "1"}, -{{24, 36}, "Sequence Name", "SH", "1"}, -{{24, 37}, "Angio Flag", "CS", "1"}, -{{24, 38}, "Intervention Drug Information Sequence", "SQ", "1"}, -{{24, 39}, "Intervention Drug Stop Time", "TM", "1"}, -{{24, 40}, "Intervention Drug Dose", "DS", "1"}, -{{24, 41}, "Intervention Drug Sequence", "SQ", "1"}, -{{24, 42}, "Additional Drug Sequence", "SQ", "1"}, -{{24, 49}, "Radiopharmaceutical", "LO", "1"}, -{{24, 52}, "Intervention Drug Name", "LO", "1"}, -{{24, 53}, "Intervention Drug Start Time", "TM", "1"}, -{{24, 54}, "Intervention Sequence", "SQ", "1"}, -{{24, 56}, "Intervention Status", "CS", "1"}, -{{24, 58}, "Intervention Description", "ST", "1"}, -{{24, 64}, "Cine Rate", "IS", "1"}, -{{24, 80}, "Slice Thickness", "DS", "1"}, -{{24, 96}, "KVP", "DS", "1"}, -{{24, 112}, "Counts Accumulated", "IS", "1"}, -{{24, 113}, "Acquisition Termination Condition", "CS", "1"}, -{{24, 114}, "Effective Duration", "DS", "1"}, -{{24, 115}, "Acquisition Start Condition", "CS", "1"}, -{{24, 116}, "Acquisition Start Condition Data", "IS", "1"}, -{{24, 117}, "Acquisition Termination Condition Data", "IS", "1"}, -{{24, 128}, "Repetition Time", "DS", "1"}, -{{24, 129}, "Echo Time", "DS", "1"}, -{{24, 130}, "Inversion Time", "DS", "1"}, -{{24, 131}, "Number of Averages", "DS", "1"}, -{{24, 132}, "Imaging Frequency", "DS", "1"}, -{{24, 133}, "Imaged Nucleus", "SH", "1"}, -{{24, 134}, "Echo Number(s)", "IS", "1-n"}, -{{24, 135}, "Magnetic Field Strength", "DS", "1"}, -{{24, 136}, "Spacing Between Slices", "DS", "1"}, -{{24, 137}, "Number of Phase Encoding Steps", "IS", "1"}, -{{24, 144}, "Data Collection Diameter", "DS", "1"}, -{{24, 145}, "Echo Train Length", "IS", "1"}, -{{24, 147}, "Percent Sampling", "DS", "1"}, -{{24, 148}, "Percent Phase Field of View", "DS", "1"}, -{{24, 149}, "Pixel Bandwidth", "DS", "1"}, -{{24, 4096}, "Device Serial Number", "LO", "1"}, -{{24, 4100}, "Plate ID", "LO", "1"}, -{{24, 4112}, "Secondary Capture Device ID", "LO", "1"}, -{{24, 4113}, "Hardcopy Creation Device ID", "LO", "1"}, -{{24, 4114}, "Date of Secondary Capture", "DA", "1"}, -{{24, 4116}, "Time of Secondary Capture", "TM", "1"}, -{{24, 4118}, "Secondary Capture Device Manufacturer", "LO", "1"}, -{{24, 4119}, "Hardcopy Device Manufacturer", "LO", "1"}, -{{24, 4120}, "Secondary Capture Device Manufacturer's Model Name", "LO", "1"}, -{{24, 4121}, "Secondary Capture Device Software Version(s)", "LO", "1-n"}, -{{24, 4122}, "Hardcopy Device Software Version", "LO", "1-n"}, -{{24, 4123}, "Hardcopy Device Manfuacturer's Model Name", "LO", "1"}, -{{24, 4128}, "Software Version(s)", "LO", "1-n"}, -{{24, 4130}, "Video Image Format Acquired", "SH", "1"}, -{{24, 4131}, "Digital Image Format Acquired", "LO", "1"}, -{{24, 4144}, "Protocol Name", "LO", "1"}, -{{24, 4160}, "Contrast/Bolus Route", "LO", "1"}, -{{24, 4161}, "Contrast/Bolus Volume", "DS", "1"}, -{{24, 4162}, "Contrast/Bolus Start Time", "TM", "1"}, -{{24, 4163}, "Contrast/Bolus Stop Time", "TM", "1"}, -{{24, 4164}, "Contrast/Bolus Total Dose", "DS", "1"}, -{{24, 4165}, "Syringe Counts", "IS", "1"}, -{{24, 4166}, "Contrast Flow Rate", "DS", "1-n"}, -{{24, 4167}, "Contrast Flow Duration", "DS", "1-n"}, -{{24, 4168}, "Contrast/Bolus Ingredient", "CS", "1"}, -{{24, 4169}, "Contrast/Bolus Ingredient Concentration", "DS", "1"}, -{{24, 4176}, "Spatial Resolution", "DS", "1"}, -{{24, 4192}, "Trigger Time", "DS", "1"}, -{{24, 4193}, "Trigger Source or Type", "LO", "1"}, -{{24, 4194}, "Nominal Interval", "IS", "1"}, -{{24, 4195}, "Frame Time", "DS", "1"}, -{{24, 4196}, "Framing Type", "LO", "1"}, -{{24, 4197}, "Frame Time Vector", "DS", "1-n"}, -{{24, 4198}, "Frame Delay", "DS", "1"}, -{{24, 4199}, "Image Trigger Delay", "DS", "1"}, -{{24, 4200}, "Multiplex Group Time Offset", "DS", "1"}, -{{24, 4201}, "Trigger Time Offset", "DS", "1"}, -{{24, 4202}, "Synchronization Trigger", "CS", "1"}, -{{24, 4204}, "Synchronization Channel", "US", "2"}, -{{24, 4206}, "Trigger Sample Position", "UL", "1"}, -{{24, 4208}, "Radiopharmaceutical Route", "LO", "1"}, -{{24, 4209}, "Radiopharmaceutical Volume", "DS", "1"}, -{{24, 4210}, "Radiopharmaceutical Start Time", "TM", "1"}, -{{24, 4211}, "Radiopharmaceutical Stop Time", "TM", "1"}, -{{24, 4212}, "Radionuclide Total Dose", "DS", "1"}, -{{24, 4213}, "Radionuclide Half Life", "DS", "1"}, -{{24, 4214}, "Radionuclide Positron Fraction", "DS", "1"}, -{{24, 4215}, "Radiopharmaceutical Specific Activity", "DS", "1"}, -{{24, 4224}, "Beat Rejection Flag", "CS", "1"}, -{{24, 4225}, "Low R-R Value", "IS", "1"}, -{{24, 4226}, "High R-R Value", "IS", "1"}, -{{24, 4227}, "Intervals Acquired", "IS", "1"}, -{{24, 4228}, "Intervals Rejected", "IS", "1"}, -{{24, 4229}, "PVC Rejection", "LO", "1"}, -{{24, 4230}, "Skip Beats", "IS", "1"}, -{{24, 4232}, "Heart Rate", "IS", "1"}, -{{24, 4240}, "Cardiac Number of Images", "IS", "1"}, -{{24, 4244}, "Trigger Window", "IS", "1"}, -{{24, 4352}, "Reconstruction Diameter", "DS", "1"}, -{{24, 4368}, "Distance Source to Detector", "DS", "1"}, -{{24, 4369}, "Distance Source to Patient", "DS", "1"}, -{{24, 4372}, "Estimated Radiographic Magnification Factor", "DS", "1"}, -{{24, 4384}, "Gantry/Detector Tilt", "DS", "1"}, -{{24, 4385}, "Gantry/Detector Slew", "DS", "1"}, -{{24, 4400}, "Table Height", "DS", "1"}, -{{24, 4401}, "Table Traverse", "DS", "1"}, -{{24, 4404}, "Table Motion", "CS", "1"}, -{{24, 4405}, "Table Vertical Increment", "DS", "1-n"}, -{{24, 4406}, "Table Lateral Increment", "DS", "1-n"}, -{{24, 4407}, "Table Longitudinal Increment", "DS", "1-n"}, -{{24, 4408}, "Table Angle", "DS", "1"}, -{{24, 4410}, "Table Type", "CS", "1"}, -{{24, 4416}, "Rotation Direction", "CS", "1"}, -{{24, 4417}, "Angular Position", "DS", "1"}, -{{24, 4418}, "Radial Position", "DS", "1-n"}, -{{24, 4419}, "Scan Arc", "DS", "1"}, -{{24, 4420}, "Angular Step", "DS", "1"}, -{{24, 4421}, "Center of Rotation Offset", "DS", "1"}, -{{24, 4423}, "Field of View Shape", "CS", "1"}, -{{24, 4425}, "Field of View Dimension(s)", "IS", "1-2"}, -{{24, 4432}, "Exposure Time", "IS", "1"}, -{{24, 4433}, "X-ray Tube Current", "IS", "1"}, -{{24, 4434}, "Exposure", "IS", "1"}, -{{24, 4435}, "Exposure in uAs", "IS", "1"}, -{{24, 4436}, "Average Pulse Width", "DS", "1"}, -{{24, 4437}, "Radiation Setting", "CS", "1"}, -{{24, 4438}, "Rectification Type", "CS", "1"}, -{{24, 4442}, "Radiation Mode", "CS", "1"}, -{{24, 4446}, "Image Area Dose Product", "DS", "1"}, -{{24, 4448}, "Filter Type", "SH", "1"}, -{{24, 4449}, "Type of Filters", "LO", "1-n"}, -{{24, 4450}, "Intensifier Size", "DS", "1"}, -{{24, 4452}, "Imager Pixel Spacing", "DS", "2"}, -{{24, 4454}, "Grid", "CS", "1-n"}, -{{24, 4464}, "Generator Power", "IS", "1"}, -{{24, 4480}, "Collimator/grid Name", "SH", "1"}, -{{24, 4481}, "Collimator Type", "CS", "1"}, -{{24, 4482}, "Focal Distance", "IS", "1-2"}, -{{24, 4483}, "X Focus Center", "DS", "1-2"}, -{{24, 4484}, "Y Focus Center", "DS", "1-2"}, -{{24, 4496}, "Focal Spot(s)", "DS", "1-n"}, -{{24, 4497}, "Anode Target Material", "CS", "1"}, -{{24, 4512}, "Body Part Thickness", "DS", "1"}, -{{24, 4514}, "Compression Force", "DS", "1"}, -{{24, 4608}, "Date of Last Calibration", "DA", "1-n"}, -{{24, 4609}, "Time of Last Calibration", "TM", "1-n"}, -{{24, 4624}, "Convolution Kernel", "SH", "1-n"}, -{{24, 4674}, "Actual Frame Duration", "IS", "1"}, -{{24, 4675}, "Count Rate", "IS", "1"}, -{{24, 4676}, "Preferred Playback Sequencing", "US", "1"}, -{{24, 4688}, "Receive Coil Name", "SH", "1"}, -{{24, 4689}, "Transmit Coil Name", "SH", "1"}, -{{24, 4704}, "Plate Type", "SH", "1"}, -{{24, 4705}, "Phosphor Type", "LO", "1"}, -{{24, 4864}, "Scan Velocity", "DS", "1"}, -{{24, 4865}, "Whole Body Technique", "CS", "1-n"}, -{{24, 4866}, "Scan Length", "IS", "1"}, -{{24, 4880}, "Acquisition Matrix", "US", "4"}, -{{24, 4882}, "In-plane Phase Encoding Direction", "CS", "1"}, -{{24, 4884}, "Flip Angle", "DS", "1"}, -{{24, 4885}, "Variable Flip Angle Flag", "CS", "1"}, -{{24, 4886}, "SAR", "DS", "1"}, -{{24, 4888}, "dB/dt", "DS", "1"}, -{{24, 5120}, "Acquisition Device Processing Description", "LO", "1"}, -{{24, 5121}, "Acquisition Device Processing Code", "LO", "1"}, -{{24, 5122}, "Cassette Orientation", "CS", "1"}, -{{24, 5123}, "Cassette Size", "CS", "1"}, -{{24, 5124}, "Exposures on Plate", "US", "1"}, -{{24, 5125}, "Relative X-ray Exposure", "IS", "1"}, -{{24, 5200}, "Column Angulation", "DS", "1"}, -{{24, 5216}, "Tomo Layer Height", "DS", "1"}, -{{24, 5232}, "Tomo Angle", "DS", "1"}, -{{24, 5248}, "Tomo Time", "DS", "1"}, -{{24, 5264}, "Tomo Type", "CS", "1"}, -{{24, 5265}, "Tomo Class", "CS", "1"}, -{{24, 5269}, "Number of Tomosynthesis Source Images", "IS", "1"}, -{{24, 5376}, "Positioner Motion", "CS", "1"}, -{{24, 5384}, "Positioner Type", "CS", "1"}, -{{24, 5392}, "Positioner Primary Angle", "DS", "1"}, -{{24, 5393}, "Positioner Secondary Angle", "DS", "1"}, -{{24, 5408}, "Positioner Primary Angle Increment", "DS", "1-n"}, -{{24, 5409}, "Positioner Secondary Angle Increment", "DS", "1-n"}, -{{24, 5424}, "Detector Primary Angle", "DS", "1"}, -{{24, 5425}, "Detector Secondary Angle", "DS", "1"}, -{{24, 5632}, "Shutter Shape", "CS", "1-3"}, -{{24, 5634}, "Shutter Left Vertical Edge", "IS", "1"}, -{{24, 5636}, "Shutter Right Vertical Edge", "IS", "1"}, -{{24, 5638}, "Shutter Upper Horizontal Edge", "IS", "1"}, -{{24, 5640}, "Shutter Lower Horizontal Edge", "IS", "1"}, -{{24, 5648}, "Center of Circular Shutter", "IS", "2"}, -{{24, 5650}, "Radius of Circular Shutter", "IS", "1"}, -{{24, 5664}, "Vertices of the Polygonal Shutter", "IS", "2-2n"}, -{{24, 5666}, "Shutter Presentation Value", "US", "1"}, -{{24, 5667}, "Shutter Overlay Group", "US", "1"}, -{{24, 5888}, "Collimator Shape", "CS", "1-3"}, -{{24, 5890}, "Collimator Left Vertical Edge", "IS", "1"}, -{{24, 5892}, "Collimator Right Vertical Edge", "IS", "1"}, -{{24, 5894}, "Collimator Upper Horizontal Edge", "IS", "1"}, -{{24, 5896}, "Collimator Lower Horizontal Edge", "IS", "1"}, -{{24, 5904}, "Center of Circular Collimator", "IS", "2"}, -{{24, 5906}, "Radius of Circular Collimator", "IS", "1"}, -{{24, 5920}, "Vertices of the Polygonal Collimator", "IS", "2-2n"}, -{{24, 6144}, "Acquisition Time Synchronized", "CS", "1"}, -{{24, 6145}, "Time Source", "SH", "1"}, -{{24, 6146}, "Time Distribution Protocol", "CS", "1"}, -{{24, 6147}, "NTP Source Address", "LO", "1"}, -{{24, 8193}, "Page Number Vector", "IS", "1-n"}, -{{24, 8194}, "Frame Label Vector", "SH", "1-n"}, -{{24, 8195}, "Frame Primary Angle Vector", "DS", "1-n"}, -{{24, 8196}, "Frame Secondary Angle Vector", "DS", "1-n"}, -{{24, 8197}, "Slice Location Vector", "DS", "1-n"}, -{{24, 8198}, "Display Window Label Vector", "SH", "1-n"}, -{{24, 8208}, "Nominal Scanned Pixel Spacing", "DS", "2"}, -{{24, 8224}, "Digitizing Device Transport Direction", "CS", "1"}, -{{24, 8240}, "Rotation of Scanned Film", "DS", "1"}, -{{24, 12544}, "IVUS Acquisition", "CS", "1"}, -{{24, 12545}, "IVUS Pullback Rate", "DS", "1"}, -{{24, 12546}, "IVUS Gated Rate", "DS", "1"}, -{{24, 12547}, "IVUS Pullback Start Frame Number", "IS", "1"}, -{{24, 12548}, "IVUS Pullback Stop Frame Number", "IS", "1"}, -{{24, 12549}, "Lesion Number", "IS", "1-n"}, -{{24, 20480}, "Output Power", "SH", "1-n"}, -{{24, 20496}, "Transducer Data", "LO", "3"}, -{{24, 20498}, "Focus Depth", "DS", "1"}, -{{24, 20512}, "Processing Function", "LO", "1"}, -{{24, 20513}, "Postprocessing Function", "LO", "1"}, -{{24, 20514}, "Mechanical Index", "DS", "1"}, -{{24, 20516}, "Bone Thermal Index", "DS", "1"}, -{{24, 20518}, "Cranial Thermal Index", "DS", "1"}, -{{24, 20519}, "Soft Tissue Thermal Index", "DS", "1"}, -{{24, 20520}, "Soft Tissue-focus Thermal Index", "DS", "1"}, -{{24, 20521}, "Soft Tissue-surface Thermal Index", "DS", "1"}, -{{24, 20560}, "Depth of Scan Field", "IS", "1"}, -{{24, 20736}, "Patient Position", "CS", "1"}, -{{24, 20737}, "View Position", "CS", "1"}, -{{24, 20740}, "Projection Eponymous Name Code Sequence", "SQ", "1"}, -{{24, 24576}, "Sensitivity", "DS", "1"}, -{{24, 24593}, "Sequence of Ultrasound Regions", "SQ", "1"}, -{{24, 24594}, "Region Spatial Format", "US", "1"}, -{{24, 24596}, "Region Data Type", "US", "1"}, -{{24, 24598}, "Region Flags", "UL", "1"}, -{{24, 24600}, "Region Location Min X0", "UL", "1"}, -{{24, 24602}, "Region Location Min Y0", "UL", "1"}, -{{24, 24604}, "Region Location Max X1", "UL", "1"}, -{{24, 24606}, "Region Location Max Y1", "UL", "1"}, -{{24, 24608}, "Reference Pixel X0", "SL", "1"}, -{{24, 24610}, "Reference Pixel Y0", "SL", "1"}, -{{24, 24612}, "Physical Units X Direction", "US", "1"}, -{{24, 24614}, "Physical Units Y Direction", "US", "1"}, -{{24, 24616}, "Reference Pixel Physical Value X", "FD", "1"}, -{{24, 24618}, "Reference Pixel Physical Value Y", "FD", "1"}, -{{24, 24620}, "Physical Delta X", "FD", "1"}, -{{24, 24622}, "Physical Delta Y", "FD", "1"}, -{{24, 24624}, "Transducer Frequency", "UL", "1"}, -{{24, 24625}, "Transducer Type", "CS", "1"}, -{{24, 24626}, "Pulse Repetition Frequency", "UL", "1"}, -{{24, 24628}, "Doppler Correction Angle", "FD", "1"}, -{{24, 24630}, "Steering Angle", "FD", "1"}, -{{24, 24633}, "Doppler Sample Volume X Position", "SL", "1"}, -{{24, 24635}, "Doppler Sample Volume Y Position", "SL", "1"}, -{{24, 24637}, "TM-Line Position X0", "SL", "1"}, -{{24, 24639}, "TM-Line Position Y0", "SL", "1"}, -{{24, 24641}, "TM-Line Position X1", "SL", "1"}, -{{24, 24643}, "TM-Line Position Y1", "SL", "1"}, -{{24, 24644}, "Pixel Component Organization", "US", "1"}, -{{24, 24646}, "Pixel Component Mask", "UL", "1"}, -{{24, 24648}, "Pixel Component Range Start", "UL", "1"}, -{{24, 24650}, "Pixel Component Range Stop", "UL", "1"}, -{{24, 24652}, "Pixel Component Physical Units", "US", "1"}, -{{24, 24654}, "Pixel Component Data Type", "US", "1"}, -{{24, 24656}, "Number of Table Break Points", "UL", "1"}, -{{24, 24658}, "Table of X Break Points", "UL", "1-n"}, -{{24, 24660}, "Table of Y Break Points", "FD", "1-n"}, -{{24, 24662}, "Number of Table Entries", "UL", "1"}, -{{24, 24664}, "Table of Pixel Values", "UL", "1-n"}, -{{24, 24666}, "Table of Parameter Values", "FL", "1-n"}, -{{24, 24672}, "R Wave Time Vector", "FL", "1-n"}, -{{24, 28672}, "Detector Conditions Nominal Flag", "CS", "1"}, -{{24, 28673}, "Detector Temperature", "DS", "1"}, -{{24, 28676}, "Detector Type", "CS", "1"}, -{{24, 28677}, "Detector Configuration", "CS", "1"}, -{{24, 28678}, "Detector Description", "LT", "1"}, -{{24, 28680}, "Detector Mode", "LT", "1"}, -{{24, 28682}, "Detector ID", "SH", "1"}, -{{24, 28684}, "Date of Last Detector Calibration", "DA", "1"}, -{{24, 28686}, "Time of Last Detector Calibration", "TM", "1"}, -{{24, 28688}, "Exposures on Detector Since Last Calibration", "IS", "1"}, -{{24, 28689}, "Exposures on Detector Since Manufactured", "IS", "1"}, -{{24, 28690}, "Detector Time Since Last Exposure", "DS", "1"}, -{{24, 28692}, "Detector Active Time", "DS", "1"}, -{{24, 28694}, "Detector Activation Offset From Exposure", "DS", "1"}, -{{24, 28698}, "Detector Binning", "DS", "2"}, -{{24, 28704}, "Detector Element Physical Size", "DS", "2"}, -{{24, 28706}, "Detector Element Spacing", "DS", "2"}, -{{24, 28708}, "Detector Active Shape", "CS", "1"}, -{{24, 28710}, "Detector Active Dimension(s)", "DS", "1-2"}, -{{24, 28712}, "Detector Active Origin", "DS", "2"}, -{{24, 28714}, "Detector Manufacturer Name", "LO", "1"}, -{{24, 28715}, "Detector Manufacturer's Model Name", "LO", "1"}, -{{24, 28720}, "Field of View Origin", "DS", "2"}, -{{24, 28722}, "Field of View Rotation", "DS", "1"}, -{{24, 28724}, "Field of View Horizontal Flip", "CS", "1"}, -{{24, 28736}, "Grid Absorbing Material", "LT", "1"}, -{{24, 28737}, "Grid Spacing Material", "LT", "1"}, -{{24, 28738}, "Grid Thickness", "DS", "1"}, -{{24, 28740}, "Grid Pitch", "DS", "1"}, -{{24, 28742}, "Grid Aspect Ratio", "IS", "2"}, -{{24, 28744}, "Grid Period", "DS", "1"}, -{{24, 28748}, "Grid Focal Distance", "DS", "1"}, -{{24, 28752}, "Filter Material", "CS", "1-n"}, -{{24, 28754}, "Filter Thickness Minimum", "DS", "1-n"}, -{{24, 28756}, "Filter Thickness Maximum", "DS", "1-n"}, -{{24, 28768}, "Exposure Control Mode", "CS", "1"}, -{{24, 28770}, "Exposure Control Mode Description", "LT", "1"}, -{{24, 28772}, "Exposure Status", "CS", "1"}, -{{24, 28773}, "Phototimer Setting", "DS", "1"}, -{{24, 33104}, "Exposure Time in XS", "DS", "1"}, -{{24, 33105}, "X-Ray Tube Current in XA", "DS", "1"}, -{{24, 36868}, "Content Qualification", "CS", "1"}, -{{24, 36869}, "Pulse Sequence Name", "SH", "1"}, -{{24, 36870}, "MR Imaging Modifier Sequence", "SQ", "1"}, -{{24, 36872}, "Echo Pulse Sequence", "CS", "1"}, -{{24, 36873}, "Inversion Recovery", "CS", "1"}, -{{24, 36880}, "Flow Compensation", "CS", "1"}, -{{24, 36881}, "Multiple Spin Echo", "CS", "1"}, -{{24, 36882}, "Multi-planar Excitation", "CS", "1"}, -{{24, 36884}, "Phase Contrast", "CS", "1"}, -{{24, 36885}, "Time of Flight Contrast", "CS", "1"}, -{{24, 36886}, "Spoiling", "CS", "1"}, -{{24, 36887}, "Steady State Pulse Sequence", "CS", "1"}, -{{24, 36888}, "Echo Planar Pulse Sequence", "CS", "1"}, -{{24, 36889}, "Tag Angle First Axis", "FD", "1"}, -{{24, 36896}, "Magnetization Transfer", "CS", "1"}, -{{24, 36897}, "T2 Preparation", "CS", "1"}, -{{24, 36898}, "Blood Signal Nulling", "CS", "1"}, -{{24, 36900}, "Saturation Recovery", "CS", "1"}, -{{24, 36901}, "Spectrally Selected Suppression", "CS", "1"}, -{{24, 36902}, "Spectrally Selected Excitation", "CS", "1"}, -{{24, 36903}, "Spatial Pre-saturation", "CS", "1"}, -{{24, 36904}, "Tagging", "CS", "1"}, -{{24, 36905}, "Oversampling Phase", "CS", "1"}, -{{24, 36898}, "Blood Signal Nulling", "CS", "1"}, -{{24, 36912}, "Tag Spacing First Dimension", "FD", "1"}, -{{24, 36914}, "Geometry of k-Space Traversal", "CS", "1"}, -{{24, 36915}, "Segmented k-Space Traversal", "CS", "1"}, -{{24, 36916}, "Rectilinear Phase Encode Reordering", "CS", "1"}, -{{24, 36917}, "Tag Thickness", "FD", "1"}, -{{24, 36918}, "Partial Fourier Direction", "CS", "1"}, -{{24, 36919}, "Cardiac Synchronization Technique", "CS", "1"}, -{{24, 36929}, "Receive Coil Manufacturer Name", "LO", "1"}, -{{24, 36930}, "MR Receive Coil Sequence", "SQ", "1"}, -{{24, 36931}, "Receive Coil Type", "CS", "1"}, -{{24, 36932}, "Quadrature Receive Coil", "CS", "1"}, -{{24, 36933}, "Multi-Coil Definition Sequence", "SQ", "1"}, -{{24, 36934}, "Multi-Coil Configuration", "LO", "1"}, -{{24, 36935}, "Multi-Coil Element Name", "SH", "1"}, -{{24, 36936}, "Multi-Coil Element Used", "CS", "1"}, -{{24, 36937}, "MR Transmit Coil Sequence", "SQ", "1"}, -{{24, 36944}, "Transmit Coil Manufacturer Name", "LO", "1"}, -{{24, 36945}, "Transmit Coil Type", "CS", "1"}, -{{24, 36946}, "Spectral Width", "FD", "1-2"}, -{{24, 36947}, "Chemical Shift Reference", "FD", "1-2"}, -{{24, 36948}, "Volume Localization Technique", "CS", "1"}, -{{24, 36952}, "MR Acquisition Frequency Encoding Steps", "US", "1"}, -{{24, 36953}, "De-coupling", "CS", "1"}, -{{24, 36960}, "De-coupled Nucleus", "CS", "1-2"}, -{{24, 36961}, "De-coupling Frequency", "FD", "1-2"}, -{{24, 36962}, "De-coupling Method", "CS", "1"}, -{{24, 36963}, "De-coupling Chemical Shift Reference", "FD", "1-2"}, -{{24, 36964}, "k-space Filtering", "CS", "1"}, -{{24, 36965}, "Time Domain Filtering", "CS", "1-2"}, -{{24, 36966}, "Number of Zero fills", "US", "1-2"}, -{{24, 36967}, "Baseline Correction", "CS", "1"}, -{{24, 36969}, "Parallel Reduction Factor In-plane", "FD", "1"}, -{{24, 36976}, "Cardiac R-R Interval Specified", "FD", "1"}, -{{24, 36979}, "Acquisition Duration", "FD", "1"}, -{{24, 36980}, "Frame Acquisition Datetime", "DT", "1"}, -{{24, 36981}, "Diffusion Directionality", "CS", "1"}, -{{24, 36982}, "Diffusion Gradient Direction Sequence", "SQ", "1"}, -{{24, 36983}, "Parallel Acquisition", "CS", "1"}, -{{24, 36984}, "Parallel Acquisition Technique", "CS", "1"}, -{{24, 36985}, "Inversion Times", "FD", "1-n"}, -{{24, 36992}, "Metabolite Map Description", "ST", "1"}, -{{24, 36993}, "Partial Fourier", "CS", "1"}, -{{24, 36994}, "Effective Echo Time", "FD", "1"}, -{{24, 36995}, "Metabolite Map Code Sequence", "SQ", "1"}, -{{24, 36996}, "Chemical Shift Sequence", "SQ", "1"}, -{{24, 36997}, "Cardiac Signal Source", "CS", "1"}, -{{24, 36999}, "Diffusion b-value", "FD", "1"}, -{{24, 37001}, "Diffusion Gradient Orientation", "FD", "3"}, -{{24, 37008}, "Velocity Encoding Direction", "FD", "3"}, -{{24, 37009}, "Velocity Encoding Minimum Value", "FD", "1"}, -{{24, 37011}, "Number of k-Space Trajectories", "US", "1"}, -{{24, 37012}, "Coverage of k-Space", "CS", "1"}, -{{24, 37013}, "Spectroscopy Acquisition Phase Rows", "UL", "1"}, -{{24, 37016}, "Transmitter Frequency", "FD", "1-2"}, -{{24, 37120}, "Resonant Nucleus", "CS", "1-2"}, -{{24, 37121}, "Frequency Correction", "CS", "1"}, -{{24, 37123}, "MR Spectroscopy FOV/Geometry Sequence", "SQ", "1"}, -{{24, 37124}, "Slab Thickness", "FD", "1"}, -{{24, 37125}, "Slab Orientation", "FD", "3"}, -{{24, 37126}, "Mid Slab Position", "FD", "3"}, -{{24, 37127}, "MR Spatial Saturation Sequence", "SQ", "1"}, -{{24, 37138}, "MR Timing and Related Parameters Sequence", "SQ", "1"}, -{{24, 37140}, "MR Echo Sequence", "SQ", "1"}, -{{24, 37141}, "MR Modifier Sequence", "SQ", "1"}, -{{24, 37143}, "MR Diffusion Sequence", "SQ", "1"}, -{{24, 37144}, "Cardiac Trigger Sequence", "SQ", "1"}, -{{24, 37145}, "MR Averages Sequence", "SQ", "1"}, -{{24, 37157}, "MR FOV/Geometry Sequence", "SQ", "1"}, -{{24, 37158}, "Volume Localization Sequence", "SQ", "1"}, -{{24, 37159}, "Spectroscopy Acquisition Data Columns", "UL", "1"}, -{{24, 37191}, "Diffusion Anisotropy Type", "CS", "1"}, -{{24, 37201}, "Frame Reference Datetime", "DT", "1"}, -{{24, 37202}, "MR Metabolite Map Sequence", "SQ", "1"}, -{{24, 37205}, "Parallel Reduction Factor out-of-plane", "FD", "1"}, -{{24, 37209}, "Spectroscopy Acquisition Out-of-plane Phase Steps", "UL", "1"}, -{{24, 37222}, "Bulk Motion Status", "CS", "1"}, -{{24, 37224}, "Parallel Reduction Factor Second In-plane", "FD", "1"}, -{{24, 37225}, "Cardiac Beat Rejection Technique", "CS", "1"}, -{{24, 37232}, "Respiratory Motion Compensation Technique", "CS", "1"}, -{{24, 37233}, "Respiratory Signal Source", "CS", "1"}, -{{24, 37234}, "Bulk Motion Compensation Technique", "CS", "1"}, -{{24, 37235}, "Bulk Motion Signal Source", "CS", "1"}, -{{24, 37236}, "Applicable Safety Standard Agency", "CS", "1"}, -{{24, 37237}, "Applicable Safety Standard Description", "LO", "1"}, -{{24, 37238}, "Operating Mode Sequence", "SQ", "1"}, -{{24, 37239}, "Operating Mode Type", "CS", "1"}, -{{24, 37240}, "Operating Mode", "CS", "1"}, -{{24, 37241}, "Specific Absorption Rate Definition", "CS", "1"}, -{{24, 37248}, "Gradient Output Type", "CS", "1"}, -{{24, 37249}, "Specific Absorption Rate Value", "FD", "1"}, -{{24, 37250}, "Gradient Output", "FD", "1"}, -{{24, 37251}, "Flow Compensation Direction", "CS", "1"}, -{{24, 37252}, "Tagging Delay", "FD", "1"}, -{{24, 37269}, "Chemical Shifts Minimum Integration Limit in Hz", "FD", "1", "Retired"}, -{{24, 37270}, "Chemical Shifts Maximum Integration Limit in Hz", "FD", "1", "Retired"}, -{{24, 37271}, "MR Velocity Encoding Sequence", "SQ", "1"}, -{{24, 37272}, "First Order Phase Correction", "CS", "1"}, -{{24, 37273}, "Water Referenced Phase Correction", "CS", "1"}, -{{24, 37376}, "MR Spectroscopy Acquisition Type", "CS", "1"}, -{{24, 37396}, "Respiratory Cycle Position", "CS", "1"}, -{{24, 37399}, "Velocity Encoding Maximum Value", "FD", "1"}, -{{24, 37400}, "Tag Spacing Second Dimension", "FD", "1"}, -{{24, 37401}, "Tag Angle Second Axis", "SS", "1"}, -{{24, 37408}, "Frame Acquisition Duration", "FD", "1"}, -{{24, 37414}, "MR Image Frame Type Sequence", "SQ", "1"}, -{{24, 37415}, "MR Spectroscopy Frame Type Sequence", "SQ", "1"}, -{{24, 37425}, "MR Acquisition Phase Encoding Steps in-plane", "US", "1"}, -{{24, 37426}, "MR Acquisition Phase Encoding Steps out-of-plane", "US", "1"}, -{{24, 37428}, "Spectroscopy Acquisition Phase Columns", "UL", "1"}, -{{24, 37430}, "Cardiac Cycle Position", "CS", "1"}, -{{24, 37433}, "Specific Absorption Rate Sequence", "SQ", "1"}, -{{24, 37525}, "Chemical Shifts Minimum Integration Limit in ppm", "FD", "1"}, -{{24, 37526}, "Chemical Shifts Maximum Integration Limit in ppm", "FD", "1"}, -{{24, 37440}, "RF Echo Train Length", "US", "1"}, -{{24, 37441}, "Gradient Echo Train Length", "US", "1"}, -{{24, 37633}, "CT Acquisition Type Sequence", "SQ", "1"}, -{{24, 37634}, "Acquisition Type", "CS", "1"}, -{{24, 37635}, "Tube Angle", "FD", "1"}, -{{24, 37636}, "CT Acquisition Details Sequence", "SQ", "1"}, -{{24, 37637}, "Revolution Time", "FD", "1"}, -{{24, 37638}, "Single Collimation Width", "FD", "1"}, -{{24, 37639}, "Total Collimation Width", "FD", "1"}, -{{24, 37640}, "CT Table Dynamics Sequence", "SQ", "1"}, -{{24, 37641}, "Table Speed", "FD", "1"}, -{{24, 37648}, "Table Feed per Rotation", "FD", "1"}, -{{24, 37649}, "Spiral Pitch Factor", "FD", "1"}, -{{24, 37650}, "CT Geometry Sequence", "SQ", "1"}, -{{24, 37651}, "Data Collection Center (Patient)", "FD", "3"}, -{{24, 37652}, "CT Reconstruction Sequence", "SQ", "1"}, -{{24, 37653}, "Reconstruction Algorithm", "CS", "1"}, -{{24, 37654}, "Convolution Kernel Group", "CS", "1"}, -{{24, 37655}, "Reconstruction Field of View", "FD", "2"}, -{{24, 37656}, "Reconstruction Target Center (Patient)", "FD", "3"}, -{{24, 37657}, "Reconstruction Angle", "FD", "1"}, -{{24, 37664}, "Image Filter", "SH", "1"}, -{{24, 37665}, "CT Exposure Sequence", "SQ", "1"}, -{{24, 37666}, "Reconstruction Pixel Spacing", "FD", "2"}, -{{24, 37667}, "Exposure Modulation Type", "CS", "1"}, -{{24, 37668}, "Estimated Dose Saving", "FD", "1"}, -{{24, 37669}, "CT X-ray Details Sequence", "SQ", "1"}, -{{24, 37670}, "CT Position Sequence", "SQ", "1"}, -{{24, 37671}, "Table Position", "FD", "1"}, -{{24, 37672}, "Exposure Time in ms", "FD", "1"}, -{{24, 37673}, "CT Image Frame Type Sequence", "SQ", "1"}, -{{24, 37680}, "X-Ray Tube Current in mA", "FD", "1"}, -{{24, 37682}, "Exposure in mAs", "FD", "1"}, -{{24, 37683}, "Constant Volume Flag", "CS", "1"}, -{{24, 37684}, "Fluoroscopy Flag", "CS", "1"}, -{{24, 37685}, "Distance Source to Data Collection Center", "FD", "1"}, -{{24, 37687}, "Contrast/Bolus Agent Number", "US", "1"}, -{{24, 37688}, "Contrast/Bolus Ingredient Code Sequence", "SQ", "1"}, -{{24, 37696}, "Contrast Administration Profile Sequence", "SQ", "1"}, -{{24, 37697}, "Contrast/Bolus Usage Sequence", "SQ", "1"}, -{{24, 37698}, "Contrast/Bolus Agent Administered", "CS", "1"}, -{{24, 37699}, "Contrast/Bolus Agent Detected", "CS", "1"}, -{{24, 37700}, "Contrast/Bolus Agent Phase", "CS", "1"}, -{{24, 37701}, "CTDIvol", "FD", "1"}, -{{24, 40961}, "Contributing Equipment Sequence", "SQ", "1"}, -{{24, 40962}, "Contribution DateTime", "DT", "1"}, -{{24, 40963}, "Contribution Description", "ST", "1"}, -{{32, 13}, "Study Instance UID", "UI", "1"}, -{{32, 14}, "Series Instance UID", "UI", "1"}, -{{32, 16}, "Study ID", "SH", "1"}, -{{32, 17}, "Series Number", "IS", "1"}, -{{32, 18}, "Acquisition Number", "IS", "1"}, -{{32, 19}, "Instance Number", "IS", "1"}, -{{32, 25}, "Item Number", "IS", "1"}, -{{32, 32}, "Patient Orientation", "CS", "2"}, -{{32, 34}, "Overlay Number", "IS", "1"}, -{{32, 36}, "Curve Number", "IS", "1"}, -{{32, 38}, "Lookup Table Number", "IS", "1"}, -{{32, 50}, "Image Position (Patient)", "DS", "3"}, -{{32, 55}, "Image Orientation (Patient)", "DS", "6"}, -{{32, 82}, "Frame of Reference UID", "UI", "1"}, -{{32, 96}, "Laterality", "CS", "1"}, -{{32, 98}, "Image Laterality", "CS", "1"}, -{{32, 256}, "Temporal Position Identifier", "IS", "1"}, -{{32, 261}, "Number of Temporal Positions", "IS", "1"}, -{{32, 272}, "Temporal Resolution", "DS", "1"}, -{{32, 512}, "Synchronization Frame of Reference UID", "UI", "1"}, -{{32, 4096}, "Series in Study", "IS", "1"}, -{{32, 4098}, "Images in Acquisition", "IS", "1"}, -{{32, 4100}, "Acquisitions in Study", "IS", "1"}, -{{32, 4160}, "Position Reference Indicator", "LO", "1"}, -{{32, 4161}, "Slice Location", "DS", "1"}, -{{32, 4208}, "Other Study Numbers", "IS", "1-n"}, -{{32, 4608}, "Number of Patient Related Studies", "IS", "1"}, -{{32, 4610}, "Number of Patient Related Series", "IS", "1"}, -{{32, 4612}, "Number of Patient Related Instances", "IS", "1"}, -{{32, 4614}, "Number of Study Related Series", "IS", "1"}, -{{32, 4616}, "Number of Study Related Instances", "IS", "1"}, -{{32, 4617}, "Number of Series Related Instances", "IS", "1"}, -{{32, 16384}, "Image Comments", "LT", "1"}, -{{32, 36950}, "Stack ID", "SH", "1"}, -{{32, 36951}, "In-Stack Position Number", "UL", "1"}, -{{32, 36977}, "Frame Anatomy Sequence", "SQ", "1"}, -{{32, 36978}, "Frame Laterality", "CS", "1"}, -{{32, 37137}, "Frame Content Sequence", "SQ", "1"}, -{{32, 37139}, "Plane Position Sequence", "SQ", "1"}, -{{32, 37142}, "Plane Orientation Sequence", "SQ", "1"}, -{{32, 37160}, "Temporal Position Index", "UL", "1"}, -{{32, 37203}, "Trigger Delay Time", "FD", "1"}, -{{32, 37206}, "Frame Acquisition Number", "US", "1"}, -{{32, 37207}, "Dimension Index Values", "UL", "1-n"}, -{{32, 37208}, "Frame Comments", "LT", "1"}, -{{32, 37217}, "Concatenation UID", "UI", "1"}, -{{32, 37218}, "In-concatenation Number", "US", "1"}, -{{32, 37219}, "In-concatenation Total Number", "US", "1"}, -{{32, 37220}, "Dimension Organization UID", "UI", "1"}, -{{32, 37221}, "Dimension Index Pointer", "AT", "1"}, -{{32, 37223}, "Functional Group Pointer", "AT", "1"}, -{{32, 37395}, "Dimension Index Private Creator", "LO", "1"}, -{{32, 37409}, "Dimension Organization Sequence", "SQ", "1"}, -{{32, 37410}, "Dimension Index Sequence", "SQ", "1"}, -{{32, 37416}, "Concatenation Frame Offset Number", "UL", "1"}, -{{32, 37432}, "Functional Group Private Creator", "LO", "1"}, -{{34, 1}, "Light Path Filter Pass-Through Wavelength", "US", "1"}, -{{34, 2}, "Light Path Filter Pass Band", "US", "2"}, -{{34, 3}, "Image Path Filter Pass-Through Wavelength", "US", "1"}, -{{34, 4}, "Image Path Filter Pass Band", "US", "2"}, -{{34, 5}, "Patient Eye Movement Commanded", "CS", "1"}, -{{34, 6}, "Patient Eye Movement Command Code Sequence", "SQ", "1"}, -{{34, 7}, "Spherical Lens Power", "FL", "1"}, -{{34, 8}, "Cylinder Lens Power", "FL", "1"}, -{{34, 9}, "Cylinder Axis", "FL", "1"}, -{{34, 10}, "Emmetropic Magnification", "FL", "1"}, -{{34, 11}, "Intra Ocular Pressure", "FL", "1"}, -{{34, 12}, "Horizontal Field of View", "FL", "1"}, -{{34, 13}, "Pupil Dilated", "CS", "1"}, -{{34, 14}, "Degree of Dilation", "FL", "1"}, -{{34, 16}, "Stereo Baseline Angle", "FL", "1"}, -{{34, 17}, "Stereo Baseline Displacement", "FL", "1"}, -{{34, 18}, "Stereo Horizontal Pixel Offset", "FL", "1"}, -{{34, 19}, "Stereo Vertical Pixel Offset", "FL", "1"}, -{{34, 20}, "Stereo Rotation", "FL", "1"}, -{{34, 21}, "Acquisition Device Type Code Sequence", "SQ", "1"}, -{{34, 22}, "Illumination Type Code Sequence", "SQ", "1"}, -{{34, 23}, "Light Path Filter Type Stack Code Sequence", "SQ", "1"}, -{{34, 24}, "Image Path Filter Type Stack Code Sequence", "SQ", "1"}, -{{34, 25}, "Lenses Code Sequence", "SQ", "1"}, -{{34, 26}, "Channel Description Code Sequence", "SQ", "1"}, -{{34, 27}, "Refractive State Sequence", "SQ", "1"}, -{{34, 28}, "Mydriatic Agent Code Sequence", "SQ", "1"}, -{{34, 29}, "Relative Image Position Code Sequence", "SQ", "1"}, -{{34, 32}, "Stereo Pairs Sequence", "SQ", "1"}, -{{34, 33}, "Left Image Sequence", "SQ", "1"}, -{{34, 34}, "Right Image Sequence", "SQ", "1"}, -{{40, 2}, "Samples per Pixel", "US", "1"}, -{{40, 3}, "Samples per Pixel Used", "US", "1"}, -{{40, 4}, "Photometric Interpretation", "CS", "1"}, -{{40, 6}, "Planar Configuration", "US", "1"}, -{{40, 8}, "Number of Frames", "IS", "1"}, -{{40, 9}, "Frame Increment Pointer", "AT", "1-n"}, -{{40, 10}, "Frame Dimension Pointer", "AT", "1-n"}, -{{40, 16}, "Rows", "US", "1"}, -{{40, 17}, "Columns", "US", "1"}, -{{40, 18}, "Planes", "US", "1"}, -{{40, 20}, "Ultrasound Color Data Present", "US", "1"}, -{{40, 48}, "Pixel Spacing", "DS", "2"}, -{{40, 49}, "Zoom Factor", "DS", "2"}, -{{40, 50}, "Zoom Center", "DS", "2"}, -{{40, 52}, "Pixel Aspect Ratio", "IS", "2"}, -{{40, 81}, "Corrected Image", "CS", "1-n"}, -{{40, 256}, "Bits Allocated", "US", "1"}, -{{40, 257}, "Bits Stored", "US", "1"}, -{{40, 258}, "High Bit", "US", "1"}, -{{40, 259}, "Pixel Representation", "US", "1"}, -{{40, 262}, "Smallest Image Pixel Value", "US", "1"}, -{{40, 263}, "Largest Image Pixel Value", "US", "1"}, -{{40, 264}, "Smallest Pixel Value in Series", "US", "1"}, -{{40, 265}, "Largest Pixel Value in Series", "US", "1"}, -{{40, 272}, "Smallest Image Pixel Value in Plane", "US", "1"}, -{{40, 273}, "Largest Image Pixel Value in Plane", "US", "1"}, -{{40, 288}, "Pixel Padding Value", "US", "1"}, -{{40, 768}, "Quality Control Image", "CS", "1"}, -{{40, 769}, "Burned In Annotation", "CS", "1"}, -{{40, 4160}, "Pixel Intensity Relationship", "CS", "1"}, -{{40, 4161}, "Pixel Intensity Relationship Sign", "SS", "1"}, -{{40, 4176}, "Window Center", "DS", "1-n"}, -{{40, 4177}, "Window Width", "DS", "1-n"}, -{{40, 4178}, "Rescale Intercept", "DS", "1"}, -{{40, 4179}, "Rescale Slope", "DS", "1"}, -{{40, 4180}, "Rescale Type", "LO", "1"}, -{{40, 4181}, "Window Center & Width Explanation", "LO", "1-n"}, -{{40, 4240}, "Recommended Viewing Mode", "CS", "1"}, -{{40, 4353}, "Red Palette Color Lookup Table Descriptor", "US", "3"}, -{{40, 4354}, "Green Palette Color Lookup Table Descriptor", "US", "3"}, -{{40, 4355}, "Blue Palette Color Lookup Table Descriptor", "US", "3"}, -{{40, 4505}, "Palette Color Lookup Table UID", "UI", "1"}, -{{40, 4609}, "Red Palette Color Lookup Table Data", "OW", "1"}, -{{40, 4610}, "Green Palette Color Lookup Table Data", "OW", "1"}, -{{40, 4611}, "Blue Palette Color Lookup Table Data", "OW", "1"}, -{{40, 4641}, "Segmented Red Palette Color Lookup Table Data", "OW", "1"}, -{{40, 4642}, "Segmented Green Palette Color Lookup Table Data", "OW", "1"}, -{{40, 4643}, "Segmented Blue Palette Color Lookup Table Data", "OW", "1"}, -{{40, 4864}, "Implant Present", "CS", "1"}, -{{40, 4944}, "Partial View", "CS", "1"}, -{{40, 4945}, "Partial View Description", "ST", "1"}, -{{40, 8464}, "Lossy Image Compression", "CS", "1"}, -{{40, 8466}, "Lossy Image Compression Ratio", "DS", "1-n"}, -{{40, 8468}, "Lossy Image Compression Method", "CS", "1-n"}, -{{40, 12288}, "Modality LUT Sequence", "SQ", "1"}, -{{40, 12290}, "LUT Descriptor", "US", "3"}, -{{40, 12291}, "LUT Explanation", "LO", "1"}, -{{40, 12292}, "Modality LUT Type", "LO", "1"}, -{{40, 12294}, "LUT Data", "US", "1-n", "or OW", "1"}, -{{40, 12304}, "VOI LUT Sequence", "SQ", "1"}, -{{40, 12560}, "Softcopy VOI LUT Sequence", "SQ", "1"}, -{{40, 20480}, "Bi-Plane Acquisition Sequence", "SQ", "1"}, -{{40, 24592}, "Representative Frame Number", "US", "1"}, -{{40, 24608}, "Frame Numbers of Interest (FOI)", "US", "1-n"}, -{{40, 24610}, "Frame(s) of Interest Description", "LO", "1-n"}, -{{40, 24611}, "Frame of Interest Type", "CS", "1-n"}, -{{40, 24640}, "R Wave Pointer", "US", "1-n"}, -{{40, 24832}, "Mask Subtraction Sequence", "SQ", "1"}, -{{40, 24833}, "Mask Operation", "CS", "1"}, -{{40, 24834}, "Applicable Frame Range", "US", "2-2n"}, -{{40, 24848}, "Mask Frame Numbers", "US", "1-n"}, -{{40, 24850}, "Contrast Frame Averaging", "US", "1"}, -{{40, 24852}, "Mask Sub-pixel Shift", "FL", "2"}, -{{40, 24864}, "TID Offset", "SS", "1"}, -{{40, 24976}, "Mask Operation Explanation", "ST", "1"}, -{{40, 36865}, "Data Point Rows", "UL", "1"}, -{{40, 36866}, "Data Point Columns", "UL", "1"}, -{{40, 36867}, "Signal Domain Columns", "CS", "1"}, -{{40, 37017}, "Largest Monochrome Pixel Value", "US", "1", "Retired"}, -{{40, 37128}, "Data Representation", "CS", "1"}, -{{40, 37136}, "Pixel Measures Sequence", "SQ", "1"}, -{{40, 37170}, "Frame VOI LUT Sequence", "SQ", "1"}, -{{40, 37189}, "Pixel Value Transformation Sequence", "SQ", "1"}, -{{40, 37429}, "Signal Domain Rows", "CS", "1"}, -{{50, 10}, "Study Status ID", "CS", "1"}, -{{50, 12}, "Study Priority ID", "CS", "1"}, -{{50, 18}, "Study ID Issuer", "LO", "1"}, -{{50, 50}, "Study Verified Date", "DA", "1"}, -{{50, 51}, "Study Verified Time", "TM", "1"}, -{{50, 52}, "Study Read Date", "DA", "1"}, -{{50, 53}, "Study Read Time", "TM", "1"}, -{{50, 4096}, "Scheduled Study Start Date", "DA", "1"}, -{{50, 4097}, "Scheduled Study Start Time", "TM", "1"}, -{{50, 4112}, "Scheduled Study Stop Date", "DA", "1"}, -{{50, 4113}, "Scheduled Study Stop Time", "TM", "1"}, -{{50, 4128}, "Scheduled Study Location", "LO", "1"}, -{{50, 4129}, "Scheduled Study Location AE Title(s)", "AE", "1-n"}, -{{50, 4144}, "Reason for Study", "LO", "1"}, -{{50, 4145}, "Requesting Physician Identification Sequence", "SQ", "1"}, -{{50, 4146}, "Requesting Physician", "PN", "1"}, -{{50, 4147}, "Requesting Service", "LO", "1"}, -{{50, 4160}, "Study Arrival Date", "DA", "1"}, -{{50, 4161}, "Study Arrival Time", "TM", "1"}, -{{50, 4176}, "Study Completion Date", "DA", "1"}, -{{50, 4177}, "Study Completion Time", "TM", "1"}, -{{50, 4181}, "Study Component Status ID", "CS", "1"}, -{{50, 4192}, "Requested Procedure Description", "LO", "1"}, -{{50, 4196}, "Requested Procedure Code Sequence", "SQ", "1"}, -{{50, 4208}, "Requested Contrast Agent", "LO", "1"}, -{{50, 16384}, "Study Comments", "LT", "1"}, -{{56, 4}, "Referenced Patient Alias Sequence", "SQ", "1"}, -{{56, 8}, "Visit Status ID", "CS", "1"}, -{{56, 16}, "Admission ID", "LO", "1"}, -{{56, 17}, "Issuer of Admission ID", "LO", "1"}, -{{56, 22}, "Route of Admissions", "LO", "1"}, -{{56, 26}, "Scheduled Admission Date", "DA", "1"}, -{{56, 27}, "Scheduled Admission Time", "TM", "1"}, -{{56, 28}, "Scheduled Discharge Date", "DA", "1"}, -{{56, 29}, "Scheduled Discharge Time", "TM", "1"}, -{{56, 30}, "Scheduled Patient Institution Residence", "LO", "1"}, -{{56, 32}, "Admitting Date", "DA", "1"}, -{{56, 33}, "Admitting Time", "TM", "1"}, -{{56, 48}, "Discharge Date", "DA", "1"}, -{{56, 50}, "Discharge Time", "TM", "1"}, -{{56, 64}, "Discharge Diagnosis Description", "LO", "1"}, -{{56, 68}, "Discharge Diagnosis Code Sequence", "SQ", "1"}, -{{56, 80}, "Special Needs", "LO", "1"}, -{{56, 768}, "Current Patient Location", "LO", "1"}, -{{56, 1024}, "Patient's Institution Residence", "LO", "1"}, -{{56, 1280}, "Patient State", "LO", "1"}, -{{56, 16384}, "Visit Comments", "LT", "1"}, -{{58, 4}, "Waveform Originality", "CS", "1"}, -{{58, 5}, "Number of Waveform Channels", "US", "1"}, -{{58, 16}, "Number of Waveform Samples", "UL", "1"}, -{{58, 26}, "Sampling Frequency", "DS", "1"}, -{{58, 32}, "Multiplex Group Label", "SH", "1"}, -{{58, 512}, "Channel Definition Sequence", "SQ", "1"}, -{{58, 514}, "Waveform Channel Number", "IS", "1"}, -{{58, 515}, "Channel Label", "SH", "1"}, -{{58, 517}, "Channel Status", "CS", "1-n"}, -{{58, 520}, "Channel Source Sequence", "SQ", "1"}, -{{58, 521}, "Channel Source Modifiers Sequence", "SQ", "1"}, -{{58, 522}, "Source Waveform Sequence", "SQ", "1"}, -{{58, 524}, "Channel Derivation Description", "LO", "1"}, -{{58, 528}, "Channel Sensitivity", "DS", "1"}, -{{58, 529}, "Channel Sensitivity Units Sequence", "SQ", "1"}, -{{58, 530}, "Channel Sensitivity Correction Factor", "DS", "1"}, -{{58, 531}, "Channel Baseline", "DS", "1"}, -{{58, 532}, "Channel Time Skew", "DS", "1"}, -{{58, 533}, "Channel Sample Skew", "DS", "1"}, -{{58, 536}, "Channel Offset", "DS", "1"}, -{{58, 538}, "Waveform Bits Stored", "US", "1"}, -{{58, 544}, "Filter Low Frequency", "DS", "1"}, -{{58, 545}, "Filter High Frequency", "DS", "1"}, -{{58, 546}, "Notch Filter Frequency", "DS", "1"}, -{{58, 547}, "Notch Filter Bandwidth", "DS", "1"}, -{{58, 768}, "Multiplexed Audio Channels Description Code Sequence", "SQ", "1"}, -{{58, 769}, "Channel Identification Code", "IS", "1"}, -{{58, 770}, "Channel Mode", "CS", "1"}, -{{64, 1}, "Scheduled Station AE Title", "AE", "1-n"}, -{{64, 2}, "Scheduled Procedure Step Start Date", "DA", "1"}, -{{64, 3}, "Scheduled Procedure Step Start Time", "TM", "1"}, -{{64, 4}, "Scheduled Procedure Step End Date", "DA", "1"}, -{{64, 5}, "Scheduled Procedure Step End Time", "TM", "1"}, -{{64, 6}, "Scheduled Performing Physician's Name", "PN", "1"}, -{{64, 7}, "Scheduled Procedure Step Description", "LO", "1"}, -{{64, 8}, "Scheduled Protocol Code Sequence", "SQ", "1"}, -{{64, 9}, "Scheduled Procedure Step ID", "SH", "1"}, -{{64, 10}, "Stage Code Sequence", "SQ", "1"}, -{{64, 11}, "Scheduled Performing Physician Identification Sequence", "SQ", "1"}, -{{64, 16}, "Scheduled Station Name", "SH", "1-n"}, -{{64, 17}, "Scheduled Procedure Step Location", "SH", "1"}, -{{64, 18}, "Pre-Medication", "LO", "1"}, -{{64, 32}, "Scheduled Procedure Step Status", "CS", "1"}, -{{64, 256}, "Scheduled Procedure Step Sequence", "SQ", "1"}, -{{64, 544}, "Referenced Non-Image Composite SOP Instance Sequence", "SQ", "1"}, -{{64, 577}, "Performed Station AE Title", "AE", "1"}, -{{64, 578}, "Performed Station Name", "SH", "1"}, -{{64, 579}, "Performed Location", "SH", "1"}, -{{64, 580}, "Performed Procedure Step Start Date", "DA", "1"}, -{{64, 581}, "Performed Procedure Step Start Time", "TM", "1"}, -{{64, 592}, "Performed Procedure Step End Date", "DA", "1"}, -{{64, 593}, "Performed Procedure Step End Time", "TM", "1"}, -{{64, 594}, "Performed Procedure Step Status", "CS", "1"}, -{{64, 595}, "Performed Procedure Step ID", "SH", "1"}, -{{64, 596}, "Performed Procedure Step Description", "LO", "1"}, -{{64, 597}, "Performed Procedure Type Description", "LO", "1"}, -{{64, 608}, "Performed Protocol Code Sequence", "SQ", "1"}, -{{64, 624}, "Scheduled Step Attributes Sequence", "SQ", "1"}, -{{64, 629}, "Request Attributes Sequence", "SQ", "1"}, -{{64, 640}, "Comments on the Performed Procedure Step", "ST", "1"}, -{{64, 641}, "Performed Procedure Step Discontinuation Reason Code Sequence", "SQ", "1"}, -{{64, 659}, "Quantity Sequence", "SQ", "1"}, -{{64, 660}, "Quantity", "DS", "1"}, -{{64, 661}, "Measuring Units Sequence", "SQ", "1"}, -{{64, 662}, "Billing Item Sequence", "SQ", "1"}, -{{64, 768}, "Total Time of Fluoroscopy", "US", "1"}, -{{64, 769}, "Total Number of Exposures", "US", "1"}, -{{64, 770}, "Entrance Dose", "US", "1"}, -{{64, 771}, "Exposed Area", "US", "1-2"}, -{{64, 774}, "Distance Source to Entrance", "DS", "1"}, -{{64, 782}, "Exposure Dose Sequence", "SQ", "1"}, -{{64, 784}, "Comments on Radiation Dose", "ST", "1"}, -{{64, 786}, "X-Ray Output", "DS", "1"}, -{{64, 788}, "Half Value Layer", "DS", "1"}, -{{64, 790}, "Organ Dose", "DS", "1"}, -{{64, 792}, "Organ Exposed", "CS", "1"}, -{{64, 800}, "Billing Procedure Step Sequence", "SQ", "1"}, -{{64, 801}, "Film Consumption Sequence", "SQ", "1"}, -{{64, 804}, "Billing Supplies and Devices Sequence", "SQ", "1"}, -{{64, 832}, "Performed Series Sequence", "SQ", "1"}, -{{64, 1024}, "Comments on the Scheduled Procedure Step", "LT", "1"}, -{{64, 1088}, "Protocol Context Sequence", "SQ", "1"}, -{{64, 1089}, "Content Item Modifier Sequence", "SQ", "1"}, -{{64, 1290}, "Specimen Accession Number", "LO", "1"}, -{{64, 1360}, "Specimen Sequence", "SQ", "1"}, -{{64, 1361}, "Specimen Identifier", "LO", "1"}, -{{64, 1365}, "Acquisition Context Sequence", "SQ", "1"}, -{{64, 1366}, "Acquisition Context Description", "ST", "1"}, -{{64, 1434}, "Specimen Type Code Sequence", "SQ", "1"}, -{{64, 1786}, "Slide Identifier", "LO", "1"}, -{{64, 1818}, "Image Center Point Coordinates Sequence", "SQ", "1"}, -{{64, 1834}, "X offset in Slide Coordinate System", "DS", "1"}, -{{64, 1850}, "Y offset in Slide Coordinate System", "DS", "1"}, -{{64, 1866}, "Z offset in Slide Coordinate System", "DS", "1"}, -{{64, 2264}, "Pixel Spacing Sequence", "SQ", "1"}, -{{64, 2266}, "Coordinate System Axis Code Sequence", "SQ", "1"}, -{{64, 2282}, "Measurement Units Code Sequence", "SQ", "1"}, -{{64, 4097}, "Requested Procedure ID", "SH", "1"}, -{{64, 4098}, "Reason for the Requested Procedure", "LO", "1"}, -{{64, 4099}, "Requested Procedure Priority", "SH", "1"}, -{{64, 4100}, "Patient Transport Arrangements", "LO", "1"}, -{{64, 4101}, "Requested Procedure Location", "LO", "1"}, -{{64, 4104}, "Confidentiality Code", "LO", "1"}, -{{64, 4105}, "Reporting Priority", "SH", "1"}, -{{64, 4106}, "Reason for Requested Procedure Code Sequence", "SQ", "1"}, -{{64, 4112}, "Names of Intended Recipients of Results", "PN", "1-n"}, -{{64, 4113}, "Intended Recipients of Results Identification Sequence", "SQ", "1"}, -{{64, 4353}, "Person Identification Code Sequence", "SQ", "1"}, -{{64, 4354}, "Person's Address", "ST", "1"}, -{{64, 4355}, "Person's Telephone Numbers", "LO", "1-n"}, -{{64, 5120}, "Requested Procedure Comments", "LT", "1"}, -{{64, 8196}, "Issue Date of Imaging Service Request", "DA", "1"}, -{{64, 8197}, "Issue Time of Imaging Service Request", "TM", "1"}, -{{64, 8200}, "Order Entered By", "PN", "1"}, -{{64, 8201}, "Order Enterer's Location", "SH", "1"}, -{{64, 8208}, "Order Callback Phone Number", "SH", "1"}, -{{64, 8214}, "Placer Order Number / Imaging Service Request", "LO", "1"}, -{{64, 8215}, "Filler Order Number / Imaging Service Request", "LO", "1"}, -{{64, 9216}, "Imaging Service Request Comments", "LT", "1"}, -{{64, 12289}, "Confidentiality Constraint on Patient Data Description", "LO", "1"}, -{{64, 16385}, "General Purpose Scheduled Procedure Step Status", "CS", "1"}, -{{64, 16386}, "General Purpose Performed Procedure Step Status", "CS", "1"}, -{{64, 16387}, "General Purpose Scheduled Procedure Step Priority", "CS", "1"}, -{{64, 16388}, "Scheduled Processing Applications Code Sequence", "SQ", "1"}, -{{64, 16389}, "Scheduled Procedure Step Start Date and Time", "DT", "1"}, -{{64, 16390}, "Multiple Copies Flag", "CS", "1"}, -{{64, 16391}, "Performed Processing Applications Code Sequence", "SQ", "1"}, -{{64, 16393}, "Human Performer Code Sequence", "SQ", "1"}, -{{64, 16400}, "Scheduled Procedure Step Modification Date and Time", "DT", "1"}, -{{64, 16401}, "Expected Completion Date and Time", "DT", "1"}, -{{64, 16405}, "Resulting General Purpose Performed Procedure Steps Sequence", "SQ", "1"}, -{{64, 16406}, "Referenced General Purpose Scheduled Procedure Step Sequence", "SQ", "1"}, -{{64, 16408}, "Scheduled Workitem Code Sequence", "SQ", "1"}, -{{64, 16409}, "Performed Workitem Code Sequence", "SQ", "1"}, -{{64, 16416}, "Input Availability Flag", "CS", "1"}, -{{64, 16417}, "Input InformationSequence", "SQ", "1"}, -{{64, 16418}, "Relevant Information Sequence", "SQ", "1"}, -{{64, 16419}, "Referenced General Purpose Scheduled Procedure Step Transaction UID", "UI", "1"}, -{{64, 16421}, "Scheduled Station Name Code Sequence", "SQ", "1"}, -{{64, 16422}, "Scheduled Station Class Code Sequence", "SQ", "1"}, -{{64, 16423}, "Scheduled Station Geographic Location Code Sequence", "SQ", "1"}, -{{64, 16424}, "Performed Station Name Code Sequence", "SQ", "1"}, -{{64, 16425}, "Performed Station Class Code Sequence", "SQ", "1"}, -{{64, 16432}, "Performed Station Geographic Location Code Sequence", "SQ", "1"}, -{{64, 16433}, "Requested Subsequent Workitem Code Sequence", "SQ", "1"}, -{{64, 16434}, "Non-DICOM Output Code Sequence", "SQ", "1"}, -{{64, 16435}, "Output Information Sequence", "SQ", "1"}, -{{64, 16436}, "Scheduled Human Performers Sequence", "SQ", "1"}, -{{64, 16437}, "Actual Human Performers Sequence", "SQ", "1"}, -{{64, 16438}, "Human Performer's Organization", "LO", "1"}, -{{64, 16439}, "Human Performer's Name", "PN", "1"}, -{{64, 33538}, "Entrance Dose in mGy", "DS", "1"}, -{{64, 37014}, "Real World Value Mapping Sequence", "SQ", "1"}, -{{64, 37392}, "LUT Label", "SH", "1"}, -{{64, 37393}, "Real World Value Last Value Mapped", "US", "1"}, -{{64, 37394}, "Real World Value LUT Data", "FD", "1-n"}, -{{64, 37398}, "Real World Value First Value Mapped", "US", "1"}, -{{64, 37412}, "Real World Value Intercept", "FD", "1"}, -{{64, 37413}, "Real World Value Slope", "FD", "1"}, -{{64, 40976}, "Relationship Type", "CS", "1"}, -{{64, 40999}, "Verifying Organization", "LO", "1"}, -{{64, 41008}, "Verification DateTime", "DT", "1"}, -{{64, 41010}, "Observation DateTime", "DT", "1"}, -{{64, 41024}, "Value Type", "CS", "1"}, -{{64, 41027}, "Concept Name Code Sequence", "SQ", "1"}, -{{64, 41040}, "Continuity Of Content", "CS", "1"}, -{{64, 41075}, "Verifying Observer Sequence", "SQ", "1"}, -{{64, 41077}, "Verifying Observer Name", "PN", "1"}, -{{64, 41096}, "Verifying Observer Identification Code Sequence", "SQ", "1"}, -{{64, 41136}, "Referenced Waveform Channels", "US", "2-2n"}, -{{64, 41248}, "DateTime", "DT", "1"}, -{{64, 41249}, "Date", "DA", "1"}, -{{64, 41250}, "Time", "TM", "1"}, -{{64, 41251}, "Person Name", "PN", "1"}, -{{64, 41252}, "UID", "UI", "1"}, -{{64, 41264}, "Temporal Range Type", "CS", "1"}, -{{64, 41266}, "Referenced Sample Positions", "UL", "1-n"}, -{{64, 41270}, "Referenced Frame Numbers", "US", "1-n"}, -{{64, 41272}, "Referenced Time Offsets", "DS", "1-n"}, -{{64, 41274}, "Referenced Datetime", "DT", "1-n"}, -{{64, 41312}, "Text Value", "UT", "1"}, -{{64, 41320}, "Concept Code Sequence", "SQ", "1"}, -{{64, 41328}, "Purpose of Reference Code Sequence", "SQ", "1"}, -{{64, 41344}, "Annotation Group Number", "US", "1"}, -{{64, 41365}, "Modifier Code Sequence", "SQ", "1"}, -{{64, 41728}, "Measured Value Sequence", "SQ", "1"}, -{{64, 41729}, "Numeric Value Qualifier Code Sequence", "SQ", "1"}, -{{64, 41738}, "Numeric Value", "DS", "1-n"}, -{{64, 41824}, "Predecessor Documents Sequence", "SQ", "1"}, -{{64, 41840}, "Referenced Request Sequence", "SQ", "1"}, -{{64, 41842}, "Performed Procedure Code Sequence", "SQ", "1"}, -{{64, 41845}, "Current Requested Procedure Evidence Sequence", "SQ", "1"}, -{{64, 41861}, "Pertinent Other Evidence Sequence", "SQ", "1"}, -{{64, 42129}, "Completion Flag", "CS", "1"}, -{{64, 42130}, "Completion Flag Description", "LO", "1"}, -{{64, 42131}, "Verification Flag", "CS", "1"}, -{{64, 42244}, "Content Template Sequence", "SQ", "1"}, -{{64, 42277}, "Identical Documents Sequence", "SQ", "1"}, -{{64, 42800}, "Content Sequence", "SQ", "1"}, -{{64, 45088}, "Annotation Sequence", "SQ", "1"}, -{{64, 56064}, "Template Identifier", "CS", "1"}, -{{64, 56179}, "Referenced Content Item Identifier", "UL", "1-n"}, -{{80, 4}, "Calibration Image", "CS", "1"}, -{{80, 16}, "Device Sequence", "SQ", "1"}, -{{80, 20}, "Device Length", "DS", "1"}, -{{80, 22}, "Device Diameter", "DS", "1"}, -{{80, 23}, "Device Diameter Units", "CS", "1"}, -{{80, 24}, "Device Volume", "DS", "1"}, -{{80, 25}, "Inter-marker Distance", "DS", "1"}, -{{80, 32}, "Device Description", "LO", "1"}, -{{84, 16}, "Energy Window Vector", "US", "1-n"}, -{{84, 17}, "Number of Energy Windows", "US", "1"}, -{{84, 18}, "Energy Window Information Sequence", "SQ", "1"}, -{{84, 19}, "Energy Window Range Sequence", "SQ", "1"}, -{{84, 20}, "Energy Window Lower Limit", "DS", "1"}, -{{84, 21}, "Energy Window Upper Limit", "DS", "1"}, -{{84, 22}, "Radiopharmaceutical Information Sequence", "SQ", "1"}, -{{84, 23}, "Residual Syringe Counts", "IS", "1"}, -{{84, 24}, "Energy Window Name", "SH", "1"}, -{{84, 32}, "Detector Vector", "US", "1-n"}, -{{84, 33}, "Number of Detectors", "US", "1"}, -{{84, 34}, "Detector Information Sequence", "SQ", "1"}, -{{84, 48}, "Phase Vector", "US", "1-n"}, -{{84, 49}, "Number of Phases", "US", "1"}, -{{84, 50}, "Phase Information Sequence", "SQ", "1"}, -{{84, 51}, "Number of Frames in Phase", "US", "1"}, -{{84, 54}, "Phase Delay", "IS", "1"}, -{{84, 56}, "Pause Between Frames", "IS", "1"}, -{{84, 57}, "Phase Description", "CS", "1"}, -{{84, 80}, "Rotation Vector", "US", "1-n"}, -{{84, 81}, "Number of Rotations", "US", "1"}, -{{84, 82}, "Rotation Information Sequence", "SQ", "1"}, -{{84, 83}, "Number of Frames in Rotation", "US", "1"}, -{{84, 96}, "R-R Interval Vector", "US", "1-n"}, -{{84, 97}, "Number of R-R Intervals", "US", "1"}, -{{84, 98}, "Gated Information Sequence", "SQ", "1"}, -{{84, 99}, "Data Information Sequence", "SQ", "1"}, -{{84, 112}, "Time Slot Vector", "US", "1-n"}, -{{84, 113}, "Number of Time Slots", "US", "1"}, -{{84, 114}, "Time Slot Information Sequence", "SQ", "1"}, -{{84, 115}, "Time Slot Time", "DS", "1"}, -{{84, 128}, "Slice Vector", "US", "1-n"}, -{{84, 129}, "Number of Slices", "US", "1"}, -{{84, 144}, "Angular View Vector", "US", "1-n"}, -{{84, 256}, "Time Slice Vector", "US", "1-n"}, -{{84, 257}, "Number of Time Slices", "US", "1"}, -{{84, 512}, "Start Angle", "DS", "1"}, -{{84, 514}, "Type of Detector Motion", "CS", "1"}, -{{84, 528}, "Trigger Vector", "IS", "1-n"}, -{{84, 529}, "Number of Triggers in Phase", "US", "1"}, -{{84, 544}, "View Code Sequence", "SQ", "1"}, -{{84, 546}, "View Modifier Code Sequence", "SQ", "1"}, -{{84, 768}, "Radionuclide Code Sequence", "SQ", "1"}, -{{84, 770}, "Administration Route Code Sequence", "SQ", "1"}, -{{84, 772}, "Radiopharmaceutical Code Sequence", "SQ", "1"}, -{{84, 774}, "Calibration Data Sequence", "SQ", "1"}, -{{84, 776}, "Energy Window Number", "US", "1"}, -{{84, 1024}, "Image ID", "SH", "1"}, -{{84, 1040}, "Patient Orientation Code Sequence", "SQ", "1"}, -{{84, 1042}, "Patient Orientation Modifier Code Sequence", "SQ", "1"}, -{{84, 1044}, "Patient Gantry Relationship Code Sequence", "SQ", "1"}, -{{84, 1280}, "Slice Progression Direction", "CS", "1"}, -{{84, 4096}, "Series Type", "CS", "2"}, -{{84, 4097}, "Units", "CS", "1"}, -{{84, 4098}, "Counts Source", "CS", "1"}, -{{84, 4100}, "Reprojection Method", "CS", "1"}, -{{84, 4352}, "Randoms Correction Method", "CS", "1"}, -{{84, 4353}, "Attenuation Correction Method", "LO", "1"}, -{{84, 4354}, "Decay Correction", "CS", "1"}, -{{84, 4355}, "Reconstruction Method", "LO", "1"}, -{{84, 4356}, "Detector Lines of Response Used", "LO", "1"}, -{{84, 4357}, "Scatter Correction Method", "LO", "1"}, -{{84, 4608}, "Axial Acceptance", "DS", "1"}, -{{84, 4609}, "Axial Mash", "IS", "2"}, -{{84, 4610}, "Transverse Mash", "IS", "1"}, -{{84, 4611}, "Detector Element Size", "DS", "2"}, -{{84, 4624}, "Coincidence Window Width", "DS", "1"}, -{{84, 4640}, "Secondary Counts Type", "CS", "1-n"}, -{{84, 4864}, "Frame Reference Time", "DS", "1"}, -{{84, 4880}, "Primary (Prompts) Counts Accumulated", "IS", "1"}, -{{84, 4881}, "Secondary Counts Accumulated", "IS", "1-n"}, -{{84, 4896}, "Slice Sensitivity Factor", "DS", "1"}, -{{84, 4897}, "Decay Factor", "DS", "1"}, -{{84, 4898}, "Dose Calibration Factor", "DS", "1"}, -{{84, 4899}, "Scatter Fraction Factor", "DS", "1"}, -{{84, 4900}, "Dead Time Factor", "DS", "1"}, -{{84, 4912}, "Image Index", "US", "1"}, -{{84, 5120}, "Counts Included", "CS", "1-n"}, -{{84, 5121}, "Dead Time Correction Flag", "CS", "1"}, -{{96, 12288}, "Histogram Sequence", "SQ", "1"}, -{{96, 12290}, "Histogram Number of Bins", "US", "1"}, -{{96, 12292}, "Histogram First Bin Value", "US", "1"}, -{{96, 12294}, "Histogram Last Bin Value", "US", "1"}, -{{96, 12296}, "Histogram Bin Width", "US", "1"}, -{{96, 12304}, "Histogram Explanation", "LO", "1"}, -{{96, 12320}, "Histogram Data", "UL", "1-n"}, -{{112, 1}, "Graphic Annotation Sequence", "SQ", "1"}, -{{112, 2}, "Graphic Layer", "CS", "1"}, -{{112, 3}, "Bounding Box Annotation Units", "CS", "1"}, -{{112, 4}, "Anchor Point Annotation Units", "CS", "1"}, -{{112, 5}, "Graphic Annotation Units", "CS", "1"}, -{{112, 6}, "Unformatted Text Value", "ST", "1"}, -{{112, 8}, "Text Object Sequence", "SQ", "1"}, -{{112, 9}, "Graphic Object Sequence", "SQ", "1"}, -{{112, 16}, "Bounding Box Top Left Hand Corner", "FL", "2"}, -{{112, 17}, "Bounding Box Bottom Right Hand Corner", "FL", "2"}, -{{112, 18}, "Bounding Box Text Horizontal Justification", "CS", "1"}, -{{112, 20}, "Anchor Point", "FL", "2"}, -{{112, 21}, "Anchor Point Visibility", "CS", "1"}, -{{112, 32}, "Graphic Dimensions", "US", "1"}, -{{112, 33}, "Number of Graphic Points", "US", "1"}, -{{112, 34}, "Graphic Data", "FL", "2-n"}, -{{112, 35}, "Graphic Type", "CS", "1"}, -{{112, 36}, "Graphic Filled", "CS", "1"}, -{{112, 65}, "Image Horizontal Flip", "CS", "1"}, -{{112, 66}, "Image Rotation", "US", "1"}, -{{112, 82}, "Displayed Area Top Left Hand Corner", "SL", "2"}, -{{112, 83}, "Displayed Area Bottom Right Hand Corner", "SL", "2"}, -{{112, 90}, "Displayed Area Selection Sequence", "SQ", "1"}, -{{112, 96}, "Graphic Layer Sequence", "SQ", "1"}, -{{112, 98}, "Graphic Layer Order", "IS", "1"}, -{{112, 102}, "Graphic Layer Recommended Display Grayscale Value", "US", "1"}, -{{112, 103}, "Graphic Layer Recommended Display RGB Value", "US", "3"}, -{{112, 104}, "Graphic Layer Description", "LO", "1"}, -{{112, 128}, "Content Label", "CS", "1"}, -{{112, 129}, "Content Description", "LO", "1"}, -{{112, 130}, "Presentation Creation Date", "DA", "1"}, -{{112, 131}, "Presentation Creation Time", "TM", "1"}, -{{112, 132}, "Content Creator's Name", "PN", "1"}, -{{112, 256}, "Presentation Size Mode", "CS", "1"}, -{{112, 257}, "Presentation Pixel Spacing", "DS", "2"}, -{{112, 258}, "Presentation Pixel Aspect Ratio", "IS", "2"}, -{{112, 259}, "Presentation Pixel Magnification Ratio", "FL", "1"}, -{{112, 774}, "Shape Type", "CS", "1"}, -{{112, 776}, "Registration Sequence", "SQ", "1"}, -{{112, 777}, "Matrix Registration Sequence", "SQ", "1"}, -{{112, 778}, "Matrix Sequence", "SQ", "1"}, -{{112, 780}, "Frame of Reference Transformation Matrix Type", "CS", "1"}, -{{112, 781}, "Registration Type Code Sequence", "SQ", "1"}, -{{112, 783}, "Fiducial Description", "ST", "1"}, -{{112, 784}, "Fiducial Identifier", "SH", "1"}, -{{112, 785}, "Fiducial Identifier Code Sequence", "SQ", "1"}, -{{112, 786}, "Contour Uncertainty Radius", "FD", "1"}, -{{112, 788}, "Used Fiducials Sequence", "SQ", "1"}, -{{112, 792}, "Graphic Coordinates Data Sequence", "SQ", "1"}, -{{112, 794}, "Fiducial UID", "UI", "1"}, -{{112, 796}, "Fiducial Set Sequence", "SQ", "1"}, -{{112, 798}, "Fiducial Sequence", "SQ", "1"}, -{{136, 304}, "Storage Media File-set ID", "SH", "1"}, -{{136, 320}, "Storage Media File-set UID", "UI", "1"}, -{{136, 512}, "Icon Image Sequence", "SQ", "1"}, -{{136, 2308}, "Topic Title", "LO", "1"}, -{{136, 2310}, "Topic Subject", "ST", "1"}, -{{136, 2320}, "Topic Author", "LO", "1"}, -{{136, 2322}, "Topic Key Words", "LO", "1-32"}, -{{256, 1040}, "SOP Instance Status", "CS", "1"}, -{{256, 1056}, "SOP Authorization Date and Time", "DT", "1"}, -{{256, 1060}, "SOP Authorization Comment", "LT", "1"}, -{{256, 1062}, "Authorization Equipment Certification Number", "LO", "1"}, -{{1024, 5}, "MAC ID Number", "US", "1"}, -{{1024, 16}, "MAC Calculation Transfer Syntax UID", "UI", "1"}, -{{1024, 21}, "MAC Algorithm", "CS", "1"}, -{{1024, 32}, "Data Elements Signed", "AT", "1-n"}, -{{1024, 256}, "Digital Signature UID", "UI", "1"}, -{{1024, 261}, "Digital Signature DateTime", "DT", "1"}, -{{1024, 272}, "Certificate Type", "CS", "1"}, -{{1024, 277}, "Certificate of Signer", "OB", "1"}, -{{1024, 288}, "Signature", "OB", "1"}, -{{1024, 773}, "Certified Timestamp Type", "CS", "1"}, -{{1024, 784}, "Certified Timestamp", "OB", "1"}, -{{1024, 1280}, "Encrypted Attributes Sequence", "SQ", "1"}, -{{1024, 1296}, "Encrypted Content Transfer Syntax UID", "UI", "1"}, -{{1024, 1312}, "Encrypted Content", "OB", "1"}, -{{1024, 1360}, "Modified Attributes Sequence", "SQ", "1"}, -{{8192, 16}, "Number of Copies", "IS", "1"}, -{{8192, 30}, "Printer Configuration Sequence", "SQ", "1"}, -{{8192, 32}, "Print Priority", "CS", "1"}, -{{8192, 48}, "Medium Type", "CS", "1"}, -{{8192, 64}, "Film Destination", "CS", "1"}, -{{8192, 80}, "Film Session Label", "LO", "1"}, -{{8192, 96}, "Memory Allocation", "IS", "1"}, -{{8192, 97}, "Maximum Memory Allocation", "IS", "1"}, -{{8192, 98}, "Color Image Printing Flag", "CS", "1"}, -{{8192, 99}, "Collation Flag", "CS", "1"}, -{{8192, 101}, "Annotation Flag", "CS", "1"}, -{{8192, 103}, "Image Overlay Flag", "CS", "1"}, -{{8192, 105}, "Presentation LUT Flag", "CS", "1"}, -{{8192, 106}, "Image Box Presentation LUT Flag", "CS", "1"}, -{{8192, 160}, "Memory Bit Depth", "US", "1"}, -{{8192, 161}, "Printing Bit Depth", "US", "1"}, -{{8192, 162}, "Media Installed Sequence", "SQ", "1"}, -{{8192, 164}, "Other Media Available Sequence", "SQ", "1"}, -{{8192, 168}, "Supported Image Display Formats Sequence", "SQ", "1"}, -{{8192, 1280}, "Referenced Film Box Sequence", "SQ", "1"}, -{{8192, 1296}, "Referenced Stored Print Sequence", "SQ", "1"}, -{{8208, 16}, "Image Display Format", "ST", "1"}, -{{8208, 48}, "Annotation Display Format ID", "CS", "1"}, -{{8208, 64}, "Film Orientation", "CS", "1"}, -{{8208, 80}, "Film Size ID", "CS", "1"}, -{{8208, 82}, "Printer Resolution ID", "CS", "1"}, -{{8208, 84}, "Default Printer Resolution ID", "CS", "1"}, -{{8208, 96}, "Magnification Type", "CS", "1"}, -{{8208, 128}, "Smoothing Type", "CS", "1"}, -{{8208, 166}, "Default Magnification Type", "CS", "1"}, -{{8208, 167}, "Other Magnification Types Available", "CS", "1-n"}, -{{8208, 168}, "Default Smoothing Type", "CS", "1"}, -{{8208, 169}, "Other Smoothing Types Available", "CS", "1-n"}, -{{8208, 256}, "Border Density", "CS", "1"}, -{{8208, 272}, "Empty Image Density", "CS", "1"}, -{{8208, 288}, "Min Density", "US", "1"}, -{{8208, 304}, "Max Density", "US", "1"}, -{{8208, 320}, "Trim", "CS", "1"}, -{{8208, 336}, "Configuration Information", "ST", "1"}, -{{8208, 338}, "Configuration Information Description", "LT", "1"}, -{{8208, 340}, "Maximum Collated Films", "IS", "1"}, -{{8208, 350}, "Illumination", "US", "1"}, -{{8208, 352}, "Reflected Ambient Light", "US", "1"}, -{{8208, 886}, "Printer Pixel Spacing", "DS", "2"}, -{{8208, 1280}, "Referenced Film Session Sequence", "SQ", "1"}, -{{8208, 1296}, "Referenced Image Box Sequence", "SQ", "1"}, -{{8208, 1312}, "Referenced Basic Annotation Box Sequence", "SQ", "1"}, -{{8224, 16}, "Image Position", "US", "1"}, -{{8224, 32}, "Polarity", "CS", "1"}, -{{8224, 48}, "Requested Image Size", "DS", "1"}, -{{8224, 64}, "Requested Decimate/Crop Behavior", "CS", "1"}, -{{8224, 80}, "Requested Resolution ID", "CS", "1"}, -{{8224, 160}, "Requested Image Size Flag", "CS", "1"}, -{{8224, 162}, "Decimate/Crop Result", "CS", "1"}, -{{8224, 272}, "Basic Grayscale Image Sequence", "SQ", "1"}, -{{8224, 273}, "Basic Color Image Sequence", "SQ", "1"}, -{{8240, 16}, "Annotation Position", "US", "1"}, -{{8240, 32}, "Text String", "LO", "1"}, -{{8256, 16}, "Referenced Overlay Plane Sequence", "SQ", "1"}, -{{8256, 17}, "Referenced Overlay Plane Groups", "US", "1-99"}, -{{8256, 32}, "Overlay Pixel Data Sequence", "SQ", "1"}, -{{8256, 96}, "Overlay Magnification Type", "CS", "1"}, -{{8256, 112}, "Overlay Smoothing Type", "CS", "1"}, -{{8256, 114}, "Overlay or Image Magnification", "CS", "1"}, -{{8256, 116}, "Magnify to Number of Columns", "US", "1"}, -{{8256, 128}, "Overlay Foreground Density", "CS", "1"}, -{{8256, 130}, "Overlay Background Density", "CS", "1"}, -{{8272, 16}, "Presentation LUT Sequence", "SQ", "1"}, -{{8272, 32}, "Presentation LUT Shape", "CS", "1"}, -{{8272, 1280}, "Referenced Presentation LUT Sequence", "SQ", "1"}, -{{8448, 16}, "Print Job ID", "SH", "1"}, -{{8448, 32}, "Execution Status", "CS", "1"}, -{{8448, 48}, "Execution Status Info", "CS", "1"}, -{{8448, 64}, "Creation Date", "DA", "1"}, -{{8448, 80}, "Creation Time", "TM", "1"}, -{{8448, 112}, "Originator", "AE", "1"}, -{{8448, 320}, "Destination AE", "AE", "1"}, -{{8448, 352}, "Owner ID", "SH", "1"}, -{{8448, 368}, "Number of Films", "IS", "1"}, -{{8448, 1280}, "Referenced Print Job Sequence", "SQ", "1"}, -{{8464, 16}, "Printer Status", "CS", "1"}, -{{8464, 32}, "Printer Status Info", "CS", "1"}, -{{8464, 48}, "Printer Name", "LO", "1"}, -{{8464, 153}, "Print Queue ID", "SH", "1"}, -{{8480, 16}, "Queue Status", "CS", "1"}, -{{8480, 80}, "Print Job Description Sequence", "SQ", "1"}, -{{8480, 112}, "Referenced Print Job Sequence", "SQ", "1"}, -{{8496, 16}, "Print Management Capabilities Sequence", "SQ", "1"}, -{{8496, 21}, "Printer Characteristics Sequence", "SQ", "1"}, -{{8496, 48}, "Film Box Content Sequence", "SQ", "1"}, -{{8496, 64}, "Image Box Content Sequence", "SQ", "1"}, -{{8496, 80}, "Annotation Content Sequence", "SQ", "1"}, -{{8496, 96}, "Image Overlay Box Content Sequence", "SQ", "1"}, -{{8496, 128}, "Presentation LUT Content Sequence", "SQ", "1"}, -{{8496, 160}, "Proposed Study Sequence", "SQ", "1"}, -{{8496, 192}, "Original Image Sequence", "SQ", "1"}, -{{8704, 1}, "Label Using Information Extracted From Instances", "CS", "1"}, -{{8704, 2}, "Label Text", "UT", "1"}, -{{8704, 3}, "Label Style Selection", "CS", "1"}, -{{8704, 4}, "Media Disposition", "LT", "1"}, -{{8704, 5}, "Barcode Value", "LT", "1"}, -{{8704, 6}, "Barcode Symbology", "CS", "1"}, -{{8704, 7}, "Allow Media Splitting", "CS", "1"}, -{{8704, 8}, "Include Non-DICOM Objects", "CS", "1"}, -{{8704, 9}, "Include Display Application", "CS", "1"}, -{{8704, 10}, "Preserve Composite Instances After Media Creation", "CS", "1"}, -{{8704, 11}, "Total Number of Pieces of Media Created", "US", "1"}, -{{8704, 12}, "Requested Media Application Profile", "LO", "1"}, -{{8704, 13}, "Referenced Storage Media Sequence", "SQ", "1"}, -{{8704, 14}, "Failure Attributes", "AT", "1-n"}, -{{8704, 15}, "Allow Lossy Compression", "CS", "1"}, -{{8704, 32}, "Request Priority", "CS", "1"}, -{{12290, 2}, "RT Image Label", "SH", "1"}, -{{12290, 3}, "RT Image Name", "LO", "1"}, -{{12290, 4}, "RT Image Description", "ST", "1"}, -{{12290, 10}, "Reported Values Origin", "CS", "1"}, -{{12290, 12}, "RT Image Plane", "CS", "1"}, -{{12290, 13}, "X-Ray Image Receptor Translation", "DS", "3"}, -{{12290, 14}, "X-Ray Image Receptor Angle", "DS", "1"}, -{{12290, 16}, "RT Image Orientation", "DS", "6"}, -{{12290, 17}, "Image Plane Pixel Spacing", "DS", "2"}, -{{12290, 18}, "RT Image Position", "DS", "2"}, -{{12290, 32}, "Radiation Machine Name", "SH", "1"}, -{{12290, 34}, "Radiation Machine SAD", "DS", "1"}, -{{12290, 36}, "Radiation Machine SSD", "DS", "1"}, -{{12290, 38}, "RT Image SID", "DS", "1"}, -{{12290, 40}, "Source to Reference Object Distance", "DS", "1"}, -{{12290, 41}, "Fraction Number", "IS", "1"}, -{{12290, 48}, "Exposure Sequence", "SQ", "1"}, -{{12290, 50}, "Meterset Exposure", "DS", "1"}, -{{12290, 52}, "Diaphragm Position", "DS", "4"}, -{{12290, 64}, "Fluence Map Sequence", "SQ", "1"}, -{{12290, 65}, "Fluence Data Source", "CS", "1"}, -{{12290, 66}, "Fluence Data Scale", "DS", "1"}, -{{12292, 1}, "DVH Type", "CS", "1"}, -{{12292, 2}, "Dose Units", "CS", "1"}, -{{12292, 4}, "Dose Type", "CS", "1"}, -{{12292, 6}, "Dose Comment", "LO", "1"}, -{{12292, 8}, "Normalization Point", "DS", "3"}, -{{12292, 10}, "Dose Summation Type", "CS", "1"}, -{{12292, 12}, "Grid Frame Offset Vector", "DS", "2-n"}, -{{12292, 14}, "Dose Grid Scaling", "DS", "1"}, -{{12292, 16}, "RT Dose ROI Sequence", "SQ", "1"}, -{{12292, 18}, "Dose Value", "DS", "1"}, -{{12292, 20}, "Tissue Heterogeneity Correction", "CS", "1-3"}, -{{12292, 64}, "DVH Normalization Point", "DS", "3"}, -{{12292, 66}, "DVH Normalization Dose Value", "DS", "1"}, -{{12292, 80}, "DVH Sequence", "SQ", "1"}, -{{12292, 82}, "DVH Dose Scaling", "DS", "1"}, -{{12292, 84}, "DVH Volume Units", "CS", "1"}, -{{12292, 86}, "DVH Number of Bins", "IS", "1"}, -{{12292, 88}, "DVH Data", "DS", "2-2n"}, -{{12292, 96}, "DVH Referenced ROI Sequence", "SQ", "1"}, -{{12292, 98}, "DVH ROI Contribution Type", "CS", "1"}, -{{12292, 112}, "DVH Minimum Dose", "DS", "1"}, -{{12292, 114}, "DVH Maximum Dose", "DS", "1"}, -{{12292, 116}, "DVH Mean Dose", "DS", "1"}, -{{12294, 2}, "Structure Set Label", "SH", "1"}, -{{12294, 4}, "Structure Set Name", "LO", "1"}, -{{12294, 6}, "Structure Set Description", "ST", "1"}, -{{12294, 8}, "Structure Set Date", "DA", "1"}, -{{12294, 9}, "Structure Set Time", "TM", "1"}, -{{12294, 16}, "Referenced Frame of Reference Sequence", "SQ", "1"}, -{{12294, 18}, "RT Referenced Study Sequence", "SQ", "1"}, -{{12294, 20}, "RT Referenced Series Sequence", "SQ", "1"}, -{{12294, 22}, "Contour Image Sequence", "SQ", "1"}, -{{12294, 32}, "Structure Set ROI Sequence", "SQ", "1"}, -{{12294, 34}, "ROI Number", "IS", "1"}, -{{12294, 36}, "Referenced Frame of Reference UID", "UI", "1"}, -{{12294, 38}, "ROI Name", "LO", "1"}, -{{12294, 40}, "ROI Description", "ST", "1"}, -{{12294, 42}, "ROI Display Color", "IS", "3"}, -{{12294, 44}, "ROI Volume", "DS", "1"}, -{{12294, 48}, "RT Related ROI Sequence", "SQ", "1"}, -{{12294, 51}, "RT ROI Relationship", "CS", "1"}, -{{12294, 54}, "ROI Generation Algorithm", "CS", "1"}, -{{12294, 56}, "ROI Generation Description", "LO", "1"}, -{{12294, 57}, "ROI Contour Sequence", "SQ", "1"}, -{{12294, 64}, "Contour Sequence", "SQ", "1"}, -{{12294, 66}, "Contour Geometric Type", "CS", "1"}, -{{12294, 68}, "Contour Slab Thickness", "DS", "1"}, -{{12294, 69}, "Contour Offset Vector", "DS", "3"}, -{{12294, 70}, "Number of Contour Points", "IS", "1"}, -{{12294, 72}, "Contour Number", "IS", "1"}, -{{12294, 73}, "Attached Contours", "IS", "1-n"}, -{{12294, 80}, "Contour Data", "DS", "3-3n"}, -{{12294, 128}, "RT ROI Observations Sequence", "SQ", "1"}, -{{12294, 130}, "Observation Number", "IS", "1"}, -{{12294, 132}, "Referenced ROI Number", "IS", "1"}, -{{12294, 133}, "ROI Observation Label", "SH", "1"}, -{{12294, 134}, "RT ROI Identification Code Sequence", "SQ", "1"}, -{{12294, 136}, "ROI Observation Description", "ST", "1"}, -{{12294, 160}, "Related RT ROI Observations Sequence", "SQ", "1"}, -{{12294, 164}, "RT ROI Interpreted Type", "CS", "1"}, -{{12294, 166}, "ROI Interpreter", "PN", "1"}, -{{12294, 176}, "ROI Physical Properties Sequence", "SQ", "1"}, -{{12294, 178}, "ROI Physical Property", "CS", "1"}, -{{12294, 180}, "ROI Physical Property Value", "DS", "1"}, -{{12294, 192}, "Frame of Reference Relationship Sequence", "SQ", "1"}, -{{12294, 194}, "Related Frame of Reference UID", "UI", "1"}, -{{12294, 196}, "Frame of Reference Transformation Type", "CS", "1"}, -{{12294, 198}, "Frame of Reference Transformation Matrix", "DS", "16"}, -{{12294, 200}, "Frame of Reference Transformation Comment", "LO", "1"}, -{{12296, 16}, "Measured Dose Reference Sequence", "SQ", "1"}, -{{12296, 18}, "Measured Dose Description", "ST", "1"}, -{{12296, 20}, "Measured Dose Type", "CS", "1"}, -{{12296, 22}, "Measured Dose Value", "DS", "1"}, -{{12296, 32}, "Treatment Session Beam Sequence", "SQ", "1"}, -{{12296, 34}, "Current Fraction Number", "IS", "1"}, -{{12296, 36}, "Treatment Control Point Date", "DA", "1"}, -{{12296, 37}, "Treatment Control Point Time", "TM", "1"}, -{{12296, 42}, "Treatment Termination Status", "CS", "1"}, -{{12296, 43}, "Treatment Termination Code", "SH", "1"}, -{{12296, 44}, "Treatment Verification Status", "CS", "1"}, -{{12296, 48}, "Referenced Treatment Record Sequence", "SQ", "1"}, -{{12296, 50}, "Specified Primary Meterset", "DS", "1"}, -{{12296, 51}, "Specified Secondary Meterset", "DS", "1"}, -{{12296, 54}, "Delivered Primary Meterset", "DS", "1"}, -{{12296, 55}, "Delivered Secondary Meterset", "DS", "1"}, -{{12296, 58}, "Specified Treatment Time", "DS", "1"}, -{{12296, 59}, "Delivered Treatment Time", "DS", "1"}, -{{12296, 64}, "Control Point Delivery Sequence", "SQ", "1"}, -{{12296, 66}, "Specified Meterset", "DS", "1"}, -{{12296, 68}, "Delivered Meterset", "DS", "1"}, -{{12296, 72}, "Dose Rate Delivered", "DS", "1"}, -{{12296, 80}, "Treatment Summary Calculated Dose Reference Sequence", "SQ", "1"}, -{{12296, 82}, "Cumulative Dose to Dose Reference", "DS", "1"}, -{{12296, 84}, "First Treatment Date", "DA", "1"}, -{{12296, 86}, "Most Recent Treatment Date", "DA", "1"}, -{{12296, 90}, "Number of Fractions Delivered", "IS", "1"}, -{{12296, 96}, "Override Sequence", "SQ", "1"}, -{{12296, 98}, "Override Parameter Pointer", "AT", "1"}, -{{12296, 100}, "Measured Dose Reference Number", "IS", "1"}, -{{12296, 102}, "Override Reason", "ST", "1"}, -{{12296, 112}, "Calculated Dose Reference Sequence", "SQ", "1"}, -{{12296, 114}, "Calculated Dose Reference Number", "IS", "1"}, -{{12296, 116}, "Calculated Dose Reference Description", "ST", "1"}, -{{12296, 118}, "Calculated Dose Reference Dose Value", "DS", "1"}, -{{12296, 120}, "Start Meterset", "DS", "1"}, -{{12296, 122}, "End Meterset", "DS", "1"}, -{{12296, 128}, "Referenced Measured Dose Reference Sequence", "SQ", "1"}, -{{12296, 130}, "Referenced Measured Dose Reference Number", "IS", "1"}, -{{12296, 144}, "Referenced Calculated Dose Reference Sequence", "SQ", "1"}, -{{12296, 146}, "Referenced Calculated Dose Reference Number", "IS", "1"}, -{{12296, 160}, "Beam Limiting Device Leaf Pairs Sequence", "SQ", "1"}, -{{12296, 176}, "Recorded Wedge Sequence", "SQ", "1"}, -{{12296, 192}, "Recorded Compensator Sequence", "SQ", "1"}, -{{12296, 208}, "Recorded Block Sequence", "SQ", "1"}, -{{12296, 224}, "Treatment Summary Measured Dose Reference Sequence", "SQ", "1"}, -{{12296, 256}, "Recorded Source Sequence", "SQ", "1"}, -{{12296, 261}, "Source Serial Number", "LO", "1"}, -{{12296, 272}, "Treatment Session Application Setup Sequence", "SQ", "1"}, -{{12296, 278}, "Application Setup Check", "CS", "1"}, -{{12296, 288}, "Recorded Brachy Accessory Device Sequence", "SQ", "1"}, -{{12296, 290}, "Referenced Brachy Accessory Device Number", "IS", "1"}, -{{12296, 304}, "Recorded Channel Sequence", "SQ", "1"}, -{{12296, 306}, "Specified Channel Total Time", "DS", "1"}, -{{12296, 308}, "Delivered Channel Total Time", "DS", "1"}, -{{12296, 310}, "Specified Number of Pulses", "IS", "1"}, -{{12296, 312}, "Delivered Number of Pulses", "IS", "1"}, -{{12296, 314}, "Specified Pulse Repetition Interval", "DS", "1"}, -{{12296, 316}, "Delivered Pulse Repetition Interval", "DS", "1"}, -{{12296, 320}, "Recorded Source Applicator Sequence", "SQ", "1"}, -{{12296, 322}, "Referenced Source Applicator Number", "IS", "1"}, -{{12296, 336}, "Recorded Channel Shield Sequence", "SQ", "1"}, -{{12296, 338}, "Referenced Channel Shield Number", "IS", "1"}, -{{12296, 352}, "Brachy Control Point Delivered Sequence", "SQ", "1"}, -{{12296, 354}, "Safe Position Exit Date", "DA", "1"}, -{{12296, 356}, "Safe Position Exit Time", "TM", "1"}, -{{12296, 358}, "Safe Position Return Date", "DA", "1"}, -{{12296, 360}, "Safe Position Return Time", "TM", "1"}, -{{12296, 512}, "Current Treatment Status", "CS", "1"}, -{{12296, 514}, "Treatment Status Comment", "ST", "1"}, -{{12296, 544}, "Fraction Group Summary Sequence", "SQ", "1"}, -{{12296, 547}, "Referenced Fraction Number", "IS", "1"}, -{{12296, 548}, "Fraction Group Type", "CS", "1"}, -{{12296, 560}, "Beam Stopper Position", "CS", "1"}, -{{12296, 576}, "Fraction Status Summary Sequence", "SQ", "1"}, -{{12296, 592}, "Treatment Date", "DA", "1"}, -{{12296, 593}, "Treatment Time", "TM", "1"}, -{{12298, 2}, "RT Plan Label", "SH", "1"}, -{{12298, 3}, "RT Plan Name", "LO", "1"}, -{{12298, 4}, "RT Plan Description", "ST", "1"}, -{{12298, 6}, "RT Plan Date", "DA", "1"}, -{{12298, 7}, "RT Plan Time", "TM", "1"}, -{{12298, 9}, "Treatment Protocols", "LO", "1-n"}, -{{12298, 10}, "Treatment Intent", "CS", "1"}, -{{12298, 11}, "Treatment Sites", "LO", "1-n"}, -{{12298, 12}, "RT Plan Geometry", "CS", "1"}, -{{12298, 14}, "Prescription Description", "ST", "1"}, -{{12298, 16}, "Dose Reference Sequence", "SQ", "1"}, -{{12298, 18}, "Dose Reference Number", "IS", "1"}, -{{12298, 19}, "Dose Reference UID", "UI", "1"}, -{{12298, 20}, "Dose Reference Structure Type", "CS", "1"}, -{{12298, 21}, "Nominal Beam Energy Unit", "CS", "1"}, -{{12298, 22}, "Dose Reference Description", "LO", "1"}, -{{12298, 24}, "Dose Reference Point Coordinates", "DS", "3"}, -{{12298, 26}, "Nominal Prior Dose", "DS", "1"}, -{{12298, 32}, "Dose Reference Type", "CS", "1"}, -{{12298, 33}, "Constraint Weight", "DS", "1"}, -{{12298, 34}, "Delivery Warning Dose", "DS", "1"}, -{{12298, 35}, "Delivery Maximum Dose", "DS", "1"}, -{{12298, 37}, "Target Minimum Dose", "DS", "1"}, -{{12298, 38}, "Target Prescription Dose", "DS", "1"}, -{{12298, 39}, "Target Maximum Dose", "DS", "1"}, -{{12298, 40}, "Target Underdose Volume Fraction", "DS", "1"}, -{{12298, 42}, "Organ at Risk Full-volume Dose", "DS", "1"}, -{{12298, 43}, "Organ at Risk Limit Dose", "DS", "1"}, -{{12298, 44}, "Organ at Risk Maximum Dose", "DS", "1"}, -{{12298, 45}, "Organ at Risk Overdose Volume Fraction", "DS", "1"}, -{{12298, 64}, "Tolerance Table Sequence", "SQ", "1"}, -{{12298, 66}, "Tolerance Table Number", "IS", "1"}, -{{12298, 67}, "Tolerance Table Label", "SH", "1"}, -{{12298, 68}, "Gantry Angle Tolerance", "DS", "1"}, -{{12298, 70}, "Beam Limiting Device Angle Tolerance", "DS", "1"}, -{{12298, 72}, "Beam Limiting Device Tolerance Sequence", "SQ", "1"}, -{{12298, 74}, "Beam Limiting Device Position Tolerance", "DS", "1"}, -{{12298, 76}, "Patient Support Angle Tolerance", "DS", "1"}, -{{12298, 78}, "Table Top Eccentric Angle Tolerance", "DS", "1"}, -{{12298, 81}, "Table Top Vertical Position Tolerance", "DS", "1"}, -{{12298, 82}, "Table Top Longitudinal Position Tolerance", "DS", "1"}, -{{12298, 83}, "Table Top Lateral Position Tolerance", "DS", "1"}, -{{12298, 85}, "RT Plan Relationship", "CS", "1"}, -{{12298, 112}, "Fraction Group Sequence", "SQ", "1"}, -{{12298, 113}, "Fraction Group Number", "IS", "1"}, -{{12298, 114}, "Fraction Group Description", "LO", "1"}, -{{12298, 120}, "Number of Fractions Planned", "IS", "1"}, -{{12298, 121}, "Number of Fraction Pattern Digits Per Day", "IS", "1"}, -{{12298, 122}, "Repeat Fraction Cycle Length", "IS", "1"}, -{{12298, 123}, "Fraction Pattern", "LT", "1"}, -{{12298, 128}, "Number of Beams", "IS", "1"}, -{{12298, 130}, "Beam Dose Specification Point", "DS", "3"}, -{{12298, 132}, "Beam Dose", "DS", "1"}, -{{12298, 134}, "Beam Meterset", "DS", "1"}, -{{12298, 160}, "Number of Brachy Application Setups", "IS", "1"}, -{{12298, 162}, "Brachy Application Setup Dose Specification Point", "DS", "3"}, -{{12298, 164}, "Brachy Application Setup Dose", "DS", "1"}, -{{12298, 176}, "Beam Sequence", "SQ", "1"}, -{{12298, 178}, "Treatment Machine Name", "SH", "1"}, -{{12298, 179}, "Primary Dosimeter Unit", "CS", "1"}, -{{12298, 180}, "Source-Axis Distance", "DS", "1"}, -{{12298, 182}, "Beam Limiting Device Sequence", "SQ", "1"}, -{{12298, 184}, "RT Beam Limiting Device Type", "CS", "1"}, -{{12298, 186}, "Source to Beam Limiting Device Distance", "DS", "1"}, -{{12298, 188}, "Number of Leaf/Jaw Pairs", "IS", "1"}, -{{12298, 190}, "Leaf Position Boundaries", "DS", "3-n"}, -{{12298, 192}, "Beam Number", "IS", "1"}, -{{12298, 194}, "Beam Name", "LO", "1"}, -{{12298, 195}, "Beam Description", "ST", "1"}, -{{12298, 196}, "Beam Type", "CS", "1"}, -{{12298, 198}, "Radiation Type", "CS", "1"}, -{{12298, 199}, "High-Dose Technique Type", "CS", "1"}, -{{12298, 200}, "Reference Image Number", "IS", "1"}, -{{12298, 202}, "Planned Verification Image Sequence", "SQ", "1"}, -{{12298, 204}, "Imaging Device-Specific Acquisition Parameters", "LO", "1-n"}, -{{12298, 206}, "Treatment Delivery Type", "CS", "1"}, -{{12298, 208}, "Number of Wedges", "IS", "1"}, -{{12298, 209}, "Wedge Sequence", "SQ", "1"}, -{{12298, 210}, "Wedge Number", "IS", "1"}, -{{12298, 211}, "Wedge Type", "CS", "1"}, -{{12298, 212}, "Wedge ID", "SH", "1"}, -{{12298, 213}, "Wedge Angle", "IS", "1"}, -{{12298, 214}, "Wedge Factor", "DS", "1"}, -{{12298, 216}, "Wedge Orientation", "DS", "1"}, -{{12298, 218}, "Source to Wedge Tray Distance", "DS", "1"}, -{{12298, 224}, "Number of Compensators", "IS", "1"}, -{{12298, 225}, "Material ID", "SH", "1"}, -{{12298, 226}, "Total Compensator Tray Factor", "DS", "1"}, -{{12298, 227}, "Compensator Sequence", "SQ", "1"}, -{{12298, 228}, "Compensator Number", "IS", "1"}, -{{12298, 229}, "Compensator ID", "SH", "1"}, -{{12298, 230}, "Source to Compensator Tray Distance", "DS", "1"}, -{{12298, 231}, "Compensator Rows", "IS", "1"}, -{{12298, 232}, "Compensator Columns", "IS", "1"}, -{{12298, 233}, "Compensator Pixel Spacing", "DS", "2"}, -{{12298, 234}, "Compensator Position", "DS", "2"}, -{{12298, 235}, "Compensator Transmission Data", "DS", "1-n"}, -{{12298, 236}, "Compensator Thickness Data", "DS", "1-n"}, -{{12298, 237}, "Number of Boli", "IS", "1"}, -{{12298, 238}, "Compensator Type", "CS", "1"}, -{{12298, 240}, "Number of Blocks", "IS", "1"}, -{{12298, 242}, "Total Block Tray Factor", "DS", "1"}, -{{12298, 244}, "Block Sequence", "SQ", "1"}, -{{12298, 245}, "Block Tray ID", "SH", "1"}, -{{12298, 246}, "Source to Block Tray Distance", "DS", "1"}, -{{12298, 248}, "Block Type", "CS", "1"}, -{{12298, 249}, "Accessory Code", "LO", "1"}, -{{12298, 250}, "Block Divergence", "CS", "1"}, -{{12298, 251}, "Block Mounting Position", "CS", "1"}, -{{12298, 252}, "Block Number", "IS", "1"}, -{{12298, 254}, "Block Name", "LO", "1"}, -{{12298, 256}, "Block Thickness", "DS", "1"}, -{{12298, 258}, "Block Transmission", "DS", "1"}, -{{12298, 260}, "Block Number of Points", "IS", "1"}, -{{12298, 262}, "Block Data", "DS", "2-2n"}, -{{12298, 263}, "Applicator Sequence", "SQ", "1"}, -{{12298, 264}, "Applicator ID", "SH", "1"}, -{{12298, 265}, "Applicator Type", "CS", "1"}, -{{12298, 266}, "Applicator Description", "LO", "1"}, -{{12298, 268}, "Cumulative Dose Reference Coefficient", "DS", "1"}, -{{12298, 270}, "Final Cumulative Meterset Weight", "DS", "1"}, -{{12298, 272}, "Number of Control Points", "IS", "1"}, -{{12298, 273}, "Control Point Sequence", "SQ", "1"}, -{{12298, 274}, "Control Point Index", "IS", "1"}, -{{12298, 276}, "Nominal Beam Energy", "DS", "1"}, -{{12298, 277}, "Dose Rate Set", "DS", "1"}, -{{12298, 278}, "Wedge Position Sequence", "SQ", "1"}, -{{12298, 280}, "Wedge Position", "CS", "1"}, -{{12298, 282}, "Beam Limiting Device Position Sequence", "SQ", "1"}, -{{12298, 284}, "Leaf/Jaw Positions", "DS", "2-2n"}, -{{12298, 286}, "Gantry Angle", "DS", "1"}, -{{12298, 287}, "Gantry Rotation Direction", "CS", "1"}, -{{12298, 288}, "Beam Limiting Device Angle", "DS", "1"}, -{{12298, 289}, "Beam Limiting Device Rotation Direction", "CS", "1"}, -{{12298, 290}, "Patient Support Angle", "DS", "1"}, -{{12298, 291}, "Patient Support Rotation Direction", "CS", "1"}, -{{12298, 292}, "Table Top Eccentric Axis Distance", "DS", "1"}, -{{12298, 293}, "Table Top Eccentric Angle", "DS", "1"}, -{{12298, 294}, "Table Top Eccentric Rotation Direction", "CS", "1"}, -{{12298, 296}, "Table Top Vertical Position", "DS", "1"}, -{{12298, 297}, "Table Top Longitudinal Position", "DS", "1"}, -{{12298, 298}, "Table Top Lateral Position", "DS", "1"}, -{{12298, 300}, "Isocenter Position", "DS", "3"}, -{{12298, 302}, "Surface Entry Point", "DS", "3"}, -{{12298, 304}, "Source to Surface Distance", "DS", "1"}, -{{12298, 308}, "Cumulative Meterset Weight", "DS", "1"}, -{{12298, 384}, "Patient Setup Sequence", "SQ", "1"}, -{{12298, 386}, "Patient Setup Number", "IS", "1"}, -{{12298, 388}, "Patient Additional Position", "LO", "1"}, -{{12298, 400}, "Fixation Device Sequence", "SQ", "1"}, -{{12298, 402}, "Fixation Device Type", "CS", "1"}, -{{12298, 404}, "Fixation Device Label", "SH", "1"}, -{{12298, 406}, "Fixation Device Description", "ST", "1"}, -{{12298, 408}, "Fixation Device Position", "SH", "1"}, -{{12298, 416}, "Shielding Device Sequence", "SQ", "1"}, -{{12298, 418}, "Shielding Device Type", "CS", "1"}, -{{12298, 420}, "Shielding Device Label", "SH", "1"}, -{{12298, 422}, "Shielding Device Description", "ST", "1"}, -{{12298, 424}, "Shielding Device Position", "SH", "1"}, -{{12298, 432}, "Setup Technique", "CS", "1"}, -{{12298, 434}, "Setup Technique Description", "ST", "1"}, -{{12298, 436}, "Setup Device Sequence", "SQ", "1"}, -{{12298, 438}, "Setup Device Type", "CS", "1"}, -{{12298, 440}, "Setup Device Label", "SH", "1"}, -{{12298, 442}, "Setup Device Description", "ST", "1"}, -{{12298, 444}, "Setup Device Parameter", "DS", "1"}, -{{12298, 464}, "Setup Reference Description", "ST", "1"}, -{{12298, 466}, "Table Top Vertical Setup Displacement", "DS", "1"}, -{{12298, 468}, "Table Top Longitudinal Setup Displacement", "DS", "1"}, -{{12298, 470}, "Table Top Lateral Setup Displacement", "DS", "1"}, -{{12298, 512}, "Brachy Treatment Technique", "CS", "1"}, -{{12298, 514}, "Brachy Treatment Type", "CS", "1"}, -{{12298, 518}, "Treatment Machine Sequence", "SQ", "1"}, -{{12298, 528}, "Source Sequence", "SQ", "1"}, -{{12298, 530}, "Source Number", "IS", "1"}, -{{12298, 532}, "Source Type", "CS", "1"}, -{{12298, 534}, "Source Manufacturer", "LO", "1"}, -{{12298, 536}, "Active Source Diameter", "DS", "1"}, -{{12298, 538}, "Active Source Length", "DS", "1"}, -{{12298, 546}, "Source Encapsulation Nominal Thickness", "DS", "1"}, -{{12298, 548}, "Source Encapsulation Nominal Transmission", "DS", "1"}, -{{12298, 550}, "Source Isotope Name", "LO", "1"}, -{{12298, 552}, "Source Isotope Half Life", "DS", "1"}, -{{12298, 554}, "Reference Air Kerma Rate", "DS", "1"}, -{{12298, 556}, "Air Kerma Rate Reference Date", "DA", "1"}, -{{12298, 558}, "Air Kerma Rate Reference Time", "TM", "1"}, -{{12298, 560}, "Application Setup Sequence", "SQ", "1"}, -{{12298, 562}, "Application Setup Type", "CS", "1"}, -{{12298, 564}, "Application Setup Number", "IS", "1"}, -{{12298, 566}, "Application Setup Name", "LO", "1"}, -{{12298, 568}, "Application Setup Manufacturer", "LO", "1"}, -{{12298, 576}, "Template Number", "IS", "1"}, -{{12298, 578}, "Template Type", "SH", "1"}, -{{12298, 580}, "Template Name", "LO", "1"}, -{{12298, 592}, "Total Reference Air Kerma", "DS", "1"}, -{{12298, 608}, "Brachy Accessory Device Sequence", "SQ", "1"}, -{{12298, 610}, "Brachy Accessory Device Number", "IS", "1"}, -{{12298, 611}, "Brachy Accessory Device ID", "SH", "1"}, -{{12298, 612}, "Brachy Accessory Device Type", "CS", "1"}, -{{12298, 614}, "Brachy Accessory Device Name", "LO", "1"}, -{{12298, 618}, "Brachy Accessory Device Nominal Thickness", "DS", "1"}, -{{12298, 620}, "Brachy Accessory Device Nominal Transmission", "DS", "1"}, -{{12298, 640}, "Channel Sequence", "SQ", "1"}, -{{12298, 642}, "Channel Number", "IS", "1"}, -{{12298, 644}, "Channel Length", "DS", "1"}, -{{12298, 646}, "Channel Total Time", "DS", "1"}, -{{12298, 648}, "Source Movement Type", "CS", "1"}, -{{12298, 650}, "Number of Pulses", "IS", "1"}, -{{12298, 652}, "Pulse Repetition Interval", "DS", "1"}, -{{12298, 656}, "Source Applicator Number", "IS", "1"}, -{{12298, 657}, "Source Applicator ID", "SH", "1"}, -{{12298, 658}, "Source Applicator Type", "CS", "1"}, -{{12298, 660}, "Source Applicator Name", "LO", "1"}, -{{12298, 662}, "Source Applicator Length", "DS", "1"}, -{{12298, 664}, "Source Applicator Manufacturer", "LO", "1"}, -{{12298, 668}, "Source Applicator Wall Nominal Thickness", "DS", "1"}, -{{12298, 670}, "Source Applicator Wall Nominal Transmission", "DS", "1"}, -{{12298, 672}, "Source Applicator Step Size", "DS", "1"}, -{{12298, 674}, "Transfer Tube Number", "IS", "1"}, -{{12298, 676}, "Transfer Tube Length", "DS", "1"}, -{{12298, 688}, "Channel Shield Sequence", "SQ", "1"}, -{{12298, 690}, "Channel Shield Number", "IS", "1"}, -{{12298, 691}, "Channel Shield ID", "SH", "1"}, -{{12298, 692}, "Channel Shield Name", "LO", "1"}, -{{12298, 696}, "Channel Shield Nominal Thickness", "DS", "1"}, -{{12298, 698}, "Channel Shield Nominal Transmission", "DS", "1"}, -{{12298, 712}, "Final Cumulative Time Weight", "DS", "1"}, -{{12298, 720}, "Brachy Control Point Sequence", "SQ", "1"}, -{{12298, 722}, "Control Point Relative Position", "DS", "1"}, -{{12298, 724}, "Control Point 3D Position", "DS", "3"}, -{{12298, 726}, "Cumulative Time Weight", "DS", "1"}, -{{12298, 736}, "Compensator Divergence", "CS", "1"}, -{{12298, 737}, "Compensator Mounting Position", "CS", "1"}, -{{12298, 738}, "Source to Compensator Distance", "DS", "1-n"}, -{{12300, 2}, "Referenced RT Plan Sequence", "SQ", "1"}, -{{12300, 4}, "Referenced Beam Sequence", "SQ", "1"}, -{{12300, 6}, "Referenced Beam Number", "IS", "1"}, -{{12300, 7}, "Referenced Reference Image Number", "IS", "1"}, -{{12300, 8}, "Start Cumulative Meterset Weight", "DS", "1"}, -{{12300, 9}, "End Cumulative Meterset Weight", "DS", "1"}, -{{12300, 10}, "Referenced Brachy Application Setup Sequence", "SQ", "1"}, -{{12300, 12}, "Referenced Brachy Application Setup Number", "IS", "1"}, -{{12300, 14}, "Referenced Source Number", "IS", "1"}, -{{12300, 32}, "Referenced Fraction Group Sequence", "SQ", "1"}, -{{12300, 34}, "Referenced Fraction Group Number", "IS", "1"}, -{{12300, 64}, "Referenced Verification Image Sequence", "SQ", "1"}, -{{12300, 66}, "Referenced Reference Image Sequence", "SQ", "1"}, -{{12300, 80}, "Referenced Dose Reference Sequence", "SQ", "1"}, -{{12300, 81}, "Referenced Dose Reference Number", "IS", "1"}, -{{12300, 85}, "Brachy Referenced Dose Reference Sequence", "SQ", "1"}, -{{12300, 96}, "Referenced Structure Set Sequence", "SQ", "1"}, -{{12300, 106}, "Referenced Patient Setup Number", "IS", "1"}, -{{12300, 128}, "Referenced Dose Sequence", "SQ", "1"}, -{{12300, 160}, "Referenced Tolerance Table Number", "IS", "1"}, -{{12300, 176}, "Referenced Bolus Sequence", "SQ", "1"}, -{{12300, 192}, "Referenced Wedge Number", "IS", "1"}, -{{12300, 208}, "Referenced Compensator Number", "IS", "1"}, -{{12300, 224}, "Referenced Block Number", "IS", "1"}, -{{12300, 240}, "Referenced Control Point Index", "IS", "1"}, -{{12302, 2}, "Approval Status", "CS", "1"}, -{{12302, 4}, "Review Date", "DA", "1"}, -{{12302, 5}, "Review Time", "TM", "1"}, -{{12302, 8}, "Reviewer Name", "PN", "1"}, -{{16392, 64}, "Results ID", "SH", "1"}, -{{16392, 66}, "Results ID Issuer", "LO", "1"}, -{{16392, 80}, "Referenced Interpretation Sequence", "SQ", "1"}, -{{16392, 256}, "Interpretation Recorded Date", "DA", "1"}, -{{16392, 257}, "Interpretation Recorded Time", "TM", "1"}, -{{16392, 258}, "Interpretation Recorder", "PN", "1"}, -{{16392, 259}, "Reference to Recorded Sound", "LO", "1"}, -{{16392, 264}, "Interpretation Transcription Date", "DA", "1"}, -{{16392, 265}, "Interpretation Transcription Time", "TM", "1"}, -{{16392, 266}, "Interpretation Transcriber", "PN", "1"}, -{{16392, 267}, "Interpretation Text", "ST", "1"}, -{{16392, 268}, "Interpretation Author", "PN", "1"}, -{{16392, 273}, "Interpretation Approver Sequence", "SQ", "1"}, -{{16392, 274}, "Interpretation Approval Date", "DA", "1"}, -{{16392, 275}, "Interpretation Approval Time", "TM", "1"}, -{{16392, 276}, "Physician Approving Interpretation", "PN", "1"}, -{{16392, 277}, "Interpretation Diagnosis Description", "LT", "1"}, -{{16392, 279}, "Interpretation Diagnosis Code Sequence", "SQ", "1"}, -{{16392, 280}, "Results Distribution List Sequence", "SQ", "1"}, -{{16392, 281}, "Distribution Name", "PN", "1"}, -{{16392, 282}, "Distribution Address", "LO", "1"}, -{{16392, 512}, "Interpretation ID", "SH", "1"}, -{{16392, 514}, "Interpretation ID Issuer", "LO", "1"}, -{{16392, 528}, "Interpretation Type ID", "CS", "1"}, -{{16392, 530}, "Interpretation Status ID", "CS", "1"}, -{{16392, 768}, "Impressions", "ST", "1"}, -{{16392, 16384}, "Results Comments", "ST", "1"}, -{{20478, 1}, "MAC Parameters Sequence", "SQ", "1"}, - -# these groups should all be 50xxH -{{0x5000, 5}, "Curve Dimensions", "US", "1"}, -{{0x5000, 16}, "Number of Points", "US", "1"}, -{{0x5000, 32}, "Type of Data", "CS", "1"}, -{{0x5000, 34}, "Curve Description", "LO", "1"}, -{{0x5000, 48}, "Axis Units", "SH", "1-n"}, -{{0x5000, 64}, "Axis Labels", "SH", "1-n"}, -{{0x5000, 259}, "Data Value Representation", "US", "1"}, -{{0x5000, 260}, "Minimum Coordinate Value", "US", "1-n"}, -{{0x5000, 261}, "Maximum Coordinate Value", "US", "1-n"}, -{{0x5000, 262}, "Curve Range", "SH", "1-n"}, -{{0x5000, 272}, "Curve Data Descriptor", "US", "1-n"}, -{{0x5000, 274}, "Coordinate Start Value", "US", "1-n"}, -{{0x5000, 276}, "Coordinate Step Value", "US", "1-n"}, -{{0x5000, 4097}, "Curve Activation Layer", "CS", "1"}, -{{0x5000, 8192}, "Audio Type", "US", "1"}, -{{0x5000, 8194}, "Audio Sample Format", "US", "1"}, -{{0x5000, 8196}, "Number of Channels", "US", "1"}, -{{0x5000, 8198}, "Number of Samples", "UL", "1"}, -{{0x5000, 8200}, "Sample Rate", "UL", "1"}, -{{0x5000, 8202}, "Total Time", "UL", "1"}, -{{0x5000, 8204}, "Audio Sample Data", "OW", "1"}, -{{0x5000, 8206}, "Audio Comments", "LT", "1"}, -{{0x5000, 9472}, "Curve Label", "LO", "1"}, -{{0x5000, 9728}, "Referenced Overlay Sequence", "SQ", "1"}, -{{0x5000, 9744}, "Referenced Overlay Group", "US", "1"}, -{{0x5000, 12288}, "Curve Data", "OW", "1"}, - - -{{20992, 37417}, "Shared Functional Groups Sequence", "SQ", "1"}, -{{20992, 37424}, "Per-frame Functional Groups Sequence", "SQ", "1"}, -{{21504, 256}, "Waveform Sequence", "SQ", "1"}, -{{21504, 272}, "Channel Minimum Value", "OB", "1"}, -{{21504, 274}, "Channel Maximum Value", "OB", "1"}, -{{21504, 4100}, "Waveform Bits Allocated", "US", "1"}, -{{21504, 4102}, "Waveform Sample Interpretation", "CS", "1"}, -{{21504, 4106}, "Waveform Padding Value", "OB", "1"}, -{{21504, 4112}, "Waveform Data", "OB", "1"}, -{{22016, 16}, "First Order Phase Correction Angle", "OF", "1"}, -{{22016, 32}, "Spectroscopy Data", "OF", "1"}, - - -# these groups should all be 60xxH -{{0x6000, 16}, "Overlay Rows", "US", "1"}, -{{0x6000, 17}, "Overlay Columns", "US", "1"}, -{{0x6000, 18}, "Overlay Planes", "US", "1"}, -{{0x6000, 21}, "Number of Frames in Overlay", "IS", "1"}, -{{0x6000, 34}, "Overlay Description", "LO", "1"}, -{{0x6000, 64}, "Overlay Type", "CS", "1"}, -{{0x6000, 69}, "Overlay Subtype", "LO", "1"}, -{{0x6000, 80}, "Overlay Origin", "SS", "2"}, -{{0x6000, 81}, "Image Frame Origin", "US", "1"}, -{{0x6000, 82}, "Overlay Plane Origin", "US", "1"}, -{{0x6000, 256}, "Overlay Bits Allocated", "US", "1"}, -{{0x6000, 258}, "Overlay Bit Position", "US", "1"}, -{{0x6000, 4097}, "Overlay Activation Layer", "CS", "1"}, -{{0x6000, 4865}, "ROI Area", "IS", "1"}, -{{0x6000, 4866}, "ROI Mean", "DS", "1"}, -{{0x6000, 4867}, "ROI Standard Deviation", "DS", "1"}, -{{0x6000, 5376}, "Overlay Label", "LO", "1"}, -{{0x6000, 12288}, "Overlay Data", "OB", "1"}, - - -{{32736, 16}, "Pixel Data", "OW", "1"}, -{{65530, 65530}, "Digital Signatures Sequence", "SQ", "1"}, -{{65532, 65532}, "Data Set Trailing Padding", "OB", "1"}, - -# item tags are always implicit VR, but in the one special case of -# encapsulated pixel data, they represent a "basic offset table" of -# 32-bit integers. We only call dicom_field on it in this case, so it's -# marked "UL" so it'll work. -{{65534, 57344}, "Item", "UL", "1"}, - -{{65534, 57357}, "Item Delimitation Item", "XX", "1"}, -{{65534, 57565}, "Sequence Delimitation Item", "XX", "1"}, -{{2, 0}, "Group Length", "UL", "1"}, -{{2, 1}, "File Meta Information Version", "OB", "1"}, -{{2, 2}, "Media Storage SOP Class UID", "UI", "1"}, -{{2, 3}, "Media Storage SOP Instance UID", "UI", "1"}, -{{2, 16}, "Transfer Syntax UID", "UI", "1"}, -{{2, 18}, "Implementation Class UID", "UI", "1"}, -{{2, 19}, "Implementation Version Name", "SH", "1"}, -{{2, 22}, "Source Application Entity Title", "AE", "1"}, -{{2, 256}, "Private Information Creator UID", "UI", "1"}, -{{2, 258}, "Private Information", "OB", "1"}, -{{4, 0}, "Group Length", "UL", "1"}, -{{4, 4400}, "File-set ID", "CS", "1"}, -{{4, 4417}, "File-set Descriptor File ID", "CS", "1-8"}, -{{4, 4418}, "Specific Character Set of File-set Descriptor File", "CS", "1"}, -{{4, 4608}, "Offset of the First Directory Record of the Root Directory Entity", "UL", "1"}, -{{4, 4610}, "Offset of the Last Directory Record of the Root Directory Entity", "UL", "1"}, -{{4, 4626}, "File-set Consistency Flag", "US", "1"}, -{{4, 4640}, "Directory Record Sequence", "SQ", "1"}, -{{4, 5120}, "Offset of the Next Directory Record", "UL", "1"}, -{{4, 5136}, "Record In-use Flag", "US", "1"}, -{{4, 5152}, "Offset of Referenced Lower-Level Directory Entity", "UL", "1"}, -{{4, 5168}, "Directory Record Type", "CS", "1"}, -{{4, 5170}, "Private Record UID", "UI", "1"}, -{{4, 5376}, "Referenced File ID", "CS", "1-8"}, -{{4, 5380}, "MRDR Directory Record Offset", "UL", "1"}, -{{4, 5392}, "Referenced SOP Class UID in File", "UI", "1"}, -{{4, 5393}, "Referenced SOP Instance UID in File", "UI", "1"}, -{{4, 5394}, "Referenced Transfer Syntax UID in File", "UI", "1"}, -{{4, 5402}, "Referenced Related General SOP Class UID in File", "UI", "1-n"}, -{{4, 5632}, "Number of References", "UL", "1"}} diff --git a/extras/dicom.jl b/extras/dicom.jl deleted file mode 100644 index 36faa97f906a1..0000000000000 --- a/extras/dicom.jl +++ /dev/null @@ -1,418 +0,0 @@ -include("dcm_dict.jl") - -function dcm_init() - dcm_dict = Dict() - for d in (_dcmdict_data_::Array{Any,1}) - dcm_dict[(uint16(d[1][1]),uint16(d[1][2]))] = d[2:] - end - dcm_dict -end - -const dcm_dict = dcm_init() -_dcmdict_data_ = 0 - -function lookup_vr(gelt) - if gelt[1]&0xff00 == 0x5000 - gelt = (0x5000,gelt[2]) - elseif gelt[1]&0xff00 == 0x6000 - gelt = (0x6000,gelt[2]) - end - r = get(dcm_dict, gelt, false) - !is(r,false) && r[2] -end - -type DcmElt - tag::(Uint16,Uint16) - data::Array{Any,1} - vr::ASCIIString # "" except for non-standard VR - DcmElt(tag, data) = new(tag,data,"") -end - -function lookup(d, t) - for el in d - if isequal(el.tag,t) - return el - end - end - return false -end - -always_implicit(grp, elt) = (grp == 0xFFFE && (elt == 0xE0DD||elt == 0xE000|| - elt == 0xE00D)) - -VR_names={"AE","AS","AT","CS","DA","DS","DT","FL","FD","IS","LO","LT","OB","OF", - "OW","PN","SH","SL","SQ","SS","ST","TM","UI","UL","UN","US","UT"} - -# mapping UID => bigendian? explicitvr? -meta_uids = {"1.2.840.10008.1.2" => (false, false), - "1.2.840.10008.1.2.1" => (false, true), - "1.2.840.10008.1.2.1.99"=> (false, true), - "1.2.840.10008.1.2.2" => (true, true)} - -dcm_store(st, grp, elt, writef) = dcm_store(st, grp, elt, writef, false) -function dcm_store(st, grp, elt, writef, vr) - lentype = Uint32 - write(st, uint16(grp)) - write(st, uint16(elt)) - if !is(vr,false) - write(st, vr) - if contains(("OB", "OW", "OF", "SQ", "UT", "UN"), vr) - write(st, uint16(0)) - else - lentype = Uint16 - end - end - p = position(st) - write(st, zero(lentype)) - writef(st) - endp = position(st) - sz = endp-p-4 - seek(st, p) - write(st, convert(lentype, sz)) - seek(st, endp) - if isodd(sz) - write(st, uint8(0)) - end -end - -function undefined_length(st, vr) - data = memio() - w1 = w2 = 0 - while true - # read until 0xFFFE 0xE0DD - w1 = w2 - w2 = read(st, Uint16) - if w1 == 0xFFFE - if w2 == 0xE0DD - break - end - write(data, w1) - end - if w2 != 0xFFFE - write(data, w2) - end - end - skip(st, 4) - takebuf_array(data) -end - -function sequence_item(st, evr, sz) - item = {} - while true - elt = element(st, evr) - if isequal(elt.tag, (0xFFFE,0xE00D)) - break - end - push(item, elt) - end - return item -end - -function sequence_item_write(st, evr, item) - for el in item - element_write(st, evr, el) - end - write(st, Uint16[0xFFFE, 0xE00D, 0x0000, 0x0000]) -end - -function sequence_parse(st, evr, sz) - sq = {} - while sz > 0 - grp = read(st, Uint16) - elt = read(st, Uint16) - itemlen = read(st, Uint32) - if grp==0xFFFE && elt==0xE0DD - return sq - end - if grp != 0xFFFE || elt != 0xE000 - error("dicom error: expected item tag in sequence") - end - push(sq, sequence_item(st, evr, itemlen)) - if itemlen != 0xffffffff - sz -= itemlen - end - end - return sq -end - -function sequence_write(st, evr, item) - for el in item - dcm_store(st, 0xFFFE, 0xE000, s->sequence_item_write(s, evr, el)) - end - write(st, Uint16[0xFFFE, 0xE0DD, 0x0000, 0x0000]) -end - -# always little-endian, "encapsulated" iff sz==0xffffffff -pixeldata_parse(st, sz, vr) = pixeldata_parse(st, sz, vr, false) -function pixeldata_parse(st, sz, vr, dcm) - yr=1 - zr=1 - if vr=="OB" - xr = sz - dtype = Uint8 - else - xr = div(sz,2) - dtype = Uint16 - end - if !is(dcm,false) - f = lookup(dcm, (0x0028,0x0010)) - if !is(f,false) - xr = f.data[1] - end - f = lookup(dcm, (0x0028,0x0011)) - if !is(f,false) - yr = f.data[1] - end - f = lookup(dcm, (0x0028,0x0012)) - if !is(f,false) - zr = f.data[1] - end - end - if sz != 0xffffffff - data = Array(dtype, xr, yr, zr) - read(st, data) - else - # start with Basic Offset Table Item - data = {element(st, false)} - while true - grp = read(st, Uint16) - elt = read(st, Uint16) - xr = read(st, Uint32) - if grp == 0xFFFE && elt == 0xE0DD - return data - end - if grp != 0xFFFE || elt != 0xE000 - error("dicom error: expected item tag in encapsulated pixel data") - end - if is(dtype,Uint16); xr = div(xr,2); end - push(data, read(st, Array(dtype, xr))) - end - end - return data -end - -function pixeldata_write(st, evr, el) - if length(el) > 1 - error("dicom error: compression not supported") - end - d = el[1] - nt = eltype(d) - vr = is(nt,Uint8) || is(nt,Int8) ? "OB" : - is(nt,Uint16) || is(nt,Int16) ? "OW" : - is(nt,Float32) ? "OF" : - error("dicom error: unsupported pixel format") - if !is(evr,false) - dcm_store(st, 0x7FE0, 0x0010, s->write(s,d), vr) - elseif vr != "OW" - error("dicom error: implicit VR only supports 16-bit pixels") - else - dcm_store(st, 0x7FE0, 0x0010, s->write(s,d)) - end -end - -function skip_spaces(st) - while true - c = read(st,Char) - if c != ' ' - return c - end - end -end - -function string_parse(st, sz, maxlen, spaces) - endpos = position(st)+sz - data = {""} - first = true - while position(st) < endpos - c = !first||spaces ? read(st,Char) : skip_spaces(st) - if c == '\\' - push(data, "") - first = true - else - data[end] = string(data[end],c) # TODO: inefficient - first = false - end - end - if !spaces - return map(rstrip,data) - end - return data -end - -numeric_parse(st, T, sz) = { read(st, T) for i=1:div(sz,sizeof(T)) } - -element(st, evr) = element(st, evr, false) -function element(st, evr, dcm) - lentype = Uint32 - diffvr = false - local grp - try - grp = read(st, Uint16) - catch - return false - end - elt = read(st, Uint16) - gelt = (grp,elt) - if evr && !always_implicit(grp,elt) - vr = ASCIIString(read(st, Uint8, 2)) - if contains(("OB", "OW", "OF", "SQ", "UT", "UN"), vr) - skip(st, 2) - else - lentype = Uint16 - end - diffvr = !isequal(vr, lookup_vr(gelt)) - else - vr = lookup_vr(gelt) - end - if is(vr,false) - error("dicom error: unknown tag ", gelt) - end - - sz = read(st,lentype) - - data = - vr=="ST" || vr=="LT" || vr=="UT" ? bytestring(read(st, Uint8, sz)) : - - sz==0 || vr=="XX" ? {} : - - vr == "SQ" ? sequence_parse(st, evr, sz) : - - gelt == (0x7FE0,0x0010) ? pixeldata_parse(st, sz, vr, dcm) : - - sz == 0xffffffff ? undefined_length(st, vr) : - - vr == "FL" ? numeric_parse(st, Float32, sz) : - vr == "FD" ? numeric_parse(st, Float64, sz) : - vr == "SL" ? numeric_parse(st, Int32 , sz) : - vr == "SS" ? numeric_parse(st, Int16 , sz) : - vr == "UL" ? numeric_parse(st, Uint32 , sz) : - vr == "US" ? numeric_parse(st, Uint16 , sz) : - - vr == "OB" ? read(st, Uint8 , sz) : - vr == "OF" ? read(st, Float32, div(sz,4)) : - vr == "OW" ? read(st, Uint16 , div(sz,2)) : - - vr == "AT" ? { read(st,Uint16,2) for n=1:div(sz,4) } : - - vr == "AS" ? ASCIIString(read(st,Uint8,4)) : - - vr == "DS" ? map(integer, string_parse(st, sz, 16, false)) : - vr == "IS" ? map(integer, string_parse(st, sz, 12, false)) : - - vr == "AE" ? string_parse(st, sz, 16, false) : - vr == "CS" ? string_parse(st, sz, 16, false) : - vr == "SH" ? string_parse(st, sz, 16, false) : - vr == "LO" ? string_parse(st, sz, 64, false) : - vr == "UI" ? string_parse(st, sz, 64, false) : - vr == "PN" ? string_parse(st, sz, 64, true) : - - vr == "DA" ? string_parse(st, sz, 10, true) : - vr == "DT" ? string_parse(st, sz, 26, false) : - vr == "TM" ? string_parse(st, sz, 16, false) : - read(st, Uint8, sz) - - if isodd(sz) && sz != 0xffffffff - skip(st, 1) - end - delt = DcmElt(gelt, isa(data,Vector{Any}) ? data : {data}) - if diffvr - # record non-standard VR - delt.vr = vr - end - return delt -end - -# todo: support maxlen -string_write(vals, maxlen) = join(vals, '\\') - -function element_write(st, evr, el::DcmElt) - gelt = el.tag - if el.vr != "" - vr = el.vr - else - vr = lookup_vr(el.tag) - if is(vr,false) - error("dicom error: unknown tag ", gelt) - end - end - if el.tag == (0x7FE0, 0x0010) - return pixeldata_write(st, evr, el.data) - end - if !is(evr,false) - evr = vr - end - el = el.data - if vr == "SQ" - return dcm_store(st, gelt[1], gelt[2], - s->sequence_write(s, evr, el), evr) - end - data = - isempty(el) ? Uint8[] : - contains(("OB","OF","OW","ST","LT","UT"), vr) ? el[1] : - contains(("AE", "CS", "SH", "LO", "UI", "PN", "DA", "DT", "TM"), vr) ? - string_write(el, 0) : - vr == "FL" ? convert(Array{Float32,1}, el) : - vr == "FD" ? convert(Array{Float64,1}, el) : - vr == "SL" ? convert(Array{Int32,1}, el) : - vr == "SS" ? convert(Array{Int16,1}, el) : - vr == "UL" ? convert(Array{Uint32,1}, el) : - vr == "US" ? convert(Array{Uint16,1}, el) : - vr == "AT" ? [el...] : - contains(("DS","IS"), vr) ? string_write(map(string,el), 0) : - el[1] - - dcm_store(st, gelt[1], gelt[2], s->write(s, data), evr) -end - -function dcm_parse(st) - evr = false - skip(st, 128) - sig = ASCIIString(read(st,Uint8,4)) - if sig != "DICM" - error("dicom error: invalid file header") - end - # a bit of a hack to detect explicit VR. seek past the first tag, - # and check to see if a valid VR name is there - skip(st, 4) - sig = ASCIIString(read(st,Uint8,2)) - evr = contains(VR_names, sig) - skip(st, -6) - data = {} - while true - fld = element(st, evr, data) - if is(fld,false) - return data - else - push(data, fld) - end - # look for transfer syntax UID - if fld.tag == (0x0002,0x0010) - fld = get(meta_uids, fld.data[1], false) - if !is(fld,false) - evr = fld[2] - if fld[1] - # todo: set byte order to big - else - # todo: set byte order to little - end - end - end - end - return data -end - -function dcm_write(st, d) - write(st, zeros(Uint8, 128)) - write(st, "DICM") - # if any elements specify a VR then use explicit VR syntax - evr = anyp(x->x.vr!="", d) - # insert UID for our transfer syntax - if evr - element_write(st, evr, DcmElt((0x0002,0x0010),{"1.2.840.10008.1.2.1"})) - else - element_write(st, evr, DcmElt((0x0002,0x0010),{"1.2.840.10008.1.2"})) - end - for el in d - element_write(st, evr, el) - end -end diff --git a/extras/enum.jl b/extras/enum.jl index 02fdd44e60ec4..3c82d3894195d 100644 --- a/extras/enum.jl +++ b/extras/enum.jl @@ -1,8 +1,8 @@ macro enum(T,syms...) N = int(Int.nbits) T = esc(T) - sh = expr(:block, - {:(if x===$sym return print($(string(sym))) end) for sym in syms}) + sh = Expr(:block) + sh.args = {:(if x===$sym return print($(string(sym))) end) for sym in syms} blk = quote bitstype ($N) ($T) $(esc(:symbols))(_::Type{$T}) = $syms @@ -10,9 +10,9 @@ macro enum(T,syms...) $(esc(:show))(io::IO, x::($T)) = $sh end for (i,sym) in enumerate(syms) - push(blk.args, :(const $(esc(sym)) = box($T,unbox(Int,$(i-1))))) + push!(blk.args, :(const $(esc(sym)) = box($T,unbox(Int,$(i-1))))) end - push(blk.args, :nothing) + push!(blk.args, :nothing) blk.head = :toplevel return blk end diff --git a/extras/glpk.jl b/extras/glpk.jl deleted file mode 100644 index 2fa010897bfaf..0000000000000 --- a/extras/glpk.jl +++ /dev/null @@ -1,2561 +0,0 @@ -### -### GLPK API Wrapper -### - -module GLPK - -export - # Types - Param, - Error, - Prob, - SimplexParam, - InteriorParam, - IntoptParam, - BasisFact, - Data, - MathProgWorkspace, - - # Methods - version, - set_prob_name, - set_obj_name, - set_row_name, - set_col_name, - set_obj_dir, - add_rows, - add_cols, - set_row_bnds, - set_col_bnds, - set_obj_coef, - set_mat_row, - set_mat_col, - load_matrix, - check_dup, - sort_matrix, - del_rows, - del_cols, - copy_prob, - erase_prob, - get_prob_name, - get_obj_name, - get_obj_dir, - get_num_rows, - get_num_cols, - get_row_name, - get_col_name, - get_row_type, - get_row_lb, - get_row_ub, - get_col_type, - get_col_lb, - get_col_ub, - get_obj_coef, - get_num_nz, - get_mat_row, - get_mat_col, - create_index, - find_row, - find_col, - delete_index, - set_rii, - set_sjj, - get_rii, - get_sjj, - scale_prob, - unscale_prob, - set_row_stat, - set_col_stat, - std_basis, - adv_basis, - cpx_basis, - simplex, - exact, - init_smcp, - get_status, - get_prim_stat, - get_dual_stat, - get_obj_val, - get_row_stat, - get_row_prim, - get_row_dual, - get_col_stat, - get_col_prim, - get_col_dual, - get_unbnd_ray, - interior, - init_iptcp, - ipt_status, - ipt_obj_val, - ipt_row_prim, - ipt_row_dual, - ipt_col_prim, - ipt_col_dual, - set_col_kind, - get_col_kind, - get_num_int, - get_num_bin, - intopt, - init_iocp, - mip_status, - mip_obj_val, - mip_row_val, - mip_col_val, - read_mps, - write_mps, - read_lp, - write_lp, - read_prob, - write_prob, - mpl_read_model, - mpl_read_data, - mpl_generate, - mpl_build_prob, - mpl_postsolve, - print_sol, - read_sol, - write_sol, - print_ipt, - read_ipt, - write_ipt, - print_mip, - read_mip, - write_mip, - print_ranges, - print_ranges, - bf_exists, - factorize, - bf_updated, - get_bfcp, - set_bfcp, - get_bhead, - get_row_bind, - get_col_bind, - ftran, - btran, - warm_up, - eval_tab_row, - eval_tab_col, - transform_row, - transform_col, - prim_rtest, - dual_rtest, - analyze_bound, - analyze_coef, - init_env, - free_env, - term_out, - open_tee, - close_tee, - malloc, - calloc, - free, - mem_usage, - mem_limit, - time, - difftime, - sdf_open_file, - sdf_read_int, - sdf_read_num, - sdf_read_item, - sdf_read_text, - sdf_line, - sdf_close_file, - read_cnfsat, - check_cnfsat, - write_cnfsat, - minisat1, - intfeas1 - -import Base.pointer, Base.assign, Base.ref - -## Shared library interface setup -#{{{ -include("$JULIA_HOME/../share/julia/extras/glpk_h.jl") - -_jl_libglpk = dlopen("libglpk") -_jl_libglpk_wrapper = dlopen("libglpk_wrapper") - -macro glpk_ccall(func, args...) - f = "glp_$(func)" - quote - ccall(dlsym(_jl_libglpk, $f), $(args...)) - end -end - -macro glpkw_ccall(func, args...) - f = "_jl_glpkw__$(func)" - quote - ccall(dlsym(_jl_libglpk_wrapper, $f), $(args...)) - end -end - -# We need to define GLPK.version as first thing -# in order to perform a sanity check -# (since we import structs from the header, -# we must ensure that the binary is the correct -# one) -function version() - csp = @glpk_ccall version Ptr{Uint8} () - str = Array(Uint8, 100) - strp = pointer(str) - k = 0 - for i = 1 : 100 - ccall(:memcpy, Ptr{Void}, (Ptr{Void}, Ptr{Void}, Int), strp, csp, sizeof(Uint8)) - if str[i] == '\0' - k = i - break - end - strp += sizeof(Uint8) - csp += sizeof(Uint8) - end - if k == 0 - throw(GLPError("error reading version")) - end - vstr = ASCIIString(str[1:k - 1]) - return tuple(map(x->int32(parse_int(x)), split(vstr, '.'))...) -end - -if version() != (MAJOR_VERSION, MINOR_VERSION) - bv = version() - hv = (MAJOR_VERSION, MINOR_VERSION) - error("GLPK error: mismatched versions: header=$(hv[1]).$(hv[2]) binary=$(bv[1]).$(bv[2])") -end -#}}} - -## Preliminary definitions -#{{{ - -# General structure for the parameters types - -abstract Param - -pointer(param::Param) = param.struct - -typealias ParamFieldDescriptor (ASCIIString, BitsKind) - -type ParamDescriptor - struct_name::String - field_names::Vector{ASCIIString} - field_types::Vector{BitsKind} - function ParamDescriptor(cstr::String, struct_desc) - struct_name = cstr - c_struct_desc = convert(Vector{ParamFieldDescriptor}, struct_desc) - field_names = [ x[1]::ASCIIString for x = c_struct_desc ] - field_types = [ x[2]::BitsKind for x = c_struct_desc ] - new(struct_name, field_names, field_types) - end -end - -function assign{T}(param::Param, val::T, field_name::String) - if pointer(param) == C_NULL - error("param is not allocated") - end - for i = 1 : length(param.desc.field_names) - if field_name == param.desc.field_names[i] - if pointer(param) == C_NULL - throw(Error("invalid struct")) - end - t = param.desc.field_types[i] - csf = strcat("_jl_glpkw__", param.desc.struct_name, "_set_", field_name) - ccs = :(ccall(dlsym(GLPK._jl_libglpk_wrapper, $csf), Void, (Ptr{Void}, $t), pointer($param), $val)) - eval(ccs) - return - end - end - error("field '$field_name' not found in struct '$(param.desc.struct_name)'") -end - -function ref(param::Param, field_name::String) - if pointer(param) == C_NULL - error("param is not allocated") - end - for i = 1 : length(param.desc.field_names) - if field_name == param.desc.field_names[i] - if pointer(param) == C_NULL - throw(Error("invalid struct")) - end - t = param.desc.field_types[i] - cgf = strcat("_jl_glpkw__", param.desc.struct_name, "_get_", field_name) - ccg = :(ccall(dlsym(GLPK._jl_libglpk_wrapper, $cgf), $t, (Ptr{Void},), pointer($param))) - return eval(ccg) - end - end - error("field '$field_name' not found in struct '$(param.desc.struct_name)'") -end - - - - -# We define some types which allow to pass optional agruments -# to the function. -# In this framework, optional arguments can be passed either -# as an empty vector [] or as the 'nothing' constant - -typealias VecOrNothing Union(Vector, Nothing) -function _jl_glpk__convert_vecornothing{T}(::Type{T}, a::VecOrNothing) - if isequal(a, nothing) || isa(a, Array{None}) - return T[] - elseif T <: Integer - if !(eltype(a) <: Integer) - throw(Error("integer-valued array required, or [] or nothing")) - end - elseif T <: Real - if !(eltype(a) <: Real) - throw(Error("real-valued array required, or [] or nothing")) - end - end - convert(Array{T}, a) -end -_jl_glpk__vecornothing_length(a::VecOrNothing) = is(a, nothing) ? 0 : length(a) - - -# General exception: all GLP functions -# throw this in case of errors -type Error <: Exception - msg::String -end -#}}} - - -## Main types definitions -#{{{ -# All structs in original glpk are wrapped up in -# composite types, which initialize and destroy themselves -# as needed, and expose pointers when asked to by -# ccall's. -# -# Therefore, the original C glp API -# -# int glp_simplex(prob * lp, glp_smpc * param) -# -# becomes -# -# GLPK.simplex(lp::GLPK.Prob, param::GLPK.SimplexParam) -# -# -# The map between names is as follows: -# -# +-------------+--------------------------+ -# | C | Julia | -# +-------------+--------------------------+ -# | glp_prob | GLPK.Prob | -# | glp_smcp | GLPK.SimplexParam | -# | glp_iptcp | GLPK.InteriorParam | -# | glp_iocp | GLPK.IntoptParam | -# | glp_bfcp | GLPK.BasisFactParam | -# | glp_tran | GLPK.MathProgWorkspace | -# | glp_data | GLPK.Data | -# +-------------+--------------------------+ -# -# In order to get/set the value of a cstruct field, you can -# use vector-like referncing with the field name as an argument, -# e.g.: -# -# lps_opts = GLPK.SimplexParam() -# lps_opts["msg_lev"] = GLPK.MSG_ERR -# lps_opts["presolve"] = GLPK.ON -# - -type Prob - p::Ptr{Void} - function Prob() - p = @glpk_ccall create_prob Ptr{Void} () - prob = new(p) - finalizer(prob, delete_prob) - return prob - end -end - -function delete_prob(prob::Prob) - if prob.p == C_NULL - return - end - @glpk_ccall delete_prob Void (Ptr{Void},) prob.p - prob.p = C_NULL - return -end - - -_jl_glpk__simplex_param_struct_desc = ParamDescriptor("smcp", - [("msg_lev", Int32), ("meth", Int32), ("pricing", Int32), - ("r_test", Int32), ("tol_bnd", Float64), ("tol_dj", Float64), - ("tol_piv", Float64), ("obj_ll", Float64), ("obj_ul", Float64), - ("it_lim", Int32), ("tm_lim", Int32), ("out_frq", Int32), - ("out_dly", Int32), ("presolve", Int32)]) - -type SimplexParam <: Param - struct::Ptr{Void} - desc::ParamDescriptor - function SimplexParam() - struct = @glpkw_ccall smcp_init Ptr{Void} () - param = new(struct, _jl_glpk__simplex_param_struct_desc) - finalizer(param, _jl_glpkw__smcp_delete) - return param - end -end - -function _jl_glpkw__smcp_delete(param::SimplexParam) - @glpkw_ccall smcp_delete Void (Ptr{Void},) pointer(param) - param.struct = C_NULL -end - - -_jl_glpk__interior_param_struct_desc = ParamDescriptor("iptcp", - [("msg_lev", Int32), ("ord_alg", Int32)]) - -type InteriorParam <: Param - struct::Ptr{Void} - desc::ParamDescriptor - function InteriorParam() - struct = @glpkw_ccall iptcp_init Ptr{Void} () - param = new(struct, _jl_glpk__interior_param_struct_desc) - finalizer(param, _jl_glpkw__iptcp_delete) - return param - end -end - -function _jl_glpkw__iptcp_delete(param::InteriorParam) - @glpkw_ccall iptcp_delete Void (Ptr{Void},) pointer(param) - param.struct = C_NULL -end - - -_jl_glpk__intopt_param_struct_desc = ParamDescriptor("iocp", - [("msg_lev", Int32), ("br_tech", Int32), ("bt_tech", Int32), - ("pp_tech", Int32), ("fp_heur", Int32), ("gmi_cuts", Int32), - ("mir_cuts", Int32), ("cov_cuts", Int32), ("clq_cuts", Int32), - ("tol_int", Float64), ("tol_obj", Float64), ("mip_gap", Float64), - ("tm_lim", Int32), ("out_frq", Int32), ("out_dly", Int32), - ("cb_func", Ptr{Void}), ("cb_info", Ptr{Void}), ("cb_size", Int32), - ("presolve", Int32), ("binarize", Int32)]) - -type IntoptParam <: Param - struct::Ptr{Void} - desc::ParamDescriptor - function IntoptParam() - struct = @glpkw_ccall iocp_init Ptr{Void} () - param = new(struct, _jl_glpk__intopt_param_struct_desc) - finalizer(param, _jl_glpkw__iocp_delete) - return param - end -end - -function _jl_glpkw__iocp_delete(param::IntoptParam) - @glpkw_ccall iocp_delete Void (Ptr{Void},) pointer(param) - param.struct = C_NULL -end - - -_jl_glpk__basisfact_param_struct_desc = ParamDescriptor("bfcp", - [("type", Int32), ("lu_size", Int32), ("piv_tol", Float64), - ("piv_lim", Int32), ("suhl", Int32), ("eps_tol", Float64), - ("max_gro", Float64), ("nfs_max", Int32), ("upd_tol", Float64), - ("nrs_max", Int32), ("rs_size", Int32)]) - -type BasisFactParam <: Param - struct::Ptr{Void} - desc::ParamDescriptor - function BasisFactParam() - struct = @glpkw_ccall bfcp_init Ptr{Void} () - param = new(struct, _jl_glpk__basisfact_param_struct_desc) - finalizer(param, _jl_glpkw__bfcp_delete) - return param - end -end - -function _jl_glpkw__bfcp_delete(param::BasisFactParam) - @glpkw_ccall bfcp_delete Void (Ptr{Void},) pointer(param) - param.struct = C_NULL -end - -type Data - p::Ptr{Void} -end - -pointer(data::Data) = data.p - -type MathProgWorkspace - p::Ptr{Void} - function MathProgWorkspace() - tran = @glpk_ccall mpl_alloc_wksp Ptr{Void} () - wksp = new(tran) - finalizer(wksp, GLPK.mpl_free_wksp) - return wksp - end -end - -function mpl_free_wksp(tran::MathProgWorkspace) - if tran.p == C_NULL - return - end - @glpk_ccall mpl_free_wksp Void (Ptr{Void},) tran.p - tran.p = C_NULL - return -end -#}}} - - -## Check functions for internal use -#{{{ -# Functions which perform all sorts of -# sanity checks on input parameters and -# throw exceptions in case of errors. -# Ideally, it should never be possible -# to pass an invalid parameter to the -# underlying glp API. - -function _jl_glpk__check_prob(prob::Prob) - if prob.p == C_NULL - throw(Error("Invalid GLPK.Prob")) - end - return true -end - -function _jl_glpk__check_string_length(s::String, minl::Integer, maxl::Integer) - l = length(s) - if !(minl <= l <= maxl) - throw(Error("Invalid string length $l (must be $minl <= length <= $maxl)")) - end - return true -end - -function _jl_glpk__check_row_is_valid(prob::Prob, row::Integer) - rows = @glpk_ccall get_num_rows Int32 (Ptr{Void},) prob.p - if (row < 1 || row > rows) - throw(Error("Invalid row $row (must be 1 <= row <= $rows)")) - end - return true -end - -function _jl_glpk__check_col_is_valid(prob::Prob, col::Integer) - cols = @glpk_ccall get_num_cols Int32 (Ptr{Void},) prob.p - if (col < 1 || col > cols) - throw(Error("Invalid col $col (must be 1 <= col <= $cols)")) - end - return true -end - -function _jl_glpk__check_col_is_valid_w0(prob::Prob, col::Integer) - cols = @glpk_ccall get_num_cols Int32 (Ptr{Void},) prob.p - if (col < 0 || col > cols) - throw(Error("Invalid col $col (must be 0 <= col <= $cols)")) - end - return true -end - -function _jl_glpk__check_obj_dir_is_valid(dir::Integer) - if !(dir == MIN || dir == MAX) - throw(Error("Invalid obj_dir $dir (use MIN or MAX)")) - end - return true -end - -function _jl_glpk__check_bounds_type_is_valid(bounds_type::Integer) - if !(bounds_type == FR || - bounds_type == LO || - bounds_type == UP || - bounds_type == DB || - bounds_type == FX) - throw(Error("Invalid bounds_type $bounds_type (allowed values: GLPK.FR, GLPK.LO, GLPK.UP, GLPK.DB, GLPK.FX)")) - end - return true -end - -function _jl_glpk__check_bounds_are_valid(bounds_type::Integer, lb::Real, ub::Real) - if bounds_type == DB && lb > ub - throw(Error("Invalid bounds for double-bounded variable: $lb > $ub")) - elseif bounds_type == FX && lb != ub - throw(Error("Invalid bounds for fixed variable: $lb != $ub")) - end - return true -end - -function _jl_glpk__check_vectors_size(numel::Integer, vecs...) - if numel < 0 - throw(Error("Invalid numer of elements: $numel")) - end - if numel > 0 - for v = vecs - if isempty(v) - throw(Error("Number of elements is $numel but vector is empty or nothing")) - elseif length(v) < numel - throw(Error("Wrong vector size: $(length(v)) (numel declared as $numel)")) - end - end - end - return true -end - -function _jl_glpk__check_vectors_all_same_size(vec0::VecOrNothing, vecs::VecOrNothing...) - l0 = _jl_glpk__vecornothing_length(vec0) - for v in vecs - l = _jl_glpk__vecornothing_length(v) - if l != l0 - throw(Error("incosistent vector lengths: $l0 and $l")) - end - end - return true -end - -function _jl_glpk__check_indices_vectors_dup(prob::Prob, numel::Integer, ia::Vector{Int32}, ja::Vector{Int32}) - rows = @glpk_ccall get_num_rows Int32 (Ptr{Void},) prob.p - cols = @glpk_ccall get_num_cols Int32 (Ptr{Void},) prob.p - #numel = length(ia) - - off32 = sizeof(Int32) - iap = pointer(ia) - off32 - jap = pointer(ja) - off32 - - k = @glpk_ccall check_dup Int32 (Int32, Int32, Int32, Ptr{Int32}, Ptr{Int32}) rows cols numel iap jap - if k < 0 - throw(Error("indices out of bounds: $(ia[-k]),$(ja[-k]) (bounds are (1,1) <= (ia,ja) <= ($rows,$cols))")) - elseif k > 0 - throw(Error("duplicate index entry: $(ia[k]),$(ja[k])")) - end - return true -end - -function _jl_glpk__check_rows_and_cols(rows::Integer, cols::Integer) - if (rows < 0) - throw(Error("rows < 0 : $rows")) - end - if (cols < 0) - throw(Error("cols < 0 : $rows")) - end -end - -function _jl_glpk__check_rows_ids(prob::Prob, min_size::Integer, num_rows::Integer, rows_ids::Vector{Int32}) - rows = @glpk_ccall get_num_rows Int32 (Ptr{Void},) prob.p - if num_rows < min_size || num_rows > rows - throw(Error("invalid vector size: $num_rows (min=$min_size max=$rows)")) - end - if num_rows == 0 - return true - end - if length(rows_ids) < num_rows - throw(Error("invalid vector size: declared>=$num_rows actual=$(length(rows_ids))")) - end - ind_set = IntSet() - add_each(ind_set, rows_ids[1 : num_rows]) - if min(ind_set) < 1 || max(ind_set) > rows - throw(Error("index out of bounds (min=1 max=$rows)")) - elseif length(ind_set) != length(rows_ids) - throw(Error("one or more duplicate index(es) found")) - end - return true -end - -function _jl_glpk__check_cols_ids(prob::Prob, min_size::Integer, num_cols::Integer, cols_ids::Vector{Int32}) - cols = @glpk_ccall get_num_cols Int32 (Ptr{Void},) prob.p - if num_cols < min_size || num_cols > cols - throw(Error("invalid vector size: $num_cols (min=$min_size max=$cols)")) - end - if num_cols == 0 - return 0 - end - if length(cols_ids) < num_cols - throw(Error("invalid vector size: declared>=$num_cols actual=$(length(cols_ids))")) - end - ind_set = IntSet() - add_each(ind_set, cols_ids[1 : num_cols]) - if min(ind_set) < 1 || max(ind_set) > cols - throw(Error("index out of bounds (min=1 max=$cols)")) - elseif length(ind_set) != length(cols_ids) - throw(Error("one or more duplicate index(es) found")) - end - return true -end - -function _jl_glpk__check_list_ids(prob::Prob, len::Integer, list_ids::Vector{Int32}) - if len == 0 - return true - end - rows = @glpk_ccall get_num_rows Int32 (Ptr{Void},) prob.p - cols = @glpk_ccall get_num_cols Int32 (Ptr{Void},) prob.p - # note1 the documentation does not mention forbidding duplicates in this case - # note2 the size should already be checked as this function is only called - # by GLPK.print_ranges - #if len < 0 #|| len > rows + cols - ##throw(Error("invalid vector size: $len (min=0 max=$(rows + cols))")) - #throw(Error("invalid vector size: $len < 0")) - #end - #if length(list_ids) < len - #throw(Error("invalid vector size: declared>=$len actual=$(length(list_ids))")) - #end - if min(list_ids[1:len]) < 1 || max(list_ids[1:len]) > rows + cols - throw(Error("index out of bounds (min=1 max=$(rows + cols))")) - end - return true -end - -function _jl_glpk__check_status_is_optimal(prob::Prob) - ret = @glpk_ccall get_status Int32 (Ptr{Void},) prob.p - if ret == OPT - throw(Error("current basic solution is not optimal")) - end - return true -end - -function _jl_glpk__check_bf_exists(prob::Prob) - ret = @glpk_ccall bf_exists Int32 (Ptr{Void},) prob.p - if ret == 0 - throw(Error("no bf solution found (use GLPK.factorize)")) - end - return true -end - -function _jl_glpk__check_var_is_basic(prob::Prob, ind::Integer) - rows = @glpk_ccall get_num_rows Int32 (Ptr{Void},) prob.p - if ind <= rows - j = @glpk_ccall get_row_stat Int32 (Ptr{Void}, Int32) prob.p ind - if j != BS - throw(Error("variable $ind is non-basic")) - end - else - j = @glpk_ccall get_col_stat Int32 (Ptr{Void}, Int32) prob.p ind-rows - if j != BS - throw(Error("variable $ind is non-basic")) - end - end -end - -function _jl_glpk__check_var_is_non_basic(prob::Prob, ind::Integer) - rows = @glpk_ccall get_num_rows Int32 (Ptr{Void},) prob.p - if ind <= rows - j = @glpk_ccall get_row_stat Int32 (Ptr{Void}, Int32) prob.p ind - if j == BS - throw(Error("variable $ind is basic")) - end - else - j = @glpk_ccall get_col_stat Int32 (Ptr{Void}, Int32) prob.p ind-rows - if j == BS - throw(Error("variable $ind is basic")) - end - end -end - -function _jl_glpk__check_is_prim_feasible(prob::Prob) - if FEAS != @glpk_ccall get_prim_stat Int32 (Ptr{Void},) prob.p - throw(Error("problem is not primal feasible")) - end - return true -end - -function _jl_glpk__check_is_dual_feasible(prob::Prob) - if FEAS != @glpk_ccall get_dual_stat Int32 (Ptr{Void},) prob.p - throw(Error("problem is not dual feasible")) - end - return true -end - -function _jl_glpk__check_copy_names_flag(names::Integer) - if names != ON && names != OFF - throw(Error("invalid copy_names flag $names (use GLPK.ON or GLPK.OFF)")) - end - return true -end - -function _jl_glpk__check_scale_flags(flags::Integer) - all = (SF_GM | SF_EQ | SF_2N | SF_SKIP) - if (flags | all) != all && flags != SF_AUTO - throw(Error("invalid scale flags $flags")) - end - return true -end - -function _jl_glpk__check_stat_is_valid(stat::Integer) - if (stat != BS && - stat != NL && - stat != NU && - stat != NF && - stat != NS) - throw(Error("invalid status $stat (use GLPK.BS or GLPK.NL or GLPK.NU or GLPK.NF or GLPK.NS)")) - end -end - -function _jl_glpk__check_adv_basis_flags(flags::Integer) - if flags != 0 - throw(Error("adv_basis flags must be set to 0 (found $flags instead)")) - end - return true -end - -function _jl_glpk__check_simplex_param(param::SimplexParam) - if pointer(param) == C_NULL - throw(Error("param = NULL")) - end - return true -end - -function _jl_glpk__check_interior_param(param::InteriorParam) - if pointer(param) == C_NULL - throw(Error("param = NULL")) - end - return true -end - -function _jl_glpk__check_kind_is_valid(kind::Integer) - if (kind != CV && - kind != IV && - kind != BV) - throw(Error("invalid kind $kind (use GLPK.CV or GLPK.IV or GLPK.BV)")) - end - return true -end - -function _jl_glpk__check_intopt_param(param::IntoptParam) - if pointer(param) == C_NULL - throw(Error("param = NULL")) - end - return true -end - -function _jl_glpk__check_file_is_readable(filename::String) - try - f = open(filename, "r") - close(f) - catch err - throw(Error("file $filename not readable")) - end - return true -end - -function _jl_glpk__check_file_is_writable(filename::String) - try - f = open(filename, "w") - close(f) - catch err - throw(Error("file $filename not writable")) - end - return true -end - -function _jl_glpk__check_mps_format(format::Integer) - if (format != MPS_DECK && - format != MPS_FILE) - throw(Error("invalid MPS format $format (use GLPK.MPS_DECK or GLPK.MPS_FILE)")) - end - return true -end - -function _jl_glpk__check_mps_param(param) - if param != C_NULL - throw(Error("MPS param must be C_NULL")) - end - return true -end - -function _jl_glpk__check_lp_param(param) - if param != C_NULL - throw(Error("LP param must be C_NULL")) - end - return true -end - -function _jl_glpk__check_read_prob_flags(flags::Integer) - if flags != 0 - throw(Error("read_prob flags must be 0")) - end - return true -end - -function _jl_glpk__check_write_prob_flags(flags::Integer) - if flags != 0 - throw(Error("write_prob flags must be 0")) - end - return true -end - -function _jl_glpk__check_print_ranges_flags(flags::Integer) - if flags != 0 - throw(Error("print_ranges flags must be set to 0 (found $flags instead)")) - end - return true -end - - -function _jl_glpk__check_bfcp(param::BasisFactParam) - if pointer(param) == C_NULL - throw(Error("Invalid GLPK.BasisFactParam")) - end - return true -end - -function _jl_glpk__check_data(data::Data) - if pointer(data) == C_NULL - throw(Error("Invalid GLPK.Data")) - end - return true -end - -function _jl_glpk__check_mpl_workspace(tran::MathProgWorkspace) - if tran.p == C_NULL - throw(Error("Invalid GLPK.MathProgWorkspace")) - end - return true -end - -function _jl_glpk__check_rowcol_is_valid(prob::Prob, k::Integer) - rows = @glpk_ccall get_num_rows Int32 (Ptr{Void},) prob.p - cols = @glpk_ccall get_num_cols Int32 (Ptr{Void},) prob.p - - k_max = rows + cols - - if !(1 <= k <= k_max) - throw(Error("index out of bounds: $k (bounds are 1 <= k <= $k_max")) - end - return true -end - -function _jl_glpk__check_dir_is_valid(dir::Integer) - if !(dir == 1 || dir == -1) - throw(Error("invalid direction $dir (must be 1 or -1)")) - end - return true -end - -function _jl_glpk__check_eps_is_valid(eps::Real) - if (eps < 0) - throw(Error("invalid eps $eps (must be >= 0)")) - end - return true -end - -function _jl_glpk__check_init_env_succeeded(ret::Integer) - if !(0 <= ret <= 1) - throw(Error("initialization failed")) - end - return true -end - -function _jl_glpk__check_term_out_flag(flag::Integer) - if !(flag == ON || flag == OFF) - throw(Error("invalid flag $flag (use GLPK.ON or GLPK.OFF)")) - end - return true -end - -function _jl_glpk__check_open_tee_succeeded(ret::Integer) - if !(0 <= ret <= 1) - throw(Error("GLPK.open_tee failed")) - end - return true -end - -function _jl_glpk__check_alloc_size(n::Integer) - if n <= 0 - throw(Error("invalid alloc size $n")) - end - return true -end - -function _jl_glpk__check_pointer_is_valid(ptr::Ptr) - if ptr == C_NULL - throw(Error("invalid pointer")) - end - return true -end - -function _jl_glpk__check_sdf_file_opened(data_p::Ptr) - if data_p == C_NULL - throw(Error("GLPK.sdf_open_file failed")) - end - return true -end -#}}} - - -## GLP functions -#{{{ -# The API interface is as close as possible to the original -# one. -# The general translation rules are: -# -# * function names tranlsate like this: glp_func -> GLPK.func -# * constant names tranlsate like this: GLPK_CONST -> GLPK.CONST -# * whenever the C library accepts NULL as argument, -# the Julia one will accept the nothing constant. -# * vectors do not need to have an extra element at the -# beginning to accomodate to the 1-based GLP indexing. -# * most functions will accept any kind of vectors as inputs, -# provided they can be converted to be C-compatible -# (i.e. to either Int32 (int) or Float64 (double) elements). -# * the exceptions to the above are those functions which write -# their output in a vector, in which case the vector type must -# be strictly C-compatible. -# * all char[] strings become Strings, both in inputs and in output. -# -# A single exception to the strict compatibility is GLPK.version(), -# which returns a tuple of integers in the form (major, minor) -# rather than a string. - -function set_prob_name(prob::Prob, name::Union(String,Nothing)) - _jl_glpk__check_prob(prob) - if is(name, nothing) - name = "" - end - _jl_glpk__check_string_length(name, 0, 255) - @glpk_ccall set_prob_name Void (Ptr{Void}, Ptr{Uint8}) prob.p bytestring(name) -end - -function set_obj_name(prob::Prob, name::Union(String,Nothing)) - _jl_glpk__check_prob(prob) - if is(name, nothing) - name = "" - end - _jl_glpk__check_string_length(name, 0, 255) - @glpk_ccall set_obj_name Void (Ptr{Void}, Ptr{Uint8}) prob.p bytestring(name) -end - -function set_row_name(prob::Prob, row::Integer, name::Union(String,Nothing)) - _jl_glpk__check_prob(prob) - _jl_glpk__check_row_is_valid(prob, row) - if is(name, nothing) - name = "" - end - _jl_glpk__check_string_length(name, 0, 255) - @glpk_ccall set_row_name Void (Ptr{Void}, Int32, Ptr{Uint8}) prob.p row bytestring(name) -end - -function set_col_name(prob::Prob, col::Integer, name::Union(String,Nothing)) - _jl_glpk__check_prob(prob) - _jl_glpk__check_col_is_valid(prob, col) - if is(name, nothing) - name = "" - end - _jl_glpk__check_string_length(name, 0, 255) - @glpk_ccall set_col_name Void (Ptr{Void}, Int32, Ptr{Uint8}) prob.p col bytestring(name) -end - -function set_obj_dir(prob::Prob, dir::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_obj_dir_is_valid(dir) - @glpk_ccall set_obj_dir Void (Ptr{Void}, Int32) prob.p dir -end - -function add_rows(prob::Prob, rows::Integer) - _jl_glpk__check_prob(prob) - @glpk_ccall add_rows Int32 (Ptr{Void}, Int32) prob.p rows -end - -function add_cols(prob::Prob, cols::Integer) - _jl_glpk__check_prob(prob) - @glpk_ccall add_cols Int32 (Ptr{Void}, Int32) prob.p cols -end - -function set_row_bnds(prob::Prob, row::Integer, bounds_type::Integer, lb::Real, ub::Real) - _jl_glpk__check_prob(prob) - _jl_glpk__check_row_is_valid(prob, row) - _jl_glpk__check_bounds_type_is_valid(bounds_type) - _jl_glpk__check_bounds_are_valid(bounds_type, lb, ub) - @glpk_ccall set_row_bnds Void (Ptr{Void}, Int32, Int32, Float64, Float64) prob.p row bounds_type lb ub -end - -function set_col_bnds(prob::Prob, col::Integer, bounds_type::Integer, lb::Real, ub::Real) - _jl_glpk__check_prob(prob) - _jl_glpk__check_col_is_valid(prob, col) - _jl_glpk__check_bounds_type_is_valid(bounds_type) - _jl_glpk__check_bounds_are_valid(bounds_type, lb, ub) - @glpk_ccall set_col_bnds Void (Ptr{Void}, Int32, Int32, Float64, Float64) prob.p col bounds_type lb ub -end - -function set_obj_coef(prob::Prob, col::Integer, coef::Real) - _jl_glpk__check_prob(prob) - _jl_glpk__check_col_is_valid_w0(prob, col) - @glpk_ccall set_obj_coef Void (Ptr{Void}, Int32, Float64) prob.p col coef -end - -function set_mat_row{Ti<:Integer, Tv<:Real}(prob::Prob, row::Integer, len::Integer, ind::Vector{Ti}, val::Vector{Tv}) - _jl_glpk__check_prob(prob) - _jl_glpk__check_vectors_size(len, ind, val) - _jl_glpk__check_row_is_valid(prob, row) - if len > 0 - ind32 = int32(ind) - val64 = float64(val) - off32 = sizeof(Int32) - off64 = sizeof(Float64) - ind32p = pointer(ind32) - off32 - val64p = pointer(val64) - off64 - _jl_glpk__check_cols_ids(prob, 0, len, ind32) - else - ind32p = C_NULL - val64p = C_NULL - end - - @glpk_ccall set_mat_row Void (Ptr{Void}, Int32, Int32, Ptr{Int32}, Ptr{Float64}) prob.p row len ind32p val64p -end -function set_mat_row(prob::Prob, row::Integer, len::Integer, ind::VecOrNothing, val::VecOrNothing) - ind = _jl_glpk__convert_vecornothing(Int32, ind) - val = _jl_glpk__convert_vecornothing(Float64, ar) - set_mat_row(prob, row, len, ind, val) -end -function set_mat_row(prob::Prob, row::Integer, ind::VecOrNothing, val::VecOrNothing) - _jl_glpk__check_vectors_all_same_size(ind, val) - l = _jl_glpk__vecornothing_length(ind) - set_mat_row(prob, row, l, ind, val) -end - - -function set_mat_col{Ti<:Integer, Tv<:Real}(prob::Prob, col::Integer, len::Integer, ind::Vector{Ti}, val::Vector{Tv}) - _jl_glpk__check_prob(prob) - _jl_glpk__check_vectors_size(len, ind, val) - _jl_glpk__check_col_is_valid(prob, col) - if len > 0 - ind32 = int32(ind) - val64 = float64(val) - off32 = sizeof(Int32) - off64 = sizeof(Float64) - ind32p = pointer(ind32) - off32 - val64p = pointer(val64) - off64 - _jl_glpk__check_rows_ids(prob, 0, len, ind32) - else - ind32p = C_NULL - val64p = C_NULL - end - - @glpk_ccall set_mat_col Void (Ptr{Void}, Int32, Int32, Ptr{Int32}, Ptr{Float64}) prob.p col len ind32p val64p -end -function set_mat_col(prob::Prob, col::Integer, len::Integer, ind::VecOrNothing, val::VecOrNothing) - ind = _jl_glpk__convert_vecornothing(Int32, ind) - val = _jl_glpk__convert_vecornothing(Float64, ar) - set_mat_col(prob, col, len, ind, val) -end -function set_mat_col(prob::Prob, col::Integer, ind::VecOrNothing, val::VecOrNothing) - _jl_glpk__check_vectors_all_same_size(ind, val) - l = _jl_glpk__vecornothing_length(ind) - set_mat_col(prob, col, l, ind, val) -end - -function load_matrix{Ti<:Integer, Tv<:Real}(prob::Prob, numel::Integer, ia::Vector{Ti}, ja::Vector{Ti}, ar::Vector{Tv}) - _jl_glpk__check_prob(prob) - _jl_glpk__check_vectors_size(numel, ia, ja, ar) - if numel == 0 - return - end - ia32 = int32(ia) - ja32 = int32(ja) - ar64 = float64(ar) - _jl_glpk__check_indices_vectors_dup(prob, numel, ia32, ja32) - - off32 = sizeof(Int32) - off64 = sizeof(Float64) - ia32p = pointer(ia32) - off32 - ja32p = pointer(ja32) - off32 - ar64p = pointer(ar64) - off64 - - @glpk_ccall load_matrix Void (Ptr{Void}, Int32, Ptr{Int32}, Ptr{Int32}, Ptr{Float64}) prob.p numel ia32p ja32p ar64p -end - -function load_matrix(prob::Prob, numel::Integer, ia::VecOrNothing, ja::VecOrNothing, ar::VecOrNothing) - ia = _jl_glpk__convert_vecornothing(Int32, ia) - ja = _jl_glpk__convert_vecornothing(Int32, ja) - ar = _jl_glpk__convert_vecornothing(Float64, ar) - load_matrix(prob, numel, ia, ja, ar) -end - -function load_matrix(prob::Prob, ia::VecOrNothing, ja::VecOrNothing, ar::VecOrNothing) - _jl_glpk__check_vectors_all_same_size(ia, ja, ar) - l = _jl_glpk__vecornothing_length(ar) - load_matrix(prob, l, ia, ja, ar) -end - -function load_matrix{Ti<:Integer, Tv<:Real}(prob::Prob, a::SparseMatrixCSC{Tv, Ti}) - (ia, ja, ar) = findn_nzs(a) - load_matrix(prob, ia, ja, ar) -end - -function check_dup{Ti<:Integer}(rows::Integer, cols::Integer, numel::Integer, ia::Vector{Ti}, ja::Vector{Ti}) - _jl_glpk__check_rows_and_cols(rows, cols) - _jl_glpk__check_vectors_size(numel, ia, ja) - ia32 = int32(ia) - ja32 = int32(ja) - - off32 = sizeof(Int32) - ia32p = pointer(ia32) - off32 - ja32p = pointer(ja32) - off32 - - @glpk_ccall check_dup Int32 (Int32, Int32, Int32, Ptr{Int32}, Ptr{Int32}) rows cols numel ia32p ja32p -end - -function check_dup(rows::Integer, cols::Integer, numel::Integer, ia::VecOrNothing, ja::VecOrNothing) - ia = _jl_glpk__convert_vecornothing(Int32, ia) - ja = _jl_glpk__convert_vecornothing(Int32, ja) - check_dup(rows, cols, numel, ia, ja) -end - -function check_dup(rows::Integer, cols::Integer, ia::VecOrNothing, ja::VecOrNothing) - _jl_glpk__check_vectors_all_same_size(ia, ja) - l = _jl_glpk__vecornothing_length(ia) - check_dup(rows, cols, l, ia, ja) -end - -function sort_matrix(prob::Prob) - _jl_glpk__check_prob(prob) - @glpk_ccall sort_matrix Void (Ptr{Void},) prob.p -end - -function del_rows{Ti<:Integer}(prob::Prob, num_rows::Integer, rows_ids::AbstractVector{Ti}) - _jl_glpk__check_prob(prob) - rows_ids32 = int32(rows_ids) - _jl_glpk__check_rows_ids(prob, 1, num_rows, rows_ids32) - - off32 = sizeof(Int32) - rows_ids32p = pointer(rows_ids32) - off32 - @glpk_ccall del_rows Void (Ptr{Void}, Int32, Ptr{Int32}) prob.p num_rows rows_ids32p -end -del_rows{Ti<:Integer}(prob::Prob, rows_ids::AbstractVector{Ti}) = - del_rows(prob, length(rows_ids), rows_ids) - -function del_cols{Ti<:Integer}(prob::Prob, num_cols::Integer, cols_ids::AbstractVector{Ti}) - _jl_glpk__check_prob(prob) - cols_ids32 = int32(cols_ids) - _jl_glpk__check_cols_ids(prob, 1, num_cols, cols_ids32) - - off32 = sizeof(Int32) - cols_ids32p = pointer(cols_ids32) - off32 - @glpk_ccall del_cols Void (Ptr{Void}, Int32, Ptr{Int32}) prob.p num_cols cols_ids32p -end -del_cols{Ti<:Integer}(prob::Prob, cols_ids::AbstractVector{Ti}) = - del_cols(prob, length(cols_ids), cols_ids) - -function copy_prob(prob_dest::Prob, prob::Prob, copy_names::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_copy_names_flag(copy_names) - @glpk_ccall copy_prob Void (Ptr{Void}, Ptr{Void}, Int32) prob_dest.p prob.p copy_names -end - -function erase_prob(prob::Prob) - _jl_glpk__check_prob(prob) - @glpk_ccall erase_prob Void (Ptr{Void},) prob.p -end - -function get_prob_name(prob::Prob) - _jl_glpk__check_prob(prob) - name_cstr = @glpk_ccall get_prob_name Ptr{Uint8} (Ptr{Void},) prob.p - if name_cstr == C_NULL - return "" - else - return bytestring(name_cstr) - end -end - -function get_obj_name(prob::Prob) - _jl_glpk__check_prob(prob) - name_cstr = @glpk_ccall get_obj_name Ptr{Uint8} (Ptr{Void},) prob.p - if name_cstr == C_NULL - return "" - else - return bytestring(name_cstr) - end -end - -function get_obj_dir(prob::Prob) - _jl_glpk__check_prob(prob) - @glpk_ccall get_obj_dir Int32 (Ptr{Void},) prob.p -end - -function get_num_rows(prob::Prob) - _jl_glpk__check_prob(prob) - @glpk_ccall get_num_rows Int32 (Ptr{Void},) prob.p -end - -function get_num_cols(prob::Prob) - _jl_glpk__check_prob(prob) - @glpk_ccall get_num_cols Int32 (Ptr{Void},) prob.p -end - -function get_row_name(prob::Prob, row::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_row_is_valid(prob, row) - name_cstr = @glpk_ccall get_row_name Ptr{Uint8} (Ptr{Void}, Int32) prob.p row - if name_cstr == C_NULL - return "" - else - return bytestring(name_cstr) - end -end - -function get_col_name(prob::Prob, col::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_col_is_valid(prob, col) - name_cstr = @glpk_ccall get_col_name Ptr{Uint8} (Ptr{Void}, Int32) prob.p col - if name_cstr == C_NULL - return "" - else - return bytestring(name_cstr) - end -end - -function get_row_type(prob::Prob, row::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_row_is_valid(prob, row) - @glpk_ccall get_row_type Int32 (Ptr{Void}, Int32) prob.p row -end - -function get_row_lb(prob::Prob, row::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_row_is_valid(prob, row) - @glpk_ccall get_row_lb Float64 (Ptr{Void}, Int32) prob.p row -end - -function get_row_ub(prob::Prob, row::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_row_is_valid(prob, row) - @glpk_ccall get_row_ub Float64 (Ptr{Void}, Int32) prob.p row -end - -function get_col_type(prob::Prob, col::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_col_is_valid(prob, col) - @glpk_ccall get_col_type Int32 (Ptr{Void}, Int32) prob.p col -end - -function get_col_lb(prob::Prob, col::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_col_is_valid(prob, col) - @glpk_ccall get_col_lb Float64 (Ptr{Void}, Int32) prob.p col -end - -function get_col_ub(prob::Prob, col::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_col_is_valid(prob, col) - @glpk_ccall get_col_ub Float64 (Ptr{Void}, Int32) prob.p col -end - -function get_obj_coef(prob::Prob, col::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_col_is_valid_w0(prob, col) - @glpk_ccall get_obj_coef Float64 (Ptr{Void}, Int32) prob.p col -end - -function get_num_nz(prob::Prob) - _jl_glpk__check_prob(prob) - @glpk_ccall get_num_nz Int32 (Ptr{Void},) prob.p -end - -function get_mat_row(prob::Prob, row::Integer, ind::Union(Vector{Int32},Nothing), val::Union(Vector{Float64},Nothing)) - _jl_glpk__check_prob(prob) - _jl_glpk__check_row_is_valid(prob, row) - numel = @glpk_ccall get_mat_row Int32 (Ptr{Void}, Int32, Ptr{Int32}, Ptr{Float64}) prob.p row C_NULL C_NULL - if numel == 0 - return 0 - end - if !isequal(ind, nothing) - _jl_glpk__check_vectors_size(numel, ind) - off32 = sizeof(Int32) - ind32p = pointer(ind) - off32 - else - ind32p = C_NULL - end - if !isequal(val, nothing) - _jl_glpk__check_vectors_size(numel, val) - off64 = sizeof(Float64) - val64p = pointer(val) - off64 - else - val64p = C_NULL - end - @glpk_ccall get_mat_row Int32 (Ptr{Void}, Int32, Ptr{Int32}, Ptr{Float64}) prob.p row ind32p val64p -end - -function get_mat_row(prob::Prob, row::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_row_is_valid(prob, row) - numel = @glpk_ccall get_mat_row Int32 (Ptr{Void}, Int32, Ptr{Int32}, Ptr{Float64}) prob.p row C_NULL C_NULL - if numel == 0 - return (Int32[], Float64[]) - end - ind = Array(Int32, numel) - val = Array(Float64, numel) - - off32 = sizeof(Int32) - ind32p = pointer(ind) - off32 - off64 = sizeof(Float64) - val64p = pointer(val) - off64 - @glpk_ccall get_mat_row Int32 (Ptr{Void}, Int32, Ptr{Int32}, Ptr{Float64}) prob.p row ind32p val64p - return ind, val -end - -function get_mat_col(prob::Prob, col::Integer, ind::Union(Vector{Int32},Nothing), val::Union(Vector{Float64},Nothing)) - _jl_glpk__check_prob(prob) - _jl_glpk__check_col_is_valid(prob, col) - numel = @glpk_ccall get_mat_col Int32 (Ptr{Void}, Int32, Ptr{Int32}, Ptr{Float64}) prob.p col C_NULL C_NULL - if numel == 0 - return 0 - end - if !isequal(ind, nothing) - _jl_glpk__check_vectors_size(numel, ind) - off32 = sizeof(Int32) - ind32p = pointer(ind) - off32 - else - ind32p = C_NULL - end - if !isequal(val, nothing) - _jl_glpk__check_vectors_size(numel, val) - off64 = sizeof(Float64) - val64p = pointer(val) - off64 - else - val64p = C_NULL - end - @glpk_ccall get_mat_col Int32 (Ptr{Void}, Int32, Ptr{Int32}, Ptr{Float64}) prob.p col ind32p val64p -end - -function get_mat_col(prob::Prob, col::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_col_is_valid(prob, col) - numel = @glpk_ccall get_mat_col Int32 (Ptr{Void}, Int32, Ptr{Int32}, Ptr{Float64}) prob.p col C_NULL C_NULL - if numel == 0 - return (Int32[], Float64[]) - end - ind = Array(Int32, numel) - val = Array(Float64, numel) - - off32 = sizeof(Int32) - ind32p = pointer(ind) - off32 - off64 = sizeof(Float64) - val64p = pointer(val) - off64 - @glpk_ccall get_mat_col Int32 (Ptr{Void}, Int32, Ptr{Int32}, Ptr{Float64}) prob.p col ind32p val64p - return ind, val -end - -function create_index(prob::Prob) - _jl_glpk__check_prob(prob) - @glpk_ccall create_index Void (Ptr{Void},) prob.p -end - -function find_row(prob::Prob, name::String) - _jl_glpk__check_prob(prob) - @glpk_ccall find_row Int32 (Ptr{Void}, Ptr{Uint8}) prob.p bytestring(name) -end - -function find_col(prob::Prob, name::String) - _jl_glpk__check_prob(prob) - @glpk_ccall find_col Int32 (Ptr{Void}, Ptr{Uint8}) prob.p bytestring(name) -end - -function delete_index(prob::Prob) - _jl_glpk__check_prob(prob) - @glpk_ccall delete_index Void (Ptr{Void},) prob.p -end - -function set_rii(prob::Prob, row::Integer, rii::Real) - _jl_glpk__check_prob(prob) - _jl_glpk__check_row_is_valid(prob, row) - @glpk_ccall set_rii Void (Ptr{Void}, Int32, Float64) prob.p row rii -end - -function set_sjj(prob::Prob, col::Integer, sjj::Real) - _jl_glpk__check_prob(prob) - _jl_glpk__check_col_is_valid(prob, col) - @glpk_ccall set_sjj Void (Ptr{Void}, Int32, Float64) prob.p col sjj -end - -function get_rii(prob::Prob, row::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_row_is_valid(prob, row) - @glpk_ccall get_rii Float64 (Ptr{Void}, Int32) prob.p row -end - -function get_sjj(prob::Prob, col::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_col_is_valid(prob, col) - @glpk_ccall get_sjj Float64 (Ptr{Void}, Int32) prob.p col -end - -function scale_prob(prob::Prob, flags::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_scale_flags(flags) - @glpk_ccall scale_prob Void (Ptr{Void}, Int32) prob.p flags -end - -function unscale_prob(prob::Prob) - _jl_glpk__check_prob(prob) - @glpk_ccall unscale_prob Void (Ptr{Void},) prob.p -end - -function set_row_stat(prob::Prob, row::Integer, stat::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_row_is_valid(prob, row) - _jl_glpk__check_stat_is_valid(stat) - @glpk_ccall set_row_stat Void (Ptr{Void}, Int32, Int32) prob.p row stat -end - -function set_col_stat(prob::Prob, col::Integer, stat::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_col_is_valid(prob, col) - _jl_glpk__check_stat_is_valid(stat) - @glpk_ccall set_col_stat Void (Ptr{Void}, Int32, Int32) prob.p col stat -end - -function std_basis(prob::Prob) - _jl_glpk__check_prob(prob) - @glpk_ccall std_basis Void (Ptr{Void},) prob.p -end - -function adv_basis(prob::Prob, flags::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_adv_basis_flags(flags) - @glpk_ccall adv_basis Void (Ptr{Void}, Int32) prob.p flags -end -adv_basis(prob::Prob) = adv_basis(prob, 0) - -function cpx_basis(prob::Prob) - _jl_glpk__check_prob(prob) - @glpk_ccall cpx_basis Void (Ptr{Void},) prob.p -end - -function simplex{Tp<:Union(SimplexParam, Nothing)}(prob::Prob, param::Tp) - _jl_glpk__check_prob(prob) - if param == nothing - param_ptr = C_NULL - else - param_ptr = pointer(param) - end - @glpk_ccall simplex Int32 (Ptr{Void}, Ptr{Void}) prob.p param_ptr -end - -simplex(prob::Prob) = - simplex(prob, nothing) - -function exact{Tp<:Union(SimplexParam, Nothing)}(prob::Prob, param::Tp) - _jl_glpk__check_prob(prob) - if param == nothing - param_ptr = C_NULL - else - param_ptr = pointer(param) - end - @glpk_ccall exact Int32 (Ptr{Void}, Ptr{Void}) prob.p param_ptr -end - -exact(prob::Prob) = - exact(prob, nothing) - -function init_smcp(param::SimplexParam) - _jl_glpk__check_simplex_param(param) - @glpk_ccall init_smcp Int32 (Ptr{Void},) pointer(param) -end - -function get_status(prob::Prob) - _jl_glpk__check_prob(prob) - @glpk_ccall get_status Int32 (Ptr{Void},) prob.p -end - -function get_prim_stat(prob::Prob) - _jl_glpk__check_prob(prob) - @glpk_ccall get_prim_stat Int32 (Ptr{Void},) prob.p -end - -function get_dual_stat(prob::Prob) - _jl_glpk__check_prob(prob) - @glpk_ccall get_dual_stat Int32 (Ptr{Void},) prob.p -end - -function get_obj_val(prob::Prob) - _jl_glpk__check_prob(prob) - @glpk_ccall get_obj_val Float64 (Ptr{Void},) prob.p -end - -function get_row_stat(prob::Prob, row::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_row_is_valid(prob, row) - @glpk_ccall get_row_stat Int32 (Ptr{Void}, Int32) prob.p row -end - -function get_row_prim(prob::Prob, row::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_row_is_valid(prob, row) - @glpk_ccall get_row_prim Float64 (Ptr{Void}, Int32) prob.p row -end - -function get_row_dual(prob::Prob, row::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_row_is_valid(prob, row) - @glpk_ccall get_row_dual Float64 (Ptr{Void}, Int32) prob.p row -end - -function get_col_stat(prob::Prob, col::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_col_is_valid(prob, col) - @glpk_ccall get_col_stat Int32 (Ptr{Void}, Int32) prob.p col -end - -function get_col_prim(prob::Prob, col::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_col_is_valid(prob, col) - @glpk_ccall get_col_prim Float64 (Ptr{Void}, Int32) prob.p col -end - -function get_col_dual(prob::Prob, col::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_col_is_valid(prob, col) - @glpk_ccall get_col_dual Float64 (Ptr{Void}, Int32) prob.p col -end - -function get_unbnd_ray(prob::Prob) - _jl_glpk__check_prob(prob) - @glpk_ccall get_unbnd_ray Int32 (Ptr{Void},) prob.p -end - -function interior{Tp<:Union(InteriorParam, Nothing)}(prob::Prob, param::Tp) - _jl_glpk__check_prob(prob) - if param == nothing - param_ptr::Ptr{Void} = C_NULL - else - param_ptr = pointer(param) - end - @glpk_ccall interior Int32 (Ptr{Void}, Ptr{Void}) prob.p param_ptr -end - -interior(prob::Prob) = interior(prob, nothing) - -function init_iptcp(param::InteriorParam) - _jl_glpk__check_interior_param(param) - @glpk_ccall init_iptcp Int32 (Ptr{Void},) pointer(param) -end - -function ipt_status(prob::Prob) - _jl_glpk__check_prob(prob) - @glpk_ccall ipt_status Int32 (Ptr{Void},) prob.p -end - -function ipt_obj_val(prob::Prob) - _jl_glpk__check_prob(prob) - @glpk_ccall ipt_obj_val Float64 (Ptr{Void},) prob.p -end - -function ipt_row_prim(prob::Prob, row::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_row_is_valid(prob, row) - @glpk_ccall ipt_row_prim Float64 (Ptr{Void}, Int32) prob.p row -end - -function ipt_row_dual(prob::Prob, row::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_row_is_valid(prob, row) - @glpk_ccall ipt_row_dual Float64 (Ptr{Void}, Int32) prob.p row -end - -function ipt_col_prim(prob::Prob, col::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_col_is_valid(prob, col) - @glpk_ccall ipt_col_prim Float64 (Ptr{Void}, Int32) prob.p col -end - -function ipt_col_dual(prob::Prob, col::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_col_is_valid(prob, col) - @glpk_ccall ipt_col_dual Float64 (Ptr{Void}, Int32) prob.p col -end - -function set_col_kind(prob::Prob, col::Integer, kind::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_col_is_valid(prob, col) - _jl_glpk__check_kind_is_valid(kind) - @glpk_ccall set_col_kind Void (Ptr{Void}, Int32, Int32) prob.p col kind -end - -function get_col_kind(prob::Prob, col::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_col_is_valid(prob, col) - @glpk_ccall get_col_kind Int32 (Ptr{Void}, Int32) prob.p col -end - -function get_num_int(prob::Prob) - _jl_glpk__check_prob(prob) - @glpk_ccall get_num_int Int32 (Ptr{Void},) prob.p -end - -function get_num_bin(prob::Prob) - _jl_glpk__check_prob(prob) - @glpk_ccall get_num_bin Int32 (Ptr{Void},) prob.p -end - -function intopt{Tp<:Union(IntoptParam, Nothing)}(prob::Prob, param::Tp) - _jl_glpk__check_prob(prob) - if param == nothing - param_ptr::Ptr{Void} = C_NULL - else - param_ptr = pointer(param) - end - @glpk_ccall intopt Int32 (Ptr{Void}, Ptr{Void}) prob.p param_ptr -end - -intopt(prob::Prob) = intopt(prob, nothing) - -function init_iocp(param::IntoptParam) - _jl_glpk__check_intopt_param(param) - @glpk_ccall init_iocp Int32 (Ptr{Void},) pointer(param) -end - -function mip_status(prob::Prob) - _jl_glpk__check_prob(prob) - @glpk_ccall mip_status Int32 (Ptr{Void},) prob.p -end - -function mip_obj_val(prob::Prob) - _jl_glpk__check_prob(prob) - @glpk_ccall mip_obj_val Float64 (Ptr{Void},) prob.p -end - -function mip_row_val(prob::Prob, row::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_row_is_valid(prob, row) - @glpk_ccall mip_row_val Float64 (Ptr{Void}, Int32) prob.p row -end - -function mip_col_val(prob::Prob, col::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_col_is_valid(prob, col) - @glpk_ccall mip_col_val Float64 (Ptr{Void}, Int32) prob.p col -end - -#TODO -#function lpx_check_kkt(prob::Prob, scaled::Integer, kkt) - -function read_mps(prob::Prob, format::Integer, param, filename::String) - _jl_glpk__check_prob(prob) - _jl_glpk__check_mps_format(format) - if is(param, nothing) - param = C_NULL - else - _jl_glpk__check_mps_param(param) - end - - _jl_glpk__check_file_is_readable(filename) - ret = @glpk_ccall read_mps Int32 (Ptr{Void}, Int32, Ptr{Void}, Ptr{Uint8}) prob.p format param bytestring(filename) - if ret != 0 - throw(Error("Error reading MPS file")) - end - return ret -end - -read_mps(prob::Prob, format::Integer, filename::String) = - read_mps(prob, format, C_NULL, filename) - -function write_mps(prob::Prob, format::Integer, param, filename::String) - _jl_glpk__check_prob(prob) - _jl_glpk__check_mps_format(format) - if is(param, nothing) - param = C_NULL - else - _jl_glpk__check_mps_param(param) - end - _jl_glpk__check_file_is_writable(filename) - ret = @glpk_ccall write_mps Int32 (Ptr{Void}, Int32, Ptr{Void}, Ptr{Uint8}) prob.p format param bytestring(filename) - if ret != 0 - throw(Error("Error writing MPS file")) - end - return ret -end - -write_mps(prob::Prob, format::Integer, filename::String) = - write_mps(prob, format, C_NULL, filename) - -function read_lp(prob::Prob, param, filename::String) - _jl_glpk__check_prob(prob) - _jl_glpk__check_lp_param(param) - _jl_glpk__check_file_is_readable(filename) - ret = @glpk_ccall read_lp Int32 (Ptr{Void}, Ptr{Void}, Ptr{Uint8}) prob.p param bytestring(filename) - if ret != 0 - throw(Error("Error reading LP file")) - end - return ret -end - -read_lp(prob::Prob, filename::String) = - read_lp(prob, C_NULL, filename) - -function write_lp(prob::Prob, param, filename::String) - _jl_glpk__check_prob(prob) - _jl_glpk__check_lp_param(param) - _jl_glpk__check_file_is_writable(filename) - ret = @glpk_ccall write_lp Int32 (Ptr{Void}, Ptr{Void}, Ptr{Uint8}) prob.p param bytestring(filename) - if ret != 0 - throw(Error("Error writing LP file")) - end - return ret -end - -write_lp(prob::Prob, filename::String) = - write_lp(prob, C_NULL, filename) - -function read_prob(prob::Prob, flags::Integer, filename::String) - _jl_glpk__check_prob(prob) - _jl_glpk__check_read_prob_flags(flags) - _jl_glpk__check_file_is_readable(filename) - @glpk_ccall read_prob Int32 (Ptr{Void}, Int32, Ptr{Uint8}) prob.p flags bytestring(filename) -end - -read_prob(prob::Prob, filename::String) = - read_prob(prob, 0, filename) - -function write_prob(prob::Prob, flags::Integer, filename::String) - _jl_glpk__check_prob(prob) - _jl_glpk__check_write_prob_flags(flags) - _jl_glpk__check_file_is_writable(filename) - @glpk_ccall write_prob Int32 (Ptr{Void}, Int32, Ptr{Uint8}) prob.p flags bytestring(filename) -end - -write_prob(prob::Prob, filename::String) = - write_prob(prob, 0, filename) - -function mpl_read_model(tran::MathProgWorkspace, filename::String, skip::Integer) - _jl_glpk__check_mpl_workspace(tran) - _jl_glpk__check_file_is_readable(filename) - ret = @glpk_ccall mpl_read_model Int32 (Ptr{Void}, Ptr{Uint8}, Int32) tran.p bytestring(filename) skip - if ret != 0 - throw(Error("Error reading MathProg file")) - end - return ret -end - -function mpl_read_data(tran::MathProgWorkspace, filename::String) - _jl_glpk__check_mpl_workspace(tran) - _jl_glpk__check_file_is_readable(filename) - ret = @glpk_ccall mpl_read_data Int32 (Ptr{Void}, Ptr{Uint8}) tran.p bytestring(filename) - if ret != 0 - throw(Error("Error reading MathProg data file")) - end - return ret -end - -function mpl_generate(tran::MathProgWorkspace, filename::Union(String, Nothing)) - _jl_glpk__check_mpl_workspace(tran) - if is(filename, nothing) - cfilename = C_NULL - else - _jl_glpk__check_file_is_writable(filename) - cfilename = bytestring(filename) - end - ret = @glpk_ccall mpl_generate Int32 (Ptr{Void}, Ptr{Uint8}) tran.p cfilename - if ret != 0 - throw(Error("Error generating MathProg model")) - end - return ret - -end -mpl_generate(tran::MathProgWorkspace) = mpl_generate(tran, nothing) - -function mpl_build_prob(tran::MathProgWorkspace, prob::Prob) - _jl_glpk__check_mpl_workspace(tran) - _jl_glpk__check_prob(prob) - @glpk_ccall mpl_build_prob Void (Ptr{Void}, Ptr{Void}) tran.p prob.p -end - -function mpl_postsolve(tran::MathProgWorkspace, prob::Prob, sol::Integer) - _jl_glpk__check_mpl_workspace(tran) - _jl_glpk__check_prob(prob) - if !(sol == SOL || sol == IPT || sol == MIP) - throw(Error("Invalid parameter sol $sol (use GLPK.SOL, GLPK.IPT or GLPK.MIP)")) - end - ret = @glpk_ccall mpl_postsolve Int32 (Ptr{Void}, Ptr{Void}, Int32) tran.p prob.p sol - if ret != 0 - throw(Error("Error postsolving MathProg model")) - end - return ret -end - -function print_sol(prob::Prob, filename::String) - _jl_glpk__check_prob(prob) - _jl_glpk__check_file_is_writable(filename) - ret = @glpk_ccall print_sol Int32 (Ptr{Void}, Ptr{Uint8}) prob.p bytestring(filename) - if ret != 0 - throw(Error("Error printing solution")) - end - return ret -end - -function read_sol(prob::Prob, filename::String) - _jl_glpk__check_prob(prob) - _jl_glpk__check_file_is_readable(filename) - ret = @glpk_ccall read_sol Int32 (Ptr{Void}, Ptr{Uint8}) prob.p bytestring(filename) - if ret != 0 - throw(Error("Error reading solution")) - end - return ret -end - -function write_sol(prob::Prob, filename::String) - _jl_glpk__check_prob(prob) - _jl_glpk__check_file_is_writable(filename) - ret = @glpk_ccall write_sol Int32 (Ptr{Void}, Ptr{Uint8}) prob.p bytestring(filename) - if ret != 0 - throw(Error("Error writing solution")) - end - return ret -end - -function print_ipt(prob::Prob, filename::String) - _jl_glpk__check_prob(prob) - _jl_glpk__check_file_is_writable(filename) - ret = @glpk_ccall print_ipt Int32 (Ptr{Void}, Ptr{Uint8}) prob.p bytestring(filename) - if ret != 0 - throw(Error("Error printing interior point solution")) - end - return ret -end - -function read_ipt(prob::Prob, filename::String) - _jl_glpk__check_prob(prob) - _jl_glpk__check_file_is_readable(filename) - ret = @glpk_ccall read_ipt Int32 (Ptr{Void}, Ptr{Uint8}) prob.p bytestring(filename) - if ret != 0 - throw(Error("Error reading interior point solution")) - end - return ret -end - -function write_ipt(prob::Prob, filename::String) - _jl_glpk__check_prob(prob) - _jl_glpk__check_file_is_writable(filename) - ret = @glpk_ccall write_ipt Int32 (Ptr{Void}, Ptr{Uint8}) prob.p bytestring(filename) - if ret != 0 - throw(Error("Error writing interior point solution")) - end - return ret -end - -function print_mip(prob::Prob, filename::String) - _jl_glpk__check_prob(prob) - _jl_glpk__check_file_is_writable(filename) - ret = @glpk_ccall print_mip Int32 (Ptr{Void}, Ptr{Uint8}) prob.p bytestring(filename) - if ret != 0 - throw(Error("Error printing mixed integer programming solution")) - end - return ret -end - -function read_mip(prob::Prob, filename::String) - _jl_glpk__check_prob(prob) - _jl_glpk__check_file_is_readable(filename) - ret = @glpk_ccall read_mip Int32 (Ptr{Void}, Ptr{Uint8}) prob.p bytestring(filename) - if ret != 0 - throw(Error("Error reading mixed integer programming solution")) - end - return ret -end - -function write_mip(prob::Prob, filename::String) - _jl_glpk__check_prob(prob) - _jl_glpk__check_file_is_writable(filename) - ret = @glpk_ccall write_mip Int32 (Ptr{Void}, Ptr{Uint8}) prob.p bytestring(filename) - if ret != 0 - throw(Error("Error writing mixed integer programming solution")) - end - return ret -end - -function print_ranges{Ti<:Integer}(prob::Prob, len::Integer, list::Vector{Ti}, flags::Integer, filename::String) - _jl_glpk__check_prob(prob) - _jl_glpk__check_vectors_size(len, list) - _jl_glpk__check_status_is_optimal(prob) - _jl_glpk__check_bf_exists(prob) - _jl_glpk__check_print_ranges_flags(flags) - _jl_glpk__check_file_is_writable(filename) - - if len > 0 - list32 = int32(list) - _jl_glpk__check_list_ids(prob, len, list32) - - off32 = sizeof(Int32) - list32p = pointer(list32) - off32 - else - list32p = C_NULL - end - - @glpk_ccall print_ranges Int32 (Ptr{Void}, Int32, Ptr{Int32}, Int32, Ptr{Uint8}) prob.p len list32p flags bytestring(filename) -end - -print_ranges{Ti<:Integer}(prob::Prob, list::Vector{Ti}, flags::Integer, filename::String) = - print_ranges(prob, length(list), list, flags, filename) - -print_ranges{Ti<:Integer}(prob::Prob, len::Integer, list::Vector{Ti}, filename::String) = - print_ranges(prob, len, list, 0, filename) - -print_ranges{Ti<:Integer}(prob::Prob, list::Vector{Ti}, filename::String) = - print_ranges(prob, length(list), list, 0, filename) - -function print_ranges(prob::Prob, len::Integer, list::VecOrNothing, flags::Integer, filename::String) - list = _jl_glpk__convert_vecornothing(Int32, list) - print_ranges(prob, len, list, flags, filename) -end - -print_ranges(prob::Prob, list::VecOrNothing, flags::Integer, filename::String) = - print_ranges(prob, _jl_glpk__vecornothing_length(list), list, flags, filename) - -print_ranges(prob::Prob, len::Integer, list::VecOrNothing, filename::String) = - print_ranges(prob, len, list, 0, filename) - -print_ranges(prob::Prob, list::VecOrNothing, filename::String) = - print_ranges(prob, _jl_glpk__vecornothing_length(list), list, 0, filename) - -print_ranges(prob::Prob, filename::String) = - print_ranges(prob, 0, nothing, 0, filename) - -function bf_exists(prob::Prob) - _jl_glpk__check_prob(prob) - @glpk_ccall bf_exists Int32 (Ptr{Void},) prob.p -end - -function factorize(prob::Prob) - _jl_glpk__check_prob(prob) - @glpk_ccall factorize Int32 (Ptr{Void},) prob.p -end - -function bf_updated(prob::Prob) - _jl_glpk__check_prob(prob) - @glpk_ccall bf_updated Int32 (Ptr{Void},) prob.p -end - -function get_bfcp(prob::Prob, param::BasisFactParam) - _jl_glpk__check_prob(prob) - _jl_glpk__check_bfcp(param) - @glpk_ccall get_bfcp Void (Ptr{Void}, Ptr{Void}) prob.p pointer(param) -end - -function set_bfcp(prob::Prob, param::Union(BasisFactParam,Nothing)) - _jl_glpk__check_prob(prob) - if is(param, nothing) - param_p = C_NULL - else - _jl_glpk__check_bfcp(param) - param_p = pointer(param) - end - @glpk_ccall set_bfcp Void (Ptr{Void}, Ptr{Void}) prob.p param_p -end -set_bfcp(prob::Prob) = set_bfcp(prob, nothing) - -function get_bhead(prob::Prob, k::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_row_is_valid(prob, k) - @glpk_ccall get_bhead Int32 (Ptr{Void}, Int32) prob.p k -end - -function get_row_bind(prob::Prob, row::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_bf_exists(prob) - _jl_glpk__check_row_is_valid(prob, row) - @glpk_ccall get_row_bind Int32 (Ptr{Void}, Int32) prob.p row -end - -function get_col_bind(prob::Prob, col::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_bf_exists(prob) - _jl_glpk__check_col_is_valid(prob, col) - @glpk_ccall get_col_bind Int32 (Ptr{Void}, Int32) prob.p col -end - -function ftran(prob::Prob, x::Vector{Float64}) - _jl_glpk__check_prob(prob) - rows = @glpk_ccall get_num_rows Int32 (Ptr{Void},) prob.p - _jl_glpk__check_vectors_size(rows, x) - off64 = sizeof(Float64) - x64p = pointer(x) - off64 - @glpk_ccall ftran Void (Ptr{Void}, Ptr{Float64}) prob.p x64p -end - -function btran(prob::Prob, x::Vector{Float64}) - _jl_glpk__check_prob(prob) - rows = @glpk_ccall get_num_rows Int32 (Ptr{Void},) prob.p - _jl_glpk__check_vectors_size(rows, x) - off64 = sizeof(Float64) - x64p = pointer(x) - off64 - @glpk_ccall btran Void (Ptr{Void}, Ptr{Float64}) prob.p x64p -end - -function warm_up(prob::Prob) - _jl_glpk__check_prob(prob) - @glpk_ccall warm_up Int32 (Ptr{Void},) prob.p -end - -function eval_tab_row(prob::Prob, k::Integer, ind::Vector{Int32}, val::Vector{Float64}) - _jl_glpk__check_prob(prob) - _jl_glpk__check_bf_exists(prob) - rows = @glpk_ccall get_num_rows Int32 (Ptr{Void},) prob.p - cols = @glpk_ccall get_num_cols Int32 (Ptr{Void},) prob.p - - k_max = rows + cols - - if !(1 <= k <= k_max) - throw(Error("index out of bounds: $k (bounds are 1 <= k <= $k_max")) - end - - _jl_glpk__check_var_is_basic(prob, k) - - grow(ind, k_max - length(ind)) - grow(val, k_max - length(val)) - - off32 = sizeof(Int32) - off64 = sizeof(Float64) - ind32p = pointer(ind) - off32 - val64p = pointer(val) - off64 - - len = @glpk_ccall eval_tab_row Int32 (Ptr{Void}, Int32, Ptr{Int32}, Ptr{Float64}) prob.p k ind32p val64p - - del(ind, len+1:length(ind)) - del(val, len+1:length(val)) - - return len -end - -function eval_tab_row(prob::Prob, k::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_bf_exists(prob) - rows = @glpk_ccall get_num_rows Int32 (Ptr{Void},) prob.p - cols = @glpk_ccall get_num_cols Int32 (Ptr{Void},) prob.p - - k_max = rows + cols - - if !(1 <= k <= k_max) - throw(Error("index out of bounds: $k (bounds are 1 <= k <= $k_max")) - end - - _jl_glpk__check_var_is_basic(prob, k) - - ind = Array(Int32, k_max) - val = Array(Float64, k_max) - - off32 = sizeof(Int32) - off64 = sizeof(Float64) - ind32p = pointer(ind) - off32 - val64p = pointer(val) - off64 - - len = @glpk_ccall eval_tab_row Int32 (Ptr{Void}, Int32, Ptr{Int32}, Ptr{Float64}) prob.p k ind32p val64p - - del(ind, len+1:length(ind)) - del(val, len+1:length(val)) - - return ind, val -end - -function eval_tab_col(prob::Prob, k::Integer, ind::Vector{Int32}, val::Vector{Float64}) - _jl_glpk__check_prob(prob) - _jl_glpk__check_bf_exists(prob) - - rows = @glpk_ccall get_num_rows Int32 (Ptr{Void},) prob.p - cols = @glpk_ccall get_num_cols Int32 (Ptr{Void},) prob.p - - k_max = rows + cols - - if !(1 <= k <= k_max) - throw(Error("index out of bounds: $k (bounds are 1 <= k <= $k_max")) - end - - _jl_glpk__check_var_is_non_basic(prob, k) - - grow(ind, k_max - length(ind)) - grow(val, k_max - length(val)) - - off32 = sizeof(Int32) - off64 = sizeof(Float64) - ind32p = pointer(ind) - off32 - val64p = pointer(val) - off64 - - len = @glpk_ccall eval_tab_col Int32 (Ptr{Void}, Int32, Ptr{Int32}, Ptr{Float64}) prob.p k ind32p val64p - - del(ind, len+1:length(ind)) - del(val, len+1:length(val)) - - return len -end - -function eval_tab_col(prob::Prob, k::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_bf_exists(prob) - - rows = @glpk_ccall get_num_rows Int32 (Ptr{Void},) prob.p - cols = @glpk_ccall get_num_cols Int32 (Ptr{Void},) prob.p - - k_max = rows + cols - - if !(1 <= k <= k_max) - throw(Error("index out of bounds: $k (bounds are 1 <= k <= $k_max")) - end - - _jl_glpk__check_var_is_non_basic(prob, k) - - ind = Array(Int32, k_max) - val = Array(Float64, k_max) - - off32 = sizeof(Int32) - off64 = sizeof(Float64) - ind32p = pointer(ind) - off32 - val64p = pointer(val) - off64 - - len = @glpk_ccall eval_tab_col Int32 (Ptr{Void}, Int32, Ptr{Int32}, Ptr{Float64}) prob.p k ind32p val64p - - del(ind, len+1:length(ind)) - del(val, len+1:length(val)) - - return ind, val -end - -function transform_row(prob::Prob, len::Integer, ind::Vector{Int32}, val::Vector{Float64}) - _jl_glpk__check_prob(prob) - _jl_glpk__check_bf_exists(prob) - _jl_glpk__check_col_is_valid(prob, len) - _jl_glpk__check_vectors_size(len, ind, val) - - cols = @glpk_ccall get_num_cols Int32 (Ptr{Void},) prob.p - - grow(ind, cols - length(ind)) - grow(val, cols - length(val)) - - off32 = sizeof(Int32) - off64 = sizeof(Float64) - ind32p = pointer(ind) - off32 - val64p = pointer(val) - off64 - - len1 = @glpk_ccall transform_row Int32 (Ptr{Void}, Int32, Ptr{Int32}, Ptr{Float64}) prob.p len ind32p val64p - - del(ind, len1+1:length(ind)) - del(val, len1+1:length(val)) - - return len1 -end - -function transform_row(prob::Prob, ind::Vector{Int32}, val::Vector{Float64}) - _jl_glpk__check_vectors_all_same_size(ind, val) - transform_row(prob, length(ind), ind, val) -end - -function transform_col(prob::Prob, len::Integer, ind::Vector{Int32}, val::Vector{Float64}) - _jl_glpk__check_prob(prob) - _jl_glpk__check_bf_exists(prob) - _jl_glpk__check_row_is_valid(prob, len) - _jl_glpk__check_vectors_size(len, ind, val) - - rows = @glpk_ccall get_num_rows Int32 (Ptr{Void},) prob.p - - grow(ind, rows - length(ind)) - grow(val, rows - length(val)) - - off32 = sizeof(Int32) - off64 = sizeof(Float64) - ind32p = pointer(ind) - off32 - val64p = pointer(val) - off64 - - len1 = @glpk_ccall transform_col Int32 (Ptr{Void}, Int32, Ptr{Int32}, Ptr{Float64}) prob.p len ind32p val64p - - del(ind, len1+1:length(ind)) - del(val, len1+1:length(val)) - - return len1 -end - -function transform_col(prob::Prob, ind::Vector{Int32}, val::Vector{Float64}) - _jl_glpk__check_vectors_all_same_size(ind, val) - transform_col(prob, length(ind), ind, val) -end - -function prim_rtest{Ti<:Integer, Tv<:Real}(prob::Prob, len::Integer, ind::Vector{Ti}, val::Vector{Tv}, dir::Integer, eps::Real) - _jl_glpk__check_prob(prob) - _jl_glpk__check_bf_exists(prob) - _jl_glpk__check_is_prim_feasible(prob) - _jl_glpk__check_row_is_valid(prob, len) - _jl_glpk__check_vectors_size(len, ind, val) - _jl_glpk__check_dir_is_valid(dir) - _jl_glpk__check_eps_is_valid(eps) - - for i = 1:len - _jl_glpk__check_var_is_basic(prob, ind[i]) - end - - ind32 = int32(ind) - val64 = float64(val) - off32 = sizeof(Int32) - off64 = sizeof(Float64) - ind32p = pointer(ind32) - off32 - val64p = pointer(val64) - off64 - - piv = @glpk_ccall prim_rtest Int32 (Ptr{Void}, Int32, Ptr{Int32}, Ptr{Float64}, Int32, Float64) prob.p len ind32p val64p dir eps - return piv -end - -function prim_rtest{Ti<:Integer, Tv<:Real}(prob::Prob, ind::Vector{Ti}, val::Vector{Tv}, dir::Integer, eps::Real) - _jl_glpk__check_vectors_all_same_size(ind, val) - prim_rtest(prob, length(ind), ind, val, dir, eps) -end - -function dual_rtest{Ti<:Integer, Tv<:Real}(prob::Prob, len::Integer, ind::Vector{Ti}, val::Vector{Tv}, dir::Integer, eps::Real) - _jl_glpk__check_prob(prob) - _jl_glpk__check_bf_exists(prob) - _jl_glpk__check_is_dual_feasible(prob) - _jl_glpk__check_col_is_valid(prob, len) - _jl_glpk__check_vectors_size(len, ind, val) - _jl_glpk__check_dir_is_valid(dir) - _jl_glpk__check_eps_is_valid(eps) - - for i = 1:len - _jl_glpk__check_var_is_non_basic(prob, ind[i]) - end - - ind32 = int32(ind) - val64 = float64(val) - off32 = sizeof(Int32) - off64 = sizeof(Float64) - ind32p = pointer(ind32) - off32 - val64p = pointer(val64) - off64 - - piv = @glpk_ccall dual_rtest Int32 (Ptr{Void}, Int32, Ptr{Int32}, Ptr{Float64}, Int32, Float64) prob.p len ind32p val64p dir eps - return piv -end - -function dual_rtest{Ti<:Integer, Tv<:Real}(prob::Prob, ind::Vector{Ti}, val::Vector{Tv}, dir::Integer, eps::Real) - _jl_glpk__check_vectors_all_same_size(ind, val) - dual_rtest(prob, length(ind), ind, val, dir, eps) -end - -function analyze_bound(prob::Prob, k, limit1, var1, limit2, var2) - error("Unsupported. Use GLPK.analyze_bound(prob, k) instead.") -end - -function analyze_bound(prob::Prob, k::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_bf_exists(prob) - _jl_glpk__check_rowcol_is_valid(prob, k) - _jl_glpk__check_var_is_non_basic(prob, k) - - limit1 = Array(Float64, 1) - var1 = Array(Int32, 1) - limit2 = Array(Float64, 1) - var2 = Array(Int32, 1) - - @glpk_ccall analyze_bound Void (Ptr{Void}, Int32, Ptr{Float64}, Ptr{Int32}, Ptr{Float64}, Ptr{Int32}) prob.p k pointer(limit1) pointer(var1) pointer(limit2) pointer(var2) - - return limit1[1], var1[1], limit2[1], var2[1] -end - -function analyze_coef(prob::Prob, k, coef1, var1, value1, coef2, var2, value2) - error("Unsupported. Use GLPK.analyze_coef(prob, k) instead.") -end - -function analyze_coef(prob::Prob, k::Integer) - _jl_glpk__check_prob(prob) - _jl_glpk__check_bf_exists(prob) - _jl_glpk__check_rowcol_is_valid(prob, k) - _jl_glpk__check_var_is_basic(prob, k) - - coef1 = Array(Float64, 1) - var1 = Array(Int32, 1) - value1 = Array(Float64, 1) - coef2 = Array(Float64, 1) - var2 = Array(Int32, 1) - value2 = Array(Float64, 1) - - @glpk_ccall analyze_coef Void (Ptr{Void}, Int32, Ptr{Float64}, Ptr{Int32}, Ptr{Float64}, Ptr{Float64}, Ptr{Int32}, Ptr{Float64}) prob.p k pointer(coef1) pointer(var1) pointer(value1) pointer(coef2) pointer(var2) pointer(value2) - - return coef1[1], var1[1], value1[1], coef2[1], var2[1], value2[1] -end - -function init_env() - ret = @glpk_ccall init_env Int32 () - _jl_glpk__check_init_env_succeeded(ret) - return ret -end - -function free_env() - ret = @glpk_ccall free_env Int32 () -end - -function term_out(flag::Integer) - _jl_glpk__check_term_out_flag(flag) - @glpk_ccall term_out Int32 (Int32,) flag -end - -function open_tee(filename::String) - ret = @glpk_ccall open_tee Int32 (Ptr{Uint8},) bytestring(filename) - _jl_glpk__check_open_tee_succeeded(ret) - return ret -end - -function close_tee() - @glpk_ccall close_tee Int32 () -end - -function malloc(size::Integer) - _jl_glpk__check_alloc_size(size) - @glpk_ccall malloc Ptr{Void} (Int32,) size -end - -function calloc(n::Integer, size::Integer) - _jl_glpk__check_alloc_size(n) - _jl_glpk__check_alloc_size(size) - @glpk_ccall calloc Ptr{Void} (Int32, Int32) n size -end - -function free(ptr::Ptr) - _jl_glpk__check_pointer_is_valid(ptr) - @glpk_ccall free Void (Ptr{Void},) ptr -end - -function mem_usage(count, cpeak, total, tpeak) - error("Unsupported. Use GLPK.mem_usage() instead.") -end - -function mem_usage() - data32 = Array(Int32, 2) - data32_p = pointer(data32) - off32 = sizeof(Int32) - count_p = data32_p - cpeak_p = data32_p + off32 - - data64 = Array(Int64, 2) - data64_p = pointer(data64) - off64 = sizeof(Int64) - - total_p = data64_p - tpeak_p = data64_p + off64 - - @glpk_ccall mem_usage Void (Ptr{Int32}, Ptr{Int32}, Ptr{Int64}, Ptr{Int64}) count_p cpeak_p total_p tpeak_p - - count = data32[1] - cpeak = data32[2] - total = data64[1] - tpeak = data64[2] - - return count, cpeak, total, tpeak -end - -function mem_limit(limit::Integer) - @glpk_ccall mem_limit Void (Int32,) limit -end - -function time() - @glpk_ccall time Int64 () -end - -function difftime(t1::Integer, t0::Integer) - @glpk_ccall difftime Float64 (Int64, Int64) t1 t0 -end - -function sdf_open_file(filename::String) - _jl_glpk__check_file_is_readable(filename) - data_p = @glpk_ccall sdf_open_file Ptr{Void} (Ptr{Uint8},) bytestring(filename) - _jl_glpk__check_sdf_file_opened(data_p) - return Data(data_p) -end - -function sdf_read_int(data::Data) - _jl_glpk__check_data(data) - @glpk_ccall sdf_read_int Int32 (Ptr{Void},) pointer(data) -end - -function sdf_read_num(data::Data) - _jl_glpk__check_data(data) - @glpk_ccall sdf_read_num Float64 (Ptr{Void},) pointer(data) -end - -function sdf_read_item(data::Data) - _jl_glpk__check_data(data) - item_cstr = @glpk_ccall sdf_read_item Ptr{Uint8} (Ptr{Void},) pointer(data) - return bytestring(item_cstr) -end - -function sdf_read_text(data::Data) - _jl_glpk__check_data(data) - text_cstr = @glpk_ccall sdf_read_text Ptr{Uint8} (Ptr{Void},) pointer(data) - return bytestring(text_cstr) -end - -function sdf_line(data::Data) - _jl_glpk__check_data(data) - @glpk_ccall sdf_line Int32 (Ptr{Void},) pointer(data) -end - -function sdf_close_file(data::Data) - _jl_glpk__check_data(data) - @glpk_ccall sdf_close_file Void (Ptr{Void},) pointer(data) -end - -function read_cnfsat(prob::Prob, filename::String) - _jl_glpk__check_prob(prob) - _jl_glpk__check_file_is_readable(filename) - ret = @glpk_ccall read_cnfsat Int32 (Ptr{Void}, Ptr{Uint8}) prob.p bytestring(filename) - if ret != 0 - throw(Error("Error reading CNF file")) - end - return ret -end - -function check_cnfsat(prob::Prob) - _jl_glpk__check_prob(prob) - @glpk_ccall check_cnfsat Int32 (Ptr{Void},) prob.p -end - -function write_cnfsat(prob::Prob, filename::String) - _jl_glpk__check_prob(prob) - _jl_glpk__check_file_is_writable(filename) - ret = @glpk_ccall write_cnfsat Int32 (Ptr{Void}, Ptr{Uint8}) prob.p bytestring(filename) - if ret != 0 - throw(Error("Error writing CNF file")) - end - return ret -end - -function minisat1(prob::Prob) - _jl_glpk__check_prob(prob) - @glpk_ccall minisat1 Int32 (Ptr{Void},) prob.p -end - -function intfeas1(prob::Prob, use_bound::Integer, obj_bound::Integer) - _jl_glpk__check_prob(prob) - # TODO : more checks: - # 1) columns must be GLPK.BV od GLPK.FX - # 2) constraints and objj coeffs must be integer - @glpk_ccall intfeas1 Int32 (Ptr{Void}, Int32, Int32) prob.p use_bound obj_bound -end - - -# FUNCTIONS NOT WRAPPED: -# -# 1) All glp_ios_* [because they should be called -# from within a callback]: -# -# glp_ios_reason -# glp_ios_get_prob -# glp_ios_row_attr -# glp_ios_mip_gap -# glp_ios_node_data -# glp_ios_select_node -# glp_ios_heur_sol -# glp_ios_can_branch -# glp_ios_branch_upon -# glp_ios_terminate -# glp_ios_tree_size -# glp_ios_curr_node -# glp_ios_next_node -# glp_ios_prev_node -# glp_ios_up_node -# glp_ios_node_level -# glp_ios_node_bound -# glp_ios_best_node -# glp_ios_pool_size -# glp_ios_add_row -# glp_ios_del_row -# glp_ios_clear_pool -# -# 2) Printout functions [because they use varargs/va_list, -# or need callbacks, or are implemented as macros]: -# -# glp_printf -# glp_vprintf -# glp_term_hook -# glp_error -# glp_assert -# glp_error_hook -# -# 3) Plain data file reading functions [because they either -# use longjmp or varargs]: -# -# glp_sdf_set_jump -# glp_sdf_error -# glp_sdf_warning -# -# 4) Additional functions [because wat?]: -# -# lpx_check_kkt - -#}}} - -end # module diff --git a/extras/gzip.jl b/extras/gzip.jl deleted file mode 100644 index 040226c8c318a..0000000000000 --- a/extras/gzip.jl +++ /dev/null @@ -1,483 +0,0 @@ -## gzip file io ## - -module GZip - -import Base.show, Base.fd, Base.close, Base.flush, Base.truncate, Base.seek -import Base.skip, Base.position, Base.eof, Base.read, Base.readall -import Base.readuntil, Base.readline, Base.write - -export - GZipStream, - show, - -# io functions - gzopen, - gzdopen, - fd, - close, - flush, - truncate, - seek, - skip, - position, - eof, - read, - readall, - readuntil, - readline, - write, - -# lower-level io functions - gzgetc, - gzungetc, - gzgets, - gzputc, - gzwrite, - gzread, - gzbuffer, - -# File offset - ZFileOffset, - -# GZError, ZError, related constants (zlib_h.jl) - GZError, - ZError, - Z_OK, - Z_STREAM_END, - Z_NEED_DICT, - Z_ERRNO, - Z_STREAM_ERROR, - Z_DATA_ERROR, - Z_MEM_ERROR, - Z_BUF_ERROR, - Z_VERSION_ERROR, - -# Compression constants (zlib_h.jl) - Z_NO_COMPRESSION, - Z_BEST_SPEED, - Z_BEST_COMPRESSION, - Z_DEFAULT_COMPRESSION, - -# Compression strategy (zlib_h.jl) - Z_FILTERED, - Z_HUFFMAN_ONLY, - Z_RLE, - Z_FIXED, - Z_DEFAULT_STRATEGY, - -# Default buffer sizes - Z_DEFAULT_BUFSIZE, - Z_BIG_BUFSIZE - -#load("zlib_h") -include("$JULIA_HOME/../share/julia/extras/zlib_h.jl") - -# Expected line length for strings -const GZ_LINE_BUFSIZE = 256 - -# Wrapper around gzFile -type GZipStream <: IO - name::String - gz_file::Ptr{Void} - buf_size::Int - - _closed::Bool - - GZipStream(name::String, gz_file::Ptr{Void}, buf_size::Int) = - (x = new(name, gz_file, buf_size, false); finalizer(x, close); x) -end -GZipStream(name::String, gz_file::Ptr{Void}) = GZipStream(name, gz_file, Z_DEFAULT_BUFSIZE) - -# gzerror -function gzerror(err::Integer, s::GZipStream) - e = Int32[err] - if !s._closed - msg_p = ccall(dlsym(_zlib, :gzerror), Ptr{Uint8}, (Ptr{Void}, Ptr{Int32}), - s.gz_file, e) - msg = (msg_p == C_NULL ? "" : bytestring(msg_p)) - else - msg = "(GZipStream closed)" - end - (e[1], msg) -end -gzerror(s::GZipStream) = gzerror(0, s) - -type GZError <: Exception - err::Int32 - err_str::String - - GZError(e::Integer, str::String) = new(int32(e), str) - GZError(e::Integer, s::GZipStream) = (a = gzerror(e, s); new(a[1], a[2])) - GZError(s::GZipStream) = (a = gzerror(s); new(a[1], a[2])) -end - -# show -show(io, s::GZipStream) = print(io, "GZipStream(", s.name, ")") - -macro test_eof_gzerr(s, cc, val) - quote - if $(esc(s))._closed throw(EOFError()) end - ret = $(esc(cc)) - if ret == $(esc(val)) - if eof($(esc(s))) throw(EOFError()) else throw(GZError($(esc(s)))) end - end - ret - end -end - -macro test_eof_gzerr2(s, cc, val) - quote - if $(esc(s))._closed throw(EOFError()) end - ret = $(esc(cc)) - if ret == $(esc(val)) && !eof($(esc(s))) throw(GZError($(esc(s)))) end - ret - end -end - -macro test_gzerror(s, cc, val) - quote - if $(esc(s))._closed throw(EOFError()) end - ret = $(esc(cc)) - if ret == $(esc(val)) throw(ret, GZError($(esc(s)))) end - ret - end -end - -macro test_gzerror0(s, cc) - quote - if $(esc(s))._closed throw(EOFError()) end - ret = $(esc(cc)) - if ret <= 0 throw(GZError(ret, $(esc(s)))) end - ret - end -end - -macro test_z_ok(cc) - quote - ret = $(esc(cc)) - if (ret != Z_OK) throw(ZError(ret)) end - ret - end -end - -# Easy access to gz reading/writing functions (Internal) -gzgetc(s::GZipStream) = - @test_eof_gzerr(s, ccall(dlsym(_zlib, :gzgetc), Int32, (Ptr{Void},), s.gz_file), -1) - -gzungetc(c::Integer, s::GZipStream) = - @test_eof_gzerr(s, ccall(dlsym(_zlib, :gzungetc), Int32, (Int32, Ptr{Void}), c, s.gz_file), -1) - -gzgets(s::GZipStream, a::Array{Uint8}) = - @test_eof_gzerr2(s, ccall(dlsym(_zlib, :gzgets), Ptr{Uint8}, (Ptr{Void}, Ptr{Uint8}, Int32), - s.gz_file, a, int32(length(a))), C_NULL) - -gzgets(s::GZipStream, p::Ptr{Uint8}, len::Integer) = - @test_eof_gzerr2(s, ccall(dlsym(_zlib, :gzgets), Ptr{Uint8}, (Ptr{Void}, Ptr{Uint8}, Int32), - s.gz_file, p, int32(len)), C_NULL) - -gzputc(s::GZipStream, c::Integer) = - @test_gzerror(s, ccall(dlsym(_zlib, :gzputc), Int32, (Ptr{Void}, Int32), - s.gz_file, int32(c)), -1) - -gzwrite(s::GZipStream, p::Ptr, len::Integer) = - @test_gzerror0(s, ccall(dlsym(_zlib, :gzwrite), Int32, (Ptr{Void}, Ptr{Void}, Uint32), - s.gz_file, p, len)) - -gzread(s::GZipStream, p::Ptr, len::Integer) = - @test_gzerror(s, ccall(dlsym(_zlib, :gzread), Int32, (Ptr{Void}, Ptr{Void}, Uint32), - s.gz_file, p, len), -1) - -# Doesn't exist in zlib 1.2.3 or earlier -if dlsym_e(_zlib, :gzbuffer) != C_NULL - gzbuffer(gz_file::Ptr, gz_buf_size::Integer) = - ccall(dlsym(_zlib, :gzbuffer), Int32, (Ptr{Void}, Uint32), gz_file, gz_buf_size) -else - gzbuffer(gz_file::Ptr, gz_buf_size::Integer) = int32(-1) -end - -##### - -# Use 64-bit functions if available - -if dlsym_e(_zlib, :gzopen64) != C_NULL - const _gzopen = :gzopen64 - const _gzseek = :gzseek64 - const _gztell = :gztell64 - #_gzoffset = :gzoffset64 ## not implemented -else - const _gzopen = :gzopen - const _gzseek = :gzseek - const _gztell = :gztell - #_gzoffset = :gzoffset ## not implemented -end - -function gzopen(fname::String, gzmode::String, gz_buf_size::Integer) - # gzmode can contain extra characters specifying - # * compression level (0-9) - # * strategy ('f' => filtered data, 'h' -> Huffman-only compression, - # 'R' -> run-length encoding, 'F' -> fixed code compression) - # - # '+' is also not allowed - - # For windows, force binary mode; doesn't hurt on unix - if !contains(gzmode, 'b') - gzmode *= "b" - end - - gz_file = ccall(dlsym(_zlib, _gzopen), Ptr{Void}, (Ptr{Uint8}, Ptr{Uint8}), fname, gzmode) - if gz_file == C_NULL - throw(GZError(-1, "gzopen failed")) - end - if gz_buf_size != Z_DEFAULT_BUFSIZE - if gzbuffer(gz_file, gz_buf_size) == -1 - # Generally a non-fatal error, although it shouldn't happen here - gz_buf_size = Z_DEFAULT_BUFSIZE - end - end - return GZipStream("", gz_file, gz_buf_size) -end -gzopen(fname::String, gzmode::String) = gzopen(fname, gzmode, Z_DEFAULT_BUFSIZE) -gzopen(fname::String) = gzopen(fname, "rb", Z_DEFAULT_BUFSIZE) - -function gzopen(f::Function, args...) - io = gzopen(args...) - x = try f(io) catch err - close(io) - throw(err) - end - close(io) - return x -end - -function gzdopen(name::String, fd::Integer, gzmode::String, gz_buf_size::Integer) - if !contains(gzmode, 'b') - gzmode *= "b" - end - - # Duplicate the file descriptor, since we have no way to tell gzclose() - # not to close the original fd - dup_fd = ccall(:dup, Int32, (Int32,), fd) - - gz_file = ccall(dlsym(_zlib, :gzdopen), Ptr{Void}, (Int32, Ptr{Uint8}), dup_fd, gzmode) - if gz_file == C_NULL - throw(GZError(-1, "gzdopen failed")) - end - if gz_buf_size != Z_DEFAULT_BUFSIZE - if gzbuffer(gz_file, gz_buf_size) == -1 - # Generally a non-fatal error, although it shouldn't happen here - gz_buf_size = Z_DEFAULT_BUFSIZE - end - end - return GZipStream(name, gz_file, gz_buf_size) -end -gzdopen(fd::Integer, gzmode::String, gz_buf_size::Integer) = gzdopen(string(""), fd, gzmode, gz_buf_size) -gzdopen(fd::Integer, gz_buf_size::Integer) = gzdopen(fd, "rb", gz_buf_size) -gzdopen(fd::Integer, gzmode::String) = gzdopen(fd, gzmode, Z_DEFAULT_BUFSIZE) -gzdopen(fd::Integer) = gzdopen(fd, "rb", Z_DEFAULT_BUFSIZE) -gzdopen(s::IOStream, args...) = gzdopen(fd(s), args...) - - -fd(s::GZipStream) = error("fd is not supported for GZipStreams") - -function close(s::GZipStream) - - # The garbage collector needs to be temporarily disabled because of a possible - # race condition if it runs between testing and setting s._closed - - gc_disable() - if s._closed - gc_enable() - return Z_STREAM_ERROR - end - s._closed = true - gc_enable() - - s.name *= " (closed)" - - ret = (@test_z_ok ccall(dlsym(_zlib, :gzclose), Int32, (Ptr{Void},), s.gz_file)) - - return ret -end - -flush(s::GZipStream, fl::Integer) = - @test_z_ok ccall(dlsym(_zlib, :gzflush), Int32, (Ptr{Void}, Int32), s.gz_file, int32(fl)) -flush(s::GZipStream) = flush(s, Z_SYNC_FLUSH) - -truncate(s::GZipStream, n::Integer) = error("truncate is not supported for GZipStreams") - -# Note: seeks to byte position within uncompressed data stream -seek(s::GZipStream, n::Integer) = - (ccall(dlsym(_zlib, _gzseek), ZFileOffset, (Ptr{Void}, ZFileOffset, Int32), - s.gz_file, n, SEEK_SET)!=-1 || # Mimick behavior of seek(s::IOStream, n) - error("seek (gzseek) failed")) - -seek_end(s::GZipStream) = error("seek_end is not supported for GZipStreams") - -# Note: skips bytes within uncompressed data stream -skip(s::GZipStream, n::Integer) = - (ccall(dlsym(_zlib, _gzseek), ZFileOffset, (Ptr{Void}, ZFileOffset, Int32), - s.gz_file, n, SEEK_CUR)!=-1 || - error("skip (gzseek) failed")) # Mimick behavior of skip(s::IOStream, n) - -position(s::GZipStream) = - ccall(dlsym(_zlib, _gztell), ZFileOffset, (Ptr{Void},), s.gz_file) - -eof(s::GZipStream) = bool(ccall(dlsym(_zlib, :gzeof), Int32, (Ptr{Void},), s.gz_file)) - -function check_eof(s::GZipStream) - # Force eof to be set... - try - c = gzgetc(s) - gzungetc(c, s) - catch e - if !isa(e, EOFError) - throw(e) - end - end -end - -# Mimics read(s::IOStream, a::Array{T}) -function read{T<:Union(Int8,Uint8,Int16,Uint16,Int32,Uint32,Int64,Uint64, - Int128,Uint128,Float32,Float64,Complex64,Complex128)}(s::GZipStream, a::Array{T}) - nb = numel(a)*sizeof(T) - # Note: this will overflow and succeed without warning if nb > 4GB - ret = ccall(dlsym(_zlib, :gzread), Int32, - (Ptr{Void}, Ptr{Void}, Uint32), s.gz_file, a, nb) - if ret == -1 - throw(GZError(s)) - end - if ret < nb - throw(EOFError()) # TODO: Do we have/need a way to read without throwing an error near the end of the file? - end - check_eof(s) - a -end - -function read(s::GZipStream, ::Type{Uint8}) - ret = gzgetc(s) - if ret == -1 - throw(GZError(s)) - end - check_eof(s) - uint8(ret) -end - - -# For this function, it's really unfortunate that zlib is -# not integrated with ios -# TODO: are we coping the buffer on return? If so, figure out how not to. -function readall(s::GZipStream, bufsize::Int) - buf = Array(Uint8, bufsize) - len = 0 - while true - ret = gzread(s, pointer(buf)+len, bufsize) - if ret == 0 - # check error status to make sure stream was not truncated - # (we won't normally get an error until the close, because it's - # possible that the file is still being written to.) - - ## *** Disabled, to allow the function to return the buffer *** - ## *** Truncation error will be generated on gzclose... *** - - #(err, msg) = gzerror(s) - #if err != Z_OK - # throw(GZError(err, msg)) - #end - - # Resize buffer to exact length - if length(buf) > len - grow(buf, len-length(buf)) - end - return bytestring(buf) - end - len += ret - # Grow the buffer so that bufsize bytes will fit - grow(buf, bufsize-(length(buf)-len)) - end -end -readall(s::GZipStream) = readall(s, Z_BIG_BUFSIZE) - -# TODO: Create a c-wrapper based on gzreadline -function readuntil(s::GZipStream, delim) - if delim == '\n' - return readline(s) - else - buf = memio(GZ_LINE_BUFSIZE, false) - c = read(s, Char) - print(buf, c) - while c != delim && !eof(s) - try - c = read(s, Char) - print(buf, c) - catch e - if !isa(e, EOFError) - throw(e) - end - end - end - check_eof(s) - takebuf_string(buf) - end -end - - -function readline(s::GZipStream) - buf = Array(Uint8, GZ_LINE_BUFSIZE) - pos = 1 - - if gzgets(s, buf) == C_NULL # Throws an exception on error - return "" - end - - while(true) - # since gzgets didn't return C_NULL, there must be a \0 in the buffer - eos = memchr(buf, '\0', pos) - if eos == 1 || buf[eos-1] == '\n' - return bytestring(buf[1:eos-1]) - end - - # If we're at the end of the file, return the string - if eof(s) return bytestring(buf[1:eos-1]) end - - # Otherwise, append to the end of the previous buffer - - # Grow the buffer so that there's room for GZ_LINE_BUFSIZE chars - add_len = GZ_LINE_BUFSIZE - (length(buf)-eos+1) - grow(buf, add_len) - pos = eos - - # Read in the next chunk - if gzgets(s, pointer(buf)+pos-1, GZ_LINE_BUFSIZE) == C_NULL - # eof(s); remove extra buffer space - grow(buf, -GZ_LINE_BUFSIZE) - return bytestring(buf) - end - end -end - -write(s::GZipStream, b::Uint8) = gzputc(s, b) - -function write{T}(s::GZipStream, a::Array{T}) - if isa(T,BitsKind) - return gzwrite(s, pointer(a), numel(a)*sizeof(T)) - else - invoke(write, (Any, Array), s, a) - end -end - -write(s::GZipStream, p::Ptr, nb::Integer) = gzwrite(s, p, nb) - -function write{T,N}(s::GZipStream, a::SubArray{T,N,Array}) - if !isa(T,BitsKind) || stride(a,1)!=1 - return invoke(write, (Any, AbstractArray), s, a) - end - colsz = size(a,1)*sizeof(T) - if N==1 - write(s, pointer(a, 1), colsz) - else - cartesian_map((idxs...)->write(s, pointer(a, idxs), colsz), - tuple(1, size(a)[2:]...)) - end -end - -end # module GZip diff --git a/extras/image.jl b/extras/image.jl deleted file mode 100644 index ca15c6a2b867c..0000000000000 --- a/extras/image.jl +++ /dev/null @@ -1,944 +0,0 @@ -import Base.ref, Base.assign, Base.sub, Base.size, Base.copy - -## Color spaces -abstract ColorSpace -type CSnil <: ColorSpace -end -type CSgray <: ColorSpace -end -type CSsRGB <: ColorSpace -end -type CSCMYK <: ColorSpace -end -# Color space where each channel is given a name, e.g., -# cs = CSNamed("GFP","tdTomato") -# or -# cs = CSNamed(["GFP","tdTomato"]) -type CSNamed <: ColorSpace - str::Vector{ASCIIString} -end -CSNamed(t...) = CSNamed([t...]) # allow tuple -function ref(n::CSNamed,ind::Int) - return n.str[ind] -end -function assign(n::CSNamed,value,key) - n.str[key] = value -end - -# The super-type of all images -abstract Image - -# General principles: - -# Image types implement fields needed to specify an image data array -# A, and all fields critical to the interpretation of this array. In -# addition, a "metadata" field is present so that users can store -# other information as desired. - -# The dimensions of the data array fall into 3 general categories: -# space dimensions (e.g., x and y), time (if the data array -# represents a sequence of images over time), and channel dimension -# (e.g., color channel index). It's important to know the storage order of -# the data array. This is signaled by a storage order string, which -# introduces a one-character name for each array dimension. For -# example, one could create an image out of a data array A[y,x,c] as -# img = ImageArray(A,"yxc") -# Images can then be manipulated in "ordinary" ways, -# imgsnip = img[50:200,100:175,1:3] -# but also in terms of these coordinate names, e.g., -# imsnip = img['x',100:175,'y',50:200] -# which would yield the same result. -# -# There are two reserved choices for the array dimension names: 't' -# (for time) and 'c' (for channel). All other choices are assumed to -# be spatial. The comparison is case-sensitive, so 'T' and 'C' can -# be used for spatial axes. Thus, "yxc" might be used for an RGB -# image with color data in the third array dimension, and "xyzt" for -# 3d grayscale over time. -# -# Other than the usage of 't' and 'c', the choices of dimension -# names is arbitrary. One suggestion is to choose a name that -# indicates the direction of increasing array index. For example, -# choosing "br" (for "bottom-right") instead of "yx" might more -# clearly signal that the upper-left corner (as displayed on the -# screen) should be A[1,1], and the bottom-right corner is -# A[sz1,sz2]. In MRI, "RAS" might indicate a standard right-handed -# coordinate system ('R' = rightward-increasing, 'A' = -# anterior-increasing, 'S' = superior-increasing). Note that "ASR" -# would imply the same coordinate system but that the data are -# stored in [anterior/posterior, superior/inferior, right/left] -# order. -# -# The remaining "principal" fields are those that are minimally needed -# to interpret the data array: -# The spatial geometry is specified by fields that document how -# indices for the array's spatial dimensions correspond to -# physical space (any linear relationship is supported, via a -# transform matrix); -# The timing information is supplied by a lookup vector specifying -# the time of each temporal slice; -# The channel data is specified in terms of a colorspace string -# ("sRGB"), or a list of strings specifying the meaning of each -# channel index (e.g., ["GFP","tdTomato"] for a 2-color -# fluorescence image) - -# More detail on spatial specifications: -# arrayi stands for "array index", i.e., the (integer) indices into -# the data array -# physc means "physical coordinate", i.e., units in actual space (e.g., -# position in millimeters) -# arrayi2physc is a n-by-(n+1) transform matrix T; p = T*[a,1] would -# take a column vector a containing the index coordinates of a -# single element and convert it into a column vector of physical -# coordinates. In other words, the separation between adjacent -# "pixels" along the jth array dimension corresponds to a -# physical-space displacement of T*[ej,0], where ej is the unit -# vector along the jth dimension. The right-hand column of T can be -# used to encode translations, so that the (ficticious) array item -# A[0,...,0] corresponds to a physical-space origin of coordinates -# at position T[:,end]. There are utility functions that make -# it easy to specify T in common cases, e.g., -# set_pixel_spacing(im,[0.15 0.15 3]) -# would create a transform matrix for a confocal microscopy stack -# with 0.15 microns between pixels in the x- and y- dimensions, and -# 3 microns between slices along the z-dimension, with the result -# T = [0.15 0 0 0; -# 0 0.15 0 0; -# 0 0 3 0] -# - -# A final important task is representing valid pixels, since -# real-world imaging devices/situations can result in a subset of -# the data being untrustworthy. In cases where the underlying data -# type has NaN, you can easily mark the invalid pixels in the data -# array itself. However, when the data type does not have NaN, the -# valid field is necessary. Note that when both are possible, the -# validity of a pixel should be evaluated as !isnan(data) & valid, -# meaning that marking a pixel as invalid by either NaN or setting -# valid false suffices. -# The valid field can be set to true (all pixels are trustworthy), a -# boolean matrix of the size of the data array (marking trustworthy -# pixels individually), or as a container of arrays whose product -# would be equal to the full-size valid pixels array. For example, -# valid = [good_pixels_per_frame,good_frames] -# where good_pixels_per_frame is a boolean of size [sizex sizey] and -# good_frames is a boolean of size [1 1 n_frames]. - - -# Utility functions: -# Make sure the storage order string doesn't duplicate any names -function assert_chars_unique(s::ASCIIString) - ss = sort(b"$s") - for i = 2:length(ss) - if ss[i] == ss[i-1] - error("Array dimension names cannot repeat") - end - end -end - -function isspatial(s::ASCIIString) -# this returns a vector of bools, is it OK to have the name start -# with "is"? - indx = trues(length(s)) - matcht = match(r"t",s) - if !is(matcht,nothing) - indx[matcht.offset] = false; - end - matchc = match(r"c",s) - if !is(matchc,nothing) - indx[matchc.offset] = false; - end - return indx -end - -getminmax(::Type{Uint8}) = [typemin(Uint8),typemax(Uint8)] -getminmax(::Type{Uint16}) = [typemin(Uint16),typemax(Uint16)] -getminmax(::Type{Uint32}) = [typemin(Uint32),typemax(Uint32)] -getminmax(::Type{Int8}) = [typemin(Int8),typemax(Int8)] -getminmax(::Type{Int16}) = [typemin(Int16),typemax(Int16)] -getminmax(::Type{Int32}) = [typemin(Int32),typemax(Int32)] -getminmax(::Type{Float32}) = [typemin(Float32),typemax(Float32)] -getminmax(::Type{Float64}) = [typemin(Float64),typemax(Float64)] - -# An image type with all data held in memory -type ImageArray{DataType<:Number} <: Image - data::Array{DataType} # the raw data - arrayi_order::ASCIIString # storage order of data array, e.g. "yxc" - minmax::Vector{DataType} # min and max possible values - size_ancestor::Vector{Int} # size of the _original_ array (pre-snip) - arrayi_range::Vector{Range1{Int}} # vector of ranges (snipping out blocks) - arrayi2physc::Matrix{Float64} # transform matrix - physc_unit::Vector # vector of strings, e.g., "microns" - physc_name::Vector # vector of strings, like "X" or "horizontal" - arrayti2physt::Vector{Float64}# time coordinate lookup table - t_unit::String # time coordinate unit string - color_space # object of type ColorSpace - valid # which pixels can be trusted? - metadata # arbitrary metadata, like acquisition date&time, etc. -end -# Empty constructor (doesn't seem to work now, for unknown reason) -ImageArray{DataType<:Number}() = - ImageArray{DataType}(Array(DataType,0), - "", - getminmax(DataType), - Array(Int,0), - Array(Range1,0), - zeros(0,0), - Array(ASCIIString,0), - Array(ASCIIString,0), - zeros(0), - "", - "", - false, - "") -# Construct from a data array, providing defaults for everything -# except the storage order -function ImageArray{DataType<:Number}(data::Array{DataType},arrayi_order::ASCIIString) - sz = size(data) - szv = vcat(sz...) - n_dims = length(sz) - if strlen(arrayi_order) != n_dims - error("storage order string must have a length equal to the number of dimensions in the array") - end - # Enforce uniqueness of each array coordinate name - assert_chars_unique(arrayi_order) - # Count # of spatial dimensions - matcht = match(r"t",arrayi_order) - matchc = match(r"c",arrayi_order) - n_spatial_dims = n_dims - !is(matcht,nothing) - !is(matchc,nothing) - # Set up defaults for other fields - arrayi_range = map(x->1:x,szv) - physc_unit = Array(ASCIIString,n_spatial_dims) - physc_name = Array(ASCIIString,n_spatial_dims) - physc_unit[1:n_spatial_dims] = "" - physc_name[1:n_spatial_dims] = "" - T = [eye(n_spatial_dims) zeros(n_spatial_dims)] - if !is(matcht,nothing) - tindex = matcht.offset - arrayti2physt = linspace(1.0,sz[tindex],sz[tindex]) - t_unit = "" - else - arrayti2physt = zeros(0) - t_unit = "" - end - color_space = CSnil - if !is(matchc,nothing) - if size(data,matchc.offset) == 1 - color_space = CSgray - elseif size(data,matchc.offset) == 3 - color_space = CSsRGB - elseif szv[matchc.offset] == 4 - color_space = CSCMYK - end - end - ImageArray{DataType}(data,arrayi_order,getminmax(DataType),szv,arrayi_range,T,physc_unit,physc_name,arrayti2physt,t_unit,color_space,true,"") -end - -### Copy and ref functions ### -# Deep copy---copies everything that is immutable -function copy(img::ImageArray) - ImageArray(copy(img.data), - copy(img.arrayi_order), - copy(img.minmax), - copy(img.size_ancestor), - img.arrayi_range, # ranges are immutable, or will be - copy(img.arrayi2physc), - copy(img.physc_unit), - copy(img.physc_name), - copy(img.arrayti2physt), - copy(img.t_unit), - copy(img.color_space), - copy(img.valid), - copy(img.metadata)) -end - -# Copy everything but the data and the metadata -function copy_pfields(img::ImageArray) - ImageArray(img.data, - copy(img.arrayi_order), - copy(img.minmax), - copy(img.size_ancestor), - img.arrayi_range, - copy(img.arrayi2physc), - copy(img.physc_unit), - copy(img.physc_name), - copy(img.arrayti2physt), - copy(img.t_unit), - copy(img.color_space), - copy(img.valid), - img.metadata) -end - -# Copy just the data -function copy_data{DataType}(image_out::ImageArray{DataType},image_in::ImageArray{DataType}) - image_out.data = image_in.data[image_out.arrayi_range...] -end - -# Copy just the metadata -function copy_metadata{DataType}(image_out::ImageArray{DataType},image_in::ImageArray{DataType}) - image_out.metadata = copy(image_in.metadata) -end - -# Private function for converting name/value lists into indices -function _image_named_coords_sub(img::Image,ind...) - if length(ind) % 2 != 0 - println(ind...) - error("Coordinate/value must come in pairs") - end - # Prepare the coordinates - sniprange = map(x->1:x,vcat(size(img.data)...)) - for iarg = 1:2:length(ind) - idim = strchr(img.arrayi_order,ind[iarg]) - if idim == 0 - error(strcat("Array index name '",ind[iarg],"' does not match any of the names in \"",img.arrayi_order,"\"")) - end - sniprange[idim] = ind[iarg+1] - end - return sniprange -end - -# This supports two ref syntaxes -function ref(img::ImageArray,ind...) - if isa(ind[1],Char) - ## Named ref syntax: ref(img,'a',20:50,'b',40:200,...) - imgret = copy_pfields(img) - sniprange = _image_named_coords_sub(img,ind...) - # Do the snip - imgret.data = img.data[sniprange...] - imgret.arrayi_range = sniprange - return imgret - else - # Normal ref syntax: img[20:50,40:200,...] - imgret = copy_pfields(img) - imgret.data = ref(img.data,ind...) - for i = 1:length(ind) - imgret.arrayi_range[i] = ind[i] - end - return imgret - end -end -function sub(img::ImageArray,ind...) - if isa(ind[1],Char) - ## Named sub syntax: sub(img,'a',20:50,'b',40:200,...) - imgret = copy_pfields(img) - sniprange = _image_named_coords_sub(img,ind) - # Do the snip - imgret.data = sub(img.data,sniprange...) - imgret.arrayi_range = sniprange - return imgret - else - # Normal sub syntax: img[20:50,40:200,...] - imgret = copy_pfields(img) - imgret.data = sub(img.data,ind...) - for i = 1:length(ind) - imgret.arrayi_range[i] = ind[i] - end - return imgret - end -end -function assign(img::ImageArray,val,ind...) - if isa(ind[1],Char) - ## Named assign syntax: assign(img,'a',20:50,'b',40:200,...) - sniprange = _image_named_coords_sub(img,ind) - # Do the snip - img.data[sniprange...] = val - else - # Normal assign syntax: img[20:50,40:200,...] - imgret = copy_pfields(img) - img.data[ind...] = val - end -end - - -### Utility functions ### -function size(img::ImageArray) - return size(img.data) -end - -function set_pixel_spacing(img::Image,dx::Vector) - n_spatial_dims = size(img.arrayi2physc,1) - if n_spatial_dims != length(dx) - error("Dimensions do not match") - end - for idim = 1:n_spatial_dims - img.arrayi2physc[idim,idim] = dx[idim] - end -end - -function get_pixel_spacing(img::Image) - n_spatial_dims = size(img.arrayi2physc,1) - dx = zeros(n_spatial_dims) - for idim = 1:n_spatial_dims - dx[idim] = img.arrayi2physc[idim,idim] - end - return dx -end - - -### Manipulations -function permute!{DataType}(img::ImageArray{DataType},perm) - img.data = permute(img.data,perm) - img.size_ancestor = img.size_ancestor[perm] - img.arrayi_range = img.arrayi_range[perm] - # Permute arrayi2physc: first compute the spatial permutation - flag = isspatial(img.arrayi_order) - cflag = cumsum(int(flag)) - perm_spatial = cflag[perm[flag[perm]]] - img.arrayi2physc = [img.arrayi2physc[:,perm_spatial] img.arrayi2physc[:,end]] - # Finally, permute the storage order string - img.arrayi_order = img.arrayi_order[perm] -end - -############################################################# - -function lut(pal::Vector, a) - out = similar(a, eltype(pal)) - n = numel(pal) - for i=1:numel(a) - out[i] = pal[clamp(a[i], 1, n)] - end - out -end - -function indexedcolor(data, pal) - mn = min(data); mx = max(data) - indexedcolor(data, pal, mx-mn, (mx+mn)/2) -end - -function indexedcolor(data, pal, w, l) - n = numel(pal)-1 - if n == 0 - return fill(pal[1], size(data)) - end - w_min = l - w/2 - scale = w==0 ? 1 : w/n - lut(pal, iround((data - w_min)./scale) + 1) -end - -const palette_gray32 = uint32([4278190080, 4278716424, 4279242768, 4279769112, 4280295456, 4280887593, 4281413937, 4281940281, 4282466625, 4283058762, 4283585106, 4284111450, 4284637794, 4285164138, 4285756275, 4286282619, 4286808963, 4287335307, 4287927444, 4288453788, 4288980132, 4289506476, 4290032820, 4290624957, 4291151301, 4291677645, 4292203989, 4292796126, 4293322470, 4293848814, 4294375158, 4294967295]) - -const palette_fire = uint32([4284111450, 4284702808, 4285294423, 4285886038, 4286477397, 4287069012, 4287660627, 4288251985, 4288843600, 4289435215, 4290026574, 4290618189, 4291209804, 4291801162, 4292392777, 4292984392, 4293575751, 4294167366, 4294824517, 4294757442, 4294755904, 4294754365, 4294687291, 4294685752, 4294684214, 4294617139, 4294615601, 4294614062, 4294612524, 4294545449, 4294543911, 4294542372, 4294475298, 4294473759, 4294472221, 4294405146, 4294403608, 4294402069, 4294400531, 4294333456, 4294331918, 4294330379, 4294263305, 4294261766, 4294260228, 4294258946, 4293340673, 4292422401, 4291569665, 4290651649, 4289733377, 4288880641, 4287962369, 4287109889, 4286191617, 4285273344, 4284420864, 4283502592, 4282649856, 4281731584, 4280813568, 4279960832, 4279042560, 4278190080]) - -const palette_rainbow = uint32([4279125737, 4279064810, 4279004140, 4279009006, 4278948336, 4278953201, 4278892531, 4278897397, 4278836727, 4278841593, 4278644669, 4278513537, 4278382149, 4278251018, 4280086024, 4281921031, 4283756038, 4285591045, 4287491588, 4289326595, 4291161602, 4292996609, 4294897152, 4294759425, 4294687234, 4294615300, 4294543109, 4294471175, 4294398984, 4294327050, 4294254859, 4294182925]) - -redval(p) = (p>>>16)&0xff -greenval(p) = (p>>>8)&0xff -blueval(p) = p&0xff - -function write_bitmap_data(s, img) - n, m = size(img) - if eltype(img) <: Integer - if ndims(img) == 3 && size(img,3) == 3 - for i=1:n, j=1:m, k=1:3 - write(s, uint8(img[i,j,k])) - end - elseif ndims(img) == 2 - if is(eltype(img),Int32) || is(eltype(img),Uint32) - for i=1:n, j=1:m - p = img[i,j] - write(s, uint8(redval(p))) - write(s, uint8(greenval(p))) - write(s, uint8(blueval(p))) - end - else - for i=1:n, j=1:m, k=1:3 - write(s, uint8(img[i,j])) - end - end - else - error("unsupported array dimensions") - end - elseif eltype(img) <: FloatingPoint - # prevent overflow - a = copy(img) - a[img .> 1] = 1 - a[img .< 0] = 0 - if ndims(a) == 3 && size(a,3) == 3 - for i=1:n, j=1:m, k=1:3 - write(s, uint8(255*a[i,j,k])) - end - elseif ndims(a) == 2 - for i=1:n, j=1:m, k=1:3 - write(s, uint8(255*a[i,j])) - end - else - error("unsupported array dimensions") - end - else - error("unsupported array type") - end -end - -function ppmwrite(img, file::String) - s = open(file, "w") - write(s, "P6\n") - write(s, "# ppm file written by julia\n") - n, m = size(img) - write(s, "$m $n 255\n") - write_bitmap_data(s, img) - close(s) -end - -# demo: -# m = [ mandel(complex(r,i)) for i=-1:.01:1, r=-2:.01:0.5 ]; -# ppmwrite(indexedcolor(m, palette_fire), "mandel.ppm") - -function imread(file::String) - cmd = `convert -format "%w %h" -identify $file rgb:-` - stream = fdio(read_from(cmd).fd, true) - spawn(cmd) - szline = readline(stream) - spc = strchr(szline, ' ') - w = parse_int(szline[1:spc-1]) - h = parse_int(szline[spc+1:end-1]) - img = Array(Float64, h, w, 3) - for i=1:h, j=1:w, k = 1:3 - img[i,j,k] = float64(read(stream, Uint8))/255.0 - end - img -end - -function imwrite(I, file::String) - if length(file) > 3 && file[end-3:end]==".ppm" - # fall back to built-in ppmwrite in case convert not available - return ppmwrite(I, file) - end - h, w = size(I) - cmd = `convert -size $(w)x$(h) -depth 8 rgb: $file` - stream = fdio(write_to(cmd).fd, true) - spawn(cmd) - write_bitmap_data(stream, I) - close(stream) - wait(cmd) -end - -function imshow(img, range) - if ndims(img) == 2 - # only makes sense for gray scale images - img = imadjustintensity(img, range) - end - tmp::String = "./tmp.ppm" - imwrite(img, tmp) - cmd = `feh $tmp` - spawn(cmd) -end - -imshow(img) = imshow(img, []) - -function imadjustintensity{T}(img::Array{T,2}, range) - if length(range) == 0 - range = [min(img) max(img)] - elseif length(range) == 1 - error("incorrect range") - end - tmp = (img - range[1])/(range[2] - range[1]) - tmp[tmp .> 1] = 1 - tmp[tmp .< 0] = 0 - out = tmp -end - -function rgb2gray{T}(img::Array{T,3}) - n, m = size(img) - wr, wg, wb = 0.30, 0.59, 0.11 - out = Array(T, n, m) - if ndims(img)==3 && size(img,3)==3 - for i=1:n, j=1:m - out[i,j] = wr*img[i,j,1] + wg*img[i,j,2] + wb*img[i,j,3] - end - elseif is(eltype(img),Int32) || is(eltype(img),Uint32) - for i=1:n, j=1:m - p = img[i,j] - out[i,j] = wr*redval(p) + wg*greenval(p) + wb*blueval(p) - end - else - error("unsupported array type") - end - out -end - -rgb2gray{T}(img::Array{T,2}) = img - -function sobel() - f = [1.0 2.0 1.0; 0.0 0.0 0.0; -1.0 -2.0 -1.0] - return f, f' -end - -function prewitt() - f = [1.0 1.0 1.0; 0.0 0.0 0.0; -1.0 -1.0 -1.0] - return f, f' -end - -# average filter -function imaverage(filter_size) - if length(filter_size) != 2 - error("wrong filter size") - end - m, n = filter_size[1], filter_size[2] - if mod(m, 2) != 1 || mod(n, 2) != 1 - error("filter dimensions must be odd") - end - f = ones(Float64, m, n)/(m*n) -end - -imaverage() = imaverage([3 3]) - -# laplacian filter kernel -function imlaplacian(diagonals::String) - if diagonals == "diagonals" - return [1.0 1.0 1.0; 1.0 -8.0 1.0; 1.0 1.0 1.0] - elseif diagonals == "nodiagonals" - return [0.0 1.0 0.0; 1.0 -4.0 1.0; 0.0 1.0 0.0] - end -end - -imlaplacian() = imlaplacian("nodiagonals") - -# more general version -function imlaplacian(alpha::Number) - lc = alpha/(1 + alpha) - lb = (1 - alpha)/(1 + alpha) - lm = -4/(1 + alpha) - return [lc lb lc; lb lm lb; lc lb lc] -end - -# 2D gaussian filter kernel -function gaussian2d(sigma::Number, filter_size) - if length(filter_size) == 0 - # choose 'good' size - m = 4*ceil(sigma)+1 - n = m - elseif length(filter_size) != 2 - error("wrong filter size") - else - m, n = filter_size[1], filter_size[2] - end - if mod(m, 2) != 1 || mod(n, 2) != 1 - error("filter dimensions must be odd") - end - g = [exp(-(X.^2+Y.^2)/(2*sigma.^2)) for X=-floor(m/2):floor(m/2), Y=-floor(n/2):floor(n/2)] - return g/sum(g) -end - -gaussian2d(sigma::Number) = gaussian2d(sigma, []) -gaussian2d() = gaussian2d(0.5, []) - -# difference of gaussian -function imdog(sigma::Number) - m = 4*ceil(sqrt(2)*sigma)+1 - return gaussian2d(sqrt(2)*sigma, [m m]) - gaussian2d(sigma, [m m]) -end - -imdog() = imdog(0.5) - -# laplacian of gaussian -function imlog(sigma::Number) - m = 4*ceil(sigma)+1 - return [((x^2+y^2-sigma^2)/sigma^4)*exp(-(x^2+y^2)/(2*sigma^2)) for x=-floor(m/2):floor(m/2), y=-floor(m/2):floor(m/2)] -end - -imlog() = imlog(0.5) - -# Sum of squared differences -function ssd{T}(A::Array{T}, B::Array{T}) - return sum((A-B).^2) -end - -# normalized by Array size -ssdn{T}(A::Array{T}, B::Array{T}) = ssd(A, B)/numel(A) - -# sum of absolute differences -function sad{T}(A::Array{T}, B::Array{T}) - return sum(abs(A-B)) -end - -# normalized by Array size -sadn{T}(A::Array{T}, B::Array{T}) = sad(A, B)/numel(A) - -# normalized cross correlation -function ncc{T}(A::Array{T}, B::Array{T}) - Am = (A-mean(A))[:] - Bm = (B-mean(B))[:] - return dot(Am,Bm)/(norm(Am)*norm(Bm)) -end - -function imfilter{T}(img::Matrix{T}, filter::Matrix{T}, border::String, value) - si, sf = size(img), size(filter) - A = zeros(T, si[1]+sf[1]-1, si[2]+sf[2]-1) - s1, s2 = int((sf[1]-1)/2), int((sf[2]-1)/2) - # correlation instead of convolution - filter = fliplr(fliplr(filter).') - mid1 = s1+1:s1+si[1] - mid2 = s2+1:s2+si[2] - left = 1:s2 - right = size(A,2)-s2+1:size(A,2) - top = 1:s1 - bot = size(A,1)-s1+1:size(A,1) - if border == "replicate" - A[mid1, mid2] = img - A[mid1, left] = repmat(img[:,1], 1, s2) - A[mid1, right] = repmat(img[:,end], 1, s2) - A[top, mid2] = repmat(img[1,:], s1, 1) - A[bot, mid2] = repmat(img[end,:], s1, 1) - A[top, left] = fliplr(fliplr(img[top, left])') - A[bot, left] = img[end-s1+1:end, left]' - A[top, right] = img[top, end-s2+1:end]' - A[bot, right] = flipud(fliplr(img[end-s1+1:end, end-s2+1:end]))' - elseif border == "circular" - A[mid1, mid2] = img - A[mid1, left] = img[:, end-s2+1:end] - A[mid1, right] = img[:, left] - A[top, mid2] = img[end-s1+1:end, :] - A[bot, mid2] = img[top, :] - A[top, left] = img[end-s1+1:end, end-s2+1:end] - A[bot, left] = img[top, end-s2+1:end] - A[top, right] = img[end-s1+1:end, left] - A[bot, right] = img[top, left] - elseif border == "mirror" - A[mid1, mid2] = img - A[mid1, left] = fliplr(img[:, left]) - A[mid1, right] = fliplr(img[:, end-s2+1:end]) - A[top, mid2] = flipud(img[top, :]) - A[bot, mid2] = flipud(img[end-s1+1:end, :]) - A[top, left] = fliplr(fliplr(img[top, left])') - A[bot, left] = img[end-s1+1:end, left]' - A[top, right] = img[top, end-s2+1:end]' - A[bot, right] = flipud(fliplr(img[end-s1+1:end, end-s2+1:end]))' - elseif border == "value" - A += value - A[mid1, mid2] = img - else - error("wrong border treatment") - end - # check if separable - U, S, V = svd(filter) - separable = true; - for i = 2:length(S) - # assumption that <10^-7 \approx 0 - separable = separable && (abs(S[i]) < 1e-7) - end - if separable - # conv2 isn't suitable for this (kernel center should be the actual center of the kernel) - #C = conv2(U[:,1]*sqrt(S[1]), vec(V[1,:])*sqrt(S[1]), A) - x = U[:,1]*sqrt(S[1]) - y = vec(V[1,:])*sqrt(S[1]) - sa = size(A) - m = length(y)+sa[1] - n = length(x)+sa[2] - B = zeros(T, m, n) - B[int(length(x)/2)+1:sa[1]+int(length(x)/2),int(length(y)/2)+1:sa[2]+int(length(y)/2)] = A - yp = zeros(T, m) - halfy = int((m-length(y)-1)/2) - yp[halfy+1:halfy+length(y)] = y - y = fft(yp) - xp = zeros(T, n) - halfx = int((n-length(x)-1)/2) - xp[halfx+1:halfx+length(x)] = x - x = fft(xp) - C = fftshift(ifft2(fft2(B) .* (y * x.'))) - if T <: Real - C = real(C) - end - else - #C = conv2(A, filter) - sa, sb = size(A), size(filter) - At = zeros(T, sa[1]+sb[1]-1, sa[2]+sb[2]-1) - Bt = zeros(T, sa[1]+sb[1]-1, sa[2]+sb[2]-1) - halfa1 = ifloor((size(At,1)-sa[1])/2) - halfa2 = ifloor((size(At,2)-sa[2])/2) - halfb1 = ifloor((size(Bt,1)-sb[1])/2) - halfb2 = ifloor((size(Bt,2)-sb[2])/2) - At[halfa1+1:halfa1+sa[1], halfa2+1:halfa2+sa[2]] = A - Bt[halfb1+1:halfb1+sb[1], halfb2+1:halfb2+sb[2]] = filter - C = fftshift(ifft2(fft2(At).*fft2(Bt))) - if T <: Real - C = real(C) - end - end - sc = size(C) - out = C[int(sc[1]/2-si[1]/2):int(sc[1]/2+si[1]/2)-1, int(sc[2]/2-si[2]/2):int(sc[2]/2+si[2]/2)-1] -end - -# imfilter for multi channel images -function imfilter{T}(img::Array{T,3}, filter::Matrix{T}, border::String, value) - x, y, c = size(img) - out = zeros(T, x, y, c) - for i = 1:c - out[:,:,i] = imfilter(img[:,:,i], filter, border, value) - end - out -end - -imfilter(img, filter) = imfilter(img, filter, "replicate", 0) -imfilter(img, filter, border) = imfilter(img, filter, border, 0) - -function imlineardiffusion{T}(img::Array{T,2}, dt::FloatingPoint, iterations::Integer) - u = img - f = imlaplacian() - for i = dt:dt:dt*iterations - u = u + dt*imfilter(u, f, "replicate") - end - u -end - -function imthresh{T}(img::Array{T,2}, threshold::FloatingPoint) - if !(0.0 <= threshold <= 1.0) - error("threshold must be between 0 and 1") - end - img_max, img_min = max(img), min(img) - tmp = zeros(T, size(img)) - # matter of taste? - #tmp[img >= threshold*(img_max-img_min)+img_min] = 1 - tmp[img >= threshold] = 1 - return tmp -end - -function imgaussiannoise{T}(img::Array{T}, variance::Number, mean::Number) - return img + sqrt(variance)*randn(size(img)) + mean -end - -imgaussiannoise{T}(img::Array{T}, variance::Number) = imgaussiannoise(img, variance, 0) -imgaussiannoise{T}(img::Array{T}) = imgaussiannoise(img, 0.01, 0) - -# 'illustrates' fourier transform -ftshow{T}(A::Array{T,2}) = imshow(log(1+abs(fftshift(A))),[]) - -function rgb2ntsc{T}(img::Array{T}) - trans = [0.299 0.587 0.114; 0.596 -0.274 -0.322; 0.211 -0.523 0.312] - out = zeros(T, size(img)) - for i = 1:size(img,1), j = 1:size(img,2) - out[i,j,:] = trans * vec(img[i,j,:]) - end - return out -end - -function ntsc2rgb{T}(img::Array{T}) - trans = [1 0.956 0.621; 1 -0.272 -0.647; 1 -1.106 1.703] - out = zeros(T, size(img)) - for i = 1:size(img,1), j = 1:size(img,2) - out[i,j,:] = trans * vec(img[i,j,:]) - end - return out -end - -function rgb2ycbcr{T}(img::Array{T}) - trans = [65.481 128.533 24.966; -37.797 -74.203 112; 112 -93.786 -18.214] - offset = [16.0; 128.0; 128.0] - out = zeros(T, size(img)) - for i = 1:size(img,1), j = 1:size(img,2) - out[i,j,:] = offset + trans * vec(img[i,j,:]) - end - return out -end - -function ycbcr2rgb{T}(img::Array{T}) - trans = inv([65.481 128.533 24.966; -37.797 -74.203 112; 112 -93.786 -18.214]) - offset = [16.0; 128.0; 128.0] - out = zeros(T, size(img)) - for i = 1:size(img,1), j = 1:size(img,2) - out[i,j,:] = trans * (vec(img[i,j,:]) - offset) - end - return out -end - -function imcomplement{T}(img::Array{T}) - return 1 - img -end - -function rgb2hsi{T}(img::Array{T}) - R = img[:,:,1] - G = img[:,:,2] - B = img[:,:,3] - H = acos((1/2*(2*R - G - B)) ./ (((R - G).^2 + (R - B).*(G - B)).^(1/2)+eps(T))) - H[B .> G] = 2*pi - H[B .> G] - H /= 2*pi - rgb_sum = R + G + B - rgb_sum[rgb_sum .== 0] = eps(T) - S = 1 - 3./(rgb_sum).*min(R, G, B) - H[S .== 0] = 0 - I = 1/3*(R + G + B) - return cat(3, H, S, I) -end - -function hsi2rgb{T}(img::Array{T}) - H = img[:,:,1]*(2pi) - S = img[:,:,2] - I = img[:,:,3] - R = zeros(T, size(img,1), size(img,2)) - G = zeros(T, size(img,1), size(img,2)) - B = zeros(T, size(img,1), size(img,2)) - RG = 0 .<= H .< 2*pi/3 - GB = 2*pi/3 .<= H .< 4*pi/3 - BR = 4*pi/3 .<= H .< 2*pi - # RG sector - B[RG] = I[RG].*(1 - S[RG]) - R[RG] = I[RG].*(1 + (S[RG].*cos(H[RG]))./cos(pi/3 - H[RG])) - G[RG] = 3*I[RG] - R[RG] - B[RG] - # GB sector - R[GB] = I[GB].*(1 - S[GB]) - G[GB] = I[GB].*(1 + (S[GB].*cos(H[GB] - pi/3))./cos(H[GB])) - B[GB] = 3*I[GB] - R[GB] - G[GB] - # BR sector - G[BR] = I[BR].*(1 - S[BR]) - B[BR] = I[BR].*(1 + (S[BR].*cos(H[BR] - 2*pi/3))./cos(-pi/3 - H[BR])) - R[BR] = 3*I[BR] - G[BR] - B[BR] - return cat(3, R, G, B) -end - -function imstretch{T}(img::Array{T,2}, m::Number, slope::Number) - return 1./(1 + (m./(img + eps(T))).^slope) -end - -function imedge{T}(img::Array{T}, method::String, border::String) - # needs more methods - if method == "sobel" - s1, s2 = sobel() - img1 = imfilter(img, s1, border) - img2 = imfilter(img, s2, border) - return img1, img2, sqrt(img1.^2 + img2.^2), atan2(img2, img1) - elseif method == "prewitt" - s1, s2 = prewitt() - img1 = imfilter(img, s1, border) - img2 = imfilter(img, s2, border) - return img1, img2, sqrt(img1.^2 + img2.^2), atan2(img2, img1) - end -end - -imedge{T}(img::Array{T}, method::String) = imedge(img, method, "replicate") -imedge{T}(img::Array{T}) = imedge(img, "sobel", "replicate") - -# forward and backward differences -# can be very helpful for discretized continuous models -forwarddiffy{T}(u::Array{T,2}) = [u[2:end,:]; u[end,:]] - u -forwarddiffx{T}(u::Array{T,2}) = [u[:,2:end] u[:,end]] - u -backdiffy{T}(u::Array{T,2}) = u - [u[1,:]; u[1:end-1,:]] -backdiffx{T}(u::Array{T,2}) = u - [u[:,1] u[:,1:end-1]] - -function imROF{T}(img::Array{T,2}, lambda::Number, iterations::Integer) - # Total Variation regularized image denoising using the primal dual algorithm - # Also called Rudin Osher Fatemi (ROF) model - # lambda: regularization parameter - s1, s2 = size(img) - p = zeros(T, s1, s2, 2) - u = zeros(T, s1, s2) - grad_u = zeros(T, s1, s2, 2) - div_p = zeros(T, s1, s2) - dt = lambda/4 - for i = 1:iterations - div_p = backdiffx(p[:,:,1]) + backdiffy(p[:,:,2]) - u = img + div_p/lambda - grad_u = cat(3, forwarddiffx(u), forwarddiffy(u)) - grad_u_mag = sqrt(grad_u[:,:,1].^2 + grad_u[:,:,2].^2) - tmp = 1 + grad_u_mag*dt - p = (dt*grad_u + p)./cat(3, tmp, tmp) - end - return u -end - -# ROF Model for color images -function imROF{T}(img::Array{T,3}, lambda::Number, iterations::Integer) - out = zeros(T, size(img)) - for i = 1:size(img, 3) - out[:,:,i] = imROF(img[:,:,i], lambda, iterations) - end - return out -end diff --git a/extras/iostring.jl b/extras/iostring.jl deleted file mode 100644 index 358b76b19ff92..0000000000000 --- a/extras/iostring.jl +++ /dev/null @@ -1,76 +0,0 @@ -## work with Vector{Uint8} via I/O primitives ## - -import Base.read, Base.skip, Base.seek, Base.seek_end, Base.position -import Base.truncate, Base.eof, Base.close, Base.write -import Base.bytestring - -# Stateful string -type IOString <: IO - data::Vector{Uint8} - ptr::Int - - IOString(data::Vector{Uint8}) = new(data, 1) - # TODO: should be copy on write if given a string - IOString(str::String) = IOString(str.data) - IOString() = IOString(Uint8[]) -end - -function read{T}(from::IOString, a::Array{T}) - if isa(T, BitsKind) - nb = numel(a)*sizeof(T) - if length(from.data) - from.ptr + 1 < nb - throw(EOFError()) - end - from.ptr += nb - return reshape(reinterpret(T, from.data[from.ptr-nb:from.ptr-1]), size(a)) - else - error("Read from IOString only supports bits types or arrays of bits types; got $T.") - end -end - -function read(from::IOString, ::Type{Uint8}) - if from.ptr > length(from.data) - throw(EOFError()) - end - from.ptr += 1 - return from.data[from.ptr-1] -end - -read{T}(from::IOString, ::Type{Ptr{T}}) = convert(Ptr{T}, read(from, Uint)) - -skip(io::IOString, n::Integer) = io.ptr += n -seek(io::IOString, n::Integer) = io.ptr = n+1 -seek_end(io::IOString) = io.ptr = length(io.data)+1 -position(io::IOString) = io.ptr-1 -truncate(io::IOString, n::Integer) = (grow(io.data, n-length(io.data)); io.ptr = min(io.ptr, n+1); uint(0)) -eof(io::IOString) = io.ptr-1 == length(io.data) -close(io::IOString) = (grow(io.data, 0); io.ptr = 1; nothing) - -bytestring(io::IOString) = bytestring(io.data) - -function write{T}(to::IOString, a::Array{T}) - if isa(T, BitsKind) - nb = numel(a)*sizeof(T) - nshort = to.ptr + nb - length(to.data) - 1 - if nshort > 0 - grow(to.data, nshort) - end - to.data[to.ptr:to.ptr+nb-1] = reinterpret(Uint8, a, (sizeof(T)*numel(a),)) - to.ptr += nb - else - error("Write to IOString only supports bits types or arrays of bits types; got $T.") - end - nb -end - -function write(to::IOString, a::Uint8) - if to.ptr + 1 > length(to.data) - push(to.data, a) - else - to.data[to.ptr] = a - end - to.ptr += 1 - sizeof(Uint8) -end - -write(to::IOString, p::Ptr) = write(to, convert(Uint, p)) diff --git a/extras/julia_web.jl b/extras/julia_web.jl deleted file mode 100644 index 63f01b9116700..0000000000000 --- a/extras/julia_web.jl +++ /dev/null @@ -1,241 +0,0 @@ -########################################### -# plotting functions -########################################### - -# number of points to plot for functions -const __PLOT_POINTS = 450 - -# the aspect ratio of plots -const __PLOT_ASPECT_RATIO = 1.95 - -# how similar the domain and range needs to be for aspect ratio preservation -const __PRESERVE_ASPECT_RATIO_THRESHOLD = 0.05 - -# how much extra padding to add around the plot -const __HORIZONTAL_PADDING = 0.05 -const __VERTICAL_PADDING = 0.05 - -# helper functions -function __safe_min(x::Array{Float64, 1}) - m = NaN - for i=1:length(x) - if x[i] != Inf && x[i] != -Inf && !isequal(x[i], NaN) - if isequal(m, NaN) || x[i] < m - m = x[i] - end - end - end - if isequal(m, NaN) - return error("unable to determine window dimensions") - end - return m -end - -function __safe_max(x::Array{Float64, 1}) - m = NaN - for i=1:length(x) - if x[i] != Inf && x[i] != -Inf && !isequal(x[i], NaN) - if isequal(m, NaN) || x[i] > m - m = x[i] - end - end - end - if isequal(m, NaN) - return error("unable to determine window dimensions") - end - return m -end - -# plot an array (window determined manually) - -plot(x::Array, y::Array, xmin::Number, xmax::Number, ymin::Number, ymax::Number) = - plot(x, y, xmin, xmax, ymin, ymax, "line") - -function plot(x::Array, y::Array, xmin::Number, xmax::Number, ymin::Number, ymax::Number, plottype::String) - # make sure we have arrays of numbers - x_safe = try convert(Array{Float64, 1}, x[:]) catch error("x coordinates must be convertable to float64") end - y_safe = try convert(Array{Float64, 1}, y[:]) catch error("y coordinates must be convertable to float64") end - - # make sure there are the same number of x and y coordinates - if length(x_safe) != length(y_safe) return error("size of x and y arrays must be equal") end - - # make sure there are enough data to plot - if length(x_safe) < 1 return error("at least two data points required for line plot") end - - # make sure the window is okay - if xmin == Inf || xmin == -Inf || isequal(xmin, NaN) return error(strcat("invalid xmin: ", string(xmin))) end - if xmax == Inf || xmax == -Inf || isequal(xmax, NaN) return error(strcat("invalid xmax: ", string(xmax))) end - if ymin == Inf || ymin == -Inf || isequal(ymin, NaN) return error(strcat("invalid ymin: ", string(ymin))) end - if ymax == Inf || ymax == -Inf || isequal(ymax, NaN) return error(strcat("invalid ymax: ", string(ymax))) end - if xmin >= xmax return error("xmax must be greater than xmin") end - if ymin >= ymax return error("ymax must be greater than ymin") end - - # remove points with infinite or NaN components - pairs = {} - for i=1:length(x_safe) - if x_safe[i] != Inf && x_safe[i] != -Inf && !isequal(x_safe[i], NaN) - if y_safe[i] != Inf && y_safe[i] != -Inf && !isequal(y_safe[i], NaN) - pairs = [pairs, {(x_safe[i], y_safe[i])}] - end - end - end - x_safe = [pairs[i][1] for i=1:length(pairs)] - y_safe = [pairs[i][2] for i=1:length(pairs)] - - # send the message to the browser - __write_message(__Message(__MSG_OUTPUT_PLOT, { - plottype, - strcat("[", join([string(i) for i=x_safe], ","), "]"), - strcat("[", join([string(i) for i=y_safe], ","), "]"), - string(float64(xmin)), - string(float64(xmax)), - string(float64(ymin)), - string(float64(ymax)) - })) -end - -# plot an array (window determined automatically) - -plot(x::Array, y::Array) = plot(x, y, "line") - -function plot(x::Array, y::Array, plottype::String) - # make sure we have arrays of numbers - x_safe = try convert(Array{Float64, 1}, x[:]) catch error("x coordinates must be convertable to float64") end - y_safe = try convert(Array{Float64, 1}, y[:]) catch error("y coordinates must be convertable to float64") end - - # make sure there are the same number of x and y coordinates - if length(x_safe) != length(y_safe) return error("size of x and y arrays must be equal") end - - # make sure there are enough data to plot - if length(x_safe) < 1 return error("at least two data points required for line plot") end - - # determine the window - xmin = __safe_min(x_safe) - xmax = __safe_max(x_safe) - ymin = __safe_min(y_safe) - ymax = __safe_max(y_safe) - if xmin == xmax - xmin -= 0.5 - xmax += 0.5 - end - if ymin == ymax - ymin -= 0.5 - ymax += 0.5 - end - - # determine if we want to preserve the aspect ratio - if abs((ymax-ymin)/(xmax-xmin)-1) < __PRESERVE_ASPECT_RATIO_THRESHOLD - # we do -- determine the center of the plot - cx = (xmax+xmin)/2.0 - cy = (ymax+ymin)/2.0 - - # determine how big the window is - w = max(xmax-xmin, ymax-ymin)/2.0 - wx = w+2.0*w*__HORIZONTAL_PADDING - wy = w+2.0*w*__VERTICAL_PADDING - - # add some horizontal padding to preserve the aspect ratio - plot(x_safe, y_safe, cx-wx*__PLOT_ASPECT_RATIO, cx+wx*__PLOT_ASPECT_RATIO, cy-wy, cy+wy, plottype) - else - # nope -- just add some padding - plot(x_safe, y_safe, - xmin-(xmax-xmin)*__HORIZONTAL_PADDING, - xmax+(xmax-xmin)*__HORIZONTAL_PADDING, - ymin-(ymax-ymin)*__VERTICAL_PADDING, - ymax+(ymax-ymin)*__VERTICAL_PADDING, - plottype) - end -end - -# plot an array (window determined automatically) - -plot(y::Array) = plot(y, "line") - -function plot(y::Array, plottype) - # make sure we have an array of numbers - y_safe = try convert(Array{Float64, 1}, y[:]) catch error("y coordinates must be convertable to float64") end - - # make sure there are enough data to plot - if length(y_safe) < 1 return error("at least two data points required for line plot") end - - # don't use +/-Inf or NaN when determining window - for i=1:length(y_safe) - if y_safe[i] == Inf || y_safe[i] == -Inf || isequal(y_safe[i], NaN) - y_safe[i] = 0.0 - end - end - - # determine the window - x_safe = [i-1 for i=1:length(y_safe)] - xmin = 0 - xmax = length(y)-1 - ymin = __safe_min(y_safe) - ymax = __safe_max(y_safe) - if ymin == ymax - ymin -= 0.5 - ymax += 0.5 - end - - # determine if we want to preserve the aspect ratio - if abs((ymax-ymin)/(xmax-xmin)-1) < __PRESERVE_ASPECT_RATIO_THRESHOLD - # we do -- determine the center of the plot - cx = (xmax+xmin)/2.0 - cy = (ymax+ymin)/2.0 - - # determine how big the window is - w = max(xmax-xmin, ymax-ymin)/2.0 - wx = w+2.0*w*__HORIZONTAL_PADDING - wy = w+2.0*w*__VERTICAL_PADDING - - # add some horizontal padding to preserve the aspect ratio - plot(x_safe, y_safe, cx-wx*__PLOT_ASPECT_RATIO, cx+wx*__PLOT_ASPECT_RATIO, cy-wy, cy+wy, plottype) - else - # nope -- just add some padding - plot(x_safe, y_safe, - xmin-(xmax-xmin)*__HORIZONTAL_PADDING, - xmax+(xmax-xmin)*__HORIZONTAL_PADDING, - ymin-(ymax-ymin)*__VERTICAL_PADDING, - ymax+(ymax-ymin)*__VERTICAL_PADDING, - plottype) - end -end - -# plot a function (vertical window determined automatically) - -plot(f::Function, xmin::Number, xmax::Number) = plot(f, xmin, xmax, "line") - -function plot(f::Function, xmin::Number, xmax::Number, plottype::String) - # make sure the window is okay - if xmin == Inf || xmin == -Inf || isequal(xmin, NaN) return error(strcat("invalid xmin: ", string(xmin))) end - if xmax == Inf || xmax == -Inf || isequal(xmax, NaN) return error(strcat("invalid xmax: ", string(xmax))) end - if xmin >= xmax return error("xmax must be greater than xmin") end - - # make the range - x = [xmin+float64(i-1)*(xmax-xmin)/(__PLOT_POINTS-1) for i=1:__PLOT_POINTS] - y = [try float64(f(i)) catch 0 end for i=x] - - # make the plot - plot(x, y, plottype) -end - -# plot a function (window determined manually) - -plot(f::Function, xmin::Number, xmax::Number, ymin::Number, ymax::Number) = - plot(f, xmin, xmax, ymin, ymax, "line") - -function plot(f::Function, xmin::Number, xmax::Number, ymin::Number, ymax::Number, plottype::String) - # make sure the window is okay - if xmin == Inf || xmin == -Inf || isequal(xmin, NaN) return error(strcat("invalid xmin: ", string(xmin))) end - if xmax == Inf || xmax == -Inf || isequal(xmax, NaN) return error(strcat("invalid xmax: ", string(xmax))) end - if ymin == Inf || ymin == -Inf || isequal(ymin, NaN) return error(strcat("invalid ymin: ", string(ymin))) end - if ymax == Inf || ymax == -Inf || isequal(ymax, NaN) return error(strcat("invalid ymax: ", string(ymax))) end - if xmin >= xmax return error("xmax must be greater than xmin") end - if ymin >= ymax return error("ymax must be greater than ymin") end - - # make the range - x = [xmin+float64(i-1)*(xmax-xmin)/(__PLOT_POINTS-1) for i=1:__PLOT_POINTS] - y = [try float64(f(i)) catch 0 end for i=x] - - # make the plot - plot(x, y, xmin, xmax, ymin, ymax, plottype) -end diff --git a/extras/julia_web_base.jl b/extras/julia_web_base.jl deleted file mode 100644 index bcd8db670dfb4..0000000000000 --- a/extras/julia_web_base.jl +++ /dev/null @@ -1,217 +0,0 @@ -########################################### -# protocol -########################################### - -###### the julia<-->server protocol ####### - -# the message type is sent as a byte -# the next byte indicates how many arguments there are -# each argument is four bytes indicating the size of the argument, then the data for that argument - -###### the server<-->browser protocol ##### - -# messages are sent as arrays of arrays (json) -# the outer array is an "array of messages" -# each message is itself an array: -# [message_type::number, arg0::string, arg1::string, ...] - -# import the message types -load("webrepl_msgtypes_h") - -########################################### -# set up the socket connection -########################################### - -# open a socket on any port -__ports = [int16(4444)] -__sockfd = ccall(:open_any_tcp_port, Int32, (Ptr{Int16},), __ports) -if __sockfd == -1 - # couldn't open the socket - println("could not open server socket on port 4444.") - exit() -end - -# print the socket number so the server knows what it is -println(__ports[1]) - -# wait for the server to connect to the socket -__connectfd = ccall(:accept, Int32, (Int32, Ptr{Void}, Ptr{Void}), __sockfd, C_NULL, C_NULL) - -# create an io object from the file descriptor -__io = fdio(__connectfd) - -########################################### -# protocol implementation -########################################### - -# a message -type __Message - msg_type::Uint8 - args::Array{Any, 1} -end - -# read a message -function __read_message() - msg_type = read(__io, Uint8) - args = {} - num_args = read(__io, Uint8) - for i=1:num_args - arg_length = read(__io, Uint32) - arg = ASCIIString(read(__io, Uint8, arg_length)) - push(args, arg) - end - return __Message(msg_type, args) -end - -# send a message -function __write_message(msg) - write(__io, uint8(msg.msg_type)) - write(__io, uint8(length(msg.args))) - for arg=msg.args - write(__io, uint32(length(arg))) - write(__io, arg) - end - flush(__io) -end - -# print a message (useful for debugging) -function __print_message(msg) - print(msg.msg_type) - print(": [ ") - for arg=msg.args - print("\"") - print(arg) - print("\" ") - end - println("]") -end - -########################################### -# standard web library -########################################### - -# load the special functions available to the web repl -load("julia_web") - -########################################### -# input event handler -########################################### - -# store the result of the previous input -ans = nothing - -# callback for that event handler -function __socket_callback(fd) - # read the message - __msg = __read_message() - - # MSG_INPUT_EVAL - if __msg.msg_type == __MSG_INPUT_EVAL && length(__msg.args) == 3 - # parse the arguments - __user_name = __msg.args[1] - __user_id = __msg.args[2] - __input = __msg.args[3] - - # split the input into lines - __lines = split(__input, '\n') - - # try to parse each line incrementally - __parsed_exprs = {} - __input_so_far = "" - __all_nothing = true - - for i=1:length(__lines) - # add the next line of input - __input_so_far = strcat(__input_so_far, __lines[i], "\n") - - # try to parse it - __expr = parse_input_line(__input_so_far) - - # if there was nothing to parse, just keep going - if __expr == nothing - continue - end - __all_nothing = false - __expr_multitoken = isa(__expr, Expr) - - # stop now if there was a parsing error - if __expr_multitoken && __expr.head == :error - # send everyone the input - __write_message(__Message(__MSG_OUTPUT_EVAL_INPUT, {__user_id, __user_name, __input})) - return __write_message(__Message(__MSG_OUTPUT_EVAL_ERROR, {__user_id, __expr.args[1]})) - end - - # if the expression was incomplete, just keep going - if __expr_multitoken && __expr.head == :continue - continue - end - - # add the parsed expression to the list - __input_so_far = "" - __parsed_exprs = [__parsed_exprs, {(__user_id, __expr)}] - end - - # if the input was empty, stop early - if __all_nothing - # send everyone the input - __write_message(__Message(__MSG_OUTPUT_EVAL_INPUT, {__user_id, __user_name, __input})) - return __write_message(__Message(__MSG_OUTPUT_EVAL_RESULT, {__user_id, ""})) - end - - # tell the browser if we didn't get a complete expression - if length(__parsed_exprs) == 0 - return __write_message(__Message(__MSG_OUTPUT_EVAL_INCOMPLETE, {__user_id})) - end - - # send everyone the input - __write_message(__Message(__MSG_OUTPUT_EVAL_INPUT, {__user_id, __user_name, __input})) - - put(__eval_channel, __parsed_exprs) - end -end - -# event handler for socket input -add_fd_handler(__connectfd, __socket_callback) - -web_show(user_id, ans) = - __Message(__MSG_OUTPUT_EVAL_RESULT, {user_id, sprint(repl_show, ans)}) - -function __eval_exprs(__parsed_exprs) - global ans - user_id = "" - - # try to evaluate the expressions - for i=1:length(__parsed_exprs) - # evaluate the expression and stop if any exceptions happen - user_id = __parsed_exprs[i][1] - try - ans = eval(__parsed_exprs[i][2]) - catch __error - return __write_message(__Message(__MSG_OUTPUT_EVAL_ERROR, {user_id, sprint(show, __error)})) - end - end - - # send the result of the last expression - if isa(ans,Nothing) - return __write_message(__Message(__MSG_OUTPUT_EVAL_RESULT, {user_id, ""})) - else - return __write_message(web_show(user_id, ans)) - end -end - -# print version info -println("Julia ", Base._jl_version_string) -println(Base._jl_commit_string, "\n") - -# work around bug displaying "\n " -#print(" ",replace(Base._jl_banner_plain, "\n", "\n ")) - -########################################### -# wait forever while asynchronous processing happens -########################################### - -__eval_channel = RemoteRef() - -while true - __eval_exprs(take(__eval_channel)) -end diff --git a/extras/libhdfs.jl b/extras/libhdfs.jl deleted file mode 100644 index 3ec3df3d51c72..0000000000000 --- a/extras/libhdfs.jl +++ /dev/null @@ -1,191 +0,0 @@ -libhdfs=dlopen("libhdfs") -_hdfsConnectAsUser= dlsym(libhdfs, :hdfsConnectAsUser) -_hdfsConnect= dlsym(libhdfs, :hdfsConnect) -_hdfsDisconnect= dlsym(libhdfs, :hdfsDisconnect) -_hdfsOpenFile= dlsym(libhdfs,:hdfsOpenFile) -_hdfsCloseFile= dlsym(libhdfs, :hdfsCloseFile) -_hdfsExists= dlsym(libhdfs, :hdfsExists) -_hdfsSeek= dlsym(libhdfs, :hdfsSeek) -_hdfsTell= dlsym(libhdfs, :hdfsTell) -_hdfsRead= dlsym(libhdfs, :hdfsRead) -_hdfsPread= dlsym(libhdfs, :hdfsPread) -_hdfsWrite= dlsym(libhdfs, :hdfsWrite) -_hdfsFlush= dlsym(libhdfs, :hdfsFlush) -_hdfsAvailable= dlsym(libhdfs, :hdfsAvailable) -_hdfsCopy= dlsym(libhdfs, :hdfsCopy) -_hdfsMove= dlsym(libhdfs, :hdfsMove) -_hdfsDelete= dlsym(libhdfs, :hdfsDelete) -_hdfsRename= dlsym(libhdfs, :hdfsRename) -_hdfsGetWorkingDirectory= dlsym(libhdfs, :hdfsGetWorkingDirectory) -_hdfsSetWorkingDirectory= dlsym(libhdfs, :hdfsSetWorkingDirectory) -_hdfsCreateDirectory= dlsym(libhdfs, :hdfsCreateDirectory) -_hdfsSetReplication= dlsym(libhdfs, :hdfsSetReplication) -_hdfsListDirectory=dlsym(libhdfs, :hdfsListDirectory) -_hdfsGetPathInfo=dlsym(libhdfs, :hdfsGetPathInfo) -_hdfsFreeFileInfo=dlsym(libhdfs, :hdfsFreeFileInfo) -_hdfsGetHosts=dlsym(libhdfs, :hdfsGetHosts) -_hdfsFreeHosts=dlsym(libhdfs, :hdfsFreeHosts) -_hdfsGetDefaultBlockSize= dlsym(libhdfs, :hdfsGetDefaultBlockSize) -_hdfsGetCapacity= dlsym(libhdfs, :hdfsGetCapacity) -_hdfsGetUsed= dlsym(libhdfs, :hdfsGetUsed) -_hdfsChown=dlsym(libhdfs, :hdfsChown) -_hdfsChmod=dlsym(libhdfs, :hdfsChmod) -_hdfsUtime=dlsym(libhdfs, :hdfsUtime) - -## used to enforce typing ## - -type HdfsFS - ptr::Ptr{Void} -end - -type HdfsFile - ptr::Ptr{Void} -end - -type HdfsFileInfo - ptr::Ptr{Void} -end - - -## libhdfs functions as ccalls ## -# strings can be passed to Ptr{Uint8} (char *) -# functions segfault if passed bad hdfsFS arguments -# multiple dispatch is used for convenience -# commented functions have not been tried out - -function hdfs_connect_as_user(host, port, user) - fs = ccall(_hdfsConnectAsUser, Ptr{Void}, (Ptr{Uint8},Int32,Ptr{Uint8}),host,port,user) - return HdfsFS(fs) -end -hdfs_connect_as_user(host, port)=hdfs_connect(host, port) -hdfs_connect_as_user()=hdfs_connect() - -function hdfs_connect(host,port) - fs = ccall(_hdfsConnect, Ptr{Void}, (Ptr{Uint8},Int32),host,port) - return HdfsFS(fs) -end -function hdfs_connect() - fs = ccall(_hdfsConnect, Ptr{Void}, (Ptr{Uint8},Int32),"default",0) - return HdfsFS(fs) -end - -hdfs_disconnect(fs::HdfsFS)=ccall(_hdfsDisconnect, Int32, (Ptr{Void},),fs.ptr) - -# file control flags need to be done manually -function hdfs_open_file(fs::HdfsFS,path,flags,bufferSize,replication,blocksize) - file = ccall(_hdfsOpenFile, Ptr{Void}, (Ptr{Void},Ptr{Uint8},Int32,Int32,Int16,Int32),fs.ptr,path,flags,bufferSize,replication,blocksize) - return HdfsFile(file) -end -function hdfs_open_file(fs::HdfsFS,path,flags) - file = ccall(_hdfsOpenFile, Ptr{Void}, (Ptr{Void},Ptr{Uint8},Int32,Int32,Int16,Int32),fs.ptr,path,flags,0,0,0) - return HdfsFile(file) -end - -hdfs_close_file(fs::HdfsFS, file::HdfsFile)=ccall(_hdfsCloseFile,Int32,(Ptr{Void},Ptr{Void}),fs.ptr,file.ptr) - -hdfs_exists(fs::HdfsFS, path)=ccall(_hdfsExists,Int32,(Ptr{Void},Ptr{Uint8}),fs.ptr,path) - -hdfs_seek(fs::HdfsFS, file::HdfsFile, desiredPos)=ccall(_hdfsSeek,Int32,(Ptr{Void},Ptr{Void},Int64),fs.ptr, file.ptr, desiredPos) - -hdfs_tell(fs::HdfsFS, file::HdfsFile)=ccall(_hdfsTell,Int64,(Ptr{Void},Ptr{Void}), fs.ptr, file.ptr) - -hdfs_read(fs::HdfsFS, file::HdfsFile, buffer, length)=ccall(_hdfsRead,Int32, (Ptr{Void},Ptr{Void},Ptr{Void},Int32), fs.ptr, file.ptr, buffer, length) -function hdfs_read(fs::HdfsFS, file::HdfsFile, length) - buffer = Array(Uint8,length) - r = ccall(_hdfsRead,Int32, (Ptr{Void},Ptr{Void},Ptr{Void},Int32), fs.ptr, file.ptr, buffer, length) - if r==-1 - error("-1") - else - print("read ",r," bytes\n") - return buffer - end -end - -hdfs_pread(fs::HdfsFS, file::HdfsFile, position, buffer, length)=ccall(_hdfsPread,Int32, (Ptr{Void},Ptr{Void},Int64,Ptr{Void},Int32), fs.ptr, file.ptr, position, buffer, length) -function hdfs_pread(fs::HdfsFS, file::HdfsFile, position, length) - buffer = Array(Uint8,length) - r = ccall(_hdfsPread,Int32, (Ptr{Void},Ptr{Void},Ptr{Void},Int32), fs.ptr, file.ptr, buffer, position, length) - if r==-1 - error("-1") - else - print("read ",r," bytes\n") - return buffer - end -end - -#can be passed an ASCIIString (length not necessary in that case) -hdfs_write(fs::HdfsFS, file::HdfsFile, buffer, length)=ccall(_hdfsWrite,Int32,(Ptr{Void},Ptr{Void},Ptr{Void},Int32),fs.ptr, file.ptr, buffer, length) -hdfs_write(fs::HdfsFS, file::HdfsFile, buffer::ASCIIString, length)=ccall(_hdfsWrite,Int32,(Ptr{Void},Ptr{Void},Ptr{Void},Int32),fs.ptr, file.ptr, convert(Ptr{Uint8},buffer), length) -hdfs_write(fs::HdfsFS, file::HdfsFile, buffer::ASCIIString)=ccall(_hdfsWrite,Int32,(Ptr{Void},Ptr{Void},Ptr{Void},Int32),fs.ptr, file.ptr, convert(Ptr{Uint8},buffer), length(buffer)) - -hdfs_flush(fs::HdfsFS, file::HdfsFile)=ccall(_hdfsFlush, Int32, (Ptr{Void},Ptr{Void}), fs.ptr, file.ptr) - -hdfs_available(fs::HdfsFS, file::HdfsFile)=ccall(_hdfsAvailable, Int32, (Ptr{Void},Ptr{Void}), fs.ptr, file.ptr) - -hdfs_copy(srcFS::HdfsFS, src, dstFS::HdfsFS, dst)=ccall(_hdfsCopy, Int32, (Ptr{Void},Ptr{Uint8},Ptr{Void},Ptr{Uint8}), srcFS.ptr, src, dstFS.ptr, dst) - -hdfs_move(srcFS::HdfsFS, src, dstFS::HdfsFS, dst)=ccall(_hdfsMove, Int32, (Ptr{Void},Ptr{Uint8},Ptr{Void},Ptr{Uint8}), srcFS.ptr, src, dstFS.ptr, dst) - -hdfs_delete(fs::HdfsFS, path)=ccall(_hdfsDelete, Int32, (Ptr{Void},Ptr{Uint8}), fs.ptr, path) - -hdfs_rename(fs::HdfsFS, oldPath, newPath)=ccall(_hdfsRename, Int32, (Ptr{Void}, Ptr{Uint8},Ptr{Uint8}), fs.ptr, oldPath, newPath) - -hdfs_get_working_directory(fs::HdfsFS, buffer, bufferSize)=ccall(_hdfsGetWorkingDirectory, Ptr{Uint8}, (Ptr{Void}, Ptr{Uint8}, Int32), fs.ptr, buffer, bufferSize) -function hdfs_get_working_directory(fs::HdfsFS,bufferSize) - buffer = Array(Uint8, bufferSize) - path = ccall(_hdfsGetWorkingDirectory, Ptr{Uint8}, (Ptr{Void}, Ptr{Uint8}, Int32), fs.ptr, buffer, bufferSize) - return bytestring(path) -end -function hdfs_get_working_directory(fs::HdfsFS) - buffer = Array(Uint8, 128) - path = ccall(_hdfsGetWorkingDirectory, Ptr{Uint8}, (Ptr{Void}, Ptr{Uint8}, Int32), fs.ptr, buffer, 128) - return bytestring(path) -end - -hdfs_set_working_directory(fs::HdfsFS, path)=ccall(_hdfsSetWorkingDirectory, Int32, (Ptr{Void}, Ptr{Uint8}), fs.ptr, path) - -hdfs_create_directory(fs::HdfsFS, path)=ccall(_hdfsCreateDirectory, Int32, (Ptr{Void}, Ptr{Uint8}), fs.ptr, path) - -hdfs_set_replication(fs::HdfsFS, path, replication)=ccall(_hdfsSetReplication, Int32, (Ptr{Void}, Ptr{Uint8}, Int16), fs.ptr, path, replication) - -#function hdfs_list_directory(fs::HdfsFS, path, numEntries) -# fileInfo = ccall(_hdfsListDirectory, Ptr{Void}, (Ptr{Void}, Ptr{Uint8}, Int32), fs.ptr, path, numEntries) -# return HdfsFileInfo(fileInfo) -#end - -#function hdfs_get_path_info(fs::HdfsFS, path) -# fileInfo = ccall(_hdfsGetPathInfo, Ptr{Void}, (Ptr{Void}, Ptr{Uint8}), fs.ptr, path) -# return HdfsFileInfo(fileInfo) -#end - -#hdfs_free_file_info(fileInfo::HdfsFileInfo, numEntries)=ccall(_hdfsFreeFileInfo, Void, (Ptr{Void}, Int32), fileInfo.ptr, numEntries) - -#hdfs_get_hosts(fs::HdfsFS, path, start, length)=ccall(_hdfsGetHosts, Ptr{Ptr{Ptr{Uint8}}}, (Ptr{Void}, Ptr{Uint8}, Int64, Int64), fs.ptr, path, start, length) - -#hdfs_free_hosts(blockHosts)=ccall(_hdfsFreeHosts, Void, (Ptr{Ptr{Ptr{Uint8}}},), blockHosts) - -hdfs_get_default_block_size(fs::HdfsFS)=ccall(_hdfsGetDefaultBlockSize, Int64, (Ptr{Void},),fs.ptr) - -hdfs_get_capacity(fs::HdfsFS)=ccall(_hdfsGetCapacity, Int64, (Ptr{Void},),fs.ptr) - -hdfs_get_used(fs::HdfsFS)=ccall(_hdfsGetUsed, Int64, (Ptr{Void},),fs.ptr) - -#hdfs_chown(fs::HdfsFS, path, owner, group)=ccall(_hdfsChown, Int32, (Ptr{Void}, Ptr{Uint8}, Ptr{Uint8}, Ptr{Uint8}), fs.ptr, path, owner, group) - -#hdfs_chmod(fs::HdfsFS, path, mode)=ccall(_hdfsChmod, Int32, (Ptr{Void}, Ptr{Uint8}, Int16), fs.ptr, path, mode) - -#last two arguments are to be time_t (system dependent) -#hdfs_utime(fs::HdfsFS, path, mtime, atime)=ccall(_hdfsUtime, Int32, (Ptr{Void}, Ptr{Uint8}, int, int), fs.ptr, path, mtime, atime) - - - -## file control flags ## -# these are system-dependent -#Int32 O_WRONLY=1 -#Int32 O_RDONLY=0 -#Int32 O_RDWR=2 -#Int32 O_CREAT=64 -#Int32 O_EXCL=128 -#Int32 O_APPEND=1024 -#Int32 O_TRUNC=512 -#Int32 O_NONBLOCK=2048 diff --git a/extras/linprog.jl b/extras/linprog.jl deleted file mode 100644 index 1f7a137747c40..0000000000000 --- a/extras/linprog.jl +++ /dev/null @@ -1,494 +0,0 @@ -## -## Linear Programming and Mixed Integer Programming interfaces -## for optimization and constraint satisfaction problems -## - -require("glpk") - -module LinProgGLPK - -import GLPK - -export - linprog, - linprog_interior, - linprog_simplex, - linprog_exact, - mixintprog - -typealias VecOrNothing GLPK.VecOrNothing - -# General notes: the interface is provided as a collection of -# high-level functions which use the glpk library. -# Most functions have almost same interface -# as matlab's linprog, e.g.: -# -# (z, x, flag) = linprog(f, A, b, Aeq, beq, lb, ub, params) -# -# There's a function for each solving method: -# linprog_interior -# linprog_simplex -# linprog_exact -# mixintprog -# -# The function linprog is an alias to linprog_interior -# -# These functions all seek to solve the problem -# -# z = min_{x} (f' * x) -# -# where the vector x is subject to these constraints: -# -# A * x <= b -# Aeq * x == b -# lb <= x <= ub -# -# The return flag is 0 in case of success, and follows -# the glpk library convention otherwise. -# In case of failure, z and x are set to nothing, otherwise -# they will hold the solution found -# -# The parameters Aeq, beq, lb, ub and params are optional. -# This mean they can be either passed as the constant 'nothing' -# or as an empty vector [] or not provided at all. -# -# Some methods have slightly different function calls, see -# individual notes for additional information - -typealias SparseOrFullMat{T} Union(Matrix{T}, SparseMatrixCSC{T}) -typealias MatOrNothing Union(Matrix, SparseMatrixCSC, Vector{None}, Nothing) - -# Linear Programming, Interior point method (default) -#{{{ - -function linprog_interior{T<:Real,P<:Union(GLPK.InteriorParam,Nothing)}(f::Vector{T}, A::SparseOrFullMat{T}, b::Vector{T}, - Aeq::SparseOrFullMat{T}, beq::Vector{T}, lb::Vector{T}, ub::Vector{T}, params::P) - - lp, n = _jl_linprog__setup_prob(f, A, b, Aeq, beq, lb, ub, params) - - ret = GLPK.interior(lp, params) - #println("ret=$ret") - - if ret == 0 - z = GLPK.ipt_obj_val(lp) - x = zeros(Float64, n) - for c = 1 : n - x[c] = GLPK.ipt_col_prim(lp, c) - end - return (z, x, ret) - else - # throw exception here ? - return (nothing, nothing, ret) - end -end -function linprog_interior{T<:Real,P<:Union(GLPK.InteriorParam,Nothing)}(f::Vector{T}, A::MatOrNothing, b::VecOrNothing, - Aeq::MatOrNothing, beq::VecOrNothing, lb::VecOrNothing, ub::VecOrNothing, params::P) - - cA = _jl_linprog__convert_matornothing(T, A) - cb = _jl_linprog__convert_vecornothing(T, b) - cAeq = _jl_linprog__convert_matornothing(T, Aeq) - cbeq = _jl_linprog__convert_vecornothing(T, beq) - clb = _jl_linprog__convert_vecornothing(T, lb) - cub = _jl_linprog__convert_vecornothing(T, ub) - return linprog_interior(f, cA, cb, cAeq, cbeq, clb, cub, params) - -end - -linprog_interior{T<:Real}(f::Vector{T}, A::MatOrNothing, b::VecOrNothing) = - linprog_interior(f, A, b, nothing, nothing, nothing, nothing, nothing) - -linprog_interior{T<:Real}(f::Vector{T}, A::MatOrNothing, b::VecOrNothing, - Aeq::MatOrNothing, beq::VecOrNothing) = - linprog_interior(f, A, b, Aeq, beq, nothing, nothing, nothing) - -linprog_interior{T<:Real}(f::Vector{T}, A::MatOrNothing, b::VecOrNothing, - Aeq::MatOrNothing, beq::VecOrNothing, lb::VecOrNothing, - ub::VecOrNothing) = - linprog_interior(f, A, b, Aeq, beq, lb, ub, nothing) - -linprog = linprog_interior -#}}} - -# Linear Programming, Simplex Method -#{{{ -function linprog_simplex{T<:Real,P<:Union(GLPK.SimplexParam,Nothing)}(f::Vector{T}, A::SparseOrFullMat{T}, b::Vector{T}, - Aeq::SparseOrFullMat{T}, beq::Vector{T}, lb::Vector{T}, ub::Vector{T}, params::P) - - lp, n = _jl_linprog__setup_prob(f, A, b, Aeq, beq, lb, ub, params) - - ret = GLPK.simplex(lp, params) - #println("ret=$ret") - - if ret == 0 - z = GLPK.get_obj_val(lp) - x = zeros(Float64, n) - for c = 1 : n - x[c] = GLPK.get_col_prim(lp, c) - end - return (z, x, ret) - else - # throw exception here ? - return (nothing, nothing, ret) - end -end -function linprog_simplex{T<:Real,P<:Union(GLPK.SimplexParam,Nothing)}(f::Vector{T}, A::MatOrNothing, b::VecOrNothing, - Aeq::MatOrNothing, beq::VecOrNothing, lb::VecOrNothing, ub::VecOrNothing, params::P) - - cA = _jl_linprog__convert_matornothing(T, A) - cb = _jl_linprog__convert_vecornothing(T, b) - cAeq = _jl_linprog__convert_matornothing(T, Aeq) - cbeq = _jl_linprog__convert_vecornothing(T, beq) - clb = _jl_linprog__convert_vecornothing(T, lb) - cub = _jl_linprog__convert_vecornothing(T, ub) - return linprog_simplex(f, cA, cb, cAeq, cbeq, clb, cub, params) - -end - -linprog_simplex{T<:Real}(f::Vector{T}, A::MatOrNothing, b::VecOrNothing) = - linprog_simplex(f, A, b, nothing, nothing, nothing, nothing, nothing) - -linprog_simplex{T<:Real}(f::Vector{T}, A::MatOrNothing, b::VecOrNothing, - Aeq::MatOrNothing, beq::VecOrNothing) = - linprog_simplex(f, A, b, Aeq, beq, nothing, nothing, nothing) - -linprog_simplex{T<:Real}(f::Vector{T}, A::MatOrNothing, b::VecOrNothing, - Aeq::MatOrNothing, beq::VecOrNothing, lb::VecOrNothing, - ub::VecOrNothing) = - linprog_simplex(f, A, b, Aeq, beq, lb, ub, nothing) -#}}} - -# Linear Programming, Simplex-exact Method -#{{{ - -# Notes: -# * uses GLPK.simplex as a preliminary step -# * the exact step only accepts the "it_lim" and "tm_lim" options, -# which means no message suppression is possible - -function linprog_exact{T<:Real,P<:Union(GLPK.SimplexParam,Nothing)}(f::Vector{T}, A::SparseOrFullMat{T}, b::Vector{T}, - Aeq::SparseOrFullMat{T}, beq::Vector{T}, lb::Vector{T}, ub::Vector{T}, params::P) - - lp, n = _jl_linprog__setup_prob(f, A, b, Aeq, beq, lb, ub, params) - - ret = GLPK.simplex(lp, params) - if ret != 0 - # throw exception here ? - return (nothing, nothing, ret) - end - - ret = GLPK.exact(lp, params) - if ret == 0 - z = GLPK.get_obj_val(lp) - x = zeros(Float64, n) - for c = 1 : n - x[c] = GLPK.get_col_prim(lp, c) - end - return (z, x, ret) - else - # throw exception here ? - return (nothing, nothing, ret) - end -end -function linprog_exact{T<:Real,P<:Union(GLPK.SimplexParam,Nothing)}(f::Vector{T}, A::MatOrNothing, b::VecOrNothing, - Aeq::MatOrNothing, beq::VecOrNothing, lb::VecOrNothing, ub::VecOrNothing, params::P) - - cA = _jl_linprog__convert_matornothing(T, A) - cb = _jl_linprog__convert_vecornothing(T, b) - cAeq = _jl_linprog__convert_matornothing(T, Aeq) - cbeq = _jl_linprog__convert_vecornothing(T, beq) - clb = _jl_linprog__convert_vecornothing(T, lb) - cub = _jl_linprog__convert_vecornothing(T, ub) - return linprog_exact(f, cA, cb, cAeq, cbeq, clb, cub, params) - -end - -linprog_exact{T<:Real}(f::Vector{T}, A::MatOrNothing, b::VecOrNothing) = - linprog_exact(f, A, b, nothing, nothing, nothing, nothing, nothing) - -linprog_exact{T<:Real}(f::Vector{T}, A::MatOrNothing, b::VecOrNothing, - Aeq::MatOrNothing, beq::VecOrNothing) = - linprog_exact(f, A, b, Aeq, beq, nothing, nothing, nothing) - -linprog_exact{T<:Real}(f::Vector{T}, A::MatOrNothing, b::VecOrNothing, - Aeq::MatOrNothing, beq::VecOrNothing, lb::VecOrNothing, - ub::VecOrNothing) = - linprog_exact(f, A, b, Aeq, beq, lb, ub, nothing) -#}}} - -# Mixed Integer Programming -#{{{ - -# Notes: -# * same syntax as linprog algorithms, with an additional col_kind vector and -# an additional set of parameters for the presolve step; and an additional -# return flag for the presolve step: -# -# (z, x, flag, ps_flag) = mixintprog(f, A, b, Aeq, beq, lb, ub, col_kind, param, ps_param) -# -# * if the col_kind vector is not provided, all variables default to integer -# * if the "presolve" options is set to GLPK.OFF, then it uses linear programming -# for presolving, via the simplex point method with parameters ps_param (if ps_param is nothing -# or not given, uses the defaults) - -function mixintprog{T<:Real,Ti<:Integer,P<:Union(GLPK.IntoptParam,Nothing),Px<:Union(GLPK.SimplexParam,Nothing)}( - f::Vector{T}, A::SparseOrFullMat{T}, b::Vector{T}, Aeq::SparseOrFullMat{T}, beq::Vector{T}, - lb::Vector{T}, ub::Vector{T}, col_kind::Vector{Ti}, params::P, params_presolve::Px) - - lp, n = _jl_linprog__setup_prob(f, A, b, Aeq, beq, lb, ub, params) - _jl_mixintprog_set_col_kind(lp, n, col_kind) - - if params == nothing || pointer(params) == C_NULL || params["presolve"] != GLPK.ON - ret_ps = GLPK.simplex(lp, params_presolve) - if ret_ps != 0 - # throw exception here ? - # XXX GLPK.ESTOP ?? - return (nothing, nothing, GLPK.ESTOP, ret_ps) - end - else - ret_ps = 0 - end - - ret = GLPK.intopt(lp, params) - if ret == 0 - z = GLPK.mip_obj_val(lp) - x = zeros(Float64, n) - for c = 1 : n - x[c] = GLPK.mip_col_val(lp, c) - end - return (z, x, ret, ret_ps) - else - # throw exception here ? - return (nothing, nothing, ret, ret_ps) - end -end -function mixintprog{T<:Real,P<:Union(GLPK.IntoptParam,Nothing),Px<:Union(GLPK.SimplexParam,Nothing)}( - f::Vector{T}, A::MatOrNothing, b::VecOrNothing, Aeq::MatOrNothing, beq::VecOrNothing, - lb::VecOrNothing, ub::VecOrNothing, col_kind::VecOrNothing, params::P, params_presolve::Px) - - cA = _jl_linprog__convert_matornothing(T, A) - cb = _jl_linprog__convert_vecornothing(T, b) - cAeq = _jl_linprog__convert_matornothing(T, Aeq) - cbeq = _jl_linprog__convert_vecornothing(T, beq) - clb = _jl_linprog__convert_vecornothing(T, lb) - cub = _jl_linprog__convert_vecornothing(T, ub) - ccol_kind = _jl_linprog__convert_vecornothing(Int32, col_kind) - return mixintprog(f, cA, cb, cAeq, cbeq, clb, cub, ccol_kind, params, params_presolve) - -end - -mixintprog{T<:Real}(f::Vector{T}, A::MatOrNothing, b::VecOrNothing) = - mixintprog(f, A, b, nothing, nothing, nothing, nothing, nothing, nothing, nothing) - -mixintprog{T<:Real}(f::Vector{T}, A::MatOrNothing, b::VecOrNothing, - Aeq::MatOrNothing, beq::VecOrNothing) = - mixintprog(f, A, b, Aeq, beq, nothing, nothing, nothing, nothing, nothing) - -mixintprog{T<:Real}(f::Vector{T}, A::MatOrNothing, b::VecOrNothing, - Aeq::MatOrNothing, beq::VecOrNothing, lb::VecOrNothing, - ub::VecOrNothing) = - mixintprog(f, A, b, Aeq, beq, lb, ub, nothing, nothing, nothing) - -mixintprog{T<:Real}(f::Vector{T}, A::MatOrNothing, b::VecOrNothing, - Aeq::MatOrNothing, beq::VecOrNothing, lb::VecOrNothing, - ub::VecOrNothing, col_kind::VecOrNothing) = - mixintprog(f, A, b, Aeq, beq, lb, ub, col_kind, nothing, nothing) - -mixintprog{T<:Real,P<:Union(GLPK.IntoptParam,Nothing)}(f::Vector{T}, A::MatOrNothing, b::VecOrNothing, - Aeq::MatOrNothing, beq::VecOrNothing, lb::VecOrNothing, - ub::VecOrNothing, col_kind::VecOrNothing, params::P) = - mixintprog(f, A, b, Aeq, beq, lb, ub, col_kind, params, nothing) -#}}} - -## Common auxiliary functions -#{{{ -function _jl_linprog__convert_vecornothing{T}(::Type{T}, a::VecOrNothing) - if isequal(a, nothing) || isa(a, Array{None}) - return T[] - elseif T <: Integer - if !(eltype(a) <: Integer) - error("integer-valued array required, or [] or nothing") - end - elseif T <: Real - if !(eltype(a) <: Real) - error("real-valued array required, or [] or nothing") - end - end - return convert(Array{T}, a) -end -function _jl_linprog__convert_matornothing{T}(::Type{T}, a::MatOrNothing) - if isequal(a, nothing) || isa(a, Array{None}) - return Array(T, 0, 0) - elseif T <: Integer - if !(eltype(a) <: Integer) - error("integer-valued array required, or [] or nothing") - end - elseif T <: Real - if !(eltype(a) <: Real) - error("real-valued array required, or [] or nothing") - end - end - if issparse(a) - return convert(SparseMatrixCSC{T}, a) - else - return convert(Array{T}, a) - end -end - -function _jl_linprog__setup_prob{T<:Real, P<:Union(GLPK.Param, Nothing)}(f::Vector{T}, A::SparseOrFullMat{T}, b::Vector{T}, - Aeq::SparseOrFullMat{T}, beq::Vector{T}, lb::Vector{T}, ub::Vector{T}, params::P) - - lp = GLPK.Prob() - GLPK.set_obj_dir(lp, GLPK.MIN) - - n = size(f, 1) - - m = _jl_linprog__check_A_b(A, b, n) - meq = _jl_linprog__check_A_b(Aeq, beq, n) - - has_lb, has_ub = _jl_linprog__check_lb_ub(lb, ub, n) - - #println("n=$n m=$m meq=$meq has_lb=$has_lb ub=$has_ub") - - if m > 0 - GLPK.add_rows(lp, m) - for r = 1 : m - #println(" r=$r b=$(b[r])") - GLPK.set_row_bnds(lp, r, GLPK.UP, 0.0, b[r]) - end - end - if meq > 0 - GLPK.add_rows(lp, meq) - for r = 1 : meq - r0 = r + m - #println(" r=$r r0=$r0 beq=$(beq[r])") - GLPK.set_row_bnds(lp, r0, GLPK.FX, beq[r], beq[r]) - end - end - - GLPK.add_cols(lp, n) - - for c = 1 : n - GLPK.set_obj_coef(lp, c, f[c]) - #println(" c=$c f=$(f[c])") - end - - if has_lb && has_ub - for c = 1 : n - #println(" c=$c lb=$(lb[c]) ub=$(ub[c])") - bounds_type = (lb[c] != ub[c] ? GLPK.DB : GLPK.FX) - GLPK.set_col_bnds(lp, c, bounds_type, lb[c], ub[c]) - end - elseif has_lb - for c = 1 : n - #println(" c=$c lb=$(lb[c])") - GLPK.set_col_bnds(lp, c, GLPK.LO, lb[c], 0.0) - end - elseif has_ub - for c = 1 : n - #println(" c=$c ub=$(ub[c])") - GLPK.set_col_bnds(lp, c, GLPK.UP, 0.0, ub[c]) - end - end - - if (m > 0 && issparse(A)) && (meq > 0 && issparse(Aeq)) - (ia, ja, ar) = findn_nzs([A; Aeq]) - elseif (m > 0 && issparse(A)) && (meq == 0) - (ia, ja, ar) = findn_nzs(A) - elseif (m == 0) && (meq > 0 && issparse(Aeq)) - (ia, ja, ar) = findn_nzs(Aeq) - else - (ia, ja, ar) = _jl_linprog__dense_matrices_to_glpk_format(m, meq, n, A, Aeq) - end - #println("ia=$ia") - #println("ja=$ja") - #println("ar=$ar") - - GLPK.load_matrix(lp, ia, ja, ar) - return (lp, n) -end - -function _jl_linprog__check_A_b{T}(A::SparseOrFullMat{T}, b::Vector{T}, n::Int) - m = 0 - if !isempty(A) - if size(A, 2) != n - error("invlid A size: $(size(A))") - end - m = size(A, 1) - if isempty(b) - error("b is empty but a is not") - end - if size(b, 1) != m - error("invalid b size: $(size(b))") - end - else - if !isempty(b) - error("A is empty but b is not") - end - end - return m -end - -function _jl_linprog__check_lb_ub{T}(lb::Vector{T}, ub::Vector{T}, n::Int) - has_lb = false - has_ub = false - if !isempty(lb) - if size(lb, 1) != n - error("invlid lb size: $(size(lb))") - end - has_lb = true - end - if !isempty(ub) - if size(ub, 1) != n - error("invalid ub size: $(size(ub))") - end - has_ub = true - end - return (has_lb, has_ub) -end - -function _jl_linprog__dense_matrices_to_glpk_format(m, meq, n, A, Aeq) - l = (m + meq) * n - - ia = zeros(Int32, l) - ja = zeros(Int32, l) - ar = zeros(Float64, l) - - k = 0 - for r = 1 : m - for c = 1 : n - k += 1 - ia[k] = r - ja[k] = c - ar[k] = A[r, c] - end - end - for r = 1 : meq - for c = 1 : n - r0 = r + m - k += 1 - ia[k] = r0 - ja[k] = c - ar[k] = Aeq[r, c] - end - end - return (ia, ja, ar) -end - -function _jl_mixintprog_set_col_kind{Ti<:Integer}(lp::GLPK.Prob, n::Int, col_kind::Vector{Ti}) - if isempty(col_kind) - for i = 1 : n - GLPK.set_col_kind(lp, i, GLPK.IV) - end - return - end - if length(col_kind) != n - error("wrong col_kind vector size") - end - for i = 1 : n - GLPK.set_col_kind(lp, i, col_kind[i]) - end -end - -#}}} - -end # module diff --git a/extras/lru.jl b/extras/lru.jl index ddb53aab940f9..c945daccb4017 100644 --- a/extras/lru.jl +++ b/extras/lru.jl @@ -16,10 +16,10 @@ # collections, the difference in performance is small, and this implmentation # is simpler and easier to understand. -import Base.isempty, Base.numel, Base.length, Base.sizeof +import Base.isempty, Base.length, Base.sizeof import Base.start, Base.next, Base.done import Base.has, Base.get -import Base.assign, Base.ref, Base.del, Base.del_all +import Base.setindex!, Base.getindex, Base.delete!, Base.empty! import Base.show abstract LRU{K,V} <: Associative{K,V} @@ -54,7 +54,6 @@ BoundedLRU() = BoundedLRU{Any, Any}() ## collections ## isempty(lru::LRU) = isempty(lru.q) -numel(lru::LRU) = numel(lru.q) length(lru::LRU) = length(lru.q) has(lru::LRU, key) = has(lru.ht, key) @@ -65,14 +64,14 @@ has(lru::LRU, key) = has(lru.ht, key) get(lru::LRU, key, default) = has(lru, key) ? lru[key] : default -function del_all(lru::LRU) - del_all(lru.ht) - del_all(lru.q) +function empty!(lru::LRU) + empty!(lru.ht) + empty!(lru.q) end -show(io, lru::UnboundedLRU) = print("UnboundedLRU()") -show(io, lru::BoundedLRU) = print("BoundedLRU($(lru.maxsize))") +show(io::IO, lru::UnboundedLRU) = print(io,"UnboundedLRU()") +show(io::IO, lru::BoundedLRU) = print(io,"BoundedLRU($(lru.maxsize))") ## indexable ## @@ -86,42 +85,42 @@ function locate(q, x) error("Item not found.") end -function ref(lru::LRU, key) +function getindex(lru::LRU, key) item = lru.ht[key] idx = locate(lru.q, item) - del(lru.q, idx) - enqueue(lru.q, item) + delete!(lru.q, idx) + unshift!(lru.q, item) item.v end -function assign(lru::LRU, v, key) +function setindex!(lru::LRU, v, key) if has(lru, key) item = lru.ht[key] idx = locate(lru.q, item) item.v = v - del(lru.q, idx) + delete!(lru.q, idx) else item = CacheItem(key, v) lru.ht[key] = item end - enqueue(lru.q, item) + unshift!(lru.q, item) end # Eviction -function assign{V,K}(lru::BoundedLRU, v::V, key::K) - invoke(assign, (LRU, V, K), lru, v, key) +function setindex!{V,K}(lru::BoundedLRU, v::V, key::K) + invoke(setindex!, (LRU, V, K), lru, v, key) nrm = length(lru) - lru.maxsize for i in 1:nrm - rm = pop(lru.q) - del(lru.ht, rm.k) + rm = pop!(lru.q) + delete!(lru.ht, rm.k) end end ## associative ## -function del(lru::LRU, key) +function delete!(lru::LRU, key) item = lru.ht[key] idx = locate(lru.q, item) - del(lru.ht, key) - del(lru.q, idx) + delete!(lru.ht, key) + delete!(lru.q, idx) end diff --git a/examples/lru_test.jl b/extras/lru_test.jl similarity index 94% rename from examples/lru_test.jl rename to extras/lru_test.jl index b414352d81495..757bee522de2a 100644 --- a/examples/lru_test.jl +++ b/extras/lru_test.jl @@ -1,4 +1,4 @@ -load("lru") +require("lru") const TestLRU = UnboundedLRU{ASCIIString, ASCIIString}() const TestBLRUs = BoundedLRU{ASCIIString, ASCIIString}(100) @@ -22,7 +22,7 @@ for lru in ( TestBLRUxl, ) for n in nmax - del_all(lru) + empty!(lru) @printf(" %s, %d items\n", lru, n) print(" Simple eviction: ") for i in 1:n @@ -38,7 +38,7 @@ for lru in ( print(" Lookup, random access: ") for i in 1:n - str = get_str(randi(n)) + str = get_str(rand(1:n)) if has(lru, str) # the bounded LRUs can have cache misses blah = lru[str] @assert lru.q[1].v == blah @@ -46,5 +46,5 @@ for lru in ( end println("pass") end - del_all(lru) + empty!(lru) end diff --git a/extras/nearequal.jl b/extras/nearequal.jl index eb0ca83760dcf..d21d16cb8c408 100644 --- a/extras/nearequal.jl +++ b/extras/nearequal.jl @@ -40,7 +40,7 @@ for fun in (:isapprox, :isapproxn) error("Arrays must have the same sizes (first is $(size(X)), second is $(size(Y))).") end Z = similar(X, Bool) - for i in 1:numel(X) + for i in 1:length(X) Z[i] = ($fun)(X[i], Y[i]) end Z diff --git a/extras/ode.jl b/extras/ode.jl deleted file mode 100644 index 21ebec57a6a15..0000000000000 --- a/extras/ode.jl +++ /dev/null @@ -1,432 +0,0 @@ -#ODE23 Solve non-stiff differential equations. -# -# ODE23(F,TSPAN,Y0) with TSPAN = [T0 TFINAL] integrates the system -# of differential equations dy/dt = f(t,y) from t = T0 to t = TFINAL. -# The initial condition is y(T0) = Y0. -# -# The first argument, F, is a function handle or an anonymous function -# that defines f(t,y). This function must have two input arguments, -# t and y, and must return a column vector of the derivatives, dy/dt. -# -# With two output arguments, [T,Y] = ODE23(...) returns a column -# vector T and an array Y where Y(:,k) is the solution at T(k). -# -# More than four input arguments, ODE23(F,TSPAN,Y0,RTOL,P1,P2,...), -# are passed on to F, F(T,Y,P1,P2,...). -# -# ODE23 uses the Runge-Kutta (2,3) method of Bogacki and Shampine (BS23). -# -# Example -# tspan = [0, 2*pi] -# y_0 = [1, 0] -# F = (t, y) -> [0 1; -1 0]*y -# ode23(F, tspan, y_0) -# -# See also ODE23. - -# Initialize variables. -# Adapted from Cleve Moler's textbook -# http://www.mathworks.com/moler/ncm/ode23tx.m - -load("poly") - -function ode23(F::Function, tspan::AbstractVector, y_0::AbstractVector) - - rtol = 1.e-5 - atol = 1.e-8 - - t0 = tspan[1] - tfinal = tspan[end] - tdir = sign(tfinal - t0) - threshold = atol / rtol - hmax = abs(0.1*(tfinal-t0)) - t = t0 - y = y_0[:] - - tout = t - yout = y.' - - tlen = length(t) - - # Compute initial step size. - - s1 = F(t, y) - r = norm(s1./max(abs(y), threshold), Inf) + realmin() # TODO: fix type bug in max() - h = tdir*0.8*rtol^(1/3)/r - - # The main loop. - - while t != tfinal - - hmin = 16*eps()*abs(t) - if abs(h) > hmax; h = tdir*hmax; end - if abs(h) < hmin; h = tdir*hmin; end - - # Stretch the step if t is close to tfinal. - - if 1.1*abs(h) >= abs(tfinal - t) - h = tfinal - t; - end - - # Attempt a step. - - s2 = F(t+h/2, y+h/2*s1) - s3 = F(t+3*h/4, y+3*h/4*s2) - tnew = t + h - ynew = y + h*(2*s1 + 3*s2 + 4*s3)/9 - s4 = F(tnew, ynew) - - # Estimate the error. - - e = h*(-5*s1 + 6*s2 + 8*s3 - 9*s4)/72 - err = norm(e./max(max(abs(y), abs(ynew)), threshold), Inf) + realmin() - - # Accept the solution if the estimated error is less than the tolerance. - - if err <= rtol - t = tnew - y = ynew - tout = [tout; t] - yout = [yout; y.'] - s1 = s4 # Reuse final function value to start new step - end - - # Compute a new step size. - - h = h*min(5, 0.8*(rtol/err)^(1/3)) - - # Exit early if step size is too small. - - if abs(h) <= hmin - println("Step size ", h, " too small at t = ", t) - t = tfinal - end - - end # while (t != tfinal) - - return (tout, yout) - -end # ode23 - - -# ode45 adapted from http://users.powernet.co.uk/kienzle/octave/matcompat/scripts/ode_v1.11/ode45.m - -# ode45 (v1.11) integrates a system of ordinary differential equations using -# 4th & 5th order embedded formulas from Dormand & Prince or Fehlberg. -# -# The Fehlberg 4(5) pair is established and works well, however, the -# Dormand-Prince 4(5) pair minimizes the local truncation error in the -# 5th-order estimate which is what is used to step forward (local extrapolation.) -# Generally it produces more accurate results and costs roughly the same -# computationally. The Dormand-Prince pair is the default. -# -# This is a 4th-order accurate integrator therefore the local error normally -# expected would be O(h^5). However, because this particular implementation -# uses the 5th-order estimate for xout (i.e. local extrapolation) moving -# forward with the 5th-order estimate should yield errors on the order of O(h^6). -# -# The order of the RK method is the order of the local *truncation* error, d. -# The local truncation error is defined as the principle error term in the -# portion of the Taylor series expansion that gets dropped. This portion of -# the Taylor series exapansion is within the group of terms that gets multipled -# by h in the solution definition of the general RK method. Therefore, the -# order-p solution created by the RK method will be roughly accurate to -# within O(h^(p+1)). The difference between two different-order solutions is -# the definition of the "local error," l. This makes the local error, l, as -# large as the error in the lower order method, which is the truncation -# error, d, times h, resulting in O(h^(p+1)). -# Summary: For an RK method of order-p, -# - the local truncation error is O(h^p) -# - the local error (used for stepsize adjustment) is O(h^(p+1)) -# -# This requires 6 function evaluations per integration step. -# -# The error estimate formula and slopes are from -# Numerical Methods for Engineers, 2nd Ed., Chappra & Cannle, McGraw-Hill, 1985 -# -# Usage: -# (tout, xout) = ode45(F, tspan, x0) -# -# INPUT: -# F - User-defined function -# Call: xprime = F(t,x) -# t - Time (scalar). -# x - Solution column-vector. -# xprime - Returned derivative COLUMN-vector; xprime(i) = dx(i)/dt. -# tspan - [ tstart, tfinal ] -# x0 - Initial value COLUMN-vector. -# -# OUTPUT: -# tout - Returned integration time points (column-vector). -# xout - Returned solution, one solution column-vector per tout-value. -# -# Original Octave implementation: -# Marc Compere -# CompereM@asme.org -# created : 06 October 1999 -# modified: 17 January 2001 - -function oderkf{T}(F::Function, tspan::AbstractVector, x0::AbstractVector{T}, a, b4, b5) - tol = 1.0e-5 - - # see p.91 in the Ascher & Petzold reference for more infomation. - pow = 1/6; - - c = sum(a, 2) - - # Initialization - t = tspan[1] - tfinal = tspan[end] - hmax = (tfinal - t)/2.5 - hmin = (tfinal - t)/1e9 - h = (tfinal - t)/100 # initial guess at a step size - x = x0 - tout = [t] # first output time - xout = x.' # first output solution - - k = zeros(eltype(x), (length(c),length(x))) - - while (t < tfinal) & (h >= hmin) - if t + h > tfinal - h = tfinal - t - end - - # Compute the slopes by computing the k[:,j+1]'th column based on the previous k[:,1:j] columns - # notes: k needs to end up as an Nxs, a is 7x6, which is s by (s-1), - # s is the number of intermediate RK stages on [t (t+h)] (Dormand-Prince has s=7 stages) - if -eps() < c[end]-1 < eps() && t != tspan[1] - # Assign the last stage for x(k) as the first stage for computing x[k+1]. - # This is part of the Dormand-Prince pair caveat. - # k[:,7] has already been computed, so use it instead of recomputing it - # again as k[:,1] during the next step. - k[1,:] = k[end,:] - else - k[1,:] = F(t,x) # first stage - end - - for j = 2:length(c) - k[j,:] = F(t + h.*c[j], x + h.*(a[j,1:j-1]*k[1:j-1,:]).') - end - - # compute the 4th order estimate - x4 = x + h.*(b4*k).' - - # compute the 5th order estimate - x5 = x + h.*(b5*k).' - - # estimate the local truncation error - gamma1 = x5 - x4 - - # Estimate the error and the acceptable error - delta = norm(gamma1, Inf) # actual error - tau = tol*max(norm(x,Inf), 1.0) # allowable error - - # Update the solution only if the error is acceptable - if (delta <= tau) - t = t + h - x = x5 # <-- using the higher order estimate is called 'local extrapolation' - tout = [tout; t] - xout = [xout; x.'] - end - - # Update the step size - if delta == 0.0 - delta = 1e-16 - end - h = min(hmax, 0.8*h*(tau/delta)^pow) - end # while (t < tfinal) & (h >= hmin) - - if (t < tfinal) - println("Step size grew too small. t=", t, ", h=", h, ", x=", x) - end - - return (tout, xout) -end - -# Both the Dormand-Prince and Fehlberg 4(5) coefficients are from a tableau in -# U.M. Ascher, L.R. Petzold, Computer Methods for Ordinary Differential Equations -# and Differential-Agebraic Equations, Society for Industrial and Applied Mathematics -# (SIAM), Philadelphia, 1998 -# -# Dormand-Prince coefficients -dp_coefficients = ([ 0 0 0 0 0 0 - 1/5 0 0 0 0 0 - 3/40 9/40 0 0 0 0 - 44/45 -56/15 32/9 0 0 0 - 19372/6561 -25360/2187 64448/6561 -212/729 0 0 - 9017/3168 -355/33 46732/5247 49/176 -5103/18656 0 - 35/384 0 500/1113 125/192 -2187/6784 11/84], - # 4th order b-coefficients - [5179/57600 0 7571/16695 393/640 -92097/339200 187/2100 1/40], - # 5th order b-coefficients - [35/384 0 500/1113 125/192 -2187/6784 11/84 0], - ) -ode45_dp(F, tspan, x0) = oderkf(F, tspan, x0, dp_coefficients...) - -# Fehlberg coefficients -fb_coefficients = ([ 0 0 0 0 0 - 1/4 0 0 0 0 - 3/32 9/32 0 0 0 - 1932/2197 -7200/2197 7296/2197 0 0 - 439/216 -8 3680/513 -845/4104 0 - -8/27 2 -3544/2565 1859/4104 -11/40], - # 4th order b-coefficients - [25/216 0 1408/2565 2197/4104 -1/5 0], - # 5th order b-coefficients - [16/135 0 6656/12825 28561/56430 -9/50 2/55], - ) -ode45_fb(F, tspan, x0) = oderkf(F, tspan, x0, fb_coefficients...) - -# Cash-Karp coefficients -# Numerical Recipes in Fortran 77 -ck_coefficients = ([ 0 0 0 0 0 - 1/5 0 0 0 0 - 3/40 9/40 0 0 0 - 3/10 -9/10 6/5 0 0 - -11/54 5/2 -70/27 35/27 0 - 1631/55296 175/512 575/13824 44275/110592 253/4096], - # 4th order b-coefficients - [37/378 0 250/621 125/594 0 512/1771], - # 5th order b-coefficients - [2825/27648 0 18575/48384 13525/55296 277/14336 1/4], - ) -ode45_ck(F, tspan, x0) = oderkf(F, tspan, x0, ck_coefficients...) - -# Use Dormand Prince version of ode45 by default -ode45 = ode45_dp - -#ODE4 Solve non-stiff differential equations, fourth order -# fixed-step Runge-Kutta method. -# -# [T,X] = ODE4(ODEFUN, TSPAN, X0) with TSPAN = [T0:H:TFINAL] -# integrates the system of differential equations x' = f(t,x) from time -# T0 to TFINAL in steps of H with initial conditions X0. Function -# ODEFUN(T,X) must return a column vector corresponding to f(t,x). Each -# row in the solution array X corresponds to a time returned in the -# column vector T. -function ode4{T}(F::Function, tspan::AbstractVector, x0::AbstractVector{T}) - h = diff(tspan) - x = Array(T, (length(tspan), length(x0))) - x[1,:] = x0' - - midxdot = Array(T, (4, length(x0))) - for i = 1:(length(tspan)-1) - # Compute midstep derivatives - midxdot[1,:] = F(tspan[i], x[i,:]') - midxdot[2,:] = F(tspan[i]+h[i]./2, x[i,:]' + midxdot[1,:]'.*h[i]./2) - midxdot[3,:] = F(tspan[i]+h[i]./2, x[i,:]' + midxdot[2,:]'.*h[i]./2) - midxdot[4,:] = F(tspan[i]+h[i], x[i,:]' + midxdot[3,:]'.*h[i]) - - # Integrate - x[i+1,:] = x[i,:] + 1./6.*h[i].*[1 2 2 1]*midxdot - end - return (tspan, x) -end - -#ODEROSENBROCK Solve stiff differential equations, Rosenbrock method -# with provided coefficients. -function oderosenbrock{T}(F::Function, G::Function, tspan::AbstractVector, x0::AbstractVector{T}, gamma, a, b, c) - h = diff(tspan) - x = Array(T, length(tspan), length(x0)) - x[1,:] = x0' - - solstep = 1 - while tspan[solstep] < max(tspan) - ts = tspan[solstep] - hs = h[solstep] - xs = reshape(x[solstep,:], size(x0)) - dFdx = G(ts, xs) - jac = eye(size(dFdx)[1])./gamma./hs-dFdx - - g = zeros(size(a)[1], length(x0)) - g[1,:] = jac \ F(ts + b[1].*hs, xs) - for i = 2:size(a)[1] - g[i,:] = jac \ (F(ts + b[i].*hs, xs + (a[i,1:i-1]*g[1:i-1,:]).') + (c[i,1:i-1]*g[1:i-1,:]).'./hs) - end - - x[solstep+1,:] = x[solstep,:] + b*g - solstep += 1 - end - return (tspan, x) -end - -function oderosenbrock{T}(F::Function, tspan::AbstractVector, x0::AbstractVector{T}, gamma, a, b, c) - # Crude forward finite differences estimator as fallback - function jacobian(F::Function, t::Number, x::AbstractVector) - ftx = F(t, x) - dFdx = zeros(length(x), length(x)) - for j = 1:length(x) - dx = zeros(size(x)) - # The 100 below is heuristic - dx[j] = (x[j]+(x[j]==0))./100 - dFdx[:,j] = (F(t,x+dx)-ftx)./dx[j] - end - return dFdx - end - oderosenbrock(F, (t, x)->jacobian(F, t, x), tspan, x0, gamma, a, b, c) -end - -# Kaps-Rentrop coefficients -kr4_coefficients = (0.231, - [0 0 0 0 - 2 0 0 0 - 4.4524708 4.163528 0 0 - 4.4524708 4.163528 0 0], - [3.957037 4.624892 0.617477 1.282613], - [ 0 0 0 0 - -5.071675 0 0 0 - 6.020153 0.159750 0 0 - -1.856344 -8.505381 -2.084075 0],) -ode4s_kr(F, tspan, x0) = oderosenbrock(F, tspan, x0, kr4_coefficients...) -ode4s_kr(F, G, tspan, x0) = oderosenbrock(F, G, tspan, x0, kr4_coefficients...) -# Shampine coefficients -s4_coefficients = (0.5, - [ 0 0 0 0 - 2 0 0 0 - 48/25 6/25 0 0 - 48/25 6/25 0 0], - [19/9 1/2 25/108 125/108], - [ 0 0 0 0 - -8 0 0 0 - 372/25 12/5 0 0 - -112/125 -54/125 -2/5 0],) -ode4s_s(F, tspan, x0) = oderosenbrock(F, tspan, x0, s4_coefficients...) -ode4s_s(F, G, tspan, x0) = oderosenbrock(F, G, tspan, x0, s4_coefficients...) - -# Use Shampine coefficients by default (matching Numerical Recipes) -const ode4s = ode4s_s - -# ODE_MS Fixed-step, fixed-order multi-step numerical method with Adams-Bashforth-Moulton coefficients -function ode_ms{T}(F::Function, tspan::AbstractVector, x0::AbstractVector{T}, order::Integer) - h = diff(tspan) - x = zeros(T,(length(tspan), length(x0))) - x[1,:] = x0 - - if 1 <= order <= 4 - b = [ 1 0 0 0 - -1/2 3/2 0 0 - 5/12 -16/12 23/12 0 - -9/24 37/24 -59/24 55/24]; - else - for steporder = size(b,1):order - s = steporder - 1; - for j = 0:s - # Assign in correct order for multiplication below - # (a factor depending on j and s) .* (an integral of a polynomial with -(0:s), except -j, as roots) - b[steporder,s-j+1] = (-1).^j./factorial(j)./factorial(s-j).*diff(polyval(polyint(poly(diagm(-[0:j-1; j+1:s]))),0:1)); - end - end - end - - # TODO: use a better data structure here (should be an order-element circ buffer) - xdot = similar(x) - for i = 1:length(tspan)-1 - # Need to run the first several steps at reduced order - steporder = min(i, order) - xdot[i,:] = F(tspan[i], x[i,:]') - x[i+1,:] = x[i,:] + b[steporder,1:steporder]*xdot[i-(steporder-1):i,:].*h[i] - end - return (tspan, x) -end - -ode4ms(F, tspan, x0) = ode_ms(F, tspan, x0, 4) diff --git a/extras/pkg.jl b/extras/pkg.jl new file mode 100644 index 0000000000000..efc85c43d40a0 --- /dev/null +++ b/extras/pkg.jl @@ -0,0 +1 @@ +error("Pkg no longer needs to be required as it is part of base Julia.") diff --git a/extras/pkg2.jl b/extras/pkg2.jl new file mode 100644 index 0000000000000..06371e3564312 --- /dev/null +++ b/extras/pkg2.jl @@ -0,0 +1,104 @@ +# module Pkg2 +import Base: Git, isequal, isless, hash, isempty, contains + +### VersionSet ### + +immutable VersionInterval + lower::VersionNumber + upper::VersionNumber +end + +isempty(i::VersionInterval) = i.upper <= i.lower +contains(i::VersionInterval, v::VersionNumber) = a.lower <= v < a.upper +intersect(a::VersionInterval, b::VersionInterval) = VersionInterval(max(a.lower,b.lower), min(a.upper,b.upper)) +intersect(A::Vector{VersionInterval}, B::Vector{VersionInterval}) = + sortby!(filter!(i->!isempty(i), vec([ intersect(a,b) for a in A, b in B ])), i->i.lower) + +typealias Requires Dict{ByteString,Vector{VersionInterval}} + +function parse_requires(readable) + reqs = Requires() + for line in eachline(readable) + ismatch(r"^\s*(?:#|$)", line) && continue + fields = split(replace(line, r"#.*$", "")) + pkg = shift!(fields) + if !all(x->ismatch(Base.VERSION_REGEX,x), fields) + error("invalid requires entry for $pkg: $fields") + end + vers = [ convert(VersionNumber,x) for x in fields ] + if !issorted(vers) + error("invalid requires entry for $pkg: $vers") + end + ivals = VersionInterval[] + if isempty(vers) + push!(ivals, VersionInterval(typemin(VersionNumber),typemax(VersionNumber))) + else + isodd(length(vers)) && push!(vers, typemax(VersionNumber)) + while !isempty(vers) + push!(ivals, VersionInterval(shift!(vers), shift!(vers))) + end + end + reqs[pkg] = has(reqs,pkg) ? intersect(reqs[pkg], ivals) : ivals + end + return reqs +end +parse_requires(file::String) = isfile(file) ? open(parse_requires,file) : Requires() + +function merge!(A::Requires, B::Requires) + for (pkg, ivals) in B + A[pkg] = has(A,pkg) ? intersect(A[pkg], ivals) : ivals + end + return A +end + +immutable Installed + name::ByteString + fixed::Bool + reqs::Requires +end + +function isfixed(pkg::String) + isfile("METDATA", pkg, "url") || return true + ispath(pkg, ".git") || return true + cd(pkg) do + Git.dirty() && return true + Git.attached() && return true + for line in eachline(`git branch -r --contains`) + return false + end + return true + end +end + +function installed() + pkgs = Installed[] + for line in eachline(`ls -1`) + pkg = chomp(line) + pkg == "METADATA" && continue + pkg == "REQUIRE" && continue + isfile(pkg, "src", "$pkg.jl") || continue + reqs = parse_requires(joinpath(pkg, "REQUIRE")) + push!(pkgs, Installed(pkg, isfixed(pkg), reqs)) + end + return pkgs +end + +function available() + pkgs = Dict{ByteString,Dict{VersionNumber,Requires}}() + for line in eachline(`ls -1 METADATA`) + pkg = chomp(line) + isfile("METADATA", pkg, "url") || continue + versions = joinpath("METADATA", pkg, "versions") + isdir(versions) || continue + for line in eachline(`ls -1 $versions`) + ver = chomp(line) + ismatch(Base.VERSION_REGEX, ver) || continue + isfile(versions, ver, "sha1") || continue + if !has(pkgs,pkg) pkgs[pkg] = Dict{VersionNumber,Requires}() end + pkgs[pkg][convert(VersionNumber,ver)] = parse_requires(joinpath(versions, ver, "requires")) + end + end + return pkgs +end + +# end # module diff --git a/extras/poly.jl b/extras/poly.jl deleted file mode 100644 index 1d74386e0cdc8..0000000000000 --- a/extras/poly.jl +++ /dev/null @@ -1,269 +0,0 @@ -# Polynomial type manipulations - -#todo: division -#todo: sparse polynomials? - -import Base.length, Base.ref, Base.assign, Base.copy, Base.zero, Base.one -import Base.show, Base.*, Base./, Base.-, Base.+, Base.== - -type Polynomial{T<:Number} - a::Vector{T} - nzfirst::Int #for effiencicy, track the first non-zero index - function Polynomial(a::Vector{T}) - nzfirst = 0 #find and chop leading zeros - for i = 1:length(a) - if a[i] != 0 then - break - end - nzfirst = i - end - new(a, nzfirst) - end -end - -Polynomial{T<:Number}(a::Vector{T}) = Polynomial{T}(a) - -length(p::Polynomial) = length(p.a)-p.nzfirst -ref(p::Polynomial, i) = p.a[i+p.nzfirst] -assign(p::Polynomial, v, i) = (p.a[i+p.nzfirst] = v) - -copy(p::Polynomial) = Polynomial(copy(p.a[1+p.nzfirst:end])) - -zero{T}(p::Polynomial{T}) = Polynomial([zero(T)]) -one{T}(p::Polynomial{T}) = Polynomial([one(T)]) - -function show(io,p::Polynomial) - n = length(p) - print(io,"Polynomial(") - if n <= 0 - print(io,"0") - elseif n == 1 - print(io,p[1]) - else - print(io,"$(p[1])x^$(n-1)"); - for i = 2:n-1 - if p[i] != 0 - print(io," + $(p[i])x^$(n-i)") - end - end - if p[n] != 0 - print(io," + $(p[n])") - end - end - print(io,")") -end - -function show{T<:Complex}(p::Polynomial{T}) - n = length(p) - print("Polynomial(") - if n <= 0 - print("0") - elseif n == 1 - print("[$(p[1])]") - else - print("[$(p[1])]x^$(n-1)") - for i = 2:n-1 - if p[i] != 0 - print(" + [$(p[i])]x^$(n-i)") - end - end - if p[n] != 0 - print(" + [$(p[n])]") - end - end - print(")") -end - -*(c::Number, p::Polynomial) = Polynomial(c * p.a[1+p.nzfirst:end]) -*(p::Polynomial, c::Number) = Polynomial(c * p.a[1+p.nzfirst:end]) -/(p::Polynomial, c::Number) = Polynomial(p.a[1+p.nzfirst:end] / c) --(p::Polynomial) = Polynomial(-p.a[1+p.nzfirst:end]) - --(p::Polynomial, c::Number) = +(p, -c) -+(c::Number, p::Polynomial) = +(p, c) -function +(p::Polynomial, c::Number) - if length(p) < 1 - return Polynomial([c,]) - else - p2 = copy(p) - p2.a[end] += c; - return p2; - end -end -function -(c::Number, p::Polynomial) - if length(p) < 1 - return Polynomial([c,]) - else - p2 = -p; - p2.a[end] += c; - return p2; - end -end - -function +{T,S}(p1::Polynomial{T}, p2::Polynomial{S}) - R = promote_type(T,S) - n = length(p1) - m = length(p2) - if n > m - a = Array(R, n) - for i = 1:m - a[n-m+i] = p1[n-m+i] + p2[i] - end - for i = 1:n-m - a[i] = p1[i] - end - else - a = Array(R, m) - for i = 1:n - a[m-n+i] = p1[i] + p2[m-n+i] - end - for i = 1:m-n - a[i] = p2[i] - end - end - Polynomial(a) -end - -function -{T,S}(p1::Polynomial{T}, p2::Polynomial{S}) - R = promote_type(T,S) - n = length(p1) - m = length(p2) - if n > m - a = Array(R, n) - for i = 1:m - a[n-m+i] = p1[n-m+i] - p2[i] - end - for i = 1:n-m - a[i] = p1[i] - end - else - a = Array(R, m) - for i = 1:n - a[m-n+i] = p1[i] - p2[m-n+i] - end - for i = 1:m-n - a[i] = -p2[i] - end - end - Polynomial(a) -end - -function *{T,S}(p1::Polynomial{T}, p2::Polynomial{S}) - R = promote_type(T,S) - n = length(p1) - m = length(p2) - if n == 0 || m == 0 - return Polynomial(R[]) - end - a = zeros(R, n+m-1) - for i = 1:length(p1) - for j = 1:length(p2) - a[i+j-1] += p1[i] * p2[j] - end - end - Polynomial(a) -end - - -function ==(p1::Polynomial, p2::Polynomial) - if length(p1) != length(p2) - return false - else - return p1.a[1+p1.nzfirst:end] == p2.a[1+p2.nzfirst:end] - end -end - -function polyval{T}(p::Polynomial{T}, x::Number) - R = promote_type(T, typeof(x)) - lenp = length(p) - if lenp == 0 - return zero(R) - else - y = convert(R, p[1]) - for i = 2:lenp - y = p[i] + x.*y - end - return y - end -end - -function polyval(p::Polynomial, x::AbstractVector) - y = zeros(size(x)) - for i = 1:length(x) - y[i] = polyval(p, x[i]) - end - return y -end - -polyint(p::Polynomial) = polyint(p, 0) -function polyint{T}(p::Polynomial{T}, k::Number) - R = promote_type(promote_type(T, Float64), typeof(k)) - n = length(p) - a2 = Array(R, n+1) - for i = 1:n - a2[i] = p[i] / (n-i+1) - end - a2[end] = k - Polynomial(a2) -end - -function polydir{T}(p::Polynomial{T}) - n = length(p) - if n > 0 - a2 = Array(T, n-1) - for i = 1:n-1 - a2[i] = p[i] * (n-i) - end - else - a2 = zeros(T, 0) - end - Polynomial(a2) -end - -function poly{T}(r::AbstractVector{T}) - n = length(r) - c = zeros(T, n+1) - c[1] = 1 - for j = 1:n - c[2:j+1] = c[2:j+1]-r[j]*c[1:j] - end - return Polynomial(c) -end -poly(A::Matrix) = poly(eig(A)[1]) - -function roots{T}(p::Polynomial{T}) - num_zeros = 0 - if length(p) == 0 return zeros(T,0) end - while p[end-num_zeros] == 0 - if num_zeros == length(p)-1 - return zeros(T, 0) - end - num_zeros += 1 - end - n = length(p)-num_zeros-1 - if n < 1 - return zeros(T, length(p)-1) - end - R = promote_type(T, Float64) - companion = zeros(R, n, n) - a0 = p[end-num_zeros] - for i = 1:n-1 - companion[1,i] = -p[end-num_zeros-i] / a0 - companion[i+1,i] = 1; - end - companion[1,end] = -p[1] / a0 - D,V = eig(companion) - T_r = typeof(real(D[1])) - T_i = typeof(imag(D[1])) - if all(imag(D) .< 2*eps(T_i)) - r = zeros(T_r, length(p)-1) - r[1:n] = 1./real(D) - return r - else - r = zeros(typeof(D[1]),length(p)-1) - r[1:n] = 1./D - return r - end -end - - diff --git a/extras/profile.jl b/extras/profile.jl deleted file mode 100644 index b67d1f46c2487..0000000000000 --- a/extras/profile.jl +++ /dev/null @@ -1,347 +0,0 @@ -module Profile - -PROFILE_LINES = 1 -PROFILE_DESCEND = 2 -PROFILE_STATE = PROFILE_LINES | PROFILE_DESCEND # state is a bitfield - -# Record of expressions to parse according to the current PROFILE_STATE -PROFILE_EXPR = {} - -# To avoid the performance penalty of global variables, we design the -# macro to create local variables through a "let" block that shares -# the timing and count data with "reporting" and "clearing" functions. -PROFILE_REPORTS = {} # list of reporting functions -PROFILE_CLEARS = {} # list of clearing functions -PROFILE_TAGS = {} # line #s for all timing variables - -# Profile calibration, to compensate for the overhead of calling time() -PROFILE_CALIB = 0 -# Do it inside a let block, just like in real profiling, in case of -# extra overhead -let # tlast::Uint64 = 0x0, tnow::Uint64 = 0x0 -global profile_calib -function profile_calib(n_iter) - trec = Array(Uint64, n_iter) - for i = 1:n_iter - tlast = time_ns() - tnow = time_ns() - trec[i] = tnow - tlast - end - return trec -end -end -PROFILE_CALIB = min(profile_calib(100)) - -# Utilities -# Generic expression type testing -is_expr_head(ex::Expr, s::Symbol) = ex.head == s -is_expr_head(nonex, s::Symbol) = false - -# Test whether an expression is a function declaration -function isfuncexpr(ex::LineNumberNode) - return false -end -function isfuncexpr(ex::Expr) - return ex.head == :function || (ex.head == :(=) && ex.args[1].head == :call) -end - -# Get the "full syntax" of the function call -function funcsyntax(ex::Expr) - return ex.args[1] -end - -# Get the symbol associated with the function call -function funcsym(ex::Expr) - tmp = funcsyntax(ex) - tmp = tmp.args[1] - if is_expr_head(tmp, :curly) - tmp = tmp.args[1] - end - return tmp -end - -# Test for control-flow statements -is_cf_expr(ex::Expr) = contains([:for, :while, :if, :try], ex.head) -is_cf_expr(ex) = false - -# General switchyard function -function insert_profile(ex::Expr, tlast, tnow, timers, counters, tags, indx::Int, retsym, rettest) - if ex.head == :block - insert_profile_block(ex, tlast, tnow, timers, counters, tags, indx, retsym, rettest) - elseif is_cf_expr(ex) - insert_profile_cf(ex, tlast, tnow, timers, counters, tags, indx, retsym) - else - error("Don't know what to do") - end -end - -# Insert profiling statements into a code block -# rettest is a function with the following syntax: -# rettest(Expr, Int) -# and evaluates to true if the return value of Expr needs to be saved -# before inserting profiling statements. -function insert_profile_block(fblock::Expr, tlast, tnow, timers, counters, tags, indx::Int, retsym, rettest) - global PROFILE_STATE, PROFILE_DESCEND - if fblock.head != :block - println(fblock) - error("expression is not a block") - end - descend = PROFILE_STATE & PROFILE_DESCEND > 0 - fblocknewargs = {} - for i = 1:length(fblock.args) - if isa(fblock.args[i],LineNumberNode) || is_expr_head(fblock.args[i], :line) - # This is a line expression, so no counters/timers required - push(fblocknewargs,fblock.args[i]) - # ...but keep track of the line # for use during reporting - lasttag = fblock.args[i] - elseif descend && is_cf_expr(fblock.args[i]) - # This is a control-flow statement, it requires special - # handling (recursive) - cfnew, indx = insert_profile_cf(fblock.args[i], tlast, tnow, timers, counters, tags, indx, retsym) - push(fblocknewargs, cfnew) - else - # This is an "ordinary" statement - saveret = rettest(fblock, i) - push(tags,lasttag) - if saveret - if is_expr_head(fblock.args[i], :return) - push(fblocknewargs, :($retsym = $(fblock.args[i].args[1]))) - else - push(fblocknewargs, :($retsym = $(fblock.args[i]))) - end - else - push(fblocknewargs, fblock.args[i]) - end - # This next line inserts timing statements between two - # lines of code, equivalent to: - # timehr(PROFILE_USE_CLOCK, tnow) # end time of prev - # timers[indx] += timehr_diff(tlast, tnow) - # counters[indx] += 1 - # timehr(PROFILE_USE_CLOCK, tlast) # start time for next - append!(fblocknewargs,{:($tnow = time_ns()), :(($timers)[($indx)] += $tnow - $tlast), :(($counters)[($indx)] += 1), :($tlast = time_ns())}) - indx += 1 - if saveret - push(fblocknewargs, :(return $retsym)) - end - end - end - return expr(:block, fblocknewargs), indx -end - -# Handling control-flow statements -function insert_profile_cf(ex::Expr, tlast, tnow, timers, counters, tags, indx::Int, retsym) - rettest = (ex, i) -> is_expr_head(ex, :return) - if length(ex.args) == 2 - # This is a for, while, or 2-argument if or try block - block1, indx = insert_profile(ex.args[2], tlast, tnow, timers, counters, tags, indx, retsym, rettest) - return expr(ex.head, {ex.args[1], block1}), indx - elseif length(ex.args) == 3 - # This is for a 3-argument if or try block - block1, indx = insert_profile(ex.args[2], tlast, tnow, timers, counters, tags, indx, retsym, rettest) - block2, indx = insert_profile(ex.args[3], tlast, tnow, timers, counters, tags, indx, retsym, rettest) - return expr(ex.head, {ex.args[1], block1, block2}), indx - else - error("Wrong number of arguments") - end -end - -# Insert timing and counters into function body. -# Function bodies differ from blocks in these respects: -# - We need to initialize tlast -# - The final statement of a function should be returned, even if there -# is no explicit return statement -# - Functions can be defined in "short-form" (e.g., -# "isempty(x) = numel(x)==0"), and the return value for these -# needs to be managed, too -function insert_profile_function(ex::Expr, tlast, tnow, timers, counters, tags, indx::Int, retsym) - fblock = ex.args[2] - if fblock.head != :block - error("Can't parse func expression") - end - # Prepare the test for whether we need to save the return value of - # a given line of code. We may need to store the return value - # because we need to run timing operations after computing the - # output. - # For a function, this will be true in three cases: - # - For a "f1(x) = x+1" type of function declaration - # - For an explicit return statement - # - For the last line of a function that does not have - # an explicit return statement in it. - if ex.head == :(=) - # This is a short-form function declaration - savefunc = (ex, i) -> true - else - # Long form, check to see if it's a return or the last line - savefunc = (ex, i) -> i == length(fblock.args) || is_expr_head(ex, :return) - end - # Insert the profiling statements in the function - fblocknewargs, indx = insert_profile_block(fblock, tlast, tnow, timers, counters, tags, indx, retsym, savefunc) - # Prepend the initialization of tlast - fblocknewargs = vcat({:($tlast = time_ns())}, fblocknewargs.args) - return expr(:function,{funcsyntax(ex),expr(:block,fblocknewargs)}), indx -end - -function profile_parse(ex::Expr) - if PROFILE_STATE & PROFILE_LINES > 0 - # Create the "let" variables for timing and counting - tlast = gensym() - tnow = gensym() - timers = gensym() - counters = gensym() - # Keep track of line numbers - tags = {} - # Preserve return values - retsym = gensym() - # Create the symbols used for reporting and clearing the data - # for this block - funcreport = gensym() - funcclear = gensym() - # Parse the block and insert instructions - indx = 1 - coreargs = {} - if ex.head == :block - # This is a block which may contain many function declarations - for i = 1:length(ex.args) - if isfuncexpr(ex.args[i]) - # Insert "global" statement for each function - push(coreargs,expr(:global,funcsym(ex.args[i]))) - # Insert function-call counters - newfuncexpr, indx = insert_profile_function(ex.args[i], tlast, tnow, timers, counters, tags, indx, retsym) - push(coreargs, newfuncexpr) - else - push(coreargs,ex.args[i]) - end - end - elseif isfuncexpr(ex) - # This is a single function declaration - push(coreargs,expr(:global,funcsym(ex))) - newfuncexpr, indx = insert_profile_function(ex, tlast, tnow, timers, counters, tags, indx, retsym) - push(coreargs, newfuncexpr) - else - error("Could not parse expression") - end - n_lines = indx-1 - # Insert reporting function - # Because we're using a gensym for the function name, we can't - # quote the whole thing - push(coreargs, expr(:global, funcreport)) - push(coreargs, expr(:function, {expr(:call, {funcreport}), expr(:block,{:(return $timers, $counters)})})) - # Insert clearing function - push(coreargs, expr(:global, funcclear)) - push(coreargs, expr(:function, {expr(:call, {funcclear}), expr(:block,{:(fill!($timers,0)), :(fill!($counters,0))})})) - # Put all this inside a let block - excore = expr(:block,coreargs) - exlet = expr(:let,{expr(:block,excore), :($timers = zeros(Uint64, $n_lines)), :($counters = zeros(Uint64, $n_lines))}) - return exlet, tags, funcreport, funcclear - else - return ex ,{}, :funcnoop, :funcnoop - end -end - -function funcnoop() -end - -function profile_parse_all() - del_all(PROFILE_REPORTS) - del_all(PROFILE_CLEARS) - del_all(PROFILE_TAGS) - retargs = {} - for i = 1:length(PROFILE_EXPR) - newblock, tags, funcreport, funcclear = profile_parse(PROFILE_EXPR[i]) - retargs = vcat(retargs, newblock.args) - if !isempty(tags) - push(PROFILE_TAGS, tags) - push(PROFILE_REPORTS, esc(funcreport)) - push(PROFILE_CLEARS, esc(funcclear)) - end - end - push(retargs,:(return nothing)) - return esc(expr(:block,retargs)) -end - -function profile_report() - exret = cell(length(PROFILE_REPORTS)+2) - ret = gensym() - exret[1] = :($ret = {}) - for i = 1:length(PROFILE_REPORTS) - exret[i+1] = :(push($ret,$(expr(:call,{PROFILE_REPORTS[i]})))) - end - exret[end] = :(profile_print($ret)) - return expr(:block,exret) -end - -compensated_time(t, c) = t >= c*PROFILE_CALIB ? t-c*PROFILE_CALIB : 0 -show_unquoted(linex::Expr) = show_linenumber(linex.args...) -show_unquoted(lnn::LineNumberNode) = show_linenumber(lnn.line) -show_linenumber(line) = strcat("\t# line ",line) -show_linenumber(line, file) = strcat("\t# ",file,", line ",line) - -function profile_print(tc) - # Compute total elapsed time - ttotal = 0.0 - for i = 1:length(tc) - timers = tc[i][1] - counters = tc[i][2] - for j = 1:length(counters) - comp_time = compensated_time(timers[j], counters[j]) - ttotal += comp_time - end - end - # Display output - for i = 1:length(tc) - timers = tc[i][1] - counters = tc[i][2] - println(" count time(%) time(s)") - for j = 1:length(counters) - if counters[j] != 0 - comp_time = compensated_time(timers[j], counters[j]) - @printf("%8d %5.2f %f %s\n", counters[j], - 100*(comp_time/ttotal), - comp_time*1e-9, - show_unquoted(PROFILE_TAGS[i][j])) - end - end - end -end - -function profile_clear() - exret = cell(length(PROFILE_CLEARS)+1) - for i = 1:length(PROFILE_CLEARS) - exret[i] = expr(:call,{PROFILE_CLEARS[i]}) - end - exret[end] = :(return nothing) - return expr(:block,exret) -end - -macro profile(ex) - global PROFILE_STATE - if isa(ex,Symbol) - # State changes - if ex == :off - PROFILE_STATE = 0 - elseif ex == :on - PROFILE_STATE = PROFILE_LINES - elseif ex == :reset - elseif ex == :report - return profile_report() - elseif ex == :clear - return profile_clear() - else - error("Profile mode not recognized") - end - return profile_parse_all() - elseif isa(ex,Expr) - push(PROFILE_EXPR,ex) - exret, tags, funcreport, funcclear = profile_parse(ex) - if !isempty(tags) - push(PROFILE_TAGS, tags) - push(PROFILE_REPORTS, esc(funcreport)) - push(PROFILE_CLEARS, esc(funcclear)) - end - return esc(exret) - end -end - -export @profile - -end # module Profile diff --git a/extras/strpack.jl b/extras/strpack.jl deleted file mode 100644 index 56386a0224433..0000000000000 --- a/extras/strpack.jl +++ /dev/null @@ -1,545 +0,0 @@ -load("iostring") -load("lru") - -bswap(c::Char) = identity(c) # white lie which won't work for multibyte characters - -# Represents data endianness -abstract Endianness -type BigEndian <: Endianness; end -type LittleEndian <: Endianness; end -type NativeEndian <: Endianness; end - -# Represents a packed composite type -type Struct - canonical::String - endianness::Endianness - types - pack::Function - unpack::Function - struct::Type -end -function Struct{T}(::Type{T}, endianness) - if !isa(T, CompositeKind) - error("Type $T is not a composite type.") - end - if !isbitsequivalent(T) - error("Type $T is not bits-equivalent.") - end - s = canonicalize(T, endianness) - if has(STRUCTS, s) - return STRUCTS[s] - end - types = composite_fieldinfo(T) - packer, unpacker = endianness_converters(endianness) - pack = struct_pack(packer, types, T) - unpack = struct_unpack(unpacker, types, T) - struct_utils(T) - STRUCTS[s] = Struct(s, endianness, types, pack, unpack, T) -end -Struct{T}(::Type{T}) = Struct(T, NativeEndian()) - -# Represents a particular way of adding bytes to maintain certain alignments -type DataAlign - ttable::Dict - # default::(Type -> Integer); used for bits types not in ttable - default::Function - # aggregate::(Vector{Type} -> Integer); used for composite types not in ttable - aggregate::Function -end -DataAlign(def::Function, agg::Function) = DataAlign((Type=>Integer)[], def, agg) - -canonicalize(s::String) = replace(s, r"\s|#.*$"m, "") - -# colons chosen since they are not allowed in struct-format strings or in type names -canonicalize(t::Type,e::Endianness) = strcat("::", string(t), "::", string(e)) - -# A byte of padding -bitstype 8 PadByte -write(s, x::PadByte) = write(s, uint8(0)) -read(s, ::Type{PadByte}) = read(s, Uint8) - - -# TODO Handle strings and arrays -function isbitsequivalent{T}(::Type{T}) - if isa(T, BitsKind) - return true - elseif !isa(T, CompositeKind) - return false - end - for S in T.types - if !isbitsequivalent(S) - return false - end - end - true -end -isbitsequivalent(struct::Struct) = isbitsequivalent(struct.struct) - -function composite_fieldinfo{T}(::Type{T}) - types = cell(length(T.names)) - for i in 1:length(T.names) - types[i] = T.types[i], 1, T.names[i] - end - types -end - -function calcsize(types) - size = 0 - for (elemtype, dims) in types - typ = elemtype <: Array ? eltype(elemtype) : elemtype - size += if isa(typ, BitsKind) - prod(dims)*sizeof(typ) - elseif isa(typ, CompositeKind) - prod(dims)*sizeof(Struct(typ)) - else - error("Improper type $typ in struct.") - end - end - size -end - -# Struct string syntax -# Note that not all of these are checked by the regex itself but are verified after -# Presented in regex-style EBNF -# -# struct_string := endianness? element_specifier* -# endianness := "<" | ">" | "!" | "=" | "@" -# element_specifier := name? size? type -# name := "[" identifier "]" -# size := unsigned_integer | "(" unsigned_integer ("," unsigned_integer)* ")" -# type := predefined_type | "{" identifier "}" -# predefined_type := "x" | "c" | "b" | "B" | "?" | "h" | "i" | "I" | "l" | "L" | "q" | "Q" | "f" | "d" -function struct_parse(s::String) - t = {} - i = 2 - endianness = if s[1] == '<' - LittleEndian() - elseif s[1] == '>' || s[1] == '!' - BigEndian() - elseif s[1] == '=' - NativeEndian() - elseif s[1] == '@' - println("Warning: struct does not support fully native structures.") - NativeEndian() - else - i = 1 # no byte order command - NativeEndian() - end - - tmap = ['x' => PadByte, - 'c' => Char, - 'b' => Int8, - 'B' => Uint8, - '?' => Bool, - 'h' => Int16, - 'H' => Uint16, - 'i' => Int32, - 'I' => Uint32, - 'l' => Int32, - 'L' => Uint32, - 'q' => Int64, - 'Q' => Uint64, - 'f' => Float32, - 'd' => Float64, - #'s' => ASCIIString, #TODO - ] - t = {} - while i <= length(s) - m = match(r"^ # at the beginning of the string, find - (?:\[([a-zA-Z]\w*)\])? # an optional name in [] - (?: # then - (\d+) # a vector length - | # or - \((\d+(?:,\d+)*)\) # a comma-separated array size in () - )? # or neither - (?: # followed by either - ([a-zA-Z?]) # a predefined type specifier - | # or - {([a-zA-Z]\w*)} # another type in {} - ) - "x, s[i:end]) - if isa(m, Nothing) - error("Failed to compile struct; syntax error at ...$(s[i])...") - end - name, oneD, nD, typ, custtyp = m.captures - dims = if isa(oneD, Nothing) && isa(nD, Nothing) - 1 - elseif isa(nD, Nothing) - int(oneD) - else - tuple(map(int, split(nD, ','))...) - end - elemtype = if isa(custtyp, Nothing) - tmap[typ[1]] - else - testtype = eval(symbol(custtyp)) #is there an easier way to do this? - if isbitsequivalent(testtype) - testtype - else - error("Failed to compile struct; $testtype is not a bits-equivalent type.") - end - end - i += length(m.match) - push(t, (elemtype, dims, name)) - end - (endianness, t) -end - -# Generate an anonymous composite type from a list of its element types -function gen_typelist(types::Array) - xprs = {} - for (typ, dims, name) in types - fn = !isa(name, Nothing) ? symbol(name) : gensym("field$(length(xprs)+1)") - xpr = if dims == 1 - :(($fn)::($typ)) - else - if typ != ASCIIString - sz = length(dims) - :(($fn)::Array{($typ),($sz)}) - else - :(($fn)::($typ)) - end - end - push(xprs, xpr) - end - xprs -end -function gen_type(types) - @gensym struct - fields = gen_typelist(types) - typedef = quote - type $struct - $(fields...) - end - $struct - end - eval(typedef) -end - -# Generate an unpack function for a composite type -function gen_readers(convert::Function, types::Array, stream::Symbol, offset::Symbol, strategy::Symbol) - xprs, rvars = {}, {} - @gensym pad - push(xprs, :($offset = 0)) - for (typ, dims) in types - push(xprs, quote - $pad = pad_next($offset, $typ, $strategy) - if $pad > 0 - skip($stream, $pad) - $offset += $pad - end - $offset += sizeof($typ)*prod($dims) - end) - rvar = gensym() - push(rvars, rvar) - push(xprs, if isa(typ, CompositeKind) - :($rvar = unpack($stream, $typ)) - elseif dims == 1 - :($rvar = ($convert)(read($stream, $typ))) - else - :($rvar = map($convert, read($stream, $typ, $dims...))) - end) - end - xprs, rvars -end -function struct_unpack(convert, types, struct_type) - @gensym in offset strategy - readers, rvars = gen_readers(convert, types, in, offset, strategy) - unpackdef = quote - (($in)::IO, ($strategy)::DataAlign) -> begin - $(readers...) - # tail pad - skip($in, pad_next($offset, $struct_type, $strategy)) - ($struct_type)($(rvars...)) - end - end - eval(unpackdef) -end - -# Generate a pack function for a composite type -function gen_writers(convert::Function, types::Array, struct_type, stream::Symbol, struct::Symbol, offset::Symbol, strategy::Symbol) - @gensym fieldnames pad - xprs = {:(local $fieldnames = $struct_type.names), :($offset = 0)} - elnum = 0 - for (typ, dims) in types - elnum += 1 - push(xprs, quote - $pad = pad_next($offset, $typ, $strategy) - if $pad > 0 - write($stream, fill(uint8(0), $pad)) - $offset += $pad - end - $offset += sizeof($typ)*prod($dims) - end) - push(xprs, if isa(typ, CompositeKind) - :(pack($stream, getfield($struct, ($fieldnames)[$elnum]))) - elseif dims == 1 - :(write($stream, ($convert)(getfield($struct, ($fieldnames)[$elnum])))) - else - ranges = tuple([1:d for d in dims]...) - :(write($stream, map($convert, ref(getfield($struct, ($fieldnames)[$elnum]), ($ranges)...)))) - end) - end - xprs -end -function struct_pack(convert, types, struct_type) - @gensym out struct offset strategy - writers = gen_writers(convert, types, struct_type, out, struct, offset, strategy) - packdef = quote - (($out)::IO, ($strategy)::DataAlign, ($struct)::($struct_type)) -> begin - $(writers...) - # tail pad - write($out, fill(uint8(0), pad_next($offset, $struct_type, $strategy))) - end - end - eval(packdef) -end - -endianness_converters{T<:Endianness}(::T) = error("endianness type $T not recognized") -endianness_converters(::BigEndian) = hton, ntoh -endianness_converters(::LittleEndian) = htol, ltoh -endianness_converters(::NativeEndian) = identity, identity - -function struct_utils(struct_type) - @eval ref(struct::($struct_type), i::Integer) = struct.(($struct_type).names[i]) - @eval ref(struct::($struct_type), x) = [struct.(($struct_type).names[i]) for i in x] - @eval length(struct::($struct_type)) = length(($struct_type).names) - # this could be better - @eval isequal(a::($struct_type), b::($struct_type)) = isequal(a[1:end], b[1:end]) -end - -# Structure cache: -# * a given canonical struct string returns the same struct (until you run out of cache space) -# * we don't spend time regenerating types and functions when we don't have to -const STRUCTS = BoundedLRU() - -function interp_struct_parse(str::String) - s = canonicalize(str) - if has(STRUCTS, s) - return STRUCTS[s] - end - endianness, types = struct_parse(s) - packer, unpacker = endianness_converters(endianness) - struct_type = gen_type(types) - pack = struct_pack(packer, types, struct_type) - unpack = struct_unpack(unpacker, types, struct_type) - struct_utils(struct_type) - STRUCTS[s] = Struct(s, endianness, types, pack, unpack, struct_type) -end - -macro s_str(str) - interp_struct_parse(str) -end - -# Julian aliases for the "object-style" calls to pack/unpack/struct -function pack(out::IO, s::Struct, strategy::DataAlign, struct_or_only_item) - if isa(struct_or_only_item, s.struct) - s.pack(out, strategy, struct_or_only_item) - else - s.pack(out, strategy, s.struct(struct_or_only_item)) - end -end -pack{T}(out::IO, composite::T, strategy::DataAlign) = pack(out, Struct(T), strategy, composite) -pack{T}(out::IO, composite::T) = pack(out, Struct(T), align_packed, composite) -pack(out::IO, s::Struct, strategy::DataAlign, args...) = s.pack(out, strategy, s.struct(args...)) -pack(out::IO, s::Struct, args...) = s.pack(out, align_packed, s.struct(args...)) - -unpack(in::IO, s::Struct, strategy::DataAlign) = s.unpack(in, strategy) -unpack(in::IO, s::Struct) = s.unpack(in, align_packed) -unpack{T}(in::IO, ::Type{T}, strategy::DataAlign) = Struct(T).unpack(in, strategy) -unpack{T}(in::IO, ::Type{T}) = Struct(T).unpack(in, align_packed) - -struct(s::Struct, items...) = s.struct(items...) - -sizeof(s::Struct) = calcsize(s.types) -sizeof(s::Struct, strategy::DataAlign) = calcsize(pad(s, strategy)) - -# Convenience methods when you just want to use strings -macro withIOString(iostr, ex) - quote - $iostr = IOString() - $ex - $iostr - end -end -pack(s::Struct, strategy::DataAlign, arg) = @withIOString iostr pack(iostr, s, strategy, arg) -pack(s::Struct, strategy::DataAlign, args...) = @withIOString iostr pack(iostr, s, strategy, args...) -pack(composite, strategy) = @withIOString iostr pack(iostr, composite, strategy) -pack(s::Struct, arg) = @withIOString iostr pack(iostr, s, arg) -pack(s::Struct, args...) = @withIOString iostr pack(iostr, s, args...) -pack(composite) = @withIOString iostr pack(iostr, composite) - -unpack(str::String, s::Struct) = unpack(IOString(str), s) -unpack(str::String, ctyp) = unpack(IOString(str), ctyp) - -## Alignment strategies and utility functions ## - -# default alignment for bitstype T is nextpow2(sizeof(::Type{T})) -# TODO: figure out why this can't be done with multiple dispatch -function type_alignment_default(typ) - if typ <: AbstractArray - typ = eltype(typ) - end - nextpow2(sizeof(typ)) -end - -# default strategy -align_default = DataAlign(type_alignment_default, x -> max(map(type_alignment_default, x))) - -# equivalent to __attribute__ (( __packed__ )) -align_packed = DataAlign(_ -> 1, _ -> 1) - -# equivalent to #pragma pack(n) -align_packmax(da::DataAlign, n::Integer) = DataAlign( - da.ttable, - _ -> min(type_alignment_default(_), n), - da.aggregate, - ) - -# equivalent to __attribute__ (( align(n) )) -align_structpack(da::DataAlign, n::Integer) = DataAlign( - da.ttable, - da.default, - _ -> n, - ) - -# is there a more efficient way to do this? -function merge(a::Dict, b::Dict) - c = Dict() - for (k, v) in a - c[k] = v - end - for (k, v) in b - c[k] = v - end - c -end - -# provide an alignment table -align_table(da::DataAlign, ttable::Dict) = DataAlign( - merge(da.ttable, ttable), - da.default, - da.aggregate, - ) - -# convenience forms using a default alignment -for fun in (:align_packmax, :align_structpack, :align_table) - @eval ($fun)(arg) = ($fun)(align_default, arg) -end - -# Specific architectures -align_x86_pc_linux_gnu = align_table(align_default, - [ - Int64 => 4, - Uint64 => 4, - Float64 => 4, - ]) - -# Get alignment for a given type -function alignment_for(strategy::DataAlign, typ::Type) - if has(strategy.ttable, typ) - strategy.ttable[typ] - elseif isa(typ, CompositeKind) - strategy.aggregate(map(x->x[1], Struct(typ).types)) - else - strategy.default(typ) - end -end -function alignment_for(strategy::DataAlign, s::Struct) - if has(strategy.ttable, s.struct) - strategy.ttable[s.struct] - else - strategy.aggregate(map(x->x[1], s.types)) - end -end - -function pad_next(offset, typ, strategy::DataAlign) - align_to = alignment_for(strategy, typ) - (align_to - offset % align_to) % align_to -end - -function pad(s::Struct, strategy::DataAlign) - offset = 0 - newtypes = {} - for (typ, dims) in s.types - fix = pad_next(offset, typ, strategy) - if fix > 0 - push(newtypes, (PadByte, fix)) - offset += fix - end - push(newtypes, (typ, dims)) - offset += sizeof(typ) * prod(dims) - end - fix = pad_next(offset, s, strategy) - if fix > 0 - push(newtypes, (PadByte, fix)) - end - newtypes -end - -function show_struct_layout(s::Struct, strategy::DataAlign, width, bytesize) - offset = 0 - for (typ, dims) in pad(s, strategy) - for i in 1:prod(dims) - tstr = string(typ) - tstr = tstr[1:min(sizeof(typ)*bytesize-2, length(tstr))] - str = @sprintf("[%s%s]", tstr, "-"^(bytesize*sizeof(typ)-2-length(tstr))) - typsize = sizeof(typ) - while !isempty(str) - if offset % width == 0 - @printf("0x%04X ", offset) - end - len_prn = min(width - (offset % width), typsize) - nprint = bytesize*len_prn - print(str[1:nprint]) - str = str[nprint+1:end] - typsize -= len_prn - offset += len_prn - if offset % width == 0 - println() - end - end - end - end - if offset % width != 0 - println() - end -end -show_struct_layout(s::Struct, strategy::DataAlign) = show_struct_layout(s, strategy, 8, 10) -show_struct_layout(s::Struct, strategy::DataAlign, width) = show_struct_layout(s, strategy, width, 10) - -## Native layout ## -const libLLVM = dlopen("libLLVM-3.1") -const LLVMAlign = dlsym(libLLVM, :LLVMPreferredAlignmentOfType) -macro llvmalign(tsym) - quote - int(ccall(LLVMAlign, Uint, (Ptr, Ptr), tgtdata, - ccall(dlsym(libLLVM, $tsym), Ptr, ()))) - end -end - -align_native = align_table(align_default, let - tgtdata = ccall(dlsym(libLLVM, :LLVMCreateTargetData), Ptr, (String,), "") - - int8align = @llvmalign :LLVMInt8Type - int16align = @llvmalign :LLVMInt16Type - int32align = @llvmalign :LLVMInt32Type - int64align = @llvmalign :LLVMInt64Type - float32align = @llvmalign :LLVMFloatType - float64align = @llvmalign :LLVMDoubleType - - ccall(dlsym(libLLVM, :LLVMDisposeTargetData), Void, (Ptr,), tgtdata) - - [ - Int8 => int8align, - Uint8 => int8align, - Int16 => int16align, - Uint16 => int16align, - Int32 => int32align, - Uint32 => int32align, - Int64 => int64align, - Uint64 => int64align, - Float32 => float32align, - Float64 => float64align, - ] -end) diff --git a/extras/suitesparse.jl b/extras/suitesparse.jl deleted file mode 100644 index 98b6410e889ae..0000000000000 --- a/extras/suitesparse.jl +++ /dev/null @@ -1,765 +0,0 @@ -module SuiteSparse - -import Base.SparseMatrixCSC, Base.size, Base.nnz, Base.eltype, Base.show, Base.triu, Base.norm, Base.solve, Base.(\), Base.ctranspose, Base.transpose - -export # types - CholmodPtr, - CholmodCommon, - CholmodSparse, - CholmodFactor, - CholmodDense, - CholmodSparseOut, - UmfpackPtr, - UmfpackLU, - UmfpackLU!, - UmfpackLUTrans, - # methods - chm_aat, # drop prefix? - eltype, #? maybe not - indtype, #? maybe not - nnz, - show, - size, - solve, - \, - At_ldiv_B, - Ac_ldiv_B - -require("suitesparse_h") - -const libsuitesparse_wrapper = dlopen("libsuitesparse_wrapper") -const libcholmod = dlopen("libcholmod") -const libumfpack = dlopen("libumfpack") -try - global const libspqr = dlopen("libspqr") -catch err - # XXX:can be removed when suitesparse > 4.0.2 - println(E" -Oops, Suitesparse needs to be rebuilt. Try running: - - $ touch deps/SuiteSparse-4.0.2/Makefile - $ make -") - throw(err) -end -const _chm_aat = dlsym(libcholmod, :cholmod_aat) -const _chm_amd = dlsym(libcholmod, :cholmod_amd) -const _chm_analyze = dlsym(libcholmod, :cholmod_analyze) -const _chm_colamd = dlsym(libcholmod, :cholmod_colamd) -const _chm_copy = dlsym(libcholmod, :cholmod_copy) -const _chm_factorize = dlsym(libcholmod, :cholmod_factorize) -const _chm_free_dn = dlsym(libcholmod, :cholmod_free_dense) -const _chm_free_fa = dlsym(libcholmod, :cholmod_free_factor) -const _chm_free_sp = dlsym(libcholmod, :cholmod_free_sparse) -const _chm_print_dn = dlsym(libcholmod, :cholmod_print_dense) -const _chm_print_fa = dlsym(libcholmod, :cholmod_print_factor) -const _chm_print_sp = dlsym(libcholmod, :cholmod_print_sparse) -const _chm_solve = dlsym(libcholmod, :cholmod_solve) -const _chm_sort = dlsym(libcholmod, :cholmod_sort) -const _chm_submatrix = dlsym(libcholmod, :cholmod_submatrix) - -const _spqr_C_QR = dlsym(libspqr, :SuiteSparseQR_C_QR) -const _spqr_C_backslash = dlsym(libspqr, :SuiteSparseQR_C_backslash) -const _spqr_C_backslash_default = dlsym(libspqr, :SuiteSparseQR_C_backslash_default) -const _spqr_C_backslash_sparse = dlsym(libspqr, :SuiteSparseQR_C_backslash_sparse) -const _spqr_C_factorize = dlsym(libspqr, :SuiteSparseQR_C_factorize) -const _spqr_C_symbolic = dlsym(libspqr, :SuiteSparseQR_C_symbolic) -const _spqr_C_numeric = dlsym(libspqr, :SuiteSparseQR_C_numeric) -const _spqr_C_free = dlsym(libspqr, :SuiteSparseQR_C_free) -const _spqr_C_solve = dlsym(libspqr, :SuiteSparseQR_C_solve) -const _spqr_C_qmult = dlsym(libspqr, :SuiteSparseQR_C_qmult) - -type MatrixIllConditionedException <: Exception end - -function _jl_convert_to_0_based_indexing!(S::SparseMatrixCSC) - for i=1:(S.colptr[end]-1); S.rowval[i] -= 1; end - for i=1:length(S.colptr); S.colptr[i] -= 1; end - return S -end - -function _jl_convert_to_1_based_indexing!(S::SparseMatrixCSC) - for i=1:length(S.colptr); S.colptr[i] += 1; end - for i=1:(S.colptr[end]-1); S.rowval[i] += 1; end - return S -end - -_jl_convert_to_0_based_indexing(S) = _jl_convert_to_0_based_indexing!(copy(S)) -_jl_convert_to_1_based_indexing(S) = _jl_convert_to_1_based_indexing!(copy(S)) - -## CHOLMOD - -typealias CHMVTypes Union(Complex64, Complex128, Float32, Float64) -typealias CHMITypes Union(Int32, Int64) - -function chm_itype{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}) - if !(Ti<:CHMITypes) error("chm_itype: indtype(S) must be in CHMITypes") end - Ti == Int32 ? _jl_CHOLMOD_INT : _jl_CHOLMOD_LONG -end - -function chm_xtype{T}(S::SparseMatrixCSC{T}) - if !(T<:CHMVTypes) error("chm_xtype: eltype(S) must be in CHMVTypes") end - T <: Complex ? _JL_CHOLMOD_COMPLEX : _jl_CHOLMOD_REAL -end - -function chm_dtype{T}(S::SparseMatrixCSC{T}) - if !(T<:CHMVTypes) error("chm_dtype: eltype(S) must be in CHMVTypes") end - T <: Union(Float32, Complex64) ? _jl_CHOLMOD_SINGLE : _jl_CHOLMOD_DOUBLE -end - -# Wrapper for memory allocated by CHOLMOD. Carry along the value and index types. -## FIXME: CholmodPtr and UmfpackPtr should be amalgamated -type CholmodPtr{Tv<:CHMVTypes,Ti<:CHMITypes} - val::Vector{Ptr{Void}} -end - -eltype{Tv,Ti}(P::CholmodPtr{Tv,Ti}) = Tv -indtype{Tv,Ti}(P::CholmodPtr{Tv,Ti}) = Ti - -function _jl_cholmod_common_finalizer(x::Vector{Ptr{Void}}) - st = ccall(dlsym(libcholmod, :cholmod_finish), Int32, (Ptr{Void},), x[1]) - if st != _jl_CHOLMOD_TRUE error("Error calling cholmod_finish") end - c_free(x[1]) -end - -type CholmodCommon - pt::Vector{Ptr{Void}} - function CholmodCommon() - pt = Array(Ptr{Void}, 1) - ccall(dlsym(libsuitesparse_wrapper, :jl_cholmod_common), Void, - (Ptr{Void},), pt) - st = ccall(dlsym(libcholmod, :cholmod_start), Int, (Ptr{Void}, ), pt[1]) - if st != _jl_CHOLMOD_TRUE error("Error calling cholmod_start") end - finalizer(pt, _jl_cholmod_common_finalizer) - new(pt) - end -end - -function show(io, cm::CholmodCommon) - st = ccall(dlsym(libcholmod, :cholmod_print_common), Int32, - (Ptr{Uint8},Ptr{Void}), "", cm.pt[1]) - if st != _jl_CHOLMOD_TRUE error("Error calling cholmod_print_common") end -end - -type CholmodSparse{Tv<:CHMVTypes,Ti<:CHMITypes} - pt::CholmodPtr{Tv,Ti} - ## cp contains a copy of the original matrix but with 0-based indices - cp::SparseMatrixCSC{Tv,Ti} - stype::Int - cm::CholmodCommon - function CholmodSparse(S::SparseMatrixCSC{Tv,Ti}, stype::Int, cm::CholmodCommon) - pt = CholmodPtr{Tv,Ti}(Array(Ptr{Void}, 1)) - cp = _jl_convert_to_0_based_indexing(S) - - ccall(dlsym(libsuitesparse_wrapper, :jl_cholmod_sparse), Void, - (Ptr{Void}, Uint, Uint, Uint, Ptr{Void}, Ptr{Void}, Ptr{Void}, - Ptr{Void}, Ptr{Void}, Int32, Int32, Int32, Int32, Int32, Int32), - pt.val, S.m, S.n, nnz(S), cp.colptr, cp.rowval, C_NULL, - cp.nzval, C_NULL, stype, chm_itype(S), chm_xtype(S), chm_dtype(S), - _jl_CHOLMOD_TRUE, _jl_CHOLMOD_TRUE) - finalizer(pt, x->c_free(x.val[1])) - new(pt, cp, int(stype), cm) - end -end - -CholmodSparse{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}, stype::Int) = CholmodSparse{Tv,Ti}(S, stype, CholmodCommon()) - -function CholmodSparse{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}, cm::CholmodCommon) - stype = S.m == S.n && ishermitian(m) - CholmodSparse{Tv,Ti}(stype ? triu(S) : S, int(stype), cm) -end - -CholmodSparse(S::SparseMatrixCSC) = CholmodSparse(S, CholmodCommon()) - -function show(io, cs::CholmodSparse) - ccall(_chm_print_sp, - Int32, (Ptr{Void}, Ptr{Uint8},Ptr{Void}), cs.pt.val[1], "", cs.cm.pt[1]) -end - -size(cs::CholmodSparse) = size(cs.cp) -nnz(cs::CholmodSparse) = cs.cp.colptr[end] -eltype{T}(cs::CholmodSparse{T}) = T -indtype{Tv,Ti}(cs::CholmodSparse{Tv,Ti}) = Ti - -SparseMatrixCSC(cs::CholmodSparse) = _jl_convert_to_1_based_indexing(cs.cp) - -## For testing only. The infinity and 1 norms of a sparse matrix are simply -## the same norm applied to its nzval field. -function norm(cs::CholmodSparse, p::Number) - ccall(dlsym(libcholmod, :cholmod_norm_sparse), Float64, - (Ptr{Void}, Int32, Ptr{Void}), cs.pt.val[1], p == Inf ? 0 : 1, cs.cm.pt[1]) -end - -norm(cs::CholmodSparse) = norm(cs, Inf) - -## Approximate minimal degree ordering -function chm_amd(cs::CholmodSparse) - aa = Array(Int32, cs.cp.m) - st = cs.stype == 0 ? ccall(_chm_colamd, Int32, - (Ptr{Void}, Ptr{Void}, Uint, Int32, Ptr{Int32}, Ptr{Void}), - cs.pt.val[1], C_NULL, 0, 1, aa, cs.cm.pt[1]) : - ccall(_chm_amd, Int32, (Ptr{Void}, Ptr{Void}, Uint, Ptr{Int32}, Ptr{Void}), - cs.pt.val[1], C_NULL, 0, aa, cs.cm.pt[1]) - if st != _jl_CHOLMOD_TRUE error("Error in cholmod_amd") end - aa -end - -type CholmodFactor{Tv<:CHMVTypes,Ti<:CHMITypes} <: Factorization{Tv} - pt::CholmodPtr{Tv,Ti} - cs::CholmodSparse{Tv,Ti} - function CholmodFactor(pt::CholmodPtr{Tv,Ti}, cs::CholmodSparse{Tv,Ti}) - ff = new(pt, cs) - finalizer(ff, _jl_cholmod_factor_finalizer) - ff - end -end - -function _jl_cholmod_factor_finalizer(x::CholmodFactor) - if ccall(_chm_free_fa, Int32, (Ptr{Void}, Ptr{Void}), x.pt.val, x.cs.cm[1]) != _jl_CHOLMOD_TRUE - error("CHOLMOD error in cholmod_free_factor") - end -end - -function size(F::CholmodFactor) - n = size(F.cs,1) - (n, n) -end - -eltype{T}(F::CholmodFactor{T}) = T -indtype{Tv,Ti}(F::CholmodFactor{Tv,Ti}) = Ti - -function CholmodFactor{Tv,Ti}(cs::CholmodSparse{Tv,Ti}) - pt = CholmodPtr{Tv,Ti}(Array(Ptr{Void}, 1)) - pt.val[1] = ccall(_chm_analyze, Ptr{Void}, - (Ptr{Void}, Ptr{Void}), cs.pt.val[1], cs.cm.pt[1]) - st = ccall(_chm_factorize, Int32, - (Ptr{Void}, Ptr{Void}, Ptr{Void}), cs.pt.val[1], pt.val[1], cs.cm.pt[1]) - if st != _jl_CHOLMOD_TRUE error("CHOLMOD failure in factorize") end - CholmodFactor{Tv,Ti}(pt, cs) -end - -function show(io, cf::CholmodFactor) - st = ccall(_chm_print_fa, Int32, (Ptr{Void}, Ptr{Uint8}, Ptr{Void}), cf.pt.val[1], "", cf.cs.cm.pt[1]) - if st != _jl_CHOLMOD_TRUE error("Cholmod error in print_factor") end -end - -type CholmodDense{T<:CHMVTypes} - pt::Vector{Ptr{Void}} - m::Int - n::Int - aa::VecOrMat{T} # original array - cm::CholmodCommon -end - -function CholmodDense{T<:CHMVTypes}(b::VecOrMat{T}, cm::CholmodCommon) - m = size(b, 1) - n = isa(b, Matrix) ? size(b, 2) : 1 - - xtype = T <: Complex ? _jl_CHOLMOD_COMPLEX : _jl_CHOLMOD_REAL - dtype = T <: Float32 || T == Complex64 ? _jl_CHOLMOD_SINGLE : _jl_CHOLMOD_DOUBLE - - pt = Array(Ptr{Void}, 1) - - ccall(dlsym(libsuitesparse_wrapper, :jl_cholmod_dense), Void, - (Ptr{Void}, Uint, Uint, Uint, Uint, Ptr{Void}, Ptr{Void}, Int32, Int32), - pt, m, n, length(b), m, b, C_NULL, xtype, dtype) - finalizer(pt, x->c_free(pt[1])) - CholmodDense{T}(pt, m, n, copy(b), cm) -end - -CholmodDense{T<:Integer}(B::VecOrMat{T}, cm::CholmodCommon) = CholmodDense(float64(B), cm) - -size(cd::CholmodDense) = (cd.m, cd.n) - -function show(io, cd::CholmodDense) - st = ccall(_chm_print_dn, Int32, (Ptr{Void},Ptr{Uint8},Ptr{Void}), cd.pt[1], "", cd.cm.pt[1]) - if st != _jl_CHOLMOD_TRUE error("Cholmod error in print_dense") end -end - -type CholmodDenseOut{Tv<:CHMVTypes,Ti<:CHMITypes} - pt::CholmodPtr{Tv,Ti} - m::Int - n::Int - cm::CholmodCommon - function CholmodDenseOut(pt::CholmodPtr{Tv,Ti}, m::Int, n::Int, cm::CholmodCommon) - dd = new(pt, m, n, cm) - finalizer(dd, _jl_cholmod_denseout_finalizer) - dd - end -end - -function _jl_cholmod_denseout_finalizer(cd::CholmodDenseOut) - st = ccall(_chm_free_dn, Int32, (Ptr{Void}, Ptr{Void}), cd.pt.val, cd.cm.pt[1]) - if st != _jl_CHOLMOD_TRUE error("Error in cholmod_free_dense") end -end - -eltype{T}(cdo::CholmodDenseOut{T}) = T -indtype{Tv,Ti}(cdo::CholmodDenseOut{Tv,Ti}) = Ti -size(cd::CholmodDenseOut) = (cd.m, cd.n) - -function convert{T}(::Type{Array{T}}, cdo::CholmodDenseOut{T}) - mm = Array(T, size(cdo)) - ccall(dlsym(libsuitesparse_wrapper, :jl_cholmod_dense_copy_out), Void, - (Ptr{Void}, Ptr{T}), cdo.pt.val[1], mm) - mm -end - -function solve{Tv,Ti}(cf::CholmodFactor{Tv,Ti}, B::CholmodDense{Tv}, solv::Integer) - m, n = size(B) - cdo = CholmodPtr{Tv,Ti}(Array(Ptr{Void},1)) - cdo.val[1] = ccall(_chm_solve, Ptr{Void}, - (Int32, Ptr{Void}, Ptr{Void}, Ptr{Void}), - solv, cf.pt.val[1], B.pt[1], cf.cs.cm.pt[1]) - return cdo, m, n, cf.cs.cm - CholmodDenseOut(cdo, m, n, cf.cs.cm) -end - -solve(cf::CholmodFactor, B::CholmodDense) = solve(cf, B, _jl_CHOLMOD_A) - -(\){Tf,Tb}(cf::CholmodFactor{Tf}, b::VecOrMat{Tb}) = solve(cf, CholmodDense{Tf}(convert(Array{Tf},b), cf.cs.cm), _jl_CHOLMOD_A) - -type CholmodSparseOut{Tv<:CHMVTypes,Ti<:CHMITypes} - pt::CholmodPtr{Tv,Ti} - m::Int - n::Int - cm::CholmodCommon - function CholmodSparseOut(pt::CholmodPtr{Tv,Ti}, m::Int, n::Int, cm::CholmodCommon) - cso = new(pt, m, n, cm) - finalizer(cso, _jl_cholmod_sparseout_finalizer) - cso - end -end - -function _jl_cholmod_sparseout_finalizer(cso::CholmodSparseOut) - st = ccall(_chm_free_sp, Int32, - (Ptr{Void}, Ptr{Void}), cso.pt.val, cso.cm.pt[1]) - if st != _jl_CHOLMOD_TRUE error("Error in cholmod_free_sparse") end -end - -function nnz(cso::CholmodSparseOut) - ccall(dlsym(libcholmod, :cholmod_nnz), Int32, - (Ptr{Void}, Ptr{Void}), cso.pt.val[1], cso.cm.pt[1]) -end -size(cso::CholmodSparseOut) = (cso.m, cso.n) -eltype{T}(cso::CholmodSparseOut{T}) = T -indtype{Tv,Ti}(cso::CholmodSparseOut{Tv,Ti}) = Ti - -function solve{Tv,Ti}(cf::CholmodFactor{Tv,Ti}, B::CholmodSparse{Tv,Ti}, solv::Integer) - m, n = size(B) - cso = CholmodPtr{Tv,Ti}(Array(Ptr{Void},1)) - cso.val[1] = ccall(dlsym(libcholmod, :cholmod_spsolve), Ptr{Void}, - (Int32, Ptr{Void}, Ptr{Void}, Ptr{Void}), - solv, cf.pt.val[1], B.pt[1], B.cm.pt[1]) - CholmodSparseOut{Tv,Ti}(cso, m, n, cf.cs.cm) -end - -function CholmodSparseOut{Tv,Ti}(cf::CholmodFactor{Tv,Ti}) - n = size(cf.cs)[1] - cso = CholmodPtr{Tv,Ti}(Array(Ptr{Void},1)) - cso.val[1] = ccall(dlsym(libcholmod, :cholmod_factor_to_sparse), Ptr{Void}, - (Ptr{Void}, Ptr{Void}), cf.pt.val[1], cf.cs.cm.pt[1]) - CholmodSparseOut{Tv,Ti}(cso, n, n, cf.cs.cm) -end - -function SparseMatrixCSC{Tv,Ti}(cso::CholmodSparseOut{Tv,Ti}) - nz = nnz(cso) - sp = SparseMatrixCSC{Tv,Ti}(cso.m, cso.n, Array(Ti, cso.n + 1), Array(Ti, nz), Array(Tv, nz)) - st = ccall(dlsym(libsuitesparse_wrapper, :jl_cholmod_sparse_copy_out), Int32, - (Ptr{Void}, Ptr{Ti}, Ptr{Ti}, Ptr{Tv}), - cso.pt.val[1], sp.colptr, sp.rowval, sp.nzval) - if st == 1 error("CholmodSparseOut object is not packed") end - if st == 2 error("CholmodSparseOut object is not sorted") end # Should not occur - if st == 3 error("CholmodSparseOut object has INTLONG itype") end - _jl_convert_to_1_based_indexing!(sp) -end - -function show(io, cso::CholmodSparseOut) - sp = ccall(_chm_print_sp, Int32, (Ptr{Void}, Ptr{Uint8},Ptr{Void}), cso.pt.val[1], "", cso.cm.pt[1]) - if sp != _jl_CHOLMOD_TRUE error("Cholmod error in print_sparse") end -end - -function chm_aat{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, symm::Bool) - cs = CholmodSparse(A, 0) - aa = CholmodPtr{Tv,Ti}(Array(Ptr{Void},1)) - aa.val[1] = ccall(_chm_aat, Ptr{Void}, (Ptr{Void},Ptr{Int},Int32,Int32,Ptr{Void}), - cs.pt.val[1], C_NULL, 0, 1, cs.cm.pt[1]) - if ccall(_chm_sort, Int32, (Ptr{Void}, Ptr{Void}), aa.val[1], cs.cm.pt[1]) != _jl_CHOLMOD_TRUE - error("Cholmod error in sort") - end - if symm - pt = ccall(_chm_copy, Ptr{Void}, (Ptr{Void}, Int32, Int32, Ptr{Void}), - aa.val[1], 1, 1, cs.cm.pt[1]) - if ccall(_chm_free_sp, Int32, (Ptr{Void}, Ptr{Void}), aa.val, cs.cm.pt[1]) != _jl_CHOLMOD_TRUE - error("Cholmod error in free_sparse") - end - aa.val[1] = pt - end - m = size(A, 1) - CholmodSparseOut{Tv,Ti}(aa, m, m, cs.cm) -end - -chm_aat{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}) = chm_aat(A, false) - -## call wrapper function to create cholmod_sparse objects -_jl_cholmod_sparse(S) = _jl_cholmod_sparse(S, 0) - -function _jl_cholmod_sparse{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}, stype::Int) - cs = Array(Ptr{Void}, 1) - - if Ti == Int32; itype = _jl_CHOLMOD_INT; - elseif Ti == Int64; itype = _jl_CHOLMOD_LONG; end - - if Tv == Float64 || Tv == Float32; xtype = _jl_CHOLMOD_REAL; - elseif Tv == Complex128 || Tv == Complex64 ; xtype = _jl_CHOLMOD_COMPLEX; end - - if Tv == Float64 || Tv == Complex128; dtype = _jl_CHOLMOD_DOUBLE; - elseif Tv == Float32 || Tv == Complex64 ; dtype = _jl_CHOLMOD_SINGLE; end - - ccall(dlsym(libsuitesparse_wrapper, :jl_cholmod_sparse), - Ptr{Void}, - (Ptr{Void}, Int, Int, Int, Ptr{Void}, Ptr{Void}, Ptr{Void}, Ptr{Void}, Ptr{Void}, - Int32, Int32, Int32, Int32, Int32, Int32), - cs, int(S.m), int(S.n), int(length(S.nzval)), S.colptr, S.rowval, C_NULL, S.nzval, C_NULL, - int32(stype), itype, xtype, dtype, _jl_CHOLMOD_TRUE, _jl_CHOLMOD_TRUE - ) - - return cs -end - -## Call wrapper function to create cholmod_dense objects -function _jl_cholmod_dense{T}(B::VecOrMat{T}) - m = size(B, 1) - n = isa(B, Matrix) ? size(B, 2) : 1 - - cd = Array(Ptr{Void}, 1) - - if T == Float64 || T == Float32; xtype = _jl_CHOLMOD_REAL; - elseif T == Complex128 || T == Complex64 ; xtype = _jl_CHOLMOD_COMPLEX; end - - if T == Float64 || T == Complex128; dtype = _jl_CHOLMOD_DOUBLE; - elseif T == Float32 || T == Complex64 ; dtype = _jl_CHOLMOD_SINGLE; end - - ccall(dlsym(libsuitesparse_wrapper, :jl_cholmod_dense), - Ptr{Void}, - (Ptr{Void}, Int, Int, Int, Int, Ptr{T}, Ptr{Void}, Int32, Int32), - cd, m, n, numel(B), m, B, C_NULL, xtype, dtype - ) - - return cd -end - -function _jl_cholmod_dense_copy_out{T}(x::Ptr{Void}, sol::VecOrMat{T}) - ccall(dlsym(libsuitesparse_wrapper, :jl_cholmod_dense_copy_out), - Void, - (Ptr{Void}, Ptr{T}), - x, sol - ) - return sol -end - -function _jl_cholmod_transpose_unsym{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}, cm::Array{Ptr{Void}, 1}) - S_t = SparseMatrixCSC(Tv, S.n, S.m, nnz(S)+1) - - # Allocate space for a cholmod_sparse object - cs = _jl_cholmod_sparse(S) - cs_t = _jl_cholmod_sparse(S_t) - - status = ccall(dlsym(libcholmod, :cholmod_transpose_unsym), - Int32, - (Ptr{Void}, Int32, Ptr{Int32}, Ptr{Int32}, Int32, Ptr{Void}, Ptr{Void}), - cs[1], int32(1), C_NULL, C_NULL, int32(-1), cs_t[1], cm[1]); - - # Deallocate space for cholmod_sparse objects - c_free(cs[1]) - c_free(cs_t[1]) - - return S_t -end - -function _jl_cholmod_analyze{Tv<:Union(Float64,Complex128), Ti<:CHMITypes}(cs::Array{Ptr{Void},1}, cm::Array{Ptr{Void},1}) - ccall(_chm_analyze, Ptr{Void}, (Ptr{Void}, Ptr{Void}), cs[1], cm[1]) -end - -function _jl_cholmod_factorize{Tv<:Union(Float64,Complex128), Ti<:CHMITypes}(cs::Array{Ptr{Void},1}, cs_factor::Ptr{Void}, cm::Array{Ptr{Void},1}) - st = ccall(_chm_factorize, Int32, (Ptr{Void}, Ptr{Void}, Ptr{Void}), cs[1], cs_factor, cm[1]) - if st != _jl_CHOLMOD_TRUE error("CHOLMOD could not factorize the matrix") end -end - -function _jl_cholmod_solve(cs_factor::Ptr{Void}, cd_rhs::Array{Ptr{Void},1}, cm::Array{Ptr{Void},1}) - ccall(_chm_solve, Ptr{Void}, (Int32, Ptr{Void}, Ptr{Void}, Ptr{Void}), - _jl_CHOLMOD_A, cs_factor, cd_rhs[1], cm[1]) -end - -## UMFPACK - -# Wrapper for memory allocated by umfpack. Carry along the value and index types. -type UmfpackPtr{Tv<:Union(Float64,Complex128),Ti<:CHMITypes} - val::Vector{Ptr{Void}} -end - -type UmfpackLU{Tv<:Union(Float64,Complex128),Ti<:CHMITypes} <: Factorization{Tv} - numeric::UmfpackPtr{Tv,Ti} - mat::SparseMatrixCSC{Tv,Ti} -end - -function show(io, f::UmfpackLU) - @printf("UMFPACK LU Factorization of a %d-by-%d sparse matrix\n", - size(f.mat,1), size(f.mat,2)) - println(f.numeric) - _jl_umfpack_report(f) -end - -type UmfpackLUTrans{Tv<:Union(Float64,Complex128),Ti<:CHMITypes} <: Factorization{Tv} - numeric::UmfpackPtr{Tv,Ti} - mat::SparseMatrixCSC{Tv,Ti} -end - -function show(io, f::UmfpackLUTrans) - @printf("UMFPACK LU Factorization of a transposed %d-by-%d sparse matrix\n", - size(f.mat,1), size(f.mat,2)) - println(f.numeric) - _jl_umfpack_report(f) -end - -function UmfpackLU{Tv<:Union(Float64,Complex128),Ti<:CHMITypes}(S::SparseMatrixCSC{Tv,Ti}) - Scopy = copy(S) - Scopy = _jl_convert_to_0_based_indexing!(Scopy) - numeric = [] - - try - symbolic = _jl_umfpack_symbolic(Scopy) - numeric = _jl_umfpack_numeric(Scopy, symbolic) - catch e - if is(e,MatrixIllConditionedException) - error("Input matrix is ill conditioned or singular"); - else - error("Error calling UMFPACK") - end - end - - return UmfpackLU(numeric,Scopy) -end - -function UmfpackLU!{Tv<:Union(Float64,Complex128),Ti<:CHMITypes}(S::SparseMatrixCSC{Tv,Ti}) - Sshallow = SparseMatrixCSC(S.m,S.n,S.colptr,S.rowval,S.nzval) - Sshallow = _jl_convert_to_0_based_indexing!(Sshallow) - numeric = [] - - try - symbolic = _jl_umfpack_symbolic(Sshallow) - numeric = _jl_umfpack_numeric(Sshallow, symbolic) - catch e - Sshallow = _jl_convert_to_1_based_indexing!(Sshallow) - if is(e,MatrixIllConditionedException) - error("Input matrix is ill conditioned or singular"); - else - error("Error calling UMFPACK") - end - end - - S.rowval = [] - S.nzval = [] - S.colptr = ones(S.n+1) - - return UmfpackLU(numeric,Sshallow) -end - -function UmfpackLUTrans(S::SparseMatrixCSC) - x = UmfpackLU(S) - return UmfpackLUTrans(x.numeric, x.mat) -end - -# Solve with Factorization - -(\){T}(fact::UmfpackLU{T}, b::Vector) = fact \ convert(Array{T,1}, b) -(\){T}(fact::UmfpackLU{T}, b::Vector{T}) = _jl_umfpack_solve(fact.mat,b,fact.numeric) - -(\){T}(fact::UmfpackLUTrans{T}, b::Vector) = fact \ convert(Array{T,1}, b) -(\){T}(fact::UmfpackLUTrans{T}, b::Vector{T}) = _jl_umfpack_transpose_solve(fact.mat,b,fact.numeric) - -ctranspose(fact::UmfpackLU) = UmfpackLUTrans(fact.numeric, fact.mat) - -# Solve directly with matrix - -(\)(S::SparseMatrixCSC, b::Vector) = UmfpackLU(S) \ b -At_ldiv_B(S::SparseMatrixCSC, b::Vector) = UmfpackLUTrans(S) \ b -Ac_ldiv_B(S::SparseMatrixCSC, b::Vector) = UmfpackLUTrans(S) \ b - -## Wrappers around UMFPACK routines - -for (f_sym_r, f_sym_c, inttype) in - (("umfpack_di_symbolic","umfpack_zi_symbolic",:Int32), - ("umfpack_dl_symbolic","umfpack_zl_symbolic",:Int64)) - @eval begin - - function _jl_umfpack_symbolic{Tv<:Float64,Ti<:$inttype}(S::SparseMatrixCSC{Tv,Ti}) - # Pointer to store the symbolic factorization returned by UMFPACK - Symbolic = UmfpackPtr{Tv,Ti}(Array(Ptr{Void},1)) - status = ccall(dlsym(libumfpack, $f_sym_r), - Ti, - (Ti, Ti, - Ptr{Ti}, Ptr{Ti}, Ptr{Float64}, Ptr{Void}, Ptr{Float64}, Ptr{Float64}), - S.m, S.n, - S.colptr, S.rowval, S.nzval, Symbolic.val, C_NULL, C_NULL) - if status != _jl_UMFPACK_OK; error("Error in symbolic factorization"); end - finalizer(Symbolic,_jl_umfpack_free_symbolic) - return Symbolic - end - - function _jl_umfpack_symbolic{Tv<:Complex128,Ti<:$inttype}(S::SparseMatrixCSC{Tv,Ti}) - # Pointer to store the symbolic factorization returned by UMFPACK - Symbolic = UmfpackPtr{Tv,Ti}(Array(Ptr{Void},1)) - status = ccall(dlsym(libumfpack, $f_sym_c), - Ti, - (Ti, Ti, - Ptr{Ti}, Ptr{Ti}, Ptr{Float64}, Ptr{Float64}, Ptr{Void}, - Ptr{Float64}, Ptr{Float64}), - S.m, S.n, - S.colptr, S.rowval, real(S.nzval), imag(S.nzval), Symbolic.val, - C_NULL, C_NULL) - if status != _jl_UMFPACK_OK; error("Error in symbolic factorization"); end - finalizer(Symbolic,_jl_umfpack_free_symbolic) # Check: do we need to free if there was an error? - return Symbolic - end - - end -end - -for (f_num_r, f_num_c, inttype) in - (("umfpack_di_numeric","umfpack_zi_numeric",:Int32), - ("umfpack_dl_numeric","umfpack_zl_numeric",:Int64)) - @eval begin - - function _jl_umfpack_numeric{Tv<:Float64,Ti<:$inttype}(S::SparseMatrixCSC{Tv,Ti}, Symbolic) - # Pointer to store the numeric factorization returned by UMFPACK - Numeric = UmfpackPtr{Tv,Ti}(Array(Ptr{Void},1)) - status = ccall(dlsym(libumfpack, $f_num_r), - Ti, - (Ptr{Ti}, Ptr{Ti}, Ptr{Float64}, Ptr{Void}, Ptr{Void}, - Ptr{Float64}, Ptr{Float64}), - S.colptr, S.rowval, S.nzval, Symbolic.val[1], Numeric.val, - C_NULL, C_NULL) - if status > 0; throw(MatrixIllConditionedException); end - if status != _jl_UMFPACK_OK; error("Error in numeric factorization"); end - finalizer(Numeric,_jl_umfpack_free_numeric) - return Numeric - end - - function _jl_umfpack_numeric{Tv<:Complex128,Ti<:$inttype}(S::SparseMatrixCSC{Tv,Ti}, Symbolic) - # Pointer to store the numeric factorization returned by UMFPACK - Numeric = UmfpackPtr{Tv,Ti}(Array(Ptr{Void},1)) - status = ccall(dlsym(libumfpack, $f_num_c), - Ti, - (Ptr{Ti}, Ptr{Ti}, Ptr{Float64}, Ptr{Float64}, Ptr{Void}, Ptr{Void}, - Ptr{Float64}, Ptr{Float64}), - S.colptr, S.rowval, real(S.nzval), imag(S.nzval), Symbolic.val[1], Numeric.val, - C_NULL, C_NULL) - if status > 0; throw(MatrixIllConditionedException); end - if status != _jl_UMFPACK_OK; error("Error in numeric factorization"); end - finalizer(Numeric,_jl_umfpack_free_numeric) - return Numeric - end - - end -end - -for (f_sol_r, f_sol_c, inttype) in - (("umfpack_di_solve","umfpack_zi_solve",:Int32), - ("umfpack_dl_solve","umfpack_zl_solve",:Int64)) - @eval begin - - function _jl_umfpack_solve{Tv<:Float64,Ti<:$inttype}(S::SparseMatrixCSC{Tv,Ti}, - b::Vector{Tv}, Numeric::UmfpackPtr{Tv,Ti}) - x = similar(b) - status = ccall(dlsym(libumfpack, $f_sol_r), - Ti, - (Ti, Ptr{Ti}, Ptr{Ti}, Ptr{Float64}, - Ptr{Float64}, Ptr{Float64}, Ptr{Void}, Ptr{Float64}, Ptr{Float64}), - _jl_UMFPACK_A, S.colptr, S.rowval, S.nzval, - x, b, Numeric.val[1], C_NULL, C_NULL) - if status != _jl_UMFPACK_OK; error("Error in solve"); end - return x - end - - function _jl_umfpack_solve{Tv<:Complex128,Ti<:$inttype}(S::SparseMatrixCSC{Tv,Ti}, - b::Vector{Tv}, Numeric::UmfpackPtr{Tv,Ti}) - xr = similar(b, Float64) - xi = similar(b, Float64) - status = ccall(dlsym(libumfpack, $f_sol_c), - Ti, - (Ti, Ptr{Ti}, Ptr{Ti}, Ptr{Float64}, Ptr{Float64}, Ptr{Float64}, Ptr{Float64}, - Ptr{Float64}, Ptr{Float64}, Ptr{Void}, Ptr{Float64}, Ptr{Float64}), - _jl_UMFPACK_A, S.colptr, S.rowval, real(S.nzval), imag(S.nzval), - xr, xi, real(b), imag(b), Numeric.val[1], C_NULL, C_NULL) - if status != _jl_UMFPACK_OK; error("Error in solve"); end - return complex(xr,xi) - end - - function _jl_umfpack_transpose_solve{Tv<:Float64,Ti<:$inttype}(S::SparseMatrixCSC{Tv,Ti}, - b::Vector{Tv}, Numeric::UmfpackPtr{Tv,Ti}) - x = similar(b) - status = ccall(dlsym(libumfpack, $f_sol_r), - Ti, - (Ti, Ptr{Ti}, Ptr{Ti}, Ptr{Float64}, - Ptr{Float64}, Ptr{Float64}, Ptr{Void}, Ptr{Float64}, Ptr{Float64}), - _jl_UMFPACK_At, S.colptr, S.rowval, S.nzval, - x, b, Numeric.val[1], C_NULL, C_NULL) - if status != _jl_UMFPACK_OK; error("Error in solve"); end - return x - end - - function _jl_umfpack_transpose_solve{Tv<:Complex128,Ti<:$inttype}(S::SparseMatrixCSC{Tv,Ti}, - b::Vector{Tv}, Numeric::UmfpackPtr{Tv,Ti}) - xr = similar(b, Float64) - xi = similar(b, Float64) - status = ccall(dlsym(libumfpack, $f_sol_c), - Ti, - (Ti, Ptr{Ti}, Ptr{Ti}, Ptr{Float64}, Ptr{Float64}, Ptr{Float64}, Ptr{Float64}, - Ptr{Float64}, Ptr{Float64}, Ptr{Void}, Ptr{Float64}, Ptr{Float64}), - _jl_UMFPACK_At, S.colptr, S.rowval, real(S.nzval), imag(S.nzval), - xr, xi, real(b), imag(b), Numeric.val[1], C_NULL, C_NULL) - if status != _jl_UMFPACK_OK; error("Error in solve"); end - return complex(xr,xi) - end - - end -end - -for (f_report, elty, inttype) in - (("umfpack_di_report_numeric", :Float64, :Int32), - ("umfpack_zi_report_numeric", :Complex128, :Int32), - ("umfpack_dl_report_numeric", :Float64, :Int64), - ("umfpack_zl_report_numeric", :Complex128, :Int64)) - @eval begin - - function _jl_umfpack_report{Tv<:$elty,Ti<:$inttype}(slu::UmfpackLU{Tv,Ti}) - - control = zeros(Float64, _jl_UMFPACK_CONTROL) - control[_jl_UMFPACK_PRL] = 4 - - ccall(dlsym(libumfpack, $f_report), - Ti, - (Ptr{Void}, Ptr{Float64}), - slu.numeric.val[1], control) - end - - end -end - - -for (f_symfree, f_numfree, elty, inttype) in - (("umfpack_di_free_symbolic","umfpack_di_free_numeric",:Float64,:Int32), - ("umfpack_zi_free_symbolic","umfpack_zi_free_numeric",:Complex128,:Int32), - ("umfpack_dl_free_symbolic","umfpack_dl_free_numeric",:Float64,:Int64), - ("umfpack_zl_free_symbolic","umfpack_zl_free_numeric",:Complex128,:Int64)) - @eval begin - - _jl_umfpack_free_symbolic{Tv<:$elty,Ti<:$inttype}(Symbolic::UmfpackPtr{Tv,Ti}) = - ccall(dlsym(libumfpack, $f_symfree), Void, (Ptr{Void},), Symbolic.val) - - _jl_umfpack_free_numeric{Tv<:$elty,Ti<:$inttype}(Numeric::UmfpackPtr{Tv,Ti}) = - ccall(dlsym(libumfpack, $f_numfree), Void, (Ptr{Void},), Numeric.val) - - end -end - -end #module diff --git a/extras/suitesparse_h.jl b/extras/suitesparse_h.jl deleted file mode 100644 index ce4f161d35e41..0000000000000 --- a/extras/suitesparse_h.jl +++ /dev/null @@ -1,135 +0,0 @@ -## CHOLMOD - -const _jl_CHOLMOD_TRUE = int32(1) -const _jl_CHOLMOD_FALSE = int32(0) - -# Types of systems to solve -const _jl_CHOLMOD_A = int32(0) # solve Ax=b -const _jl_CHOLMOD_LDLt = int32(1) # solve LDL'x=b -const _jl_CHOLMOD_LD = int32(2) # solve LDx=b -const _jl_CHOLMOD_DLt = int32(3) # solve DL'x=b -const _jl_CHOLMOD_L = int32(4) # solve Lx=b -const _jl_CHOLMOD_Lt = int32(5) # solve L'x=b -const _jl_CHOLMOD_D = int32(6) # solve Dx=b -const _jl_CHOLMOD_P = int32(7) # permute x=Px -const _jl_CHOLMOD_Pt = int32(8) # permute x=P'x - -# itype defines the types of integer used: -const _jl_CHOLMOD_INT = int32(0) # all integer arrays are int -const _jl_CHOLMOD_LONG = int32(2) # all integer arrays are UF_long - -# dtype defines what the numerical type is (double or float): -const _jl_CHOLMOD_DOUBLE = int32(0) # all numerical values are double -const _jl_CHOLMOD_SINGLE = int32(1) # all numerical values are float - -# xtype defines the kind of numerical values used: -const _jl_CHOLMOD_PATTERN = int32(0) # pattern only, no numerical values -const _jl_CHOLMOD_REAL = int32(1) # a real matrix -const _jl_CHOLMOD_COMPLEX = int32(2) # a complex matrix (ANSI C99 compatible) -const _jl_CHOLMOD_ZOMPLEX = int32(3) # a complex matrix (MATLAB compatible) - -# Definitions for cholmod_common: -const _jl_CHOLMOD_MAXMETHODS = int32(9) # maximum number of different methods that - # cholmod_analyze can try. Must be >= 9. - -# Common->status values. zero means success, negative means a fatal error, positive is a warning. -const _jl_CHOLMOD_OK = int32(0) # success -const _jl_CHOLMOD_NOT_INSTALLED = int32(-1) # failure: method not installed -const _jl_CHOLMOD_OUT_OF_MEMORY = int32(-2) # failure: out of memory -const _jl_CHOLMOD_TOO_LARGE = int32(-3) # failure: integer overflow occured -const _jl_CHOLMOD_INVALID = int32(-4) # failure: invalid input -const _jl_CHOLMOD_NOT_POSDEF = int32(1) # warning: matrix not pos. def. -const _jl_CHOLMOD_DSMALL = int32(2) # warning: D for LDL' or diag(L) or LL' has tiny absolute value - -# ordering method (also used for L->ordering) -const _jl_CHOLMOD_NATURAL = int32(0) # use natural ordering -const _jl_CHOLMOD_GIVEN = int32(1) # use given permutation -const _jl_CHOLMOD_AMD = int32(2) # use minimum degree (AMD) -const _jl_CHOLMOD_METIS = int32(3) # use METIS' nested dissection -const _jl_CHOLMOD_NESDIS = int32(4) # use _jl_CHOLMOD's version of nested dissection: - # node bisector applied recursively, followed - # by constrained minimum degree (CSYMAMD or CCOLAMD) -const _jl_CHOLMOD_COLAMD = int32(5) # use AMD for A, COLAMD for A*A' - -# POSTORDERED is not a method, but a result of natural ordering followed by a -# weighted postorder. It is used for L->ordering, not method [ ].ordering. -const _jl_CHOLMOD_POSTORDERED = int32(6) # natural ordering, postordered. - -# supernodal strategy (for Common->supernodal) -const _jl_CHOLMOD_SIMPLICIAL = int32(0) # always do simplicial -const _jl_CHOLMOD_AUTO = int32(1) # select simpl/super depending on matrix -const _jl_CHOLMOD_SUPERNODAL = int32(2) # always do supernodal - -## UMFPACK - -## Type of solve -const _jl_UMFPACK_A = 0 # Ax=b -const _jl_UMFPACK_At = 1 # A'x=b -const _jl_UMFPACK_Aat = 2 # A.'x=b -const _jl_UMFPACK_Pt_L = 3 # P'Lx=b -const _jl_UMFPACK_L = 4 # Lx=b -const _jl_UMFPACK_Lt_P = 5 # L'Px=b -const _jl_UMFPACK_Lat_P = 6 # L.'Px=b -const _jl_UMFPACK_Lt = 7 # L'x=b -const _jl_UMFPACK_Lat = 8 # L.'x=b -const _jl_UMFPACK_U_Qt = 9 # UQ'x=b -const _jl_UMFPACK_U = 10 # Ux=b -const _jl_UMFPACK_Q_Ut = 11 # QU'x=b -const _jl_UMFPACK_Q_Uat = 12 # QU.'x=b -const _jl_UMFPACK_Ut = 13 # U'x=b -const _jl_UMFPACK_Uat = 14 # U.'x=b - -## Sizes of Control and Info arrays for returning information from solver -const _jl_UMFPACK_INFO = 90 -const _jl_UMFPACK_CONTROL = 20 -const _jl_UMFPACK_PRL = 1 - -## Status codes -const _jl_UMFPACK_OK = 0 -const _jl_UMFPACK_WARNING_singular_matrix = 1 -const _jl_UMFPACK_WARNING_determinant_underflow = 2 -const _jl_UMFPACK_WARNING_determinant_overflow = 3 -const _jl_UMFPACK_ERROR_out_of_memory = -1 -const _jl_UMFPACK_ERROR_invalid_Numeric_object = -3 -const _jl_UMFPACK_ERROR_invalid_Symbolic_object = -4 -const _jl_UMFPACK_ERROR_argument_missing = -5 -const _jl_UMFPACK_ERROR_n_nonpositive = -6 -const _jl_UMFPACK_ERROR_invalid_matrix = -8 -const _jl_UMFPACK_ERROR_different_pattern = -11 -const _jl_UMFPACK_ERROR_invalid_system = -13 -const _jl_UMFPACK_ERROR_invalid_permutation = -15 -const _jl_UMFPACK_ERROR_internal_error = -911 -const _jl_UMFPACK_ERROR_file_IO = -17 -const _jl_UMFPACK_ERROR_ordering_failed = -18 - -## SuiteSparseQR - -## ordering options -const SPQR_ORDERING_FIXED = int32(0) -const SPQR_ORDERING_NATURAL = int32(1) -const SPQR_ORDERING_COLAMD = int32(2) -const SPQR_ORDERING_GIVEN = int32(3) # only used for C/C++ interface -const SPQR_ORDERING_CHOLMOD = int32(4) # CHOLMOD best-effort (COLAMD, METIS,...) -const SPQR_ORDERING_AMD = int32(5) # AMD(A'*A) -const SPQR_ORDERING_METIS = int32(6) # metis(A'*A) -const SPQR_ORDERING_DEFAULT = int32(7) # SuiteSparseQR default ordering -const SPQR_ORDERING_BEST = int32(8) # try COLAMD, AMD, and METIS; pick best -const SPQR_ORDERING_BESTAMD = int32(9) # try COLAMD and AMD; pick best - -# Let [m n] = size of the matrix after pruning singletons. The default -# ordering strategy is to use COLAMD if m <= 2*n. Otherwise, AMD(A'A) is -# tried. If there is a high fill-in with AMD then try METIS(A'A) and take -# the best of AMD and METIS. METIS is not tried if it isn't installed. - -## Operations in qmult -const SPQR_QTX = int32(0) # Y = Q'*X -const SPQR_QX = int32(1) # Y = Q*X -const SPQR_XQT = int32(2) # Y = X*Q' -const SPQR_XQ = int32(3) # Y = X*Q - -## Types of systems to solve -const SPQR_RX_EQUALS_B = int32(0) # solve R*X=B or X = R\B -const SPQR_RETX_EQUALS_B = int32(1) # solve R*E'*X=B or X = E*(R\B) -const SPQR_RTX_EQUALS_B = int32(2) # solve R'*X=B or X = R'\B -const SPQR_RTX_EQUALS_ETB = int32(3) # solve R'*X=E'*B or X = R'\(E'*B) - diff --git a/extras/test.jl b/extras/test.jl index bb61e559329cc..14219bb28cf6d 100644 --- a/extras/test.jl +++ b/extras/test.jl @@ -59,7 +59,7 @@ tests(filenames) = tests(filenames, test_printer_raw) function _tests_task(filenames) for fn = filenames - load(fn) + require(fn) end end @@ -70,16 +70,16 @@ function test_printer_raw(hdl::Task) print(".") else println("") - dump(stdout_stream, t) + dump(STDOUT, t) println("") end end println("") end -function dump(io::IOStream, t::TestResult) +function dump(io, t::TestResult) println(io, "In $(t.context) / $(t.group)") - println(io, strcat(t.expr_str, " ", t.succeed ? "succeeded" : "FAILED")) + println(io, string(t.expr_str, " ", t.succeed ? "succeeded" : "FAILED")) println(io, "$(t.operation) with args:") println(io, "1: $(t.arg1)\n2: $(t.arg2)\n3: $(t.arg3)") println(io, "Exception: $(t.exception_thrown)") @@ -88,10 +88,10 @@ end # things to set state function test_context(context::String) - tls(:context, context) + task_local_storage(:context, context) end function test_group(group::String) - tls(:group, group) + task_local_storage(:group, group) end @@ -99,21 +99,21 @@ end # that does the real work macro test(ex) quote - $(_test(expr(:quote, ex), true)) + $(_test(Expr(:quote, ex), true)) end end macro testfails(ex) quote - $(_test(expr(:quote, ex), false)) + $(_test(Expr(:quote, ex), false)) end end function _test(ex::Expr, expect_succeed::Bool) local tr = TestResult() try - tr.context = tls(:context) - tr.group = tls(:group) + tr.context = task_local_storage(:context) + tr.group = task_local_storage(:group) catch x # not running in a context -- oh well! end @@ -151,11 +151,9 @@ function _test(ex::Expr, expect_succeed::Bool) end end - # if we failed with an exception, handle throws_exception - if tr.exception_thrown != NoException() && ex.args[1] == :throws_exception - if isa(tr.exception_thrown, eval(ex.args[3])) # we got the right one - tr.succeed = true - end + # if we expected an exception, see if we got the right one + if ex.args[1] == :throws_exception + tr.succeed = isa(tr.exception_thrown, eval(ex.args[3])) # we got the right one end # if we're running takes_less_than, see how we did diff --git a/extras/time.jl b/extras/time.jl new file mode 100644 index 0000000000000..3d333c92e52d8 --- /dev/null +++ b/extras/time.jl @@ -0,0 +1,43 @@ +module Time +export TimeDelta + +import Base.show, Base.+, Base.-, Base.convert, Base.promote_rule + +type TimeDelta{p} + v::Int64 +end + +const PREFIXES = [ + "yocto", "zepto", "atto", "femto", "pico", "nano", "micro", "milli", + "", "kilo", "mega", "giga", "tera", "peta", "exa", "zetta", "yotta", +] +const ZERO_INDEX = 9 +const MAX_INDEX = 17 + +function show{p}(io::IO, x::TimeDelta{p}) + k = max(1,min(MAX_INDEX,fld(p,3)+ZERO_INDEX)) + r = p-3(k-ZERO_INDEX) + prefix = PREFIXES[k] + if r == 0 + s = x.v == 1 ? "" : "s" + print(io, "$(x.v) $(prefix)second$s") + elseif r > 0 + print(io, "$(x.v*10^r) $(prefix)seconds") + else + print(io, "$(x.v/10^-r) $(prefix)seconds") + end +end + +convert{p,q}(::Type{TimeDelta{p}}, x::TimeDelta{q}) = + TimeDelta{p}(p <= q ? x.v*10^(q-p) : div(x.v,10^(p-q))) + +promote_rule{p,q}(::Type{TimeDelta{p}}, ::Type{TimeDelta{q}}) = TimeDelta{min(p,q)} + +-{p}(x::TimeDelta{p}) = TimeDelta{p}(-x.v) ++{p}(x::TimeDelta{p}, y::TimeDelta{p}) = TimeDelta{p}(x.v+y.v) +-{p}(x::TimeDelta{p}, y::TimeDelta{p}) = TimeDelta{p}(x.v-y.v) + ++(x::TimeDelta, y::TimeDelta) = +(promote(x,y)...) +-(x::TimeDelta, y::TimeDelta) = -(promote(x,y)...) + +end # module diff --git a/extras/units.jl b/extras/units.jl deleted file mode 100644 index e8ed39eaa67d3..0000000000000 --- a/extras/units.jl +++ /dev/null @@ -1,367 +0,0 @@ -# Support for physical units: I/O and conversion -# Timothy E. Holy, 2012 - -abstract SIPrefix -type Yocto <: SIPrefix end -type Zepto <: SIPrefix end -type Atto <: SIPrefix end -type Femto <: SIPrefix end -type Pico <: SIPrefix end -type Nano <: SIPrefix end -type Micro <: SIPrefix end -type Milli <: SIPrefix end -type Centi <: SIPrefix end -type Deci <: SIPrefix end -type SINone <: SIPrefix end -type Deca <: SIPrefix end -type Hecto <: SIPrefix end -type Kilo <: SIPrefix end -type Mega <: SIPrefix end -type Giga <: SIPrefix end -type Tera <: SIPrefix end -type Peta <: SIPrefix end -type Exa <: SIPrefix end -type Zetta <: SIPrefix end -type Yotta <: SIPrefix end - -# PrettyShow and PrettyString -pshow(x) = pshow(OUTPUT_STREAM::IOStream, x) -function pstring(x) - s = memio(0, false) - pshow(s, x) - takebuf_string(s) -end -# LatexShow and LatexString -lshow(x) = lshow(OUTPUT_STREAM::IOStream, x) -function lstring(x) - s = memio(0, false) - lshow(s, x) - takebuf_string(s) -end -# FullShow and FullString -fshow(x) = fshow(OUTPUT_STREAM::IOStream, x) -function fstring(x) - s = memio(0, false) - fshow(s, x) - takebuf_string(s) -end - -let -# Prefix ToSINone Show PrettyShow LatexShow Full -const prefix_table = { - (Yocto, 1e-24, "y", "y", "y", "yocto") - (Zepto, 1e-21, "z", "z", "z", "zepto") - (Atto, 1e-18, "a", "a", "a", "atto") - (Femto, 1e-15, "f", "f", "f", "femto") - (Pico, 1e-12, "p", "p", "p", "pico") - (Nano, 1e-9, "n", "n", "n", "nano") - (Micro, 1e-6, "u", "\u03bc", L"$\mu$", "micro") - (Milli, 1e-3, "m", "m", "m", "milli") - (Centi, 1e-2, "c", "c", "c", "centi") - (Deci, 1e-1, "d", "d", "d", "deci") - (Deca, 1e1, "da", "da", "da", "deca") - (Hecto, 1e2, "h", "h", "h", "hecto") - (Kilo, 1e3, "k", "k", "k", "kilo") - (Mega, 1e6, "M", "M", "M", "mega") - (Giga, 1e9, "G", "G", "G", "giga") - (Tera, 1e12, "T", "T", "T", "tera") - (Peta, 1e15, "P", "P", "P", "peta") - (Exa, 1e18, "E", "E", "E", "exa") - (Zetta, 1e21, "Z", "Z", "Z", "zetta") - (Yotta, 1e24, "Y", "Y", "Y", "yotta") -} -global to_reference -global show -global pshow -global lshow -global _unit_si_prefixes -for (t, f, s, ps, ls, fs) in prefix_table - @eval to_reference(::Type{$t}) = $f - @eval show(io, ::Type{$t}) = print(io, $s) - @eval pshow(io, ::Type{$t}) = print(io, $ps) - @eval lshow(io, ::Type{$t}) = print(io, $ls) - @eval fshow(io, ::Type{$t}) = print(io, $fs) -end -function return_prefix(i::Int) - if i <= length(prefix_table) - return prefix_table[i][1] - elseif i == length(prefix_table)+1 - return SINone - else - error("Something is wrong") - end -end -_unit_si_prefixes = ntuple(length(prefix_table)+1, i->return_prefix(i)) -end # let -to_reference(::Type{SINone}) = 1 -show(io, ::Type{SINone}) = nothing -pshow(io, ::Type{SINone}) = nothing -lshow(io, ::Type{SINone}) = nothing -fshow(io, ::Type{SINone}) = nothing - -# Units -abstract UnitBase -type Unit{TP<:SIPrefix, TU<:UnitBase} end -Unit{TP<:SIPrefix, TU<:UnitBase}(tp::Type{TP}, tu::Type{TU}) = Unit{tp, tu} -Unit{TU<:UnitBase}(tu::Type{TU}) = Unit{SINone, tu} -function show{TP<:SIPrefix, TU<:UnitBase}(io, tu::Unit{TP, TU}) - print(io, TP) - print(io, TU) -end - -# Values with units -type Quantity{TP<:SIPrefix, TU<:UnitBase, Tdata} - value::Tdata -end -Quantity{TP<:SIPrefix, TU<:UnitBase, Tdata}(tp::Type{TP}, tu::Type{TU}, val::Tdata) = Quantity{tp, tu, Tdata}(val) -Quantity{TU<:UnitBase, Tdata}(tu::Type{TU}, val::Tdata) = Quantity{SINone, tu, Tdata}(val) -prefix{TP<:SIPrefix, TU<:UnitBase, Tdata}(q::Quantity{TP, TU, Tdata}) = TP -base{TP<:SIPrefix, TU<:UnitBase, Tdata}(q::Quantity{TP, TU, Tdata}) = TU - -function show{TP<:SIPrefix, TU<:UnitBase}(io, q::Quantity{TP, TU}) - print(io, q.value, " ") - show(io, TP) - show(io, TU) -end -function pshow{TP<:SIPrefix, TU<:UnitBase}(io, q::Quantity{TP, TU}) - print(io, q.value, " ") - pshow(io, TP) - pshow(io, TU) -end -function lshow{TP<:SIPrefix, TU<:UnitBase}(io, q::Quantity{TP, TU}) - print(io, q.value, " ") - lshow(io, TP) - lshow(io, TU) -end -function fshow{TP<:SIPrefix, TU<:UnitBase}(io, q::Quantity{TP, TU}) - print(io, q.value, " ") - fshow(io, TP) - fshow(io, TU) -end - -# Functions and dictionaries for parsing -_unit_string_dict = (String=>Tuple)[] - -function _unit_gen_func_multiplicative(table) - for (t, r, to_r, s, ps, ls, fs) in table - @eval reference(::Type{$t}) = $r - @eval to_reference(::Type{$t}) = x->x*$to_r - @eval from_reference(::Type{$t}) = x->x/$to_r - @eval show(io, ::Type{$t}) = print(io, $s) - @eval pshow(io, ::Type{$t}) = print(io, $ps) - @eval lshow(io, ::Type{$t}) = print(io, $ls) - @eval fshow(io, ::Type{$t}) = print(io, $fs) - end -end - -function _unit_gen_func(table) - for (t, r, to_func, from_func, s, ps, ls, fs) in table - @eval reference(::Type{$t}) = $r - @eval to_reference(::Type{$t}) = $to_func - @eval from_reference(::Type{$t}) = $from_func - @eval show(io, ::Type{$t}) = print(io, $s) - @eval pshow(io, ::Type{$t}) = print(io, $ps) - @eval lshow(io, ::Type{$t}) = print(io, $ls) - @eval fshow(io, ::Type{$t}) = print(io, $fs) - end -end - - -function _unit_gen_dict_with_prefix(table) - for (u, rest) in table - ustr = string(u) - upstr = pstring(u) - for p in _unit_si_prefixes - pstr = string(p) - key = pstr*ustr -# println(key, ": ", p, ", ", u) - _unit_string_dict[key] = (p, u) - # Add "pretty" variants, too - ppstr = pstring(p) - _unit_string_dict[pstr*upstr] = (p, u) - _unit_string_dict[ppstr*ustr] = (p, u) - _unit_string_dict[ppstr*upstr] = (p, u) - end - end -end - -function _unit_gen_dict(table) - for (u, rest) in table - key = string(u) -# println(key, ": ", u) - _unit_string_dict[key] = (SINone, u) - upstr = pstring(u) - if key != upstr - _unit_string_dict[upstr] = (SINone, u) - end - end -end - -# Unknown unit -type Unknown <: UnitBase end - -# Length units -type Meter <: UnitBase end -type Angstrom <: UnitBase end -type Inch <: UnitBase end -type Foot <: UnitBase end -type Yard <: UnitBase end -type Mile <: UnitBase end -type LightYear <: UnitBase end -type Parsec <: UnitBase end -type AstronomicalUnit <: UnitBase end -let - # Unit RefUnit ToRef show pshow lshow fshow -const utable = { - (Meter, Meter, 1, "m", "m", "m", "meter") - (Angstrom, Meter, 1e-10, "A", "\u212b",L"$\AA$","angstrom") - (Inch, Meter, 25.4/1000, "in", "in", "in", "inch") - (Foot, Meter, 12*25.4/1000, "ft", "ft", "ft", "foot") - (Yard, Meter, 36*25.4/1000, "yd", "yd", "yd", "yard") - (Mile, Meter, 5280*12*25.4/1000,"mi", "mi", "mi", "mile") - (LightYear,Meter, 9.4605284e15, "ly", "ly", "ly", "lightyear") - (Parsec, Meter, 3.08568025e16, "pc", "pc", "pc", "parsec") - (AstronomicalUnit, Meter, 149_597_870_700, "AU", "AU", "AU", "astronomical unit") -} -_unit_gen_func_multiplicative(utable) -_unit_gen_dict_with_prefix({utable[1]}) # parse prefixes only for Meter -_unit_gen_dict(utable[2:end]) -end - -# Time units -type Second <: UnitBase end -type Minute <: UnitBase end -type Hour <: UnitBase end -type Day <: UnitBase end -type Week <: UnitBase end -type YearJulian <: UnitBase end -type PlanckTime <: UnitBase end -let - # Unit RefUnit ToRef show pshow lshow fshow -const utable = { - (Second, Second, 1, "s", "s", "s", "second") - (Minute, Second, 60, "min", "min", "min", "minute") - (Hour, Second, 3600, "hr", "hr", "hr", "hour") - (Day, Second, 86400, "d", "d", "d", "day") - (YearJulian, Second, 365.25*86400, "yr", "yr", "yr", "year") - (PlanckTime, Second, 5.3910632e-44, "tP", "tP", L"$t_P$","Planck time") -} -_unit_gen_func_multiplicative(utable) -_unit_gen_dict_with_prefix({utable[1]}) # prefixes are only common for seconds -_unit_gen_dict(utable[2:end]) -end - -# Rate units -type Herz <: UnitBase end -let - # Unit RefUnit ToRef show pshow lshow fshow -const utable = { - (Herz, Herz, 1, "Hz", "Hz", "Hz", "Herz") -} -_unit_gen_func_multiplicative(utable) -_unit_gen_dict_with_prefix(utable) -end - -# Mass units -# (note English units like pounds are technically weight, not mass) -type Gram <: UnitBase end -type AtomicMassUnit <: UnitBase end -type Dalton <: UnitBase end -type PlanckMass <: UnitBase end -let - # Unit RefUnit ToRef show pshow lshow fshow -const utable = { - (Gram, Gram, 1, "g", "g", "g", "gram") - (AtomicMassUnit, Gram, 1.66053892173e-24, "amu","amu", "amu", "atomic mass unit") - (Dalton, Gram, 1.66053892173e-24, "Da", "Da", "Da", "Dalton") - (PlanckMass, Gram, 2.1765113e-5, "mP", "mP", L"$m_P$","Planck mass") -} -_unit_gen_func_multiplicative(utable) -_unit_gen_dict_with_prefix({utable[1]}) -_unit_gen_dict(utable[2:end]) -end - -# Electric current units -type Ampere <: UnitBase end -let - # Unit RefUnit ToRef show pshow lshow fshow -const utable = { - (Ampere, Ampere, 1, "A", "A", "A", "ampere") -} -_unit_gen_func_multiplicative(utable) -_unit_gen_dict_with_prefix(utable) -end - - -# Temperature units -# The conversions for these are not just a product -type Kelvin <: UnitBase end -type Celsius <: UnitBase end -type Fahrenheit <: UnitBase end -let - # Unit RefUnit ToRef FromRef show pshow lshow fshow -const utable = { - (Kelvin, Kelvin, x->x, x->x, "K", "K", "K", "Kelvin") - (Celsius, Kelvin, x->x+273.15, x->x-273.15,"C", "C", "C", "Celsius") - (Fahrenheit, Kelvin, x->(x+459.67)*5/9, x->x*9/5-459.67,"F","F", "F", "Fahrenheit") -} -_unit_gen_func(utable) -_unit_gen_dict_with_prefix({utable[1]}) # prefixes are only common for Kelvin -_unit_gen_dict(utable[2:end]) -end - -# Luminosity units -type Candela <: UnitBase end -let - # Unit RefUnit ToRef show pshow lshow fshow -const utable = { - (Candela, Candela, 1, "cd", "cd", "cd", "candela") -} -_unit_gen_func_multiplicative(utable) -_unit_gen_dict_with_prefix(utable) -end - - -# Amount units -type Mole <: UnitBase end -type Entities <: UnitBase end -let - # Unit RefUnit ToRef show pshow lshow fshow -const utable = { - (Mole, Mole, 1, "mol", "mol", "mol", "mole") - (Entities, Mole, 1/6.0221417930e23, "", "", "", "entities") -} -_unit_gen_func_multiplicative(utable) -_unit_gen_dict_with_prefix({utable[1]}) -end - - -# Parsing string to extract Quantity -function parse_quantity(s::String, strict::Bool) - # Find the last character of the numeric component - m = match(r"[0-9\.\+-](?![0-9\.\+-])", s) - if m == nothing - error("String does not have a 'value unit' structure") - end - val = float64(s[1:m.offset]) - ustr = strip(s[m.offset+1:end]) - if isempty(ustr) - if strict - error("String does not have a 'value unit' structure") - else - return Quantity(SINone, Unknown, val) - end - end - (prefix, unit) = _unit_string_dict[ustr] - return Quantity(prefix, unit, val) -end -parse_quantity(s::String) = parse_quantity(s, true) - - -# Conversion between units -function convert{Uin<:UnitBase, Uout<:UnitBase, Pin<:SIPrefix, Pout<:SIPrefix, T}(::Type{Unit{Pout, Uout}}, q::Quantity{Pin, Uin, T}) - if reference(Uin) != reference(Uout) - error("Not convertable") - end - return Quantity(Pout, Uout, from_reference(Uout)(to_reference(Uin)(q.value*to_reference(Pin))) / to_reference(Pout)) -end diff --git a/extras/zlib.jl b/extras/zlib.jl index aa90d343b816a..056ab7f99c2f0 100644 --- a/extras/zlib.jl +++ b/extras/zlib.jl @@ -43,12 +43,12 @@ export # Z_BIG_BUFSIZE, # ZFileOffset -load("zlib_h") +include("zlib_h.jl") # zlib functions # Returns the maximum size of the compressed output buffer for a given uncompressed input size -compress_bound(input_size::Uint) = ccall(dlsym(_zlib, :compressBound), Uint, (Uint, ), input_size) +compress_bound(input_size::Uint) = ccall((:compressBound, _zlib), Uint, (Uint, ), input_size) compress_bound(input_size::Integer) = compress_bound(convert(Uint, input_size)) # Compress @@ -57,7 +57,7 @@ function compress(source::Array{Uint8}, level::Int32) nb = compress_to_buffer(source, dest, level) # Shrink the buffer to the actual compressed size - return grow(dest, nb-length(dest)) + return resize!(dest, nb) end compress(source::Array{Uint8}, level::Integer) = compress(source, int32(level)) compress(source::Array{Uint8}) = compress(source, Z_DEFAULT_COMPRESSION) @@ -72,7 +72,7 @@ function compress_to_buffer(source::Array{Uint8}, dest::Array{Uint8}, level::Int dest_buf_size = Uint[length(dest)] # Compress the input - ret = ccall(dlsym(_zlib, :compress2), Int32, (Ptr{Uint8}, Ptr{Uint}, Ptr{Uint}, Uint, Int32), + ret = ccall((:compress2, _zlib), Int32, (Ptr{Uint8}, Ptr{Uint}, Ptr{Uint}, Uint, Int32), dest, dest_buf_size, source, length(source), int32(level)) if ret != Z_OK @@ -108,12 +108,12 @@ function uncompress(source::Array{Uint8}, uncompressed_size::Int) # Z_BUF_ERROR: resize buf, try again # Note: resizing by powers of 2 seems to be more efficient at allocating memory uncompressed_size = nextpow2(uncompressed_size*2) - grow(dest, uncompressed_size-length(dest)) + resize!(dest, uncompressed_size) end end # Shrink the buffer to the actual uncompressed size - return grow(dest, sz-length(dest)) + return resize!(dest, sz) end uncompress(source::Array{Uint8}) = uncompress(source, nextpow2(length(source)<<1)) @@ -127,7 +127,7 @@ function uncompress_to_buffer(source::Array{Uint8}, dest::Array{Uint8}) dest_buf_size = Uint[uncompressed_size] # Uncompress the input - ret = ccall(dlsym(_zlib, :uncompress), Int32, (Ptr{Uint}, Ptr{Uint}, Ptr{Uint}, Uint), + ret = ccall((:uncompress, _zlib), Int32, (Ptr{Uint}, Ptr{Uint}, Ptr{Uint}, Uint), dest, dest_buf_size, source, length(source)) if ret != Z_OK diff --git a/extras/zlib_h.jl b/extras/zlib_h.jl index a31efe5e981e5..557c374e1c17b 100644 --- a/extras/zlib_h.jl +++ b/extras/zlib_h.jl @@ -1,10 +1,10 @@ # general zlib constants, definitions -_zlib = dlopen("libz") +const _zlib = "libz" # Constants -zlib_version = bytestring(ccall(dlsym(_zlib, :zlibVersion), Ptr{Uint8}, ())) +zlib_version = bytestring(ccall((:zlibVersion, _zlib), Ptr{Uint8}, ())) ZLIB_VERSION = tuple([int(c) for c in split(zlib_version, '.')]...) # Flush values @@ -29,7 +29,7 @@ const Z_VERSION_ERROR = int32(-6) # Zlib errors as Exceptions -zerror(e::Integer) = bytestring(ccall(dlsym(_zlib, :zError), Ptr{Uint8}, (Int32,), e)) +zerror(e::Integer) = bytestring(ccall((:zError, _zlib), Ptr{Uint8}, (Int32,), e)) type ZError <: Exception err::Int32 err_str::String @@ -76,13 +76,17 @@ const SEEK_CUR = int32(1) # 64-bit functions are not available # Get compile-time option flags -zlib_compile_flags = ccall(dlsym(_zlib, :zlibCompileFlags), Uint, ()) - -z_off_t_sz = 2 << ((zlib_compile_flags >> 6) & uint(3)) -if z_off_t_sz == sizeof(FileOffset) || (sizeof(FileOffset) == 8 && dlsym_e(_zlib, :crc32_combine64) != C_NULL) - typealias ZFileOffset FileOffset -elseif z_off_t_sz == 4 # 64-bit functions not available - typealias ZFileOffset Int32 -else - error("Can't figure out what to do with ZFileOffset. sizeof(z_off_t) = ", z_off_t_sz) +zlib_compile_flags = ccall((:zlibCompileFlags, _zlib), Uint, ()) + +let _zlib_h = dlopen("libz") + global ZFileOffset + + z_off_t_sz = 2 << ((zlib_compile_flags >> 6) & uint(3)) + if z_off_t_sz == sizeof(FileOffset) || (sizeof(FileOffset) == 8 && dlsym_e(_zlib_h, :gzopen64) != C_NULL) + typealias ZFileOffset FileOffset + elseif z_off_t_sz == 4 # 64-bit functions not available + typealias ZFileOffset Int32 + else + error("Can't figure out what to do with ZFileOffset. sizeof(z_off_t) = ", z_off_t_sz) + end end diff --git a/src/Makefile b/src/Makefile index d8a352f98c0d0..76ece6ed9f721 100644 --- a/src/Makefile +++ b/src/Makefile @@ -6,7 +6,7 @@ override CXXFLAGS += $(JCXXFLAGS) SRCS = \ jltypes gf ast builtins module codegen interpreter \ - alloc dlload sys init task array dump toplevel + alloc dlload sys init task array dump toplevel jl_uv jlapi FLAGS = \ -D_GNU_SOURCE \ @@ -15,7 +15,7 @@ FLAGS = \ -I$(shell $(LLVM_CONFIG) --includedir) \ -I$(JULIAHOME)/deps/libuv/include -I$(JULIAHOME)/usr/include -LIBS = $(shell $(LLVM_CONFIG) --libfiles) $(WHOLE_ARCHIVE) $(JULIAHOME)/src/flisp/libflisp.a $(WHOLE_ARCHIVE) $(JULIAHOME)/src/support/libsupport.a -L$(USR)/lib $(USR)/$(JL_LIBDIR)/libuv.a $(OSLIBS) -lpthread $(shell $(LLVM_CONFIG) --ldflags) +LIBS = $(WHOLE_ARCHIVE) $(JULIAHOME)/src/flisp/libflisp.a $(WHOLE_ARCHIVE) $(JULIAHOME)/src/support/libsupport.a -L$(BUILD)/lib $(BUILD)/lib/libuv.a $(shell $(LLVM_CONFIG) --libs) $(NO_WHOLE_ARCHIVE) $(shell $(LLVM_CONFIG) --ldflags) $(OSLIBS) ifneq ($(MAKECMDGOALS),debug) TARGET = @@ -43,22 +43,22 @@ release debug: %: libjulia-% HEADERS = julia.h $(wildcard support/*.h) $(JULIAHOME)/deps/libuv/include/uv.h %.o: %.c $(HEADERS) - $(QUIET_CC) $(CC) $(CFLAGS) $(SHIPFLAGS) -c $< -o $@ + $(QUIET_CC) $(CC) $(CPPFLAGS) $(CFLAGS) $(SHIPFLAGS) -c $< -o $@ %.do: %.c $(HEADERS) - $(QUIET_CC) $(CC) $(CFLAGS) $(DEBUGFLAGS) -c $< -o $@ + $(QUIET_CC) $(CC) $(CPPFLAGS) $(CFLAGS) $(DEBUGFLAGS) -c $< -o $@ %.o: %.cpp $(HEADERS) - $(QUIET_CC) $(CXX) $(CXXFLAGS) $(SHIPFLAGS) $(shell $(LLVM_CONFIG) --cppflags) -c $< -o $@ + $(QUIET_CC) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(SHIPFLAGS) $(shell $(LLVM_CONFIG) --cppflags) -c $< -o $@ %.do: %.cpp $(HEADERS) - $(QUIET_CC) $(CXX) $(CXXFLAGS) $(DEBUGFLAGS) $(shell $(LLVM_CONFIG) --cppflags) -c $< -o $@ + $(QUIET_CC) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(DEBUGFLAGS) $(shell $(LLVM_CONFIG) --cppflags) -c $< -o $@ ast.o ast.do: julia_flisp.boot.inc flisp/*.h julia_flisp.boot.inc: julia_flisp.boot flisp/libflisp.a - $(QUIET_FLISP) flisp/flisp ./bin2hex.scm < $< > $@ + $(QUIET_FLISP) ./flisp/flisp ./bin2hex.scm < $< > $@ julia_flisp.boot: julia-parser.scm julia-syntax.scm \ match.scm utils.scm jlfrontend.scm mk_julia_flisp_boot.scm flisp/libflisp.a - $(QUIET_FLISP) flisp/flisp ./mk_julia_flisp_boot.scm + $(QUIET_FLISP) ./flisp/flisp ./mk_julia_flisp_boot.scm codegen.o codegen.do: intrinsics.cpp debuginfo.cpp cgutils.cpp ccall.cpp builtins.o builtins.do: table.c @@ -69,13 +69,13 @@ support/libsupport.a: support/*.h support/*.c flisp/libflisp.a: flisp/*.h flisp/*.c support/libsupport.a $(MAKE) -C flisp -$(USR)/$(JL_LIBDIR)/libjulia-debug.$(SHLIB_EXT): julia.expmap $(DOBJS) flisp/libflisp.a support/libsupport.a - $(QUIET_LINK) $(CXX) $(DEBUGFLAGS) $(DOBJS) -shared -o $@ $(LIBS) $(LDFLAGS) +$(BUILD)/$(JL_LIBDIR)/libjulia-debug.$(SHLIB_EXT): julia.expmap $(DOBJS) flisp/libflisp.a support/libsupport.a $(BUILD)/lib/libuv.a + $(QUIET_LINK) $(CXX) $(DEBUGFLAGS) $(DOBJS) $(RPATH_ORIGIN) -shared -o $@ $(LDFLAGS) $(LIBS) $(INSTALL_NAME_CMD)libjulia-debug.$(SHLIB_EXT) $@ libjulia-debug.a: julia.expmap $(DOBJS) flisp/libflisp.a support/libsupport.a rm -f $@ $(QUIET_LINK) ar -rcs $@ $(DOBJS) -libjulia-debug: $(USR)/$(JL_LIBDIR)/libjulia-debug.$(SHLIB_EXT) +libjulia-debug: $(BUILD)/$(JL_LIBDIR)/libjulia-debug.$(SHLIB_EXT) ifeq ($(SHLIB_EXT), so) SONAME = -Wl,-soname=libjulia-release.so @@ -83,25 +83,34 @@ else SONAME = endif -$(USR)/$(JL_LIBDIR)/libjulia-release.$(SHLIB_EXT): julia.expmap $(OBJS) flisp/libflisp.a support/libsupport.a - $(QUIET_LINK) $(CXX) $(SHIPFLAGS) $(OBJS) $(LIBS) -shared -o $@ $(LDFLAGS) $(SONAME) +$(BUILD)/$(JL_LIBDIR)/libjulia-release.$(SHLIB_EXT): julia.expmap $(OBJS) flisp/libflisp.a support/libsupport.a $(BUILD)/lib/libuv.a + $(QUIET_LINK) $(CXX) $(SHIPFLAGS) $(OBJS) $(RPATH_ORIGIN) -shared -o $@ $(LDFLAGS) $(LIBS) $(SONAME) $(INSTALL_NAME_CMD)libjulia-release.$(SHLIB_EXT) $@ libjulia-release.a: julia.expmap $(OBJS) flisp/libflisp.a support/libsupport.a rm -f $@ $(QUIET_LINK) ar -rcs $@ $(OBJS) -libjulia-release: $(USR)/$(JL_LIBDIR)/libjulia-release.$(SHLIB_EXT) +libjulia-release: $(BUILD)/$(JL_LIBDIR)/libjulia-release.$(SHLIB_EXT) clean: - rm -f $(USR)/$(JL_LIBDIR)/libjulia* - rm -f julia_flisp.boot julia_flisp.boot.inc - rm -f *.do *.o *~ *# *.$(SHLIB_EXT) *.a + -rm -f $(BUILD)/$(JL_LIBDIR)/libjulia* + -rm -f julia_flisp.boot julia_flisp.boot.inc + -rm -f *.do *.o *~ *# *.$(SHLIB_EXT) *.a h2j clean-flisp: - $(MAKE) -C flisp clean + -$(MAKE) -C flisp clean clean-support: - $(MAKE) -C support clean + -$(MAKE) -C support clean cleanall: clean clean-flisp clean-support .PHONY: debug release clean cleanall clean-* + + +h2j: h2j.cpp + $(QUIET_CC) $(CXX) $(CFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(DEBUGFLAGS) $(shell $(LLVM_CONFIG) --cppflags) $< -o $@ \ + -lclangFrontendTool -lclangBasic -lclangLex -lclangDriver -lclangFrontend -lclangParse \ + -lclangAST -lclangSema -lclangAnalysis -lclangEdit \ + -lclangRewrite -lclangSerialization -lclangStaticAnalyzerCheckers \ + -lclangStaticAnalyzerCore -lclangStaticAnalyzerFrontend -lclangTooling \ + -lclangCodeGen -lclangARCMigrate -lclang $(LIBS) $(LDFLAGS) diff --git a/src/alloc.c b/src/alloc.c index eb7b901981b21..7d0e3523c134d 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -12,44 +12,45 @@ jl_value_t *jl_true; jl_value_t *jl_false; -jl_tag_type_t *jl_undef_type; +jl_datatype_t *jl_undef_type; jl_tvar_t *jl_typetype_tvar; -jl_tag_type_t *jl_typetype_type; +jl_datatype_t *jl_typetype_type; jl_value_t *jl_ANY_flag; -jl_struct_type_t *jl_function_type; -jl_struct_type_t *jl_box_type; -jl_type_t *jl_box_any_type; +jl_datatype_t *jl_function_type; +jl_datatype_t *jl_box_type; +jl_value_t *jl_box_any_type; jl_typename_t *jl_box_typename; -jl_struct_type_t *jl_typector_type; +jl_datatype_t *jl_typector_type; -jl_struct_type_t *jl_array_type; +jl_datatype_t *jl_array_type; jl_typename_t *jl_array_typename; -jl_type_t *jl_array_uint8_type; -jl_type_t *jl_array_any_type; -jl_type_t *jl_array_symbol_type; +jl_value_t *jl_array_uint8_type; +jl_value_t *jl_array_any_type=NULL; +jl_value_t *jl_array_symbol_type; jl_function_t *jl_bottom_func; -jl_struct_type_t *jl_weakref_type; -jl_struct_type_t *jl_ascii_string_type; -jl_struct_type_t *jl_utf8_string_type; -jl_struct_type_t *jl_expr_type; -jl_struct_type_t *jl_symbolnode_type; -jl_struct_type_t *jl_getfieldnode_type; -jl_struct_type_t *jl_linenumbernode_type; -jl_struct_type_t *jl_labelnode_type; -jl_struct_type_t *jl_gotonode_type; -jl_struct_type_t *jl_quotenode_type; -jl_struct_type_t *jl_topnode_type; -jl_bits_type_t *jl_intrinsic_type; -jl_struct_type_t *jl_methtable_type; -jl_struct_type_t *jl_method_type; -jl_struct_type_t *jl_lambda_info_type; -jl_struct_type_t *jl_module_type; -jl_struct_type_t *jl_errorexception_type=NULL; -jl_struct_type_t *jl_typeerror_type; -jl_struct_type_t *jl_methoderror_type; -jl_struct_type_t *jl_loaderror_type; -jl_bits_type_t *jl_pointer_type; +jl_datatype_t *jl_weakref_type; +jl_datatype_t *jl_ascii_string_type; +jl_datatype_t *jl_utf8_string_type; +jl_datatype_t *jl_expr_type; +jl_datatype_t *jl_symbolnode_type; +jl_datatype_t *jl_getfieldnode_type; +jl_datatype_t *jl_linenumbernode_type; +jl_datatype_t *jl_labelnode_type; +jl_datatype_t *jl_gotonode_type; +jl_datatype_t *jl_quotenode_type; +jl_datatype_t *jl_topnode_type; +jl_datatype_t *jl_intrinsic_type; +jl_datatype_t *jl_methtable_type; +jl_datatype_t *jl_method_type; +jl_datatype_t *jl_lambda_info_type; +jl_datatype_t *jl_module_type; +jl_datatype_t *jl_errorexception_type=NULL; +jl_datatype_t *jl_typeerror_type; +jl_datatype_t *jl_methoderror_type; +jl_datatype_t *jl_loaderror_type; +jl_datatype_t *jl_pointer_type; +jl_datatype_t *jl_voidpointer_type; jl_value_t *jl_an_empty_cell=NULL; jl_value_t *jl_stackovf_exception; jl_value_t *jl_divbyzero_exception; @@ -76,20 +77,20 @@ jl_sym_t *null_sym; jl_sym_t *body_sym; jl_sym_t *macro_sym; jl_sym_t *method_sym; jl_sym_t *enter_sym; jl_sym_t *leave_sym; jl_sym_t *exc_sym; jl_sym_t *error_sym; -jl_sym_t *static_typeof_sym; +jl_sym_t *static_typeof_sym; jl_sym_t *kw_sym; jl_sym_t *new_sym; jl_sym_t *using_sym; jl_sym_t *const_sym; jl_sym_t *thunk_sym; jl_sym_t *anonymous_sym; jl_sym_t *underscore_sym; jl_sym_t *abstracttype_sym; jl_sym_t *bitstype_sym; jl_sym_t *compositetype_sym; jl_sym_t *type_goto_sym; -jl_sym_t *global_sym; +jl_sym_t *global_sym; jl_sym_t *tuple_sym; typedef struct { int64_t a; int64_t b; } bits128_t; -jl_value_t *jl_new_bits(jl_bits_type_t *bt, void *data) +jl_value_t *jl_new_bits(jl_datatype_t *bt, void *data) { if (bt == jl_uint8_type) return jl_box_uint8(*(uint8_t*)data); else if (bt == jl_int64_type) return jl_box_int64(*(int64_t*)data); @@ -97,40 +98,39 @@ jl_value_t *jl_new_bits(jl_bits_type_t *bt, void *data) else if (bt == jl_int32_type) return jl_box_int32(*(int32_t*)data); else if (bt == jl_float64_type) return jl_box_float64(*(double*)data); - size_t nb = jl_bitstype_nbits(bt)/8; + size_t nb = jl_datatype_size(bt); jl_value_t *v = (jl_value_t*)allocobj((NWORDS(LLT_ALIGN(nb,sizeof(void*)))+1)* sizeof(void*)); - v->type = (jl_type_t*)bt; + v->type = (jl_value_t*)bt; switch (nb) { - case 1: *(int8_t*) jl_bits_data(v) = *(int8_t*)data; break; - case 2: *(int16_t*) jl_bits_data(v) = *(int16_t*)data; break; - case 4: *(int32_t*) jl_bits_data(v) = *(int32_t*)data; break; - case 8: *(int64_t*) jl_bits_data(v) = *(int64_t*)data; break; - case 16: *(bits128_t*)jl_bits_data(v) = *(bits128_t*)data; break; - default: memcpy(jl_bits_data(v), data, nb); + case 1: *(int8_t*) jl_data_ptr(v) = *(int8_t*)data; break; + case 2: *(int16_t*) jl_data_ptr(v) = *(int16_t*)data; break; + case 4: *(int32_t*) jl_data_ptr(v) = *(int32_t*)data; break; + case 8: *(int64_t*) jl_data_ptr(v) = *(int64_t*)data; break; + case 16: *(bits128_t*)jl_data_ptr(v) = *(bits128_t*)data; break; + default: memcpy(jl_data_ptr(v), data, nb); } return v; } void jl_assign_bits(void *dest, jl_value_t *bits) { - size_t nb = jl_bitstype_nbits(jl_typeof(bits))/8; + size_t nb = jl_datatype_size(jl_typeof(bits)); switch (nb) { - case 1: *(int8_t*)dest = *(int8_t*)jl_bits_data(bits); break; - case 2: *(int16_t*)dest = *(int16_t*)jl_bits_data(bits); break; - case 4: *(int32_t*)dest = *(int32_t*)jl_bits_data(bits); break; - case 8: *(int64_t*)dest = *(int64_t*)jl_bits_data(bits); break; - case 16: *(bits128_t*)dest = *(bits128_t*)jl_bits_data(bits); break; - default: memcpy(dest, jl_bits_data(bits), nb); + case 1: *(int8_t*)dest = *(int8_t*)jl_data_ptr(bits); break; + case 2: *(int16_t*)dest = *(int16_t*)jl_data_ptr(bits); break; + case 4: *(int32_t*)dest = *(int32_t*)jl_data_ptr(bits); break; + case 8: *(int64_t*)dest = *(int64_t*)jl_data_ptr(bits); break; + case 16: *(bits128_t*)dest = *(bits128_t*)jl_data_ptr(bits); break; + default: memcpy(dest, jl_data_ptr(bits), nb); } } -int jl_field_index(jl_struct_type_t *t, jl_sym_t *fld, int err) +int jl_field_index(jl_datatype_t *t, jl_sym_t *fld, int err) { jl_tuple_t *fn = t->names; - size_t i; - for(i=0; i < jl_tuple_len(fn); i++) { + for(size_t i=0; i < jl_tuple_len(fn); i++) { if (jl_tupleref(fn,i) == (jl_value_t*)fld) { return (int)i; } @@ -142,18 +142,18 @@ int jl_field_index(jl_struct_type_t *t, jl_sym_t *fld, int err) jl_value_t *jl_get_nth_field(jl_value_t *v, size_t i) { - jl_struct_type_t *st = (jl_struct_type_t*)jl_typeof(v); + jl_datatype_t *st = (jl_datatype_t*)jl_typeof(v); size_t offs = jl_field_offset(st,i) + sizeof(void*); if (st->fields[i].isptr) { return *(jl_value_t**)((char*)v + offs); } - return jl_new_bits((jl_bits_type_t*)jl_tupleref(st->types,i), + return jl_new_bits((jl_datatype_t*)jl_tupleref(st->types,i), (char*)v + offs); } int jl_field_isdefined(jl_value_t *v, jl_sym_t *fld, int err) { - jl_struct_type_t *st = (jl_struct_type_t*)jl_typeof(v); + jl_datatype_t *st = (jl_datatype_t*)jl_typeof(v); int i = jl_field_index(st, fld, err); if (i == -1) return 0; size_t offs = jl_field_offset(st,i) + sizeof(void*); @@ -165,7 +165,7 @@ int jl_field_isdefined(jl_value_t *v, jl_sym_t *fld, int err) jl_value_t *jl_set_nth_field(jl_value_t *v, size_t i, jl_value_t *rhs) { - jl_struct_type_t *st = (jl_struct_type_t*)jl_typeof(v); + jl_datatype_t *st = (jl_datatype_t*)jl_typeof(v); size_t offs = jl_field_offset(st,i) + sizeof(void*); if (st->fields[i].isptr) { *(jl_value_t**)((char*)v + offs) = rhs; @@ -176,51 +176,58 @@ jl_value_t *jl_set_nth_field(jl_value_t *v, size_t i, jl_value_t *rhs) return rhs; } -DLLEXPORT jl_value_t *jl_new_struct(jl_struct_type_t *type, ...) +DLLEXPORT jl_value_t *jl_new_struct(jl_datatype_t *type, ...) { if (type->instance != NULL) return type->instance; va_list args; size_t nf = jl_tuple_len(type->names); - size_t i; va_start(args, type); jl_value_t *jv = newstruct(type); - for(i=0; i < nf; i++) { + for(size_t i=0; i < nf; i++) { jl_set_nth_field(jv, i, va_arg(args, jl_value_t*)); } - if (nf == 0) type->instance = jv; + if (type->size == 0) type->instance = jv; va_end(args); return jv; } -DLLEXPORT jl_value_t *jl_new_struct_uninit(jl_struct_type_t *type) +DLLEXPORT jl_value_t *jl_new_structv(jl_datatype_t *type, jl_value_t **args, uint32_t na) { if (type->instance != NULL) return type->instance; size_t nf = jl_tuple_len(type->names); jl_value_t *jv = newstruct(type); - memset(&((void**)jv)[1], 0, type->size); - if (nf == 0) type->instance = jv; + for(size_t i=0; i < na; i++) { + jl_set_nth_field(jv, i, args[i]); + } + for(size_t i=na; i < nf; i++) { + if (type->fields[i].isptr) + *(jl_value_t**)((char*)jv+jl_field_offset(type,i)+sizeof(void*)) = NULL; + } + if (type->size == 0) type->instance = jv; return jv; } -DLLEXPORT jl_value_t *jl_new_structt(jl_struct_type_t *type, jl_tuple_t *t) +DLLEXPORT jl_value_t *jl_new_struct_uninit(jl_datatype_t *type) { - assert(jl_tuple_len(type->names) == jl_tuple_len(t)); - jl_value_t *jv = jl_new_struct_uninit(type); - for(size_t i=0; i < jl_tuple_len(t); i++) { - jl_set_nth_field(jv, i, jl_tupleref(t, i)); - } + if (type->instance != NULL) return type->instance; + jl_value_t *jv = newstruct(type); + if (type->size == 0) type->instance = jv; + else memset(&((void**)jv)[1], 0, type->size); return jv; } jl_tuple_t *jl_tuple(size_t n, ...) { va_list args; - size_t i; if (n == 0) return jl_null; va_start(args, n); - jl_tuple_t *jv = (jl_tuple_t*)newobj((jl_type_t*)jl_tuple_type, n+1); +#ifdef OVERLAP_TUPLE_LEN + jl_tuple_t *jv = (jl_tuple_t*)newobj((jl_value_t*)jl_tuple_type, n); +#else + jl_tuple_t *jv = (jl_tuple_t*)newobj((jl_value_t*)jl_tuple_type, n+1); +#endif jl_tuple_set_len_unsafe(jv, n); - for(i=0; i < n; i++) { + for(size_t i=0; i < n; i++) { jl_tupleset(jv, i, va_arg(args, jl_value_t*)); } va_end(args); @@ -229,8 +236,12 @@ jl_tuple_t *jl_tuple(size_t n, ...) jl_tuple_t *jl_tuple1(void *a) { +#ifdef OVERLAP_TUPLE_LEN + jl_tuple_t *t = (jl_tuple_t*)alloc_2w(); +#else jl_tuple_t *t = (jl_tuple_t*)alloc_3w(); - t->type = (jl_type_t*)jl_tuple_type; +#endif + t->type = (jl_value_t*)jl_tuple_type; jl_tuple_set_len_unsafe(t, 1); jl_tupleset(t, 0, a); return t; @@ -238,8 +249,12 @@ jl_tuple_t *jl_tuple1(void *a) jl_tuple_t *jl_tuple2(void *a, void *b) { +#ifdef OVERLAP_TUPLE_LEN + jl_tuple_t *t = (jl_tuple_t*)alloc_3w(); +#else jl_tuple_t *t = (jl_tuple_t*)alloc_4w(); - t->type = (jl_type_t*)jl_tuple_type; +#endif + t->type = (jl_value_t*)jl_tuple_type; jl_tuple_set_len_unsafe(t, 2); jl_tupleset(t, 0, a); jl_tupleset(t, 1, b); @@ -249,7 +264,11 @@ jl_tuple_t *jl_tuple2(void *a, void *b) jl_tuple_t *jl_alloc_tuple_uninit(size_t n) { if (n == 0) return jl_null; - jl_tuple_t *jv = (jl_tuple_t*)newobj((jl_type_t*)jl_tuple_type, n+1); +#ifdef OVERLAP_TUPLE_LEN + jl_tuple_t *jv = (jl_tuple_t*)newobj((jl_value_t*)jl_tuple_type, n); +#else + jl_tuple_t *jv = (jl_tuple_t*)newobj((jl_value_t*)jl_tuple_type, n+1); +#endif jl_tuple_set_len_unsafe(jv, n); return jv; } @@ -258,8 +277,7 @@ jl_tuple_t *jl_alloc_tuple(size_t n) { if (n == 0) return jl_null; jl_tuple_t *jv = jl_alloc_tuple_uninit(n); - size_t i; - for(i=0; i < n; i++) { + for(size_t i=0; i < n; i++) { jl_tupleset(jv, i, NULL); } return jv; @@ -284,8 +302,7 @@ jl_tuple_t *jl_tuple_fill(size_t n, jl_value_t *v) { if (n==0) return jl_null; jl_tuple_t *tup = jl_alloc_tuple_uninit(n); - size_t i; - for(i=0; i < n; i++) { + for(size_t i=0; i < n; i++) { jl_tupleset(tup, i, v); } return tup; @@ -295,7 +312,7 @@ DLLEXPORT jl_function_t *jl_new_closure(jl_fptr_t fptr, jl_value_t *env, jl_lambda_info_t *linfo) { jl_function_t *f = (jl_function_t*)alloc_4w(); - f->type = (jl_type_t*)jl_function_type; + f->type = (jl_value_t*)jl_function_type; f->fptr = (fptr!=NULL ? fptr : linfo->fptr); f->env = env; f->linfo = linfo; @@ -306,15 +323,15 @@ DLLEXPORT jl_lambda_info_t *jl_new_lambda_info(jl_value_t *ast, jl_tuple_t *sparams) { jl_lambda_info_t *li = - (jl_lambda_info_t*)newobj((jl_type_t*)jl_lambda_info_type, + (jl_lambda_info_t*)newobj((jl_value_t*)jl_lambda_info_type, LAMBDA_INFO_NW); li->ast = ast; - li->file = (jl_value_t*)null_sym; + li->file = null_sym; li->line = 0; if (ast != NULL && jl_is_expr(ast)) { jl_expr_t *body1 = (jl_expr_t*)jl_exprarg(jl_lam_body((jl_expr_t*)ast),0); if (jl_is_expr(body1) && ((jl_expr_t*)body1)->head == line_sym) { - li->file = jl_exprarg(body1, 1); + li->file = (jl_sym_t*)jl_exprarg(body1, 1); li->line = jl_unbox_long(jl_exprarg(body1, 0)); } } @@ -332,6 +349,8 @@ jl_lambda_info_t *jl_new_lambda_info(jl_value_t *ast, jl_tuple_t *sparams) li->unspecialized = NULL; li->specializations = NULL; li->name = anonymous_sym; + li->def = li; + li->capt = NULL; return li; } @@ -345,9 +364,9 @@ static jl_sym_t *mk_symbol(const char *str) size_t len = strlen(str); sym = (jl_sym_t*)malloc((sizeof(jl_sym_t)-sizeof(void*)+len+1+7)&-8); - sym->type = (jl_type_t*)jl_sym_type; + sym->type = (jl_value_t*)jl_sym_type; sym->left = sym->right = NULL; -#ifdef __LP64__ +#ifdef _P64 sym->hash = memhash(str, len)^0xAAAAAAAAAAAAAAAAL; #else sym->hash = memhash32(str, len)^0xAAAAAAAA; @@ -359,7 +378,7 @@ static jl_sym_t *mk_symbol(const char *str) static void unmark_symbols_(jl_sym_t *root) { while (root != NULL) { - root->type = (jl_type_t*)(((uptrint_t)root->type)&~1UL); + root->type = (jl_value_t*)(((uptrint_t)root->type)&~1UL); unmark_symbols_(root->left); root = root->right; } @@ -439,41 +458,25 @@ DLLEXPORT jl_sym_t *jl_tagged_gensym(const char* str, int32_t len) jl_typename_t *jl_new_typename(jl_sym_t *name) { - jl_typename_t *tn=(jl_typename_t*)newobj((jl_type_t*)jl_typename_type, 4); + jl_typename_t *tn=(jl_typename_t*)newobj((jl_value_t*)jl_typename_type, 4); tn->name = name; tn->module = jl_current_module; tn->primary = NULL; - tn->cache = jl_null; + tn->cache = (jl_value_t*)jl_null; return tn; } -jl_tag_type_t *jl_new_tagtype(jl_value_t *name, jl_tag_type_t *super, - jl_tuple_t *parameters) +jl_datatype_t *jl_new_abstracttype(jl_value_t *name, jl_datatype_t *super, + jl_tuple_t *parameters) { - jl_typename_t *tn=NULL; - JL_GC_PUSH(&tn); - - if (jl_is_typename(name)) - tn = (jl_typename_t*)name; - else - tn = jl_new_typename((jl_sym_t*)name); - jl_tag_type_t *t = (jl_tag_type_t*)newobj((jl_type_t*)jl_tag_kind, - TAG_TYPE_NW); - t->name = tn; - t->super = super; - t->parameters = parameters; - t->fptr = NULL; - t->env = NULL; - t->linfo = NULL; - if (t->name->primary == NULL) - t->name->primary = (jl_value_t*)t; - JL_GC_POP(); - return t; + jl_datatype_t *dt = jl_new_datatype((jl_sym_t*)name, super, parameters, jl_null, jl_null, 1, 0); + dt->pointerfree = 0; + return dt; } jl_function_t *jl_instantiate_method(jl_function_t *f, jl_tuple_t *sp); -void jl_add_constructors(jl_struct_type_t *t) +void jl_add_constructors(jl_datatype_t *t) { if (t->name == jl_array_typename) { t->fptr = jl_f_no_function; @@ -484,11 +487,10 @@ void jl_add_constructors(jl_struct_type_t *t) if (t->ctor_factory == (jl_value_t*)jl_nothing || t->ctor_factory == (jl_value_t*)jl_null) { - assert(jl_tuple_len(t->parameters) == 0); } else { assert(jl_tuple_len(t->parameters) > 0); - if (t != (jl_struct_type_t*)t->name->primary) { + if (t != (jl_datatype_t*)t->name->primary) { // instantiating assert(jl_is_function(t->ctor_factory)); @@ -497,10 +499,9 @@ void jl_add_constructors(jl_struct_type_t *t) jl_tuple_t *sparams = jl_alloc_tuple_uninit(np*2); jl_function_t *cfactory = NULL; JL_GC_PUSH(&sparams, &cfactory); - size_t i; - for(i=0; i < np; i++) { + for(size_t i=0; i < np; i++) { jl_tupleset(sparams, i*2+0, - jl_tupleref(((jl_struct_type_t*)t->name->primary)->parameters, i)); + jl_tupleref(((jl_datatype_t*)t->name->primary)->parameters, i)); jl_tupleset(sparams, i*2+1, jl_tupleref(t->parameters, i)); } @@ -519,34 +520,35 @@ void jl_add_constructors(jl_struct_type_t *t) JL_CALLABLE(jl_f_ctor_trampoline) { - jl_add_constructors((jl_struct_type_t*)F); + jl_add_constructors((jl_datatype_t*)F); return jl_apply((jl_function_t*)F, args, nargs); } -jl_struct_type_t *jl_new_uninitialized_struct_type(size_t nfields) +jl_datatype_t *jl_new_uninitialized_datatype(size_t nfields) { - return (jl_struct_type_t*) - newobj((jl_type_t*)jl_struct_kind, - NWORDS(sizeof(jl_struct_type_t) - sizeof(void*) + + return (jl_datatype_t*) + newobj((jl_value_t*)jl_datatype_type, + NWORDS(sizeof(jl_datatype_t) - sizeof(void*) + (nfields-1)*sizeof(jl_fielddesc_t))); } -void jl_compute_struct_offsets(jl_struct_type_t *st) +void jl_compute_field_offsets(jl_datatype_t *st) { size_t sz = 0, alignm = 0; + int ptrfree = 1; - for(size_t i=0; i < st->types->length; i++) { + for(size_t i=0; i < jl_tuple_len(st->types); i++) { jl_value_t *ty = jl_tupleref(st->types, i); size_t fsz, al; - if (jl_is_bits_type(ty)) { - fsz = jl_bitstype_nbits(ty)/8; - al = fsz; // alignment == size for bits types + if (jl_isbits(ty) && (al=((jl_datatype_t*)ty)->alignment)!=0) { + fsz = jl_datatype_size(ty); st->fields[i].isptr = 0; } else { fsz = sizeof(void*); al = fsz; st->fields[i].isptr = 1; + ptrfree = 0; } sz = LLT_ALIGN(sz, al); if (al > alignm) @@ -557,44 +559,17 @@ void jl_compute_struct_offsets(jl_struct_type_t *st) } st->alignment = alignm; st->size = LLT_ALIGN(sz, alignm); -} - -jl_struct_type_t *jl_new_struct_type(jl_sym_t *name, jl_tag_type_t *super, - jl_tuple_t *parameters, - jl_tuple_t *fnames, jl_tuple_t *ftypes) -{ - jl_typename_t *tn = jl_new_typename(name); - JL_GC_PUSH(&tn); - jl_struct_type_t *t = jl_new_uninitialized_struct_type(fnames->length); - t->name = tn; - t->name->primary = (jl_value_t*)t; - t->super = super; - t->parameters = parameters; - t->names = fnames; - t->types = ftypes; - t->fptr = jl_f_ctor_trampoline; - t->env = (jl_value_t*)t; - t->linfo = NULL; - t->ctor_factory = (jl_value_t*)jl_null; - t->instance = NULL; - if (!jl_is_leaf_type((jl_value_t*)t)) { - t->uid = 0; - } - else { - t->uid = jl_assign_type_uid(); - if (t->types != NULL) - jl_compute_struct_offsets(t); - } - JL_GC_POP(); - return t; + st->pointerfree = ptrfree && !st->abstract; } extern int jl_boot_file_loaded; -jl_bits_type_t *jl_new_bits_type(jl_value_t *name, jl_tag_type_t *super, - jl_tuple_t *parameters, size_t nbits) +jl_datatype_t *jl_new_datatype(jl_sym_t *name, jl_datatype_t *super, + jl_tuple_t *parameters, + jl_tuple_t *fnames, jl_tuple_t *ftypes, + int abstract, int mutabl) { - jl_bits_type_t *t=NULL; + jl_datatype_t *t=NULL; jl_typename_t *tn=NULL; JL_GC_PUSH(&t, &tn); @@ -608,34 +583,58 @@ jl_bits_type_t *jl_new_bits_type(jl_value_t *name, jl_tag_type_t *super, else if (!strcmp(((jl_sym_t*)name)->name, "Bool")) t = jl_bool_type; } - int makenew = (t==NULL); - if (makenew) { - t = (jl_bits_type_t*)newobj((jl_type_t*)jl_bits_kind, BITS_TYPE_NW); + if (t == NULL) { + t = jl_new_uninitialized_datatype(jl_tuple_len(fnames)); if (jl_is_typename(name)) tn = (jl_typename_t*)name; else tn = jl_new_typename((jl_sym_t*)name); t->name = tn; } + + if (t->name->primary == NULL) + t->name->primary = (jl_value_t*)t; t->super = super; t->parameters = parameters; - t->nbits = nbits; - if (!jl_is_leaf_type((jl_value_t*)t)) + t->names = fnames; + t->types = ftypes; + t->abstract = abstract; + t->mutabl = mutabl; + t->pointerfree = 0; + t->fptr = jl_f_no_function; + t->env = (jl_value_t*)t; + t->linfo = NULL; + t->ctor_factory = (jl_value_t*)jl_null; + t->instance = NULL; + t->struct_decl = NULL; + t->size = 0; + t->alignment = 0; + if (abstract || jl_tuple_len(parameters) > 0) { t->uid = 0; - else if (makenew) + } + else { t->uid = jl_assign_type_uid(); - t->fptr = NULL; - t->env = NULL; - t->linfo = NULL; - if (t->name->primary == NULL) - t->name->primary = (jl_value_t*)t; + if (t->types != NULL) + jl_compute_field_offsets(t); + } JL_GC_POP(); return t; } +jl_datatype_t *jl_new_bitstype(jl_value_t *name, jl_datatype_t *super, + jl_tuple_t *parameters, size_t nbits) +{ + jl_datatype_t *bt = jl_new_datatype((jl_sym_t*)name, super, parameters, + jl_null, jl_null, 0, 0); + bt->size = nbits/8; + bt->alignment = bt->size; + bt->pointerfree = 1; + return bt; +} + jl_uniontype_t *jl_new_uniontype(jl_tuple_t *types) { - jl_uniontype_t *t = (jl_uniontype_t*)newobj((jl_type_t*)jl_union_kind, 1); + jl_uniontype_t *t = (jl_uniontype_t*)newobj((jl_value_t*)jl_uniontype_type,1); // don't make unions of 1 type; Union(T)==T assert(jl_tuple_len(types) != 1); t->types = types; @@ -644,9 +643,9 @@ jl_uniontype_t *jl_new_uniontype(jl_tuple_t *types) // type constructor ----------------------------------------------------------- -jl_typector_t *jl_new_type_ctor(jl_tuple_t *params, jl_type_t *body) +jl_typector_t *jl_new_type_ctor(jl_tuple_t *params, jl_value_t *body) { - jl_typector_t *tc = (jl_typector_t*)newobj((jl_type_t*)jl_typector_type,2); + jl_typector_t *tc = (jl_typector_t*)newobj((jl_value_t*)jl_typector_type,2); tc->parameters = params; tc->body = body; return (jl_typector_t*)tc; @@ -655,19 +654,19 @@ jl_typector_t *jl_new_type_ctor(jl_tuple_t *params, jl_type_t *body) // bits constructors ---------------------------------------------------------- #define BOXN_FUNC(nb,nw) \ -jl_value_t *jl_box##nb(jl_bits_type_t *t, int##nb##_t x) \ +jl_value_t *jl_box##nb(jl_datatype_t *t, int##nb##_t x) \ { \ - assert(jl_is_bits_type(t)); \ - assert(jl_bitstype_nbits(t)/8 == sizeof(x)); \ + assert(jl_is_bitstype(t)); \ + assert(jl_datatype_size(t) == sizeof(x)); \ jl_value_t *v = alloc_##nw##w(); \ - v->type = (jl_type_t*)t; \ - *(int##nb##_t*)jl_bits_data(v) = x; \ + v->type = (jl_value_t*)t; \ + *(int##nb##_t*)jl_data_ptr(v) = x; \ return v; \ } BOXN_FUNC(8, 2) BOXN_FUNC(16, 2) BOXN_FUNC(32, 2) -#ifdef __LP64__ +#ifdef _P64 BOXN_FUNC(64, 2) #else BOXN_FUNC(64, 3) @@ -676,9 +675,9 @@ BOXN_FUNC(64, 3) #define UNBOX_FUNC(j_type,c_type) \ c_type jl_unbox_##j_type(jl_value_t *v) \ { \ - assert(jl_is_bits_type(jl_typeof(v))); \ - assert(jl_bitstype_nbits(jl_typeof(v))/8 == sizeof(c_type)); \ - return *(c_type*)jl_bits_data(v); \ + assert(jl_is_bitstype(jl_typeof(v))); \ + assert(jl_datatype_size(jl_typeof(v)) == sizeof(c_type)); \ + return *(c_type*)jl_data_ptr(v); \ } UNBOX_FUNC(int8, int8_t) UNBOX_FUNC(uint8, uint8_t) @@ -691,17 +690,19 @@ UNBOX_FUNC(uint64, uint64_t) UNBOX_FUNC(bool, int8_t) UNBOX_FUNC(float32, float) UNBOX_FUNC(float64, double) +UNBOX_FUNC(voidpointer, void*) #define BOX_FUNC(typ,c_type,pfx,nw) \ jl_value_t *pfx##_##typ(c_type x) \ { \ jl_value_t *v = alloc_##nw##w(); \ - v->type = (jl_type_t*)jl_##typ##_type; \ - *(c_type*)jl_bits_data(v) = x; \ + v->type = (jl_value_t*)jl_##typ##_type; \ + *(c_type*)jl_data_ptr(v) = x; \ return v; \ } BOX_FUNC(float32, float, jl_box, 2) -#ifdef __LP64__ +BOX_FUNC(voidpointer, void*, jl_box, 2) //2 pointers == two words on all platforms +#ifdef _P64 BOX_FUNC(float64, double, jl_box, 2) #else BOX_FUNC(float64, double, jl_box, 3) @@ -717,8 +718,8 @@ jl_value_t *jl_box_##typ(c_type x) \ if ((u##c_type)idx < (u##c_type)NBOX_C) \ return boxed_##typ##_cache[idx]; \ jl_value_t *v = alloc_##nw##w(); \ - v->type = (jl_type_t*)jl_##typ##_type; \ - *(c_type*)jl_bits_data(v) = x; \ + v->type = (jl_value_t*)jl_##typ##_type; \ + *(c_type*)jl_data_ptr(v) = x; \ return v; \ } #define UIBOX_FUNC(typ,c_type,nw) \ @@ -728,8 +729,8 @@ jl_value_t *jl_box_##typ(c_type x) \ if (x < NBOX_C) \ return boxed_##typ##_cache[x]; \ jl_value_t *v = alloc_##nw##w(); \ - v->type = (jl_type_t*)jl_##typ##_type; \ - *(c_type*)jl_bits_data(v) = x; \ + v->type = (jl_value_t*)jl_##typ##_type; \ + *(c_type*)jl_data_ptr(v) = x; \ return v; \ } SIBOX_FUNC(int16, int16_t, 2) @@ -737,7 +738,7 @@ SIBOX_FUNC(int32, int32_t, 2) UIBOX_FUNC(uint16, uint16_t, 2) UIBOX_FUNC(uint32, uint32_t, 2) UIBOX_FUNC(char, uint32_t, 2) -#ifdef __LP64__ +#ifdef _P64 SIBOX_FUNC(int64, int64_t, 2) UIBOX_FUNC(uint64, uint64_t, 2) #else @@ -815,7 +816,7 @@ jl_expr_t *jl_exprn(jl_sym_t *head, size_t n) jl_array_t *ar = n==0 ? (jl_array_t*)jl_an_empty_cell : jl_alloc_cell_1d(n); JL_GC_PUSH(&ar); jl_expr_t *ex = (jl_expr_t*)alloc_4w(); - ex->type = (jl_type_t*)jl_expr_type; + ex->type = (jl_value_t*)jl_expr_type; ex->head = head; ex->args = ar; ex->etype = (jl_value_t*)jl_any_type; @@ -827,16 +828,18 @@ jl_expr_t *jl_exprn(jl_sym_t *head, size_t n) // do anything without being able to make Exprs. JL_CALLABLE(jl_f_new_expr) { - JL_NARGS(Expr, 3, 3); + JL_NARGSV(Expr, 1); JL_TYPECHK(Expr, symbol, args[0]); - if (!jl_typeis(args[1], (jl_value_t*)jl_array_any_type)) { - jl_type_error("Expr", (jl_value_t*)jl_array_any_type, args[1]); - } + jl_array_t *ar = jl_alloc_cell_1d(nargs-1); + JL_GC_PUSH(&ar); + for(size_t i=1; i < nargs; i++) + jl_cellset(ar, i-1, args[i]); jl_expr_t *ex = (jl_expr_t*)alloc_4w(); - ex->type = (jl_type_t*)jl_expr_type; + ex->type = (jl_value_t*)jl_expr_type; ex->head = (jl_sym_t*)args[0]; - ex->args = (jl_array_t*)args[1]; - ex->etype = args[2]; + ex->args = ar; + ex->etype = (jl_value_t*)jl_any_type; + JL_GC_POP(); return (jl_value_t*)ex; } diff --git a/src/array.c b/src/array.c index ec9db38337325..410743c7624de 100644 --- a/src/array.c +++ b/src/array.c @@ -11,7 +11,17 @@ // array constructors --------------------------------------------------------- -static jl_array_t *_new_array(jl_type_t *atype, +static inline int store_unboxed(jl_value_t *el_type) +{ + return jl_is_datatype(el_type) && jl_is_leaf_type(el_type) && jl_is_immutable(el_type) && jl_is_pointerfree((jl_datatype_t*)el_type); +} + +int jl_array_store_unboxed(jl_value_t *el_type) +{ + return store_unboxed(el_type); +} + +static jl_array_t *_new_array(jl_value_t *atype, uint32_t ndims, size_t *dims) { size_t i, tot, nel=1; @@ -24,11 +34,11 @@ static jl_array_t *_new_array(jl_type_t *atype, jl_error("invalid Array dimension size"); nel *= dims[i]; } - jl_type_t *el_type = (jl_type_t*)jl_tparam0(atype); + jl_value_t *el_type = jl_tparam0(atype); - isunboxed = jl_is_bits_type(el_type); + isunboxed = store_unboxed(el_type); if (isunboxed) { - elsz = jl_bitstype_nbits(el_type)/8; + elsz = jl_datatype_size(el_type); tot = elsz * nel; if (elsz == 1) { // hidden 0 terminator for all byte arrays @@ -41,24 +51,42 @@ static jl_array_t *_new_array(jl_type_t *atype, } int ndimwords = jl_array_ndimwords(ndims); + size_t tsz = sizeof(jl_array_t)-sizeof(void*); + tsz += ndimwords*sizeof(size_t); if (tot <= ARRAY_INLINE_NBYTES) { - size_t tsz = tot>sizeof(size_t) ? tot-sizeof(size_t) : tot; - a = allocobj((sizeof(jl_array_t)+tsz+ndimwords*sizeof(size_t)+15)&-16); + size_t basesz = tsz; + if (isunboxed && elsz >= 4) + tsz = (tsz+15)&-16; // align data area 16 + size_t doffs = tsz; + tsz += tot; + if (((tsz&0xf) == 0) && tsz == basesz) { + // leave at least 1 word at end for owner pointer + tsz += sizeof(void*); + } + tsz = (tsz+15)&-16; // align whole object 16 + a = allocobj(tsz); a->type = atype; a->ismalloc = 0; - data = (&a->_space[0] + ndimwords*sizeof(size_t)); + a->isinline = 1; + data = (char*)a + doffs; if (tot > 0 && !isunboxed) { memset(data, 0, tot); } } else { - a = allocobj((sizeof(jl_array_t)+ndimwords*sizeof(size_t)+15)&-16); + if ((tsz&0xf) == 0) { + // leave at least 1 word at end for owner pointer + tsz += sizeof(void*); + } + tsz = (tsz+15)&-16; // align whole object size 16 + a = allocobj(tsz); JL_GC_PUSH(&a); a->type = atype; a->ismalloc = 1; + a->isinline = 0; // temporarily initialize to make gc-safe a->data = NULL; - jl_value_t **powner = (jl_value_t**)(&a->_space[0] + ndimwords*sizeof(size_t)); + jl_value_t **powner = (jl_value_t**)(&a->_pad + ndimwords); *powner = (jl_value_t*)jl_gc_managed_malloc(tot); data = ((jl_mallocptr_t*)*powner)->ptr; if (!isunboxed) @@ -68,7 +96,9 @@ static jl_array_t *_new_array(jl_type_t *atype, a->data = data; if (elsz == 1) ((char*)data)[tot-1] = '\0'; +#ifdef STORE_ARRAY_LEN a->length = nel; +#endif a->ndims = ndims; a->ptrarray = !isunboxed; a->elsize = elsz; @@ -88,7 +118,7 @@ static jl_array_t *_new_array(jl_type_t *atype, static jl_mallocptr_t *array_new_buffer(jl_array_t *a, size_t newlen); -jl_array_t *jl_reshape_array(jl_type_t *atype, jl_array_t *data, +jl_array_t *jl_reshape_array(jl_value_t *atype, jl_array_t *data, jl_tuple_t *dims) { size_t i; @@ -100,26 +130,40 @@ jl_array_t *jl_reshape_array(jl_type_t *atype, jl_array_t *data, a->type = atype; a->ndims = ndims; a->data = NULL; + a->isinline = 0; + jl_value_t *el_type = jl_tparam0(atype); + if (store_unboxed(el_type)) { + a->elsize = jl_datatype_size(el_type); + a->ptrarray = 0; + } + else { + a->elsize = sizeof(void*); + a->ptrarray = 1; + } JL_GC_PUSH(&a); char *d = data->data; if (data->ndims == 1) d -= data->offset*data->elsize; - if (d == jl_array_inline_data_area(data)) { - if (data->ndims == 1) { + if (data->isinline) { + if (data->ndims == 1 || + // also copy out data if aligned wrong + (((((size_t)d)&0x0f)!=0) && !a->ptrarray && a->elsize>=4)) { // data might resize, so switch it to shared representation. - // problem: we'd like to do that, but it might not be valid, - // since the buffer might be used from C in a way that it's - // assumed not to move. for now, just copy the data (note this - // case only happens for sizes <= ARRAY_INLINE_NBYTES) - jl_mallocptr_t *mp = array_new_buffer(data, data->length); - memcpy(mp->ptr, data->data, data->length * data->elsize); + // problem: the buffer might be used from C in a way that it's + // assumed not to move. for now just hope this doesn't happen. + size_t datalen = jl_array_len(data); + jl_mallocptr_t *mp = array_new_buffer(data, datalen); + memcpy(mp->ptr, data->data, datalen * data->elsize); a->data = mp->ptr; jl_array_data_owner(a) = (jl_value_t*)mp; a->ismalloc = 1; - //data->data = mp->ptr; - //data->offset = 0; - //data->maxsize = data->length; - //jl_array_data_owner(data) = (jl_value_t*)mp; + + data->data = mp->ptr; + data->offset = 0; + data->maxsize = datalen; + jl_array_data_owner(data) = (jl_value_t*)mp; + data->ismalloc = 1; + data->isinline = 0; } else { a->ismalloc = 0; @@ -132,20 +176,14 @@ jl_array_t *jl_reshape_array(jl_type_t *atype, jl_array_t *data, } if (a->data == NULL) a->data = data->data; - jl_type_t *el_type = (jl_type_t*)jl_tparam0(atype); - if (jl_is_bits_type(el_type)) { - a->elsize = jl_bitstype_nbits(el_type)/8; - a->ptrarray = 0; - } - else { - a->elsize = sizeof(void*); - a->ptrarray = 1; - } if (ndims == 1) { - a->length = jl_unbox_long(jl_tupleref(dims,0)); - a->nrows = a->length; - a->maxsize = a->length; + size_t l = jl_unbox_long(jl_tupleref(dims,0)); +#ifdef STORE_ARRAY_LEN + a->length = l; +#endif + a->nrows = l; + a->maxsize = l; a->offset = 0; } else { @@ -157,7 +195,9 @@ jl_array_t *jl_reshape_array(jl_type_t *atype, jl_array_t *data, jl_error("invalid Array dimension size"); l *= adims[i]; } +#ifdef STORE_ARRAY_LEN a->length = l; +#endif } JL_GC_POP(); @@ -165,26 +205,29 @@ jl_array_t *jl_reshape_array(jl_type_t *atype, jl_array_t *data, } // own_buffer != 0 iff GC should call free() on this pointer eventually -jl_array_t *jl_ptr_to_array_1d(jl_type_t *atype, void *data, size_t nel, +jl_array_t *jl_ptr_to_array_1d(jl_value_t *atype, void *data, size_t nel, int own_buffer) { size_t elsz; jl_array_t *a; - jl_type_t *el_type = (jl_type_t*)jl_tparam0(atype); + jl_value_t *el_type = jl_tparam0(atype); - int isunboxed = jl_is_bits_type(el_type); + int isunboxed = store_unboxed(el_type); if (isunboxed) - elsz = jl_bitstype_nbits(el_type)/8; + elsz = jl_datatype_size(el_type); else elsz = sizeof(void*); a = allocobj((sizeof(jl_array_t)+jl_array_ndimwords(1)*sizeof(size_t)+15)&-16); a->type = atype; a->data = data; +#ifdef STORE_ARRAY_LEN a->length = nel; +#endif a->elsize = elsz; a->ptrarray = !isunboxed; a->ndims = 1; + a->isinline = 0; if (own_buffer) { a->ismalloc = 1; @@ -195,14 +238,14 @@ jl_array_t *jl_ptr_to_array_1d(jl_type_t *atype, void *data, size_t nel, jl_array_data_owner(a) = (jl_value_t*)a; } - a->nrows = a->length; - a->maxsize = a->length; + a->nrows = nel; + a->maxsize = nel; a->offset = 0; return a; } -jl_array_t *jl_ptr_to_array(jl_type_t *atype, void *data, jl_tuple_t *dims, +jl_array_t *jl_ptr_to_array(jl_value_t *atype, void *data, jl_tuple_t *dims, int own_buffer) { size_t i, elsz, nel=1; @@ -212,11 +255,11 @@ jl_array_t *jl_ptr_to_array(jl_type_t *atype, void *data, jl_tuple_t *dims, for(i=0; i < ndims; i++) { nel *= jl_unbox_long(jl_tupleref(dims, i)); } - jl_type_t *el_type = (jl_type_t*)jl_tparam0(atype); + jl_value_t *el_type = jl_tparam0(atype); - int isunboxed = jl_is_bits_type(el_type); + int isunboxed = store_unboxed(el_type); if (isunboxed) - elsz = jl_bitstype_nbits(el_type)/8; + elsz = jl_datatype_size(el_type); else elsz = sizeof(void*); @@ -224,10 +267,13 @@ jl_array_t *jl_ptr_to_array(jl_type_t *atype, void *data, jl_tuple_t *dims, a = allocobj((sizeof(jl_array_t) + ndimwords*sizeof(size_t)+15)&-16); a->type = atype; a->data = data; +#ifdef STORE_ARRAY_LEN a->length = nel; +#endif a->elsize = elsz; a->ptrarray = !isunboxed; a->ndims = ndims; + a->isinline = 0; if (own_buffer) { a->ismalloc = 1; @@ -239,8 +285,8 @@ jl_array_t *jl_ptr_to_array(jl_type_t *atype, void *data, jl_tuple_t *dims, } if (ndims == 1) { - a->nrows = a->length; - a->maxsize = a->length; + a->nrows = nel; + a->maxsize = nel; a->offset = 0; } else { @@ -253,12 +299,12 @@ jl_array_t *jl_ptr_to_array(jl_type_t *atype, void *data, jl_tuple_t *dims, return a; } -jl_array_t *jl_new_array_(jl_type_t *atype, uint32_t ndims, size_t *dims) +jl_array_t *jl_new_array_(jl_value_t *atype, uint32_t ndims, size_t *dims) { return _new_array(atype, ndims, dims); } -jl_array_t *jl_new_array(jl_type_t *atype, jl_tuple_t *dims) +jl_array_t *jl_new_array(jl_value_t *atype, jl_tuple_t *dims) { size_t ndims = jl_tuple_len(dims); size_t *adims = alloca(ndims*sizeof(size_t)); @@ -268,24 +314,24 @@ jl_array_t *jl_new_array(jl_type_t *atype, jl_tuple_t *dims) return _new_array(atype, ndims, adims); } -jl_array_t *jl_alloc_array_1d(jl_type_t *atype, size_t nr) +jl_array_t *jl_alloc_array_1d(jl_value_t *atype, size_t nr) { return _new_array(atype, 1, &nr); } -jl_array_t *jl_alloc_array_2d(jl_type_t *atype, size_t nr, size_t nc) +jl_array_t *jl_alloc_array_2d(jl_value_t *atype, size_t nr, size_t nc) { size_t d[2] = {nr, nc}; return _new_array(atype, 2, &d[0]); } -jl_array_t *jl_alloc_array_3d(jl_type_t *atype, size_t nr, size_t nc, size_t z) +jl_array_t *jl_alloc_array_3d(jl_value_t *atype, size_t nr, size_t nc, size_t z) { size_t d[3] = {nr, nc, z}; return _new_array(atype, 3, &d[0]); } -jl_array_t *jl_pchar_to_array(char *str, size_t len) +jl_array_t *jl_pchar_to_array(const char *str, size_t len) { jl_array_t *a = jl_alloc_array_1d(jl_array_uint8_type, len); memcpy(a->data, str, len); @@ -295,15 +341,15 @@ jl_array_t *jl_pchar_to_array(char *str, size_t len) jl_value_t *jl_array_to_string(jl_array_t *a) { // TODO: check type of array? - jl_struct_type_t* string_type = u8_isvalid(a->data, a->length) == 1 ? // ASCII + jl_datatype_t* string_type = u8_isvalid(a->data, jl_array_len(a)) == 1 ? // ASCII jl_ascii_string_type : jl_utf8_string_type; jl_value_t *s = alloc_2w(); - s->type = (jl_type_t*)string_type; + s->type = (jl_value_t*)string_type; jl_set_nth_field(s, 0, (jl_value_t*)a); return s; } -jl_value_t *jl_pchar_to_string(char *str, size_t len) +jl_value_t *jl_pchar_to_string(const char *str, size_t len) { jl_array_t *a = jl_pchar_to_array(str, len); JL_GC_PUSH(&a); @@ -312,7 +358,7 @@ jl_value_t *jl_pchar_to_string(char *str, size_t len) return s; } -jl_value_t *jl_cstr_to_string(char *str) +jl_value_t *jl_cstr_to_string(const char *str) { return jl_pchar_to_string(str, strlen(str)); } @@ -324,11 +370,21 @@ jl_array_t *jl_alloc_cell_1d(size_t n) // array primitives ----------------------------------------------------------- +#ifndef STORE_ARRAY_LEN +DLLEXPORT size_t jl_array_len_(jl_array_t *a) +{ + size_t l = 1; + for(size_t i=0; i < jl_array_ndims(a); i++) + l *= jl_array_dim(a, i); + return l; +} +#endif + JL_CALLABLE(jl_f_arraylen) { JL_NARGS(arraylen, 1, 1); JL_TYPECHK(arraylen, array, args[0]); - return jl_box_long(((jl_array_t*)args[0])->length); + return jl_box_long(jl_array_len((jl_array_t*)args[0])); } JL_CALLABLE(jl_f_arraysize) @@ -359,10 +415,10 @@ JL_CALLABLE(jl_f_arraysize) jl_value_t *jl_arrayref(jl_array_t *a, size_t i) { - jl_type_t *el_type = (jl_type_t*)jl_tparam0(jl_typeof(a)); + jl_value_t *el_type = (jl_value_t*)jl_tparam0(jl_typeof(a)); jl_value_t *elt; - if (jl_is_bits_type(el_type)) { - elt = jl_new_bits((jl_bits_type_t*)el_type, + if (!a->ptrarray) { + elt = jl_new_bits((jl_datatype_t*)el_type, &((char*)a->data)[i*a->elsize]); } else { @@ -378,30 +434,22 @@ static size_t array_nd_index(jl_array_t *a, jl_value_t **args, size_t nidxs, char *fname) { size_t i=0; - if (nidxs == 1) { - if (!jl_is_long(args[0])) - jl_type_error(fname, (jl_value_t*)jl_long_type, args[0]); - i = jl_unbox_long(args[0])-1; - } - else { - size_t k, stride=1; - size_t nd = jl_array_ndims(a); - for(k=0; k < nidxs; k++) { - if (!jl_is_long(args[k])) - jl_type_error(fname, (jl_value_t*)jl_long_type, args[k]); - size_t ii = jl_unbox_long(args[k])-1; - i += ii * stride; - if (k < nidxs-1) { - size_t d = k>=nd ? 1 : jl_array_dim(a, k); - if (ii >= d) - jl_throw(jl_bounds_exception); - stride = stride * d; - } - } - } - if (i >= a->length) { + size_t k, stride=1; + size_t nd = jl_array_ndims(a); + for(k=0; k < nidxs; k++) { + if (!jl_is_long(args[k])) + jl_type_error(fname, (jl_value_t*)jl_long_type, args[k]); + size_t ii = jl_unbox_long(args[k])-1; + i += ii * stride; + size_t d = k>=nd ? 1 : jl_array_dim(a, k); + if (k < nidxs-1 && ii >= d) + jl_throw(jl_bounds_exception); + stride *= d; + } + for(; k < nd; k++) + stride *= jl_array_dim(a, k); + if (i >= stride) jl_throw(jl_bounds_exception); - } return i; } @@ -431,7 +479,7 @@ void jl_arrayset(jl_array_t *a, jl_value_t *rhs, size_t i) if (!jl_subtype(rhs, el_type, 1)) jl_type_error("arrayset", el_type, rhs); } - if (jl_is_bits_type(el_type)) { + if (!a->ptrarray) { jl_assign_bits(&((char*)a->data)[i*a->elsize], rhs); } else { @@ -451,7 +499,7 @@ JL_CALLABLE(jl_f_arrayset) void jl_arrayunset(jl_array_t *a, size_t i) { - if (i >= a->length) + if (i >= jl_array_len(a)) jl_throw(jl_bounds_exception); char *ptail = (char*)a->data + i*a->elsize; if (a->ptrarray) @@ -475,7 +523,7 @@ static jl_mallocptr_t *array_new_buffer(jl_array_t *a, size_t newlen) void jl_array_grow_end(jl_array_t *a, size_t inc) { // optimized for the case of only growing and shrinking at the end - size_t alen = a->length; + size_t alen = jl_array_len(a); if ((alen + inc) > a->maxsize - a->offset) { size_t newlen = a->maxsize==0 ? (inc<4?4:inc) : a->maxsize*2; while ((alen + inc) > newlen - a->offset) @@ -493,20 +541,39 @@ void jl_array_grow_end(jl_array_t *a, size_t inc) a->data = newdata; jl_array_data_owner(a) = (jl_value_t*)mp; a->ismalloc = 1; + a->isinline = 0; } - a->length += inc; a->nrows += inc; +#ifdef STORE_ARRAY_LEN + a->length += inc; +#endif + a->nrows += inc; } void jl_array_del_end(jl_array_t *a, size_t dec) { - if (dec > a->length) + if (dec > a->nrows) jl_throw(jl_bounds_exception); - char *ptail = (char*)a->data + (a->length-dec)*a->elsize; + char *ptail = (char*)a->data + (a->nrows-dec)*a->elsize; if (a->ptrarray) memset(ptail, 0, dec*a->elsize); else ptail[0] = 0; - a->length -= dec; a->nrows -= dec; +#ifdef STORE_ARRAY_LEN + a->length -= dec; +#endif + a->nrows -= dec; +} + +void jl_array_sizehint(jl_array_t *a, size_t sz) +{ + if (sz <= jl_array_len(a)) + return; + size_t inc = sz - jl_array_len(a); + jl_array_grow_end(a, inc); +#ifdef STORE_ARRAY_LEN + a->length -= inc; +#endif + a->nrows -= inc; } void jl_array_grow_beg(jl_array_t *a, size_t inc) @@ -521,7 +588,7 @@ void jl_array_grow_beg(jl_array_t *a, size_t inc) a->offset -= inc; } else { - size_t alen = a->length; + size_t alen = a->nrows; size_t anb = alen*es; char *newdata; jl_mallocptr_t *mp = NULL; @@ -543,16 +610,19 @@ void jl_array_grow_beg(jl_array_t *a, size_t inc) } memmove(&newdata[nb], a->data, anb); a->data = newdata; - if (mp) { jl_array_data_owner(a) = (jl_value_t*)mp; a->ismalloc = 1; } + if (mp) { jl_array_data_owner(a) = (jl_value_t*)mp; a->ismalloc = 1; a->isinline = 0; } } - a->length += inc; a->nrows += inc; +#ifdef STORE_ARRAY_LEN + a->length += inc; +#endif + a->nrows += inc; } void jl_array_del_beg(jl_array_t *a, size_t dec) { if (dec == 0) return; - if (dec > a->length) + if (dec > a->nrows) jl_throw(jl_bounds_exception); size_t es = a->elsize; size_t nb = dec*es; @@ -560,21 +630,24 @@ void jl_array_del_beg(jl_array_t *a, size_t dec) size_t offset = a->offset; offset += dec; a->data = (char*)a->data + nb; - a->length -= dec; a->nrows -= dec; +#ifdef STORE_ARRAY_LEN + a->length -= dec; +#endif + a->nrows -= dec; // make sure offset doesn't grow forever due to deleting at beginning // and growing at end size_t newoffs = offset; if (offset >= 13*a->maxsize/20) { - newoffs = 17*(a->maxsize - a->length)/100; + newoffs = 17*(a->maxsize - a->nrows)/100; } -#ifdef __LP64__ +#ifdef _P64 while (newoffs > (size_t)((uint32_t)-1)) { newoffs = newoffs/2; } #endif if (newoffs != offset) { - size_t anb = a->length*es; + size_t anb = a->nrows*es; size_t delta = (offset - newoffs)*es; a->data = (char*)a->data - delta; memmove(a->data, (char*)a->data + delta, anb); @@ -582,9 +655,9 @@ void jl_array_del_beg(jl_array_t *a, size_t dec) a->offset = newoffs; } -void jl_cell_1d_push(jl_array_t *a, jl_value_t *item) +DLLEXPORT void jl_cell_1d_push(jl_array_t *a, jl_value_t *item) { assert(jl_typeis(a, jl_array_any_type)); jl_array_grow_end(a, 1); - jl_cellset(a, a->length-1, item); + jl_cellset(a, jl_array_dim(a,0)-1, item); } diff --git a/src/ast.c b/src/ast.c index dd276c57d6c09..e522c64437dd2 100644 --- a/src/ast.c +++ b/src/ast.c @@ -19,7 +19,7 @@ static char flisp_system_image[] = { extern fltype_t *iostreamtype; static fltype_t *jvtype; -static jl_value_t *scm_to_julia(value_t e); +static jl_value_t *scm_to_julia(value_t e, int expronly); static value_t julia_to_scm(jl_value_t *v); DLLEXPORT void jl_lisp_prompt(void) @@ -45,15 +45,15 @@ value_t fl_invoke_julia_macro(value_t *args, uint32_t nargs) if (nargs < 1) argcount("invoke-julia-macro", nargs, 1); jl_function_t *f = NULL; - jl_value_t **margs = alloca(nargs * sizeof(jl_value_t*)); + jl_value_t **margs; + JL_GC_PUSHARGS(margs, nargs); int i; for(i=0; i < nargs; i++) margs[i] = NULL; - JL_GC_PUSHARGS(margs, nargs); - for(i=1; i < nargs; i++) margs[i] = scm_to_julia(args[i]); + for(i=1; i < nargs; i++) margs[i] = scm_to_julia(args[i], 1); jl_value_t *result; JL_TRY { - margs[0] = scm_to_julia(args[0]); + margs[0] = scm_to_julia(args[0], 1); f = (jl_function_t*)jl_toplevel_eval(margs[0]); result = jl_apply(f, &margs[1], nargs-1); } @@ -93,6 +93,9 @@ static builtinspec_t julia_flisp_ast_ext[] = { { NULL, NULL } }; +static value_t true_sym; +static value_t false_sym; + DLLEXPORT void jl_init_frontend(void) { fl_init(2*512*1024); @@ -111,6 +114,8 @@ DLLEXPORT void jl_init_frontend(void) NULL, NULL); assign_global_builtins(julia_flisp_ast_ext); + true_sym = symbol("true"); + false_sym = symbol("false"); } static jl_sym_t *scmsym_to_julia(value_t s) @@ -126,37 +131,37 @@ static jl_sym_t *scmsym_to_julia(value_t s) return jl_symbol(symbol_name(s)); } -static jl_value_t *scm_to_julia_(value_t e); +static jl_value_t *scm_to_julia_(value_t e, int expronly); -static jl_value_t *full_list(value_t e) +static jl_value_t *full_list(value_t e, int expronly) { size_t ln = llength(e); if (ln == 0) return jl_an_empty_cell; jl_array_t *ar = jl_alloc_cell_1d(ln); size_t i=0; while (iscons(e)) { - jl_cellset(ar, i, scm_to_julia_(car_(e))); + jl_cellset(ar, i, scm_to_julia_(car_(e), expronly)); e = cdr_(e); i++; } return (jl_value_t*)ar; } -static jl_value_t *full_list_of_lists(value_t e) +static jl_value_t *full_list_of_lists(value_t e, int expronly) { size_t ln = llength(e); if (ln == 0) return jl_an_empty_cell; jl_array_t *ar = jl_alloc_cell_1d(ln); size_t i=0; while (iscons(e)) { - jl_cellset(ar, i, full_list(car_(e))); + jl_cellset(ar, i, full_list(car_(e),expronly)); e = cdr_(e); i++; } return (jl_value_t*)ar; } -static jl_value_t *scm_to_julia(value_t e) +static jl_value_t *scm_to_julia(value_t e, int expronly) { #ifdef JL_GC_MARKSWEEP int en = jl_gc_is_enabled(); @@ -164,7 +169,7 @@ static jl_value_t *scm_to_julia(value_t e) #endif jl_value_t *v; JL_TRY { - v = scm_to_julia_(e); + v = scm_to_julia_(e, expronly); } JL_CATCH { // if expression cannot be converted, replace with error expr @@ -178,7 +183,7 @@ static jl_value_t *scm_to_julia(value_t e) return v; } -static jl_value_t *scm_to_julia_(value_t e) +static jl_value_t *scm_to_julia_(value_t e, int eo) { if (fl_isnumber(e)) { if (iscprim(e)) { @@ -204,7 +209,7 @@ static jl_value_t *scm_to_julia_(value_t e) } if (isfixnum(e)) { int64_t ne = numval(e); -#ifdef __LP64__ +#ifdef _P64 return (jl_value_t*)jl_box_int64(ne); #else if (ne > S32_MAX || ne < S32_MIN) @@ -212,8 +217,8 @@ static jl_value_t *scm_to_julia_(value_t e) return (jl_value_t*)jl_box_int32((int32_t)ne); #endif } - uint64_t n = toulong(e, "scm_to_julia"); -#ifdef __LP64__ + size_t n = tosize(e, "scm_to_julia"); +#ifdef _P64 return (jl_value_t*)jl_box_int64((int64_t)n); #else if (n > S32_MAX) @@ -222,13 +227,10 @@ static jl_value_t *scm_to_julia_(value_t e) #endif } if (issymbol(e)) { - if (!fl_isgensym(e)) { - char *sn = symbol_name(e); - if (!strcmp(sn, "true")) - return jl_true; - else if (!strcmp(sn, "false")) - return jl_false; - } + if (e == true_sym) + return jl_true; + else if (e == false_sym) + return jl_false; return (jl_value_t*)scmsym_to_julia(e); } if (fl_isstring(e)) { @@ -260,23 +262,23 @@ static jl_value_t *scm_to_julia_(value_t e) jl_expr_t *ex = jl_exprn(lambda_sym, n); e = cdr_(e); value_t largs = car_(e); - jl_cellset(ex->args, 0, full_list(largs)); + jl_cellset(ex->args, 0, full_list(largs,eo)); e = cdr_(e); value_t ee = car_(e); jl_array_t *vinf = jl_alloc_cell_1d(3); - jl_cellset(vinf, 0, full_list(car_(ee))); + jl_cellset(vinf, 0, full_list(car_(ee),eo)); ee = cdr_(ee); - jl_cellset(vinf, 1, full_list_of_lists(car_(ee))); + jl_cellset(vinf, 1, full_list_of_lists(car_(ee),eo)); ee = cdr_(ee); - jl_cellset(vinf, 2, full_list_of_lists(car_(ee))); + jl_cellset(vinf, 2, full_list_of_lists(car_(ee),eo)); assert(!iscons(cdr_(ee))); jl_cellset(ex->args, 1, vinf); e = cdr_(e); for(i=2; i < n; i++) { assert(iscons(e)); - jl_cellset(ex->args, i, scm_to_julia_(car_(e))); + jl_cellset(ex->args, i, scm_to_julia_(car_(e), eo)); e = cdr_(e); } return @@ -284,30 +286,32 @@ static jl_value_t *scm_to_julia_(value_t e) } e = cdr_(e); - if (sym == line_sym && n==1) { - return jl_new_struct(jl_linenumbernode_type, - scm_to_julia_(car_(e))); - } - if (sym == label_sym) { - return jl_new_struct(jl_labelnode_type, - scm_to_julia_(car_(e))); - } - if (sym == goto_sym) { - return jl_new_struct(jl_gotonode_type, - scm_to_julia_(car_(e))); - } - if (sym == quote_sym) { - return jl_new_struct(jl_quotenode_type, - scm_to_julia_(car_(e))); - } - if (sym == top_sym) { - return jl_new_struct(jl_topnode_type, - scm_to_julia_(car_(e))); + if (!eo) { + if (sym == line_sym && n==1) { + return jl_new_struct(jl_linenumbernode_type, + scm_to_julia_(car_(e),0)); + } + if (sym == label_sym) { + return jl_new_struct(jl_labelnode_type, + scm_to_julia_(car_(e),0)); + } + if (sym == goto_sym) { + return jl_new_struct(jl_gotonode_type, + scm_to_julia_(car_(e),0)); + } + if (sym == quote_sym) { + return jl_new_struct(jl_quotenode_type, + scm_to_julia_(car_(e),0)); + } + if (sym == top_sym) { + return jl_new_struct(jl_topnode_type, + scm_to_julia_(car_(e),0)); + } } jl_expr_t *ex = jl_exprn(sym, n); for(i=0; i < n; i++) { assert(iscons(e)); - jl_cellset(ex->args, i, scm_to_julia_(car_(e))); + jl_cellset(ex->args, i, scm_to_julia_(car_(e),eo)); e = cdr_(e); } return (jl_value_t*)ex; @@ -331,11 +335,12 @@ static jl_value_t *scm_to_julia_(value_t e) static value_t array_to_list(jl_array_t *a) { - long i; + if (jl_array_len(a) > 300000) + jl_error("expression too large"); value_t lst=FL_NIL, temp=FL_NIL; fl_gc_handle(&lst); fl_gc_handle(&temp); - for(i=jl_array_len(a)-1; i >= 0; i--) { + for(long i=jl_array_len(a)-1; i >= 0; i--) { temp = julia_to_scm(jl_cellref(a,i)); lst = fl_cons(temp, lst); } @@ -391,9 +396,6 @@ static value_t julia_to_scm(jl_value_t *v) if (jl_is_long(v) && fits_fixnum(jl_unbox_long(v))) { return fixnum(jl_unbox_long(v)); } - if (jl_typeis(v,jl_array_any_type)) { - return array_to_list((jl_array_t*)v); - } value_t opaque = cvalue(jvtype, sizeof(void*)); *(jl_value_t**)cv_data((cvalue_t*)ptr(opaque)) = v; return opaque; @@ -404,10 +406,10 @@ DLLEXPORT jl_value_t *jl_parse_input_line(const char *str) { value_t e = fl_applyn(1, symbol_value(symbol("jl-parse-string")), cvalue_static_cstring(str)); - if (e == FL_T || e == FL_F || e == FL_EOF) + if (e == FL_EOF) return jl_nothing; - return scm_to_julia(e); + return scm_to_julia(e,0); } // this is for parsing one expression out of a string, keeping track of @@ -421,14 +423,14 @@ DLLEXPORT jl_value_t *jl_parse_string(const char *str, int pos0, int greedy) JL_GC_PUSH(&expr, &pos1); value_t e = car_(p); - if (e == FL_T || e == FL_F || e == FL_EOF) { + if (e == FL_EOF) { expr = (jl_value_t*)jl_null; } else { - expr = scm_to_julia(e); + expr = scm_to_julia(e,0); } - pos1 = jl_box_long(toulong(cdr_(p),"parse")); + pos1 = jl_box_long(tosize(cdr_(p),"parse")); jl_value_t *result = (jl_value_t*)jl_tuple2(expr, pos1); JL_GC_POP(); return result; @@ -450,24 +452,25 @@ extern int jl_lineno; jl_value_t *jl_parse_next() { value_t c = fl_applyn(0, symbol_value(symbol("jl-parser-next"))); - if (c == FL_F) + if (c == FL_EOF) return NULL; if (iscons(c)) { value_t a = car_(c); if (isfixnum(a)) { jl_lineno = numval(a); - //ios_printf(ios_stderr, " on line %d\n", jl_lineno); - return scm_to_julia(cdr_(c)); + //jl_printf(JL_STDERR, " on line %d\n", jl_lineno); + return scm_to_julia(cdr_(c),0); } } - return scm_to_julia(c); + return scm_to_julia(c,0); } -void jl_load_file_string(const char *text) +void jl_load_file_string(const char *text, char *filename) { - fl_applyn(1, symbol_value(symbol("jl-parse-string-stream")), - cvalue_static_cstring(text)); - jl_parse_eval_all(""); + fl_applyn(2, symbol_value(symbol("jl-parse-string-stream")), + cvalue_static_cstring(text), + cvalue_static_cstring(filename)); + jl_parse_eval_all(filename); } // returns either an expression or a thunk @@ -476,13 +479,7 @@ jl_value_t *jl_expand(jl_value_t *expr) int np = jl_gc_n_preserved_values(); value_t arg = julia_to_scm(expr); value_t e = fl_applyn(1, symbol_value(symbol("jl-expand-to-thunk")), arg); - jl_value_t *result; - if (e == FL_T || e == FL_F || e == FL_EOF) { - result = NULL; - } - else { - result = scm_to_julia(e); - } + jl_value_t *result = scm_to_julia(e,0); while (jl_gc_n_preserved_values() > np) { jl_gc_unpreserve(); } @@ -495,7 +492,7 @@ DLLEXPORT jl_value_t *jl_macroexpand(jl_value_t *expr) value_t arg = julia_to_scm(expr); value_t e = fl_applyn(1, symbol_value(symbol("jl-macroexpand")), arg); jl_value_t *result; - result = scm_to_julia(e); + result = scm_to_julia(e,0); while (jl_gc_n_preserved_values() > np) { jl_gc_unpreserve(); } @@ -562,10 +559,6 @@ jl_array_t *jl_lam_vinfo(jl_expr_t *l) // get array of var info records for captured vars jl_array_t *jl_lam_capt(jl_expr_t *l) { - if (jl_is_tuple(l)) { - // in compressed form - return (jl_array_t*)jl_tupleref(l, 3); - } assert(jl_is_expr(l)); jl_value_t *le = jl_exprarg(l, 1); assert(jl_is_array(le)); @@ -622,7 +615,7 @@ static jl_value_t *copy_ast(jl_value_t *expr, jl_tuple_t *sp, int do_sp) jl_lambda_info_t *li = (jl_lambda_info_t*)expr; /* if (sp == jl_null && li->ast && - jl_lam_capt((jl_expr_t*)li->ast)->length == 0) + jl_array_len(jl_lam_capt((jl_expr_t*)li->ast)) == 0) return expr; */ // TODO: avoid if above condition is true and decls have already @@ -647,14 +640,13 @@ static jl_value_t *copy_ast(jl_value_t *expr, jl_tuple_t *sp, int do_sp) jl_expr_t *e = (jl_expr_t*)expr; jl_expr_t *ne = jl_exprn(e->head, jl_array_len(e->args)); JL_GC_PUSH(&ne); - size_t i; if (e->head == lambda_sym) { jl_exprarg(ne, 0) = copy_ast(jl_exprarg(e,0), sp, 0); jl_exprarg(ne, 1) = copy_ast(jl_exprarg(e,1), sp, 0); jl_exprarg(ne, 2) = copy_ast(jl_exprarg(e,2), sp, 1); } else { - for(i=0; i < jl_array_len(e->args); i++) + for(size_t i=0; i < jl_array_len(e->args); i++) jl_exprarg(ne, i) = copy_ast(jl_exprarg(e,i), sp, 1); } JL_GC_POP(); @@ -663,6 +655,27 @@ static jl_value_t *copy_ast(jl_value_t *expr, jl_tuple_t *sp, int do_sp) return expr; } +static jl_value_t *dont_copy_ast(jl_value_t *expr, jl_tuple_t *sp, int do_sp) +{ + if (jl_is_symbol(expr) || jl_is_lambda_info(expr)) { + return copy_ast(expr, sp, do_sp); + } + else if (jl_is_expr(expr)) { + jl_expr_t *e = (jl_expr_t*)expr; + if (e->head == lambda_sym) { + jl_exprarg(e, 0) = dont_copy_ast(jl_exprarg(e,0), sp, 0); + jl_exprarg(e, 1) = dont_copy_ast(jl_exprarg(e,1), sp, 0); + jl_exprarg(e, 2) = dont_copy_ast(jl_exprarg(e,2), sp, 1); + } + else { + for(size_t i=0; i < jl_array_len(e->args); i++) + jl_exprarg(e, i) = dont_copy_ast(jl_exprarg(e,i), sp, 1); + } + return (jl_value_t*)e; + } + return expr; +} + // TODO: eval decl types for arguments of non-generic functions static void eval_decl_types(jl_array_t *vi, jl_tuple_t *spenv) { @@ -699,14 +712,17 @@ DLLEXPORT jl_value_t *jl_prepare_ast(jl_lambda_info_t *li, jl_tuple_t *sparams) { jl_tuple_t *spenv = NULL; - jl_value_t *l_ast = li->ast; - if (l_ast == NULL) return NULL; - jl_value_t *ast = l_ast; + jl_value_t *ast = li->ast; + if (ast == NULL) return NULL; JL_GC_PUSH(&spenv, &ast); - if (jl_is_tuple(ast)) - ast = jl_uncompress_ast((jl_tuple_t*)ast); spenv = jl_tuple_tvars_to_symbols(sparams); - ast = copy_ast(ast, sparams, 1); + if (!jl_is_expr(ast)) { + ast = jl_uncompress_ast(li, ast); + ast = dont_copy_ast(ast, sparams, 1); + } + else { + ast = copy_ast(ast, sparams, 1); + } jl_module_t *last_m = jl_current_module; JL_TRY { jl_current_module = li->module; diff --git a/src/builtin_proto.h b/src/builtin_proto.h index ba3dd68816125..70a9f8330f638 100644 --- a/src/builtin_proto.h +++ b/src/builtin_proto.h @@ -5,6 +5,7 @@ JL_CALLABLE(jl_f_new_expr); JL_CALLABLE(jl_f_new_box); +JL_CALLABLE(jl_f_new_module); JL_CALLABLE(jl_f_throw); JL_CALLABLE(jl_f_is); JL_CALLABLE(jl_f_no_function); @@ -13,6 +14,7 @@ JL_CALLABLE(jl_f_subtype); JL_CALLABLE(jl_f_isa); JL_CALLABLE(jl_f_typeassert); JL_CALLABLE(jl_f_apply); +JL_CALLABLE(jl_f_kwcall); JL_CALLABLE(jl_f_top_eval); JL_CALLABLE(jl_f_isdefined); JL_CALLABLE(jl_f_tuple); diff --git a/src/builtins.c b/src/builtins.c index cecc095946dde..d85ea3e1b4f7b 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -105,6 +105,17 @@ void jl_pop_handler(int n) // primitives ----------------------------------------------------------------- +static int bits_equal(void *a, void *b, int sz) +{ + switch (sz) { + case 1: return *(int8_t*)a == *(int8_t*)b; + case 2: return *(int16_t*)a == *(int16_t*)b; + case 4: return *(int32_t*)a == *(int32_t*)b; + case 8: return *(int64_t*)a == *(int64_t*)b; + default: return memcmp(a, b, sz)==0; + } +} + int jl_egal(jl_value_t *a, jl_value_t *b) { if (a == b) @@ -112,21 +123,6 @@ int jl_egal(jl_value_t *a, jl_value_t *b) jl_value_t *ta = (jl_value_t*)jl_typeof(a); if (ta != (jl_value_t*)jl_typeof(b)) return 0; - if (jl_is_bits_type(ta)) { - size_t nb = jl_bitstype_nbits(ta)/8; - switch (nb) { - case 1: - return *(int8_t*)jl_bits_data(a) == *(int8_t*)jl_bits_data(b); - case 2: - return *(int16_t*)jl_bits_data(a) == *(int16_t*)jl_bits_data(b); - case 4: - return *(int32_t*)jl_bits_data(a) == *(int32_t*)jl_bits_data(b); - case 8: - return *(int64_t*)jl_bits_data(a) == *(int64_t*)jl_bits_data(b); - default: - return memcmp(jl_bits_data(a), jl_bits_data(b), nb)==0; - } - } if (jl_is_tuple(a)) { size_t l = jl_tuple_len(a); if (l != jl_tuple_len(b)) @@ -137,9 +133,32 @@ int jl_egal(jl_value_t *a, jl_value_t *b) } return 1; } - if (ta == (jl_value_t*)jl_union_kind) - return jl_egal(jl_fieldref(a,0), jl_fieldref(b,0)); - return 0; + jl_datatype_t *dt = (jl_datatype_t*)ta; + if (dt->mutabl) return 0; + size_t sz = dt->size; + if (sz == 0) return 1; + size_t nf = jl_tuple_len(dt->names); + if (nf == 0) { + return bits_equal(jl_data_ptr(a), jl_data_ptr(b), sz); + } + for (size_t f=0; f < nf; f++) { + size_t offs = dt->fields[f].offset; + char *ao = (char*)jl_data_ptr(a) + offs; + char *bo = (char*)jl_data_ptr(b) + offs; + int eq; + if (dt->fields[f].isptr) { + jl_value_t *af = *(jl_value_t**)ao; + jl_value_t *bf = *(jl_value_t**)bo; + if (af == bf) eq = 1; + else if (af==NULL || bf==NULL) eq = 0; + else eq = jl_egal(af, bf); + } + else { + eq = bits_equal(ao, bo, dt->fields[f].size); + } + if (!eq) return 0; + } + return 1; } JL_CALLABLE(jl_f_is) @@ -179,6 +198,12 @@ JL_CALLABLE(jl_f_isa) return (jl_subtype(args[0],args[1],1) ? jl_true : jl_false); } +DLLEXPORT void jl_typeassert(jl_value_t *x, jl_value_t *t) +{ + if (!jl_subtype(x,t,1)) + jl_type_error("typeassert", t, x); +} + JL_CALLABLE(jl_f_typeassert) { JL_NARGS(typeassert, 2, 2); @@ -261,8 +286,63 @@ JL_CALLABLE(jl_f_apply) return result; } +#include "newobj_internal.h" + +JL_CALLABLE(jl_f_kwcall) +{ + if (nargs < 3) + jl_error("internal error: malformed keyword argument call"); + JL_TYPECHK(apply, function, args[0]); + jl_function_t *f = (jl_function_t*)args[0]; + if (!jl_is_gf(f)) + jl_error("function does not accept keyword arguments"); + jl_function_t *sorter = ((jl_methtable_t*)f->env)->kwsorter; + if (sorter == NULL) + jl_errorf("function %s does not accept keyword arguments", + jl_gf_name(f)->name); + + size_t nkeys = jl_unbox_long(args[1]); + size_t nrest=0; + size_t pa = 3 + 2*nkeys; + jl_value_t *rkw = args[2 + 2*nkeys]; + if (rkw != (jl_value_t*)jl_null) { + if (!jl_is_array(rkw)) { + if (jl_append_any_func == NULL) { + jl_append_any_func = + (jl_function_t*)jl_get_global(jl_base_module, + jl_symbol("append_any")); + } + rkw = jl_apply(jl_append_any_func, &rkw, 1); + args[2 + 2*nkeys] = rkw; // gc root + } + nrest = jl_array_len(rkw); + } + + size_t kwlen = (nkeys+nrest)*2; +#ifdef OVERLAP_TUPLE_LEN + jl_tuple_t *kwtuple = (jl_tuple_t*)newobj((jl_value_t*)jl_tuple_type, kwlen); +#else + jl_tuple_t *kwtuple = (jl_tuple_t*)newobj((jl_value_t*)jl_tuple_type, kwlen+1); +#endif + jl_tuple_set_len_unsafe(kwtuple, kwlen); + + for(size_t i=0; i < nkeys*2; i+=2) { + jl_tupleset(kwtuple, i , args[2+i]); + jl_tupleset(kwtuple, i+1, args[2+i+1]); + } + for(size_t i=0; i < nrest; i++) { + jl_value_t *ri = jl_cellref(rkw, i); + jl_tupleset(kwtuple, (nkeys+i)*2 , jl_tupleref(ri,0)); + jl_tupleset(kwtuple, (nkeys+i)*2+1, jl_tupleref(ri,1)); + } + args[pa-1] = (jl_value_t*)kwtuple; + return jl_apply(sorter, &args[pa-1], nargs-(pa-1)); +} + // eval ----------------------------------------------------------------------- +extern int jl_lineno; + JL_CALLABLE(jl_f_top_eval) { jl_module_t *m; @@ -280,19 +360,24 @@ JL_CALLABLE(jl_f_top_eval) if (jl_is_symbol(ex)) { return jl_eval_global_var(m, (jl_sym_t*)ex); } + jl_value_t *v=NULL; + int last_lineno = jl_lineno; if (m == jl_current_module) { - return jl_toplevel_eval(ex); + v = jl_toplevel_eval(ex); + jl_lineno = last_lineno; + return v; } - jl_value_t *v=NULL; jl_module_t *last_m = jl_current_module; JL_TRY { jl_current_module = m; v = jl_toplevel_eval(ex); } JL_CATCH { + jl_lineno = last_lineno; jl_current_module = last_m; jl_rethrow(); } + jl_lineno = last_lineno; jl_current_module = last_m; assert(v); return v; @@ -318,8 +403,8 @@ JL_CALLABLE(jl_f_isdefined) s = (jl_sym_t*)args[1]; if (!jl_is_module(args[0])) { jl_value_t *vt = (jl_value_t*)jl_typeof(args[0]); - if (!jl_is_struct_type(vt)) { - jl_type_error("isdefined", (jl_value_t*)jl_struct_kind, args[0]); + if (!jl_is_datatype(vt)) { + jl_type_error("isdefined", (jl_value_t*)jl_datatype_type, args[0]); } return jl_field_isdefined(args[0], s, 1) ? jl_true : jl_false; } @@ -373,10 +458,10 @@ JL_CALLABLE(jl_f_get_field) if (vt == (jl_value_t*)jl_module_type) { return jl_eval_global_var((jl_module_t*)v, (jl_sym_t*)args[1]); } - if (!jl_is_struct_type(vt)) { - jl_type_error("getfield", (jl_value_t*)jl_struct_kind, v); + if (!jl_is_datatype(vt)) { + jl_type_error("getfield", (jl_value_t*)jl_datatype_type, v); } - jl_struct_type_t *st = (jl_struct_type_t*)vt; + jl_datatype_t *st = (jl_datatype_t*)vt; jl_sym_t *fld = (jl_sym_t*)args[1]; jl_value_t *fval = jl_get_nth_field(v, jl_field_index(st, fld, 1)); if (fval == NULL) @@ -392,9 +477,11 @@ JL_CALLABLE(jl_f_set_field) jl_value_t *vt = (jl_value_t*)jl_typeof(v); if (vt == (jl_value_t*)jl_module_type) jl_error("cannot assign variables in other modules"); - if (!jl_is_struct_type(vt)) - jl_type_error("setfield", (jl_value_t*)jl_struct_kind, v); - jl_struct_type_t *st = (jl_struct_type_t*)vt; + if (!jl_is_datatype(vt)) + jl_type_error("setfield", (jl_value_t*)jl_datatype_type, v); + jl_datatype_t *st = (jl_datatype_t*)vt; + if (!st->mutabl) + jl_errorf("type %s is immutable", st->name->name->name); jl_sym_t *fld = (jl_sym_t*)args[1]; size_t i = jl_field_index(st, fld, 1); jl_value_t *ft = jl_tupleref(st->types,i); @@ -413,16 +500,16 @@ JL_CALLABLE(jl_f_field_type) jl_value_t *vt = (jl_value_t*)jl_typeof(v); if (vt == (jl_value_t*)jl_module_type) jl_error("cannot assign variables in other modules"); - if (!jl_is_struct_type(vt)) - jl_type_error("fieldtype", (jl_value_t*)jl_struct_kind, v); - jl_struct_type_t *st = (jl_struct_type_t*)vt; + if (!jl_is_datatype(vt)) + jl_type_error("fieldtype", (jl_value_t*)jl_datatype_type, v); + jl_datatype_t *st = (jl_datatype_t*)vt; jl_sym_t *fld = (jl_sym_t*)args[1]; return jl_tupleref(st->types, jl_field_index(st, fld, 1)); } // conversion ----------------------------------------------------------------- -static jl_value_t *convert(jl_type_t *to, jl_value_t *x, jl_function_t *conv_f) +static jl_value_t *convert(jl_value_t *to, jl_value_t *x, jl_function_t *conv_f) { jl_value_t *args[2]; if (jl_subtype(x, (jl_value_t*)to, 1)) @@ -449,7 +536,7 @@ JL_CALLABLE(jl_f_convert_tuple) } else if (i < pl) { pe = jl_tupleref(to,i); - if (jl_is_seq_type(pe)) { + if (jl_is_vararg_type(pe)) { pe = jl_tparam0(pe); pseq = 1; } @@ -459,7 +546,7 @@ JL_CALLABLE(jl_f_convert_tuple) break; } assert(pe != NULL); - jl_tupleset(out, i, convert((jl_type_t*)pe, ce, f)); + jl_tupleset(out, i, convert((jl_value_t*)pe, ce, f)); } JL_GC_POP(); if (out == NULL) @@ -469,7 +556,7 @@ JL_CALLABLE(jl_f_convert_tuple) JL_CALLABLE(jl_f_convert_default) { - jl_type_t *to = (jl_type_t*)args[0]; + jl_value_t *to = args[0]; jl_value_t *x = args[1]; if (!jl_subtype(x, (jl_value_t*)to, 1)) { jl_no_method_error((jl_function_t*)args[2], args, 2); @@ -487,6 +574,10 @@ DLLEXPORT void *jl_array_ptr(jl_array_t *a) { return a->data; } +DLLEXPORT void *jl_value_ptr(jl_value_t *a) +{ + return (void*)a; +} // printing ------------------------------------------------------------------- @@ -537,12 +628,16 @@ DLLEXPORT int jl_strtof(char *str, float *out) jl_value_t *jl_stdout_obj() { - return jl_get_global(jl_base_module, jl_symbol("stdout_stream")); + jl_value_t *stdout_obj = jl_get_global(jl_base_module, jl_symbol("STDOUT")); + if (stdout_obj != NULL) return stdout_obj; + return jl_get_global(jl_base_module, jl_symbol("OUTPUT_STREAM")); } jl_value_t *jl_stderr_obj() { - return jl_get_global(jl_base_module, jl_symbol("stderr_stream")); + jl_value_t *stderr_obj = jl_get_global(jl_base_module, jl_symbol("STDERR")); + if (stderr_obj != NULL) return stderr_obj; + return jl_get_global(jl_base_module, jl_symbol("OUTPUT_STREAM")); } static jl_function_t *jl_show_gf=NULL; @@ -556,7 +651,7 @@ void jl_show(jl_value_t *stream, jl_value_t *v) if (jl_show_gf==NULL || stream==NULL) { JL_PRINTF(JL_STDERR, "could not show value of type %s", jl_is_tuple(v) ? "Tuple" : - ((jl_tag_type_t*)jl_typeof(v))->name->name->name); + ((jl_datatype_t*)jl_typeof(v))->name->name->name); return; } jl_value_t *args[2] = {stream,v}; @@ -567,7 +662,7 @@ void jl_show(jl_value_t *stream, jl_value_t *v) // comma_one prints a comma for 1 element, e.g. "(x,)" void jl_show_tuple(jl_value_t *st, jl_tuple_t *t, char opn, char cls, int comma_one) { - ios_t *s = (ios_t*)jl_iostr_data(st); + JL_STREAM *s = ((JL_STREAM**)st)[1]; JL_PUTC(opn, s); size_t i, n=jl_tuple_len(t); for(i=0; i < n; i++) { @@ -584,14 +679,14 @@ static void show_function(JL_STREAM *s, jl_value_t *v) JL_PUTS(jl_gf_name(v)->name, s); } else { - JL_PUTS("#", s); + JL_PUTS("# function", s); } } static void show_type(jl_value_t *st, jl_value_t *t) { - ios_t *s = (ios_t*)jl_iostr_data(st); - if (jl_is_union_type(t)) { + uv_stream_t *s =((uv_stream_t**)st)[1]; + if (jl_is_uniontype(t)) { if (t == (jl_value_t*)jl_bottom_type) { JL_WRITE(s, "None", 4); } @@ -603,7 +698,7 @@ static void show_type(jl_value_t *st, jl_value_t *t) jl_show_tuple(st, ((jl_uniontype_t*)t)->types, '(', ')', 0); } } - else if (jl_is_seq_type(t)) { + else if (jl_is_vararg_type(t)) { jl_show(st, jl_tparam0(t)); JL_WRITE(s, "...", 3); } @@ -611,8 +706,8 @@ static void show_type(jl_value_t *st, jl_value_t *t) jl_show(st, (jl_value_t*)((jl_typector_t*)t)->body); } else { - assert(jl_is_some_tag_type(t)); - jl_tag_type_t *tt = (jl_tag_type_t*)t; + assert(jl_is_datatype(t)); + jl_datatype_t *tt = (jl_datatype_t*)t; JL_PUTS(tt->name->name->name, s); jl_tuple_t *p = tt->parameters; if (jl_tuple_len(p) > 0) @@ -622,7 +717,7 @@ static void show_type(jl_value_t *st, jl_value_t *t) DLLEXPORT void jl_show_any(jl_value_t *str, jl_value_t *v) { - ios_t *s = (ios_t*)jl_iostr_data(str); + uv_stream_t *s = ((uv_stream_t**)str)[1]; // fallback for printing some other builtin types if (jl_is_tuple(v)) { jl_show_tuple(str, (jl_tuple_t*)v, '(', ')', 1); @@ -634,21 +729,20 @@ DLLEXPORT void jl_show_any(jl_value_t *str, jl_value_t *v) show_function(s, v); } else if (jl_typeis(v,jl_intrinsic_type)) { - JL_PRINTF(s, "#", *(uint32_t*)jl_bits_data(v)); + JL_PRINTF(s, "# intrinsic function %d", *(uint32_t*)jl_data_ptr(v)); } else { jl_value_t *t = (jl_value_t*)jl_typeof(v); - assert(jl_is_struct_type(t) || jl_is_bits_type(t)); - jl_tag_type_t *tt = (jl_tag_type_t*)t; - JL_PUTS(tt->name->name->name, s); - if (tt->parameters != jl_null) { - jl_show_tuple(str, tt->parameters, '{', '}', 0); + assert(jl_is_datatype(t)); + jl_datatype_t *dt = (jl_datatype_t*)t; + JL_PUTS(dt->name->name->name, s); + if (dt->parameters != jl_null) { + jl_show_tuple(str, dt->parameters, '{', '}', 0); } JL_PUTC('(', s); - if (jl_is_struct_type(tt)) { - jl_struct_type_t *st = (jl_struct_type_t*)tt; + if (jl_tuple_len(dt->names)>0 || dt->size==0) { size_t i; - size_t n = jl_tuple_len(st->names); + size_t n = jl_tuple_len(dt->names); for(i=0; i < n; i++) { jl_value_t *fval = jl_get_nth_field(v, i); if (fval == NULL) @@ -660,11 +754,11 @@ DLLEXPORT void jl_show_any(jl_value_t *str, jl_value_t *v) } } else { - size_t nb = jl_bitstype_nbits(tt)/8; - char *data = (char*)jl_bits_data(v); + size_t nb = jl_datatype_size(dt); + char *data = (char*)jl_data_ptr(v); JL_PUTS("0x", s); for(int i=nb-1; i >= 0; --i) - ios_printf(s, "%02hhx", data[i]); + jl_printf(s, "%02hhx", data[i]); } JL_PUTC(')', s); } @@ -683,8 +777,8 @@ JL_CALLABLE(jl_trampoline) // to run inference on all thunks. slows down loading files. if (f->linfo->inferred == 0) { if (!jl_in_inference) { - if (jl_is_tuple(f->linfo->ast)) { - f->linfo->ast = jl_uncompress_ast((jl_tuple_t*)f->linfo->ast); + if (!jl_is_expr(f->linfo->ast)) { + f->linfo->ast = jl_uncompress_ast(f->linfo, f->linfo->ast); } if (jl_eval_with_compiler_p(jl_lam_body((jl_expr_t*)f->linfo->ast),1)) { jl_type_infer(f->linfo, jl_tuple_type, f->linfo); @@ -700,7 +794,7 @@ JL_CALLABLE(jl_trampoline) JL_CALLABLE(jl_f_instantiate_type) { JL_NARGSV(instantiate_type, 1); - if (!jl_is_some_tag_type(args[0])) + if (!jl_is_datatype(args[0])) JL_TYPECHK(instantiate_type, typector, args[0]); return jl_apply_type_(args[0], &args[1], nargs-1); } @@ -712,7 +806,7 @@ JL_CALLABLE(jl_f_new_type_constructor) if (!jl_is_type(args[1])) jl_type_error("typealias", (jl_value_t*)jl_type_type, args[1]); jl_tuple_t *p = (jl_tuple_t*)args[0]; - return (jl_value_t*)jl_new_type_ctor(p, (jl_type_t*)args[1]); + return (jl_value_t*)jl_new_type_ctor(p, args[1]); } JL_CALLABLE(jl_f_typevar) @@ -723,7 +817,7 @@ JL_CALLABLE(jl_f_typevar) JL_TYPECHK(typevar, symbol, args[0]); if (jl_boundp(jl_current_module, (jl_sym_t*)args[0]) && jl_is_type(jl_get_global(jl_current_module, (jl_sym_t*)args[0]))) { - ios_printf(JL_STDERR, "Warning: type parameter name %s shadows an identifier.\n", ((jl_sym_t*)args[0])->name); + jl_printf(JL_STDERR, "Warning: type parameter name %s shadows an identifier.\n", ((jl_sym_t*)args[0])->name); } jl_value_t *lb = (jl_value_t*)jl_bottom_type; jl_value_t *ub = (jl_value_t*)jl_any_type; @@ -816,7 +910,7 @@ JL_CALLABLE(jl_f_invoke) // hashing -------------------------------------------------------------------- -#ifdef __LP64__ +#ifdef _P64 #define bitmix(a,b) int64hash((a)^bswap_64(b)) #define hash64(a) int64hash(a) #else @@ -824,45 +918,56 @@ JL_CALLABLE(jl_f_invoke) #define hash64(a) int64to32hash(a) #endif +static uptrint_t bits_hash(void *b, size_t sz) +{ + switch (sz) { + case 1: return int32hash(*(int8_t*)b); + case 2: return int32hash(*(int16_t*)b); + case 4: return int32hash(*(int32_t*)b); + case 8: return hash64(*(int64_t*)b); + default: +#ifdef _P64 + return memhash((char*)b, sz); +#else + return memhash32((char*)b, sz); +#endif + } +} + DLLEXPORT uptrint_t jl_object_id(jl_value_t *v) { if (jl_is_symbol(v)) return ((jl_sym_t*)v)->hash; jl_value_t *tv = (jl_value_t*)jl_typeof(v); - if (jl_is_bits_type(tv)) { - size_t nb = jl_bitstype_nbits(tv)/8; - uptrint_t h = inthash((uptrint_t)tv); - switch (nb) { - case 1: - return int32hash(*(int8_t*)jl_bits_data(v) ^ h); - case 2: - return int32hash(*(int16_t*)jl_bits_data(v) ^ h); - case 4: - return int32hash(*(int32_t*)jl_bits_data(v) ^ h); - case 8: - return hash64(*(int64_t*)jl_bits_data(v) ^ h); - default: -#ifdef __LP64__ - return h ^ memhash((char*)jl_bits_data(v), nb); -#else - return h ^ memhash32((char*)jl_bits_data(v), nb); -#endif + if (tv == (jl_value_t*)jl_tuple_type) { + uptrint_t h = 0; + size_t l = jl_tuple_len(v); + for(size_t i = 0; i < l; i++) { + uptrint_t u = jl_object_id(jl_tupleref(v,i)); + h = bitmix(h, u); } + return h; } - if (tv == (jl_value_t*)jl_union_kind) { -#ifdef __LP64__ - return jl_object_id(jl_fieldref(v,0))^0xA5A5A5A5A5A5A5A5L; -#else - return jl_object_id(jl_fieldref(v,0))^0xA5A5A5A5; -#endif + jl_datatype_t *dt = (jl_datatype_t*)tv; + if (dt->mutabl) return inthash((uptrint_t)v); + size_t sz = jl_datatype_size(tv); + uptrint_t h = inthash((uptrint_t)tv); + if (sz == 0) return ~h; + size_t nf = jl_tuple_len(dt->names); + if (nf == 0) { + return bits_hash(jl_data_ptr(v), sz) ^ h; } - if (jl_is_struct_type(tv)) - return inthash((uptrint_t)v); - assert(jl_is_tuple(v)); - uptrint_t h = 0; - size_t l = jl_tuple_len(v); - for(size_t i = 0; i < l; i++) { - uptrint_t u = jl_object_id(jl_tupleref(v,i)); + for (size_t f=0; f < nf; f++) { + size_t offs = dt->fields[f].offset; + char *vo = (char*)jl_data_ptr(v) + offs; + uptrint_t u; + if (dt->fields[f].isptr) { + jl_value_t *f = *(jl_value_t**)vo; + u = f==NULL ? 0 : jl_object_id(f); + } + else { + u = bits_hash(vo, dt->fields[f].size); + } h = bitmix(h, u); } return h; @@ -889,6 +994,7 @@ void jl_init_primitives(void) add_builtin_func("isa", jl_f_isa); add_builtin_func("typeassert", jl_f_typeassert); add_builtin_func("apply", jl_f_apply); + add_builtin_func("kwcall", jl_f_kwcall); add_builtin_func("throw", jl_f_throw); add_builtin_func("tuple", jl_f_tuple); add_builtin_func("Union", jl_f_union); @@ -926,12 +1032,9 @@ void jl_init_primitives(void) add_builtin("Tuple", (jl_value_t*)jl_tuple_type); add_builtin("NTuple", (jl_value_t*)jl_ntuple_type); add_builtin("Type", (jl_value_t*)jl_type_type); - add_builtin("...", (jl_value_t*)jl_seq_type); - add_builtin("BitsKind", (jl_value_t*)jl_bits_kind); - add_builtin("CompositeKind", (jl_value_t*)jl_struct_kind); - add_builtin("AbstractKind", (jl_value_t*)jl_tag_kind); - add_builtin("UnionKind", (jl_value_t*)jl_union_kind); - // todo: this should only be visible to compiler components + add_builtin("Vararg", (jl_value_t*)jl_vararg_type); + add_builtin("DataType", (jl_value_t*)jl_datatype_type); + add_builtin("UnionType", (jl_value_t*)jl_uniontype_type); add_builtin("Undef", (jl_value_t*)jl_undef_type); add_builtin("Module", (jl_value_t*)jl_module_type); @@ -955,7 +1058,7 @@ void jl_init_primitives(void) add_builtin("QuoteNode", (jl_value_t*)jl_quotenode_type); add_builtin("TopNode", (jl_value_t*)jl_topnode_type); -#ifdef __LP64__ +#ifdef _P64 add_builtin("Int", (jl_value_t*)jl_int64_type); #else add_builtin("Int", (jl_value_t*)jl_int32_type); diff --git a/src/ccall.cpp b/src/ccall.cpp index 0d3c77b7b5645..7ed9a354abf6a 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -3,6 +3,7 @@ // --- library symbol lookup --- // map from "libX" to full soname "libX.so.ver" +#if defined(__linux__) static std::map sonameMap; static bool got_sonames = false; @@ -46,10 +47,20 @@ extern "C" const char *jl_lookup_soname(char *pfx, size_t n) } return NULL; } +#endif // map from user-specified lib names to handles static std::map libMap; +int add_library_mapping(char *lib, void *hnd) +{ + if(libMap[lib] == NULL && hnd != NULL) { + libMap[lib] = hnd; + return 0; + } else + return -1; +} + static void *add_library_sym(char *name, char *lib) { void *hnd; @@ -59,9 +70,9 @@ static void *add_library_sym(char *name, char *lib) else { hnd = libMap[lib]; if (hnd == NULL) { - hnd = jl_load_dynamic_library(lib); + hnd = jl_load_dynamic_library(lib, JL_RTLD_DEFAULT); if (hnd != NULL) - libMap[lib] = hnd; + libMap[lib] = hnd; else return NULL; } @@ -147,22 +158,27 @@ extern "C" void *jl_value_to_pointer(jl_value_t *jt, jl_value_t *v, int argn, jl_value_t *jvt = (jl_value_t*)jl_typeof(v); if (addressof) { if (jvt == jt) { - assert(jl_is_bits_type(jt)); - size_t osz = jl_bitstype_nbits(jt)/8; - return alloc_temp_arg_copy(jl_bits_data(v), osz); + if (jl_is_bitstype(jvt)) { + size_t osz = jl_datatype_size(jt); + return alloc_temp_arg_copy(jl_data_ptr(v), osz); + } + else if (!jl_is_tuple(jvt) && jl_is_leaf_type(jvt) && !jl_is_array_type(jvt)) { + return v + 1; + } } goto value_to_pointer_error; } else { if (jl_is_cpointer_type(jvt) && jl_tparam0(jvt) == jt) { - return (void*)jl_unbox_long(v); + return (void*)jl_unbox_voidpointer(v); } } + if (((jl_value_t*)jl_uint8_type == jt || (jl_value_t*)jl_int8_type == jt) && jl_is_byte_string(v)) { return jl_string_data(v); } - if (jl_is_array(v)) { + if (jl_is_array_type(jvt)) { if (jl_tparam0(jl_typeof(v)) == jt || jt==(jl_value_t*)jl_bottom_type) return ((jl_array_t*)v)->data; if (jl_is_cpointer_type(jt)) { @@ -176,6 +192,7 @@ extern "C" void *jl_value_to_pointer(jl_value_t *jt, jl_value_t *v, int argn, return temp; } } + value_to_pointer_error: std::map::iterator it = argNumberStrings.find(argn); if (it == argNumberStrings.end()) { @@ -229,6 +246,7 @@ static Value *julia_to_native(Type *ty, jl_value_t *jt, Value *jv, jv = boxed(jv); } else if (jl_is_cpointer_type(jt)) { + assert(ty->isPointerTy()); jl_value_t *aty = expr_type(argex, ctx); if (jl_is_array_type(aty) && (jl_tparam0(jt) == jl_tparam0(aty) || @@ -239,25 +257,51 @@ static Value *julia_to_native(Type *ty, jl_value_t *jt, Value *jv, if (aty == (jl_value_t*)jl_ascii_string_type || aty == (jl_value_t*)jl_utf8_string_type) { return builder.CreateBitCast(emit_arrayptr(emit_nthptr(jv,1)), ty); } + if (jl_is_structtype(aty) && jl_is_leaf_type(aty) && !jl_is_array_type(aty)) { + if (!addressOf) { + emit_error("ccall: expected addressOf operator", ctx); + return literal_pointer_val(jl_nothing); + } + return builder.CreateBitCast(emit_nthptr_addr(jv, (size_t)1), ty); // skip type tag field + } Value *p = builder.CreateCall4(value_to_pointer_func, literal_pointer_val(jl_tparam0(jt)), jv, ConstantInt::get(T_int32, argn), ConstantInt::get(T_int32, (int)addressOf)); - assert(ty->isPointerTy()); return builder.CreateBitCast(p, ty); } + else if (jl_is_structtype(jt)) { + if (addressOf) + jl_error("ccall: unexpected addressOf operator"); // the only "safe" thing to emit here is the expected struct + assert (ty->isStructTy() && (Type*)((jl_datatype_t*)jt)->struct_decl == ty); + jl_value_t *aty = expr_type(argex, ctx); + if (aty != jt) { + std::stringstream msg; + msg << "ccall argument "; + msg << argn; + emit_typecheck(jv, jt, msg.str(), ctx); + } + //TODO: check instead that prefix matches + //if (!jl_is_structtype(aty)) + // emit_typecheck(emit_typeof(jv), (jl_value_t*)jl_struct_kind, "ccall: Struct argument called with something that isn't a struct", ctx); + // //safe thing would be to also check that jl_typeof(aty)->size > sizeof(ty) here and/or at runtime + Value *pjv = builder.CreateBitCast(emit_nthptr_addr(jv, (size_t)1), PointerType::get(ty,0)); + return builder.CreateLoad(pjv, false); + } // TODO: error for & with non-pointer argument type - assert(jl_is_bits_type(jt)); + assert(jl_is_bitstype(jt)); std::stringstream msg; msg << "ccall argument "; msg << argn; emit_typecheck(jv, jt, msg.str(), ctx); - Value *p = bitstype_pointer(jv); + Value *p = data_pointer(jv); return builder.CreateLoad(builder.CreateBitCast(p, PointerType::get(ty,0)), false); } +static jl_value_t *jl_signed_type=NULL; + // --- code generator for ccall itself --- // ccall(pointer, rettype, (argtypes...), args...) @@ -265,10 +309,18 @@ static Value *emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) { JL_NARGSV(ccall, 3); jl_value_t *ptr=NULL, *rt=NULL, *at=NULL; + Value *jl_ptr=NULL; JL_GC_PUSH(&ptr, &rt, &at); - ptr = jl_interpret_toplevel_expr_in(ctx->module, args[1], - &jl_tupleref(ctx->sp,0), - jl_tuple_len(ctx->sp)/2); + ptr = static_eval(args[1], ctx, true); + if (ptr == NULL) { + jl_value_t *ptr_ty = expr_type(args[1], ctx); + Value *arg1 = emit_unboxed(args[1], ctx); + if (!jl_is_cpointer_type(ptr_ty)) { + emit_cpointercheck(arg1, + "ccall: function argument not a pointer or valid, constant expression", ctx); + } + jl_ptr = emit_unbox(T_size, T_psize, arg1); + } rt = jl_interpret_toplevel_expr_in(ctx->module, args[2], &jl_tupleref(ctx->sp,0), jl_tuple_len(ctx->sp)/2); @@ -282,87 +334,110 @@ static Value *emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) jl_tuple_len(ctx->sp)/2); void *fptr=NULL; char *f_name=NULL, *f_lib=NULL; - if (jl_is_tuple(ptr) && jl_tuple_len(ptr)==1) { - ptr = jl_tupleref(ptr,0); - } - if (jl_is_symbol(ptr)) - f_name = ((jl_sym_t*)ptr)->name; - else if (jl_is_byte_string(ptr)) - f_name = jl_string_data(ptr); - if (f_name != NULL) { - // just symbol, default to JuliaDLHandle + if (ptr != NULL) { + if (jl_is_tuple(ptr) && jl_tuple_len(ptr)==1) { + ptr = jl_tupleref(ptr,0); + } + if (jl_is_symbol(ptr)) + f_name = ((jl_sym_t*)ptr)->name; + else if (jl_is_byte_string(ptr)) + f_name = jl_string_data(ptr); + if (f_name != NULL) { + // just symbol, default to JuliaDLHandle #ifdef __WIN32__ - fptr = jl_dlsym_e(jl_dl_handle, f_name); - if (!fptr) { - fptr = jl_dlsym_e(jl_kernel32_handle, f_name); - if (!fptr) { - fptr = jl_dlsym_e(jl_ntdll_handle, f_name); - if (!fptr) { - fptr = jl_dlsym_e(jl_crtdll_handle, f_name); - if (!fptr) { - fptr = jl_dlsym(jl_winsock_handle, f_name); - } - } - } + //TODO: store the f_lib name instead of fptr + fptr = jl_dlsym_win32(f_name); +#else + // will look in process symbol table +#endif + } + else if (jl_is_cpointer_type(jl_typeof(ptr))) { + fptr = *(void**)jl_data_ptr(ptr); + } + else if (jl_is_tuple(ptr) && jl_tuple_len(ptr)>1) { + jl_value_t *t0 = jl_tupleref(ptr,0); + jl_value_t *t1 = jl_tupleref(ptr,1); + if (jl_is_symbol(t0)) + f_name = ((jl_sym_t*)t0)->name; + else if (jl_is_byte_string(t0)) + f_name = jl_string_data(t0); + else + JL_TYPECHK(ccall, symbol, t0); + if (jl_is_symbol(t1)) + f_lib = ((jl_sym_t*)t1)->name; + else if (jl_is_byte_string(t1)) + f_lib = jl_string_data(t1); + else + JL_TYPECHK(ccall, symbol, t1); } else { - // available in process symbol table - fptr = NULL; + JL_TYPECHK(ccall, pointer, ptr); } -#else - // will look in process symbol table -#endif - } - else if (jl_is_cpointer_type(jl_typeof(ptr))) { - fptr = *(void**)jl_bits_data(ptr); - } - else if (jl_is_tuple(ptr) && jl_tuple_len(ptr)>1) { - jl_value_t *t0 = jl_tupleref(ptr,0); - jl_value_t *t1 = jl_tupleref(ptr,1); - if (jl_is_symbol(t0)) - f_name = ((jl_sym_t*)t0)->name; - else if (jl_is_byte_string(t0)) - f_name = jl_string_data(t0); - else - JL_TYPECHK(ccall, symbol, t0); - if (jl_is_symbol(t1)) - f_lib = ((jl_sym_t*)t1)->name; - else if (jl_is_byte_string(t1)) - f_lib = jl_string_data(t1); - else - JL_TYPECHK(ccall, symbol, t1); - } - else { - JL_TYPECHK(ccall, pointer, ptr); } - if (f_name == NULL && fptr == NULL) { + if (f_name == NULL && fptr == NULL && jl_ptr == NULL) { JL_GC_POP(); emit_error("ccall: null function pointer", ctx); return literal_pointer_val(jl_nothing); } + JL_TYPECHK(ccall, type, rt); JL_TYPECHK(ccall, tuple, at); JL_TYPECHK(ccall, type, at); jl_tuple_t *tt = (jl_tuple_t*)at; std::vector fargt(0); std::vector fargt_sig(0); - Type *lrt = julia_type_to_llvm(rt); + Type *lrt = julia_struct_to_llvm(rt); if (lrt == NULL) { JL_GC_POP(); + emit_error("ccall: return type doesn't correspond to a C type", ctx); return literal_pointer_val(jl_nothing); } size_t i; bool haspointers = false; bool isVa = false; - for(i=0; i < jl_tuple_len(tt); i++) { + size_t nargt = jl_tuple_len(tt); + std::vector attrs; + + for(i=0; i < nargt; i++) { jl_value_t *tti = jl_tupleref(tt,i); - if (jl_is_seq_type(tti)) { + if (jl_is_vararg_type(tti)) { isVa = true; tti = jl_tparam0(tti); } - Type *t = julia_type_to_llvm(tti); + if (jl_is_bitstype(tti)) { + // see pull req #978. need to annotate signext/zeroext for + // small integer arguments. + jl_datatype_t *bt = (jl_datatype_t*)tti; + if (bt->size < 4) { + if (jl_signed_type == NULL) { + jl_signed_type = jl_get_global(jl_core_module,jl_symbol("Signed")); + } +#ifdef LLVM32 + Attributes::AttrVal av; + if (jl_signed_type && jl_subtype(tti, jl_signed_type, 0)) + av = Attributes::SExt; + else + av = Attributes::ZExt; + attrs.push_back(AttributeWithIndex::get(getGlobalContext(), i+1, + ArrayRef(&av, 1))); +#else + Attribute::AttrConst av; + if (jl_signed_type && jl_subtype(tti, jl_signed_type, 0)) + av = Attribute::SExt; + else + av = Attribute::ZExt; + attrs.push_back(AttributeWithIndex::get(i+1, av)); +#endif + } + } + Type *t = julia_struct_to_llvm(tti); if (t == NULL) { JL_GC_POP(); + std::stringstream msg; + msg << "ccall: the type of argument "; + msg << i+1; + msg << " doesn't correspond to a C type"; + emit_error(msg.str(), ctx); return literal_pointer_val(jl_nothing); } fargt.push_back(t); @@ -386,6 +461,10 @@ static Value *emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) cc = CallingConv::X86_FastCall; nargs--; } + else if (lhd == jl_symbol("thiscall")) { + cc = CallingConv::X86_ThisCall; + nargs--; + } } if ((!isVa && jl_tuple_len(tt) != (nargs-2)/2) || @@ -394,11 +473,18 @@ static Value *emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) // some special functions if (fptr == &jl_array_ptr) { + assert(lrt->isPointerTy()); Value *ary = emit_expr(args[4], ctx); JL_GC_POP(); return mark_julia_type(builder.CreateBitCast(emit_arrayptr(ary),lrt), rt); } + if (fptr == &jl_value_ptr) { + assert(lrt->isPointerTy()); + Value *ary = emit_expr(args[4], ctx); + JL_GC_POP(); + return mark_julia_type(builder.CreateBitCast(ary,lrt),rt); + } // see if there are & arguments for(i=4; i < nargs+1; i+=2) { @@ -413,22 +499,31 @@ static Value *emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) Value *llvmf; FunctionType *functype = FunctionType::get(lrt, fargt_sig, isVa); - if (fptr != NULL) { + if (jl_ptr != NULL) { + null_pointer_check(jl_ptr,ctx); + Type *funcptype = PointerType::get(functype,0); + llvmf = builder.CreateIntToPtr(jl_ptr, funcptype); + } else if (fptr != NULL) { Type *funcptype = PointerType::get(functype,0); llvmf = literal_pointer_val(fptr, funcptype); } else { - if (f_lib != NULL) { - if (add_library_sym(f_name, f_lib) == NULL) { - JL_GC_POP(); - std::stringstream msg; - msg << "ccall: could not find function "; - msg << f_name; + void *symaddr; + if (f_lib != NULL) + symaddr = add_library_sym(f_name, f_lib); + else + symaddr = sys::DynamicLibrary::SearchForAddressOfSymbol(f_name); + if (symaddr == NULL) { + JL_GC_POP(); + std::stringstream msg; + msg << "ccall: could not find function "; + msg << f_name; + if (f_lib != NULL) { msg << " in library "; msg << f_lib; - emit_error(msg.str(), ctx); - return literal_pointer_val(jl_nothing); } + emit_error(msg.str(), ctx); + return literal_pointer_val(jl_nothing); } llvmf = jl_Module->getOrInsertFunction(f_name, functype); } @@ -467,12 +562,13 @@ static Value *emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) jargty = jl_tupleref(tt,ai); } Value *arg; - if (largty == jl_pvalue_llvmt) { + if (largty == jl_pvalue_llvmt || + largty->isStructTy()) { arg = emit_expr(argi, ctx, true); } else { arg = emit_unboxed(argi, ctx); - if (jl_is_bits_type(expr_type(argi, ctx))) { + if (jl_is_bitstype(expr_type(argi, ctx))) { if (addressOf) arg = emit_unbox(largty->getContainedType(0), largty, arg); else @@ -498,6 +594,11 @@ static Value *emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) if (cc != CallingConv::C) ((CallInst*)result)->setCallingConv(cc); +#ifdef LLVM32 + ((CallInst*)result)->setAttributes(AttrListPtr::get(getGlobalContext(), ArrayRef(attrs))); +#else + ((CallInst*)result)->setAttributes(AttrListPtr::get(attrs.data(),attrs.size())); +#endif // restore temp argument area stack pointer if (haspointers) { assert(saveloc != NULL); @@ -509,11 +610,30 @@ static Value *emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) } ctx->argDepth = last_depth; if (0) { // Enable this to turn on SSPREQ (-fstack-protector) on the function containing this ccall +#ifdef LLVM32 + ctx->f->addFnAttr(Attributes::StackProtectReq); +#else ctx->f->addFnAttr(Attribute::StackProtectReq); +#endif } JL_GC_POP(); if (lrt == T_void) return literal_pointer_val((jl_value_t*)jl_nothing); + if (lrt->isStructTy()) { + //fprintf(stderr, "ccall rt: %s -> %s\n", f_name, ((jl_tag_type_t*)rt)->name->name->name); + assert(jl_is_structtype(rt)); + Value *strct = + builder.CreateCall(jlallocobj_func, + ConstantInt::get(T_size, + sizeof(void*)+((jl_datatype_t*)rt)->size)); + builder.CreateStore(literal_pointer_val((jl_value_t*)rt), + emit_nthptr_addr(strct, (size_t)0)); + builder.CreateStore(result, + builder.CreateBitCast( + emit_nthptr_addr(strct, (size_t)1), + PointerType::get(lrt,0))); + return mark_julia_type(strct, rt); + } return mark_julia_type(result, rt); } diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 5834dc6c0ac17..54a411c5a8e22 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -39,7 +39,7 @@ static GlobalVariable *stringConst(const std::string &txt) static Value *literal_pointer_val(void *p, Type *t) { -#ifdef __LP64__ +#if defined(_P64) return ConstantExpr::getIntToPtr(ConstantInt::get(T_int64, (uint64_t)p), t); #else @@ -60,6 +60,8 @@ static Value *literal_pointer_val(void *p) // --- mapping between julia and llvm types --- +static Type *julia_struct_to_llvm(jl_value_t *jt); + static Type *julia_type_to_llvm(jl_value_t *jt) { if (jt == (jl_value_t*)jl_bool_type) return T_int1; @@ -73,18 +75,53 @@ static Type *julia_type_to_llvm(jl_value_t *jt) lt = T_int8; return PointerType::get(lt, 0); } - if (jl_is_bits_type(jt)) { - int nb = jl_bitstype_nbits(jt); + if (jl_is_bitstype(jt)) { + int nb = jl_datatype_size(jt)*8; if (nb == 8) return T_int8; if (nb == 16) return T_int16; if (nb == 32) return T_int32; if (nb == 64) return T_int64; else return Type::getIntNTy(getGlobalContext(), nb); } + if (jl_isbits(jt)) { + if (((jl_datatype_t*)jt)->size == 0) { + // TODO: come up with a representation for a 0-size value, + // and make this 0 size everywhere. as an argument, simply + // skip passing it. + return jl_pvalue_llvmt; + } + return julia_struct_to_llvm(jt); + } if (jt == (jl_value_t*)jl_bottom_type) return T_void; return jl_pvalue_llvmt; } +static Type *julia_struct_to_llvm(jl_value_t *jt) +{ + if (jl_is_structtype(jt) && !jl_is_array_type(jt)) { + if (!jl_is_leaf_type(jt)) + return NULL; + jl_datatype_t *jst = (jl_datatype_t*)jt; + if (jst->struct_decl == NULL) { + size_t ntypes = jl_tuple_len(jst->types); + if (ntypes == 0) + return NULL; + std::vector latypes(0); + size_t i; + for(i = 0; i < ntypes; i++) { + jl_value_t *ty = jl_tupleref(jst->types, i); + Type *lty = ty==(jl_value_t*)jl_bool_type ? T_int8 : julia_type_to_llvm(ty); + if (jst->fields[i].isptr) + lty = jl_pvalue_llvmt; + latypes.push_back(lty); + } + jst->struct_decl = (void*)StructType::create(latypes, jst->name->name->name); + } + return (Type*)jst->struct_decl; + } + return julia_type_to_llvm(jt); +} + // NOTE: llvm cannot express all julia types (for example unsigned), // so this is an approximation. it's only correct if the associated LLVM // value is not tagged with our value name hack. @@ -173,23 +210,26 @@ static jl_value_t *julia_type_of(Value *v) return jl_typeid_to_type(id); } -static Value *NoOpCast(Value *v) +static Value *NoOpInst(Value *v) { - v = CastInst::Create(Instruction::BitCast, v, v->getType()); + v = SelectInst::Create(ConstantInt::get(T_int1,1), v, v); builder.Insert((Instruction*)v); return v; } static Value *mark_julia_type(Value *v, jl_value_t *jt) { - if (jt == (jl_value_t*)jl_any_type) + if (jt == (jl_value_t*)jl_any_type || v->getType()==jl_pvalue_llvmt) return v; - if (has_julia_type(v) && julia_type_of(v) == jt) - return v; - if (julia_type_of_without_metadata(v,false) == jt) + if (has_julia_type(v)) { + if (julia_type_of(v) == jt) + return v; + } + else if (julia_type_of_without_metadata(v,false) == jt) { return v; + } if (dyn_cast(v) == NULL) - v = NoOpCast(v); + v = NoOpInst(v); assert(dyn_cast(v)); char name[3]; int id = jl_type_to_typeid(jt); @@ -203,7 +243,7 @@ static Value *mark_julia_type(Value *v, jl_value_t *jt) return v; } -static Value *mark_julia_type(Value *v, jl_bits_type_t *jt) +static Value *mark_julia_type(Value *v, jl_datatype_t *jt) { return mark_julia_type(v, (jl_value_t*)jt); } @@ -220,9 +260,16 @@ static Value *emit_typeof(Value *p) tt = builder. CreateLoad(builder.CreateGEP(tt,ConstantInt::get(T_size,0)), false); +#ifdef OVERLAP_TUPLE_LEN + tt = builder. + CreateIntToPtr(builder. + CreateAnd(builder.CreatePtrToInt(tt, T_int64), + ConstantInt::get(T_int64,0x000ffffffffffffe)), + jl_pvalue_llvmt); +#endif return tt; } - return literal_pointer_val(llvm_type_to_julia(p->getType())); + return literal_pointer_val(julia_type_of(p)); } static void emit_error(const std::string &txt, jl_codectx_t *ctx) @@ -280,7 +327,8 @@ static void raise_exception_if(Value *cond, GlobalVariable *exc, static void null_pointer_check(Value *v, jl_codectx_t *ctx) { - raise_exception_unless(builder.CreateICmpNE(v,V_null), jlundeferr_var, ctx); + raise_exception_unless(builder.CreateICmpNE(v,Constant::getNullValue(v->getType())), + jlundeferr_var, ctx); } static Value *boxed(Value *v, jl_value_t *jt=NULL); @@ -338,7 +386,7 @@ static void emit_func_check(Value *x, jl_codectx_t *ctx) literal_pointer_val((jl_value_t*)jl_function_type)), builder. CreateICmpEQ(xty, - literal_pointer_val((jl_value_t*)jl_struct_kind))); + literal_pointer_val((jl_value_t*)jl_datatype_type))); BasicBlock *elseBB1 = BasicBlock::Create(getGlobalContext(),"notf", ctx->f); BasicBlock *mergeBB1 = BasicBlock::Create(getGlobalContext(),"isf"); builder.CreateCondBr(isfunc, mergeBB1, elseBB1); @@ -403,7 +451,7 @@ static Value *typed_store(Value *ptr, Value *idx_0based, Value *rhs, Type *elty = julia_type_to_llvm(jltype); assert(elty != NULL); if (elty==T_int1) { elty = T_int8; } - if (jl_is_bits_type(jltype)) + if (jl_isbits(jltype) && ((jl_datatype_t*)jltype)->size > 0) rhs = emit_unbox(elty, PointerType::get(elty,0), rhs); else rhs = boxed(rhs); @@ -484,7 +532,7 @@ static jl_value_t *expr_type(jl_value_t *e, jl_codectx_t *ctx) return (jl_value_t*)jl_any_type; } type_of_constant: - if (jl_is_some_tag_type(e)) + if (jl_is_datatype(e) || jl_is_uniontype(e) || jl_is_typector(e)) return (jl_value_t*)jl_wrap_Type(e); return (jl_value_t*)jl_typeof(e); } @@ -493,11 +541,13 @@ static jl_value_t *expr_type(jl_value_t *e, jl_codectx_t *ctx) static Value *emit_tuplelen(Value *t) { - Value *lenbits = emit_nthptr(t, 1); -#ifdef __LP64__ - return builder.CreatePtrToInt(lenbits, T_int64); +#ifdef OVERLAP_TUPLE_LEN + Value *lenbits = emit_nthptr(t, (size_t)0); + return builder.CreateLShr(builder.CreatePtrToInt(lenbits, T_int64), + ConstantInt::get(T_int32, 52)); #else - return builder.CreatePtrToInt(lenbits, T_int32); + Value *lenbits = emit_nthptr(t, 1); + return builder.CreatePtrToInt(lenbits, T_size); #endif } @@ -507,7 +557,7 @@ static Value *emit_n_varargs(jl_codectx_t *ctx) int nreq = ctx->nReqArgs; Value *valen = builder.CreateSub((Value*)ctx->argCount, ConstantInt::get(T_int32, nreq)); -#ifdef __LP64__ +#ifdef _P64 return builder.CreateSExt(valen, T_int64); #else return valen; @@ -516,10 +566,18 @@ static Value *emit_n_varargs(jl_codectx_t *ctx) static Value *emit_arraysize(Value *t, Value *dim) { -#ifdef __LP64__ +#ifdef STORE_ARRAY_LEN +#ifdef _P64 int o = 3; #else int o = 4; +#endif +#else +#ifdef _P64 + int o = 2; +#else + int o = 3; +#endif #endif Value *dbits = emit_nthptr(t, builder.CreateAdd(dim, @@ -527,15 +585,57 @@ static Value *emit_arraysize(Value *t, Value *dim) return builder.CreatePtrToInt(dbits, T_size); } +static jl_arrayvar_t *arrayvar_for(jl_value_t *ex, jl_codectx_t *ctx) +{ + if (ex == NULL) return NULL; + char *aname=NULL; + if (jl_is_symbol(ex)) + aname = ((jl_sym_t*)ex)->name; + else if (jl_is_symbolnode(ex)) + aname = jl_symbolnode_sym(ex)->name; + if (aname && ctx->arrayvars->find(aname) != ctx->arrayvars->end()) { + return &(*ctx->arrayvars)[aname]; + } + return NULL; +} + static Value *emit_arraysize(Value *t, int dim) { return emit_arraysize(t, ConstantInt::get(T_int32, dim)); } -static Value *emit_arraylen(Value *t) +static Value *emit_arraylen_prim(Value *t, jl_value_t *ty) { +#ifdef STORE_ARRAY_LEN + (void)ty; Value *lenbits = emit_nthptr(t, 2); return builder.CreatePtrToInt(lenbits, T_size); +#else + jl_value_t *p1 = jl_tparam1(ty); + if (jl_is_long(p1)) { + size_t nd = jl_unbox_long(p1); + Value *l = ConstantInt::get(T_size, 1); + for(size_t i=0; i < nd; i++) { + l = builder.CreateMul(l, emit_arraysize(t, (int)(i+1))); + } + return l; + } + else { + std::vector fargt(0); + fargt.push_back(jl_pvalue_llvmt); + FunctionType *ft = FunctionType::get(T_size, fargt, false); + Value *alen = jl_Module->getOrInsertFunction("jl_array_len_", ft); + return builder.CreateCall(alen, t); + } +#endif +} + +static Value *emit_arraylen(Value *t, jl_value_t *ex, jl_codectx_t *ctx) +{ + jl_arrayvar_t *av = arrayvar_for(ex, ctx); + if (av!=NULL) + return builder.CreateLoad(av->len); + return emit_arraylen_prim(t, expr_type(ex,ctx)); } static Value *emit_arrayptr(Value *t) @@ -543,13 +643,39 @@ static Value *emit_arrayptr(Value *t) return emit_nthptr(t, 1); } -static Value *bitstype_pointer(Value *x) +static Value *emit_arrayptr(Value *t, jl_value_t *ex, jl_codectx_t *ctx) +{ + jl_arrayvar_t *av = arrayvar_for(ex, ctx); + if (av!=NULL) + return builder.CreateLoad(av->dataptr); + return emit_arrayptr(t); +} + +static Value *emit_arraysize(Value *t, jl_value_t *ex, int dim, jl_codectx_t *ctx) +{ + if (dim == 1) { + jl_arrayvar_t *av = arrayvar_for(ex, ctx); + if (av!=NULL) + return builder.CreateLoad(av->nr); + } + return emit_arraysize(t, dim); +} + +static void assign_arrayvar(jl_arrayvar_t &av, Value *ar) +{ + builder.CreateStore(builder.CreateBitCast(emit_arrayptr(ar),T_pint8), + av.dataptr); + builder.CreateStore(emit_arraylen_prim(ar, av.ty), av.len); + builder.CreateStore(emit_arraysize(ar,1), av.nr); +} + +static Value *data_pointer(Value *x) { return builder.CreateGEP(builder.CreateBitCast(x, jl_ppvalue_llvmt), ConstantInt::get(T_size, 1)); } -static Value *emit_array_nd_index(Value *a, size_t nd, jl_value_t **args, +static Value *emit_array_nd_index(Value *a, jl_value_t *ex, size_t nd, jl_value_t **args, size_t nidxs, jl_codectx_t *ctx) { Value *i = ConstantInt::get(T_size, 0); @@ -564,7 +690,7 @@ static Value *emit_array_nd_index(Value *a, size_t nd, jl_value_t **args, i = builder.CreateAdd(i, builder.CreateMul(ii, stride)); if (k < nidxs-1) { Value *d = - k >= nd ? ConstantInt::get(T_size, 1) : emit_arraysize(a, k+1); + k >= nd ? ConstantInt::get(T_size, 1) : emit_arraysize(a, ex, k+1, ctx); #if CHECK_BOUNDS==1 BasicBlock *okBB = BasicBlock::Create(getGlobalContext(), "ib"); // if !(i < d) goto error @@ -576,7 +702,7 @@ static Value *emit_array_nd_index(Value *a, size_t nd, jl_value_t **args, } } #if CHECK_BOUNDS==1 - Value *alen = emit_arraylen(a); + Value *alen = emit_arraylen(a, ex, ctx); // if !(i < alen) goto error builder.CreateCondBr(builder.CreateICmpULT(i, alen), endBB, failBB); @@ -607,7 +733,7 @@ static Value *tpropagate(Value *a, Value *b) static Value *init_bits_value(Value *newv, Value *jt, Type *t, Value *v) { builder.CreateStore(jt, builder.CreateBitCast(newv, jl_ppvalue_llvmt)); - builder.CreateStore(v , builder.CreateBitCast(bitstype_pointer(newv), + builder.CreateStore(v , builder.CreateBitCast(data_pointer(newv), PointerType::get(t,0))); return newv; } @@ -618,7 +744,7 @@ static Value *allocate_box_dynamic(Value *jlty, int nb, Value *v) if (v->getType()->isPointerTy()) { v = builder.CreatePtrToInt(v, T_size); } - size_t sz = sizeof(void*) + (nb+7)/8; + size_t sz = sizeof(void*) + nb; Value *newv = builder.CreateCall(jlallocobj_func, ConstantInt::get(T_size, sz)); // TODO: make sure this is rooted. I think it is. @@ -638,7 +764,8 @@ static Value *boxed(Value *v, jl_value_t *jt) if (t == T_int1) return julia_bool(v); if (jt == NULL) jt = julia_type_of(v); - jl_bits_type_t *jb = (jl_bits_type_t*)jt; + jl_datatype_t *jb = (jl_datatype_t*)jt; + assert(jl_is_datatype(jb)); if (jb == jl_int8_type) return builder.CreateCall(box_int8_func, builder.CreateSExt(v, T_int32)); @@ -649,7 +776,7 @@ static Value *boxed(Value *v, jl_value_t *jt) //if (jb == jl_float64_type) return builder.CreateCall(box_float64_func, v); if (jb == jl_float64_type) { // manually inline alloc & init of Float64 box. cheap, I know. -#ifdef __LP64__ +#ifdef _P64 Value *newv = builder.CreateCall(jlalloc2w_func); #else Value *newv = builder.CreateCall(jlalloc3w_func); @@ -664,10 +791,37 @@ static Value *boxed(Value *v, jl_value_t *jt) if (jb == jl_uint64_type) return builder.CreateCall(box_uint64_func, v); if (jb == jl_char_type) return builder.CreateCall(box_char_func, v); // TODO: skip the call for constant arguments - if (!jl_is_bits_type(jt)) { + if (!jl_isbits(jt)) { assert("Don't know how to box this type" && false); return NULL; } - int nb = jl_bitstype_nbits(jt); - return allocate_box_dynamic(literal_pointer_val(jt), nb, v); + if (!jb->abstract && jb->size == 0) { + if (jb->instance == NULL) + jl_new_struct_uninit(jb); + assert(jb->instance != NULL); + return literal_pointer_val(jb->instance); + } + return allocate_box_dynamic(literal_pointer_val(jt),jl_datatype_size(jt),v); +} + + +static void emit_cpointercheck(Value *x, const std::string &msg, + jl_codectx_t *ctx) +{ + Value *t = emit_typeof(x); + emit_typecheck(t, (jl_value_t*)jl_datatype_type, msg, ctx); + + Value *istype = + builder.CreateICmpEQ(emit_nthptr(t, offsetof(jl_datatype_t,name)/sizeof(char*)), + literal_pointer_val((jl_value_t*)jl_pointer_type->name)); + BasicBlock *failBB = BasicBlock::Create(getGlobalContext(),"fail",ctx->f); + BasicBlock *passBB = BasicBlock::Create(getGlobalContext(),"pass"); + builder.CreateCondBr(istype, passBB, failBB); + builder.SetInsertPoint(failBB); + + emit_type_error(x, (jl_value_t*)jl_pointer_type, msg, ctx); + + builder.CreateBr(passBB); + ctx->f->getBasicBlockList().push_back(passBB); + builder.SetInsertPoint(passBB); } diff --git a/src/codegen.cpp b/src/codegen.cpp index 6b855119c43df..58d5b6258c5da 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -11,21 +11,32 @@ #include "llvm/Intrinsics.h" #include "llvm/PassManager.h" #include "llvm/Analysis/Verifier.h" +#include "llvm/Attributes.h" +#if defined(LLVM_VERSION_MAJOR) && LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 2 +#include "llvm/DebugInfo.h" +#include "llvm/DIBuilder.h" +#include "llvm/IRBuilder.h" +#define LLVM32 +#else #include "llvm/Analysis/DebugInfo.h" #include "llvm/Analysis/DIBuilder.h" #include "llvm/Target/TargetData.h" +#include "llvm/Support/IRBuilder.h" +#endif #include "llvm/Target/TargetOptions.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #if defined(LLVM_VERSION_MAJOR) && LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 1 #include "llvm/Transforms/Vectorize.h" #endif -#include "llvm/Support/IRBuilder.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/DynamicLibrary.h" #include "llvm/Config/llvm-config.h" #include +#ifdef __WIN32__ +#include +#endif #include #include #include @@ -41,6 +52,14 @@ using namespace llvm; extern "C" { #include "julia.h" #include "builtin_proto.h" +void * __stack_chk_guard = NULL; +void __attribute__(()) __stack_chk_fail() +{ + /* put your panic function or similar in here */ + fprintf(stderr, "warning: stack corruption detected\n"); + //assert(0 && "stack corruption detected"); + //abort(); +} } #define CONDITION_REQUIRES_BOOL @@ -82,9 +101,6 @@ static Type *T_pfloat32; static Type *T_float64; static Type *T_pfloat64; static Type *T_void; -#ifdef JL_GC_MARKSWEEP -static Type *T_gcframe; -#endif // constants static Value *V_null; @@ -142,6 +158,9 @@ static Function *box8_func; static Function *box16_func; static Function *box32_func; static Function *box64_func; +#ifdef __WIN32__ +static Function *resetstkoflw_func; +#endif /* stuff to fix up: @@ -155,9 +174,9 @@ static Function *box64_func; // --- entry point --- -static Function *emit_function(jl_lambda_info_t *lam); +static Function *emit_function(jl_lambda_info_t *lam, bool cstyle); //static int n_compile=0; -static Function *to_function(jl_lambda_info_t *li) +static Function *to_function(jl_lambda_info_t *li, bool cstyle) { JL_SIGATOMIC_BEGIN(); assert(!li->inInference); @@ -167,7 +186,7 @@ static Function *to_function(jl_lambda_info_t *li) nested_compile = true; Function *f = NULL; JL_TRY { - f = emit_function(li); + f = emit_function(li, cstyle); } JL_CATCH { li->functionObject = NULL; @@ -233,7 +252,18 @@ extern "C" void jl_compile(jl_function_t *f) if (li->functionObject == NULL) { // objective: assign li->functionObject li->inCompile = 1; - (void)to_function(li); + (void)to_function(li, false); + li->inCompile = 0; + } +} + +void jl_cstyle_compile(jl_function_t *f) +{ + jl_lambda_info_t *li = f->linfo; + if (li->cFunctionObject == NULL) { + // objective: assign li->cFunctionObject + li->inCompile = 1; + (void)to_function(li, true); li->inCompile = 0; } } @@ -266,14 +296,12 @@ const jl_value_t *jl_dump_function(jl_function_t *f, jl_tuple_t *types) llvmf = (Function*)sf->linfo->functionObject; } else { - llvmf = to_function(sf->linfo); + llvmf = to_function(sf->linfo, false); } llvmf->print(stream); return jl_cstr_to_string((char*)stream.str().c_str()); } -static jl_value_t *ast_rettype(jl_value_t *ast); - extern "C" DLLEXPORT void *jl_function_ptr(jl_function_t *f, jl_value_t *rt, jl_value_t *argt) { @@ -282,18 +310,28 @@ void *jl_function_ptr(jl_function_t *f, jl_value_t *rt, jl_value_t *argt) JL_TYPECHK(jl_function_ptr, type, argt); if (jl_is_gf(f) && (jl_is_leaf_type(rt) || rt == (jl_value_t*)jl_bottom_type) && jl_is_leaf_type(argt)) { jl_function_t *ff = jl_get_specialization(f, (jl_tuple_t*)argt); - if (ff != NULL && ff->env == (jl_value_t*)jl_null && ff->linfo != NULL && - ff->linfo->cFunctionObject != NULL) { - jl_lambda_info_t *li = ff->linfo; - jl_value_t *astrt = ast_rettype(li->ast); - if (jl_types_equal((jl_value_t*)li->specTypes, argt) && - (jl_types_equal(astrt, rt) || - (astrt==(jl_value_t*)jl_nothing->type && rt==(jl_value_t*)jl_bottom_type))) { - return jl_ExecutionEngine->getPointerToFunction((Function*)ff->linfo->cFunctionObject); + if (ff != NULL && ff->env==(jl_value_t*)jl_null && ff->linfo != NULL) { + if (ff->linfo->cFunctionObject == NULL) { + jl_cstyle_compile(ff); } - else { - jl_errorf("function_ptr: type signature of %s does not match", - li->name->name); + if (ff->linfo->cFunctionObject != NULL) { + jl_lambda_info_t *li = ff->linfo; + jl_value_t *astrt = jl_ast_rettype(li, li->ast); + if (!jl_types_equal((jl_value_t*)li->specTypes, argt)) { + jl_errorf("cfunction: type signature of %s does not match", + li->name->name); + } + if (!jl_types_equal(astrt, rt) && + !(astrt==(jl_value_t*)jl_nothing->type && rt==(jl_value_t*)jl_bottom_type)) { + if (astrt == (jl_value_t*)jl_bottom_type) { + jl_errorf("cfunction: %s does not return", li->name->name); + } + else { + jl_errorf("cfunction: return type of %s does not match", + li->name->name); + } + } + return jl_ExecutionEngine->getPointerToFunction((Function*)ff->linfo->cFunctionObject); } } } @@ -301,6 +339,13 @@ void *jl_function_ptr(jl_function_t *f, jl_value_t *rt, jl_value_t *argt) return NULL; } +typedef struct { + Value *dataptr; + Value *len; + Value *nr; + jl_value_t *ty; +} jl_arrayvar_t; + // information about the context of a piece of code: its enclosing // function and module, and visible local variables and labels. typedef struct { @@ -312,6 +357,7 @@ typedef struct { std::map *isAssigned; std::map *isCaptured; std::map *escapes; + std::map *arrayvars; std::set *volatilevars; std::map *declTypes; std::map *labels; @@ -323,7 +369,7 @@ typedef struct { Value *envArg; Value *argArray; Value *argCount; - AllocaInst *argTemp; + Instruction *argTemp; int argDepth; int maxDepth; int argSpaceOffs; @@ -338,7 +384,7 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool boxed=true, bool valuepos=true); static Value *emit_unboxed(jl_value_t *e, jl_codectx_t *ctx); static int is_global(jl_sym_t *s, jl_codectx_t *ctx); -static void make_gcroot(Value *v, jl_codectx_t *ctx); +static Value *make_gcroot(Value *v, jl_codectx_t *ctx); static Value *global_binding_pointer(jl_module_t *m, jl_sym_t *s, jl_binding_t **pbnd, bool assign); static Value *emit_checked_var(Value *bp, const char *name, jl_codectx_t *ctx); @@ -402,20 +448,67 @@ static jl_value_t *static_eval(jl_value_t *ex, jl_codectx_t *ctx, bool sparams) if (jl_is_expr(ex)) { jl_expr_t *e = (jl_expr_t*)ex; if (e->head == call_sym || e->head == call1_sym) { - if (e->args->length == 3) { - jl_value_t *f = static_eval(jl_exprarg(e,0),ctx,sparams); - if (f && jl_is_function(f)) { - if (((jl_function_t*)f)->fptr == &jl_f_get_field) { - m = (jl_module_t*)static_eval(jl_exprarg(e,1),ctx,sparams); - s = (jl_sym_t*)static_eval(jl_exprarg(e,2),ctx,sparams); - if (m && jl_is_module(m) && s && jl_is_symbol(s)) { - jl_binding_t *b = jl_get_binding(m, s); - if (b && b->constp) - return b->value; + jl_value_t *f = static_eval(jl_exprarg(e,0),ctx,sparams); + if (f && jl_is_function(f)) { + jl_fptr_t fptr = ((jl_function_t*)f)->fptr; + if (fptr == &jl_apply_generic) { + if (f == jl_get_global(jl_base_module, jl_symbol("dlsym")) || + f == jl_get_global(jl_base_module, jl_symbol("dlopen"))) + { + size_t i; + size_t n = jl_array_dim0(e->args); + jl_value_t **v; + JL_GC_PUSHARGS(v, n); + memset(v, 0, n*sizeof(jl_value_t*)); + v[0] = f; + for (i = 1; i < n; i++) { + v[i] = static_eval(jl_exprarg(e,i),ctx,sparams); + if (v[i] == NULL) { + JL_GC_POP(); + return NULL; + } } + jl_value_t *result = jl_apply_generic(f, v+1, (uint32_t)n-1); + JL_GC_POP(); + return result; + } + } else if (jl_array_dim0(e->args) == 3 && fptr == &jl_f_get_field) { + m = (jl_module_t*)static_eval(jl_exprarg(e,1),ctx,sparams); + s = (jl_sym_t*)static_eval(jl_exprarg(e,2),ctx,sparams); + if (m && jl_is_module(m) && s && jl_is_symbol(s)) { + jl_binding_t *b = jl_get_binding(m, s); + if (b && b->constp) + return b->value; + } + } else if (fptr == &jl_f_tuple) { + size_t i; + size_t n = jl_array_dim0(e->args)-1; + if (n==0) return (jl_value_t*)jl_null; + jl_value_t **v; + JL_GC_PUSHARGS(v, n); + memset(v, 0, n*sizeof(jl_value_t*)); + for (i = 0; i < n; i++) { + v[i] = static_eval(jl_exprarg(e,i+1),ctx,sparams); + if (v[i] == NULL) { + JL_GC_POP(); + return NULL; + } + } + jl_tuple_t *tup = jl_alloc_tuple_uninit(n); + for(i=0; i < n; i++) { + jl_tupleset(tup, i, v[i]); } + JL_GC_POP(); + return (jl_value_t*)tup; } } + // The next part is probably valid, but it is untested + //} else if (e->head == tuple_sym) { + // size_t i; + // for (i = 0; i < jl_array_dim0(e->args); i++) + // if (static_eval(jl_exprarg(e,i), ctx, sparams) == NULL) + // return NULL; + // return ex; } return NULL; } @@ -445,7 +538,8 @@ static bool local_var_occurs(jl_value_t *e, jl_sym_t *s) } else if (jl_is_expr(e)) { jl_expr_t *ex = (jl_expr_t*)e; - for(int i=0; i < (int)ex->args->length; i++) { + size_t alength = jl_array_dim0(ex->args); + for(int i=0; i < (int)alength; i++) { if (local_var_occurs(jl_exprarg(ex,i),s)) return true; } @@ -461,7 +555,8 @@ static std::set assigned_in_try(jl_array_t *stmts, int s, long l, int *pend) { std::set av; - for(int i=s; i < (int)stmts->length; i++) { + size_t slength = jl_array_dim0(stmts); + for(int i=s; i < (int)slength; i++) { jl_value_t *st = jl_arrayref(stmts,i); if (jl_is_expr(st)) { if (((jl_expr_t*)st)->head == assign_sym) { @@ -490,15 +585,16 @@ static std::set assigned_in_try(jl_array_t *stmts, int s, long l, static std::set find_volatile_vars(jl_array_t *stmts) { std::set vv; - for(int i=0; i < (int)stmts->length; i++) { + size_t slength = jl_array_dim0(stmts); + for(int i=0; i < (int)slength; i++) { jl_value_t *st = jl_arrayref(stmts,i); if (jl_is_expr(st)) { if (((jl_expr_t*)st)->head == enter_sym) { - int last = (int)stmts->length-1; + int last = (int)slength-1; std::set as = assigned_in_try(stmts, i+1, jl_unbox_long(jl_exprarg(st,0)), &last); - for(int j=0; j < (int)stmts->length; j++) { + for(int j=0; j < (int)slength; j++) { if (j < i || j > last) { std::set::iterator it = as.begin(); for(; it != as.end(); it++) { @@ -533,8 +629,8 @@ static void max_arg_depth(jl_value_t *expr, int32_t *max, int32_t *sp, esc = true; jl_expr_t *e = (jl_expr_t*)expr; size_t i; - if (e->head == call_sym || e->head == call1_sym) { - int alen = e->args->length; + if (e->head == call_sym || e->head == call1_sym || e->head == new_sym) { + int alen = jl_array_dim0(e->args); int lastsp = *sp; jl_value_t *f = jl_exprarg(e,0); if (expr_is_symbol(f)) { @@ -554,7 +650,8 @@ static void max_arg_depth(jl_value_t *expr, int32_t *max, int32_t *sp, } else { esc = true; - // first 3 arguments are static + // 2nd and 3d arguments are static + max_arg_depth(jl_exprarg(e,1), max, sp, esc, ctx); for(i=4; i < (size_t)alen; i++) { max_arg_depth(jl_exprarg(e,i), max, sp, esc, ctx); } @@ -581,9 +678,14 @@ static void max_arg_depth(jl_value_t *expr, int32_t *max, int32_t *sp, (*sp)++; if (*sp > *max) *max = *sp; } + if (e->head == new_sym && *max < 1) + *max = 1; (*sp) = lastsp; } else if (e->head == method_sym) { + int lastsp = *sp; + if (jl_is_expr(jl_exprarg(e,0))) + (*sp)++; max_arg_depth(jl_exprarg(e,1), max, sp, esc, ctx); (*sp)++; if (*sp > *max) *max = *sp; @@ -593,10 +695,11 @@ static void max_arg_depth(jl_value_t *expr, int32_t *max, int32_t *sp, max_arg_depth(jl_exprarg(e,3), max, sp, esc, ctx); (*sp)++; if (*sp > *max) *max = *sp; - (*sp)-=2; + (*sp) = lastsp; } else { - for(i=0; i < e->args->length; i++) { + size_t elen = jl_array_dim0(e->args); + for(i=0; i < elen; i++) { max_arg_depth(jl_exprarg(e,i), max, sp, esc, ctx); } } @@ -619,7 +722,7 @@ static void max_arg_depth(jl_value_t *expr, int32_t *max, int32_t *sp, } } -static void make_gcroot(Value *v, jl_codectx_t *ctx) +static Value *make_gcroot(Value *v, jl_codectx_t *ctx) { Value *froot = builder.CreateGEP(ctx->argTemp, ConstantInt::get(T_size, @@ -629,28 +732,21 @@ static void make_gcroot(Value *v, jl_codectx_t *ctx) ctx->argDepth++; if (ctx->argDepth > ctx->maxDepth) ctx->maxDepth = ctx->argDepth; + return froot; } // --- lambda --- -extern "C" jl_value_t *jl_uncompress_ast(jl_tuple_t *data); - -static jl_value_t *ast_rettype(jl_value_t *ast) -{ - if (jl_is_tuple(ast)) - return jl_tupleref(ast, 2); - assert(jl_is_expr(ast)); - return jl_lam_body((jl_expr_t*)ast)->etype; -} - static void jl_add_linfo_root(jl_lambda_info_t *li, jl_value_t *val) { + li = li->def; if (li->roots == NULL) { li->roots = jl_alloc_cell_1d(1); jl_cellset(li->roots, 0, val); } else { - for(size_t i=0; i < li->roots->length; i++) { + size_t rlen = jl_array_dim0(li->roots); + for(size_t i=0; i < rlen; i++) { if (jl_arrayref(li->roots,i) == val) return; } @@ -663,8 +759,12 @@ static Value *emit_lambda_closure(jl_value_t *expr, jl_codectx_t *ctx) assert(jl_is_lambda_info(expr)); size_t i; jl_value_t *ast = ((jl_lambda_info_t*)expr)->ast; - jl_array_t *capt = jl_lam_capt((jl_expr_t*)ast); - if (capt->length == 0) { + jl_array_t *capt; + if (jl_is_expr(ast)) + capt = jl_lam_capt((jl_expr_t*)ast); + else + capt = (jl_array_t*)((jl_lambda_info_t*)expr)->capt; + if (capt == NULL || jl_array_dim0(capt) == 0) { // no captured vars; lift jl_value_t *fun = (jl_value_t*)jl_new_closure(NULL, (jl_value_t*)jl_null, @@ -674,9 +774,10 @@ static Value *emit_lambda_closure(jl_value_t *expr, jl_codectx_t *ctx) } int argStart = ctx->argDepth; - Value *captured[1+capt->length]; - captured[0] = ConstantInt::get(T_size, capt->length); - for(i=0; i < capt->length; i++) { + size_t clen = jl_array_dim0(capt); + Value *captured[1+clen]; + captured[0] = ConstantInt::get(T_size, clen); + for(i=0; i < clen; i++) { Value *val; jl_array_t *vi = (jl_array_t*)jl_cellref(capt, i); assert(jl_is_array(vi)); @@ -685,7 +786,11 @@ static Value *emit_lambda_closure(jl_value_t *expr, jl_codectx_t *ctx) std::map::iterator it = ctx->closureEnv->find(s->name); if (it != ctx->closureEnv->end()) { int idx = (*it).second; +#ifdef OVERLAP_TUPLE_LEN + val = emit_nthptr((Value*)ctx->envArg, idx+1); +#else val = emit_nthptr((Value*)ctx->envArg, idx+2); +#endif } else { Value *l = (*ctx->vars)[s->name]; @@ -706,7 +811,7 @@ static Value *emit_lambda_closure(jl_value_t *expr, jl_codectx_t *ctx) Value *env_tuple; env_tuple = builder.CreateCall(jlntuple_func, ArrayRef(&captured[0], - 1+capt->length)); + 1+clen)); ctx->argDepth = argStart; make_gcroot(env_tuple, ctx); Value *result = builder.CreateCall3(jlclosure_func, @@ -747,19 +852,40 @@ static Value *emit_getfield(jl_value_t *expr, jl_sym_t *name, jl_codectx_t *ctx) return emit_checked_var(bp, name->name, ctx); } - jl_struct_type_t *sty = (jl_struct_type_t*)expr_type(expr, ctx); + jl_datatype_t *sty = (jl_datatype_t*)expr_type(expr, ctx); JL_GC_PUSH(&sty); - if (jl_is_struct_type(sty) && sty != jl_module_type && sty->uid != 0) { - size_t idx = jl_field_index(sty, name, 0); - if (idx != (size_t)-1) { - Value *strct = emit_expr(expr, ctx); - Value *addr = - builder.CreateGEP(builder.CreateBitCast(strct, T_pint8), - ConstantInt::get(T_size, - sty->fields[idx].offset + sizeof(void*))); + if (jl_is_structtype(sty) && sty != jl_module_type && sty->uid != 0) { + unsigned idx = jl_field_index(sty, name, 0); + if (idx != (unsigned)-1) { jl_value_t *jfty = jl_tupleref(sty->types, idx); - JL_GC_POP(); - return typed_load(addr, ConstantInt::get(T_size, 0), jfty, ctx); + Value *strct = emit_expr(expr, ctx); + if (strct->getType() == jl_pvalue_llvmt) { + Value *addr = + builder.CreateGEP(builder.CreateBitCast(strct, T_pint8), + ConstantInt::get(T_size, + sty->fields[idx].offset + sizeof(void*))); + JL_GC_POP(); + if (sty->fields[idx].isptr) { + Value *fldv = builder.CreateLoad(builder.CreateBitCast(addr,jl_ppvalue_llvmt)); + null_pointer_check(fldv, ctx); + return fldv; + } + else { + return typed_load(addr, ConstantInt::get(T_size, 0), jfty, ctx); + } + } + else { + Value *fldv = builder. + CreateExtractValue(strct, ArrayRef(&idx,1)); + if (jfty == (jl_value_t*)jl_bool_type) { + fldv = builder.CreateTrunc(fldv, T_int1); + } + else if (sty->fields[idx].isptr) { + null_pointer_check(fldv, ctx); + } + JL_GC_POP(); + return mark_julia_type(fldv, jfty); + } } } // TODO: attempt better codegen for approximate types, if the types @@ -779,14 +905,96 @@ static Value *emit_getfield(jl_value_t *expr, jl_sym_t *name, jl_codectx_t *ctx) return result; } -static void emit_setfield(jl_struct_type_t *sty, Value *strct, size_t idx, - Value *rhs, jl_codectx_t *ctx) +static void emit_setfield(jl_datatype_t *sty, Value *strct, size_t idx, + Value *rhs, jl_codectx_t *ctx, bool checked=true) +{ + if (sty->mutabl || !checked) { + Value *addr = + builder.CreateGEP(builder.CreateBitCast(strct, T_pint8), + ConstantInt::get(T_size, sty->fields[idx].offset + sizeof(void*))); + jl_value_t *jfty = jl_tupleref(sty->types, idx); + if (sty->fields[idx].isptr) { + builder.CreateStore(boxed(rhs), + builder.CreateBitCast(addr, jl_ppvalue_llvmt)); + } + else { + typed_store(addr, ConstantInt::get(T_size, 0), rhs, jfty, ctx); + } + } + else { + // TODO: better error + emit_error("type is immutable", ctx); + } +} + +// emit code for is (===). rt1 and rt2 are the julia types of the arguments, +// arg1 and arg2 are expressions for the arguments if we have them, or NULL, +// and varg1 and varg2 are LLVM values for the arguments if we have them. +static Value *emit_f_is(jl_value_t *rt1, jl_value_t *rt2, + jl_value_t *arg1, jl_value_t *arg2, + Value *varg1, Value *varg2, jl_codectx_t *ctx) { - Value *addr = - builder.CreateGEP(builder.CreateBitCast(strct, T_pint8), - ConstantInt::get(T_size, sty->fields[idx].offset + sizeof(void*))); - jl_value_t *jfty = jl_tupleref(sty->types, idx); - typed_store(addr, ConstantInt::get(T_size, 0), rhs, jfty, ctx); + if (jl_is_type_type(rt1) && jl_is_type_type(rt2) && + !jl_is_typevar(jl_tparam0(rt1)) && !jl_is_typevar(jl_tparam0(rt2)) && + (!arg1 || is_constant(arg1, ctx)) && + (!arg2 || is_constant(arg2, ctx))) { + if (jl_tparam0(rt1) == jl_tparam0(rt2)) + return ConstantInt::get(T_int1, 1); + return ConstantInt::get(T_int1, 0); + } + int ptr_comparable = 0; + if (rt1==(jl_value_t*)jl_sym_type || rt2==(jl_value_t*)jl_sym_type || + jl_is_mutable_datatype(rt1) || jl_is_mutable_datatype(rt2)) + ptr_comparable = 1; + int last_depth = ctx->argDepth; + if (arg1 && !varg1) { + varg1 = emit_expr(arg1, ctx); + if (arg2 && !varg2 && varg1->getType() == jl_pvalue_llvmt) { + make_gcroot(varg1, ctx); + } + } + Value *answer; + if (arg2 && !varg2) + varg2 = emit_expr(arg2, ctx); + Type *at1 = varg1->getType(); + Type *at2 = varg2->getType(); + if (at1 != jl_pvalue_llvmt && at2 != jl_pvalue_llvmt) { + if (julia_type_of(varg1) != julia_type_of(varg2)) { + answer = ConstantInt::get(T_int1, 0); + goto done; + } + if (at1 == at2) { + if (at1->isIntegerTy() || at1->isPointerTy() || + at1->isFloatingPointTy()) { + answer = builder.CreateICmpEQ(JL_INT(varg1),JL_INT(varg2)); + goto done; + } + if (at1->isStructTy() && !ptr_comparable) { + // TODO: tuples + jl_datatype_t *sty = (jl_datatype_t*)rt1; + assert(jl_is_datatype(sty)); + answer = ConstantInt::get(T_int1, 1); + for(unsigned i=0; i < jl_tuple_len(sty->names); i++) { + jl_value_t *fldty = jl_tupleref(sty->types,i); + Value *subAns = + emit_f_is(fldty, fldty, NULL, NULL, + builder.CreateExtractValue(varg1, ArrayRef(&i,1)), + builder.CreateExtractValue(varg2, ArrayRef(&i,1)), + ctx); + answer = builder.CreateAnd(answer, subAns); + } + goto done; + } + } + } + varg1 = boxed(varg1); varg2 = boxed(varg2); + if (ptr_comparable) + answer = builder.CreateICmpEQ(varg1, varg2); + else + answer = builder.CreateTrunc(builder.CreateCall2(jlegal_func, varg1, varg2), T_int1); + done: + ctx->argDepth = last_depth; + return answer; } static Value *emit_known_call(jl_value_t *ff, jl_value_t **args, size_t nargs, @@ -795,7 +1003,7 @@ static Value *emit_known_call(jl_value_t *ff, jl_value_t **args, size_t nargs, jl_value_t *expr) { if (jl_typeis(ff, jl_intrinsic_type)) { - return emit_intrinsic((intrinsic)*(uint32_t*)jl_bits_data(ff), + return emit_intrinsic((intrinsic)*(uint32_t*)jl_data_ptr(ff), args, nargs, ctx); } if (!jl_is_func(ff)) { @@ -829,36 +1037,11 @@ static Value *emit_known_call(jl_value_t *ff, jl_value_t **args, size_t nargs, } } else if (f->fptr == &jl_f_is && nargs==2) { - jl_value_t *rt1 = expr_type(args[1], ctx); - jl_value_t *rt2 = expr_type(args[2], ctx); - if (jl_is_type_type(rt1) && jl_is_type_type(rt2) && - !jl_is_typevar(jl_tparam0(rt1)) && - !jl_is_typevar(jl_tparam0(rt2)) && - is_constant(args[1], ctx) && is_constant(args[2], ctx)) { - JL_GC_POP(); - if (jl_tparam0(rt1) == jl_tparam0(rt2)) - return ConstantInt::get(T_int1, 1); - return ConstantInt::get(T_int1, 0); - } + rt1 = expr_type(args[1], ctx); + rt2 = expr_type(args[2], ctx); + Value *ans = emit_f_is(rt1,rt2, args[1],args[2], NULL,NULL, ctx); JL_GC_POP(); - int ptr_comparable = 0; - if (rt1==(jl_value_t*)jl_sym_type || rt2==(jl_value_t*)jl_sym_type || - jl_is_struct_type(rt1) || jl_is_struct_type(rt2)) - ptr_comparable = 1; - Value *arg1 = emit_expr(args[1], ctx); - Value *arg2 = emit_expr(args[2], ctx); - if (arg1->getType() != jl_pvalue_llvmt && - arg2->getType() != jl_pvalue_llvmt) { - if (julia_type_of(arg1) != julia_type_of(arg2)) { - return ConstantInt::get(T_int1, 0); - } - return builder.CreateICmpEQ(JL_INT(arg1),JL_INT(arg2)); - } - arg1 = boxed(arg1); arg2 = boxed(arg2); - if (ptr_comparable) - return builder.CreateICmpEQ(arg1, arg2); - else - return builder.CreateTrunc(builder.CreateCall2(jlegal_func, arg1, arg2), T_int1); + return ans; } else if (f->fptr == &jl_f_typeof && nargs==1) { jl_value_t *aty = expr_type(args[1], ctx); rt1 = aty; @@ -872,7 +1055,7 @@ static Value *emit_known_call(jl_value_t *ff, jl_value_t **args, size_t nargs, } Value *arg1 = boxed(emit_expr(args[1], ctx)); JL_GC_POP(); - return emit_nthptr(arg1, (size_t)0); + return emit_typeof(arg1); } } else if (f->fptr == &jl_f_typeassert && nargs==2) { @@ -882,7 +1065,17 @@ static Value *emit_known_call(jl_value_t *ff, jl_value_t **args, size_t nargs, jl_value_t *tp0 = jl_tparam0(ty); if (jl_subtype(arg, tp0, 0)) { JL_GC_POP(); - return emit_expr(args[1], ctx); + Value *v = emit_expr(args[1], ctx); + if (tp0 == jl_bottom_type) { + return builder.CreateUnreachable(); + } + return v; + } + if (tp0 == jl_bottom_type) { + emit_expr(args[1], ctx); + emit_error("reached code declared unreachable", ctx); + JL_GC_POP(); + return builder.CreateUnreachable(); } if (!jl_is_tuple(tp0) && jl_is_leaf_type(tp0)) { Value *arg1 = emit_expr(args[1], ctx); @@ -891,6 +1084,23 @@ static Value *emit_known_call(jl_value_t *ff, jl_value_t **args, size_t nargs, return arg1; } } + if (jl_subtype(ty, (jl_value_t*)jl_type_type, 0)) { + std::vector fargt(0); + fargt.push_back(jl_pvalue_llvmt); + fargt.push_back(jl_pvalue_llvmt); + FunctionType *ft = FunctionType::get(T_void, fargt, false); + Value *typeassert = jl_Module->getOrInsertFunction("jl_typeassert", ft); + Value *arg1 = emit_expr(args[1], ctx); + int ldepth = ctx->argDepth; + if (arg1->getType() != jl_pvalue_llvmt) { + arg1 = boxed(arg1); + make_gcroot(arg1, ctx); + } + builder.CreateCall2(typeassert, arg1, boxed(emit_expr(args[2], ctx))); + ctx->argDepth = ldepth; + JL_GC_POP(); + return arg1; + } } else if (f->fptr == &jl_f_isa && nargs==2) { jl_value_t *arg = expr_type(args[1], ctx); rt1 = arg; @@ -947,12 +1157,16 @@ static Value *emit_known_call(jl_value_t *ff, jl_value_t **args, size_t nargs, if (jl_is_long(args[2])) { size_t tlen = jl_tuple_len(tty); int isseqt = - tlen>0 && jl_is_seq_type(jl_tupleref(tty, tlen-1)); + tlen>0 && jl_is_vararg_type(jl_tupleref(tty, tlen-1)); size_t idx = jl_unbox_long(args[2]); if (idx > 0 && (idx < tlen || (idx == tlen && !isseqt))) { // known to be in bounds JL_GC_POP(); +#ifdef OVERLAP_TUPLE_LEN + return emit_nthptr(arg1, idx); +#else return emit_nthptr(arg1, idx+1); +#endif } if (idx==0 || (!isseqt && idx > tlen)) { builder.CreateCall2(jlthrow_line_func, @@ -967,8 +1181,12 @@ static Value *emit_known_call(jl_value_t *ff, jl_value_t **args, size_t nargs, emit_unboxed(args[2], ctx)); emit_bounds_check(idx, tlen, ctx); JL_GC_POP(); +#ifdef OVERLAP_TUPLE_LEN + return emit_nthptr(arg1, idx); +#else return emit_nthptr(arg1, builder.CreateAdd(idx, ConstantInt::get(T_size,1))); +#endif } } else if (f->fptr == &jl_f_tuple) { @@ -978,7 +1196,9 @@ static Value *emit_known_call(jl_value_t *ff, jl_value_t **args, size_t nargs, } size_t i; for(i=0; i < nargs; i++) { - if (!jl_is_bits_type(jl_typeof(args[i+1]))) + jl_value_t *it = (jl_value_t*)jl_typeof(args[i+1]); + if (!(jl_is_immutable_datatype(it) && + it!=(jl_value_t*)jl_quotenode_type && it!=(jl_value_t*)jl_topnode_type)) break; } if (i >= nargs) { @@ -998,24 +1218,46 @@ static Value *emit_known_call(jl_value_t *ff, jl_value_t **args, size_t nargs, // first, then do hand-over-hand to track the tuple. Value *arg1 = boxed(emit_expr(args[1], ctx)); make_gcroot(arg1, ctx); +#ifdef OVERLAP_TUPLE_LEN + size_t nwords = nargs+1; +#else + size_t nwords = nargs+2; +#endif Value *tup = builder.CreateCall(jlallocobj_func, - ConstantInt::get(T_size, - sizeof(void*)*(nargs+2))); + ConstantInt::get(T_size, sizeof(void*)*nwords)); +#ifdef OVERLAP_TUPLE_LEN + builder.CreateStore(arg1, emit_nthptr_addr(tup, 1)); +#else builder.CreateStore(arg1, emit_nthptr_addr(tup, 2)); +#endif ctx->argDepth--; make_gcroot(tup, ctx); +#ifdef OVERLAP_TUPLE_LEN + builder. + CreateStore(builder. + CreateOr(builder.CreatePtrToInt(literal_pointer_val((jl_value_t*)jl_tuple_type), T_int64), + ConstantInt::get(T_int64, nargs<<52)), + builder.CreateBitCast(emit_nthptr_addr(tup, (size_t)0), + T_pint64)); +#else builder.CreateStore(literal_pointer_val((jl_value_t*)jl_tuple_type), emit_nthptr_addr(tup, (size_t)0)); builder.CreateStore(literal_pointer_val((jl_value_t*)nargs), emit_nthptr_addr(tup, (size_t)1)); +#endif +#ifdef OVERLAP_TUPLE_LEN + size_t offs = 1; +#else + size_t offs = 2; +#endif for(i=1; i < nargs; i++) { builder.CreateStore(V_null, - emit_nthptr_addr(tup, i+2)); + emit_nthptr_addr(tup, i+offs)); } for(i=1; i < nargs; i++) { builder.CreateStore(boxed(emit_expr(args[i+1], ctx)), - emit_nthptr_addr(tup, i+2)); + emit_nthptr_addr(tup, i+offs)); } ctx->argDepth = last_depth; JL_GC_POP(); @@ -1034,7 +1276,7 @@ static Value *emit_known_call(jl_value_t *ff, jl_value_t **args, size_t nargs, // todo: also allow e.g. Union of several array types Value *arg1 = emit_expr(args[1], ctx); JL_GC_POP(); - return emit_arraylen(arg1); + return emit_arraylen(arg1, args[1], ctx); } } else if (f->fptr == &jl_f_arraysize && nargs==2) { @@ -1049,7 +1291,7 @@ static Value *emit_known_call(jl_value_t *ff, jl_value_t **args, size_t nargs, uint32_t idx = (uint32_t)jl_unbox_long(args[2]); if (idx > 0 && idx <= ndims) { JL_GC_POP(); - return emit_arraysize(ary, idx); + return emit_arraysize(ary, args[1], idx, ctx); } else if (idx > ndims) { JL_GC_POP(); @@ -1097,15 +1339,20 @@ static Value *emit_known_call(jl_value_t *ff, jl_value_t **args, size_t nargs, if (jl_is_array_type(aty) && indexes_ok) { jl_value_t *ety = jl_tparam0(aty); if (!jl_is_typevar(ety)) { - if (!jl_is_bits_type(ety)) + if (!jl_array_store_unboxed(ety)) ety = (jl_value_t*)jl_any_type; jl_value_t *ndp = jl_tparam1(aty); if (jl_is_long(ndp) || nargs==2) { Value *ary = emit_expr(args[1], ctx); size_t nd = jl_is_long(ndp) ? jl_unbox_long(ndp) : 1; - Value *idx = emit_array_nd_index(ary, nd, &args[2], nargs-1, ctx); + Value *idx = emit_array_nd_index(ary, args[1], nd, &args[2], nargs-1, ctx); JL_GC_POP(); - return typed_load(emit_arrayptr(ary), idx, ety, ctx); + if (jl_array_store_unboxed(ety) && + ((jl_datatype_t*)ety)->size == 0) { + jl_new_struct_uninit((jl_datatype_t*)ety); + return literal_pointer_val(((jl_datatype_t*)ety)->instance); + } + return typed_load(emit_arrayptr(ary, args[1], ctx), idx, ety, ctx); } } } @@ -1122,15 +1369,22 @@ static Value *emit_known_call(jl_value_t *ff, jl_value_t **args, size_t nargs, if (jl_is_array_type(aty) && indexes_ok) { jl_value_t *ety = jl_tparam0(aty); if (!jl_is_typevar(ety) && jl_subtype(vty, ety, 0)) { - if (!jl_is_bits_type(ety)) + if (!jl_array_store_unboxed(ety)) ety = (jl_value_t*)jl_any_type; jl_value_t *ndp = jl_tparam1(aty); if (jl_is_long(ndp) || nargs==3) { Value *ary = emit_expr(args[1], ctx); size_t nd = jl_is_long(ndp) ? jl_unbox_long(ndp) : 1; - Value *idx = emit_array_nd_index(ary, nd, &args[3], nargs-2, ctx); - typed_store(emit_arrayptr(ary), idx, - emit_unboxed(args[2],ctx), ety, ctx); + Value *idx = emit_array_nd_index(ary, args[1], nd, &args[3], nargs-2, ctx); + if (jl_array_store_unboxed(ety) && + ((jl_datatype_t*)ety)->size == 0) { + // no-op + } + else { + typed_store(emit_arrayptr(ary,args[1],ctx), idx, + ety==(jl_value_t*)jl_any_type ? emit_expr(args[2],ctx) : emit_unboxed(args[2],ctx), + ety, ctx); + } JL_GC_POP(); return ary; } @@ -1146,9 +1400,9 @@ static Value *emit_known_call(jl_value_t *ff, jl_value_t **args, size_t nargs, } } else if (f->fptr == &jl_f_set_field && nargs==3) { - jl_struct_type_t *sty = (jl_struct_type_t*)expr_type(args[1], ctx); + jl_datatype_t *sty = (jl_datatype_t*)expr_type(args[1], ctx); rt1 = (jl_value_t*)sty; - if (jl_is_struct_type(sty) && sty != jl_module_type && + if (jl_is_structtype(sty) && sty != jl_module_type && jl_is_quotenode(args[2]) && jl_is_symbol(jl_fieldref(args[2],0))) { size_t idx = jl_field_index(sty, (jl_sym_t*)jl_fieldref(args[2],0), 0); @@ -1193,6 +1447,32 @@ static Value *emit_known_call(jl_value_t *ff, jl_value_t **args, size_t nargs, return NULL; } +static Value *emit_jlcall(Value *theFptr, Value *theF, jl_value_t **args, + size_t nargs, jl_codectx_t *ctx) +{ + // emit arguments + int argStart = ctx->argDepth; + for(size_t i=0; i < nargs; i++) { + Value *anArg = emit_expr(args[i], ctx); + // put into argument space + make_gcroot(boxed(anArg), ctx); + } + + // call + Value *myargs; + if (ctx->argTemp != NULL && nargs > 0) { + myargs = builder.CreateGEP(ctx->argTemp, + ConstantInt::get(T_size, argStart+ctx->argSpaceOffs)); + } + else { + myargs = Constant::getNullValue(jl_ppvalue_llvmt); + } + Value *result = builder.CreateCall3(theFptr, theF, myargs, + ConstantInt::get(T_int32,nargs)); + ctx->argDepth = argStart; + return result; +} + static Value *emit_call(jl_value_t **args, size_t arglen, jl_codectx_t *ctx, jl_value_t *expr) { @@ -1227,13 +1507,13 @@ static Value *emit_call(jl_value_t **args, size_t arglen, jl_codectx_t *ctx, } #endif if (hdtype!=(jl_value_t*)jl_function_type && - hdtype!=(jl_value_t*)jl_struct_kind && + hdtype!=(jl_value_t*)jl_datatype_type && !(jl_is_type_type(hdtype) && - jl_is_struct_type(jl_tparam0(hdtype)))) { + jl_is_datatype(jl_tparam0(hdtype)))) { emit_func_check(theFunc, ctx); } // extract pieces of the function object - // TODO: try extractelement instead + // TODO: try extractvalue instead theFptr = builder.CreateBitCast(emit_nthptr(theFunc, 1), jl_fptr_llvmt); theF = theFunc; } @@ -1268,29 +1548,11 @@ static Value *emit_call(jl_value_t **args, size_t arglen, jl_codectx_t *ctx, result = literal_pointer_val((jl_value_t*)jl_nothing); } else { - result = mark_julia_type(result, ast_rettype(f->linfo->ast)); + result = mark_julia_type(result, jl_ast_rettype(f->linfo, f->linfo->ast)); } } else { - // emit arguments - int argStart = ctx->argDepth; - for(size_t i=0; i < nargs; i++) { - Value *anArg = emit_expr(args[i+1], ctx); - // put into argument space - make_gcroot(boxed(anArg), ctx); - } - - // call - Value *myargs; - if (ctx->argTemp != NULL) { - myargs = builder.CreateGEP(ctx->argTemp, - ConstantInt::get(T_size, argStart+ctx->argSpaceOffs)); - } - else { - myargs = Constant::getNullValue(jl_ppvalue_llvmt); - } - result = builder.CreateCall3(theFptr, theF, myargs, - ConstantInt::get(T_int32,nargs)); + result = emit_jlcall(theFptr, theF, &args[1], nargs, ctx); } ctx->argDepth = last_depth; @@ -1329,9 +1591,17 @@ static Value *var_binding_pointer(jl_sym_t *s, jl_binding_t **pbnd, if (it != ctx->closureEnv->end()) { int idx = (*it).second; if (isBoxed(s->name, ctx)) { +#ifdef OVERLAP_TUPLE_LEN + return emit_nthptr_addr(emit_nthptr((Value*)ctx->envArg, idx+1), 1); +#else return emit_nthptr_addr(emit_nthptr((Value*)ctx->envArg, idx+2), 1); +#endif } +#ifdef OVERLAP_TUPLE_LEN + return emit_nthptr_addr((Value*)ctx->envArg, idx+1); +#else return emit_nthptr_addr((Value*)ctx->envArg, idx+2); +#endif } Value *l = (*ctx->vars)[s->name]; if (l != NULL) { @@ -1422,20 +1692,35 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx) assert(false); jl_binding_t *bnd=NULL; Value *bp = var_binding_pointer(s, &bnd, true, ctx); + Value *rval; if (bnd) { + rval = boxed(emit_expr(r, ctx, true)); builder.CreateCall2(jlcheckassign_func, literal_pointer_val((void*)bnd), - boxed(emit_expr(r, ctx, true))); + rval); } else { bool vol = ctx->volatilevars->find(s) != ctx->volatilevars->end(); Type *vt = bp->getType(); - if (vt->isPointerTy() && vt->getContainedType(0)!=jl_pvalue_llvmt) - builder.CreateStore(emit_unbox(vt->getContainedType(0), vt, - emit_unboxed(r, ctx)), - bp, vol); - else - builder.CreateStore(boxed(emit_expr(r, ctx, true)), bp, vol); + jl_value_t *rt = expr_type(r,ctx); + if ((jl_is_symbol(r) || jl_is_symbolnode(r)) && rt == jl_bottom_type) { + // sometimes x = y::None occurs + if (builder.GetInsertBlock()->getTerminator() != NULL) + return; + } + if (vt->isPointerTy() && vt->getContainedType(0)!=jl_pvalue_llvmt) { + rval = emit_unbox(vt->getContainedType(0), vt, emit_unboxed(r, ctx)); + } + else { + rval = boxed(emit_expr(r, ctx, true)); + } + if (builder.GetInsertBlock()->getTerminator() == NULL) { + builder.CreateStore(rval, bp, vol); + jl_arrayvar_t *av = arrayvar_for(l, ctx); + if (av!=NULL) { + assign_arrayvar(*av, rval); + } + } } } @@ -1464,10 +1749,15 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, return NULL; } else if (jl_is_linenode(expr)) { + if(valuepos) + jl_error("Linenode in value position"); return NULL; } else if (jl_is_quotenode(expr)) { jl_value_t *jv = jl_fieldref(expr,0); + if (jl_is_bitstype(jl_typeof(jv))) { + return emit_expr(jv, ctx, isboxed, valuepos); + } assert(jl_is_symbol(jv)); return literal_pointer_val(jv); } @@ -1514,7 +1804,7 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, else if (jl_is_lambda_info(expr)) { return emit_lambda_closure(expr, ctx); } - else if (jl_is_tuple(expr) || jl_is_union_type(expr)) { + else if (jl_is_tuple(expr) || jl_is_uniontype(expr)) { needroot = 1; } if (needroot) { @@ -1558,7 +1848,7 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, } else if (head == call_sym || head == call1_sym) { - return emit_call(args, ex->args->length, ctx, (jl_value_t*)ex); + return emit_call(args, jl_array_dim0(ex->args), ctx, (jl_value_t*)ex); } else if (head == assign_sym) { @@ -1568,24 +1858,44 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, } } else if (head == method_sym) { - jl_value_t *mn; - if (jl_is_symbolnode(args[0])) { - mn = (jl_value_t*)jl_symbolnode_sym(args[0]); + jl_value_t *mn = args[0]; + bool iskw = false; + Value *theF = NULL; + if (jl_is_expr(mn)) { + if (((jl_expr_t*)mn)->head == kw_sym) { + iskw = true; + mn = jl_exprarg(mn,0); + } + theF = emit_expr(mn, ctx); + if (!iskw) { + mn = jl_fieldref(jl_exprarg(mn, 2), 0); + } } - else { - mn = args[0]; + if (jl_is_symbolnode(mn)) { + mn = (jl_value_t*)jl_symbolnode_sym(mn); } assert(jl_is_symbol(mn)); int last_depth = ctx->argDepth; Value *name = literal_pointer_val(mn); jl_binding_t *bnd = NULL; Value *bp; - if (is_global((jl_sym_t*)mn, ctx)) { - bnd = jl_get_binding_for_method_def(ctx->module, (jl_sym_t*)mn); - bp = literal_pointer_val(&bnd->value, jl_ppvalue_llvmt); + if (iskw) { + // fenv = theF->env + Value *fenv = emit_nthptr(theF, 2); + // bp = &((jl_methtable_t*)fenv)->kwsorter + bp = emit_nthptr_addr(fenv, 7); + } + else if (theF != NULL) { + bp = make_gcroot(theF, ctx); } else { - bp = var_binding_pointer((jl_sym_t*)mn, &bnd, false, ctx); + if (is_global((jl_sym_t*)mn, ctx)) { + bnd = jl_get_binding_for_method_def(ctx->module, (jl_sym_t*)mn); + bp = literal_pointer_val(&bnd->value, jl_ppvalue_llvmt); + } + else { + bp = var_binding_pointer((jl_sym_t*)mn, &bnd, false, ctx); + } } Value *a1 = emit_expr(args[1], ctx); make_gcroot(boxed(a1), ctx); @@ -1595,9 +1905,8 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, make_gcroot(boxed(a3), ctx); Value *mdargs[6] = { name, bp, literal_pointer_val((void*)bnd), a1, a2, a3 }; - builder.CreateCall(jlmethod_func, ArrayRef(&mdargs[0], 6)); ctx->argDepth = last_depth; - return literal_pointer_val((jl_value_t*)jl_nothing); + return builder.CreateCall(jlmethod_func, ArrayRef(&mdargs[0], 6)); } else if (head == const_sym) { jl_sym_t *sym = (jl_sym_t*)args[0]; @@ -1626,13 +1935,28 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, } else if (head == new_sym) { jl_value_t *ty = expr_type(args[0], ctx); + size_t nargs = jl_array_len(ex->args); if (jl_is_type_type(ty) && - jl_is_struct_type(jl_tparam0(ty)) && + jl_is_datatype(jl_tparam0(ty)) && jl_is_leaf_type(jl_tparam0(ty))) { ty = jl_tparam0(ty); - jl_struct_type_t *sty = (jl_struct_type_t*)ty; + jl_datatype_t *sty = (jl_datatype_t*)ty; size_t nf = jl_tuple_len(sty->names); if (nf > 0) { + if (jl_isbits(sty)) { + Type *lt = julia_type_to_llvm(ty); + Value *strct = UndefValue::get(lt); + for(size_t i=0; i < nf; i++) { + unsigned idx = i; + Type *fty = julia_type_to_llvm(jl_tupleref(sty->types,i)); + Value *fval = emit_unbox(fty, PointerType::get(fty,0), emit_unboxed(args[i+1],ctx)); + if (fty == T_int1) + fval = builder.CreateZExt(fval, T_int8); + strct = builder. + CreateInsertValue(strct, fval, ArrayRef(&idx,1)); + } + return mark_julia_type(strct,ty); + } Value *strct = builder.CreateCall(jlallocobj_func, ConstantInt::get(T_size, @@ -1641,19 +1965,25 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, emit_nthptr_addr(strct, (size_t)0)); for(size_t i=0; i < nf; i++) { if (sty->fields[i].isptr) { - emit_setfield(sty, strct, i, V_null, ctx); + emit_setfield(sty, strct, i, V_null, ctx, false); } } + make_gcroot(strct, ctx); + for(size_t i=1; i < nargs; i++) { + emit_setfield(sty, strct, i-1, emit_expr(args[i],ctx), ctx, + false); + } + ctx->argDepth--; return strct; } else { // 0 fields, singleton return literal_pointer_val - (jl_new_struct_uninit((jl_struct_type_t*)ty)); + (jl_new_struct_uninit((jl_datatype_t*)ty)); } } Value *typ = emit_expr(args[0], ctx); - return builder.CreateCall(jlnew_func, typ); + return emit_jlcall(jlnew_func, typ, &args[1], nargs-1, ctx); } else if (head == exc_sym) { return builder.CreateLoad(jlexc_var, true); @@ -1669,18 +1999,36 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, Value *jbuf = builder.CreateGEP((*ctx->handlers)[labl], ConstantInt::get(T_size,0)); builder.CreateCall(jlenter_func, jbuf); +#ifndef __WIN32__ Value *sj = builder.CreateCall2(setjmp_func, jbuf, ConstantInt::get(T_int32,0)); +#else + Value *sj = builder.CreateCall(setjmp_func, jbuf); +#endif Value *isz = builder.CreateICmpEQ(sj, ConstantInt::get(T_int32,0)); BasicBlock *tryblk = BasicBlock::Create(getGlobalContext(), "try", ctx->f); BasicBlock *handlr = (*ctx->labels)[labl]; assert(handlr); +#ifdef __WIN32__ + BasicBlock *cond_resetstkoflw_blk = BasicBlock::Create(getGlobalContext(), "cond_resetstkoflw", ctx->f); + BasicBlock *resetstkoflw_blk = BasicBlock::Create(getGlobalContext(), "resetstkoflw", ctx->f); + builder.CreateCondBr(isz, tryblk, cond_resetstkoflw_blk); + builder.SetInsertPoint(cond_resetstkoflw_blk); + builder.CreateCondBr(builder.CreateICmpEQ( + literal_pointer_val(jl_stackovf_exception), + builder.CreateLoad(jlexc_var, true)), + resetstkoflw_blk, handlr); + builder.SetInsertPoint(resetstkoflw_blk); + builder.CreateCall(resetstkoflw_func); + builder.CreateBr(handlr); +#else builder.CreateCondBr(isz, tryblk, handlr); +#endif builder.SetInsertPoint(tryblk); } else { if (!strcmp(head->name, "$")) - jl_error("syntax error: prefix $ in non-quoted expression"); + jl_error("syntax: prefix $ in non-quoted expression"); // some expression types are metadata and can be ignored if (valuepos || !(head == line_sym || head == type_goto_sym)) { jl_errorf("unsupported or misplaced expression %s in function %s", @@ -1697,8 +2045,8 @@ static bool store_unboxed_p(char *name, jl_codectx_t *ctx) jl_value_t *jt = (*ctx->declTypes)[name]; // only store a variable unboxed if type inference has run, which // checks that the variable is not referenced undefined. - return (ctx->linfo->inferred && jl_is_bits_type(jt) && - jl_is_leaf_type(jt) && + return (ctx->linfo->inferred && jl_isbits(jt) && + ((jl_datatype_t*)jt)->size > 0 && // don't unbox intrinsics, since inference depends on their having // stable addresses for table lookup. jt != (jl_value_t*)jl_intrinsic_type && !(*ctx->isCaptured)[name]); @@ -1719,6 +2067,24 @@ static AllocaInst *alloc_local(char *name, jl_codectx_t *ctx) return lv; } +static void maybe_alloc_arrayvar(char *name, jl_codectx_t *ctx) +{ + jl_value_t *jt = (*ctx->declTypes)[name]; + if (jl_is_array_type(jt) && jl_is_leaf_type(jt) && + jl_unbox_long(jl_tparam1(jt)) != 1) { + // TODO: this optimization does not yet work with 1-d arrays, since the + // length and data pointer can change at any time via push! + // we could make it work by reloading the metadata when the array is + // passed to an external function (ideally only impure functions) + jl_arrayvar_t av; + av.dataptr = builder.CreateAlloca(T_pint8); + av.len = builder.CreateAlloca(T_size); + av.nr = builder.CreateAlloca(T_size); + av.ty = jt; + (*ctx->arrayvars)[name] = av; + } +} + // --- generate function bodies --- extern char *jl_stack_lo; @@ -1743,14 +2109,15 @@ static Function *gen_jlcall_wrapper(jl_lambda_info_t *lam, Function *f) DebugLoc noDbg; builder.SetCurrentDebugLocation(noDbg); - size_t nargs = lam->specTypes->length; + size_t nargs = jl_tuple_len(lam->specTypes); Value *args[nargs]; for(size_t i=0; i < nargs; i++) { Value *argPtr = builder.CreateGEP(argArray, ConstantInt::get(T_size, i)); Value *theArg = builder.CreateLoad(argPtr, false); jl_value_t *ty = jl_tupleref(lam->specTypes, i); - if (jl_is_leaf_type(ty) && jl_is_bits_type(ty)) { + if (jl_is_leaf_type(ty) && jl_isbits(ty) && + ((jl_datatype_t*)ty)->size > 0) { Type *lty = julia_type_to_llvm(ty); assert(lty != NULL); theArg = emit_unbox(lty, PointerType::get(lty,0), theArg); @@ -1761,20 +2128,21 @@ static Function *gen_jlcall_wrapper(jl_lambda_info_t *lam, Function *f) // wrappers can be reused for different functions of the same type. Value *r = builder.CreateCall(f, ArrayRef(&args[0], nargs)); if (r->getType() != jl_pvalue_llvmt) { - r = boxed(r, ast_rettype(lam->ast)); + r = boxed(r, jl_ast_rettype(lam, lam->ast)); } builder.CreateRet(r); return w; } -static Function *emit_function(jl_lambda_info_t *lam) +// cstyle = compile with c-callable signature, not jlcall +static Function *emit_function(jl_lambda_info_t *lam, bool cstyle) { // step 1. unpack AST and allocate codegen context for this function jl_expr_t *ast = (jl_expr_t*)lam->ast; jl_tuple_t *sparams = NULL; JL_GC_PUSH(&ast, &sparams); - if (jl_is_tuple(ast)) { - ast = (jl_expr_t*)jl_uncompress_ast((jl_tuple_t*)ast); + if (!jl_is_expr(ast)) { + ast = (jl_expr_t*)jl_uncompress_ast(lam, (jl_value_t*)ast); } assert(jl_is_expr(ast)); sparams = jl_tuple_tvars_to_symbols(lam->sparams); @@ -1787,6 +2155,7 @@ static Function *emit_function(jl_lambda_info_t *lam) std::map isAssigned; std::map isCaptured; std::map escapes; + std::map arrayvars; std::set volvars; std::map declTypes; std::map labels; @@ -1799,6 +2168,7 @@ static Function *emit_function(jl_lambda_info_t *lam) ctx.isAssigned = &isAssigned; ctx.isCaptured = &isCaptured; ctx.escapes = &escapes; + ctx.arrayvars = &arrayvars; ctx.volatilevars = &volvars; ctx.declTypes = &declTypes; ctx.labels = &labels; @@ -1813,8 +2183,10 @@ static Function *emit_function(jl_lambda_info_t *lam) // step 2. process var-info lists to see what vars are captured, need boxing jl_array_t *largs = jl_lam_args(ast); + size_t largslen = jl_array_dim0(largs); jl_array_t *lvars = jl_lam_locals(ast); - size_t nreq = largs->length; + size_t lvarslen = jl_array_dim0(lvars); + size_t nreq = largslen; int va = 0; if (nreq > 0 && jl_is_rest_arg(jl_cellref(largs,nreq-1))) { nreq--; @@ -1824,8 +2196,9 @@ static Function *emit_function(jl_lambda_info_t *lam) ctx.nReqArgs = nreq; jl_array_t *vinfos = jl_lam_vinfo(ast); + size_t vinfoslen = jl_array_dim0(vinfos); size_t i; - for(i=0; i < vinfos->length; i++) { + for(i=0; i < vinfoslen; i++) { jl_array_t *vi = (jl_array_t*)jl_cellref(vinfos, i); assert(jl_is_array(vi)); char *vname = ((jl_sym_t*)jl_cellref(vi,0))->name; @@ -1836,8 +2209,9 @@ static Function *emit_function(jl_lambda_info_t *lam) declTypes[vname] = jl_cellref(vi,1); } vinfos = jl_lam_capt(ast); - bool hasCapt = (vinfos->length > 0); - for(i=0; i < vinfos->length; i++) { + vinfoslen = jl_array_dim0(vinfos); + bool hasCapt = (vinfoslen > 0); + for(i=0; i < vinfoslen; i++) { jl_array_t *vi = (jl_array_t*)jl_cellref(vinfos, i); assert(jl_is_array(vi)); char *vname = ((jl_sym_t*)jl_cellref(vi,0))->name; @@ -1856,34 +2230,41 @@ static Function *emit_function(jl_lambda_info_t *lam) Function *f = NULL; bool specsig = false; - if (!va && !hasCapt && lam->specTypes != NULL) { - // no captured vars and not vararg - // consider specialized signature - for(size_t i=0; i < lam->specTypes->length; i++) { - if (jl_is_bits_type(jl_tupleref(lam->specTypes, i))) { - specsig = true; - break; + if (cstyle && !va && !hasCapt) { + specsig = true; + } + else { + if (!va && !hasCapt && lam->specTypes != NULL) { + // no captured vars and not vararg + // consider specialized signature + for(size_t i=0; i < jl_tuple_len(lam->specTypes); i++) { + if (jl_isbits(jl_tupleref(lam->specTypes, i))) { + specsig = true; + break; + } } + if (jl_tuple_len(lam->specTypes) == 0) + specsig = true; } - if (lam->specTypes->length == 0) - specsig = true; } std::string funcName = lam->name->name; // try to avoid conflicts in the global symbol table funcName = "julia_" + funcName; + jl_value_t *jlrettype = jl_ast_rettype(lam, (jl_value_t*)ast); if (specsig) { std::vector fsig(0); - for(size_t i=0; i < lam->specTypes->length; i++) { + for(size_t i=0; i < jl_tuple_len(lam->specTypes); i++) { fsig.push_back(julia_type_to_llvm(jl_tupleref(lam->specTypes,i))); } - jl_value_t *jlrettype = ast_rettype((jl_value_t*)ast); Type *rt = (jlrettype == (jl_value_t*)jl_nothing->type ? T_void : julia_type_to_llvm(jlrettype)); f = Function::Create(FunctionType::get(rt, fsig, false), Function::ExternalLinkage, funcName, jl_Module); - if (lam->functionObject == NULL) { + if (lam->cFunctionObject == NULL) { lam->cFunctionObject = (void*)f; + } + if (lam->functionObject == NULL) { lam->functionObject = (void*)gen_jlcall_wrapper(lam, f); } } @@ -1894,12 +2275,24 @@ static Function *emit_function(jl_lambda_info_t *lam) lam->functionObject = (void*)f; } } - + //TODO: this seems to cause problems, but should be made to work eventually + //if (jlrettype == (jl_value_t*)jl_bottom_type) + // f->setDoesNotReturn(); +#ifdef DEBUG +#ifdef __WIN32__ + AttrBuilder *attr = new AttrBuilder(); + attr->addStackAlignmentAttr(16); + attr->addAlignmentAttr(16); + f->addAttribute(~0U, Attributes::get(f->getContext(), *attr)); +#endif + f->addFnAttr(Attributes::StackProtectReq); +#endif ctx.f = f; // step 5. set up debug info context and create first basic block jl_value_t *stmt = jl_cellref(stmts,0); std::string filename = "no file"; + char *dbgFuncName = lam->name->name; int lno = -1; // look for initial (line num filename) node if (jl_is_linenode(stmt)) { @@ -1907,9 +2300,12 @@ static Function *emit_function(jl_lambda_info_t *lam) } else if (jl_is_expr(stmt) && ((jl_expr_t*)stmt)->head == line_sym) { lno = jl_unbox_long(jl_exprarg(stmt, 0)); - if (((jl_expr_t*)stmt)->args->length > 1) { + if (jl_array_dim0(((jl_expr_t*)stmt)->args) > 1) { assert(jl_is_symbol(jl_exprarg(stmt, 1))); filename = ((jl_sym_t*)jl_exprarg(stmt, 1))->name; + if (jl_array_dim0(((jl_expr_t*)stmt)->args) > 2) { + dbgFuncName = ((jl_sym_t*)jl_exprarg(stmt, 2))->name; + } } } ctx.lineno = lno; @@ -1920,13 +2316,14 @@ static Function *emit_function(jl_lambda_info_t *lam) DIFile fil = dbuilder->createFile(filename, "."); DISubprogram SP = dbuilder->createFunction((DIDescriptor)dbuilder->getCU(), - lam->name->name, - lam->name->name, + dbgFuncName, dbgFuncName, fil, 0, dbuilder->createSubroutineType(fil,EltTypeArray), false, true, 0, true, f); + //ios_printf(ios_stderr, "\n*** compiling %s at %s:%d\n\n", + // lam->name->name, filename.c_str(), lno); BasicBlock *b0 = BasicBlock::Create(jl_LLVMContext, "top", f); builder.SetInsertPoint(b0); @@ -1962,17 +2359,18 @@ static Function *emit_function(jl_lambda_info_t *lam) // step 7. allocate local variables // must be first for the mem2reg pass to work int n_roots = 0; - for(i=0; i < largs->length; i++) { + for(i=0; i < largslen; i++) { char *argname = jl_decl_var(jl_cellref(largs,i))->name; if (store_unboxed_p(argname, &ctx)) { alloc_local(argname, &ctx); //argumentMap[argname] = lv; } - else if (isAssigned[argname] || (va && i==largs->length-1)) { + else if (isAssigned[argname] || (va && i==largslen-1)) { n_roots++; } + maybe_alloc_arrayvar(argname, &ctx); } - for(i=0; i < lvars->length; i++) { + for(i=0; i < lvarslen; i++) { char *varname = ((jl_sym_t*)jl_cellref(lvars,i))->name; if (store_unboxed_p(varname, &ctx)) { alloc_local(varname, &ctx); @@ -1980,6 +2378,7 @@ static Function *emit_function(jl_lambda_info_t *lam) else { n_roots++; } + maybe_alloc_arrayvar(varname, &ctx); } // fetch env out of function object if we need it @@ -1996,33 +2395,36 @@ static Function *emit_function(jl_lambda_info_t *lam) ctx.argDepth = 0; ctx.maxDepth = 0; #ifdef JL_GC_MARKSWEEP - AllocaInst *gcframe = NULL; + Instruction *gcframe = NULL; Instruction *argSpaceInits = NULL; StoreInst *storeFrameSize = NULL; #endif + BasicBlock::iterator first_gcframe_inst; + BasicBlock::iterator last_gcframe_inst; if (n_roots > 0) { - ctx.argTemp = builder.CreateAlloca(jl_pvalue_llvmt, - ConstantInt::get(T_int32, n_roots)); #ifdef JL_GC_MARKSWEEP // allocate gc frame - gcframe = builder.CreateAlloca(T_gcframe, 0); - builder.CreateStore(builder.CreateBitCast(ctx.argTemp, - PointerType::get(jl_ppvalue_llvmt,0)), - builder.CreateConstGEP2_32(gcframe, 0, 0)); + ctx.argTemp = builder.CreateAlloca(jl_pvalue_llvmt, + ConstantInt::get(T_int32,n_roots+2)); + gcframe = (Instruction*)ctx.argTemp; + first_gcframe_inst = BasicBlock::iterator(gcframe); + ctx.argTemp = (Instruction*)builder.CreateConstGEP1_32(ctx.argTemp, 2); storeFrameSize = - builder.CreateStore(ConstantInt::get(T_size, n_roots), - builder.CreateConstGEP2_32(gcframe, 0, 1)); - builder.CreateStore(ConstantInt::get(T_int32, 0), - builder.CreateConstGEP2_32(gcframe, 0, 2)); + builder.CreateStore(ConstantInt::get(T_size, n_roots<<1), + builder.CreateBitCast(builder.CreateConstGEP1_32(gcframe, 0), T_psize)); builder.CreateStore(builder.CreateLoad(jlpgcstack_var, false), - builder.CreateConstGEP2_32(gcframe, 0, 3)); - builder.CreateStore(gcframe, jlpgcstack_var, false); + builder.CreateBitCast(builder.CreateConstGEP1_32(gcframe, 1), PointerType::get(jl_ppvalue_llvmt,0))); + Instruction *linst=builder.CreateStore(gcframe, jlpgcstack_var, false); + last_gcframe_inst = BasicBlock::iterator(linst); // initialize local variable stack roots to null for(i=0; i < (size_t)ctx.argSpaceOffs; i++) { Value *varSlot = builder.CreateConstGEP1_32(ctx.argTemp,i); builder.CreateStore(V_null, varSlot); } argSpaceInits = &b0->back(); +#else + ctx.argTemp = builder.CreateAlloca(jl_pvalue_llvmt, + ConstantInt::get(T_int32, n_roots)); #endif } else { @@ -2032,18 +2434,18 @@ static Function *emit_function(jl_lambda_info_t *lam) // get pointers for locals stored in the gc frame array (argTemp) int varnum = 0; - for(i=0; i < largs->length; i++) { + for(i=0; i < largslen; i++) { char *argname = jl_decl_var(jl_cellref(largs,i))->name; if (store_unboxed_p(argname, &ctx)) { } - else if (isAssigned[argname] || (va && i==largs->length-1)) { + else if (isAssigned[argname] || (va && i==largslen-1)) { Value *av = builder.CreateConstGEP1_32(ctx.argTemp,varnum); varnum++; localVars[argname] = av; //argumentMap[argname] = av; } } - for(i=0; i < lvars->length; i++) { + for(i=0; i < lvarslen; i++) { char *varname = ((jl_sym_t*)jl_cellref(lvars,i))->name; if (store_unboxed_p(varname, &ctx)) { } @@ -2056,7 +2458,7 @@ static Function *emit_function(jl_lambda_info_t *lam) assert(varnum == ctx.argSpaceOffs); // step 9. create boxes for boxed locals - for(i=0; i < lvars->length; i++) { + for(i=0; i < lvarslen; i++) { char *varname = ((jl_sym_t*)jl_cellref(lvars,i))->name; if (isBoxed(varname, &ctx)) { Value *lv = localVars[varname]; @@ -2065,14 +2467,16 @@ static Function *emit_function(jl_lambda_info_t *lam) } // step 10. allocate space for exception handler contexts - for(i=0; i < stmts->length; i++) { + size_t stmtslen = jl_array_dim0(stmts); + for(i=0; i < stmtslen; i++) { jl_value_t *stmt = jl_cellref(stmts,i); if (jl_is_expr(stmt) && ((jl_expr_t*)stmt)->head == enter_sym) { int labl = jl_unbox_long(jl_exprarg(stmt,0)); - Value *handlr = + AllocaInst *handlr = builder.CreateAlloca(T_int8, ConstantInt::get(T_int32, sizeof(jl_handler_t))); + handlr->setAlignment(128); // bits == 16 bytes handlers[labl] = handlr; } } @@ -2124,22 +2528,19 @@ static Function *emit_function(jl_lambda_info_t *lam) argPtr = builder.CreateGEP(argArray, ConstantInt::get(T_size, i)); } + Value *theArg; + if (specsig) + theArg = argPtr; + else + theArg = builder.CreateLoad(argPtr, false); Value *lv = localVars[argname]; if (lv == NULL) { // if this argument hasn't been given space yet, we've decided // to leave it in the input argument array. - if (specsig) - passedArgumentMap[argname] = argPtr; - else - passedArgumentMap[argname] = builder.CreateLoad(argPtr, false); + passedArgumentMap[argname] = theArg; //argumentMap[argname] = argPtr; } else { - Value *theArg; - if (specsig) - theArg = argPtr; - else - theArg = builder.CreateLoad(argPtr, false); // keep track of original (boxed) value to avoid re-boxing passedArgumentMap[argname] = theArg; if (isBoxed(argname, &ctx)) { @@ -2157,6 +2558,11 @@ static Function *emit_function(jl_lambda_info_t *lam) theArg), lv); } + // get arrayvar data if applicable + if (arrayvars.find(argname) != arrayvars.end()) { + jl_arrayvar_t av = arrayvars[argname]; + assign_arrayvar(av, theArg); + } } // step 13. allocate rest argument if necessary @@ -2183,7 +2589,7 @@ static Function *emit_function(jl_lambda_info_t *lam) // step 14. associate labels with basic blocks to resolve forward jumps BasicBlock *prev=NULL; - for(i=0; i < stmts->length; i++) { + for(i=0; i < stmtslen; i++) { jl_value_t *ex = jl_cellref(stmts,i); if (jl_is_labelnode(ex)) { int lname = jl_labelnode_label(ex); @@ -2202,8 +2608,9 @@ static Function *emit_function(jl_lambda_info_t *lam) } // step 15. compile body statements + std::vector gc_frame_pops; bool prevlabel = false; - for(i=0; i < stmts->length; i++) { + for(i=0; i < stmtslen; i++) { jl_value_t *stmt = jl_cellref(stmts,i); if (jl_is_linenode(stmt)) { int lno = jl_linenode_line(stmt); @@ -2239,7 +2646,9 @@ static Function *emit_function(jl_lambda_info_t *lam) #ifdef JL_GC_MARKSWEEP // JL_GC_POP(); if (n_roots > 0) { - builder.CreateStore(builder.CreateLoad(builder.CreateConstGEP2_32(gcframe, 0, 3), false), + Instruction *gcpop = (Instruction*)builder.CreateConstGEP1_32(gcframe, 1); + gc_frame_pops.push_back(gcpop); + builder.CreateStore(builder.CreateBitCast(builder.CreateLoad(gcpop, false), jl_ppvalue_llvmt), jlpgcstack_var); } #endif @@ -2247,7 +2656,7 @@ static Function *emit_function(jl_lambda_info_t *lam) builder.CreateRetVoid(); else builder.CreateRet(retval); - if (i != stmts->length-1) { + if (i != stmtslen-1) { BasicBlock *bb = BasicBlock::Create(getGlobalContext(), "ret", ctx.f); builder.SetInsertPoint(bb); @@ -2264,32 +2673,67 @@ static Function *emit_function(jl_lambda_info_t *lam) // step 16. fix up size of stack root list (just a code simplification) if (n_roots > 0) { - BasicBlock::iterator bbi(ctx.argTemp); - AllocaInst *newArgTemp = - new AllocaInst(jl_pvalue_llvmt, - ConstantInt::get(T_int32, ctx.argSpaceOffs + - ctx.maxDepth)); - ReplaceInstWithInst(ctx.argTemp->getParent()->getInstList(), bbi, - newArgTemp); - - BasicBlock::iterator bbi2(storeFrameSize); - StoreInst *newFrameSize = - new StoreInst(ConstantInt::get(T_size, ctx.argSpaceOffs + - ctx.maxDepth), - storeFrameSize->getPointerOperand()); - ReplaceInstWithInst(storeFrameSize->getParent()->getInstList(), bbi2, - newFrameSize); - - BasicBlock::InstListType &instList = argSpaceInits->getParent()->getInstList(); - Instruction *after = argSpaceInits; - - for(i=0; i < (size_t)ctx.maxDepth; i++) { - Instruction *argTempi = - GetElementPtrInst::Create(newArgTemp, - ConstantInt::get(T_int32, i+ctx.argSpaceOffs)); - instList.insertAfter(after, argTempi); - after = new StoreInst(V_null, argTempi); - instList.insertAfter(argTempi, after); + if (ctx.argSpaceOffs + ctx.maxDepth == 0) { + // 0 roots; remove gc frame entirely + // replace instruction uses with Undef first to avoid LLVM assertion failures + BasicBlock::iterator bbi = first_gcframe_inst; + while (1) { + Instruction &iii = *bbi; + iii.replaceAllUsesWith(UndefValue::get(iii.getType())); + if (bbi == last_gcframe_inst) break; + bbi++; + } + for(size_t i=0; i < gc_frame_pops.size(); i++) { + Instruction *pop = gc_frame_pops[i]; + BasicBlock::iterator pi(pop); + for(size_t j=0; j < 4; j++) { + Instruction &iii = *pi; + iii.replaceAllUsesWith(UndefValue::get(iii.getType())); + pi++; + } + } + + BasicBlock::InstListType &il = gcframe->getParent()->getInstList(); + il.erase(first_gcframe_inst, last_gcframe_inst); + // erase() erases up *to* the end point; erase last inst too + il.erase(last_gcframe_inst); + for(size_t i=0; i < gc_frame_pops.size(); i++) { + Instruction *pop = gc_frame_pops[i]; + BasicBlock::InstListType &il2 = pop->getParent()->getInstList(); + BasicBlock::iterator pi(pop); + for(size_t j=0; j < 4; j++) { + pi = il2.erase(pi); + } + } + } + else { + BasicBlock::iterator bbi(gcframe); + AllocaInst *newgcframe = + new AllocaInst(jl_pvalue_llvmt, + ConstantInt::get(T_int32, (ctx.argSpaceOffs + + ctx.maxDepth + 2))); + ReplaceInstWithInst(ctx.argTemp->getParent()->getInstList(), bbi, + newgcframe); + + BasicBlock::iterator bbi2(storeFrameSize); + StoreInst *newFrameSize = + new StoreInst(ConstantInt::get(T_size, (ctx.argSpaceOffs + + ctx.maxDepth)<<1), + storeFrameSize->getPointerOperand()); + ReplaceInstWithInst(storeFrameSize->getParent()->getInstList(), bbi2, + newFrameSize); + + BasicBlock::InstListType &instList = argSpaceInits->getParent()->getInstList(); + Instruction *after = argSpaceInits; + + for(i=0; i < (size_t)ctx.maxDepth; i++) { + Instruction *argTempi = + GetElementPtrInst::Create(newgcframe, + ConstantInt::get(T_int32, i+ctx.argSpaceOffs+2)); + instList.insertAfter(after, argTempi); + after = new StoreInst(V_null, argTempi); + instList.insertAfter(argTempi, after); + } } } @@ -2321,7 +2765,11 @@ static Function *jlfunc_to_llvm(const std::string &cname, void *addr) extern "C" jl_value_t *jl_new_box(jl_value_t *v) { jl_value_t *box = (jl_value_t*)alloc_2w(); +#ifdef OVERLAP_TUPLE_LEN + box->type = (size_t)jl_box_any_type; +#else box->type = jl_box_any_type; +#endif ((jl_value_t**)box)[1] = v; return box; } @@ -2340,11 +2788,10 @@ static void init_julia_llvm_env(Module *m) T_pint64 = PointerType::get(T_int64, 0); T_uint8 = T_int8; T_uint16 = T_int16; T_uint32 = T_int32; T_uint64 = T_int64; -#ifdef __LP64__ - T_size = T_uint64; -#else - T_size = T_uint32; -#endif + if (sizeof(size_t) == 8) + T_size = T_uint64; + else + T_size = T_uint32; T_psize = PointerType::get(T_size, 0); T_float32 = Type::getFloatTy(getGlobalContext()); T_pfloat32 = PointerType::get(T_float32, 0); @@ -2371,22 +2818,21 @@ static void init_julia_llvm_env(Module *m) jl_fptr_llvmt = PointerType::get(jl_func_sig, 0); #ifdef JL_GC_MARKSWEEP - StructType *gcfst = StructType::create(getGlobalContext(), "jl_gcframe_t"); - Type *gcframeStructElts[4] = { - PointerType::get(jl_ppvalue_llvmt,0), - T_size, - T_int32, - PointerType::getUnqual(gcfst) }; - gcfst->setBody(ArrayRef(gcframeStructElts, 4)); - T_gcframe = gcfst; - jlpgcstack_var = - new GlobalVariable(*jl_Module, PointerType::get(T_gcframe,0), + new GlobalVariable(*jl_Module, jl_ppvalue_llvmt, true, GlobalVariable::ExternalLinkage, NULL, "jl_pgcstack"); jl_ExecutionEngine->addGlobalMapping(jlpgcstack_var, (void*)&jl_pgcstack); #endif + global_to_llvm("__stack_chk_guard", (void*)&__stack_chk_guard); + Function *jl__stack_chk_fail = + Function::Create(FunctionType::get(T_void, false), + Function::ExternalLinkage, + "__stack_chk_fail", jl_Module); + //jl__stack_chk_fail->setDoesNotReturn(); + jl_ExecutionEngine->addGlobalMapping(jl__stack_chk_fail, (void*)&__stack_chk_fail); + jltrue_var = global_to_llvm("jl_true", (void*)&jl_true); jlfalse_var = global_to_llvm("jl_false", (void*)&jl_false); jlnull_var = global_to_llvm("jl_null", (void*)&jl_null); @@ -2434,22 +2880,27 @@ static void init_julia_llvm_env(Module *m) (Function*)jl_Module->getOrInsertFunction("jl_throw_with_superfluous_argument", FunctionType::get(T_void, args2_throw, false)); jlthrow_line_func->setDoesNotReturn(); + jl_ExecutionEngine->addGlobalMapping(jlthrow_line_func, (void*)&jl_throw_with_superfluous_argument); jlnew_func = - Function::Create(FunctionType::get(jl_pvalue_llvmt, args1_, false), - Function::ExternalLinkage, - "jl_new_struct_uninit", jl_Module); - jl_ExecutionEngine->addGlobalMapping(jlnew_func, - (void*)&jl_new_struct_uninit); + Function::Create(jl_func_sig, Function::ExternalLinkage, + "jl_new_structv", jl_Module); + jl_ExecutionEngine->addGlobalMapping(jlnew_func, (void*)&jl_new_structv); std::vector args2(0); args2.push_back(T_pint8); +#ifndef __WIN32__ args2.push_back(T_int32); +#endif setjmp_func = Function::Create(FunctionType::get(T_int32, args2, false), Function::ExternalLinkage, "sigsetjmp", jl_Module); //Intrinsic::getDeclaration(jl_Module, Intrinsic::eh_sjlj_setjmp); +#ifdef LLVM32 + setjmp_func->addFnAttr(Attributes::ReturnsTwice); +#else setjmp_func->addFnAttr(Attribute::ReturnsTwice); +#endif jl_ExecutionEngine->addGlobalMapping(setjmp_func, (void*)&jl_setjmp_f); std::vector te_args(0); @@ -2537,6 +2988,12 @@ static void init_julia_llvm_env(Module *m) "jl_enter_handler", jl_Module); jl_ExecutionEngine->addGlobalMapping(jlenter_func, (void*)&jl_enter_handler); +#ifdef __WIN32__ + resetstkoflw_func = Function::Create(FunctionType::get(T_void, false), + Function::ExternalLinkage, "_resetstkoflw", jl_Module); + jl_ExecutionEngine->addGlobalMapping(resetstkoflw_func, (void*)&_resetstkoflw); +#endif + std::vector lhargs(0); lhargs.push_back(T_int32); jlleave_func = @@ -2577,15 +3034,16 @@ static void init_julia_llvm_env(Module *m) // set up optimization passes FPM = new FunctionPassManager(jl_Module); +#ifndef LLVM32 FPM->add(new TargetData(*jl_ExecutionEngine->getTargetData())); - +#endif // list of passes from vmkit FPM->add(createCFGSimplificationPass()); // Clean up disgusting code FPM->add(createPromoteMemoryToRegisterPass());// Kill useless allocas - //FPM->add(createInstructionCombiningPass()); // Cleanup for scalarrepl. + FPM->add(createInstructionCombiningPass()); // Cleanup for scalarrepl. FPM->add(createScalarReplAggregatesPass()); // Break up aggregate allocas - //FPM->add(createInstructionCombiningPass()); // Cleanup for scalarrepl. + FPM->add(createInstructionCombiningPass()); // Cleanup for scalarrepl. FPM->add(createJumpThreadingPass()); // Thread jumps. FPM->add(createCFGSimplificationPass()); // Merge & remove BBs //FPM->add(createInstructionCombiningPass()); // Combine silly seq's @@ -2638,6 +3096,7 @@ extern "C" void jl_init_codegen(void) #ifdef DEBUG llvm::JITEmitDebugInfo = true; #endif + //llvm::JITEmitDebugInfoToDisk = true; llvm::NoFramePointerElim = true; llvm::NoFramePointerElimNonLeaf = true; #ifdef __MINGW32__ @@ -2653,6 +3112,9 @@ extern "C" void jl_init_codegen(void) options.NoFramePointerElimNonLeaf = true; #ifdef __MINGW32__ options.StackAlignmentOverride = 16; +#endif +#ifdef __APPLE__ + options.JITExceptionHandling = 1; #endif jl_ExecutionEngine = EngineBuilder(jl_Module) .setEngineKind(EngineKind::JIT) diff --git a/src/dlload.c b/src/dlload.c index 401bf5a740b7f..3a7cb15eee90a 100644 --- a/src/dlload.c +++ b/src/dlload.c @@ -5,7 +5,6 @@ #include #ifdef _WIN32 -# define _WIN32_WINNT 0x0501 # include # include #else @@ -17,8 +16,8 @@ static char *extensions[] = { "", ".dylib" }; #define N_EXTENSIONS 2 #elif defined(_WIN32) -static char *extensions[] = { ".dll" }; -#define N_EXTENSIONS 1 +static char *extensions[] = { "", ".dll" }; +#define N_EXTENSIONS 2 #else static char *extensions[] = { ".so", "" }; #define N_EXTENSIONS 2 @@ -31,13 +30,32 @@ static char *extensions[] = { ".so", "" }; extern char *julia_home; +#if defined(__linux__) char *jl_lookup_soname(char *pfx, size_t n); +#endif -int jl_uv_dlopen(const char* filename, uv_lib_t* lib) +#define JL_RTLD(flags, FLAG) (flags & JL_RTLD_ ## FLAG ? RTLD_ ## FLAG : 0) + +int jl_uv_dlopen(const char* filename, uv_lib_t* lib, unsigned flags) { -#ifdef RTLD_DEEPBIND +#if defined(RTLD_GLOBAL) && defined(RTLD_LAZY) /* POSIX flags available */ dlerror(); /* Reset error status. */ - lib->handle = dlopen(filename, RTLD_LAZY|RTLD_DEEPBIND); + lib->handle = dlopen(filename, + (flags & JL_RTLD_NOW ? RTLD_NOW : RTLD_LAZY) + | JL_RTLD(flags, GLOBAL) | JL_RTLD(flags, LOCAL) +#ifdef RTLD_NODELETE + | JL_RTLD(flags, NODELETE) +#endif +#ifdef RTLD_NOLOAD + | JL_RTLD(flags, NOLOAD) +#endif +#ifdef RTLD_DEEPBIND + | JL_RTLD(flags, DEEPBIND) +#endif +#ifdef RTLD_FIRST + | JL_RTLD(flags, FIRST) +#endif + ); if (lib->handle) { lib->errmsg = NULL; return 0; @@ -50,7 +68,7 @@ int jl_uv_dlopen(const char* filename, uv_lib_t* lib) #endif } -uv_lib_t *jl_load_dynamic_library(char *modname) +uv_lib_t *jl_load_dynamic_library_(char *modname, unsigned flags, int throw_err) { int error; char *ext; @@ -75,7 +93,7 @@ uv_lib_t *jl_load_dynamic_library(char *modname) #else else if (modname[0] == '/') { #endif - error = jl_uv_dlopen(modname,handle); + error = jl_uv_dlopen(modname,handle,flags); if (!error) goto done; } @@ -83,35 +101,21 @@ uv_lib_t *jl_load_dynamic_library(char *modname) ext = extensions[i]; path[0] = '\0'; handle->handle = NULL; - if (modname[0] != '/') { - if (julia_home) { - /* try julia_home/../lib */ - snprintf(path, PATHBUF, "%s/../lib/%s%s", julia_home, modname, ext); - error = jl_uv_dlopen(path, handle); - if (!error) goto done; - // if file exists but didn't load, show error details - struct stat sbuf; - if (stat(path, &sbuf) != -1) { - //JL_PRINTF(JL_STDERR, "could not load module %s (%d): %s\n", modname, error, uv_dlerror(handle)); - //jl_errorf("could not load module %s: %s", modname, uv_dlerror(handle)); - goto error; - } - } - } /* try loading from standard library path */ snprintf(path, PATHBUF, "%s%s", modname, ext); - error = jl_uv_dlopen(path, handle); + error = jl_uv_dlopen(path, handle,flags); if (!error) goto done; } -#if !defined(__APPLE__) && !defined(_WIN32) +#if defined(__linux__) char *soname = jl_lookup_soname(modname, strlen(modname)); - error = (soname==NULL) || jl_uv_dlopen(soname, handle); + error = (soname==NULL) || jl_uv_dlopen(soname, handle, flags); if (!error) goto done; #endif -error: - //JL_PRINTF(JL_STDERR, "could not load module %s (%d): %s\n", modname, error, uv_dlerror(handle)); - jl_errorf("could not load module %s: %s", modname, uv_dlerror(handle)); + if (throw_err) { + //JL_PRINTF(JL_STDERR, "could not load module %s (%d): %s\n", modname, error, uv_dlerror(handle)); + jl_errorf("could not load module %s: %s", modname, uv_dlerror(handle)); + } uv_dlclose(handle); free(handle); return NULL; @@ -119,6 +123,16 @@ uv_lib_t *jl_load_dynamic_library(char *modname) return handle; } +uv_lib_t *jl_load_dynamic_library_e(char *modname, unsigned flags) +{ + return jl_load_dynamic_library_(modname, flags, 0); +} + +uv_lib_t *jl_load_dynamic_library(char *modname, unsigned flags) +{ + return jl_load_dynamic_library_(modname, flags, 1); +} + void *jl_dlsym_e(uv_lib_t *handle, char *symbol) { void *ptr; @@ -132,7 +146,32 @@ void *jl_dlsym(uv_lib_t *handle, char *symbol) void *ptr; int error = uv_dlsym(handle, symbol, &ptr); if (error != 0) { - JL_PRINTF(JL_STDERR, "symbol could not be found %s (%d): %s\n", symbol, error, uv_dlerror(handle)); + jl_printf(JL_STDERR, "symbol could not be found %s (%d): %s\n", symbol, error, uv_dlerror(handle)); } return ptr; } + +#ifdef __WIN32__ +//Look for symbols in win32 libraries +void *jl_dlsym_win32(char *f_name) +{ + void *fptr = jl_dlsym_e(jl_exe_handle, f_name); + if(!fptr) { + fptr = jl_dlsym_e(jl_dl_handle, f_name); + if (!fptr) { + fptr = jl_dlsym_e(jl_kernel32_handle, f_name); + if (!fptr) { + fptr = jl_dlsym_e(jl_ntdll_handle, f_name); + if (!fptr) { + fptr = jl_dlsym_e(jl_crtdll_handle, f_name); + if (!fptr) { + fptr = jl_dlsym(jl_winsock_handle, f_name); + } + } + } + } + } + return fptr; +} + +#endif diff --git a/src/dump.c b/src/dump.c index 98d7c87a3a989..5dbb8303b2bc2 100644 --- a/src/dump.c +++ b/src/dump.c @@ -24,8 +24,10 @@ static const ptrint_t LongExpr_tag = 25; static const ptrint_t LiteralVal_tag = 26; static const ptrint_t SmallInt64_tag = 27; static const ptrint_t IdTable_tag = 28; -static const ptrint_t Null_tag = 254; -static const ptrint_t BackRef_tag = 255; +static const ptrint_t Int32_tag = 29; +static const ptrint_t Null_tag = 253; +static const ptrint_t ShortBackRef_tag = 254; +static const ptrint_t BackRef_tag = 255; static ptrint_t VALUE_TAGS; @@ -35,7 +37,7 @@ static jl_array_t *tree_literal_values=NULL; static jl_value_t *jl_idtable_type=NULL; // queue of types to cache -static jl_array_t *tagtype_list=NULL; +static jl_array_t *datatype_list=NULL; #define write_uint8(s, n) ios_putc((n), (s)) #define read_uint8(s) ((uint8_t)ios_getc(s)) @@ -95,54 +97,41 @@ static void jl_serialize_fptr(ios_t *s, void *fptr) void **pbp = ptrhash_bp(&fptr_to_id, fptr); if (*pbp == HT_NOTFOUND) jl_error("unknown function pointer"); - write_int32(s, *(ptrint_t*)pbp); + write_uint16(s, *(ptrint_t*)pbp); } -static void jl_serialize_tag_type(ios_t *s, jl_value_t *v) +static void jl_serialize_datatype(ios_t *s, jl_datatype_t *dt) { - if (jl_is_struct_type(v)) { - writetag(s, (jl_value_t*)jl_struct_kind); - jl_serialize_value(s, jl_struct_kind); - write_uint16(s, ((jl_struct_type_t*)v)->names->length); - write_int32(s, ((jl_struct_type_t*)v)->uid); - write_int32(s, ((jl_struct_type_t*)v)->size); - write_int32(s, ((jl_struct_type_t*)v)->alignment); - size_t nf = ((jl_struct_type_t*)v)->names->length; - ios_write(s, (char*)&((jl_struct_type_t*)v)->fields[0], nf*sizeof(jl_fielddesc_t)); - jl_serialize_value(s, ((jl_struct_type_t*)v)->name); - jl_serialize_value(s, ((jl_struct_type_t*)v)->parameters); - jl_serialize_value(s, ((jl_struct_type_t*)v)->super); - jl_serialize_value(s, ((jl_struct_type_t*)v)->names); - jl_serialize_value(s, ((jl_struct_type_t*)v)->types); - jl_serialize_value(s, ((jl_struct_type_t*)v)->ctor_factory); - jl_serialize_value(s, ((jl_struct_type_t*)v)->env); - jl_serialize_value(s, ((jl_struct_type_t*)v)->linfo); - jl_serialize_fptr(s, ((jl_struct_type_t*)v)->fptr); - } - else if (jl_is_bits_type(v)) { - writetag(s, jl_struct_kind); - jl_serialize_value(s, jl_bits_kind); - if (v == (jl_value_t*)jl_int32_type) - write_uint8(s, 2); - else if (v == (jl_value_t*)jl_bool_type) - write_uint8(s, 3); - else if (v == (jl_value_t*)jl_int64_type) - write_uint8(s, 4); - else - write_uint8(s, 0); - jl_serialize_value(s, ((jl_tag_type_t*)v)->name); - jl_serialize_value(s, ((jl_bits_type_t*)v)->parameters); - write_int32(s, ((jl_bits_type_t*)v)->nbits); - jl_serialize_value(s, ((jl_bits_type_t*)v)->super); - write_int32(s, ((jl_bits_type_t*)v)->uid); - } - else { - assert(jl_is_tag_type(v)); - writetag(s, jl_tag_kind); - jl_serialize_value(s, ((jl_tag_type_t*)v)->name); - jl_serialize_value(s, ((jl_tag_type_t*)v)->parameters); - jl_serialize_value(s, ((jl_tag_type_t*)v)->super); + writetag(s, (jl_value_t*)jl_datatype_type); + jl_serialize_value(s, (jl_value_t*)jl_datatype_type); + int tag = 0; + if (dt == jl_int32_type) + tag = 2; + else if (dt == jl_bool_type) + tag = 3; + else if (dt == jl_int64_type) + tag = 4; + write_uint8(s, tag); + size_t nf = jl_tuple_len(dt->names); + write_uint16(s, nf); + write_int32(s, dt->size); + if (nf > 0) { + write_int32(s, dt->alignment); + ios_write(s, (char*)&dt->fields[0], nf*sizeof(jl_fielddesc_t)); + jl_serialize_value(s, dt->names); + jl_serialize_value(s, dt->types); } + write_uint8(s, dt->abstract | (dt->mutabl<<1) | (dt->pointerfree<<2)); + if (!dt->abstract) + write_int32(s, dt->uid); + + jl_serialize_value(s, dt->name); + jl_serialize_value(s, dt->parameters); + jl_serialize_value(s, dt->super); + jl_serialize_value(s, dt->ctor_factory); + jl_serialize_value(s, dt->env); + jl_serialize_value(s, dt->linfo); + jl_serialize_fptr(s, dt->fptr); } static void jl_serialize_module(ios_t *s, jl_module_t *m) @@ -182,9 +171,15 @@ static void jl_serialize_module(ios_t *s, jl_module_t *m) static int is_ast_node(jl_value_t *v) { + if (jl_is_lambda_info(v)) { + jl_lambda_info_t *li = (jl_lambda_info_t*)v; + if (jl_is_expr(li->ast)) + li->ast = jl_compress_ast(li, li->ast); + return 0; + } return jl_is_symbol(v) || jl_is_expr(v) || jl_typeis(v, jl_array_any_type) || jl_is_tuple(v) || - jl_is_union_type(v) || jl_is_int32(v) || jl_is_int64(v) || + jl_is_uniontype(v) || jl_is_int32(v) || jl_is_int64(v) || jl_is_symbolnode(v) || jl_is_bool(v) || jl_is_typevar(v) || jl_is_topnode(v) || jl_is_quotenode(v) || jl_is_gotonode(v) || jl_is_labelnode(v) || jl_is_linenode(v) || jl_is_getfieldnode(v); @@ -193,7 +188,7 @@ static int is_ast_node(jl_value_t *v) static int literal_val_id(jl_value_t *v) { for(int i=0; i < jl_array_len(tree_literal_values); i++) { - if (jl_cellref(tree_literal_values,i) == v) + if (jl_egal(jl_cellref(tree_literal_values,i), v)) return i; } jl_cell_1d_push(tree_literal_values, v); @@ -224,8 +219,14 @@ static void jl_serialize_value_(ios_t *s, jl_value_t *v) else { bp = ptrhash_bp(&backref_table, v); if (*bp != HT_NOTFOUND) { - write_uint8(s, BackRef_tag); - write_int32(s, (ptrint_t)*bp); + if ((uptrint_t)*bp < 65536) { + write_uint8(s, ShortBackRef_tag); + write_uint16(s, (uptrint_t)*bp); + } + else { + write_uint8(s, BackRef_tag); + write_int32(s, (uptrint_t)*bp); + } return; } ptrhash_put(&backref_table, v, (void*)(ptrint_t)ios_pos(s)); @@ -262,10 +263,9 @@ static void jl_serialize_value_(ios_t *s, jl_value_t *v) jl_array_t *ar = (jl_array_t*)v; writetag(s, (jl_value_t*)jl_array_type); jl_serialize_value(s, jl_typeof(ar)); - jl_value_t *elty = jl_tparam0(jl_typeof(ar)); for (i=0; i < ar->ndims; i++) jl_serialize_value(s, jl_box_long(jl_array_dim(ar,i))); - if (jl_is_bits_type(elty)) { + if (!ar->ptrarray) { size_t tot = jl_array_len(ar) * ar->elsize; ios_write(s, jl_array_data(ar), tot); } @@ -292,8 +292,8 @@ static void jl_serialize_value_(ios_t *s, jl_value_t *v) jl_serialize_value(s, jl_exprarg(e, i)); } } - else if (jl_is_some_tag_type(v)) { - jl_serialize_tag_type(s, v); + else if (jl_is_datatype(v)) { + jl_serialize_datatype(s, (jl_datatype_t*)v); } else if (jl_is_typevar(v)) { writetag(s, jl_tvar_type); @@ -307,9 +307,7 @@ static void jl_serialize_value_(ios_t *s, jl_value_t *v) jl_function_t *f = (jl_function_t*)v; jl_serialize_value(s, (jl_value_t*)f->linfo); jl_serialize_value(s, f->env); - if (f->linfo && f->linfo->ast && - (jl_is_expr(f->linfo->ast) || jl_is_tuple(f->linfo->ast)) && - f->fptr != &jl_trampoline) { + if (f->linfo && f->linfo->ast && f->fptr != &jl_trampoline) { jl_serialize_fptr(s, &jl_trampoline); } else { @@ -334,6 +332,9 @@ static void jl_serialize_value_(ios_t *s, jl_value_t *v) jl_serialize_value(s, (jl_value_t*)li->file); write_int32(s, li->line); jl_serialize_value(s, (jl_value_t*)li->module); + jl_serialize_value(s, (jl_value_t*)li->roots); + jl_serialize_value(s, (jl_value_t*)li->def); + jl_serialize_value(s, (jl_value_t*)li->capt); } else if (jl_typeis(v, jl_module_type)) { jl_serialize_module(s, (jl_module_t*)v); @@ -342,32 +343,41 @@ static void jl_serialize_value_(ios_t *s, jl_value_t *v) jl_error("Task cannot be serialized"); } else { - jl_value_t *t = (jl_value_t*)jl_typeof(v); - if (jl_is_bits_type(t)) { - void *data = jl_bits_data(v); - if (t == (jl_value_t*)jl_int64_type && - *(int64_t*)data >= S32_MIN && *(int64_t*)data <= S32_MAX) { - writetag(s, (jl_value_t*)SmallInt64_tag); - write_int32(s, (int32_t)*(int64_t*)data); + jl_datatype_t *t = (jl_datatype_t*)jl_typeof(v); + void *data = jl_data_ptr(v); + if (t == jl_int64_type && + *(int64_t*)data >= S32_MIN && *(int64_t*)data <= S32_MAX) { + writetag(s, (jl_value_t*)SmallInt64_tag); + write_int32(s, (int32_t)*(int64_t*)data); + return; + } + if (t == jl_int32_type) { + writetag(s, (jl_value_t*)Int32_tag); + write_int32(s, (int32_t)*(int32_t*)data); + return; + } + if ((jl_value_t*)t == jl_idtable_type) + writetag(s, (jl_value_t*)IdTable_tag); + else + writetag(s, (jl_value_t*)jl_datatype_type); + jl_serialize_value(s, t); + size_t nf = jl_tuple_len(t->names); + if (nf == 0 && jl_datatype_size(t)>0) { + if (t->name == jl_pointer_type->name) { + write_int32(s, 0); +#ifdef _P64 + write_int32(s, 0); +#endif } else { - int nb = ((jl_bits_type_t*)t)->nbits; - writetag(s, jl_bits_kind); - jl_serialize_value(s, t); - ios_write(s, data, nb/8); + ios_write(s, data, jl_datatype_size(t)); } } - else if (jl_is_struct_type(t)) { - if (t == jl_idtable_type) - writetag(s, (jl_value_t*)IdTable_tag); - else - writetag(s, jl_struct_kind); - jl_serialize_value(s, t); - if (t == jl_idtable_type) { + else { + if ((jl_value_t*)t == jl_idtable_type) { jl_array_t *data = (jl_array_t*)jl_get_nth_field(v, 0); jl_value_t **d = (jl_value_t**)data->data; - size_t i; - for(i=0; i < data->length; i+=2) { + for(size_t i=0; i < jl_array_len(data); i+=2) { if (d[i+1] != NULL) { jl_serialize_value(s, d[i+1]); jl_serialize_value(s, d[i]); @@ -376,17 +386,11 @@ static void jl_serialize_value_(ios_t *s, jl_value_t *v) jl_serialize_value(s, NULL); } else { - jl_struct_type_t *st = (jl_struct_type_t*)t; - size_t nf = jl_tuple_len(st->names); - size_t i; - for(i=0; i < nf; i++) { + for(size_t i=0; i < nf; i++) { jl_serialize_value(s, jl_get_nth_field(v, i)); } } } - else { - assert(0); - } } } @@ -396,7 +400,7 @@ static jl_value_t *jl_deserialize_value(ios_t *s); static jl_fptr_t jl_deserialize_fptr(ios_t *s) { - int fptr = read_int32(s); + int fptr = read_uint16(s); if (fptr == 0) return NULL; void **pbp = ptrhash_bp(&id_to_fptr, (void*)(ptrint_t)fptr); @@ -405,81 +409,61 @@ static jl_fptr_t jl_deserialize_fptr(ios_t *s) return *(jl_fptr_t*)pbp; } -static jl_value_t *jl_deserialize_tag_type(ios_t *s, jl_struct_type_t *kind, int pos) +static jl_value_t *jl_deserialize_datatype(ios_t *s, int pos) { - if (kind == jl_struct_kind) { - uint16_t nf = read_uint16(s); - jl_struct_type_t *st = jl_new_uninitialized_struct_type(nf); - st->uid = read_int32(s); - st->size = read_int32(s); - st->alignment = read_int32(s); - ios_read(s, (char*)&st->fields[0], nf*sizeof(jl_fielddesc_t)); - st->instance = NULL; - ptrhash_put(&backref_table, (void*)(ptrint_t)pos, st); - st->name = (jl_typename_t*)jl_deserialize_value(s); - st->parameters = (jl_tuple_t*)jl_deserialize_value(s); - st->super = (jl_tag_type_t*)jl_deserialize_value(s); - st->names = (jl_tuple_t*)jl_deserialize_value(s); - st->types = (jl_tuple_t*)jl_deserialize_value(s); - st->ctor_factory = jl_deserialize_value(s); - st->env = jl_deserialize_value(s); - st->linfo = (jl_lambda_info_t*)jl_deserialize_value(s); - st->fptr = jl_deserialize_fptr(s); - if (st->name == jl_array_type->name) { - // builtin types are not serialized, so their caches aren't - // explicitly saved. so we reconstruct the caches of builtin - // parametric types here. - jl_cell_1d_push(tagtype_list, (jl_value_t*)st); - } - return (jl_value_t*)st; - } - else if (kind == jl_bits_kind) { - int form = read_uint8(s); - jl_bits_type_t *bt; - if (form == 2) - bt = jl_int32_type; - else if (form == 3) - bt = jl_bool_type; - else if (form == 4) - bt = jl_int64_type; - else - bt = (jl_bits_type_t*)newobj((jl_type_t*)jl_bits_kind, - BITS_TYPE_NW); - ptrhash_put(&backref_table, (void*)(ptrint_t)pos, bt); - bt->name = (jl_typename_t*)jl_deserialize_value(s); - bt->parameters = (jl_tuple_t*)jl_deserialize_value(s); - - size_t nbits = read_int32(s); - bt->nbits = nbits; - bt->fptr = NULL; - bt->env = NULL; - bt->linfo = NULL; - bt->super = (jl_tag_type_t*)jl_deserialize_value(s); - bt->uid = read_int32(s); - if (bt->name == jl_pointer_type->name) { - jl_cell_1d_push(tagtype_list, (jl_value_t*)bt); - } - return (jl_value_t*)bt; + int tag = read_uint8(s); + uint16_t nf = read_uint16(s); + size_t size = read_int32(s); + jl_datatype_t *dt; + if (tag == 2) + dt = jl_int32_type; + else if (tag == 3) + dt = jl_bool_type; + else if (tag == 4) + dt = jl_int64_type; + else + dt = jl_new_uninitialized_datatype(nf); + dt->size = size; + + assert(tree_literal_values==NULL); + ptrhash_put(&backref_table, (void*)(ptrint_t)pos, dt); + + if (nf > 0) { + dt->alignment = read_int32(s); + ios_read(s, (char*)&dt->fields[0], nf*sizeof(jl_fielddesc_t)); + dt->names = (jl_tuple_t*)jl_deserialize_value(s); + dt->types = (jl_tuple_t*)jl_deserialize_value(s); } else { - assert(kind == jl_tag_kind); - jl_tag_type_t *tt = - (jl_tag_type_t*)newobj((jl_type_t*)jl_tag_kind, TAG_TYPE_NW); - ptrhash_put(&backref_table, (void*)(ptrint_t)pos, tt); - tt->name = (jl_typename_t*)jl_deserialize_value(s); - tt->parameters = (jl_tuple_t*)jl_deserialize_value(s); - tt->super = (jl_tag_type_t*)jl_deserialize_value(s); - tt->fptr = NULL; - tt->env = NULL; - tt->linfo = NULL; - if (tt->name == jl_type_type->name || tt->name == jl_seq_type->name || - tt->name == jl_abstractarray_type->name) { - jl_cell_1d_push(tagtype_list, (jl_value_t*)tt); - } - return (jl_value_t*)tt; + dt->alignment = dt->size; + dt->names = dt->types = jl_null; } - assert(0); - return NULL; + uint8_t flags = read_uint8(s); + dt->abstract = flags&1; + dt->mutabl = (flags>>1)&1; + dt->pointerfree = (flags>>2)&1; + if (!dt->abstract) + dt->uid = read_int32(s); + else + dt->uid = 0; + dt->name = (jl_typename_t*)jl_deserialize_value(s); + dt->parameters = (jl_tuple_t*)jl_deserialize_value(s); + dt->super = (jl_datatype_t*)jl_deserialize_value(s); + dt->ctor_factory = jl_deserialize_value(s); + dt->env = jl_deserialize_value(s); + dt->linfo = (jl_lambda_info_t*)jl_deserialize_value(s); + dt->fptr = jl_deserialize_fptr(s); + dt->struct_decl = NULL; + dt->instance = NULL; + if (dt->name == jl_array_type->name || dt->name == jl_pointer_type->name || + dt->name == jl_type_type->name || dt->name == jl_vararg_type->name || + dt->name == jl_abstractarray_type->name) { + // builtin types are not serialized, so their caches aren't + // explicitly saved. so we reconstruct the caches of builtin + // parametric types here. + jl_cell_1d_push(datatype_list, (jl_value_t*)dt); + } + return (jl_value_t*)dt; } jl_array_t *jl_eqtable_put(jl_array_t *h, void *key, void *val); @@ -496,9 +480,9 @@ static jl_value_t *jl_deserialize_value(ios_t *s) assert(v != HT_NOTFOUND); return v; } - if (tag == BackRef_tag) { + if (tag == BackRef_tag || tag == ShortBackRef_tag) { assert(tree_literal_values == NULL); - ptrint_t offs = read_int32(s); + ptrint_t offs = (tag == BackRef_tag) ? read_int32(s) : read_uint16(s); void **bp = ptrhash_bp(&backref_table, (void*)(ptrint_t)offs); assert(*bp != HT_NOTFOUND); return (jl_value_t*)*bp; @@ -543,15 +527,14 @@ static jl_value_t *jl_deserialize_value(ios_t *s) } else if (vtag == (jl_value_t*)jl_array_type) { jl_value_t *aty = jl_deserialize_value(s); - jl_value_t *elty = jl_tparam0(aty); int16_t ndims = jl_unbox_long(jl_tparam1(aty)); size_t *dims = alloca(ndims*sizeof(size_t)); for(i=0; i < ndims; i++) dims[i] = jl_unbox_long(jl_deserialize_value(s)); - jl_array_t *a = jl_new_array_((jl_type_t*)aty, ndims, dims); + jl_array_t *a = jl_new_array_((jl_value_t*)aty, ndims, dims); if (usetable) ptrhash_put(&backref_table, (void*)(ptrint_t)pos, (jl_value_t*)a); - if (jl_is_bits_type(elty)) { + if (!a->ptrarray) { size_t tot = jl_array_len(a) * a->elsize; ios_read(s, jl_array_data(a), tot); } @@ -582,7 +565,7 @@ static jl_value_t *jl_deserialize_value(ios_t *s) return jl_cellref(tree_literal_values, read_uint16(s)); } else if (vtag == (jl_value_t*)jl_tvar_type) { - jl_tvar_t *tv = (jl_tvar_t*)newobj((jl_type_t*)jl_tvar_type, 4); + jl_tvar_t *tv = (jl_tvar_t*)newobj((jl_value_t*)jl_tvar_type, 4); if (usetable) ptrhash_put(&backref_table, (void*)(ptrint_t)pos, tv); tv->name = (jl_sym_t*)jl_deserialize_value(s); @@ -593,7 +576,7 @@ static jl_value_t *jl_deserialize_value(ios_t *s) } else if (vtag == (jl_value_t*)jl_function_type) { jl_function_t *f = - (jl_function_t*)newobj((jl_type_t*)jl_function_type, 3); + (jl_function_t*)newobj((jl_value_t*)jl_function_type, 3); if (usetable) ptrhash_put(&backref_table, (void*)(ptrint_t)pos, f); f->linfo = (jl_lambda_info_t*)jl_deserialize_value(s); @@ -603,7 +586,7 @@ static jl_value_t *jl_deserialize_value(ios_t *s) } else if (vtag == (jl_value_t*)jl_lambda_info_type) { jl_lambda_info_t *li = - (jl_lambda_info_t*)newobj((jl_type_t*)jl_lambda_info_type, + (jl_lambda_info_t*)newobj((jl_value_t*)jl_lambda_info_type, LAMBDA_INFO_NW); if (usetable) ptrhash_put(&backref_table, (void*)(ptrint_t)pos, li); @@ -614,12 +597,14 @@ static jl_value_t *jl_deserialize_value(ios_t *s) li->specTypes = (jl_tuple_t*)jl_deserialize_value(s); li->specializations = (jl_array_t*)jl_deserialize_value(s); li->inferred = read_int8(s); - li->file = jl_deserialize_value(s); + li->file = (jl_sym_t*)jl_deserialize_value(s); li->line = read_int32(s); li->module = (jl_module_t*)jl_deserialize_value(s); + li->roots = (jl_array_t*)jl_deserialize_value(s); + li->def = (jl_lambda_info_t*)jl_deserialize_value(s); + li->capt = jl_deserialize_value(s); li->fptr = &jl_trampoline; - li->roots = NULL; li->functionObject = NULL; li->cFunctionObject = NULL; li->inInference = 0; @@ -639,7 +624,7 @@ static jl_value_t *jl_deserialize_value(ios_t *s) break; jl_binding_t *b = jl_get_binding_wr(m, (jl_sym_t*)name); b->value = jl_deserialize_value(s); - b->type = (jl_type_t*)jl_deserialize_value(s); + b->type = (jl_value_t*)jl_deserialize_value(s); b->owner = (jl_module_t*)jl_deserialize_value(s); int8_t flags = read_int8(s); b->constp = (flags>>2) & 1; @@ -658,64 +643,68 @@ static jl_value_t *jl_deserialize_value(ios_t *s) ptrhash_put(&backref_table, (void*)(ptrint_t)pos, v); return v; } - else if (vtag == (jl_value_t*)jl_bits_kind) { - jl_bits_type_t *bt = (jl_bits_type_t*)jl_deserialize_value(s); - int nby = bt->nbits/8; - char *data = alloca(nby); - ios_read(s, data, nby); - jl_value_t *v=NULL; - if (bt == jl_int32_type) - v = jl_box_int32(*(int32_t*)data); - else if (bt == jl_int64_type) - v = jl_box_int64(*(int64_t*)data); - else if (bt == jl_bool_type) - v = jl_box_bool(*(int8_t*)data); - else { - switch (bt->nbits) { - case 8: v = jl_box8 (bt, *(int8_t*) data); break; - case 16: v = jl_box16(bt, *(int16_t*)data); break; - case 32: v = jl_box32(bt, *(int32_t*)data); break; - case 64: v = jl_box64(bt, *(int64_t*)data); break; - default: - v = (jl_value_t*)allocobj(sizeof(void*)+nby); - v->type = (jl_type_t*)bt; - memcpy(jl_bits_data(v), data, nby); - } - } + else if (vtag == (jl_value_t*)Int32_tag) { + jl_value_t *v = jl_box_int32(read_int32(s)); if (usetable) ptrhash_put(&backref_table, (void*)(ptrint_t)pos, v); return v; } - else if (vtag == (jl_value_t*)jl_struct_kind || vtag == (jl_value_t*)IdTable_tag) { - jl_struct_type_t *typ = (jl_struct_type_t*)jl_deserialize_value(s); - if (typ == jl_struct_kind || typ == jl_bits_kind) - return jl_deserialize_tag_type(s, typ, pos); - size_t nf = jl_tuple_len(typ->names); - jl_value_t *v = jl_new_struct_uninit(typ); - if (usetable) - ptrhash_put(&backref_table, (void*)(ptrint_t)pos, v); - if (vtag == (jl_value_t*)IdTable_tag) { - jl_array_t *a = jl_alloc_cell_1d(32); - while (1) { - jl_value_t *val = jl_deserialize_value(s); - if (val == NULL) - break; - jl_value_t *key = jl_deserialize_value(s); - a = jl_eqtable_put(a, key, val); + else if (vtag == (jl_value_t*)jl_datatype_type || vtag == (jl_value_t*)IdTable_tag) { + jl_datatype_t *dt = (jl_datatype_t*)jl_deserialize_value(s); + if (dt == jl_datatype_type) + return jl_deserialize_datatype(s, pos); + size_t nf = jl_tuple_len(dt->names); + jl_value_t *v; + if (nf == 0 && jl_datatype_size(dt)>0) { + int nby = jl_datatype_size(dt); + char *data = alloca(nby); + ios_read(s, data, nby); + v = NULL; + if (dt == jl_int32_type) + v = jl_box_int32(*(int32_t*)data); + else if (dt == jl_int64_type) + v = jl_box_int64(*(int64_t*)data); + else if (dt == jl_bool_type) + v = jl_box_bool(*(int8_t*)data); + else { + switch (nby) { + case 1: v = jl_box8 (dt, *(int8_t*) data); break; + case 2: v = jl_box16(dt, *(int16_t*)data); break; + case 4: v = jl_box32(dt, *(int32_t*)data); break; + case 8: v = jl_box64(dt, *(int64_t*)data); break; + default: + v = (jl_value_t*)allocobj(sizeof(void*)+nby); + v->type = (jl_value_t*)dt; + memcpy(jl_data_ptr(v), data, nby); + } } - jl_set_nth_field(v, 0, (jl_value_t*)a); + if (usetable) + ptrhash_put(&backref_table, (void*)(ptrint_t)pos, v); } else { - for(i=0; i < nf; i++) { - jl_set_nth_field(v, i, jl_deserialize_value(s)); + v = jl_new_struct_uninit(dt); + if (usetable) + ptrhash_put(&backref_table, (void*)(ptrint_t)pos, v); + if (vtag == (jl_value_t*)IdTable_tag) { + jl_array_t *a = jl_alloc_cell_1d(32); + while (1) { + jl_value_t *val = jl_deserialize_value(s); + if (val == NULL) + break; + jl_value_t *key = jl_deserialize_value(s); + a = jl_eqtable_put(a, key, val); + } + jl_set_nth_field(v, 0, (jl_value_t*)a); + } + else { + for(i=0; i < nf; i++) { + jl_set_nth_field(v, i, jl_deserialize_value(s)); + } } } // TODO: put WeakRefs on the weak_refs list return v; } - else if (vtag == (jl_value_t*)jl_tag_kind) { - return jl_deserialize_tag_type(s, jl_tag_kind, pos); - } assert(0); return NULL; } @@ -739,7 +728,7 @@ void jl_save_system_image(char *fname) // delete cached slow ASCIIString constructor if present jl_methtable_t *mt = jl_gf_mtable((jl_function_t*)jl_ascii_string_type); jl_array_t *spec = mt->defs->func->linfo->specializations; - if (spec->length > 0 && + if (jl_array_len(spec) > 0 && ((jl_lambda_info_t*)jl_cellref(spec,0))->inferred == 0) { mt->cache = JL_NULL; mt->cache_arg1 = JL_NULL; @@ -765,6 +754,7 @@ extern jl_function_t *jl_typeinf_func; extern int jl_boot_file_loaded; extern void jl_get_builtin_hooks(void); extern void jl_get_system_hooks(void); +extern void jl_get_uv_hooks(void); DLLEXPORT void jl_restore_system_image(char *fname) @@ -773,14 +763,14 @@ void jl_restore_system_image(char *fname) char *fpath = fname; if (ios_file(&f, fpath, 1, 0, 0, 0) == NULL) { JL_PRINTF(JL_STDERR, "system image file not found\n"); - jl_exit(1); + exit(1); } #ifdef JL_GC_MARKSWEEP int en = jl_gc_is_enabled(); jl_gc_disable(); #endif - tagtype_list = jl_alloc_cell_1d(0); + datatype_list = jl_alloc_cell_1d(0); jl_array_type->env = jl_deserialize_value(&f); @@ -792,22 +782,16 @@ void jl_restore_system_image(char *fname) jl_current_module = jl_base_module; // run start_image in Base // cache builtin parametric types - for(int i=0; i < jl_array_len(tagtype_list); i++) { - jl_value_t *v = jl_cellref(tagtype_list, i); - uint32_t uid=0; - if (jl_is_struct_type(v)) - uid = ((jl_struct_type_t*)v)->uid; - else if (jl_is_bits_type(v)) - uid = ((jl_bits_type_t*)v)->uid; - jl_cache_type_((jl_tag_type_t*)v); - if (jl_is_struct_type(v)) - ((jl_struct_type_t*)v)->uid = uid; - else if (jl_is_bits_type(v)) - ((jl_bits_type_t*)v)->uid = uid; + for(int i=0; i < jl_array_len(datatype_list); i++) { + jl_value_t *v = jl_cellref(datatype_list, i); + uint32_t uid = ((jl_datatype_t*)v)->uid; + jl_cache_type_((jl_datatype_t*)v); + ((jl_datatype_t*)v)->uid = uid; } jl_get_builtin_hooks(); jl_get_system_hooks(); + jl_get_uv_hooks(); jl_boot_file_loaded = 1; jl_typeinf_func = (jl_function_t*)jl_get_global(jl_base_module, jl_symbol("typeinf_ext")); @@ -825,41 +809,59 @@ void jl_restore_system_image(char *fname) #endif } +DLLEXPORT +jl_value_t *jl_ast_rettype(jl_lambda_info_t *li, jl_value_t *ast) +{ + if (jl_is_expr(ast)) + return jl_lam_body((jl_expr_t*)ast)->etype; + tree_literal_values = li->def->roots; + ios_t src; + jl_array_t *bytes = (jl_array_t*)ast; + ios_mem(&src, 0); + ios_setbuf(&src, bytes->data, jl_array_len(bytes), 0); + src.size = jl_array_len(bytes); + jl_value_t *rt = jl_deserialize_value(&src); + tree_literal_values = NULL; + return rt; +} + DLLEXPORT jl_value_t *jl_compress_ast(jl_lambda_info_t *li, jl_value_t *ast) { ios_t dest; ios_mem(&dest, 0); + jl_array_t *last_tlv = tree_literal_values; int en = jl_gc_is_enabled(); jl_gc_disable(); - if (li->roots == NULL) - li->roots = jl_alloc_cell_1d(0); - tree_literal_values = li->roots; + jl_lambda_info_t *def = li->def; + if (def->roots == NULL) { + def->roots = jl_alloc_cell_1d(0); + } + tree_literal_values = def->roots; + li->capt = (jl_value_t*)jl_lam_capt((jl_expr_t*)ast); + if (jl_array_len(li->capt) == 0) + li->capt = NULL; + jl_serialize_value(&dest, jl_lam_body((jl_expr_t*)ast)->etype); jl_serialize_value(&dest, ast); //JL_PRINTF(JL_STDERR, "%d bytes, %d values\n", dest.size, vals->length); jl_value_t *v = (jl_value_t*)jl_takebuf_array(&dest); if (jl_array_len(tree_literal_values) == 0) { - tree_literal_values = (jl_array_t*)jl_an_empty_cell; - li->roots = NULL; + def->roots = NULL; } - v = (jl_value_t*)jl_tuple(4, v, tree_literal_values, - jl_lam_body((jl_expr_t*)ast)->etype, - jl_lam_capt((jl_expr_t*)ast)); - - tree_literal_values = NULL; + tree_literal_values = last_tlv; if (en) jl_gc_enable(); return v; } DLLEXPORT -jl_value_t *jl_uncompress_ast(jl_tuple_t *data) +jl_value_t *jl_uncompress_ast(jl_lambda_info_t *li, jl_value_t *data) { - jl_array_t *bytes = (jl_array_t*)jl_tupleref(data, 0); - tree_literal_values = (jl_array_t*)jl_tupleref(data, 1); + jl_array_t *bytes = (jl_array_t*)data; + tree_literal_values = li->def->roots; ios_t src; ios_mem(&src, 0); ios_setbuf(&src, bytes->data, jl_array_len(bytes), 0); @@ -867,6 +869,7 @@ jl_value_t *jl_uncompress_ast(jl_tuple_t *data) int en = jl_gc_is_enabled(); jl_gc_disable(); jl_gc_ephemeral_on(); + (void)jl_deserialize_value(&src); // skip ret type jl_value_t *v = jl_deserialize_value(&src); jl_gc_ephemeral_off(); if (en) @@ -885,17 +888,17 @@ void jl_init_serializer(void) htable_new(&id_to_fptr, 0); htable_new(&backref_table, 50000); - void *tags[] = { jl_symbol_type, jl_tag_kind, jl_bits_kind, jl_struct_kind, + void *tags[] = { jl_symbol_type, jl_datatype_type, jl_function_type, jl_tuple_type, jl_array_type, jl_expr_type, (void*)LongSymbol_tag, (void*)LongTuple_tag, (void*)LongExpr_tag, (void*)LiteralVal_tag, (void*)SmallInt64_tag, (void*)IdTable_tag, + (void*)Int32_tag, jl_module_type, jl_tvar_type, jl_lambda_info_type, jl_null, jl_false, jl_true, jl_any_type, jl_symbol("Any"), jl_symbol("Array"), jl_symbol("TypeVar"), - jl_symbol("FuncKind"), jl_symbol("Box"), - jl_symbol("apply"), + jl_symbol("Box"), jl_symbol("apply"), lambda_sym, body_sym, return_sym, call_sym, colons_sym, null_sym, goto_ifnot_sym, assign_sym, @@ -909,7 +912,7 @@ void jl_init_serializer(void) jl_symbol("v"), jl_symbol("w"), jl_symbol("x"), jl_symbol("y"), jl_symbol("z"), jl_symbol("A"), jl_symbol("B"), jl_symbol("C"), - jl_symbol("M"), jl_symbol("I"), jl_symbol("N"), + jl_symbol("I"), jl_symbol("N"), jl_symbol("T"), jl_symbol("S"), jl_symbol("X"), jl_symbol("Y"), jl_symbol("add_int"), jl_symbol("sub_int"), @@ -924,7 +927,7 @@ void jl_init_serializer(void) jl_symbol("convert"), jl_symbol("typeassert"), jl_symbol("getfield"), jl_symbol("setfield"), jl_symbol("tupleref"), jl_symbol("tuplelen"), - jl_symbol("apply_type"), jl_symbol("tuple"), + jl_symbol("apply_type"), tuple_sym, jl_box_int32(0), jl_box_int32(1), jl_box_int32(2), jl_box_int32(3), jl_box_int32(4), jl_box_int32(5), @@ -937,7 +940,7 @@ void jl_init_serializer(void) jl_box_int32(24), jl_box_int32(25), jl_box_int32(26), jl_box_int32(27), jl_box_int32(28), jl_box_int32(29), jl_box_int32(30), jl_box_int32(31), jl_box_int32(32), -#ifndef __LP64__ +#ifndef _P64 jl_box_int32(33), jl_box_int32(34), jl_box_int32(35), jl_box_int32(36), jl_box_int32(37), jl_box_int32(38), jl_box_int32(39), jl_box_int32(40), jl_box_int32(41), @@ -961,7 +964,7 @@ void jl_init_serializer(void) jl_box_int64(24), jl_box_int64(25), jl_box_int64(26), jl_box_int64(27), jl_box_int64(28), jl_box_int64(29), jl_box_int64(30), jl_box_int64(31), jl_box_int64(32), -#ifdef __LP64__ +#ifdef _P64 jl_box_int64(33), jl_box_int64(34), jl_box_int64(35), jl_box_int64(36), jl_box_int64(37), jl_box_int64(38), jl_box_int64(39), jl_box_int64(40), jl_box_int64(41), @@ -977,19 +980,20 @@ void jl_init_serializer(void) jl_labelnode_type, jl_linenumbernode_type, jl_gotonode_type, jl_quotenode_type, jl_topnode_type, jl_type_type, jl_bottom_type, jl_pointer_type, - jl_seq_type, jl_ntuple_type, jl_abstractarray_type, + jl_vararg_type, jl_ntuple_type, jl_abstractarray_type, jl_box_type, jl_typector_type, jl_undef_type, jl_top_type, - jl_typename_type, jl_task_type, jl_union_kind, + jl_typename_type, jl_task_type, jl_uniontype_type, jl_typetype_type, jl_typetype_tvar, jl_ANY_flag, jl_array_any_type, jl_intrinsic_type, jl_method_type, - jl_methtable_type, + jl_methtable_type, jl_voidpointer_type, + jl_array_symbol_type, jl_tupleref(jl_tuple_type,0), jl_symbol_type->name, jl_pointer_type->name, - jl_tag_kind->name, jl_union_kind->name, jl_bits_kind->name, jl_struct_kind->name, + jl_datatype_type->name, jl_uniontype_type->name, jl_array_type->name, jl_expr_type->name, jl_typename_type->name, jl_type_type->name, jl_methtable_type->name, jl_method_type->name, jl_tvar_type->name, - jl_seq_type->name, jl_ntuple_type->name, jl_abstractarray_type->name, + jl_vararg_type->name, jl_ntuple_type->name, jl_abstractarray_type->name, jl_lambda_info_type->name, jl_module_type->name, jl_box_type->name, jl_function_type->name, jl_typector_type->name, jl_intrinsic_type->name, jl_undef_type->name, @@ -1021,7 +1025,7 @@ void jl_init_serializer(void) jl_f_set_field, jl_f_field_type, jl_f_arraylen, jl_f_arrayref, jl_f_arrayset, jl_f_arraysize, - jl_f_instantiate_type, + jl_f_instantiate_type, jl_f_kwcall, jl_f_convert_default, jl_f_convert_tuple, jl_trampoline, jl_f_new_type_constructor, jl_f_typevar, jl_f_union, @@ -1029,6 +1033,7 @@ void jl_init_serializer(void) jl_f_invoke, jl_apply_generic, jl_unprotect_stack, jl_f_task, jl_f_yieldto, jl_f_ctor_trampoline, + jl_f_new_module, NULL }; i=2; while (fptrs[i-2] != NULL) { diff --git a/src/file_constants.h b/src/file_constants.h new file mode 100644 index 0000000000000..348a96d3b6768 --- /dev/null +++ b/src/file_constants.h @@ -0,0 +1,23 @@ +#include +#include +#include +const JL_DUMMY = 0 +const JL_O_WRONLY = O_WRONLY +const JL_O_RDONLY = O_RDONLY +const JL_O_RDWR = O_RDWR +const JL_O_APPEND = O_APPEND +const JL_O_CREAT = O_CREAT +const JL_O_EXCL = O_EXCL +const JL_O_TRUNC = O_TRUNC +#ifdef O_TEMPORARY +const JL_O_TEMPORARY = O_TEMPORARY +#endif +#ifdef O_SHORT_LIVED +const JL_O_SHORT_LIVED = O_SHORT_LIVED +#endif +#ifdef O_SEQUENTIAL +const JL_O_SEQUENTIAL = O_SEQUENTIAL +#endif +#ifdef O_RANDOM +const JL_O_RANDOM = O_RANDOM +#endif diff --git a/src/flisp/Makefile b/src/flisp/Makefile index 6e353af6330ee..39fbd87c9600e 100644 --- a/src/flisp/Makefile +++ b/src/flisp/Makefile @@ -14,12 +14,15 @@ SRCS = flisp.c builtins.c string.c equalhash.c table.c iostream.c \ OBJS = $(SRCS:%.c=%.o) DOBJS = $(SRCS:%.c=%.do) LLTDIR = ../support -LLT = $(LLTDIR)/libsupport.a $(USR)/$(JL_LIBDIR)/libuv.a +LLT = $(LLTDIR)/libsupport.a $(BUILD)/lib/libuv.a FLAGS = -Wall -Wno-strict-aliasing -I$(LLTDIR) $(CFLAGS) \ -DUSE_COMPUTED_GOTO $(HFILEDIRS:%=-I%) $(LIBDIRS:%=-L%) -fvisibility=hidden LIBFILES = $(LLT) -LIBS = $(LIBFILES) -lm -lpthread +LIBS = $(LIBFILES) -lm +ifneq ($(OS),WINNT) +LIBS += -lpthread +endif DEBUGFLAGS += $(FLAGS) SHIPFLAGS += $(FLAGS) @@ -33,9 +36,9 @@ debug: $(EXENAME)-debug HEADERS = $(wildcard *.h) $(JULIAHOME)/deps/libuv/include/uv.h %.o: %.c $(HEADERS) - $(QUIET_CC) $(CC) $(SHIPFLAGS) -c $< -o $@ + $(QUIET_CC) $(CC) $(CPPFLAGS) $(SHIPFLAGS) -c $< -o $@ %.do: %.c $(HEADERS) - $(QUIET_CC) $(CC) $(DEBUGFLAGS) -c $< -o $@ + $(QUIET_CC) $(CC) $(CPPFLAGS) $(DEBUGFLAGS) -c $< -o $@ flisp.o: flisp.c cvalues.c types.c flisp.h print.c read.c equal.c flisp.do: flisp.c cvalues.c types.c flisp.h print.c read.c equal.c @@ -47,19 +50,19 @@ $(LLT): $(LLTDIR)/*.h $(LLTDIR)/*.c $(LIBTARGET)-debug.a: $(DOBJS) rm -rf $@ - $(QUIET_LINK) ar -rcs $@ $(DOBJS) + $(QUIET_LINK) $(AR) -rcs $@ $(DOBJS) ln -sf $@ $(LIBTARGET).a $(LIBTARGET).a: $(OBJS) rm -rf $@ - $(QUIET_LINK) ar -rcs $@ $(OBJS) + $(QUIET_LINK) $(AR) -rcs $@ $(OBJS) $(EXENAME)-debug: $(DOBJS) $(LIBFILES) $(LIBTARGET)-debug.a flmain.do - $(QUIET_CC) $(CC) $(DEBUGFLAGS) $(DOBJS) flmain.do -o $(EXENAME)-debug $(LIBS) $(LIBTARGET).a $(OSLIBS) + $(QUIET_CC) $(CC) $(DEBUGFLAGS) $(DOBJS) flmain.do -o $(EXENAME)-debug $(LIBTARGET).a $(LIBS) $(OSLIBS) ./$(EXENAME)-debug unittest.lsp $(EXENAME): $(OBJS) $(LIBFILES) $(LIBTARGET).a flmain.o - $(QUIET_CC) $(CC) $(SHIPFLAGS) $(OBJS) flmain.o -o $(EXENAME) $(LIBS) $(LIBTARGET).a $(OSLIBS) + $(QUIET_CC) $(CC) $(SHIPFLAGS) $(OBJS) flmain.o $(LDFLAGS) -o $(EXENAME) $(LIBTARGET).a $(LIBS) $(OSLIBS) ./$(EXENAME) unittest.lsp clean: diff --git a/src/flisp/builtins.c b/src/flisp/builtins.c index da5e635874a72..d233141fe5446 100644 --- a/src/flisp/builtins.c +++ b/src/flisp/builtins.c @@ -240,7 +240,7 @@ static value_t fl_fixnum(value_t *args, u_int32_t nargs) } else if (iscprim(args[0])) { cprim_t *cp = (cprim_t*)ptr(args[0]); - return fixnum(conv_to_long(cp_data(cp), cp_numtype(cp))); + return fixnum(conv_to_ptrdiff(cp_data(cp), cp_numtype(cp))); } type_error("fixnum", "number", args[0]); } @@ -279,7 +279,7 @@ static value_t fl_vector_alloc(value_t *args, u_int32_t nargs) value_t f, v; if (nargs == 0) lerror(ArgError, "vector.alloc: too few arguments"); - i = (fixnum_t)toulong(args[0], "vector.alloc"); + i = (fixnum_t)tosize(args[0], "vector.alloc"); if (i < 0) lerror(ArgError, "vector.alloc: invalid size"); if (nargs == 2) diff --git a/src/flisp/cvalues.c b/src/flisp/cvalues.c index 07a84607a131b..1d81821e12a55 100644 --- a/src/flisp/cvalues.c +++ b/src/flisp/cvalues.c @@ -1,4 +1,4 @@ -#ifdef __LP64__ +#ifdef _P64 #define NWORDS(sz) (((sz)+7)>>3) #else #define NWORDS(sz) (((sz)+3)>>2) @@ -8,7 +8,7 @@ static int ALIGN2, ALIGN4, ALIGN8, ALIGNPTR; value_t int8sym, uint8sym, int16sym, uint16sym, int32sym, uint32sym; value_t int64sym, uint64sym; -value_t longsym, ulongsym, bytesym, wcharsym; +value_t ptrdiffsym, sizesym, bytesym, wcharsym; value_t floatsym, doublesym; value_t gftypesym, stringtypesym, wcstringtypesym; value_t emptystringsym; @@ -21,7 +21,7 @@ static fltype_t *int8type, *uint8type; static fltype_t *int16type, *uint16type; static fltype_t *int32type, *uint32type; static fltype_t *int64type, *uint64type; -static fltype_t *longtype, *ulongtype; +static fltype_t *ptrdifftype, *sizetype; static fltype_t *floattype, *doubletype; fltype_t *bytetype, *wchartype; fltype_t *stringtype, *wcstringtype; @@ -302,12 +302,12 @@ num_ctor(int64, int64, T_INT64) num_ctor(uint64, uint64, T_UINT64) num_ctor(byte, uint8, T_UINT8) num_ctor(wchar, int32, T_INT32) -#ifdef __LP64__ -num_ctor(long, int64, T_INT64) -num_ctor(ulong, uint64, T_UINT64) +#ifdef _P64 +num_ctor(ptrdiff, int64, T_INT64) +num_ctor(size, uint64, T_UINT64) #else -num_ctor(long, int32, T_INT32) -num_ctor(ulong, uint32, T_UINT32) +num_ctor(ptrdiff, int32, T_INT32) +num_ctor(size, uint32, T_UINT32) #endif num_ctor(float, float, T_FLOAT) num_ctor(double, double, T_DOUBLE) @@ -317,16 +317,16 @@ value_t size_wrap(size_t sz) if (fits_fixnum(sz)) return fixnum(sz); assert(sizeof(void*) == sizeof(size_t)); - return mk_ulong(sz); + return mk_size(sz); } -size_t toulong(value_t n, char *fname) +size_t tosize(value_t n, char *fname) { if (isfixnum(n)) return numval(n); if (iscprim(n)) { cprim_t *cp = (cprim_t*)ptr(n); - return conv_to_ulong(cp_data(cp), cp_numtype(cp)); + return conv_to_size(cp_data(cp), cp_numtype(cp)); } type_error(fname, "number", n); return 0; @@ -360,7 +360,7 @@ static int cvalue_array_init(fltype_t *ft, value_t arg, void *dest) cnt = predict_arraylen(arg); if (iscons(cdr_(cdr_(type)))) { - size_t tc = toulong(car_(cdr_(cdr_(type))), "array"); + size_t tc = tosize(car_(cdr_(cdr_(type))), "array"); if (tc != cnt) lerror(ArgError, "array: size mismatch"); } @@ -460,8 +460,8 @@ size_t ctype_sizeof(value_t type, int *palign) *palign = ALIGN8; return 8; } - if (type == longsym || type == ulongsym) { -#ifdef __LP64__ + if (type == ptrdiffsym || type == sizesym) { +#ifdef _P64 *palign = ALIGN8; return 8; #else @@ -480,7 +480,7 @@ size_t ctype_sizeof(value_t type, int *palign) if (!iscons(cdr_(cdr_(type)))) lerror(ArgError, "sizeof: incomplete type"); value_t n = car_(cdr_(cdr_(type))); - size_t sz = toulong(n, "sizeof"); + size_t sz = tosize(n, "sizeof"); return sz * ctype_sizeof(t, palign); } } @@ -638,26 +638,26 @@ static numerictype_t sym_to_numtype(value_t type) return T_INT16; else if (type == uint16sym) return T_UINT16; -#ifdef __LP64__ +#ifdef _P64 else if (type == int32sym || type == wcharsym) #else - else if (type == int32sym || type == wcharsym || type == longsym) + else if (type == int32sym || type == wcharsym || type == ptrdiffsym) #endif return T_INT32; -#ifdef __LP64__ +#ifdef _P64 else if (type == uint32sym) #else - else if (type == uint32sym || type == ulongsym) + else if (type == uint32sym || type == sizesym) #endif return T_UINT32; -#ifdef __LP64__ - else if (type == int64sym || type == longsym) +#ifdef _P64 + else if (type == int64sym || type == ptrdiffsym) #else else if (type == int64sym) #endif return T_INT64; -#ifdef __LP64__ - else if (type == uint64sym || type == ulongsym) +#ifdef _P64 + else if (type == uint64sym || type == sizesym) #else else if (type == uint64sym) #endif @@ -666,7 +666,6 @@ static numerictype_t sym_to_numtype(value_t type) return T_FLOAT; else if (type == doublesym) return T_DOUBLE; - assert(0); return N_NUMTYPES; } @@ -687,7 +686,7 @@ value_t cvalue_new(value_t *args, u_int32_t nargs) size_t cnt; if (iscons(cdr_(cdr_(type)))) - cnt = toulong(car_(cdr_(cdr_(type))), "array"); + cnt = tosize(car_(cdr_(cdr_(type))), "array"); else if (nargs == 2) cnt = predict_arraylen(args[1]); else @@ -725,20 +724,20 @@ value_t cvalue_compare(value_t a, value_t b) } static void check_addr_args(char *fname, value_t arr, value_t ind, - char **data, ulong_t *index) + char **data, size_t *index) { size_t numel; cvalue_t *cv = (cvalue_t*)ptr(arr); *data = cv_data(cv); numel = cv_len(cv)/(cv_class(cv)->elsz); - *index = toulong(ind, fname); + *index = tosize(ind, fname); if (*index >= numel) bounds_error(fname, arr, ind); } static value_t cvalue_array_aref(value_t *args) { - char *data; ulong_t index; + char *data; size_t index; fltype_t *eltype = cv_class((cvalue_t*)ptr(args[0]))->eltype; value_t el = 0; numerictype_t nt = eltype->numtype; @@ -771,7 +770,7 @@ static value_t cvalue_array_aref(value_t *args) static value_t cvalue_array_aset(value_t *args) { - char *data; ulong_t index; + char *data; size_t index; fltype_t *eltype = cv_class((cvalue_t*)ptr(args[0]))->eltype; check_addr_args("aset!", args[0], args[1], &data, &index); char *dest = data + index*eltype->size; @@ -861,8 +860,8 @@ static void cvalues_init(void) ctor_cv_intern(uint64); ctor_cv_intern(byte); ctor_cv_intern(wchar); - ctor_cv_intern(long); - ctor_cv_intern(ulong); + ctor_cv_intern(ptrdiff); + ctor_cv_intern(size); ctor_cv_intern(float); ctor_cv_intern(double); @@ -887,12 +886,12 @@ static void cvalues_init(void) mk_primtype(uint32); mk_primtype(int64); mk_primtype(uint64); -#ifdef __LP64__ - mk_primtype_(long,int64); - mk_primtype_(ulong,uint64); +#ifdef _P64 + mk_primtype_(ptrdiff,int64); + mk_primtype_(size,uint64); #else - mk_primtype_(long,int32); - mk_primtype_(ulong,uint32); + mk_primtype_(ptrdiff,int32); + mk_primtype_(size,uint32); #endif mk_primtype_(byte,uint8); mk_primtype_(wchar,int32); diff --git a/src/flisp/equal.c b/src/flisp/equal.c index 60d514ea21d77..2301eec81f70b 100644 --- a/src/flisp/equal.c +++ b/src/flisp/equal.c @@ -278,7 +278,7 @@ value_t fl_equal(value_t a, value_t b) * less redundant tag checking, 3-bit tags */ -#ifdef __LP64__ +#ifdef _P64 #define MIX(a, b) int64hash((int64_t)(a) ^ (int64_t)(b)); #define doublehash(a) int64hash(a) #else diff --git a/src/flisp/flisp.boot b/src/flisp/flisp.boot index 0209f9ca633d5..571385e21a4a4 100644 --- a/src/flisp/flisp.boot +++ b/src/flisp/flisp.boot @@ -157,7 +157,7 @@ largc lvargc vargc argc compile-in lastcdr caddr ret values #fn(function) encode-byte-code bcode:code const-to-idx-vec]) filter keyword-arg?]) #fn(length)]) #fn(length)]) make-code-emitter lastcdr lambda-vars filter #.pair? - lambda])] #0=[#:g689 ()]) + lambda])] #0=[#:g695 ()]) compile-for #fn(":000r5e0g4316X0e1|}^g2342e1|}^g3342e1|}^g4342e2|c342;e4c541;" [1arg-lambda? compile-in emit for error "for: third form must be a 1-argument lambda"] compile-for) compile-if #fn("<000r4c0qe1|31e1|31g3\x84e2g331e3g331F6;0e4g331560e53045;" [#fn(";000r5g2]\x82>0e0~\x7fi02g344;g2^\x82>0e0~\x7fi02g444;e0~\x7f^g2342e1~c2|332e0~\x7fi02g3342i026<0e1~c3325:0e1~c4}332e5~|322e0~\x7fi02g4342e5~}42;" [compile-in @@ -190,7 +190,9 @@ const-to-idx-vec #fn("9000r1c0qc1e2|313141;" [#fn("9000r1e0c1qe2~31322|;" [table.foreach #fn("8000r2~}|\\;" []) bcode:ctable]) #fn(vector.alloc) bcode:nconst] const-to-idx-vec) count #fn("7000r2c0q]41;" [#fn("9000r1c0qm02|~\x7f`43;" [#fn(":000r3}\x8550g2;~|}N|}M31690g2aw540g243;" [] count-)])] count) - delete-duplicates #fn("8000r1|?640|;c0|M|N42;" [#fn("8000r2e0|}32680e1}41;|e1}31K;" [member + delete-duplicates #fn("8000r1e0|bD326<0c1qc23041;|?640|;c3|M|N42;" [length> + #fn("8000r1c0q]31~_42;" [#fn("6000r1c0qm02|;" [#fn("9000r2|?680e0}41;c1i10|M32690~|N}42;c2i10|M]332~|N|M}K42;" [reverse! + #fn(has?) #fn(put!)])])]) #fn(table) #fn("8000r2e0|}32680e1}41;|e1}31K;" [member delete-duplicates])] delete-duplicates) div #fn("8000r2|}V|`X16C02}`X16402a17502b/17402`w;" [] div) emit #fn("G000s2g2\x85b0}c0<16C02|`[F16:02|`[Mc1<6;0|`[c2O5:0|`}|`[K\\5\xe20c3}c4326A0e5|g2M32L1m2530]2c6qc7}c832312c9qc7}c:32312}c;\x82\\0g2c<>6=0c=m12_m25F0g2c>>6=0c?m12_m2530^530]2}c@\x82\\0g2cA>6=0cBm12_m25F0g2cC>6=0cDm12_m2530^530]2cEq|`[F690|`[M530_|`[322|;" [car diff --git a/src/flisp/flisp.c b/src/flisp/flisp.c index 843ded75bae64..4cb53756483d9 100644 --- a/src/flisp/flisp.c +++ b/src/flisp/flisp.c @@ -1370,7 +1370,7 @@ static value_t apply_cl(uint32_t nargs) if (fits_fixnum(s)) v = fixnum(s); else - v = mk_long(s); + v = mk_ptrdiff(s); } else { v = fl_add_any(&Stack[SP-2], 2, 0); @@ -1408,7 +1408,7 @@ static value_t apply_cl(uint32_t nargs) if (fits_fixnum(s)) v = fixnum(s); else - v = mk_long(s); + v = mk_ptrdiff(s); } else { Stack[SP-1] = fl_neg(Stack[SP-1]); @@ -1513,7 +1513,7 @@ static value_t apply_cl(uint32_t nargs) if (isfixnum(e)) i = numval(e); else - i = (uint32_t)toulong(e, "aref"); + i = (uint32_t)tosize(e, "aref"); if ((unsigned)i >= vector_size(v)) bounds_error("aref", v, e); v = vector_elt(v, i); @@ -2148,28 +2148,30 @@ value_t fl_map1(value_t *args, u_int32_t nargs) lerror(ArgError, "map: too few arguments"); if (!iscons(args[1])) return NIL; value_t first, last, v; + int64_t argSP = args-Stack; + assert(argSP >= 0 && argSP < N_STACK); if (nargs == 2) { if (SP+3 > N_STACK) grow_stack(); - PUSH(args[0]); - PUSH(car_(args[1])); + PUSH(Stack[argSP]); + PUSH(car_(Stack[argSP+1])); v = _applyn(1); PUSH(v); v = mk_cons(); car_(v) = POP(); cdr_(v) = NIL; last = first = v; - args[1] = cdr_(args[1]); + Stack[argSP+1] = cdr_(Stack[argSP+1]); fl_gc_handle(&first); fl_gc_handle(&last); - while (iscons(args[1])) { - Stack[SP-2] = args[0]; - Stack[SP-1] = car_(args[1]); + while (iscons(Stack[argSP+1])) { + Stack[SP-2] = Stack[argSP]; + Stack[SP-1] = car_(Stack[argSP+1]); v = _applyn(1); PUSH(v); v = mk_cons(); car_(v) = POP(); cdr_(v) = NIL; cdr_(last) = v; last = v; - args[1] = cdr_(args[1]); + Stack[argSP+1] = cdr_(Stack[argSP+1]); } POPN(2); fl_free_gc_handles(2); @@ -2177,10 +2179,10 @@ value_t fl_map1(value_t *args, u_int32_t nargs) else { size_t i; while (SP+nargs+1 > N_STACK) grow_stack(); - PUSH(args[0]); + PUSH(Stack[argSP]); for(i=1; i < nargs; i++) { - PUSH(car(args[i])); - args[i] = cdr_(args[i]); + PUSH(car(Stack[argSP+i])); + Stack[argSP+i] = cdr_(Stack[argSP+i]); } v = _applyn(nargs-1); PUSH(v); @@ -2189,11 +2191,11 @@ value_t fl_map1(value_t *args, u_int32_t nargs) last = first = v; fl_gc_handle(&first); fl_gc_handle(&last); - while (iscons(args[1])) { - Stack[SP-nargs] = args[0]; + while (iscons(Stack[argSP+1])) { + Stack[SP-nargs] = Stack[argSP]; for(i=1; i < nargs; i++) { - Stack[SP-nargs+i] = car(args[i]); - args[i] = cdr_(args[i]); + Stack[SP-nargs+i] = car(Stack[argSP+i]); + Stack[argSP+i] = cdr_(Stack[argSP+i]); } v = _applyn(nargs-1); PUSH(v); @@ -2296,7 +2298,7 @@ static void lisp_init(size_t initial_heapsize) #ifdef __linux__ set(symbol("*os-name*"), symbol("linux")); -#elif defined(WIN32) || defined(WIN64) +#elif defined(_WIN32) || defined(_WIN64) set(symbol("*os-name*"), symbol("win32")); #elif defined(__APPLE__) set(symbol("*os-name*"), symbol("macos")); diff --git a/src/flisp/flisp.h b/src/flisp/flisp.h index 29eae56f4b3e4..7e67c7ed590d0 100644 --- a/src/flisp/flisp.h +++ b/src/flisp/flisp.h @@ -8,8 +8,9 @@ typedef uptrint_t value_t; typedef int_t fixnum_t; -#ifdef __LP64__ +#if NBITS==64 #define T_FIXNUM T_INT64 +#define labs llabs #else #define T_FIXNUM T_INT32 #endif @@ -57,7 +58,7 @@ typedef struct { #define tagptr(p,t) (((value_t)(p)) | (t)) #define fixnum(x) ((value_t)(((fixnum_t)(x))<<2)) #define numval(x) (((fixnum_t)(x))>>2) -#ifdef __LP64__ +#if NBITS==64 #define fits_fixnum(x) (((x)>>61) == 0 || (~((x)>>61)) == 0) #else #define fits_fixnum(x) (((x)>>29) == 0 || (~((x)>>29)) == 0) @@ -291,10 +292,8 @@ typedef int64_t fl_int64_t; typedef uint64_t fl_uint64_t; typedef char fl_char_t; typedef char char_t; -typedef long fl_long_t; -typedef long long_t; -typedef unsigned long fl_ulong_t; -typedef unsigned long ulong_t; +typedef ptrdiff_t fl_ptrdiff_t; +typedef size_t fl_size_t; typedef double fl_double_t; typedef float fl_float_t; @@ -303,7 +302,7 @@ typedef value_t (*builtin_t)(value_t*, uint32_t); extern value_t QUOTE; extern value_t int8sym, uint8sym, int16sym, uint16sym, int32sym, uint32sym; extern value_t int64sym, uint64sym; -extern value_t longsym, ulongsym, bytesym, wcharsym; +extern value_t ptrdiffsym, sizesym, bytesym, wcharsym; extern value_t arraysym, cfunctionsym, voidsym, pointersym; extern value_t stringtypesym, wcstringtypesym, emptystringsym; extern value_t floatsym, doublesym; @@ -322,7 +321,7 @@ value_t cvalue_from_ref(fltype_t *type, void *ptr, size_t sz, value_t parent); value_t cbuiltin(char *name, builtin_t f); size_t cvalue_arraylen(value_t v); value_t size_wrap(size_t sz); -size_t toulong(value_t n, char *fname); +size_t tosize(value_t n, char *fname); value_t cvalue_string(size_t sz); value_t cvalue_static_cstring(const char *str); value_t string_from_cstr(char *str); diff --git a/src/flisp/iostream.c b/src/flisp/iostream.c index b6d7248f3d2af..175f5e9efb038 100644 --- a/src/flisp/iostream.c +++ b/src/flisp/iostream.c @@ -109,7 +109,7 @@ value_t fl_buffer(value_t *args, u_int32_t nargs) value_t fl_read(value_t *args, u_int32_t nargs) { - value_t arg; + value_t arg = 0; if (nargs > 1) { argcount("read", nargs, 1); } @@ -215,7 +215,7 @@ value_t fl_ioseek(value_t *args, u_int32_t nargs) { argcount("io.seek", nargs, 2); ios_t *s = toiostream(args[0], "io.seek"); - size_t pos = toulong(args[1], "io.seek"); + size_t pos = tosize(args[1], "io.seek"); off_t res = ios_seek(s, (off_t)pos); if (res == -1) return FL_F; @@ -255,7 +255,7 @@ value_t fl_ioread(value_t *args, u_int32_t nargs) if (nargs == 3) { // form (io.read s type count) ft = get_array_type(args[1]); - n = toulong(args[2], "io.read") * ft->elsz; + n = tosize(args[2], "io.read") * ft->elsz; } else { ft = get_type(args[1]); @@ -279,9 +279,9 @@ static void get_start_count_args(value_t *args, uint32_t nargs, size_t sz, size_t *offs, size_t *nb, char *fname) { if (nargs > 1) { - *offs = toulong(args[1], fname); + *offs = tosize(args[1], fname); if (nargs > 2) - *nb = toulong(args[2], fname); + *nb = tosize(args[2], fname); else *nb = sz - *offs; if (*offs >= sz || *offs + *nb > sz) @@ -314,7 +314,7 @@ value_t fl_iowrite(value_t *args, u_int32_t nargs) static char get_delim_arg(value_t arg, char *fname) { - size_t uldelim = toulong(arg, fname); + size_t uldelim = tosize(arg, fname); if (uldelim > 0x7f) { // wchars > 0x7f, or anything else > 0xff, are out of range if ((iscprim(arg) && cp_class((cprim_t*)ptr(arg))==wchartype) || @@ -364,7 +364,7 @@ value_t fl_iocopy(value_t *args, u_int32_t nargs) ios_t *dest = toiostream(args[0], "io.copy"); ios_t *src = toiostream(args[1], "io.copy"); if (nargs == 3) { - size_t n = toulong(args[2], "io.copy"); + size_t n = tosize(args[2], "io.copy"); return size_wrap(ios_copy(dest, src, n)); } return size_wrap(ios_copyall(dest, src)); diff --git a/src/flisp/print.c b/src/flisp/print.c index eeb20030a4856..5bf478539dfb7 100644 --- a/src/flisp/print.c +++ b/src/flisp/print.c @@ -614,8 +614,8 @@ static void cvalue_printdata(ios_t *f, void *data, size_t len, value_t type, } } else if (type == uint64sym -#ifdef __LP64__ - || type == ulongsym +#ifdef _P64 + || type == sizesym #endif ) { uint64_t ui64 = *(uint64_t*)data; @@ -627,18 +627,24 @@ static void cvalue_printdata(ios_t *f, void *data, size_t len, value_t type, else if (issymbol(type)) { // handle other integer prims. we know it's smaller than uint64 // at this point, so int64 is big enough to capture everything. - int64_t i64 = conv_to_int64(data, sym_to_numtype(type)); - if (weak || print_princ) - HPOS += ios_printf(f, "%lld", i64); - else - HPOS += ios_printf(f, "#%s(%lld)", symbol_name(type), i64); + numerictype_t nt = sym_to_numtype(type); + if (nt == N_NUMTYPES) { + HPOS += ios_printf(f, "#<%s>", symbol_name(type)); + } + else { + int64_t i64 = conv_to_int64(data, nt); + if (weak || print_princ) + HPOS += ios_printf(f, "%lld", i64); + else + HPOS += ios_printf(f, "#%s(%lld)", symbol_name(type), i64); + } } else if (iscons(type)) { if (car_(type) == arraysym) { value_t eltype = car(cdr_(type)); size_t cnt, elsize; if (iscons(cdr_(cdr_(type)))) { - cnt = toulong(car_(cdr_(cdr_(type))), "length"); + cnt = tosize(car_(cdr_(cdr_(type))), "length"); elsize = cnt ? len/cnt : 0; } else { @@ -707,8 +713,8 @@ static void cvalue_print(ios_t *f, value_t v) void *fptr = *(void**)data; label = (value_t)ptrhash_get(&reverse_dlsym_lookup_table, cv); if (label == (value_t)HT_NOTFOUND) { - HPOS += ios_printf(f, "#", - (unsigned long)(builtin_t)fptr); + HPOS += ios_printf(f, "#", + (size_t)(builtin_t)fptr); } else { if (print_princ) { diff --git a/src/flisp/string.c b/src/flisp/string.c index 6c316bcb2b370..653a35f6f5446 100644 --- a/src/flisp/string.c +++ b/src/flisp/string.c @@ -31,11 +31,11 @@ value_t fl_string_count(value_t *args, u_int32_t nargs) size_t len = cv_len((cvalue_t*)ptr(args[0])); size_t stop = len; if (nargs > 1) { - start = toulong(args[1], "string.count"); + start = tosize(args[1], "string.count"); if (start > len) bounds_error("string.count", args[0], args[1]); if (nargs > 2) { - stop = toulong(args[2], "string.count"); + stop = tosize(args[2], "string.count"); if (stop > len) bounds_error("string.count", args[0], args[2]); if (stop <= start) @@ -46,7 +46,10 @@ value_t fl_string_count(value_t *args, u_int32_t nargs) return size_wrap(u8_charnum(str+start, stop-start)); } +#if defined(__WIN32__) || defined(__linux__) extern int wcwidth(wchar_t c); +#endif + value_t fl_string_width(value_t *args, u_int32_t nargs) { @@ -194,11 +197,11 @@ value_t fl_string_sub(value_t *args, u_int32_t nargs) char *s = tostring(args[0], "string.sub"); size_t len = cv_len((cvalue_t*)ptr(args[0])); size_t i1, i2; - i1 = toulong(args[1], "string.sub"); + i1 = tosize(args[1], "string.sub"); if (i1 > len) bounds_error("string.sub", args[0], args[1]); if (nargs == 3) { - i2 = toulong(args[2], "string.sub"); + i2 = tosize(args[2], "string.sub"); if (i2 > len) bounds_error("string.sub", args[0], args[2]); } @@ -217,7 +220,7 @@ value_t fl_string_char(value_t *args, u_int32_t nargs) argcount("string.char", nargs, 2); char *s = tostring(args[0], "string.char"); size_t len = cv_len((cvalue_t*)ptr(args[0])); - size_t i = toulong(args[1], "string.char"); + size_t i = tosize(args[1], "string.char"); if (i >= len) bounds_error("string.char", args[0], args[1]); size_t sl = u8_seqlen(&s[i]); @@ -256,7 +259,7 @@ value_t fl_string_find(value_t *args, u_int32_t nargs) char cbuf[8]; size_t start = 0; if (nargs == 3) - start = toulong(args[2], "string.find"); + start = tosize(args[2], "string.find"); else argcount("string.find", nargs, 2); char *s = tostring(args[0], "string.find"); @@ -307,10 +310,10 @@ value_t fl_string_inc(value_t *args, u_int32_t nargs) argcount("string.inc", nargs, 2); char *s = tostring(args[0], "string.inc"); size_t len = cv_len((cvalue_t*)ptr(args[0])); - size_t i = toulong(args[1], "string.inc"); + size_t i = tosize(args[1], "string.inc"); size_t cnt = 1; if (nargs == 3) - cnt = toulong(args[2], "string.inc"); + cnt = tosize(args[2], "string.inc"); while (cnt--) { if (i >= len) bounds_error("string.inc", args[0], args[1]); @@ -325,10 +328,10 @@ value_t fl_string_dec(value_t *args, u_int32_t nargs) argcount("string.dec", nargs, 2); char *s = tostring(args[0], "string.dec"); size_t len = cv_len((cvalue_t*)ptr(args[0])); - size_t i = toulong(args[1], "string.dec"); + size_t i = tosize(args[1], "string.dec"); size_t cnt = 1; if (nargs == 3) - cnt = toulong(args[2], "string.dec"); + cnt = tosize(args[2], "string.dec"); // note: i is allowed to start at index len if (i > len) bounds_error("string.dec", args[0], args[1]); @@ -342,7 +345,7 @@ value_t fl_string_dec(value_t *args, u_int32_t nargs) static unsigned long get_radix_arg(value_t arg, char *fname) { - unsigned long radix = toulong(arg, fname); + unsigned long radix = (unsigned long)tosize(arg, fname); if (radix < 2 || radix > 36) lerrorf(ArgError, "%s: invalid radix", fname); return radix; diff --git a/src/flisp/system.lsp b/src/flisp/system.lsp index 25e7ca8b3017e..9c004e9ac606d 100644 --- a/src/flisp/system.lsp +++ b/src/flisp/system.lsp @@ -308,14 +308,24 @@ (define (reverse! l) (reverse!- () l)) (define (delete-duplicates lst) - (if (atom? lst) - lst - (let ((elt (car lst)) - (tail (cdr lst))) - (if (member elt tail) - (delete-duplicates tail) - (cons elt - (delete-duplicates tail)))))) + (if (length> lst 20) + (let ((t (table))) + (let loop ((l lst) (acc '())) + (if (atom? l) + (reverse! acc) + (if (has? t (car l)) + (loop (cdr l) acc) + (begin + (put! t (car l) #t) + (loop (cdr l) (cons (car l) acc))))))) + (if (atom? lst) + lst + (let ((elt (car lst)) + (tail (cdr lst))) + (if (member elt tail) + (delete-duplicates tail) + (cons elt + (delete-duplicates tail))))))) ; backquote ------------------------------------------------------------------- diff --git a/src/gc.c b/src/gc.c index 28a94eb391bee..d9b9025d6b0fb 100644 --- a/src/gc.c +++ b/src/gc.c @@ -24,13 +24,17 @@ // OBJPROFILE counts objects by type //#define OBJPROFILE -#ifdef __LP64__ +#ifdef _P64 # define BVOFFS 2 #else # define BVOFFS 4 #endif +#ifdef _P64 #define GC_PAGE_SZ (1536*sizeof(void*))//bytes +#else +#define GC_PAGE_SZ (2048*sizeof(void*))//bytes +#endif typedef struct _gcpage_t { char data[GC_PAGE_SZ]; @@ -58,7 +62,7 @@ typedef struct _pool_t { typedef struct _bigval_t { struct _bigval_t *next; size_t sz; -#ifndef __LP64__ +#ifndef _P64 uptrint_t _pad0; uptrint_t _pad1; #endif @@ -88,7 +92,7 @@ static size_t allocd_bytes = 0; static size_t freed_bytes = 0; #define default_collect_interval (3200*1024*sizeof(void*)) static size_t collect_interval = default_collect_interval; -#ifdef __LP64__ +#ifdef _P64 # define max_collect_interval 1250000000UL #else # define max_collect_interval 500000000UL @@ -128,7 +132,7 @@ void jl_gc_unpreserve(void) DLLEXPORT jl_weakref_t *jl_gc_new_weakref(jl_value_t *value) { jl_weakref_t *wr = (jl_weakref_t*)alloc_2w(); - wr->type = (jl_type_t*)jl_weakref_type; + wr->type = (jl_value_t*)jl_weakref_type; wr->value = value; arraylist_push(&weak_refs, wr); return wr; @@ -205,7 +209,7 @@ void jl_gc_add_finalizer(jl_value_t *v, jl_function_t *f) static int szclass(size_t sz) { -#ifndef __LP64__ +#ifndef _P64 if (sz <= 8) return 0; #endif if (sz <= 56) return ((sz+3)/4) - 2; @@ -219,17 +223,38 @@ static int szclass(size_t sz) return 41; } +#ifdef __LP64__ +#define malloc_a16(sz) malloc(((sz)+15)&-16) +#else +#if defined(WIN32) +// TODO - use _aligned_malloc, which requires _aligned_free +#define malloc_a16(sz) malloc(((sz)+15)&-16) + +#elif defined(__APPLE__) +#define malloc_a16(sz) malloc(((sz)+15)&-16) + +#else +static inline void *malloc_a16(size_t sz) +{ + void *ptr; + if (posix_memalign(&ptr, 16, (sz+15)&-16)) + return NULL; + return ptr; +} +#endif +#endif + static void *alloc_big(size_t sz) { if (allocd_bytes > collect_interval) { jl_gc_collect(); } - sz = (sz+3) & -4; size_t offs = BVOFFS*sizeof(void*); - if (sz + offs < offs) // overflow in adding offs, size was "negative" + if (sz+offs+15 < offs+15) // overflow in adding offs, size was "negative" jl_throw(jl_memory_exception); - bigval_t *v = (bigval_t*)malloc(sz + offs); - allocd_bytes += (sz+offs); + size_t allocsz = (sz+offs+15) & -16; + bigval_t *v = (bigval_t*)malloc_a16(allocsz); + allocd_bytes += allocsz; if (v == NULL) jl_throw(jl_memory_exception); v->sz = sz; @@ -283,8 +308,8 @@ jl_mallocptr_t *jl_gc_managed_malloc(size_t sz) if (allocd_bytes > collect_interval) { jl_gc_collect(); } - sz = (sz+3) & -4; - void *b = malloc(sz); + sz = (sz+15) & -16; + void *b = malloc_a16(sz); if (b == NULL) jl_throw(jl_memory_exception); allocd_bytes += sz; @@ -316,7 +341,7 @@ static void sweep_malloc_ptrs(void) static void add_page(pool_t *p) { - gcpage_t *pg = malloc(sizeof(gcpage_t)); + gcpage_t *pg = malloc_a16(sizeof(gcpage_t)); if (pg == NULL) jl_throw(jl_memory_exception); gcval_t *v = (gcval_t*)&pg->data[0]; @@ -445,8 +470,8 @@ static void push_root(jl_value_t *v) (*((ptrint_t*)bp))++; #endif gc_setmark(v); - if (gc_typeof(vt) == (jl_value_t*)jl_bits_kind || - vt == (jl_value_t*)jl_weakref_type) { + if (vt == (jl_value_t*)jl_weakref_type || + (jl_is_datatype(vt) && ((jl_datatype_t*)vt)->pointerfree)) { return; } if (mark_sp >= mark_stack_size) { @@ -469,19 +494,17 @@ static void gc_mark_stack(jl_gcframe_t *s, ptrint_t offset) { while (s != NULL) { s = (jl_gcframe_t*)((char*)s + offset); - size_t i; - jl_value_t ***rts = (jl_value_t***)((char*)s->roots + offset); - if (s->indirect) { - size_t nr = s->nroots; - for(i=0; i < nr; i++) { + jl_value_t ***rts = (jl_value_t***)(((void**)s)+2); + size_t nr = s->nroots>>1; + if (s->nroots & 1) { + for(size_t i=0; i < nr; i++) { jl_value_t **ptr = (jl_value_t**)((char*)rts[i] + offset); if (*ptr != NULL) gc_push_root(*ptr); } } else { - size_t nr = s->nroots; - for(i=0; i < nr; i++) { + for(size_t i=0; i < nr; i++) { if (rts[i] != NULL) gc_push_root(rts[i]); } @@ -500,7 +523,8 @@ static void gc_mark_module(jl_module_t *m) gc_setmark_buf(b); if (b->value != NULL) gc_push_root(b->value); - gc_push_root(b->type); + if (b->type != (jl_value_t*)jl_any_type) + gc_push_root(b->type); } } } @@ -527,16 +551,15 @@ static void gc_mark_all() gc_push_root(elt); } } - else if (((jl_struct_type_t*)(vt))->name == jl_array_typename) { + else if (((jl_datatype_t*)(vt))->name == jl_array_typename) { jl_array_t *a = (jl_array_t*)v; char *data = a->data; if (data == NULL) continue; int ndims = jl_array_ndims(a); - void *data_area = jl_array_inline_data_area(a); char *data0 = data; if (ndims == 1) data0 -= a->offset*a->elsize; - if (data0 != data_area) { - jl_value_t *owner = *(jl_value_t**)data_area; + if (!a->isinline) { + jl_value_t *owner = jl_array_data_owner(a); if (a->ismalloc) { // jl_mallocptr_t if (gc_marked(owner)) @@ -553,7 +576,7 @@ static void gc_mark_all() } } if (a->ptrarray) { - size_t l = a->length; + size_t l = jl_array_len(a); for(size_t i=0; i < l; i++) { jl_value_t *elt = ((jl_value_t**)data)[i]; if (elt != NULL) gc_push_root(elt); @@ -590,11 +613,11 @@ static void gc_mark_all() } } else { - jl_struct_type_t *st = (jl_struct_type_t*)vt; - int nf = (int)jl_tuple_len(st->names); + jl_datatype_t *dt = (jl_datatype_t*)vt; + int nf = (int)jl_tuple_len(dt->names); for(int i=0; i < nf; i++) { - if (st->fields[i].isptr) { - jl_value_t *fld = *(jl_value_t**)((char*)v + st->fields[i].offset + sizeof(void*)); + if (dt->fields[i].isptr) { + jl_value_t *fld = *(jl_value_t**)((char*)v + dt->fields[i].offset + sizeof(void*)); if (fld) gc_push_root(fld); } @@ -610,6 +633,18 @@ extern jl_value_t * volatile jl_task_arg_in_transit; double clock_now(void); #endif +static void gc_mark_uv_handle(uv_handle_t *handle, void *arg) +{ + if(handle->data) { + gc_push_root((jl_value_t*)(handle->data)); + } +} + +static void gc_mark_uv_state(uv_loop_t *loop) +{ + uv_walk(loop,gc_mark_uv_handle,0); +} + static void gc_mark(void) { // mark all roots @@ -629,12 +664,16 @@ static void gc_mark(void) gc_push_root(jl_unprotect_stack_func); gc_push_root(jl_bottom_func); gc_push_root(jl_typetype_type); + gc_push_root(jl_tupletype_type); // constants gc_push_root(jl_null); gc_push_root(jl_true); gc_push_root(jl_false); + // libuv loops + gc_mark_uv_state(jl_global_event_loop()); + jl_mark_box_caches(); size_t i; @@ -650,7 +689,7 @@ static void gc_mark(void) } gc_mark_all(); - + // find unmarked objects that need to be finalized. // this must happen last. for(i=0; i < finalizer_table.size; i+=2) { @@ -667,7 +706,7 @@ static void gc_mark(void) gc_mark_all(); } -static int is_gc_enabled = 0; +static int is_gc_enabled = 1; DLLEXPORT void jl_gc_enable(void) { is_gc_enabled = 1; } DLLEXPORT void jl_gc_disable(void) { is_gc_enabled = 0; } DLLEXPORT int jl_gc_is_enabled(void) { return is_gc_enabled; } @@ -683,12 +722,11 @@ static void big_obj_stats(void); #ifdef OBJPROFILE static void print_obj_profile(void) { - jl_value_t *errstream = jl_stderr_obj(); for(int i=0; i < obj_counts.size; i+=2) { if (obj_counts.table[i+1] != HT_NOTFOUND) { - ios_printf(ios_stderr, "%d ", obj_counts.table[i+1]-1); - jl_show(errstream, obj_counts.table[i]); - ios_printf(ios_stderr, "\n"); + jl_printf(JL_STDERR, "%d ", obj_counts.table[i+1]-1); + jl_debug_print_type(JL_STDERR, (jl_value_t*)obj_counts.table[i]); + jl_printf(JL_STDERR, "\n"); } } } @@ -773,7 +811,7 @@ void *alloc_2w(void) #ifdef MEMDEBUG return alloc_big(2*sizeof(void*)); #endif -#ifdef __LP64__ +#ifdef _P64 return pool_alloc(&pools[2]); #else return pool_alloc(&pools[0]); @@ -785,7 +823,7 @@ void *alloc_3w(void) #ifdef MEMDEBUG return alloc_big(3*sizeof(void*)); #endif -#ifdef __LP64__ +#ifdef _P64 return pool_alloc(&pools[4]); #else return pool_alloc(&pools[1]); @@ -797,7 +835,7 @@ void *alloc_4w(void) #ifdef MEMDEBUG return alloc_big(4*sizeof(void*)); #endif -#ifdef __LP64__ +#ifdef _P64 return pool_alloc(&pools[6]); #else return pool_alloc(&pools[2]); @@ -807,17 +845,17 @@ void *alloc_4w(void) #ifdef GC_FINAL_STATS static double process_t0; #include -void print_gc_stats(void) +void jl_print_gc_stats(JL_STREAM *s) { malloc_stats(); double ptime = clock_now()-process_t0; - ios_printf(ios_stderr, "exec time\t%.5f sec\n", ptime); - ios_printf(ios_stdout, "gc time \t%.5f sec (%2.1f%%)\n", total_gc_time, + jl_printf(s, "exec time\t%.5f sec\n", ptime); + jl_printf(s, "gc time \t%.5f sec (%2.1f%%)\n", total_gc_time, (total_gc_time/ptime)*100); struct mallinfo mi = mallinfo(); - ios_printf(ios_stdout, "malloc size\t%d MB\n", mi.uordblks/1024/1024); - ios_printf(ios_stdout, "total freed\t%llu b\n", total_freed_bytes); - ios_printf(ios_stdout, "free rate\t%.1f MB/sec\n", + jl_printf(s, "malloc size\t%d MB\n", mi.uordblks/1024/1024); + jl_printf(s, "total freed\t%llu b\n", total_freed_bytes); + jl_printf(s, "free rate\t%.1f MB/sec\n", (total_freed_bytes/total_gc_time)/1024/1024); } #endif @@ -831,7 +869,7 @@ void jl_gc_init(void) 288, 320, 352, 384, 416, 448, 480, 512, - 640, 768, 896, 1024, + 640, 768, 896, 1024, 1536, 2048 }; int i; @@ -855,7 +893,6 @@ void jl_gc_init(void) #endif #ifdef GC_FINAL_STATS process_t0 = clock_now(); - atexit(print_gc_stats); #endif } diff --git a/src/gf.c b/src/gf.c index 48898a36e8b82..2131f5c163a0c 100644 --- a/src/gf.c +++ b/src/gf.c @@ -25,13 +25,14 @@ static jl_methtable_t *new_method_table(jl_sym_t *name) { jl_methtable_t *mt = (jl_methtable_t*)allocobj(sizeof(jl_methtable_t)); - mt->type = (jl_type_t*)jl_methtable_type; + mt->type = (jl_value_t*)jl_methtable_type; mt->name = name; mt->defs = JL_NULL; mt->cache = JL_NULL; mt->cache_arg1 = JL_NULL; mt->cache_targ = JL_NULL; mt->max_args = 0; + mt->kwsorter = NULL; #ifdef JL_GF_PROFILE mt->ncalls = 0; #endif @@ -67,9 +68,9 @@ static int cache_match_by_type(jl_value_t **types, size_t n, jl_tuple_t *sig, if (!jl_subtype(a, decl, 0)) return 0; } - else if (jl_is_tag_type(a) && jl_is_tag_type(decl) && - ((jl_tag_type_t*)decl)->name == jl_type_type->name && - ((jl_tag_type_t*)a )->name == jl_type_type->name) { + else if (jl_is_datatype(a) && jl_is_datatype(decl) && + ((jl_datatype_t*)decl)->name == jl_type_type->name && + ((jl_datatype_t*)a )->name == jl_type_type->name) { jl_value_t *tp0 = jl_tparam0(decl); if (tp0 == (jl_value_t*)jl_typetype_tvar) { // in the case of Type{T}, the types don't have @@ -92,17 +93,12 @@ static int cache_match_by_type(jl_value_t **types, size_t n, jl_tuple_t *sig, } static inline int cache_match(jl_value_t **args, size_t n, jl_tuple_t *sig, - int va) + int va, size_t lensig) { // NOTE: This function is a huge performance hot spot!! - if (jl_tuple_len(sig) > n) { - if (n != jl_tuple_len(sig)-1) - return 0; - } - size_t i; - for(i=0; i < n; i++) { + for(size_t i=0; i < n; i++) { jl_value_t *decl = jl_tupleref(sig, i); - if (i == jl_tuple_len(sig)-1) { + if (i == lensig-1) { if (va) { jl_value_t *t = jl_tparam0(decl); for(; i < n; i++) { @@ -113,14 +109,26 @@ static inline int cache_match(jl_value_t **args, size_t n, jl_tuple_t *sig, } } jl_value_t *a = args[i]; - if (jl_is_tuple(decl)) { + if (decl == (jl_value_t*)jl_any_type) { + } + else if ((jl_value_t*)jl_typeof(a) == decl) { + /* + we know there are only concrete types here, and types are + hash-consed, so pointer comparison should work. + */ + } + else if (jl_is_tuple(decl)) { // tuples don't have to match exactly, to avoid caching // signatures for tuples of every length - if (!jl_is_tuple(a) || !jl_subtype(a, decl, 1)) + if (!jl_is_tuple(a) || //!jl_subtype(a, decl, 1)) + !jl_tuple_subtype(((jl_tuple_t*)a)->data, jl_tuple_len(a), + ((jl_tuple_t*)decl)->data, jl_tuple_len(decl), + 1, 0)) return 0; } else if (jl_is_type_type(decl) && - jl_is_nontuple_type(a)) { //*** + (jl_is_nontuple_type(a) || + (jl_is_tuple(a)&&jl_is_type(a)))) { jl_value_t *tp0 = jl_tparam0(decl); if (tp0 == (jl_value_t*)jl_typetype_tvar) { // in the case of Type{T}, the types don't have @@ -132,15 +140,8 @@ static inline int cache_match(jl_value_t **args, size_t n, jl_tuple_t *sig, return 0; } } - else if (decl == (jl_value_t*)jl_any_type) { - } else { - /* - we know there are only concrete types here, and types are - hash-consed, so pointer comparison should work. - */ - if ((jl_value_t*)jl_typeof(a) != decl) - return 0; + return 0; } } return 1; @@ -149,23 +150,20 @@ static inline int cache_match(jl_value_t **args, size_t n, jl_tuple_t *sig, static inline jl_methlist_t *mtcache_hash_lookup(jl_array_t *a, jl_value_t *ty, int tparam) { - uptrint_t uid; - if ((jl_is_struct_type(ty) && (uid = ((jl_struct_type_t*)ty)->uid)) || - (jl_is_bits_type(ty) && (uid = ((jl_bits_type_t*)ty)->uid))) { - jl_methlist_t *ml = (jl_methlist_t*)jl_cellref(a, uid & (a->length-1)); - if (ml && ml!=JL_NULL) { - jl_value_t *t = jl_tupleref(ml->sig, 0); - if (tparam) t = jl_tparam0(t); - if (t == ty) - return ml; - } + uptrint_t uid = ((jl_datatype_t*)ty)->uid; + jl_methlist_t *ml = (jl_methlist_t*)jl_cellref(a, uid & (a->nrows-1)); + if (ml && ml!=JL_NULL) { + jl_value_t *t = jl_tupleref(ml->sig, 0); + if (tparam) t = jl_tparam0(t); + if (t == ty) + return ml; } return JL_NULL; } static void mtcache_rehash(jl_array_t **pa) { - size_t len = (*pa)->length; + size_t len = (*pa)->nrows; jl_value_t **d = (jl_value_t**)(*pa)->data; jl_array_t *n = jl_alloc_cell_1d(len*2); jl_value_t **nd = (jl_value_t**)n->data; @@ -176,11 +174,7 @@ static void mtcache_rehash(jl_array_t **pa) jl_value_t *t = jl_tupleref(ml->sig,0); if (jl_is_type_type(t)) t = jl_tparam0(t); - uptrint_t uid; - if (jl_is_struct_type(t)) - uid = ((jl_struct_type_t*)t)->uid; - else - uid = ((jl_bits_type_t*)t)->uid; + uptrint_t uid = ((jl_datatype_t*)t)->uid; nd[uid & (len*2-1)] = (jl_value_t*)ml; } } @@ -191,10 +185,9 @@ static jl_methlist_t **mtcache_hash_bp(jl_array_t **pa, jl_value_t *ty, int tparam) { uptrint_t uid; - if ((jl_is_struct_type(ty) && (uid = ((jl_struct_type_t*)ty)->uid)) || - (jl_is_bits_type(ty) && (uid = ((jl_bits_type_t*)ty)->uid))) { + if (jl_is_datatype(ty) && (uid = ((jl_datatype_t*)ty)->uid)) { while (1) { - jl_methlist_t **pml = (jl_methlist_t**)&jl_cellref(*pa, uid & ((*pa)->length-1)); + jl_methlist_t **pml = (jl_methlist_t**)&jl_cellref(*pa, uid & ((*pa)->nrows-1)); if (*pml == NULL || *pml == JL_NULL) { *pml = JL_NULL; return pml; @@ -223,13 +216,13 @@ static jl_function_t *jl_method_table_assoc_exact_by_type(jl_methtable_t *mt, jl_value_t *ty = jl_t0(types); if (jl_is_type_type(ty)) { jl_value_t *a0 = jl_tparam0(ty); - if (mt->cache_targ != JL_NULL) { + if (mt->cache_targ != JL_NULL && jl_is_datatype(a0)) { ml = mtcache_hash_lookup(mt->cache_targ, a0, 1); if (ml!=JL_NULL) goto mt_assoc_bt_lkup; } } - if (mt->cache_arg1 != JL_NULL) { + if (mt->cache_arg1 != JL_NULL && jl_is_datatype(ty)) { ml = mtcache_hash_lookup(mt->cache_arg1, ty, 0); } } @@ -254,15 +247,12 @@ static jl_function_t *jl_method_table_assoc_exact(jl_methtable_t *mt, if (n > 0) { jl_value_t *a0 = args[0]; jl_value_t *ty = (jl_value_t*)jl_typeof(a0); - if (ty == (jl_value_t*)jl_struct_kind || - ty == (jl_value_t*)jl_bits_kind) { - if (mt->cache_targ != JL_NULL) { - ml = mtcache_hash_lookup(mt->cache_targ, a0, 1); - if (ml != JL_NULL) - goto mt_assoc_lkup; - } + if (mt->cache_targ != JL_NULL && ty == (jl_value_t*)jl_datatype_type) { + ml = mtcache_hash_lookup(mt->cache_targ, a0, 1); + if (ml != JL_NULL) + goto mt_assoc_lkup; } - if (mt->cache_arg1 != JL_NULL) { + if (mt->cache_arg1 != JL_NULL && jl_is_datatype(ty)) { ml = mtcache_hash_lookup(mt->cache_arg1, ty, 0); if (ml != JL_NULL) { if (ml->next==JL_NULL && n==1 && jl_tuple_len(ml->sig)==1) @@ -286,8 +276,10 @@ static jl_function_t *jl_method_table_assoc_exact(jl_methtable_t *mt, ml = mt->cache; mt_assoc_lkup: while (ml != JL_NULL) { - if (jl_tuple_len(ml->sig) == n || ml->va) { - if (cache_match(args, n, (jl_tuple_t*)ml->sig, ml->va)) { + size_t lensig = jl_tuple_len(ml->sig); + if ((lensig == n || ml->va) && + !(lensig > n && n != lensig-1)) { + if (cache_match(args, n, (jl_tuple_t*)ml->sig, ml->va, lensig)) { return ml->func; } } @@ -309,6 +301,7 @@ jl_lambda_info_t *jl_add_static_parameters(jl_lambda_info_t *l, jl_tuple_t *sp) nli->module = l->module; nli->file = l->file; nli->line = l->line; + nli->def = l->def; JL_GC_POP(); return nli; } @@ -350,10 +343,8 @@ jl_function_t *jl_method_cache_insert(jl_methtable_t *mt, jl_tuple_t *type, // the table indexed for that purpose. if (t0 != (jl_value_t*)jl_typetype_type && jl_is_type_type(t0)) { jl_value_t *a0 = jl_tparam0(t0); - if (jl_is_struct_type(a0)) - uid = ((jl_struct_type_t*)a0)->uid; - else if (jl_is_bits_type(a0)) - uid = ((jl_bits_type_t*)a0)->uid; + if (jl_is_datatype(a0)) + uid = ((jl_datatype_t*)a0)->uid; if (uid > 0) { if (mt->cache_targ == JL_NULL) mt->cache_targ = jl_alloc_cell_1d(16); @@ -361,10 +352,8 @@ jl_function_t *jl_method_cache_insert(jl_methtable_t *mt, jl_tuple_t *type, goto ml_do_insert; } } - if (jl_is_struct_type(t0)) - uid = ((jl_struct_type_t*)t0)->uid; - else if (jl_is_bits_type(t0)) - uid = ((jl_bits_type_t*)t0)->uid; + if (jl_is_datatype(t0)) + uid = ((jl_datatype_t*)t0)->uid; if (uid > 0) { if (mt->cache_arg1 == JL_NULL) mt->cache_arg1 = jl_alloc_cell_1d(16); @@ -375,38 +364,50 @@ jl_function_t *jl_method_cache_insert(jl_methtable_t *mt, jl_tuple_t *type, return jl_method_list_insert(pml, type, method, jl_null, 0)->func; } -#if defined(JL_TRACE) || defined(TRACE_INFERENCE) -static char *type_summary(jl_value_t *t) +static void print_tuple_elts(JL_STREAM *s, jl_tuple_t *v) { - if (jl_is_tuple(t)) return "Tuple"; - if (jl_is_some_tag_type(t)) - return ((jl_tag_type_t*)t)->name->name->name; - JL_PRINTF(JL_STDERR, "unexpected argument type: "); - jl_show(jl_stderr_obj(), t); - JL_PRINTF(JL_STDERR, "\n"); - assert(0); - return NULL; + for(size_t i=0; i < jl_tuple_len(v); i++) { + if (i > 0) JL_PRINTF(s, ", "); + jl_debug_print_type(s, jl_tupleref(v,i)); + } } -#endif -#ifdef TRACE_INFERENCE -static void print_sig(jl_tuple_t *type) +void jl_debug_print_type(JL_STREAM *s, jl_value_t *v) { - size_t i; - for(i=0; i < jl_tuple_len(type); i++) { - if (i > 0) JL_PRINTF(JL_STDERR, ", "); - jl_value_t *v = jl_tupleref(type,i); - if (jl_is_tuple(v)) { - JL_PUTC('(', JL_STDERR); - print_sig((jl_tuple_t*)v); - JL_PUTC(')', JL_STDERR); - } - else { - JL_PRINTF(JL_STDERR, "%s", type_summary(v)); + if (jl_is_tuple(v)) { + JL_PUTC('(', s); + print_tuple_elts(s, (jl_tuple_t*)v); + JL_PUTC(')', s); + } + else if (jl_is_symbol(v)) { + JL_PRINTF(s, "%s", ((jl_sym_t*)v)->name); + } + else if (jl_is_long(v)) { + JL_PRINTF(s, "%lld", jl_unbox_long(v)); + } + else if (jl_is_datatype(v)) { + jl_datatype_t *dt = (jl_datatype_t*)v; + JL_PRINTF(s, "%s", dt->name->name->name); + if (jl_tuple_len(dt->parameters) > 0) { + JL_PUTC('{', s); + print_tuple_elts(s, dt->parameters); + JL_PUTC('}', s); } } + else if (jl_is_typector(v)) { + jl_debug_print_type(s, ((jl_typector_t*)v)->body); + } + else if (jl_is_uniontype(v)) { + JL_PRINTF(s, "Union"); + jl_debug_print_type(s, (jl_value_t*)((jl_uniontype_t*)v)->types); + } + else if (jl_is_typevar(v)) { + JL_PRINTF(s, ((jl_tvar_t*)v)->name->name); + } + else { + JL_PRINTF(s, ""); + } } -#endif extern jl_function_t *jl_typeinf_func; @@ -433,9 +434,9 @@ void jl_type_infer(jl_lambda_info_t *li, jl_tuple_t *argtypes, fargs[2] = (jl_value_t*)jl_null; fargs[3] = (jl_value_t*)def; #ifdef TRACE_INFERENCE - JL_PRINTF(JL_STDERR,"inference on %s(", li->name->name); - print_sig(argtypes); - JL_PRINTF(JL_STDERR, ")\n"); + JL_PRINTF(JL_STDERR,"inference on %s", li->name->name); + jl_debug_print_type(JL_STDERR, (jl_value_t*)argtypes); + JL_PRINTF(JL_STDERR, "\n"); #endif #ifdef ENABLE_INFERENCE jl_value_t *newast = jl_apply(jl_typeinf_func, fargs, 4); @@ -454,7 +455,7 @@ static jl_value_t *nth_slot_type(jl_tuple_t *sig, size_t i) return NULL; if (i < len-1) return jl_tupleref(sig, i); - if (jl_is_seq_type(jl_tupleref(sig,len-1))) { + if (jl_is_vararg_type(jl_tupleref(sig,len-1))) { return jl_tparam0(jl_tupleref(sig,len-1)); } if (i == len-1) @@ -480,9 +481,9 @@ static int tuple_all_Any(jl_tuple_t *t) static int is_kind(jl_value_t *v) { - return (v==(jl_value_t*)jl_union_kind || v==(jl_value_t*)jl_struct_kind || - v==(jl_value_t*)jl_bits_kind || v==(jl_value_t*)jl_typector_type || - v==(jl_value_t*)jl_tag_kind); + return (v==(jl_value_t*)jl_uniontype_type || + v==(jl_value_t*)jl_datatype_type || + v==(jl_value_t*)jl_typector_type); } static jl_value_t *ml_matches(jl_methlist_t *ml, jl_value_t *type, @@ -501,6 +502,27 @@ static jl_function_t *cache_method(jl_methtable_t *mt, jl_tuple_t *type, for (i=0; i < jl_tuple_len(type); i++) { jl_value_t *elt = jl_tupleref(type,i); jl_value_t *decl_i = nth_slot_type(decl,i); + if (jl_is_type_type(elt) && jl_is_tuple(jl_tparam0(elt)) && + !jl_is_type_type(decl_i)) { + jl_methlist_t *curr = mt->defs; + int ok=1; + while (curr != JL_NULL) { + jl_value_t *slottype = nth_slot_type(curr->sig, i); + if (slottype && curr->func!=method) { + if (jl_is_type_type(slottype) && + jl_type_intersection(slottype, decl_i) != jl_bottom_type) { + ok=0; + break; + } + } + curr = curr->next; + } + if (ok) { + elt = jl_full_type(jl_tparam0(elt)); + jl_tupleset(type, i, elt); + } + } + int set_to_any = 0; if (decl_i == jl_ANY_flag) { // don't specialize on slots marked ANY @@ -541,7 +563,7 @@ static jl_function_t *cache_method(jl_methtable_t *mt, jl_tuple_t *type, if (i < jl_tuple_len(decl)) { jl_value_t *declt = jl_tupleref(decl,i); // for T..., intersect with T - if (jl_is_seq_type(declt)) + if (jl_is_vararg_type(declt)) declt = jl_tparam0(declt); if (declt == (jl_value_t*)jl_tuple_type || jl_subtype((jl_value_t*)jl_tuple_type, declt, 0)) { @@ -596,7 +618,8 @@ static jl_function_t *cache_method(jl_methtable_t *mt, jl_tuple_t *type, } } } - else if (jl_is_type_type(elt) && jl_is_type_type(jl_tparam0(elt))) { + else if (jl_is_type_type(elt) && jl_is_type_type(jl_tparam0(elt)) && + (decl_i==NULL || !jl_has_typevars(decl_i))) { /* actual argument was Type{...}, we computed its type as Type{Type{...}}. we must avoid unbounded nesting here, so @@ -607,7 +630,7 @@ static jl_function_t *cache_method(jl_methtable_t *mt, jl_tuple_t *type, if (i < jl_tuple_len(decl)) { jl_value_t *declt = jl_tupleref(decl,i); // for T..., intersect with T - if (jl_is_seq_type(declt)) + if (jl_is_vararg_type(declt)) declt = jl_tparam0(declt); jl_tupleset(type, i, jl_type_intersection(declt, (jl_value_t*)jl_typetype_type)); @@ -617,7 +640,8 @@ static jl_function_t *cache_method(jl_methtable_t *mt, jl_tuple_t *type, } assert(jl_tupleref(type,i) != (jl_value_t*)jl_bottom_type); } - else if (jl_is_type_type(elt) && very_general_type(decl_i)) { + else if (jl_is_type_type(elt) && very_general_type(decl_i) && + !jl_has_typevars(decl_i)) { /* here's a fairly complex heuristic: if this argument slot's declared type is Any, and no definition overlaps with Type @@ -635,7 +659,7 @@ static jl_function_t *cache_method(jl_methtable_t *mt, jl_tuple_t *type, Type{TC} nor TypeConstructor is more specific. To solve this, we identify "kind slots", which are slots - for which some definition specifies a kind (e.g. AbstractKind). + for which some definition specifies a kind (e.g. DataType). Those tend to be in reflective functions that look at types themselves. For these slots we specialize on jl_typeof(T) instead of Type{T}, i.e. the kind of the type rather than the specific @@ -643,7 +667,7 @@ static jl_function_t *cache_method(jl_methtable_t *mt, jl_tuple_t *type, */ int ok=1, kindslot=0; jl_methlist_t *curr = mt->defs; - jl_value_t *kind = (jl_value_t*)jl_typeof(jl_tparam0(elt)); + jl_value_t *kind = (jl_value_t*)jl_full_type(jl_tparam0(elt)); while (curr != JL_NULL) { jl_value_t *slottype = nth_slot_type(curr->sig, i); if (slottype && curr->func!=method) { @@ -689,7 +713,8 @@ static jl_function_t *cache_method(jl_methtable_t *mt, jl_tuple_t *type, while (curr != JL_NULL) { jl_value_t *slottype = nth_slot_type(curr->sig, i); if (slottype && curr->func!=method) { - if (jl_subtype(slottype, decl_i, 0)) { + if (jl_is_type_type(slottype) && + jl_type_intersection(slottype, decl_i) != jl_bottom_type) { ok=0; break; } @@ -706,7 +731,7 @@ static jl_function_t *cache_method(jl_methtable_t *mt, jl_tuple_t *type, // supertype of any other method signatures. so far we are conservative // and the types we find should be bigger. if (jl_tuple_len(type) > mt->max_args && - jl_is_seq_type(jl_tupleref(decl,jl_tuple_len(decl)-1))) { + jl_is_vararg_type(jl_tupleref(decl,jl_tuple_len(decl)-1))) { size_t nspec = mt->max_args + 2; jl_tuple_t *limited = jl_alloc_tuple(nspec); for(i=0; i < nspec-1; i++) { @@ -732,17 +757,17 @@ static jl_function_t *cache_method(jl_methtable_t *mt, jl_tuple_t *type, type = limited; if (all_are_subtypes) { // avoid Type{Type{...}...}... - if (jl_is_type_type(lasttype)) + if (jl_is_type_type(lasttype) && jl_is_type_type(jl_tparam0(lasttype))) lasttype = (jl_value_t*)jl_type_type; temp = (jl_value_t*)jl_tuple1(lasttype); - jl_tupleset(type, i, jl_apply_type((jl_value_t*)jl_seq_type, + jl_tupleset(type, i, jl_apply_type((jl_value_t*)jl_vararg_type, (jl_tuple_t*)temp)); } else { jl_value_t *lastdeclt = jl_tupleref(decl,jl_tuple_len(decl)-1); if (jl_tuple_len(sparams) > 0) { lastdeclt = (jl_value_t*) - jl_instantiate_type_with((jl_type_t*)lastdeclt, + jl_instantiate_type_with((jl_value_t*)lastdeclt, sparams->data, jl_tuple_len(sparams)/2); } @@ -783,12 +808,12 @@ static jl_function_t *cache_method(jl_methtable_t *mt, jl_tuple_t *type, // a new closure is generated on each call to the enclosing function. lilist = method->linfo->specializations; int k; - for(k=0; k < lilist->length; k++) { + for(k=0; k < lilist->nrows; k++) { li = (jl_lambda_info_t*)jl_cellref(lilist, k); if (jl_types_equal((jl_value_t*)li->specTypes, (jl_value_t*)type)) break; } - if (k == lilist->length) lilist=NULL; + if (k == lilist->nrows) lilist=NULL; } if (lilist != NULL && !li->inInference) { assert(li); @@ -850,6 +875,7 @@ static jl_value_t *lookup_match(jl_value_t *a, jl_value_t *b, jl_tuple_t **penv, jl_value_t *ti = jl_type_intersection_matching(a, b, penv, tvars); if (ti == (jl_value_t*)jl_bottom_type) return ti; + assert(jl_is_tuple(*penv)); jl_value_t **ee = alloca(sizeof(void*) * jl_tuple_len(*penv)); int n=0; // only keep vars in tvars list @@ -931,7 +957,7 @@ static jl_function_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_tuple_t *tt, in break; } if (i < jl_tuple_len(tt)) { - newsig = (jl_tuple_t*)jl_instantiate_type_with((jl_type_t*)m->sig, + newsig = (jl_tuple_t*)jl_instantiate_type_with((jl_value_t*)m->sig, &jl_tupleref(env,0), jl_tuple_len(env)/2); } @@ -948,12 +974,12 @@ static jl_function_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_tuple_t *tt, in return nf; } -jl_tag_type_t *jl_wrap_Type(jl_value_t *t); +jl_datatype_t *jl_wrap_Type(jl_value_t *t); -static int sigs_eq(jl_value_t *a, jl_value_t *b) +static int sigs_eq(jl_value_t *a, jl_value_t *b, int useenv) { if (jl_has_typevars(a) || jl_has_typevars(b)) { - return jl_types_equal_generic(a,b); + return jl_types_equal_generic(a,b,useenv); } return jl_subtype(a, b, 0) && jl_subtype(b, a, 0); } @@ -991,10 +1017,10 @@ int jl_args_morespecific(jl_value_t *a, jl_value_t *b) static int is_va_tuple(jl_tuple_t *t) { - return (jl_tuple_len(t)>0 && jl_is_seq_type(jl_tupleref(t,jl_tuple_len(t)-1))); + return (jl_tuple_len(t)>0 && jl_is_vararg_type(jl_tupleref(t,jl_tuple_len(t)-1))); } -static void print_func_loc(ios_t *s, jl_lambda_info_t *li); +static void print_func_loc(JL_STREAM *s, jl_lambda_info_t *li); /* warn about ambiguous method priorities @@ -1015,9 +1041,10 @@ static void print_func_loc(ios_t *s, jl_lambda_info_t *li); so (T,T) is not equivalent to (Any,Any). (TODO) */ static void check_ambiguous(jl_methlist_t *ml, jl_tuple_t *type, - jl_tuple_t *sig, jl_sym_t *fname, + jl_methlist_t *oldmeth, jl_sym_t *fname, jl_lambda_info_t *linfo) { + jl_tuple_t *sig = oldmeth->sig; size_t tl = jl_tuple_len(type); size_t sl = jl_tuple_len(sig); // we know !jl_args_morespecific(type, sig) @@ -1032,22 +1059,22 @@ static void check_ambiguous(jl_methlist_t *ml, jl_tuple_t *type, JL_GC_PUSH(&isect); jl_methlist_t *l = ml; while (l != JL_NULL) { - if (sigs_eq(isect, (jl_value_t*)l->sig)) + if (sigs_eq(isect, (jl_value_t*)l->sig, 0)) goto done_chk_amb; // ok, intersection is covered l = l->next; } char *n = fname->name; jl_value_t *errstream = jl_stderr_obj(); - ios_t *s = JL_STDERR; - ios_printf(s, "Warning: New definition %s", n); + JL_STREAM *s = JL_STDERR; + JL_PRINTF(s, "Warning: New definition \n %s", n); jl_show(errstream, (jl_value_t*)type); print_func_loc(s, linfo); - ios_printf(s, " is ambiguous with %s", n); + JL_PRINTF(s, "\nis ambiguous with \n %s", n); jl_show(errstream, (jl_value_t*)sig); - print_func_loc(s, ml->func->linfo); - ios_printf(s, ".\n Make sure %s", n); + print_func_loc(s, oldmeth->func->linfo); + JL_PRINTF(s, ".\nMake sure \n %s", n); jl_show(errstream, isect); - ios_printf(s, " is defined first.\n"); + JL_PRINTF(s, "\nis defined first.\n"); done_chk_amb: JL_GC_POP(); } @@ -1058,8 +1085,8 @@ static int has_unions(jl_tuple_t *type) int i; for(i=0; i < jl_tuple_len(type); i++) { jl_value_t *t = jl_tupleref(type,i); - if (jl_is_union_type(t) || - (jl_is_seq_type(t) && jl_is_union_type(jl_tparam0(t)))) + if (jl_is_uniontype(t) || + (jl_is_vararg_type(t) && jl_is_uniontype(jl_tparam0(t)))) return 1; } return 0; @@ -1076,13 +1103,29 @@ jl_methlist_t *jl_method_list_insert(jl_methlist_t **pml, jl_tuple_t *type, l = *pml; while (l != JL_NULL) { if (((l->tvars==jl_null) == (tvars==jl_null)) && - sigs_eq((jl_value_t*)type, (jl_value_t*)l->sig)) { + sigs_eq((jl_value_t*)type, (jl_value_t*)l->sig, 1)) { // method overwritten + if (check_amb && l->func->linfo && method->linfo && + (l->func->linfo->module != method->linfo->module) && + // special case: allow adding Array() methods in Base + (pml != &((jl_methtable_t*)jl_array_type->env)->defs || + method->linfo->module != jl_base_module)) { + jl_module_t *newmod = method->linfo->module; + jl_value_t *errstream = jl_stderr_obj(); + JL_STREAM *s = JL_STDERR; + JL_PRINTF(s, "Warning: Method definition %s", method->linfo->name->name); + jl_show(errstream, (jl_value_t*)type); + JL_PRINTF(s, " in module %s", l->func->linfo->module->name->name); + print_func_loc(s, l->func->linfo); + JL_PRINTF(s, " overwritten in module %s", newmod->name->name); + print_func_loc(s, method->linfo); + JL_PRINTF(s, ".\n"); + } JL_SIGATOMIC_BEGIN(); l->sig = type; l->tvars = tvars; l->va = (jl_tuple_len(type) > 0 && - jl_is_seq_type(jl_tupleref(type,jl_tuple_len(type)-1))) ? + jl_is_vararg_type(jl_tupleref(type,jl_tuple_len(type)-1))) ? 1 : 0; l->invokes = JL_NULL; l->func = method; @@ -1097,20 +1140,19 @@ jl_methlist_t *jl_method_list_insert(jl_methlist_t **pml, jl_tuple_t *type, if (jl_args_morespecific((jl_value_t*)type, (jl_value_t*)l->sig)) break; if (check_amb) { - check_ambiguous(*pml, (jl_tuple_t*)type, (jl_tuple_t*)l->sig, + check_ambiguous(*pml, (jl_tuple_t*)type, l, method->linfo ? method->linfo->name : - anonymous_sym, - method->linfo); + anonymous_sym, method->linfo); } pl = &l->next; l = l->next; } jl_methlist_t *newrec = (jl_methlist_t*)allocobj(sizeof(jl_methlist_t)); - newrec->type = (jl_type_t*)jl_method_type; + newrec->type = (jl_value_t*)jl_method_type; newrec->sig = type; newrec->tvars = tvars; newrec->va = (jl_tuple_len(type) > 0 && - jl_is_seq_type(jl_tupleref(type,jl_tuple_len(type)-1))) ? + jl_is_vararg_type(jl_tupleref(type,jl_tuple_len(type)-1))) ? 1 : 0; newrec->func = method; newrec->invokes = JL_NULL; @@ -1213,9 +1255,9 @@ static jl_tuple_t *arg_type_tuple(jl_value_t **args, size_t nargs) jl_tuple_t *tt = jl_alloc_tuple(nargs); JL_GC_PUSH(&tt); size_t i; - for(i=0; i < jl_tuple_len(tt); i++) { + for(i=0; i < nargs; i++) { jl_value_t *a; - if (jl_is_nontuple_type(args[i])) { //*** + if (jl_is_type(args[i])) { a = (jl_value_t*)jl_wrap_Type(args[i]); } else { @@ -1286,7 +1328,7 @@ static void show_call(jl_value_t *F, jl_value_t **args, uint32_t nargs) JL_PRINTF(JL_STDOUT, "%s(", jl_gf_name(F)->name); for(size_t i=0; i < nargs; i++) { if (i > 0) JL_PRINTF(JL_STDOUT, ", "); - JL_PRINTF(JL_STDOUT, "%s", type_summary((jl_value_t*)jl_typeof(args[i]))); + jl_debug_print_type(JL_STDOUT, jl_typeof(args[i])); } JL_PRINTF(JL_STDOUT, ")\n"); } @@ -1419,7 +1461,10 @@ jl_value_t *jl_gf_invoke(jl_function_t *gf, jl_tuple_t *types, newsig = (jl_tuple_t*)m->sig; if (env != (jl_value_t*)jl_false) { - tpenv = (jl_tuple_t*)env; + jl_value_t *ti = + lookup_match((jl_value_t*)tt, (jl_value_t*)m->sig, &tpenv, m->tvars); + assert(ti != (jl_value_t*)jl_bottom_type); + (void)ti; // don't bother computing this if no arguments are tuples for(i=0; i < jl_tuple_len(tt); i++) { if (jl_is_tuple(jl_tupleref(tt,i))) @@ -1427,7 +1472,7 @@ jl_value_t *jl_gf_invoke(jl_function_t *gf, jl_tuple_t *types, } if (i < jl_tuple_len(tt)) { newsig = - (jl_tuple_t*)jl_instantiate_type_with((jl_type_t*)m->sig, + (jl_tuple_t*)jl_instantiate_type_with((jl_value_t*)m->sig, &jl_tupleref(tpenv,0), jl_tuple_len(tpenv)/2); } @@ -1439,7 +1484,7 @@ jl_value_t *jl_gf_invoke(jl_function_t *gf, jl_tuple_t *types, return jl_apply(mfunc, args, nargs); } -static void print_func_loc(ios_t *s, jl_lambda_info_t *li) +static void print_func_loc(JL_STREAM *s, jl_lambda_info_t *li) { long lno = li->line; if (lno > 0) { @@ -1450,7 +1495,7 @@ static void print_func_loc(ios_t *s, jl_lambda_info_t *li) static void print_methlist(jl_value_t *outstr, char *name, jl_methlist_t *ml) { - ios_t *s = (ios_t*)jl_iostr_data(outstr); + JL_STREAM *s = (JL_STREAM*)jl_iostr_data(outstr); while (ml != JL_NULL) { JL_PRINTF(s, "%s", name); if (ml->tvars != jl_null) { @@ -1531,6 +1576,7 @@ DLLEXPORT jl_tuple_t *jl_match_method(jl_value_t *type, jl_value_t *sig, return result; } +// returns a match as (argtypes, static_params, lambdainfo, cloenv) static jl_tuple_t *match_method(jl_value_t *type, jl_function_t *func, jl_tuple_t *sig, jl_tuple_t *tvars) { @@ -1549,13 +1595,13 @@ static jl_tuple_t *match_method(jl_value_t *type, jl_function_t *func, else { cenv = (jl_value_t*)jl_null; } + assert(jl_is_tuple(env)); result = jl_tuple(4, ti, env, func->linfo, cenv); } JL_GC_POP(); return result; } -// returns linked tuples (argtypes, static_params, lambdainfo, cloenv, next) static jl_value_t *ml_matches(jl_methlist_t *ml, jl_value_t *type, jl_sym_t *name, int lim) { @@ -1599,12 +1645,15 @@ static jl_value_t *ml_matches(jl_methlist_t *ml, jl_value_t *type, return (jl_value_t*)t; } -void jl_add_constructors(jl_struct_type_t *t); +void jl_add_constructors(jl_datatype_t *t); JL_CALLABLE(jl_f_ctor_trampoline); -// return linked tuples (t1, M1, (t2, M2, (... ()))) of types and methods. +// return a cell array of tuples, each describing a method match: +// {(t, spvals, li, cenv), ...} // t is the intersection of the type argument and the method signature, -// and M is the corresponding LambdaStaticData (jl_lambda_info_t) +// spvals is any matched static parameter values, li is the LambdaStaticData, +// and cenv is the closure environment or (). +// // lim is the max # of methods to return. if there are more return jl_false. // -1 for no limit. DLLEXPORT @@ -1614,18 +1663,10 @@ jl_value_t *jl_matching_methods(jl_function_t *gf, jl_value_t *type, int lim) if (gf->fptr == jl_f_no_function) return (jl_value_t*)jl_an_empty_cell; if (gf->fptr == jl_f_ctor_trampoline) - jl_add_constructors((jl_struct_type_t*)gf); + jl_add_constructors((jl_datatype_t*)gf); if (!jl_is_gf(gf)) { return (jl_value_t*)jl_an_empty_cell; } jl_methtable_t *mt = jl_gf_mtable(gf); return ml_matches(mt->defs, type, jl_gf_name(gf), lim); } - -DLLEXPORT -int jl_is_builtin(jl_value_t *v) -{ - return ((jl_is_func(v) && (((jl_function_t*)v)->linfo==NULL) && - !jl_is_gf(v)) || - jl_typeis(v,jl_intrinsic_type)); -} diff --git a/src/h2j.cpp b/src/h2j.cpp index 1b950569f071e..158d531f74932 100644 --- a/src/h2j.cpp +++ b/src/h2j.cpp @@ -22,11 +22,14 @@ using namespace clang; class PrintFunctionsConsumer : public ASTConsumer { public: - virtual void HandleTopLevelDecl(DeclGroupRef DG) { + virtual bool HandleTopLevelDecl(DeclGroupRef DG) { for (DeclGroupRef::iterator i = DG.begin(), e = DG.end(); i != e; ++i) { const Decl *D = *i; const FunctionDecl *FD = dyn_cast(D); - if (!FD || !FD->hasPrototype() || !FD->isExternC() || !FD->isGlobal()) return; + //D->dump(); + //cout << '\n'; + //return true; + if (!FD || !FD->hasPrototype() || !FD->isExternC() || !FD->isGlobal() || FD->getBuiltinID() != 0) return true; cout << FD->getResultType().getAsString() << " "; cout << FD->getNameAsString() << "("; bool printComma = false; @@ -40,6 +43,7 @@ class PrintFunctionsConsumer : public ASTConsumer { } cout << ");\n"; } + return true; } }; @@ -49,15 +53,15 @@ int main() ci.createDiagnostics(0,NULL); TargetOptions to; - to.Triple = llvm::sys::getHostTriple(); + to.Triple = llvm::sys::getDefaultTargetTriple(); TargetInfo *pti = TargetInfo::CreateTargetInfo(ci.getDiagnostics(), to); ci.setTarget(pti); ci.getHeaderSearchOpts().AddPath( - StringRef("lib/clang/3.0/include"), frontend::Angled, false, false, false + StringRef("../usr/lib/clang/3.0/include"), frontend::Angled, false, false, false ); ci.getHeaderSearchOpts().AddPath( - StringRef("src/support"), frontend::Quoted, true, false, false + StringRef("support"), frontend::Quoted, true, false, false ); ci.createFileManager(); @@ -67,7 +71,7 @@ int main() ci.setASTConsumer(astConsumer); ci.createASTContext(); - const FileEntry *pFile = ci.getFileManager().getFile("src/julia.h"); + const FileEntry *pFile = ci.getFileManager().getFile("julia.h"); ci.getSourceManager().createMainFileID(pFile); ci.getDiagnosticClient().BeginSourceFile(ci.getLangOpts(), &ci.getPreprocessor()); clang::ParseAST(ci.getPreprocessor(), astConsumer, ci.getASTContext()); diff --git a/src/init.c b/src/init.c index e350791cc6631..b9b3919d5e231 100644 --- a/src/init.c +++ b/src/init.c @@ -21,9 +21,23 @@ #include #ifdef __WIN32__ # define WIN32_LEAN_AND_MEAN +// Copied from MINGW_FLOAT_H which may not be found due to a colision with the builtin gcc float.h +// eventually we can probably integrate this into OpenLibm. +void __cdecl __MINGW_NOTHROW _fpreset (void); +void __cdecl __MINGW_NOTHROW fpreset (void); +#define _FPE_INVALID 0x81 +#define _FPE_DENORMAL 0x82 +#define _FPE_ZERODIVIDE 0x83 +#define _FPE_OVERFLOW 0x84 +#define _FPE_UNDERFLOW 0x85 +#define _FPE_INEXACT 0x86 +#define _FPE_UNEMULATED 0x87 +#define _FPE_SQRTNEG 0x88 +#define _FPE_STACKOVERFLOW 0x8a +#define _FPE_STACKUNDERFLOW 0x8b +#define _FPE_EXPLICITGEN 0x8c /* raise( SIGFPE ); */ # include #endif - #if defined(__linux__) //#define _GNU_SOURCE #include // for setting CPU affinity @@ -49,24 +63,41 @@ static void jl_find_stack_bottom(void) jl_stack_lo = jl_stack_hi - stack_size; } -#ifndef __WIN32__ +#ifdef __WIN32__ +void __cdecl fpe_handler(int arg,int num) +#else void fpe_handler(int arg) +#endif { (void)arg; +#ifndef __WIN32__ sigset_t sset; sigemptyset(&sset); sigaddset(&sset, SIGFPE); sigprocmask(SIG_UNBLOCK, &sset, NULL); - - jl_throw(jl_divbyzero_exception); +#else + fpreset(); + signal(SIGFPE, (void (__cdecl *)(int))fpe_handler); + switch(num) { + case _FPE_INVALID: + case _FPE_OVERFLOW: + case _FPE_UNDERFLOW: + default: + jl_errorf("Unexpected FPE Error 0x%X", num); + break; + case _FPE_ZERODIVIDE: +#endif + jl_throw(jl_divbyzero_exception); +#ifdef __WIN32__ + break; + } +#endif } +#ifndef __WIN32__ void segv_handler(int sig, siginfo_t *info, void *context) { sigset_t sset; - sigemptyset(&sset); - sigaddset(&sset, SIGSEGV); - sigprocmask(SIG_UNBLOCK, &sset, NULL); if ( #ifdef COPY_STACKS @@ -78,66 +109,326 @@ void segv_handler(int sig, siginfo_t *info, void *context) (char*)jl_current_task->stack+jl_current_task->ssize #endif ) { + sigemptyset(&sset); + sigaddset(&sset, SIGSEGV); + sigprocmask(SIG_UNBLOCK, &sset, NULL); jl_throw(jl_stackovf_exception); } else { - signal(SIGSEGV, SIG_DFL); + uv_tty_reset_mode(); + sigfillset(&sset); + sigprocmask(SIG_UNBLOCK, &sset, NULL); + signal(sig, SIG_DFL); + if (sig != SIGSEGV && + sig != SIGBUS && + sig != SIGILL) + raise(sig); } } +#endif + volatile sig_atomic_t jl_signal_pending = 0; volatile sig_atomic_t jl_defer_signal = 0; +#ifdef __WIN32__ +volatile HANDLE hMainThread = NULL; +void restore_signals() +{ + SetConsoleCtrlHandler(NULL,0); //turn on ctrl-c handler +} +static void __fastcall win_raise_exception(void* excpt) +{ //why __fastcall? because the first two arguments are passed in registers, making this easier + jl_throw(excpt); +} +static BOOL WINAPI sigint_handler(DWORD wsig) //This needs winapi types to guarantee __stdcall +{ + int sig; + //windows signals use different numbers from unix + switch(wsig) { + case CTRL_C_EVENT: sig = SIGINT; break; + //case CTRL_BREAK_EVENT: sig = SIGTERM; break; + // etc. + default: sig = SIGTERM; break; + } + if (jl_defer_signal) { + jl_signal_pending = sig; + } + else { + jl_signal_pending = 0; + if ((DWORD)-1 == SuspendThread(hMainThread)) { + //error + fputs("error: SuspendThread failed\n",stderr); + return 0; + } + CONTEXT ctxThread; + memset(&ctxThread,0,sizeof(CONTEXT)); + ctxThread.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER; + if (!GetThreadContext(hMainThread, &ctxThread)) { + //error + fputs("error: GetThreadContext failed\n",stderr); + return 0; + } +#ifdef _WIN64 + ctxThread.Rip = (DWORD64)&win_raise_exception; + ctxThread.Rcx = (DWORD64)jl_interrupt_exception; + ctxThread.Rsp &= (DWORD64)-16; + ctxThread.Rsp -= 8; //fix up the stack pointer -- this seems to be correct by observation +#elif _WIN32 + ctxThread.Eip = (DWORD)&win_raise_exception; + ctxThread.Ecx = (DWORD)jl_interrupt_exception; + ctxThread.Esp &= (DWORD)-16; + ctxThread.Esp -= 4; //fix up the stack pointer +#else +#error WIN16 not supported :P +#endif + ctxThread.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER; + if (!SetThreadContext(hMainThread,&ctxThread)) { + fputs("error: SetThreadContext failed\n",stderr); + //error + return 0; + } + if ((DWORD)-1 == ResumeThread(hMainThread)) { + fputs("error: ResumeThread failed\n",stderr); + //error + return 0; + } + } + return 1; +} +static LONG WINAPI exception_handler(struct _EXCEPTION_POINTERS *ExceptionInfo) { + if (ExceptionInfo->ExceptionRecord->ExceptionFlags == 0) { + switch (ExceptionInfo->ExceptionRecord->ExceptionCode) { + case EXCEPTION_STACK_OVERFLOW: +#ifdef _WIN64 + ExceptionInfo->ContextRecord->Rip = (DWORD64)&win_raise_exception; + ExceptionInfo->ContextRecord->Rcx = (DWORD64)jl_stackovf_exception; + ExceptionInfo->ContextRecord->Rsp &= (DWORD64)-16; + ExceptionInfo->ContextRecord->Rsp -= 8; //fix up the stack pointer -- this seems to be correct by observation +#elif _WIN32 + ExceptionInfo->ContextRecord->Eip = (DWORD)&win_raise_exception; + ExceptionInfo->ContextRecord->Ecx = (DWORD)jl_stackovf_exception; + ExceptionInfo->ContextRecord->Esp &= (DWORD)-16; + ExceptionInfo->ContextRecord->Esp -= 4; //fix up the stack pointer +#else +#error WIN16 not supported :P +#endif + return EXCEPTION_CONTINUE_EXECUTION; + default: + puts("Please submit a bug report with steps to reproduce this fault, and any error messages that follow (in their entirety). Thanks.\n"); + break; + } + } + return EXCEPTION_CONTINUE_SEARCH; +} +#else void restore_signals() { sigset_t sset; sigemptyset(&sset); sigprocmask(SIG_SETMASK, &sset, 0); } - void sigint_handler(int sig, siginfo_t *info, void *context) { - sigset_t sset; - sigemptyset(&sset); - sigaddset(&sset, SIGINT); - sigprocmask(SIG_UNBLOCK, &sset, NULL); - if (jl_defer_signal) { jl_signal_pending = sig; } else { jl_signal_pending = 0; + sigset_t sset; + sigemptyset(&sset); + sigaddset(&sset, SIGINT); + sigprocmask(SIG_UNBLOCK, &sset, NULL); jl_throw(jl_interrupt_exception); } } #endif -void jl_atexit_hook() +struct uv_shutdown_queue_item { uv_handle_t *h; struct uv_shutdown_queue_item *next; }; +struct uv_shutdown_queue { struct uv_shutdown_queue_item *first; struct uv_shutdown_queue_item *last; }; +static void jl_shutdown_uv_cb(uv_shutdown_t* req, int status) +{ + //if (status == 0) + jl_close_uv((uv_handle_t*)req->handle); + free(req); +} +static void jl_uv_exitcleanup_add(uv_handle_t* handle, struct uv_shutdown_queue *queue) { + struct uv_shutdown_queue_item *item = malloc(sizeof(struct uv_shutdown_queue_item)); + item->h = handle; + item->next = NULL; + if (queue->last) queue->last->next = item; + if (!queue->first) queue->first = item; + queue->last = item; +} +static void jl_uv_exitcleanup_walk(uv_handle_t* handle, void *arg) { + if (handle != (uv_handle_t*)jl_uv_stdout && handle != (uv_handle_t*)jl_uv_stderr) + jl_uv_exitcleanup_add(handle, arg); +} +DLLEXPORT void uv_atexit_hook() +{ +#if defined(JL_GC_MARKSWEEP) && defined(GC_FINAL_STATS) + jl_print_gc_stats(JL_STDERR); +#endif if (jl_base_module) { jl_value_t *f = jl_get_global(jl_base_module, jl_symbol("_atexit")); if (f!=NULL && jl_is_function(f)) { jl_apply((jl_function_t*)f, NULL, 0); } } + uv_loop_t* loop = jl_global_event_loop(); + struct uv_shutdown_queue queue = {NULL, NULL}; + uv_walk(loop, jl_uv_exitcleanup_walk, &queue); + // close stdout and stderr last, since we like being + // able to show stuff (incl. printf's) + jl_uv_exitcleanup_add((uv_handle_t*)jl_uv_stdout, &queue); + jl_uv_exitcleanup_add((uv_handle_t*)jl_uv_stderr, &queue); + struct uv_shutdown_queue_item *item = queue.first; + while (item) { + uv_handle_t *handle = item->h; + if (uv_is_closing(handle)) { + item = item->next; + continue; + } + switch(handle->type) { + case UV_TTY: + case UV_UDP: +//#ifndef __WIN32__ // unix only supports shutdown on TCP and NAMED_PIPE +// but uv_shutdown doesn't seem to be particularly reliable, so we'll avoid it in general + jl_close_uv(handle); + break; +//#endif + case UV_TCP: + case UV_NAMED_PIPE: + if (uv_is_writable((uv_stream_t*)handle)) { // uv_shutdown returns an error if not writable + uv_shutdown_t *req = malloc(sizeof(uv_shutdown_t)); + int err = uv_shutdown(req, (uv_stream_t*)handle, jl_shutdown_uv_cb); + if (err != 0) { + printf("shutdown err: %s\n", uv_strerror(uv_last_error(jl_global_event_loop()))); + jl_close_uv(handle); + } + } + else { + jl_close_uv(handle); + } + break; + case UV_POLL: + case UV_TIMER: + case UV_PREPARE: + case UV_CHECK: + case UV_IDLE: + case UV_ASYNC: + case UV_SIGNAL: + case UV_PROCESS: + case UV_FS_EVENT: + case UV_FS_POLL: + jl_close_uv(handle); + break; + case UV_HANDLE: + case UV_STREAM: + case UV_UNKNOWN_HANDLE: + case UV_HANDLE_TYPE_MAX: + case UV_RAW_FD: + case UV_RAW_HANDLE: + default: + assert(0); + } + item = item->next; + } + uv_run(loop,UV_RUN_DEFAULT); //let libuv spin until everything has finished closing } void jl_get_builtin_hooks(void); uv_lib_t *jl_dl_handle; +#ifdef __WIN32__ +uv_lib_t _jl_ntdll_handle; +uv_lib_t _jl_exe_handle; +uv_lib_t _jl_kernel32_handle; +uv_lib_t _jl_crtdll_handle; +uv_lib_t _jl_winsock_handle; + +uv_lib_t *jl_ntdll_handle=&_jl_ntdll_handle; +uv_lib_t *jl_exe_handle=&_jl_exe_handle; +uv_lib_t *jl_kernel32_handle=&_jl_kernel32_handle; +uv_lib_t *jl_crtdll_handle=&_jl_crtdll_handle; +uv_lib_t *jl_winsock_handle=&_jl_winsock_handle; +#endif +uv_loop_t *jl_io_loop; #ifdef COPY_STACKS void jl_switch_stack(jl_task_t *t, jl_jmp_buf *where); extern jl_jmp_buf * volatile jl_jmp_target; #endif +#ifdef __WIN32__ +static long chachedPagesize = 0; +long getPageSize (void) +{ + if (!chachedPagesize) { + SYSTEM_INFO systemInfo; + GetSystemInfo (&systemInfo); + chachedPagesize = systemInfo.dwPageSize; + } + return chachedPagesize; +} +#else +long getPageSize (void) +{ + return sysconf(_SC_PAGESIZE); +} +#endif + +void *init_stdio_handle(uv_file fd,int readable) +{ + void *handle; + uv_handle_type type = uv_guess_handle(fd); + switch(type) + { + case UV_TTY: + handle = malloc(sizeof(uv_tty_t)); + uv_tty_init(jl_io_loop,(uv_tty_t*)handle,fd,readable); + ((uv_tty_t*)handle)->data=0; + uv_tty_set_mode((void*)handle,0); //cooked stdio + break; + case UV_NAMED_PIPE: + case UV_FILE: + handle = malloc(sizeof(uv_pipe_t)); + uv_pipe_init(jl_io_loop, (uv_pipe_t*)handle,(readable?UV_PIPE_READABLE:UV_PIPE_WRITEABLE)); + uv_pipe_open((uv_pipe_t*)handle,fd); + ((uv_pipe_t*)handle)->data=0; + break; + case UV_TCP: + case UV_UDP: + default: + handle=NULL; + jl_errorf("This type of handle for stdio is not yet supported (%d)!\n",type); + break; + } + return handle; +} + +void init_stdio() +{ //order must be 2,1,0 + JL_STDERR = init_stdio_handle(2,0); + JL_STDOUT = init_stdio_handle(1,0); + JL_STDIN = init_stdio_handle(0,1); +} + void julia_init(char *imageFile) { - (void)uv_default_loop(); - restore_signals(); //XXX: this needs to be early in load process - jl_page_size = sysconf(_SC_PAGESIZE); + jl_page_size = getPageSize(); jl_find_stack_bottom(); - jl_dl_handle = jl_load_dynamic_library(NULL); + jl_dl_handle = jl_load_dynamic_library(NULL, JL_RTLD_DEFAULT); +#ifdef __WIN32__ + uv_dlopen("ntdll.dll",jl_ntdll_handle); //bypass julia's pathchecking for system dlls + uv_dlopen("Kernel32.dll",jl_kernel32_handle); + uv_dlopen("msvcrt.dll",jl_crtdll_handle); + uv_dlopen("Ws2_32.dll",jl_winsock_handle); + _jl_exe_handle.handle = GetModuleHandleA(NULL); +#endif + jl_io_loop = uv_default_loop(); //this loop will internal events (spawining process etc.) + init_stdio(); #if defined(__linux__) int ncores = jl_cpu_cores(); @@ -198,8 +489,8 @@ void julia_init(char *imageFile) for(i=1; i < jl_core_module->bindings.size; i+=2) { if (table[i] != HT_NOTFOUND) { jl_binding_t *b = (jl_binding_t*)table[i]; - if (b->value && jl_is_some_tag_type(b->value)) { - jl_tag_type_t *tt = (jl_tag_type_t*)b->value; + if (b->value && jl_is_datatype(b->value)) { + jl_datatype_t *tt = (jl_datatype_t*)b->value; tt->name->module = jl_core_module; } } @@ -208,8 +499,9 @@ void julia_init(char *imageFile) // the Main module is the one which is always open, and set as the // current module for bare (non-module-wrapped) toplevel expressions. // it does "using Base" if Base is available. - if (jl_base_module != NULL) - jl_module_using(jl_main_module, jl_base_module); + if (jl_base_module != NULL) { + jl_add_standard_imports(jl_main_module); + } // eval() uses Main by default, so Main.eval === Core.eval jl_module_import(jl_main_module, jl_core_module, jl_symbol("eval")); jl_current_module = jl_main_module; @@ -243,10 +535,13 @@ void julia_init(char *imageFile) JL_PRINTF(JL_STDERR, "sigaction: %s\n", strerror(errno)); jl_exit(1); } +#else + if (signal(SIGFPE, (void (__cdecl *)(int))fpe_handler) == SIG_ERR) { + JL_PRINTF(JL_STDERR, "Couldn't set SIGFPE\n"); + jl_exit(1); + } #endif - atexit(jl_atexit_hook); - #ifdef JL_GC_MARKSWEEP jl_gc_enable(); #endif @@ -255,9 +550,11 @@ void julia_init(char *imageFile) DLLEXPORT void jl_install_sigint_handler() { #ifdef __WIN32__ - DuplicateHandle( GetCurrentProcess(), GetCurrentThread(), - GetCurrentProcess(), (PHANDLE)&hMainThread, 0, - TRUE, DUPLICATE_SAME_ACCESS ); + if (!DuplicateHandle( GetCurrentProcess(), GetCurrentThread(), + GetCurrentProcess(), (PHANDLE)&hMainThread, 0, + TRUE, DUPLICATE_SAME_ACCESS )) { + JL_PRINTF(JL_STDERR, "Couldn't access handle to main thread\n"); + } SetConsoleCtrlHandler((PHANDLER_ROUTINE)sigint_handler,1); #else struct sigaction act; @@ -273,17 +570,34 @@ DLLEXPORT void jl_install_sigint_handler() //printf("sigint installed\n"); } -DLLEXPORT -int julia_trampoline(int argc, char *argv[], int (*pmain)(int ac,char *av[])) + +extern void * __stack_chk_guard; + +DLLEXPORT int julia_trampoline(int argc, char **argv, int (*pmain)(int ac,char *av[])) { +#if defined(_WIN32) //&& !defined(_WIN64) + SetUnhandledExceptionFilter(exception_handler); +#endif + unsigned char * p = (unsigned char *) &__stack_chk_guard; + char a = p[sizeof(__stack_chk_guard)-1]; + char b = p[sizeof(__stack_chk_guard)-2]; + char c = p[0]; + /* If you have the ability to generate random numbers in your kernel then use them */ + p[sizeof(__stack_chk_guard)-1] = 255; + p[sizeof(__stack_chk_guard)-2] = '\n'; + p[0] = 0; #ifdef COPY_STACKS // initialize base context of root task jl_root_task->stackbase = (char*)&argc; - if (jl_setjmp(jl_root_task->base_ctx, 1)) { + if (jl_setjmp(jl_root_task->base_ctx, 0)) { jl_switch_stack(jl_current_task, jl_jmp_target); } #endif - return pmain(argc, argv); + int ret = pmain(argc, argv); + p[sizeof(__stack_chk_guard)-1] = a; + p[sizeof(__stack_chk_guard)-2] = b; + p[0] = c; + return ret; } jl_function_t *jl_typeinf_func=NULL; @@ -312,16 +626,16 @@ void jl_get_builtin_hooks(void) jl_root_task->tls = jl_nothing; jl_root_task->consumers = jl_nothing; - jl_char_type = (jl_bits_type_t*)core("Char"); - jl_int8_type = (jl_bits_type_t*)core("Int8"); - jl_uint8_type = (jl_bits_type_t*)core("Uint8"); - jl_int16_type = (jl_bits_type_t*)core("Int16"); - jl_uint16_type = (jl_bits_type_t*)core("Uint16"); - jl_uint32_type = (jl_bits_type_t*)core("Uint32"); - jl_uint64_type = (jl_bits_type_t*)core("Uint64"); + jl_char_type = (jl_datatype_t*)core("Char"); + jl_int8_type = (jl_datatype_t*)core("Int8"); + jl_uint8_type = (jl_datatype_t*)core("Uint8"); + jl_int16_type = (jl_datatype_t*)core("Int16"); + jl_uint16_type = (jl_datatype_t*)core("Uint16"); + jl_uint32_type = (jl_datatype_t*)core("Uint32"); + jl_uint64_type = (jl_datatype_t*)core("Uint64"); - jl_float32_type = (jl_bits_type_t*)core("Float32"); - jl_float64_type = (jl_bits_type_t*)core("Float64"); + jl_float32_type = (jl_datatype_t*)core("Float32"); + jl_float64_type = (jl_datatype_t*)core("Float64"); jl_stackovf_exception = jl_apply((jl_function_t*)core("StackOverflowError"), NULL, 0); @@ -342,24 +656,23 @@ void jl_get_builtin_hooks(void) jl_memory_exception = jl_apply((jl_function_t*)core("MemoryError"),NULL,0); - jl_ascii_string_type = (jl_struct_type_t*)core("ASCIIString"); - jl_utf8_string_type = (jl_struct_type_t*)core("UTF8String"); - jl_symbolnode_type = (jl_struct_type_t*)core("SymbolNode"); - jl_getfieldnode_type = (jl_struct_type_t*)core("GetfieldNode"); + jl_ascii_string_type = (jl_datatype_t*)core("ASCIIString"); + jl_utf8_string_type = (jl_datatype_t*)core("UTF8String"); + jl_symbolnode_type = (jl_datatype_t*)core("SymbolNode"); + jl_getfieldnode_type = (jl_datatype_t*)core("GetfieldNode"); - jl_array_uint8_type = - (jl_type_t*)jl_apply_type((jl_value_t*)jl_array_type, - jl_tuple2(jl_uint8_type, - jl_box_long(1))); + jl_array_uint8_type = jl_apply_type((jl_value_t*)jl_array_type, + jl_tuple2(jl_uint8_type, + jl_box_long(1))); } DLLEXPORT void jl_get_system_hooks(void) { if (jl_errorexception_type) return; // only do this once - jl_errorexception_type = (jl_struct_type_t*)basemod("ErrorException"); - jl_typeerror_type = (jl_struct_type_t*)basemod("TypeError"); - jl_methoderror_type = (jl_struct_type_t*)basemod("MethodError"); - jl_loaderror_type = (jl_struct_type_t*)basemod("LoadError"); - jl_weakref_type = (jl_struct_type_t*)basemod("WeakRef"); + jl_errorexception_type = (jl_datatype_t*)basemod("ErrorException"); + jl_typeerror_type = (jl_datatype_t*)basemod("TypeError"); + jl_methoderror_type = (jl_datatype_t*)basemod("MethodError"); + jl_loaderror_type = (jl_datatype_t*)basemod("LoadError"); + jl_weakref_type = (jl_datatype_t*)basemod("WeakRef"); } diff --git a/src/interpreter.c b/src/interpreter.c index 171ffa2a693aa..290fb563c7231 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -46,11 +46,11 @@ jl_value_t *jl_interpret_toplevel_expr_in(jl_module_t *m, jl_value_t *e, static jl_value_t *do_call(jl_function_t *f, jl_value_t **args, size_t nargs, jl_value_t **locals, size_t nl) { - jl_value_t **argv = alloca((nargs+1) * sizeof(jl_value_t*)); + jl_value_t **argv; + JL_GC_PUSHARGS(argv, nargs+1); size_t i; argv[0] = (jl_value_t*)f; for(i=1; i < nargs+1; i++) argv[i] = NULL; - JL_GC_PUSHARGS(argv, nargs+1); for(i=0; i < nargs; i++) argv[i+1] = eval(args[i], locals, nl); jl_value_t *result = jl_apply(f, &argv[1], nargs); @@ -67,6 +67,7 @@ jl_value_t *jl_eval_global_var(jl_module_t *m, jl_sym_t *e) } extern int jl_boot_file_loaded; +extern int inside_typedef; static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl) { @@ -117,12 +118,13 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl) } jl_expr_t *ex = (jl_expr_t*)e; jl_value_t **args = &jl_cellref(ex->args,0); + size_t nargs = jl_array_len(ex->args); if (ex->head == call_sym || ex->head == call1_sym) { jl_function_t *f = (jl_function_t*)eval(args[0], locals, nl); if (!jl_is_func(f)) jl_type_error("apply", (jl_value_t*)jl_function_type, (jl_value_t*)f); - return do_call(f, &args[1], ex->args->length-1, locals, nl); + return do_call(f, &args[1], nargs-1, locals, nl); } else if (ex->head == assign_sym) { jl_value_t *sym = args[0]; @@ -139,9 +141,13 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl) } else if (ex->head == new_sym) { jl_value_t *thetype = eval(args[0], locals, nl); - JL_GC_PUSH(&thetype); - assert(jl_is_struct_type(thetype)); - jl_value_t *v = jl_new_struct_uninit((jl_struct_type_t*)thetype); + jl_value_t *v=NULL; + JL_GC_PUSH(&thetype, &v); + assert(jl_is_structtype(thetype)); + v = jl_new_struct_uninit((jl_datatype_t*)thetype); + for(size_t i=1; i < nargs; i++) { + jl_set_nth_field(v, i-1, eval(args[i], locals, nl)); + } JL_GC_POP(); return v; } @@ -161,15 +167,36 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl) jl_sym_t *fname = (jl_sym_t*)args[0]; jl_value_t **bp=NULL; jl_binding_t *b=NULL; - for (size_t i=0; i < nl; i++) { - if (locals[i*2] == (jl_value_t*)fname) { - bp = &locals[i*2+1]; - break; + jl_value_t *gf=NULL; + int kw=0; + if (jl_is_expr(fname)) { + if (((jl_expr_t*)fname)->head == kw_sym) { + kw = 1; + fname = (jl_sym_t*)jl_exprarg(fname, 0); + } + gf = eval((jl_value_t*)fname, locals, nl); + assert(jl_is_function(gf)); + assert(jl_is_gf(gf)); + if (!kw) { + fname = (jl_sym_t*)jl_fieldref(jl_exprarg(fname, 2), 0); + bp = &gf; + } + else { + bp = (jl_value_t**)&((jl_methtable_t*)((jl_function_t*)gf)->env)->kwsorter; } + assert(jl_is_symbol(fname)); } - if (bp == NULL) { - b = jl_get_binding_for_method_def(jl_current_module, fname); - bp = &b->value; + else { + for (size_t i=0; i < nl; i++) { + if (locals[i*2] == (jl_value_t*)fname) { + bp = &locals[i*2+1]; + break; + } + } + if (bp == NULL) { + b = jl_get_binding_for_method_def(jl_current_module, fname); + bp = &b->value; + } } jl_value_t *atypes=NULL, *meth=NULL, *tvars=NULL; JL_GC_PUSH(&atypes, &meth, &tvars); @@ -179,7 +206,7 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl) jl_method_def(fname, bp, b, (jl_tuple_t*)atypes, (jl_function_t*)meth, (jl_tuple_t*)tvars); JL_GC_POP(); - return jl_nothing; + return *bp; } else if (ex->head == const_sym) { jl_value_t *sym = args[0]; @@ -195,7 +222,7 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl) else if (ex->head == global_sym) { // create uninitialized mutable binding for "global x" decl // TODO: handle type decls - for (size_t i=0; i < ex->args->length; i++) { + for (size_t i=0; i < jl_array_len(ex->args); i++) { assert(jl_is_symbol(args[i])); jl_get_binding_wr(jl_current_module, (jl_sym_t*)args[i]); } @@ -206,11 +233,12 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl) jl_value_t *para = eval(args[1], locals, nl); jl_value_t *super = NULL; JL_GC_PUSH(¶, &super); - jl_tag_type_t *tt=jl_new_tagtype(name, jl_any_type, (jl_tuple_t*)para); + jl_datatype_t *dt = + jl_new_abstracttype(name, jl_any_type, (jl_tuple_t*)para); jl_binding_t *b = jl_get_binding_wr(jl_current_module, (jl_sym_t*)name); - jl_checked_assignment(b, (jl_value_t*)tt); + jl_checked_assignment(b, (jl_value_t*)dt); super = eval(args[2], locals, nl); - jl_set_tag_type_super(tt, super); + jl_set_datatype_super(dt, super); JL_GC_POP(); return (jl_value_t*)jl_nothing; } @@ -226,34 +254,39 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl) if (nb < 1 || nb>=(1<<23) || (nb&7) != 0) jl_errorf("invalid number of bits in type %s", ((jl_sym_t*)name)->name); - jl_bits_type_t *bt = jl_new_bits_type(name, jl_any_type, (jl_tuple_t*)para, nb); + jl_datatype_t *dt = + jl_new_bitstype(name, jl_any_type, (jl_tuple_t*)para, nb); jl_binding_t *b = jl_get_binding_wr(jl_current_module, (jl_sym_t*)name); - jl_checked_assignment(b, (jl_value_t*)bt); + jl_checked_assignment(b, (jl_value_t*)dt); super = eval(args[3], locals, nl); - jl_set_tag_type_super((jl_tag_type_t*)bt, super); + jl_set_datatype_super(dt, super); JL_GC_POP(); return (jl_value_t*)jl_nothing; } else if (ex->head == compositetype_sym) { - void jl_add_constructors(jl_struct_type_t *t); + void jl_add_constructors(jl_datatype_t *t); jl_value_t *name = args[0]; jl_value_t *para = eval(args[1], locals, nl); jl_value_t *fnames = NULL; jl_value_t *super = NULL; - jl_struct_type_t *st = NULL; - JL_GC_PUSH(¶, &super, &fnames, &st); + jl_datatype_t *dt = NULL; + JL_GC_PUSH(¶, &super, &fnames, &dt); fnames = eval(args[2], locals, nl); - st = jl_new_struct_type((jl_sym_t*)name, jl_any_type, (jl_tuple_t*)para, - (jl_tuple_t*)fnames, NULL); - st->ctor_factory = eval(args[3], locals, nl); + dt = jl_new_datatype((jl_sym_t*)name, jl_any_type, (jl_tuple_t*)para, + (jl_tuple_t*)fnames, NULL, + 0, args[6]==jl_true ? 1 : 0); + dt->fptr = jl_f_ctor_trampoline; + dt->ctor_factory = eval(args[3], locals, nl); jl_binding_t *b = jl_get_binding_wr(jl_current_module, (jl_sym_t*)name); - jl_checked_assignment(b, (jl_value_t*)st); - st->types = (jl_tuple_t*)eval(args[5], locals, nl); - jl_check_type_tuple(st->types, st->name->name, "type definition"); + jl_checked_assignment(b, (jl_value_t*)dt); + inside_typedef = 1; + dt->types = (jl_tuple_t*)eval(args[5], locals, nl); + inside_typedef = 0; + jl_check_type_tuple(dt->types, dt->name->name, "type definition"); super = eval(args[4], locals, nl); - jl_set_tag_type_super((jl_tag_type_t*)st, super); - jl_compute_struct_offsets(st); - jl_add_constructors(st); + jl_set_datatype_super(dt, super); + jl_compute_field_offsets(dt); + jl_add_constructors(dt); JL_GC_POP(); return (jl_value_t*)jl_nothing; } @@ -280,7 +313,7 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl) } else if (ex->head == error_sym || ex->head == jl_continue_sym) { if (jl_is_byte_string(args[0])) - jl_errorf("syntax error: %s", jl_string_data(args[0])); + jl_errorf("syntax: %s", jl_string_data(args[0])); jl_throw(args[0]); } jl_errorf("unsupported or misplaced expression %s", ex->head->name); @@ -291,12 +324,12 @@ static int label_idx(jl_value_t *tgt, jl_array_t *stmts) { size_t j; long ltgt = jl_unbox_long(tgt); - for(j=0; j < stmts->length; j++) { + for(j=0; j < stmts->nrows; j++) { jl_value_t *l = jl_cellref(stmts,j); if (jl_is_labelnode(l) && jl_labelnode_label(l)==ltgt) break; } - assert(j < stmts->length); + assert(j < stmts->nrows); return j; } @@ -360,20 +393,21 @@ jl_value_t *jl_interpret_toplevel_thunk_with(jl_lambda_info_t *lam, jl_expr_t *ast = (jl_expr_t*)lam->ast; jl_array_t *stmts = jl_lam_body(ast)->args; jl_array_t *l = jl_lam_locals(ast); + size_t llength = jl_array_len(l); jl_value_t **names = &((jl_value_t**)l->data)[0]; - nl += l->length; - jl_value_t **locals = (jl_value_t**)alloca(nl*2*sizeof(void*)); + nl += llength; + jl_value_t **locals; + JL_GC_PUSHARGS(locals, nl*2); jl_value_t *r = (jl_value_t*)jl_null; size_t i=0; - for(i=0; i < l->length; i++) { + for(i=0; i < llength; i++) { locals[i*2] = names[i]; locals[i*2+1] = NULL; } for(; i < nl; i++) { - locals[i*2] = loc[(i-l->length)*2]; - locals[i*2+1] = loc[(i-l->length)*2+1]; + locals[i*2] = loc[(i-llength)*2]; + locals[i*2+1] = loc[(i-llength)*2+1]; } - JL_GC_PUSHARGS(locals, nl*2); r = eval_body(stmts, locals, nl, 0); JL_GC_POP(); return r; diff --git a/src/intrinsics.cpp b/src/intrinsics.cpp index 5a316934f216d..34aa71a8352bc 100644 --- a/src/intrinsics.cpp +++ b/src/intrinsics.cpp @@ -24,8 +24,7 @@ namespace JL_I { and_int, or_int, xor_int, not_int, shl_int, lshr_int, ashr_int, bswap_int, ctpop_int, ctlz_int, cttz_int, // conversion - sext16, zext16, sext32, zext32, sext64, zext64, sext_int, zext_int, - trunc8, trunc16, trunc32, trunc64, trunc_int, + sext_int, zext_int, trunc_int, fptoui32, fptosi32, fptoui64, fptosi64, fpsiround32, fpsiround64, fpuiround32, fpuiround64, uitofp32, sitofp32, uitofp64, sitofp64, @@ -34,13 +33,14 @@ namespace JL_I { abs_float, copysign_float, flipsign_int, // pointer access - pointerref, pointerset, + pointerref, pointerset, pointertoref, // checked arithmetic checked_sadd, checked_uadd, checked_ssub, checked_usub, checked_smul, checked_umul, - checked_fptoui32, checked_fptosi32, checked_fptoui64, checked_fptosi64, + checked_fptoui, checked_fptosi, + nan_dom_err, // c interface - ccall, + ccall, jl_alloca }; }; @@ -135,19 +135,19 @@ static Value *emit_unboxed(jl_value_t *e, jl_codectx_t *ctx) else if (e == jl_false) { return ConstantInt::get(T_int1, 0); } - else if (jl_is_bits_type(jl_typeof(e))) { - jl_bits_type_t *bt = (jl_bits_type_t*)jl_typeof(e); - int nb = jl_bitstype_nbits(bt); - if (nb == 8) + else if (jl_is_bitstype(jl_typeof(e))) { + jl_datatype_t *bt = (jl_datatype_t*)jl_typeof(e); + int nb = jl_datatype_size(bt); + if (nb == 1) return mark_julia_type(ConstantInt::get(T_int8, jl_unbox_int8(e)), (jl_value_t*)bt); - if (nb == 16) + if (nb == 2) return mark_julia_type(ConstantInt::get(T_int16, jl_unbox_int16(e)), (jl_value_t*)bt); - if (nb == 32) + if (nb == 4) return mark_julia_type(ConstantInt::get(T_int32, jl_unbox_int32(e)), (jl_value_t*)bt); - if (nb == 64) + if (nb == 8) return mark_julia_type(ConstantInt::get(T_int64, jl_unbox_int64(e)), (jl_value_t*)bt); // TODO: bigger sizes @@ -158,16 +158,18 @@ static Value *emit_unboxed(jl_value_t *e, jl_codectx_t *ctx) // emit code to unpack a raw value from a box static Value *emit_unbox(Type *to, Type *pto, Value *x) { - if (x->getType() != jl_pvalue_llvmt) { + Type *ty = x->getType(); + if (ty != jl_pvalue_llvmt) { // bools are stored internally as int8 (for now) - if (x->getType() == T_int1 && to == T_int8) + if (ty == T_int1 && to == T_int8) return builder.CreateZExt(x, T_int8); - if (x->getType()->isPointerTy() && !to->isPointerTy()) + if (ty->isPointerTy() && !to->isPointerTy()) return builder.CreatePtrToInt(x, to); - assert(x->getType() == to); + if (ty != to) + jl_error("unbox: T != typeof(x)"); return x; } - Value *p = bitstype_pointer(x); + Value *p = data_pointer(x); if (to == T_int1) { // bools stored as int8, so an extra Trunc is needed to get an int1 return builder.CreateTrunc(builder. @@ -175,6 +177,10 @@ static Value *emit_unbox(Type *to, Type *pto, Value *x) CreateBitCast(p, T_pint8), false), T_int1); } + if (to->isStructTy() && !to->isSized()) { + // empty struct - TODO - is this a good way to represent it? + return UndefValue::get(to); + } return builder.CreateLoad(builder.CreateBitCast(p, pto), false); } @@ -186,11 +192,11 @@ static Value *auto_unbox(jl_value_t *x, jl_codectx_t *ctx) return v; } jl_value_t *bt = expr_type(x, ctx); - if (!jl_is_bits_type(bt)) { + if (!jl_is_bitstype(bt)) { if (jl_is_symbol(x)) { bt = (*ctx->declTypes)[((jl_sym_t*)x)->name]; } - if (bt == NULL || !jl_is_bits_type(bt)) { + if (bt == NULL || !jl_is_bitstype(bt)) { // TODO: make sure this code is valid; hopefully it is // unreachable but it should still be well-formed. emit_error("auto_unbox: unable to determine argument type", ctx); @@ -199,7 +205,7 @@ static Value *auto_unbox(jl_value_t *x, jl_codectx_t *ctx) } Type *to = julia_type_to_llvm(bt); if (to == NULL || to == jl_pvalue_llvmt) { - unsigned int nb = jl_bitstype_nbits(bt); + unsigned int nb = jl_datatype_size(bt)*8; to = IntegerType::get(jl_LLVMContext, nb); } return emit_unbox(to, PointerType::get(to, 0), v); @@ -213,12 +219,12 @@ static int try_to_determine_bitstype_nbits(jl_value_t *targ, jl_codectx_t *ctx) jl_value_t *p = jl_tparam0(et); if (p == (jl_value_t*)jl_bool_type) return 1; - if (jl_is_bits_type(p)) - return jl_bitstype_nbits(p); + if (jl_is_bitstype(p)) + return jl_datatype_size(p)*8; if (jl_is_typevar(p)) { jl_value_t *ub = ((jl_tvar_t*)p)->ub; - if (jl_is_bits_type(ub)) - return jl_bitstype_nbits(ub); + if (jl_is_bitstype(ub)) + return jl_datatype_size(ub)*8; } } return -1; @@ -245,9 +251,9 @@ static Value *generic_unbox(jl_value_t *targ, jl_value_t *x, jl_codectx_t *ctx) } JL_CATCH { } - if (bt == NULL || !jl_is_bits_type(bt)) + if (bt == NULL || !jl_is_bitstype(bt)) jl_error("unbox: could not determine argument size"); - nb = (bt==(jl_value_t*)jl_bool_type) ? 1 : jl_bitstype_nbits(bt); + nb = (bt==(jl_value_t*)jl_bool_type) ? 1 : jl_datatype_size(bt)*8; } Type *to = IntegerType::get(jl_LLVMContext, nb); return emit_unbox(to, PointerType::get(to, 0), emit_unboxed(x, ctx)); @@ -261,7 +267,7 @@ static Value *generic_box(jl_value_t *targ, jl_value_t *x, jl_codectx_t *ctx) jl_value_t *bt = NULL; jl_value_t *et = expr_type(targ, ctx); if (jl_is_type_type(et) && jl_is_leaf_type(jl_tparam0(et)) && - jl_is_bits_type(jl_tparam0(et))) { + jl_is_bitstype(jl_tparam0(et))) { bt = jl_tparam0(et); } else { @@ -276,13 +282,13 @@ static Value *generic_box(jl_value_t *targ, jl_value_t *x, jl_codectx_t *ctx) if (bt == NULL) { } - else if (!jl_is_bits_type(bt)) { + else if (!jl_is_bitstype(bt)) { jl_error("box: expected bits type as first argument"); } else { llvmt = julia_type_to_llvm(bt); if (nb == -1) - nb = (bt==(jl_value_t*)jl_bool_type) ? 1 : jl_bitstype_nbits(bt); + nb = (bt==(jl_value_t*)jl_bool_type) ? 1 : jl_datatype_size(bt)*8; } if (nb == -1) @@ -321,48 +327,40 @@ static Value *generic_box(jl_value_t *targ, jl_value_t *x, jl_codectx_t *ctx) } // dynamically-determined type; evaluate. - return allocate_box_dynamic(emit_expr(targ, ctx), nb, vx); + return allocate_box_dynamic(emit_expr(targ, ctx), (nb+7)/8, vx); } -static Value *generic_trunc(jl_value_t *targ, jl_value_t *x, jl_codectx_t *ctx) +static Type *staticeval_bitstype(jl_value_t *targ, const char *fname, jl_codectx_t *ctx) { jl_value_t *bt = jl_interpret_toplevel_expr_in(ctx->module, targ, &jl_tupleref(ctx->sp,0), jl_tuple_len(ctx->sp)/2); - if (!jl_is_bits_type(bt)) - jl_error("trunc_int: expected bits type as first argument"); + if (!jl_is_bitstype(bt)) + jl_errorf("%s: expected bits type as first argument", fname); Type *to = julia_type_to_llvm(bt); if (to == NULL) { - unsigned int nb = jl_bitstype_nbits(bt); + unsigned int nb = jl_datatype_size(bt)*8; to = IntegerType::get(jl_LLVMContext, nb); } + return to; +} + +static Value *generic_trunc(jl_value_t *targ, jl_value_t *x, jl_codectx_t *ctx) +{ + Type *to = staticeval_bitstype(targ, "trunc_int", ctx); return builder.CreateTrunc(JL_INT(auto_unbox(x,ctx)), to); } static Value *generic_sext(jl_value_t *targ, jl_value_t *x, jl_codectx_t *ctx) { - jl_value_t *bt = - jl_interpret_toplevel_expr_in(ctx->module, targ, - &jl_tupleref(ctx->sp,0), - jl_tuple_len(ctx->sp)/2); - if (!jl_is_bits_type(bt)) - jl_error("sext_int: expected bits type as first argument"); - unsigned int nb = jl_bitstype_nbits(bt); - Type *to = IntegerType::get(jl_LLVMContext, nb); + Type *to = staticeval_bitstype(targ, "sext_int", ctx); return builder.CreateSExt(JL_INT(auto_unbox(x,ctx)), to); } static Value *generic_zext(jl_value_t *targ, jl_value_t *x, jl_codectx_t *ctx) { - jl_value_t *bt = - jl_interpret_toplevel_expr_in(ctx->module, targ, - &jl_tupleref(ctx->sp,0), - jl_tuple_len(ctx->sp)/2); - if (!jl_is_bits_type(bt)) - jl_error("zext_int: expected bits type as first argument"); - unsigned int nb = jl_bitstype_nbits(bt); - Type *to = IntegerType::get(jl_LLVMContext, nb); + Type *to = staticeval_bitstype(targ, "zext_int", ctx); return builder.CreateZExt(JL_INT(auto_unbox(x,ctx)), to); } @@ -388,6 +386,58 @@ static Value *emit_eqfui64(Value *x, Value *y) T_int64))); } +static Value *emit_checked_fptosi(Type *to, Value *x, jl_codectx_t *ctx) +{ + x = FP(x); + Value *v = builder.CreateFPToSI(x, to); + if (x->getType() == T_float32 && to == T_int32) { + raise_exception_unless + (builder.CreateFCmpOEQ(builder.CreateFPExt(x, T_float64), + builder.CreateSIToFP(v, T_float64)), + jlinexacterr_var, ctx); + } + else { + Value *xx = x, *vv = v; + if (x->getType() == T_float32) + xx = builder.CreateFPExt(x, T_float64); + if (to->getPrimitiveSizeInBits() < 64) + vv = builder.CreateSExt(v, T_int64); + raise_exception_unless(emit_eqfsi64(xx, vv), jlinexacterr_var, ctx); + } + return v; +} + +static Value *emit_checked_fptosi(jl_value_t *targ, Value *x, jl_codectx_t *ctx) +{ + return emit_checked_fptosi(staticeval_bitstype(targ, "checked_fptosi", ctx), x, ctx); +} + +static Value *emit_checked_fptoui(Type *to, Value *x, jl_codectx_t *ctx) +{ + x = FP(x); + Value *v = builder.CreateFPToUI(x, to); + if (x->getType() == T_float32 && to == T_int32) { + raise_exception_unless + (builder.CreateFCmpOEQ(builder.CreateFPExt(x, T_float64), + builder.CreateUIToFP(v, T_float64)), + jlinexacterr_var, ctx); + } + else { + Value *xx = x, *vv = v; + if (x->getType() == T_float32) + xx = builder.CreateFPExt(x, T_float64); + if (to->getPrimitiveSizeInBits() < 64) + vv = builder.CreateZExt(v, T_int64); + raise_exception_unless(emit_eqfui64(xx, vv), jlinexacterr_var, ctx); + } + return v; +} + +static Value *emit_checked_fptoui(jl_value_t *targ, Value *x, jl_codectx_t *ctx) +{ + return emit_checked_fptoui(staticeval_bitstype(targ, "checked_fptoui", ctx), x, ctx); +} + static Value *emit_pointerref(jl_value_t *e, jl_value_t *i, jl_codectx_t *ctx) { jl_value_t *aty = expr_type(e, ctx); @@ -396,19 +446,37 @@ static Value *emit_pointerref(jl_value_t *e, jl_value_t *i, jl_codectx_t *ctx) jl_value_t *ety = jl_tparam0(aty); if(jl_is_typevar(ety)) jl_error("pointerref: invalid pointer"); - if (!jl_is_bits_type(ety)) { - ety = (jl_value_t*)jl_any_type; - } - if ((jl_bits_type_t*)expr_type(i, ctx) != jl_long_type) { + if ((jl_datatype_t*)expr_type(i, ctx) != jl_long_type) { jl_error("pointerref: invalid index type"); } - //Value *idx = builder.CreateIntCast(auto_unbox(i,ctx), T_size, false); //TODO: use this instead (and remove assert jl_is_long)? + Value *thePtr = auto_unbox(e,ctx); Value *idx = emit_unbox(T_size, T_psize, emit_unboxed(i, ctx)); Value *im1 = builder.CreateSub(idx, ConstantInt::get(T_size, 1)); - return typed_load(auto_unbox(e, ctx), im1, ety, ctx); + if (!jl_isbits(ety)) { + if (ety == (jl_value_t*)jl_any_type) + return builder.CreateLoad(builder.CreateGEP( + builder.CreateBitCast(thePtr, jl_ppvalue_llvmt), + im1)); + if (!jl_is_structtype(ety) || jl_is_array_type(ety) || !jl_is_leaf_type(ety)) + jl_error("pointerref: invalid pointer type"); + uint64_t size = ((jl_datatype_t*)ety)->size; + Value *strct = + builder.CreateCall(jlallocobj_func, + ConstantInt::get(T_size, + sizeof(void*)+size)); + builder.CreateStore(literal_pointer_val((jl_value_t*)ety), + emit_nthptr_addr(strct, (size_t)0)); + im1 = builder.CreateMul(im1, ConstantInt::get(T_size, size)); + thePtr = builder.CreateGEP(builder.CreateBitCast(thePtr, T_pint8), im1); + builder.CreateMemCpy(builder.CreateBitCast(emit_nthptr_addr(strct, (size_t)1), T_pint8), + thePtr, size, 1); + return mark_julia_type(strct, ety); + } + return typed_load(thePtr, im1, ety, ctx); } -static Value *emit_pointerset(jl_value_t *e, jl_value_t *x, jl_value_t *i, jl_codectx_t *ctx) { +static Value *emit_pointerset(jl_value_t *e, jl_value_t *x, jl_value_t *i, jl_codectx_t *ctx) +{ jl_value_t *aty = expr_type(e, ctx); if (!jl_is_cpointer_type(aty)) jl_error("pointerset: expected pointer type as first argument"); @@ -418,10 +486,10 @@ static Value *emit_pointerset(jl_value_t *e, jl_value_t *x, jl_value_t *i, jl_co jl_value_t *xty = expr_type(x, ctx); if (!jl_subtype(xty, ety, 0)) jl_error("pointerset: type mismatch in assign"); - if (!jl_is_bits_type(ety)) { - ety = (jl_value_t*)jl_any_type; + if (!jl_isbits(ety)) { + jl_error("pointerset: invalid pointer type"); //ety = (jl_value_t*)jl_any_type; } - if ((jl_bits_type_t*)expr_type(i, ctx) != jl_long_type) { + if ((jl_datatype_t*)expr_type(i, ctx) != jl_long_type) { jl_error("pointerset: invalid index type"); } Value *idx = emit_unbox(T_size, T_psize, emit_unboxed(i, ctx)); @@ -437,42 +505,34 @@ static Value *emit_pointerset(jl_value_t *e, jl_value_t *x, jl_value_t *i, jl_co static Value *emit_intrinsic(intrinsic f, jl_value_t **args, size_t nargs, jl_codectx_t *ctx) { - if (f == ccall) return emit_ccall(args, nargs, ctx); - if (f == box) { - if (nargs!=2) - jl_error("box: wrong number of arguments"); - return generic_box(args[1], args[2], ctx); - } - if (f == unbox) { - if (nargs!=2) - jl_error("unbox: wrong number of arguments"); - return generic_unbox(args[1], args[2], ctx); - } - if (f == trunc_int) { - if (nargs!=2) - jl_error("trunc_int: wrong number of arguments"); - return generic_trunc(args[1], args[2], ctx); - } - if (f == sext_int) { - if (nargs!=2) - jl_error("sext_int: wrong number of arguments"); - return generic_sext(args[1], args[2], ctx); + switch (f) { + case ccall: return emit_ccall(args, nargs, ctx); + + HANDLE(box,2) return generic_box(args[1], args[2], ctx); + HANDLE(unbox,2) return generic_unbox(args[1], args[2], ctx); + HANDLE(trunc_int,2) return generic_trunc(args[1], args[2], ctx); + HANDLE(sext_int,2) return generic_sext(args[1], args[2], ctx); + HANDLE(zext_int,2) return generic_zext(args[1], args[2], ctx); + HANDLE(pointerref,2) return emit_pointerref(args[1], args[2], ctx); + HANDLE(pointerset,3) return emit_pointerset(args[1], args[2], args[3], ctx); + HANDLE(pointertoref,1) { + Value *p = auto_unbox(args[1], ctx); + if (p->getType()->isIntegerTy()) { + return builder.CreateIntToPtr(p, jl_pvalue_llvmt); + } + return builder.CreateBitCast(p, jl_pvalue_llvmt); } - if (f == zext_int) { - if (nargs!=2) - jl_error("zext_int: wrong number of arguments"); - return generic_zext(args[1], args[2], ctx); + HANDLE(checked_fptosi,2) { + Value *x = FP(auto_unbox(args[2], ctx)); + return emit_checked_fptosi(args[1], x, ctx); } - if (f == pointerref) { - if (nargs!=2) - jl_error("pointerref: wrong number of arguments"); - return emit_pointerref(args[1], args[2], ctx); + HANDLE(checked_fptoui,2) { + Value *x = FP(auto_unbox(args[2], ctx)); + return emit_checked_fptoui(args[1], x, ctx); } - if (f == pointerset) { - if (nargs!=3) - jl_error("pointerset: wrong number of arguments"); - return emit_pointerset(args[1], args[2], args[3], ctx); + default: ; } + if (nargs < 1) jl_error("invalid intrinsic call"); Value *x = auto_unbox(args[1], ctx); Value *y = NULL; @@ -558,47 +618,47 @@ static Value *emit_intrinsic(intrinsic f, jl_value_t **args, size_t nargs, HANDLE(ltfsi64,2) { x = FP(x); fy = JL_INT(y); + Value *ffy = builder.CreateSIToFP(fy, T_float64); + Value *siffy = builder.CreateFPToSI(ffy, T_int64); return builder.CreateOr( - builder.CreateFCmpOLT(x, builder.CreateSIToFP(fy, T_float64)), + builder.CreateFCmpOLT(x, ffy), builder.CreateAnd( - builder.CreateFCmpOEQ(x, builder.CreateSIToFP(fy, T_float64)), - builder.CreateICmpSGT( - fy, builder.CreateFPToSI( - builder.CreateSIToFP(fy, T_float64), - T_int64 - ) - ) + // ensure x < 2.0^63 + builder.CreateFCmpOLT(x, ConstantFP::get(T_float64, + 9.223372036854776e18)), + builder.CreateAnd(builder.CreateFCmpOEQ(x, ffy), + builder.CreateICmpSGT(fy, siffy)) ) ); } HANDLE(ltfui64,2) { x = FP(x); fy = JL_INT(y); + Value *ffy = builder.CreateUIToFP(fy, T_float64); + Value *uiffy = builder.CreateFPToUI(ffy, T_int64); return builder.CreateOr( - builder.CreateFCmpOLT(x, builder.CreateUIToFP(fy, T_float64)), + builder.CreateFCmpOLT(x, ffy), builder.CreateAnd( - builder.CreateFCmpOEQ(x, builder.CreateUIToFP(fy, T_float64)), - builder.CreateICmpUGT( - fy, builder.CreateFPToUI( - builder.CreateUIToFP(fy, T_float64), - T_int64 - ) - ) + // ensure x < 2.0^64 + builder.CreateFCmpOLT(x, ConstantFP::get(T_float64, + 1.8446744073709552e19)), + builder.CreateAnd(builder.CreateFCmpOEQ(x, ffy), + builder.CreateICmpUGT(fy, uiffy)) ) ); } HANDLE(lefsi64,2) { x = FP(x); fy = JL_INT(y); + Value *ffy = builder.CreateSIToFP(fy, T_float64); return builder.CreateOr( - builder.CreateFCmpOLT(x, builder.CreateSIToFP(fy, T_float64)), + builder.CreateFCmpOLT(x, ffy), builder.CreateAnd( - builder.CreateFCmpOEQ(x, builder.CreateSIToFP(fy, T_float64)), - builder.CreateICmpSGE( - fy, builder.CreateFPToSI( - builder.CreateSIToFP(fy, T_float64), - T_int64 - ) + builder.CreateFCmpOLT(x, ConstantFP::get(T_float64, + 9.223372036854776e18)), + builder.CreateAnd( + builder.CreateFCmpOEQ(x, ffy), + builder.CreateICmpSGE(fy, builder.CreateFPToSI(ffy,T_int64)) ) ) ); @@ -606,15 +666,15 @@ static Value *emit_intrinsic(intrinsic f, jl_value_t **args, size_t nargs, HANDLE(lefui64,2) { x = FP(x); fy = JL_INT(y); + Value *ffy = builder.CreateUIToFP(fy, T_float64); return builder.CreateOr( - builder.CreateFCmpOLT(x, builder.CreateUIToFP(fy, T_float64)), + builder.CreateFCmpOLT(x, ffy), builder.CreateAnd( - builder.CreateFCmpOEQ(x, builder.CreateUIToFP(fy, T_float64)), - builder.CreateICmpUGE( - fy, builder.CreateFPToUI( - builder.CreateUIToFP(fy, T_float64), - T_int64 - ) + builder.CreateFCmpOLT(x, ConstantFP::get(T_float64, + 1.8446744073709552e19)), + builder.CreateAnd( + builder.CreateFCmpOEQ(x, ffy), + builder.CreateICmpUGE(fy, builder.CreateFPToUI(ffy, T_int64)) ) ) ); @@ -622,66 +682,62 @@ static Value *emit_intrinsic(intrinsic f, jl_value_t **args, size_t nargs, HANDLE(ltsif64,2) { x = JL_INT(x); fy = FP(y); + Value *fx = builder.CreateSIToFP(x, T_float64); return builder.CreateOr( - builder.CreateFCmpOLT(builder.CreateSIToFP(x, T_float64), fy), - builder.CreateAnd( - builder.CreateFCmpOEQ(builder.CreateSIToFP(x, T_float64), fy), - builder.CreateICmpSLT( - x, builder.CreateFPToSI( - builder.CreateSIToFP(x, T_float64), - T_int64 - ) - ) - ) - ); + builder.CreateOr( + builder.CreateFCmpOGE(fy, ConstantFP::get(T_float64, + 9.223372036854776e18)), + builder.CreateFCmpOLT(fx, fy)), + builder.CreateAnd( + builder.CreateFCmpOEQ(fx, fy), + builder.CreateICmpSLT(x, builder.CreateFPToSI(fx, T_int64)) + ) + ); } HANDLE(ltuif64,2) { x = JL_INT(x); fy = FP(y); + Value *fx = builder.CreateUIToFP(x, T_float64); return builder.CreateOr( - builder.CreateFCmpOLT(builder.CreateUIToFP(x, T_float64), fy), - builder.CreateAnd( - builder.CreateFCmpOEQ(builder.CreateUIToFP(x, T_float64), fy), - builder.CreateICmpULT( - x, builder.CreateFPToUI( - builder.CreateUIToFP(x, T_float64), - T_int64 - ) - ) - ) - ); + builder.CreateOr( + builder.CreateFCmpOGE(fy, ConstantFP::get(T_float64, + 1.8446744073709552e19)), + builder.CreateFCmpOLT(fx, fy)), + builder.CreateAnd( + builder.CreateFCmpOEQ(fx, fy), + builder.CreateICmpULT(x, builder.CreateFPToUI(fx, T_int64)) + ) + ); } HANDLE(lesif64,2) { x = JL_INT(x); fy = FP(y); + Value *fx = builder.CreateSIToFP(x, T_float64); return builder.CreateOr( - builder.CreateFCmpOLT(builder.CreateSIToFP(x, T_float64), fy), - builder.CreateAnd( - builder.CreateFCmpOEQ(builder.CreateSIToFP(x, T_float64), fy), - builder.CreateICmpSLE( - x, builder.CreateFPToSI( - builder.CreateSIToFP(x, T_float64), - T_int64 - ) - ) - ) - ); + builder.CreateOr( + builder.CreateFCmpOGE(fy, ConstantFP::get(T_float64, + 9.223372036854776e18)), + builder.CreateFCmpOLT(fx, fy)), + builder.CreateAnd( + builder.CreateFCmpOEQ(fx, fy), + builder.CreateICmpSLE(x, builder.CreateFPToSI(fx, T_int64)) + ) + ); } HANDLE(leuif64,2) { x = JL_INT(x); fy = FP(y); + Value *fx = builder.CreateUIToFP(x, T_float64); return builder.CreateOr( - builder.CreateFCmpOLT(builder.CreateUIToFP(x, T_float64), fy), - builder.CreateAnd( - builder.CreateFCmpOEQ(builder.CreateUIToFP(x, T_float64), fy), - builder.CreateICmpULE( - x, builder.CreateFPToUI( - builder.CreateUIToFP(x, T_float64), - T_int64 - ) - ) - ) - ); + builder.CreateOr( + builder.CreateFCmpOGE(fy, ConstantFP::get(T_float64, + 1.8446744073709552e19)), + builder.CreateFCmpOLT(fx, fy)), + builder.CreateAnd( + builder.CreateFCmpOEQ(fx, fy), + builder.CreateICmpULE(x, builder.CreateFPToUI(fx, T_int64)) + ) + ); } HANDLE(fpiseq32,2) { @@ -811,16 +867,6 @@ static Value *emit_intrinsic(intrinsic f, jl_value_t **args, size_t nargs, } #endif - HANDLE(sext16,1) return builder.CreateSExt(JL_INT(x), T_int16); - HANDLE(zext16,1) return builder.CreateZExt(JL_INT(x), T_int16); - HANDLE(sext32,1) return builder.CreateSExt(JL_INT(x), T_int32); - HANDLE(zext32,1) return builder.CreateZExt(JL_INT(x), T_int32); - HANDLE(sext64,1) return builder.CreateSExt(JL_INT(x), T_int64); - HANDLE(zext64,1) return builder.CreateZExt(JL_INT(x), T_int64); - HANDLE(trunc8,1) return builder.CreateTrunc(JL_INT(x), T_int8); - HANDLE(trunc16,1) return builder.CreateTrunc(JL_INT(x), T_int16); - HANDLE(trunc32,1) return builder.CreateTrunc(JL_INT(x), T_int32); - HANDLE(trunc64,1) return builder.CreateTrunc(JL_INT(x), T_int64); HANDLE(fptoui32,1) return builder.CreateFPToUI(FP(x), T_int32); HANDLE(fptosi32,1) return builder.CreateFPToSI(FP(x), T_int32); HANDLE(fptoui64,1) return builder.CreateFPToUI(FP(x), T_int64); @@ -902,39 +948,13 @@ static Value *emit_intrinsic(intrinsic f, jl_value_t **args, size_t nargs, return builder.CreateFPExt(builder.CreateLoad(jlfloat32temp_var, true), T_float64); - HANDLE(checked_fptosi32,1) { - x = FP(x); - Value *v = builder.CreateFPToSI(x, T_int32); - raise_exception_unless - (builder.CreateFCmpOEQ(builder.CreateFPExt(x, T_float64), - builder.CreateSIToFP(v, T_float64)), - jlinexacterr_var, ctx); - return v; - } - HANDLE(checked_fptoui32,1) { - x = FP(x); - Value *v = builder.CreateFPToUI(x, T_int32); - raise_exception_unless - (builder.CreateFCmpOEQ(builder.CreateFPExt(x, T_float64), - builder.CreateUIToFP(v, T_float64)), - jlinexacterr_var, ctx); - return v; - } - HANDLE(checked_fptosi64,1) { - x = FP(x); - Value *v = builder.CreateFPToSI(x, T_int64); - if (x->getType() == T_float32) - x = builder.CreateFPExt(x, T_float64); - raise_exception_unless(emit_eqfsi64(x, v), jlinexacterr_var, ctx); - return v; - } - HANDLE(checked_fptoui64,1) { - x = FP(x); - Value *v = builder.CreateFPToUI(x, T_int64); - if (x->getType() == T_float32) - x = builder.CreateFPExt(x, T_float64); - raise_exception_unless(emit_eqfui64(x, v), jlinexacterr_var, ctx); - return v; + HANDLE(nan_dom_err,2) { + // nan_dom_err(f, x) throw DomainError if isnan(f)&&!isnan(x) + Value *f = FP(x); x = FP(y); + raise_exception_unless(builder.CreateOr(builder.CreateFCmpORD(f,f), + builder.CreateFCmpUNO(x,x)), + jldomerr_var, ctx); + return f; } HANDLE(abs_float,1) @@ -985,6 +1005,9 @@ static Value *emit_intrinsic(intrinsic f, jl_value_t **args, size_t nargs, Value *tmp = builder.CreateAShr(fy, ConstantInt::get(intt,((IntegerType*)intt)->getBitWidth()-1)); return builder.CreateXor(builder.CreateAdd(x,tmp),tmp); } + HANDLE(jl_alloca,1) { + return builder.CreateAlloca(IntegerType::get(jl_LLVMContext, 8),JL_INT(x)); + } default: assert(false); } @@ -1058,10 +1081,7 @@ extern "C" void jl_init_intrinsic_functions(void) ADD_I(and_int); ADD_I(or_int); ADD_I(xor_int); ADD_I(not_int); ADD_I(shl_int); ADD_I(lshr_int); ADD_I(ashr_int); ADD_I(bswap_int); ADD_I(ctpop_int); ADD_I(ctlz_int); ADD_I(cttz_int); - ADD_I(sext16); ADD_I(zext16); ADD_I(sext32); ADD_I(zext32); - ADD_I(sext64); ADD_I(zext64); ADD_I(sext_int); ADD_I(zext_int); - ADD_I(trunc8); ADD_I(trunc16); ADD_I(trunc32); ADD_I(trunc64); - ADD_I(trunc_int); + ADD_I(sext_int); ADD_I(zext_int); ADD_I(trunc_int); ADD_I(fptoui32); ADD_I(fptosi32); ADD_I(fptoui64); ADD_I(fptosi64); ADD_I(fpsiround32); ADD_I(fpsiround64); ADD_I(fpuiround32); ADD_I(fpuiround64); @@ -1069,11 +1089,12 @@ extern "C" void jl_init_intrinsic_functions(void) ADD_I(fptrunc32); ADD_I(fpext64); ADD_I(abs_float); ADD_I(copysign_float); ADD_I(flipsign_int); - ADD_I(pointerref); ADD_I(pointerset); + ADD_I(pointerref); ADD_I(pointerset); ADD_I(pointertoref); ADD_I(checked_sadd); ADD_I(checked_uadd); ADD_I(checked_ssub); ADD_I(checked_usub); ADD_I(checked_smul); ADD_I(checked_umul); - ADD_I(checked_fptosi32); ADD_I(checked_fptoui32); - ADD_I(checked_fptosi64); ADD_I(checked_fptoui64); + ADD_I(checked_fptosi); ADD_I(checked_fptoui); + ADD_I(nan_dom_err); ADD_I(ccall); + ADD_I(jl_alloca); } diff --git a/src/jl_uv.c b/src/jl_uv.c new file mode 100644 index 0000000000000..076a0579c3163 --- /dev/null +++ b/src/jl_uv.c @@ -0,0 +1,706 @@ +#define WINVER _WIN32_WINNT +#define _WIN32_WINDOWS _WIN32_WINNT +#include +#include +#include +#include +#include +#include + +#ifdef __WIN32__ +#include +#include +#include +#else +#include "errno.h" +#include +#endif + +#include "julia.h" +#include "support/ios.h" +#include "uv.h" + +#ifdef __cplusplus +#include +extern "C" { +#endif + + +/** libuv callbacks */ +//These callbacks are implemented in stream.jl +#define JL_CB_TYPES(XX) \ + XX(close) \ + XX(return_spawn) \ + XX(readcb) \ + XX(alloc_buf) \ + XX(connectcb) \ + XX(connectioncb) \ + XX(asynccb) \ + XX(getaddrinfo) +//TODO add UDP and other missing callbacks + +#define JULIA_HOOK_(m,hook) ((jl_function_t*)jl_get_global(m, jl_symbol("_uv_hook_" #hook))) +#define JULIA_HOOK(hook) jl_uvhook_##hook +#define XX(hook) static jl_function_t *JULIA_HOOK(hook) = 0; +JL_CB_TYPES(XX) +#undef XX +DLLEXPORT void jl_get_uv_hooks() +{ + if (JULIA_HOOK(close)) return; // only do this once +#define XX(hook) JULIA_HOOK(hook) = JULIA_HOOK_(jl_base_module, hook); + JL_CB_TYPES(XX) +#undef XX +} +#undef JL_CB_TYPES + +int base_module_conflict = 0; //set to 1 if Base is getting redefined since it means there are two place to try the callbacks +// warning: this is defined without the standard do {...} while (0) wrapper, since I wanted ret to escape +// warning: during bootstrapping, callbacks will be called twice if a MethodError occured at ANY time during callback call +#define JULIA_CB(hook,args...) \ + jl_value_t *ret; \ + if (!base_module_conflict) { \ + ret = jl_callback_call(JULIA_HOOK(hook),args); \ + } else { \ + JL_TRY { \ + ret = jl_callback_call(JULIA_HOOK(hook),args); \ + /* jl_puts(#hook " original succeeded\n",jl_uv_stderr); */ \ + } \ + JL_CATCH { \ + if (jl_typeof(jl_exception_in_transit) == (jl_value_t*)jl_methoderror_type) { \ + /* jl_puts("\n" #hook " being retried with new Base bindings --> ",jl_uv_stderr); */ \ + jl_function_t *cb_func = JULIA_HOOK_((jl_module_t*)jl_get_global(jl_main_module, jl_symbol("Base")), hook); \ + ret = jl_callback_call(cb_func,args); \ + /* jl_puts(#hook " succeeded\n",jl_uv_stderr); */ \ + } else { \ + jl_rethrow(); \ + } \ + } \ + } + +jl_value_t *jl_callback_call(jl_function_t *f,jl_value_t *val,int count,...) +{ + if (val != 0) + count += 1; + jl_value_t **argv; + JL_GC_PUSHARGS(argv,count); + memset(argv, 0, count*sizeof(jl_value_t*)); + jl_value_t *v; + va_list argp; + va_start(argp,count); + int i; + argv[0]=val; + for(i=((val==0)?0:1); idata,0); (void)ret; + //TODO: maybe notify Julia handle to close itself + free(handle); +} + +void jl_return_spawn(uv_process_t *p, int exit_status, int term_signal) +{ + JULIA_CB(return_spawn,p->data,2,CB_INT32,exit_status,CB_INT32,term_signal); + (void)ret; +} + +void jl_readcb(uv_stream_t *handle, ssize_t nread, uv_buf_t buf) +{ + JULIA_CB(readcb,handle->data,3,CB_INT,nread,CB_PTR,(buf.base),CB_INT32,buf.len); + (void)ret; +} + +uv_buf_t jl_alloc_buf(uv_handle_t *handle, size_t suggested_size) +{ + uv_buf_t buf; + JULIA_CB(alloc_buf,handle->data,1,CB_INT32,suggested_size); + if (!jl_is_tuple(ret) || !jl_is_pointer(jl_t0(ret)) || !jl_is_int32(jl_t1(ret))) { + jl_error("jl_alloc_buf: Julia function returned invalid value for buffer allocation callback"); + } + buf.base = jl_unbox_voidpointer(jl_t0(ret)); + buf.len = jl_unbox_int32(jl_t1(ret)); + return buf; +} + +void jl_connectcb(uv_connect_t *connect, int status) +{ + JULIA_CB(connectcb,connect->handle->data,1,CB_INT32,status); + (void)ret; +} + +void jl_connectioncb(uv_stream_t *stream, int status) +{ + JULIA_CB(connectioncb,stream->data,1,CB_INT32,status); + (void)ret; +} + +void jl_getaddrinfocb(uv_getaddrinfo_t *req,int status, struct addrinfo *addr) +{ + JULIA_CB(getaddrinfo,req->data,2,CB_PTR,addr,CB_INT32,status); + (void)ret; +} + +void jl_asynccb(uv_handle_t *handle, int status) +{ + JULIA_CB(asynccb,handle->data,1,CB_INT32,status); + (void)ret; +} + +/** libuv constructors */ +DLLEXPORT uv_async_t *jl_make_async(uv_loop_t *loop,jl_value_t *julia_struct) +{ + if (!loop) + return 0; + uv_async_t *async = malloc(sizeof(uv_async_t)); + if (uv_async_init(loop,async,(uv_async_cb)&jl_asynccb)) { + free(async); + return 0; + } + async->data=julia_struct; + return async; +} + +DLLEXPORT uv_timer_t *jl_make_timer(uv_loop_t *loop, jl_value_t *julia_struct) +{ + if (!loop) + return 0; + uv_timer_t *timer = malloc(sizeof(uv_timer_t)); + if (uv_timer_init(loop,timer)) { + free(timer); + return 0; + } + timer->data=julia_struct; + return timer; +} + +DLLEXPORT uv_idle_t *jl_idle_init(uv_loop_t *loop, jl_value_t *julia_struct) +{ + if (!loop) + return 0; + uv_idle_t *idle = malloc(sizeof(uv_idle_t)); + if (uv_idle_init(loop,idle)) { + free(idle); + return 0; + } + idle->data = julia_struct; + return idle; +} + +DLLEXPORT uv_tcp_t *jl_make_tcp(uv_loop_t* loop, jl_value_t *julia_struct) +{ + if (!loop) + return 0; + uv_tcp_t *tcp = malloc(sizeof(uv_tcp_t)); + if (uv_tcp_init(loop,tcp)) { + free(tcp); + return 0; + } + tcp->data=julia_struct; + return tcp; +} + +/** This file contains wrappers for most of libuv's stream functionailty. Once we can allocate structs in Julia, this file will be removed */ + +DLLEXPORT int jl_run_once(uv_loop_t *loop) +{ + loop->stop_flag = 0; + if (loop) return uv_run(loop,UV_RUN_ONCE); + else return 0; +} + +DLLEXPORT void jl_run_event_loop(uv_loop_t *loop) +{ + loop->stop_flag = 0; + if (loop) uv_run(loop,UV_RUN_DEFAULT); +} + +DLLEXPORT int jl_process_events(uv_loop_t *loop) +{ + loop->stop_flag = 0; + if (loop) return uv_run(loop,UV_RUN_NOWAIT); + else return 0; +} + +DLLEXPORT uv_pipe_t *jl_init_pipe(uv_pipe_t *pipe, int writable, int julia_only, jl_value_t *julia_struct) +{ + int flags; + flags = writable ? UV_PIPE_WRITEABLE : UV_PIPE_READABLE; + if (!julia_only) + flags |= UV_PIPE_SPAWN_SAFE; + uv_pipe_init(jl_io_loop, pipe, flags); + pipe->data = julia_struct;//will be initilized on io + return pipe; +} + +DLLEXPORT void jl_close_uv(uv_handle_t *handle) +{ + if (!handle) + return; + if (handle->type==UV_TTY) + uv_tty_set_mode((uv_tty_t*)handle,0); + uv_close(handle,&closeHandle); +} + +DLLEXPORT void jl_uv_associate_julia_struct(uv_handle_t *handle, jl_value_t *data) +{ + handle->data = data; +} + +DLLEXPORT int16_t jl_start_reading(uv_stream_t *handle) +{ + if (!handle) + return -2; + return uv_read_start(handle,&jl_alloc_buf,&jl_readcb); +} + +DLLEXPORT int jl_listen(uv_stream_t* stream, int backlog) +{ + return uv_listen(stream,backlog,&jl_connectioncb); +} + +#ifdef __APPLE__ +#include +#else +extern char **environ; +#endif + +DLLEXPORT int jl_spawn(char *name, char **argv, uv_loop_t *loop, + uv_process_t *proc, jl_value_t *julia_struct, + uv_handle_type stdin_type,uv_pipe_t *stdin_pipe, + uv_handle_type stdout_type,uv_pipe_t *stdout_pipe, + uv_handle_type stderr_type,uv_pipe_t *stderr_pipe) +{ +#ifdef __APPLE__ + char **environ = *_NSGetEnviron(); +#endif + uv_process_options_t opts; + uv_stdio_container_t stdio[3]; + int error; + opts.file = name; +#ifndef __WIN32__ + opts.env = environ; +#else + opts.env = NULL; +#endif + opts.cwd = NULL; + opts.args = argv; + opts.flags = 0; + opts.stdio = stdio; + opts.stdio_count = 3; + stdio[0].type = stdin_type; + stdio[0].data.stream = (uv_stream_t*)(stdin_pipe); + stdio[1].type = stdout_type; + stdio[1].data.stream = (uv_stream_t*)(stdout_pipe); + stdio[2].type = stderr_type; + stdio[2].data.stream = (uv_stream_t*)(stderr_pipe); + //opts.detached = 0; #This has been removed upstream to be uncommented once it is possible again + opts.exit_cb = &jl_return_spawn; + error = uv_spawn(loop,proc,opts); + proc->data = julia_struct; + return error; +} + +#ifdef __WIN32__ +#include +DLLEXPORT struct tm* localtime_r(const time_t *t, struct tm *tm) +{ + auto struct tm *tmp = localtime(t); //localtime is reentrant on windows + if (tmp) + *tm = *tmp; + return tmp; +} +#endif + +DLLEXPORT uv_loop_t *jl_new_event_loop() +{ + return uv_loop_new(); +} + +DLLEXPORT uv_loop_t *jl_global_event_loop() +{ + return jl_io_loop; +} + +DLLEXPORT void jl_async_send(uv_async_t *handle) +{ + if (handle) uv_async_send(handle); +} + +DLLEXPORT int jl_idle_start(uv_idle_t *idle) +{ + if (!idle||(idle)->data) + jl_error("jl_idle_start: Invalid handle"); + return uv_idle_start(idle,(uv_idle_cb)&jl_asynccb); +} + +//units are in ms +DLLEXPORT int jl_timer_start(uv_timer_t* timer, int64_t timeout, int64_t repeat) +{ + return uv_timer_start(timer,(uv_timer_cb)&jl_asynccb,timeout,repeat); +} + +DLLEXPORT int jl_timer_stop(uv_timer_t* timer) +{ + return uv_timer_stop(timer); +} + +DLLEXPORT int jl_puts(char *str, uv_stream_t *stream) +{ + return jl_write(stream,str,strlen(str)); +} + +DLLEXPORT int jl_pututf8(uv_stream_t *s, uint32_t wchar ) +{ + char buf[8]; + if (wchar < 0x80) + return jl_putc((int)wchar, s); + size_t n = u8_toutf8(buf, 8, &wchar, 1); + return jl_write(s, buf, n); +} + +static char chars[] = { + 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 +}; + +static void jl_free_buffer(uv_write_t* req, int status) +{ + if (req->data) { + free(req->data); + } + free(req); +} + +DLLEXPORT int jl_putc(unsigned char c, uv_stream_t *stream) +{ + if (stream!=0) { + if (stream->typedata=0; + uv_buf_t buf[] = {{.base = chars+c,.len=1}}; + int err = uv_write(uvw,stream,buf,1,&jl_free_buffer); + JL_SIGATOMIC_END(); + return err ? 0 : 1; + } + else { + ios_t *handle = (ios_t*)stream; + return ios_putc(c,handle); + } + } + return 0; +} + +DLLEXPORT size_t jl_write(uv_stream_t *stream, const char *str, size_t n) +{ + //TODO: BAD!! Needed because Julia can't yet detect null stdio + if (stream == 0) + return 0; + if (stream->typedata = data; + int err = uv_write(uvw,stream,buf,1,&jl_free_buffer); + JL_SIGATOMIC_END(); + return err ? 0 : n; + } + else { + ios_t *handle = (ios_t*)stream; + return ios_write(handle,str,n); + } +} + +extern int vasprintf(char **str, const char *fmt, va_list ap); + +int jl_vprintf(uv_stream_t *s, const char *format, va_list args) +{ + char *str=NULL; + int c; + va_list al; + va_copy(al, args); + + c = vasprintf(&str, format, al); + + if (c >= 0) { + jl_write(s, str, c); + LLT_FREE(str); + } + va_end(al); + return c; +} + +int jl_printf(uv_stream_t *s, const char *format, ...) +{ + va_list args; + int c; + + va_start(args, format); + c = jl_vprintf(s, format, args); + va_end(args); + return c; +} + +char *jl_bufptr(ios_t *s) +{ + return s->buf; +} + +DLLEXPORT size_t jl_sizeof_uv_stream_t() +{ + return sizeof(uv_stream_t); +} + +DLLEXPORT size_t jl_sizeof_uv_pipe_t() +{ + return sizeof(uv_pipe_t); +} + +DLLEXPORT size_t jl_sizeof_uv_process_t() +{ + return sizeof(uv_process_t); +} + +DLLEXPORT void uv_atexit_hook(); +DLLEXPORT void jl_exit(int exitcode) +{ + /*if (jl_io_loop) { + jl_process_events(&jl_io_loop); + }*/ + uv_tty_reset_mode(); + uv_atexit_hook(); + exit(exitcode); +} + +DLLEXPORT int jl_cwd(char *buffer, size_t size) +{ + return (uv_cwd(buffer,size)).code; +} + +DLLEXPORT int jl_getpid() +{ +#ifdef __WIN32__ + return GetCurrentProcessId(); +#else + return getpid(); +#endif +} + +//NOTE: This function expects port/host to be in network byte-order (Big Endian) +DLLEXPORT int jl_tcp_bind(uv_tcp_t* handle, uint16_t port, uint32_t host) +{ + struct sockaddr_in addr; + memset(&addr, 0, sizeof(struct sockaddr_in)); + addr.sin_port = port; + addr.sin_addr.s_addr = host; + addr.sin_family = AF_INET; + int err = uv_tcp_bind(handle,addr); + return err; +} + +DLLEXPORT void getlocalip(char *buf, size_t len) +{ + uv_err_t err; + uv_interface_address_t * ifAddrStruct=NULL; + struct sockaddr_in ifa; + void * tmpAddrPtr=NULL; + int count=0; + + err = uv_interface_addresses(&ifAddrStruct,&count); + if (err.code!=0) + if (ifAddrStruct!=NULL) + uv_free_interface_addresses(ifAddrStruct,count); + + for (int i = 0; i < count; i++) { + ifa = (ifAddrStruct+i)->address.address4; + if (ifa.sin_family==AF_INET) { // check it is IP4 + // is a valid IP4 Address +#ifndef __WIN32__ + tmpAddrPtr=&(ifa.sin_addr); + inet_ntop(AF_INET, tmpAddrPtr, buf, len); //Not available on WinXP +#else + strncpy(buf,inet_ntoa(ifa.sin_addr),len-1); + buf[len]=0; +#endif + + if (strcmp(buf,"127.0.0.1")) //TODO: use (ifa.internal == false) + break; + //printf("%s IP Address %s\n", ifa->ifa_name, addressBuffer); + } + /* + else if (ifa->ifa_addr && ifa->ifa_addr->sa_family==AF_INET6) { // check it is IP6 + // is a valid IP6 Address + tmpAddrPtr=&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr; + char addressBuffer[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN); + printf("%s IP Address %s\n", ifa->ifa_name, addressBuffer); + } + */ + } + if (ifAddrStruct!=NULL) uv_free_interface_addresses(ifAddrStruct,count); +} + +DLLEXPORT int jl_getaddrinfo(uv_loop_t *loop, const char *host, const char *service, jl_function_t *cb) +{ + uv_getaddrinfo_t *req = malloc(sizeof(uv_getaddrinfo_t)); + struct addrinfo hints; + + memset (&hints, 0, sizeof (hints)); + hints.ai_family = AF_INET; //ipv4 for now + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags |= AI_CANONNAME; + + req->data = cb; + + return uv_getaddrinfo(loop,req,jl_getaddrinfocb,host,service,&hints); +} + +DLLEXPORT struct sockaddr *jl_sockaddr_from_addrinfo(struct addrinfo *addrinfo) +{ + struct sockaddr *addr = malloc(sizeof(struct sockaddr)); + memcpy(addr,addrinfo->ai_addr,sizeof(struct sockaddr)); + return addr; +} + +DLLEXPORT int jl_sockaddr_is_ip4(struct sockaddr *addr) +{ + return (addr->sa_family==AF_INET); +} + +DLLEXPORT unsigned int jl_sockaddr_host4(struct sockaddr *addr) +{ + return ((struct sockaddr_in*)addr)->sin_addr.s_addr; +} + + +DLLEXPORT void jl_sockaddr_set_port(struct sockaddr *addr,uint16_t port) +{ + if (addr->sa_family==AF_INET) { + ((struct sockaddr_in*)addr)->sin_port=port; + } + else { + ((struct sockaddr_in6*)addr)->sin6_port=port; + } +} + +DLLEXPORT int jl_tcp4_connect(uv_tcp_t *handle,uint32_t host, uint16_t port) +{ + struct sockaddr_in addr; + uv_connect_t *req = malloc(sizeof(uv_connect_t)); + memset(&addr, 0, sizeof(struct sockaddr_in)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = host; + addr.sin_port = port; + return uv_tcp_connect(req,handle,addr,&jl_connectcb); +} + +DLLEXPORT int jl_connect_raw(uv_tcp_t *handle,struct sockaddr *addr) +{ + uv_connect_t *req = malloc(sizeof(uv_connect_t)); + if (addr->sa_family==AF_INET) { + return uv_tcp_connect(req,handle,*((struct sockaddr_in*)addr),&jl_connectcb); + } + else { + return uv_tcp_connect6(req,handle,*((struct sockaddr_in6*)addr),&jl_connectcb); + } + free(req); + return -2; //error! Only IPv4 and IPv6 are implemented atm +} + +DLLEXPORT int jl_last_errno(uv_loop_t *loop) +{ + return (uv_last_error(loop)).code; +} + +DLLEXPORT int jl_last_system_errno(uv_loop_t *loop) +{ + return (uv_last_error(loop)).sys_errno_; +} + +DLLEXPORT const char *jl_uv_strerror(int a, int b) +{ + uv_err_t err = {a,b}; + return uv_strerror(err); +} + +DLLEXPORT const char *jl_uv_err_name(int a, int b) +{ + uv_err_t err = {a,b}; + return uv_err_name(err); +} + +DLLEXPORT char *jl_ios_buf_base(ios_t *ios) +{ + return ios->buf; +} + +DLLEXPORT uv_lib_t *jl_wrap_raw_dl_handle(void *handle) +{ + uv_lib_t *lib = malloc(sizeof(uv_lib_t)); + lib->handle=handle; + lib->errmsg=NULL; + return lib; +} + +DLLEXPORT long SC_CLK_TCK() { +#ifndef __WIN32__ + return sysconf(_SC_CLK_TCK); +#else + return 0; +#endif +} + +#ifdef __cplusplus +} +#endif diff --git a/src/jlapi.c b/src/jlapi.c new file mode 100644 index 0000000000000..d9ae4bb542388 --- /dev/null +++ b/src/jlapi.c @@ -0,0 +1,180 @@ +/* + jlapi.c + miscellaneous functions for users of libjulia.so, to handle initialization + and the style of use where julia is not in control most of the time. +*/ +#include +#include +#include +#include +#include +#include "julia.h" +extern char *julia_home; + +DLLEXPORT char *jl_locate_sysimg(char *jlhome) +{ + if (jlhome == NULL) { + char *julia_path = (char*)malloc(512); + size_t path_size = 512; + uv_exepath(julia_path, &path_size); + julia_home = strdup(dirname(julia_path)); + free(julia_path); + } + else { + julia_home = jlhome; + } + char path[512]; + snprintf(path, sizeof(path), "%s%s%s", + julia_home, PATHSEPSTRING, JL_SYSTEM_IMAGE_PATH); + return strdup(path); +} + +DLLEXPORT void *jl_eval_string(char *str); + +// argument is the usr/lib directory where libjulia is, or NULL to guess. +// if that doesn't work, try the full path to the "lib" directory that +// contains lib/julia/sys.ji +DLLEXPORT void jl_init(char *julia_home_dir) +{ + libsupport_init(); + char *image_file = jl_locate_sysimg(julia_home_dir); + julia_init(image_file); + jl_set_const(jl_core_module, jl_symbol("JULIA_HOME"), + jl_cstr_to_string(julia_home)); + jl_module_export(jl_core_module, jl_symbol("JULIA_HOME")); + jl_eval_string("Base.reinit_stdio()"); + jl_eval_string("Base.librandom_init()"); + jl_eval_string("Base.init_sched()"); + jl_eval_string("Base.init_head_sched()"); + jl_eval_string("Base.init_load_path()"); +} + +#ifdef COPY_STACKS +void jl_switch_stack(jl_task_t *t, jl_jmp_buf *where); +extern jl_jmp_buf * volatile jl_jmp_target; +#endif + +DLLEXPORT void *jl_eval_string(char *str) +{ +#ifdef COPY_STACKS + jl_root_task->stackbase = (char*)&str; + if (jl_setjmp(jl_root_task->base_ctx, 1)) { + jl_switch_stack(jl_current_task, jl_jmp_target); + } +#endif + jl_value_t *r; + JL_TRY { + jl_value_t *ast = jl_parse_input_line(str); + JL_GC_PUSH(&ast); + r = jl_toplevel_eval(ast); + JL_GC_POP(); + } + JL_CATCH { + //jl_show(jl_stderr_obj(), jl_exception_in_transit); + r = NULL; + } + return r; +} + +DLLEXPORT jl_value_t *jl_exception_occurred(void) +{ + return jl_is_null(jl_exception_in_transit) ? NULL : + jl_exception_in_transit; +} + +DLLEXPORT void jl_exception_clear(void) +{ + jl_exception_in_transit = (jl_value_t*)jl_null; +} + +// get the name of a type as a string +DLLEXPORT const char *jl_typename_str(jl_value_t *v) +{ + if (jl_is_tuple(v)) + return "Tuple"; + return ((jl_datatype_t*)v)->name->name->name; +} + +// get the name of typeof(v) as a string +DLLEXPORT const char *jl_typeof_str(jl_value_t *v) +{ + return jl_typename_str((jl_value_t*)jl_typeof(v)); +} + +DLLEXPORT void *jl_array_eltype(jl_value_t *a) +{ + return jl_tparam0(jl_typeof(a)); +} + +DLLEXPORT int jl_array_rank(jl_value_t *a) +{ + return jl_array_ndims(a); +} + +DLLEXPORT size_t jl_array_size(jl_value_t *a, int d) +{ + return jl_array_dim(a, d); +} + +DLLEXPORT void *jl_array_ptr(jl_array_t *a); + +DLLEXPORT const char *jl_bytestring_ptr(jl_value_t *s) +{ + return jl_string_data(s); +} + +DLLEXPORT jl_value_t *jl_call1(jl_function_t *f, jl_value_t *a) +{ + jl_value_t *v; + JL_TRY { + JL_GC_PUSH(&f,&a); + v = jl_apply(f, &a, 1); + JL_GC_POP(); + } + JL_CATCH { + v = NULL; + } + return v; +} + +DLLEXPORT jl_value_t *jl_call2(jl_function_t *f, jl_value_t *a, jl_value_t *b) +{ + jl_value_t *v; + JL_TRY { + JL_GC_PUSH(&f,&a,&b); + jl_value_t *args[2] = {a,b}; + v = jl_apply(f, args, 2); + JL_GC_POP(); + } + JL_CATCH { + v = NULL; + } + return v; +} + +JL_CALLABLE(jl_f_get_field); +DLLEXPORT jl_value_t *jl_get_field(jl_value_t *o, char *fld) +{ + jl_value_t *v; + JL_TRY { + jl_value_t *s = (jl_value_t*)jl_symbol(fld); + jl_value_t *args[2] = {o, s}; + v = jl_f_get_field(NULL, args, 2); + } + JL_CATCH { + v = NULL; + } + return v; +} + +DLLEXPORT void jl_sigatomic_begin(void) +{ + JL_SIGATOMIC_BEGIN(); +} + +DLLEXPORT void jl_sigatomic_end(void) +{ + if (jl_defer_signal == 0) + jl_error("sigatomic_end called in non-sigatomic region"); + JL_SIGATOMIC_END(); +} diff --git a/src/jlfrontend.scm b/src/jlfrontend.scm index aac1abe4d391a..f7362c4b89771 100644 --- a/src/jlfrontend.scm +++ b/src/jlfrontend.scm @@ -18,11 +18,11 @@ `(continue ,msg) e)) (begin - (newline) - (display "unexpected error: ") - (prn e) - (print-stack-trace (stacktrace)) - #f))) + ;;(newline) + ;;(display "unexpected error: ") + ;;(prn e) + ;;(print-stack-trace (stacktrace)) + '(error "malformed expression")))) thk)) ;; assigned variables except those marked local or inside inner functions @@ -31,6 +31,10 @@ ((quoted? e) '()) (else (case (car e) ((=) (list (decl-var (cadr e)))) + ((method) (let ((n (method-expr-name e))) + (if (symbol? n) + (list n) + '()))) ((lambda) '()) ((local local!) '()) ((break-block) (find-possible-globals (caddr e))) @@ -93,7 +97,8 @@ (define (expand-toplevel-expr- e) (let ((ex (expand-toplevel-expr-- e))) - (cond ((simple-assignment? ex) (cadr ex)) + (cond ((contains (lambda (x) (equal? x '(top ccall))) ex) ex) + ((simple-assignment? ex) (cadr ex)) ((and (length= ex 2) (eq? (car ex) 'body) (not (lambda-ex? (cadadr ex)))) ;; (body (return x)) => x @@ -106,7 +111,10 @@ (define (expand-toplevel-expr e) (if (and (pair? e) (eq? (car e) 'toplevel)) - `(toplevel ,@(map expand-toplevel-expr (cdr e))) + ;;`(toplevel ,@(map expand-toplevel-expr (cdr e))) + ;; delay expansion so defined global variables take effect for later + ;; toplevel expressions. + e (let ((last *in-expand*)) (if (not last) (begin (reset-gensyms) @@ -128,13 +136,24 @@ (define (jl-parse-string s) (parser-wrap (lambda () - (let* ((inp (make-token-stream (open-input-string s))) - (expr (julia-parse inp))) - (expand-toplevel-expr expr))))) + (let ((inp (make-token-stream (open-input-string s)))) + ;; parse all exprs into a (toplevel ...) form + (let loop ((exprs '())) + ;; delay expansion so macros run in the Task executing + ;; the input, not the task parsing it (issue #2378) + ;; used to be (expand-toplevel-expr expr) + (let ((expr (julia-parse inp))) + (if (eof-object? expr) + (cond ((null? exprs) expr) + ((length= exprs 1) (car exprs)) + (else (cons 'toplevel (reverse! exprs)))) + (if (and (pair? expr) (eq? (car expr) 'toplevel)) + (loop (nreconc (cdr expr) exprs)) + (loop (cons expr exprs)))))))))) ;; parse file-in-a-string -(define (jl-parse-string-stream str) - (jl-parser-set-stream "string" (open-input-string str))) +(define (jl-parse-string-stream str filename) + (jl-parser-set-stream filename (open-input-string str))) (define (jl-parse-file s) (jl-parser-set-stream s (open-input-file s))) @@ -161,7 +180,7 @@ (let ((e (parser-wrap (lambda () (julia-parse current-token-stream))))) (if (eof-object? e) - #f + e (cons (+ (input-port-line (ts:port current-token-stream)) (if (eqv? (peek-token current-token-stream) #\newline) -1 0)) diff --git a/src/jltypes.c b/src/jltypes.c index eda9ae7b028eb..6f181453837ca 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -15,44 +15,41 @@ #include "jltypes_internal.h" #include "builtin_proto.h" -jl_tag_type_t *jl_any_type; -jl_tag_type_t *jl_type_type; -jl_struct_type_t *jl_typename_type; -jl_struct_type_t *jl_sym_type; -jl_struct_type_t *jl_symbol_type; +jl_datatype_t *jl_any_type; +jl_datatype_t *jl_type_type; +jl_datatype_t *jl_typename_type; +jl_datatype_t *jl_sym_type; +jl_datatype_t *jl_symbol_type; jl_tuple_t *jl_tuple_type; -jl_tag_type_t *jl_ntuple_type; +jl_value_t *jl_tupletype_type; +jl_datatype_t *jl_ntuple_type; jl_typename_t *jl_ntuple_typename; -jl_struct_type_t *jl_tvar_type; +jl_datatype_t *jl_tvar_type; +jl_datatype_t *jl_uniontype_type; +jl_datatype_t *jl_datatype_type; -jl_struct_type_t *jl_union_kind; -jl_struct_type_t *jl_tag_kind; -jl_struct_type_t *jl_tag_type_type; -jl_struct_type_t *jl_struct_kind; -jl_struct_type_t *jl_bits_kind; - -jl_type_t *jl_bottom_type; +jl_value_t *jl_bottom_type; jl_value_t *jl_top_type; -jl_tag_type_t *jl_seq_type; -jl_tag_type_t *jl_abstractarray_type; - -jl_bits_type_t *jl_bool_type; -jl_bits_type_t *jl_char_type; -jl_bits_type_t *jl_int8_type; -jl_bits_type_t *jl_uint8_type; -jl_bits_type_t *jl_int16_type; -jl_bits_type_t *jl_uint16_type; -jl_bits_type_t *jl_int32_type; -jl_bits_type_t *jl_uint32_type; -jl_bits_type_t *jl_int64_type; -jl_bits_type_t *jl_uint64_type; -jl_bits_type_t *jl_float32_type; -jl_bits_type_t *jl_float64_type; +jl_datatype_t *jl_vararg_type; +jl_datatype_t *jl_abstractarray_type; + +jl_datatype_t *jl_bool_type; +jl_datatype_t *jl_char_type; +jl_datatype_t *jl_int8_type; +jl_datatype_t *jl_uint8_type; +jl_datatype_t *jl_int16_type; +jl_datatype_t *jl_uint16_type; +jl_datatype_t *jl_int32_type; +jl_datatype_t *jl_uint32_type; +jl_datatype_t *jl_int64_type; +jl_datatype_t *jl_uint64_type; +jl_datatype_t *jl_float32_type; +jl_datatype_t *jl_float64_type; jl_tuple_t *jl_null; jl_value_t *jl_nothing; -void jl_add_constructors(jl_struct_type_t *t); +void jl_add_constructors(jl_datatype_t *t); // --- type properties and predicates --- @@ -82,10 +79,10 @@ int jl_has_typevars_(jl_value_t *v, int incl_wildcard) if (jl_is_typector(v)) return incl_wildcard; jl_tuple_t *t; - if (jl_is_union_type(v)) + if (jl_is_uniontype(v)) t = ((jl_uniontype_t*)v)->types; - else if (jl_is_some_tag_type(v)) - t = ((jl_tag_type_t*)v)->parameters; + else if (jl_is_datatype(v)) + t = ((jl_datatype_t*)v)->parameters; else if (jl_is_tuple(v)) t = (jl_tuple_t*)v; else @@ -111,8 +108,14 @@ int jl_has_typevars(jl_value_t *v) DLLEXPORT int jl_is_leaf_type(jl_value_t *v) { - if (jl_is_struct_type(v) || jl_is_bits_type(v)) { - jl_tuple_t *t = ((jl_tag_type_t*)v)->parameters; + if (jl_is_datatype(v)) { + if (((jl_datatype_t*)v)->abstract) { + if (jl_is_type_type(v)) { + return !jl_is_typevar(jl_tparam0(v)); + } + return 0; + } + jl_tuple_t *t = ((jl_datatype_t*)v)->parameters; for(int i=0; i < jl_tuple_len(t); i++) { if (jl_is_typevar(jl_tupleref(t,i))) return 0; @@ -127,9 +130,6 @@ DLLEXPORT int jl_is_leaf_type(jl_value_t *v) } return 1; } - if (jl_is_type_type(v)) { - return !jl_is_typevar(jl_tparam0(v)); - } return 0; } @@ -158,7 +158,7 @@ static int count_union_components(jl_tuple_t *types) size_t i, c=0; for(i=0; i < jl_tuple_len(types); i++) { jl_value_t *e = jl_tupleref(types,i); - if (jl_is_union_type(e)) { + if (jl_is_uniontype(e)) { c += count_union_components(((jl_uniontype_t*)e)->types); } else { @@ -173,7 +173,7 @@ static void flatten_type_union(jl_tuple_t *types, jl_value_t **out, size_t *idx) size_t i; for(i=0; i < jl_tuple_len(types); i++) { jl_value_t *e = jl_tupleref(types,i); - if (jl_is_union_type(e)) { + if (jl_is_uniontype(e)) { flatten_type_union(((jl_uniontype_t*)e)->types, out, idx); } else { @@ -196,14 +196,18 @@ static int union_elt_morespecific(const void *a, const void *b) return jl_object_id(va) < jl_object_id(vb) ? -1 : 1; } +// NOTE: this is a hack to avoid simplifying type unions too early inside +// type definitions. (issue #2365) +int inside_typedef = 0; + DLLEXPORT jl_tuple_t *jl_compute_type_union(jl_tuple_t *types) { size_t n = count_union_components(types); - jl_value_t **temp = alloca(n * sizeof(jl_value_t*)); + jl_value_t **temp; + JL_GC_PUSHARGS(temp, n); size_t idx=0; flatten_type_union(types, temp, &idx); - JL_GC_PUSHARGS(temp, n); assert(idx == n); size_t i, j, ndel=0; for(i=0; i < n; i++) { @@ -212,6 +216,8 @@ jl_tuple_t *jl_compute_type_union(jl_tuple_t *types) if (temp[i] == temp[j] || (!jl_has_typevars(temp[i]) && !jl_has_typevars(temp[j]) && + !(inside_typedef && (jl_is_typevar(temp[i]) || + jl_is_typevar(temp[j]))) && (type_eqv_(temp[i], temp[j]) || jl_subtype(temp[i], temp[j], 0)))) { temp[i] = NULL; @@ -254,8 +260,10 @@ jl_value_t *jl_type_union(jl_tuple_t *types) typedef enum {invariant, covariant} variance_t; +#define MAX_CENV_SIZE 128 + typedef struct { - jl_value_t *data[128]; + jl_value_t **data; size_t n; } cenv_t; @@ -264,11 +272,12 @@ static inline int is_btv(jl_value_t *v) return jl_is_typevar(v) && ((jl_tvar_t*)v)->bound; } -static void extend_(jl_value_t *var, jl_value_t *val, cenv_t *soln, int allow) +static void extend_(jl_value_t *var, jl_value_t *val, cenv_t *soln, int allow, + int ordered) { if (!allow && var == val) return; - if (val < var && is_btv(val) && is_btv(var)) { + if (!ordered && val < var && is_btv(val) && is_btv(var)) { jl_value_t *temp = val; val = var; var = temp; @@ -279,7 +288,7 @@ static void extend_(jl_value_t *var, jl_value_t *val, cenv_t *soln, int allow) type_eqv_(soln->data[i+1],val)))) return; } - if (soln->n >= sizeof(soln->data)/sizeof(void*)) + if (soln->n >= MAX_CENV_SIZE) jl_error("type too large"); soln->data[soln->n++] = var; soln->data[soln->n++] = val; @@ -287,7 +296,12 @@ static void extend_(jl_value_t *var, jl_value_t *val, cenv_t *soln, int allow) static void extend(jl_value_t *var, jl_value_t *val, cenv_t *soln) { - extend_(var, val, soln, 0); + extend_(var, val, soln, 0, 0); +} + +static void extend_ordered(jl_value_t *var, jl_value_t *val, cenv_t *soln) +{ + extend_(var, val, soln, 0, 1); } static jl_value_t *jl_type_intersect(jl_value_t *a, jl_value_t *b, @@ -338,8 +352,8 @@ static size_t tuple_intersect_size(jl_tuple_t *a, jl_tuple_t *b, int *bot) if (al == bl) return al; if (al > bl) return tuple_intersect_size(b, a, bot); assert(al < bl); - if (jl_is_seq_type(jl_tupleref(b,bl-1))) { - if (al > 0 && jl_is_seq_type(jl_tupleref(a,al-1))) { + if (jl_is_vararg_type(jl_tupleref(b,bl-1))) { + if (al > 0 && jl_is_vararg_type(jl_tupleref(a,al-1))) { return bl; } else { @@ -349,7 +363,7 @@ static size_t tuple_intersect_size(jl_tuple_t *a, jl_tuple_t *b, int *bot) return 0; } } - if (al > 0 && jl_is_seq_type(jl_tupleref(a,al-1))) { + if (al > 0 && jl_is_vararg_type(jl_tupleref(a,al-1))) { return bl; } *bot=1; @@ -376,7 +390,7 @@ static jl_value_t *intersect_tuple(jl_tuple_t *a, jl_tuple_t *b, for(ci=0; ci < n; ci++) { if (ai < al) { ae = jl_tupleref(a,ai); - if (jl_is_seq_type(ae)) { + if (jl_is_vararg_type(ae)) { aseq=1; ae = jl_tparam0(ae); } @@ -384,7 +398,7 @@ static jl_value_t *intersect_tuple(jl_tuple_t *a, jl_tuple_t *b, } if (bi < bl) { be = jl_tupleref(b,bi); - if (jl_is_seq_type(be)) { + if (jl_is_vararg_type(be)) { bseq=1; be = jl_tparam0(be); } @@ -407,7 +421,7 @@ static jl_value_t *intersect_tuple(jl_tuple_t *a, jl_tuple_t *b, } if (aseq && bseq) { ce = (jl_value_t*)jl_tuple1(ce); - ce = (jl_value_t*)jl_apply_type((jl_value_t*)jl_seq_type, + ce = (jl_value_t*)jl_apply_type((jl_value_t*)jl_vararg_type, (jl_tuple_t*)ce); } jl_tupleset(tc, ci, ce); @@ -417,7 +431,7 @@ static jl_value_t *intersect_tuple(jl_tuple_t *a, jl_tuple_t *b, return result; } -static jl_value_t *intersect_tag(jl_tag_type_t *a, jl_tag_type_t *b, +static jl_value_t *intersect_tag(jl_datatype_t *a, jl_datatype_t *b, cenv_t *penv, cenv_t *eqc, variance_t var) { assert(a->name == b->name); @@ -553,11 +567,37 @@ static long meet_tuple_lengths(long bv, long vv, int *bot) return vv; } +// convert a type to the value it would have if assigned to a static parameter +// in covariant context. +// example: (Type{Int},) => (DataType,) +// calling f{T}(x::T) as f((Int,)) should give T == (DataType,), but we +// might temporarily represent this type as (Type{Int},) for more precision. +static jl_value_t *type_to_static_parameter_value(jl_value_t *t) +{ + if (jl_is_type_type(t) && !jl_is_typevar(jl_tparam0(t))) + return jl_full_type(jl_tparam0(t)); + if (jl_is_tuple(t)) { + size_t l = jl_tuple_len(t); + jl_tuple_t *nt = jl_alloc_tuple(l); + JL_GC_PUSH(&nt); + for(size_t i=0; i < l; i++) { + jl_tupleset(nt, i, type_to_static_parameter_value(jl_tupleref(t,i))); + } + JL_GC_POP(); + return (jl_value_t*)nt; + } + return t; +} + static int match_intersection_mode = 0; static jl_value_t *intersect_typevar(jl_tvar_t *a, jl_value_t *b, cenv_t *penv, cenv_t *eqc, variance_t var) { + if (var == covariant) { + // matching T to Type{S} in covariant context + b = type_to_static_parameter_value(b); + } if (jl_subtype(b, (jl_value_t*)a, 0)) { if (!a->bound) return b; } @@ -640,16 +680,14 @@ static jl_value_t *jl_type_intersect(jl_value_t *a, jl_value_t *b, return b; } // union - if (jl_is_union_type(a)) + if (jl_is_uniontype(a)) return intersect_union((jl_uniontype_t*)a, b, penv, eqc, var); - if (jl_is_union_type(b)) + if (jl_is_uniontype(b)) return intersect_union((jl_uniontype_t*)b, a, penv, eqc, var); if (a == (jl_value_t*)jl_undef_type) return (jl_value_t*)jl_bottom_type; if (b == (jl_value_t*)jl_undef_type) return (jl_value_t*)jl_bottom_type; - if (a == (jl_value_t*)jl_any_type || - a == jl_ANY_flag) return b; - if (b == (jl_value_t*)jl_any_type || - b == jl_ANY_flag) return a; + if (a == (jl_value_t*)jl_any_type || a == jl_ANY_flag) return b; + if (b == (jl_value_t*)jl_any_type || b == jl_ANY_flag) return a; // tuple if (jl_is_tuple(a)) { jl_value_t *temp=NULL; @@ -674,9 +712,9 @@ static jl_value_t *jl_type_intersect(jl_value_t *a, jl_value_t *b, if (i >= eqc->n) { // don't know N yet, so add a constraint for it based on // the length of the other tuple - if (alen > 0 && jl_is_seq_type(jl_tupleref(a,alen-1))) { + if (alen > 0 && jl_is_vararg_type(jl_tupleref(a,alen-1))) { temp = (jl_value_t*)jl_tuple1(elty); - jl_tupleset(b, alen-1, jl_apply_type((jl_value_t*)jl_seq_type, + jl_tupleset(b, alen-1, jl_apply_type((jl_value_t*)jl_vararg_type, (jl_tuple_t*)temp)); if (jl_is_typevar(lenvar)) { // store "at least N" constraints in the <: env @@ -717,6 +755,19 @@ static jl_value_t *jl_type_intersect(jl_value_t *a, jl_value_t *b, } } } + if (jl_is_type_type(b) && jl_is_typevar(jl_tparam0(b))) { + jl_tvar_t *btp0 = (jl_tvar_t*)jl_tparam0(b); + if (jl_subtype(jl_tupletype_type, (jl_value_t*)btp0, 0)) { + b = jl_tupletype_type; + } + else if (jl_subtype(btp0->ub, a, 1)) { + JL_GC_POP(); + return b; + } + else if (jl_is_tuple(btp0->ub)) { + b = jl_full_type(btp0->ub); + } + } if (!jl_is_tuple(b)) { JL_GC_POP(); return (jl_value_t*)jl_bottom_type; @@ -728,32 +779,44 @@ static jl_value_t *jl_type_intersect(jl_value_t *a, jl_value_t *b, if (jl_is_tuple(b)) { return jl_type_intersect(b, a, penv,eqc,var); } + if (jl_is_ntuple_type(a) && jl_is_type_type(b)) { + jl_value_t *temp = a; + a = b; + b = temp; + } + if (jl_is_ntuple_type(b) && jl_is_type_type(a) && jl_is_tuple(jl_tparam0(a))) { + jl_value_t *atyp = jl_full_type(jl_tparam0(a)); + JL_GC_PUSH(&atyp); + jl_value_t *ti = jl_type_intersect(atyp, b, penv,eqc,var); + JL_GC_POP(); + return ti; + } // tag - if (!jl_is_some_tag_type(a) || !jl_is_some_tag_type(b)) + if (!jl_is_datatype(a) || !jl_is_datatype(b)) return (jl_value_t*)jl_bottom_type; - jl_tag_type_t *tta = (jl_tag_type_t*)a; - jl_tag_type_t *ttb = (jl_tag_type_t*)b; + jl_datatype_t *tta = (jl_datatype_t*)a; + jl_datatype_t *ttb = (jl_datatype_t*)b; if (tta->name == ttb->name) return (jl_value_t*)intersect_tag(tta, ttb, penv, eqc, var); - jl_tag_type_t *super = NULL; - jl_tag_type_t *sub = NULL; + jl_datatype_t *super = NULL; + jl_datatype_t *sub = NULL; jl_value_t *env = NULL; jl_tuple_t *p = NULL; JL_GC_PUSH(&super, &sub, &env, &p); while (tta != jl_any_type) { if (tta->name == ttb->name) { - sub = (jl_tag_type_t*)a; - super = (jl_tag_type_t*)b; + sub = (jl_datatype_t*)a; + super = (jl_datatype_t*)b; break; } tta = tta->super; } if (sub == NULL) { - tta = (jl_tag_type_t*)a; + tta = (jl_datatype_t*)a; while (ttb != jl_any_type) { if (tta->name == ttb->name) { - sub = (jl_tag_type_t*)b; - super = (jl_tag_type_t*)a; + sub = (jl_datatype_t*)b; + super = (jl_datatype_t*)a; break; } ttb = ttb->super; @@ -765,11 +828,11 @@ static jl_value_t *jl_type_intersect(jl_value_t *a, jl_value_t *b, } if (sub->super == jl_type_type && jl_is_type_type((jl_value_t*)super)) { - // subtypes of Type like BitsKind do not constrain the type + // subtypes of Type like DataType do not constrain the type // parameter, and yet contain Type instances with a more specific // parameter (like Type{Int}). This is a special case. jl_value_t *tp0 = jl_tparam0(super); - if (jl_is_typevar(tp0) || (jl_type_t*)sub == jl_typeof(tp0)) { + if (jl_is_typevar(tp0) || (jl_value_t*)sub == jl_typeof(tp0)) { JL_GC_POP(); return (jl_value_t*)super; } @@ -777,25 +840,25 @@ static jl_value_t *jl_type_intersect(jl_value_t *a, jl_value_t *b, return (jl_value_t*)jl_bottom_type; } - super = (jl_tag_type_t*)jl_type_intersect((jl_value_t*)sub->super, (jl_value_t*)super, penv, eqc, var); + super = (jl_datatype_t*)jl_type_intersect((jl_value_t*)sub->super, (jl_value_t*)super, penv, eqc, var); - if ((jl_type_t*)super == jl_bottom_type) { + if ((jl_value_t*)super == jl_bottom_type) { JL_GC_POP(); return (jl_value_t*)jl_bottom_type; } // super needs to be instantiated so the matching below finds actual types // and doesn't fail due to the presence of extra typevars. - super = (jl_tag_type_t*)jl_instantiate_type_with((jl_type_t*)super, eqc->data, eqc->n/2); + super = (jl_datatype_t*)jl_instantiate_type_with((jl_value_t*)super, eqc->data, eqc->n/2); size_t n = jl_tuple_len(sub->parameters); assert(sub->name->primary != NULL); jl_value_t *tc = sub->name->primary; - jl_tuple_t *tc_params = ((jl_tag_type_t*)tc)->parameters; + jl_tuple_t *tc_params = ((jl_datatype_t*)tc)->parameters; // compute what constraints the supertype imposes on the subtype jl_tuple_t *subs_sup_params = - ((jl_tag_type_t*)((jl_tag_type_t*)tc)->super)->parameters; + ((jl_datatype_t*)((jl_datatype_t*)tc)->super)->parameters; // match the intersected supertype against the pattern this subtype // uses to instantiate its supertype. this tells us what subtype parameter // values are implied by the intersected supertype, or that the @@ -1101,41 +1164,37 @@ static int solve_tvar_constraints(cenv_t *env, cenv_t *soln) return 1; } -#if 0 -static char *type_summary(jl_value_t *t) +/* +char *type_summary(jl_value_t *t) { if (jl_is_tuple(t)) return "Tuple"; - if (jl_is_some_tag_type(t)) - return ((jl_tag_type_t*)t)->name->name->name; + if (jl_is_datatype(t)) + return ((jl_datatype_t*)t)->name->name->name; return "?"; } -static void print_env(cenv_t *soln) +void print_env(cenv_t *soln) { for(int i=0; i < soln->n; i+=2) { jl_value_t *T, *S; T = soln->data[i]; S = soln->data[i+1]; - ios_printf(ios_stdout, + JL_PRINTF(JL_STDOUT, "%s@%x=%s ", ((jl_tvar_t*)T)->name->name, T, type_summary(S)); } - ios_printf(ios_stdout, "\n"); + JL_PRINTF(JL_STDOUT, "\n"); } -#endif +*/ jl_value_t *jl_type_intersection_matching(jl_value_t *a, jl_value_t *b, jl_tuple_t **penv, jl_tuple_t *tvars) { - cenv_t eqc; eqc.n = 0; memset(eqc.data, 0, sizeof(eqc.data)); - cenv_t env; env.n = 0; memset(env.data, 0, sizeof(env.data)); - jl_value_t *ti = NULL; - - JL_GC_PUSH(&ti); - int nrts = sizeof(eqc.data)/sizeof(void*); - JL_GC_PUSHARGS(eqc.data, nrts); - jl_gcframe_t __gc_stkf3_ = { (jl_value_t***)env.data, nrts, - 0, jl_pgcstack }; - jl_pgcstack = &__gc_stkf3_; + jl_value_t **rts; + JL_GC_PUSHARGS(rts, 1 + 2*MAX_CENV_SIZE); + memset(rts, 0, (1+2*MAX_CENV_SIZE)*sizeof(void*)); + cenv_t eqc; eqc.n = 0; eqc.data = &rts[1]; + cenv_t env; env.n = 0; env.data = &rts[1+MAX_CENV_SIZE]; + jl_value_t **pti = &rts[0]; has_ntuple_intersect_tuple = 0; JL_TRY { @@ -1144,15 +1203,15 @@ jl_value_t *jl_type_intersection_matching(jl_value_t *a, jl_value_t *b, // that we allow Range{T} to exist, even though the declaration of // Range specifies Range{T<:Real}. Therefore intersection cannot see // that some parameter values actually don't match. - ti = jl_type_intersect(a, b, &env, &eqc, covariant); + *pti = jl_type_intersect(a, b, &env, &eqc, covariant); } JL_CATCH { - ti = (jl_value_t*)jl_bottom_type; + *pti = (jl_value_t*)jl_bottom_type; } - if (ti == (jl_value_t*)jl_bottom_type || + if (*pti == (jl_value_t*)jl_bottom_type || !(env.n > 0 || eqc.n > 0 || tvars != jl_null)) { - JL_GC_POP(); JL_GC_POP(); JL_GC_POP(); - return ti; + JL_GC_POP(); + return *pti; } int e; @@ -1174,16 +1233,16 @@ jl_value_t *jl_type_intersection_matching(jl_value_t *a, jl_value_t *b, to find all other constraints on N first, then do intersection again with that knowledge. */ - ti = jl_type_intersect(a, b, &env, &eqc, covariant); - if (ti == (jl_value_t*)jl_bottom_type) { - JL_GC_POP(); JL_GC_POP(); JL_GC_POP(); - return ti; + *pti = jl_type_intersect(a, b, &env, &eqc, covariant); + if (*pti == (jl_value_t*)jl_bottom_type) { + JL_GC_POP(); + return *pti; } } } if (!solve_tvar_constraints(&env, &eqc)) { - JL_GC_POP(); JL_GC_POP(); JL_GC_POP(); + JL_GC_POP(); return (jl_value_t*)jl_bottom_type; } //JL_PRINTF(JL_STDOUT, "env: "); print_env(&env); @@ -1197,6 +1256,7 @@ jl_value_t *jl_type_intersection_matching(jl_value_t *a, jl_value_t *b, tvarslen = 1; } else { + assert(jl_is_tuple(tvars)); tvs = &jl_t0(tvars); tvarslen = jl_tuple_len(tvars); } @@ -1210,7 +1270,7 @@ jl_value_t *jl_type_intersection_matching(jl_value_t *a, jl_value_t *b, // bind type vars to themselves if they were not matched explicitly // during type intersection. if (e >= env0) - extend_(tv, tv, &eqc, 1); + extend_(tv, tv, &eqc, 1, 0); } *penv = jl_alloc_tuple_uninit(eqc.n); @@ -1221,16 +1281,16 @@ jl_value_t *jl_type_intersection_matching(jl_value_t *a, jl_value_t *b, if (env0 > 0) { JL_TRY { - ti = (jl_value_t*)jl_instantiate_type_with((jl_type_t*)ti, + *pti=(jl_value_t*)jl_instantiate_type_with((jl_value_t*)*pti, &jl_t0(*penv), eqc.n/2); } JL_CATCH { - ti = (jl_value_t*)jl_bottom_type; + *pti = (jl_value_t*)jl_bottom_type; } } - JL_GC_POP(); JL_GC_POP(); JL_GC_POP(); - return ti; + JL_GC_POP(); + return *pti; } // --- type instantiation and cache --- @@ -1257,33 +1317,33 @@ static int type_eqv_(jl_value_t *a, jl_value_t *b) if (jl_is_tuple(a)) { if (jl_is_tuple(b)) { jl_tuple_t *ta = (jl_tuple_t*)a; jl_tuple_t *tb = (jl_tuple_t*)b; - int sqa = (jl_tuple_len(ta)>0 && - jl_is_seq_type(jl_tupleref(ta,jl_tuple_len(ta)-1))); - int sqb = (jl_tuple_len(tb)>0 && - jl_is_seq_type(jl_tupleref(tb,jl_tuple_len(tb)-1))); - if (sqa && sqb) - return extensionally_same_type(a, b); - if (sqa != sqb || jl_tuple_len(ta) != jl_tuple_len(tb)) - return 0; - for(int i=0; i < jl_tuple_len(ta); i++) { - if (!type_eqv_(jl_tupleref(ta,i),jl_tupleref(tb,i))) + int la = jl_tuple_len(ta), lb = jl_tuple_len(tb); + if (la != lb) return 0; + int sqa = (la>0 && jl_is_vararg_type(jl_tupleref(ta,la-1))); + int sqb = (lb>0 && jl_is_vararg_type(jl_tupleref(tb,lb-1))); + if (sqa != sqb) return 0; + for(int i=0; i < la; i++) { + jl_value_t *ea=jl_tupleref(ta,i), *eb=jl_tupleref(tb,i); + if (jl_is_vararg_type(ea)) ea = jl_tparam0(ea); + if (jl_is_vararg_type(eb)) eb = jl_tparam0(eb); + if (!type_eqv_(ea, eb)) return 0; } return 1; } return 0; } - if (jl_is_union_type(a)) { - if (jl_is_union_type(b)) { + if (jl_is_uniontype(a)) { + if (jl_is_uniontype(b)) { return extensionally_same_type(a, b); } return 0; } - if (!jl_is_some_tag_type(a) || !jl_is_some_tag_type(b)) { + if (!jl_is_datatype(a) || !jl_is_datatype(b)) { return jl_egal(a, b); } - jl_tag_type_t *tta = (jl_tag_type_t*)a; - jl_tag_type_t *ttb = (jl_tag_type_t*)b; + jl_datatype_t *tta = (jl_datatype_t*)a; + jl_datatype_t *ttb = (jl_datatype_t*)b; if (tta->name != ttb->name) return 0; jl_tuple_t *ap = tta->parameters; jl_tuple_t *bp = ttb->parameters; @@ -1304,17 +1364,21 @@ int jl_types_equal(jl_value_t *a, jl_value_t *b) return type_eqv_(a, b); } -static int type_le_generic(jl_value_t *a, jl_value_t *b) +static int type_le_generic(jl_value_t *a, jl_value_t *b, int useenv) { jl_value_t *env = jl_type_match(a, b); if (env == jl_false) return 0; + size_t l = jl_tuple_len(env); // make sure all typevars correspond to other unique typevars - for(int i=0; i < jl_tuple_len(env); i+=2) { - if (!jl_is_typevar(jl_tupleref(env,i+1))) + for(size_t i=0; i < l; i+=2) { + jl_value_t *envi = jl_tupleref(env,i+1); + if (!jl_is_typevar(envi)) return 0; - for(int j=0; j < jl_tuple_len(env); j+=2) { + if (useenv && ((jl_tvar_t*)envi)->bound!=((jl_tvar_t*)jl_tupleref(env,i))->bound) + return 0; + for(size_t j=0; j < l; j+=2) { if (i != j) { - if (jl_tupleref(env,i+1) == jl_tupleref(env,j+1)) + if (envi == jl_tupleref(env,j+1)) return 0; } } @@ -1322,16 +1386,15 @@ static int type_le_generic(jl_value_t *a, jl_value_t *b) return 1; } -int jl_types_equal_generic(jl_value_t *a, jl_value_t *b) +int jl_types_equal_generic(jl_value_t *a, jl_value_t *b, int useenv) { - return type_le_generic(a, b) && type_le_generic(b, a); + return type_le_generic(a, b, useenv) && type_le_generic(b, a, useenv); } static int valid_type_param(jl_value_t *v) { // TODO: maybe more things - return jl_is_type(v) || jl_is_long(v) || jl_is_symbol(v) || - jl_is_typevar(v); + return jl_is_type(v) || jl_is_long(v) || jl_is_symbol(v) || jl_is_typevar(v); } jl_value_t *jl_apply_type_(jl_value_t *tc, jl_value_t **params, size_t n) @@ -1344,17 +1407,16 @@ jl_value_t *jl_apply_type_(jl_value_t *tc, jl_value_t **params, size_t n) size_t i; char *tname; jl_tuple_t *tp; - jl_struct_type_t *stprimary = NULL; + jl_datatype_t *stprimary = NULL; if (jl_is_typector(tc)) { tp = ((jl_typector_t*)tc)->parameters; tname = "alias"; } else { - assert(jl_is_some_tag_type(tc)); - tp = ((jl_tag_type_t*)tc)->parameters; - tname = ((jl_tag_type_t*)tc)->name->name->name; - if (jl_is_struct_type(tc)) - stprimary = (jl_struct_type_t*)((jl_tag_type_t*)tc)->name->primary; + assert(jl_is_datatype(tc)); + tp = ((jl_datatype_t*)tc)->parameters; + tname = ((jl_datatype_t*)tc)->name->name->name; + stprimary = (jl_datatype_t*)((jl_datatype_t*)tc)->name->primary; } for(i=0; i < n; i++) { jl_value_t *pi = params[i]; @@ -1372,9 +1434,9 @@ jl_value_t *jl_apply_type_(jl_value_t *tc, jl_value_t **params, size_t n) size_t ntp = jl_tuple_len(tp); if (n > ntp) jl_errorf("too many parameters for type %s", tname); - jl_value_t **env = alloca(2 * ntp * sizeof(jl_value_t*)); - memset(env, 0, 2 * ntp * sizeof(jl_value_t*)); + jl_value_t **env; JL_GC_PUSHARGS(env, 2*ntp); + memset(env, 0, 2 * ntp * sizeof(jl_value_t*)); size_t ne = 0; for(i=0; i < ntp; i++) { jl_tvar_t *tv = (jl_tvar_t*)jl_tupleref(tp,i); @@ -1404,7 +1466,7 @@ jl_value_t *jl_apply_type_(jl_value_t *tc, jl_value_t **params, size_t n) ne++; } if (jl_is_typector(tc)) tc = (jl_value_t*)((jl_typector_t*)tc)->body; - jl_type_t *result = jl_instantiate_type_with((jl_type_t*)tc, env, ne); + jl_value_t *result = jl_instantiate_type_with((jl_value_t*)tc, env, ne); JL_GC_POP(); return (jl_value_t*)result; } @@ -1414,21 +1476,34 @@ jl_value_t *jl_apply_type(jl_value_t *tc, jl_tuple_t *params) return jl_apply_type_(tc, &jl_tupleref(params,0), jl_tuple_len(params)); } -static jl_type_t *lookup_type(jl_tuple_t *table, - jl_typename_t *tn, jl_value_t **key, size_t n) +static int typekey_compare(jl_datatype_t *tt, jl_value_t **key, size_t n) +{ + size_t j; + for(j=0; j < n; j++) { + if (!type_eqv_(jl_tupleref(tt->parameters,j), key[j])) + return 0; + } + return 1; +} + +static jl_value_t *lookup_type(jl_typename_t *tn, jl_value_t **key, size_t n) { if (n==0) return NULL; - while (table != jl_null) { - jl_tag_type_t *tt = (jl_tag_type_t*)jl_t0(table); - if (tt->name == tn && n == jl_tuple_len(tt->parameters)) { - size_t i; - for(i=0; i < n; i++) { - if (!type_eqv_(jl_tupleref(tt->parameters,i), key[i])) - break; - } - if (i==n) return (jl_type_t*)tt; - } - table = (jl_tuple_t*)jl_t1(table); + jl_value_t *cache = tn->cache; + jl_value_t **data; + size_t cl; + if (jl_is_tuple(cache)) { + data = ((jl_tuple_t*)cache)->data; + cl = jl_tuple_len(cache); + } + else { + data = jl_array_data(cache); + cl = jl_array_len(cache); + } + for(size_t i=0; i < cl; i++) { + jl_datatype_t *tt = (jl_datatype_t*)data[i]; + if (typekey_compare(tt, key, n)) + return (jl_value_t*)tt; } return NULL; } @@ -1443,12 +1518,12 @@ int jl_assign_type_uid(void) return int32hash(t_uid_ctr++); } -static void cache_type_(jl_type_t *type) +static void cache_type_(jl_value_t *type) { // only cache concrete types - jl_tuple_t *t = ((jl_tag_type_t*)type)->parameters; + jl_tuple_t *t = ((jl_datatype_t*)type)->parameters; if (jl_tuple_len(t) == 0) return; - if (jl_is_tag_type(type)) { + if (jl_is_abstracttype(type)) { if (jl_has_typevars_((jl_value_t*)type,1)) return; } @@ -1461,34 +1536,59 @@ static void cache_type_(jl_type_t *type) } } // assign uid - if (jl_is_struct_type(type) && ((jl_struct_type_t*)type)->uid==0) - ((jl_struct_type_t*)type)->uid = jl_assign_type_uid(); - else if (jl_is_bits_type(type) && ((jl_bits_type_t*)type)->uid==0) - ((jl_bits_type_t*)type)->uid = jl_assign_type_uid(); - jl_tuple_t *tc = ((jl_tag_type_t*)type)->name->cache; - ((jl_tag_type_t*)type)->name->cache = jl_tuple2(type, tc); + if (!jl_is_abstracttype(type) && ((jl_datatype_t*)type)->uid==0) + ((jl_datatype_t*)type)->uid = jl_assign_type_uid(); + jl_value_t *cache = ((jl_datatype_t*)type)->name->cache; + // this needs to work before jl_array_any_type exists, so start with + // a tuple and switch to an Array when possible. + if (jl_array_any_type != NULL) { + if (jl_is_tuple(cache)) { + jl_array_t *nc = jl_alloc_cell_1d(jl_tuple_len(cache)); + memcpy(nc->data, ((jl_tuple_t*)cache)->data, sizeof(void*)*jl_tuple_len(cache)); + cache = (jl_value_t*)nc; + ((jl_datatype_t*)type)->name->cache = cache; + } + jl_cell_1d_push((jl_array_t*)cache, (jl_value_t*)type); + } + else { + assert(jl_is_tuple(cache)); + size_t n = jl_tuple_len(cache); + jl_tuple_t *nc = jl_alloc_tuple_uninit(n+1); + memcpy(nc->data, ((jl_tuple_t*)cache)->data, sizeof(void*) * n); + jl_tupleset(nc, n, (jl_value_t*)type); + ((jl_datatype_t*)type)->name->cache = (jl_value_t*)nc; + } } -void jl_cache_type_(jl_tag_type_t *type) +jl_value_t *jl_cache_type_(jl_datatype_t *type) { - cache_type_((jl_type_t*)type); + jl_value_t *t = lookup_type(type->name, type->parameters->data, + jl_tuple_len(type->parameters)); + if (t != NULL) return t; + cache_type_((jl_value_t*)type); + return (jl_value_t*)type; } JL_CALLABLE(jl_f_tuple); JL_CALLABLE(jl_f_ctor_trampoline); -static jl_type_t *inst_type_w_(jl_value_t *t, jl_value_t **env, size_t n, - jl_tuple_t *stack) +typedef struct _jl_typestack_t { + jl_datatype_t *tt; + struct _jl_typestack_t *prev; +} jl_typestack_t; + +static jl_value_t *inst_type_w_(jl_value_t *t, jl_value_t **env, size_t n, + jl_typestack_t *stack) { - jl_tuple2_t top; + jl_typestack_t top; size_t i; - if (n == 0) return (jl_type_t*)t; + if (n == 0) return (jl_value_t*)t; if (jl_is_typevar(t)) { for(i=0; i < n; i++) { if (env[i*2] == t) - return (jl_type_t*)env[i*2+1]; + return (jl_value_t*)env[i*2+1]; } - return (jl_type_t*)t; + return (jl_value_t*)t; } if (jl_is_tuple(t)) { jl_tuple_t *p = (jl_tuple_t*)t; @@ -1498,35 +1598,35 @@ static jl_type_t *inst_type_w_(jl_value_t *t, jl_value_t **env, size_t n, jl_tupleset(nt, i, (jl_value_t*)inst_type_w_(jl_tupleref(p,i), env, n, stack)); } JL_GC_POP(); - return (jl_type_t*)nt; + return (jl_value_t*)nt; } - if (jl_is_union_type(t)) { + if (jl_is_uniontype(t)) { jl_tuple_t *tw = (jl_tuple_t*)inst_type_w_((jl_value_t*)((jl_uniontype_t*)t)->types, env, n, stack); JL_GC_PUSH(&tw); - jl_type_t *res = (jl_type_t*)jl_new_uniontype(tw); + jl_value_t *res = (jl_value_t*)jl_new_uniontype(tw); JL_GC_POP(); return res; } - if (jl_is_some_tag_type(t)) { - jl_tag_type_t *tt = (jl_tag_type_t*)t; + if (jl_is_datatype(t)) { + jl_datatype_t *tt = (jl_datatype_t*)t; jl_tuple_t *tp = tt->parameters; if (jl_is_null(tp)) - return (jl_type_t*)t; + return (jl_value_t*)t; jl_typename_t *tn = tt->name; jl_value_t *tc = tn->primary; // don't instantiate "Foo" without parameters inside Foo - if (t == tc && stack!=jl_null) - return (jl_type_t*)t; - jl_type_t *result; + if (t == tc && stack!=NULL) + return (jl_value_t*)t; + jl_value_t *result; size_t ntp = jl_tuple_len(tp); - assert(ntp == jl_tuple_len(((jl_tag_type_t*)tc)->parameters)); - jl_value_t **iparams = (jl_value_t**)alloca((ntp+2) * sizeof(void*)); + assert(ntp == jl_tuple_len(((jl_datatype_t*)tc)->parameters)); + jl_value_t **iparams; + JL_GC_PUSHARGS(iparams, ntp+2); for(i=0; i < ntp+2; i++) iparams[i] = NULL; jl_value_t **rt1 = &iparams[ntp+0]; // some extra gc roots jl_value_t **rt2 = &iparams[ntp+1]; int cacheable = 1, isabstract = 0; - JL_GC_PUSHARGS(iparams, ntp+2); for(i=0; i < ntp; i++) { jl_value_t *elt = jl_tupleref(tp, i); if (elt == t) { @@ -1535,7 +1635,7 @@ static jl_type_t *inst_type_w_(jl_value_t *t, jl_value_t **env, size_t n, else { iparams[i] = (jl_value_t*)inst_type_w_(elt, env, n, stack); jl_value_t *tv = - jl_tupleref(((jl_tag_type_t*)tc)->parameters, i); + jl_tupleref(((jl_datatype_t*)tc)->parameters, i); if (jl_is_typevar(tv) && !jl_is_typevar(iparams[i])) { // TODO: Undef should not be special here; fix. // maybe introduce Top == Union(Any,Undef), and make this @@ -1557,14 +1657,23 @@ static jl_type_t *inst_type_w_(jl_value_t *t, jl_value_t **env, size_t n, // if an identical instantiation is already in process somewhere // up the stack, return it. this computes a fixed point for // recursive types. - jl_type_t *lkup = lookup_type(stack, tn, iparams, ntp); - if (lkup != NULL && lkup != (jl_type_t*)tc) { + jl_typestack_t *tmp = stack; + jl_value_t *lkup = NULL; + while (tmp != NULL) { + if (tmp->tt->name==tn && ntp==jl_tuple_len(tmp->tt->parameters) && + typekey_compare(tmp->tt, iparams, ntp)) { + lkup = (jl_value_t*)tmp->tt; + break; + } + tmp = tmp->prev; + } + if (lkup != NULL && lkup != (jl_value_t*)tc) { result = lkup; goto done_inst_tt; } // check type cache if (cacheable) { - lkup = lookup_type(tn->cache, tn, iparams, ntp); + lkup = (jl_value_t*)lookup_type(tn, iparams, ntp); if (lkup != NULL) { result = lkup; goto done_inst_tt; } @@ -1573,7 +1682,7 @@ static jl_type_t *inst_type_w_(jl_value_t *t, jl_value_t **env, size_t n, // always use original type constructor if (tc != t) { //(tc != NULL && tc != t) - result = (jl_type_t*)jl_apply_type_(tc, iparams, ntp); + result = (jl_value_t*)jl_apply_type_(tc, iparams, ntp); goto done_inst_tt; } @@ -1582,98 +1691,68 @@ static jl_type_t *inst_type_w_(jl_value_t *t, jl_value_t **env, size_t n, for(i=0; i < ntp; i++) jl_tupleset(iparams_tuple, i, iparams[i]); *rt1 = (jl_value_t*)iparams_tuple; - if (jl_is_tag_type(t)) { - jl_tag_type_t *tagt = (jl_tag_type_t*)t; - jl_tag_type_t *ntt = - (jl_tag_type_t*)newobj((jl_type_t*)jl_tag_kind, TAG_TYPE_NW); - *rt2 = (jl_value_t*)ntt; - top.data[0] = (jl_value_t*)ntt; - top.data[1] = (jl_value_t*)stack; - stack = (jl_tuple_t*)⊤ - ntt->name = tn; - // temporarily initialize all fields so object is valid during - // allocation of other objects (possible GC) - ntt->fptr = NULL; - ntt->env = NULL; - ntt->linfo = NULL; - ntt->super = jl_any_type; - ntt->parameters = iparams_tuple; - ntt->super = (jl_tag_type_t*)inst_type_w_((jl_value_t*)tagt->super,env,n,stack); - if (cacheable) cache_type_((jl_type_t*)ntt); - result = (jl_type_t*)ntt; - } - else if (jl_is_bits_type(t)) { - jl_bits_type_t *bitst = (jl_bits_type_t*)t; - jl_bits_type_t *nbt = - (jl_bits_type_t*)newobj((jl_type_t*)jl_bits_kind, BITS_TYPE_NW); - *rt2 = (jl_value_t*)nbt; - top.data[0] = (jl_value_t*)nbt; - top.data[1] = (jl_value_t*)stack; - stack = (jl_tuple_t*)⊤ - nbt->name = tn; - nbt->fptr = NULL; - nbt->env = NULL; - nbt->linfo = NULL; - nbt->super = jl_any_type; - nbt->parameters = iparams_tuple; - nbt->nbits = bitst->nbits; - nbt->super = (jl_tag_type_t*)inst_type_w_((jl_value_t*)bitst->super, env, n, stack); - nbt->uid = 0; - if (cacheable) cache_type_((jl_type_t*)nbt); - result = (jl_type_t*)nbt; - } - else { - assert(jl_is_struct_type(t)); - jl_struct_type_t *st = (jl_struct_type_t*)t; - // create and initialize new struct type - jl_struct_type_t *nst = - jl_new_uninitialized_struct_type(st->names->length); - *rt2 = (jl_value_t*)nst; - // associate these parameters with the new struct type on - // the stack, in case one of its field types references it. - top.data[0] = (jl_value_t*)nst; - top.data[1] = (jl_value_t*)stack; - stack = (jl_tuple_t*)⊤ - nst->name = tn; - nst->super = jl_any_type; - nst->parameters = iparams_tuple; - nst->names = st->names; - nst->types = jl_null; // to be filled in below - if (isabstract) { - nst->fptr = jl_f_no_function; + + jl_datatype_t *dt = (jl_datatype_t*)t; + // create and initialize new type + jl_datatype_t *ndt = + jl_new_uninitialized_datatype(jl_tuple_len(dt->names)); + *rt2 = (jl_value_t*)ndt; + // associate these parameters with the new type on + // the stack, in case one of its field types references it. + top.tt = (jl_datatype_t*)ndt; + top.prev = stack; + stack = ⊤ + ndt->name = tn; + ndt->super = jl_any_type; + ndt->parameters = iparams_tuple; + ndt->names = dt->names; + ndt->types = jl_null; // to be filled in below + if (isabstract || !jl_is_function(dt->ctor_factory)) + ndt->fptr = jl_f_no_function; + else + ndt->fptr = jl_f_ctor_trampoline; + ndt->mutabl = dt->mutabl; + ndt->abstract = dt->abstract; + ndt->env = (jl_value_t*)ndt; + ndt->linfo = NULL; + ndt->ctor_factory = dt->ctor_factory; + ndt->instance = NULL; + ndt->uid = 0; + ndt->struct_decl = NULL; + ndt->size = ndt->alignment = 0; + ndt->super = (jl_datatype_t*)inst_type_w_((jl_value_t*)dt->super, env,n,stack); + jl_tuple_t *ftypes = dt->types; + if (ftypes != NULL) { + // recursively instantiate the types of the fields + ndt->types = (jl_tuple_t*)inst_type_w_((jl_value_t*)ftypes, env, n, stack); + if (!isabstract) { + jl_compute_field_offsets(ndt); } else { - nst->fptr = jl_f_ctor_trampoline; + ndt->size = 0; + ndt->pointerfree = 0; } - nst->env = (jl_value_t*)nst; - nst->linfo = NULL; - nst->ctor_factory = st->ctor_factory; - nst->instance = NULL; - nst->uid = 0; - nst->super = (jl_tag_type_t*)inst_type_w_((jl_value_t*)st->super, env,n,stack); - jl_tuple_t *ftypes = st->types; - if (ftypes != NULL) { - // recursively instantiate the types of the fields - nst->types = (jl_tuple_t*)inst_type_w_((jl_value_t*)ftypes, env, n, stack); - if (!isabstract) - jl_compute_struct_offsets(nst); - } - if (cacheable) cache_type_((jl_type_t*)nst); - result = (jl_type_t*)nst; + if (tn == jl_array_typename) + ndt->pointerfree = 0; + if (jl_tuple_len(ftypes) == 0) + ndt->alignment = ndt->size = dt->size; } + if (cacheable) cache_type_((jl_value_t*)ndt); + result = (jl_value_t*)ndt; + done_inst_tt: JL_GC_POP(); return result; } - return (jl_type_t*)t; + return (jl_value_t*)t; } -jl_type_t *jl_instantiate_type_with(jl_type_t *t, jl_value_t **env, size_t n) +jl_value_t *jl_instantiate_type_with(jl_value_t *t, jl_value_t **env, size_t n) { - return inst_type_w_((jl_value_t*)t, env, n, jl_null); + return inst_type_w_((jl_value_t*)t, env, n, NULL); } -jl_tag_type_t *jl_wrap_Type(jl_value_t *t) +jl_datatype_t *jl_wrap_Type(jl_value_t *t) { jl_value_t *env[2]; env[0] = jl_tparam0(jl_type_type); @@ -1681,25 +1760,25 @@ jl_tag_type_t *jl_wrap_Type(jl_value_t *t) // env[1] = (jl_value_t*)((jl_typector_t*)t)->body; //else env[1] = t; - return (jl_tag_type_t*) - jl_instantiate_type_with((jl_type_t*)jl_type_type, env, 1); + return (jl_datatype_t*) + jl_instantiate_type_with((jl_value_t*)jl_type_type, env, 1); } -void jl_reinstantiate_inner_types(jl_tag_type_t *t) +void jl_reinstantiate_inner_types(jl_datatype_t *t) { - jl_tuple2_t top; - top.data[0] = (jl_value_t*)t; - top.data[1] = (jl_value_t*)jl_null; + jl_typestack_t top; + top.tt = (jl_datatype_t*)t; + top.prev = NULL; size_t n = jl_tuple_len(t->parameters); jl_value_t **env = alloca(n*2*sizeof(void*)); for(int i=0; i < n; i++) { env[i*2] = jl_tupleref(t->parameters,i); env[i*2+1] = env[i*2]; } - t->super = (jl_tag_type_t*)inst_type_w_((jl_value_t*)t->super, env, n, (jl_tuple_t*)&top); - if (jl_is_struct_type(t)) { - jl_struct_type_t *st = (jl_struct_type_t*)t; - st->types = (jl_tuple_t*)inst_type_w_((jl_value_t*)st->types, env, n, (jl_tuple_t*)&top); + t->super = (jl_datatype_t*)inst_type_w_((jl_value_t*)t->super, env, n, &top); + if (jl_is_datatype(t)) { + jl_datatype_t *st = (jl_datatype_t*)t; + st->types = (jl_tuple_t*)inst_type_w_((jl_value_t*)st->types, env, n, &top); } } @@ -1713,8 +1792,8 @@ static int jl_tuple_subtype_(jl_value_t **child, size_t cl, size_t ci=0, pi=0; int mode = 0; while(1) { - int cseq = !ta && (ci= cl) @@ -1761,7 +1840,7 @@ static int tuple_all_subtype(jl_tuple_t *t, jl_value_t *super, size_t ci; for(ci=0; ci < jl_tuple_len(t); ci++) { jl_value_t *ce = jl_tupleref(t,ci); - if (!ta && jl_is_seq_type(ce)) + if (!ta && jl_is_vararg_type(ce)) ce = jl_tparam0(ce); if (!jl_subtype_le(ce, super, ta, morespecific, invariant)) return 0; @@ -1783,9 +1862,7 @@ static int jl_subtype_le(jl_value_t *a, jl_value_t *b, int ta, int morespecific, if (ta) { if (jl_is_type_type(b)) { jl_value_t *bp = jl_tparam0(b); - return jl_subtype_le((jl_value_t*)jl_typeof(a), - (jl_value_t*)jl_type_type, 0, morespecific, 0) && - jl_subtype_le(a, bp, 0, morespecific, 1); + return jl_is_type(a) && jl_subtype_le(a, bp, 0, morespecific, 1); } } else if (a == b) { @@ -1795,9 +1872,9 @@ static int jl_subtype_le(jl_value_t *a, jl_value_t *b, int ta, int morespecific, size_t i, j; if (jl_is_tuple(a)) { if ((jl_tuple_t*)b == jl_tuple_type) return 1; - if (jl_is_tag_type(b) && - ((jl_tag_type_t*)b)->name == jl_ntuple_typename) { - jl_tuple_t *tp = ((jl_tag_type_t*)b)->parameters; + if (jl_is_datatype(b) && + ((jl_datatype_t*)b)->name == jl_ntuple_typename) { + jl_tuple_t *tp = ((jl_datatype_t*)b)->parameters; return tuple_all_subtype((jl_tuple_t*)a, jl_tupleref(tp,1), ta, morespecific, invariant); @@ -1809,7 +1886,7 @@ static int jl_subtype_le(jl_value_t *a, jl_value_t *b, int ta, int morespecific, } } - if (!ta && jl_is_union_type(a)) { + if (!ta && jl_is_uniontype(a)) { jl_tuple_t *ap = ((jl_uniontype_t*)a)->types; if (morespecific) { // Union a is more specific than b if some element of a is @@ -1843,7 +1920,24 @@ static int jl_subtype_le(jl_value_t *a, jl_value_t *b, int ta, int morespecific, return 1; } - if (jl_is_union_type(b)) { + if (!ta && jl_is_type_type(a) && !invariant) { + jl_value_t *tp0a = jl_tparam0(a); + if (jl_is_typevar(tp0a)) { + jl_value_t *ub = ((jl_tvar_t*)tp0a)->ub; + jl_value_t *lb = ((jl_tvar_t*)tp0a)->lb; + if (jl_subtype_le(ub, b, 1, 0, 0) && + !jl_subtype_le((jl_value_t*)jl_any_type, ub, 0, 0, 0)) { + if (morespecific || jl_subtype_le(lb, b, 1, 0, 0)) + return 1; + } + } + else { + if (jl_subtype_le(tp0a, b, 1, 0, 0)) + return 1; + } + } + + if (jl_is_uniontype(b)) { if (invariant) return 0; jl_tuple_t *bp = ((jl_uniontype_t*)b)->types; @@ -1860,14 +1954,19 @@ static int jl_subtype_le(jl_value_t *a, jl_value_t *b, int ta, int morespecific, if ((a==(jl_value_t*)jl_undef_type && !jl_is_typevar(b)) || b==(jl_value_t*)jl_undef_type) return 0; - if (!invariant && (jl_tag_type_t*)b == jl_any_type) return 1; + if (!invariant && (jl_datatype_t*)b == jl_any_type) return 1; + + if (jl_is_type_type(b) && jl_is_typevar(jl_tparam0(b)) && jl_is_tuple(a)) { + return (jl_subtype_le(a, jl_tupletype_type, 0, morespecific, 0) && + jl_subtype_le(a, jl_tparam0(b), 0, morespecific, 1)); + } - if (jl_is_some_tag_type(a) && jl_is_some_tag_type(b)) { - if ((jl_tag_type_t*)a == jl_any_type) return 0; - jl_tag_type_t *tta = (jl_tag_type_t*)a; - jl_tag_type_t *ttb = (jl_tag_type_t*)b; + if (jl_is_datatype(a) && jl_is_datatype(b)) { + if ((jl_datatype_t*)a == jl_any_type) return 0; + jl_datatype_t *tta = (jl_datatype_t*)a; + jl_datatype_t *ttb = (jl_datatype_t*)b; int super=0; - while (tta != (jl_tag_type_t*)jl_any_type) { + while (tta != (jl_datatype_t*)jl_any_type) { if (tta->name == ttb->name) { if (super && morespecific) { if (tta->name != jl_type_type->name) @@ -1879,6 +1978,10 @@ static int jl_subtype_le(jl_value_t *a, jl_value_t *b, int ta, int morespecific, jl_tupleref(ttb->parameters,1), 0, morespecific, invariant); } + if (super && ttb->name == jl_type_type->name && jl_is_typevar(jl_tparam0(b))) { + if (jl_subtype_le(a, jl_tparam0(b), 0, morespecific, 1)) + return 1; + } assert(jl_tuple_len(tta->parameters) == jl_tuple_len(ttb->parameters)); for(i=0; i < jl_tuple_len(tta->parameters); i++) { jl_value_t *apara = jl_tupleref(tta->parameters,i); @@ -1899,11 +2002,16 @@ static int jl_subtype_le(jl_value_t *a, jl_value_t *b, int ta, int morespecific, tta = tta->super; super = 1; } assert(!invariant); - if (((jl_tag_type_t*)a)->name == jl_type_type->name) { + /* + if (((jl_datatype_t*)a)->name == jl_type_type->name) { // Type{T} also matches >:typeof(T) - if (!jl_is_typevar(jl_tparam0(a))) - return jl_subtype_le(jl_tparam0(a), b, 1, morespecific, 0); + jl_value_t *tp0a = jl_tparam0(a); + if (!jl_is_typevar(tp0a)) + return jl_subtype_le(tp0a, b, 1, morespecific, 0); + if (jl_subtype_le((jl_value_t*)jl_uniontype_type, b, 0, 0, 0)) + return jl_subtype_le(((jl_tvar_t*)tp0a)->ub, b, 1, morespecific, 0); } + */ return 0; } @@ -1927,20 +2035,22 @@ static int jl_subtype_le(jl_value_t *a, jl_value_t *b, int ta, int morespecific, return jl_subtype_le(a, (jl_value_t*)((jl_tvar_t*)b)->ub, 0, 0, 0) && jl_subtype_le((jl_value_t*)((jl_tvar_t*)b)->lb, a, 0, 0, 0); } - if ((jl_tag_type_t*)a == jl_any_type) return 0; + if ((jl_datatype_t*)a == jl_any_type) return 0; + if (jl_is_tuple(b)) { - if (jl_is_tag_type(a) && - ((jl_tag_type_t*)a)->name == jl_ntuple_typename) { + if (jl_is_datatype(a) && + ((jl_datatype_t*)a)->name == jl_ntuple_typename) { // only ((T>:S)...,) can be a supertype of NTuple[N,S] jl_tuple_t *tp = (jl_tuple_t*)b; - jl_value_t *ntp = jl_tupleref(((jl_tag_type_t*)a)->parameters, 1); - if (jl_tuple_len(tp) == 1 && jl_is_seq_type(jl_tupleref(tp,0))) { + jl_value_t *ntp = jl_tupleref(((jl_datatype_t*)a)->parameters, 1); + if (jl_tuple_len(tp) == 1 && jl_is_vararg_type(jl_tupleref(tp,0))) { return jl_subtype_le(ntp, jl_tparam0(jl_tupleref(tp,0)), 0, morespecific, invariant); } } return 0; } + if (jl_is_tuple(a)) return 0; return jl_egal(a, b); @@ -1971,8 +2081,8 @@ static jl_value_t *tuple_match(jl_tuple_t *child, jl_tuple_t *parent, size_t cl = jl_tuple_len(child); size_t pl = jl_tuple_len(parent); while(1) { - int cseq = (ci= cl) return (pi>=pl || pseq) ? jl_true : jl_false; if (cseq && !pseq) @@ -2035,7 +2145,7 @@ static jl_value_t *type_match_(jl_value_t *child, jl_value_t *parent, return jl_false; } } - extend(parent, child, env); + extend_ordered(parent, child, env); return jl_true; } @@ -2052,10 +2162,11 @@ static jl_value_t *type_match_(jl_value_t *child, jl_value_t *parent, return jl_true; if (child == (jl_value_t*)jl_any_type) return jl_false; - if (jl_is_union_type(child)) { + if (jl_is_uniontype(child)) { jl_tuple_t *t = ((jl_uniontype_t*)child)->types; if (morespecific) { cenv_t tenv; + tenv.data = alloca(MAX_CENV_SIZE*sizeof(void*)); for(i=0; i < jl_tuple_len(t); i++) { int n = env->n; tmp = type_match_(jl_tupleref(t,i), parent, env, 1, invariant); @@ -2098,7 +2209,7 @@ static jl_value_t *type_match_(jl_value_t *child, jl_value_t *parent, } return jl_true; } - if (jl_is_union_type(parent)) { + if (jl_is_uniontype(parent)) { jl_tuple_t *t = ((jl_uniontype_t*)parent)->types; int n = env->n; for(i=0; i < jl_tuple_len(t); i++) { @@ -2111,13 +2222,13 @@ static jl_value_t *type_match_(jl_value_t *child, jl_value_t *parent, } if (jl_is_tuple(child)) { - if (jl_is_tag_type(parent) && - ((jl_tag_type_t*)parent)->name == jl_ntuple_typename) { - jl_tuple_t *tp = ((jl_tag_type_t*)parent)->parameters; + if (jl_is_datatype(parent) && + ((jl_datatype_t*)parent)->name == jl_ntuple_typename) { + jl_tuple_t *tp = ((jl_datatype_t*)parent)->parameters; size_t alen = jl_tuple_len(child); // if child has a sequence type, there exists no N such that // NTuple[N,Any] could be its supertype. - if (alen>0 && jl_is_seq_type(jl_tupleref(child,alen-1))) + if (alen>0 && jl_is_vararg_type(jl_tupleref(child,alen-1))) return jl_false; jl_value_t *nt_len = jl_tupleref(tp,0); jl_value_t *childlen = jl_box_long(jl_tuple_len(child)); @@ -2132,7 +2243,7 @@ static jl_value_t *type_match_(jl_value_t *child, jl_value_t *parent, } jl_value_t *p_seq = (jl_value_t*)jl_tuple1(jl_tupleref(tp,1)); JL_GC_PUSH(&p_seq); - p_seq = (jl_value_t*)jl_apply_type((jl_value_t*)jl_seq_type, + p_seq = (jl_value_t*)jl_apply_type((jl_value_t*)jl_vararg_type, (jl_tuple_t*)p_seq); p_seq = (jl_value_t*)jl_tuple1(p_seq); tmp = tuple_match((jl_tuple_t*)child, (jl_tuple_t*)p_seq, @@ -2148,13 +2259,13 @@ static jl_value_t *type_match_(jl_value_t *child, jl_value_t *parent, return jl_false; } if (jl_is_tuple(parent)) { - if (jl_is_tag_type(child) && - ((jl_tag_type_t*)child)->name == jl_ntuple_typename) { + if (jl_is_datatype(child) && + ((jl_datatype_t*)child)->name == jl_ntuple_typename) { // only ((T>:S)...,) can be a supertype of NTuple[N,S] jl_tuple_t *tp = (jl_tuple_t*)parent; - jl_value_t *ntp = jl_tupleref(((jl_tag_type_t*)child)->parameters, + jl_value_t *ntp = jl_tupleref(((jl_datatype_t*)child)->parameters, 1); - if (jl_tuple_len(tp) == 1 && jl_is_seq_type(jl_tupleref(tp,0))) { + if (jl_tuple_len(tp) == 1 && jl_is_vararg_type(jl_tupleref(tp,0))) { return type_match_(ntp, jl_tparam0(jl_tupleref(tp,0)), env, morespecific, invariant); } @@ -2162,15 +2273,15 @@ static jl_value_t *type_match_(jl_value_t *child, jl_value_t *parent, return jl_false; } - if (!jl_is_some_tag_type(child) || !jl_is_some_tag_type(parent)) { + if (!jl_is_datatype(child) || !jl_is_datatype(parent)) { return jl_egal(child,parent) ? jl_true : jl_false; } - jl_tag_type_t *tta = (jl_tag_type_t*)child; - jl_tag_type_t *ttb = (jl_tag_type_t*)parent; + jl_datatype_t *tta = (jl_datatype_t*)child; + jl_datatype_t *ttb = (jl_datatype_t*)parent; int super = 0; - while (tta != (jl_tag_type_t*)jl_any_type) { + while (tta != (jl_datatype_t*)jl_any_type) { if (tta->name == ttb->name) { - // note: CompositeKind <: Type, but Type{T} <: CompositeKind + // note: DataType <: Type, but Type{T} <: DataType // for any specific T. if (super && morespecific && tta->name != jl_type_type->name) return jl_true; @@ -2190,7 +2301,7 @@ static jl_value_t *type_match_(jl_value_t *child, jl_value_t *parent, tta = tta->super; super = 1; } assert(!invariant); - if (((jl_tag_type_t*)child)->name == jl_type_type->name && + if (((jl_datatype_t*)child)->name == jl_type_type->name && ttb->name != jl_type_type->name) { // Type{T} also matches >:typeof(T) return type_match_(jl_full_type(jl_tparam0(child)), @@ -2208,8 +2319,10 @@ static jl_value_t *type_match_(jl_value_t *child, jl_value_t *parent, */ jl_value_t *jl_type_match_(jl_value_t *a, jl_value_t *b, int morespecific) { - cenv_t env; env.n = 0; memset(env.data, 0, sizeof(env.data)); - JL_GC_PUSHARGS(env.data, sizeof(env.data)/sizeof(void*)); + jl_value_t **rts; + JL_GC_PUSHARGS(rts, MAX_CENV_SIZE); + cenv_t env; env.n = 0; env.data = rts; + memset(env.data, 0, MAX_CENV_SIZE*sizeof(void*)); jl_value_t *m = type_match_(a, b, &env, morespecific, 0); if (m != jl_false) { m = (jl_value_t*)jl_alloc_tuple_uninit(env.n); @@ -2235,7 +2348,7 @@ jl_value_t *jl_type_match_morespecific(jl_value_t *a, jl_value_t *b) jl_tvar_t *jl_new_typevar(jl_sym_t *name, jl_value_t *lb, jl_value_t *ub) { - jl_tvar_t *tv = (jl_tvar_t*)newobj((jl_type_t*)jl_tvar_type, 4); + jl_tvar_t *tv = (jl_tvar_t*)newobj((jl_value_t*)jl_tvar_type, 4); tv->name = name; tv->lb = lb; tv->ub = ub; @@ -2254,64 +2367,63 @@ extern void jl_init_int32_int64_cache(void); void jl_init_types(void) { // create base objects - jl_struct_kind = jl_new_uninitialized_struct_type(10); - jl_struct_kind->type = (jl_type_t*)jl_struct_kind; - jl_typename_type = jl_new_uninitialized_struct_type(4); - jl_sym_type = jl_new_uninitialized_struct_type(0); + jl_datatype_type = jl_new_uninitialized_datatype(14); + jl_datatype_type->type = (jl_value_t*)jl_datatype_type; + jl_typename_type = jl_new_uninitialized_datatype(4); + jl_sym_type = jl_new_uninitialized_datatype(0); jl_symbol_type = jl_sym_type; jl_tuple_type = jl_alloc_tuple(1); - jl_tuple_type->type = (jl_type_t*)jl_tuple_type; + jl_tuple_type->type = (jl_value_t*)jl_tuple_type; +#ifdef OVERLAP_TUPLE_LEN + jl_tuple_set_len_unsafe(jl_tuple_type, 1); +#endif - jl_null = (jl_tuple_t*)newobj((jl_type_t*)jl_tuple_type, 1); + jl_null = (jl_tuple_t*)newobj((jl_value_t*)jl_tuple_type, 1); jl_tuple_set_len_unsafe(jl_null, 0); jl_nothing = (jl_value_t*)jl_null; // for bootstrapping - jl_tag_kind = jl_new_uninitialized_struct_type(6); - jl_tag_type_type = jl_tag_kind; - - jl_any_type = jl_new_tagtype((jl_value_t*)jl_symbol("Any"), NULL, jl_null); + jl_any_type = jl_new_abstracttype((jl_value_t*)jl_symbol("Any"), NULL, jl_null); jl_any_type->super = jl_any_type; - jl_type_type = jl_new_tagtype((jl_value_t*)jl_symbol("Type"), jl_any_type, jl_null); + jl_type_type = jl_new_abstracttype((jl_value_t*)jl_symbol("Type"), jl_any_type, jl_null); // initialize them. lots of cycles. - jl_tag_kind->name = jl_new_typename(jl_symbol("AbstractKind")); - jl_tag_kind->name->primary = (jl_value_t*)jl_tag_kind; - jl_tag_kind->super = jl_type_type; - jl_tag_kind->parameters = jl_null; - jl_tag_kind->names = jl_tuple(6, jl_symbol(""),jl_symbol(""),jl_symbol(""), - jl_symbol("name"), jl_symbol("super"), - jl_symbol("parameters")); - jl_tag_kind->types = jl_tuple(6, jl_any_type, jl_any_type, jl_any_type, - jl_typename_type, jl_type_type, - jl_tuple_type); - jl_tag_kind->fptr = jl_f_no_function; - jl_tag_kind->env = (jl_value_t*)jl_null; - jl_tag_kind->linfo = NULL; - jl_tag_kind->ctor_factory = NULL; - jl_tag_kind->instance = NULL; - jl_tag_kind->uid = jl_assign_type_uid(); - - jl_struct_kind->name = jl_new_typename(jl_symbol("CompositeKind")); - jl_struct_kind->name->primary = (jl_value_t*)jl_struct_kind; - jl_struct_kind->super = (jl_tag_type_t*)jl_type_type; - jl_struct_kind->parameters = jl_null; - jl_struct_kind->names = jl_tuple(10, jl_symbol("fptr"), - jl_symbol("env"), jl_symbol("code"), - jl_symbol("name"), jl_symbol("super"), - jl_symbol("parameters"), - jl_symbol("names"), jl_symbol("types"), - jl_symbol(""), jl_symbol("")); - jl_struct_kind->types = jl_tuple(10, jl_any_type, jl_any_type, jl_any_type, - jl_typename_type, jl_type_type, - jl_tuple_type, jl_tuple_type, - jl_tuple_type, jl_any_type, jl_any_type); - jl_struct_kind->fptr = jl_f_no_function; - jl_struct_kind->env = (jl_value_t*)jl_null; - jl_struct_kind->linfo = NULL; - jl_struct_kind->ctor_factory = NULL; - jl_struct_kind->instance = NULL; - jl_struct_kind->uid = jl_assign_type_uid(); + jl_datatype_type->name = jl_new_typename(jl_symbol("DataType")); + jl_datatype_type->name->primary = (jl_value_t*)jl_datatype_type; + jl_datatype_type->super = jl_type_type; + jl_datatype_type->parameters = jl_null; + jl_datatype_type->names = jl_tuple(14, jl_symbol("fptr"), + jl_symbol("env"), + jl_symbol("code"), + jl_symbol("name"), + jl_symbol("super"), + jl_symbol("parameters"), + jl_symbol("names"), + jl_symbol("types"), + jl_symbol("ctor_factory"), + jl_symbol("instance"), + jl_symbol("size"), + jl_symbol("abstract"), + jl_symbol("mutable"), + jl_symbol("pointerfree")); + jl_datatype_type->types = jl_tuple(14, jl_any_type,jl_any_type,jl_any_type, + jl_typename_type, jl_type_type, + jl_tuple_type, jl_tuple_type, + jl_tuple_type, jl_any_type, jl_any_type, + jl_any_type, //types will be fixed later + jl_any_type, jl_any_type, jl_any_type); + jl_datatype_type->fptr = jl_f_no_function; + jl_datatype_type->env = (jl_value_t*)jl_null; + jl_datatype_type->linfo = NULL; + jl_datatype_type->ctor_factory = NULL; + jl_datatype_type->instance = NULL; + jl_datatype_type->uid = jl_assign_type_uid(); + jl_datatype_type->struct_decl = NULL; + jl_datatype_type->abstract = 0; + jl_datatype_type->pointerfree = 0; + // NOTE: types should not really be mutable, but the instance and + // struct_decl fields are basically caches, which are mutated. + jl_datatype_type->mutabl = 1; jl_typename_type->name = jl_new_typename(jl_symbol("TypeName")); jl_typename_type->name->primary = (jl_value_t*)jl_typename_type; @@ -2319,15 +2431,19 @@ void jl_init_types(void) jl_typename_type->parameters = jl_null; jl_typename_type->names = jl_tuple(4, jl_symbol("name"), jl_symbol("module"), - jl_symbol(""), jl_symbol("")); + jl_symbol("primary"), jl_symbol("")); jl_typename_type->types = jl_tuple(4, jl_sym_type, jl_any_type, - jl_type_type, jl_tuple_type); + jl_type_type, jl_any_type); jl_typename_type->uid = jl_assign_type_uid(); jl_typename_type->fptr = jl_f_no_function; jl_typename_type->env = (jl_value_t*)jl_null; jl_typename_type->linfo = NULL; jl_typename_type->ctor_factory = NULL; jl_typename_type->instance = NULL; + jl_typename_type->struct_decl = NULL; + jl_typename_type->abstract = 0; + jl_typename_type->pointerfree = 0; + jl_typename_type->mutabl = 1; jl_sym_type->name = jl_new_typename(jl_symbol("Symbol")); jl_sym_type->name->primary = (jl_value_t*)jl_sym_type; @@ -2341,214 +2457,218 @@ void jl_init_types(void) jl_sym_type->ctor_factory = NULL; jl_sym_type->instance = NULL; jl_sym_type->uid = jl_assign_type_uid(); + jl_sym_type->struct_decl = NULL; + jl_sym_type->size = 0; + jl_sym_type->abstract = 0; + jl_sym_type->pointerfree = 0; + jl_sym_type->mutabl = 1; // now they can be used to create the remaining base kinds and types - jl_union_kind = jl_new_struct_type(jl_symbol("UnionKind"), - jl_type_type, jl_null, - jl_tuple(1, jl_symbol("types")), - jl_tuple(1, jl_tuple_type)); - jl_union_kind->fptr = jl_f_no_function; - - jl_bottom_type = (jl_type_t*)jl_new_struct(jl_union_kind, jl_null); - - jl_bits_kind = - jl_new_struct_type(jl_symbol("BitsKind"), jl_type_type, - jl_null, - jl_tuple(7, jl_symbol(""), jl_symbol(""), - jl_symbol(""), - jl_symbol("name"), jl_symbol("super"), - jl_symbol("parameters"), - jl_symbol("nbits")), - jl_tuple(7, jl_any_type, jl_any_type, jl_any_type, - jl_typename_type, jl_type_type, - jl_tuple_type, jl_any_type)); - // cannot be created with normal constructor due to hidden fields - jl_bits_kind->fptr = jl_f_no_function; - - jl_tvar_type = jl_new_struct_type(jl_symbol("TypeVar"), - jl_any_type, jl_null, - jl_tuple(3, jl_symbol("name"), - jl_symbol("lb"), - jl_symbol("ub")), - jl_tuple(3, jl_sym_type, jl_type_type, - jl_type_type)); + jl_uniontype_type = jl_new_datatype(jl_symbol("UnionType"), + jl_type_type, jl_null, + jl_tuple(1, jl_symbol("types")), + jl_tuple(1, jl_tuple_type), + 0, 0); + jl_uniontype_type->fptr = jl_f_no_function; + + jl_bottom_type = (jl_value_t*)jl_new_struct(jl_uniontype_type, jl_null); + + jl_tvar_type = jl_new_datatype(jl_symbol("TypeVar"), + jl_any_type, jl_null, + jl_tuple(3, jl_symbol("name"), + jl_symbol("lb"), + jl_symbol("ub")), + jl_tuple(3, jl_sym_type, jl_type_type, + jl_type_type), + 0, 0); jl_tvar_type->fptr = jl_f_typevar; - jl_undef_type = jl_new_tagtype((jl_value_t*)jl_symbol("Undef"), - jl_any_type, jl_null); + jl_undef_type = jl_new_abstracttype((jl_value_t*)jl_symbol("Undef"), + jl_any_type, jl_null); - jl_top_type = jl_new_struct(jl_union_kind, + jl_top_type = jl_new_struct(jl_uniontype_type, jl_tuple2(jl_any_type, jl_undef_type)); jl_tvar_t *tttvar = jl_new_typevar(jl_symbol("T"), - (jl_value_t*)jl_bottom_type, - jl_top_type); + (jl_value_t*)jl_bottom_type,jl_top_type); jl_type_type->parameters = jl_tuple(1, tttvar); jl_tuple_t *tv; - tv = jl_tuple1(tvar("T")); - jl_seq_type = jl_new_tagtype((jl_value_t*)jl_symbol("..."), - jl_any_type, tv); + jl_vararg_type = jl_new_abstracttype((jl_value_t*)jl_symbol("Vararg"), + jl_any_type, tv); jl_tupleset(jl_tuple_type, 0, - (jl_value_t*)jl_apply_type((jl_value_t*)jl_seq_type, + (jl_value_t*)jl_apply_type((jl_value_t*)jl_vararg_type, jl_tuple(1,jl_any_type))); tv = jl_tuple2(tvar("N"), tvar("T")); - jl_ntuple_type = jl_new_tagtype((jl_value_t*)jl_symbol("NTuple"), - jl_any_type, tv); + jl_ntuple_type = jl_new_abstracttype((jl_value_t*)jl_symbol("NTuple"), + jl_any_type, tv); jl_ntuple_typename = jl_ntuple_type->name; + jl_tupletype_type = + (jl_value_t*)jl_tuple1(jl_apply_type((jl_value_t*)jl_vararg_type, + jl_tuple1(jl_type_type))); + // non-primitive definitions follow jl_int32_type = NULL; - jl_int32_type = jl_new_bits_type((jl_value_t*)jl_symbol("Int32"), - jl_any_type, jl_null, 32); + jl_int32_type = jl_new_bitstype((jl_value_t*)jl_symbol("Int32"), + jl_any_type, jl_null, 32); jl_int64_type = NULL; - jl_int64_type = jl_new_bits_type((jl_value_t*)jl_symbol("Int64"), - jl_any_type, jl_null, 64); + jl_int64_type = jl_new_bitstype((jl_value_t*)jl_symbol("Int64"), + jl_any_type, jl_null, 64); jl_init_int32_int64_cache(); - jl_tupleset(jl_bits_kind->types, 6, (jl_value_t*)jl_int32_type); jl_bool_type = NULL; - jl_bool_type = jl_new_bits_type((jl_value_t*)jl_symbol("Bool"), - jl_any_type, jl_null, 8); + jl_bool_type = jl_new_bitstype((jl_value_t*)jl_symbol("Bool"), + jl_any_type, jl_null, 8); jl_false = jl_box8(jl_bool_type, 0); jl_true = jl_box8(jl_bool_type, 1); jl_method_type = - jl_new_struct_type(jl_symbol("Method"), jl_any_type, jl_null, - jl_tuple(6, jl_symbol("sig"), jl_symbol("va"), - jl_symbol("tvars"), jl_symbol("func"), - jl_symbol("invokes"), jl_symbol("next")), - jl_tuple(6, jl_tuple_type, jl_bool_type, - jl_tuple_type, jl_any_type, - jl_any_type, jl_any_type)); + jl_new_datatype(jl_symbol("Method"), jl_any_type, jl_null, + jl_tuple(6, jl_symbol("sig"), jl_symbol("va"), + jl_symbol("tvars"), jl_symbol("func"), + jl_symbol("invokes"), jl_symbol("next")), + jl_tuple(6, jl_tuple_type, jl_bool_type, + jl_tuple_type, jl_any_type, + jl_any_type, jl_any_type), + 0, 1); jl_method_type->fptr = jl_f_no_function; jl_methtable_type = - jl_new_struct_type(jl_symbol("MethodTable"), jl_any_type, jl_null, - jl_tuple(6, jl_symbol("name"), jl_symbol("defs"), - jl_symbol("cache"), jl_symbol("cache_arg1"), - jl_symbol("cache_targ"), - jl_symbol("max_args")), - jl_tuple(6, jl_sym_type, jl_any_type, jl_any_type, - jl_any_type, jl_any_type, jl_long_type)); + jl_new_datatype(jl_symbol("MethodTable"), jl_any_type, jl_null, + jl_tuple(7, jl_symbol("name"), jl_symbol("defs"), + jl_symbol("cache"), jl_symbol("cache_arg1"), + jl_symbol("cache_targ"), + jl_symbol("max_args"), jl_symbol("kwsorter")), + jl_tuple(7, jl_sym_type, jl_any_type, jl_any_type, + jl_any_type, jl_any_type, jl_long_type, + jl_any_type), + 0, 1); jl_methtable_type->fptr = jl_f_no_function; tv = jl_tuple2(tvar("T"), tvar("N")); - jl_abstractarray_type = jl_new_tagtype((jl_value_t*)jl_symbol("AbstractArray"), - jl_any_type, tv); + jl_abstractarray_type = jl_new_abstracttype((jl_value_t*)jl_symbol("AbstractArray"), + jl_any_type, tv); tv = jl_tuple2(tvar("T"), tvar("N")); jl_array_type = - jl_new_struct_type(jl_symbol("Array"), - (jl_tag_type_t*) - jl_apply_type((jl_value_t*)jl_abstractarray_type, tv), - tv, - jl_null, jl_null); + jl_new_datatype(jl_symbol("Array"), + (jl_datatype_t*) + jl_apply_type((jl_value_t*)jl_abstractarray_type, tv), + tv, + jl_null, jl_null, 0, 1); jl_array_typename = jl_array_type->name; jl_array_type->linfo = NULL; + jl_array_type->pointerfree = 0; jl_initialize_generic_function((jl_function_t*)jl_array_type, jl_array_typename->name); jl_array_any_type = - (jl_type_t*)jl_apply_type((jl_value_t*)jl_array_type, - jl_tuple(2, jl_any_type, - jl_box_long(1))); + (jl_value_t*)jl_apply_type((jl_value_t*)jl_array_type, + jl_tuple(2, jl_any_type, + jl_box_long(1))); jl_array_symbol_type = - (jl_type_t*)jl_apply_type((jl_value_t*)jl_array_type, - jl_tuple(2, jl_symbol_type, - jl_box_long(1))); + (jl_value_t*)jl_apply_type((jl_value_t*)jl_array_type, + jl_tuple(2, jl_symbol_type, + jl_box_long(1))); jl_expr_type = - jl_new_struct_type(jl_symbol("Expr"), - jl_any_type, jl_null, - jl_tuple(3, jl_symbol("head"), jl_symbol("args"), - jl_symbol("typ")), - jl_tuple(3, jl_sym_type, jl_array_any_type, - jl_any_type)); + jl_new_datatype(jl_symbol("Expr"), + jl_any_type, jl_null, + jl_tuple(3, jl_symbol("head"), jl_symbol("args"), + jl_symbol("typ")), + jl_tuple(3, jl_sym_type, jl_array_any_type, + jl_any_type), + 0, 1); jl_expr_type->fptr = jl_f_new_expr; jl_linenumbernode_type = - jl_new_struct_type(jl_symbol("LineNumberNode"), jl_any_type, jl_null, - jl_tuple(1, jl_symbol("line")), - jl_tuple(1, jl_long_type)); + jl_new_datatype(jl_symbol("LineNumberNode"), jl_any_type, jl_null, + jl_tuple(1, jl_symbol("line")), + jl_tuple(1, jl_long_type), 0, 0); jl_labelnode_type = - jl_new_struct_type(jl_symbol("LabelNode"), jl_any_type, jl_null, - jl_tuple(1, jl_symbol("label")), - jl_tuple(1, jl_long_type)); + jl_new_datatype(jl_symbol("LabelNode"), jl_any_type, jl_null, + jl_tuple(1, jl_symbol("label")), + jl_tuple(1, jl_long_type), 0, 0); jl_gotonode_type = - jl_new_struct_type(jl_symbol("GotoNode"), jl_any_type, jl_null, - jl_tuple(1, jl_symbol("label")), - jl_tuple(1, jl_long_type)); + jl_new_datatype(jl_symbol("GotoNode"), jl_any_type, jl_null, + jl_tuple(1, jl_symbol("label")), + jl_tuple(1, jl_long_type), 0, 0); jl_quotenode_type = - jl_new_struct_type(jl_symbol("QuoteNode"), jl_any_type, jl_null, - jl_tuple(1, jl_symbol("value")), - jl_tuple(1, jl_any_type)); + jl_new_datatype(jl_symbol("QuoteNode"), jl_any_type, jl_null, + jl_tuple(1, jl_symbol("value")), + jl_tuple(1, jl_any_type), 0, 0); jl_topnode_type = - jl_new_struct_type(jl_symbol("TopNode"), jl_any_type, jl_null, - jl_tuple(1, jl_symbol("name")), - jl_tuple(1, jl_sym_type)); + jl_new_datatype(jl_symbol("TopNode"), jl_any_type, jl_null, + jl_tuple(1, jl_symbol("name")), + jl_tuple(1, jl_sym_type), 0, 0); jl_module_type = - jl_new_struct_type(jl_symbol("Module"), jl_any_type, jl_null, - jl_tuple(2, jl_symbol("name"), jl_symbol("parent")), - jl_tuple(2, jl_sym_type, jl_any_type)); + jl_new_datatype(jl_symbol("Module"), jl_any_type, jl_null, + jl_tuple(2, jl_symbol("name"), jl_symbol("parent")), + jl_tuple(2, jl_sym_type, jl_any_type), 0, 1); + jl_module_type->fptr = jl_f_new_module; jl_tupleset(jl_typename_type->types, 1, jl_module_type); jl_lambda_info_type = - jl_new_struct_type(jl_symbol("LambdaStaticData"), - jl_any_type, jl_null, - jl_tuple(12, jl_symbol("ast"), jl_symbol("sparams"), - jl_symbol("tfunc"), jl_symbol("name"), - /* - jl_symbol("roots"), jl_symbol("specTypes"), + jl_new_datatype(jl_symbol("LambdaStaticData"), + jl_any_type, jl_null, + jl_tuple(14, jl_symbol("ast"), jl_symbol("sparams"), + jl_symbol("tfunc"), jl_symbol("name"), + jl_symbol("roots"), + /* jl_symbol("specTypes"), jl_symbol("unspecialized"), jl_symbol("specializations")*/ - jl_symbol(""), jl_symbol(""), - jl_symbol(""), jl_symbol(""), - jl_symbol("inferred"), - jl_symbol("file"), jl_symbol("line"), - jl_symbol("module")), - jl_tuple(12, jl_any_type, jl_tuple_type, - jl_any_type, jl_sym_type, - jl_any_type, jl_tuple_type, - jl_any_type, jl_array_any_type, - jl_bool_type, - jl_sym_type, jl_long_type, - jl_module_type)); + jl_symbol(""), jl_symbol(""), jl_symbol(""), + jl_symbol("module"), jl_symbol("def"), + jl_symbol("capt"), + jl_symbol("file"), jl_symbol("line"), + jl_symbol("inferred")), + jl_tuple(14, jl_any_type, jl_tuple_type, + jl_any_type, jl_sym_type, + jl_any_type, jl_tuple_type, + jl_any_type, jl_array_any_type, + jl_module_type, jl_any_type, + jl_any_type, + jl_sym_type, jl_int32_type, + jl_bool_type), + 0, 1); jl_lambda_info_type->fptr = jl_f_no_function; jl_box_type = - jl_new_struct_type(jl_symbol("Box"), - jl_any_type, jl_null, - jl_tuple(1, jl_symbol("contents")), - jl_tuple(1, jl_any_type)); + jl_new_datatype(jl_symbol("Box"), + jl_any_type, jl_null, + jl_tuple(1, jl_symbol("contents")), + jl_tuple(1, jl_any_type), 0, 1); jl_box_type->fptr = jl_f_new_box; jl_box_typename = jl_box_type->name; - jl_box_any_type = (jl_type_t*)jl_box_type; + jl_box_any_type = (jl_value_t*)jl_box_type; jl_typector_type = - jl_new_struct_type(jl_symbol("TypeConstructor"), - jl_type_type, jl_null, - jl_tuple(2, jl_symbol("parameters"), - jl_symbol("body")), - jl_tuple(2, jl_tuple_type, jl_any_type)); + jl_new_datatype(jl_symbol("TypeConstructor"), + jl_type_type, jl_null, + jl_tuple(2, jl_symbol("parameters"), + jl_symbol("body")), + jl_tuple(2, jl_tuple_type, jl_any_type), + 0, 0); jl_typector_type->fptr = jl_f_new_type_constructor; jl_function_type = - jl_new_struct_type(jl_symbol("Function"), jl_any_type, jl_null, - jl_tuple(3, jl_symbol("fptr"), jl_symbol("env"), - jl_symbol("code")), - jl_tuple(3, jl_any_type, jl_any_type, - jl_lambda_info_type)); + jl_new_datatype(jl_symbol("Function"), jl_any_type, jl_null, + jl_tuple(3, jl_symbol("fptr"), jl_symbol("env"), + jl_symbol("code")), + jl_tuple(3, jl_any_type, jl_any_type, + jl_lambda_info_type), + 0, 1); jl_function_type->fptr = jl_f_no_function; jl_tupleset(jl_method_type->types, 3, jl_function_type); @@ -2556,55 +2676,57 @@ void jl_init_types(void) jl_bottom_func = jl_new_closure(jl_f_no_function, JL_NULL, NULL); - jl_intrinsic_type = jl_new_bits_type((jl_value_t*)jl_symbol("IntrinsicFunction"), - jl_any_type, jl_null, 32); + jl_intrinsic_type = jl_new_bitstype((jl_value_t*)jl_symbol("IntrinsicFunction"), + jl_any_type, jl_null, 32); tv = jl_tuple1(tvar("T")); jl_pointer_type = - jl_new_bits_type((jl_value_t*)jl_symbol("Ptr"), jl_any_type, tv, - sizeof(void*)*8); + jl_new_bitstype((jl_value_t*)jl_symbol("Ptr"), jl_any_type, tv, + sizeof(void*)*8); // Type{T} jl_typetype_tvar = jl_new_typevar(jl_symbol("T"), (jl_value_t*)jl_bottom_type, jl_top_type); - jl_typetype_type = (jl_tag_type_t*) - jl_apply_type((jl_value_t*)jl_type_type, - jl_tuple(1,jl_typetype_tvar)); + jl_typetype_type = (jl_datatype_t*)jl_apply_type((jl_value_t*)jl_type_type, + jl_tuple(1,jl_typetype_tvar)); jl_ANY_flag = (jl_value_t*)tvar("ANY"); // complete builtin type metadata jl_value_t *pointer_void = jl_apply_type((jl_value_t*)jl_pointer_type, jl_tuple(1,jl_bottom_type)); - jl_tupleset(jl_struct_kind->types, 0, pointer_void); + jl_voidpointer_type = (jl_datatype_t*)pointer_void; + jl_tupleset(jl_datatype_type->types, 0, pointer_void); + jl_tupleset(jl_datatype_type->types, 10, jl_int32_type); + jl_tupleset(jl_datatype_type->types, 11, (jl_value_t*)jl_bool_type); + jl_tupleset(jl_datatype_type->types, 12, (jl_value_t*)jl_bool_type); + jl_tupleset(jl_datatype_type->types, 13, (jl_value_t*)jl_bool_type); jl_tupleset(jl_function_type->types, 0, pointer_void); - jl_compute_struct_offsets(jl_struct_kind); - jl_compute_struct_offsets(jl_typename_type); - jl_compute_struct_offsets(jl_tag_kind); - jl_compute_struct_offsets(jl_union_kind); - jl_compute_struct_offsets(jl_bits_kind); - jl_compute_struct_offsets(jl_tvar_type); - jl_compute_struct_offsets(jl_method_type); - jl_compute_struct_offsets(jl_methtable_type); - jl_compute_struct_offsets(jl_expr_type); - jl_compute_struct_offsets(jl_linenumbernode_type); - jl_compute_struct_offsets(jl_labelnode_type); - jl_compute_struct_offsets(jl_gotonode_type); - jl_compute_struct_offsets(jl_quotenode_type); - jl_compute_struct_offsets(jl_topnode_type); - jl_compute_struct_offsets(jl_module_type); - jl_compute_struct_offsets(jl_lambda_info_type); - jl_compute_struct_offsets(jl_box_type); - jl_compute_struct_offsets(jl_typector_type); - jl_compute_struct_offsets(jl_function_type); + jl_compute_field_offsets(jl_datatype_type); + jl_compute_field_offsets(jl_typename_type); + jl_compute_field_offsets(jl_uniontype_type); + jl_compute_field_offsets(jl_tvar_type); + jl_compute_field_offsets(jl_method_type); + jl_compute_field_offsets(jl_methtable_type); + jl_compute_field_offsets(jl_expr_type); + jl_compute_field_offsets(jl_linenumbernode_type); + jl_compute_field_offsets(jl_labelnode_type); + jl_compute_field_offsets(jl_gotonode_type); + jl_compute_field_offsets(jl_quotenode_type); + jl_compute_field_offsets(jl_topnode_type); + jl_compute_field_offsets(jl_module_type); + jl_compute_field_offsets(jl_lambda_info_type); + jl_compute_field_offsets(jl_box_type); + jl_compute_field_offsets(jl_typector_type); + jl_compute_field_offsets(jl_function_type); call_sym = jl_symbol("call"); call1_sym = jl_symbol("call1"); quote_sym = jl_symbol("quote"); top_sym = jl_symbol("top"); - dots_sym = jl_symbol("..."); + dots_sym = jl_symbol("Vararg"); line_sym = jl_symbol("line"); jl_continue_sym = jl_symbol("continue"); error_sym = jl_symbol("error"); @@ -2640,4 +2762,6 @@ void jl_init_types(void) compositetype_sym = jl_symbol("composite_type"); type_goto_sym = jl_symbol("type_goto"); toplevel_sym = jl_symbol("toplevel"); + tuple_sym = jl_symbol("tuple"); + kw_sym = jl_symbol("kw"); } diff --git a/src/jltypes_internal.h b/src/jltypes_internal.h index 8a8ce21399c96..aea1c17e182c2 100644 --- a/src/jltypes_internal.h +++ b/src/jltypes_internal.h @@ -1,7 +1,7 @@ #ifndef JLTYPES_INTERNAL_H #define JLTYPES_INTERNAL_H -void jl_cache_type_(jl_tag_type_t *type); +jl_value_t *jl_cache_type_(jl_datatype_t *type); int jl_get_t_uid_ctr(void); void jl_set_t_uid_ctr(int i); diff --git a/src/julia-parser.scm b/src/julia-parser.scm index d2d007a84cf1c..57816ba55f1d0 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -74,6 +74,9 @@ (define (assignment? e) (and (pair? e) (eq? (car e) '=))) +(define (typedecl? e) + (and (length= e 3) (eq? (car e) |::|) (symbol? (cadr e)))) + (define unary-ops '(+ - ! ~ |<:| |>:|)) ; operators that are both unary and binary @@ -82,12 +85,12 @@ ; operators that are special forms, not function names (define syntactic-operators '(= := += -= *= /= //= .//= .*= ./= |\\=| |.\\=| ^= .^= %= |\|=| &= $= => - <<= >>= >>>= -> --> |\|\|| && |::| |.|)) + <<= >>= >>>= -> --> |\|\|| && |::| |.| ...)) (define syntactic-unary-operators '($ &)) (define reserved-words '(begin while if for try return break continue function macro quote let local global const - abstract typealias type bitstype ccall do + abstract typealias type bitstype immutable ccall do module baremodule using import export importall)) (define (syntactic-op? op) (memq op syntactic-operators)) @@ -146,8 +149,11 @@ (let loop ((str (string c)) (c (peek-char port))) (if (and (not (eof-object? c)) (opchar? c)) - (let ((newop (string str c))) - (if (operator? (string->symbol newop)) + (let* ((newop (string str c)) + (opsym (string->symbol newop))) + (if (eq? opsym '...) + (error "invalid syntax ....")) + (if (operator? opsym) (begin (read-char port) (loop newop (peek-char port))) (string->symbol str))) @@ -413,13 +419,20 @@ (define (parse-cond s) (let ((ex (parse-or s))) - (if (not (eq? (peek-token s) '?)) - ex - (begin (take-token s) - (let ((then (without-range-colon (parse-eq* s)))) - (if (not (eq? (take-token s) ':)) - (error "colon expected in ? expression") - (list 'if ex then (parse-cond s)))))))) + (cond ((eq? (peek-token s) '?) + (begin (take-token s) + (let ((then (without-range-colon (parse-eq* s)))) + (if (not (eq? (take-token s) ':)) + (error "colon expected in ? expression") + (list 'if ex then (parse-cond s)))))) + #;((string? ex) + (let loop ((args (list ex))) + (let ((next (peek-token s))) + (if (or (eof-object? next) (closing-token? next) + (newline? next)) + `(call (top string) ,@(reverse args)) + (loop (cons (parse-or s) args)))))) + (else ex)))) (define (invalid-initial-token? tok) (or (eof-object? tok) @@ -518,6 +531,10 @@ (if (closing-token? (peek-token s)) ': ; missing last argument (parse-expr s)))) + (if (and (not (ts:space? s)) + (or (eq? argument '<) (eq? argument '>))) + (error (string ': argument " found instead of " + argument ':))) (if first? (loop (list t ex argument) #f) (loop (append ex (list argument)) #t))))) @@ -577,17 +594,6 @@ (define (parse-shift s) (parse-LtoR s parse-term (prec-ops 8))) -; given an expression and the next token, is there a juxtaposition -; operator between them? -(define (juxtapose? expr t) - (and (not (operator? t)) - (not (operator? expr)) - (not (memq t reserved-words)) - (not (closing-token? t)) - (not (newline? t)) - (or (number? expr) - (not (memv t '(#\( #\[ #\{)))))) - (define (parse-term s) (let ((ops (prec-ops 9))) (let loop ((ex (parse-rational s)) @@ -632,16 +638,28 @@ (define (maybe-negate op num) (if (eq? op '-) (- num) num)) +; given an expression and the next token, is there a juxtaposition +; operator between them? +(define (juxtapose? expr t) + (and (not (operator? t)) + (not (operator? expr)) + (not (memq t reserved-words)) + (not (closing-token? t)) + (not (newline? t)) + (not (and (pair? expr) (eq? (car expr) '...))) + (or (number? expr) + (not (memv t '(#\( #\[ #\{)))))) + (define (parse-juxtapose ex s) (let ((next (peek-token s))) ;; numeric literal juxtaposition is a unary operator - (if (and (juxtapose? ex next) - (not (ts:space? s))) - (begin - #;(if (and (number? ex) (= ex 0)) - (error "juxtaposition with literal 0")) - `(call * ,ex ,(parse-unary s))) - ex))) + (cond ((and (juxtapose? ex next) + (not (ts:space? s))) + (begin + #;(if (and (number? ex) (= ex 0)) + (error "juxtaposition with literal 0")) + `(call * ,ex ,(parse-unary s)))) + (else ex)))) (define (parse-unary s) (let ((t (require-token s))) @@ -666,7 +684,7 @@ (list 'call op (parse-factor s))) num)) (let ((next (peek-token s))) - (cond ((closing-token? next) + (cond ((or (closing-token? next) (newline? next)) op) ; return operator by itself, as in (+) ((eqv? next #\{) ;; this case is +{T}(x::T) = ... (ts:put-back! s op) @@ -710,7 +728,8 @@ ((->) (take-token s) ;; -> is unusual: it binds tightly on the left and ;; loosely on the right. - (list '-> ex (parse-eq* s))) + (let ((lno (line-number-filename-node s))) + `(-> ,ex (block ,lno ,(parse-eq* s))))) (else ex))))) @@ -755,26 +774,34 @@ ; ref is syntax, so we can distinguish ; a[i] = x from ; ref(a,i) = x - (let ((al (with-end-symbol (parse-ref s #\] )))) - (if (dict-literal? ex) - (if (and (not(null? al)) (eq? (car al) 'comprehension)) - (if (and (not(null? (cdr al))) - (dict-literal? (cadr al))) - (loop (list* 'typed-dict-comprehension ex (cdr al))) - (error "invalid dict comprehension syntax")) - (if (every dict-literal? al) - (loop (list* 'typed-dict ex al)) - (else (error "invalid dict literal")))) - (if (any dict-literal? al) - (error "invalid dict type specification") - (if (and (not(null? al)) (eq? (car al) 'comprehension)) - (loop (list* 'typed-comprehension ex (cdr al))) - (loop (list* 'ref ex al))))))) + (let ((al (with-end-symbol (parse-cat s #\] )))) + (if (null? al) + (if (dict-literal? ex) + (loop (list 'typed_dict ex)) + (loop (list 'ref ex))) + (case (car al) + ((dict) (loop (list* 'typed_dict ex (cdr al)))) + ((hcat) (loop (list* 'typed_hcat ex (cdr al)))) + ((vcat) + (if (any (lambda (x) + (and (pair? x) (eq? (car x) 'row))) + (cdr al)) + (loop (list* 'typed_vcat ex (cdr al))) + (loop (list* 'ref ex (cdr al))))) + ((comprehension) + (loop (list* 'typed_comprehension ex (cdr al)))) + ((dict_comprehension) + (loop (list* 'typed_dict_comprehension ex (cdr al)))) + (else (error "unknown parse-cat result (internal error)")))))) ((|.|) (take-token s) (if (eqv? (peek-token s) #\() (loop `(|.| ,ex ,(parse-atom s))) - (loop `(|.| ,ex (quote ,(parse-atom s)))))) + (let ((name (parse-atom s))) + (if (and (pair? name) (eq? (car name) 'macrocall)) + `(macrocall (|.| ,ex (quote ,(cadr name))) + ,@(cddr name)) + (loop `(|.| ,ex (quote ,name))))))) ((|.'| |'|) (take-token s) (loop (list t ex))) ((#\{ ) (take-token s) @@ -784,16 +811,18 @@ (if (and (symbol? ex) (not (operator? ex)) (not (ts:space? s))) ;; custom prefixed string literals, x"s" => @x_str "s" - (let ((str (begin (take-token s) - (parse-string-literal s))) - (macname (symbol (string #\@ ex '_str)))) - (let ((nxt (peek-token s))) - (if (and (symbol? nxt) (not (operator? nxt)) - (not (ts:space? s))) - ;; string literal suffix, "s"x - (loop `(macrocall ,macname ,(car str) - ,(string (take-token s)))) - (loop `(macrocall ,macname ,(car str)))))) + (let* ((str (begin (take-token s) + (parse-string-literal s #t))) + (nxt (peek-token s)) + (suffix (if (triplequote-string-literal? str) '_mstr '_str)) + (macname (symbol (string #\@ ex suffix))) + (macstr (cdr str))) + (if (and (symbol? nxt) (not (operator? nxt)) + (not (ts:space? s))) + ;; string literal suffix, "s"x + (loop `(macrocall ,macname ,@macstr + ,(string (take-token s)))) + (loop `(macrocall ,macname ,@macstr)))) ex)) (else ex)))))))) @@ -823,10 +852,18 @@ (with-normal-ops (without-whitespace-newline (case word - ((begin) (begin0 (parse-block s) - (expect-end s))) - ((quote) (begin0 (list 'quote (parse-block s)) - (expect-end s))) + ((begin quote) + (let ((loc (begin (skip-ws-and-comments (ts:port s)) + (line-number-filename-node s))) + (blk (parse-block s))) + (expect-end s) + (let ((blk (if (and (length> blk 1) + (pair? (cadr blk)) (eq? (caadr blk) 'line)) + (list* 'block loc (cddr blk)) + blk))) + (if (eq? word 'quote) + (list 'quote blk) + blk)))) ((while) (begin0 (list 'while (parse-cond s) (parse-block s)) (expect-end s))) ((for) @@ -895,10 +932,15 @@ (list word def body))) ((abstract) (list 'abstract (parse-subtype-spec s))) - ((type) - (let ((sig (parse-subtype-spec s))) - (begin0 (list word sig (parse-block s)) - (expect-end s)))) + ((type immutable) + (let ((immu? (eq? word 'immutable))) + (if (and immu? (eq? (peek-token s) 'type)) + ;; allow "immutable type" + (take-token s)) + (let ((sig (parse-subtype-spec s))) + (begin0 (list 'type (if (eq? word 'type) 'true 'false) + sig (parse-block s)) + (expect-end s))))) ((bitstype) (list 'bitstype (with-space-sensitive (parse-cond s)) (parse-subtype-spec s))) @@ -974,20 +1016,19 @@ ;; add definitions for module-local eval (let ((x (gensym))) `(= (call eval ,x) - (call (|.| Core 'eval) ,name ,x))) + (call (|.| (top Core) 'eval) ,name ,x))) `(= (call eval m x) - (call (|.| Core 'eval) m x)) + (call (|.| (top Core) 'eval) m x)) (cdr body)) body)))) ((export) (let ((es (map macrocall-to-atsym - (parse-comma-separated-assignments s)))) + (parse-comma-separated s parse-atom)))) (if (not (every symbol? es)) (error "invalid export statement")) `(export ,@es))) - ((import using) - (let ((imports (parse-comma-separated s (lambda (s) - (parse-import s word))))) + ((import using importall) + (let ((imports (parse-imports s word))) (if (length= imports 1) (car imports) (cons 'toplevel imports)))) @@ -998,7 +1039,7 @@ (take-token s) (let ((al (parse-arglist s #\)))) (if (and (length> al 1) - (memq (cadr al) '(cdecl stdcall fastcall))) + (memq (cadr al) '(cdecl stdcall fastcall thiscall))) ;; place (callingconv) at end of arglist `(ccall ,(car al) ,@(cddr al) (,(cadr al))) `(ccall ,.al)))))) @@ -1020,6 +1061,27 @@ (cadr e) e)) +(define (parse-imports s word) + (let* ((first (parse-import s word)) + (from (if (and (eq? (peek-token s) ':) (not (ts:space? s))) + (begin (take-token s) #t) + (begin + (if (eqv? (peek-token s) #\,) + (begin (take-token s) + (if (eqv? (peek-token s) #\newline) + (take-token s)))) + #f))) + (rest (if (or (eqv? (peek-token s) #\newline) + (eof-object? (peek-token s))) + '() + (parse-comma-separated s (lambda (s) + (parse-import s word)))))) + (if from + (map (lambda (x) + (cons (car x) (append (cdr first) (cdr x)))) + rest) + (cons first rest)))) + (define (parse-import s word) (let ((ns (macrocall-to-atsym (parse-atom s)))) (let loop ((path (list ns))) @@ -1032,7 +1094,7 @@ ((eq? nxt '|.|) (take-token s) (loop (cons (macrocall-to-atsym (parse-atom s)) path))) - ((or (memv nxt '(#\newline #\; #\,)) + ((or (memv nxt '(#\newline #\; #\, :)) (eof-object? nxt)) `(,word ,@(reverse path))) ((eqv? (string.sub (string nxt) 0 1) ".") @@ -1082,6 +1144,23 @@ ((#\newline) (reverse! (cons e exprs))) (else (loop (cons e exprs))))))))) +(define (separate-keywords argl) + (receive + (kws args) (separate (lambda (x) + (and (assignment? x) + (or (symbol? (cadr x)) + (typedecl? (cadr x))))) + argl) + (if (null? kws) + args + `((keywords ,@kws) ,@args)))) + +(define (has-keywords? lst) + (and (pair? lst) (pair? (car lst)) (eq? (caar lst) 'keywords))) + +(define (has-parameters? lst) + (and (pair? lst) (pair? (car lst)) (eq? (caar lst) 'parameters))) + ; handle function call argument list, or any comma-delimited list. ; . an extra comma at the end is allowed ; . expressions after a ; are enclosed in (parameters ...) @@ -1095,19 +1174,27 @@ (let ((t (require-token s))) (if (equal? t closer) (begin (take-token s) - (reverse lst)) + (let ((lst (reverse lst))) + (if (eqv? closer #\) ) + (separate-keywords lst) + lst))) (if (equal? t #\;) (begin (take-token s) (if (equal? (peek-token s) closer) ;; allow f(a, b; ) (begin (take-token s) (reverse lst)) - (reverse (cons (cons 'parameters (loop '())) - lst)))) + (let ((params (loop '())) + (lst (separate-keywords (reverse lst)))) + (let ((params (cons 'parameters + (if (has-keywords? params) + (append (cdar params) (cdr params)) + params)))) + (if (has-keywords? lst) + (list* (car lst) params (cdr lst)) + (list* params lst)))))) (let* ((nxt (parse-eq* s)) (c (require-token s))) - (if (assignment? nxt) - (error "assignment in argument list not allowed")) (cond ((eqv? c #\,) (begin (take-token s) (loop (cons nxt lst)))) ((eqv? c #\;) (loop (cons nxt lst))) @@ -1144,6 +1231,13 @@ (else (error "missing separator in array expression"))))))) +(define (parse-dict s first closer) + (let ((v (parse-vcat s first closer))) + (if (any dict-literal? (cdr v)) + (if (every dict-literal? (cdr v)) + `(dict ,@(cdr v)) + (error "invalid dict literal"))))) + (define (parse-comprehension s first closer) (let ((r (parse-comma-separated-iters s))) (if (not (eqv? (require-token s) closer)) @@ -1151,6 +1245,12 @@ (take-token s)) `(comprehension ,first ,@r))) +(define (parse-dict-comprehension s first closer) + (let ((c (parse-comprehension s first closer))) + (if (dict-literal? (cadr c)) + `(dict_comprehension ,@(cdr c)) + (error "invalid dict comprehension")))) + (define (parse-matrix s first closer) (define (fix head v) (cons head (reverse v))) (define (update-outer v outer) @@ -1187,46 +1287,35 @@ (else (loop (cons (parse-eq* s) vec) outer))))))) +(define (peek-non-newline-token s) + (let loop ((t (peek-token s))) + (if (newline? t) + (begin (take-token s) + (loop (peek-token s))) + t))) + (define (parse-cat s closer) (with-normal-ops (with-inside-vec (if (eqv? (require-token s) closer) (begin (take-token s) - (list 'vcat)) ; [] => (vcat) + '()) (let ((first (parse-eq* s))) - (case (peek-token s) - ;; dispatch to array syntax, comprehension, or matrix syntax - ((#\,) - (parse-vcat s first closer)) - ;;((|\||) - ;; (error "old syntax")) - ((for) - (take-token s) - (parse-comprehension s first closer)) - (else - (parse-matrix s first closer)))))))) - -(define (parse-ref s closer) - (with-normal-ops - (with-inside-ref - (parse-ref- s closer)))) -(define (parse-ref- s closer) - (let loop ((lst '())) - (let ((t (require-token s))) - (if (equal? t closer) - (begin (take-token s) - (reverse lst)) - (let* ((nxt (parse-eq* s)) - (c (require-token s))) - (cond ((eqv? c #\,) - (begin (take-token s) (loop (cons nxt lst)))) - ((equal? c closer) (loop (cons nxt lst))) - ((eqv? c 'for) - (if (null? lst) - (begin (take-token s) (parse-comprehension s nxt closer)) - (error "invalid comprehension syntax"))) - (else - (error "invalid ref syntax")))))))) + (if (dict-literal? first) + (case (peek-non-newline-token s) + ((for) + (take-token s) + (parse-dict-comprehension s first closer)) + (else + (parse-dict s first closer))) + (case (peek-token s) + ((#\,) + (parse-vcat s first closer)) + ((for) + (take-token s) + (parse-comprehension s first closer)) + (else + (parse-matrix s first closer))))))))) ; for sequenced evaluation inside expressions: e.g. (a;b, c;d) (define (parse-stmts-within-expr s) @@ -1285,26 +1374,87 @@ (error "incomplete: invalid string syntax") c)) -; reads a raw string literal with no processing. -; quote can be escaped with \, but the \ is left in place. -; returns ("str" . b), b is a boolean telling whether interpolation is used -(define (parse-string-literal s) - (let ((b (open-output-string)) - (p (ts:port s)) - (interpolate #f)) - (let loop ((c (read-char p))) - (if (eqv? c #\") - #t - (begin (if (eqv? c #\\) - (let ((nextch (read-char p))) - (begin (write-char #\\ b) - (write-char (not-eof-3 nextch) b))) - (begin - (if (eqv? c #\$) - (set! interpolate #t)) - (write-char (not-eof-3 c) b))) - (loop (read-char p))))) - (cons (io.tostring! b) interpolate))) +(define (take-char p) + (begin (read-char p) p)) + +(define (parse-string-literal s custom) + (let ((p (ts:port s))) + (if (eqv? (peek-char p) #\") + (if (eqv? (peek-char (take-char p)) #\") + (parse-string-literal- 'triple_quoted_string 2 (take-char p) s custom) + '(single_quoted_string "")) + (parse-string-literal- 'single_quoted_string 0 p s custom)))) + +(define (parse-interpolate s) + (let* ((p (ts:port s)) + (c (peek-char p))) + (cond ((identifier-char? c) + (parse-atom s)) + ((eqv? c #\() + (read-char p) + (let ((ex (parse-eq* s)) + (t (require-token s))) + (cond ((eqv? t #\) ) + (take-token s) + ex) + (else (error "invalid interpolation syntax"))))) + (else (error (string "invalid interpolation syntax: " c)))))) + +(define (tostr custom io) + (if custom + (io.tostring! io) + (let ((str (unescape-string (io.tostring! io)))) + (if (not (string.isutf8 str)) + (error "invalid UTF-8 sequence") + str)))) + +;; custom = custom string literal +;; when custom is #t, unescape only \\ and \" +;; otherwise do full unescaping, and parse interpolations too +(define (parse-string-literal- head n p s custom) + (let loop ((c (read-char p)) + (b (open-output-string)) + (e (list head)) + (quotes 0)) + (cond + ((eqv? c #\") + (if (< quotes n) + (loop (read-char p) b e (+ quotes 1)) + (reverse (cons (tostr custom b) e)))) + + ((= quotes 1) + (if (not custom) (write-char #\\ b)) + (write-char #\" b) + (loop c b e 0)) + + ((= quotes 2) + (if (not custom) (write-char #\\ b)) + (write-char #\" b) + (if (not custom) (write-char #\\ b)) + (write-char #\" b) + (loop c b e 0)) + + ((eqv? c #\\) + (let ((nxch (not-eof-3 (read-char p)))) + (if (or (not custom) + (not (or (eqv? nxch #\") #;(eqv? nxch #\\)))) + (write-char #\\ b)) + (write-char nxch b) + (loop (read-char p) b e 0))) + + ((and (eqv? c #\$) (not custom)) + (let ((ex (parse-interpolate s))) + (loop (read-char p) + (open-output-string) + (list* ex (tostr custom b) e) + 0))) + + (else + (write-char (not-eof-3 c) b) + (loop (read-char p) b e 0))))) + +(define (interpolate-string-literal? s) (length> s 2)) +(define (triplequote-string-literal? s) (eqv? (car s) 'triple_quoted_string)) (define (not-eof-1 c) (if (eof-object? c) @@ -1428,19 +1578,18 @@ (if (eqv? (require-token s) #\}) (begin (take-token s) '(cell1d)) (let ((vex (parse-cat s #\}))) - (cond ((eq? (car vex) 'comprehension) - (if (and (not (null? (cdr vex))) - (dict-literal? (cadr vex))) - `(typed-dict-comprehension (=> (top Any) (top Any)) ,@(cdr vex)) - `(typed-comprehension (top Any) ,@(cdr vex)))) - ((and (eq? (car vex) 'vcat) - (any dict-literal? (cdr vex))) - (if (every dict-literal? (cdr vex)) - `(typed-dict (=> (top Any) (top Any)) ,@(cdr vex)) - (error "invalid dict literal"))) - ((eq? (car vex) 'hcat) - `(cell2d 1 ,(length (cdr vex)) ,@(cdr vex))) - (else ; (vcat ...) + (if (null? vex) + '(cell1d) + (case (car vex) + ((comprehension) + `(typed_comprehension (top Any) ,@(cdr vex))) + ((dict_comprehension) + `(typed_dict_comprehension (=> (top Any) (top Any)) ,@(cdr vex))) + ((dict) + `(typed_dict (=> (top Any) (top Any)) ,@(cdr vex))) + ((hcat) + `(cell2d 1 ,(length (cdr vex)) ,@(cdr vex))) + (else ; (vcat ...) (if (and (pair? (cadr vex)) (eq? (caadr vex) 'row)) (let ((nr (length (cdr vex))) (nc (length (cdadr vex)))) @@ -1461,31 +1610,23 @@ (eq? (car x) 'row))) (cddr vex)) (error "inconsistent shape in cell expression") - `(cell1d ,@(cdr vex))))))))) + `(cell1d ,@(cdr vex)))))))))) ;; cat expression ((eqv? t #\[ ) (take-token s) (let ((vex (parse-cat s #\]))) - (if (and (eq? (car vex) 'comprehension) - (dict-literal? (cadr vex))) - `(dict-comprehension ,@(cdr vex)) - (if (any dict-literal? (cdr vex)) - (if (every dict-literal? (cdr vex)) - `(dict ,@(cdr vex)) - (error "invalid dict literal")) - vex)))) + (if (null? vex) '(vcat) vex))) ;; string literal ((eqv? t #\") (take-token s) - (let ((ps (parse-string-literal s))) - (if (cdr ps) - `(macrocall @str ,(car ps)) - (let ((str (unescape-string (car ps)))) - (if (not (string.isutf8 str)) - (error "invalid UTF-8 sequence")) - str)))) + (let ((ps (parse-string-literal s #f))) + (if (triplequote-string-literal? ps) + `(macrocall @mstr ,@(cdr ps)) + (if (interpolate-string-literal? ps) + `(call (top string) ,@(cdr ps)) + (cadr ps))))) ;; macro call ((eqv? t #\@) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index d5bfa44aa8c87..1fd425261a139 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -83,29 +83,94 @@ e) (reverse a))))) -(define (expand-update-operator op lhs rhs) +(define (expand-update-operator- op lhs rhs) (let ((e (remove-argument-side-effects lhs))) `(block ,@(cdr e) (= ,(car e) (call ,op ,(car e) ,rhs))))) -; (a > b > c) => (call & (call > a b) (call > b c)) +(define (expand-update-operator op lhs rhs) + (if (and (pair? lhs) (eq? (car lhs) 'ref)) + ;; expand indexing inside op= first, to remove "end" and ":" + (let* ((ex (apply-patterns patterns lhs)) + (stmts (butlast (cdr ex))) + (refex (last (cdr ex))) + (nuref `(ref ,(caddr refex) ,@(cdddr refex)))) + `(block ,@stmts + ,(expand-update-operator- op nuref rhs))) + (expand-update-operator- op lhs rhs))) + +(define (dotop? o) (and (symbol? o) (eqv? (string.char (string o) 0) #\.))) + +;; accumulate a series of comparisons, with the given "and" constructor, +;; exit criteria, and "take" function that consumes part of a list, +;; returning (expression . rest) +(define (comp-accum e make-and done? take) + (let loop ((e e) + (expr '())) + (if (done? e) (cons expr e) + (let ((ex_rest (take e))) + (loop (cdr ex_rest) + (if (null? expr) + (car ex_rest) + (make-and expr (car ex_rest)))))))) + +(define (add-init arg arg2 expr) + (if (eq? arg arg2) expr + `(block (= ,arg2 ,arg) ,expr))) + +;; generate a comparison from e.g. (a < b ...) +;; returning (expr . rest) +(define (compare-one e) + (let* ((arg (caddr e)) + (arg2 (if (and (pair? arg) + (pair? (cdddr e))) + (gensy) arg))) + (if (and (not (dotop? (cadr e))) + (length> e 5) + (pair? (cadddr (cdr e))) + (dotop? (cadddr (cddr e)))) + ;; look ahead: if the 2nd argument of the next comparison is also + ;; an argument to an eager (dot) op, make sure we don't skip the + ;; initialization of its variable by short-circuiting + (let ((s (gensy))) + (cons `(block + ,@(if (eq? arg arg2) '() `((= ,arg2 ,arg))) + (= ,s ,(cadddr (cdr e))) + (call ,(cadr e) ,(car e) ,arg2)) + (list* arg2 (cadddr e) s (cddddr (cdr e))))) + (cons + (add-init arg arg2 + `(call ,(cadr e) ,(car e) ,arg2)) + (cons arg2 (cdddr e)))))) + +;; convert a series of scalar comparisons into && expressions +(define (expand-scalar-compare e) + (comp-accum e + (lambda (a b) `(&& ,a ,b)) + (lambda (x) (or (not (length> x 2)) (dotop? (cadr x)))) + compare-one)) + +;; convert a series of scalar and vector comparisons into & calls, +;; combining as many scalar comparisons as possible into short-circuit +;; && sequences. +(define (expand-vector-compare e) + (comp-accum e + (lambda (a b) `(call & ,a ,b)) + (lambda (x) (not (length> x 2))) + (lambda (e) + (if (dotop? (cadr e)) + (compare-one e) + (expand-scalar-compare e))))) + (define (expand-compare-chain e) - (if (length> e 3) - (let ((arg2 (caddr e))) - (if (pair? arg2) - (let ((g (gensy))) - `(call & (call ,(cadr e) ,(car e) (= ,g ,arg2)) - ,(expand-compare-chain (cons g (cdddr e))))) - `(call & (call ,(cadr e) ,(car e) ,arg2) - ,(expand-compare-chain (cddr e))))) - `(call ,(cadr e) ,(car e) ,(caddr e)))) + (car (expand-vector-compare e))) ;; last = is this last index? (define (end-val a n tuples last) (if (null? tuples) (if last (if (= n 1) - `(call (top length) ,a) + `(call (top endof) ,a) `(call (top trailingsize) ,a ,n)) #;`(call (top div) (call (top length) ,a) @@ -188,7 +253,9 @@ (cons (replace-end (expand-index-colon idx) a n tuples last) ret))))))) -(define (make-decl n t) `(|::| ,n ,t)) +(define (make-decl n t) `(|::| ,n ,(if (and (pair? t) (eq? (car t) '...)) + `(curly Vararg ,(cadr t)) + t))) (define (function-expr argl body) (let ((t (llist-types argl)) @@ -216,6 +283,15 @@ (map (lambda (x) `(call (top TypeVar) ',x ,@bnd)) sl) (map (lambda (x ub) `(call (top TypeVar) ',x ,ub ,@bnd)) sl upperbounds)))) +(define (sparam-name sp) + (cond ((symbol? sp) + sp) + ((and (length= sp 3) + (eq? (car sp) '|<:|) + (symbol? (cadr sp))) + (cadr sp)) + (else (error "malformed type parameter list")))) + (define (sparam-name-bounds sparams names bounds) (cond ((null? sparams) (values (reverse names) (reverse bounds))) @@ -230,10 +306,25 @@ (else (error "malformed type parameter list")))) -(define (method-def-expr name sparams argl body) +(define (method-expr-name m) + (let ((lhs (cadr m))) + (cond ((symbol? lhs) lhs) + ((eq? (car lhs) 'kw) (cadr lhs)) + (else lhs)))) + +(define (sym-ref? e) + (or (symbol? e) + (and (length= e 3) (eq? (car e) '|.|) + (sym-ref? (cadr e)) + (pair? (caddr e)) (eq? (car (caddr e)) 'quote) + (symbol? (cadr (caddr e)))))) + +(define (method-def-expr- name sparams argl body) (if (has-dups (llist-vars argl)) (error "function argument names not unique")) - (if (not (symbol? name)) + (if (not (or (sym-ref? name) + (and (pair? name) (eq? (car name) 'kw) + (sym-ref? (cadr name))))) (error (string "invalid method name " name))) (let* ((types (llist-types argl)) (body (method-lambda-expr argl body))) @@ -247,10 +338,190 @@ ,@(symbols->typevars names bounds #t) ,body)))))) -(define (struct-def-expr name params super fields) +(define (vararg? x) (and (pair? x) (eq? (car x) '...))) + +(define (const-default? x) + (or (number? x) (string? x) (char? x) (and (pair? x) (eq? (car x) 'quote)))) + +(define (keywords-method-def-expr name sparams argl body) + (let* ((kargl (cdar argl)) ;; keyword expressions (= k v) + (pargl (cdr argl)) ;; positional args + ;; 1-element list of vararg argument, or empty if none + (vararg (let ((l (if (null? pargl) '() (last pargl)))) + (if (vararg? l) + (list l) '()))) + ;; positional args without vararg + (pargl (if (null? vararg) pargl (butlast pargl))) + ;; keywords glob + (restkw (let ((l (last kargl))) + (if (vararg? l) + (list (cadr l)) '()))) + (kargl (if (null? restkw) kargl (butlast kargl))) + ;; the keyword::Type expressions + (vars (map cadr kargl)) + ;; keyword default values + (vals (map caddr kargl)) + ;; just the keyword names + (keynames (map decl-var vars)) + ;; 1-element list of function's line number node, or empty if none + (lno (if (and (pair? (cadr body)) (eq? (caadr body) 'line)) + (list (cadr body)) + '())) + ;; body statements, minus line number node + (stmts (if (null? lno) (cdr body) (cddr body)))) + (let ((kw (gensy)) (i (gensy)) (ii (gensy)) (elt (gensy)) (rkw (gensy)) + (mangled (symbol (string name "#" (gensym)))) + (flags (map (lambda (x) (gensy)) vals))) + `(block + ;; call with keyword args pre-sorted - original method code goes here + ,(method-def-expr- + mangled sparams + `(,@vars ,@restkw ,@pargl ,@vararg) + `(block + ,@(if (null? lno) '() + (list (append (car lno) (list name)))) + ,@stmts)) + + ;; call with no keyword args + ,(method-def-expr- + name sparams (append pargl vararg) + `(block + ;; call mangled(vals..., [rest_kw ,]pargs..., [vararg]...) + (return (call ,mangled + ,@vals + ,@(if (null? restkw) '() '((cell1d))) + ,@(map arg-name pargl) + ,@(if (null? vararg) '() + (list `(... ,(arg-name (car vararg))))))))) + + ;; call with unsorted keyword args. this sorts and re-dispatches. + ,(method-def-expr- + (list 'kw name) sparams + `((:: ,kw (top Tuple)) ,@pargl ,@vararg) + `(block + ,@lno + ;; initialize keyword args to their defaults, or set a flag telling + ;; whether this keyword needs to be set. + ,@(map (lambda (name dflt flag) + (if (const-default? dflt) + `(= ,name ,dflt) + `(= ,flag true))) + keynames vals flags) + ,@(if (null? restkw) '() + `((= ,rkw (cell1d)))) + ;; for i = 1:(length(kw)>>1) + (for (= ,i (: 1 (call (top >>) (call (top length) ,kw) 1))) + (block + ;; ii = i*2 - 1 + (= ,ii (call (top -) (call (top *) ,i 2) 1)) + (= ,elt (call (top tupleref) ,kw ,ii)) + ,(foldl (lambda (kvf else) + (let* ((k (car kvf)) + (rval0 `(call (top tupleref) ,kw + (call (top +) ,ii 1))) + (rval (if (decl? k) + `(call (top typeassert) + ,rval0 + ,(caddr k)) + rval0))) + ;; if kw[ii] == 'k; k = kw[ii+1]::Type; end + `(if (comparison ,elt === (quote ,(decl-var k))) + (block + (= ,(decl-var k) ,rval) + ,@(if (not (const-default? (cadr kvf))) + `((= ,(caddr kvf) false)) + '())) + ,else))) + (if (null? restkw) + ;; if no rest kw, give error for unrecognized + `(call (top error) "unrecognized keyword " ,elt) + ;; otherwise add to rest keywords + `(ccall 'jl_cell_1d_push Void (tuple Any Any) + ,rkw (tuple ,elt + (call (top tupleref) ,kw + (call (top +) ,ii 1))))) + (map list vars vals flags)))) + ;; set keywords that weren't present to their default values + ,@(apply append + (map (lambda (name dflt flag) + (if (const-default? dflt) + '() + `((if ,flag (= ,name ,dflt))))) + keynames vals flags)) + ;; finally, call the core function + (return (call ,mangled + ,@keynames + ,@(if (null? restkw) '() (list rkw)) + ,@(map arg-name pargl) + ,@(if (null? vararg) '() + (list `(... ,(arg-name (car vararg))))))))) + ;; return primary function + ,name)))) + +(define (optional-positional-defs name sparams req opt dfl body overall-argl . kw) + `(block + ,@(map (lambda (n) + (let* ((passed (append req (list-head opt n))) + ;; only keep static parameters used by these arguments + (sp (filter (lambda (sp) + (contains (lambda (e) (eq? e (sparam-name sp))) + passed)) + sparams)) + (vals (list-tail dfl n)) + (absent (list-tail opt n)) ;; absent arguments + (body + (if (any (lambda (defaultv) + ;; does any default val expression... + (contains (lambda (e) + ;; contain "e" such that... + (any (lambda (a) + ;; "e" is in an absent arg + (contains (lambda (u) + (eq? u e)) + a)) + absent)) + defaultv)) + vals) + ;; then add only one next argument + `(block (call ,name ,@kw ,@(map arg-name passed) ,(car vals))) + ;; otherwise add all + `(block (call ,name ,@kw ,@(map arg-name passed) ,@vals))))) + (method-def-expr name sp (append kw passed) body))) + (iota (length opt))) + ,(method-def-expr name sparams overall-argl body))) + +(define (method-def-expr name sparams argl body) + (if (has-keywords? argl) + ;; here (keywords ...) is optional positional args + (let ((opt (map cadr (cdar argl))) + (dfl (map caddr (cdar argl))) + (argl (cdr argl))) + (if (has-parameters? argl) + ;; both! + ;; separate into keyword version with all positional args, + ;; and a series of optional-positional-defs that delegate keywords + (let ((kw (car argl)) + (argl (cdr argl))) + (receive + (vararg req) (separate vararg? argl) + (optional-positional-defs name sparams req opt dfl body + (cons kw (append req opt vararg)) + `(parameters (... ,(gensy)))))) + ;; optional positional only + (receive + (vararg req) (separate vararg? argl) + (optional-positional-defs name sparams req opt dfl body + (append req opt vararg))))) + (if (has-parameters? argl) + ;; keywords only + (keywords-method-def-expr name sparams argl body) + ;; neither + (method-def-expr- name sparams argl body)))) + +(define (struct-def-expr name params super fields mut) (receive (params bounds) (sparam-name-bounds params '() '()) - (struct-def-expr- name params bounds super (flatten-blocks fields)))) + (struct-def-expr- name params bounds super (flatten-blocks fields) mut))) (define (default-inner-ctor name field-names field-types) `(function (call ,name @@ -266,19 +537,16 @@ (block (call (curly ,name ,@params) ,@field-names)))) -(define (new-call Texpr args field-names) - (cond ((> (length args) (length field-names)) +(define (new-call Texpr args field-names field-types mutabl) + (cond ((length> args (length field-names)) `(call (top error) "new: too many arguments")) - ((null? args) - `(new ,Texpr)) (else - (let ((g (gensy))) - `(block (= ,g (new ,Texpr)) - ,@(map (lambda (fld val) `(= (|.| ,g (quote ,fld)) ,val)) - (list-head field-names (length args)) args) - ,g))))) + `(new ,Texpr + ,@(map (lambda (fty val) + `(call (top convert) ,fty ,val)) + (list-head field-types (length args)) args))))) -(define (rewrite-ctor ctor Tname params field-names) +(define (rewrite-ctor ctor Tname params field-names field-types mutabl) (define (ctor-body body) `(block ;; make type name global (global ,Tname) @@ -289,7 +557,9 @@ Tname `(curly ,Tname ,@params)) args - field-names))) + field-names + field-types + mutabl))) body))) (let ((ctor2 (pattern-replace @@ -317,7 +587,7 @@ (else (list x)))) e)))) -(define (struct-def-expr- name params bounds super fields) +(define (struct-def-expr- name params bounds super fields mut) (receive (fields defs) (separate (lambda (x) (or (symbol? x) (decl? x))) fields) @@ -332,14 +602,15 @@ (const ,name) (composite_type ,name (tuple ,@params) (tuple ,@(map (lambda (x) `',x) field-names)) - (null) ,super (tuple ,@field-types)) + (null) ,super (tuple ,@field-types) + ,mut) (call (lambda () (scope-block (block (global ,name) ,@(map (lambda (c) - (rewrite-ctor c name '() field-names)) + (rewrite-ctor c name '() field-names field-types mut)) defs2))))) (null)) ;; parametric case @@ -360,10 +631,12 @@ (global ,@params) ,@(map (lambda (c) - (rewrite-ctor c name params field-names)) + (rewrite-ctor c name params field-names + field-types mut)) defs2) ,name))) - ,super (tuple ,@field-types)))) + ,super (tuple ,@field-types) + ,mut))) (scope-block (block (global ,@params) @@ -456,6 +729,23 @@ (loop (if isseq F (cdr F)) (cdr A) stmts (list* rt (ccall-conversion ty ca) C)))))) +(define (block-returns? e) + (if (assignment? e) + (block-returns? (caddr e)) + (and (pair? e) (eq? (car e) 'block) + (any return? (cdr e))))) + +(define (replace-return e bb ret retval) + (cond ((or (atom? e) (quoted? e)) e) + ((or (eq? (car e) 'lambda) + (eq? (car e) 'function) + (eq? (car e) '->)) e) + ((eq? (car e) 'return) + `(block ,@(if ret `((= ,ret true)) '()) + (= ,retval ,(cadr e)) + (break ,bb))) + (else (map (lambda (x) (replace-return x bb ret retval)) e)))) + ;; patterns that introduce lambdas (define binding-form-patterns (pattern-set @@ -545,25 +835,46 @@ (-> (tuple ,@argl) ,body))) ;; type definition - (pattern-lambda (type sig (block . fields)) + (pattern-lambda (type mut sig (block . fields)) (receive (name params super) (analyze-type-sig sig) - (struct-def-expr name params super fields))) + (struct-def-expr name params super fields mut))) ;; try with finally (pattern-lambda (try tryb var catchb finalb) + (let ((hasret (or (contains return? tryb) + (contains return? catchb)))) (let ((err (gensy)) + (ret (and hasret + (or (not (block-returns? tryb)) + (and catchb + (not (block-returns? catchb)))) + (gensy))) + (retval (gensy)) + (bb (gensy)) (val (gensy))) - `(scope-block - (block - (= ,err false) - (= ,val (try ,(if catchb - `(try ,tryb ,var ,catchb) - tryb) - #f - (= ,err true))) - ,finalb - (if ,err (ccall 'jl_rethrow Void (tuple))) - ,val)))) + (let ((tryb (replace-return tryb bb ret retval)) + (catchb (replace-return catchb bb ret retval))) + `(scope-block + (block + (local ,retval) + (local ,val) + (= ,err false) + ,@(if ret `((= ,ret false)) '()) + (break-block + ,bb + (try (= ,val + ,(if catchb + `(try ,tryb ,var ,catchb) + tryb)) + #f + (= ,err true))) + ,finalb + (if ,err (ccall 'jl_rethrow Void (tuple))) + ,(if hasret + (if ret + `(if ,ret (return ,retval) ,val) + `(return ,retval)) + val))))))) ;; try - catch (pattern-lambda (try tryb var catchb) @@ -686,6 +997,7 @@ (define (make-assignment l r) `(= ,l ,r)) (define (assignment? e) (and (pair? e) (eq? (car e) '=))) +(define (return? e) (and (pair? e) (eq? (car e) 'return))) (define (const-check-symbol s) (if (not (symbol? s)) @@ -743,6 +1055,26 @@ (+ i 1))))) ,t))) +(define (lower-kw-call f kw pa) + (let ((invalid (filter (lambda (x) + (not (or (assignment? x) + (vararg? x)))) + kw))) + (if (pair? invalid) + (error (string "invalid keyword argument " (car invalid)))) + (receive + (keys restkeys) (separate assignment? kw) + `(call (top kwcall) ,f ,(length keys) + ,@(apply append + (map (lambda (a) `((quote ,(cadr a)) ,(caddr a))) + keys)) + ,(if (null? restkeys) + '(tuple) + (if (length= restkeys 1) + (cadr (car restkeys)) + `(call (top append_any) ,@(map cadr restkeys)))) + ,@pa)))) + (define patterns (pattern-set (pattern-lambda (block) @@ -793,7 +1125,8 @@ ;; (a, b, ...) = (x, y, ...) (tuple-to-assignments lhss x) ;; (a, b, ...) = other - (let* ((xx (if (symbol? x) x (gensy))) + (let* ((xx (if (and (symbol? x) (not (memq x lhss))) + x (gensy))) (ini (if (eq? x xx) '() `((= ,xx ,x)))) (st (gensy))) `(block @@ -825,7 +1158,7 @@ ,@stmts ,@stuff ,@rini - (call (top assign) ,arr ,r ,@new-idxs) + (call setindex! ,arr ,r ,@new-idxs) ,r))))) (pattern-lambda (ref a . idxs) @@ -842,12 +1175,25 @@ (new-idxs stuff) (process-indexes arr idxs) `(block ,@(append stmts stuff) - (call (top ref) ,arr ,@new-idxs))))) + (call getindex ,arr ,@new-idxs))))) (pattern-lambda (curly type . elts) `(call (top apply_type) ,type ,@elts)) - ; call with splat + ;; call with keywords + (pattern-lambda (call f (keywords . kwargs) ...) + (let ((kw (if (and (length> __ 3) + (pair? (cadddr __)) + (eq? (car (cadddr __)) 'parameters)) + (append kwargs (cdr (cadddr __))) + kwargs))) + (lower-kw-call f kw (if (eq? kw kwargs) + (cdddr __) + (cddddr __))))) + (pattern-lambda (call f (parameters . kwargs) ...) + (lower-kw-call f kwargs (cdddr __))) + + ;; call with splat (pattern-lambda (call f ... (... _) ...) (let ((argl (cddr __))) ; wrap sequences of non-... arguments in tuple() @@ -868,18 +1214,16 @@ `(call (top apply) ,f ,@(tuple-wrap argl '())))) ; tuple syntax (a, b...) - ; note, directly inside tuple ... means sequence type + ; note, directly inside tuple ... means Vararg type (pattern-lambda (tuple . args) `(call (top tuple) ,@(map (lambda (x) (if (and (length= x 2) (eq? (car x) '...)) - `(curly ... ,(cadr x)) + `(curly Vararg ,(cadr x)) x)) args))) - (pattern-lambda (... a) `(curly ... ,a)) - ;; dict syntax (pattern-lambda (dict . args) `(call (top Dict) @@ -887,13 +1231,13 @@ (tuple ,@(map caddr args)))) ;; typed dict syntax - (pattern-lambda (typed-dict atypes . args) + (pattern-lambda (typed_dict atypes . args) (if (and (length= atypes 3) (eq? (car atypes) '=>)) `(call (curly (top Dict) ,(cadr atypes) ,(caddr atypes)) (tuple ,@(map cadr args)) (tuple ,@(map caddr args))) - (error (string "invalid typed-dict syntax " atypes)))) + (error (string "invalid typed_dict syntax " atypes)))) ;; cell array syntax (pattern-lambda (cell1d . args) @@ -1010,7 +1354,7 @@ `(call (top next) ,coll ,state)) ,body)))))) - ; update operators + ;; update operators (pattern-lambda (+= a b) (expand-update-operator '+ a b)) (pattern-lambda (-= a b) (expand-update-operator '- a b)) (pattern-lambda (*= a b) (expand-update-operator '* a b)) @@ -1064,6 +1408,40 @@ ,@(apply nconc rows))) `(call (top vcat) ,@a))) + (pattern-lambda (typed_hcat t . a) + (let ((result (gensy)) + (ncols (length a))) + `(block + (if (call (top !) (call (top isa) ,t Type)) + (call error "invalid array index")) + (= ,result (call (top Array) ,t 1 ,ncols)) + ,@(map (lambda (x i) `(call (top setindex!) ,result ,x ,i)) + a (cdr (iota (+ ncols 1)))) + ,result))) + + (pattern-lambda (typed_vcat t . rows) + (if (any (lambda (x) (not (and (pair? x) (eq? 'row (car x))))) rows) + (error "invalid array literal") + (let ((result (gensy)) + (nrows (length rows)) + (ncols (length (cdar rows)))) + (if (any (lambda (x) (not (= (length (cdr x)) ncols))) rows) + (error "invalid array literal") + `(block + (if (call (top !) (call (top isa) ,t Type)) + (call error "invalid array index")) + (= ,result (call (top Array) ,t ,nrows ,ncols)) + ,@(apply nconc + (map + (lambda (row i) + (map + (lambda (x j) `(call (top setindex!) ,result ,x ,i ,j)) + (cdr row) + (cdr (iota (+ ncols 1))))) + rows + (cdr (iota (+ nrows 1))))) + ,result))))) + ;; transpose operator (pattern-lambda (|'| a) `(call ctranspose ,a)) (pattern-lambda (|.'| a) `(call transpose ,a)) @@ -1098,75 +1476,7 @@ (error "ccall argument types must be a tuple; try (T,)")) (lower-ccall name RT (cdr argtypes) args))) - )) ; patterns - -;; Comprehensions - -(define (lower-nd-comprehension atype expr ranges) - (let ((result (gensy)) - (ri (gensy)) - (oneresult (gensy))) - ;; evaluate one expression to figure out type and size - ;; compute just one value by inserting a break inside loops - (define (evaluate-one ranges) - (if (null? ranges) - `(= ,oneresult ,expr) - (if (eq? (car ranges) `:) - (evaluate-one (cdr ranges)) - `(for ,(car ranges) - (block ,(evaluate-one (cdr ranges)) - (break)) )))) - - ;; compute the dimensions of the result - (define (compute-dims ranges oneresult-dim) - (if (null? ranges) - (list) - (if (eq? (car ranges) `:) - (cons `(call (top size) ,oneresult ,oneresult-dim) - (compute-dims (cdr ranges) (+ oneresult-dim 1))) - (cons `(call (top length) ,(caddr (car ranges))) - (compute-dims (cdr ranges) oneresult-dim)) ))) - - ;; construct loops to cycle over all dimensions of an n-d comprehension - (define (construct-loops ranges iters oneresult-dim) - (if (null? ranges) - (if (null? iters) - `(block (call (top assign) ,result ,expr ,ri) - (+= ,ri 1)) - `(block (call (top assign) ,result (ref ,expr ,@(reverse iters)) ,ri) - (+= ,ri 1)) ) - (if (eq? (car ranges) `:) - (let ((i (gensy))) - `(for (= ,i (: 1 (call (top size) ,oneresult ,oneresult-dim))) - ,(construct-loops (cdr ranges) (cons i iters) (+ oneresult-dim 1)) )) - `(for ,(car ranges) - ,(construct-loops (cdr ranges) iters oneresult-dim) )))) - - (define (get-eltype) - (if (null? atype) - `((call (top eltype) ,oneresult)) - `(,atype))) - - ;; Evaluate the comprehension - `(scope-block - (block - (= ,oneresult (tuple)) - ,(evaluate-one ranges) - (= ,result (call (top Array) ,@(get-eltype) - ,@(compute-dims ranges 1))) - (= ,ri 1) - ,(construct-loops (reverse ranges) (list) 1) - ,result )))) - -(define (lhs-vars e) - (cond ((symbol? e) (list e)) - ((and (pair? e) (eq? (car e) 'tuple)) - (apply append (map lhs-vars (cdr e)))) - (else '()))) - -(define lower-comprehensions - (pattern-set - + ;; comprehensions (pattern-lambda (comprehension expr . ranges) (if (any (lambda (x) (eq? x ':)) ranges) @@ -1187,7 +1497,7 @@ (if (null? ranges) `(block (= ,oneresult ,expr) (type_goto ,initlabl) - (call (top assign) ,result ,oneresult ,ri) + (call (top setindex!) ,result ,oneresult ,ri) (+= ,ri 1)) `(for ,(car ranges) ,(construct-loops (cdr ranges))))) @@ -1212,7 +1522,7 @@ ;; typed array comprehensions (pattern-lambda - (typed-comprehension atype expr . ranges) + (typed_comprehension atype expr . ranges) (if (any (lambda (x) (eq? x ':)) ranges) (lower-nd-comprehension atype expr ranges) (let ( (result (gensy)) @@ -1227,7 +1537,7 @@ ;; construct loops to cycle over all dimensions of an n-d comprehension (define (construct-loops ranges rs) (if (null? ranges) - `(block (call (top assign) ,result ,expr ,ri) + `(block (call (top setindex!) ,result ,expr ,ri) (+= ,ri 1)) `(for (= ,(cadr (car ranges)) ,(car rs)) ,(construct-loops (cdr ranges) (cdr rs))))) @@ -1247,7 +1557,7 @@ ;; dict comprehensions (pattern-lambda - (dict-comprehension expr . ranges) + (dict_comprehension expr . ranges) (if (any (lambda (x) (eq? x ':)) ranges) (error "invalid iteration syntax") (let ((result (gensy)) @@ -1262,7 +1572,7 @@ `(block (= ,onekey ,(cadr expr)) (= ,oneval ,(caddr expr)) (type_goto ,initlabl) - (call (top assign) ,result ,oneval ,onekey)) + (call (top setindex!) ,result ,oneval ,onekey)) `(for ,(car ranges) ,(construct-loops (cdr ranges))))) @@ -1279,26 +1589,26 @@ (apply append (map (lambda (r) (lhs-vars (cadr r))) ranges))) (label ,initlabl) (= ,result (call (curly (top Dict) - (static_typeof ,onekey) - (static_typeof ,oneval)))) + (static_typeof ,onekey) + (static_typeof ,oneval)))) ,(construct-loops (reverse loopranges)) ,result))))))) ;; typed dict comprehensions (pattern-lambda - (typed-dict-comprehension atypes expr . ranges) + (typed_dict_comprehension atypes expr . ranges) (if (any (lambda (x) (eq? x ':)) ranges) (error "invalid iteration syntax") (if (not (and (length= atypes 3) (eq? (car atypes) '=>))) - (error "invalid typed-dict-comprehension syntax") + (error "invalid typed_dict_comprehension syntax") (let ( (result (gensy)) (rs (map (lambda (x) (gensy)) ranges)) ) ;; construct loops to cycle over all dimensions of an n-d comprehension (define (construct-loops ranges rs) (if (null? ranges) - `(call (top assign) ,result ,(caddr expr) ,(cadr expr)) + `(call (top setindex!) ,result ,(caddr expr) ,(cadr expr)) `(for (= ,(cadr (car ranges)) ,(car rs)) ,(construct-loops (cdr ranges) (cdr rs))))) @@ -1314,8 +1624,69 @@ ,(construct-loops (reverse ranges) (reverse rs)) ,result))))))) -)) ;; lower-comprehensions + )) ; patterns +(define (lower-nd-comprehension atype expr ranges) + (let ((result (gensy)) + (ri (gensy)) + (oneresult (gensy))) + ;; evaluate one expression to figure out type and size + ;; compute just one value by inserting a break inside loops + (define (evaluate-one ranges) + (if (null? ranges) + `(= ,oneresult ,expr) + (if (eq? (car ranges) `:) + (evaluate-one (cdr ranges)) + `(for ,(car ranges) + (block ,(evaluate-one (cdr ranges)) + (break)) )))) + + ;; compute the dimensions of the result + (define (compute-dims ranges oneresult-dim) + (if (null? ranges) + (list) + (if (eq? (car ranges) `:) + (cons `(call (top size) ,oneresult ,oneresult-dim) + (compute-dims (cdr ranges) (+ oneresult-dim 1))) + (cons `(call (top length) ,(caddr (car ranges))) + (compute-dims (cdr ranges) oneresult-dim)) ))) + + ;; construct loops to cycle over all dimensions of an n-d comprehension + (define (construct-loops ranges iters oneresult-dim) + (if (null? ranges) + (if (null? iters) + `(block (call (top setindex!) ,result ,expr ,ri) + (+= ,ri 1)) + `(block (call (top setindex!) ,result (ref ,expr ,@(reverse iters)) ,ri) + (+= ,ri 1)) ) + (if (eq? (car ranges) `:) + (let ((i (gensy))) + `(for (= ,i (: 1 (call (top size) ,oneresult ,oneresult-dim))) + ,(construct-loops (cdr ranges) (cons i iters) (+ oneresult-dim 1)) )) + `(for ,(car ranges) + ,(construct-loops (cdr ranges) iters oneresult-dim) )))) + + (define (get-eltype) + (if (null? atype) + `((call (top eltype) ,oneresult)) + `(,atype))) + + ;; Evaluate the comprehension + `(scope-block + (block + (= ,oneresult (tuple)) + ,(evaluate-one ranges) + (= ,result (call (top Array) ,@(get-eltype) + ,@(compute-dims ranges 1))) + (= ,ri 1) + ,(construct-loops (reverse ranges) (list) 1) + ,result )))) + +(define (lhs-vars e) + (cond ((symbol? e) (list e)) + ((and (pair? e) (eq? (car e) 'tuple)) + (apply append (map lhs-vars (cdr e)))) + (else '()))) ; (op (op a b) c) => (a b c) etc. (define (flatten-op op e) @@ -1576,16 +1947,20 @@ (else (if (and dest (not tail) (eq? (car e) 'method)) - (error (string "misplaced method definition for " (cadr e)))) - (let ((r (map (lambda (arg) (to-lff arg #t #f)) - (cdr e)))) - (cond ((symbol? dest) - (cons `(= ,dest ,(cons (car e) (map car r))) - (apply append (map cdr r)))) - (else - (let ((ex (cons (car e) (map car r)))) - (cons (if tail `(return ,ex) ex) - (apply append (map cdr r))))))))))) + (let ((ex (to-lff (method-expr-name e) dest tail)) + (fu (to-lff e #f #f))) + (cons (car ex) + (append fu (cdr ex)))) + ;(error (string "misplaced method definition for " (cadr e)))) + (let ((r (map (lambda (arg) (to-lff arg #t #f)) + (cdr e)))) + (cond ((symbol? dest) + (cons `(= ,dest ,(cons (car e) (map car r))) + (apply append (map cdr r)))) + (else + (let ((ex (cons (car e) (map car r)))) + (cons (if tail `(return ,ex) ex) + (apply append (map cdr r)))))))))))) (to-blk (to-lff e #t #t))) #| future issue: @@ -1626,7 +2001,12 @@ So far only the second case can actually occur. '() (case (car e) ((lambda scope-block) '()) - ((= method) + ((method) + (let ((v (decl-var (method-expr-name e)))) + (if (memq v env) + '() + (list v)))) + ((=) (let ((v (decl-var (cadr e)))) (if (memq v env) '() @@ -1921,7 +2301,7 @@ So far only the second case can actually occur. ,@vs) env captvars)))) ((eq? (car e) 'method) - (let ((vi (var-info-for (cadr e) env))) + (let ((vi (var-info-for (method-expr-name e) env))) (if vi (begin (vinfo:set-asgn! vi #t) @@ -2077,12 +2457,12 @@ So far only the second case can actually occur. ((not (any (lambda (x) (match '($ (tuple (... x))) x)) e)) - `(call (top expr) ,@(map expand-backquote e))) + `(call (top Expr) ,@(map expand-backquote e))) (else (let loop ((p (cdr e)) (q '())) (if (null? p) (let ((forms (reverse q))) - `(call (top expr) ,(expand-backquote (car e)) + `(call (top splicedexpr) ,(expand-backquote (car e)) (call (top append_any) ,@forms))) ;; look for splice inside backquote, e.g. (a,$(x...),b) (if (match '($ (tuple (... x))) (car p)) @@ -2092,23 +2472,6 @@ So far only the second case can actually occur. (cons `(cell1d ,(expand-backquote (car p))) q)))))))) -(define (julia-expand-strs e) - (cond ((not (pair? e)) e) - ((and (eq? (car e) 'macrocall) (eq? (cadr e) '@str)) - ;; expand macro - (let ((form - (apply invoke-julia-macro (cadr e) (cddr e)))) - (if (not form) - (error (string "macro " (cadr e) " not defined"))) - (if (and (pair? form) (eq? (car form) 'error)) - (error (cadr form))) - (let ((form (car form)) - (m (cdr form))) - ;; m is the macro's def module, or #f if def env === use env - (resolve-expansion-vars form m)))) - (else - (map julia-expand-strs e)))) - (define (julia-expand-macros e) (cond ((not (pair? e)) e) ((and (eq? (car e) 'quote) (pair? (cadr e))) @@ -2117,7 +2480,7 @@ So far only the second case can actually occur. ((eq? (car e) 'macrocall) ;; expand macro (let ((form - (apply invoke-julia-macro (cadr e) (cddr e)))) + (apply invoke-julia-macro (cadr e) (cddr e)))) (if (not form) (error (string "macro " (cadr e) " not defined"))) (if (and (pair? form) (eq? (car form) 'error)) @@ -2126,12 +2489,17 @@ So far only the second case can actually occur. (m (cdr form))) ;; m is the macro's def module, or #f if def env === use env (julia-expand-macros - (resolve-expansion-vars (julia-expand-strs form) m))))) + (resolve-expansion-vars form m))))) (else (map julia-expand-macros e)))) (define (pair-with-gensyms v) - (map (lambda (s) (cons s (gensy))) v)) + (map (lambda (s) (cons s (named-gensy s))) v)) + +(define (unescape e) + (if (and (pair? e) (eq? (car e) 'escape)) + (cadr e) + e)) (define (resolve-expansion-vars- e env m) (cond ((or (eq? e 'true) (eq? e 'false) (eq? e 'end)) @@ -2150,6 +2518,18 @@ So far only the second case can actually occur. `(macrocall ,@(map (lambda (x) (resolve-expansion-vars- x env m)) (cdr e)))) + ((type) + `(type ,(cadr e) ,(unescape (caddr e)) + ;; type has special behavior: identifiers inside are + ;; field names, not expressions. + ,(map (lambda (x) + (cond ((atom? x) x) + ((and (pair? x) (eq? (car x) '|::|)) + `(|::| ,(cadr x) + ,(resolve-expansion-vars- (caddr x) env m))) + (else + (resolve-expansion-vars- x env m)))) + (cadddr e)))) ;; todo: trycatch (else (cons (car e) @@ -2229,8 +2609,7 @@ So far only the second case can actually occur. (define (julia-expand01 ex) (to-LFF (pattern-expand patterns - (pattern-expand lower-comprehensions - (pattern-expand binding-form-patterns ex))))) + (pattern-expand binding-form-patterns ex)))) (define (julia-expand0 ex) (let ((e (julia-expand-macros ex))) diff --git a/src/julia.expmap b/src/julia.expmap index e757d91131c87..1a811f412fade 100644 --- a/src/julia.expmap +++ b/src/julia.expmap @@ -1,10 +1,11 @@ { global: + asprintf; bitvector_any1; bitvector_count; bitvector_next; clock_now; - connect_to_host; + ev_break; get_exename; getlocalip; int32hash; @@ -21,6 +22,7 @@ ios_getc; ios_getutf8; ios_mem; + ios_peekc; ios_peekutf8; ios_pos; ios_printf; @@ -33,6 +35,7 @@ ios_seek; ios_seek_end; ios_skip; + ios_splitbuf; ios_stderr; ios_stdin; ios_stdout; @@ -40,38 +43,52 @@ ios_trunc; ios_write; ios_write_direct; + iswprint; jl_alloc_array_1d; jl_alloc_array_2d; jl_alloc_array_3d; jl_alloc_cell_1d; + jl_cell_1d_push; jl_apply_generic; jl_array_del_beg; jl_array_del_end; jl_array_grow_beg; jl_array_grow_end; + jl_array_sizehint; jl_array_ptr; jl_arrayref; jl_arrayset; jl_arrayunset; jl_array_to_string; + jl_async_send; + jl_atexit_hook; jl_backtrace_type; jl_base_module; jl_boundp; jl_defines_or_exports_p; jl_box_int32; jl_box_int64; - jl_buf_mutex_lock; - jl_buf_mutex_unlock; + jl_unbox_int32; + jl_unbox_int64; + jl_unbox_float32; + jl_unbox_float64; + jl_unbox_voidpointer; + jl_callback; + jl_clear_input; + jl_close_uv; jl_compile_hint; jl_compress_ast; + jl_connect_raw; jl_continue_sym; jl_core_module; jl_cpu_cores; jl_cstr_to_string; jl_current_module; + jl_current_os; jl_current_output_stream; jl_current_output_stream_obj; jl_current_task; + jl_cwd; jl_defer_signal; jl_dlsym; jl_dlsym_e; @@ -89,8 +106,23 @@ jl_errno; jl_errorexception_type; jl_exception_in_transit; + jl_exit; jl_expand; jl_expr_type; + jl_eval_string; + jl_exception_occurred; + jl_exception_clear; + jl_typeof_str; + jl_typename_str; + jl_array_eltype; + jl_array_rank; + jl_array_size; + jl_get_field; + jl_call1; + jl_call2; + jl_sigatomic_begin; + jl_sigatomic_end; + jl_init; jl_ascii_string_type; jl_utf8_string_type; jl_fd_clr; @@ -114,26 +146,44 @@ jl_get_nth_field; jl_get_root_symbol; jl_get_system_hooks; + jl_get_uv_hooks; + jl_getaddrinfo; + jl_getpid; jl_getutf8; + jl_global_event_loop; jl_hrtime; + jl_idle_init; + jl_idle_start; + jl_idle_stop; jl_init_frontend; + jl_init_pipe; jl_install_sigint_handler; + jl_ios_buf_base; jl_ios_eof; jl_ios_fd; jl_ios_size; - jl_is_builtin; jl_is_const; jl_is_leaf_type; jl_is_rest_arg; + jl_is_unix; + jl_last_errno; jl_lisp_prompt; + jl_listen; jl_load_; jl_load; jl_load_dynamic_library; + jl_load_dynamic_library_e; + jl_load_file_string; jl_loaderror_type; jl_load_file_string; + jl_locate_sysimg; jl_lstat; jl_macroexpand; jl_main_module; + jl_make_async; + jl_make_pipe; + jl_make_tcp; + jl_make_timer; jl_matching_methods; jl_match_method; jl_module_export; @@ -141,9 +191,12 @@ jl_module_name; jl_module_parent; jl_module_type; + jl_native_alignment; + jl_is_char_signed; jl_nb_available; jl_new_array; jl_new_closure; + jl_new_event_loop; jl_new_gf_internal; jl_new_lambda_info; jl_new_struct_uninit; @@ -151,22 +204,32 @@ jl_new_structt; jl_nothing; jl_object_id; + jl_os_name; jl_parse_input_line; jl_parse_input_line; jl_parse_string; + jl_pchar_to_array; jl_pchar_to_string; jl_pgcstack; jl_prepare_ast; + jl_ast_rettype; jl_print_int64; jl_print_symbol; + jl_printf; + jl_process_events; jl_process_exited; jl_process_exit_status; jl_process_signaled; + jl_process_stop_signal; jl_process_stopped; jl_process_stop_signal; jl_process_term_signal; jl_ptr_to_array; jl_ptr_to_array_1d; + jl_putc; + jl_puts; + jl_pututf8; + jl_readBuffer; jl_readdir; jl_readuntil; jl_throw; @@ -174,24 +237,33 @@ jl_rethrow_other; jl_throw_with_superfluous_argument; jl_get_backtrace; + jl_backtrace_from_here; + jl_lookup_code_address; + rec_backtrace; jl_reshape_array; jl_restore_system_image; + jl_run_event_loop; + jl_run_once; jl_save_system_image; jl_set_const; jl_set_current_module; jl_set_current_output_stream_obj; jl_set_global; jl_set_timeval; + jl_setjmp; jl_show; jl_show_any; jl_signal_pending; - jl_sizeof_fd_set; - jl_sizeof_ios_t; - jl_sizeof_off_t; - jl_sizeof_stat; - jl_sizeof_timeval; - jl_sizeof_uv_fs_t; + jl_sizeof_*; + jl_sockaddr_from_addrinfo; + jl_sockaddr_set_port; + jl_sockaddr_is_ip4; + jl_sockaddr_host4; + jl_tcp4_connect; + jl_spawn; + jl_stackovf_exception; jl_start_io_thread; + jl_start_reading; jl_stat; jl_stat_blksize; jl_stat_blocks; @@ -205,11 +277,11 @@ jl_stat_rdev; jl_stat_size; jl_stat_uid; - jl_stderr; jl_stderr_obj; - jl_stdin; + jl_stderr_stream; + jl_stdin_callback; jl_stdin_callback; - jl_stdout; + jl_stdin_stream; jl_stdout_obj; jl_stdout_stream; jl_strtod; @@ -222,14 +294,22 @@ jl_takebuf_array; jl_takebuf_raw; jl_takebuf_string; + jl_tcp_bind; + jl_tcp_init; + jl_test; + jl_timer_start; + jl_timer_stop; jl_toplevel_eval; jl_type_intersection; jl_type_match; jl_types_equal; + jl_typeassert; + jl_array_len_; jl_uncompress_ast; - jl_uv_fs_req_cleanup; - jl_uv_fs_t_ptr; - jl_uv_fs_t_ptr_offset; + jl_uv_*; + jl_wrap_raw_dl_handle; + jl_write; + jl_value_ptr; jl_zero_denormals; julia_free; julia_home; @@ -237,16 +317,27 @@ julia_trampoline; libsupport_init; locale_is_utf8; + localtime_r; memhash; memhash32; memhash32_seed; memhash_seed; open_any_tcp_port; repl_callback_enable; + restore_signals; + rl_clear_input; + SC_CLK_TCK; u8_isvalid; u8_strlen; u8_strwidth; - uv_exepath; + wcwidth; + uv_*; + add_library_mapping; + + /* freebsd */ + environ; + __progname; + local: *; }; diff --git a/src/julia.h b/src/julia.h index 1f0f6ee509c59..7ec097b5b6e57 100644 --- a/src/julia.h +++ b/src/julia.h @@ -15,43 +15,51 @@ #include "arraylist.h" #include -#if defined(__FreeBSD__) +#ifndef __WIN32__ # define jl_jmp_buf sigjmp_buf #else # define jl_jmp_buf jmp_buf +# include //for _resetstkoflw #endif +#define JL_STREAM uv_stream_t +#define JL_STDOUT jl_uv_stdout +#define JL_STDERR jl_uv_stderr +#define JL_STDIN jl_uv_stdin +#define JL_PRINTF jl_printf +#define JL_PUTC jl_putc +#define JL_PUTS jl_puts +#define JL_WRITE jl_write -// Check windows -#if _WIN32 || _WIN64 -#if _WIN64 -#define ENVIRONMENT64 -#else -#define ENVIRONMENT32 -#endif -#endif - -// Check GCC #if __GNUC__ #define NORETURN __attribute__ ((noreturn)) -#if __x86_64__ || __ppc64__ -#define ENVIRONMENT64 -#else -#define ENVIRONMENT32 -#endif #else #define NORETURN #endif +#ifdef _P64 +// a risky way to save 8 bytes per tuple +//#define OVERLAP_TUPLE_LEN +#endif + +// if this is not defined, only individual dimension sizes are +// stored and not total length, to save space. +#define STORE_ARRAY_LEN -#define JL_STRUCT_TYPE \ - struct _jl_type_t *type; +#ifdef OVERLAP_TUPLE_LEN +#define JL_DATA_TYPE \ + size_t type : 52; \ + size_t _resvd : 12; +#else +#define JL_DATA_TYPE \ + struct _jl_value_t *type; +#endif typedef struct _jl_value_t { - JL_STRUCT_TYPE + JL_DATA_TYPE } jl_value_t; typedef struct _jl_sym_t { - JL_STRUCT_TYPE + JL_DATA_TYPE struct _jl_sym_t *left; struct _jl_sym_t *right; uptrint_t hash; // precomputed hash value @@ -62,17 +70,16 @@ typedef struct _jl_sym_t { } jl_sym_t; typedef struct { - JL_STRUCT_TYPE +#ifdef OVERLAP_TUPLE_LEN + size_t type : 52; + size_t length : 12; +#else + JL_DATA_TYPE size_t length; +#endif jl_value_t *data[1]; } jl_tuple_t; -typedef struct { - JL_STRUCT_TYPE - size_t length; - jl_value_t *data[2]; -} jl_tuple2_t; - // pseudo-object to track managed malloc pointers // currently only referenced from an array's data owner field typedef struct _jl_mallocptr_t { @@ -92,13 +99,16 @@ typedef struct _jl_mallocptr_t { allocated inline. */ typedef struct { - JL_STRUCT_TYPE + JL_DATA_TYPE void *data; +#ifdef STORE_ARRAY_LEN size_t length; +#endif - unsigned short ndims:14; + unsigned short ndims:13; unsigned short ptrarray:1; // representation is pointer array unsigned short ismalloc:1; // data owner is a jl_mallocptr_t + unsigned short isinline:1; // data stored inline uint16_t elsize; uint32_t offset; // for 1-d only. does not need to get big. @@ -111,43 +121,36 @@ typedef struct { }; // other dim sizes go here for ndims > 2 + // followed by alignment padding and inline data, or an owner pointer union { char _space[1]; void *_pad; }; } jl_array_t; +#ifdef STORE_ARRAY_LEN #define jl_array_len(a) (((jl_array_t*)(a))->length) +#else +DLLEXPORT size_t jl_array_len_(jl_array_t *a); +#define jl_array_len(a) jl_array_len_((jl_array_t*)(a)) +#endif #define jl_array_data(a) ((void*)((jl_array_t*)(a))->data) #define jl_array_dim(a,i) ((&((jl_array_t*)(a))->nrows)[i]) +#define jl_array_dim0(a) (((jl_array_t*)(a))->nrows) +#define jl_array_nrows(a) (((jl_array_t*)(a))->nrows) #define jl_array_ndims(a) ((int32_t)(((jl_array_t*)a)->ndims)) -#define jl_array_data_owner(a) (*((jl_value_t**)jl_array_inline_data_area(a))) +#define jl_array_data_owner(a) (*((jl_value_t**)(&a->_pad+jl_array_ndimwords(jl_array_ndims(a))))) // compute # of extra words needed to store dimensions static inline int jl_array_ndimwords(uint32_t ndims) { -#ifdef __LP64__ - // on 64-bit, ndimwords must be even to give 16-byte alignment - return (ndims == 0 ? 0 : ((ndims-1) & -2)); -#else - // on 32-bit, ndimwords must = 4k+1 to give 16-byte alignment - return (ndims & -4) + 1; -#endif -} - -static inline void *jl_array_inline_data_area(jl_array_t *a) -{ - return &a->_space[0] + jl_array_ndimwords(jl_array_ndims(a))*sizeof(size_t); + return (ndims < 3 ? 0 : ndims-2); } -typedef struct _jl_type_t { - JL_STRUCT_TYPE -} jl_type_t; - typedef jl_value_t *(*jl_fptr_t)(jl_value_t*, jl_value_t**, uint32_t); typedef struct _jl_lambda_info_t { - JL_STRUCT_TYPE + JL_DATA_TYPE // this holds the static data for a function: // a syntax tree, static parameters, and (if it has been compiled) // a function pointer. @@ -164,19 +167,21 @@ typedef struct _jl_lambda_info_t { struct _jl_function_t *unspecialized; // array of all lambda infos with code generated from this one jl_array_t *specializations; - int8_t inferred; - jl_value_t *file; - ptrint_t line; struct _jl_module_t *module; + struct _jl_lambda_info_t *def; // original this is specialized from + jl_value_t *capt; // captured var info + jl_sym_t *file; + int32_t line; + int8_t inferred; // hidden fields: + // flag telling if inference is running on this function + // used to avoid infinite recursion + int8_t inInference : 1; + int8_t inCompile : 1; jl_fptr_t fptr; // jlcall entry point void *functionObject; // jlcall llvm Function void *cFunctionObject; // c callable llvm Function - // flag telling if inference is running on this function - // used to avoid infinite recursion - uptrint_t inInference : 1; - uptrint_t inCompile : 1; } jl_lambda_info_t; #define LAMBDA_INFO_NW (NWORDS(sizeof(jl_lambda_info_t))-1) @@ -187,18 +192,18 @@ typedef struct _jl_lambda_info_t { jl_lambda_info_t *linfo; typedef struct _jl_function_t { - JL_STRUCT_TYPE + JL_DATA_TYPE JL_FUNC_FIELDS } jl_function_t; typedef struct { - JL_STRUCT_TYPE + JL_DATA_TYPE jl_tuple_t *parameters; - jl_type_t *body; + jl_value_t *body; } jl_typector_t; typedef struct { - JL_STRUCT_TYPE + JL_DATA_TYPE jl_sym_t *name; struct _jl_module_t *module; // if this is the name of a parametric type, this field points to the @@ -206,62 +211,47 @@ typedef struct { // a type alias, for example, might make a type constructor that is // not the original. jl_value_t *primary; - jl_tuple_t *cache; + jl_value_t *cache; } jl_typename_t; typedef struct { - JL_STRUCT_TYPE + JL_DATA_TYPE jl_tuple_t *types; } jl_uniontype_t; -typedef struct _jl_tag_type_t { - JL_STRUCT_TYPE - JL_FUNC_FIELDS - jl_typename_t *name; - struct _jl_tag_type_t *super; - jl_tuple_t *parameters; -} jl_tag_type_t; - typedef struct { uint16_t offset; // offset relative to data start, excluding type tag uint16_t size:15; uint16_t isptr:1; } jl_fielddesc_t; -typedef struct { - JL_STRUCT_TYPE +typedef struct _jl_datatype_t { + JL_DATA_TYPE JL_FUNC_FIELDS jl_typename_t *name; - jl_tag_type_t *super; + struct _jl_datatype_t *super; jl_tuple_t *parameters; jl_tuple_t *names; jl_tuple_t *types; // to create a set of constructors for this sort of type jl_value_t *ctor_factory; jl_value_t *instance; // for singletons + int32_t size; + uint8_t abstract; + uint8_t mutabl; + uint8_t pointerfree; // hidden fields: - uint32_t uid; - uint32_t size; uint32_t alignment; // strictest alignment over all fields + uint32_t uid; + void *struct_decl; //llvm::Value* jl_fielddesc_t fields[1]; -} jl_struct_type_t; +} jl_datatype_t; -#define jl_field_offset(st,i) (((jl_struct_type_t*)st)->fields[i].offset) -#define jl_field_size(st,i) (((jl_struct_type_t*)st)->fields[i].size) +#define jl_field_offset(st,i) (((jl_datatype_t*)st)->fields[i].offset) +#define jl_field_size(st,i) (((jl_datatype_t*)st)->fields[i].size) typedef struct { - JL_STRUCT_TYPE - JL_FUNC_FIELDS - jl_typename_t *name; - jl_tag_type_t *super; - jl_tuple_t *parameters; - int32_t nbits; - // hidden fields: - uint32_t uid; -} jl_bits_type_t; - -typedef struct { - JL_STRUCT_TYPE + JL_DATA_TYPE jl_sym_t *name; jl_value_t *lb; // lower bound jl_value_t *ub; // upper bound @@ -269,7 +259,7 @@ typedef struct { } jl_tvar_t; typedef struct { - JL_STRUCT_TYPE + JL_DATA_TYPE jl_value_t *value; } jl_weakref_t; @@ -277,15 +267,21 @@ typedef struct { // not first-class jl_sym_t *name; jl_value_t *value; - jl_type_t *type; + jl_value_t *type; struct _jl_module_t *owner; // for individual imported bindings unsigned constp:1; unsigned exportp:1; unsigned imported:1; } jl_binding_t; +typedef struct _jl_callback_t { + JL_DATA_TYPE + jl_function_t *function; + jl_tuple_t *types; +} jl_callback_t; + typedef struct _jl_module_t { - JL_STRUCT_TYPE + JL_DATA_TYPE jl_sym_t *name; struct _jl_module_t *parent; htable_t bindings; @@ -293,7 +289,7 @@ typedef struct _jl_module_t { } jl_module_t; typedef struct _jl_methlist_t { - JL_STRUCT_TYPE + JL_DATA_TYPE jl_tuple_t *sig; int8_t va; jl_tuple_t *tvars; @@ -310,63 +306,69 @@ typedef struct _jl_methlist_t { //#define JL_GF_PROFILE typedef struct _jl_methtable_t { - JL_STRUCT_TYPE + JL_DATA_TYPE jl_sym_t *name; jl_methlist_t *defs; jl_methlist_t *cache; jl_array_t *cache_arg1; jl_array_t *cache_targ; ptrint_t max_args; // max # of non-vararg arguments in a signature + jl_function_t *kwsorter; // keyword argument sorter function #ifdef JL_GF_PROFILE int ncalls; #endif } jl_methtable_t; typedef struct { - JL_STRUCT_TYPE + JL_DATA_TYPE jl_sym_t *head; jl_array_t *args; jl_value_t *etype; } jl_expr_t; -extern jl_tag_type_t *jl_any_type; -extern jl_tag_type_t *jl_type_type; +enum CALLBACK_TYPE { CB_PTR, CB_INT32, CB_INT64 }; +#ifdef _P64 +#define CB_INT CB_INT64 +#else +#define CB_INT CB_INT32 +#endif + +extern jl_datatype_t *jl_any_type; +extern jl_datatype_t *jl_type_type; extern jl_tvar_t *jl_typetype_tvar; -extern jl_tag_type_t *jl_typetype_type; +extern jl_datatype_t *jl_typetype_type; extern jl_value_t *jl_ANY_flag; -extern jl_tag_type_t *jl_undef_type; -extern jl_struct_type_t *jl_typename_type; -extern jl_struct_type_t *jl_typector_type; -extern jl_struct_type_t *jl_sym_type; -extern jl_struct_type_t *jl_symbol_type; +extern jl_datatype_t *jl_undef_type; +extern jl_datatype_t *jl_typename_type; +extern jl_datatype_t *jl_typector_type; +extern jl_datatype_t *jl_sym_type; +extern jl_datatype_t *jl_symbol_type; extern jl_tuple_t *jl_tuple_type; -extern jl_tag_type_t *jl_ntuple_type; +extern jl_value_t *jl_tupletype_type; +extern jl_datatype_t *jl_ntuple_type; extern jl_typename_t *jl_ntuple_typename; -extern jl_struct_type_t *jl_tvar_type; -extern jl_struct_type_t *jl_task_type; +extern jl_datatype_t *jl_tvar_type; +extern jl_datatype_t *jl_task_type; -extern jl_struct_type_t *jl_union_kind; -extern jl_struct_type_t *jl_tag_kind; -extern jl_struct_type_t *jl_tag_type_type; -extern DLLEXPORT jl_struct_type_t *jl_struct_kind; -extern jl_struct_type_t *jl_bits_kind; +extern jl_datatype_t *jl_uniontype_type; +extern jl_datatype_t *jl_datatype_type; -extern jl_type_t *jl_bottom_type; +extern jl_value_t *jl_bottom_type; extern jl_value_t *jl_top_type; -extern jl_struct_type_t *jl_lambda_info_type; -extern DLLEXPORT jl_struct_type_t *jl_module_type; -extern jl_tag_type_t *jl_seq_type; -extern jl_struct_type_t *jl_function_type; -extern jl_tag_type_t *jl_abstractarray_type; -extern jl_struct_type_t *jl_array_type; +extern jl_datatype_t *jl_lambda_info_type; +extern DLLEXPORT jl_datatype_t *jl_module_type; +extern jl_datatype_t *jl_vararg_type; +extern jl_datatype_t *jl_function_type; +extern jl_datatype_t *jl_abstractarray_type; +extern jl_datatype_t *jl_array_type; extern jl_typename_t *jl_array_typename; -extern jl_struct_type_t *jl_weakref_type; -extern DLLEXPORT jl_struct_type_t *jl_ascii_string_type; -extern DLLEXPORT jl_struct_type_t *jl_utf8_string_type; -extern DLLEXPORT jl_struct_type_t *jl_errorexception_type; -extern DLLEXPORT jl_struct_type_t *jl_loaderror_type; -extern jl_struct_type_t *jl_typeerror_type; -extern jl_struct_type_t *jl_methoderror_type; +extern jl_datatype_t *jl_weakref_type; +extern DLLEXPORT jl_datatype_t *jl_ascii_string_type; +extern DLLEXPORT jl_datatype_t *jl_utf8_string_type; +extern DLLEXPORT jl_datatype_t *jl_errorexception_type; +extern DLLEXPORT jl_datatype_t *jl_loaderror_type; +extern jl_datatype_t *jl_typeerror_type; +extern jl_datatype_t *jl_methoderror_type; extern jl_value_t *jl_stackovf_exception; extern jl_value_t *jl_memory_exception; extern jl_value_t *jl_divbyzero_exception; @@ -378,40 +380,40 @@ extern jl_value_t *jl_interrupt_exception; extern jl_value_t *jl_bounds_exception; extern jl_value_t *jl_an_empty_cell; -extern jl_struct_type_t *jl_box_type; -extern jl_type_t *jl_box_any_type; +extern jl_datatype_t *jl_box_type; +extern jl_value_t *jl_box_any_type; extern jl_typename_t *jl_box_typename; -extern jl_bits_type_t *jl_bool_type; -extern jl_bits_type_t *jl_char_type; -extern jl_bits_type_t *jl_int8_type; -extern jl_bits_type_t *jl_uint8_type; -extern jl_bits_type_t *jl_int16_type; -extern jl_bits_type_t *jl_uint16_type; -extern jl_bits_type_t *jl_int32_type; -extern jl_bits_type_t *jl_uint32_type; -extern jl_bits_type_t *jl_int64_type; -extern jl_bits_type_t *jl_uint64_type; -extern jl_bits_type_t *jl_float32_type; -extern jl_bits_type_t *jl_float64_type; - -extern jl_bits_type_t *jl_pointer_type; - -extern jl_type_t *jl_array_uint8_type; -extern jl_type_t *jl_array_any_type; -extern jl_type_t *jl_array_symbol_type; -extern DLLEXPORT jl_struct_type_t *jl_expr_type; -extern jl_struct_type_t *jl_symbolnode_type; -extern jl_struct_type_t *jl_getfieldnode_type; -extern jl_struct_type_t *jl_linenumbernode_type; -extern jl_struct_type_t *jl_labelnode_type; -extern jl_struct_type_t *jl_gotonode_type; -extern jl_struct_type_t *jl_quotenode_type; -extern jl_struct_type_t *jl_topnode_type; -extern jl_bits_type_t *jl_intrinsic_type; -extern jl_struct_type_t *jl_methtable_type; -extern jl_struct_type_t *jl_method_type; -extern jl_struct_type_t *jl_task_type; +extern jl_datatype_t *jl_bool_type; +extern jl_datatype_t *jl_char_type; +extern jl_datatype_t *jl_int8_type; +extern jl_datatype_t *jl_uint8_type; +extern jl_datatype_t *jl_int16_type; +extern jl_datatype_t *jl_uint16_type; +extern jl_datatype_t *jl_int32_type; +extern jl_datatype_t *jl_uint32_type; +extern jl_datatype_t *jl_int64_type; +extern jl_datatype_t *jl_uint64_type; +extern jl_datatype_t *jl_float32_type; +extern jl_datatype_t *jl_float64_type; +extern jl_datatype_t *jl_voidpointer_type; +extern jl_datatype_t *jl_pointer_type; + +extern jl_value_t *jl_array_uint8_type; +extern jl_value_t *jl_array_any_type; +extern jl_value_t *jl_array_symbol_type; +extern DLLEXPORT jl_datatype_t *jl_expr_type; +extern jl_datatype_t *jl_symbolnode_type; +extern jl_datatype_t *jl_getfieldnode_type; +extern jl_datatype_t *jl_linenumbernode_type; +extern jl_datatype_t *jl_labelnode_type; +extern jl_datatype_t *jl_gotonode_type; +extern jl_datatype_t *jl_quotenode_type; +extern jl_datatype_t *jl_topnode_type; +extern jl_datatype_t *jl_intrinsic_type; +extern jl_datatype_t *jl_methtable_type; +extern jl_datatype_t *jl_method_type; +extern jl_datatype_t *jl_task_type; extern jl_tuple_t *jl_null; #define JL_NULL ((void*)jl_null) @@ -425,10 +427,12 @@ extern jl_function_t *jl_bottom_func; extern uv_lib_t *jl_dl_handle; #if defined(__WIN32__) || defined (_WIN32) extern uv_lib_t *jl_ntdll_handle; +extern uv_lib_t *jl_exe_handle; extern uv_lib_t *jl_kernel32_handle; extern uv_lib_t *jl_crtdll_handle; extern uv_lib_t *jl_winsock_handle; #endif +extern uv_loop_t *jl_io_loop; // some important symbols extern jl_sym_t *call_sym; @@ -449,14 +453,15 @@ extern jl_sym_t *null_sym; extern jl_sym_t *body_sym; extern jl_sym_t *macro_sym; extern jl_sym_t *method_sym; extern jl_sym_t *enter_sym; extern jl_sym_t *leave_sym; extern jl_sym_t *exc_sym; extern jl_sym_t *new_sym; -extern jl_sym_t *static_typeof_sym; +extern jl_sym_t *static_typeof_sym; extern jl_sym_t *kw_sym; extern jl_sym_t *const_sym; extern jl_sym_t *thunk_sym; extern jl_sym_t *anonymous_sym; extern jl_sym_t *underscore_sym; extern jl_sym_t *abstracttype_sym; extern jl_sym_t *bitstype_sym; extern jl_sym_t *compositetype_sym; extern jl_sym_t *type_goto_sym; -extern jl_sym_t *global_sym; +extern jl_sym_t *global_sym; extern jl_sym_t *tuple_sym; -#ifdef __LP64__ + +#ifdef _P64 #define NWORDS(sz) (((sz)+7)>>3) #else #define NWORDS(sz) (((sz)+3)>>2) @@ -470,8 +475,13 @@ void *allocobj(size_t sz); #define allocobj(nb) malloc(nb) #endif +#ifdef OVERLAP_TUPLE_LEN +#define jl_tupleref(t,i) (((jl_value_t**)(t))[1+(i)]) +#define jl_tupleset(t,i,x) ((((jl_value_t**)(t))[1+(i)])=(jl_value_t*)(x)) +#else #define jl_tupleref(t,i) (((jl_value_t**)(t))[2+(i)]) #define jl_tupleset(t,i,x) ((((jl_value_t**)(t))[2+(i)])=(jl_value_t*)(x)) +#endif #define jl_t0(t) jl_tupleref(t,0) #define jl_t1(t) jl_tupleref(t,1) @@ -491,20 +501,28 @@ void *allocobj(size_t sz); #define jl_getfieldnode_name(s) ((jl_sym_t*)jl_fieldref(s,1)) #define jl_getfieldnode_type(s) (jl_fieldref(s,2)) -#define jl_tparam0(t) jl_tupleref(((jl_tag_type_t*)(t))->parameters, 0) -#define jl_tparam1(t) jl_tupleref(((jl_tag_type_t*)(t))->parameters, 1) +#define jl_tparam0(t) jl_tupleref(((jl_datatype_t*)(t))->parameters, 0) +#define jl_tparam1(t) jl_tupleref(((jl_datatype_t*)(t))->parameters, 1) +#ifdef OVERLAP_TUPLE_LEN +#define jl_typeof(v) ((jl_value_t*)((uptrint_t)((jl_value_t*)(v))->type & 0x000ffffffffffffeULL)) +#else #define jl_typeof(v) (((jl_value_t*)(v))->type) -#define jl_typeis(v,t) (jl_typeof(v)==(jl_type_t*)(t)) +#endif +#define jl_typeis(v,t) (jl_typeof(v)==(jl_value_t*)(t)) #define jl_is_null(v) (((jl_value_t*)(v)) == ((jl_value_t*)jl_null)) #define jl_is_tuple(v) jl_typeis(v,jl_tuple_type) -#define jl_is_tag_type(v) jl_typeis(v,jl_tag_kind) -#define jl_is_some_tag_type(v) (jl_is_tag_type(v)||jl_is_struct_type(v)||jl_is_bits_type(v)) -#define jl_is_bits_type(v) jl_typeis(v,jl_bits_kind) -#define jl_bitstype_nbits(t) (((jl_bits_type_t*)t)->nbits) -#define jl_is_struct_type(v) jl_typeis(v,jl_struct_kind) -#define jl_is_union_type(v) jl_typeis(v,jl_union_kind) +#define jl_is_datatype(v) jl_typeis(v,jl_datatype_type) +#define jl_datatype_size(t) (((jl_datatype_t*)t)->size) +#define jl_is_pointerfree(t) (((jl_datatype_t*)t)->pointerfree) +#define jl_ismutable(t) (((jl_datatype_t*)t)->mutabl) +#define jl_is_mutable(t) (((jl_datatype_t*)t)->mutabl) +#define jl_is_mutable_datatype(t) (jl_is_datatype(t) && (((jl_datatype_t*)t)->mutabl)) +#define jl_isimmutable(t) (!((jl_datatype_t*)t)->mutabl) +#define jl_is_immutable(t) (!((jl_datatype_t*)t)->mutabl) +#define jl_is_immutable_datatype(t) (jl_is_datatype(t) && (!((jl_datatype_t*)t)->mutabl)) +#define jl_is_uniontype(v) jl_typeis(v,jl_uniontype_type) #define jl_is_typevar(v) jl_typeis(v,jl_tvar_type) #define jl_is_typector(v) jl_typeis(v,jl_typector_type) #define jl_is_TypeConstructor(v) jl_typeis(v,jl_typector_type) @@ -529,7 +547,7 @@ void *allocobj(size_t sz); #define jl_is_module(v) jl_typeis(v,jl_module_type) #define jl_is_mtable(v) jl_typeis(v,jl_methtable_type) #define jl_is_task(v) jl_typeis(v,jl_task_type) -#define jl_is_func(v) (jl_typeis(v,jl_function_type) || jl_is_struct_type(v)) +#define jl_is_func(v) (jl_typeis(v,jl_function_type) || jl_is_datatype(v)) #define jl_is_function(v) jl_is_func(v) #define jl_is_ascii_string(v) jl_typeis(v,jl_ascii_string_type) #define jl_is_utf8_string(v) jl_typeis(v,jl_utf8_string_type) @@ -547,59 +565,84 @@ void *allocobj(size_t sz); #define jl_gf_mtable(f) ((jl_methtable_t*)((jl_function_t*)(f))->env) #define jl_gf_name(f) (jl_gf_mtable(f)->name) -// get a pointer to the data in a value of bits type -#define jl_bits_data(v) (&((void**)(v))[1]) +// get a pointer to the data in a datatype +#define jl_data_ptr(v) (&((void**)(v))[1]) + +static inline int jl_is_bitstype(void *v) +{ + return (jl_is_datatype(v) && jl_isimmutable(v) && + jl_tuple_len(((jl_datatype_t*)(v))->names)==0 && + !((jl_datatype_t*)(v))->abstract && + ((jl_datatype_t*)(v))->size > 0); +} + +static inline int jl_is_structtype(void *v) +{ + return (jl_is_datatype(v) && + (jl_tuple_len(((jl_datatype_t*)(v))->names) > 0 || + ((jl_datatype_t*)(v))->size == 0) && + !((jl_datatype_t*)(v))->abstract); +} + +static inline int jl_isbits(void *t) // corresponding to isbits() in julia +{ + return (jl_is_datatype(t) && !((jl_datatype_t*)t)->mutabl && + ((jl_datatype_t*)t)->pointerfree && !((jl_datatype_t*)t)->abstract); +} + +static inline int jl_is_abstracttype(void *v) +{ + return (jl_is_datatype(v) && ((jl_datatype_t*)(v))->abstract); +} static inline int jl_is_array_type(void *t) { - return (jl_is_struct_type(t) && - ((jl_struct_type_t*)(t))->name == jl_array_typename); + return (jl_is_datatype(t) && + ((jl_datatype_t*)(t))->name == jl_array_typename); } static inline int jl_is_array(void *v) { - jl_type_t *t = jl_typeof(v); + jl_value_t *t = jl_typeof(v); return jl_is_array_type(t); } static inline int jl_is_box(void *v) { - jl_type_t *t = jl_typeof(v); - return (jl_is_struct_type(t) && - ((jl_struct_type_t*)(t))->name == jl_box_typename); + jl_value_t *t = jl_typeof(v); + return (jl_is_datatype(t) && + ((jl_datatype_t*)(t))->name == jl_box_typename); } static inline int jl_is_cpointer_type(void *t) { - return (jl_is_bits_type(t) && - ((jl_bits_type_t*)(t))->name == jl_pointer_type->name); + return (jl_is_datatype(t) && + ((jl_datatype_t*)(t))->name == jl_pointer_type->name); } -static inline int jl_is_seq_type(jl_value_t *v) +static inline int jl_is_vararg_type(jl_value_t *v) { - return (jl_is_tag_type(v) && - ((jl_tag_type_t*)(v))->name == jl_seq_type->name); + return (jl_is_datatype(v) && + ((jl_datatype_t*)(v))->name == jl_vararg_type->name); } static inline int jl_is_ntuple_type(jl_value_t *v) { - return (jl_is_tag_type(v) && - ((jl_tag_type_t*)v)->name == jl_ntuple_typename); + return (jl_is_datatype(v) && + ((jl_datatype_t*)v)->name == jl_ntuple_typename); } static inline int jl_is_nontuple_type(jl_value_t *v) { - return (jl_typeis(v, jl_union_kind) || - jl_typeis(v, jl_struct_kind) || - jl_typeis(v, jl_tag_kind) || - jl_typeis(v, jl_bits_kind) || + return (jl_typeis(v, jl_uniontype_type) || + jl_typeis(v, jl_datatype_type) || jl_typeis(v, jl_typector_type)); } static inline int jl_is_type_type(jl_value_t *v) { - return (jl_is_tag_type(v) && - ((jl_tag_type_t*)(v))->name == jl_type_type->name); + return (jl_is_datatype(v) && + ((jl_datatype_t*)(v))->name == jl_type_type->name); } // type info accessors @@ -617,7 +660,7 @@ int jl_subtype_invariant(jl_value_t *a, jl_value_t *b, int ta); DLLEXPORT jl_value_t *jl_type_match(jl_value_t *a, jl_value_t *b); jl_value_t *jl_type_match_morespecific(jl_value_t *a, jl_value_t *b); DLLEXPORT int jl_types_equal(jl_value_t *a, jl_value_t *b); -int jl_types_equal_generic(jl_value_t *a, jl_value_t *b); +int jl_types_equal_generic(jl_value_t *a, jl_value_t *b, int useenv); jl_value_t *jl_type_union(jl_tuple_t *types); jl_value_t *jl_type_intersection_matching(jl_value_t *a, jl_value_t *b, jl_tuple_t **penv, jl_tuple_t *tvars); @@ -627,28 +670,29 @@ int jl_args_morespecific(jl_value_t *a, jl_value_t *b); // type constructors jl_typename_t *jl_new_typename(jl_sym_t *name); jl_tvar_t *jl_new_typevar(jl_sym_t *name,jl_value_t *lb,jl_value_t *ub); -jl_typector_t *jl_new_type_ctor(jl_tuple_t *params, jl_type_t *body); +jl_typector_t *jl_new_type_ctor(jl_tuple_t *params, jl_value_t *body); jl_value_t *jl_apply_type(jl_value_t *tc, jl_tuple_t *params); jl_value_t *jl_apply_type_(jl_value_t *tc, jl_value_t **params, size_t n); -jl_type_t *jl_instantiate_type_with(jl_type_t *t, jl_value_t **env, size_t n); +jl_value_t *jl_instantiate_type_with(jl_value_t *t, jl_value_t **env, size_t n); jl_uniontype_t *jl_new_uniontype(jl_tuple_t *types); -jl_tag_type_t *jl_new_tagtype(jl_value_t *name, jl_tag_type_t *super, - jl_tuple_t *parameters); -jl_struct_type_t *jl_new_uninitialized_struct_type(size_t nfields); -jl_struct_type_t *jl_new_struct_type(jl_sym_t *name, jl_tag_type_t *super, - jl_tuple_t *parameters, - jl_tuple_t *fnames, jl_tuple_t *ftypes); -jl_bits_type_t *jl_new_bits_type(jl_value_t *name, jl_tag_type_t *super, - jl_tuple_t *parameters, size_t nbits); -jl_tag_type_t *jl_wrap_Type(jl_value_t *t); // x -> Type{x} -void jl_set_tag_type_super(jl_tag_type_t *tt, jl_value_t *super); +jl_datatype_t *jl_new_abstracttype(jl_value_t *name, jl_datatype_t *super, + jl_tuple_t *parameters); +jl_datatype_t *jl_new_uninitialized_datatype(size_t nfields); +jl_datatype_t *jl_new_datatype(jl_sym_t *name, jl_datatype_t *super, + jl_tuple_t *parameters, + jl_tuple_t *fnames, jl_tuple_t *ftypes, + int abstract, int mutabl); +jl_datatype_t *jl_new_bitstype(jl_value_t *name, jl_datatype_t *super, + jl_tuple_t *parameters, size_t nbits); +jl_datatype_t *jl_wrap_Type(jl_value_t *t); // x -> Type{x} +void jl_set_datatype_super(jl_datatype_t *tt, jl_value_t *super); // constructors -jl_value_t *jl_new_bits(jl_bits_type_t *bt, void *data); +jl_value_t *jl_new_bits(jl_datatype_t *bt, void *data); void jl_assign_bits(void *dest, jl_value_t *bits); -DLLEXPORT jl_value_t *jl_new_struct(jl_struct_type_t *type, ...); -DLLEXPORT jl_value_t *jl_new_struct_uninit(jl_struct_type_t *type); -DLLEXPORT jl_value_t *jl_new_structt(jl_struct_type_t *type, jl_tuple_t *t); +DLLEXPORT jl_value_t *jl_new_struct(jl_datatype_t *type, ...); +DLLEXPORT jl_value_t *jl_new_structv(jl_datatype_t *type, jl_value_t **args, uint32_t na); +DLLEXPORT jl_value_t *jl_new_struct_uninit(jl_datatype_t *type); jl_function_t *jl_new_closure(jl_fptr_t proc, jl_value_t *env, jl_lambda_info_t *li); jl_lambda_info_t *jl_new_lambda_info(jl_value_t *ast, jl_tuple_t *sparams); @@ -685,59 +729,64 @@ DLLEXPORT jl_value_t *jl_box_int64(int64_t x); jl_value_t *jl_box_uint64(uint64_t x); jl_value_t *jl_box_float32(float x); jl_value_t *jl_box_float64(double x); -jl_value_t *jl_box8 (jl_bits_type_t *t, int8_t x); -jl_value_t *jl_box16(jl_bits_type_t *t, int16_t x); -jl_value_t *jl_box32(jl_bits_type_t *t, int32_t x); -jl_value_t *jl_box64(jl_bits_type_t *t, int64_t x); -int8_t jl_unbox_bool(jl_value_t *v); -int8_t jl_unbox_int8(jl_value_t *v); -uint8_t jl_unbox_uint8(jl_value_t *v); -int16_t jl_unbox_int16(jl_value_t *v); -uint16_t jl_unbox_uint16(jl_value_t *v); -int32_t jl_unbox_int32(jl_value_t *v); -uint32_t jl_unbox_uint32(jl_value_t *v); -int64_t jl_unbox_int64(jl_value_t *v); -uint64_t jl_unbox_uint64(jl_value_t *v); -float jl_unbox_float32(jl_value_t *v); -double jl_unbox_float64(jl_value_t *v); - -#ifdef __LP64__ +jl_value_t *jl_box_voidpointer(void *x); +jl_value_t *jl_box8 (jl_datatype_t *t, int8_t x); +jl_value_t *jl_box16(jl_datatype_t *t, int16_t x); +jl_value_t *jl_box32(jl_datatype_t *t, int32_t x); +jl_value_t *jl_box64(jl_datatype_t *t, int64_t x); +DLLEXPORT int8_t jl_unbox_bool(jl_value_t *v); +DLLEXPORT int8_t jl_unbox_int8(jl_value_t *v); +DLLEXPORT uint8_t jl_unbox_uint8(jl_value_t *v); +DLLEXPORT int16_t jl_unbox_int16(jl_value_t *v); +DLLEXPORT uint16_t jl_unbox_uint16(jl_value_t *v); +DLLEXPORT int32_t jl_unbox_int32(jl_value_t *v); +DLLEXPORT uint32_t jl_unbox_uint32(jl_value_t *v); +DLLEXPORT int64_t jl_unbox_int64(jl_value_t *v); +DLLEXPORT uint64_t jl_unbox_uint64(jl_value_t *v); +DLLEXPORT float jl_unbox_float32(jl_value_t *v); +DLLEXPORT double jl_unbox_float64(jl_value_t *v); +DLLEXPORT void *jl_unbox_voidpointer(jl_value_t *v); + +#ifdef _P64 #define jl_box_long(x) jl_box_int64(x) +#define jl_box_ulong(x) jl_box_uint64(x) #define jl_unbox_long(x) jl_unbox_int64(x) #define jl_is_long(x) jl_is_int64(x) #define jl_long_type jl_int64_type #else #define jl_box_long(x) jl_box_int32(x) +#define jl_box_ulong(x) jl_box_uint32(x) #define jl_unbox_long(x) jl_unbox_int32(x) #define jl_is_long(x) jl_is_int32(x) #define jl_long_type jl_int32_type #endif // structs -void jl_compute_struct_offsets(jl_struct_type_t *st); -int jl_field_index(jl_struct_type_t *t, jl_sym_t *fld, int err); +void jl_compute_field_offsets(jl_datatype_t *st); +int jl_field_index(jl_datatype_t *t, jl_sym_t *fld, int err); DLLEXPORT jl_value_t *jl_get_nth_field(jl_value_t *v, size_t i); jl_value_t *jl_set_nth_field(jl_value_t *v, size_t i, jl_value_t *rhs); int jl_field_isdefined(jl_value_t *v, jl_sym_t *fld, int err); // arrays -DLLEXPORT jl_array_t *jl_new_array(jl_type_t *atype, jl_tuple_t *dims); -DLLEXPORT jl_array_t *jl_new_arrayv(jl_type_t *atype, ...); -jl_array_t *jl_new_array_(jl_type_t *atype, uint32_t ndims, size_t *dims); -DLLEXPORT jl_array_t *jl_reshape_array(jl_type_t *atype, jl_array_t *data, +DLLEXPORT jl_array_t *jl_new_array(jl_value_t *atype, jl_tuple_t *dims); +DLLEXPORT jl_array_t *jl_new_arrayv(jl_value_t *atype, ...); +jl_array_t *jl_new_array_(jl_value_t *atype, uint32_t ndims, size_t *dims); +DLLEXPORT jl_array_t *jl_reshape_array(jl_value_t *atype, jl_array_t *data, jl_tuple_t *dims); -DLLEXPORT jl_array_t *jl_ptr_to_array_1d(jl_type_t *atype, void *data, +DLLEXPORT jl_array_t *jl_ptr_to_array_1d(jl_value_t *atype, void *data, size_t nel, int own_buffer); -DLLEXPORT jl_array_t *jl_ptr_to_array(jl_type_t *atype, void *data, +DLLEXPORT jl_array_t *jl_ptr_to_array(jl_value_t *atype, void *data, jl_tuple_t *dims, int own_buffer); +int jl_array_store_unboxed(jl_value_t *el_type); -DLLEXPORT jl_array_t *jl_alloc_array_1d(jl_type_t *atype, size_t nr); -DLLEXPORT jl_array_t *jl_alloc_array_2d(jl_type_t *atype, size_t nr, size_t nc); -DLLEXPORT jl_array_t *jl_alloc_array_3d(jl_type_t *atype, size_t nr, size_t nc, +DLLEXPORT jl_array_t *jl_alloc_array_1d(jl_value_t *atype, size_t nr); +DLLEXPORT jl_array_t *jl_alloc_array_2d(jl_value_t *atype, size_t nr, size_t nc); +DLLEXPORT jl_array_t *jl_alloc_array_3d(jl_value_t *atype, size_t nr, size_t nc, size_t z); -DLLEXPORT jl_array_t *jl_pchar_to_array(char *str, size_t len); -DLLEXPORT jl_value_t *jl_pchar_to_string(char *str, size_t len); -DLLEXPORT jl_value_t *jl_cstr_to_string(char *str); +DLLEXPORT jl_array_t *jl_pchar_to_array(const char *str, size_t len); +DLLEXPORT jl_value_t *jl_pchar_to_string(const char *str, size_t len); +DLLEXPORT jl_value_t *jl_cstr_to_string(const char *str); DLLEXPORT jl_value_t *jl_array_to_string(jl_array_t *a); DLLEXPORT jl_array_t *jl_alloc_cell_1d(size_t n); DLLEXPORT jl_value_t *jl_arrayref(jl_array_t *a, size_t i); // 0-indexed @@ -749,6 +798,8 @@ DLLEXPORT void jl_array_grow_end(jl_array_t *a, size_t inc); DLLEXPORT void jl_array_del_end(jl_array_t *a, size_t dec); DLLEXPORT void jl_array_grow_beg(jl_array_t *a, size_t inc); DLLEXPORT void jl_array_del_beg(jl_array_t *a, size_t dec); +DLLEXPORT void jl_array_sizehint(jl_array_t *a, size_t sz); +DLLEXPORT void *jl_value_ptr(jl_value_t *a); void jl_cell_1d_push(jl_array_t *a, jl_value_t *item); // system information @@ -758,24 +809,57 @@ DLLEXPORT int32_t jl_stat(const char* path, char* statbuf); // environment entries DLLEXPORT jl_value_t *jl_environ(int i); +#ifdef __WIN32__ +DLLEXPORT jl_value_t *jl_env_done(char *pos); +#endif + +DLLEXPORT int jl_spawn(char *name, char **argv, uv_loop_t *loop, + uv_process_t *proc, jl_value_t *julia_struct, + uv_handle_type stdin_type,uv_pipe_t *stdin_pipe, + uv_handle_type stdout_type,uv_pipe_t *stdout_pipe, + uv_handle_type stderr_type,uv_pipe_t *stderr_pipe); +DLLEXPORT void jl_run_event_loop(uv_loop_t *loop); +DLLEXPORT int jl_run_once(uv_loop_t *loop); +DLLEXPORT int jl_process_events(uv_loop_t *loop); + +DLLEXPORT uv_loop_t *jl_global_event_loop(); -// child process status -DLLEXPORT int jl_process_exited(int status); -DLLEXPORT int jl_process_signaled(int status); -DLLEXPORT int jl_process_stopped(int status); +DLLEXPORT uv_pipe_t *jl_make_pipe(int writable, int julia_only, jl_value_t *julia_struct); +DLLEXPORT void jl_close_uv(uv_handle_t *handle); -DLLEXPORT int jl_process_exit_status(int status); -DLLEXPORT int jl_process_term_signal(int status); -DLLEXPORT int jl_process_stop_signal(int status); +DLLEXPORT int16_t jl_start_reading(uv_stream_t *handle); -// access to std filehandles -DLLEXPORT int jl_stdin(void); -DLLEXPORT int jl_stdout(void); -DLLEXPORT int jl_stderr(void); +DLLEXPORT void jl_callback(void *callback); + +DLLEXPORT uv_async_t *jl_make_async(uv_loop_t *loop, jl_value_t *julia_struct); +DLLEXPORT void jl_async_send(uv_async_t *handle); +DLLEXPORT uv_idle_t * jl_make_idle(uv_loop_t *loop, jl_value_t *julia_struct); +DLLEXPORT int jl_idle_start(uv_idle_t *idle); +DLLEXPORT int jl_idle_stop(uv_idle_t *idle); + +DLLEXPORT int jl_putc(unsigned char c, uv_stream_t *stream); +DLLEXPORT int jl_puts(char *str, uv_stream_t *stream); +DLLEXPORT int jl_pututf8(uv_stream_t *s, uint32_t wchar); + +DLLEXPORT uv_timer_t *jl_make_timer(uv_loop_t *loop, jl_value_t *julia_struct); +DLLEXPORT int jl_timer_stop(uv_timer_t* timer); + +DLLEXPORT uv_tcp_t *jl_tcp_init(uv_loop_t *loop); +DLLEXPORT int jl_tcp_bind(uv_tcp_t* handle, uint16_t port, uint32_t host); + +DLLEXPORT void NORETURN jl_exit(int status); + +DLLEXPORT size_t jl_sizeof_uv_stream_t(); +DLLEXPORT size_t jl_sizeof_uv_pipe_t(); +DLLEXPORT int jl_sizeof_ios_t(); + +#ifdef __WIN32__ +DLLEXPORT struct tm* localtime_r(const time_t *t, struct tm *tm); +#endif // exceptions -void jl_error(const char *str); -void jl_errorf(const char *fmt, ...); +void NORETURN jl_error(const char *str); +void NORETURN jl_errorf(const char *fmt, ...); void jl_too_few_args(const char *fname, int min); void jl_too_many_args(const char *fname, int max); void jl_type_error(const char *fname, jl_value_t *expected, jl_value_t *got); @@ -802,10 +886,11 @@ void jl_restore_system_image(char *fname); // front end interface DLLEXPORT jl_value_t *jl_parse_input_line(const char *str); +DLLEXPORT jl_value_t *jl_parse_string(const char *str, int pos0, int greedy); void jl_start_parsing_file(const char *fname); void jl_stop_parsing(); jl_value_t *jl_parse_next(); -DLLEXPORT void jl_load_file_string(const char *text); +DLLEXPORT void jl_load_file_string(const char *text, char *filename); DLLEXPORT jl_value_t *jl_expand(jl_value_t *expr); jl_lambda_info_t *jl_wrap_expr(jl_value_t *expr); @@ -816,6 +901,7 @@ DLLEXPORT jl_value_t *jl_stdout_obj(); DLLEXPORT jl_value_t *jl_stderr_obj(); DLLEXPORT int jl_egal(jl_value_t *a, jl_value_t *b); DLLEXPORT uptrint_t jl_object_id(jl_value_t *v); +void jl_debug_print_type(JL_STREAM *s, jl_value_t *v); // modules extern DLLEXPORT jl_module_t *jl_main_module; @@ -837,13 +923,34 @@ DLLEXPORT void jl_set_const(jl_module_t *m, jl_sym_t *var, jl_value_t *val); void jl_checked_assignment(jl_binding_t *b, jl_value_t *rhs); void jl_declare_constant(jl_binding_t *b); void jl_module_using(jl_module_t *to, jl_module_t *from); +void jl_module_use(jl_module_t *to, jl_module_t *from, jl_sym_t *s); void jl_module_import(jl_module_t *to, jl_module_t *from, jl_sym_t *s); +void jl_module_importall(jl_module_t *to, jl_module_t *from); DLLEXPORT void jl_module_export(jl_module_t *from, jl_sym_t *s); +void jl_add_standard_imports(jl_module_t *m); // external libraries -DLLEXPORT uv_lib_t *jl_load_dynamic_library(char *fname); +enum JL_RTLD_CONSTANT { + JL_RTLD_LOCAL=0U, JL_RTLD_GLOBAL=1U, /* LOCAL=0 since it is the default */ + JL_RTLD_LAZY=2U, JL_RTLD_NOW=4U, + /* Linux/glibc and MacOS X: */ + JL_RTLD_NODELETE=8U, JL_RTLD_NOLOAD=16U, + /* Linux/glibc: */ JL_RTLD_DEEPBIND=32U, + /* MacOS X 10.5+: */ JL_RTLD_FIRST=64U +}; +#define JL_RTLD_DEFAULT (JL_RTLD_LAZY | JL_RTLD_DEEPBIND) +DLLEXPORT uv_lib_t *jl_load_dynamic_library(char *fname, unsigned flags); +DLLEXPORT uv_lib_t *jl_load_dynamic_library_e(char *fname, unsigned flags); DLLEXPORT void *jl_dlsym_e(uv_lib_t *handle, char *symbol); DLLEXPORT void *jl_dlsym(uv_lib_t *handle, char *symbol); +DLLEXPORT uv_lib_t *jl_wrap_raw_dl_handle(void *handle); +void *jl_dlsym_e(uv_lib_t *handle, char *symbol); //supress errors +void *jl_dlsym_win32(char *name); +DLLEXPORT int add_library_mapping(char *lib, void *hnd); + +// event loop +DLLEXPORT void jl_runEventLoop(); +DLLEXPORT void jl_processEvents(); // compiler void jl_compile(jl_function_t *f); @@ -876,13 +983,14 @@ jl_array_t *jl_lam_locals(jl_expr_t *l); jl_array_t *jl_lam_vinfo(jl_expr_t *l); jl_array_t *jl_lam_capt(jl_expr_t *l); jl_expr_t *jl_lam_body(jl_expr_t *l); +jl_value_t *jl_ast_rettype(jl_lambda_info_t *li, jl_value_t *ast); jl_sym_t *jl_decl_var(jl_value_t *ex); DLLEXPORT int jl_is_rest_arg(jl_value_t *ex); jl_value_t *jl_prepare_ast(jl_lambda_info_t *li, jl_tuple_t *sparams); jl_value_t *jl_compress_ast(jl_lambda_info_t *li, jl_value_t *ast); -jl_value_t *jl_uncompress_ast(jl_tuple_t *data); +jl_value_t *jl_uncompress_ast(jl_lambda_info_t *li, jl_value_t *data); static inline int jl_vinfo_capt(jl_array_t *vi) { @@ -925,33 +1033,36 @@ jl_value_t *jl_apply(jl_function_t *f, jl_value_t **args, uint32_t nargs) #ifdef JL_GC_MARKSWEEP typedef struct _jl_gcframe_t { - jl_value_t ***roots; size_t nroots; - int indirect; struct _jl_gcframe_t *prev; + // actual roots go here } jl_gcframe_t; // NOTE: it is the caller's responsibility to make sure arguments are // rooted. foo(f(), g()) will not work, and foo can't do anything about it, // so the caller must do -// jl_value_t *x, *y; JL_GC_PUSH(&x, &y); +// jl_value_t *x=NULL, *y=NULL; JL_GC_PUSH(&x, &y); // x = f(); y = g(); foo(x, y) extern DLLEXPORT jl_gcframe_t *jl_pgcstack; -#define JL_GC_PUSH(...) \ - void *__gc_rts[] = {__VA_ARGS__}; \ - jl_gcframe_t __gc_stkf_ = { (jl_value_t***)__gc_rts, VA_NARG(__VA_ARGS__), \ - 1, jl_pgcstack }; \ - jl_pgcstack = &__gc_stkf_; +#define JL_GC_PUSH(...) \ + void *__gc_stkf[] = {(void*)((VA_NARG(__VA_ARGS__)<<1)|1), jl_pgcstack, \ + __VA_ARGS__}; \ + jl_pgcstack = (jl_gcframe_t*)__gc_stkf; -#define JL_GC_PUSHARGS(rts,n) \ - jl_gcframe_t __gc_stkf2_ = { (jl_value_t***)rts, (n), \ - 0, jl_pgcstack }; \ - jl_pgcstack = &__gc_stkf2_; +#define JL_GC_PUSHARGS(rts_var,n) \ + rts_var = ((jl_value_t**)alloca(((n)+2)*sizeof(jl_value_t*)))+2; \ + ((void**)rts_var)[-2] = (void*)(((size_t)n)<<1); \ + ((void**)rts_var)[-1] = jl_pgcstack; \ + jl_pgcstack = (jl_gcframe_t*)&(((void**)rts_var)[-2]) #define JL_GC_POP() (jl_pgcstack = jl_pgcstack->prev) +#ifdef GC_FINAL_STATS +void jl_print_gc_stats(JL_STREAM *s); +#endif + void jl_gc_init(void); void jl_gc_setmark(jl_value_t *v); DLLEXPORT void jl_gc_enable(void); @@ -992,6 +1103,7 @@ static inline void *alloc_4w() { return allocobj(4*sizeof(void*)); } DLLEXPORT extern volatile sig_atomic_t jl_signal_pending; DLLEXPORT extern volatile sig_atomic_t jl_defer_signal; +DLLEXPORT void jl_handle_sigint(); #define JL_SIGATOMIC_BEGIN() (jl_defer_signal++) #define JL_SIGATOMIC_END() \ @@ -1001,6 +1113,8 @@ DLLEXPORT extern volatile sig_atomic_t jl_defer_signal; raise(jl_signal_pending); \ } while(0) +DLLEXPORT void restore_signals(void); + // tasks and exceptions // info describing an exception handler @@ -1013,13 +1127,14 @@ typedef struct _jl_handler_t { } jl_handler_t; typedef struct _jl_task_t { - JL_STRUCT_TYPE + JL_DATA_TYPE struct _jl_task_t *on_exit; struct _jl_task_t *last; jl_value_t *tls; jl_value_t *consumers; int8_t done; int8_t runnable; + jl_value_t *result; jl_jmp_buf ctx; union { void *stackbase; @@ -1030,22 +1145,30 @@ typedef struct _jl_task_t { void *stkbuf; size_t ssize; jl_function_t *start; - jl_value_t *result; // current exception handler jl_handler_t *eh; // saved gc stack top for context switches jl_gcframe_t *gcstack; } jl_task_t; +typedef union jl_any_stream { + ios_t ios; + uv_stream_t stream; +} jl_any_stream; + +DLLEXPORT void jl_uv_associate_julia_struct(uv_handle_t *handle, jl_value_t *data); +DLLEXPORT int jl_uv_fs_result(uv_fs_t *f); + extern DLLEXPORT jl_task_t * volatile jl_current_task; extern DLLEXPORT jl_task_t *jl_root_task; extern DLLEXPORT jl_value_t *jl_exception_in_transit; jl_task_t *jl_new_task(jl_function_t *start, size_t ssize); jl_value_t *jl_switchto(jl_task_t *t, jl_value_t *arg); -DLLEXPORT void jl_throw(jl_value_t *e); -DLLEXPORT void jl_rethrow(); -DLLEXPORT void jl_rethrow_other(jl_value_t *e); +DLLEXPORT void NORETURN jl_throw(jl_value_t *e); +DLLEXPORT void NORETURN jl_throw_with_superfluous_argument(jl_value_t *e, int); +DLLEXPORT void NORETURN jl_rethrow(); +DLLEXPORT void NORETURN jl_rethrow_other(jl_value_t *e); DLLEXPORT jl_array_t *jl_takebuf_array(ios_t *s); DLLEXPORT jl_value_t *jl_takebuf_string(ios_t *s); @@ -1055,14 +1178,20 @@ DLLEXPORT void jl_free2(void *p, void *hint); DLLEXPORT int jl_cpu_cores(void); -#define JL_STDOUT ios_stdout -#define JL_STDERR ios_stderr -#define JL_PRINTF ios_printf -#define JL_PUTC ios_putc -#define JL_PUTS ios_puts -#define JL_WRITE ios_write -#define jl_exit exit -#define JL_STREAM ios_t +DLLEXPORT size_t jl_write(uv_stream_t *stream, const char *str, size_t n); +DLLEXPORT int jl_printf(uv_stream_t *s, const char *format, ...); +DLLEXPORT int jl_vprintf(uv_stream_t *s, const char *format, va_list args); + +DLLEXPORT size_t rec_backtrace(ptrint_t *data, size_t maxsize); + +//IO objects +extern DLLEXPORT uv_stream_t *jl_uv_stdin; //these are actually uv_tty_t's and can be cast to such, but that gives warnings whenver they are used as streams +extern DLLEXPORT uv_stream_t * jl_uv_stdout; +extern DLLEXPORT uv_stream_t * jl_uv_stderr; + +DLLEXPORT JL_STREAM *jl_stdout_stream(); +DLLEXPORT JL_STREAM *jl_stdin_stream(); +DLLEXPORT JL_STREAM *jl_stderr_stream(); static inline void jl_eh_restore_state(jl_handler_t *eh) { @@ -1078,9 +1207,11 @@ DLLEXPORT void jl_enter_handler(jl_handler_t *eh); DLLEXPORT void jl_pop_handler(int n); #if defined(__WIN32__) -#define jl_setjmp_f _setjmp -#define jl_setjmp(a,b) setjmp(a) -#define jl_longjmp(a,b) longjmp(a,b) +int __attribute__ ((__nothrow__,__returns_twice__)) jl_setjmp(jmp_buf _Buf); +__declspec(noreturn) __attribute__ ((__nothrow__)) void jl_longjmp(jmp_buf _Buf,int _Value); +#define jl_setjmp_f jl_setjmp +#define jl_setjmp(a,b) jl_setjmp(a) +#define jl_longjmp(a,b) jl_longjmp(a,b) #else // determine actual entry point name #if defined(sigsetjmp) @@ -1100,8 +1231,15 @@ DLLEXPORT void jl_pop_handler(int n); #define JL_EH_POP() jl_eh_restore_state(&__eh) +#ifdef __WIN32__ +#define JL_CATCH \ + else \ + for (i__ca=1, jl_eh_restore_state(&__eh); i__ca; i__ca=0) \ + if (((jl_exception_in_transit==jl_stackovf_exception) && _resetstkoflw()) || 1) +#else #define JL_CATCH \ else \ for (i__ca=1, jl_eh_restore_state(&__eh); i__ca; i__ca=0) +#endif #endif diff --git a/src/module.c b/src/module.c index 67dc1eb1e4a44..36483d916d4c4 100644 --- a/src/module.c +++ b/src/module.c @@ -12,7 +12,7 @@ jl_module_t *jl_current_module=NULL; jl_module_t *jl_new_module(jl_sym_t *name) { jl_module_t *m = (jl_module_t*)allocobj(sizeof(jl_module_t)); - m->type = (jl_type_t*)jl_module_type; + m->type = (jl_value_t*)jl_module_type; m->name = name; htable_new(&m->bindings, 0); jl_set_const(m, name, (jl_value_t*)m); @@ -25,12 +25,29 @@ jl_module_t *jl_new_module(jl_sym_t *name) return m; } +JL_CALLABLE(jl_f_new_module) +{ + jl_sym_t *name; + if (nargs == 0) { + name = anonymous_sym; + } + else { + JL_NARGS(Module, 1, 1); + JL_TYPECHK(Module, symbol, args[0]); + name = (jl_sym_t*)args[0]; + } + jl_module_t *m = jl_new_module(name); + m->parent = jl_main_module; + jl_add_standard_imports(m); + return (jl_value_t*)m; +} + static jl_binding_t *new_binding(jl_sym_t *name) { jl_binding_t *b = (jl_binding_t*)allocb(sizeof(jl_binding_t)); b->name = name; b->value = NULL; - b->type = (jl_type_t*)jl_any_type; + b->type = (jl_value_t*)jl_any_type; b->owner = NULL; b->constp = 0; b->exportp = 0; @@ -51,7 +68,7 @@ jl_binding_t *jl_get_binding_wr(jl_module_t *m, jl_sym_t *var) } else if ((*bp)->owner != m) { // TODO: change this to an error soon - ios_printf(JL_STDERR, + jl_printf(JL_STDERR, "Warning: imported binding for %s overwritten in module %s\n", var->name, m->name->name); } else { @@ -140,6 +157,14 @@ jl_binding_t *jl_get_binding(jl_module_t *m, jl_sym_t *var) return jl_get_binding_(m, var, NULL); } +static int eq_bindings(jl_binding_t *a, jl_binding_t *b) +{ + if (a==b) return 1; + if (a->name == b->name && a->owner == b->owner) return 1; + if (a->constp && a->value && b->constp && b->value == a->value) return 1; + return 0; +} + static void module_import_(jl_module_t *to, jl_module_t *from, jl_sym_t *s, int explicit) { @@ -147,9 +172,9 @@ static void module_import_(jl_module_t *to, jl_module_t *from, jl_sym_t *s, return; jl_binding_t *b = jl_get_binding(from, s); if (b == NULL) { - ios_printf(JL_STDERR, - "Warning: could not import %s.%s into %s\n", - from->name->name, s->name, to->name->name); + jl_printf(JL_STDERR, + "Warning: could not import %s.%s into %s\n", + from->name->name, s->name, to->name->name); } else { jl_binding_t **bp = (jl_binding_t**)ptrhash_bp(&to->bindings, s); @@ -163,20 +188,27 @@ static void module_import_(jl_module_t *to, jl_module_t *from, jl_sym_t *s, bto->imported = (explicit!=0); } else if (bto->owner != to && bto->owner != NULL) { - ios_printf(JL_STDERR, - "Warning: ignoring conflicting import of %s.%s into %s\n", - from->name->name, s->name, to->name->name); + // already imported from somewhere else + jl_binding_t *bval = jl_get_binding(to, s); + if (bval->constp && bval->value && b->constp && b->value == bval->value) { + // equivalent binding + bto->imported = (explicit!=0); + return; + } + jl_printf(JL_STDERR, + "Warning: ignoring conflicting import of %s.%s into %s\n", + from->name->name, s->name, to->name->name); } else if (bto->constp || bto->value) { + // conflict with name owned by destination module assert(bto->owner == to); - if (bto->constp && bto->value && b->constp && - b->value == bto->value) { - // import of equivalent binding + if (bto->constp && bto->value && b->constp && b->value == bto->value) { + // equivalent binding return; } - ios_printf(JL_STDERR, - "Warning: import of %s.%s into %s conflicts with an existing identifier; ignored.\n", - from->name->name, s->name, to->name->name); + jl_printf(JL_STDERR, + "Warning: import of %s.%s into %s conflicts with an existing identifier; ignored.\n", + from->name->name, s->name, to->name->name); } else { bto->owner = b->owner; @@ -197,6 +229,23 @@ void jl_module_import(jl_module_t *to, jl_module_t *from, jl_sym_t *s) module_import_(to, from, s, 1); } +void jl_module_use(jl_module_t *to, jl_module_t *from, jl_sym_t *s) +{ + module_import_(to, from, s, 0); +} + +void jl_module_importall(jl_module_t *to, jl_module_t *from) +{ + void **table = from->bindings.table; + for(size_t i=1; i < from->bindings.size; i+=2) { + if (table[i] != HT_NOTFOUND) { + jl_binding_t *b = (jl_binding_t*)table[i]; + if (b->exportp && (b->owner==from || b->imported)) + jl_module_import(to, from, b->name); + } + } +} + void jl_module_using(jl_module_t *to, jl_module_t *from) { if (to == from) @@ -205,6 +254,27 @@ void jl_module_using(jl_module_t *to, jl_module_t *from) if (from == to->usings.items[i]) return; } + // print a warning if something visible via this "using" conflicts with + // an existing identifier. note that an identifier added later may still + // silently override a "using" name. + void **table = from->bindings.table; + for(size_t i=1; i < from->bindings.size; i+=2) { + if (table[i] != HT_NOTFOUND) { + jl_binding_t *b = (jl_binding_t*)table[i]; + if (b->exportp && (b->owner==from || b->imported)) { + //jl_module_import(to, from, b->name); + jl_sym_t *var = (jl_sym_t*)table[i-1]; + jl_binding_t **tobp = (jl_binding_t**)ptrhash_bp(&to->bindings, var); + if (*tobp != HT_NOTFOUND && (*tobp)->owner != NULL && + !eq_bindings(jl_get_binding(to,var), b)) { + jl_printf(JL_STDERR, + "Warning: using %s.%s in module %s conflicts with an existing identifier.\n", + from->name->name, var->name, to->name->name); + } + } + } + } + arraylist_push(&to->usings, from); } @@ -268,13 +338,14 @@ DLLEXPORT int jl_is_const(jl_module_t *m, jl_sym_t *var) void jl_checked_assignment(jl_binding_t *b, jl_value_t *rhs) { if (b->constp && b->value != NULL) { - //jl_errorf("cannot redefine constant %s", b->name->name); - JL_PRINTF(JL_STDERR, "Warning: redefinition of constant %s ignored.\n", - b->name->name); - } - else { - b->value = rhs; + if (!jl_egal(rhs, b->value) && + (jl_typeof(rhs) != jl_typeof(b->value) || + jl_is_type(rhs) || jl_is_function(rhs) || jl_is_module(rhs))) { + jl_errorf("invalid redefinition of constant %s", b->name->name); + } + JL_PRINTF(JL_STDERR,"Warning: redefining constant %s\n",b->name->name); } + b->value = rhs; } void jl_declare_constant(jl_binding_t *b) @@ -309,7 +380,7 @@ DLLEXPORT jl_value_t *jl_module_names(jl_module_t *m, int all) if (b->exportp || (b->owner == m && (all || m == jl_main_module))) { jl_array_grow_end(a, 1); //XXX: change to jl_arrayset if array storage allocation for Array{Symbols,1} changes: - jl_cellset(a, a->length-1, (jl_value_t*)b->name); + jl_cellset(a, jl_array_dim0(a)-1, (jl_value_t*)b->name); } } } diff --git a/src/newobj_internal.h b/src/newobj_internal.h index 7af224a4c6ff4..72d9ce4415ede 100644 --- a/src/newobj_internal.h +++ b/src/newobj_internal.h @@ -1,23 +1,20 @@ #ifndef NEWOBJ_INTERNAL_H #define NEWOBJ_INTERNAL_H -static inline jl_value_t *newobj(jl_type_t *type, size_t nfields) +static inline jl_value_t *newobj(jl_value_t *type, size_t nfields) { jl_value_t *jv = (jl_value_t*)allocobj((1+nfields) * sizeof(void*)); jv->type = type; return jv; } -static inline jl_value_t *newstruct(jl_struct_type_t *type) +static inline jl_value_t *newstruct(jl_datatype_t *type) { jl_value_t *jv = (jl_value_t*)allocobj(sizeof(void*) + type->size); - jv->type = (jl_type_t*)type; + jv->type = (jl_value_t*)type; return jv; } -#define TAG_TYPE_NW (NWORDS(sizeof(jl_tag_type_t))-1) -#define BITS_TYPE_NW (NWORDS(sizeof(jl_bits_type_t))-1) - int jl_assign_type_uid(void); #endif diff --git a/src/os_detect.h b/src/os_detect.h index f608207db51a3..d1969d3dddc02 100644 --- a/src/os_detect.h +++ b/src/os_detect.h @@ -70,7 +70,7 @@ const OS_NAME = :OS_CURRENT #define OS_NAME_IFELSE(NUM,NAME) JL_IF(JL_BOOL(NUM),elseif,if) (os==:NAME) return #define ATTR(IS_UNIX) JL_TF(JL_BOOL(IS_UNIX)); \n -function _jl_is_unix(os::Symbol) +function is_unix(os::Symbol) JL_OS_MAP2(OS_NAME_IFELSE,ATTR) else error("Unknown Operating System") diff --git a/src/support/Makefile b/src/support/Makefile index feaf1e6a9d38f..5a826f0b1a1e5 100644 --- a/src/support/Makefile +++ b/src/support/Makefile @@ -4,16 +4,22 @@ include $(JULIAHOME)/Make.inc override CFLAGS += $(JCFLAGS) override CXXFLAGS += $(JCXXFLAGS) -SRCS = hashing.c timefuncs.c dblprint.c ptrhash.c operators.c socket.c \ - utf8.c ios.c htable.c bitvector.c \ - int2str.c libsupportinit.c arraylist.c +OBJS = hashing.o timefuncs.o dblprint.o ptrhash.o operators.o \ + utf8.o ios.o htable.o bitvector.o \ + int2str.o libsupportinit.o arraylist.o ifeq ($(OS),WINNT) -SRCS += asprintf +OBJS += asprintf.o wcwidth.o +ifeq ($(ARCH),i686) +OBJS += _setjmp.win32.o _longjmp.win32.o +else ifeq ($(ARCH),i386) +OBJS += _setjmp.win32.o _longjmp.win32.o +else ifeq ($(ARCH),x86_64) +OBJS += _setjmp.win64.o _longjmp.win64.o +endif endif -OBJS = $(SRCS:%.c=%.o) -DOBJS = $(SRCS:%.c=%.do) +DOBJS = $(OBJS:%.o=%.do) ifneq ($(MAKECMDGOALS),debug) XOBJS = $(OBJS) @@ -31,15 +37,19 @@ default: release HEADERS = $(wildcard *.h) $(JULIAHOME)/deps/libuv/include/uv.h %.o: %.c $(HEADERS) - $(QUIET_CC) $(CC) $(SHIPFLAGS) -c $< -o $@ + $(QUIET_CC) $(CC) $(CPPFLAGS) $(SHIPFLAGS) -c $< -o $@ %.do: %.c $(HEADERS) - $(QUIET_CC) $(CC) $(DEBUGFLAGS) -c $< -o $@ + $(QUIET_CC) $(CC) $(CPPFLAGS) $(DEBUGFLAGS) -c $< -o $@ +%.o: %.S + $(QUIET_CC) $(CC) $(CPPFLAGS) $(SHIPFLAGS) -c $< -o $@ +%.do: %.S + $(QUIET_CC) $(CC) $(CPPFLAGS) $(DEBUGFLAGS) -c $< -o $@ release debug: libsupport.a libsupport.a: $(XOBJS) rm -rf $@ - $(QUIET_LINK) ar -rcs $@ $^ + $(QUIET_LINK) $(AR) -rcs $@ $^ clean: rm -f *.o diff --git a/src/support/MurmurHash3.h b/src/support/MurmurHash3.h index e5b7f30292a62..7f29e4d50c220 100644 --- a/src/support/MurmurHash3.h +++ b/src/support/MurmurHash3.h @@ -7,23 +7,8 @@ //----------------------------------------------------------------------------- // Platform-specific functions and macros - -// Microsoft Visual Studio - -#if defined(_MSC_VER) - -typedef unsigned char uint8_t; -typedef unsigned long uint32_t; -typedef unsigned __int64 uint64_t; - -// Other compilers - -#else // defined(_MSC_VER) - #include -#endif // !defined(_MSC_VER) - //----------------------------------------------------------------------------- void MurmurHash3_x86_32 ( const void * key, int len, uint32_t seed, void * out ); diff --git a/src/support/_longjmp.win32.S b/src/support/_longjmp.win32.S new file mode 100644 index 0000000000000..8a8411029d33c --- /dev/null +++ b/src/support/_longjmp.win32.S @@ -0,0 +1,69 @@ +/* $NetBSD: _setjmp.S,v 1.8 2005/10/05 20:18:12 christos Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of the 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 REGENTS 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 REGENTS 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. + * + * from: @(#)_setjmp.s 5.1 (Berkeley) 4/23/90 + */ + +/*#include +#if defined(LIBC_SCCS) + RCSID("$NetBSD: _setjmp.S,v 1.8 2005/10/05 20:18:12 christos Exp $") +#endif +*/ +#include "../../deps/openlibm/i387/bsd_asm.h" + +/* + * C library -- _setjmp, _longjmp + * + * _longjmp(a,v) + * will generate a "return(v)" from the last call to + * _setjmp(a) + * by restoring registers from the stack. + * The previous signal state is NOT restored. + */ + +ENTRY(jl_longjmp) + movl 4(%esp),%edx + movl 8(%esp),%eax + movl 0(%edx),%ebp + movl 4(%edx),%ebx + movl 8(%edx),%edi + movl 12(%edx),%esi + movl 16(%edx),%esp + movl 20(%edx),%ecx + testl %eax,%eax + jnz 1f + incl %eax +1: movl %ecx,0(%esp) + ret +END(jl_longjmp) + diff --git a/src/support/_longjmp.win64.S b/src/support/_longjmp.win64.S new file mode 100644 index 0000000000000..37674a4fee51e --- /dev/null +++ b/src/support/_longjmp.win64.S @@ -0,0 +1,87 @@ +/* $NetBSD: _setjmp.S,v 1.1 2001/06/19 00:25:02 fvdl Exp $ */ + +/* + * Copyright (c) 2001 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Frank van der Linden for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC + * 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. + */ + +/* +#include +#include +#if defined(LIBC_SCCS) + RCSID("$NetBSD: _setjmp.S,v 1.1 2001/06/19 00:25:02 fvdl Exp $") +#endif +*/ +#include "../../deps/openlibm/amd64/bsd_asm.h" + + +/* + * C library -- _setjmp, _longjmp + * + * _longjmp(a,v) + * will generate a "return(v)" from the last call to + * _setjmp(a) + * by restoring registers from the stack. + * The previous signal state is NOT restored. + */ + +ENTRY(jl_longjmp) + movq 8(%rcx),%rbx + movq 16(%rcx),%rsp + movq 24(%rcx),%rbp + movq 32(%rcx),%rsi + movq 40(%rcx),%rdi + movq 48(%rcx),%r12 + movq 56(%rcx),%r13 + movq 64(%rcx),%r14 + movq 72(%rcx),%r15 + movq 80(%rcx),%r8 + movaps 96(%rcx),%xmm6 + movaps 112(%rcx),%xmm7 + movaps 128(%rcx),%xmm8 + movaps 144(%rcx),%xmm9 + movaps 160(%rcx),%xmm10 + movaps 176(%rcx),%xmm11 + movaps 192(%rcx),%xmm12 + movaps 208(%rcx),%xmm13 + movaps 224(%rcx),%xmm14 + movaps 240(%rcx),%xmm15 + + movl %edx,%eax + testl %eax,%eax + jnz 1f + incl %eax +1: movq %r8,0(%rsp) + ret +END(jl_longjmp) + diff --git a/src/support/_setjmp.win32.S b/src/support/_setjmp.win32.S new file mode 100644 index 0000000000000..db1fcb9d5f9e1 --- /dev/null +++ b/src/support/_setjmp.win32.S @@ -0,0 +1,66 @@ +/* $NetBSD: _setjmp.S,v 1.8 2005/10/05 20:18:12 christos Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of the 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 REGENTS 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 REGENTS 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. + * + * from: @(#)_setjmp.s 5.1 (Berkeley) 4/23/90 + */ + +/*#include +#if defined(LIBC_SCCS) + RCSID("$NetBSD: _setjmp.S,v 1.8 2005/10/05 20:18:12 christos Exp $") +#endif +*/ +#include "../../deps/openlibm/i387/bsd_asm.h" + +/* + * C library -- _setjmp, _longjmp + * + * _longjmp(a,v) + * will generate a "return(v)" from the last call to + * _setjmp(a) + * by restoring registers from the stack. + * The previous signal state is NOT restored. + */ + +ENTRY(jl_setjmp) + movl 4(%esp),%eax + movl 0(%esp),%edx + movl %ebp, 0(%eax) /* rta */ + movl %ebx, 4(%eax) + movl %edi, 8(%eax) + movl %esi,12(%eax) + movl %esp,16(%eax) + movl %edx,20(%eax) + xorl %eax,%eax + ret +END(jl_setjmp) + diff --git a/src/support/_setjmp.win64.S b/src/support/_setjmp.win64.S new file mode 100644 index 0000000000000..9475c7f44a3ab --- /dev/null +++ b/src/support/_setjmp.win64.S @@ -0,0 +1,85 @@ +/* $NetBSD: _setjmp.S,v 1.1 2001/06/19 00:25:02 fvdl Exp $ */ + +/* + * Copyright (c) 2001 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Frank van der Linden for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC + * 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. + */ + +/* +#include +#include +#if defined(LIBC_SCCS) + RCSID("$NetBSD: _setjmp.S,v 1.1 2001/06/19 00:25:02 fvdl Exp $") +#endif +*/ +#include "../../deps/openlibm/amd64/bsd_asm.h" + +/* + * C library -- _setjmp, _longjmp + * + * _longjmp(a,v) + * will generate a "return(v)" from the last call to + * _setjmp(a) + * by restoring registers from the stack. + * The previous signal state is NOT restored. + */ + +ENTRY(jl_setjmp) + movq 0(%rsp),%rdx + movq $0,0(%rcx) + movq %rbx,8(%rcx) + movq %rsp,16(%rcx) + movq %rbp,24(%rcx) + movq %rsi,32(%rcx) + movq %rdi,40(%rcx) + movq %r12,48(%rcx) + movq %r13,56(%rcx) + movq %r14,64(%rcx) + movq %r15,72(%rcx) + movq %rdx,80(%rcx) + movq $0,88(%rcx) + movaps %xmm6,96(%rcx) + movaps %xmm7,112(%rcx) + movaps %xmm8,128(%rcx) + movaps %xmm9,144(%rcx) + movaps %xmm10,160(%rcx) + movaps %xmm11,176(%rcx) + movaps %xmm12,192(%rcx) + movaps %xmm13,208(%rcx) + movaps %xmm14,224(%rcx) + movaps %xmm15,240(%rcx) + + xorq %rax,%rax + ret +END(jl_setjmp) + diff --git a/src/support/dtypes.h b/src/support/dtypes.h index 372f62aff9f73..ae139b596b299 100644 --- a/src/support/dtypes.h +++ b/src/support/dtypes.h @@ -37,7 +37,7 @@ #define BYTE_ORDER __BYTE_ORDER #endif -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(__FreeBSD__) #include #define __LITTLE_ENDIAN LITTLE_ENDIAN #define __BIG_ENDIAN BIG_ENDIAN @@ -78,68 +78,40 @@ #define LLT_REALLOC(p,n) realloc((p),(n)) #define LLT_FREE(x) free(x) -typedef int bool_t; - #if defined(__INTEL_COMPILER) && defined(WIN32) # define STATIC_INLINE static # define INLINE -# ifdef __LP64__ -typedef unsigned long size_t; -# else -typedef unsigned int size_t; -# endif #else # define STATIC_INLINE static inline # define INLINE inline #endif +#include +#include +typedef int bool_t; typedef unsigned char byte_t; /* 1 byte */ -#if defined(WIN32) -typedef short int16_t; -typedef int int32_t; -typedef long long int64_t; -typedef unsigned char u_int8_t; -typedef unsigned short u_int16_t; -typedef unsigned int u_int32_t; -#ifdef __LP64__ -typedef unsigned long u_int64_t; -#else -typedef unsigned long long u_int64_t; -#endif -#ifdef __INTEL_COMPILER -typedef signed char int8_t; -typedef short int16_t; -typedef int int32_t; -#endif -#else -#include -#endif -#ifdef __LP64__ +#ifdef _P64 #define TOP_BIT 0x8000000000000000 #define NBITS 64 -typedef unsigned long uint_t; // preferred int type on platform -typedef long int_t; -typedef int64_t offset_t; -typedef u_int64_t index_t; -typedef int64_t ptrint_t; // pointer-size int -typedef u_int64_t u_ptrint_t; +typedef uint64_t uint_t; // preferred int type on platform +typedef int64_t int_t; #else #define TOP_BIT 0x80000000 #define NBITS 32 -typedef unsigned long uint_t; -typedef long int_t; -typedef int32_t offset_t; -typedef u_int32_t index_t; -typedef int32_t ptrint_t; -typedef u_int32_t u_ptrint_t; +typedef uint32_t uint_t; +typedef int32_t int_t; #endif +typedef ptrdiff_t ptrint_t; // pointer-size int +typedef size_t uptrint_t; +typedef ptrdiff_t offset_t; +typedef size_t index_t; -typedef u_int8_t uint8_t; -typedef u_int16_t uint16_t; -typedef u_int32_t uint32_t; -typedef u_int64_t uint64_t; -typedef u_ptrint_t uptrint_t; +typedef uint8_t u_int8_t; +typedef uint16_t u_int16_t; +typedef uint32_t u_int32_t; +typedef uint64_t u_int64_t; +typedef uptrint_t u_ptrint_t; #define LLT_ALIGN(x, sz) (((x) + (sz-1)) & (-sz)) @@ -191,12 +163,12 @@ typedef enum { T_INT8, T_UINT8, T_INT16, T_UINT16, T_INT32, T_UINT32, #define N_NUMTYPES ((int)T_DOUBLE+1) -#ifdef __LP64__ -# define T_LONG T_INT64 -# define T_ULONG T_UINT64 +#ifdef _P64 +# define T_PTRDIFF T_INT64 +# define T_SIZE T_UINT64 #else -# define T_LONG T_INT32 -# define T_ULONG T_UINT32 +# define T_PTRDIFF T_INT32 +# define T_SIZE T_UINT32 #endif #endif diff --git a/src/support/hashing.c b/src/support/hashing.c index d9b8cad8085c5..2b0898d9c89d8 100644 --- a/src/support/hashing.c +++ b/src/support/hashing.c @@ -64,7 +64,7 @@ uint64_t memhash(const char* buf, size_t n) uint64_t out[2]; // TODO: expose 128-bit hash -#ifdef __LP64__ +#ifdef _P64 MurmurHash3_x64_128(buf, n, _MHASH_SEED_, out); #else MurmurHash3_x86_128(buf, n, _MHASH_SEED_, out); @@ -77,7 +77,7 @@ uint64_t memhash_seed(const char* buf, size_t n, uint32_t seed) uint64_t out[2]; // TODO: expose 128-bit hash -#ifdef __LP64__ +#ifdef _P64 MurmurHash3_x64_128(buf, n, seed, out); #else MurmurHash3_x86_128(buf, n, seed, out); diff --git a/src/support/hashing.h b/src/support/hashing.h index 0c28abfa7e60e..99fd1f038b3f9 100644 --- a/src/support/hashing.h +++ b/src/support/hashing.h @@ -5,7 +5,7 @@ uint_t nextipow2(uint_t i); DLLEXPORT u_int32_t int32hash(u_int32_t a); DLLEXPORT u_int64_t int64hash(u_int64_t key); DLLEXPORT u_int32_t int64to32hash(u_int64_t key); -#ifdef __LP64__ +#ifdef _P64 #define inthash int64hash #else #define inthash int32hash diff --git a/src/support/ios.c b/src/support/ios.c index 55879a3ece88e..6173d8b9140fa 100644 --- a/src/support/ios.c +++ b/src/support/ios.c @@ -63,8 +63,7 @@ static int _fd_available(long fd) static int _enonfatal(int err) { - return (err == EAGAIN || err == EINPROGRESS || err == EINTR || - err == EWOULDBLOCK); + return (err == EAGAIN ||/* err == EINPROGRESS ||*/ err == EINTR /*|| err == EWOULDBLOCK*/); //jwn } #define SLEEP_TIME 5//ms @@ -471,6 +470,7 @@ off_t ios_skip(ios_t *s, off_t offs) off_t fdpos = lseek(s->fd, offs, SEEK_CUR); if (fdpos == (off_t)-1) return fdpos; + s->fpos = fdpos; s->bpos = s->size = 0; s->_eof = 0; } @@ -769,7 +769,6 @@ static void _ios_init(ios_t *s) s->_eof = 0; s->rereadable = 0; s->readonly = 0; - s->mutex_initialized = 0; } /* stream object initializers. we do no allocation. */ @@ -783,7 +782,11 @@ ios_t *ios_file(ios_t *s, char *fname, int rd, int wr, int create, int trunc) int flags = wr ? (rd ? O_RDWR : O_WRONLY) : O_RDONLY; if (create) flags |= O_CREAT; if (trunc) flags |= O_TRUNC; - fd = open(fname, flags, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH/*644*/); + fd = open(fname, flags, S_IRUSR | S_IWUSR /* 600 */ +#ifndef __WIN32__ + | S_IRGRP | S_IROTH /* 644 */ +#endif + ); if (fd == -1) goto open_file_err; s = ios_fd(s, fd, 1, 1); diff --git a/src/support/ios.h b/src/support/ios.h index 89a58b22872c4..f67cc609e7f54 100644 --- a/src/support/ios.h +++ b/src/support/ios.h @@ -2,8 +2,7 @@ #define IOS_H #include -#include -#include "../../deps/libuv/include/uv.h" +#include "../../usr/include/uv.h" // this flag controls when data actually moves out to the underlying I/O // channel. memory streams are a special case of this where the data @@ -11,7 +10,6 @@ //make it compatible with UV Handles typedef enum { bm_none=UV_HANDLE_TYPE_MAX+1, bm_line, bm_block, bm_mem } bufmode_t; - typedef enum { bst_none, bst_rd, bst_wr } bufstate_t; #define IOS_INLSIZE 54 @@ -58,12 +56,7 @@ typedef struct { // request durable writes (fsync) // unsigned char durable:1; - unsigned char mutex_initialized:1; - int64_t userdata; - pthread_mutex_t mutex; - - // todo: mutex char local[IOS_INLSIZE]; } ios_t; @@ -136,7 +129,7 @@ int ios_prevutf8(ios_t *s); DLLEXPORT int ios_putc(int c, ios_t *s); //wint_t ios_putwc(ios_t *s, wchar_t wc); DLLEXPORT int ios_getc(ios_t *s); -int ios_peekc(ios_t *s); +DLLEXPORT int ios_peekc(ios_t *s); //wint_t ios_getwc(ios_t *s); int ios_ungetc(int c, ios_t *s); //wint_t ios_ungetwc(ios_t *s, wint_t wc); diff --git a/src/support/libsupport.h b/src/support/libsupport.h index 83e325c1cf272..0c70d9a2bf985 100644 --- a/src/support/libsupport.h +++ b/src/support/libsupport.h @@ -1,13 +1,32 @@ #ifndef LIBSUPPORT_H #define LIBSUPPORT_H +// Check windows +#if _WIN32 || _WIN64 +#if _WIN64 +#define _P64 +#else +#define _P32 +#endif +#endif + +// Check GCC +#if __GNUC__ +#if __x86_64__ || __ppc64__ +#define _P64 +#else +#define _P32 +#endif +#else +#error pointer size not known for your platform / compiler +#endif + #include #include #include "dtypes.h" #include "utils.h" #include "utf8.h" #include "ios.h" -#include "socket.h" #include "timefuncs.h" #include "hashing.h" #include "ptrhash.h" diff --git a/src/support/socket.c b/src/support/socket.c deleted file mode 100644 index ba18b7e7cdef3..0000000000000 --- a/src/support/socket.c +++ /dev/null @@ -1,200 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include "dtypes.h" - -#if defined(__APPLE__) -#include -#include -#include -#endif - -#include "socket.h" - - -int mysocket(int domain, int type, int protocol) -{ - int val; - int s = socket(domain, type, protocol); - if (s < 0) - return s; - val = 131072; - setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char*)&val, sizeof(int)); - val = 131072; - setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char*)&val, sizeof(int)); - return s; -} - -#ifdef WIN32 -void bzero(void *s, size_t n) -{ - memset(s, 0, n); -} -#endif - -/* returns a socket on which to accept() connections */ -int open_tcp_port(short portno) -{ - int sockfd; - //int val; - struct sockaddr_in serv_addr; - - sockfd = mysocket(PF_INET, SOCK_STREAM, IPPROTO_TCP); - if (sockfd < 0) - return -1; - //val = 1; - //setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)); - bzero(&serv_addr, sizeof(serv_addr)); - serv_addr.sin_family = AF_INET; - serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); - serv_addr.sin_port = htons(portno); - if (bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) { - return -1; - } - - listen(sockfd, 4); - return sockfd; -} - -/* returns a socket on which to accept() connections, finding some - available port (portno is value-return) */ -int open_any_tcp_port(short *portno) - -{ - int sockfd; - //int val; - struct sockaddr_in serv_addr; - - sockfd = mysocket(PF_INET, SOCK_STREAM, IPPROTO_TCP); - if (sockfd < 0) - return -1; - //val = 1; - //setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)); - bzero(&serv_addr, sizeof(serv_addr)); - serv_addr.sin_family = AF_INET; - serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); - serv_addr.sin_port = htons(*portno); - while (bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) { - (*portno)++; - serv_addr.sin_port = htons(*portno); - } - - listen(sockfd, 4); - return sockfd; -} - -/* returns a socket on which to accept() connections, finding some - available port (portno is value-return) */ -int open_any_udp_port(short *portno) -{ - int sockfd; - struct sockaddr_in serv_addr; - - sockfd = mysocket(PF_INET, SOCK_DGRAM, 0); - if (sockfd < 0) - return -1; - bzero(&serv_addr, sizeof(serv_addr)); - serv_addr.sin_family = AF_INET; - serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); - serv_addr.sin_port = htons(*portno); - while (bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) { - (*portno)++; - serv_addr.sin_port = htons(*portno); - } - - return sockfd; -} - -#ifndef WIN32 -void closesocket(int fd) -{ - close(fd); -} -#endif - -/* returns a socket to use to send data to the given address */ -int connect_to_host(char *hostname, short portno) -{ - struct hostent *host_info; - int sockfd, yes=1; - struct sockaddr_in host_addr; - - host_info = gethostbyname(hostname); - if (host_info == NULL) { - return -1; - } - - sockfd = mysocket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (sockfd < 0) { - return -1; - } - (void)setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)); - memset((char*)&host_addr, 0, sizeof(host_addr)); - host_addr.sin_family = host_info->h_addrtype; - memcpy((char*)&host_addr.sin_addr, host_info->h_addr, - host_info->h_length); - - host_addr.sin_port = htons(portno); - - if (connect(sockfd, (struct sockaddr*)&host_addr, - sizeof(struct sockaddr_in)) != 0) { - closesocket(sockfd); - return -1; - } - - return sockfd; -} - -int connect_to_addr(struct sockaddr_in *host_addr) -{ - int sockfd, yes=1; - - sockfd = mysocket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (sockfd < 0) { - return -1; - } - (void)setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)); - - if (connect(sockfd, (struct sockaddr*)host_addr, - sizeof(struct sockaddr_in)) != 0) { - closesocket(sockfd); - return -1; - } - - return sockfd; -} - -void getlocalip(char *buf, size_t len) -{ - struct ifaddrs * ifAddrStruct=NULL; - struct ifaddrs * ifa=NULL; - void * tmpAddrPtr=NULL; - buf[0] = '\0'; - - getifaddrs(&ifAddrStruct); - - for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) { - if (ifa->ifa_addr && ifa->ifa_addr->sa_family==AF_INET) { // check it is IP4 - // is a valid IP4 Address - tmpAddrPtr=&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr; - inet_ntop(AF_INET, tmpAddrPtr, buf, len); - if (strcmp(buf,"127.0.0.1")) - break; - //printf("%s IP Address %s\n", ifa->ifa_name, addressBuffer); - } - /* - else if (ifa->ifa_addr && ifa->ifa_addr->sa_family==AF_INET6) { // check it is IP6 - // is a valid IP6 Address - tmpAddrPtr=&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr; - char addressBuffer[INET6_ADDRSTRLEN]; - inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN); - printf("%s IP Address %s\n", ifa->ifa_name, addressBuffer); - } - */ - } - if (ifAddrStruct!=NULL) freeifaddrs(ifAddrStruct); -} diff --git a/src/support/socket.h b/src/support/socket.h deleted file mode 100644 index a92b51b4733a9..0000000000000 --- a/src/support/socket.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef LLTSOCKET_H -#define LLTSOCKET_H - -#ifdef WIN32 -#include -#else -#include -#include -#include -#include -#include -#include -#include -#include -#endif - -int open_tcp_port(short portno); -DLLEXPORT int open_any_tcp_port(short *portno); -DLLEXPORT int open_any_udp_port(short *portno); -DLLEXPORT int connect_to_host(char *hostname, short portno); -DLLEXPORT void getlocalip(char *buf, size_t len); -int connect_to_addr(struct sockaddr_in *host_addr); - -#ifdef WIN32 -void bzero(void *s, size_t n); -#endif -#ifndef WIN32 -void closesocket(int fd); -#endif - -#endif diff --git a/src/support/timefuncs.c b/src/support/timefuncs.c index ed1a5d86e4521..44cdf08d04238 100644 --- a/src/support/timefuncs.c +++ b/src/support/timefuncs.c @@ -10,7 +10,7 @@ #include "dtypes.h" -#ifdef WIN32 +#ifdef __WIN32__ #include #include #include @@ -22,7 +22,7 @@ #include "timefuncs.h" -#ifdef WIN32 +#ifdef __WIN32__ double floattime(void) { struct timeb tstruct; diff --git a/src/support/utf8.c b/src/support/utf8.c index 09b63ba6e092c..9f4dee5c0bfbd 100644 --- a/src/support/utf8.c +++ b/src/support/utf8.c @@ -75,8 +75,11 @@ size_t u8_codingsize(uint32_t *wcstr, size_t n) { size_t i, c=0; - for(i=0; i < n; i++) - c += u8_charlen(wcstr[i]); + for(i=0; i < n; i++) { + size_t cl = u8_charlen(wcstr[i]); + if (cl == 0) cl = 3; // invalid: encoded as replacement char + c += cl; + } return c; } @@ -165,6 +168,14 @@ size_t u8_toutf8(char *dest, size_t sz, const uint32_t *src, size_t srcsz) *dest++ = ((ch>>6) & 0x3F) | 0x80; *dest++ = (ch & 0x3F) | 0x80; } + else { + if (dest >= dest_end-2) + break; + // invalid: use replacement char \ufffd + *dest++ = 0xef; + *dest++ = 0xbf; + *dest++ = 0xbd; + } i++; } return (dest-dest0); @@ -194,7 +205,10 @@ size_t u8_wc_toutf8(char *dest, uint32_t ch) dest[3] = (ch & 0x3F) | 0x80; return 4; } - return 0; + dest[0] = 0xef; + dest[1] = 0xbf; + dest[2] = 0xbd; + return 3; } /* charnum => byte offset */ @@ -243,7 +257,9 @@ size_t u8_strlen(const char *s) return count; } -extern int wcwidth(wchar_t c); +#if defined(__WIN32__) || defined(__linux__) +extern int wcwidth(uint32_t ch); +#endif size_t u8_strwidth(const char *s) { diff --git a/src/support/utils.h b/src/support/utils.h index 857789e46358e..d0ac2d3805eb7 100644 --- a/src/support/utils.h +++ b/src/support/utils.h @@ -21,12 +21,12 @@ int64_t conv_to_int64(void *data, numerictype_t tag); uint64_t conv_to_uint64(void *data, numerictype_t tag); int32_t conv_to_int32(void *data, numerictype_t tag); uint32_t conv_to_uint32(void *data, numerictype_t tag); -#ifdef __LP64__ -#define conv_to_long conv_to_int64 -#define conv_to_ulong conv_to_uint64 +#ifdef _P64 +#define conv_to_ptrdiff conv_to_int64 +#define conv_to_size conv_to_uint64 #else -#define conv_to_long conv_to_int32 -#define conv_to_ulong conv_to_uint32 +#define conv_to_ptrdiff conv_to_int32 +#define conv_to_size conv_to_uint32 #endif int cmp_same_lt(void *a, void *b, numerictype_t tag); int cmp_same_eq(void *a, void *b, numerictype_t tag); diff --git a/src/support/wcwidth.c b/src/support/wcwidth.c index 814e357f35223..71a5a6cf77846 100644 --- a/src/support/wcwidth.c +++ b/src/support/wcwidth.c @@ -1,3 +1,4 @@ +#include "dtypes.h" //for DLLEXPORT /* * This is an implementation of wcwidth() and wcswidth() (defined in * IEEE Std 1002.1-2001) for Unicode. @@ -124,7 +125,7 @@ static int bisearch(uint32_t ucs, const struct interval *table, int max) { #include #include -int wcwidth(uint32_t ucs) +DLLEXPORT int wcwidth(uint32_t ucs) { /* sorted list of non-overlapping intervals of non-spacing characters */ /* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */ diff --git a/src/sys.c b/src/sys.c index f7fa16cf89de7..6d74c695822de 100644 --- a/src/sys.c +++ b/src/sys.c @@ -4,10 +4,10 @@ */ #include "julia.h" #include "uv.h" +#include #include #include #include -#include #ifndef __WIN32__ #include #include @@ -17,44 +17,15 @@ #include #include #include -#include + +#define __STDC_CONSTANT_MACROS +#define __STDC_LIMIT_MACROS +#include #ifdef __SSE__ #include #endif -// --- io and select --- - -DLLEXPORT int jl_sizeof_fd_set(void) { return sizeof(fd_set); } - -DLLEXPORT int jl_sizeof_timeval(void) { return sizeof(struct timeval); } - -DLLEXPORT void jl_set_timeval(struct timeval *tv, double tout) -{ - tv->tv_sec = (int)tout; - tv->tv_usec = (int)((tout-(int)tout)*1.0e6); -} - -DLLEXPORT void jl_fd_clr(fd_set *set, int fd) -{ - FD_CLR(fd, set); -} - -DLLEXPORT int jl_fd_isset(fd_set *set, int fd) -{ - return FD_ISSET(fd, set); -} - -DLLEXPORT void jl_fd_set(fd_set *set, int fd) -{ - FD_SET(fd, set); -} - -DLLEXPORT void jl_fd_zero(fd_set *set) -{ - FD_ZERO(set); -} - DLLEXPORT uint32_t jl_getutf8(ios_t *s) { uint32_t wc=0; @@ -69,6 +40,8 @@ DLLEXPORT size_t jl_ios_size(ios_t *s) DLLEXPORT int jl_sizeof_off_t(void) { return sizeof(off_t); } +DLLEXPORT int jl_sizeof_ios_t(void) { return sizeof(ios_t); } + DLLEXPORT long jl_ios_fd(ios_t *s) { return s->fd; @@ -90,127 +63,121 @@ DLLEXPORT int jl_ios_eof(ios_t *s) return 0; } -// --- io constructors --- - -DLLEXPORT int jl_sizeof_ios_t(void) { return sizeof(ios_t); } - -// hack to expose ios_stdout to julia. we could create a new iostream pointing -// to stdout, but then there would be two buffers for one descriptor, and -// ios_stdout is used before julia IOStream is available, creating a potential -// mess. -DLLEXPORT jl_value_t *jl_stdout_stream(void) -{ - jl_array_t *a = jl_alloc_array_1d(jl_array_uint8_type, sizeof(ios_t)); - a->data = (void*)ios_stdout; - jl_array_data_owner(a) = (jl_value_t*)a; - return (jl_value_t*)a; -} - // --- dir/file stuff --- DLLEXPORT int jl_sizeof_uv_fs_t(void) { return sizeof(uv_fs_t); } -DLLEXPORT void jl_uv_fs_req_cleanup(uv_fs_t* req) { - uv_fs_req_cleanup(req); +DLLEXPORT void jl_uv_fs_req_cleanup(uv_fs_t* req) +{ + uv_fs_req_cleanup(req); } DLLEXPORT int jl_readdir(const char* path, uv_fs_t* readdir_req) { - // Note that the flags field is mostly ignored by libuv - return uv_fs_readdir(uv_default_loop(), readdir_req, path, 0 /*flags*/, NULL); + // Note that the flags field is mostly ignored by libuv + return uv_fs_readdir(uv_default_loop(), readdir_req, path, 0 /*flags*/, NULL); } DLLEXPORT char* jl_uv_fs_t_ptr(uv_fs_t* req) {return req->ptr; } DLLEXPORT char* jl_uv_fs_t_ptr_offset(uv_fs_t* req, int offset) {return req->ptr + offset; } +DLLEXPORT int jl_uv_fs_result(uv_fs_t *f) { return f->result; } // --- stat --- -DLLEXPORT int jl_sizeof_stat(void) { return sizeof(struct stat); } +DLLEXPORT int jl_sizeof_stat(void) { return sizeof(uv_statbuf_t); } DLLEXPORT int32_t jl_stat(const char* path, char* statbuf) { - uv_fs_t req; - int ret; + uv_fs_t req; + int ret; - // Ideally one would use the statbuf for the storage in req, but - // it's not clear that this is possible using libuv - ret = uv_fs_stat(uv_default_loop(), &req, path, NULL); - if (ret == 0) - memcpy(statbuf, req.ptr, sizeof(struct stat)); - uv_fs_req_cleanup(&req); - return ret; + // Ideally one would use the statbuf for the storage in req, but + // it's not clear that this is possible using libuv + ret = uv_fs_stat(uv_default_loop(), &req, path, NULL); + if (ret == 0) + memcpy(statbuf, req.ptr, sizeof(uv_statbuf_t)); + uv_fs_req_cleanup(&req); + return ret; } DLLEXPORT int32_t jl_lstat(const char* path, char* statbuf) { - uv_fs_t req; - int ret; + uv_fs_t req; + int ret; - ret = uv_fs_lstat(uv_default_loop(), &req, path, NULL); - if (ret == 0) - memcpy(statbuf, req.ptr, sizeof(struct stat)); - uv_fs_req_cleanup(&req); - return ret; + ret = uv_fs_lstat(uv_default_loop(), &req, path, NULL); + if (ret == 0) + memcpy(statbuf, req.ptr, sizeof(uv_statbuf_t)); + uv_fs_req_cleanup(&req); + return ret; } DLLEXPORT int32_t jl_fstat(int fd, char *statbuf) { - uv_fs_t req; - int ret; + uv_fs_t req; + int ret; - ret = uv_fs_fstat(uv_default_loop(), &req, fd, NULL); - if (ret == 0) - memcpy(statbuf, req.ptr, sizeof(struct stat)); - uv_fs_req_cleanup(&req); - return ret; + ret = uv_fs_fstat(uv_default_loop(), &req, fd, NULL); + if (ret == 0) + memcpy(statbuf, req.ptr, sizeof(uv_statbuf_t)); + uv_fs_req_cleanup(&req); + return ret; } DLLEXPORT unsigned int jl_stat_dev(char *statbuf) { - return ((struct stat*) statbuf)->st_dev; + return ((uv_statbuf_t*) statbuf)->st_dev; } DLLEXPORT unsigned int jl_stat_ino(char *statbuf) { - return ((struct stat*) statbuf)->st_ino; + return ((uv_statbuf_t*) statbuf)->st_ino; } DLLEXPORT unsigned int jl_stat_mode(char *statbuf) { - return ((struct stat*) statbuf)->st_mode; + return ((uv_statbuf_t*) statbuf)->st_mode; } DLLEXPORT unsigned int jl_stat_nlink(char *statbuf) { - return ((struct stat*) statbuf)->st_nlink; + return ((uv_statbuf_t*) statbuf)->st_nlink; } DLLEXPORT unsigned int jl_stat_uid(char *statbuf) { - return ((struct stat*) statbuf)->st_uid; + return ((uv_statbuf_t*) statbuf)->st_uid; } DLLEXPORT unsigned int jl_stat_gid(char *statbuf) { - return ((struct stat*) statbuf)->st_gid; + return ((uv_statbuf_t*) statbuf)->st_gid; } DLLEXPORT unsigned int jl_stat_rdev(char *statbuf) { - return ((struct stat*) statbuf)->st_rdev; + return ((uv_statbuf_t*) statbuf)->st_rdev; } DLLEXPORT off_t jl_stat_size(char *statbuf) { - return ((struct stat*) statbuf)->st_size; + return ((uv_statbuf_t*) statbuf)->st_size; } DLLEXPORT unsigned int jl_stat_blksize(char *statbuf) { - return ((struct stat*) statbuf)->st_blksize; +#if defined(__WIN32__) + return 0; +#else + return ((uv_statbuf_t*) statbuf)->st_blksize; +#endif } DLLEXPORT unsigned int jl_stat_blocks(char *statbuf) { - return ((struct stat*) statbuf)->st_blocks; +#if defined(__WIN32__) + return 0; +#else + return ((uv_statbuf_t*) statbuf)->st_blocks; +#endif } #if defined(__APPLE__) || defined(__FreeBSD__) @@ -227,24 +194,36 @@ DLLEXPORT unsigned int jl_stat_blocks(char *statbuf) // atime is stupid, let's not support it DLLEXPORT double jl_stat_atime(char *statbuf) { - struct stat *s; - s = (struct stat*) statbuf; + uv_statbuf_t *s; + s = (uv_statbuf_t*) statbuf; +#if defined(__WIN32__) + return (double)s->st_atime; +#else return (double)s->st_ATIM.tv_sec + (double)s->st_ATIM.tv_nsec * 1e-9; +#endif } */ DLLEXPORT double jl_stat_mtime(char *statbuf) { - struct stat *s; - s = (struct stat*) statbuf; + uv_statbuf_t *s; + s = (uv_statbuf_t*) statbuf; +#if defined(__WIN32__) + return (double)s->st_mtime; +#else return (double)s->st_MTIM.tv_sec + (double)s->st_MTIM.tv_nsec * 1e-9; +#endif } DLLEXPORT double jl_stat_ctime(char *statbuf) { - struct stat *s; - s = (struct stat*) statbuf; + uv_statbuf_t *s; + s = (uv_statbuf_t*) statbuf; +#if defined(__WIN32__) + return (double)s->st_ctime; +#else return (double)s->st_CTIM.tv_sec + (double)s->st_CTIM.tv_nsec * 1e-9; +#endif } // --- buffer manipulation --- @@ -305,19 +284,14 @@ jl_value_t *jl_readuntil(ios_t *s, uint8_t delim) a = jl_takebuf_array(&dest); } else { +#ifdef STORE_ARRAY_LEN a->length = n; +#endif a->nrows = n; ((char*)a->data)[n] = '\0'; } } - JL_GC_PUSH(&a); - jl_struct_type_t* string_type = u8_isvalid(a->data, a->length) == 1 ? // ASCII - jl_ascii_string_type : jl_utf8_string_type; - jl_value_t *str = alloc_2w(); - str->type = (jl_type_t*)string_type; - jl_set_nth_field(str, 0, (jl_value_t*)a); - JL_GC_POP(); - return str; + return (jl_value_t*)a; } void jl_free2(void *p, void *hint) @@ -355,14 +329,15 @@ DLLEXPORT int jl_cpu_cores(void) return sysconf(_SC_NPROCESSORS_ONLN); #elif defined(__WIN32__) //Try to get WIN7 API method - GAPC gapc = (GAPC) jl_dlsym( + GAPC gapc = (GAPC) jl_dlsym_e( jl_kernel32_handle, "GetActiveProcessorCount" ); if (gapc) { return gapc(ALL_PROCESSOR_GROUPS); - } else { //fall back on GetSystemInfo + } + else { //fall back on GetSystemInfo SYSTEM_INFO info; GetSystemInfo(&info); return info.dwNumberOfProcessors; @@ -395,10 +370,15 @@ jl_value_t *jl_environ(int i) char *env = environ[i]; return env ? jl_pchar_to_string(env, strlen(env)) : jl_nothing; } - +#ifdef __WIN32__ +jl_value_t *jl_env_done(char *pos) +{ + return (*pos==0)?jl_true:jl_false; +} +#endif // -- child process status -- -#if defined _MSC_VER || defined __MINGW32__ +#if defined _MSC_VER || defined __WIN32__ /* Native Woe32 API. */ #include @@ -423,177 +403,97 @@ int jl_process_stop_signal(int status) { return WSTOPSIG(status); } // -- access to std filehandles -- -int jl_stdin(void) { return STDIN_FILENO; } -int jl_stdout(void) { return STDOUT_FILENO; } -int jl_stderr(void) { return STDERR_FILENO; } - -// -- I/O thread -- - -static pthread_t io_thread; -static pthread_mutex_t q_mut; -static pthread_mutex_t wake_mut; -static pthread_cond_t wake_cond; - -typedef struct _sendreq_t { - int fd; - ios_t *buf; - int now; - struct _sendreq_t *next; -} sendreq_t; +JL_STREAM *JL_STDIN=0; +JL_STREAM *JL_STDOUT=0; +JL_STREAM *JL_STDERR=0; -static sendreq_t *ioq = NULL; -static sendreq_t *ioq_freelist = NULL; +JL_STREAM *jl_stdin_stream(void) { return (JL_STREAM*) JL_STDIN; } +JL_STREAM *jl_stdout_stream(void) { return (JL_STREAM*) JL_STDOUT; } +JL_STREAM *jl_stderr_stream(void) { return (JL_STREAM*) JL_STDERR; } -int _os_write_all(long fd, void *buf, size_t n, size_t *nwritten); +// -- set/clear the FZ/DAZ flags on x86 & x86-64 -- -static void *run_io_thr(void *arg) -{ - sigset_t set; - sigemptyset(&set); - sigaddset(&set, SIGFPE); - sigaddset(&set, SIGINT); - sigaddset(&set, SIGSEGV); - pthread_sigmask(SIG_BLOCK, &set, NULL); - - while (1) { - while (ioq == NULL) { - pthread_mutex_lock(&wake_mut); - pthread_cond_wait(&wake_cond, &wake_mut); - pthread_mutex_unlock(&wake_mut); - } - assert(ioq != NULL); - - pthread_mutex_lock(&q_mut); - sendreq_t *r = ioq; - ioq = ioq->next; - pthread_mutex_unlock(&q_mut); - - if (!r->now) { - int64_t now = (int64_t)(clock_now()*1e6); - int64_t waittime = r->buf->userdata+200-now; // microseconds - if (waittime > 0) { - struct timespec wt; - wt.tv_sec = 0; - wt.tv_nsec = waittime * 1000; - nanosleep(&wt, NULL); - } - } - - pthread_mutex_lock(&r->buf->mutex); - size_t sz; - size_t n = r->buf->size; - char *buf = ios_takebuf(r->buf, &sz); - pthread_mutex_unlock(&r->buf->mutex); +#ifdef __SSE__ - size_t nw; - _os_write_all(r->fd, buf, n, &nw); - free(buf); +#ifdef _WIN32 +#define cpuid __cpuid +#else - pthread_mutex_lock(&q_mut); - r->next = ioq_freelist; - ioq_freelist = r; - pthread_mutex_unlock(&q_mut); - } - return NULL; +void cpuid(int32_t CPUInfo[4], int32_t InfoType) +{ + __asm__ __volatile__ ( + #if defined(__i386__) && defined(__PIC__) + "xchg %%ebx, %%esi;" + "cpuid;" + "xchg %%esi, %%ebx;": + "=S" (CPUInfo[1]) , + #else + "cpuid": + "=b" (CPUInfo[1]), + #endif + "=a" (CPUInfo[0]), + "=c" (CPUInfo[2]), + "=d" (CPUInfo[3]) : + "a" (InfoType) + ); } -DLLEXPORT void jl_buf_mutex_lock(ios_t *s) -{ - if (!s->mutex_initialized) { - pthread_mutex_init(&s->mutex, NULL); - s->mutex_initialized = 1; - } - pthread_mutex_lock(&s->mutex); -} +#endif -DLLEXPORT void jl_buf_mutex_unlock(ios_t *s) +DLLEXPORT uint8_t jl_zero_denormals(uint8_t isZero) { - pthread_mutex_unlock(&s->mutex); -} + uint32_t flags = 0x00000000; + int32_t info[4]; -DLLEXPORT void jl_enq_send_req(ios_t *dest, ios_t *buf, int now) -{ - pthread_mutex_lock(&q_mut); - sendreq_t *req = ioq; - sendreq_t **pr = &ioq; - while (req != NULL) { - if (req->fd == dest->fd) { - if (now && !req->now) { - // increase priority - *pr = req->next; - req->next = ioq; - ioq = req; - req->now = 1; - } - pthread_mutex_unlock(&q_mut); - return; + cpuid(info, 0); + if (info[0] >= 1) { + cpuid(info, 0x00000001); + if ((info[3] & ((int)1 << 26)) != 0) { + // SSE2 supports both FZ and DAZ + flags = 0x00008040; + } + else if ((info[3] & ((int)1 << 25)) != 0) { + // SSE supports only the FZ flag + flags = 0x00008000; } - pr = &req->next; - req = req->next; } - if (ioq_freelist != NULL) { - req = ioq_freelist; - ioq_freelist = ioq_freelist->next; - } - else { - req = (sendreq_t*)malloc(sizeof(sendreq_t)); - } - req->fd = dest->fd; - req->buf = buf; - req->now = now; - req->next = NULL; - buf->userdata = (int64_t)(clock_now()*1e6); - if (ioq == NULL) { - ioq = req; - } - else { - if (now) { - req->next = ioq; - ioq = req; + if (flags) { + if (isZero) { + _mm_setcsr(_mm_getcsr() | flags); } else { - sendreq_t *r = ioq; - while (r->next != NULL) { - r = r->next; - } - r->next = req; + _mm_setcsr(_mm_getcsr() & ~flags); } + return 1; } - pthread_mutex_unlock(&q_mut); - pthread_cond_signal(&wake_cond); + return 0; } -DLLEXPORT void jl_start_io_thread(void) -{ - pthread_mutex_init(&q_mut, NULL); - pthread_mutex_init(&wake_mut, NULL); - pthread_cond_init(&wake_cond, NULL); - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setstacksize(&attr, 262144); - pthread_create(&io_thread, &attr, run_io_thr, NULL); -} +#else DLLEXPORT uint8_t jl_zero_denormals(uint8_t isZero) { -#ifdef __SSE2__ - // SSE2 supports both FZ and DAZ - uint32_t flags = 0x8040; -#elif __SSE__ - // SSE supports only the FZ flag - uint32_t flags = 0x8000; -#endif - -#ifdef __SSE__ - if (isZero) { - _mm_setcsr(_mm_getcsr() | flags); - } - else { - _mm_setcsr(_mm_getcsr() & ~flags); - } - return 1; -#else return 0; +} + #endif + +// -- processor native alignment information -- + +DLLEXPORT void jl_native_alignment(uint_t* int8align, uint_t* int16align, uint_t* int32align, uint_t* int64align, uint_t* float32align, uint_t* float64align) +{ + LLVMTargetDataRef tgtdata = LLVMCreateTargetData(""); + *int8align = LLVMPreferredAlignmentOfType(tgtdata, LLVMInt8Type()); + *int16align = LLVMPreferredAlignmentOfType(tgtdata, LLVMInt16Type()); + *int32align = LLVMPreferredAlignmentOfType(tgtdata, LLVMInt32Type()); + *int64align = LLVMPreferredAlignmentOfType(tgtdata, LLVMInt64Type()); + *float32align = LLVMPreferredAlignmentOfType(tgtdata, LLVMFloatType()); + *float64align = LLVMPreferredAlignmentOfType(tgtdata, LLVMDoubleType()); + LLVMDisposeTargetData(tgtdata); +} + +DLLEXPORT jl_value_t *jl_is_char_signed() +{ + return ((char)255) < 0 ? jl_true : jl_false; } diff --git a/src/table.c b/src/table.c index a9503e7d4ea80..8522500ccbcb3 100644 --- a/src/table.c +++ b/src/table.c @@ -1,4 +1,4 @@ -#define hash_size(h) ((h)->length/2) +#define hash_size(h) (jl_array_len(h)/2) // compute empirical max-probe for a given size #define max_probe(size) ((size)<=(HT_N_INLINE*2) ? (HT_N_INLINE/2) : (size)>>3) @@ -10,7 +10,7 @@ static void **jl_table_lookup_bp(jl_array_t **pa, void *key); void jl_idtable_rehash(jl_array_t **pa, size_t newsz) { - size_t sz = (*pa)->length; + size_t sz = jl_array_len(*pa); size_t i; void **ol = (void**)(*pa)->data; *pa = jl_alloc_cell_1d(newsz); @@ -56,7 +56,7 @@ static void **jl_table_lookup_bp(jl_array_t **pa, void *key) /* quadruple size, rehash, retry the insert */ /* it's important to grow the table really fast; otherwise we waste */ /* lots of time rehashing all the keys over and over. */ - sz = a->length; + sz = jl_array_len(a); if (sz >= (1<<19) || (sz <= (1<<8))) newsz = sz<<1; else if (sz <= HT_N_INLINE) @@ -121,23 +121,24 @@ jl_value_t *jl_eqtable_get(jl_array_t *h, void *key, jl_value_t *deflt) } DLLEXPORT -int jl_eqtable_del(jl_array_t *h, void *key) +jl_value_t *jl_eqtable_del(jl_array_t *h, void *key, jl_value_t *deflt) { void **bp = jl_table_peek_bp(h, key); - if (bp != NULL) { - *bp = NULL; - return 1; - } - return 0; + if (bp == NULL || *bp == NULL) + return deflt; + jl_value_t *val = *bp; + *bp = NULL; + return val; } DLLEXPORT jl_value_t *jl_eqtable_next(jl_array_t *t, uint32_t i) { if (i&1) i++; - while (i < t->length && ((void**)t->data)[i+1] == NULL) + size_t alen = jl_array_dim0(t); + while (i < alen && ((void**)t->data)[i+1] == NULL) i+=2; - if (i >= t->length) return (jl_value_t*)jl_null; + if (i >= alen) return (jl_value_t*)jl_null; jl_value_t *vi=NULL, *vt=NULL, *vv=NULL; JL_GC_PUSH(&vi, &vt); vi = jl_box_uint32(i+2); diff --git a/src/task.c b/src/task.c index 3d31da368b447..3c3af5cd85944 100644 --- a/src/task.c +++ b/src/task.c @@ -5,22 +5,21 @@ #include #include #include -#include +//#include #include #include #include #include #include "julia.h" #include "builtin_proto.h" -#if defined(__APPLE__) -#include -#elif defined(__WIN32__) -#include +#if defined(__WIN32__) +#include #include #else // This gives unwind only local unwinding options ==> faster code #define UNW_LOCAL_ONLY #include +#include // for dladdr #endif /* This probing code is derived from Douglas Jones' user thread library */ @@ -129,7 +128,7 @@ static void _probe_arch(void) */ extern size_t jl_page_size; -jl_struct_type_t *jl_task_type; +jl_datatype_t *jl_task_type; DLLEXPORT jl_task_t * volatile jl_current_task; jl_task_t *jl_root_task; jl_value_t * volatile jl_task_arg_in_transit; @@ -206,7 +205,7 @@ static void ctx_switch(jl_task_t *t, jl_jmp_buf *where) /* making task switching interrupt-safe is going to be challenging. we need JL_SIGATOMIC_BEGIN in jl_enter_handler, and then - JL_SIGATOMIC_END after every JL_TRY setjmp that returns zero. + JL_SIGATOMIC_END after every JL_TRY sigsetjmp that returns zero. also protect jl_eh_restore_state. then we need JL_SIGATOMIC_BEGIN at the top of this function (ctx_switch). the JL_SIGATOMIC_END at the end of this function handles the case @@ -403,7 +402,7 @@ static void init_task(jl_task_t *t) // this runs when the task is created ptrint_t local_sp = (ptrint_t)&t; ptrint_t new_sp = (ptrint_t)t->stack + t->ssize - _frame_offset; -#ifdef __LP64__ +#ifdef _P64 // SP must be 16-byte aligned new_sp = new_sp&-16; local_sp = local_sp&-16; @@ -413,52 +412,49 @@ static void init_task(jl_task_t *t) } #endif -#if defined(__APPLE__) || defined(__WIN32__) -#define MAX_BT_SIZE 1023 -#else #define MAX_BT_SIZE 80000 -#endif static ptrint_t bt_data[MAX_BT_SIZE+1]; static size_t bt_size = 0; -void getFunctionInfo(char **name, int *line, const char **filename, size_t pointer); +void getFunctionInfo(const char **name, int *line, const char **filename, size_t pointer); -static void push_frame_info_from_ip(jl_array_t *a, size_t ip) +static const char* name_unknown = "???"; +static int frame_info_from_ip(const char **func_name, int *line_num, const char **file_name, size_t ip, int doCframes) { - char *func_name; - int line_num; - const char *file_name; - int i = jl_array_len(a); - getFunctionInfo(&func_name, &line_num, &file_name, ip); - if (func_name != NULL) { - jl_array_grow_end(a, 3); - //ios_printf(ios_stderr, "%s at %s:%d\n", func_name, file_name, line_num); - jl_arrayset(a, (jl_value_t*)jl_symbol(func_name), i); i++; - jl_arrayset(a, (jl_value_t*)jl_symbol(file_name), i); i++; - jl_arrayset(a, jl_box_long(line_num), i); - } -} + int fromC = 0; -DLLEXPORT jl_value_t *jl_get_backtrace() -{ - jl_array_t *a = jl_alloc_cell_1d(0); - JL_GC_PUSH(&a); - for(size_t i=0; i < bt_size; i++) { - push_frame_info_from_ip(a, (size_t)bt_data[i]); + getFunctionInfo(func_name, line_num, file_name, ip); + if (*func_name == NULL && doCframes) { + fromC = 1; +#if defined(__WIN32__) + *func_name = name_unknown; // FIXME + *file_name = name_unknown; + *line_num = 0; +#else + Dl_info dlinfo; + if (dladdr((void*) ip, &dlinfo) != 0) { + *file_name = (dlinfo.dli_fname != NULL) ? dlinfo.dli_fname : name_unknown; + if (dlinfo.dli_sname != NULL) { + *func_name = dlinfo.dli_sname; + // line number in C looks tricky. addr2line and libbfd seem promising. For now, punt and just return address offset. + *line_num = ip-(size_t)dlinfo.dli_saddr; + } else { + *func_name = name_unknown; + *line_num = 0; + } + } else { + *func_name = name_unknown; + *file_name = name_unknown; + *line_num = 0; + } +#endif } - JL_GC_POP(); - return (jl_value_t*)a; + return fromC; } -#if defined(__APPLE__) -// stacktrace using execinfo -static void record_backtrace(void) -{ - bt_size = backtrace((void**)bt_data, MAX_BT_SIZE); -} -#elif defined(__WIN32__) -static void record_backtrace(void) +#if defined(__WIN32__) +DLLEXPORT size_t rec_backtrace(ptrint_t *data, size_t maxsize) { /** MINGW does not have the necessary declarations for linking CaptureStackBackTrace*/ #if defined(__MINGW_H) @@ -472,11 +468,10 @@ static void record_backtrace(void) FreeLibrary(kernel32); kernel32 = NULL; func = NULL; - bt_size = 0; - return; + return (size_t) 0; } else { - bt_size = func(0, MAX_BT_SIZE, bt_data, NULL); + return func(0, maxsize, data, NULL); } } else { @@ -485,12 +480,12 @@ static void record_backtrace(void) } FreeLibrary(kernel32); #else - bt_size = RtlCaptureStackBackTrace(0, MAX_BT_SIZE, bt_data, NULL); + return RtlCaptureStackBackTrace(0, maxsize, (void**)data, NULL); #endif } #else // stacktrace using libunwind -static void record_backtrace(void) +DLLEXPORT size_t rec_backtrace(ptrint_t *data, size_t maxsize) { unw_cursor_t cursor; unw_context_t uc; unw_word_t ip; @@ -498,24 +493,113 @@ static void record_backtrace(void) unw_getcontext(&uc); unw_init_local(&cursor, &uc); - while (unw_step(&cursor) && n < MAX_BT_SIZE) { + while (unw_step(&cursor) && n < maxsize) { unw_get_reg(&cursor, UNW_REG_IP, &ip); - bt_data[n++] = ip; + data[n++] = ip; + /* + char *func_name; + int line_num; + const char *file_name; + getFunctionInfo(&func_name, &line_num, &file_name, ip); + if (func_name != NULL) + ios_printf(ios_stdout, "in %s at %s:%d\n", func_name, file_name, line_num); + */ } - bt_size = n; + return n; } #endif +static void record_backtrace(void) +{ + bt_size = rec_backtrace(bt_data, MAX_BT_SIZE); +} + +static jl_value_t *array_ptr_void_type = NULL; +DLLEXPORT jl_value_t *jl_backtrace_from_here(void) +{ + if (array_ptr_void_type == NULL) + array_ptr_void_type = jl_apply_type((jl_value_t*)jl_array_type, + jl_tuple2(jl_voidpointer_type, + jl_box_long(1))); + jl_array_t *bt = jl_alloc_array_1d(array_ptr_void_type, MAX_BT_SIZE); + size_t n = rec_backtrace(jl_array_data(bt), MAX_BT_SIZE); + if (n < MAX_BT_SIZE) + jl_array_del_end(bt, MAX_BT_SIZE-n); + return (jl_value_t*)bt; +} + +DLLEXPORT jl_value_t *jl_lookup_code_address(void *ip, int doCframes) +{ + const char *func_name; + int line_num; + const char *file_name; + (void)frame_info_from_ip(&func_name, &line_num, &file_name, (size_t)ip, doCframes); + if (func_name != NULL) { + jl_value_t *r = (jl_value_t*)jl_alloc_tuple(3); + JL_GC_PUSH(&r); + jl_tupleset(r, 0, jl_symbol(func_name)); + jl_tupleset(r, 1, jl_symbol(file_name)); + jl_tupleset(r, 2, jl_box_long(line_num)); + JL_GC_POP(); + return r; + } + return (jl_value_t*)jl_null; +} + +DLLEXPORT jl_value_t *jl_get_backtrace(void) +{ + if (array_ptr_void_type == NULL) + array_ptr_void_type = jl_apply_type((jl_value_t*)jl_array_type, + jl_tuple2(jl_voidpointer_type, + jl_box_long(1))); + jl_array_t *bt = jl_alloc_array_1d(array_ptr_void_type, bt_size); + memcpy(bt->data, bt_data, bt_size*sizeof(void*)); + return (jl_value_t*)bt; +} + +//for looking up functions from gdb: +DLLEXPORT void gdblookup(ptrint_t ip) +{ + const char *func_name; + int line_num; + const char *file_name; + int fromC = frame_info_from_ip(&func_name, &line_num, &file_name, ip, 1); + if (func_name != NULL) { + if (fromC) + ios_printf(ios_stderr, "%s at %s: offset %x\n", func_name, file_name, line_num); + else + ios_printf(ios_stderr, "%s at %s:%d\n", func_name, file_name, line_num); + } +} + +DLLEXPORT void gdbbacktrace() +{ + record_backtrace(); + for(size_t i=0; i < bt_size; i++) + gdblookup(bt_data[i]); +} + +DLLEXPORT void jlbacktrace() +{ + for(size_t i=0; i < bt_size; i++) + gdblookup(bt_data[i]); +} + + // yield to exception handler -static void throw_internal(jl_value_t *e) +static void NORETURN throw_internal(jl_value_t *e) { jl_exception_in_transit = e; if (jl_current_task->eh != NULL) { jl_longjmp(jl_current_task->eh->eh_ctx, 1); } else { + if (jl_current_task == jl_root_task) { + JL_PRINTF(JL_STDERR, "fatal: error thrown and no exception handler available.\n"); + exit(1); + } jl_task_t *cont = jl_current_task->on_exit; - while (cont->done) + while (cont->done || cont->eh == NULL) cont = cont->on_exit; // for now, exit the task finish_task(jl_current_task, e); @@ -551,12 +635,12 @@ jl_task_t *jl_new_task(jl_function_t *start, size_t ssize) { size_t pagesz = jl_page_size; jl_task_t *t = (jl_task_t*)allocobj(sizeof(jl_task_t)); - t->type = (jl_type_t*)jl_task_type; + t->type = (jl_value_t*)jl_task_type; ssize = LLT_ALIGN(ssize, pagesz); t->ssize = ssize; t->on_exit = NULL; t->last = jl_current_task; - t->tls = jl_current_task->tls; + t->tls = jl_nothing; t->consumers = jl_nothing; t->done = 0; t->runnable = 1; @@ -650,22 +734,28 @@ jl_function_t *jl_unprotect_stack_func; void jl_init_tasks(void *stack, size_t ssize) { _probe_arch(); - jl_task_type = jl_new_struct_type(jl_symbol("Task"), jl_any_type, - jl_null, - jl_tuple(6, jl_symbol("parent"), - jl_symbol("last"), - jl_symbol("tls"), - jl_symbol("consumers"), - jl_symbol("done"), - jl_symbol("runnable")), - jl_tuple(6, jl_any_type, jl_any_type, - jl_any_type, jl_any_type, - jl_bool_type, jl_bool_type)); + jl_task_type = jl_new_datatype(jl_symbol("Task"), + jl_any_type, + jl_null, + jl_tuple(7, + jl_symbol("parent"), + jl_symbol("last"), + jl_symbol("storage"), + jl_symbol("consumers"), + jl_symbol("done"), + jl_symbol("runnable"), + jl_symbol("result")), + jl_tuple(7, + jl_any_type, jl_any_type, + jl_any_type, jl_any_type, + jl_bool_type, jl_bool_type, + jl_any_type), + 0, 1); jl_tupleset(jl_task_type->types, 0, (jl_value_t*)jl_task_type); jl_task_type->fptr = jl_f_task; jl_current_task = (jl_task_t*)allocobj(sizeof(jl_task_t)); - jl_current_task->type = (jl_type_t*)jl_task_type; + jl_current_task->type = (jl_value_t*)jl_task_type; #ifdef COPY_STACKS jl_current_task->stackbase = stack+ssize; jl_current_task->ssize = 0; // size of saved piece diff --git a/src/toplevel.c b/src/toplevel.c index 4f726c5a108eb..553693555636c 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -17,6 +17,7 @@ #include #include #include "julia.h" +#include #include "builtin_proto.h" DLLEXPORT char *julia_home = NULL; @@ -27,6 +28,16 @@ jl_module_t *jl_old_base_module = NULL; jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast); +void jl_add_standard_imports(jl_module_t *m) +{ + // using Base + jl_module_using(m, jl_base_module); + // importall Base.Operators + jl_module_importall(m, (jl_module_t*)jl_get_global(jl_base_module, + jl_symbol("Operators"))); +} + +extern int base_module_conflict; jl_value_t *jl_eval_module_expr(jl_expr_t *ex) { assert(ex->head == module_sym); @@ -49,6 +60,8 @@ jl_value_t *jl_eval_module_expr(jl_expr_t *ex) jl_old_base_module = jl_base_module; // pick up Base module during bootstrap jl_base_module = newm; + } else { + base_module_conflict = 1; } // export all modules from Main if (parent_module == jl_main_module) @@ -56,8 +69,9 @@ jl_value_t *jl_eval_module_expr(jl_expr_t *ex) // add standard imports unless baremodule if (std_imports) { - if (jl_base_module != NULL) - jl_module_using(newm, jl_base_module); // using Base + if (jl_base_module != NULL) { + jl_add_standard_imports(newm); + } } JL_GC_PUSH(&last_module); @@ -65,7 +79,7 @@ jl_value_t *jl_eval_module_expr(jl_expr_t *ex) jl_array_t *exprs = ((jl_expr_t*)jl_exprarg(ex, 2))->args; JL_TRY { - for(int i=0; i < exprs->length; i++) { + for(int i=0; i < jl_array_len(exprs); i++) { // process toplevel form jl_value_t *form = jl_cellref(exprs, i); (void)jl_toplevel_eval_flex(form, 1); @@ -84,7 +98,7 @@ jl_value_t *jl_eval_module_expr(jl_expr_t *ex) if (table[i] != HT_NOTFOUND) { jl_binding_t *b = (jl_binding_t*)table[i]; // remove non-exported macros - if (b->name->name[0]=='@' && !b->exportp) + if (b->name->name[0]=='@' && !b->exportp && b->owner==newm) b->value = NULL; // error for unassigned exports /* @@ -100,7 +114,7 @@ jl_value_t *jl_eval_module_expr(jl_expr_t *ex) static int is_intrinsic(jl_module_t *m, jl_sym_t *s) { jl_value_t *v = jl_get_global(m, s); - return (v != NULL && jl_typeof(v)==(jl_type_t*)jl_intrinsic_type); + return (v != NULL && jl_typeof(v)==(jl_value_t*)jl_intrinsic_type); } // module referenced by TopNode from within m @@ -114,7 +128,7 @@ jl_module_t *jl_base_relative_to(jl_module_t *m) static int has_intrinsics(jl_expr_t *e) { - if (e->args->length == 0) + if (jl_array_len(e->args) == 0) return 0; if (e->head == static_typeof_sym) return 1; jl_value_t *e0 = jl_exprarg(e,0); @@ -123,7 +137,7 @@ static int has_intrinsics(jl_expr_t *e) (jl_is_topnode(e0) && is_intrinsic(jl_base_relative_to(jl_current_module),(jl_sym_t*)jl_fieldref(e0,0))))) return 1; int i; - for(i=0; i < e->args->length; i++) { + for(i=0; i < jl_array_len(e->args); i++) { jl_value_t *a = jl_exprarg(e,i); if (jl_is_expr(a) && has_intrinsics((jl_expr_t*)a)) return 1; @@ -140,7 +154,7 @@ int jl_eval_with_compiler_p(jl_expr_t *expr, int compileloops) jl_array_t *body = expr->args; size_t i, maxlabl=0; // compile if there are backwards branches - for(i=0; i < body->length; i++) { + for(i=0; i < jl_array_len(body); i++) { jl_value_t *stmt = jl_cellref(body,i); if (jl_is_labelnode(stmt)) { int l = jl_labelnode_label(stmt); @@ -149,7 +163,7 @@ int jl_eval_with_compiler_p(jl_expr_t *expr, int compileloops) } size_t sz = (maxlabl+1+7)/8; char *labls = alloca(sz); memset(labls,0,sz); - for(i=0; i < body->length; i++) { + for(i=0; i < jl_array_len(body); i++) { jl_value_t *stmt = jl_cellref(body,i); if (jl_is_labelnode(stmt)) { int l = jl_labelnode_label(stmt); @@ -183,7 +197,9 @@ int jl_eval_with_compiler_p(jl_expr_t *expr, int compileloops) extern int jl_in_inference; -static jl_module_t *eval_import_path(jl_array_t *args) +static jl_value_t *require_func=NULL; + +static jl_module_t *eval_import_path_(jl_array_t *args, int retrying) { // in A.B.C, first find a binding for A in the chain of module scopes // following parent links. then evaluate the rest of the path from there. @@ -198,12 +214,24 @@ static jl_module_t *eval_import_path(jl_array_t *args) m = (jl_module_t*)mb->value; break; } - if (m == jl_main_module) + if (m == jl_main_module) { + if (!retrying) { + if (require_func == NULL && jl_base_module != NULL) + require_func = jl_get_global(jl_base_module, jl_symbol("require")); + if (require_func != NULL) { + jl_value_t *str = jl_cstr_to_string(var->name); + JL_GC_PUSH(&str); + jl_apply((jl_function_t*)require_func, &str, 1); + JL_GC_POP(); + return eval_import_path_(args, 1); + } + } jl_errorf("in module path: %s not defined", var->name); + } m = m->parent; } - for(size_t i=1; i < args->length-1; i++) { + for(size_t i=1; i < jl_array_len(args)-1; i++) { jl_value_t *s = jl_cellref(args,i); assert(jl_is_symbol(s)); m = (jl_module_t*)jl_eval_global_var(m, (jl_sym_t*)s); @@ -213,6 +241,11 @@ static jl_module_t *eval_import_path(jl_array_t *args) return m; } +static jl_module_t *eval_import_path(jl_array_t *args) +{ + return eval_import_path_(args, 0); +} + jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast) { //jl_show(ex); @@ -230,28 +263,42 @@ jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast) return jl_eval_module_expr(ex); } - // handle import, using, export toplevel-only forms - if (ex->head == using_sym) { + // handle import, using, importall, export toplevel-only forms + if (ex->head == importall_sym) { jl_module_t *m = eval_import_path(ex->args); - jl_sym_t *name = (jl_sym_t*)jl_cellref(ex->args, ex->args->length-1); + jl_sym_t *name = (jl_sym_t*)jl_cellref(ex->args, jl_array_len(ex->args)-1); assert(jl_is_symbol(name)); m = (jl_module_t*)jl_eval_global_var(m, name); if (!jl_is_module(m)) - jl_errorf("invalid using statement"); - jl_module_using(jl_current_module, m); + jl_errorf("invalid %s statement: name exists but does not refer to a module", ex->head->name); + jl_module_importall(jl_current_module, m); + return jl_nothing; + } + + if (ex->head == using_sym) { + jl_module_t *m = eval_import_path(ex->args); + jl_sym_t *name = (jl_sym_t*)jl_cellref(ex->args, jl_array_len(ex->args)-1); + assert(jl_is_symbol(name)); + jl_module_t *u = (jl_module_t*)jl_eval_global_var(m, name); + if (jl_is_module(u)) { + jl_module_using(jl_current_module, u); + } + else { + jl_module_use(jl_current_module, m, name); + } return jl_nothing; } if (ex->head == import_sym) { jl_module_t *m = eval_import_path(ex->args); - jl_sym_t *name = (jl_sym_t*)jl_cellref(ex->args, ex->args->length-1); + jl_sym_t *name = (jl_sym_t*)jl_cellref(ex->args, jl_array_len(ex->args)-1); assert(jl_is_symbol(name)); jl_module_import(jl_current_module, m, name); return jl_nothing; } if (ex->head == export_sym) { - for(size_t i=0; i < ex->args->length; i++) { + for(size_t i=0; i < jl_array_len(ex->args); i++) { jl_module_export(jl_current_module, (jl_sym_t*)jl_cellref(ex->args, i)); } @@ -260,7 +307,7 @@ jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast) if (ex->head == toplevel_sym) { int i=0; jl_value_t *res=jl_nothing; - for(i=0; i < ex->args->length; i++) { + for(i=0; i < jl_array_len(ex->args); i++) { res = jl_toplevel_eval_flex(jl_cellref(ex->args, i), fast); } return res; @@ -279,7 +326,7 @@ jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast) if (jl_is_expr(ex) && ex->head == toplevel_sym) { int i=0; jl_value_t *res=jl_nothing; - for(i=0; i < ex->args->length; i++) { + for(i=0; i < jl_array_len(ex->args); i++) { res = jl_toplevel_eval_flex(jl_cellref(ex->args, i), fast); } return res; @@ -292,7 +339,7 @@ jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast) if (!ewc) { jl_array_t *vinfos = jl_lam_vinfo((jl_expr_t*)thk->ast); int i; - for(i=0; i < vinfos->length; i++) { + for(i=0; i < jl_array_len(vinfos); i++) { if (jl_vinfo_capt((jl_array_t*)jl_cellref(vinfos,i))) { // interpreter doesn't handle closure environment ewc = 1; @@ -335,7 +382,7 @@ jl_value_t *jl_toplevel_eval(jl_value_t *v) // repeatedly call jl_parse_next and eval everything void jl_parse_eval_all(char *fname) { - //ios_printf(ios_stderr, "***** loading %s\n", fname); + //jl_printf(JL_STDERR, "***** loading %s\n", fname); int last_lineno = jl_lineno; jl_lineno=0; jl_value_t *fn=NULL, *ln=NULL, *form=NULL; @@ -348,7 +395,7 @@ void jl_parse_eval_all(char *fname) break; if (jl_is_expr(form)) { if (((jl_expr_t*)form)->head == jl_continue_sym) { - jl_errorf("syntax error: %s", jl_string_data(jl_exprarg(form,0))); + jl_errorf("syntax: %s", jl_string_data(jl_exprarg(form,0))); } if (((jl_expr_t*)form)->head == error_sym) { jl_interpret_toplevel_expr(form); @@ -374,14 +421,21 @@ int asprintf(char **strp, const char *fmt, ...); void jl_load(const char *fname) { + if (jl_current_module == jl_base_module) { + //This deliberatly uses ios, because stdio initialization has been moved to Julia + jl_printf(JL_STDOUT, "%s\n", fname); + } char *fpath = (char*)fname; - struct stat stbuf; - if (jl_stat(fpath, (char*)&stbuf) != 0) { + uv_statbuf_t stbuf; + if (jl_stat(fpath, (char*)&stbuf) != 0 || (stbuf.st_mode & S_IFMT) != S_IFREG) { jl_errorf("could not open file %s", fpath); } jl_start_parsing_file(fpath); jl_parse_eval_all(fpath); if (fpath != fname) free(fpath); + if (jl_current_module == jl_base_module) { + jl_printf(JL_STDOUT, "\e[1F\e[2K"); + } } // load from filename given as a ByteString object @@ -392,12 +446,11 @@ DLLEXPORT void jl_load_(jl_value_t *str) // type definition ------------------------------------------------------------ -void jl_reinstantiate_inner_types(jl_tag_type_t *t); +void jl_reinstantiate_inner_types(jl_datatype_t *t); void jl_check_type_tuple(jl_tuple_t *t, jl_sym_t *name, const char *ctx) { - size_t i; - for(i=0; i < jl_tuple_len(t); i++) { + for(size_t i=0; i < jl_tuple_len(t); i++) { jl_value_t *elt = jl_tupleref(t,i); if (!jl_is_type(elt) && !jl_is_typevar(elt)) { jl_type_error_rt(name->name, ctx, (jl_value_t*)jl_type_type, elt); @@ -405,30 +458,36 @@ void jl_check_type_tuple(jl_tuple_t *t, jl_sym_t *name, const char *ctx) } } -void jl_set_tag_type_super(jl_tag_type_t *tt, jl_value_t *super) +void jl_set_datatype_super(jl_datatype_t *tt, jl_value_t *super) { - if (!jl_is_tag_type(super) || super == (jl_value_t*)jl_undef_type || + if (!jl_is_datatype(super) || super == (jl_value_t*)jl_undef_type || + !jl_is_abstracttype(super) || jl_subtype(super,(jl_value_t*)jl_type_type,0)) { jl_errorf("invalid subtyping in definition of %s",tt->name->name->name); } - tt->super = (jl_tag_type_t*)super; + tt->super = (jl_datatype_t*)super; if (jl_tuple_len(tt->parameters) > 0) { - tt->name->cache = jl_null; - jl_reinstantiate_inner_types((jl_tag_type_t*)tt); + tt->name->cache = (jl_value_t*)jl_null; + jl_reinstantiate_inner_types(tt); } } // method definition ---------------------------------------------------------- extern int jl_boot_file_loaded; -void jl_add_constructors(jl_struct_type_t *t); +void jl_add_constructors(jl_datatype_t *t); jl_value_t *jl_method_def(jl_sym_t *name, jl_value_t **bp, jl_binding_t *bnd, jl_tuple_t *argtypes, jl_function_t *f, jl_tuple_t *t) { jl_value_t *gf; if (bnd) { - jl_declare_constant(bnd); + //jl_declare_constant(bnd); + if (bnd->value != NULL && !bnd->constp) { + jl_errorf("cannot define function %s; it already has a value", + bnd->name->name); + } + bnd->constp = 1; } if (*bp == NULL) { gf = (jl_value_t*)jl_new_generic_function(name); @@ -437,9 +496,9 @@ jl_value_t *jl_method_def(jl_sym_t *name, jl_value_t **bp, jl_binding_t *bnd, else { gf = *bp; if (!jl_is_gf(gf)) { - if (jl_is_struct_type(gf) && + if (jl_is_datatype(gf) && ((jl_function_t*)gf)->fptr == jl_f_ctor_trampoline) { - jl_add_constructors((jl_struct_type_t*)gf); + jl_add_constructors((jl_datatype_t*)gf); } if (!jl_is_gf(gf)) { jl_error("invalid method definition: not a generic function"); @@ -450,8 +509,20 @@ jl_value_t *jl_method_def(jl_sym_t *name, jl_value_t **bp, jl_binding_t *bnd, assert(jl_is_function(f)); assert(jl_is_tuple(argtypes)); assert(jl_is_tuple(t)); - jl_check_type_tuple(argtypes, name, "method definition"); - for(size_t i=0; i < t->length; i++) { + + for(size_t i=0; i < jl_tuple_len(argtypes); i++) { + jl_value_t *elt = jl_tupleref(argtypes,i); + if (!jl_is_type(elt) && !jl_is_typevar(elt)) { + jl_lambda_info_t *li = f->linfo; + jl_errorf("invalid type for argument %s in method definition for %s at %s:%d", + jl_is_expr(li->ast) ? + ((jl_sym_t*)jl_arrayref(jl_lam_args((jl_expr_t*)li->ast),i))->name : + "?", + name->name, li->file->name, li->line); + } + } + + for(size_t i=0; i < jl_tuple_len(t); i++) { if (!jl_is_typevar(jl_tupleref(t,i))) jl_type_error_rt(name->name, "method definition", (jl_value_t*)jl_tvar_type, jl_tupleref(t,i)); diff --git a/src/utils.scm b/src/utils.scm index 3f43fad6389ac..d6188cc64b67b 100644 --- a/src/utils.scm +++ b/src/utils.scm @@ -17,12 +17,7 @@ ((memq (car s1) s2) (diff (cdr s1) s2)) (else (cons (car s1) (diff (cdr s1) s2))))) -(define (unique lst) - (if (null? lst) - '() - (if (memq (car lst) (cdr lst)) - (unique (cdr lst)) - (cons (car lst) (unique (cdr lst)))))) +(define (unique lst) (delete-duplicates lst)) (define (has-dups lst) (if (null? lst) @@ -36,6 +31,16 @@ (any (lambda (x) (contains p x)) expr)))) +(define (butlast lst) + (if (or (null? lst) (null? (cdr lst))) + '() + (cons (car lst) (butlast (cdr lst))))) + +(define (last lst) + (if (null? (cdr lst)) + (car lst) + (last (cdr lst)))) + (define *gensyms* '()) (define *current-gensyms* '()) (define *gensy-counter* 1) @@ -47,5 +52,9 @@ g) (begin0 (car *current-gensyms*) (set! *current-gensyms* (cdr *current-gensyms*))))) +(define (named-gensy name) + (let ((g (symbol (string name "#" *gensy-counter*)))) + (set! *gensy-counter* (+ *gensy-counter* 1)) + g)) (define (reset-gensyms) (set! *current-gensyms* *gensyms*)) diff --git a/src/uv_constants.h b/src/uv_constants.h new file mode 100644 index 0000000000000..4076ac26f684f --- /dev/null +++ b/src/uv_constants.h @@ -0,0 +1,7 @@ +#include "uv.h" +#define XX(uc,lc) :UV_##uc, +const UV_UNKNOWN_HANDLE = 0 +handles = [UV_HANDLE_TYPE_MAP(XX) :UV_FILE, :UV_HANDLE_TYPE_MAX, :UV_RAW_FD, :UV_RAW_HANDLE] +for i=1:(length(handles)) +@eval const $(handles[i]) = $i +end diff --git a/test/.gitignore b/test/.gitignore new file mode 100644 index 0000000000000..00e869a2da043 --- /dev/null +++ b/test/.gitignore @@ -0,0 +1 @@ +/ccall diff --git a/test/Makefile b/test/Makefile index 3f87ddb6760db..0fb68cb21dd0b 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,14 +1,10 @@ -JULIAHOME = .. +JULIAHOME = $(abspath ..) include ../Make.inc -default all extra unicode gzip:: - @$(MAKE) -sC unicode - -TESTS = default all extra \ -core numbers strings unicode corelib hashing remote \ -arrayops linalg fft sparse bitarray suitesparse arpack \ -random math functional bigint combinatorics statistics \ -glpk linprog bigfloat poly file Rmath remote zlib image gzip +TESTS = core keywordargs numbers strings unicode corelib hashing remote iostring \ +arrayops linalg blas fft dct sparse bitarray random math functional bigint \ +sorting statistics spawn parallel suitesparse arpack bigfloat file zlib \ +all git pkg pkg2 $(TESTS) :: $(QUIET_JULIA) $(JULIA_EXECUTABLE) ./runtests.jl $@ @@ -24,8 +20,13 @@ benchmark: @$(MAKE) -C perf $@ clean: - @$(MAKE) -C unicode $@ @$(MAKE) -C perf $@ + -rm -f libccalltest.${SHLIB_EXT} ccalltest .PHONY: $(TESTS) perf benchmark clean +libccalltest.$(SHLIB_EXT): ccalltest.c + $(CC) $(CFLAGS) $(DEBUGFLAGS) -O3 $< -fPIC -shared -o $@ $(LDFLAGS) -DCC=$(CC) + +ccalltest: ccalltest.c + $(CC) $(CFLAGS) $(DEBUGFLAGS) -O3 $< -o $@ $(LDFLAGS) -DCC=$(CC) diff --git a/test/Rmath.jl b/test/Rmath.jl deleted file mode 100644 index 4c398870666ac..0000000000000 --- a/test/Rmath.jl +++ /dev/null @@ -1,197 +0,0 @@ -require("extras/Rmath") - -srand(124) - -function allEq(target::Vector{Float64}, current::Vector{Float64}, tolerance::Float64) - @test numel(target) == numel(current) - if all(target == current) - return true - end - xy = mean(abs(target - current)) - xn = mean(abs(target)) - if (isfinite(xn) && xn > tolerance) - xy /= xn - end - @test xy < tolerance - return true -end - -allEq(target::Vector{Float64}, current::Vector{Float64}) = - allEq(target, current, sqrt(eps())) - -# dbeta -@test abs(dbeta(-1, 1, 1) - 0.0) < 10e-8 -@test abs(dbeta(0, 1, 1) - 1.0) < 10e-8 -@test abs(dbeta(1, 1, 1) - 1.0) < 10e-8 - -# dbinom -@test abs(dbinom(0, 2, 0.5) - 0.25) < 10e-8 -@test abs(dbinom(1, 2, 0.5) - 0.5) < 10e-8 -@test abs(dbinom(2, 2, 0.5) - 0.25) < 10e-8 - -# dcauchy -@test abs(dcauchy(0, 0, 1) - (1 / pi) * (1 / ((0 - 0)^2 + 1^2))) < 10e-8 -@test abs(dcauchy(0, 1, 2) - (1 / pi) * (2 / ((0 - 1)^2 + 2^2))) < 10e-8 - -# dchisq -@test abs(dchisq(1, 1) - let x = 1; k = 1; (x^((k / 2) - 1) * exp(-(x / 2))) / (2^(k / 2) * gamma(k / 2)) end) < 10e-8 -@test abs(dchisq(2, 3) - let x = 2; k = 3; (x^((k / 2) - 1) * exp(-(x / 2))) / (2^(k / 2) * gamma(k / 2)) end) < 10e-8 - -# dexp -@test abs(dexp(1, 2) - (1 / 2) * exp(-(1 / 2) * 1)) < 10e-8 -@test abs(dexp(1, 3) - (1 / 3) * exp(-(1 / 3) * 1)) < 10e-8 -@test abs(dexp(2, 3) - (1 / 3) * exp(-(1 / 3) * 2)) < 10e-8 - -n = 26 - -Rbeta = rbeta (n, .8, 2) -Rbinom = rbinom (n, 55, pi/16) -Rcauchy = rcauchy (n, 12, 2) -Rchisq = rchisq (n, 3) -Rexp = rexp (n, 2) -Rf = rf (n, 12, 6) -Rgamma = rgamma (n, 2, 5) -Rgeom = rgeom (n, pi/16) -Rhyper = rhyper (n, 40, 30, 20) -Rlnorm = rlnorm (n, -1, 3) -Rlogis = rlogis (n, 12, 2) -Rnbinom = rnbinom (n, 7, .01) -Rnorm = rnorm (n, -1, 3) -Rpois = rpois (n, 12) -Rsignrank = rsignrank(n, 47) -Rt = rt (n, 11) -## Rt2 below (to preserve the following random numbers!) -Runif = runif (n, .2, 2) -Rweibull = rweibull (n, 3, 2) -Rwilcox = rwilcox (n, 13, 17) -Rt2 = rt (n, 1.01) - -Pbeta = pbeta (Rbeta, .8, 2) -Pbinom = pbinom (Rbinom, 55, pi/16) -Pcauchy = pcauchy (Rcauchy, 12, 2) -Pchisq = pchisq (Rchisq, 3) -Pexp = pexp (Rexp, 2) -Pf = pf (Rf, 12, 6) -Pgamma = pgamma (Rgamma, 2, 5) -Pgeom = pgeom (Rgeom, pi/16) -Phyper = phyper (Rhyper, 40, 30, 20) -Plnorm = plnorm (Rlnorm, -1, 3) -Plogis = plogis (Rlogis, 12, 2) -Pnbinom = pnbinom (Rnbinom, 7, .01) -Pnorm = pnorm (Rnorm, -1, 3) -Ppois = ppois (Rpois, 12) -Psignrank = psignrank(Rsignrank, 47) -Pt = pt (Rt, 11) -Pt2 = pt (Rt2, 1.01) -Punif = punif (Runif, .2, 2) -Pweibull = pweibull (Rweibull, 3, 2) -Pwilcox = pwilcox (Rwilcox, 13, 17) - -dbeta (Rbeta, .8, 2) -dbinom (Rbinom, 55, pi/16) -dcauchy (Rcauchy, 12, 2) -dchisq (Rchisq, 3) -dexp (Rexp, 2) -df (Rf, 12, 6) -dgamma (Rgamma, 2, 5) -dgeom (Rgeom, pi/16) -dhyper (Rhyper, 40, 30, 20) -dlnorm (Rlnorm, -1, 3) -dlogis (Rlogis, 12, 2) -dnbinom (Rnbinom, 7, .01) -dnorm (Rnorm, -1, 3) -dpois (Rpois, 12) -dsignrank(Rsignrank, 47) -dt (Rt, 11) -dunif (Runif, .2, 2) -dweibull (Rweibull, 3, 2) -dwilcox (Rwilcox, 13, 17) - -## Check q*(p*(.)) = identity -allEq(Rbeta, qbeta (Pbeta, .8, 2)) -allEq(Rbinom, qbinom (Pbinom, 55, pi/16)) -allEq(Rcauchy, qcauchy (Pcauchy, 12, 2)) -allEq(Rchisq, qchisq (Pchisq, 3)) -allEq(Rexp, qexp (Pexp, 2)) -allEq(Rf, qf (Pf, 12, 6)) -allEq(Rgamma, qgamma (Pgamma, 2, 5)) -allEq(Rgeom, qgeom (Pgeom, pi/16)) -allEq(Rhyper, qhyper (Phyper, 40, 30, 20)) -allEq(Rlnorm, qlnorm (Plnorm, -1, 3)) -allEq(Rlogis, qlogis (Plogis, 12, 2)) -allEq(Rnbinom, qnbinom (Pnbinom, 7, .01)) -allEq(Rnorm, qnorm (Pnorm, -1, 3)) -allEq(Rpois, qpois (Ppois, 12)) -allEq(Rsignrank, qsignrank(Psignrank, 47)) -allEq(Rt, qt (Pt, 11)) -allEq(Rt2, qt (Pt2, 1.01), 1e-2) -allEq(Runif, qunif (Punif, .2, 2)) -allEq(Rweibull, qweibull (Pweibull, 3, 2)) -allEq(Rwilcox, qwilcox (Pwilcox, 13, 17)) - -## Same with "upper tail": -allEq(Rbeta, qbeta (1- Pbeta, .8, 2, false)) -allEq(Rbinom, qbinom (1- Pbinom, 55, pi/16, false)) -allEq(Rcauchy, qcauchy (1- Pcauchy, 12, 2, false)) -allEq(Rchisq, qchisq (1- Pchisq, 3, false)) -allEq(Rexp, qexp (1- Pexp, 2, false)) -allEq(Rf, qf (1- Pf, 12, 6, false)) -allEq(Rgamma, qgamma (1- Pgamma, 2, 5, false)) -allEq(Rgeom, qgeom (1- Pgeom, pi/16, false)) -allEq(Rhyper, qhyper (1- Phyper, 40, 30, 20, false)) -allEq(Rlnorm, qlnorm (1- Plnorm, -1, 3, false)) -allEq(Rlogis, qlogis (1- Plogis, 12, 2, false)) -allEq(Rnbinom, qnbinom (1- Pnbinom, 7, .01, false)) -allEq(Rnorm, qnorm (1- Pnorm, -1, 3,false)) -allEq(Rpois, qpois (1- Ppois, 12, false)) -allEq(Rsignrank, qsignrank(1- Psignrank, 47, false)) -allEq(Rt, qt (1- Pt, 11, false)) -allEq(Rt2, qt (1- Pt2, 1.01, false), 1e-2) -allEq(Runif, qunif (1- Punif, .2, 2, false)) -allEq(Rweibull, qweibull (1- Pweibull, 3, 2, false)) -allEq(Rwilcox, qwilcox (1- Pwilcox, 13, 17, false)) - -## Check q*(p* ( log ), log) = identity -allEq(Rbeta, qbeta (log(Pbeta), .8, 2, true, true)) -allEq(Rbinom, qbinom (log(Pbinom), 55, pi/16, true, true)) -allEq(Rcauchy, qcauchy (log(Pcauchy), 12, 2, true, true)) -allEq(Rchisq, qchisq (log(Pchisq), 3, true, true), 1e-14) -allEq(Rexp, qexp (log(Pexp), 2, true, true)) -allEq(Rf, qf (log(Pf), 12, 6, true, true)) -allEq(Rgamma, qgamma (log(Pgamma), 2, 5, true, true)) -allEq(Rgeom, qgeom (log(Pgeom), pi/16, true, true)) -allEq(Rhyper, qhyper (log(Phyper), 40, 30, 20, true, true)) -allEq(Rlnorm, qlnorm (log(Plnorm), -1, 3, true, true)) -allEq(Rlogis, qlogis (log(Plogis), 12, 2, true, true)) -allEq(Rnbinom, qnbinom (log(Pnbinom), 7, .01, true, true)) -allEq(Rnorm, qnorm (log(Pnorm), -1, 3, true, true)) -allEq(Rpois, qpois (log(Ppois), 12, true, true)) -allEq(Rsignrank, qsignrank(log(Psignrank), 47, true, true)) -allEq(Rt, qt (log(Pt), 11, true, true)) -allEq(Rt2, qt (log(Pt2), 1.01, true, true), 1e-2) -allEq(Runif, qunif (log(Punif), .2, 2, true, true)) -allEq(Rweibull, qweibull (log(Pweibull), 3, 2, true, true)) -allEq(Rwilcox, qwilcox (log(Pwilcox), 13, 17, true, true)) - -## same q*(p* (log) log) with upper tail: - -allEq(Rbeta, qbeta (log(1- Pbeta), .8, 2, false, true)) -allEq(Rbinom, qbinom (log(1- Pbinom), 55, pi/16, false, true)) -allEq(Rcauchy, qcauchy (log(1- Pcauchy), 12, 2, false, true)) -allEq(Rchisq, qchisq (log(1- Pchisq), 3, false, true)) -allEq(Rexp, qexp (log(1- Pexp), 2, false, true)) -allEq(Rf, qf (log(1- Pf), 12, 6, false, true)) -allEq(Rgamma, qgamma (log(1- Pgamma), 2, 5, false, true)) -allEq(Rgeom, qgeom (log(1- Pgeom), pi/16, false, true)) -allEq(Rhyper, qhyper (log(1- Phyper), 40, 30, 20, false, true)) -allEq(Rlnorm, qlnorm (log(1- Plnorm), -1, 3, false, true)) -allEq(Rlogis, qlogis (log(1- Plogis), 12, 2, false, true)) -allEq(Rnbinom, qnbinom (log(1- Pnbinom), 7, .01, false, true)) -allEq(Rnorm, qnorm (log(1- Pnorm), -1, 3, false, true)) -allEq(Rpois, qpois (log(1- Ppois), 12, false, true)) -allEq(Rsignrank, qsignrank(log(1- Psignrank), 47, false, true)) -allEq(Rt, qt (log(1- Pt ), 11, false, true)) -allEq(Rt2, qt (log(1- Pt2), 1.01, false, true), 1e-2) -allEq(Runif, qunif (log(1- Punif), .2, 2, false, true)) -allEq(Rweibull, qweibull (log(1- Pweibull), 3, 2, false, true)) -allEq(Rwilcox, qwilcox (log(1- Pwilcox), 13, 17, false, true)) diff --git a/test/all.jl b/test/all.jl deleted file mode 100644 index 5b4e5f9d1d3c4..0000000000000 --- a/test/all.jl +++ /dev/null @@ -1,2 +0,0 @@ -load("default") -load("extra") diff --git a/test/arpack.jl b/test/arpack.jl index 471ea33f6cc0a..1d3ac5c018abc 100644 --- a/test/arpack.jl +++ b/test/arpack.jl @@ -1,17 +1,12 @@ -require("extras/arpack") - -using ARPACK - -# arpack begin -local n,a,asym,d,v -n = 10 -a = rand(n,n) -asym = a+a'+n*eye(n) + local n,a,asym,d,v + n = 10 + a = rand(n,n) + asym = a' * a -(d,v) = eigs(asym, 3) -@test sum(asym*v[:,1]-d[1]*v[:,1]) < 1e-8 + (d,v) = eigs(asym, 3) + @test sum(asym*v[:,1]-d[1]*v[:,1]) < 1e-8 -(d,v) = eigs(a,3) -@test abs(sum(a*v[:,2]-d[2]*v[:,2])) < 1e-8 + (d,v) = eigs(a,3) + @test abs(sum(a*v[:,2]-d[2]*v[:,2])) < 1e-8 end diff --git a/test/arrayops.jl b/test/arrayops.jl index 2757960b53dd3..8075b4a006c74 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -85,13 +85,63 @@ B[4,[2,3]] = 7 @test isequal(reshape(1:27, 3, 3, 3)[1,:], [1 4 7 10 13 16 19 22 25]) +a = [3, 5, -7, 6] +b = [4, 6, 2, -7, 1] +ind = findin(a, b) +@test ind == [3,4] + +# sub +A = reshape(1:120, 3, 5, 8) +sA = sub(A, 2, 1:5, 1:8) +@test size(sA) == (1, 5, 8) +@test_fails sA[2, 1:8] +@test sA[1, 2, 1:8][:] == 5:15:120 +sA[2:5:end] = -1 +@test all(sA[2:5:end] .== -1) +@test all(A[5:15:120] .== -1) + +# slice +A = reshape(1:120, 3, 5, 8) +sA = slice(A, 2, 1:5, 1:8) +@test size(sA) == (5, 8) +@test sA[2, 1:8][:] == 5:15:120 +@test sA[:,1] == 2:3:14 +@test sA[2:5:end] == 5:15:120 +sA[2:5:end] = -1 +@test all(sA[2:5:end] .== -1) +@test all(A[5:15:120] .== -1) + + +# get +let + A = reshape(1:24, 3, 8) + x = get(A, 32, -12) + @test x == -12 + x = get(A, 14, -12) + @test x == 14 + x = get(A, (2,4), -12) + @test x == 11 + x = get(A, (4,4), -12) + @test x == -12 + X = get(A, -5:5, nan(Float32)) + @test eltype(X) == Float32 + @test isnan(X) == [trues(6),falses(5)] + @test X[7:11] == 1:5 + X = get(A, (2:4, 9:-2:-13), 0) + Xv = zeros(Int, 3, 12) + Xv[1:2, 2:5] = A[2:3, 7:-2:1] + @test X == Xv + X2 = get(A, Vector{Int}[[2:4], [9:-2:-13]], 0) + @test X == X2 +end + ## arrays as dequeues l = {1,2,3} -push(l,8) +push!(l,8) @test l[1]==1 && l[2]==2 && l[3]==3 && l[4]==8 -v = pop(l) +v = pop!(l) @test v == 8 -v = pop(l) +v = pop!(l) @test v == 3 @test length(l)==2 @@ -99,6 +149,20 @@ v = pop(l) @test isequal([ones(2,2) 2*ones(2,1)], [1 1 2; 1 1 2]) @test isequal([ones(2,2), 2*ones(1,2)], [1 1; 1 1; 2 2]) +# typed array literals +X = Float64[1 2 3] +Y = [1. 2. 3.] +@test size(X) == size(Y) +for i = 1:3 @test X[i] === Y[i] end +X = Float64[1;2;3] +Y = [1.,2.,3.] +@test size(X) == size(Y) +for i = 1:3 @test X[i] === Y[i] end +X = Float64[1 2 3; 4 5 6] +Y = [1. 2. 3.; 4. 5. 6.] +@test size(X) == size(Y) +for i = 1:length(X) @test X[i] === Y[i] end + # "end" X = [ i+2j for i=1:5, j=1:5 ] @test X[end,end] == 15 @@ -143,13 +207,13 @@ end @assert indmax([10,12,9,11]) == 2 @assert indmin([10,12,9,11]) == 3 -## permute ## +## permutedims ## #keeps the num of dim p = randperm(5) q = randperm(5) a = rand(p...) -b = permute(a,q) +b = permutedims(a,q) @test isequal(size(b), tuple(p[q]...)) #hand made case @@ -165,22 +229,22 @@ for i = 1:3 end #permutes correctly -@test isequal(z,permute(y,(3,1,2))) +@test isequal(z,permutedims(y,(3,1,2))) # of a subarray a = rand(5,5) s = sub(a,2:3,2:3) -p = permute(s, [2,1]) +p = permutedims(s, [2,1]) @test p[1,1]==a[2,2] && p[1,2]==a[3,2] @test p[2,1]==a[2,3] && p[2,2]==a[3,3] -## ipermute ## +## ipermutedims ## tensors = {rand(1,2,3,4),rand(2,2,2,2),rand(5,6,5,6),rand(1,1,1,1)} for i = tensors perm = randperm(4) - @test isequal(i,ipermute(permute(i,perm),perm)) - @test isequal(i,permute(ipermute(i,perm),perm)) + @test isequal(i,ipermutedims(permutedims(i,perm),perm)) + @test isequal(i,permutedims(ipermutedims(i,perm),perm)) end @@ -203,19 +267,21 @@ v[2,2,1,1] = 40.0 ## large matrices transpose ## -for i = 1 : 5 +for i = 1 : 3 a = rand(200, 300) - @test isequal(a', permute(a, (2, 1))) + @test isequal(a', permutedims(a, (2, 1))) end -## basic darray ## +## cumsum, cummin, cummax -d = drand(10,10) -#@test isequal(d'', d) -@test isequal(convert(Array,d), d) +@assert isequal(cummin([1, 2, 5, -1, 3, -2]), [1, 1, 1, -1, -1, -2]) +@assert isequal(cummax([1, 2, 5, -1, 3, -2]), [1, 2, 5, 5, 5, 5]) -## cumsum +@assert isequal(cummax([1 0; 0 1], 1), [1 0; 1 1]) +@assert isequal(cummax([1 0; 0 1], 2), [1 1; 0 1]) +@assert isequal(cummin([1 0; 0 1], 1), [1 0; 0 0]) +@assert isequal(cummin([1 0; 0 1], 2), [1 0; 0 0]) @test sum_kbn([1,1e100,1,-1e100]) == 2 @@ -269,3 +335,66 @@ begin @test isequal(c[:,4], [2.0,2.0,2.0,2.0]*1000) end + +@test (1:5)[[true,false,true,false,true]] == [1,3,5] + +# issue #2342 +@test isequal(cumsum([1 2 3]), [1 2 3]) + +# set-like operations +@test isequal(union([1,2,3], [4,3,4]), [1,2,3,4]) +@test isequal(union(['e','c','a'], ['b','a','d']), ['e','c','a','b','d']) +@test isequal(union([1,2,3], [4,3], [5]), [1,2,3,4,5]) +@test isequal(union([1,2,3]), [1,2,3]) +@test isequal(union([1,2,3], Int64[]), [1,2,3]) +@test isequal(union([1,2,3], Float64[]), [1.0,2,3]) +@test isequal(union(Int64[], [1,2,3]), [1,2,3]) +@test isequal(union(Int64[]), Int64[]) +@test isequal(intersect([1,2,3], [4,3,4]), [3]) +@test isequal(intersect(['e','c','a'], ['b','a','d']), ['a']) +@test isequal(intersect([1,2,3], [3,1], [2,1,3]), [1,3]) +@test isequal(intersect([1,2,3]), [1,2,3]) +@test isequal(intersect([1,2,3], Int64[]), Int64[]) +@test isequal(intersect([1,2,3], Float64[]), Float64[]) +@test isequal(intersect(Int64[], [1,2,3]), Int64[]) +@test isequal(intersect(Int64[]), Int64[]) +@test isequal(setdiff([1,2,3,4], [2,5,4]), [1,3]) +@test isequal(setdiff([1,2,3,4], [7,8,9]), [1,2,3,4]) +@test isequal(setdiff([1,2,3,4], Int64[]), [1,2,3,4]) +@test isequal(setdiff([1,2,3,4], [1,2,3,4,5]), Int64[]) +@test isequal(symdiff([1,2,3], [4,3,4]), [1,2,4]) +@test isequal(symdiff(['e','c','a'], ['b','a','d']), ['e','c','b','d']) +@test isequal(symdiff([1,2,3], [4,3], [5]), [1,2,4,5]) +@test isequal(symdiff([1,2,3,4,5], [1,2,3], [3,4]), [3,5]) +@test isequal(symdiff([1,2,3]), [1,2,3]) +@test isequal(symdiff([1,2,3], Int64[]), [1,2,3]) +@test isequal(symdiff([1,2,3], Float64[]), [1.0,2,3]) +@test isequal(symdiff(Int64[], [1,2,3]), [1,2,3]) +@test isequal(symdiff(Int64[]), Int64[]) + +# mapslices +begin + local a,h,i + a = rand(5,5) + h = mapslices(v -> hist(v,0:0.1:1)[2], a, 1) + H = mapslices(v -> hist(v,0:0.1:1)[2], a, 2) + s = mapslices(sort, a, [1]) + S = mapslices(sort, a, [2]) + for i = 1:5 + @test h[:,i] == hist(a[:,i],0:0.1:1)[2] + @test vec(H[i,:]) == hist(vec(a[i,:]),0:0.1:1)[2] + @test s[:,i] == sort(a[:,i]) + @test vec(S[i,:]) == sort(vec(a[i,:])) + end +end + +# single multidimensional index +let + a = rand(6,6) + I = [1 4 5; 4 2 6; 5 6 3] + a2 = a[I] + @test size(a2) == size(I) + for i = 1:length(a2) + @test a2[i] == a[I[i]] + end +end diff --git a/test/arrayperf.jl b/test/arrayperf.jl index a6ecdc348b2fa..10d1a849a5f7d 100644 --- a/test/arrayperf.jl +++ b/test/arrayperf.jl @@ -38,12 +38,12 @@ if run_ref for n_dims in 1:10 sz = ntuple(n_dims,i->lensmall) A = randn(sz) - ind = ntuple(n_dims,i -> ((i <= ceil(n_dims/2)) ? (1:sz[i]) : (randi(sz[i])))) + ind = ntuple(n_dims,i -> ((i <= ceil(n_dims/2)) ? (1:sz[i]) : (rand(1:sz[i])))) n_el = prod(map(length,ind)) n_r = iceil(n_evals/n_el) print(n_dims, " dimensions (", n_r, " repeats, ", n_r*n_el, " operations): ") @time for i = 1:n_r - # ind = ntuple(n_dims,i -> ((i <= n_dims/2) ? (1:sz[i]) : (randi(sz[i])))) + # ind = ntuple(n_dims,i -> ((i <= n_dims/2) ? (1:sz[i]) : (rand(1:sz[i])))) B = A[ind...] end end @@ -51,12 +51,12 @@ if run_ref for n_dims in 1:length(lenbig) sz = ntuple(n_dims,i->lenbig[n_dims]) A = randn(sz) - ind = ntuple(n_dims,i -> ((i <= ceil(n_dims/2)) ? (1:sz[i]) : (randi(sz[i])))) + ind = ntuple(n_dims,i -> ((i <= ceil(n_dims/2)) ? (1:sz[i]) : (rand(1:sz[i])))) n_el = prod(map(length,ind)) n_r = iceil(n_evals/n_el) print(n_dims, " dimensions (", n_r, " repeats, ", n_r*n_el, " operations): ") @time for i = 1:n_r - # ind = ntuple(n_dims,i -> ((i <= n_dims/2) ? (1:sz[i]) : (randi(sz[i])))) + # ind = ntuple(n_dims,i -> ((i <= n_dims/2) ? (1:sz[i]) : (rand(1:sz[i])))) B = A[ind...] end end @@ -67,12 +67,12 @@ if run_ref for n_dims in 1:10 sz = ntuple(n_dims,i->lensmall) A = randn(sz) - ind = ntuple(n_dims,i -> ((i > n_dims/2) ? (1:sz[i]) : (randi(sz[i])))) + ind = ntuple(n_dims,i -> ((i > n_dims/2) ? (1:sz[i]) : (rand(1:sz[i])))) n_el = prod(map(length,ind)) n_r = iceil(n_evals/n_el) print(n_dims, " dimensions (", n_r, " repeats, ", n_r*n_el, " operations): ") @time for i = 1:n_r - # ind = ntuple(n_dims,i -> ((i <= n_dims/2) ? (1:sz[i]) : (randi(sz[i])))) + # ind = ntuple(n_dims,i -> ((i <= n_dims/2) ? (1:sz[i]) : (rand(1:sz[i])))) B = A[ind...] end end @@ -80,12 +80,12 @@ if run_ref for n_dims in 1:length(lenbig) sz = ntuple(n_dims,i->lenbig[n_dims]) A = randn(sz) - ind = ntuple(n_dims,i -> ((i > n_dims/2) ? (1:sz[i]) : (randi(sz[i])))) + ind = ntuple(n_dims,i -> ((i > n_dims/2) ? (1:sz[i]) : (rand(1:sz[i])))) n_el = prod(map(length,ind)) n_r = iceil(n_evals/n_el) print(n_dims, " dimensions (", n_r, " repeats, ", n_r*n_el, " operations): ") @time for i = 1:n_r - # ind = ntuple(n_dims,i -> ((i <= n_dims/2) ? (1:sz[i]) : (randi(sz[i])))) + # ind = ntuple(n_dims,i -> ((i <= n_dims/2) ? (1:sz[i]) : (rand(1:sz[i])))) B = A[ind...] end end @@ -95,7 +95,7 @@ if run_ref println("Random operations:") println("Small arrays:") function randind(len) - i = randi(6) + i = rand(1:6) indchoices = {1:len,1:iceil(len/2),1:iceil(3*len/4),2:2:len,1:iceil(len/2):len,len:-1:1} return indchoices[i] end @@ -159,13 +159,13 @@ if run_assign for n_dims in 1:10 sz = ntuple(n_dims,i->lensmall) B = zeros(sz) - ind = ntuple(n_dims,i -> ((i <= ceil(n_dims/2)) ? (1:sz[i]) : (randi(sz[i])))) + ind = ntuple(n_dims,i -> ((i <= ceil(n_dims/2)) ? (1:sz[i]) : (rand(1:sz[i])))) A = randn(map(length,ind)) n_el = prod(map(length,ind)) n_r = iceil(n_evals/n_el) print(n_dims, " dimensions (", n_r, " repeats, ", n_r*n_el, " operations): ") @time for i = 1:n_r - # ind = ntuple(n_dims,i -> ((i <= n_dims/2) ? (1:sz[i]) : (randi(sz[i])))) + # ind = ntuple(n_dims,i -> ((i <= n_dims/2) ? (1:sz[i]) : (rand(1:sz[i])))) # A = randn(map(length,ind)) B[ind...] = A end @@ -174,13 +174,13 @@ if run_assign for n_dims in 1:length(lenbig) sz = ntuple(n_dims,i->lenbig[n_dims]) B = zeros(sz) - ind = ntuple(n_dims,i -> ((i <= ceil(n_dims/2)) ? (1:sz[i]) : (randi(sz[i])))) + ind = ntuple(n_dims,i -> ((i <= ceil(n_dims/2)) ? (1:sz[i]) : (rand(1:sz[i])))) A = randn(map(length,ind)) n_el = prod(map(length,ind)) n_r = iceil(n_evals/n_el) print(n_dims, " dimensions (", n_r, " repeats, ", n_r*n_el, " operations): ") @time for i = 1:n_r -# ind = ntuple(n_dims,i -> ((i <= n_dims/2) ? (1:sz[i]) : (randi(sz[i])))) +# ind = ntuple(n_dims,i -> ((i <= n_dims/2) ? (1:sz[i]) : (rand(1:sz[i])))) # A = randn(map(length,ind)) B[ind...] = A end @@ -192,13 +192,13 @@ if run_assign for n_dims in 1:10 sz = ntuple(n_dims,i->lensmall) B = zeros(sz) - ind = ntuple(n_dims,i -> ((i > n_dims/2) ? (1:sz[i]) : (randi(sz[i])))) + ind = ntuple(n_dims,i -> ((i > n_dims/2) ? (1:sz[i]) : (rand(1:sz[i])))) A = randn(map(length,ind)) n_el = prod(map(length,ind)) n_r = iceil(n_evals/n_el) print(n_dims, " dimensions (", n_r, " repeats, ", n_r*n_el, " operations): ") @time for i = 1:n_r - # ind = ntuple(n_dims,i -> ((i <= n_dims/2) ? (1:sz[i]) : (randi(sz[i])))) + # ind = ntuple(n_dims,i -> ((i <= n_dims/2) ? (1:sz[i]) : (rand(1:sz[i])))) # A = randn(map(length,ind)) B[ind...] = A end @@ -207,13 +207,13 @@ if run_assign for n_dims in 1:length(lenbig) sz = ntuple(n_dims,i->lenbig[n_dims]) B = zeros(sz) - ind = ntuple(n_dims,i -> ((i > n_dims/2) ? (1:sz[i]) : (randi(sz[i])))) + ind = ntuple(n_dims,i -> ((i > n_dims/2) ? (1:sz[i]) : (rand(1:sz[i])))) A = randn(map(length,ind)) n_el = prod(map(length,ind)) n_r = iceil(n_evals/n_el) print(n_dims, " dimensions (", n_r, " repeats, ", n_r*n_el, " operations): ") @time for i = 1:n_r - # ind = ntuple(n_dims,i -> ((i <= n_dims/2) ? (1:sz[i]) : (randi(sz[i])))) + # ind = ntuple(n_dims,i -> ((i <= n_dims/2) ? (1:sz[i]) : (rand(1:sz[i])))) # A = randn(map(length,ind)) B[ind...] = A end @@ -224,7 +224,7 @@ if run_assign println("Random operations:") println("Small arrays:") function randind(len) - i = randi(6) + i = rand(1:6) indchoices = {1:len,1:iceil(len/2),1:iceil(3*len/4),2:2:len,1:iceil(len/2):len,len:-1:1} return indchoices[i] end diff --git a/test/bigfloat.jl b/test/bigfloat.jl index b986216d00647..d5efd69705a57 100644 --- a/test/bigfloat.jl +++ b/test/bigfloat.jl @@ -1,11 +1,10 @@ -cd("../extras") do -require("bigfloat") +tol = 1e-12 -a=BigFloat("12.34567890121") -b=BigFloat("12.34567890122") +a = BigFloat("12.34567890121") +b = BigFloat("12.34567890122") -@test typeof(a+0.00000000001) == BigFloat -@test abs(a+0.00000000001 - b) < 0.00000000001 +@test typeof(a+1e-11) == BigFloat +@test_approx_eq_eps a+1e-11 b tol @test !(b == a) @test b > a @test b >= a @@ -14,20 +13,69 @@ b=BigFloat("12.34567890122") c = BigFloat("24.69135780242") @test typeof(a * 2) == BigFloat -@test abs(a*2 - c) < 0.00000000001 -@test abs(c-a - a) < 0.00000000001 +@test_approx_eq_eps a*2 c tol +@test_approx_eq_eps (c-a) a tol d = BigFloat("-24.69135780242") @test typeof(d) == BigFloat -@test abs(d + c) < 0.00000000001 +@test_approx_eq_eps d+c 0 tol #Multiple calls for sanity check, since we're doing direct memory manipulation -@test string(a) == "12.34567890121" -@test string(b) == "12.34567890122" -@test string(c) == "24.69135780242" -@test string(d) == "-24.69135780242" +@test string(a) == "1.234567890121e+01" +@test string(b) == "1.234567890122e+01" +@test string(c) == "2.469135780242e+01" +@test string(d) == "-2.469135780242e+01" -@test abs((BigFloat(3)/BigFloat(2)) - BigFloat(1.5)) < 0.00000000001 +@test_approx_eq_eps (BigFloat(3)/BigFloat(2)) BigFloat(1.5) tol -end # cd +@test typeof(BigFloat(typemax(Int8))) == BigFloat +@test typeof(BigFloat(typemax(Int16))) == BigFloat +@test typeof(BigFloat(typemax(Int32))) == BigFloat +@test typeof(BigFloat(typemax(Int64))) == BigFloat +#@test typeof(BigFloat(typemax(Int128))) == BigFloat + +@test typeof(BigFloat(true)) == BigFloat +@test typeof(BigFloat(typemax(Uint8))) == BigFloat +@test typeof(BigFloat(typemax(Uint16))) == BigFloat +@test typeof(BigFloat(typemax(Uint32))) == BigFloat +@test typeof(BigFloat(typemax(Uint64))) == BigFloat +#@test typeof(BigFloat(typemax(Uint128))) == BigFloat + +@test typeof(BigFloat(realmax(Float32))) == BigFloat +@test typeof(BigFloat(realmax(Float64))) == BigFloat + +@test typeof(BigFloat(BigInt(1))) == BigFloat +@test typeof(BigFloat(BigFloat(1))) == BigFloat + +@test typeof(BigFloat(1//1)) == BigFloat +@test typeof(BigFloat(one(Rational{BigInt}))) == BigFloat + +f = BigFloat("1234567890.123") +g = BigFloat("1234567891.123") + +tol = 1e-3 + +@test_approx_eq_eps f+int8(1) g tol +@test_approx_eq_eps f+int16(1) g tol +@test_approx_eq_eps f+int32(1) g tol +@test_approx_eq_eps f+int64(1) g tol +#@test_approx_eq_eps f+int128(1) g tol + +@test_approx_eq_eps f+true g tol +@test_approx_eq_eps f+uint8(1) g tol +@test_approx_eq_eps f+uint16(1) g tol +@test_approx_eq_eps f+uint32(1) g tol +@test_approx_eq_eps f+uint64(1) g tol +#@test_approx_eq_eps f+uint128(1) g tol + +@test_approx_eq_eps f+BigInt(1) g tol + +@test_approx_eq_eps f+1f0 g tol +@test_approx_eq_eps f+1e0 g tol + +@test_approx_eq_eps f+BigFloat(1) g tol + +@test_approx_eq_eps f+(1//1) g tol + +@test_approx_eq_eps f+one(Rational{BigInt}) g tol diff --git a/test/bigint.jl b/test/bigint.jl index ee31524af22e9..f8966d3884cc1 100644 --- a/test/bigint.jl +++ b/test/bigint.jl @@ -1,8 +1,5 @@ -cd("../extras") do -require("bigint") - -a=BigInt("123456789012345678901234567890") -b=BigInt("123456789012345678901234567891") +a = BigInt("123456789012345678901234567890") +b = BigInt("123456789012345678901234567891") @test typeof(a+1) == BigInt @test a+1 == b @@ -24,7 +21,6 @@ d = BigInt("-246913578024691357802469135780") @test typeof(d) == BigInt @test d == -c - ee = typemax(Int64) @test typeof(BigInt(ee)) == BigInt @test BigInt(ee)+1 == BigInt("9223372036854775808") @@ -36,17 +32,89 @@ ee = typemax(Int64) @test string(d) == "-246913578024691357802469135780" @test string(a) == "123456789012345678901234567890" -@test div(BigInt(3), BigInt(2)) == BigInt(1) -@test rem(BigInt(3), BigInt(2)) == BigInt(1) +for i = -10:10, j = [-10:-1,1:10] + @test div(BigInt(i), BigInt(j)) == div(i,j) + @test fld(BigInt(i), BigInt(j)) == fld(i,j) + @test mod(BigInt(i), BigInt(j)) == mod(i,j) + @test rem(BigInt(i), BigInt(j)) == rem(i,j) +end + +@test typeof(BigInt(typemax(Int8))) == BigInt +@test typeof(BigInt(typemax(Int16))) == BigInt +@test typeof(BigInt(typemax(Int32))) == BigInt +@test typeof(BigInt(typemax(Int64))) == BigInt +#@test typeof(BigInt(typemax(Int128))) == BigInt + +@test typeof(BigInt(true)) == BigInt +@test typeof(BigInt(typemax(Uint8))) == BigInt +@test typeof(BigInt(typemax(Uint16))) == BigInt +@test typeof(BigInt(typemax(Uint32))) == BigInt +@test typeof(BigInt(typemax(Uint64))) == BigInt +#@test typeof(BigInt(typemax(Uint128))) == BigInt + +@test typeof(BigInt(BigInt(1))) == BigInt -@test a+int(1) == b @test a+int8(1) == b @test a+int16(1) == b @test a+int32(1) == b @test a+int64(1) == b +#@test a+int128(1) == b + +@test a+true == b +@test a+uint8(1) == b +@test a+uint16(1) == b +@test a+uint32(1) == b +@test a+uint64(1) == b +#@test a+uint128(1) == b + +@test a+BigInt(1) == b + +@test BigInt(5) << 3 == 40 +@test BigInt(5) >> 1 == 2 +@test BigInt(-5) << 3 == -40 +@test BigInt(-5) >> 1 == -3 + +@test ~BigInt(123) == -124 +@test BigInt(123) & BigInt(234) == 106 +@test BigInt(123) | BigInt(234) == 251 +@test BigInt(123) $ BigInt(234) == 145 + +@test gcd(BigInt(48), BigInt(180)) == 12 +@test lcm(BigInt(48), BigInt(180)) == 720 @test factorial(BigInt(40)) == BigInt("815915283247897734345611269596115894272000000000") @test binomial(BigInt(-53), 42) == BigInt("959509335087854414441273718") @test binomial(BigInt(113), BigInt(42)) == BigInt("18672199984318438125634054194360") -end # cd +# Large Fibonacci to exercise BigInt +# from Bill Hart, https://groups.google.com/group/julia-dev/browse_frm/thread/798e2d1322daf633 +function mul(a::Vector{BigInt}, b::Vector{BigInt}) + x = a[2]*b[2] + c = Array(BigInt,3) + c[1] = a[1]*b[1] + x + c[2] = a[1]*b[2] + a[2]*b[3] + c[3] = x + a[3]*b[3] + return c +end + +function bigfib(n) + if n == 0 + BigInt(1) + elseif n == 1 + BigInt(1) + else + r = [BigInt(1), BigInt(1), BigInt(0)] + s = [BigInt(1), BigInt(0), BigInt(1)] + while n != 0 + if (n & 1) == 1 + s = mul(s,r) + end + n >>= 1 + if n != 0 + r = mul(r,r) + end + end + s[1] + end +end +@test length(string(bigfib(1000000))) == 208988 diff --git a/test/bitarray.jl b/test/bitarray.jl index d9df41d3bd9a4..d2ceffe40dacd 100644 --- a/test/bitarray.jl +++ b/test/bitarray.jl @@ -1,13 +1,23 @@ -# for now, manually import necessary bit array functions: -import Base.rotl, Base.rotr, Base.bitzeros, Base.bitones +function tc(r1, r2) + if isa(r1, Tuple) && isa(r2, Tuple) && length(r1) == length(r2) + return all(map(x->tc(x...), [zip(r1,r2)...])) + elseif isa(r1,BitArray) + return isa(r2, Union(BitArray,Array{Bool})) + else + return typeof(r1) == typeof(r2) + end +end + +function check_bitop(func, RetT, args) + r1 = func(args...) + r2 = func(map(x->(isa(x, BitArray) ? bitunpack(x) : x), args)...) + @test isa(r1, RetT) + @test tc(r1, r2) + @test isequal(r1, convert(RetT, r2)) +end macro check_bit_operation(func, RetT, args) - quote - r1 = ($func)($(args.args...)) - r2 = ($func)(map(x->(isa(x, BitArray) ? bitunpack(x) : x), $args)...) - @test isa(r1, $RetT) - @test isequal(r1, convert($RetT, r2)) - end + :(check_bitop($func, $RetT, $args)) end let t0 = time() @@ -20,15 +30,6 @@ let t0 = time() end end -## wrappers for compatibility with old functions ## -bitrand{T}(::Type{T}, dims::Dims) = rand!(BitArray(T, dims)) -bitrand{T}(::Type{T}, dims::Int...) = bitrand(T, dims) -bitrand(dims::Dims) = rand!(BitArray(dims)) -bitrand(dims::Int...) = bitrand(dims) - -TT = Uint8 -SS = promote_type(TT, Int) - # vectors size v1 = 260 # matrices size @@ -42,9 +43,9 @@ s4 = 4 ## Conversions ## -b1 = bitrand(TT, n1, n2) +b1 = randbool(n1, n2) @test isequal(bitpack(bitunpack(b1)), b1) -i1 = randi(2, n1, n2) - 1 +i1 = rand(1:2, n1, n2) - 1 @test isequal(bitunpack(bitpack(i1)), i1) timesofar("conversions") @@ -53,45 +54,52 @@ timesofar("conversions") @check_bit_operation length Int (b1,) @check_bit_operation ndims Int (b1,) -@check_bit_operation numel Int (b1,) @check_bit_operation size (Int...) (b1,) -@test isequal(bitunpack(bitones(TT, n1, n2)), ones(TT, n1, n2)) -@test isequal(bitunpack(bitzeros(TT, n1, n2)), zeros(TT, n1, n2)) +@test isequal(bitunpack(trues(n1, n2)), ones(Bool, n1, n2)) +@test isequal(bitunpack(falses(n1, n2)), zeros(Bool, n1, n2)) -@test isequal(fill!(b1, one(TT)), bitones(TT, size(b1))) -@test isequal(fill!(b1, zero(TT)), bitzeros(TT, size(b1))) +@test isequal(fill!(b1, true), trues(size(b1))) +@test isequal(fill!(b1, false), falses(size(b1))) timesofar("utils") ## Indexing ## -b1 = bitrand(TT, n1, n2) -m1 = randi(n1) -m2 = randi(n2) -b2 = bitrand(TT, m1, m2) -@check_bit_operation copy_to BitArray{TT} (b1, b2) -@check_bit_operation ref BitArray{TT} (b1, 1:m1, m2:n2) -b2 = bitrand(TT, m1, m2) -@check_bit_operation assign BitArray{TT} (b1, b2, 1:m1, n2-m2+1:n2) - -for p1 = [randi(v1) 1 63 64 65 191 192 193] - for p2 = [randi(v1) 1 63 64 65 191 192 193] +b1 = randbool(n1, n2) +m1 = rand(1:n1) +m2 = rand(1:n2) +b2 = randbool(m1, m2) +@check_bit_operation copy! BitMatrix (b1, b2) +@check_bit_operation getindex BitMatrix (b1, 1:m1, m2:n2) +@check_bit_operation getindex BitVector (b1, 1:m1, m2) +@check_bit_operation getindex BitMatrix (b1, 1:m1, [n2,m2,1]) +b2 = randbool(m1, m2) +@check_bit_operation setindex! BitMatrix (b1, b2, 1:m1, n2-m2+1:n2) +k1 = randperm(m1) +k2 = randperm(m2) +@check_bit_operation setindex! BitMatrix (b1, b2, 1:m1, k2) +@check_bit_operation setindex! BitMatrix (b1, b2, k1, k2) +b2 = randbool(m1) +@check_bit_operation setindex! BitMatrix (b1, b2, 1:m1, m2) + +for p1 = [rand(1:v1) 1 63 64 65 191 192 193] + for p2 = [rand(1:v1) 1 63 64 65 191 192 193] for n = 0 : min(v1 - p1 + 1, v1 - p2 + 1) - b1 = bitrand(TT, v1) - b2 = bitrand(TT, v1) - @check_bit_operation copy_to BitArray{TT} (b1, p1, b2, p2, n) + b1 = randbool(v1) + b2 = randbool(v1) + @check_bit_operation copy! BitVector (b1, p1, b2, p2, n) end end end # logical indexing -b1 = bitrand(TT, n1, n2) -t1 = bitrand(Bool, n1, n2) +b1 = randbool(n1, n2) +t1 = randbool(n1, n2) @test isequal(bitunpack(b1[t1]), bitunpack(b1)[t1]) @test isequal(bitunpack(b1[t1]), bitunpack(b1)[bitunpack(t1)]) -t1 = bitrand(Bool, n1) -t2 = bitrand(Bool, n2) +t1 = randbool(n1) +t2 = randbool(n2) @test isequal(bitunpack(b1[t1, t2]), bitunpack(b1)[t1, t2]) @test isequal(bitunpack(b1[t1, t2]), bitunpack(b1)[bitunpack(t1), bitunpack(t2)]) @@ -100,29 +108,29 @@ timesofar("indexing") ## Dequeue functionality ## b1 = BitArray() -i1 = Int[] +i1 = Bool[] for m = 1 : v1 - x = randi(2) - 1 - push(b1, x) - push(i1, x) + x = randbool() + push!(b1, x) + push!(i1, x) @test isequal(bitunpack(b1), i1) end for m1 = 0 : v1 for m2 = [0, 1, 63, 64, 65, 127, 128, 129] - b1 = bitrand(TT, m1) - b2 = bitrand(TT, m2) + b1 = randbool(m1) + b2 = randbool(m2) i1 = bitunpack(b1) i2 = bitunpack(b2) @test isequal(bitunpack(append!(b1, b2)), append!(i1, i2)) end end -b1 = bitrand(TT, v1) +b1 = randbool(v1) i1 = bitunpack(b1) for m = 1 : v1 - jb = pop(b1) - ji = pop(i1) + jb = pop!(b1) + ji = pop!(i1) @test jb == ji @test isequal(bitunpack(b1), i1) end @@ -130,20 +138,20 @@ end b1 = BitArray() -i1 = Int[] +i1 = Bool[] for m = 1 : v1 - x = randi(2) - 1 - enqueue(b1, x) - enqueue(i1, x) + x = randbool() + unshift!(b1, x) + unshift!(i1, x) @test isequal(bitunpack(b1), i1) end -b1 = bitrand(TT, v1) +b1 = randbool(v1) i1 = bitunpack(b1) for m = 1 : v1 - jb = shift(b1) - ji = shift(i1) + jb = shift!(b1) + ji = shift!(i1) @test jb == ji @test isequal(bitunpack(b1), i1) end @@ -152,230 +160,404 @@ end b1 = BitArray() i1 = bitunpack(b1) for m = 1 : v1 - j = randi(m) - x = randi(2) - 1 - insert(b1, j, x) - insert(i1, j, x) + j = rand(1:m) + x = randbool() + insert!(b1, j, x) + insert!(i1, j, x) @test isequal(bitunpack(b1), i1) end -b1 = bitrand(TT, v1) +b1 = randbool(v1) i1 = bitunpack(b1) for j in [63, 64, 65, 127, 128, 129, 191, 192, 193] - x = randi(2) - 1 - insert(b1, j, x) - insert(i1, j, x) + x = rand(1:2) - 1 + insert!(b1, j, x) + insert!(i1, j, x) @test isequal(bitunpack(b1), i1) end -b1 = bitrand(TT, v1) +b1 = randbool(v1) i1 = bitunpack(b1) for m = v1 : -1 : 1 - j = randi(m) - del(b1, j) - del(i1, j) + j = rand(1:m) + delete!(b1, j) + delete!(i1, j) @test isequal(bitunpack(b1), i1) end @test length(b1) == 0 -b1 = bitrand(TT, v1) +b1 = randbool(v1) i1 = bitunpack(b1) for j in [63, 64, 65, 127, 128, 129, 191, 192, 193] - del(b1, j) - del(i1, j) + delete!(b1, j) + delete!(i1, j) @test isequal(bitunpack(b1), i1) end -b1 = bitrand(TT, v1) +b1 = randbool(v1) i1 = bitunpack(b1) for m1 = 1 : v1 for m2 = m1 : v1 b2 = copy(b1) i2 = copy(i1) - del(b2, m1:m2) - del(i2, m1:m2) + delete!(b2, m1:m2) + delete!(i2, m1:m2) @test isequal(bitunpack(b2), i2) end end -b1 = bitrand(TT, v1) +b1 = randbool(v1) i1 = bitunpack(b1) -del_all(b1) -del_all(i1) +empty!(b1) +empty!(i1) @test isequal(bitunpack(b1), i1) timesofar("dequeue") ## Unary operators ## -b1 = bitrand(TT, n1, n2) -@check_bit_operation (~) Array{TT} (b1,) -@check_bit_operation (-) Array{TT} (b1,) -@check_bit_operation sign BitArray{TT} (b1,) -@check_bit_operation real BitArray{TT} (b1,) -@check_bit_operation imag BitArray{TT} (b1,) -@check_bit_operation conj BitArray{TT} (b1,) - -b1 = bitrand(Bool, n1, n2) -@check_bit_operation (~) BitArray{Bool} (b1,) -@check_bit_operation (!) BitArray{Bool} (b1,) -@check_bit_operation (-) BitArray{Bool} (b1,) -@check_bit_operation sign BitArray{Int} (b1,) +b1 = randbool(n1, n2) +@check_bit_operation (~) BitMatrix (b1,) +@check_bit_operation (!) BitMatrix (b1,) +@check_bit_operation (-) Matrix{Int} (b1,) +@check_bit_operation sign BitMatrix (b1,) +@check_bit_operation real BitMatrix (b1,) +@check_bit_operation imag BitMatrix (b1,) +@check_bit_operation conj BitMatrix (b1,) b0 = falses(0) -@check_bit_operation (~) BitArray{Bool} (b0,) -@check_bit_operation (!) BitArray{Bool} (b0,) -@check_bit_operation (-) BitArray{Bool} (b0,) -@check_bit_operation sign BitArray{Int} (b0,) +@check_bit_operation (~) BitVector (b0,) +@check_bit_operation (!) BitVector (b0,) +@check_bit_operation (-) Vector{Int} (b0,) +@check_bit_operation sign BitVector (b0,) timesofar("unary arithmetic") ## Binary arithmetic operators ## -b1 = bitrand(TT, n1, n2) -b2 = bitrand(TT, n1, n2) -@check_bit_operation (&) BitArray{TT} (b1, b2) -@check_bit_operation (|) BitArray{TT} (b1, b2) -@check_bit_operation ($) BitArray{TT} (b1, b2) -@check_bit_operation (-) Array{TT} (b1, b2) -@check_bit_operation (.*) BitArray{TT} (b1, b2) -@check_bit_operation (./) Array{Float64} (b1, b2) -@check_bit_operation (.^) Array{Float64} (b1, b2) +# Matrix{Bool}/Matrix{Bool} -b2 = bitones(TT, n1, n2) -@check_bit_operation div Array{TT} (b1, b2) -@check_bit_operation mod Array{TT} (b1, b2) +b1 = randbool(n1, n2) +b2 = randbool(n1, n2) +@check_bit_operation (&) BitMatrix (b1, b2) +@check_bit_operation (|) BitMatrix (b1, b2) +@check_bit_operation ($) BitMatrix (b1, b2) +@check_bit_operation (+) Matrix{Int} (b1, b2) +@check_bit_operation (-) Matrix{Int} (b1, b2) +@check_bit_operation (.*) BitMatrix (b1, b2) +@check_bit_operation (./) Matrix{Float64} (b1, b2) +@check_bit_operation (.^) BitMatrix (b1, b2) -while true - global b1 - b1 = bitrand(TT, n1, n1) - if abs(det(float64(b1))) > 1e-6 - break - end -end -b2 = bitrand(TT, n1, n1) - -@check_bit_operation (*) Array{TT} (b1, b2) -@check_bit_operation (/) Array{Float64} (b1, b1) -@check_bit_operation (\) Array{Float64} (b1, b1) - -b1 = bitrand(TT, n1, n2) -b2 = randi(10, n1, n2) -@check_bit_operation (&) Array{SS} (b1, b2) -@check_bit_operation (|) Array{SS} (b1, b2) -@check_bit_operation ($) Array{SS} (b1, b2) -@check_bit_operation (-) Array{SS} (b1, b2) -@check_bit_operation (.*) Array{SS} (b1, b2) -@check_bit_operation (./) Array{Float64} (b1, b2) -@check_bit_operation (.^) Array{Float64} (b1, b2) -@check_bit_operation div Array{SS} (b1, b2) -@check_bit_operation mod Array{SS} (b1, b2) +b2 = trues(n1, n2) +@check_bit_operation div BitMatrix (b1, b2) +@check_bit_operation mod BitMatrix (b1, b2) while true global b1 - b1 = bitrand(TT, n1, n1) + b1 = randbool(n1, n1) if abs(det(float64(b1))) > 1e-6 break end end -b2 = bitunpack(b1) -@check_bit_operation (*) Array{TT} (b1, b2) -@check_bit_operation (/) Array{Float64} (b1, b2) -@check_bit_operation (\) Array{Float64} (b1, b2) - -b1 = bitrand(Bool, n1, n2) -b2 = bitrand(Bool, n1, n2) -@check_bit_operation (&) BitArray{Bool} (b1, b2) -@check_bit_operation (|) BitArray{Bool} (b1, b2) -@check_bit_operation ($) BitArray{Bool} (b1, b2) -@check_bit_operation (.*) BitArray{Bool} (b1, b2) -@check_bit_operation (*) BitArray{Bool} (b1, b1') +b2 = randbool(n1, n1) + +@check_bit_operation (*) BitMatrix (b1, b2) +@check_bit_operation (/) Matrix{Float64} (b1, b1) +@check_bit_operation (\) Matrix{Float64} (b1, b1) b0 = falses(0) -@check_bit_operation (&) BitArray{Bool} (b0, b0) -@check_bit_operation (|) BitArray{Bool} (b0, b0) -@check_bit_operation ($) BitArray{Bool} (b0, b0) -@check_bit_operation (.*) BitArray{Bool} (b0, b0) -@check_bit_operation (*) BitArray{Bool} (b0, b0') +@check_bit_operation (&) BitVector (b0, b0) +@check_bit_operation (|) BitVector (b0, b0) +@check_bit_operation ($) BitVector (b0, b0) +@check_bit_operation (.*) BitVector (b0, b0) +@check_bit_operation (*) BitMatrix (b0, b0') + +# Matrix{Bool}/Matrix{Int} +b1 = randbool(n1, n2) +i2 = rand(1:10, n1, n2) +@check_bit_operation (&) Matrix{Int} (b1, i2) +@check_bit_operation (|) Matrix{Int} (b1, i2) +@check_bit_operation ($) Matrix{Int} (b1, i2) +@check_bit_operation (+) Matrix{Int} (b1, i2) +@check_bit_operation (-) Matrix{Int} (b1, i2) +@check_bit_operation (.*) Matrix{Int} (b1, i2) +@check_bit_operation (./) Matrix{Float64} (b1, i2) +@check_bit_operation (.^) BitMatrix (b1, i2) +@check_bit_operation div Matrix{Int} (b1, i2) +@check_bit_operation mod Matrix{Int} (b1, i2) + +# Matrix{Bool}/Matrix{Float64} +b1 = randbool(n1, n2) +f2 = 1.0 + rand(n1, n2) +@check_bit_operation (.*) Matrix{Float64} (b1, f2) +@check_bit_operation (./) Matrix{Float64} (b1, f2) +@check_bit_operation (.^) Matrix{Float64} (b1, f2) +@check_bit_operation div Matrix{Float64} (b1, f2) +@check_bit_operation mod Matrix{Float64} (b1, f2) + +# Number/Matrix +b2 = randbool(n1, n2) +i1 = rand(1:10) +u1 = uint8(i1) +f1 = float64(i1) +ci1 = complex(i1) +cu1 = complex(u1) +cf1 = complex(f1) + +@check_bit_operation (&) Matrix{Int} (i1, b2) +@check_bit_operation (|) Matrix{Int} (i1, b2) +@check_bit_operation ($) Matrix{Int} (i1, b2) +@check_bit_operation (+) Matrix{Int} (i1, b2) +@check_bit_operation (-) Matrix{Int} (i1, b2) +@check_bit_operation (.*) Matrix{Int} (i1, b2) + +@check_bit_operation (&) Matrix{Uint8} (u1, b2) +@check_bit_operation (|) Matrix{Uint8} (u1, b2) +@check_bit_operation ($) Matrix{Uint8} (u1, b2) +@check_bit_operation (+) Matrix{Uint8} (u1, b2) +@check_bit_operation (-) Matrix{Uint8} (u1, b2) +@check_bit_operation (.*) Matrix{Uint8} (u1, b2) + +for (x1,t1) = {(f1, Float64), + (ci1, ComplexPair{Int}), + (cu1, ComplexPair{Uint8}), + (cf1, Complex128)} + @check_bit_operation (+) Matrix{t1} (x1, b2) + @check_bit_operation (-) Matrix{t1} (x1, b2) + @check_bit_operation (.*) Matrix{t1} (x1, b2) +end + +b2 = trues(n1, n2) +@check_bit_operation (./) Matrix{Float64} (true, b2) +@check_bit_operation div BitMatrix (true, b2) +@check_bit_operation mod BitMatrix (true, b2) +@check_bit_operation (./) Matrix{Float64} (false, b2) +@check_bit_operation div BitMatrix (false, b2) +@check_bit_operation mod BitMatrix (false, b2) + +@check_bit_operation (./) Matrix{Float64} (i1, b2) +@check_bit_operation div Matrix{Int} (i1, b2) +@check_bit_operation mod Matrix{Int} (i1, b2) + +@check_bit_operation (./) Matrix{Float32} (u1, b2) +@check_bit_operation div Matrix{Uint8} (u1, b2) +@check_bit_operation mod Matrix{Uint8} (u1, b2) + +@check_bit_operation (./) Matrix{Float64} (f1, b2) +@check_bit_operation div Matrix{Float64} (f1, b2) +@check_bit_operation mod Matrix{Float64} (f1, b2) + +@check_bit_operation (./) Matrix{Complex128} (ci1, b2) +@check_bit_operation (./) Matrix{Complex64 } (cu1, b2) +@check_bit_operation (./) Matrix{Complex128} (cf1, b2) + +b2 = randbool(n1, n2) +@check_bit_operation (.^) BitMatrix (false, b2) +@check_bit_operation (.^) BitMatrix (true, b2) +@check_bit_operation (.^) Matrix{Uint8} (0x0, b2) +@check_bit_operation (.^) Matrix{Uint8} (0x1, b2) +@check_bit_operation (.^) Matrix{Int} (-1, b2) +@check_bit_operation (.^) Matrix{Int} (0, b2) +@check_bit_operation (.^) Matrix{Int} (1, b2) +@check_bit_operation (.^) Matrix{Float64} (0.0, b2) +@check_bit_operation (.^) Matrix{Float64} (1.0, b2) +@check_bit_operation (.^) Matrix{Complex128} (0.0im, b2) +@check_bit_operation (.^) Matrix{Complex128} (1.0im, b2) +@check_bit_operation (.^) Matrix{ComplexPair{Int}} (0im, b2) +@check_bit_operation (.^) Matrix{ComplexPair{Int}} (1im, b2) +@check_bit_operation (.^) Matrix{ComplexPair{Uint}} (0x0im, b2) +@check_bit_operation (.^) Matrix{ComplexPair{Uint}} (0x1im, b2) + +# Matrix/Number +b1 = randbool(n1, n2) +i2 = rand(1:10) +u2 = uint8(i2) +f2 = float64(i2) +ci2 = complex(i2) +cu2 = complex(u2) +cf2 = complex(f2) + +@check_bit_operation (&) BitMatrix (b1, true) +@check_bit_operation (&) BitMatrix (b1, false) +@check_bit_operation (|) BitMatrix (b1, true) +@check_bit_operation (|) BitMatrix (b1, false) +@check_bit_operation ($) BitMatrix (b1, true) +@check_bit_operation ($) BitMatrix (b1, false) +@check_bit_operation (+) Matrix{Int} (b1, true) +@check_bit_operation (+) Matrix{Int} (b1, false) +@check_bit_operation (-) Matrix{Int} (b1, true) +@check_bit_operation (-) Matrix{Int} (b1, false) +@check_bit_operation (.*) BitMatrix (b1, true) +@check_bit_operation (.*) BitMatrix (b1, false) +@check_bit_operation (./) Matrix{Float64} (b1, true) +@check_bit_operation (./) Matrix{Float64} (b1, false) +@check_bit_operation div BitMatrix (b1, true) +@check_bit_operation mod BitMatrix (b1, true) + +@check_bit_operation (&) Matrix{Int} (b1, i2) +@check_bit_operation (|) Matrix{Int} (b1, i2) +@check_bit_operation ($) Matrix{Int} (b1, i2) +@check_bit_operation (+) Matrix{Int} (b1, i2) +@check_bit_operation (-) Matrix{Int} (b1, i2) +@check_bit_operation (.*) Matrix{Int} (b1, i2) +@check_bit_operation (./) Matrix{Float64} (b1, i2) +@check_bit_operation div Matrix{Int} (b1, i2) +@check_bit_operation mod Matrix{Int} (b1, i2) + +@check_bit_operation (&) Matrix{Uint8} (b1, u2) +@check_bit_operation (|) Matrix{Uint8} (b1, u2) +@check_bit_operation ($) Matrix{Uint8} (b1, u2) +@check_bit_operation (+) Matrix{Uint8} (b1, u2) +@check_bit_operation (-) Matrix{Uint8} (b1, u2) +@check_bit_operation (.*) Matrix{Uint8} (b1, u2) +@check_bit_operation (./) Matrix{Float32} (b1, u2) +@check_bit_operation div Matrix{Uint8} (b1, u2) +@check_bit_operation mod Matrix{Uint8} (b1, u2) + +@check_bit_operation (+) Matrix{Float64} (b1, f2) +@check_bit_operation (-) Matrix{Float64} (b1, f2) +@check_bit_operation (.*) Matrix{Float64} (b1, f2) +@check_bit_operation (./) Matrix{Float64} (b1, f2) +@check_bit_operation div Matrix{Float64} (b1, f2) +@check_bit_operation mod Matrix{Float64} (b1, f2) + +@check_bit_operation (+) Matrix{ComplexPair{Int}} (b1, ci2) +@check_bit_operation (-) Matrix{ComplexPair{Int}} (b1, ci2) +@check_bit_operation (.*) Matrix{ComplexPair{Int}} (b1, ci2) +@check_bit_operation (./) Matrix{Complex128} (b1, ci2) + +@check_bit_operation (+) Matrix{ComplexPair{Uint8}} (b1, cu2) +@check_bit_operation (-) Matrix{ComplexPair{Uint8}} (b1, cu2) +@check_bit_operation (.*) Matrix{ComplexPair{Uint8}} (b1, cu2) +@check_bit_operation (./) Matrix{Complex64} (b1, cu2) + +@check_bit_operation (+) Matrix{Complex128} (b1, cf2) +@check_bit_operation (-) Matrix{Complex128} (b1, cf2) +@check_bit_operation (.*) Matrix{Complex128} (b1, cf2) +@check_bit_operation (./) Matrix{Complex128} (b1, cf2) + +@check_bit_operation (.^) BitMatrix (b1, false) +@check_bit_operation (.^) BitMatrix (b1, true) +@check_bit_operation (.^) BitMatrix (b1, 0x0) +@check_bit_operation (.^) BitMatrix (b1, 0x1) +@check_bit_operation (.^) BitMatrix (b1, 0) +@check_bit_operation (.^) BitMatrix (b1, 1) +@check_bit_operation (.^) Matrix{Float64} (b1, -1.0) +@check_bit_operation (.^) Matrix{Float64} (b1, 0.0) +@check_bit_operation (.^) Matrix{Float64} (b1, 1.0) +@check_bit_operation (.^) Matrix{Complex128} (b1, 0.0im) +@check_bit_operation (.^) Matrix{Complex64 } (b1, 0x0im) +@check_bit_operation (.^) Matrix{Complex128} (b1, 0im) + +b1 = trues(n1, n2) +@check_bit_operation (.^) Matrix{Complex128} (b1, -1.0im) +@check_bit_operation (.^) Matrix{Complex128} (b1, 1.0im) +@check_bit_operation (.^) Matrix{Complex128} (b1, -1im) +@check_bit_operation (.^) Matrix{Complex128} (b1, 1im) +@check_bit_operation (.^) Matrix{Complex64 } (b1, 0x1im) timesofar("binary arithmetic") ## Binary comparison operators ## -b1 = bitrand(TT, n1, n2) -b2 = bitrand(TT, n1, n2) -@check_bit_operation (.==) BitArray{Bool} (b1, b2) -@check_bit_operation (.!=) BitArray{Bool} (b1, b2) -@check_bit_operation (.<) BitArray{Bool} (b1, b2) -@check_bit_operation (.<=) BitArray{Bool} (b1, b2) +b1 = randbool(n1, n2) +b2 = randbool(n1, n2) +@check_bit_operation (.==) BitMatrix (b1, b2) +@check_bit_operation (.!=) BitMatrix (b1, b2) +@check_bit_operation (.<) BitMatrix (b1, b2) +@check_bit_operation (.<=) BitMatrix (b1, b2) timesofar("binary comparison") ## Data movement ## -b1 = bitrand(TT, s1, s2, s3, s4) +b1 = randbool(s1, s2, s3, s4) for d = 1 : 4 - j = randi(size(b1, d)) + j = rand(1:size(b1, d)) #for j = 1 : size(b1, d) - @check_bit_operation slicedim BitArray{TT} (b1, d, j) + @check_bit_operation slicedim BitArray{4} (b1, d, j) #end - @check_bit_operation flipdim BitArray{TT} (b1, d) + @check_bit_operation flipdim BitArray{4} (b1, d) end -b1 = bitrand(TT, n1, n2) +b1 = randbool(n1, n2) for k = 1 : 4 - @check_bit_operation rotl90 BitArray{TT} (b1, k) + @check_bit_operation rotl90 BitMatrix (b1, k) end for m = 0 : v1 - b1 = bitrand(TT, m) - @check_bit_operation reverse BitArray{TT} (b1,) + b1 = randbool(m) + @check_bit_operation reverse BitVector (b1,) end -b1 = bitrand(TT, v1) -for m = [randi(v1)-1 0 1 63 64 65 191 192 193 v1-1] - @test isequal(b1 << m, [ b1[m+1:end]; bitzeros(TT, m) ]) - @test isequal(b1 >>> m, [ bitzeros(TT, m); b1[1:end-m] ]) - @test isequal(rotl(b1, m), [ b1[m+1:end]; b1[1:m] ]) - @test isequal(rotr(b1, m), [ b1[end-m+1:end]; b1[1:end-m] ]) +b1 = randbool(v1) +for m = [rand(1:v1)-1 0 1 63 64 65 191 192 193 v1-1] + @test isequal(b1 << m, [ b1[m+1:end]; falses(m) ]) + @test isequal(b1 >>> m, [ falses(m); b1[1:end-m] ]) + @test isequal(rol(b1, m), [ b1[m+1:end]; b1[1:m] ]) + @test isequal(ror(b1, m), [ b1[end-m+1:end]; b1[1:end-m] ]) end timesofar("datamove") ## nnz & find ## -b1 = bitrand(TT, v1) +b1 = randbool(v1) @check_bit_operation nnz Int (b1,) @check_bit_operation findfirst Int (b1,) -@check_bit_operation findfirst Int (bitones(TT, v1),) -@check_bit_operation findfirst Int (bitzeros(TT, v1),) +@check_bit_operation findfirst Int (trues(v1),) +@check_bit_operation findfirst Int (falses(v1),) -@check_bit_operation findfirst Int (b1, one(TT)) -@check_bit_operation findfirst Int (b1, zero(TT)) +@check_bit_operation findfirst Int (b1, true) +@check_bit_operation findfirst Int (b1, false) @check_bit_operation findfirst Int (b1, 3) -@check_bit_operation findfirst Int (x->bool(x), b1) -@check_bit_operation findfirst Int (x->!bool(x), b1) +@check_bit_operation findfirst Int (x->x, b1) +@check_bit_operation findfirst Int (x->!x, b1) @check_bit_operation findfirst Int (x->true, b1) @check_bit_operation findfirst Int (x->false, b1) -@check_bit_operation find Array{Int} (b1,) +@check_bit_operation find Vector{Int} (b1,) + +b1 = trues(v1) +for i = 0:v1-1 + @test findfirst(b1 >> i) == i+1 + @test Base.findfirstnot(~(b1 >> i)) == i+1 +end + +for i = 3:v1-1 + for j = 2:i + submask = b1 << (v1-j+1) + @test findnext((b1 >> i) | submask,j) == i+1 + @test Base.findnextnot((~(b1 >> i)) $ submask,j) == i+1 + end +end -b1 = bitrand(TT, n1, n2) -@check_bit_operation findn_nzs (Array{Int}, Array{Int}, BitArray{TT}) (b1,) +b1 = randbool(n1, n2) +@check_bit_operation findnz (Vector{Int}, Vector{Int}, BitArray) (b1,) timesofar("nnz&find") ## Reductions ## -b1 = bitrand(TT, s1, s2, s3, s4) -m1 = randi(s1) -m2 = randi(s3) -@check_bit_operation max BitArray{TT} (b1, (), (m1, m2)) -@check_bit_operation min BitArray{TT} (b1, (), (m1, m2)) -@check_bit_operation sum Array{Int} (b1, (m1, m2)) -@check_bit_operation prod BitArray{TT} (b1, (m1, m2)) +b1 = randbool(s1, s2, s3, s4) +m1 = 1 +m2 = 3 +@check_bit_operation max BitArray{4} (b1, (), (m1, m2)) +@check_bit_operation min BitArray{4} (b1, (), (m1, m2)) +@check_bit_operation sum Array{Int,4} (b1, (m1, m2)) + +@check_bit_operation max Bool (b1,) +@check_bit_operation min Bool (b1,) +@check_bit_operation any Bool (b1,) +@check_bit_operation all Bool (b1,) +@check_bit_operation sum Int (b1,) + +b0 = falses(0) +@check_bit_operation any Bool (b0,) +@check_bit_operation all Bool (b0,) +@check_bit_operation sum Int (b0,) timesofar("reductions") @@ -389,58 +571,55 @@ timesofar("reductions") ## Transpose ## -b1 = bitrand(TT, v1) -@check_bit_operation transpose BitArray{TT} (b1,) +b1 = randbool(v1) +@check_bit_operation transpose BitMatrix (b1,) for m1 = 0 : n1 for m2 = 0 : n2 - b1 = bitrand(TT, m1, m2) - @check_bit_operation transpose BitArray{TT} (b1,) + b1 = randbool(m1, m2) + @check_bit_operation transpose BitMatrix (b1,) end end timesofar("transpose") -## Permute ## +## Permutedims ## -b1 = bitrand(TT, s1, s2, s3, s4) +b1 = randbool(s1, s2, s3, s4) p = randperm(4) -@check_bit_operation permute BitArray{TT} (b1, p) +@check_bit_operation permutedims BitArray{4} (b1, p) -timesofar("permute") +timesofar("permutedims") ## Concatenation ## -b1 = bitrand(TT, v1) -b2 = bitrand(TT, v1) -@check_bit_operation hcat BitArray{TT} (b1, b2) +b1 = randbool(v1) +b2 = randbool(v1) +@check_bit_operation hcat BitMatrix (b1, b2) for m = 1 : v1 - 1 - @check_bit_operation vcat BitArray{TT} (b1[1:m], b1[m+1:end]) + @check_bit_operation vcat BitVector (b1[1:m], b1[m+1:end]) end -b1 = bitrand(TT, n1, n2) -b2 = bitrand(TT, n1) -b3 = bitrand(TT, n1, n2) -b4 = bitrand(TT, 1, n2) -@check_bit_operation hcat BitArray{TT} (b1, b2, b3) -@check_bit_operation vcat BitArray{TT} (b1, b4, b3) - -b1 = bitrand(TT, s1, s2, s3, s4) -b2 = bitrand(TT, s1, s3, s3, s4) -b3 = bitrand(TT, s1, s2, s3, s1) -@check_bit_operation cat BitArray{TT} (2, b1, b2) -@check_bit_operation cat BitArray{TT} (4, b1, b3) -@check_bit_operation cat BitArray{TT} (6, b1, b1) - -b1 = bitrand(TT, 1, v1, 1) -@check_bit_operation cat Array{SS} (2, 0, b1, 1, 1, b1) -@check_bit_operation cat Array{SS} (2, 3, b1, 4, 5, b1) - -b1 = bitrand(Bool, 1, v1, 1) -@check_bit_operation cat BitArray{Bool} (2, false, b1, true, true, b1) -@check_bit_operation cat Array{Int} (2, 3, b1, 4, 5, b1) - -b1 = bitrand(TT, n1, n2) +b1 = randbool(n1, n2) +b2 = randbool(n1) +b3 = randbool(n1, n2) +b4 = randbool(1, n2) +@check_bit_operation hcat BitMatrix (b1, b2, b3) +@check_bit_operation vcat BitMatrix (b1, b4, b3) + +b1 = randbool(s1, s2, s3, s4) +b2 = randbool(s1, s3, s3, s4) +b3 = randbool(s1, s2, s3, s1) +@check_bit_operation cat BitArray{4} (2, b1, b2) +@check_bit_operation cat BitArray{4} (4, b1, b3) +@check_bit_operation cat BitArray{6} (6, b1, b1) + +b1 = randbool(1, v1, 1) +@check_bit_operation cat Array{Int,3} (2, 0, b1, 1, 1, b1) +@check_bit_operation cat Array{Int,3} (2, 3, b1, 4, 5, b1) +@check_bit_operation cat BitArray{3} (2, false, b1, true, true, b1) + +b1 = randbool(n1, n2) for m1 = 1 : n1 - 1 for m2 = 1 : n2 - 1 @test isequal([b1[1:m1,1:m2] b1[1:m1,m2+1:end]; b1[m1+1:end,1:m2] b1[m1+1:end,m2+1:end]], b1) @@ -451,21 +630,19 @@ timesofar("cat") # Linear algebra -b1 = bitrand(TT, v1) -b2 = bitrand(TT, v1) -@check_bit_operation dot typeof(one(TT) * one(TT)) (b1, b2) -b2 = bitrand(Bool, v1) -@check_bit_operation dot typeof(one(TT) * true) (b1, b2) +b1 = randbool(v1) +b2 = randbool(v1) +@check_bit_operation dot Int (b1, b2) -b1 = bitrand(TT, n1, n2) +b1 = randbool(n1, n2) for k = -max(n1,n2) : max(n1,n2) - @check_bit_operation tril BitArray{TT} (b1, k) - @check_bit_operation triu BitArray{TT} (b1, k) + @check_bit_operation tril BitMatrix (b1, k) + @check_bit_operation triu BitMatrix (b1, k) end -#b1 = bitrand(TT, v1) -#@check_bit_operation diff Array{SS} (b1,) -#b1 = bitrand(TT, n1, n2) -#@check_bit_operation diff Array{SS} (b1,) +#b1 = randbool(v1) +#@check_bit_operation diff Vector{Int} (b1,) +#b1 = randbool(n1, n2) +#@check_bit_operation diff Vector{Int} (b1,) timesofar("linalg") diff --git a/test/blas.jl b/test/blas.jl new file mode 100644 index 0000000000000..c4aa8e97ececa --- /dev/null +++ b/test/blas.jl @@ -0,0 +1,78 @@ +## BLAS tests - testing the interface code to BLAS routines +for elty in (Float32, Float64, Complex64, Complex128) + + o4 = ones(elty, 4) + z4 = zeros(elty, 4) + + I4 = eye(elty, 4) + L4 = tril(ones(elty, (4,4))) + U4 = triu(ones(elty, (4,4))) + Z4 = zeros(elty, (4,4)) + + elm1 = convert(elty, -1) + el2 = convert(elty, 2) + v14 = convert(Vector{elty}, [1:4]) + v41 = convert(Vector{elty}, [4:-1:1]) + # gemv + @assert all(LinAlg.BLAS.gemv('N', I4, o4) .== o4) + @assert all(LinAlg.BLAS.gemv('T', I4, o4) .== o4) + @assert all(LinAlg.BLAS.gemv('N', el2, I4, o4) .== el2 * o4) + @assert all(LinAlg.BLAS.gemv('T', el2, I4, o4) .== el2 * o4) + o4cp = copy(o4) + @assert all(LinAlg.BLAS.gemv!('N', one(elty), I4, o4, elm1, o4cp) .== z4) + @assert all(o4cp .== z4) + o4cp[:] = o4 + @assert all(LinAlg.BLAS.gemv!('T', one(elty), I4, o4, elm1, o4cp) .== z4) + @assert all(o4cp .== z4) + @assert all(LinAlg.BLAS.gemv('N', U4, o4) .== v41) + @assert all(LinAlg.BLAS.gemv('N', U4, o4) .== v41) + # gemm + @assert all(LinAlg.BLAS.gemm('N', 'N', I4, I4) .== I4) + @assert all(LinAlg.BLAS.gemm('N', 'T', I4, I4) .== I4) + @assert all(LinAlg.BLAS.gemm('T', 'N', I4, I4) .== I4) + @assert all(LinAlg.BLAS.gemm('T', 'T', I4, I4) .== I4) + @assert all(LinAlg.BLAS.gemm('N', 'N', el2, I4, I4) .== el2 * I4) + @assert all(LinAlg.BLAS.gemm('N', 'T', el2, I4, I4) .== el2 * I4) + @assert all(LinAlg.BLAS.gemm('T', 'N', el2, I4, I4) .== el2 * I4) + @assert all(LinAlg.BLAS.gemm('T', 'T', el2, I4, I4) .== el2 * I4) + I4cp = copy(I4) + @assert all(LinAlg.BLAS.gemm!('N', 'N', one(elty), I4, I4, elm1, I4cp) .== Z4) + @assert all(I4cp .== Z4) + I4cp[:] = I4 + @assert all(LinAlg.BLAS.gemm!('N', 'T', one(elty), I4, I4, elm1, I4cp) .== Z4) + @assert all(I4cp .== Z4) + I4cp[:] = I4 + @assert all(LinAlg.BLAS.gemm!('T', 'N', one(elty), I4, I4, elm1, I4cp) .== Z4) + @assert all(I4cp .== Z4) + I4cp[:] = I4 + @assert all(LinAlg.BLAS.gemm!('T', 'T', one(elty), I4, I4, elm1, I4cp) .== Z4) + @assert all(I4cp .== Z4) + @assert all(LinAlg.BLAS.gemm('N', 'N', I4, U4) .== U4) + @assert all(LinAlg.BLAS.gemm('N', 'T', I4, U4) .== L4) + # gemm compared to (sy)(he)rk + if iscomplex(elm1) + @assert all(triu(LinAlg.BLAS.herk('U', 'N', U4)) .== triu(LinAlg.BLAS.gemm('N', 'T', U4, U4))) + @assert all(tril(LinAlg.BLAS.herk('L', 'N', U4)) .== tril(LinAlg.BLAS.gemm('N', 'T', U4, U4))) + @assert all(triu(LinAlg.BLAS.herk('U', 'N', L4)) .== triu(LinAlg.BLAS.gemm('N', 'T', L4, L4))) + @assert all(tril(LinAlg.BLAS.herk('L', 'N', L4)) .== tril(LinAlg.BLAS.gemm('N', 'T', L4, L4))) + @assert all(triu(LinAlg.BLAS.herk('U', 'C', U4)) .== triu(LinAlg.BLAS.gemm('T', 'N', U4, U4))) + @assert all(tril(LinAlg.BLAS.herk('L', 'C', U4)) .== tril(LinAlg.BLAS.gemm('T', 'N', U4, U4))) + @assert all(triu(LinAlg.BLAS.herk('U', 'C', L4)) .== triu(LinAlg.BLAS.gemm('T', 'N', L4, L4))) + @assert all(tril(LinAlg.BLAS.herk('L', 'C', L4)) .== tril(LinAlg.BLAS.gemm('T', 'N', L4, L4))) + ans = similar(L4) + @assert all(tril(LinAlg.BLAS.herk('L','C', L4)) .== tril(LinAlg.BLAS.herk!('L', 'C', one(elty), L4, zero(elty), ans))) + @assert all(symmetrize!(ans, 'L') .== LinAlg.BLAS.gemm('T', 'N', L4, L4)) + else + @assert all(triu(LinAlg.BLAS.syrk('U', 'N', U4)) .== triu(LinAlg.BLAS.gemm('N', 'T', U4, U4))) + @assert all(tril(LinAlg.BLAS.syrk('L', 'N', U4)) .== tril(LinAlg.BLAS.gemm('N', 'T', U4, U4))) + @assert all(triu(LinAlg.BLAS.syrk('U', 'N', L4)) .== triu(LinAlg.BLAS.gemm('N', 'T', L4, L4))) + @assert all(tril(LinAlg.BLAS.syrk('L', 'N', L4)) .== tril(LinAlg.BLAS.gemm('N', 'T', L4, L4))) + @assert all(triu(LinAlg.BLAS.syrk('U', 'T', U4)) .== triu(LinAlg.BLAS.gemm('T', 'N', U4, U4))) + @assert all(tril(LinAlg.BLAS.syrk('L', 'T', U4)) .== tril(LinAlg.BLAS.gemm('T', 'N', U4, U4))) + @assert all(triu(LinAlg.BLAS.syrk('U', 'T', L4)) .== triu(LinAlg.BLAS.gemm('T', 'N', L4, L4))) + @assert all(tril(LinAlg.BLAS.syrk('L', 'T', L4)) .== tril(LinAlg.BLAS.gemm('T', 'N', L4, L4))) + ans = similar(L4) + @assert all(tril(LinAlg.BLAS.syrk('L','T', L4)) .== tril(LinAlg.BLAS.syrk!('L', 'T', one(elty), L4, zero(elty), ans))) + @assert all(symmetrize!(ans, 'L') .== LinAlg.BLAS.gemm('T', 'N', L4, L4)) + end +end diff --git a/test/ccall.jl b/test/ccall.jl new file mode 100644 index 0000000000000..49351a5a6b4aa --- /dev/null +++ b/test/ccall.jl @@ -0,0 +1,3 @@ +ccall_test_func(x) = ccall((:testUcharX, "./libccalltest"), Int32, (Uint8,), x) +@assert ccall_test_func(3) == 1 +@assert ccall_test_func(259) == 1 diff --git a/test/ccalltest.c b/test/ccalltest.c new file mode 100644 index 0000000000000..dedd7b4827c64 --- /dev/null +++ b/test/ccalltest.c @@ -0,0 +1,24 @@ +#include + +int xs[300] = {0,0,0,1,0}; + +int __attribute((noinline)) testUcharX(unsigned char x) { + return xs[x]; +} + +#define xstr(s) str(s) +#define str(s) #s +volatile int (*fptr)(unsigned char x); +volatile int a; +volatile int b; + +int main() { + printf("all of the following should be 1 except xs[259] = 0"); + a = 3; + b = 259; + fptr = (volatile int (*)(unsigned char x))&testUcharX; + if ((((long)fptr)&((long)1)<<32) == 1) fptr = NULL; + printf("compiled with: '%s'\nxs[3] = %d\nxs[259] = %d\ntestUcharX(3) = %d\ntestUcharX(%d) = %d\nfptr(3) = %d\nfptr(259) = %d\n", + xstr(CC), xs[a], xs[b], testUcharX(a), b, testUcharX(b), fptr(a), fptr(b)); +} + diff --git a/test/combinatorics.jl b/test/combinatorics.jl deleted file mode 100644 index 57ad7da8a501d..0000000000000 --- a/test/combinatorics.jl +++ /dev/null @@ -1,20 +0,0 @@ -@test sort([2,3,1]) == [1,2,3] -@test sortr([2,3,1]) == [3,2,1] -@test sortperm([2,3,1]) == ([1,2,3],[3,1,2]) -@test !issorted([2,3,1]) -@test issorted([1,2,3]) -@test reverse([2,3,1]) == [1,3,2] -@test select([3,6,30,1,9],3) == 6 -@test sum(randperm(6)) == 21 -@test nthperm([0,1,2],3) == [1,0,2] - -@test search_sorted_first([1, 1, 2, 2, 3, 3], 0) == 1 -@test search_sorted_first([1, 1, 2, 2, 3, 3], 1) == 1 -@test search_sorted_first([1, 1, 2, 2, 3, 3], 2) == 3 -@test search_sorted_first([1, 1, 2, 2, 3, 3], 4) == 7 -@test search_sorted_first([1.0, 1, 2, 2, 3, 3], 2.5) == 5 -@test search_sorted_last([1, 1, 2, 2, 3, 3], 0) == 0 -@test search_sorted_last([1, 1, 2, 2, 3, 3], 1) == 2 -@test search_sorted_last([1, 1, 2, 2, 3, 3], 2) == 4 -@test search_sorted_last([1, 1, 2, 2, 3, 3], 4) == 6 -@test search_sorted_last([1.0, 1, 2, 2, 3, 3], 2.5) == 4 diff --git a/test/core.jl b/test/core.jl index 4aaed11c2ca83..1b7c77847d69e 100644 --- a/test/core.jl +++ b/test/core.jl @@ -19,61 +19,103 @@ @test Array{Int8,1} <: Array{Int8,1} @test !subtype(Type{None}, Type{Int32}) @test !subtype(Vector{Float64},Vector{Union(Float64,Float32)}) -@test is(None, tintersect(Vector{Float64},Vector{Union(Float64,Float32)})) +@test is(None, typeintersect(Vector{Float64},Vector{Union(Float64,Float32)})) @test !isa(Array,Type{Any}) -@test subtype(Type{ComplexPair},CompositeKind) +@test subtype(Type{ComplexPair},DataType) @test isa(ComplexPair,Type{ComplexPair}) @test !subtype(Type{Ptr{None}},Type{Ptr}) @test !subtype(Type{Rational{Int}}, Type{Rational}) let T = TypeVar(:T,true) - @test !is(None, tintersect(Array{None},AbstractArray{T})) - @test is(None, tintersect((Type{Ptr{Uint8}},Ptr{None}), - (Type{Ptr{T}},Ptr{T}))) + @test !is(None, typeintersect(Array{None},AbstractArray{T})) + @test is(None, typeintersect((Type{Ptr{Uint8}},Ptr{None}), + (Type{Ptr{T}},Ptr{T}))) @test !subtype(Type{T},TypeVar) - @test isequal(tintersect((Range{Int},(Int,Int)),(AbstractArray{T},Dims)), - (Range{Int},(Int,Int))) + @test isequal(typeintersect((Range{Int},(Int,Int)),(AbstractArray{T},Dims)), + (Range{Int},(Int,Int))) + + @test isequal(typeintersect((T, AbstractArray{T}),(Number, Array{Int,1})), + (Int, Array{Int,1})) - @test isequal(tintersect((T, AbstractArray{T}),(Number, Array{Int,1})), - (Int, Array{Int,1})) + @test isequal(typeintersect((T, AbstractArray{T}),(Int, Array{Number,1})), + None) - @test isequal(tintersect((T, AbstractArray{T}),(Int, Array{Number,1})), - None) - - @test isequal(tintersect((T, AbstractArray{T}),(Any, Array{Number,1})), - (Number, Array{Number,1})) - @test !is(None, tintersect((Array{T}, Array{T}), (Array, Array{Any}))) - @test is(None, tintersect((Vector{Vector{Int}},Vector{Vector}), - (Vector{Vector{T}},Vector{Vector{T}}))) + @test isequal(typeintersect((T, AbstractArray{T}),(Any, Array{Number,1})), + (Number, Array{Number,1})) + @test !is(None, typeintersect((Array{T}, Array{T}), (Array, Array{Any}))) + @test is(None, typeintersect((Vector{Vector{Int}},Vector{Vector}), + (Vector{Vector{T}},Vector{Vector{T}}))) end let N = TypeVar(:N,true) - @test isequal(tintersect((NTuple{N,Integer},NTuple{N,Integer}), - ((Integer,Integer), (Integer...))), - ((Integer,Integer), (Integer,Integer))) - @test isequal(tintersect((NTuple{N,Integer},NTuple{N,Integer}), - ((Integer...), (Integer,Integer))), - ((Integer,Integer), (Integer,Integer))) - local A = tintersect((NTuple{N,Any},Array{Int,N}), - ((Int,Int...),Array)) + @test isequal(typeintersect((NTuple{N,Integer},NTuple{N,Integer}), + ((Integer,Integer), (Integer...))), + ((Integer,Integer), (Integer,Integer))) + @test isequal(typeintersect((NTuple{N,Integer},NTuple{N,Integer}), + ((Integer...), (Integer,Integer))), + ((Integer,Integer), (Integer,Integer))) + local A = typeintersect((NTuple{N,Any},Array{Int,N}), + ((Int,Int...),Array)) local B = ((Int,Int...),Array{Int,N}) @test A<:B && B<:A - @test isequal(tintersect((NTuple{N,Any},Array{Int,N}), - ((Int,Int...),Array{Int,2})), - ((Int,Int), Array{Int,2})) + @test isequal(typeintersect((NTuple{N,Any},Array{Int,N}), + ((Int,Int...),Array{Int,2})), + ((Int,Int), Array{Int,2})) end -@test is(None, tintersect(Type{Any},Type{ComplexPair})) -@test is(None, tintersect(Type{Any},Type{TypeVar(:T,Real)})) +@test is(None, typeintersect(Type{Any},Type{ComplexPair})) +@test is(None, typeintersect(Type{Any},Type{TypeVar(:T,Real)})) @test !subtype(Type{Array{Integer}},Type{AbstractArray{Integer}}) @test !subtype(Type{Array{Integer}},Type{Array{TypeVar(:T,Integer)}}) -@test is(None, tintersect(Type{Function},BitsKind)) -@test is(Type{Int32}, tintersect(Type{Int32},BitsKind)) +@test is(None, typeintersect(Type{Function},UnionType)) +@test is(Type{Int32}, typeintersect(Type{Int32},DataType)) @test !subtype(Type,TypeVar) -@test !is(None, tintersect(BitsKind, Type)) -@test !is(None, tintersect(BitsKind, Type{Int})) -@test is(None, tintersect(BitsKind, Type{Integer})) -@test !is(None, tintersect(BitsKind, Type{TypeVar(:T,Int)})) -@test !is(None, tintersect(BitsKind, Type{TypeVar(:T,Integer)})) +@test !is(None, typeintersect(DataType, Type)) +@test !is(None, typeintersect(UnionType, Type)) +@test !is(None, typeintersect(DataType, Type{Int})) +@test !is(None, typeintersect(DataType, Type{TypeVar(:T,Int)})) +@test !is(None, typeintersect(DataType, Type{TypeVar(:T,Integer)})) + +@test isa(Int,Type{TypeVar(:T,Number)}) +@test !isa(DataType,Type{TypeVar(:T,Number)}) +@test subtype(DataType,Type{TypeVar(:T,Type)}) + +@test isa((),Type{()}) +@test subtype((DataType,),Type{TypeVar(:T,Tuple)}) +@test !subtype((Int,),Type{TypeVar(:T,Tuple)}) +@test isa((Int,),Type{TypeVar(:T,Tuple)}) + +@test !isa(Type{(Int,Int)},Tuple) +@test subtype(Type{(Int,Int)},Tuple) +@test subtype(Type{(Int,)}, (DataType,)) + +# this is fancy: know that any type T<:Number must be either a DataType or a UnionType +@test subtype(Type{TypeVar(:T,Number)},Union(DataType,UnionType)) +@test !subtype(Type{TypeVar(:T,Number)},DataType) +@test subtype(Type{TypeVar(:T,Tuple)},Union(Tuple,UnionType)) +@test !subtype(Type{TypeVar(:T,Tuple)},Union(DataType,UnionType)) + +@test !is(None, typeintersect((DataType,DataType),Type{TypeVar(:T,(Number,Number))})) +@test !is(None, typeintersect((DataType,UnionType),Type{(Number,None)})) + +# join +@test typejoin(Int8,Int16) === Signed +@test typejoin(Int,String) === Any +@test typejoin(Array{Float64},BitArray) <: AbstractArray +@test typejoin(Array{Bool},BitArray) <: AbstractArray{Bool} +@test typejoin((Int,Int8),(Int8,Float64)) === (Signed,Real) +@test Base.typeseq(typejoin((ASCIIString,ASCIIString),(UTF8String,ASCIIString), + (ASCIIString,UTF8String),(Int,ASCIIString,Int)), + (Any,String,Int...)) +@test Base.typeseq(typejoin((Int8,Int...),(Int8,Int8)), + (Int8,Signed...)) +@test Base.typeseq(typejoin((Int8,Int...),(Int8,Int8...)), + (Int8,Signed...)) +@test Base.typeseq(typejoin((Int8,Uint8,Int...),(Int8,Int8...)), + (Int8,Integer...)) +@test Base.typeseq(typejoin(Union(Int,String),Int), Union(Int,String)) +@test Base.typeseq(typejoin(Union(Int,String),Int8), Any) + +@test promote_type(Bool,None) === Bool # ntuples nttest1{n}(x::NTuple{n,Int}) = n @@ -292,10 +334,10 @@ end begin local mytype function mytype(vec) - convert(Vector{(ASCIIString, BitsKind)}, vec) + convert(Vector{(ASCIIString, DataType)}, vec) end some_data = {("a", Int32), ("b", Int32)} - @test isa(mytype(some_data),Vector{(ASCIIString, BitsKind)}) + @test isa(mytype(some_data),Vector{(ASCIIString, DataType)}) end type MyArray{N} <: AbstractArray{Int, N} @@ -360,6 +402,17 @@ begin end @test b == 42 @test after == 1 + + glo = 0 + function retfinally() + try + return 5 + finally + glo = 18 + end + end + @test retfinally() == 5 + @test glo == 18 end # allow typevar in Union to match as long as the arguments contain @@ -390,8 +443,8 @@ end begin local baar, foor, boor # issue #1131 - baar(x::CompositeKind) = 0 - baar(x::UnionKind) = 1 + baar(x::DataType) = 0 + baar(x::UnionType) = 1 baar(x::TypeConstructor) = 2 @test baar(StridedArray) == 2 @test baar(StridedArray.body) == 1 @@ -399,12 +452,12 @@ begin @test baar(Vector.body) == 0 boor(x) = 0 - boor(x::UnionKind) = 1 + boor(x::UnionType) = 1 @test boor(StridedArray) == 0 @test boor(StridedArray.body) == 1 # issue #1202 - foor(x::UnionKind) = 1 + foor(x::UnionType) = 1 @test_fails foor(StridedArray) @test foor(StridedArray.body) == 1 @test_fails foor(StridedArray) @@ -438,8 +491,25 @@ begin a2 = Any[101,102,103] p2 = pointer(a2) @test unsafe_ref(p2) == 101 - unsafe_assign(p2, 909, 3) - @test a2 == [101,102,909] + @test_fails unsafe_assign(p2, 909, 3) + @test a2 == [101,102,103] +end + +@test unsafe_pointer_to_objref(ccall(:jl_call1, Ptr{Void}, (Any,Any), + x -> x+1, 314158)) == 314159 +@test unsafe_pointer_to_objref(pointer_from_objref(e+pi)) == e+pi + +immutable FooBar + foo::Int + bar::Int +end +begin + local X, p + X = FooBar[ FooBar(3,1), FooBar(4,4) ] + p = convert(Ptr{FooBar}, X) + @test unsafe_ref(p, 2) == FooBar(4,4) + unsafe_assign(p, FooBar(7,3), 1) + @test X[1] == FooBar(7,3) end # issue #1287, combinations of try, catch, return @@ -469,9 +539,185 @@ end begin local f1442 - f1442(::CompositeKind) = 1 + f1442(::DataType) = 1 f1442{T}(::Type{S1442{T}}) = 2 @test f1442(S1442{Int}) == 2 - @test f1442(CompositeKind) == 1 + @test f1442(DataType) == 1 +end + +# issue #1727 +abstract Component + +type Transform <: Component + x + y + z + + Transform() = new(0, 0, 0) +end + +type Body <: Component + vel + curr_force + + Body() = new(0, 0) +end + +function NewEntity{ T<:Component }(components::Type{T}...) + map((c)->c(), components) +end + +@test_fails NewEntity(Transform, Transform, Body, Body) +@test isa(NewEntity(Transform, Transform), (Transform, Transform)) +@test_fails NewEntity(Transform, Transform, Body, Body) + +# issue #1826 +let + a = (1,2) + a,b = a + @test a==1 && b==2 +end + +# issue #1876 +let + tst = 1 + m1(i) = (tst+=1;i-1) + x = [1:4] + x[1:end] *= 2 + @test x == [2:2:8] + x[m1(end)] += 3 + @test x == [2,4,9,8] + @test tst == 2 + + # issue #1886 + X = [1:4] + r = Array(Range1{Int},1) + r[1] = 2:3 + X[r...] *= 2 + @test X == [1,4,6,4] +end + +# issue #1632 +let + f1632{R,S}(::R, ::S) = 1 + f1632{T}( ::T, ::T) = 2 + @test f1632(1, 2) == 2 + @test f1632(:a, 2) == 1 + g1632{T}( ::T, ::T) = 2 + g1632{R,S}(::R, ::S) = 1 + @test g1632(1, 2) == 2 + @test g1632(:a, 2) == 1 +end + +# issue #1628 +type I1628{X} + x::X +end +let + # here the potential problem is that the run-time value of static + # parameter X in the I1628 constructor is (DataType,DataType), + # but type inference will track it more accurately as + # (Type{Integer}, Type{Int}). + f1628() = I1628((Integer,Int)) + @test isa(f1628(), I1628{(DataType,DataType)}) +end + +let + fT{T}(x::T) = T + @test fT(Any) === DataType + @test fT(Int) === DataType + @test fT(Type{Any}) === DataType + @test fT(Type{Int}) === DataType + + ff{T}(x::Type{T}) = T + @test ff(Type{Any}) === Type{Any} + @test ff(Type{Int}) === Type{Int} + @test ff(Any) === Any + @test ff(Int) === Int +end + +# issue #2098 +let + i2098() = (c={2.0};[1:1:c[1]]) + @test isequal(i2098(), [1.0,2.0]) +end + +# issue #2161 +let + i2161_1() = promote(2,2,2.0,2) + i2161_2() = i2161_1()[1] + @test i2161_2() === 2.0 +end + +# issue #2169 +let + i2169{T}(a::Array{T}) = typemin(T) + @test invoke(i2169,(Array,),Int8[1]) === int8(-128) +end + +# issue #2365 +type B2365{T} + v::Union(T, Nothing) +end +@test B2365{Int}(nothing).v === nothing +@test B2365{Int}(0).v === 0 + +# issue #2352 +Sum=0.0; for n=1:2:10000 +Sum += -1/n + 1/(n+1) +end +@test Sum < -0.69 + +include("test_sourcepath.jl") + +# issue #2509 +immutable Foo2509; foo::Int; end +@test Foo2509(1) != Foo2509(2) +@test Foo2509(42) == Foo2509(42) + +# issue #2517 +immutable Foo2517; end +@test repr(Foo2517()) == "Foo2517()" +@test repr(Array(Foo2517,1)) == "[Foo2517()]" +@test Foo2517() === Foo2517() + +# issue #1474 +type X1474{a,b} end +begin + local Y + Y{A,B}(::Type{X1474{A,B}}) = 1 + Y{A}(::Type{X1474{A}}) = 2 + Y(::Type{X1474}) = 3 + @test Y(X1474) == 3 + @test Y(X1474{Int}) == 2 + @test Y(X1474{Int,String}) == 1 +end + +# issue #2562 +type Node2562{T} + value::T + Node2562(value::T) = new(value) +end +Node2562{T}(value::T, args...) = Node2562{T}(value, args...) +makenode2562(value) = Node2562(value) +@test isa(Node2562(0), Node2562) +@test isa(makenode2562(0), Node2562) + +# issue #2619 +type I2619{T} + v::T + I2619(v) = new(convert(T,v)) +end +bad2619 = false +function i2619() + global e2619 = try + I2619{Float64}(0.0f) + global bad2619 = true + catch _e + _e + end end +i2619() +@test !bad2619 +@test isa(e2619,ErrorException) && e2619.msg == "in i2619: f not defined" diff --git a/test/corelib.jl b/test/corelib.jl index 1480f1e74159c..ea03da79f14c2 100644 --- a/test/corelib.jl +++ b/test/corelib.jl @@ -16,8 +16,6 @@ L64 = linspace(int64(1), int64(4), 4) @test L32[2] == 2 && L64[2] == 2 @test L32[3] == 3 && L64[3] == 3 @test L32[4] == 4 && L64[4] == 4 -lsp = linspace(1, 10, 6) -@test isequal(lsp,[1,3,5,6,8,10]) r = [5:-1:1] @test r[1]==5 @@ -26,6 +24,19 @@ r = [5:-1:1] @test r[4]==2 @test r[5]==1 +@test length(.1:.1:.3) == 3 +@test length(1.1:1.1:3.3) == 3 +@test length(1.1:1.3:3) == 2 +@test length(1:1:1.8) == 1 + +let + span = 5:20 + r = -7:3:42 + @test findin(r, span) == 5:10 + r = 15:-2:-38 + @test findin(r, span) == 1:6 +end + # comprehensions X = [ i+2j for i=1:5, j=1:5 ] @test X[2,3] == 8 @@ -41,7 +52,7 @@ end @test isequal([1,2,3], [a for (a,b) in enumerate(2:4)]) @test isequal([2,3,4], [b for (a,b) in enumerate(2:4)]) -@test (10.^[-1])[1] == 0.1 +@test_fails (10.^[-1])[1] == 0.1 @test (10.^[-1.])[1] == 0.1 # tricky space sensitive syntax cases @@ -63,7 +74,7 @@ for i=1:10000 @test (h[i] == i+1) end for i=1:2:10000 - del(h, i) + delete!(h, i) end for i=1:2:10000 h[i] = i+1 @@ -72,7 +83,7 @@ for i=1:10000 @test (h[i] == i+1) end for i=1:10000 - del(h, i) + delete!(h, i) end @test isempty(h) h[77] = 100 @@ -81,7 +92,7 @@ for i=1:10000 h[i] = i+1 end for i=1:2:10000 - del(h, i) + delete!(h, i) end for i=10001:20000 h[i] = i+1 @@ -109,6 +120,23 @@ end _d = {"a"=>0} @test isa([k for k in filter(x->length(x)==1, keys(_d))], Vector{Any}) +# issue #1821 +let + d = Dict{UTF8String, Vector{Int}}() + d["a"] = [1, 2] + @test_fails d["b"] = 1 + @test isa(repr(d), String) # check that printable without error +end + +# issue #2344 +let + bestkey(d, key) = key + bestkey{K<:String,V}(d::Associative{K,V}, key) = string(key) + bar(x) = bestkey(x, :y) + @test bar([:x => [1,2,5]]) == :y + @test bar(["x" => [1,2,5]]) == "y" +end + # issue #1438 type I1438T id @@ -125,10 +153,10 @@ begin for id in seq if id > 0 x = xs[id] - add(s, x) + add!(s, x) @test has(s, x) # check that x can be found else - del(s, xs[-id]) + delete!(s, xs[-id]) end end end @@ -140,22 +168,22 @@ end @test !isequal({1 => 1}, {2 => 1}) # Generate some data to populate dicts to be compared -data_in = [ (randi(1000), randstring(2)) for _ in 1:1001 ] +data_in = [ (rand(1:1000), randstring(2)) for _ in 1:1001 ] # Populate the first dict -d1 = Dict{Int, String}(length(data_in)) +d1 = Dict{Int, String}() for (k,v) in data_in d1[k] = v end -data_in = pairs(d1) +data_in = collect(d1) # shuffle the data for i in 1:length(data_in) - j = randi(length(data_in)) + j = rand(1:length(data_in)) data_in[i], data_in[j] = data_in[j], data_in[i] end # Inserting data in different (shuffled) order should result in # equivalent dict. -d2 = Dict{Int, String}(length(data_in)) +d2 = Dict{Int, String}() for (k,v) in data_in d2[k] = v end @@ -164,16 +192,16 @@ end d3 = copy(d2) d4 = copy(d2) # Removing an item gives different dict -del(d1, data_in[randi(length(data_in))][1]) +delete!(d1, data_in[rand(1:length(data_in))][1]) @test !isequal(d1, d2) # Changing a value gives different dict -d3[data_in[randi(length(data_in))][1]] = randstring(3) +d3[data_in[rand(1:length(data_in))][1]] = randstring(3) !isequal(d1, d3) # Adding a pair gives different dict d4[1001] = randstring(3) @test !isequal(d1, d4) -@test isequal(Dict(), Dict(96)) +@test isequal(Dict(), sizehint(Dict(),96)) # Here is what currently happens when dictionaries of different types # are compared. This is not necessarily desirable. These tests are @@ -181,6 +209,15 @@ d4[1001] = randstring(3) @test !isequal({1 => 2}, {"dog" => "bone"}) @test isequal(Dict{Int, Int}(), Dict{String, String}()) +# issue #2540 +d = {x => 1 + for x in ['a', 'b', 'c']} +@test d == {'a'=>1, 'b'=>1, 'c'=> 1} + +# issue #2629 +d = (String => String)[ a => "foo" for a in ["a","b","c"]] +@test d == ["a"=>"foo","b"=>"foo","c"=>"foo"] + # ############# end of dict tests ############# # #################### set #################### @@ -193,17 +230,32 @@ d4[1001] = randstring(3) @test !isempty(Set("banana", "apple")) @test !isempty(Set(1, 1:10, "pear")) +# isless +@test isless(Set(), Set(1)) +@test isless(Set(1), Set(1,2)) +@test !isless(Set(3), Set(1,2)) +@test !(Set(3) > Set(1,2)) +@test Set(1,2,3) > Set(1,2) +@test !(Set(3) <= Set(1,2)) +@test !(Set(3) >= Set(1,2)) +@test Set(1) <= Set(1,2) +@test Set(1,2) <= Set(1,2) +@test Set(1,2) >= Set(1,2) +@test Set(1,2,3) >= Set(1,2) +@test !(Set(1,2,3) >= Set(1,2,4)) +@test !(Set(1,2,3) <= Set(1,2,4)) + # add, length s = Set() @test isempty(s) for i in 1:1000 - add(s, i) + add!(s, i) @test (length(s) == i) end -# del, has, contains +# delete!, has, contains for i in 1:2:1000 - del(s, i) + delete!(s, i) end for i in 1:2:1000 @test !has(s, i) @@ -215,7 +267,7 @@ end # elements data_in = (1,"banana", ()) s = Set(data_in...) -data_out = elements(s) +data_out = collect(s) @test is(typeof(data_out), Array{Any,1}) @test all(map(d->contains(data_out,d), data_in)) @test all(map(data_in) do d contains(data_out, d) end) @@ -232,15 +284,11 @@ data_out = elements(s) # no duplicates s = Set(1,2,3) @test length(s) == 3 -add(s,2) +add!(s,2) @test length(s) == 3 -del(s,2) +delete!(s,2) @test length(s) == 2 -# get -@test get(Set(1,2,3), 2, "ignored") == true -@test get(Set(1, 3), 2, "ignored") == false - # union s = union(Set(1,2), Set(3,4)) @test isequal(s, Set(1,2,3,4)) @@ -252,6 +300,7 @@ s = intersect(Set(1,2), Set(3,4)) @test isequal(s, Set()) s = intersect(Set(5,6,7,8), Set(7,8,9)) @test isequal(s, Set(7,8)) +@test isequal(intersect(Set(2,3,1), Set(4,2,3), Set(5,4,3,2)), Set(2,3)) # setdiff @test isequal(setdiff(Set(1,2,3), Set()), Set(1,2,3)) @@ -279,12 +328,12 @@ end # add_each s = Set(1,3,5,7) -add_each(s,(2,3,4,5)) +add_each!(s,(2,3,4,5)) @test isequal(s,Set(1,2,3,4,5,7)) # del_each s = Set(1,3,5,7) -del_each(s,(3,5)) +del_each!(s,(3,5)) @test isequal(s,Set(1,7)) # similar @@ -300,8 +349,8 @@ data_in = (1,2,9,8,4) s = Set(data_in...) c = copy(s) @test isequal(s,c) -add(s,100) -add(c,200) +add!(s,100) +add!(c,200) @test !has(c, 100) @test !has(s, 200) @@ -312,7 +361,7 @@ for data_in in ((7,8,4,5), s_new = Set() for el in s - add(s_new, el) + add!(s_new, el) end @test isequal(s, s_new) @@ -323,6 +372,26 @@ for data_in in ((7,8,4,5), end end +# zip +let i = 0 +x = 1:2:8 +y = 2:2:8 +xy = 1:8 +for (thisx, thisy) in zip(x, y) + @test thisx == xy[i+=1] + @test thisy == xy[i+=1] +end +end + +# pop! +origs = Set(1,2,3,"apple") +s = copy(origs) +for i in 1:length(origs) + el = pop!(s) + @test !has(s, el) + @test has(origs, el) +end +@test isempty(s) # isequal @test isequal(Set(), Set()) @test !isequal(Set(), Set(1)) @@ -346,3 +415,11 @@ end @test !isequal(Set{Int}(1,2,3,4), Set{Any}(1,2,3)) # ########## end of set tests ########## + +# Ensure denormal flags functions don't segfault +@test any(ccall("jl_zero_denormals", Uint8, (Uint8,), 1) .== [0x00 0x01]) +@test any(ccall("jl_zero_denormals", Uint8, (Uint8,), 0) .== [0x00 0x01]) + +# VersionNumber +@test VersionNumber(2,3,1) == VersionNumber(int8(2),uint32(3),int32(1)) == v"2.3.1" +@test v"2.3.0" < v"2.3.1" < v"2.4.8" < v"3.7.2" diff --git a/test/dct.jl b/test/dct.jl new file mode 100644 index 0000000000000..a3ed35912389b --- /dev/null +++ b/test/dct.jl @@ -0,0 +1,85 @@ +# Discrete cosine transform (DCT) tests + +a = rand(8,11) + im*rand(8,11) +@test norm(idct(dct(a)) - a) < 1e-8 + +X = reshape([1,2,7,2,1,5,9,-1,3,4,6,9],3,4) +Y = rand(17,14) +Y[3:5,9:12] = X +sX = slice(Y,3:5,9:12) + +true_Xdct = [ 13.856406460551018 -3.863239728836245 2.886751345948129 -0.274551994240164; -2.828427124746190 -2.184015211898548 -4.949747468305834 3.966116180118245; 4.898979485566356 -0.194137576915510 -2.857738033247041 2.731723009609389 ] + +true_Xdct_1 = [ 5.773502691896258 4.618802153517007 6.350852961085884 10.969655114602890; -4.242640687119286 -2.121320343559643 4.242640687119286 -3.535533905932738; 1.632993161855452 2.041241452319315 5.715476066494083 0.408248290463863 ] + +true_Xdct_2 = [ 8. -3.854030797826254 -3.0 3.761176226848022; + 4.0 -2.071929829606556 4.0 -2.388955165168770; 12. -0.765366864730179 4.0 -1.847759065022573 ] + +Xdct = dct(X) +Xdct! = float(X); dct!(Xdct!) +Xdct_1 = dct(X,1) +Xdct!_1 = float(X); dct!(Xdct!_1,1) +Xdct_2 = dct(X,2) +Xdct!_2 = float(X); dct!(Xdct!_2,2) + +Xidct = idct(true_Xdct) +Xidct! = copy(true_Xdct); idct!(Xidct!) +Xidct_1 = idct(true_Xdct_1,1) +Xidct!_1 = copy(true_Xdct_1); idct!(Xidct!_1,1) +Xidct_2 = idct(true_Xdct_2,2) +Xidct!_2 = copy(true_Xdct_2); idct!(Xidct!_2,2) + +pXdct = plan_dct(X)(X) +pXdct! = float(X); plan_dct!(pXdct!)(pXdct!) +pXdct_1 = plan_dct(X,1)(X) +pXdct!_1 = float(X); plan_dct!(pXdct!_1,1)(pXdct!_1) +pXdct_2 = plan_dct(X,2)(X) +pXdct!_2 = float(X); plan_dct!(pXdct!_2,2)(pXdct!_2) + +pXidct = plan_idct(true_Xdct)(true_Xdct) +pXidct! = copy(true_Xdct); plan_idct!(pXidct!)(pXidct!) +pXidct_1 = plan_idct(true_Xdct_1,1)(true_Xdct_1) +pXidct!_1 = copy(true_Xdct_1); plan_idct!(pXidct!_1,1)(pXidct!_1) +pXidct_2 = plan_idct(true_Xdct_2,2)(true_Xdct_2) +pXidct!_2 = copy(true_Xdct_2); plan_idct!(pXidct!_2,2)(pXidct!_2) + +sXdct = dct(sX) +psXdct = plan_dct(sX)(sX) +sYdct! = copy(Y); sXdct! = slice(sYdct!,3:5,9:12); dct!(sXdct!) +psYdct! = copy(Y); psXdct! = slice(psYdct!,3:5,9:12); plan_dct!(psXdct!)(psXdct!) + + +for i = 1:length(X) + @test_approx_eq Xdct[i] true_Xdct[i] + @test_approx_eq Xdct![i] true_Xdct[i] + @test_approx_eq Xdct_1[i] true_Xdct_1[i] + @test_approx_eq Xdct!_1[i] true_Xdct_1[i] + @test_approx_eq Xdct_2[i] true_Xdct_2[i] + @test_approx_eq Xdct!_2[i] true_Xdct_2[i] + + @test_approx_eq pXdct[i] true_Xdct[i] + @test_approx_eq pXdct![i] true_Xdct[i] + @test_approx_eq pXdct_1[i] true_Xdct_1[i] + @test_approx_eq pXdct!_1[i] true_Xdct_1[i] + @test_approx_eq pXdct_2[i] true_Xdct_2[i] + @test_approx_eq pXdct!_2[i] true_Xdct_2[i] + + @test_approx_eq Xidct[i] X[i] + @test_approx_eq Xidct![i] X[i] + @test_approx_eq Xidct_1[i] X[i] + @test_approx_eq Xidct!_1[i] X[i] + @test_approx_eq Xidct_2[i] X[i] + @test_approx_eq Xidct!_2[i] X[i] + + @test_approx_eq pXidct[i] X[i] + @test_approx_eq pXidct![i] X[i] + @test_approx_eq pXidct_1[i] X[i] + @test_approx_eq pXidct!_1[i] X[i] + @test_approx_eq pXidct_2[i] X[i] + @test_approx_eq pXidct!_2[i] X[i] + + @test_approx_eq sXdct[i] true_Xdct[i] + @test_approx_eq psXdct[i] true_Xdct[i] + @test_approx_eq sXdct![i] true_Xdct[i] + @test_approx_eq psXdct![i] true_Xdct[i] +end diff --git a/test/default.jl b/test/default.jl deleted file mode 100644 index 046cb7a87fa26..0000000000000 --- a/test/default.jl +++ /dev/null @@ -1,23 +0,0 @@ -# core tests -runtests("core") -runtests("numbers") -runtests("strings") -runtests("unicode") -runtests("corelib") -runtests("hashing") -runtests("remote") - -# array/matrix tests -runtests("arrayops") -runtests("linalg") -runtests("fft") -runtests("sparse") -runtests("bitarray") - -# other tests -runtests("random") -runtests("math") -runtests("functional") -runtests("bigint") -runtests("combinatorics") -runtests("statistics") diff --git a/test/extra.jl b/test/extra.jl deleted file mode 100644 index bd074d31f1925..0000000000000 --- a/test/extra.jl +++ /dev/null @@ -1,15 +0,0 @@ -runtests("suitesparse") -runtests("arpack") -runtests("glpk") -runtests("linprog") -runtests("bigfloat") -runtests("poly") -runtests("file") -runtests("Rmath") -runtests("zlib") -# runtests("options") -runtests("image") -# runtests("iterators") -runtests("gzip") - -runtests("perf") diff --git a/test/fft.jl b/test/fft.jl index 7c0c6458b56e3..573eab2b5b3c2 100644 --- a/test/fft.jl +++ b/test/fft.jl @@ -7,12 +7,42 @@ m4 = [16. 2 3 13; 9 7 6 12; 4 14 15 1] -fft_m4 = fft(m4) -fft2_m4 = fft2(m4) +b = rand(17,14) +b[3:6,9:12] = m4 +sm4 = slice(b,3:6,9:12) + +pm4 = plan_fft(m4,1) + +fft_m4 = fft(m4,1) fftd2_m4 = fft(m4,2) -ifft_fft_m4 = ifft(fft(m4)) -fftn_m4 = fftn(m4) -ifftn_fftn_m4 = ifftn(fftn(m4)) +ifft_fft_m4 = ifft(fft(m4,1),1) +fftn_m4 = fft(m4) +ifftn_fftn_m4 = ifft(fft(m4)) + +fft!_m4 = complex(m4); fft!(fft!_m4,1) +fft!d2_m4 = complex(m4); fft!(fft!d2_m4,2) +ifft!_fft_m4 = fft(m4,1); ifft!(ifft!_fft_m4,1) +fft!n_m4 = complex(m4); fft!(fft!n_m4) +ifft!n_fftn_m4 = fft(m4); ifft!(ifft!n_fftn_m4) + +pfft_m4 = plan_fft(m4,1)(m4) +pfftd2_m4 = plan_fft(m4,2)(m4) +pifft_fft_m4 = plan_ifft(fft_m4,1)(fft_m4) +pfftn_m4 = plan_fft(m4)(m4) +pifftn_fftn_m4 = plan_ifft(fftn_m4)(fftn_m4) + +pfft!_m4 = complex(m4); plan_fft!(pfft!_m4,1)(pfft!_m4) +pfft!d2_m4 = complex(m4); plan_fft!(pfft!d2_m4,2)(pfft!d2_m4) +pifft!_fft_m4 = fft(m4,1); plan_ifft!(pifft!_fft_m4,1)(pifft!_fft_m4) +pfft!n_m4 = complex(m4); plan_fft!(pfft!n_m4)(pfft!n_m4) +pifft!n_fftn_m4 = fft(m4); plan_ifft!(pifft!n_fftn_m4)(pifft!n_fftn_m4) + +sfftn_m4 = fft(sm4) +psfftn_m4 = plan_fft(sm4)(sm4) +sfft!n_b = complex128(b) +sfft!n_m4 = slice(sfft!n_b,3:6,9:12); fft!(sfft!n_m4) +psfft!n_b = complex128(b) +psfft!n_m4 = slice(psfft!n_b,3:6,9:12); plan_fft!(psfft!n_m4)(psfft!n_m4) true_fft_m4 = [ 34. 34. 34. 34.; @@ -33,66 +63,142 @@ true_fftd2_m4 = [ 34. -11 - 13im 4 -11 + 13im ] for i = 1:length(m4) - @assert_approx_eq fft_m4[i] true_fft_m4[i] - @assert_approx_eq fft2_m4[i] true_fftn_m4[i] - @assert_approx_eq fftd2_m4[i] true_fftd2_m4[i] - @assert_approx_eq ifft_fft_m4[i] m4[i] - @assert_approx_eq fftn_m4[i] true_fftn_m4[i] - @assert_approx_eq ifftn_fftn_m4[i] m4[i] + @test_approx_eq fft_m4[i] true_fft_m4[i] + @test_approx_eq fftd2_m4[i] true_fftd2_m4[i] + @test_approx_eq ifft_fft_m4[i] m4[i] + @test_approx_eq fftn_m4[i] true_fftn_m4[i] + @test_approx_eq ifftn_fftn_m4[i] m4[i] + + @test_approx_eq fft!_m4[i] true_fft_m4[i] + @test_approx_eq fft!d2_m4[i] true_fftd2_m4[i] + @test_approx_eq ifft!_fft_m4[i] m4[i] + @test_approx_eq fft!n_m4[i] true_fftn_m4[i] + @test_approx_eq ifft!n_fftn_m4[i] m4[i] + + @test_approx_eq pfft_m4[i] true_fft_m4[i] + @test_approx_eq pfftd2_m4[i] true_fftd2_m4[i] + @test_approx_eq pifft_fft_m4[i] m4[i] + @test_approx_eq pfftn_m4[i] true_fftn_m4[i] + @test_approx_eq pifftn_fftn_m4[i] m4[i] + + @test_approx_eq pfft!_m4[i] true_fft_m4[i] + @test_approx_eq pfft!d2_m4[i] true_fftd2_m4[i] + @test_approx_eq pifft!_fft_m4[i] m4[i] + @test_approx_eq pfft!n_m4[i] true_fftn_m4[i] + @test_approx_eq pifft!n_fftn_m4[i] m4[i] + + @test_approx_eq sfftn_m4[i] true_fftn_m4[i] + @test_approx_eq sfft!n_m4[i] true_fftn_m4[i] + @test_approx_eq psfftn_m4[i] true_fftn_m4[i] + @test_approx_eq psfft!n_m4[i] true_fftn_m4[i] end +ifft!(sfft!n_m4) +plan_ifft!(psfft!n_m4)(psfft!n_m4) +@test norm(sfft!n_m4 - m4) < 1e-8 +@test norm(psfft!n_m4 - m4) < 1e-8 + m3d = float32(reshape(1:5*3*2, 5, 3, 2)) -ifft3_fft3_m3d = ifft3(fft3(m3d)) +ifft3_fft3_m3d = ifft(fft(m3d)) + fftd3_m3d = fft(m3d,3) ifftd3_fftd3_m3d = ifft(fftd3_m3d,3) + +fft!d3_m3d = complex(m3d); fft!(fft!d3_m3d,3) +ifft!d3_fftd3_m3d = copy(fft!d3_m3d); ifft!(ifft!d3_fftd3_m3d,3) + +pfftd3_m3d = plan_fft(m3d,3)(m3d) +pifftd3_fftd3_m3d = plan_ifft(fftd3_m3d,3)(fftd3_m3d) + +pfft!d3_m3d = complex(m3d); plan_fft!(pfft!d3_m3d,3)(pfft!d3_m3d) +pifft!d3_fftd3_m3d = copy(fft!d3_m3d); plan_ifft!(pifft!d3_fftd3_m3d,3)(pifft!d3_fftd3_m3d) + @test isa(fftd3_m3d, Array{Complex64,3}) +@test isa(ifftd3_fftd3_m3d, Array{Complex64,3}) +@test isa(fft!d3_m3d, Array{Complex64,3}) +@test isa(ifft!d3_fftd3_m3d, Array{Complex64,3}) +@test isa(pfftd3_m3d, Array{Complex64,3}) +@test isa(pifftd3_fftd3_m3d, Array{Complex64,3}) +@test isa(pfft!d3_m3d, Array{Complex64,3}) +@test isa(pifft!d3_fftd3_m3d, Array{Complex64,3}) true_fftd3_m3d = Array(Float32, 5, 3, 2) true_fftd3_m3d[:,:,1] = 17:2:45 true_fftd3_m3d[:,:,2] = -15 for i = 1:length(m3d) - @assert_approx_eq fftd3_m3d[i] true_fftd3_m3d[i] - @assert_approx_eq ifftd3_fftd3_m3d[i] m3d[i] - @assert_approx_eq ifft3_fft3_m3d[i] m3d[i] + @test_approx_eq fftd3_m3d[i] true_fftd3_m3d[i] + @test_approx_eq ifftd3_fftd3_m3d[i] m3d[i] + @test_approx_eq ifft3_fft3_m3d[i] m3d[i] + + @test_approx_eq fft!d3_m3d[i] true_fftd3_m3d[i] + @test_approx_eq ifft!d3_fftd3_m3d[i] m3d[i] + + @test_approx_eq pfftd3_m3d[i] true_fftd3_m3d[i] + @test_approx_eq pifftd3_fftd3_m3d[i] m3d[i] + @test_approx_eq pfft!d3_m3d[i] true_fftd3_m3d[i] + @test_approx_eq pifft!d3_fftd3_m3d[i] m3d[i] end # rfft/rfftn -rfft_m4 = rfft(m4) +rfft_m4 = rfft(m4,1) rfftd2_m4 = rfft(m4,2) -rfftn_m4 = rfftn(m4) +rfftn_m4 = rfft(m4) + +prfft_m4 = plan_rfft(m4,1)(m4) +prfftd2_m4 = plan_rfft(m4,2)(m4) +prfftn_m4 = plan_rfft(m4)(m4) + +srfftn_m4 = rfft(sm4) +psrfftn_m4 = plan_rfft(sm4)(sm4) for i = 1:3, j = 1:4 - @assert_approx_eq rfft_m4[i,j] true_fft_m4[i,j] - @assert_approx_eq rfftd2_m4[j,i] true_fftd2_m4[j,i] - @assert_approx_eq rfftn_m4[i,j] true_fftn_m4[i,j] + @test_approx_eq rfft_m4[i,j] true_fft_m4[i,j] + @test_approx_eq rfftd2_m4[j,i] true_fftd2_m4[j,i] + @test_approx_eq rfftn_m4[i,j] true_fftn_m4[i,j] + + @test_approx_eq prfft_m4[i,j] true_fft_m4[i,j] + @test_approx_eq prfftd2_m4[j,i] true_fftd2_m4[j,i] + @test_approx_eq prfftn_m4[i,j] true_fftn_m4[i,j] + + @test_approx_eq srfftn_m4[i,j] true_fftn_m4[i,j] + @test_approx_eq psrfftn_m4[i,j] true_fftn_m4[i,j] end -irfft_rfft_m4 = irfft(rfft_m4,size(m4,1)) +irfft_rfft_m4 = irfft(rfft_m4,size(m4,1),1) irfft_rfftd2_m4 = irfft(rfftd2_m4,size(m4,2),2) -irfftn_rfftn_m4 = irfftn(rfftn_m4,size(m4,1)) +irfftn_rfftn_m4 = irfft(rfftn_m4,size(m4,1)) + +pirfft_rfft_m4 = plan_irfft(rfft_m4,size(m4,1),1)(rfft_m4) +pirfft_rfftd2_m4 = plan_irfft(rfftd2_m4,size(m4,2),2)(rfftd2_m4) +pirfftn_rfftn_m4 = plan_irfft(rfftn_m4,size(m4,1))(rfftn_m4) + for i = 1:length(m4) - @assert_approx_eq irfft_rfft_m4[i] m4[i] - @assert_approx_eq irfft_rfftd2_m4[i] m4[i] - @assert_approx_eq irfftn_rfftn_m4[i] m4[i] + @test_approx_eq irfft_rfft_m4[i] m4[i] + @test_approx_eq irfft_rfftd2_m4[i] m4[i] + @test_approx_eq irfftn_rfftn_m4[i] m4[i] + + @test_approx_eq pirfft_rfft_m4[i] m4[i] + @test_approx_eq pirfft_rfftd2_m4[i] m4[i] + @test_approx_eq pirfftn_rfftn_m4[i] m4[i] end -rfftn_m3d = rfftn(m3d) +rfftn_m3d = rfft(m3d) rfftd3_m3d = rfft(m3d,3) @test size(rfftd3_m3d) == size(fftd3_m3d) irfft_rfftd3_m3d = irfft(rfftd3_m3d,size(m3d,3),3) -irfftn_rfftn_m3d = irfftn(rfftn_m3d,size(m3d,1)) +irfftn_rfftn_m3d = irfft(rfftn_m3d,size(m3d,1)) for i = 1:length(m3d) - @assert_approx_eq rfftd3_m3d[i] true_fftd3_m3d[i] - @assert_approx_eq irfft_rfftd3_m3d[i] m3d[i] - @assert_approx_eq irfftn_rfftn_m3d[i] m3d[i] + @test_approx_eq rfftd3_m3d[i] true_fftd3_m3d[i] + @test_approx_eq irfft_rfftd3_m3d[i] m3d[i] + @test_approx_eq irfftn_rfftn_m3d[i] m3d[i] end -fftn_m3d = fftn(m3d) +fftn_m3d = fft(m3d) @test size(fftn_m3d) == (5,3,2) -rfftn_m3d = rfftn(m3d) +rfftn_m3d = rfft(m3d) @test size(rfftn_m3d) == (3,3,2) for i = 1:3, j = 1:3, k = 1:2 - @assert_approx_eq rfftn_m3d[i,j,k] fftn_m3d[i,j,k] + @test_approx_eq rfftn_m3d[i,j,k] fftn_m3d[i,j,k] end diff --git a/test/file.jl b/test/file.jl index 518c8d6aa98c6..0f6c94cb94271 100644 --- a/test/file.jl +++ b/test/file.jl @@ -1,51 +1,46 @@ -## paths - -@unix_only begin - @test split_extension(".bashrc") == (".bashrc","") - @test split_extension("/dir/.bashrc") == ("/dir/.bashrc","") - @test split_extension("a.b/a") == ("a.b/a","") - @test split_extension("a/a.b.c") == ("a/a.b",".c") - - @test split_path("a/b/c") == ["a","b","c"] - @test split_path("a//b/c") == ["a","b","c"] -end - ############################################# # Create some temporary files & directories # ############################################# # This first section may not run for non-UNIX people. # If so, create the directories and files manually, and comment out this section # (Or fix up the code to support such operations on Windows!) -dir_name = mktempdir() -filename = file_path(dir_name, "afile.txt") -file_create(filename) +dir = mktempdir() +file = joinpath(dir, "afile.txt") +touch(file) ####################################################################### # This section tests some of the features of the stat-based file info # ####################################################################### -@test isdir(dir_name) == true -@test isfile(dir_name) == false -@test islink(dir_name) == false -@test isdir(filename) == false -@test isfile(filename) == true -@test islink(filename) == false -@test isreadable(filename) == true -@test iswriteable(filename) == true +@test isdir(dir) == true +@test isfile(dir) == false +@test islink(dir) == false +@test isdir(file) == false +@test isfile(file) == true +@test islink(file) == false +@test isreadable(file) == true +@test iswriteable(file) == true # Here's something else that might be UNIX-specific? -run(`chmod -w $filename`) -@test iswriteable(filename) == false -run(`chmod +w $filename`) -@test isexecutable(filename) == false -@test filesize(filename) == 0 -@test filesize(dir_name) > 0 -@test mtime(filename) >= mtime(dir_name) +run(`chmod -w $file`) +@test iswriteable(file) == false +run(`chmod +w $file`) +@test isexecutable(file) == false +@test filesize(file) == 0 +# On windows the filesize of a folder is the accumulation of all the contained +# files and is thus zero in this case. +@windows_only begin + @test filesize(dir) == 0 +end +@unix_only begin + @test filesize(dir) > 0 +end +@test mtime(file) >= mtime(dir) # rename file -newfilename = file_path(dir_name, "bfile.txt") -path_rename(filename, newfilename) -@test ispath(filename) == false -@test isfile(newfilename) == true -filename = newfilename +newfile = joinpath(dir, "bfile.txt") +mv(file, newfile) +@test ispath(file) == false +@test isfile(newfile) == true +file = newfile ####################################################################### # This section tests temporary file and directory creation. # @@ -57,16 +52,16 @@ filename = newfilename # path = tempname() # @test ispath(path) == false -# (filename, f) = mktemp() +# (file, f) = mktemp() # print(f, "Here is some text") # close(f) -# @test isfile(filename) == true -# @test readall(filename) == "Here is some text" +# @test isfile(file) == true +# @test readall(file) == "Here is some text" ############ # Clean up # ############ -file_remove(filename) -rmdir(dir_name) -@test ispath(filename) == false -@test ispath(dir_name) == false +rm(file) +rmdir(dir) +@test ispath(file) == false +@test ispath(dir) == false diff --git a/test/functional.jl b/test/functional.jl index 677cc4b8208c0..66cd622aa5814 100644 --- a/test/functional.jl +++ b/test/functional.jl @@ -2,7 +2,7 @@ # map -- array.jl @test isequal(map((x)->"$x"[end:end], [9:11]), ["9", "0", "1"]) -# TODO: @test map_to() +# TODO: @test map!() # map -- ranges.jl @test isequal(map(i->sqrt(i), 1:5), [sqrt(i) for i in 1:5]) @test isequal(map(i->sqrt(i), 2:6), [sqrt(i) for i in 2:6]) @@ -23,7 +23,7 @@ # mapreduce -- reduce.jl @test mapreduce(-, -, [-10 -9 -3]) == ((10 - 9) - 3) -@test mapreduce((x,y)->"($x+$y)", (x)->x[1:3], ["abcd", "efgh", "01234"]) == "((abc+efg)+012)" +@test mapreduce((x)->x[1:3], (x,y)->"($x+$y)", ["abcd", "efgh", "01234"]) == "((abc+efg)+012)" # filter -- array.jl @test isequal(filter(x->(x>1), [0 1 2 3 2 1 0]), [2, 3, 2]) diff --git a/test/git.jl b/test/git.jl new file mode 100644 index 0000000000000..c5af83c207037 --- /dev/null +++ b/test/git.jl @@ -0,0 +1,33 @@ +import Base.Git +include("gitutils.jl") + +dir = string("tmp.",randstring()) +@test !ispath(dir) +mkdir(dir) +@test isdir(dir) +try cd(dir) do + + run(`git init -q`) + run(`git commit -q --allow-empty -m "initial empty commit"`) + git_verify(Dict(), Dict(), Dict()) + + # each path can have one of these content in each of head, index, work + # for a total of length(contents)^3 = 4^3 = 64 combinations. + # each path can be in any of these 64 "superpositions" before & after + # for a total of 64^2 = 4096 files needed to test all transitions + # between before and after superpositions of git repo states. + + contents = [nothing, "foo", "bar", {"baz"=>"qux"}] + b = length(contents) + states = [ [ base(b,k,6) => contents[rem(div(k,b^p),b)+1] for k=0:(b^3)^2-1 ] for p=0:5 ] + + git_setup(states[1:3]...) + try Git.transact() do + git_setup(states[4:6]...) + throw(nothing) + end catch x + is(x,nothing) || rethrow() + end + git_verify(states[1:3]...) + +end finally run(`rm -rf $dir`) end diff --git a/test/gitutils.jl b/test/gitutils.jl new file mode 100644 index 0000000000000..6976c29256699 --- /dev/null +++ b/test/gitutils.jl @@ -0,0 +1,104 @@ +function mktree(d::Dict) + lstree = "" + for (name, data) in d + if isa(data, String) + sha1 = readchomp(`echo -n $data` | `git hash-object -w --stdin`) + lstree *= "100644 blob $sha1\t$name\n" + elseif isa(data, Dict) + sha1 = mktree(data) + lstree *= "040000 tree $sha1\t$name\n" + elseif is(data, nothing) + # ignore it + else + error("mktree: don't know what to do with $name => $data") + end + end + readchomp(`echo -n $lstree` | `git mktree`) +end + +function verify_tree(d::Dict, tree::String) + # check that tree matches d + seen = Set() + for line in eachline(`git ls-tree $tree`) + m = match(r"^(\d{6}) (\w+) ([0-9a-f]{40})\t(.*)$", line) + @test m != nothing + perm, kind, sha1, name = m.captures + @test has(d,name) + data = d[name] + if isa(data, String) + @test kind == "blob" + @test data == readall(`git cat-file blob $sha1`) + elseif isa(data, Dict) + @test kind == "tree" + verify_tree(data, sha1) + else + error("verify_tree: don't know what to do with $name => $data") + end + add!(seen, name) + end + # check that nothing was missing from tree + for (name, data) in d + @test is(data,nothing) || contains(seen,name) + end +end + +function verify_work(d::Dict) + # check what's in d + for (name, data) in d + if is(data, nothing) + @test !ispath(name) + continue + end + @test ispath(name) + if isa(data, String) + @test isfile(name) + @test readall(name) == data + elseif isa(data, Dict) + cd(name) do + verify_work(data) + end + else + error("verify_work: don't know what to do with $name => $data") + end + end + # check for anything that's not in d + for line in eachline(`ls -A`) + name = chomp(line) + @test name == ".git" || has(d,name) + end +end + +function git_verify(h::Dict, i::Dict, w::Dict) + verify_tree(h, "HEAD") + verify_tree(i, readchomp(`git write-tree`)) + verify_work(w) +end + +function git_setup(h::Dict, i::Dict, w::Dict, parents::String...) + # create tree objects + headt = mktree(h) + index = mktree(i) + work = mktree(w) + + # clear the repo + for line in eachline(`ls -A`) + name = chomp(line) + name == ".git" || run(`rm -rf $name`) + end + + # create the head commit + commit_tree = `git commit-tree $headt` + for parent in parents + commit_tree = `$commit_tree -p $parent` + end + head = readchomp(`echo $headt` | commit_tree) + run(`git reset -q --soft $head`) + + run(`git read-tree $work`) # read work into the index + run(`git checkout-index -fa`) # check the index out + run(`git read-tree $index`) # setup the index + + # verify that everything is as expected + git_verify(h, i, w) +end +git_setup(h::Dict, i::Dict, w::Dict) = git_setup(h, i, w, readchomp(`git rev-parse HEAD`)) diff --git a/test/glpk.jl b/test/glpk.jl deleted file mode 100644 index a9057e58019ec..0000000000000 --- a/test/glpk.jl +++ /dev/null @@ -1,55 +0,0 @@ -cd("../extras") do -require("glpk") - -# Same example as in the GLPK manual - -lp = GLPK.Prob() -GLPK.set_prob_name(lp, "sample") -GLPK.set_obj_dir(lp, GLPK.MAX) -GLPK.add_rows(lp, 3) -GLPK.set_row_name(lp, 1, "p") -GLPK.set_row_bnds(lp, 1, GLPK.UP, 0.0, 100.0) -GLPK.set_row_name(lp, 2, "q") -GLPK.set_row_bnds(lp, 2, GLPK.UP, 0.0, 600.0) -GLPK.set_row_name(lp, 3, "r") -GLPK.set_row_bnds(lp, 3, GLPK.UP, 0.0, 300.0) -GLPK.add_cols(lp, 3) -GLPK.set_col_name(lp, 1, "x1") -GLPK.set_col_bnds(lp, 1, GLPK.LO, 0.0, 0.0) -GLPK.set_obj_coef(lp, 1, 10.0) -GLPK.set_col_name(lp, 2, "x2") -GLPK.set_col_bnds(lp, 2, GLPK.LO, 0.0, 0.0) -GLPK.set_obj_coef(lp, 2, 6.0) -GLPK.set_col_name(lp, 3, "x3") -GLPK.set_col_bnds(lp, 3, GLPK.LO, 0.0, 0.0) -GLPK.set_obj_coef(lp, 3, 4.0) -ia = zeros(Int, 9) -ja = zeros(Int, 9) -ar = zeros(FloatingPoint, 9) -ia[1] = 1; ja[1] = 1; ar[1] = 1.0 -ia[2] = 1; ja[2] = 2; ar[2] = 1.0 -ia[3] = 1; ja[3] = 3; ar[3] = 1.0 -ia[4] = 2; ja[4] = 1; ar[4] = 10.0 -ia[5] = 3; ja[5] = 1; ar[5] = 2.0 -ia[6] = 2; ja[6] = 2; ar[6] = 4.0 -ia[7] = 3; ja[7] = 2; ar[7] = 2.0 -ia[8] = 2; ja[8] = 3; ar[8] = 5.0 -ia[9] = 3; ja[9] = 3; ar[9] = 6.0 -GLPK.load_matrix(lp, 9, ia, ja, ar) - -glp_param = GLPK.SimplexParam() -glp_param["msg_lev"] = GLPK.MSG_ERR - -flag = GLPK.simplex(lp, glp_param) -z = GLPK.get_obj_val(lp) -x1 = GLPK.get_col_prim(lp, 1) -x2 = GLPK.get_col_prim(lp, 2) -x3 = GLPK.get_col_prim(lp, 3) - -tol = 1e-10 -@test abs(z - 2200. / 3) < tol -@test abs(x1 - 100. / 3) < tol -@test abs(x2 - 200. / 3) < tol -@test abs(x3) < tol - -end # cd diff --git a/test/gzip.jl b/test/gzip.jl deleted file mode 100644 index 356e31982fbd9..0000000000000 --- a/test/gzip.jl +++ /dev/null @@ -1,246 +0,0 @@ -# Testing for gzip -require("extras/gzip") - -using GZip - -########################## -# test_context("GZip tests") -########################## - -#for epoch in 1:10 - -tmp = mktempdir() - -test_infile = "$JULIA_HOME/../share/julia/extras/gzip.jl" -test_compressed = "$tmp/gzip.jl.gz" - -@windows_only gunzip="gunzip.exe" -@unix_only gunzip="gunzip" - -test_gunzip = true -try - # TODO: Update for Windows - run(`which $gunzip` > "/dev/null") -catch - test_gunzip = false -end - -######################### -# test_group("Compress Test1: gzip.jl") -########################## - -data = open(readall, test_infile); - -gzfile = gzopen(test_compressed, "wb") -@test write(gzfile, data) == length(data) -@test close(gzfile) == Z_OK -@test close(gzfile) != Z_OK - -#@test throws_exception(write(gzfile, data), GZError) -@test_fails write(gzfile, data) - -if test_gunzip - data2 = readall(`$gunzip -c $test_compressed`) - @test data == data2 -end - -data3 = gzopen(readall, test_compressed) -@test data == data3 - -# Test gzfdio -raw_file = open(test_compressed, "r") -gzfile = gzdopen(fd(raw_file), "r") -data4 = readall(gzfile) -close(gzfile) -close(raw_file) -@test data == data4 - - -# Screw up the file -raw_file = open(test_compressed, "r+") -seek(raw_file, 3) # leave the gzip magic 2-byte header -write(raw_file, zeros(Uint8, 10)) -close(raw_file) - -#@test throws_exception(gzopen(readall, test_compressed), GZError) -@test_fails gzopen(readall, test_compressed) - - -########################## -# test_group("gzip file function tests (writing)") -########################## -gzfile = gzopen(test_compressed, "wb") -write(gzfile, data) == length(data) -@test flush(gzfile) == Z_OK - -pos = position(gzfile) -@test_fails seek(gzfile, 100) # can't seek backwards on write -@test position(gzfile) == pos -@test skip(gzfile, 100) -@test position(gzfile) == pos + 100 - -#@test throws_exception(truncate(gzfile, 100), ErrorException) -#@test throws_exception(seek_end(gzfile), ErrorException) -@test_fails truncate(gzfile, 100) -@test_fails seek_end(gzfile) - -@test close(gzfile) == Z_OK - - -########################## -# test_group("gzip file function tests (strategy read/write)") -########################## - -# rewrite the test file -modes = "fhR " -if GZip.ZLIB_VERSION >= (1,2,5,2) - modes = "fhRFT " -end -for ch in modes - if ch == ' ' - ch = "" - end - for level = 0:9 - gzfile = gzopen(test_compressed, "wb$level$ch") - @test write(gzfile, data) == length(data) - @test close(gzfile) == Z_OK - - file_size = filesize(test_compressed) - - #println("wb$level$ch: ", file_size) - - if ch == 'T' - @test(file_size == length(data)) - elseif ch == 'F' - @test(file_size >= length(data)) - elseif level == 0 - @test(file_size > length(data)) - else - @test(file_size < length(data)) - end - - # readline test - gzf = gzopen(test_compressed) - s = memio() - while !eof(gzf) - write(s, readline(gzf)) - end - data2 = takebuf_string(s); - - # readuntil test - seek(gzf, 0) - while !eof(gzf) - write(s, readuntil(gzf, 'a')) - end - data3 = takebuf_string(s); - close(gzf) - - @test(data == data2) - @test(data == data3) - - end -end - -########################## -# test_group("gzip array/matrix tests (write/read)") -########################## - -let BUFSIZE = 65536 - for level = 0:3:6 - for T in [Int8,Uint8,Int16,Uint16,Int32,Uint32,Int64,Uint64,Int128,Uint128, - Float32,Float64,Complex64,Complex128] - - minval = 34567 - try - minval = min(typemax(T), 34567) - catch - # do nothing - end - - # Ordered array - b = zeros(T, BUFSIZE) - if !isa(T, Complex) - for i = 1:length(b) - b[i] = (i-1)%minval; - end - else - for i = 1:length(b) - b[i] = (i-1)%minval - (minval-(i-1))%minval * im - end - end - - # Random array - if isa(T, FloatingPoint) - r = (T)[rand(BUFSIZE)...]; - elseif isa(T, Complex64) - r = Int32[rand(BUFSIZE)...] + Int32[rand(BUFSIZE)...] * im - elseif isa(T, Complex128) - r = Int64[rand(BUFSIZE)...] + Int64[rand(BUFSIZE)...] * im - else - r = b[randi((1,BUFSIZE), BUFSIZE)]; - end - - # Array file - b_array_fn = "$tmp/b_array.raw.gz" - r_array_fn = "$tmp/r_array.raw.gz" - - gzaf_b = gzopen(b_array_fn, "w$level") - write(gzaf_b, b) - close(gzaf_b) - - #println("$T ($level) ordered: $(filesize(b_array_fn))") - - gzaf_r = gzopen(r_array_fn, "w$level") - write(gzaf_r, r) - close(gzaf_r) - - #println("$T ($level) random: $(filesize(r_array_fn))") - - b2 = zeros(T, BUFSIZE) - r2 = zeros(T, BUFSIZE) - - b2_infile = gzopen(b_array_fn) - read(b2_infile, b2); - close(b2_infile) - - r2_infile = gzopen(r_array_fn) - read(r2_infile, r2); - close(r2_infile) - - @test b == b2 - @test r == r2 - end - end -end - -########################## -# test_group("gzip unicode tests (write/read)") -########################## - -unicode_gz_file = "$tmp/unicode_test.gz" - -str1 = CharString(reinterpret(Char, read(open("$JULIA_HOME/../share/julia/test/unicode/UTF-32LE.unicode"), Uint32, 1112065)[2:])); -str2 = UTF8String(read(open("$JULIA_HOME/../share/julia/test/unicode/UTF-8.unicode"), Uint8, 4382595)[4:]); - -UTF32LE_gz = gzopen(unicode_gz_file, "w") -write(UTF32LE_gz, str1) -close(UTF32LE_gz) - -str1b = readall(`gunzip -c $unicode_gz_file`); -str1c = gzopen(readall, unicode_gz_file); -@test str1 == str1b -@test str1 == str1c - -UTF8_gz = gzopen(unicode_gz_file, "w"); -write(UTF8_gz, str2) -close(UTF8_gz) - -str2b = readall(`gunzip -c $unicode_gz_file`); -str2c = gzopen(readall, unicode_gz_file); -@test str2 == str2b -@test str2 == str2c - - -run(`rm -Rf $tmp`) - -#end # for epoch diff --git a/test/image.jl b/test/image.jl deleted file mode 100644 index 9c512cb5b4846..0000000000000 --- a/test/image.jl +++ /dev/null @@ -1,7 +0,0 @@ -require("extras/image") - -all_close(ar, v) = all(abs(ar-v) .< sqrt(eps(v))) - -@test all_close(imfilter(ones(4,4), ones(3,3)), 9.0) -@test all_close(imfilter(ones(3,3), ones(3,3)), 9.0) -@test all_close(imfilter(ones(3,3), [1 1 1;1 0.0 1;1 1 1]), 8.0) diff --git a/test/iostring.jl b/test/iostring.jl new file mode 100644 index 0000000000000..1c8456b5d0a16 --- /dev/null +++ b/test/iostring.jl @@ -0,0 +1,117 @@ +ioslength(io::IOString) = (io.seekable ? io.size : nb_available(io)) + +let io = IOString() +@assert eof(io) +@assert try read(io,Uint8); false; catch e; isa(e,EOFError); end +@assert write(io,"abc") == 3 +@assert ioslength(io) == 3 +@assert position(io) == 3 +@assert eof(io) +@assert seek(io, 0) +@assert read(io, Uint8) == 'a' +a = Array(Uint8, 2) +@assert read(io, a) == a +@assert a == ['b','c'] +@assert bytestring(io) == "abc" +@assert seek(io, 1) +@assert truncate(io, 2) +@assert position(io) == 1 +@assert !eof(io) +@assert seek_end(io) +@assert position(io) == 2 +@assert truncate(io, 0) +@assert position(io) == 0 +@assert truncate(io, 10) +@assert position(io) == 0 +@assert all(io.data .== 0) +@assert write(io,Int16[1,2,3,4,5,6]) == 12 +@assert seek(io,2) +@assert truncate(io, 10) +@assert ioslength(io) == 10 +io.readable = false +@assert try read(io,Uint8[0]); false; catch e; true; end +@assert truncate(io, 0) +@assert write(io,"boston\ncambridge\n") > 0 +@assert takebuf_string(io) == "boston\ncambridge\n" +@assert takebuf_string(io) == "" +close(io) +@assert try write(io,Uint8[0]); false; catch e; true; end +@assert try seek(io,0); false; catch e; true; end +@assert eof(io) +end + +let io = IOString("hamster\nguinea pig\nturtle") +@assert position(io) == 0 +@assert readline(io) == "hamster\n" +@assert readall(io) == "guinea pig\nturtle" +@assert try read(io,Uint8); false; catch e; isa(e,EOFError); end +@assert seek(io,0) +@assert read(io,Uint8) == 'h' +@assert try truncate(io,0); false; catch e; true; end +@assert try write(io,uint8(0)); false; catch e; true; end +@assert try write(io,Uint8[0]); false; catch e; true; end +@assert takebuf_string(io) == "hamster\nguinea pig\nturtle" +@assert takebuf_string(io) == "hamster\nguinea pig\nturtle" #should be unchanged +close(io) +end + +let io = PipeString() +@assert try read(io,Uint8); false; catch e; isa(e,EOFError); end +@assert write(io,"pancakes\nwaffles\nblueberries\n") > 0 +@assert position(io) == 0 +@assert readline(io) == "pancakes\n" +Base.compact(io) +@assert readline(io) == "waffles\n" +@assert write(io,"whipped cream\n") > 0 +@assert readline(io) == "blueberries\n" +@assert try seek(io,0); false; catch e; true; end +@assert try truncate(io,0); false; catch e; true; end +@assert readline(io) == "whipped cream\n" +Base.compact(io) +@assert position(io) == 0 +@assert ioslength(io) == 0 +Base.ensureroom(io,50) +@assert position(io) == 0 +@assert ioslength(io) == 0 +@assert length(io.data) == 50 +Base.ensureroom(io,10) +@assert ioslength(io) == 0 +@assert length(io.data) == 50 +io.maxsize = 75 +Base.ensureroom(io,100) +@assert ioslength(io) == 0 +@assert length(io.data) == 75 +@assert seek_end(io) +@assert ioslength(io) == 0 +@assert position(io) == 0 +write(io,zeros(Uint8,200)) +@assert ioslength(io) == 75 +@assert length(io.data) == 75 +write(io,1) +@assert ioslength(io) == 75 +@assert length(io.data) == 75 +write(io,[1,2,3]) +@assert ioslength(io) == 75 +@assert length(io.data) == 75 +skip(io,1) +@assert write(io,uint8(104)) == 1 +skip(io,3) +@assert write(io,"apples".data) == 3 +skip(io,71) +@assert write(io,'y') == 1 +@assert readall(io) == "happy" +@assert eof(io) +write(io,zeros(Uint8,73)) +write(io,'a') +write(io,'b') +write(io,'c') +write(io,'d') +write(io,'e') +@assert ioslength(io) == 75 +@assert length(io.data) == 75 +@assert position(io) == 0 +skip(io,72) +@assert takebuf_string(io) == "\0ab" +@assert takebuf_string(io) == "" +close(io) +end diff --git a/test/iterators.jl b/test/iterators.jl index 486f0b3528fcd..280e3a05959fa 100644 --- a/test/iterators.jl +++ b/test/iterators.jl @@ -1,11 +1,12 @@ -require("extras/iterators") +require("iterators") + using Iterators # aux function emulating a comprehension [x for x in f] function buildvec(f) v = Any[] for i = f - push(v, i) + push!(v, i) end return v end diff --git a/test/keywordargs.jl b/test/keywordargs.jl new file mode 100644 index 0000000000000..026d340559686 --- /dev/null +++ b/test/keywordargs.jl @@ -0,0 +1,83 @@ +# simple keyword args case +kwf1(ones; tens=0, hundreds=0) = ones + 10*tens + 100*hundreds +@test kwf1(2) == 2 +@test kwf1(2, hundreds=6) == 602 +@test kwf1(2, tens=6) == 62 +@test kwf1(1, hundreds=2, tens=7) == 271 +@test kwf1(3, tens=7, hundreds=2) == 273 + +@test_fails kwf1() # no method, too few args +@test_fails kwf1(1, z=0) # unsupported keyword +@test_fails kwf1(1, 2) # no method, too many positional args + +# keyword args plus varargs +kwf2(x, rest...; y=1) = (x, y, rest) +@test isequal(kwf2(0), (0, 1, ())) +@test isequal(kwf2(0,1,2), (0, 1, (1,2))) +@test isequal(kwf2(0,1,2,y=88), (0, 88, (1,2))) +@test isequal(kwf2(0,y=88,1,2), (0, 88, (1,2))) +@test_fails kwf2(0, z=1) +@test_fails kwf2(y=1) + +# keyword arg with declared type +kwf3(x; y::Float64 = 1.0) = x + y +@test kwf3(2) == 3.0 +@test kwf3(2, y=3.0) == 5.0 +@test_fails kwf3(2, y=3) # wrong type keyword + +# function with only keyword args +kwf4(;a=1,b=2) = (a,b) +@test isequal(kwf4(), (1,2)) +@test isequal(kwf4(b=10), (1,10)) + +# rest keywords +kwdelegator(ones;kw...) = kwf1(ones;kw...) +@test kwdelegator(4,hundreds=8) == 804 + +# optional positional args +opaf1(a,b=1,c=2,d=3) = (a,b,c,d) +@test isequal(opaf1(0), (0,1,2,3)) +@test isequal(opaf1(0,2), (0,2,2,3)) +@test isequal(opaf1(0,2,4), (0,2,4,3)) +@test isequal(opaf1(0,2,4,6), (0,2,4,6)) +@test_fails opaf1() +@test_fails opaf1(0,1,2,3,4) + +# optional positional plus varargs +opaf2(a=1,rest...) = (a,rest) +@test isequal(opaf2(), (1,())) +@test isequal(opaf2(2), (2,())) +@test isequal(opaf2(2,3), (2,(3,))) + +# optional positional plus keyword args +opkwf1(a=0,b=1;k=2) = (a,b,k) +@test isequal(opkwf1(), (0,1,2)) +@test isequal(opkwf1(10), (10,1,2)) +@test isequal(opkwf1(10,20), (10,20,2)) +@test_fails opkwf1(10,20,30) +@test isequal(opkwf1(10,20,k=8), (10,20,8)) +@test isequal(opkwf1(11;k=8), (11, 1,8)) +@test isequal(opkwf1(k=8), ( 0, 1,8)) + +# dictionaries as keywords +@test kwf1(4; {:hundreds=>9, :tens=>5}...) == 954 + +# with inner function +let + function kwf_maker() + f(;k=0) = 2k+1 + end + kwf5 = kwf_maker() + @test kwf5() == 1 + @test kwf5(k=2) == 5 + @test_fails kwf5(1) +end + +# with every feature! +extravagant_args(x,y=0,rest...;color="blue",kw...) = + (x,y,rest,color,kwf1(6;tens=8,kw...)) + +@test isequal(extravagant_args(1), (1,0,(),"blue",86)) +@test isequal(extravagant_args(1;hundreds=7), (1,0,(),"blue",786)) +@test isequal(extravagant_args(1,2,3;{:color=>"red", :hundreds=>3}...), + (1,2,(3,),"red",386)) diff --git a/test/linalg.jl b/test/linalg.jl index 5b264e2fedfca..de45c31630197 100644 --- a/test/linalg.jl +++ b/test/linalg.jl @@ -4,122 +4,147 @@ a = rand(n,n) b = rand(n) for elty in (Float32, Float64, Complex64, Complex128) a = convert(Matrix{elty}, a) - asym = a' + a # symmetric indefinite - apd = a'*a # symmetric positive-definite + asym = a' + a # symmetric indefinite + apd = a'*a # symmetric positive-definite b = convert(Vector{elty}, b) - capd = chold(apd) # upper Cholesky factor - r = factors(capd) - @assert_approx_eq r'*r apd - @assert_approx_eq b apd * (capd\b) - @assert_approx_eq apd * inv(capd) eye(elty, n) - @assert_approx_eq a*(capd\(a'*b)) b # least squares soln for square a - @assert_approx_eq det(capd) det(apd) - - l = factors(chold(apd, false)) # lower Cholesky factor - @assert_approx_eq l*l' apd - - cpapd = cholpd(apd) # pivoted Choleksy decomposition + capd = cholfact(apd) # upper Cholesky factor + r = capd[:U] + @test_approx_eq r'*r apd + @test_approx_eq b apd * (capd\b) + @test_approx_eq apd * inv(capd) eye(elty, n) + @test_approx_eq a*(capd\(a'*b)) b # least squares soln for square a + @test_approx_eq det(capd) det(apd) + + l = cholfact(apd, :L)[:L] # lower Cholesky factor + @test_approx_eq l*l' apd + + cpapd = cholpfact(apd) # pivoted Choleksy decomposition @test rank(cpapd) == n - @test all(diff(diag(real(cpapd.LR))).<=0.) # diagonal show be non-increasing - @assert_approx_eq b apd * (cpapd\b) - @assert_approx_eq apd * inv(cpapd) eye(elty, n) - - bc1 = BunchKaufman(asym) # Bunch-Kaufman factor of indefinite matrix - @assert_approx_eq inv(bc1) * asym eye(elty, n) - @assert_approx_eq asym * (bc1\b) b - bc2 = BunchKaufman(apd) # Bunch-Kaufman factors of a pos-def matrix - @assert_approx_eq inv(bc2) * apd eye(elty, n) - @assert_approx_eq apd * (bc2\b) b - - lua = lud(a) # LU decomposition - l,u,p = lu(a) - L,U,P = factors(lua) - @test l == L && u == U && p == P - @assert_approx_eq l*u a[p,:] - @assert_approx_eq l[invperm(p),:]*u a - @assert_approx_eq a * inv(lua) eye(elty, n) - @assert_approx_eq a*(lua\b) b - - qra = qrd(a) # QR decomposition - q,r = factors(qra) - @assert_approx_eq q'*q eye(elty, n) - @assert_approx_eq q*q' eye(elty, n) - Q,R = qr(a) - @test q == Q && r == R - @assert_approx_eq q*r a - @assert_approx_eq qra*b Q*b - @assert_approx_eq qra'*b Q'*b - @assert_approx_eq a*(qra\b) b - - qrpa = qrpd(a) # pivoted QR decomposition - q,r,p = factors(qrpa) - @assert_approx_eq q'*q eye(elty, n) - @assert_approx_eq q*q' eye(elty, n) - Q,R,P = qrp(a) - @test q == Q && r == R && p == P - @assert_approx_eq q*r a[:,p] - @assert_approx_eq q*r[:,invperm(p)] a - @assert_approx_eq a*(qrpa\b) b - - d,v = eig(asym) # symmetric eigen-decomposition - @assert_approx_eq asym*v[:,1] d[1]*v[:,1] - @assert_approx_eq v*diagmm(d,v') asym - - d,v = eig(a) # non-symmetric eigen decomposition - for i in 1:size(a,2) @assert_approx_eq a*v[:,i] d[i]*v[:,i] end - - u,s,vt = svd(a) # singular value decomposition - @assert_approx_eq u*diagmm(s,vt) a + @test all(diff(diag(real(cpapd.UL))).<=0.) # diagonal should be non-increasing + @test_approx_eq b apd * (cpapd\b) + @test_approx_eq apd * inv(cpapd) eye(elty, n) + + bc1 = BunchKaufman(asym) # Bunch-Kaufman factor of indefinite matrix + @test_approx_eq inv(bc1) * asym eye(elty, n) + @test_approx_eq asym * (bc1\b) b + bc2 = BunchKaufman(apd) # Bunch-Kaufman factors of a pos-def matrix + @test_approx_eq inv(bc2) * apd eye(elty, n) + @test_approx_eq apd * (bc2\b) b + + lua = lufact(a) # LU decomposition + l,u,p = lua[:L], lua[:U], lua[:p] + @test_approx_eq l*u a[p,:] + @test_approx_eq l[invperm(p),:]*u a + @test_approx_eq a * inv(lua) eye(elty, n) + @test_approx_eq a*(lua\b) b + + qra = qrfact(a) # QR decomposition + q,r = qra[:Q], qra[:R] + @test_approx_eq q'*full(q, false) eye(elty, n) + @test_approx_eq q*full(q, false)' eye(elty, n) + @test_approx_eq q*r a + @test_approx_eq a*(qra\b) b + + qrpa = qrpfact(a) # pivoted QR decomposition + q,r,p = qrpa[:Q], qrpa[:R], qrpa[:p] + @test_approx_eq q'*full(q, false) eye(elty, n) + @test_approx_eq q*full(q, false)' eye(elty, n) + @test_approx_eq q*r a[:,p] + @test_approx_eq q*r[:,invperm(p)] a + @test_approx_eq a*(qrpa\b) b + + d,v = eig(asym) # symmetric eigen-decomposition + @test_approx_eq asym*v[:,1] d[1]*v[:,1] + @test_approx_eq v*diagmm(d,v') asym + + d,v = eig(a) # non-symmetric eigen decomposition + for i in 1:size(a,2) @test_approx_eq a*v[:,i] d[i]*v[:,i] end + + f = schurfact(a) # Schur + @test_approx_eq f[:vectors]*f[:Schur]*f[:vectors]' a + @test_approx_eq sort(real(f[:values])) sort(real(d)) + @test_approx_eq sort(imag(f[:values])) sort(imag(d)) + @test istriu(f[:Schur]) || isreal(a) + + f = schurfact(a[1:5,1:5], a[6:10,6:10]) # Generalized Schur + @test_approx_eq f[:Q]*f[:S]*f[:Z]' a[1:5,1:5] + @test_approx_eq f[:Q]*f[:T]*f[:Z]' a[6:10,6:10] + @test istriu(f[:S]) || isreal(a) + @test istriu(f[:T]) || isreal(a) + + usv = svdfact(a) # singular value decomposition + @test_approx_eq usv[:U]*diagmm(usv[:S],usv[:Vt]) a + gsvd = svdfact(a,a[1:5,:]) # Generalized svd + @test_approx_eq gsvd[:U]*gsvd[:D1]*gsvd[:R]*gsvd[:Q]' a + @test_approx_eq gsvd[:V]*gsvd[:D2]*gsvd[:R]*gsvd[:Q]' a[1:5,:] + x = a \ b - @assert_approx_eq a*x b + @test_approx_eq a*x b x = triu(a) \ b - @assert_approx_eq triu(a)*x b + @test_approx_eq triu(a)*x b x = tril(a)\b - @assert_approx_eq tril(a)*x b + @test_approx_eq tril(a)*x b - # Test null - bnull = null(b') - @assert_approx_eq_eps norm(b'bnull) zero(elty) n*eps(one(elty)) - @assert_approx_eq_eps norm(bnull'b) zero(elty) n*eps(one(elty)) + # Test null + a15null = null(a[:,1:5]') + @test_approx_eq_eps norm(a[:,1:5]'a15null) zero(elty) n*eps(real(one(elty))) + @test_approx_eq_eps norm(a15null'a[:,1:5]) zero(elty) n*eps(real(one(elty))) @test size(null(b), 2) == 0 - # Test pinv - pinvb = pinv(b) - @assert_approx_eq b*pinvb*b b - @assert_approx_eq pinvb*b*pinvb pinvb + # Test pinv + pinva15 = pinv(a[:,1:5]) + @test_approx_eq a[:,1:5]*pinva15*a[:,1:5] a[:,1:5] + @test_approx_eq pinva15*a[:,1:5]*pinva15 pinva15 - # Complex vector rhs + # Complex vector rhs x = a\complex(b) - @assert_approx_eq a*x complex(b) + @test_approx_eq a*x complex(b) + + # Test cond + @test_approx_eq_eps cond(a, 1) 4.837320054554436e+02 0.01 + @test_approx_eq_eps cond(a, 2) 1.960057871514615e+02 0.01 + @test_approx_eq_eps cond(a, Inf) 3.757017682707787e+02 0.01 + @test_approx_eq_eps cond(a[:,1:5]) 10.233059337453463 0.01 + + # Matrix square root + asq = sqrtm(a) + @test_approx_eq asq*asq a + asymsq = sqrtm(asym) + @test_approx_eq asymsq*asymsq asym end + +## Least squares solutions a = [ones(20) 1:20 1:20] b = reshape(eye(8, 5), 20, 2) for elty in (Float32, Float64, Complex64, Complex128) a = convert(Matrix{elty}, a) b = convert(Matrix{elty}, b) - # Least squares - x = a[:,1:2]\b[:,1] # Vector rhs - @assert_approx_eq ((a[:,1:2]*x-b[:,1])'*(a[:,1:2]*x-b[:,1]))[1] convert(elty, 2.546616541353384) + x = a[:,1:2]\b[:,1] # Vector rhs + @test_approx_eq ((a[:,1:2]*x-b[:,1])'*(a[:,1:2]*x-b[:,1]))[1] convert(elty, 2.546616541353384) - x = a[:,1:2]\b # Matrix rhs - @assert_approx_eq det((a[:,1:2]*x-b)'*(a[:,1:2]*x-b)) convert(elty, 4.437969924812031) - - x = a\b # Rank deficient - @assert_approx_eq det((a*x-b)'*(a*x-b)) convert(elty, 4.437969924812031) + x = a[:,1:2]\b # Matrix rhs + @test_approx_eq det((a[:,1:2]*x-b)'*(a[:,1:2]*x-b)) convert(elty, 4.437969924812031) + + x = a\b # Rank deficient + @test_approx_eq det((a*x-b)'*(a*x-b)) convert(elty, 4.437969924812031) - # symmetric, positive definite - @assert_approx_eq inv(convert(Matrix{elty}, [6. 2; 2 1])) convert(Matrix{elty}, [0.5 -1; -1 3]) - # symmetric, negative definite - @assert_approx_eq inv(convert(Matrix{elty}, [1. 2; 2 1])) convert(Matrix{elty}, [-1. 2; 2 -1]/3) + # Underdetermined minimum norm + x = convert(Matrix{elty}, [1 0 0; 0 1 -1]) \ convert(Vector{elty}, [1,1]) + @test_approx_eq x convert(Vector{elty}, [1, 0.5, -0.5]) + + # symmetric, positive definite + @test_approx_eq inv(convert(Matrix{elty}, [6. 2; 2 1])) convert(Matrix{elty}, [0.5 -1; -1 3]) + # symmetric, negative definite + @test_approx_eq inv(convert(Matrix{elty}, [1. 2; 2 1])) convert(Matrix{elty}, [-1. 2; 2 -1]/3) end ## Test Julia fallbacks to BLAS routines -# matrices with zero dimensions + # matrices with zero dimensions @test ones(0,5)*ones(5,3) == zeros(0,3) @test ones(3,5)*ones(5,0) == zeros(3,0) @test ones(3,0)*ones(0,4) == zeros(3,4) @@ -127,7 +152,7 @@ end @test ones(0,0)*ones(0,4) == zeros(0,4) @test ones(3,0)*ones(0,0) == zeros(3,0) @test ones(0,0)*ones(0,0) == zeros(0,0) -# 2x2 + # 2x2 A = [1 2; 3 4] B = [5 6; 7 8] @test A*B == [19 22; 43 50] @@ -140,7 +165,7 @@ Bi = B+(2.5*im).*A[[2,1],[2,1]] @test Ac_mul_B(Ai, Bi) == [68.5-12im 57.5-28im; 88-3im 76.5-25im] @test A_mul_Bc(Ai, Bi) == [64.5+5.5im 43+31.5im; 104-18.5im 80.5+31.5im] @test Ac_mul_Bc(Ai, Bi) == [-28.25-66im 9.75-58im; -26-89im 21-73im] -# 3x3 + # 3x3 A = [1 2 3; 4 5 6; 7 8 9]-5 B = [1 0 5; 6 -10 3; 2 -4 -1] @test A*B == [-26 38 -27; 1 -4 -6; 28 -46 15] @@ -153,7 +178,7 @@ Bi = B+(2.5*im).*A[[2,1,3],[2,3,1]] @test Ac_mul_B(Ai, Bi) == [-21+2im -1.75+49im -51.25+19.5im; 25.5+56.5im -7-35.5im 22+35.5im; -3+12im -32.25+43im -34.75-2.5im] @test A_mul_Bc(Ai, Bi) == [-20.25+15.5im -28.75-54.5im 22.25+68.5im; -12.25+13im -15.5+75im -23+27im; 18.25+im 1.5+94.5im -27-54.5im] @test Ac_mul_Bc(Ai, Bi) == [1+2im 20.75+9im -44.75+42im; 19.5+17.5im -54-36.5im 51-14.5im; 13+7.5im 11.25+31.5im -43.25-14.5im] -# Generic integer matrix multiplication + # Generic integer matrix multiplication A = [1 2 3; 4 5 6] - 3 B = [2 -2; 3 -5; -4 7] @test A*B == [-7 9; -4 9] @@ -161,17 +186,17 @@ B = [2 -2; 3 -5; -4 7] A = ones(Int, 2, 100) B = ones(Int, 100, 3) @test A*B == [100 100 100; 100 100 100] -A = randi(20, 5, 5) - 10 -B = randi(20, 5, 5) - 10 +A = rand(1:20, 5, 5) - 10 +B = rand(1:20, 5, 5) - 10 @test At_mul_B(A, B) == A'*B @test A_mul_Bt(A, B) == A*B' -# Preallocated + # Preallocated C = Array(Int, size(A, 1), size(B, 2)) @test A_mul_B(C, A, B) == A*B @test At_mul_B(C, A, B) == A'*B @test A_mul_Bt(C, A, B) == A*B' @test At_mul_Bt(C, A, B) == A'*B' -# matrix algebra with subarrays of floats (stride != 1) + # matrix algebra with subarrays of floats (stride != 1) A = reshape(float64(1:20),5,4) Aref = A[1:2:end,1:2:end] Asub = sub(A, 1:2:5, 1:2:4) @@ -184,7 +209,7 @@ Aref = Ai[1:2:end,1:2:end] Asub = sub(Ai, 1:2:5, 1:2:4) @test Ac_mul_B(Asub, Asub) == Ac_mul_B(Aref, Aref) @test A_mul_Bc(Asub, Asub) == A_mul_Bc(Aref, Aref) -# syrk & herk + # syrk & herk A = reshape(1:1503, 501, 3)-750.0 res = float64([135228751 9979252 -115270247; 9979252 10481254 10983256; -115270247 10983256 137236759]) @test At_mul_B(A, A) == res @@ -199,13 +224,13 @@ Asub = sub(Ai, 1:2:2*cutoff, 1:3) Aref = Ai[1:2:2*cutoff, 1:3] @test Ac_mul_B(Asub, Asub) == Ac_mul_B(Aref, Aref) -# Matrix exponential + # Matrix exponential for elty in (Float32, Float64, Complex64, Complex128) A1 = convert(Matrix{elty}, [4 2 0; 1 4 1; 1 1 4]) eA1 = convert(Matrix{elty}, [147.866622446369 127.781085523181 127.781085523182; 183.765138646367 183.765138646366 163.679601723179; 71.797032399996 91.8825693231832 111.968106246371]') - @assert_approx_eq expm(A1) eA1 + @test_approx_eq expm(A1) eA1 A2 = convert(Matrix{elty}, [29.87942128909879 0.7815750847907159 -2.289519314033932; @@ -215,29 +240,40 @@ for elty in (Float32, Float64, Complex64, Complex128) [ 5496313853692458.0 -18231880972009236.0 -30475770808580460.0; -18231880972009252.0 60605228702221920.0 101291842930249760.0; -30475770808580480.0 101291842930249728.0 169294411240851968.0]) - @assert_approx_eq expm(A2) eA2 + @test_approx_eq expm(A2) eA2 A3 = convert(Matrix{elty}, [-131 19 18;-390 56 54;-387 57 52]) eA3 = convert(Matrix{elty}, [-1.50964415879218 -5.6325707998812 -4.934938326092; 0.367879439109187 1.47151775849686 1.10363831732856; 0.135335281175235 0.406005843524598 0.541341126763207]') - @assert_approx_eq expm(A3) eA3 + @test_approx_eq expm(A3) eA3 + + # Hessenberg + @test_approx_eq hessfact(A1)[:H] convert(Matrix{elty}, + [4.000000000000000 -1.414213562373094 -1.414213562373095 + -1.414213562373095 4.999999999999996 -0.000000000000000 + 0 -0.000000000000002 3.000000000000000]) end -# matmul for types w/o sizeof (issue #1282) +# Hermitian matrix exponential +A1 = randn(4,4) + im*randn(4,4) +A2 = A1 + A1' +@test_approx_eq expm(A2) expm(Hermitian(A2)) + + # matmul for types w/o sizeof (issue #1282) A = Array(ComplexPair{Int},10,10) A[:] = complex(1,1) A2 = A^2 @test A2[1,1] == 20im -# basic tridiagonal operations + # basic tridiagonal operations n = 5 d = 1 + rand(n) dl = -rand(n-1) du = -rand(n-1) v = randn(n) B = randn(n,2) -# Woodbury + # Woodbury U = randn(n,2) V = randn(2,n) C = randn(2,2) @@ -255,98 +291,227 @@ for elty in (Float32, Float64, Complex64, Complex128) F[i+1,i] = dl[i] end @test full(T) == F + # elementary operations on tridiagonals + @test conj(T) == Tridiagonal(conj(dl), conj(d), conj(du)) + @test transpose(T) == Tridiagonal(du, d, dl) + @test ctranspose(T) == Tridiagonal(conj(du), conj(d), conj(dl)) + # test interconversion of Tridiagonal and SymTridiagonal + @test Tridiagonal(dl, d, dl) == SymTridiagonal(d, dl) + @test Tridiagonal(dl, d, du) + Tridiagonal(du, d, dl) == SymTridiagonal(2d, dl+du) + @test SymTridiagonal(d, dl) + Tridiagonal(du, d, du) == SymTridiagonal(2d, dl+du) - # tridiagonal linear algebra + # tridiagonal linear algebra v = convert(Vector{elty}, v) - @assert_approx_eq T*v F*v + @test_approx_eq T*v F*v invFv = F\v - @assert_approx_eq T\v invFv - @assert_approx_eq solve(T,v) invFv + @test_approx_eq T\v invFv + @test_approx_eq solve(T,v) invFv B = convert(Matrix{elty}, B) - @assert_approx_eq solve(T, B) F\B - Tlu = lud(T) + @test_approx_eq solve(T, B) F\B + Tlu = LUTridiagonal(copy(T)) x = Tlu\v - @assert_approx_eq x invFv - @assert_approx_eq det(T) det(F) - - # symmetric tridiagonal + @test_approx_eq x invFv + @test_approx_eq det(T) det(F) + # symmetric tridiagonal Ts = SymTridiagonal(d, dl) Fs = full(Ts) invFsv = Fs\v Tldlt = ldltd(Ts) x = Tldlt\v - @assert_approx_eq x invFsv - - # eigenvalues/eigenvectors of symmetric tridiagonal + @test_approx_eq x invFsv + # eigenvalues/eigenvectors of symmetric tridiagonal if elty === Float32 || elty === Float64 DT, VT = eig(Ts) D, Vecs = eig(Fs) - @assert_approx_eq DT D - @assert_approx_eq abs(VT'Vecs) eye(elty, n) + @test_approx_eq DT D + @test_approx_eq abs(VT'Vecs) eye(elty, n) end - - # Woodbury + # Woodbury U = convert(Matrix{elty}, U) V = convert(Matrix{elty}, V) C = convert(Matrix{elty}, C) W = Woodbury(T, U, C, V) F = full(W) - @assert_approx_eq W*v F*v - @assert_approx_eq W\v F\v - @assert_approx_eq det(W) det(F) + @test_approx_eq W*v F*v + @test_approx_eq W\v F\v + @test_approx_eq det(W) det(F) + + # Diagonal + D = Diagonal(d) + DM = diagm(d) + @test_approx_eq D*v DM*v + @test_approx_eq D*U DM*U + @test_approx_eq D\v DM\v + @test_approx_eq D\U DM\U + @test_approx_eq det(D) det(DM) # Test det(A::Matrix) # In the long run, these tests should step through Strang's # axiomatic definition of determinants. # If all axioms are satisfied and all the composition rules work, # all determinants will be correct except for floating point errors. - + # The determinant of the identity matrix should always be 1. for i = 1:10 A = eye(elty, i) - @assert_approx_eq det(A) one(elty) + @test_approx_eq det(A) one(elty) end - + # The determinant of a Householder reflection matrix should always be -1. for i = 1:10 A = eye(elty, 10) A[i, i] = -one(elty) - @assert_approx_eq det(A) -one(elty) + @test_approx_eq det(A) -one(elty) end - + # The determinant of a rotation matrix should always be 1. for theta = convert(Vector{elty}, pi ./ [1:4]) R = [cos(theta) -sin(theta); sin(theta) cos(theta)] - @assert_approx_eq convert(elty, det(R)) one(elty) + @test_approx_eq convert(elty, det(R)) one(elty) end - + # issue 1490 - @assert_approx_eq_eps det(ones(elty, 3,3)) zero(elty) 3*eps(one(elty)) + @test_approx_eq_eps det(ones(elty, 3,3)) zero(elty) 3*eps(real(one(elty))) end -# LAPACK tests -srand(112) + # LAPACK tests Ainit = randn(5,5) for elty in (Float32, Float64, Complex64, Complex128) - # syevr! + # syevr! A = convert(Array{elty, 2}, Ainit) Asym = A'A - Z = Array(elty, 5, 5) - vals = LAPACK.syevr!(copy(Asym), Z) - @assert_approx_eq Z*diagmm(vals, Z') Asym + vals, Z = LinAlg.LAPACK.syevr!('V', copy(Asym)) + @test_approx_eq Z*diagmm(vals, Z') Asym @test all(vals .> 0.0) - @assert_approx_eq LAPACK.syevr!('N','V','U',copy(Asym),0.0,1.0,4,5,zeros(elty,0,0),-1.0) vals[vals .< 1.0] - @assert_approx_eq LAPACK.syevr!('N','I','U',copy(Asym),0.0,1.0,4,5,zeros(elty,0,0),-1.0) vals[4:5] - @assert_approx_eq vals LAPACK.syev!('N','U',copy(Asym)) + @test_approx_eq LinAlg.LAPACK.syevr!('N','V','U',copy(Asym),0.0,1.0,4,5,-1.0)[1] vals[vals .< 1.0] + @test_approx_eq LinAlg.LAPACK.syevr!('N','I','U',copy(Asym),0.0,1.0,4,5,-1.0)[1] vals[4:5] + @test_approx_eq vals LinAlg.LAPACK.syev!('N','U',copy(Asym)) end +#Test equivalence of eigenvectors/singular vectors taking into account possible phase (sign) differences +function test_approx_eq_vecs(a, b) + n = size(a)[1] + @test n==size(b)[1] + elty = typeof(a[1]) + @assert elty==typeof(b[1]) + for i=1:n + ev1, ev2 = a[:,i], b[:,i] + deviation = min(abs(norm(ev1-ev2)),abs(norm(ev1+ev2))) + @test_approx_eq_eps deviation 0.0 n^2*eps(abs(convert(elty, 1.0))) + end +end + +#LAPACK tests for symmetric tridiagonal matrices +n=5 +Ainit = randn(n) +Binit = randn(n-1) +for elty in (Float32, Float64) + A = convert(Array{elty, 1}, Ainit) + B = convert(Array{elty, 1}, Binit) + zero, infinity = convert(elty, 0), convert(elty, Inf) + #This tests eigenvalue and eigenvector computations using stebz! and stein! + (w, iblock, isplit, info) = LinAlg.LAPACK.stebz!('V','B',-infinity,infinity,0,0,zero,A,B) + + (evecs, ifail, info)=LinAlg.LAPACK.stein!(A,B,w) + @test info==0 + @test all(ifail .== 0) + + (e, v)=eig(SymTridiagonal(A,B)) + @test_approx_eq e w + #Take into account possible phase (sign) difference in eigenvectors + for i=1:n + ev1 = v[:,i] + ev2 = evecs[:,i] + deviation = min(abs(norm(ev1-ev2)),abs(norm(ev1+ev2))) + @test_approx_eq_eps deviation 0.0 n*eps(abs(convert(elty, 1.0))) + end + + #Test stein! call using iblock and isplit + (w, iblock, isplit, info) = LinAlg.LAPACK.stebz!('V','B',-infinity,infinity,0,0,zero,A,B) + @test info==0 + (evecs, ifail, info)=LinAlg.LAPACK.stein!(A, B, w, iblock, isplit) + @test info==0 + @test all(ifail .== 0) + test_approx_eq_vecs(v, evecs) +end + + +#Test bidiagonal matrices and their SVDs +dv = randn(n) +ev = randn(n-1) +for elty in (Float32, Float64, Complex64, Complex128) + if (elty == Complex64) + dv += im*randn(n) + ev += im*randn(n-1) + end + for isupper in (true, false) #Test upper and lower bidiagonal matrices + T = Bidiagonal{elty}(dv, ev, isupper) + + @test size(T, 1) == n + @test size(T) == (n, n) + @test full(T) == diagm(dv) + diagm(ev, isupper?1:-1) + @test Bidiagonal(full(T), isupper) == T + z = zeros(elty, n) + # idempotent tests + @test conj(conj(T)) == T + @test transpose(transpose(T)) == T + @test ctranspose(ctranspose(T)) == T + + if (elty <: Real) + #XXX If I run either of these tests separately, by themselves, things are OK. + # Enabling BOTH tests results in segfault. + # Where is the memory corruption??? + #@test_approx_eq svdvals(full(T)) svdvals(T) + u1, d1, v1 = svd(full(T)) + u2, d2, v2 = svd(T) + @test_approx_eq d1 d2 + test_approx_eq_vecs(u1, u2) + test_approx_eq_vecs(v1, v2) + end + end +end + + + ## Issue related tests # issue 1447 let A = [1.+0.im 0; 0 1] B = pinv(A) for i = 1:4 - @assert_approx_eq A[i] B[i] + @test_approx_eq A[i] B[i] end end + +# issue 2246 +let + A = [1 2 0 0; 0 1 0 0; 0 0 0 0; 0 0 0 0] + Asq = sqrtm(A) + @test_approx_eq Asq*Asq A + A2 = sub(A, 1:2, 1:2) + A2sq = sqrtm(A2) + @test_approx_eq A2sq*A2sq A2 +end + +let + N = 3 + @test_approx_eq log(det(eye(N))) logdet(eye(N)) +end + +# issue 2637 +let + a = [1, 2, 3] + b = [4, 5, 6] + @test kron(eye(2),eye(2)) == eye(4) + @test kron(a,b) == [4,5,6,8,10,12,12,15,18] + @test kron(a',b') == [4 5 6 8 10 12 12 15 18] + @test kron(a,b') == [4 5 6; 8 10 12; 12 15 18] + @test kron(a',b) == [4 8 12; 5 10 15; 6 12 18] + @test kron(a,eye(2)) == [1 0; 0 1; 2 0; 0 2; 3 0; 0 3] + @test kron(eye(2),a) == [ 1 0; 2 0; 3 0; 0 1; 0 2; 0 3] + @test kron(eye(2),2) == 2*eye(2) + @test kron(3,eye(3)) == 3*eye(3) + @test kron(a,2) == [2, 4, 6] + @test kron(b',2) == [8 10 12] +end diff --git a/test/linprog.jl b/test/linprog.jl deleted file mode 100644 index bec367e1f8532..0000000000000 --- a/test/linprog.jl +++ /dev/null @@ -1,97 +0,0 @@ -### Linear programming - -cd("../extras") # we can't use do-notation because of "using" -require("linprog") - -using LinProgGLPK - -## Simplex method - -# Set options (disable all output -# excpept for errors, turn on presolver) -lps_opts = GLPK.SimplexParam() -lps_opts["msg_lev"] = GLPK.MSG_ERR -lps_opts["presolve"] = GLPK.ON -lps_opts["it_lim"] = 1000 - -# A small dense optimization problem - -f = [ 3.; 2. ]; -A = [ 2. 1. ; - 1. 1. ]; -b = [ 100.; 80 ]; -lb = [ 0.; 0.]; - -(z, x, flag) = linprog_simplex(-f, A, b, [], [], lb, [], lps_opts); - -@test flag == 0 -@test z == -180.0 -@test isequal(x, [20.; 60.]) - - -# A constraint satisfaction (matching) problem -# passing a sparse representation -# to linprog_simplex - -f = [ 3. 2. 2. ; - 1. 0. 1. ; - 3. 3. 5. ]; -f = reshape(f, (9,)); -Aeq = [ 1. 1. 1. 0. 0. 0. 0. 0. 0. ; - 0. 0. 0. 1. 1. 1. 0. 0. 0. ; - 0. 0. 0. 0. 0. 0. 1. 1. 1. ; - 1. 0. 0. 1. 0. 0. 1. 0. 0. ; - 0. 1. 0. 0. 1. 0. 0. 1. 0. ; - 0. 0. 1. 0. 0. 1. 0. 0. 1. ]; -Aeq = sparse(Aeq); -beq = ones(Float64, 6); -lb = zeros(Float64, 9); -ub = ones(Float64, 9); - -(z, x, flag) = linprog_simplex(f, [], [], Aeq, beq, lb, ub, lps_opts); - -@test flag == 0 -@test z == 5. -@test isequal(x, [ 0.; 0.; 1. ; - 0.; 1.; 0. ; - 1.; 0.; 0. ]) - - -## Interior point method - -# Same problem and options as above - -lpi_opts = GLPK.InteriorParam() -lpi_opts["msg_lev"] = GLPK.MSG_ERR - -(z, x, ret) = linprog(f, [], [], Aeq, beq, lb, ub, lpi_opts); - -tol = 1e-4 - -@test flag == 0 -@test abs(z - 5.) < tol -@test max(abs(x - [ 0.; 0.; 1. ; - 0.; 1.; 0. ; - 1.; 0.; 0. ])) < tol - - -### Mixed interger progamming - -# Same problem and options as above - -mip_opts = GLPK.IntoptParam() -mip_opts["msg_lev"] = GLPK.MSG_ERR -mip_opts["presolve"] = GLPK.ON - -# Use binary variables -colkind = int32([ GLPK.BV for i = 1 : 9 ]) - -(z, x, ret, ret_ps) = mixintprog(f, [], [], Aeq, beq, [], [], colkind, mip_opts); - -@test flag == 0 -@test z == 5. -@test isequal(x, [ 0.; 0.; 1. ; - 0.; 1.; 0. ; - 1.; 0.; 0. ]) - -cd("../test") diff --git a/test/math.jl b/test/math.jl index 76eebd4a9a252..8c237c8efea76 100644 --- a/test/math.jl +++ b/test/math.jl @@ -1,22 +1,43 @@ +# frexp,ldexp,significand,exponent +@test frexp(12.8) == (0.8,4) +@test ldexp(0.8,4) == 12.8 +@test significand(12.8) == 1.6 +@test exponent(12.8) == 3 + +# error functions +@test_approx_eq erf(1) 0.84270079294971486934 +@test_approx_eq erfc(1) 0.15729920705028513066 +@test_approx_eq erfcx(1) 0.42758357615580700442 +@test_approx_eq erfi(1) 1.6504257587975428760 +@test_approx_eq dawson(1) 0.53807950691276841914 +# TODO: complex versions only supported on 64-bit for now +if WORD_SIZE==64 + @test_approx_eq erf(1+2im) -0.53664356577856503399-5.0491437034470346695im + @test_approx_eq erfc(1+2im) 1.5366435657785650340+5.0491437034470346695im + @test_approx_eq erfcx(1+2im) 0.14023958136627794370-0.22221344017989910261im + @test_approx_eq erfi(1+2im) -0.011259006028815025076+1.0036063427256517509im + @test_approx_eq dawson(1+2im) -13.388927316482919244-11.828715103889593303im +end + # airy -@assert_approx_eq airy(1.8) 0.0470362168668458052247 -@assert_approx_eq airyprime(1.8) -0.0685247801186109345638 -@assert_approx_eq airybi(1.8) 2.595869356743906290060 -@assert_approx_eq airybiprime(1.8) 2.98554005084659907283 +@test_approx_eq airy(1.8) 0.0470362168668458052247 +@test_approx_eq airyprime(1.8) -0.0685247801186109345638 +@test_approx_eq airybi(1.8) 2.595869356743906290060 +@test_approx_eq airybiprime(1.8) 2.98554005084659907283 # besselh true_h133 = 0.30906272225525164362 - 0.53854161610503161800im -@assert_approx_eq besselh(3,1,3) true_h133 -@assert_approx_eq besselh(-3,1,3) -true_h133 -@assert_approx_eq besselh(3,2,3) conj(true_h133) -@assert_approx_eq besselh(-3,2,3) -conj(true_h133) +@test_approx_eq besselh(3,1,3) true_h133 +@test_approx_eq besselh(-3,1,3) -true_h133 +@test_approx_eq besselh(3,2,3) conj(true_h133) +@test_approx_eq besselh(-3,2,3) -conj(true_h133) # besseli true_i33 = 0.95975362949600785698 -@assert_approx_eq besseli(3,3) true_i33 -@assert_approx_eq besseli(-3,3) true_i33 -@assert_approx_eq besseli(3,-3) -true_i33 -@assert_approx_eq besseli(-3,-3) -true_i33 +@test_approx_eq besseli(3,3) true_i33 +@test_approx_eq besseli(-3,3) true_i33 +@test_approx_eq besseli(3,-3) -true_i33 +@test_approx_eq besseli(-3,-3) -true_i33 # besselj @test besselj(0,0) == 1 @@ -37,53 +58,53 @@ j43 = besselj(4,3.) @test besselj(-4,3) == j43 @test besselj(4,-3) == j43 -@assert_approx_eq j33 0.30906272225525164362 -@assert_approx_eq j43 0.13203418392461221033 -@assert_approx_eq besselj(0.1, -0.4) 0.820421842809028916 + 0.266571215948350899im -@assert_approx_eq besselj(3.2, 1.3+0.6im) 0.01135309305831220201 + 0.03927719044393515275im -@assert_approx_eq besselj(1, 3im) 3.953370217402609396im +@test_approx_eq j33 0.30906272225525164362 +@test_approx_eq j43 0.13203418392461221033 +@test_approx_eq besselj(0.1, -0.4) 0.820421842809028916 + 0.266571215948350899im +@test_approx_eq besselj(3.2, 1.3+0.6im) 0.01135309305831220201 + 0.03927719044393515275im +@test_approx_eq besselj(1, 3im) 3.953370217402609396im # besselk true_k33 = 0.12217037575718356792 -@assert_approx_eq besselk(3,3) true_k33 -@assert_approx_eq besselk(-3,3) true_k33 +@test_approx_eq besselk(3,3) true_k33 +@test_approx_eq besselk(-3,3) true_k33 true_k3m3 = -0.1221703757571835679 - 3.0151549516807985776im -@assert_approx_eq besselk(3,-3) true_k3m3 -@assert_approx_eq besselk(-3,-3) true_k3m3 +@test_approx_eq besselk(3,-3) true_k3m3 +@test_approx_eq besselk(-3,-3) true_k3m3 # bessely y33 = bessely(3,3.) @test bessely(3,3) == y33 -@assert_approx_eq bessely(-3,3) -y33 -@assert_approx_eq y33 -0.53854161610503161800 -@assert_approx_eq bessely(3,-3) 0.53854161610503161800 - 0.61812544451050328724im +@test_approx_eq bessely(-3,3) -y33 +@test_approx_eq y33 -0.53854161610503161800 +@test_approx_eq bessely(3,-3) 0.53854161610503161800 - 0.61812544451050328724im # beta, lbeta -@assert_approx_eq beta(3/2,7/2) 5pi/128 -@assert_approx_eq beta(3,5) 1/105 -@assert_approx_eq lbeta(5,4) log(beta(5,4)) -@assert_approx_eq beta(5,4) beta(4,5) +@test_approx_eq beta(3/2,7/2) 5pi/128 +@test_approx_eq beta(3,5) 1/105 +@test_approx_eq lbeta(5,4) log(beta(5,4)) +@test_approx_eq beta(5,4) beta(4,5) # gamma, lgamma (complex argument) -@assert_approx_eq gamma(0.5) sqrt(pi) -@assert_approx_eq lgamma(1.4+3.7im) -3.7094025330996841898 + 2.4568090502768651184im -@assert_approx_eq lgamma(1.4+3.7im) log(gamma(1.4+3.7im)) +@test_approx_eq gamma(0.5) sqrt(pi) +@test_approx_eq lgamma(1.4+3.7im) -3.7094025330996841898 + 2.4568090502768651184im +@test_approx_eq lgamma(1.4+3.7im) log(gamma(1.4+3.7im)) # digamma euler_mascheroni = 0.5772156649015329 for elty in (Float32, Float64) - @assert_approx_eq digamma(convert(elty, 0.1)) convert(elty, -10.42375494041108) - @assert_approx_eq -digamma(convert(elty, 1.0)) convert(elty, euler_mascheroni) - @assert_approx_eq digamma(convert(elty, 2.0)) convert(elty, 0.4227843350984675) - @assert_approx_eq digamma(convert(elty, 3.0)) convert(elty, 0.9227843350984675) - @assert_approx_eq digamma(convert(elty, 4.0)) convert(elty, 1.256117668431801) - @assert_approx_eq digamma(convert(elty, 5.0)) convert(elty, 1.506117668431801) - @assert_approx_eq digamma(convert(elty, 10.0)) convert(elty, 2.251752589066721) + @test_approx_eq digamma(convert(elty, 0.1)) convert(elty, -10.42375494041108) + @test_approx_eq -digamma(convert(elty, 1.0)) convert(elty, euler_mascheroni) + @test_approx_eq digamma(convert(elty, 2.0)) convert(elty, 0.4227843350984675) + @test_approx_eq digamma(convert(elty, 3.0)) convert(elty, 0.9227843350984675) + @test_approx_eq digamma(convert(elty, 4.0)) convert(elty, 1.256117668431801) + @test_approx_eq digamma(convert(elty, 5.0)) convert(elty, 1.506117668431801) + @test_approx_eq digamma(convert(elty, 10.0)) convert(elty, 2.251752589066721) end # eta, zeta -@assert_approx_eq eta(1) log(2) -@assert_approx_eq eta(2) pi^2/12 -@assert_approx_eq zeta(0) -0.5 -@assert_approx_eq zeta(2) pi^2/6 -@assert_approx_eq zeta(4) pi^4/90 +@test_approx_eq eta(1) log(2) +@test_approx_eq eta(2) pi^2/12 +@test_approx_eq zeta(0) -0.5 +@test_approx_eq zeta(2) pi^2/6 +@test_approx_eq zeta(4) pi^4/90 diff --git a/test/numbers.jl b/test/numbers.jl index d6775e0fcc6f2..bf4a81dc10143 100644 --- a/test/numbers.jl +++ b/test/numbers.jl @@ -212,6 +212,35 @@ if WORD_SIZE > 32 @test base(12,typemax(Int128)) == "2a695925806818735399a37a20a31b3534a7" end +# floating-point printing +@test repr(1.0) == "1.0" +@test repr(-1.0) == "-1.0" +@test repr(0.0) == "0.0" +@test repr(-0.0) == "-0.0" +@test repr(0.1) == "0.1" +@test repr(0.2) == "0.2" +@test repr(0.3) == "0.3" +@test repr(0.1+0.2) != "0.3" +@test repr(Inf) == "Inf" +@test repr(-Inf) == "-Inf" +@test repr(NaN) == "NaN" +@test repr(-NaN) == "NaN" +@test repr(pi) == "3.141592653589793" + +@test repr(1.0f0) == "1.0f0" +@test repr(-1.0f0) == "-1.0f0" +@test repr(0.0f0) == "0.0f0" +@test repr(-0.0f0) == "-0.0f0" +@test repr(0.1f0) == "0.1f0" +@test repr(0.2f0) == "0.2f0" +@test repr(0.3f0) == "0.3f0" +@test repr(0.1f0+0.2f0) == "0.3f0" +@test repr(Inf32) == "Inf32" +@test repr(-Inf32) == "-Inf32" +@test repr(NaN32) == "NaN32" +@test repr(-NaN32) == "NaN32" +@test repr(float32(pi)) == "3.1415927f0" + # signs @test sign(1) == 1 @test sign(-1) == -1 @@ -473,8 +502,11 @@ end for x=int64(2)^53-2:int64(2)^53+5, y=[2.0^53-2 2.0^53-1 2.0^53 2.0^53+2 2.0^53+4] u = uint64(x) - @test y == float64(itrunc(y)) - # println("x=$x; y=float64($(itrunc(y)));") + if WORD_SIZE == 64 + @test y == float64(itrunc(y)) + else + @test y == float64(int64(trunc(y))) + end @test (x==y)==(y==x) @test (x!=y)==!(x==y) @@ -587,6 +619,37 @@ end @test typemax(Uint64) != 2.0^64 +@test typemax(Uint64) < float64(typemax(Uint64)) +@test typemax(Int64) < float64(typemax(Int64)) +@test typemax(Uint64) <= float64(typemax(Uint64)) +@test typemax(Int64) <= float64(typemax(Int64)) + +@test float64(typemax(Uint64)) > typemax(Uint64) +@test float64(typemax(Int64)) > typemax(Int64) +@test float64(typemax(Uint64)) >= typemax(Uint64) +@test float64(typemax(Int64)) >= typemax(Int64) + +@test float64(int128(0)) == 0.0 +@test float32(int128(0)) == 0.0f0 +@test float64(int128(-1)) == -1.0 +@test float32(int128(-1)) == -1.0f0 +@test float64(int128(3)) == 3.0 +@test float32(int128(3)) == 3.0f0 +@test float64(uint128(10121)) == 10121.0 +@test float32(uint128(10121)) == 10121.0f0 +@test float64(typemin(Int128)) == -2.0^127 +@test float32(typemin(Int128)) == -2.0f0^127 +@test float64(typemax(Int128)) == 2.0^127 +@test float32(typemax(Int128)) == 2.0f0^127 +@test float64(typemin(Uint128)) == 0.0 +@test float32(typemin(Uint128)) == 0.0f0 +@test float64(typemax(Uint128)) == 2.0^128 +@test float32(typemax(Uint128)) == 2.0f0^128 + +@test int128(-2.0^127) == typemin(Int128) +@test float64(uint128(3.7e19)) == 3.7e19 +@test float64(uint128(3.7e30)) == 3.7e30 + @test !(NaN <= 1) @test !(NaN >= 1) @test !(NaN < 1) @@ -615,7 +678,7 @@ for a = -5:5, b = -5:5 if a == b == 0; continue; end @test a//b == a/b @test a//b == a//b - @test a//b == rational(a/b) + @test a//b == convert(Rational,a/b) if b == 0 @test_fails integer(a//b) == integer(a/b) else @@ -658,6 +721,18 @@ end @test (ComplexPair(1,2)/ComplexPair(2.5,3.0))*ComplexPair(2.5,3.0) == ComplexPair(1,2) @test 0.7 < real(sqrt(ComplexPair(0,1))) < 0.707107 +for T in {Int8,Int16,Int32,Int64,Int128} + @test abs(typemin(T)) == -typemin(T) + for x in {typemin(T),convert(T,-1),zero(T),one(T),typemax(T)} + @test signed(unsigned(x)) == x + end +end + +for T in {Uint8,Uint16,Uint32,Uint64,Uint128}, + x in {typemin(T),one(T),typemax(T)} + @test unsigned(signed(x)) == x +end + for S = {Int8, Int16, Int32, Int64}, U = {Uint8, Uint16, Uint32, Uint64} @test !(-one(S) == typemax(U)) @@ -988,14 +1063,16 @@ end for x = 2^53-10:2^53+10 y = float64(x) - i = itrunc(y) + i = WORD_SIZE == 64 ? itrunc(y) : int64(trunc(y)) @test int64(trunc(y)) == i @test int64(round(y)) == i @test int64(floor(y)) == i @test int64(ceil(y)) == i - @test iround(y) == i - @test ifloor(y) == i - @test iceil(y) == i + if WORD_SIZE == 64 + @test iround(y) == i + @test ifloor(y) == i + @test iceil(y) == i + end end for x = 2^24-10:2^24+10 diff --git a/test/options.jl b/test/options.jl deleted file mode 100644 index 447335ac1af41..0000000000000 --- a/test/options.jl +++ /dev/null @@ -1,62 +0,0 @@ -require("extras/options") -using OptionsMod - -oo = Options(:a, true, :b, 7) -@test length(oo.key2index) == 2 -@test oo[:a] == true -@test oo[:b] > 6 -@test oo[:c] == nothing -@test sprint(show, oo) == "a = true, b = 7 (CheckError)" - -oo2 = Options(CheckWarn, :(a=true), :(b=7)) -@test oo2[:a] == true -oo3 = @options a=true b=7 -@test oo3[:b] == 7 - - -oo2[:b] = 6 -oo2[:c] = "cat" -@test oo2[:b] < 7 -@test oo2[:c] == "cat" - -function f1(a, b, o::Options) - @defaults o op="plus" - if op == "plus" - return a + b - else - return a - b - end - @check_used o -end -f1(a, b) = f1(a, b, Options()) -@test f1(3, 2) == 5 -@test f1(3, 2, Options(:op, "plus")) == 5 -@test f1(3, 2, Options(:op, "other")) == 1 - -function complexfun(x, opts::Options) - @defaults opts parent=3 both=7 - sub1, both1 = subfun1(x, opts) - sub2, both2 = subfun2(x, opts) - @check_used opts - return parent, both, sub1, both1, sub2, both2 -end -complexfun(x) = complexfun(x, Options()) - -function subfun1(x, opts::Options) - @defaults opts sub1="sub1 default" both=0 - @check_used opts - return sub1, both -end - -function subfun2(x, opts::Options) - @defaults opts sub2="sub2 default" both=22 - @check_used opts - return sub2, both -end - -@test complexfun(5) == (3,7,"sub1 default", 0, "sub2 default", 22) -opts = @options sub2=15 -@test complexfun(5, opts) == (3,7,"sub1 default", 0, 15, 22) -@set_options opts both=8 -@test complexfun(5, opts) == (3,8,"sub1 default", 8, 15, 8) -@set_options opts sub1a=5 diff --git a/test/parallel.jl b/test/parallel.jl new file mode 100644 index 0000000000000..d323fdfe7e054 --- /dev/null +++ b/test/parallel.jl @@ -0,0 +1,16 @@ +if nprocs() < 2 + addprocs_local(1) +end + +id_me = myid() +id_other = id_me==1 ? 2 : 1 + +@test fetch(@spawnat id_other myid()) == id_other + +d = drand((200,200), [id_me, id_other]) +s = convert(Array, d[1:150, 1:150]) +a = convert(Array, d) +@test a[1:150,1:150] == s + +@test fetch(@spawnat id_me localpart(d)[1,1]) == d[1,1] +@test fetch(@spawnat id_other localpart(d)[1,1]) == d[1,101] diff --git a/test/perf.jl b/test/perf.jl index 1fc4135488285..096fa46f5a776 100644 --- a/test/perf.jl +++ b/test/perf.jl @@ -1 +1 @@ -with_output_to_string(@thunk load("perf/perf")) +include("perf/perf.jl") diff --git a/test/perf/Makefile b/test/perf/Makefile index 7df61a2e663b0..98edb2bebcf9c 100644 --- a/test/perf/Makefile +++ b/test/perf/Makefile @@ -2,18 +2,26 @@ JULIAHOME = ../.. include $(JULIAHOME)/Make.inc include $(JULIAHOME)/deps/Versions.make +ifeq ($(OS), WINNT) +MATHEMATICABIN = MathKernel +else ifeq ($(OS), Darwin) +MATHEMATICABIN = MathKernel +else +MATHEMATICABIN = math +endif + default: benchmarks.html export OMP_NUM_THREADS=1 export GOTO_NUM_THREADS=1 export OPENBLAS_NUM_THREADS=1 -perf.h: +perf.h: $(JULIAHOME)/deps/Versions.make echo '#include "$(JULIAHOME)/deps/openblas-$(OPENBLAS_VER)/cblas.h"' > $@ echo '#include "$(JULIAHOME)/deps/random/dsfmt-$(DSFMT_VER)/dSFMT.c"' >> $@ -bin/perf%: perf.cpp perf.h - $(CXX) -O$* $< -o $@ $(JULIAHOME)/deps/openblas-$(OPENBLAS_VER)/libopenblas.a -lpthread +bin/perf%: perf.c perf.h + $(CC) -std=c99 -O$* $< -o $@ $(JULIAHOME)/deps/openblas-$(OPENBLAS_VER)/libopenblas.a -lpthread bin/fperf%: perf.f90 $(FC) -static-libgfortran -O$* -fexternal-blas $< -o $@ $(JULIAHOME)/deps/openblas-$(OPENBLAS_VER)/libopenblas.a -lpthread @@ -38,6 +46,9 @@ benchmarks/c%.csv: bin/perf% benchmarks/fortran%.csv: bin/fperf% for t in 1 2 3 4 5; do $<; done >$@ +benchmarks/go.csv: perf.go + for t in 1 2 3 4 5; do go run $<; done >$@ + benchmarks/julia.csv: perf.jl for t in 1 2 3 4 5; do ../../julia $<; done >$@ @@ -56,15 +67,20 @@ benchmarks/r.csv: perf.R benchmarks/javascript.csv: perf.js for t in 1 2 3 4 5; do node $<; done >$@ +benchmarks/mathematica.csv: perf.nb + for t in 1 2 3 4 5; do $(MATHEMATICABIN) -noprompt -run "<<$<; Exit[]"; done >$@ + BENCHMARKS = \ benchmarks/c.csv \ benchmarks/fortran.csv \ + benchmarks/go.csv \ benchmarks/julia.csv \ benchmarks/python.csv \ benchmarks/matlab.csv \ benchmarks/octave.csv \ benchmarks/r.csv \ - benchmarks/javascript.csv + benchmarks/javascript.csv \ + benchmarks/mathematica.csv benchmarks.csv: bin/collect.pl $(BENCHMARKS) $(QUIET_PERL) $^ >$@ @@ -73,6 +89,6 @@ benchmarks.html: bin/table.pl benchmarks.csv $(QUIET_PERL) $^ >$@ clean: - @rm -rf bin/perf* bin/fperf* benchmarks/*.csv benchmarks.csv *.mod + @rm -rf perf.h bin/perf* bin/fperf* benchmarks/*.csv benchmarks.csv *.mod .PHONY: all perf clean diff --git a/test/perf/bin/table.pl b/test/perf/bin/table.pl index 07b8e02738e97..0d5c8c6b9182f 100755 --- a/test/perf/bin/table.pl +++ b/test/perf/bin/table.pl @@ -29,9 +29,11 @@ "octave" => ["Octave" , "3.4" ], "r" => ["R" , "2.14.2" ], "javascript" => ["JavaScript" , "V8 3.6.6.11"], + "go" => ["Go" , "1.0.3" ], + "mathematica"=> ["Mathematica" , "9.0.1" ], ); -our @systems = qw(fortran julia python matlab octave r javascript); +our @systems = qw(fortran julia python matlab octave r javascript go mathematica); print qq[\n]; print qq[\n]; diff --git a/test/perf/perf.R b/test/perf/perf.R index 7bca9a3322617..044949cbe0d67 100644 --- a/test/perf/perf.R +++ b/test/perf/perf.R @@ -1,4 +1,4 @@ -library(R.utils) +require(compiler) assert = function(bool) { if (!bool) stop('Assertion failed') @@ -6,6 +6,7 @@ assert = function(bool) { timeit = function(name, f, ..., times=5) { tmin = Inf + f = cmpfun(f) for (t in 1:times) { t = system.time(f(...))["elapsed"] if (t < tmin) tmin = t @@ -32,8 +33,8 @@ parseintperf = function(t) { for (i in 1:t) { # R doesn't support uint32 values n = floor(2^31-1*runif(1)) - s = intToHex(n) - m = as.numeric(paste("0x",s,sep="")) + s = sprintf("0x%x", n) + m = as.numeric(s) assert(m == n) } } @@ -121,6 +122,16 @@ pisum = function() { assert(abs(pisum()-1.644834071848065) < 1e-12); timeit("pi_sum", pisum, times=1) +## pi_sum_vec ## + +pisumvec = function() { + r = 1:10000 + return(replicate(500, sum(1/((r)^2)))[1]) +} + +#assert(abs(pisumvec()-1.644834071848065) < 1e-12); +#timeit("pi_sum_vec", pisumvec, times=10) + ## rand_mat_stat ## randmatstat = function(t) { diff --git a/test/perf/perf.cpp b/test/perf/perf.c similarity index 95% rename from test/perf/perf.cpp rename to test/perf/perf.c index 3cf74080cd81b..e06e59a04c155 100644 --- a/test/perf/perf.cpp +++ b/test/perf/perf.c @@ -1,18 +1,9 @@ -#include -#include -#include -#include -#include -#include -#include -#include +#include #define DSFMT_MEXP 19937 #include "perf.h" #include "../../deps/random/randmtzig.c" -using namespace std; - double *myrand(int n) { double *d = (double *)malloc(n*sizeof(double)); dsfmt_gv_fill_array_close_open(d, n); @@ -64,15 +55,15 @@ double *matmul_aat(int n, double *b) { return c; } -int mandel(complex z) { +int mandel(double complex z) { int n = 0; - complex c = complex(real(z), imag(z)); + double complex c = z; for (n=0; n<=79; ++n) { - if (abs(z) > 2.0) { + if (cabs(z) > 2.0) { n -= 1; break; } - z = pow(z,2)+c; + z = cpow(z,2)+c; } return n+1; } @@ -81,7 +72,7 @@ int mandelperf() { int mandel_sum = 0; for (double re=-2.0; re<=0.5; re+=0.1) { for (double im=-1.0; im<=1.0; im+=0.1) { - int m = mandel(complex(re, im)); + int m = mandel(re+im*I); mandel_sum += m; } } @@ -296,7 +287,7 @@ int main() { t = clock_now()-t; if (t < tmin) tmin = t; } - assert(mandel_sum == 14720); + assert(mandel_sum == 14719); print_perf("mandel", tmin); // sort diff --git a/test/perf/perf.go b/test/perf/perf.go new file mode 100644 index 0000000000000..60087edee9fc8 --- /dev/null +++ b/test/perf/perf.go @@ -0,0 +1,202 @@ +package main + +import ( + "fmt" + matrix "github.com/skelterjohn/go.matrix" + "math" + "math/cmplx" + "math/rand" + "strconv" + "time" +) + +// fibonacci + +func fib(n int) int { + if n < 2 { + return n + } + return fib(n-1) + fib(n-2) +} + +// quicksort + +func qsort_kernel(a []float64, lo, hi int) []float64 { + i := lo + j := hi + for i < hi { + pivot := a[(lo+hi)/2] + for i <= j { + for a[i] < pivot { + i += 1 + } + for a[j] > pivot { + j -= 1 + } + if i <= j { + a[i], a[j] = a[j], a[i] + i += 1 + j -= 1 + } + } + if lo < j { + qsort_kernel(a, lo, j) + } + lo = i + j = hi + } + return a +} + +// randmatstat + +// Not implemented + +// randmatmul + +func randmatmul(n int) matrix.MatrixRO { + a := matrix.Zeros(n, n) + b := matrix.Zeros(n, n) + for i := 0; i < n; i++ { + for k := 0; k < n; k++ { + a.Set(i, k, rand.Float64()) + b.Set(i, k, rand.Float64()) + } + } + return matrix.Product(a, b) +} + +// mandelbrot + +func mandel(z complex128) int { + c := z + var n int + for n = 0; n < 79; n++ { + if cmplx.Abs(z) > 2 { + n -= 1 + break + } + z = z*z + c + } + return n + 1 +} + +func mandelperf() int { + mandel_sum := 0 + for re := -2.0; re <= 0.5; re += 0.1 { + for im := -1.0; im <= 1.0; im += 0.1 { + m := mandel(complex(re, im)) + mandel_sum += m + } + } + return mandel_sum +} + +// pisum + +func pisum() float64 { + var sum float64 + for i := 0; i < 500; i++ { + sum = 0.0 + for k := 1; k <= 10000; k++ { + sum += 1.0 / float64(k*k) + } + } + return sum +} + +func print_perf(name string, time float64) { + fmt.Printf("go,%v,%v\n", name, time*1000) +} + +// run tests + +func assert(b bool) { + if b != true { + panic("assert failed") + } +} + +func main() { + assert(fib(20) == 6765) + tmin := float64(math.MaxFloat64) + for i := 0; i < 5; i++ { + t := time.Now() + _ = fib(20) + d := float64(time.Since(t).Seconds()) + if d < tmin { + tmin = d + } + } + print_perf("fib", tmin) + + tmin = float64(math.MaxFloat64) + for i := 0; i < 5; i++ { + t := time.Now() + for k := 0; k < 1000; k++ { + n := rand.Uint32() + s := fmt.Sprintf("%x", n) + m, _ := strconv.ParseUint(s, 16, 32) + assert(uint32(m) == n) + } + d := float64(time.Since(t).Seconds()) + if d < tmin { + tmin = d + } + } + print_perf("parse_int", tmin) + + // fmt.Println(mandelperf()) + // FIXME: assert(mandelperf() == 14791) + tmin = float64(math.MaxFloat64) + for i := 0; i < 5; i++ { + t := time.Now() + _ = mandelperf() + d := float64(time.Since(t).Seconds()) + if d < tmin { + tmin = d + } + } + print_perf("mandel", tmin) + + tmin = float64(math.MaxFloat64) + for i := 0; i < 5; i++ { + lst := make([]float64, 5000) + for k := 0; k < len(lst); k++ { + lst[k] = rand.Float64() + } + t := time.Now() + qsort_kernel(lst, 0, len(lst)-1) + d := float64(time.Since(t).Seconds()) + if d < tmin { + tmin = d + } + } + print_perf("quicksort", tmin) + + assert(math.Abs(pisum()-1.644834071848065) < 1e-6) + tmin = float64(math.MaxFloat64) + for i := 0; i < 5; i++ { + t := time.Now() + pisum() + d := float64(time.Since(t).Seconds()) + if d < tmin { + tmin = d + } + } + print_perf("pi_sum", tmin) + + // randmatstat not implemented + + tmin = float64(math.MaxFloat64) + for i := 0; i < 5; i++ { + t := time.Now() + c := randmatmul(1000) + assert(c.Get(0, 0) >= 0) + d := float64(time.Since(t).Seconds()) + if d < tmin { + tmin = d + } + } + print_perf("rand_mat_mul", tmin) +} diff --git a/test/perf/perf.jl b/test/perf/perf.jl index 2bde95a092997..5ece28c3f8113 100644 --- a/test/perf/perf.jl +++ b/test/perf/perf.jl @@ -1,13 +1,16 @@ -require("test") # for running perf standalone using Test +print_output = isempty(ARGS) || contains(ARGS, "perf/perf.jl") || contains(ARGS, "perf") + macro timeit(ex,name) quote t = Inf for i=1:5 t = min(t, @elapsed $ex) end - println("julia,", $name, ",", t*1000) + if print_output + println("julia,", $name, ",", t*1000) + end #gc() end end @@ -24,9 +27,9 @@ fib(n) = n < 2 ? n : fib(n-1) + fib(n-2) function parseintperf(t) local n, m for i=1:t - n = randi(Uint32) + n = rand(Uint32) s = hex(n) - m = uint32(parse_hex(s)) + m = uint32(parseint(s,16)) end @test m == n return n @@ -59,7 +62,7 @@ function mandel(z) return maxiter end -mandelperf() = [ mandel(complex(r,i)) for r=-2.0:.1:0.5, i=-1.:.1:1. ] +mandelperf() = [ mandel(complex(r,i)) for i=-1.:.1:1., r=-2.0:.1:0.5 ] @test sum(mandelperf()) == 14791 @timeit mandelperf() "mandel" @@ -105,6 +108,20 @@ end @test abs(pisum()-1.644834071848065) < 1e-12 @timeit pisum() "pi_sum" +## slow pi series, vectorized ## + +function pisumvec() + s = 0.0 + a = [1:10000] + for j = 1:500 + s = sum(1./(a.^2)) + end + s +end + +#@test abs(pisumvec()-1.644834071848065) < 1e-12 +#@timeit pisumvec() "pi_sum_vec" + ## random matrix statistics ## function randmatstat(t) @@ -135,14 +152,14 @@ end ## printfd ## @unix_only begin -function printfd(n) - open("/dev/null","w") do io - for i = 1:n - @printf(io,"%d %d\n",i,i+1) + function printfd(n) + open("/dev/null","w") do io + for i = 1:n + @printf(io,"%d %d\n",i,i+1) + end end end -end -printfd(1) -@timeit printfd(100000) "printfd" + printfd(1) + @timeit printfd(100000) "printfd" end diff --git a/test/perf/perf.lua b/test/perf/perf.lua new file mode 100644 index 0000000000000..bde1b9b5cbdb8 --- /dev/null +++ b/test/perf/perf.lua @@ -0,0 +1,245 @@ + +local ffi = require 'ffi' +local bit = require 'bit' +local gsl = require 'gsl' + +local min, max, abs, sqrt, random, floor = math.min, math.max, math.abs, math.sqrt, math.random, math.floor +local cabs = complex.abs +local rshift = bit.rshift +local format = string.format + +local gettime +do + ffi.cdef[[ + struct timeval { + long tv_sec; + long tv_usec; + }; + + int gettimeofday(struct timeval * tp, void *tzp); + ]] + + local tv = ffi.new('struct timeval[1]') + + gettime = function() + ffi.C.gettimeofday(tv, nil) + return tv[0].tv_sec, tv[0].tv_usec + end +end + +-- return the elapsed time in ms +local function elapsed(f) + local s0, us0 = gettime() + f() + local s1, us1 = gettime() + return tonumber(s1 - s0) * 1000 + tonumber(us1 - us0) / 1000 +end + +local function timeit(f, name) + local t = nil + for k = 1, 5 do + local tx = elapsed(f) + t = t and min(t, tx) or tx + end + print(format("gsl_shell,%s,%g", name, t)) +end + +local function fib(n) + if n < 2 then + return n + else + return fib(n-1) + fib(n-2) + end +end + +assert(fib(20) == 6765) +timeit(|| fib(20), "fib") + +local function parseint() + local r = rng.new('rand') + local lmt = 2^32 - 1 + local n, m + for i = 1, 1000 do + n = r:getint(lmt) + local s = format('0x%x', tonumber(n)) + m = tonumber(s) + end + assert(m == n) + return n +end + +timeit(parseint, "parse_int") + +local function mandel(z) + local c = z + local maxiter = 80 + for n = 1, maxiter do + if cabs(z) > 2 then + return n-1 + end + z = z*z + c + end + return maxiter +end +function mandelperf() + local a, re, im, z + a = ffi.new("double[?]", 546) + r = 0 + for r = -20, 5 do + re = r*0.1 + for i=-10, 10 do + im = i*0.1 + a[r*21+i+430] = mandel(re + 1i * im) + end + end + return a +end + +do + local a = mandelperf() + local sum = 0 + for i = 0, 545 do sum = sum + a[i] end + assert(sum == 14791) +end + +timeit(mandelperf, "mandel") + +local function qsort(a, lo, hi) + local i, j = lo, hi + while i < hi do + local pivot = a[rshift(lo+hi, 1)] + while i <= j do + while a[i] < pivot do i = i+1 end + while a[j] > pivot do j = j-1 end + if i <= j then + a[i], a[j] = a[j], a[i] + i, j = i+1, j-1 + end + end + if lo < j then qsort(a, lo, j) end + lo, j = i, hi + end + return a +end + +local function sortperf() + local n = 5000 + local r = rng.new('rand') + local v = iter.ilist(|| r:get(), n) + qsort(v, 1, n) +end + + + +local function pisum() + local sum + for j = 1, 500 do + sum = 0 + for k = 1, 10000 do + sum = sum + 1 / (k*k) + end + end + return sum +end + +local function stat(v) + local p, q = 0, 0 + local n = #v + for k = 1, n do + local x = v[k] + p = p + x + q = q + x*x + end + return sqrt((n*(n*q-p*p))/((n-1)*p*p)) +end + +local function randmatstat(t) + local n = 5 + local A = iter.ilist(|| matrix.alloc(n, n), 4) + + local P = matrix.alloc(n, 4*n) + local Q = matrix.alloc(2*n, 2*n) + + local PtP1 = matrix.alloc(4*n, 4*n) + local PtP2 = matrix.alloc(4*n, 4*n) + local QtQ1 = matrix.alloc(2*n, 2*n) + local QtQ2 = matrix.alloc(2*n, 2*n) + + local get, set = A[1].get, A[1].set + + local r = rng.new('rand') + local randn = || rnd.gaussian(r, 1) + + local function hstackf(i, j) + local k, r = math.divmod(j - 1, n) + return get(A[k + 1], i, r + 1) + end + + local function vstackf(i, j) + local ik, ir = math.divmod(i - 1, n) + local jk, jr = math.divmod(j - 1, n) + return get(A[2*ik + jk + 1], ir + 1, jr + 1) + end + + local Tr, NT = gsl.CblasTrans, gsl.CblasNoTrans + + local v, w = {}, {} + + for i = 1, t do + matrix.fset(A[1], randn) + matrix.fset(A[2], randn) + matrix.fset(A[3], randn) + matrix.fset(A[4], randn) + + matrix.fset(P, hstackf) + matrix.fset(Q, vstackf) + + gsl.gsl_blas_dgemm(Tr, NT, 1.0, P, P, 0.0, PtP1) + gsl.gsl_blas_dgemm(NT, NT, 1.0, PtP1, PtP1, 0.0, PtP2) + gsl.gsl_blas_dgemm(NT, NT, 1.0, PtP2, PtP2, 0.0, PtP1) + + local vi = 0 + for j = 1, n do vi = vi + get(PtP1, j, j) end + v[i] = vi + + gsl.gsl_blas_dgemm(Tr, NT, 1.0, Q, Q, 0.0, QtQ1) + gsl.gsl_blas_dgemm(NT, NT, 1.0, QtQ1, QtQ1, 0.0, QtQ2) + gsl.gsl_blas_dgemm(NT, NT, 1.0, QtQ2, QtQ2, 0.0, QtQ1) + + local wi = 0 + for j = 1, 2*n do wi = wi + get(QtQ1, j, j) end + w[i] = wi + end + + return stat(v), stat(w) +end + +do + local s1, s2 = randmatstat(1000) + assert( 0.5 < s1 and s1 < 1.0 + and 0.5 < s2 and s2 < 1.0 ) +end + +local function randmatmult(n) + local r = rng.new('rand') + --local rand = || r:get() + local rand = random + local a = matrix.new(n, n, rand) + local b = matrix.new(n, n, rand) + return a*b +end + +local function printfd(n) + local f = io.open("/dev/null","w") + for i = 1, n do + f:write(format("%d %d\n", i, i+1)) + end + f:close() +end + + +timeit(sortperf, "quicksort") +timeit(pisum, "pi_sum") +timeit(|| randmatstat(1000), "rand_mat_stat") +timeit(|| randmatmult(1000), "rand_mat_mul") +-- timeit(|| printfd(100000), "printfd") diff --git a/test/perf/perf.m b/test/perf/perf.m index 523ebab915a0e..0761cd3495711 100644 --- a/test/perf/perf.m +++ b/test/perf/perf.m @@ -1,7 +1,9 @@ function perf() warning off; -maxNumCompThreads(1); +if exist('OCTAVE_VERSION') == 0 + maxNumCompThreads(1); +end function assert(bool) if ~bool @@ -55,16 +57,16 @@ function timeit(name, func, varargin) %% array constructors %% -o = ones(200,200); -assert(all(o) == 1) +%o = ones(200,200); +%assert(all(o) == 1) % timeit('ones', @ones, 200, 200) %% matmul and transpose %% -function oo = matmul(o) - oo = o * o.'; -end -assert(all(matmul(o) == 200)) +%function oo = matmul(o) +% oo = o * o.'; +%end +%assert(all(matmul(o) == 200)) % timeit('AtA', @matmul, o) %% mandelbrot set: complex arithmetic and comprehensions %% @@ -146,6 +148,19 @@ function timeit(name, func, varargin) assert(abs(s-1.644834071848065) < 1e-12); timeit('pi_sum',@pisum, true) +%% slow pi series, vectorized %% + +function s = pisumvec(ignore) + a = [1:10000] + for j=1:500 + s = sum( 1./(a.^2)); + end +end + +%s = pisumvec(true); +%assert(abs(s-1.644834071848065) < 1e-12); +%timeit('pi_sum_vec',@pisumvec, true) + %% random matrix statistics %% function [s1, s2] = randmatstat(t) diff --git a/test/perf/perf.nb b/test/perf/perf.nb new file mode 100644 index 0000000000000..c9e7822300373 --- /dev/null +++ b/test/perf/perf.nb @@ -0,0 +1,276 @@ +(* Benchmark script *) + +(* Set up output stream *) +SetOptions[$Output, FormatType -> OutputForm]; + +(* Test if system has a C compiler and if so set target to "C"*) +Needs["CCompilerDriver`"]; +If[ Length[CCompilers[]] > 0, + $CompilationTarget = "C" +]; + + +ClearAll[$printOutput]; +$printOutput = True; + +ClearAll[timeit]; +SetAttributes[timeit, HoldFirst]; +timeit[ex_, name_String] := Module[ + {t}, + t = Infinity; + Do[ + t = Min[t, N[First[AbsoluteTiming[ex]]]]; + , + {i, 1, 5} + ]; + If[$printOutput, + (*Print[OutputForm["mathematica," <> name <> ","], t*1000];*) + Print["mathematica,", name, ",", t*1000]; + ]; +]; + +ClearAll[test]; +SetAttributes[test, HoldFirst]; +test[ex_] := Assert[ex]; +On[Assert]; + + +(* recursive fib *) + +ClearAll[fib]; +fib = Compile[{{n, _Integer}}, + If[n < 2, n, fib[n - 1] + fib[n - 2]], + CompilationTarget -> "WVM" +]; + +test[fib[20] == 6765]; +timeit[fib[20], "fib"]; + +(* parse integer *) + +ClearAll[parseintperf]; +parseintperf[t_] := Module[ + {n, m, i, s}, + Do[ + n = RandomInteger[{0, 4294967295}]; + s = IntegerString[n, 16]; + m = FromDigits[s, 16]; + , + {i, 1, t} + ]; + test[ m == n]; + n +]; + +timeit[parseintperf[1000], "parse_int"]; + +(* array constructors *) + +test[ And @@ And @@@ Thread /@ Thread[ConstantArray[1, {200, 200}] == 1]]; + +(* matmul and transpose *) + +ClearAll[A]; +A = ConstantArray[1, {200, 200}]; +test[And @@ And @@@ Thread /@ Thread[A.ConjugateTranspose[A] == 200]]; + +(* mandelbrot set: complex arithmetic and comprehensions *) + +ClearAll[mandel]; +(*mandel[zin_] := Module[ + {z, c, maxiter, n}, + z = zin; + c = z; + maxiter = 80; + Do[ + If[ Abs[z] > 2, + maxiter = n-1; + Break[] + ]; + z = z^2 + c; + , + {n, 1, maxiter} + ]; + maxiter +];*) +mandel = Compile[{{zin, _Complex}}, + Module[ + {z = zin, c = zin, maxiter = 80, n = 0}, + Do[ + If[ Abs[z] > 2, + maxiter = n-1; + Break[] + ]; + z = z^2 + c; + , + {n, 1, maxiter} + ]; + maxiter + ] +]; + +ClearAll[mandelperf]; +mandelperf[] := Table[mandel[r + i*I], {i, -1., 1., 0.1}, {r, -2.0, 0.5, 0.1}]; + +test[ Total[mandelperf[], 2] == 14791]; +timeit[mandelperf[], "mandel"]; + +(* numeric vector sort *) + +ClearAll[qsort]; +(* qsort[ain_, loin_, hiin_] := Module[ + {a = ain, i = loin, j = hiin, lo = loin, hi = hiin, pivot}, + While[ i < hi, + pivot = a[[BitShiftRight[lo + hi] ]]; + While[ i <= j, + While[a[[i]] < pivot, i++]; + While[a[[j]] > pivot, j--]; + If[ i <= j, + a[[{i,j}]] = a[[{j, i}]]; + i++; j--; + ]; + ]; + If[ lo < j, a = qsort[a, lo, j] ]; + {lo, j} = {i, hi}; + ]; + a +]; *) +qsort = Compile[ + {{ain, _Real, 1}, {loin, _Integer}, {hiin, _Integer}}, + Module[ + {a = ain, i = loin, j = hiin, lo = loin, hi = hiin, pivot}, + While[ i < hi, + pivot = a[[ Floor[(lo + hi)/2] ]]; + While[ i <= j, + While[a[[i]] < pivot, i++]; + While[a[[j]] > pivot, j--]; + If[ i <= j, + a[[{i,j}]] = a[[{j, i}]]; + i++; j--; + ]; + ]; + If[ lo < j, a[[lo;;j]] = qsort[ a[[lo;;j]], 1, j - lo + 1] ]; + {lo, j} = {i, hi}; + ]; + a + ] +]; + + +ClearAll[sortperf]; +sortperf[n_] := Module[{vec = RandomReal[1, n]}, qsort[vec, 1, n]]; + +test[OrderedQ[sortperf[5000]] ]; +timeit[sortperf[5000], "quicksort"]; + +(* slow pi series *) + +ClearAll[pisum]; +pisum = Compile[ {}, + Module[ + {sum = 0.`}, + Do[sum = Sum[1/(k*k), {k, 1, 10000}], + {500}]; + sum + ] +]; + + +test[Abs[pisum[] - 1.644834071848065`] < 1.`*^-12 ]; +timeit[pisum[], "pi_sum"]; + +(* slow pi series, vectorized *) + +pisumvec = Compile[{}, + Module[ + {sum = 0.}, + Do[ + sum = Total[1/Range[1, 10000]^2];, + {500} + ]; + sum + ] +]; + +(* test[Abs[pisumvec[] - 1.644834071848065`] < 1.`*^-12 ];*) +(* timeit[pisumvec[], "pi_sum_vec"];*) + +(* random matrix statistics *) + +ClearAll[randmatstat]; +(*randmatstat[t_] := Module[ + {n, v, w, a, b, c, d, P, Q}, + n = 5; + v = w = ConstantArray[0., {t}]; + Do[ + a = RandomReal[NormalDistribution[], {n, n}]; + b = RandomReal[NormalDistribution[], {n, n}]; + c = RandomReal[NormalDistribution[], {n, n}]; + d = RandomReal[NormalDistribution[], {n, n}]; + P = Join[a, b, c, d, 2]; + Q = ArrayFlatten[{{a, b}, {c, d}}]; + v[[i]] = Tr[MatrixPower[Transpose[P].P, 4]]; + w[[i]] = Tr[MatrixPower[Transpose[Q].Q, 4]]; + , + {i, 1, t} + ]; + {StandardDeviation[v]/Mean[v], StandardDeviation[w]/Mean[w]} +];*) +randmatstat = Compile[{{t, _Integer}}, + Module[ + { + n = 5, + v = ConstantArray[0., t], + w = ConstantArray[0., t], + a = {{0.}}, b = {{0.}}, + c = {{0.}}, d = {{0.}}, + P = {{0.}}, Q = {{0.}} + }, + Do[ + a = RandomReal[NormalDistribution[], {n, n}]; + b = RandomReal[NormalDistribution[], {n, n}]; + c = RandomReal[NormalDistribution[], {n, n}]; + d = RandomReal[NormalDistribution[], {n, n}]; + P = Join[a, b, c, d, 2]; + Q = ArrayFlatten[{{a, b}, {c, d}}]; + v[[i]] = Tr[MatrixPower[Transpose[P].P, 4]]; + w[[i]] = Tr[MatrixPower[Transpose[Q].Q, 4]]; + , + {i, 1, t} + ]; + {StandardDeviation[v]/Mean[v], StandardDeviation[w]/Mean[w]} + ], + {{_ArrayFlatten, _Real, 2}} +]; + + +ClearAll[s1,s2]; +{s1, s2} = randmatstat[1000]; +test[0.5 < s1 < 1.0 && 0.5 < s2 < 1.0]; + +timeit[randmatstat[1000], "rand_mat_stat"]; + +(* largish random number gen & matmul *) + +timeit[RandomReal[1, {1000, 1000}].RandomReal[1, {1000, 1000}], "rand_mat_mul"]; + +(* printfd *) + +(* only on unix systems *) +If[ $OperatingSystem == "Linux"||$OperatingSystem == "MacOSX", + + ClearAll[printfd]; + printfd[n_] := Module[ + {stream}, + stream = OpenWrite["/dev/null"]; + Do[ + WriteString[stream, i, " ", i+1, "\n" ]; + , + {i, 1, n} + ]; + Close[stream]; + ]; + + timeit[printfd[100000], "printfd"]; + +]; diff --git a/test/perf/perf.py b/test/perf/perf.py index 979da9ff4e034..7b5dce15883bb 100644 --- a/test/perf/perf.py +++ b/test/perf/perf.py @@ -85,6 +85,10 @@ def pisum(): sum += 1.0/(k*k) return sum +#### Is this single threaded? +# def pisumvec(): +# return numpy.sum(1./(numpy.arange(1,10000)**2)) + def print_perf(name, time): print("python," + name + "," + str(time*1000)) @@ -132,7 +136,6 @@ def print_perf(name, time): if t < tmin: tmin = t print_perf ("quicksort", tmin) - pi = pisum() assert abs(pisum()-1.644834071848065) < 1e-6 tmin = float('inf') for i in range(5): @@ -142,6 +145,15 @@ def print_perf(name, time): if t < tmin: tmin = t print_perf ("pi_sum", tmin) + # assert abs(pisumvec()-1.644834071848065) < 1e-6 + # tmin = float('inf') + # for i in range(5): + # t = time.time() + # pisumvec() + # t = time.time()-t + # if t < tmin: tmin = t + # print_perf ("pi_sum_vec", tmin) + (s1, s2) = randmatstat(1000) assert s1 > 0.5 and s1 < 1.0 tmin = float('inf') diff --git a/test/perf2/actor_centrality.jl b/test/perf2/actor_centrality.jl index ba4a94b777d6c..e5365f567117a 100644 --- a/test/perf2/actor_centrality.jl +++ b/test/perf2/actor_centrality.jl @@ -25,7 +25,7 @@ function centrality_mean(G::Graph, start_node) if !has(dists, n) dists[n] = cdist for neigh in n.n - add(nnext, neigh) + add!(nnext, neigh) end end end @@ -44,9 +44,9 @@ function read_graph() k = split(strip(readline(io)), "\t") actor, movie = k[1], join(k[2:3], "_") ac, mn = get(G, actor), get(G, movie) - add(actors, actor) - add(ac.n, mn) - add(mn.n, ac) + add!(actors, actor) + add!(ac.n, mn) + add!(mn.n, ac) end end G, sort!([ a for a in actors]) diff --git a/test/perf2/gk.jl b/test/perf2/gk.jl index 9fe1d50b606ae..4d0f62650ff03 100644 --- a/test/perf2/gk.jl +++ b/test/perf2/gk.jl @@ -182,4 +182,4 @@ function gk(n, myeps) #print("\n \n") end -#end # @profile begin +#end # @profile begin diff --git a/test/perf2/go_benchmark.jl b/test/perf2/go_benchmark.jl index 14164edc53b1b..4c176a338ee5d 100644 --- a/test/perf2/go_benchmark.jl +++ b/test/perf2/go_benchmark.jl @@ -476,7 +476,7 @@ end function main(args) n = 10 if length(args) > 0 - n = parse_int(args[1]) + n = parseint(args[1]) end @time benchmark(n) end diff --git a/test/perf2/json.jl b/test/perf2/json.jl index 32bbfaee8d353..c185e11a6e743 100644 --- a/test/perf2/json.jl +++ b/test/perf2/json.jl @@ -36,7 +36,7 @@ function parse_json(strng::String) if next_char != ']' while true val = parse_value() - add(object, val) + add!(object, val) if next_char() == ']' break end @@ -67,7 +67,7 @@ function parse_json(strng::String) end function skip_whitespace() - while pos <= len && iswspace(strng[pos]) + while pos <= len && isspace(strng[pos]) pos = pos + 1 end end @@ -84,11 +84,11 @@ function parse_json(strng::String) # index_esc = index_esc + 1 # end # if index_esc > len_esc - # str = strcat(str, strng[pos:end]) + # str = string(str, strng[pos:end]) # pos = len + 1 # break # else - # str = strcat(str, strng[pos:esc(index_esc)-1]) + # str = string(str, strng[pos:esc(index_esc)-1]) # pos = esc(index_esc) # end nc = strng[pos] @@ -102,20 +102,20 @@ function parse_json(strng::String) pos = pos + 1 anc = strng[pos] if anc == '"' || anc == '\\' || anc == '/' - str = strcat(str, strng[pos]) + str = string(str, strng[pos]) pos = pos + 1 elseif anc == 'b' || anc == 'f'|| anc == 'n' || anc == 'r' || anc == 't' - str = strcat(str, '\\', string[pos]) + str = string(str, '\\', string[pos]) pos = pos + 1 elseif anc == 'u' if pos+4 > len error_pos("End of file reached in escaped unicode character") end - str = strcat(str, strng[pos-1:pos+4]) + str = string(str, strng[pos-1:pos+4]) pos = pos + 5 end else # should never happen - str = strcat(str,strng[pos]) + str = string(str,strng[pos]) pos = pos + 1 end end diff --git a/test/perf2/laplace/c_laplace.c b/test/perf2/laplace/c_laplace.c index eea7c7c576e71..b01c113d2a496 100644 --- a/test/perf2/laplace/c_laplace.c +++ b/test/perf2/laplace/c_laplace.c @@ -1,17 +1,14 @@ #include -#include "parameter.h" -//#define N 150 +#include main() { + int size_mat = 150; + int Niter=1024; double u[size_mat][size_mat]; double dx=0.1, dy=0.1, dx2, dy2; int i, j, k; - int Niter; - FILE *f; - f = fopen("data_C (pure)", "w"); - - scanf("%d", &Niter); + time_t t1 = clock(); for(i=0; i>8 # 24 bit for the x-value @@ -139,7 +139,7 @@ end randn_zig(sigma::Number) = sigma*randn_zig() function randn_zig!(A::Array) - for i=1:numel(A) + for i=1:length(A) A[i] = randn_zig() end return A diff --git a/test/pkg.jl b/test/pkg.jl new file mode 100644 index 0000000000000..106f02772d786 --- /dev/null +++ b/test/pkg.jl @@ -0,0 +1,20 @@ +ENV["JULIA_PKGDIR"] = string("tmp.",randstring()) +@test !isdir(Pkg.dir()) +try # ensure directory removal + +@test_fails Pkg.cd_pkgdir() +Pkg.init() +@test isdir(Pkg.dir()) +Pkg.resolve() + +@test length(Pkg.required()) == 0 +Pkg.add("Example") +@test length(Pkg.required()) == 1 +@test Pkg.required()[1].package == "Example" +Pkg.rm("Example") +@test length(Pkg.required()) == 0 + +# delete temporary Pkg directory +finally +run(`rm -rf $(Pkg.dir())`) +end diff --git a/test/pkg2.jl b/test/pkg2.jl new file mode 100644 index 0000000000000..bc99885bb8886 --- /dev/null +++ b/test/pkg2.jl @@ -0,0 +1,16 @@ +require("pkg2") + +vers = [v"0",v"1",v"2",v"3",v"4"] +ivals = [NoVersions(),AllVersions()] +for v in vers + push!(ivals,VersionsGreater(v)) +end +for v in vers, w in vers + v < w && push!(ivals,VersionsBetween(v,w)) +end +for i1 in ivals, i2 in ivals + i3 = intersect(i1,i2) + for v in vers + @test !((contains(i1,v) & contains(i2,v)) $ contains(i3,v)) + end +end diff --git a/test/poly.jl b/test/poly.jl deleted file mode 100644 index f51f074804943..0000000000000 --- a/test/poly.jl +++ /dev/null @@ -1,55 +0,0 @@ -# assert file to test polynomial -cd("../extras") do -require("poly") - - -pNULL = Polynomial(Float32[]) -p0 = Polynomial([0]) -p1 = Polynomial([0,0,0,0,0,0,0,0,0,0,0,0,0,1]) -p2 = Polynomial([0,0,1,1]) -p3 = Polynomial([0,0,0,0,1,2,1]) -p4 = Polynomial([0,1,3,3,1]) -p5 = Polynomial([0,0,0,0,0,0,0,0,0,0,0,0,0,1,4,6,4,1]) -pN = Polynomial([0,24,15,87,3,276]) -p1000 = Polynomial(randn(1000)) - -@test length(pNULL) == 0 -@test length(p1000) == 1000 -sprint(show, p1000) -sprint(show, pNULL) - -@test p3 == Polynomial([1,2,1]) -@test pN*10 == Polynomial([240, 150, 870, 30, 2760]) -@test pN/10 == Polynomial([2.4, 1.5, 8.7, 0.3, 27.6]) -@test 10*pNULL + pN == pN -@test 10*p0 + pN == pN -@test p5 + 2*p1 == Polynomial([1,4,6,4,3]) -@test 10*pNULL - pN == -pN -@test p0 - pN == -pN -@test p5 - 2*p1 == Polynomial([1,4,6,4,-1]) -@test p2*p2*p2 == p4 -@test p2^4 == p5 -@test pNULL^3 == pNULL -@test pNULL*pNULL == pNULL - -@test polyval(pN, -.125) == 276.9609375 -@test polyval(pNULL, 10) == 0 -@test polyval(p0, -10) == 0 -@test polydir(polyint(pN)) == pN -@test polyint(pNULL,1) == p1 -@test polydir(p3) == Polynomial([2,2]) -@test polydir(p1) == polydir(p0) == polydir(pNULL) == pNULL - -@test poly([-1,-1]) == p3 -@test roots(p0)==roots(p1)==roots(pNULL)==[] -@test roots(p2) == [-1] -a_roots = copy(pN.a) -@test all(abs(sort(roots(poly(a_roots))) - sort(a_roots)) .< 1e6) -@test length(roots(p5)) == 4 -@test roots(pNULL) == [] - -@test pNULL + 2 == p0 + 2 == 2 + p0 == Polynomial([2]) -@test p2 - 2 == -2 + p2 == Polynomial([1,-1]) -@test 2 - p2 == Polynomial([-1,1]) - -end # cd diff --git a/test/random.jl b/test/random.jl index ffa70db293f4b..b3f01890b769a 100644 --- a/test/random.jl +++ b/test/random.jl @@ -1 +1,5 @@ @test rand() != rand() +@test 0.0 <= rand() < 1.0 +@test rand(Uint32) >= 0 +@test -10 <= rand(-10:-5) <= -5 +@test -10 <= rand(-10:5) <= 5 diff --git a/test/remote.jl b/test/remote.jl index 2becd3a933903..ac5a4273f76b7 100644 --- a/test/remote.jl +++ b/test/remote.jl @@ -1,4 +1,17 @@ # Check that serializer hasn't gone out-of-frame -@test Base._jl_ser_tag[Symbol] == 2 -@test Base._jl_ser_tag[()] == 49 -@test Base._jl_ser_tag[false] == 125 +@test Base.ser_tag[Symbol] == 2 +@test Base.ser_tag[()] == 47 +@test Base.ser_tag[false] == 123 + +# issue #1770 +let + a = ['T', 'e', 's', 't'] + f = memio() + serialize(f, a) + seek(f, 0) + @test deserialize(f) == a + f = IOString() + serialize(f, a) + seek(f, 0) + @test deserialize(f) == a +end diff --git a/test/runtests.jl b/test/runtests.jl index 93f3f12fed215..729b3d0d2fceb 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,48 +1,24 @@ -require("test") -using Test +testnames = ["core", "keywordargs", "numbers", "strings", "unicode", "corelib", + "hashing", "remote", "iostring", "arrayops", "linalg", "blas", + "fft", "dct", "sparse", "bitarray", "random", "math", "functional", + "bigint", "sorting", "statistics", "spawn", "parallel", + "suitesparse", "arpack", "bigfloat", "file", "zlib", + "perf"] -function runtests(name) - println(" \033[1m*\033[0m \033[31m$(name)\033[0m") - flush(OUTPUT_STREAM) - load("$name") +if ARGS == ["all"] + tests = testnames +else + tests = ARGS end -function check_approx_eq(va, vb, Eps, astr, bstr) - diff = max(abs(va - vb)) - sdiff = strcat("|", astr, " - ", bstr, "| < ", Eps) - if diff < Eps - nothing - else - error("assertion failed: ", sdiff, "\n ", astr, " = ", va, "\n ", - bstr, " = ", vb) - end -end - -check_approx_eq(va, vb, astr, bstr) = check_approx_eq(va, vb, 10^4*length(va)*eps(max(max(abs(va)), max(abs(vb)))) * max(1, max(abs(va)), max(abs(vb))), astr, bstr) +ENV["OPENBLAS_NUM_THREADS"] = 1 -macro assert_approx_eq_eps(a, b, c) - quote - check_approx_eq($(esc(a)), $(esc(b)), $(esc(c)), $(string(a)), $(string(b))) - end +if CPU_CORES > 1 && length(tests)>2 + addprocs_local(2) end -macro assert_approx_eq(a, b) - quote - check_approx_eq($(esc(a)), $(esc(b)), $(string(a)), $(string(b))) - end -end +require("testdefs.jl") -macro timeit(ex,name) - quote - t = Inf - for i=1:5 - t = min(t, @elapsed $(esc(ex))) - end - println(rpad(strcat($name,":"), 20), t) - end -end +reduce(propagate_errors, nothing, pmap(runtests, tests)) -for t in ARGS - runtests(t) - println(" \033[32;1mSUCCESS\033[0m") -end +println(" \033[32;1mSUCCESS\033[0m") diff --git a/test/sorting.jl b/test/sorting.jl new file mode 100644 index 0000000000000..75b85a705e2ca --- /dev/null +++ b/test/sorting.jl @@ -0,0 +1,182 @@ +@test sort([2,3,1]) == [1,2,3] +@test sort([2,3,1],Sort.Reverse) == [3,2,1] +@test sortperm([2,3,1]) == [3,1,2] +@test !issorted([2,3,1]) +@test issorted([1,2,3]) +@test reverse([2,3,1]) == [1,3,2] +@test select([3,6,30,1,9],3) == 6 +@test sum(randperm(6)) == 21 +@test nthperm([0,1,2],3) == [1,0,2] + +@test searchsortedfirst([1, 1, 2, 2, 3, 3], 0) == 1 +@test searchsortedfirst([1, 1, 2, 2, 3, 3], 1) == 1 +@test searchsortedfirst([1, 1, 2, 2, 3, 3], 2) == 3 +@test searchsortedfirst([1, 1, 2, 2, 3, 3], 4) == 7 +@test searchsortedfirst([1.0, 1, 2, 2, 3, 3], 2.5) == 5 +@test searchsortedlast([1, 1, 2, 2, 3, 3], 0) == 0 +@test searchsortedlast([1, 1, 2, 2, 3, 3], 1) == 2 +@test searchsortedlast([1, 1, 2, 2, 3, 3], 2) == 4 +@test searchsortedlast([1, 1, 2, 2, 3, 3], 4) == 6 +@test searchsortedlast([1.0, 1, 2, 2, 3, 3], 2.5) == 4 + +rg = 49:57; rgv = [rg] +rg_r = 57:-1:49; rgv_r = [rg_r] +for i = 47:59 + @test searchsortedfirst(rg, i) == searchsortedfirst(rgv, i) + @test searchsortedlast(rg, i) == searchsortedlast(rgv, i) + @test searchsortedfirst(rg_r, i, Sort.Reverse) == + searchsortedfirst(rgv_r, i, Sort.Reverse) + @test searchsortedlast(rg_r, i, Sort.Reverse) == + searchsortedlast(rgv_r, i, Sort.Reverse) +end +rg = 1:2:17; rgv = [rg] +rg_r = 17:-2:1; rgv_r = [rg_r] +for i = -1:19 + @test searchsortedfirst(rg, i) == searchsortedfirst(rgv, i) + @test searchsortedlast(rg, i) == searchsortedlast(rgv, i) + @test searchsortedfirst(rg_r, i, Sort.Reverse) == + searchsortedfirst(rgv_r, i, Sort.Reverse) + @test searchsortedlast(rg_r, i, Sort.Reverse) == + searchsortedlast(rgv_r, i, Sort.Reverse) +end +rg = -3:0.5:2; rgv = [rg] +rg_r = 2:-0.5:-3; rgv_r = [rg_r] +for i = -5:.5:4 + @test searchsortedfirst(rg, i) == searchsortedfirst(rgv, i) + @test searchsortedlast(rg, i) == searchsortedlast(rgv, i) + @test searchsortedfirst(rg_r, i, Sort.Reverse) == + searchsortedfirst(rgv_r, i, Sort.Reverse) + @test searchsortedlast(rg_r, i, Sort.Reverse) == + searchsortedlast(rgv_r, i, Sort.Reverse) +end + +a = rand(1:10000, 1000) + +for alg in [InsertionSort, MergeSort, TimSort] + b = sort(a, alg) + @test issorted(b) + ix = sortperm(a, alg) + b = a[ix] + @test issorted(b) + @test a[ix] == b + + b = sort(a, alg, Sort.Reverse) + @test issorted(b, Sort.Reverse) + ix = sortperm(a, alg, Sort.Reverse) + b = a[ix] + @test issorted(b, Sort.Reverse) + @test a[ix] == b + + b = sortby(a, alg, x -> -10x) + @test issorted(b, Sort.By(x -> -10x)) + ix = sortperm(a, alg, Sort.By(x -> -10x)) + b = a[ix] + @test issorted(b, Sort.By(x -> -10x)) + @test a[ix] == b + + c = copy(a) + permute!(c, ix) + @test c == b + + ipermute!(c, ix) + @test c == a + + c = sort(a, alg) do x,y + x > y + end + @test b == c + + c = sortby(a, alg) do x + -10x + end + @test b == c +end + +b = sort(a, QuickSort) +@test issorted(b) +b = sort(a, QuickSort, Sort.Reverse) +@test issorted(b, Sort.Reverse) +b = sortby(a, QuickSort, x -> -10x) +@test issorted(b, Sort.By(x -> -10x)) + +@test select([3,6,30,1,9], 2, Sort.Reverse) == 9 +@test select([3,6,30,1,9], 2, Sort.By(x -> -x)) == 9 + +## more advanced sorting tests ## + +randnans(n) = reinterpret(Float64,[rand(Uint64)|0x7ff8000000000000 for i=1:n]) + +function randn_with_nans(n,p) + v = randn(n) + x = find(rand(n).= -1.0 - io = memio() - wavwrite(in_data, io, @options Fs=fs nbits=nbits compression=WAVE_FORMAT_PCM) - flush(io) - file_size = position(io) - - ## Check for the common header identifiers - seek(io, 0) - @test read(io, Uint8, 4) == b"RIFF" - @test read(io, Uint32) == file_size - 8 - @test read(io, Uint8, 4) == b"WAVE" - - ## Check that wavread works on the wavwrite produced memory - seek(io, 0) - sz = wavread(io, @options format="size") - @test sz == (nsamples, nchans) - - seek(io, 0) - out_data, out_fs, out_nbits, out_extra = wavread(io) - @test length(out_data) == nsamples * nchans - @test size(out_data, 1) == nsamples - @test size(out_data, 2) == nchans - @test typeof(out_data) == Array{Float64, 2} - @test out_fs == fs - @test out_nbits == nbits - @test out_extra == None - @test absdiff(out_data, in_data) < tol - - ## test the "subrange" option. - if nsamples > 0 - seek(io, 0) - # Don't convert to Int, test if passing a float (nsamples/2) behaves as expected - subsamples = min(10, nsamples / 2) - out_data, out_fs, out_nbits, out_extra = wavread(io, @options subrange=subsamples) - @test length(out_data) == subsamples * nchans - @test size(out_data, 1) == subsamples - @test size(out_data, 2) == nchans - @test typeof(out_data) == Array{Float64, 2} - @test out_fs == fs - @test out_nbits == nbits - @test out_extra == None - @test absdiff(out_data, in_data[1:int(subsamples), :]) < tol - - seek(io, 0) - sr = convert(Int, min(5, nsamples / 2)):convert(Int, min(23, nsamples - 1)) - out_data, out_fs, out_nbits, out_extra = wavread(io, @options subrange=sr) - @test length(out_data) == length(sr) * nchans - @test size(out_data, 1) == length(sr) - @test size(out_data, 2) == nchans - @test typeof(out_data) == Array{Float64, 2} - @test out_fs == fs - @test out_nbits == nbits - @test out_extra == None - @test absdiff(out_data, in_data[sr, :]) < tol - end -end - -## Test native encoding of 8 bits -for nchans = (1,2,4) - in_data_8 = reshape(typemin(Uint8):typemax(Uint8), int(256 / nchans), nchans) - io = memio() - wavwrite(in_data_8, io) - flush(io) - - seek(io, 0) - out_data_8, fs, nbits, extra = wavread(io, @options format="native") - @test fs == 8000 - @test nbits == 8 - @test extra == None - @test in_data_8 == out_data_8 -end - -## Test native encoding of 16 bits -for nchans = (1,2,4) - in_data_16 = reshape(typemin(Int16):typemax(Int16), int(65536 / nchans), nchans) - io = memio() - wavwrite(in_data_16, io) - flush(io) - - seek(io, 0) - out_data_16, fs, nbits, extra = wavread(io, @options format="native") - @test fs == 8000 - @test nbits == 16 - @test extra == None - @test in_data_16 == out_data_16 -end - -## Test native encoding of 24 bits -for nchans = (1,2,4) - in_data_24 = convert(Array{Int32}, reshape(-63:64, int(128 / nchans), nchans)) - io = memio() - wavwrite(in_data_24, io) - flush(io) - - seek(io, 0) - out_data_24, fs, nbits, extra = wavread(io, @options format="native") - @test fs == 8000 - @test nbits == 24 - @test extra == None - @test in_data_24 == out_data_24 -end - -## Test encoding 32 bit values -for nchans = (1,2,4) - in_data_single = convert(Array{Float32}, reshape(linspace(-1.0, 1.0, 128), int(128 / nchans), nchans)) - io = memio() - wavwrite(in_data_single, io) - flush(io) - - seek(io, 0) - out_data_single, fs, nbits, extra = wavread(io, @options format="native") - @test fs == 8000 - @test nbits == 32 - @test extra == None - @test in_data_single == out_data_single -end - -## Test encoding 32 bit values outside the valid range -for nchans = (1,2,4) - nsamps = int(128 / nchans) - in_data_single = convert(Array{Float32}, reshape(-63:64, nsamps, nchans)) - io = memio() - wavwrite(in_data_single, io) - flush(io) - - seek(io, 0) - out_data_single, fs, nbits, extra = wavread(io, @options format="native") - @test fs == 8000 - @test nbits == 32 - @test extra == None - @test [clamp(in_data_single[i, j], float32(-1), float32(1)) for i = 1:nsamps, j = 1:nchans] == out_data_single -end diff --git a/test/sparse.jl b/test/sparse.jl index dc8618808a0c6..ea888d64cbcef 100644 --- a/test/sparse.jl +++ b/test/sparse.jl @@ -1,8 +1,15 @@ +# check sparse matrix construction +@test isequal(full(sparse(complex(ones(5,5),ones(5,5)))), complex(ones(5,5),ones(5,5))) + # check matrix operations se33 = speye(3) do33 = ones(3) @test isequal(se33 * se33, se33) +# check sparse binary op +@test all(full(se33 + convert(SparseMatrixCSC{Float32,Int32}, se33)) == 2*eye(3)) +@test all(full(se33 * convert(SparseMatrixCSC{Float32,Int32}, se33)) == eye(3)) + # check horiz concatenation @test all([se33 se33] == sparse([1, 2, 3, 1, 2, 3], [1, 2, 3, 4, 5, 6], ones(6))) @@ -58,7 +65,7 @@ s116[p, p] = reshape(1:9, 3, 3) for i = 1:5 a = sprand(10, 5, 0.5) b = sprand(5, 10, 0.1) - @assert_approx_eq max(abs(a*b - dense(a)*dense(b))) 0.0 + @test max(abs(a*b - dense(a)*dense(b))) < 100*eps() end # reductions diff --git a/test/spawn.jl b/test/spawn.jl new file mode 100644 index 0000000000000..f7c9f10ffd8a7 --- /dev/null +++ b/test/spawn.jl @@ -0,0 +1,43 @@ +################################## +# Cross Plaform tests for spawn. # +################################## + +# Assumes the following are available in the +# - GNU coreutils (or equivalent) +# - perl + +#TODO: +# - Windows: +# - Add a test whether coreutils are available and skip tests if not + +#### Examples used in the manual #### + +@test readall(`echo hello | sort`) == "hello | sort\n" +@test readall(`echo hello`|`sort`) == "hello\n" + +out = readall(`echo hello` & `echo world`) +@test search(out,"world") != (0,0) +@test search(out,"hello") != (0,0) +@test readall((`echo hello` & `echo world`)|`sort`)=="hello\nworld\n" + +@test (run(`printf " \033[34m[stdio passthrough ok]\033[0m\n"`); true) + +if false + prefixer(prefix, sleep) = `perl -nle '$|=1; print "'$prefix' ", $_; sleep '$sleep';'` + @test success(`perl -le '$|=1; for(0..2){ print; sleep 1 }'` | + prefixer("A",2) & prefixer("B",2)) + @test success(`perl -le '$|=1; for(0..2){ print; sleep 1 }'` | + prefixer("X",3) & prefixer("Y",3) & prefixer("Z",3) | + prefixer("A",2) & prefixer("B",2)) +end + +@test success(`true`) +@test !success(`false`) +if false + @test success(ignorestatus(`false`)) + @test success(ignorestatus(`false`) | `true`) + @test !success(ignorestatus(`false`) | `false`) + @test !success(ignorestatus(`false`) & `false`) + @test success(ignorestatus(`false` | `false`)) + @test success(ignorestatus(`false` & `false`)) +end diff --git a/test/statistics.jl b/test/statistics.jl index dad62bfb09c71..b9164bcc3ae07 100644 --- a/test/statistics.jl +++ b/test/statistics.jl @@ -1,17 +1,44 @@ - @test median([1.]) == 1. @test median([1.,3]) == 2. @test median([1.,3,2]) == 2. -# integer array -@test median([1,3,2]) == 2 +@test median([1,3,2]) == 2.0 +@test median([1,3,2,4]) == 2.5 + +@test median([0.0,Inf]) == Inf +@test median([0.0,-Inf]) == -Inf +@test median([0.,Inf,-Inf]) == 0.0 +@test median([1.,-1.,Inf,-Inf]) == 0.0 +@test isnan(median([-Inf,Inf])) + +@test_fails median([]) +@test_fails median([NaN]) +@test_fails median([0.0,NaN]) +@test_fails median([NaN,0.0]) @test mean([1,2,3]) == 2. +@test mean([0 1 2; 4 5 6], 1) == [2. 3. 4.] @test var([1,2,3]) == 1. +@test var(1:8) == 6. +@test var([1 2 3 4 5; 6 7 8 9 10], 2) == [2.5 2.5]' +@test varm([1,2,3], 2) == 1. @test std([1,2,3]) == 1. -@test hist([1,2,3],10) == [1,0,0,0,0,1,0,0,0,1] -@test histc([1,2,3],[0,2,4]) == [1,2,0] +@test stdm([1,2,3], 2) == 1. +@test sum(hist([1,2,3])[2]) == 3 +@test hist([])[2] == [] +@test hist([1])[2] == [1] +@test hist([1,2,3],[0,2,4]) == ([0,2,4],[2,1]) +@test hist([1,2,3],0:2:4) == (0:2:4,[2,1]) +@test midpoints(1.0:1.0:10.0) == 1.5:1.0:9.5 +@test midpoints(1:10) == 1.5:9.5 +@test midpoints(Float64[1.0:1.0:10.0]) == Float64[1.5:1.0:9.5] @test quantile([1,2,3,4],0.5) == 2.5 -@test quartile([1., 3])[2] == median([1., 3]) -@test decile([0.:100.])[1] == 10.0 +@test quantile([1., 3],[.25,.5,.75])[2] == median([1., 3]) +@test quantile([0.:100.],[.1,.2,.3,.4,.5,.6,.7,.8,.9])[1] == 10.0 + +# Test covariance +X = [1 0; 2 1; 3 0; 4 1; 5 10] +y = [5, 3, 4, 2, 5] +@test_approx_eq cov(X[:,1], X[:,2]) cov(X)[1,2] +@assert issym(cov(X)) diff --git a/test/strings.jl b/test/strings.jl index 49a2155419660..11a28ba453cb9 100644 --- a/test/strings.jl +++ b/test/strings.jl @@ -54,7 +54,7 @@ cx = { for i = 1:size(cx,1) @test cx[i,1] == cx[i,2] @test string(cx[i,2]) == unescape_string(cx[i,3]) - if iswascii(cx[i,2]) || !iswprint(cx[i,2]) + if isascii(cx[i,2]) || !isprint(cx[i,2]) @test cx[i,3] == escape_string(string(cx[i,2])) end for j = 1:size(cx,1) @@ -69,13 +69,13 @@ for i = 0:0x7f, p = {"","\0","x","xxx","\x7f","\uFF","\uFFF", cp = string(c,p) op = string(char(div(i,8)), oct(i%8), p) hp = string(char(div(i,16)), hex(i%16), p) - @test strcat(unescape_string(strcat("\\",oct(i,1),p))) == cp - @test strcat(unescape_string(strcat("\\",oct(i,2),p))) == cp - @test strcat(unescape_string(strcat("\\",oct(i,3),p))) == cp - @test strcat(unescape_string(strcat("\\",oct(i,4),p))) == op - @test strcat(unescape_string(strcat("\\x",hex(i,1),p))) == cp - @test strcat(unescape_string(strcat("\\x",hex(i,2),p))) == cp - @test strcat(unescape_string(strcat("\\x",hex(i,3),p))) == hp + @test string(unescape_string(string("\\",oct(i,1),p))) == cp + @test string(unescape_string(string("\\",oct(i,2),p))) == cp + @test string(unescape_string(string("\\",oct(i,3),p))) == cp + @test string(unescape_string(string("\\",oct(i,4),p))) == op + @test string(unescape_string(string("\\x",hex(i,1),p))) == cp + @test string(unescape_string(string("\\x",hex(i,2),p))) == cp + @test string(unescape_string(string("\\x",hex(i,3),p))) == hp end @test "\z" == unescape_string("\z") == "z" @@ -132,93 +132,91 @@ end @test "\x0f" == unescape_string("\\x0f") @test "\x0F" == unescape_string("\\x0F") -# TODO: more Unicode testing here. - -@test S"foo\xe2\x88\x80" == "foo\xe2\x88\x80" - -# TODO: the above is only one of many needed tests - # integer parsing -@test parse_int(Int32,"0",36) == 0 -@test parse_int(Int32,"1",36) == 1 -@test parse_int(Int32,"9",36) == 9 -@test parse_int(Int32,"A",36) == 10 -@test parse_int(Int32,"a",36) == 10 -@test parse_int(Int32,"B",36) == 11 -@test parse_int(Int32,"b",36) == 11 -@test parse_int(Int32,"F",36) == 15 -@test parse_int(Int32,"f",36) == 15 -@test parse_int(Int32,"Z",36) == 35 -@test parse_int(Int32,"z",36) == 35 - -@test parse_int("0") == 0 -@test parse_int("-0") == 0 -@test parse_int("1") == 1 -@test parse_int("-1") == -1 -@test parse_int("9") == 9 -@test parse_int("-9") == -9 -@test parse_int("10") == 10 -@test parse_int("-10") == -10 -@test parse_int(Int64,"3830974272") == 3830974272 -@test parse_int(Int64,"-3830974272") == -3830974272 - -@test parse_bin("0") == 0 -@test parse_bin("-0") == 0 -@test parse_bin("1") == 1 -@test parse_bin("-1") == -1 -@test parse_bin("10") == 2 -@test parse_bin("-10") == -2 -@test parse_bin("11") == 3 -@test parse_bin("-11") == -3 -@test parse_bin("1111000011110000111100001111") == 252645135 -@test parse_bin("-1111000011110000111100001111") == -252645135 - -@test parse_oct("0") == 0 -@test parse_oct("-0") == 0 -@test parse_oct("1") == 1 -@test parse_oct("-1") == -1 -@test parse_oct("7") == 7 -@test parse_oct("-7") == -7 -@test parse_oct("10") == 8 -@test parse_oct("-10") == -8 -@test parse_oct("11") == 9 -@test parse_oct("-11") == -9 -@test parse_oct("72") == 58 -@test parse_oct("-72") == -58 -@test parse_oct("3172207320") == 434704080 -@test parse_oct("-3172207320") == -434704080 - -@test parse_hex("0") == 0 -@test parse_hex("-0") == 0 -@test parse_hex("1") == 1 -@test parse_hex("-1") == -1 -@test parse_hex("9") == 9 -@test parse_hex("-9") == -9 -@test parse_hex("a") == 10 -@test parse_hex("-a") == -10 -@test parse_hex("f") == 15 -@test parse_hex("-f") == -15 -@test parse_hex("10") == 16 -@test parse_hex("-10") == -16 -@test parse_hex("0BADF00D") == 195948557 -@test parse_hex("-0BADF00D") == -195948557 -@test parse_int(Int64,"BADCAB1E",16) == 3135023902 -@test parse_int(Int64,"-BADCAB1E",16) == -3135023902 -@test parse_int(Int64,"CafeBabe",16) == 3405691582 -@test parse_int(Int64,"-CafeBabe",16) == -3405691582 -@test parse_int(Int64,"DeadBeef",16) == 3735928559 -@test parse_int(Int64,"-DeadBeef",16) == -3735928559 - -@test parse_int("2\n") == 2 -@test parse_int(" 2 \n ") == 2 -@test parse_int(" 2 ") == 2 -@test parse_int("2 ") == 2 -@test parse_int(" 2") == 2 -@test parse_int("+2\n") == 2 -@test parse_int("-2") == -2 -@test_fails parse_int(" 2 \n 0") -@test_fails parse_int("2x") -@test_fails parse_int("-") +@test is(parseint(Int32,"0",36),int32(0)) +@test is(parseint(Int32,"1",36),int32(1)) +@test is(parseint(Int32,"9",36),int32(9)) +@test is(parseint(Int32,"A",36),int32(10)) +@test is(parseint(Int32,"a",36),int32(10)) +@test is(parseint(Int32,"B",36),int32(11)) +@test is(parseint(Int32,"b",36),int32(11)) +@test is(parseint(Int32,"F",36),int32(15)) +@test is(parseint(Int32,"f",36),int32(15)) +@test is(parseint(Int32,"Z",36),int32(35)) +@test is(parseint(Int32,"z",36),int32(35)) + +@test parseint("0") == 0 +@test parseint("-0") == 0 +@test parseint("1") == 1 +@test parseint("-1") == -1 +@test parseint("9") == 9 +@test parseint("-9") == -9 +@test parseint("10") == 10 +@test parseint("-10") == -10 +@test parseint(Int64,"3830974272") == 3830974272 +@test parseint(Int64,"-3830974272") == -3830974272 + +parsebin(s) = parseint(s,2) +parseoct(s) = parseint(s,8) +parsehex(s) = parseint(s,16) + +@test parsebin("0") == 0 +@test parsebin("-0") == 0 +@test parsebin("1") == 1 +@test parsebin("-1") == -1 +@test parsebin("10") == 2 +@test parsebin("-10") == -2 +@test parsebin("11") == 3 +@test parsebin("-11") == -3 +@test parsebin("1111000011110000111100001111") == 252645135 +@test parsebin("-1111000011110000111100001111") == -252645135 + +@test parseoct("0") == 0 +@test parseoct("-0") == 0 +@test parseoct("1") == 1 +@test parseoct("-1") == -1 +@test parseoct("7") == 7 +@test parseoct("-7") == -7 +@test parseoct("10") == 8 +@test parseoct("-10") == -8 +@test parseoct("11") == 9 +@test parseoct("-11") == -9 +@test parseoct("72") == 58 +@test parseoct("-72") == -58 +@test parseoct("3172207320") == 434704080 +@test parseoct("-3172207320") == -434704080 + +@test parsehex("0") == 0 +@test parsehex("-0") == 0 +@test parsehex("1") == 1 +@test parsehex("-1") == -1 +@test parsehex("9") == 9 +@test parsehex("-9") == -9 +@test parsehex("a") == 10 +@test parsehex("-a") == -10 +@test parsehex("f") == 15 +@test parsehex("-f") == -15 +@test parsehex("10") == 16 +@test parsehex("-10") == -16 +@test parsehex("0BADF00D") == 195948557 +@test parsehex("-0BADF00D") == -195948557 +@test parseint(Int64,"BADCAB1E",16) == 3135023902 +@test parseint(Int64,"-BADCAB1E",16) == -3135023902 +@test parseint(Int64,"CafeBabe",16) == 3405691582 +@test parseint(Int64,"-CafeBabe",16) == -3405691582 +@test parseint(Int64,"DeadBeef",16) == 3735928559 +@test parseint(Int64,"-DeadBeef",16) == -3735928559 + +@test parseint("2\n") == 2 +@test parseint(" 2 \n ") == 2 +@test parseint(" 2 ") == 2 +@test parseint("2 ") == 2 +@test parseint(" 2") == 2 +@test parseint("+2\n") == 2 +@test parseint("-2") == -2 +@test_fails parseint(" 2 \n 0") +@test_fails parseint("2x") +@test_fails parseint("-") # string manipulation @test strip("\t hi \n") == "hi" @@ -227,167 +225,172 @@ end astr = "Hello, world.\n" u8str = "∀ ε > 0, ∃ δ > 0: |x-y| < δ ⇒ |f(x)-f(y)| < ε" -# ascii strchr -for str in {astr, GenericString(astr)} - @test strchr(str, 'x') == 0 - @test strchr(str, '\0') == 0 - @test strchr(str, '\u80') == 0 - @test strchr(str, '∀') == 0 - @test strchr(str, 'H') == 1 - @test strchr(str, 'l') == 3 - @test strchr(str, 'l', 4) == 4 - @test strchr(str, 'l', 5) == 11 - @test strchr(str, 'l', 12) == 0 - @test strchr(str, ',') == 6 - @test strchr(str, ',', 7) == 0 - @test strchr(str, '\n') == 14 +# ascii search +for str in {astr, Base.GenericString(astr)} + @test search(str, 'x') == 0 + @test search(str, '\0') == 0 + @test search(str, '\u80') == 0 + @test search(str, '∀') == 0 + @test search(str, 'H') == 1 + @test search(str, 'l') == 3 + @test search(str, 'l', 4) == 4 + @test search(str, 'l', 5) == 11 + @test search(str, 'l', 12) == 0 + @test search(str, ',') == 6 + @test search(str, ',', 7) == 0 + @test search(str, '\n') == 14 end -# utf-8 strchr -for str in {u8str, GenericString(u8str)} - @test strchr(str, 'z') == 0 - @test strchr(str, '\0') == 0 - @test strchr(str, '\u80') == 0 - @test strchr(str, '∄') == 0 - @test strchr(str, '∀') == 1 - @test strchr(str, '∀', 2) == 0 - @test strchr(str, '∃') == 13 - @test strchr(str, '∃', 14) == 0 - @test strchr(str, 'x') == 26 - @test strchr(str, 'x', 27) == 43 - @test strchr(str, 'x', 44) == 0 - @test strchr(str, 'δ') == 17 - @test strchr(str, 'δ', 18) == 33 - @test strchr(str, 'δ', 34) == 0 - @test strchr(str, 'ε') == 5 - @test strchr(str, 'ε', 6) == 54 - @test strchr(str, 'ε', 55) == 0 +# utf-8 search +for str in {u8str, Base.GenericString(u8str)} + @test search(str, 'z') == 0 + @test search(str, '\0') == 0 + @test search(str, '\u80') == 0 + @test search(str, '∄') == 0 + @test search(str, '∀') == 1 + @test search(str, '∀', 2) == 0 + @test search(str, '∃') == 13 + @test search(str, '∃', 14) == 0 + @test search(str, 'x') == 26 + @test search(str, 'x', 27) == 43 + @test search(str, 'x', 44) == 0 + @test search(str, 'δ') == 17 + @test search(str, 'δ', 18) == 33 + @test search(str, 'δ', 34) == 0 + @test search(str, 'ε') == 5 + @test search(str, 'ε', 6) == 54 + @test search(str, 'ε', 55) == 0 end # string search with a char -@test search(astr, 'x')[1] == 0 -@test search(astr, 'H') == (1,2) -@test search(astr, 'H', 2)[1] == 0 -@test search(astr, 'l') == (3,4) -@test search(astr, 'l', 4) == (4,5) -@test search(astr, 'l', 5) == (11,12) -@test search(astr, 'l', 12)[1] == 0 -@test search(astr, '\n') == (14,15) -@test search(astr, '\n', 15)[1] == 0 -@test search(u8str, 'z')[1] == 0 -@test search(u8str, '∄')[1] == 0 -@test search(u8str, '∀') == (1,4) -@test search(u8str, '∀', 4)[1] == 0 -@test search(u8str, '∃') == (13,16) -@test search(u8str, '∃', 16)[1] == 0 -@test search(u8str, 'x') == (26,27) -@test search(u8str, 'x', 27) == (43,44) -@test search(u8str, 'x', 44)[1] == 0 -@test search(u8str, 'ε') == (5,7) -@test search(u8str, 'ε', 7) == (54,56) -@test search(u8str, 'ε', 56)[1] == 0 +@test search(astr, 'x') == 0 +@test search(astr, 'H') == 1 +@test search(astr, 'H', 2) == 0 +@test search(astr, 'l') == 3 +@test search(astr, 'l', 4) == 4 +@test search(astr, 'l', 5) == 11 +@test search(astr, 'l', 12) == 0 +@test search(astr, '\n') == 14 +@test search(astr, '\n', 15) == 0 +@test search(u8str, 'z') == 0 +@test search(u8str, '∄') == 0 +@test search(u8str, '∀') == 1 +@test search(u8str, '∀', 4) == 0 +@test search(u8str, '∃') == 13 +@test search(u8str, '∃', 16) == 0 +@test search(u8str, 'x') == 26 +@test search(u8str, 'x', 27) == 43 +@test search(u8str, 'x', 44) == 0 +@test search(u8str, 'ε') == 5 +# TODO: the character case returns (54,55), but searching for this as a +# 1-character string returns (54,56) (see below). This might be OK if all +# that matters is "> endof(s)", but needs investigation. +@test search(u8str, 'ε', 7) == 54 +@test search(u8str, 'ε', 56) == 0 # string search with a single-char string -@test search(astr, "x")[1] == 0 -@test search(astr, "H") == (1,2) -@test search(astr, "H", 2)[1] == 0 -@test search(astr, "l") == (3,4) -@test search(astr, "l", 4) == (4,5) -@test search(astr, "l", 5) == (11,12) -@test search(astr, "l", 12)[1] == 0 -@test search(astr, "\n") == (14,15) -@test search(astr, "\n", 15)[1] == 0 -@test search(u8str, "z")[1] == 0 -@test search(u8str, "∄")[1] == 0 -@test search(u8str, "∀") == (1,4) -@test search(u8str, "∀", 4)[1] == 0 -@test search(u8str, "∃") == (13,16) -@test search(u8str, "∃", 16)[1] == 0 -@test search(u8str, "x") == (26,27) -@test search(u8str, "x", 27) == (43,44) -@test search(u8str, "x", 44)[1] == 0 -@test search(u8str, "ε") == (5,7) -@test search(u8str, "ε", 7) == (54,56) -@test search(u8str, "ε", 56)[1] == 0 +@test search(astr, "x") == 0:-1 +@test search(astr, "H") == 1:1 +@test search(astr, "H", 2) == 0:-1 +@test search(astr, "l") == 3:3 +@test search(astr, "l", 4) == 4:4 +@test search(astr, "l", 5) == 11:11 +@test search(astr, "l", 12) == 0:-1 +@test search(astr, "\n") == 14:14 +@test search(astr, "\n", 15) == 0:-1 +@test search(u8str, "z") == 0:-1 +@test search(u8str, "∄") == 0:-1 +@test search(u8str, "∀") == 1:3 +@test search(u8str, "∀", 4) == 0:-1 +@test search(u8str, "∃") == 13:15 +@test search(u8str, "∃", 16) == 0:-1 +@test search(u8str, "x") == 26:26 +@test search(u8str, "x", 27) == 43:43 +@test search(u8str, "x", 44) == 0:-1 +@test search(u8str, "ε") == 5:6 +@test search(u8str, "ε", 7) == 54:55 +@test search(u8str, "ε", 56) == 0:-1 # string search with a single-char regex -@test search(astr, r"x")[1] == 0 -@test search(astr, r"H") == (1,2) -@test search(astr, r"H", 2)[1] == 0 -@test search(astr, r"l") == (3,4) -@test search(astr, r"l", 4) == (4,5) -@test search(astr, r"l", 5) == (11,12) -@test search(astr, r"l", 12)[1] == 0 -@test search(astr, r"\n") == (14,15) -@test search(astr, r"\n", 15)[1] == 0 -@test search(u8str, r"z")[1] == 0 -@test search(u8str, r"∄")[1] == 0 -@test search(u8str, r"∀") == (1,4) -@test search(u8str, r"∀", 4)[1] == 0 -@test search(u8str, r"∃") == (13,16) -@test search(u8str, r"∃", 16)[1] == 0 -@test search(u8str, r"x") == (26,27) -@test search(u8str, r"x", 27) == (43,44) -@test search(u8str, r"x", 44)[1] == 0 -@test search(u8str, r"ε") == (5,7) -@test search(u8str, r"ε", 7) == (54,56) -@test search(u8str, r"ε", 56)[1] == 0 +@test search(astr, r"x") == 0:-1 +@test search(astr, r"H") == 1:1 +@test search(astr, r"H", 2) == 0:-1 +@test search(astr, r"l") == 3:3 +@test search(astr, r"l", 4) == 4:4 +@test search(astr, r"l", 5) == 11:11 +@test search(astr, r"l", 12) == 0:-1 +@test search(astr, r"\n") == 14:14 +@test search(astr, r"\n", 15) == 0:-1 +@test search(u8str, r"z") == 0:-1 +@test search(u8str, r"∄") == 0:-1 +@test search(u8str, r"∀") == 1:3 +@test search(u8str, r"∀", 4) == 0:-1 +@test search(u8str, r"∀") == search(u8str, r"\u2200") +@test search(u8str, r"∀", 4) == search(u8str, r"\u2200", 4) +@test search(u8str, r"∃") == 13:15 +@test search(u8str, r"∃", 16) == 0:-1 +@test search(u8str, r"x") == 26:26 +@test search(u8str, r"x", 27) == 43:43 +@test search(u8str, r"x", 44) == 0:-1 +@test search(u8str, r"ε") == 5:6 +@test search(u8str, r"ε", 7) == 54:55 +@test search(u8str, r"ε", 56) == 0:-1 for i = 1:length(astr) - @test search(astr, r"."s, i) == (i,i+1) + @test search(astr, r"."s, i) == i:i end for i = 1:length(u8str) # TODO: should regex search fast-forward invalid indices? if isvalid(u8str,i) - @test search(u8str, r"."s, i) == (i,nextind(u8str,i)) + @test search(u8str, r"."s, i) == i:(nextind(u8str,i)-1) end end # string search with a zero-char string for i = 1:length(astr) - @test search(astr, "", i) == (i,i) + @test search(astr, "", i) == i:i-1 end for i = 1:length(u8str) - @test search(u8str, "", i) == (i,i) + @test search(u8str, "", i) == i:i-1 end # string search with a zero-char regex for i = 1:length(astr) - @test search(astr, r"", i) == (i,i) + @test search(astr, r"", i) == i:i-1 end for i = 1:length(u8str) # TODO: should regex search fast-forward invalid indices? if isvalid(u8str,i) - @test search(u8str, r""s, i) == (i,i) + @test search(u8str, r""s, i) == i:i-1 end end # string search with a two-char string literal -@test search("foo,bar,baz", "xx")[1] == 0 -@test search("foo,bar,baz", "fo") == (1,3) -@test search("foo,bar,baz", "fo", 3)[1] == 0 -@test search("foo,bar,baz", "oo") == (2,4) -@test search("foo,bar,baz", "oo", 4)[1] == 0 -@test search("foo,bar,baz", "o,") == (3,5) -@test search("foo,bar,baz", "o,", 5)[1] == 0 -@test search("foo,bar,baz", ",b") == (4,6) -@test search("foo,bar,baz", ",b", 6) == (8,10) -@test search("foo,bar,baz", ",b", 10)[1] == 0 -@test search("foo,bar,baz", "az") == (10,12) -@test search("foo,bar,baz", "az", 12)[1] == 0 +@test search("foo,bar,baz", "xx") == 0:-1 +@test search("foo,bar,baz", "fo") == 1:2 +@test search("foo,bar,baz", "fo", 3) == 0:-1 +@test search("foo,bar,baz", "oo") == 2:3 +@test search("foo,bar,baz", "oo", 4) == 0:-1 +@test search("foo,bar,baz", "o,") == 3:4 +@test search("foo,bar,baz", "o,", 5) == 0:-1 +@test search("foo,bar,baz", ",b") == 4:5 +@test search("foo,bar,baz", ",b", 6) == 8:9 +@test search("foo,bar,baz", ",b", 10) == 0:-1 +@test search("foo,bar,baz", "az") == 10:11 +@test search("foo,bar,baz", "az", 12) == 0:-1 # string search with a two-char regex -@test search("foo,bar,baz", r"xx")[1] == 0 -@test search("foo,bar,baz", r"fo") == (1,3) -@test search("foo,bar,baz", r"fo", 3)[1] == 0 -@test search("foo,bar,baz", r"oo") == (2,4) -@test search("foo,bar,baz", r"oo", 4)[1] == 0 -@test search("foo,bar,baz", r"o,") == (3,5) -@test search("foo,bar,baz", r"o,", 5)[1] == 0 -@test search("foo,bar,baz", r",b") == (4,6) -@test search("foo,bar,baz", r",b", 6) == (8,10) -@test search("foo,bar,baz", r",b", 10)[1] == 0 -@test search("foo,bar,baz", r"az") == (10,12) -@test search("foo,bar,baz", r"az", 12)[1] == 0 +@test search("foo,bar,baz", r"xx") == 0:-1 +@test search("foo,bar,baz", r"fo") == 1:2 +@test search("foo,bar,baz", r"fo", 3) == 0:-1 +@test search("foo,bar,baz", r"oo") == 2:3 +@test search("foo,bar,baz", r"oo", 4) == 0:-1 +@test search("foo,bar,baz", r"o,") == 3:4 +@test search("foo,bar,baz", r"o,", 5) == 0:-1 +@test search("foo,bar,baz", r",b") == 4:5 +@test search("foo,bar,baz", r",b", 6) == 8:9 +@test search("foo,bar,baz", r",b", 10) == 0:-1 +@test search("foo,bar,baz", r"az") == 10:11 +@test search("foo,bar,baz", r"az", 12) == 0:-1 # split @test isequal(split("foo,bar,baz", 'x'), ["foo,bar,baz"]) @@ -455,24 +458,24 @@ end @test replace("abcd", r"b?c?", "^") == "^a^d^" @test replace("abcd", r"[bc]?", "^") == "^a^^d^" -# {begins,ends}_with -@test begins_with("abcd", 'a') -@test begins_with("abcd", "a") -@test begins_with("abcd", "ab") -@test !begins_with("ab", "abcd") -@test !begins_with("abcd", "bc") -@test ends_with("abcd", 'd') -@test ends_with("abcd", "d") -@test ends_with("abcd", "cd") -@test !ends_with("abcd", "dc") -@test !ends_with("cd", "abcd") +# {begins,ends}with +@test beginswith("abcd", 'a') +@test beginswith("abcd", "a") +@test beginswith("abcd", "ab") +@test !beginswith("ab", "abcd") +@test !beginswith("abcd", "bc") +@test endswith("abcd", 'd') +@test endswith("abcd", "d") +@test endswith("abcd", "cd") +@test !endswith("abcd", "dc") +@test !endswith("cd", "abcd") # RepStrings and SubStrings u8str2 = u8str^2 len_u8str = length(u8str) -slen_u8str = strlen(u8str) +slen_u8str = length(u8str) len_u8str2 = length(u8str2) -slen_u8str2 = strlen(u8str2) +slen_u8str2 = length(u8str2) @test len_u8str2 == 2 * len_u8str @test slen_u8str2 == 2 * slen_u8str @@ -484,13 +487,70 @@ for i1 = 1:length(u8str2) for i2 = i1:length(u8str2) if !isvalid(u8str2, i2); continue; end @test length(u8str2[i1:i2]) == length(u8str2plain[i1:i2]) - @test strlen(u8str2[i1:i2]) == strlen(u8str2plain[i1:i2]) + @test length(u8str2[i1:i2]) == length(u8str2plain[i1:i2]) @test u8str2[i1:i2] == u8str2plain[i1:i2] end end +# quotes + interpolation (issue #455) +@test "$("string")" == "string" +arr = ["a","b","c"] +@test "[$(join(arr, " - "))]" == "[a - b - c]" + # string iteration, and issue #1454 str = "é" str_a = [str...] @test length(str_a)==1 @test str_a[1] == str[1] + +str = "s\u2200" +@test str[1:end] == str + +# triple-quote delimited strings +@test """abc""" == "abc" +@test """ab"c""" == "ab\"c" +@test """ab""c""" == "ab\"\"c" +@test """ab"\"c""" == "ab\"\"c" +@test """abc\"""" == "abc\"" +n = 3 +@test """$n\n""" == "$n\n" +@test """$(n)""" == "3" +@test """$(2n)""" == "6" +@test """$(n+4)""" == "7" +@test """$("string")""" == "string" +a = [3,1,2] +@test """$(a[2])""" == "1" +@test """$(a[3]+7)""" == "9" +@test """$(ifloor(4.5))""" == "4" +@test """ + a + b + + c + """ == "a\nb\n\nc\n" +@test """ + """ == "" +@test """x + a + """ == "x\n a\n" +@test """ + $n + """ == " $n\n" +@test """ + a + b + c""" == " a\nb\n c" +# note tab/space mixing +@test """ + a + b + """ == " a\nb\n" +@test """ + a + """ == "a\n" +s = " p" +@test """ + $s""" == "$s" +@test """ + $s + """ == " $s\n" diff --git a/test/suitesparse.jl b/test/suitesparse.jl index 8f98f3e436087..abc0620016de4 100644 --- a/test/suitesparse.jl +++ b/test/suitesparse.jl @@ -1,7 +1,151 @@ -require("extras/suitesparse") - -using SuiteSparse - se33 = speye(3) do33 = ones(3) @test isequal(se33 \ do33, do33) + +# based on deps/Suitesparse-4.0.2/UMFPACK/Demo/umfpack_di_demo.c + +using Base.LinAlg.UMFPACK.increment! + +A = sparse(increment!([0,4,1,1,2,2,0,1,2,3,4,4]), + increment!([0,4,0,2,1,2,1,4,3,2,1,2]), + [2.,1.,3.,4.,-1.,-3.,3.,6.,2.,1.,4.,2.], 5, 5) +lua = lufact(A) +L,U,p,q,Rs = lua[:(:)] +@test_approx_eq diagmm(Rs,A)[p,q] L*U + +@test_approx_eq det(lua) det(full(A)) + +b = [8., 45., -3., 3., 19.] +x = lua\b +@test_approx_eq x float([1:5]) + +@test norm(A*x-b,1) < eps(1e4) + +b = [8., 20., 13., 6., 17.] +x = lua'\b +@test_approx_eq x float([1:5]) + +@test norm(A'*x-b,1) < eps(1e4) + +using Base.LinAlg.CHOLMOD + +# based on deps/SuiteSparse-4.0.2/CHOLMOD/Demo/ + +# chm_rdsp(joinpath(JULIA_HOME, "../../deps/SuiteSparse-4.0.2/CHOLMOD/Demo/Matrix/bcsstk01.tri")) +# because the file may not exist in binary distributions and when a system suitesparse library +# is used + +## Result from C program +## ---------------------------------- cholmod_demo: +## norm (A,inf) = 3.57095e+09 +## norm (A,1) = 3.57095e+09 +## CHOLMOD sparse: A: 48-by-48, nz 224, upper. OK +## CHOLMOD dense: B: 48-by-1, OK +## bnorm 1.97917 +## Analyze: flop 6009 lnz 489 +## Factorizing A +## CHOLMOD factor: L: 48-by-48 simplicial, LDL'. nzmax 489. nz 489 OK +## Ordering: AMD fl/lnz 12.3 lnz/anz 2.2 +## ints in L: 782, doubles in L: 489 +## factor flops 6009 nnz(L) 489 (w/no amalgamation) +## nnz(A*A'): 224 +## flops / nnz(L): 12.3 +## nnz(L) / nnz(A): 2.2 +## analyze cputime: 0.0000 +## factor cputime: 0.0000 mflop: 0.0 +## solve cputime: 0.0000 mflop: 0.0 +## overall cputime: 0.0000 mflop: 0.0 +## peak memory usage: 0 (MB) +## residual 2.5e-19 (|Ax-b|/(|A||x|+|b|)) +## residual 1.3e-19 (|Ax-b|/(|A||x|+|b|)) after iterative refinement +## rcond 9.5e-06 + +A = CholmodSparse!(int32([0,1,2,3,6,9,12,15,18,20,25,30,34,36,39,43,47,52,58,62,67,71,77,84,90,93,95, + 98,103,106,110,115,119,123,130,136,142,146,150,155,161,167,174,182,189,197, + 207,215,224]), # zero-based column pointers + int32([0,1,2,1,2,3,0,2,4,0,1,5,0,4,6,1,3,7,2,8,1,3,7,8,9,0,4,6,8,10,5,6,7,11,6,12, + 7,11,13,8,10,13,14,9,13,14,15,8,10,12,14,16,7,11,12,13,16,17,0,12,16,18,1, + 5,13,15,19,2,4,14,20,3,13,15,19,20,21,2,4,12,16,18,20,22,1,5,17,18,19,23,0, + 5,24,1,25,2,3,26,2,3,25,26,27,4,24,28,0,5,24,29,6,11,24,28,30,7,25,27,31,8, + 9,26,32,8,9,25,27,31,32,33,10,24,28,30,32,34,6,11,29,30,31,35,12,17,30,36, + 13,31,35,37,14,15,32,34,38,14,15,33,37,38,39,16,32,34,36,38,40,12,17,31,35, + 36,37,41,12,16,17,18,23,36,40,42,13,14,15,19,37,39,43,13,14,15,20,21,38,43, + 44,13,14,15,20,21,37,39,43,44,45,12,16,17,22,36,40,42,46,12,16,17,18,23,41, + 42,46,47]), + [2.83226851852e6,1.63544753086e6,1.72436728395e6,-2.0e6,-2.08333333333e6, + 1.00333333333e9,1.0e6, -2.77777777778e6,1.0675e9,2.08333333333e6, + 5.55555555555e6,1.53533333333e9,-3333.33333333,-1.0e6,2.83226851852e6, + -6666.66666667,2.0e6,1.63544753086e6,-1.68e6,1.72436728395e6,-2.0e6,4.0e8,2.0e6, + -2.08333333333e6,1.00333333333e9,1.0e6,2.0e8,-1.0e6,-2.77777777778e6,1.0675e9, + -2.0e6,2.08333333333e6,5.55555555555e6,1.53533333333e9,-2.8e6,2.8360994695e6, + -30864.1975309,-5.55555555555e6,1.76741074446e6,-15432.0987654,2.77777777778e6, + 517922.131816,3.89003806848e6,-3.33333333333e6,4.29857058902e6,-2.6349902747e6, + 1.97572063531e9,-2.77777777778e6,3.33333333333e8,-2.14928529451e6, + 2.77777777778e6,1.52734651547e9,5.55555555555e6,6.66666666667e8,2.35916180402e6, + -5.55555555555e6,-1.09779731332e8,1.56411143711e9,-2.8e6,-3333.33333333,1.0e6, + 2.83226851852e6,-30864.1975309,-5.55555555555e6,-6666.66666667,-2.0e6, + 1.63544753086e6,-15432.0987654,2.77777777778e6,-1.68e6,1.72436728395e6, + -3.33333333333e6,2.0e6,4.0e8,-2.0e6,-2.08333333333e6,1.00333333333e9, + -2.77777777778e6,3.33333333333e8,-1.0e6,2.0e8,1.0e6,2.77777777778e6,1.0675e9, + 5.55555555555e6,6.66666666667e8,-2.0e6,2.08333333333e6,-5.55555555555e6, + 1.53533333333e9,-28935.1851852,-2.08333333333e6,60879.6296296,-1.59791666667e6, + 3.37291666667e6,-28935.1851852,2.08333333333e6,2.41171296296e6,-2.08333333333e6, + 1.0e8,-2.5e6,-416666.666667,1.5e9,-833333.333333,1.25e6,5.01833333333e8, + 2.08333333333e6,1.0e8,416666.666667,5.025e8,-28935.1851852,-2.08333333333e6, + -4166.66666667,-1.25e6,3.98587962963e6,-1.59791666667e6,-8333.33333333,2.5e6, + 3.41149691358e6,-28935.1851852,2.08333333333e6,-2.355e6,2.43100308642e6, + -2.08333333333e6,1.0e8,-2.5e6,5.0e8,2.5e6,-416666.666667,1.50416666667e9, + -833333.333333,1.25e6,2.5e8,-1.25e6,-3.47222222222e6,1.33516666667e9, + 2.08333333333e6,1.0e8,-2.5e6,416666.666667,6.94444444444e6,2.16916666667e9, + -28935.1851852,-2.08333333333e6,-3.925e6,3.98587962963e6,-1.59791666667e6, + -38580.2469136,-6.94444444444e6,3.41149691358e6,-28935.1851852,2.08333333333e6, + -19290.1234568,3.47222222222e6,2.43100308642e6,-2.08333333333e6,1.0e8, + -4.16666666667e6,2.5e6,-416666.666667,1.50416666667e9,-833333.333333, + -3.47222222222e6,4.16666666667e8,-1.25e6,3.47222222222e6,1.33516666667e9, + 2.08333333333e6,1.0e8,6.94444444445e6,8.33333333333e8,416666.666667, + -6.94444444445e6,2.16916666667e9,-3830.95098171,1.14928529451e6,-275828.470683, + -28935.1851852,-2.08333333333e6,-4166.66666667,1.25e6,64710.5806113, + -131963.213599,-517922.131816,-2.29857058902e6,-1.59791666667e6,-8333.33333333, + -2.5e6,3.50487988027e6,-517922.131816,-2.16567078453e6,551656.941366, + -28935.1851852,2.08333333333e6,-2.355e6,517922.131816,4.57738374749e6, + 2.29857058902e6,-551656.941367,4.8619365099e8,-2.08333333333e6,1.0e8,2.5e6, + 5.0e8,-4.79857058902e6,134990.2747,2.47238730198e9,-1.14928529451e6, + 2.29724661236e8,-5.57173510779e7,-833333.333333,-1.25e6,2.5e8,2.39928529451e6, + 9.61679848804e8,275828.470683,-5.57173510779e7,1.09411960038e7,2.08333333333e6, + 1.0e8,-2.5e6,140838.195984,-1.09779731332e8,5.31278103775e8], 48, 48, 1) +@test_approx_eq norm(A,Inf) 3.570948074697437e9 +@test_approx_eq norm(A) 3.570948074697437e9 +@test isvalid(A) + +B = A * ones(size(A,2)) +chma = cholfact(A) # LDL' form +@test isvalid(chma) +x = chma\B +@test_approx_eq x.mat ones(size(x)) + +chma = cholfact(A,true) # LL' form +@test isvalid(chma) +x = chma\B +@test_approx_eq x.mat ones(size(x)) + +#lp_afiro example +afiro = CholmodSparse!(int32([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,23,25,27,29,33,37, + 41,45,47,49,51,53,55,57,59,63,65,67,69,71,75,79,83,87,89,91,93,95,97, + 99,101,102]), + int32([2,3,6,7,8,9,12,13,16,17,18,19,20,21,22,23,24,25,26,0,1,2,23,0,3,0,21, + 1,25,4,5,6,24,4,5,7,24,4,5,8,24,4,5,9,24,6,20,7,20,8,20,9,20,3,4,4,22, + 5,26,10,11,12,21,10,13,10,23,10,20,11,25,14,15,16,22,14,15,17,22,14, + 15,18,22,14,15,19,22,16,20,17,20,18,20,19,20,13,15,15,24,14,26,15]), + [1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0, + -1.0,-1.06,1.0,0.301,1.0,-1.0,1.0,-1.0,1.0,1.0,-1.0,-1.06,1.0,0.301,-1.0, + -1.06,1.0,0.313,-1.0,-0.96,1.0,0.313,-1.0,-0.86,1.0,0.326,-1.0,2.364,-1.0, + 2.386,-1.0,2.408,-1.0,2.429,1.4,1.0,1.0,-1.0,1.0,1.0,-1.0,-0.43,1.0,0.109, + 1.0,-1.0,1.0,-1.0,1.0,-1.0,1.0,1.0,-0.43,1.0,1.0,0.109,-0.43,1.0,1.0,0.108, + -0.39,1.0,1.0,0.108,-0.37,1.0,1.0,0.107,-1.0,2.191,-1.0,2.219,-1.0,2.249, + -1.0,2.279,1.4,-1.0,1.0,-1.0,1.0,1.0,1.0], 27, 51, 0) +chmaf = cholfact(afiro) +y = afiro'*ones(size(afiro,1)) +sol = solve(chmaf, afiro*y) # least squares solution +@test isvalid(sol) +pred = afiro'*sol +@test norm(afiro * (y.mat - pred.mat)) < 1e-8 diff --git a/test/test_options.jl b/test/test_options.jl deleted file mode 100644 index ef2f932289233..0000000000000 --- a/test/test_options.jl +++ /dev/null @@ -1,70 +0,0 @@ -test_context("Options for functions") - -require("options") -using OptionsMod - -test_group("basic functionality") -oo = Options(:a, true, :b, 7) -@test length(oo.key2index) == 2 -@test oo[:a] == true -@test oo[:b] > 6 -@test oo[:c] == nothing -@test sprint(show, oo) == "a = true, b = 7 (CheckError)" - -test_group("other constructors") -oo2 = Options(CheckWarn, :(a=true), :(b=7)) -@test oo2[:a] == true -oo3 = @options a=true b=7 -@test oo3[:b] == 7 - - -test_group("changing options") -oo2[:b] = 6 -oo2[:c] = "cat" -@test oo2[:b] < 7 -@test oo2[:c] == "cat" - -test_group("simple example") -function f1(a, b, o::Options) - @defaults o op="plus" - if op == "plus" - return a + b - else - return a - b - end - @check_used o -end -f1(a, b) = f1(a, b, Options()) -@test f1(3, 2) == 5 -@test f1(3, 2, Options(:op, "plus")) == 5 -@test f1(3, 2, Options(:op, "other")) == 1 - -test_group("complex example") -function complexfun(x, opts::Options) - @defaults opts parent=3 both=7 - sub1, both1 = subfun1(x, opts) - sub2, both2 = subfun2(x, opts) - @check_used opts - return parent, both, sub1, both1, sub2, both2 -end -complexfun(x) = complexfun(x, Options()) - -function subfun1(x, opts::Options) - @defaults opts sub1="sub1 default" both=0 - @check_used opts - return sub1, both -end - -function subfun2(x, opts::Options) - @defaults opts sub2="sub2 default" both=22 - @check_used opts - return sub2, both -end - -@test complexfun(5) == (3,7,"sub1 default", 0, "sub2 default", 22) -opts = @options sub2=15 -@test complexfun(5, opts) == (3,7,"sub1 default", 0, 15, 22) -@set_options opts both=8 -@test complexfun(5, opts) == (3,8,"sub1 default", 8, 15, 8) -@set_options opts sub1a=5 -@testfails complexfun(5, opts) diff --git a/test/test_sourcepath.jl b/test/test_sourcepath.jl new file mode 100644 index 0000000000000..d0436b36ca064 --- /dev/null +++ b/test/test_sourcepath.jl @@ -0,0 +1,4 @@ +# source path in tasks +path = Base.source_path() +@test endswith(path, joinpath("test","test_sourcepath.jl")) +@test yieldto(@task Base.source_path()) == path diff --git a/test/test_test.jl b/test/test_test.jl index f3ccc8835eff6..18afea1be2f89 100644 --- a/test/test_test.jl +++ b/test/test_test.jl @@ -28,10 +28,11 @@ test_group("random tests") test_group("exception tests") @testfails complex(1,2) > 0 # fail @test throws_exception(complex(1,2) > 0, MethodError) -@testfails throws_exception(complex(1,2) > 0, SystemError) +@testfails throws_exception(complex(1,2) > 0, SystemError) +@testfails throws_exception(2 > 1, DomainError) # would correctly fail test_group("printing tests") -@test sprint(show, :(1+2)) == ":( +(1, 2) )" +@test sprint(show, :(1+2)) == ":(+(1,2))" @test prints(print_joined, ([1,2,3], " : "), "1 : 2 : 3") # prints is a helper @testfails prints(print_joined, ([1,2,3], " ! "), "1 : 2 : 3") diff --git a/test/testdefs.jl b/test/testdefs.jl new file mode 100644 index 0000000000000..2210fdaeae869 --- /dev/null +++ b/test/testdefs.jl @@ -0,0 +1,28 @@ +using Test + +function runtests(name) + println(" \033[1m*\033[0m \033[31m$(name)\033[0m") + Core.include("$name.jl") +end + +macro timeit(ex,name) + quote + t = Inf + for i = 1:5 + t = min(t, @elapsed $(esc(ex))) + end + println(rpad(string($name,":"), 20), t) + end +end + +function propagate_errors(a,b) + if isa(a,Exception) + rethrow(a) + end + if isa(b,Exception) + rethrow(b) + end + nothing +end + +shift!(LOAD_PATH) # looking in . messes things up badly diff --git a/test/unicode.jl b/test/unicode.jl index 9cf740b86376b..185af0f377f0a 100644 --- a/test/unicode.jl +++ b/test/unicode.jl @@ -1,5 +1,31 @@ -str1 = CharString(reinterpret(Char, read(open("unicode/UTF-32LE.unicode"), Uint32, 1112065)[2:])) -str2 = UTF8String(read(open("unicode/UTF-8.unicode"), Uint8, 4382595)[4:]) +# Create unicode test data directory +unicodedir = mktempdir() + +# Use perl to generate the primary data +primary_encoding = "UTF-32BE" +primary_path = replace(joinpath(unicodedir, primary_encoding*".unicode"),"\\","\\\\\\\\") +run(`perl -e " +$$fname = \"$primary_path\"; +open(UNICODEF, \">\", \"$$fname\") or die \"can\'t open $$fname: $$!\"; +binmode(UNICODEF); +print UNICODEF pack \"N*\", 0xfeff, 0..0xd7ff, 0xe000..0x10ffff; +close(UNICODEF);"` ) + +# Use iconv to generate the other data +for encoding in ["UTF-32LE", "UTF-16BE", "UTF-16LE", "UTF-8"] + output_path = joinpath(unicodedir, encoding*".unicode") + f = Base.FS.open(output_path,Base.JL_O_WRONLY|Base.JL_O_CREAT,Base.S_IRUSR | Base.S_IWUSR | Base.S_IRGRP | Base.S_IROTH) + run(`iconv -f $primary_encoding -t $encoding $primary_path` > f) + Base.FS.close(f) +end + +f=open(joinpath(unicodedir,"UTF-32LE.unicode")) +str1 = CharString(reinterpret(Char, read(f, Uint32, 1112065)[2:])) +close(f) + +f=open(joinpath(unicodedir,"UTF-8.unicode")) +str2 = UTF8String(read(f, Uint8, 4382595)[4:]) +close(f) @test str1 == str2 str1 = "∀ ε > 0, ∃ δ > 0: |x-y| < δ ⇒ |f(x)-f(y)| < ε" @@ -10,3 +36,9 @@ str2 = CharString( 41, 45, 102, 40, 121, 41, 124, 32, 60, 32, 949 ) @test str1 == str2 + +# Cleanup unicode data +for encoding in ["UTF-32BE", "UTF-32LE", "UTF-16BE", "UTF-16LE", "UTF-8"] + rm(joinpath(unicodedir,encoding*".unicode")) +end +rmdir(unicodedir) diff --git a/test/unicode/.gitignore b/test/unicode/.gitignore deleted file mode 100644 index 25e690d5d89cb..0000000000000 --- a/test/unicode/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.unicode diff --git a/test/unicode/Makefile b/test/unicode/Makefile deleted file mode 100644 index 61917a9757148..0000000000000 --- a/test/unicode/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -JULIAHOME = ../.. -include ../../Make.inc - -PRIMARY = UTF-32BE -ENCODINGS = UTF-32BE UTF-32LE UTF-16BE UTF-16LE UTF-8 - -EXT = .unicode -DERIVED = $(filter-out $(PRIMARY),$(ENCODINGS)) -DERIVED_FILES = $(addsuffix $(EXT),$(DERIVED)) -CHECKS = $(addprefix check-,$(DERIVED_FILES)) - -all: $(DERIVED_FILES) - -UTF-32BE$(EXT): - $(QUIET_PERL) perl -e 'print pack "N*", 0xfeff, 0..0xd7ff, 0xe000..0x10ffff' >$@ - -$(DERIVED_FILES): %$(EXT): $(PRIMARY)$(EXT) - $(QUIET_PERL) iconv -f $(PRIMARY) -t $* <$< >$@ - -check: $(CHECKS) - -$(CHECKS): check-%$(EXT): %$(EXT) - iconv -f $* -t $(PRIMARY) <$< | cmp $(PRIMARY)$(EXT) - -clean: - @rm -rf *$(EXT) - -.PHONY: all check $(CHECKS) clean diff --git a/test/zlib.jl b/test/zlib.jl index 09f7bb3d3ae15..8a86a032fc057 100644 --- a/test/zlib.jl +++ b/test/zlib.jl @@ -1,4 +1,4 @@ -require("extras/zlib") +require("zlib") import Zlib using Zlib @@ -17,7 +17,7 @@ for i = 1:length(b) end # Random array -r = b[randi((1,256), BUFSIZE)] +r = b[rand(1:256, BUFSIZE)] ######################## # type size tests @@ -27,7 +27,7 @@ r = b[randi((1,256), BUFSIZE)] # zlibCompileFlags function. # Get compile-time option flags -zlib_compile_flags = ccall(dlsym(Zlib._zlib, :zlibCompileFlags), Uint, ()) +zlib_compile_flags = ccall((:zlibCompileFlags, Zlib._zlib), Uint, ()) # Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: # @@ -48,7 +48,10 @@ z_off_t_sz = 2 << ((zlib_compile_flags >> 6) & uint(3)) @test(z_uInt_sz == sizeof(Uint32)) @test(z_uLong_sz == sizeof(Uint)) @test(z_voidpf_sz == sizeof(Ptr)) -@test(z_off_t_sz == sizeof(Zlib.ZFileOffset) || (dlsym(Zlib._zlib, :crc32_combine64) != C_NULL && sizeof(Zlib.ZFileOffset) == 8)) + +let _zlib_h = dlopen("libz") + @test(z_off_t_sz == sizeof(Zlib.ZFileOffset) || (dlsym_e(_zlib_h, :gzopen64) != C_NULL && sizeof(Zlib.ZFileOffset) == 8)) +end ######################## # compress/uncompress tests diff --git a/ui/Makefile b/ui/Makefile index 0ad639f443694..6391d8fe52233 100644 --- a/ui/Makefile +++ b/ui/Makefile @@ -5,11 +5,11 @@ override CFLAGS += $(JCFLAGS) override CXXFLAGS += $(JCXXFLAGS) FLAGS = -Wall -Wno-strict-aliasing -fno-omit-frame-pointer \ - -I$(JULIAHOME)/src -I$(JULIAHOME)/src/support -I$(USR)/include $(CFLAGS) + -I$(JULIAHOME)/src -I$(JULIAHOME)/src/support -I$(BUILD)/include $(CFLAGS) DEBUGFLAGS += $(FLAGS) SHIPFLAGS += $(FLAGS) -JLDFLAGS += $(shell $(LLVM_CONFIG) --ldflags) $(OSLIBS) -lpthread $(LDFLAGS) $(RPATH) +JLDFLAGS += $(LDFLAGS) $(NO_WHOLE_ARCHIVE) $(shell $(LLVM_CONFIG) --ldflags) $(OSLIBS) $(RPATH) julia-release julia-debug: %: %-basic %-readline @@ -17,25 +17,34 @@ release debug: $(MAKE) julia-$@ %.o: %.c repl.h - $(QUIET_CC) $(CC) $(CFLAGS) $(SHIPFLAGS) -c $< -o $@ + $(QUIET_CC) $(CC) $(CPPFLAGS) $(CFLAGS) $(SHIPFLAGS) -c $< -o $@ %.do: %.c repl.h - $(QUIET_CC) $(CC) $(CFLAGS) $(DEBUGFLAGS) -c $< -o $@ + $(QUIET_CC) $(CC) $(CPPFLAGS) $(CFLAGS) $(DEBUGFLAGS) -c $< -o $@ -julia-release-basic: $(USRBIN)/julia-release-basic -julia-debug-basic: $(USRBIN)/julia-debug-basic -julia-release-readline: $(USRBIN)/julia-release-readline -julia-debug-readline: $(USRBIN)/julia-debug-readline +ifeq ($(OS),WINNT) +$(BUILD)/bin/julia.bat: ${JULIAHOME}/contrib/windows/*.bat + cp ${JULIAHOME}/contrib/windows/*.bat ${BUILD}/bin +julia-release julia-debug: $(BUILD)/bin/julia.bat +endif -$(USRBIN)/julia-release-basic: repl.o repl-basic.o - $(QUIET_LINK) $(CXX) $(LINK_FLAGS) $(SHIPFLAGS) $^ -o $@ -L$(USR)/$(JL_PRIVATE_LIBDIR) -L$(USR)/$(JL_LIBDIR) $(JLDFLAGS) -ljulia-release -$(USRBIN)/julia-debug-basic: repl.do repl-basic.do - $(QUIET_LINK) $(CXX) $(LINK_FLAGS) $(DEBUGFLAGS) $^ -o $@ -L$(USR)/$(JL_PRIVATE_LIBDIR) -L$(USR)/$(JL_LIBDIR) $(JLDFLAGS) -ljulia-debug +julia-release-basic: $(BUILD)/bin/julia-release-basic$(EXE) +julia-debug-basic: $(BUILD)/bin/julia-debug-basic$(EXE) +julia-release-readline: $(BUILD)/bin/julia-release-readline$(EXE) +julia-debug-readline: $(BUILD)/bin/julia-debug-readline$(EXE) -$(USRBIN)/julia-release-readline: repl.o repl-readline.o - $(QUIET_LINK) $(CXX) $(LINK_FLAGS) $(SHIPFLAGS) $^ -o $@ $(READLINE) -L$(USR)/$(JL_PRIVATE_LIBDIR) -L$(USR)/$(JL_LIBDIR) $(JLDFLAGS) -ljulia-release -$(USRBIN)/julia-debug-readline: repl.do repl-readline.do - $(QUIET_LINK) $(CXX) $(LINK_FLAGS) $(DEBUGFLAGS) $^ -o $@ $(READLINE) -L$(USR)/$(JL_PRIVATE_LIBDIR) -L$(USR)/$(JL_LIBDIR) $(JLDFLAGS) -ljulia-debug +$(BUILD)/bin/julia-release-basic$(EXE): repl.o repl-basic.o + $(QUIET_LINK) $(CXX) $(LINK_FLAGS) $(SHIPFLAGS) $^ -o $@ -L$(BUILD)/$(JL_PRIVATE_LIBDIR) -L$(BUILD)/$(JL_LIBDIR) $(JLDFLAGS) -ljulia-release +$(BUILD)/bin/julia-debug-basic$(EXE): repl.do repl-basic.do + $(QUIET_LINK) $(CXX) $(LINK_FLAGS) $(DEBUGFLAGS) $^ -o $@ -L$(BUILD)/$(JL_PRIVATE_LIBDIR) -L$(BUILD)/$(JL_LIBDIR) $(JLDFLAGS) -ljulia-debug + +$(BUILD)/bin/julia-release-readline$(EXE): repl.o repl-readline.o + $(QUIET_LINK) $(CXX) $(LINK_FLAGS) $(SHIPFLAGS) $^ -o $@ $(READLINE) -L$(BUILD)/$(JL_PRIVATE_LIBDIR) -L$(BUILD)/$(JL_LIBDIR) $(JLDFLAGS) -ljulia-release +$(BUILD)/bin/julia-debug-readline$(EXE): repl.do repl-readline.do + $(QUIET_LINK) $(CXX) $(LINK_FLAGS) $(DEBUGFLAGS) $^ -o $@ $(READLINE) -L$(BUILD)/$(JL_PRIVATE_LIBDIR) -L$(BUILD)/$(JL_LIBDIR) $(JLDFLAGS) -ljulia-debug clean: | $(CLEAN_TARGETS) rm -f *.o *.do - rm -f $(USRBIN)/julia-*-basic $(USRBIN)/julia-*-readline $(USRBIN)/julia + rm -f $(BUILD)/bin/julia-*-basic $(BUILD)/bin/julia-*-readline $(BUILD)/bin/julia + +.PHONY: clean release debug julia-release julia-debug + diff --git a/ui/repl-basic.c b/ui/repl-basic.c index bc45f16efcc88..d64bfd2f7e2db 100644 --- a/ui/repl-basic.c +++ b/ui/repl-basic.c @@ -1,10 +1,16 @@ #include "repl.h" +#include char jl_prompt_color[] = "\033[1m\033[32mjulia> \033[0m\033[1m"; char *prompt_string = "julia> "; +char *stdin_buf = NULL; +unsigned long stdin_buf_len = 0; +unsigned long stdin_buf_maxlen = 128; + void init_repl_environment(int argc, char *argv[]) { + stdin_buf = malloc(stdin_buf_maxlen); } DLLEXPORT void jl_enable_color(void) @@ -12,43 +18,122 @@ DLLEXPORT void jl_enable_color(void) prompt_string = jl_prompt_color; } -void jl_input_line_callback(char *input) +void jl_prep_terminal(int meta_flag) { - jl_value_t *ast; - int end=0, doprint=1; +} - if (!input || ios_eof(ios_stdin)) { - end = 1; - ast = jl_nothing; +/* Restore the terminal's normal settings and modes. */ +void jl_deprep_terminal() +{ +} + +void jl_input_line_callback(char *input) +{ + if (input) { + jl_value_t *ast = jl_parse_input_line(input); + int line_done = !ast || !jl_is_expr(ast) || + (((jl_expr_t*)ast)->head != jl_continue_sym); + if (line_done) { + jl_deprep_terminal(); + int doprint = !ends_with_semicolon(input); + stdin_buf[0] = 0; //also sets input[0] == 0 + stdin_buf_len = 0; + handle_input(ast, 0, doprint); + } } - else { - ast = jl_parse_input_line(input); - // TODO - //if (jl_is_expr(ast) && ((jl_expr_t*)ast)->head == jl_continue_sym) - doprint = !ends_with_semicolon(input); +} + +void repl_callback_enable() +{ + jl_write(jl_uv_stdout, prompt_string, strlen(prompt_string)); + jl_prep_terminal(1); +} + +static void stdin_buf_pushc(char c) +{ + if (stdin_buf_len >= stdin_buf_maxlen) { + stdin_buf_maxlen *= 2; + stdin_buf = realloc(stdin_buf, stdin_buf_maxlen); + if (!stdin_buf) { + // we can safely ignore this error and continue, if that is preferred + perror("realloc"); + exit(EXIT_FAILURE); + } } - handle_input(ast, end, doprint); + stdin_buf[stdin_buf_len] = c; + stdin_buf_len++; } -char *read_expr(char *prompt) +static void basic_stdin_callback(void) { - char *input; - ios_printf(ios_stdout, prompt); - ios_flush(ios_stdout); - input = ios_readline(ios_stdin); - ios_purge(ios_stdin); - return input; + stdin_buf_pushc('\0'); + stdin_buf_len--; + jl_input_line_callback(stdin_buf); } -void repl_callback_enable() +void jl_readBuffer(char* base, ssize_t nread) { - ios_printf(ios_stdout, prompt_string); - ios_flush(ios_stdout); + char *start = base; + int esc = 0; + int newline = 0; + while (*start != 0 && nread > 0) { + if (*start < 32 || *start == 127) { + switch (*start) { + case '\n': + case '\r': + //jl_putc('\n', jl_uv_stdout); + stdin_buf_pushc('\n'); + newline = 1; + break; + case '\x03': + JL_WRITE(jl_uv_stdout, "^C\n", 3); + jl_clear_input(); + break; + case '\x04': + raise(SIGTERM); + break; + case '\x1A': +#ifndef __WIN32__ + raise(SIGTSTP); +#endif + break; + case '\e': + esc = 1; + break; + case 127: + case '\b': + if (stdin_buf_len > 0 && stdin_buf[stdin_buf_len-1] != '\n') { + stdin_buf_len--; + JL_WRITE(jl_uv_stdout,"\b \b",3); + } + } + } + else if (esc == 1) { + if (*start == '[') { + esc = 2; + } + else { + esc = 0; + } + } + else if (esc == 2) { + // for now, we just block all 3 character ctrl signals that I know about + // this misses delete ^[[3~ and possibly others? + esc = 0; + } + else { + stdin_buf_pushc(*start); + } + start++; + nread--; + } + if (newline) basic_stdin_callback(); } -void jl_stdin_callback(void) +void jl_clear_input(void) { - char *input = ios_readline(ios_stdin); - ios_purge(ios_stdin); - jl_input_line_callback(input); + stdin_buf_len = 0; + stdin_buf[0] = 0; + JL_WRITE(jl_uv_stdout,"\n",1); + repl_callback_enable(); } diff --git a/ui/repl-readline.c b/ui/repl-readline.c index 58d47e652f37a..ef8ea7d8f4c6e 100644 --- a/ui/repl-readline.c +++ b/ui/repl-readline.c @@ -18,9 +18,14 @@ */ #include "repl.h" +#ifdef __WIN32__ +# define WIN32_LEAN_AND_MEAN +# include +#endif extern int asprintf(char **strp, const char *fmt, ...); +#define USE_READLINE_STATIC #include #include @@ -40,13 +45,32 @@ DLLEXPORT void jl_enable_color(void) // yes, readline uses inconsistent indexing internally. #define history_rem(n) remove_history(n-history_base) -static void init_history(void) { +static void init_history(void) +{ using_history(); - char *home = getenv("HOME"); - if (!home) return; if (disable_history) return; - asprintf(&history_file, "%s/.julia_history", home); struct stat stat_info; + if (!stat(".julia_history", &stat_info)) { + // history file in current dir + history_file = ".julia_history"; + } + else { + char *histenv = getenv("JULIA_HISTORY"); + if (histenv) { + history_file = histenv; + } + else { +#ifndef __WIN32__ + char *home = getenv("HOME"); + if (!home) return; + asprintf(&history_file, "%s/.julia_history", home); +#else + char *home = getenv("AppData"); + if (!home) return; + asprintf(&history_file, "%s/julia/history", home); +#endif + } + } if (!stat(history_file, &stat_info)) { read_history(history_file); for (;;) { @@ -70,14 +94,20 @@ static void init_history(void) { char *p = strchr(first->line, '\0'); for (k = i+1; k < j; k++) { *p = '\n'; + #ifndef __WIN32__ p = stpcpy(p+1, history_get(i+1)->line); + #else + p = strcpy(p+1, history_get(i+1)->line); + #endif free_history_entry(history_rem(i+1)); } } - } else if (errno == ENOENT) { + } + else if (errno == ENOENT) { write_history(history_file); - } else { - ios_printf(ios_stderr, "history file error: %s\n", strerror(errno)); + } + else { + jl_printf(jl_uv_stderr, "history file error: %s\n", strerror(errno)); exit(1); } } @@ -85,7 +115,8 @@ static void init_history(void) { static int last_hist_is_temp = 0; static int last_hist_offset = -1; -static void add_history_temporary(char *input) { +static void add_history_temporary(char *input) +{ if (!input || !*input) return; if (last_hist_is_temp) { history_rem(history_length); @@ -96,7 +127,8 @@ static void add_history_temporary(char *input) { last_hist_is_temp = 1; } -static void add_history_permanent(char *input) { +static void add_history_permanent(char *input) +{ if (!input || !*input) return; if (last_hist_is_temp) { history_rem(history_length); @@ -111,14 +143,16 @@ static void add_history_permanent(char *input) { append_history(1, history_file); } -static int line_start(int point) { +static int line_start(int point) +{ if (!point) return 0; int i = point-1; for (; i; i--) if (rl_line_buffer[i] == '\n') return i+1; return rl_line_buffer[i] == '\n' ? 1 : 0; } -static int line_end(int point) { +static int line_end(int point) +{ char *nl = strchr(rl_line_buffer + point, '\n'); if (!nl) return rl_end; return nl - rl_line_buffer; @@ -127,7 +161,8 @@ static int line_end(int point) { static int strip_initial_spaces = 0; static int spaces_suppressed = 0; -static void reset_indent(void) { +static void reset_indent(void) +{ strip_initial_spaces = 0; spaces_suppressed = 0; } @@ -138,7 +173,8 @@ static int jl_word_char(uint32_t wc) return strchr(rl_completer_word_break_characters, wc) == NULL; } -static int newline_callback(int count, int key) { +static int newline_callback(int count, int key) +{ if (!rl_point) return 0; spaces_suppressed = 0; rl_insert_text("\n"); @@ -148,7 +184,8 @@ static int newline_callback(int count, int key) { return 0; } -static int return_callback(int count, int key) { +static int return_callback(int count, int key) +{ static int consecutive_returns = 0; if (rl_point > prompt_length && rl_point == rl_end && rl_line_buffer[rl_point-prompt_length-1] == '\n') @@ -162,7 +199,8 @@ static int return_callback(int count, int key) { consecutive_returns > 1; if (!rl_done) { newline_callback(count, key); - } else { + } + else { reset_indent(); rl_point = rl_end; rl_redisplay(); @@ -170,7 +208,8 @@ static int return_callback(int count, int key) { return 0; } -static int suppress_space(void) { +static int suppress_space(void) +{ int i; for (i = line_start(rl_point); i < rl_point; i++) if (rl_line_buffer[i] != ' ') return 0; @@ -178,14 +217,16 @@ static int suppress_space(void) { return 0; } -static int space_callback(int count, int key) { +static int space_callback(int count, int key) +{ if (!rl_point) strip_initial_spaces++; else if (suppress_space()) spaces_suppressed++; else rl_insert_text(" "); return 0; } -static int tab_callback(int count, int key) { +static int tab_callback(int count, int key) +{ if (!rl_point) { strip_initial_spaces += tab_width; return 0; @@ -206,14 +247,16 @@ static int tab_callback(int count, int key) { // indent to next tab stop if (suppress_space()) { spaces_suppressed += tab_width; - } else { + } + else { i = line_start(rl_point) + prompt_length; do { rl_insert_text(" "); } while ((rl_point - i) % tab_width); } return 0; } -static int line_start_callback(int count, int key) { +static int line_start_callback(int count, int key) +{ reset_indent(); int start = line_start(rl_point); int flush_left = rl_point == 0 || rl_point == start + prompt_length; @@ -221,7 +264,8 @@ static int line_start_callback(int count, int key) { return 0; } -static int line_end_callback(int count, int key) { +static int line_end_callback(int count, int key) +{ reset_indent(); int end = line_end(rl_point); int flush_right = rl_point == end; @@ -229,7 +273,8 @@ static int line_end_callback(int count, int key) { return 0; } -static int line_kill_callback(int count, int key) { +static int line_kill_callback(int count, int key) +{ reset_indent(); int end = line_end(rl_point); int flush_right = rl_point == end; @@ -239,7 +284,8 @@ static int line_kill_callback(int count, int key) { return 0; } -static int backspace_callback(int count, int key) { +static int backspace_callback(int count, int key) +{ reset_indent(); if (!rl_point) return 0; @@ -263,7 +309,8 @@ static int backspace_callback(int count, int key) { return 0; } -static int delete_callback(int count, int key) { +static int delete_callback(int count, int key) +{ reset_indent(); int j = rl_point; do { @@ -274,7 +321,8 @@ static int delete_callback(int count, int key) { return 0; } -static int left_callback(int count, int key) { +static int left_callback(int count, int key) +{ reset_indent(); if (rl_point > 0) { int i = line_start(rl_point); @@ -285,7 +333,8 @@ static int left_callback(int count, int key) { return 0; } -static int right_callback(int count, int key) { +static int right_callback(int count, int key) +{ reset_indent(); do { rl_point += (rl_line_buffer[rl_point] == '\n') ? prompt_length+1 : 1; @@ -294,7 +343,8 @@ static int right_callback(int count, int key) { return 0; } -static int up_callback(int count, int key) { +static int up_callback(int count, int key) +{ reset_indent(); int i = line_start(rl_point); if (i > 0) { @@ -302,7 +352,8 @@ static int up_callback(int count, int key) { if (j == 0) rl_point -= prompt_length; rl_point += j - i; if (rl_point >= i) rl_point = i - 1; - } else { + } + else { last_hist_offset = -1; rl_get_previous_history(count, key); rl_point = line_end(0); @@ -310,7 +361,8 @@ static int up_callback(int count, int key) { return 0; } -static int down_callback(int count, int key) { +static int down_callback(int count, int key) +{ reset_indent(); int j = line_end(rl_point); if (j < rl_end) { @@ -320,7 +372,8 @@ static int down_callback(int count, int key) { int k = line_end(j+1); if (rl_point > k) rl_point = k; return 0; - } else { + } + else { if (last_hist_offset >= 0) { history_set_pos(last_hist_offset); last_hist_offset = -1; @@ -337,7 +390,8 @@ void jl_input_line_callback(char *input) if (!input || ios_eof(ios_stdin)) { end = 1; rl_ast = NULL; - } else if (!rl_ast) { + } + else if (!rl_ast) { // In vi mode, it's possible for this function to be called w/o a // previous call to return_callback. rl_ast = jl_parse_input_line(rl_line_buffer); @@ -346,7 +400,7 @@ void jl_input_line_callback(char *input) if (rl_ast != NULL) { doprint = !ends_with_semicolon(input); add_history_permanent(input); - ios_putc('\n', ios_stdout); + jl_putc('\n', jl_uv_stdout); free(input); } @@ -370,13 +424,30 @@ static int common_prefix(const char *s1, const char *s2) return i; } +static char *lang_keywords[] = + { "if", "else", "elseif", "while", "for", "begin", "end", "quote", + "try", "catch", "return", "local", "abstract", "function", "macro", "ccall", + "finally", "typealias", "break", "continue", "type", "global", + "module", "using", "import", "export", "const", "let", "bitstype", "do", + "baremodule", "importall", "immutable", NULL }; + +static int is_keyword(char *s) +{ + for(size_t i=0; lang_keywords[i]; i++) { + if (!strcmp(lang_keywords[i],s)) + return 1; + } + return 0; +} + static void symtab_search(jl_sym_t *tree, int *pcount, ios_t *result, jl_module_t *module, const char *str, const char *prefix, int plen) { do { if (common_prefix(prefix, tree->name) == plen && - (module ? jl_defines_or_exports_p(module, tree) : jl_boundp(jl_current_module, tree))) { + (module ? jl_defines_or_exports_p(module, tree) : (jl_boundp(jl_current_module, tree) || + is_keyword(tree->name)))) { ios_puts(str, result); ios_puts(tree->name + plen, result); ios_putc('\n', result); @@ -388,8 +459,7 @@ static void symtab_search(jl_sym_t *tree, int *pcount, ios_t *result, } while (tree != NULL); } -static jl_module_t * -find_submodule_named(jl_module_t *module, const char *name) +static jl_module_t *find_submodule_named(jl_module_t *module, const char *name) { jl_sym_t *s = jl_symbol_lookup(name); if (!s) return NULL; @@ -400,6 +470,29 @@ find_submodule_named(jl_module_t *module, const char *name) return (jl_is_module(b->value)) ? (jl_module_t *)b->value : NULL; } +static char *strtok_saveptr; + +#if defined(_WIN32) +char *strtok_r(char *str, const char *delim, char **save) +{ + char *res, *last; + + if (!save) + return strtok(str, delim); + if (!str && !(str = *save)) + return NULL; + last = str + strlen(str); + if ((*save = res = strtok(str, delim))) { + *save += strlen(res); + if (*save < last) + (*save)++; + else + *save = NULL; + } + return res; +} +#endif + static int symtab_get_matches(jl_sym_t *tree, const char *str, char **answer) { int x, plen, count=0; @@ -408,7 +501,7 @@ static int symtab_get_matches(jl_sym_t *tree, const char *str, char **answer) // given str "X.Y.a", set module := X.Y and name := "a" jl_module_t *module = NULL; char *name = NULL, *strcopy = strdup(str); - for (char *s=strcopy, *r;; s=NULL) { + for (char *s=strcopy, *r=NULL;; s=NULL) { char *t = strtok_r(s, ".", &r); if (!t) { if (str[strlen(str)-1] == '.') { @@ -430,6 +523,7 @@ static int symtab_get_matches(jl_sym_t *tree, const char *str, char **answer) name = t; } + if (!name) goto symtab_get_matches_exit; plen = strlen(name); while (tree != NULL) { @@ -471,8 +565,6 @@ int tab_complete(const char *line, char **answer, int *plen) return symtab_get_matches(jl_get_root_symbol(), &line[len], answer); } -static char *strtok_saveptr; - static char *do_completions(const char *ch, int c) { static char *completions = NULL; @@ -503,7 +595,18 @@ static char **julia_completion(const char *text, int start, int end) { return rl_completion_matches(text, do_completions); } - +#ifdef __WIN32__ +int repl_sigint_handler_installed = 0; +BOOL WINAPI repl_sigint_handler(DWORD wsig) //This needs winapi types to guarantee __stdcall +{ + if (callback_en) { + JL_WRITE(jl_uv_stdout, "^C", 2); + jl_clear_input(); + return 1; + } + return 0; // continue to next handler +} +#else void sigtstp_handler(int arg) { rl_cleanup_after_signal(); @@ -525,10 +628,38 @@ void sigcont_handler(int arg) rl_forced_update_display(); } +struct sigaction jl_sigint_act = {{0}}; + +void repl_sigint_handler(int sig, siginfo_t *info, void *context) +{ + if (callback_en) { + JL_WRITE(jl_uv_stdout, "^C", 2); + jl_clear_input(); + } + else { + if (jl_sigint_act.sa_flags & SA_SIGINFO) { + jl_sigint_act.sa_sigaction(sig, info, context); + } + else { + void (*f)(int) = jl_sigint_act.sa_handler; + if (f == SIG_DFL) + raise(sig); + else if (f != SIG_IGN) + f(sig); + } + } +} +#endif + static void init_rl(void) { rl_readline_name = "julia"; rl_attempted_completion_function = julia_completion; + for(size_t i=0; lang_keywords[i]; i++) { + // make sure keywords are in symbol table + (void)jl_symbol(lang_keywords[i]); + } + rl_completer_word_break_characters = " \t\n\"\\'`@$><=;|&{}()[],+-*/?%^~!"; Keymap keymaps[] = {emacs_standard_keymap, vi_insertion_keymap}; int i; for (i = 0; i < sizeof(keymaps)/sizeof(keymaps[0]); i++) { @@ -542,31 +673,86 @@ static void init_rl(void) rl_bind_key_in_map('\005', line_end_callback, keymaps[i]); rl_bind_key_in_map('\002', left_callback, keymaps[i]); rl_bind_key_in_map('\006', right_callback, keymaps[i]); + rl_bind_keyseq_in_map("\e[1~", line_start_callback, keymaps[i]); + rl_bind_keyseq_in_map("\e[4~", line_end_callback, keymaps[i]); + rl_bind_keyseq_in_map("\e[3~", delete_callback, keymaps[i]); + rl_bind_keyseq_in_map("\e[5~", rl_named_function("beginning-of-history"), keymaps[i]); + rl_bind_keyseq_in_map("\e[6~", rl_named_function("end-of-history"), keymaps[i]); rl_bind_keyseq_in_map("\e[A", up_callback, keymaps[i]); rl_bind_keyseq_in_map("\e[B", down_callback, keymaps[i]); rl_bind_keyseq_in_map("\e[D", left_callback, keymaps[i]); rl_bind_keyseq_in_map("\e[C", right_callback, keymaps[i]); rl_bind_keyseq_in_map("\\C-d", delete_callback, keymaps[i]); + rl_bind_keyseq_in_map("\e\r", newline_callback, keymaps[i]); } - +#ifndef __WIN32__ signal(SIGTSTP, sigtstp_handler); signal(SIGCONT, sigcont_handler); +#endif +} + +void jl_prep_terminal(int meta_flag) +{ + FILE *rl_in = rl_instream; + rl_instream = stdin; + rl_prep_terminal(1); + rl_instream = rl_in; +#ifdef __WIN32__ + if (jl_uv_stdin->type == UV_TTY) uv_tty_set_mode((uv_tty_t*)jl_uv_stdin,1); //raw (and libuv-processed) + if (!repl_sigint_handler_installed) { + if (SetConsoleCtrlHandler((PHANDLER_ROUTINE)repl_sigint_handler,1)) + repl_sigint_handler_installed = 1; + } +#else + if (jl_sigint_act.sa_sigaction == NULL) { + struct sigaction oldact, repl_sigint_act; + memset(&repl_sigint_act, 0, sizeof(struct sigaction)); + sigemptyset(&repl_sigint_act.sa_mask); + repl_sigint_act.sa_sigaction = repl_sigint_handler; + repl_sigint_act.sa_flags = SA_SIGINFO; + if (sigaction(SIGINT, &repl_sigint_act, &oldact) < 0) { + JL_PRINTF(JL_STDERR, "sigaction: %s\n", strerror(errno)); + jl_exit(1); + } + if (repl_sigint_act.sa_sigaction != oldact.sa_sigaction && + jl_sigint_act.sa_sigaction != oldact.sa_sigaction) + jl_sigint_act = oldact; + } +#endif +} +/* Restore the terminal's normal settings and modes. */ +void jl_deprep_terminal () +{ + FILE *rl_in = rl_instream; + rl_instream = stdin; + rl_deprep_terminal(); + rl_instream = rl_in; +#ifdef __WIN32__ + if (jl_uv_stdin->type == UV_TTY) uv_tty_set_mode((uv_tty_t*)jl_uv_stdin,0); // cooked +#endif } void init_repl_environment(int argc, char *argv[]) { disable_history = 0; - for (int i = 0; i < argc; i++) - { - if (!strcmp(argv[i], "--no-history")) - { + for (int i = 0; i < argc; i++) { + if (!strcmp(argv[i], "--no-history")) { disable_history = 1; break; } } - prompt_length = strlen(prompt_plain); +#ifdef __WIN32__ + rl_outstream=(void*)jl_uv_stdout; + repl_sigint_handler_installed = 0; +#else + jl_sigint_act.sa_sigaction = NULL; +#endif rl_catch_signals = 0; + rl_prep_term_function = &jl_prep_terminal; + rl_deprep_term_function = &jl_deprep_terminal; + rl_instream = fopen("/dev/null","r"); + prompt_length = strlen(prompt_plain); init_history(); rl_startup_hook = (Function*)init_rl; } @@ -577,8 +763,45 @@ void repl_callback_enable() rl_callback_handler_install(prompt_string, jl_input_line_callback); } -void jl_stdin_callback(void) +#include "uv.h" + +void jl_readBuffer(char *base, ssize_t nread) { - if (callback_en) - rl_callback_read_char(); + char *start = base; + while(*start != 0 && nread > 0) { + rl_stuff_char(*start); + start++; + nread--; + } + rl_callback_read_char(); +} + +void restart(void) +{ + rl_on_new_line(); +} + +DLLEXPORT void jl_clear_input(void) +{ + //todo: how to do this better / the correct way / ??? + //move the cursor to a clean line: + char *p = rl_line_buffer; + int i; + for (i = 0; *p != '\0'; p++, i++) { + if (i >= rl_point && *p == '\n') { + jl_putc('\n', jl_uv_stdout); + } + } + jl_putc('\n', jl_uv_stdout); + jl_putc('\n', jl_uv_stdout); + //reset state: + rl_reset_line_state(); + reset_indent(); + rl_initialize(); + //and redisplay prompt: + rl_forced_update_display(); + rl_on_new_line_with_prompt(); +#ifdef __WIN32__ + jl_write(jl_uv_stdout, "\e[4C", 4); //hack: try to fix cursor location +#endif } diff --git a/ui/repl.c b/ui/repl.c index d958b205e9fe7..03e32938ef1c7 100644 --- a/ui/repl.c +++ b/ui/repl.c @@ -4,6 +4,9 @@ */ #include "repl.h" +#include "uv.h" +#define WHOLE_ARCHIVE +#include "../src/julia.h" static int lisp_prompt = 0; static char *program = NULL; @@ -14,14 +17,14 @@ static const char *usage = "julia [options] [program] [args...]\n"; static const char *opts = " -v --version Display version information\n" " -q --quiet Quiet startup without banner\n" - " -H --home= Load files relative to \n" - " -T --tab= Set REPL tab width to \n\n" + " -H --home Load files relative to \n" + " -T --tab Set REPL tab width to \n\n" - " -e --eval= Evaluate \n" - " -E --print= Evaluate and show \n" - " -P --post-boot= Evaluate right after boot\n" - " -L --load=file Load right after boot\n" - " -J --sysimage=file Start up with the given system image file\n\n" + " -e --eval Evaluate \n" + " -E --print Evaluate and show \n" + " -P --post-boot Evaluate right after boot\n" + " -L --load file Load right after boot\n" + " -J --sysimage file Start up with the given system image file\n\n" " -p n Run n local processes\n" " --machinefile file Run processes on hosts listed in file\n\n" @@ -157,21 +160,21 @@ static int exec_program(void) } else { while (1) { - if (jl_typeof(e) == (jl_type_t*)jl_loaderror_type) { + if (jl_typeof(e) == (jl_value_t*)jl_loaderror_type) { e = jl_fieldref(e, 2); // TODO: show file and line } else break; } - if (jl_typeof(e) == (jl_type_t*)jl_errorexception_type) { - ios_printf(ios_stderr, "error during bootstrap: %s\n", + if (jl_typeof(e) == (jl_value_t*)jl_errorexception_type) { + jl_printf(JL_STDERR, "error during bootstrap: %s\n", jl_string_data(jl_fieldref(e,0))); } else { - ios_printf(ios_stderr, "error during bootstrap\n"); + jl_printf(JL_STDERR, "error during bootstrap\n"); } } - ios_printf(ios_stderr, "\n"); + jl_printf(JL_STDERR, "\n"); JL_EH_POP(); return 1; } @@ -218,6 +221,16 @@ static void print_profile(void) } #endif +uv_buf_t *jl_alloc_read_buffer(uv_handle_t* handle, size_t suggested_size) +{ + if(suggested_size>512) suggested_size = 512; //Readline has a max buffer of 512 + char *buf = malloc(suggested_size); + uv_buf_t *ret = malloc(sizeof(uv_buf_t)); + *ret = uv_buf_init(buf,suggested_size); + return ret; +} + + int true_main(int argc, char *argv[]) { if (jl_base_module != NULL) { @@ -234,7 +247,9 @@ int true_main(int argc, char *argv[]) // run program if specified, otherwise enter REPL if (program) { - return exec_program(); + int ret = exec_program(); + uv_tty_reset_mode(); + return ret; } init_repl_environment(argc, argv); @@ -242,39 +257,37 @@ int true_main(int argc, char *argv[]) jl_function_t *start_client = (jl_function_t*)jl_get_global(jl_base_module, jl_symbol("_start")); + //uv_read_start(jl_stdin_tty,jl_alloc_read_buffer,&readBuffer); + if (start_client) { jl_apply(start_client, NULL, 0); + //rl_cleanup_after_signal(); return 0; } // client event loop not available; use fallback blocking version + //install_read_event_handler(&echoBack); int iserr = 0; + again: ; JL_TRY { if (iserr) { - jl_show(jl_stderr_obj(), jl_exception_in_transit); - ios_printf(ios_stderr, "\n\n"); + //jl_show(jl_exception_in_transit);# What if the error was in show? + jl_printf(JL_STDERR, "\n\n"); iserr = 0; } - while (1) { - char *input = read_expr("julia> "); - if (!input || ios_eof(ios_stdin)) { - ios_printf(ios_stdout, "\n"); - break; - } - jl_value_t *ast = jl_parse_input_line(input); - jl_value_t *value = jl_toplevel_eval(ast); - jl_show(jl_stdout_obj(), value); - ios_printf(ios_stdout, "\n\n"); - } + uv_run(jl_global_event_loop(),UV_RUN_DEFAULT); } JL_CATCH { iserr = 1; + JL_PUTS("error during run:\n",JL_STDERR); + jl_show(jl_stderr_obj(),jl_exception_in_transit); + JL_PUTS("\n",JL_STDOUT); goto again; } - - return 0; + uv_tty_reset_mode(); + return iserr; } int main(int argc, char *argv[]) diff --git a/ui/repl.expmap b/ui/repl.expmap new file mode 100644 index 0000000000000..10fc99eb60d84 --- /dev/null +++ b/ui/repl.expmap @@ -0,0 +1,6 @@ +{ + global: + jl_clear_input; + local: + *; +}; diff --git a/ui/repl.h b/ui/repl.h index 34a54f1d43475..02d76302edab4 100644 --- a/ui/repl.h +++ b/ui/repl.h @@ -32,5 +32,7 @@ extern char *ios_readline(ios_t *s); DLLEXPORT extern void repl_callback_enable(); DLLEXPORT extern void jl_enable_color(); DLLEXPORT extern void jl_stdin_callback(); +DLLEXPORT extern void jl_readBuffer(char *base, ssize_t nread); +DLLEXPORT extern void jl_clear_input(void); #endif // JL_REPL_H diff --git a/ui/webserver/.gitignore b/ui/webserver/.gitignore deleted file mode 100644 index 8b8ae4c98873b..0000000000000 --- a/ui/webserver/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -/*.o -/webserver -/julia-release-webserver -/julia-debug-webserver -/julia-debug-webserver.dSYM diff --git a/ui/webserver/Makefile b/ui/webserver/Makefile deleted file mode 100644 index c28a4f261f72c..0000000000000 --- a/ui/webserver/Makefile +++ /dev/null @@ -1,45 +0,0 @@ -JULIAHOME = $(abspath ../..) -include $(JULIAHOME)/Make.inc - -override CFLAGS += $(JCFLAGS) -override CXXFLAGS += $(JCXXFLAGS) - -LIBS = -lpthread $(USR)/$(JL_LIBDIR)/libuv.a -ifeq ($(OS), Linux) -LIBS += -lrt -endif - -ifeq ($(OS),WINNT) -LIBS += -lWs2_32 -lIphlpapi -lpsapi -endif - -WEBSERVER_SRCS = webserver.cpp server.cpp jsoncpp.cpp - -%.o: %.c - $(QUIET_CC)$(CC) $(CFLAGS) $(SHIPFLAGS) -c $< -o $@ -%.do: %.c - $(QUIET_CC)$(CC) $(CFLAGS) $(DEBUGFLAGS) -c $< -o $@ - - -LAUNCH_SCRIPT = launch-julia-webserver -ifeq ($(OS),WINNT) -LAUNCH_SCRIPT = launch-julia-webserver.bat -endif - -julia-release julia-debug: %: $(USRBIN)/%-webserver $(USRBIN)/$(LAUNCH_SCRIPT) - -release debug: - $(MAKE) julia-$@ - -$(USRBIN)/julia-release-webserver: $(WEBSERVER_SRCS) - $(QUIET_LINK) $(CXX) $(CXXFLAGS) -o $@ $(SHIPFLAGS) $(WEBSERVER_SRCS) $(LIBS) - -$(USRBIN)/julia-debug-webserver: $(WEBSERVER_SRCS) - $(QUIET_LINK) $(CXX) $(CXXFLAGS) -o $@ $(DEBUGFLAGS) $(WEBSERVER_SRCS) $(LIBS) - -$(USRBIN)/$(LAUNCH_SCRIPT): $(LAUNCH_SCRIPT) - cp $< $@ - -clean: - rm -f *.o *.do - rm -f $(USRBIN)/julia-*-webserver diff --git a/ui/webserver/json.h b/ui/webserver/json.h deleted file mode 100644 index 5c232614c72c9..0000000000000 --- a/ui/webserver/json.h +++ /dev/null @@ -1,1857 +0,0 @@ -/// Json-cpp amalgated header (http://jsoncpp.sourceforge.net/). -/// It is intented to be used with #include - -#define JSON_IS_AMALGAMATION - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: LICENSE -// ////////////////////////////////////////////////////////////////////// - -/* -The JsonCpp library's source code, including accompanying documentation, -tests and demonstration applications, are licensed under the following -conditions... - -The author (Baptiste Lepilleur) explicitly disclaims copyright in all -jurisdictions which recognize such a disclaimer. In such jurisdictions, -this software is released into the Public Domain. - -In jurisdictions which do not recognize Public Domain property (e.g. Germany as of -2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is -released under the terms of the MIT License (see below). - -In jurisdictions which recognize Public Domain property, the user of this -software may choose to accept it either as 1) Public Domain, 2) under the -conditions of the MIT License (see below), or 3) under the terms of dual -Public Domain/MIT License conditions described here, as they choose. - -The MIT License is about as close to Public Domain as a license can get, and is -described in clear, concise terms at: - - http://en.wikipedia.org/wiki/MIT_License - -The full text of the MIT License follows: - -======================================================================== -Copyright (c) 2007-2010 Baptiste Lepilleur - -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. -======================================================================== -(END LICENSE TEXT) - -The MIT license is compatible with both the GPL and commercial -software, affording one all of the rights of Public Domain with the -minor nuisance of being required to keep the above copyright notice -and license text in the source code. Note also that by accepting the -Public Domain "license" you can re-license your copy using whatever -license you like. - -*/ - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: LICENSE -// ////////////////////////////////////////////////////////////////////// - - - - - -#ifndef JSON_AMALGATED_H_INCLUDED -# define JSON_AMALGATED_H_INCLUDED -/// If defined, indicates that the source file is amalgated -/// to prevent private header inclusion. -#define JSON_IS_AMALGATED - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/config.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSON_CONFIG_H_INCLUDED -# define JSON_CONFIG_H_INCLUDED - -/// If defined, indicates that json library is embedded in CppTL library. -//# define JSON_IN_CPPTL 1 - -/// If defined, indicates that json may leverage CppTL library -//# define JSON_USE_CPPTL 1 -/// If defined, indicates that cpptl vector based map should be used instead of std::map -/// as Value container. -//# define JSON_USE_CPPTL_SMALLMAP 1 -/// If defined, indicates that Json specific container should be used -/// (hash table & simple deque container with customizable allocator). -/// THIS FEATURE IS STILL EXPERIMENTAL! There is know bugs: See #3177332 -//# define JSON_VALUE_USE_INTERNAL_MAP 1 -/// Force usage of standard new/malloc based allocator instead of memory pool based allocator. -/// The memory pools allocator used optimization (initializing Value and ValueInternalLink -/// as if it was a POD) that may cause some validation tool to report errors. -/// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined. -//# define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1 - -/// If defined, indicates that Json use exception to report invalid type manipulation -/// instead of C assert macro. -# define JSON_USE_EXCEPTION 1 - -/// If defined, indicates that the source file is amalgated -/// to prevent private header inclusion. -/// Remarks: it is automatically defined in the generated amalgated header. -// #define JSON_IS_AMALGAMATION - - -# ifdef JSON_IN_CPPTL -# include -# ifndef JSON_USE_CPPTL -# define JSON_USE_CPPTL 1 -# endif -# endif - -# ifdef JSON_IN_CPPTL -# define JSON_API CPPTL_API -# elif defined(JSON_DLL_BUILD) -# define JSON_API __declspec(dllexport) -# elif defined(JSON_DLL) -# define JSON_API __declspec(dllimport) -# else -# define JSON_API -# endif - -// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for integer -// Storages, and 64 bits integer support is disabled. -// #define JSON_NO_INT64 1 - -#if defined(_MSC_VER) && _MSC_VER <= 1200 // MSVC 6 -// Microsoft Visual Studio 6 only support conversion from __int64 to double -// (no conversion from unsigned __int64). -#define JSON_USE_INT64_DOUBLE_CONVERSION 1 -#endif // if defined(_MSC_VER) && _MSC_VER < 1200 // MSVC 6 - -#if defined(_MSC_VER) && _MSC_VER >= 1500 // MSVC 2008 -/// Indicates that the following function is deprecated. -# define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) -#endif - -#if !defined(JSONCPP_DEPRECATED) -# define JSONCPP_DEPRECATED(message) -#endif // if !defined(JSONCPP_DEPRECATED) - -namespace Json { - typedef int Int; - typedef unsigned int UInt; -# if defined(JSON_NO_INT64) - typedef int LargestInt; - typedef unsigned int LargestUInt; -# undef JSON_HAS_INT64 -# else // if defined(JSON_NO_INT64) - // For Microsoft Visual use specific types as long long is not supported -# if defined(_MSC_VER) // Microsoft Visual Studio - typedef __int64 Int64; - typedef unsigned __int64 UInt64; -# else // if defined(_MSC_VER) // Other platforms, use long long - typedef long long int Int64; - typedef unsigned long long int UInt64; -# endif // if defined(_MSC_VER) - typedef Int64 LargestInt; - typedef UInt64 LargestUInt; -# define JSON_HAS_INT64 -# endif // if defined(JSON_NO_INT64) -} // end namespace Json - - -#endif // JSON_CONFIG_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/config.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/forwards.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSON_FORWARDS_H_INCLUDED -# define JSON_FORWARDS_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -# include "config.h" -#endif // if !defined(JSON_IS_AMALGAMATION) - -namespace Json { - - // writer.h - class FastWriter; - class StyledWriter; - - // reader.h - class Reader; - - // features.h - class Features; - - // value.h - typedef unsigned int ArrayIndex; - class StaticString; - class Path; - class PathArgument; - class Value; - class ValueIteratorBase; - class ValueIterator; - class ValueConstIterator; -#ifdef JSON_VALUE_USE_INTERNAL_MAP - class ValueMapAllocator; - class ValueInternalLink; - class ValueInternalArray; - class ValueInternalMap; -#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP - -} // namespace Json - - -#endif // JSON_FORWARDS_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/forwards.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/features.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef CPPTL_JSON_FEATURES_H_INCLUDED -# define CPPTL_JSON_FEATURES_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -# include "forwards.h" -#endif // if !defined(JSON_IS_AMALGAMATION) - -namespace Json { - - /** \brief Configuration passed to reader and writer. - * This configuration object can be used to force the Reader or Writer - * to behave in a standard conforming way. - */ - class JSON_API Features - { - public: - /** \brief A configuration that allows all features and assumes all strings are UTF-8. - * - C & C++ comments are allowed - * - Root object can be any JSON value - * - Assumes Value strings are encoded in UTF-8 - */ - static Features all(); - - /** \brief A configuration that is strictly compatible with the JSON specification. - * - Comments are forbidden. - * - Root object must be either an array or an object value. - * - Assumes Value strings are encoded in UTF-8 - */ - static Features strictMode(); - - /** \brief Initialize the configuration like JsonConfig::allFeatures; - */ - Features(); - - /// \c true if comments are allowed. Default: \c true. - bool allowComments_; - - /// \c true if root must be either an array or an object value. Default: \c false. - bool strictRoot_; - }; - -} // namespace Json - -#endif // CPPTL_JSON_FEATURES_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/features.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/value.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef CPPTL_JSON_H_INCLUDED -# define CPPTL_JSON_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -# include "forwards.h" -#endif // if !defined(JSON_IS_AMALGAMATION) -# include -# include - -# ifndef JSON_USE_CPPTL_SMALLMAP -# include -# else -# include -# endif -# ifdef JSON_USE_CPPTL -# include -# endif - -/** \brief JSON (JavaScript Object Notation). - */ -namespace Json { - - /** \brief Type of the value held by a Value object. - */ - enum ValueType - { - nullValue = 0, ///< 'null' value - intValue, ///< signed integer value - uintValue, ///< unsigned integer value - realValue, ///< double value - stringValue, ///< UTF-8 string value - booleanValue, ///< bool value - arrayValue, ///< array value (ordered list) - objectValue ///< object value (collection of name/value pairs). - }; - - enum CommentPlacement - { - commentBefore = 0, ///< a comment placed on the line before a value - commentAfterOnSameLine, ///< a comment just after a value on the same line - commentAfter, ///< a comment on the line after a value (only make sense for root value) - numberOfCommentPlacement - }; - -//# ifdef JSON_USE_CPPTL -// typedef CppTL::AnyEnumerator EnumMemberNames; -// typedef CppTL::AnyEnumerator EnumValues; -//# endif - - /** \brief Lightweight wrapper to tag static string. - * - * Value constructor and objectValue member assignement takes advantage of the - * StaticString and avoid the cost of string duplication when storing the - * string or the member name. - * - * Example of usage: - * \code - * Json::Value aValue( StaticString("some text") ); - * Json::Value object; - * static const StaticString code("code"); - * object[code] = 1234; - * \endcode - */ - class JSON_API StaticString - { - public: - explicit StaticString( const char *czstring ) - : str_( czstring ) - { - } - - operator const char *() const - { - return str_; - } - - const char *c_str() const - { - return str_; - } - - private: - const char *str_; - }; - - /** \brief Represents a JSON value. - * - * This class is a discriminated union wrapper that can represents a: - * - signed integer [range: Value::minInt - Value::maxInt] - * - unsigned integer (range: 0 - Value::maxUInt) - * - double - * - UTF-8 string - * - boolean - * - 'null' - * - an ordered list of Value - * - collection of name/value pairs (javascript object) - * - * The type of the held value is represented by a #ValueType and - * can be obtained using type(). - * - * values of an #objectValue or #arrayValue can be accessed using operator[]() methods. - * Non const methods will automatically create the a #nullValue element - * if it does not exist. - * The sequence of an #arrayValue will be automatically resize and initialized - * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue. - * - * The get() methods can be used to obtanis default value in the case the required element - * does not exist. - * - * It is possible to iterate over the list of a #objectValue values using - * the getMemberNames() method. - */ - class JSON_API Value - { - friend class ValueIteratorBase; -# ifdef JSON_VALUE_USE_INTERNAL_MAP - friend class ValueInternalLink; - friend class ValueInternalMap; -# endif - public: - typedef std::vector Members; - typedef ValueIterator iterator; - typedef ValueConstIterator const_iterator; - typedef Json::UInt UInt; - typedef Json::Int Int; -# if defined(JSON_HAS_INT64) - typedef Json::UInt64 UInt64; - typedef Json::Int64 Int64; -#endif // defined(JSON_HAS_INT64) - typedef Json::LargestInt LargestInt; - typedef Json::LargestUInt LargestUInt; - typedef Json::ArrayIndex ArrayIndex; - - static const Value null; - /// Minimum signed integer value that can be stored in a Json::Value. - static const LargestInt minLargestInt; - /// Maximum signed integer value that can be stored in a Json::Value. - static const LargestInt maxLargestInt; - /// Maximum unsigned integer value that can be stored in a Json::Value. - static const LargestUInt maxLargestUInt; - - /// Minimum signed int value that can be stored in a Json::Value. - static const Int minInt; - /// Maximum signed int value that can be stored in a Json::Value. - static const Int maxInt; - /// Maximum unsigned int value that can be stored in a Json::Value. - static const UInt maxUInt; - - /// Minimum signed 64 bits int value that can be stored in a Json::Value. - static const Int64 minInt64; - /// Maximum signed 64 bits int value that can be stored in a Json::Value. - static const Int64 maxInt64; - /// Maximum unsigned 64 bits int value that can be stored in a Json::Value. - static const UInt64 maxUInt64; - - private: -#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION -# ifndef JSON_VALUE_USE_INTERNAL_MAP - class CZString - { - public: - enum DuplicationPolicy - { - noDuplication = 0, - duplicate, - duplicateOnCopy - }; - CZString( ArrayIndex index ); - CZString( const char *cstr, DuplicationPolicy allocate ); - CZString( const CZString &other ); - ~CZString(); - CZString &operator =( const CZString &other ); - bool operator<( const CZString &other ) const; - bool operator==( const CZString &other ) const; - ArrayIndex index() const; - const char *c_str() const; - bool isStaticString() const; - private: - void swap( CZString &other ); - const char *cstr_; - ArrayIndex index_; - }; - - public: -# ifndef JSON_USE_CPPTL_SMALLMAP - typedef std::map ObjectValues; -# else - typedef CppTL::SmallMap ObjectValues; -# endif // ifndef JSON_USE_CPPTL_SMALLMAP -# endif // ifndef JSON_VALUE_USE_INTERNAL_MAP -#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - - public: - /** \brief Create a default Value of the given type. - - This is a very useful constructor. - To create an empty array, pass arrayValue. - To create an empty object, pass objectValue. - Another Value can then be set to this one by assignment. - This is useful since clear() and resize() will not alter types. - - Examples: - \code - Json::Value null_value; // null - Json::Value arr_value(Json::arrayValue); // [] - Json::Value obj_value(Json::objectValue); // {} - \endcode - */ - Value( ValueType type = nullValue ); - Value( Int value ); - Value( UInt value ); -#if defined(JSON_HAS_INT64) - Value( Int64 value ); - Value( UInt64 value ); -#endif // if defined(JSON_HAS_INT64) - Value( double value ); - Value( const char *value ); - Value( const char *beginValue, const char *endValue ); - /** \brief Constructs a value from a static string. - - * Like other value string constructor but do not duplicate the string for - * internal storage. The given string must remain alive after the call to this - * constructor. - * Example of usage: - * \code - * Json::Value aValue( StaticString("some text") ); - * \endcode - */ - Value( const StaticString &value ); - Value( const std::string &value ); -# ifdef JSON_USE_CPPTL - Value( const CppTL::ConstString &value ); -# endif - Value( bool value ); - Value( const Value &other ); - ~Value(); - - Value &operator=( const Value &other ); - /// Swap values. - /// \note Currently, comments are intentionally not swapped, for - /// both logic and efficiency. - void swap( Value &other ); - - ValueType type() const; - - bool operator <( const Value &other ) const; - bool operator <=( const Value &other ) const; - bool operator >=( const Value &other ) const; - bool operator >( const Value &other ) const; - - bool operator ==( const Value &other ) const; - bool operator !=( const Value &other ) const; - - int compare( const Value &other ) const; - - const char *asCString() const; - std::string asString() const; -# ifdef JSON_USE_CPPTL - CppTL::ConstString asConstString() const; -# endif - Int asInt() const; - UInt asUInt() const; - Int64 asInt64() const; - UInt64 asUInt64() const; - LargestInt asLargestInt() const; - LargestUInt asLargestUInt() const; - float asFloat() const; - double asDouble() const; - bool asBool() const; - - bool isNull() const; - bool isBool() const; - bool isInt() const; - bool isUInt() const; - bool isIntegral() const; - bool isDouble() const; - bool isNumeric() const; - bool isString() const; - bool isArray() const; - bool isObject() const; - - bool isConvertibleTo( ValueType other ) const; - - /// Number of values in array or object - ArrayIndex size() const; - - /// \brief Return true if empty array, empty object, or null; - /// otherwise, false. - bool empty() const; - - /// Return isNull() - bool operator!() const; - - /// Remove all object members and array elements. - /// \pre type() is arrayValue, objectValue, or nullValue - /// \post type() is unchanged - void clear(); - - /// Resize the array to size elements. - /// New elements are initialized to null. - /// May only be called on nullValue or arrayValue. - /// \pre type() is arrayValue or nullValue - /// \post type() is arrayValue - void resize( ArrayIndex size ); - - /// Access an array element (zero based index ). - /// If the array contains less than index element, then null value are inserted - /// in the array so that its size is index+1. - /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) - Value &operator[]( ArrayIndex index ); - - /// Access an array element (zero based index ). - /// If the array contains less than index element, then null value are inserted - /// in the array so that its size is index+1. - /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) - Value &operator[]( int index ); - - /// Access an array element (zero based index ) - /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) - const Value &operator[]( ArrayIndex index ) const; - - /// Access an array element (zero based index ) - /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) - const Value &operator[]( int index ) const; - - /// If the array contains at least index+1 elements, returns the element value, - /// otherwise returns defaultValue. - Value get( ArrayIndex index, - const Value &defaultValue ) const; - /// Return true if index < size(). - bool isValidIndex( ArrayIndex index ) const; - /// \brief Append value to array at the end. - /// - /// Equivalent to jsonvalue[jsonvalue.size()] = value; - Value &append( const Value &value ); - - /// Access an object value by name, create a null member if it does not exist. - Value &operator[]( const char *key ); - /// Access an object value by name, returns null if there is no member with that name. - const Value &operator[]( const char *key ) const; - /// Access an object value by name, create a null member if it does not exist. - Value &operator[]( const std::string &key ); - /// Access an object value by name, returns null if there is no member with that name. - const Value &operator[]( const std::string &key ) const; - /** \brief Access an object value by name, create a null member if it does not exist. - - * If the object as no entry for that name, then the member name used to store - * the new entry is not duplicated. - * Example of use: - * \code - * Json::Value object; - * static const StaticString code("code"); - * object[code] = 1234; - * \endcode - */ - Value &operator[]( const StaticString &key ); -# ifdef JSON_USE_CPPTL - /// Access an object value by name, create a null member if it does not exist. - Value &operator[]( const CppTL::ConstString &key ); - /// Access an object value by name, returns null if there is no member with that name. - const Value &operator[]( const CppTL::ConstString &key ) const; -# endif - /// Return the member named key if it exist, defaultValue otherwise. - Value get( const char *key, - const Value &defaultValue ) const; - /// Return the member named key if it exist, defaultValue otherwise. - Value get( const std::string &key, - const Value &defaultValue ) const; -# ifdef JSON_USE_CPPTL - /// Return the member named key if it exist, defaultValue otherwise. - Value get( const CppTL::ConstString &key, - const Value &defaultValue ) const; -# endif - /// \brief Remove and return the named member. - /// - /// Do nothing if it did not exist. - /// \return the removed Value, or null. - /// \pre type() is objectValue or nullValue - /// \post type() is unchanged - Value removeMember( const char* key ); - /// Same as removeMember(const char*) - Value removeMember( const std::string &key ); - - /// Return true if the object has a member named key. - bool isMember( const char *key ) const; - /// Return true if the object has a member named key. - bool isMember( const std::string &key ) const; -# ifdef JSON_USE_CPPTL - /// Return true if the object has a member named key. - bool isMember( const CppTL::ConstString &key ) const; -# endif - - /// \brief Return a list of the member names. - /// - /// If null, return an empty list. - /// \pre type() is objectValue or nullValue - /// \post if type() was nullValue, it remains nullValue - Members getMemberNames() const; - -//# ifdef JSON_USE_CPPTL -// EnumMemberNames enumMemberNames() const; -// EnumValues enumValues() const; -//# endif - - /// Comments must be //... or /* ... */ - void setComment( const char *comment, - CommentPlacement placement ); - /// Comments must be //... or /* ... */ - void setComment( const std::string &comment, - CommentPlacement placement ); - bool hasComment( CommentPlacement placement ) const; - /// Include delimiters and embedded newlines. - std::string getComment( CommentPlacement placement ) const; - - std::string toStyledString() const; - - const_iterator begin() const; - const_iterator end() const; - - iterator begin(); - iterator end(); - - private: - Value &resolveReference( const char *key, - bool isStatic ); - -# ifdef JSON_VALUE_USE_INTERNAL_MAP - inline bool isItemAvailable() const - { - return itemIsUsed_ == 0; - } - - inline void setItemUsed( bool isUsed = true ) - { - itemIsUsed_ = isUsed ? 1 : 0; - } - - inline bool isMemberNameStatic() const - { - return memberNameIsStatic_ == 0; - } - - inline void setMemberNameIsStatic( bool isStatic ) - { - memberNameIsStatic_ = isStatic ? 1 : 0; - } -# endif // # ifdef JSON_VALUE_USE_INTERNAL_MAP - - private: - struct CommentInfo - { - CommentInfo(); - ~CommentInfo(); - - void setComment( const char *text ); - - char *comment_; - }; - - //struct MemberNamesTransform - //{ - // typedef const char *result_type; - // const char *operator()( const CZString &name ) const - // { - // return name.c_str(); - // } - //}; - - union ValueHolder - { - LargestInt int_; - LargestUInt uint_; - double real_; - bool bool_; - char *string_; -# ifdef JSON_VALUE_USE_INTERNAL_MAP - ValueInternalArray *array_; - ValueInternalMap *map_; -#else - ObjectValues *map_; -# endif - } value_; - ValueType type_ : 8; - int allocated_ : 1; // Notes: if declared as bool, bitfield is useless. -# ifdef JSON_VALUE_USE_INTERNAL_MAP - unsigned int itemIsUsed_ : 1; // used by the ValueInternalMap container. - int memberNameIsStatic_ : 1; // used by the ValueInternalMap container. -# endif - CommentInfo *comments_; - }; - - - /** \brief Experimental and untested: represents an element of the "path" to access a node. - */ - class PathArgument - { - public: - friend class Path; - - PathArgument(); - PathArgument( ArrayIndex index ); - PathArgument( const char *key ); - PathArgument( const std::string &key ); - - private: - enum Kind - { - kindNone = 0, - kindIndex, - kindKey - }; - std::string key_; - ArrayIndex index_; - Kind kind_; - }; - - /** \brief Experimental and untested: represents a "path" to access a node. - * - * Syntax: - * - "." => root node - * - ".[n]" => elements at index 'n' of root node (an array value) - * - ".name" => member named 'name' of root node (an object value) - * - ".name1.name2.name3" - * - ".[0][1][2].name1[3]" - * - ".%" => member name is provided as parameter - * - ".[%]" => index is provied as parameter - */ - class Path - { - public: - Path( const std::string &path, - const PathArgument &a1 = PathArgument(), - const PathArgument &a2 = PathArgument(), - const PathArgument &a3 = PathArgument(), - const PathArgument &a4 = PathArgument(), - const PathArgument &a5 = PathArgument() ); - - const Value &resolve( const Value &root ) const; - Value resolve( const Value &root, - const Value &defaultValue ) const; - /// Creates the "path" to access the specified node and returns a reference on the node. - Value &make( Value &root ) const; - - private: - typedef std::vector InArgs; - typedef std::vector Args; - - void makePath( const std::string &path, - const InArgs &in ); - void addPathInArg( const std::string &path, - const InArgs &in, - InArgs::const_iterator &itInArg, - PathArgument::Kind kind ); - void invalidPath( const std::string &path, - int location ); - - Args args_; - }; - - - -#ifdef JSON_VALUE_USE_INTERNAL_MAP - /** \brief Allocator to customize Value internal map. - * Below is an example of a simple implementation (default implementation actually - * use memory pool for speed). - * \code - class DefaultValueMapAllocator : public ValueMapAllocator - { - public: // overridden from ValueMapAllocator - virtual ValueInternalMap *newMap() - { - return new ValueInternalMap(); - } - - virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) - { - return new ValueInternalMap( other ); - } - - virtual void destructMap( ValueInternalMap *map ) - { - delete map; - } - - virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) - { - return new ValueInternalLink[size]; - } - - virtual void releaseMapBuckets( ValueInternalLink *links ) - { - delete [] links; - } - - virtual ValueInternalLink *allocateMapLink() - { - return new ValueInternalLink(); - } - - virtual void releaseMapLink( ValueInternalLink *link ) - { - delete link; - } - }; - * \endcode - */ - class JSON_API ValueMapAllocator - { - public: - virtual ~ValueMapAllocator(); - virtual ValueInternalMap *newMap() = 0; - virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) = 0; - virtual void destructMap( ValueInternalMap *map ) = 0; - virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) = 0; - virtual void releaseMapBuckets( ValueInternalLink *links ) = 0; - virtual ValueInternalLink *allocateMapLink() = 0; - virtual void releaseMapLink( ValueInternalLink *link ) = 0; - }; - - /** \brief ValueInternalMap hash-map bucket chain link (for internal use only). - * \internal previous_ & next_ allows for bidirectional traversal. - */ - class JSON_API ValueInternalLink - { - public: - enum { itemPerLink = 6 }; // sizeof(ValueInternalLink) = 128 on 32 bits architecture. - enum InternalFlags { - flagAvailable = 0, - flagUsed = 1 - }; - - ValueInternalLink(); - - ~ValueInternalLink(); - - Value items_[itemPerLink]; - char *keys_[itemPerLink]; - ValueInternalLink *previous_; - ValueInternalLink *next_; - }; - - - /** \brief A linked page based hash-table implementation used internally by Value. - * \internal ValueInternalMap is a tradional bucket based hash-table, with a linked - * list in each bucket to handle collision. There is an addional twist in that - * each node of the collision linked list is a page containing a fixed amount of - * value. This provides a better compromise between memory usage and speed. - * - * Each bucket is made up of a chained list of ValueInternalLink. The last - * link of a given bucket can be found in the 'previous_' field of the following bucket. - * The last link of the last bucket is stored in tailLink_ as it has no following bucket. - * Only the last link of a bucket may contains 'available' item. The last link always - * contains at least one element unless is it the bucket one very first link. - */ - class JSON_API ValueInternalMap - { - friend class ValueIteratorBase; - friend class Value; - public: - typedef unsigned int HashKey; - typedef unsigned int BucketIndex; - -# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - struct IteratorState - { - IteratorState() - : map_(0) - , link_(0) - , itemIndex_(0) - , bucketIndex_(0) - { - } - ValueInternalMap *map_; - ValueInternalLink *link_; - BucketIndex itemIndex_; - BucketIndex bucketIndex_; - }; -# endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - - ValueInternalMap(); - ValueInternalMap( const ValueInternalMap &other ); - ValueInternalMap &operator =( const ValueInternalMap &other ); - ~ValueInternalMap(); - - void swap( ValueInternalMap &other ); - - BucketIndex size() const; - - void clear(); - - bool reserveDelta( BucketIndex growth ); - - bool reserve( BucketIndex newItemCount ); - - const Value *find( const char *key ) const; - - Value *find( const char *key ); - - Value &resolveReference( const char *key, - bool isStatic ); - - void remove( const char *key ); - - void doActualRemove( ValueInternalLink *link, - BucketIndex index, - BucketIndex bucketIndex ); - - ValueInternalLink *&getLastLinkInBucket( BucketIndex bucketIndex ); - - Value &setNewItem( const char *key, - bool isStatic, - ValueInternalLink *link, - BucketIndex index ); - - Value &unsafeAdd( const char *key, - bool isStatic, - HashKey hashedKey ); - - HashKey hash( const char *key ) const; - - int compare( const ValueInternalMap &other ) const; - - private: - void makeBeginIterator( IteratorState &it ) const; - void makeEndIterator( IteratorState &it ) const; - static bool equals( const IteratorState &x, const IteratorState &other ); - static void increment( IteratorState &iterator ); - static void incrementBucket( IteratorState &iterator ); - static void decrement( IteratorState &iterator ); - static const char *key( const IteratorState &iterator ); - static const char *key( const IteratorState &iterator, bool &isStatic ); - static Value &value( const IteratorState &iterator ); - static int distance( const IteratorState &x, const IteratorState &y ); - - private: - ValueInternalLink *buckets_; - ValueInternalLink *tailLink_; - BucketIndex bucketsSize_; - BucketIndex itemCount_; - }; - - /** \brief A simplified deque implementation used internally by Value. - * \internal - * It is based on a list of fixed "page", each page contains a fixed number of items. - * Instead of using a linked-list, a array of pointer is used for fast item look-up. - * Look-up for an element is as follow: - * - compute page index: pageIndex = itemIndex / itemsPerPage - * - look-up item in page: pages_[pageIndex][itemIndex % itemsPerPage] - * - * Insertion is amortized constant time (only the array containing the index of pointers - * need to be reallocated when items are appended). - */ - class JSON_API ValueInternalArray - { - friend class Value; - friend class ValueIteratorBase; - public: - enum { itemsPerPage = 8 }; // should be a power of 2 for fast divide and modulo. - typedef Value::ArrayIndex ArrayIndex; - typedef unsigned int PageIndex; - -# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - struct IteratorState // Must be a POD - { - IteratorState() - : array_(0) - , currentPageIndex_(0) - , currentItemIndex_(0) - { - } - ValueInternalArray *array_; - Value **currentPageIndex_; - unsigned int currentItemIndex_; - }; -# endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - - ValueInternalArray(); - ValueInternalArray( const ValueInternalArray &other ); - ValueInternalArray &operator =( const ValueInternalArray &other ); - ~ValueInternalArray(); - void swap( ValueInternalArray &other ); - - void clear(); - void resize( ArrayIndex newSize ); - - Value &resolveReference( ArrayIndex index ); - - Value *find( ArrayIndex index ) const; - - ArrayIndex size() const; - - int compare( const ValueInternalArray &other ) const; - - private: - static bool equals( const IteratorState &x, const IteratorState &other ); - static void increment( IteratorState &iterator ); - static void decrement( IteratorState &iterator ); - static Value &dereference( const IteratorState &iterator ); - static Value &unsafeDereference( const IteratorState &iterator ); - static int distance( const IteratorState &x, const IteratorState &y ); - static ArrayIndex indexOf( const IteratorState &iterator ); - void makeBeginIterator( IteratorState &it ) const; - void makeEndIterator( IteratorState &it ) const; - void makeIterator( IteratorState &it, ArrayIndex index ) const; - - void makeIndexValid( ArrayIndex index ); - - Value **pages_; - ArrayIndex size_; - PageIndex pageCount_; - }; - - /** \brief Experimental: do not use. Allocator to customize Value internal array. - * Below is an example of a simple implementation (actual implementation use - * memory pool). - \code -class DefaultValueArrayAllocator : public ValueArrayAllocator -{ -public: // overridden from ValueArrayAllocator - virtual ~DefaultValueArrayAllocator() - { - } - - virtual ValueInternalArray *newArray() - { - return new ValueInternalArray(); - } - - virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) - { - return new ValueInternalArray( other ); - } - - virtual void destruct( ValueInternalArray *array ) - { - delete array; - } - - virtual void reallocateArrayPageIndex( Value **&indexes, - ValueInternalArray::PageIndex &indexCount, - ValueInternalArray::PageIndex minNewIndexCount ) - { - ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1; - if ( minNewIndexCount > newIndexCount ) - newIndexCount = minNewIndexCount; - void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount ); - if ( !newIndexes ) - throw std::bad_alloc(); - indexCount = newIndexCount; - indexes = static_cast( newIndexes ); - } - virtual void releaseArrayPageIndex( Value **indexes, - ValueInternalArray::PageIndex indexCount ) - { - if ( indexes ) - free( indexes ); - } - - virtual Value *allocateArrayPage() - { - return static_cast( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) ); - } - - virtual void releaseArrayPage( Value *value ) - { - if ( value ) - free( value ); - } -}; - \endcode - */ - class JSON_API ValueArrayAllocator - { - public: - virtual ~ValueArrayAllocator(); - virtual ValueInternalArray *newArray() = 0; - virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) = 0; - virtual void destructArray( ValueInternalArray *array ) = 0; - /** \brief Reallocate array page index. - * Reallocates an array of pointer on each page. - * \param indexes [input] pointer on the current index. May be \c NULL. - * [output] pointer on the new index of at least - * \a minNewIndexCount pages. - * \param indexCount [input] current number of pages in the index. - * [output] number of page the reallocated index can handle. - * \b MUST be >= \a minNewIndexCount. - * \param minNewIndexCount Minimum number of page the new index must be able to - * handle. - */ - virtual void reallocateArrayPageIndex( Value **&indexes, - ValueInternalArray::PageIndex &indexCount, - ValueInternalArray::PageIndex minNewIndexCount ) = 0; - virtual void releaseArrayPageIndex( Value **indexes, - ValueInternalArray::PageIndex indexCount ) = 0; - virtual Value *allocateArrayPage() = 0; - virtual void releaseArrayPage( Value *value ) = 0; - }; -#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP - - - /** \brief base class for Value iterators. - * - */ - class ValueIteratorBase - { - public: - typedef unsigned int size_t; - typedef int difference_type; - typedef ValueIteratorBase SelfType; - - ValueIteratorBase(); -#ifndef JSON_VALUE_USE_INTERNAL_MAP - explicit ValueIteratorBase( const Value::ObjectValues::iterator ¤t ); -#else - ValueIteratorBase( const ValueInternalArray::IteratorState &state ); - ValueIteratorBase( const ValueInternalMap::IteratorState &state ); -#endif - - bool operator ==( const SelfType &other ) const - { - return isEqual( other ); - } - - bool operator !=( const SelfType &other ) const - { - return !isEqual( other ); - } - - difference_type operator -( const SelfType &other ) const - { - return computeDistance( other ); - } - - /// Return either the index or the member name of the referenced value as a Value. - Value key() const; - - /// Return the index of the referenced Value. -1 if it is not an arrayValue. - UInt index() const; - - /// Return the member name of the referenced Value. "" if it is not an objectValue. - const char *memberName() const; - - protected: - Value &deref() const; - - void increment(); - - void decrement(); - - difference_type computeDistance( const SelfType &other ) const; - - bool isEqual( const SelfType &other ) const; - - void copy( const SelfType &other ); - - private: -#ifndef JSON_VALUE_USE_INTERNAL_MAP - Value::ObjectValues::iterator current_; - // Indicates that iterator is for a null value. - bool isNull_; -#else - union - { - ValueInternalArray::IteratorState array_; - ValueInternalMap::IteratorState map_; - } iterator_; - bool isArray_; -#endif - }; - - /** \brief const iterator for object and array value. - * - */ - class ValueConstIterator : public ValueIteratorBase - { - friend class Value; - public: - typedef unsigned int size_t; - typedef int difference_type; - typedef const Value &reference; - typedef const Value *pointer; - typedef ValueConstIterator SelfType; - - ValueConstIterator(); - private: - /*! \internal Use by Value to create an iterator. - */ -#ifndef JSON_VALUE_USE_INTERNAL_MAP - explicit ValueConstIterator( const Value::ObjectValues::iterator ¤t ); -#else - ValueConstIterator( const ValueInternalArray::IteratorState &state ); - ValueConstIterator( const ValueInternalMap::IteratorState &state ); -#endif - public: - SelfType &operator =( const ValueIteratorBase &other ); - - SelfType operator++( int ) - { - SelfType temp( *this ); - ++*this; - return temp; - } - - SelfType operator--( int ) - { - SelfType temp( *this ); - --*this; - return temp; - } - - SelfType &operator--() - { - decrement(); - return *this; - } - - SelfType &operator++() - { - increment(); - return *this; - } - - reference operator *() const - { - return deref(); - } - }; - - - /** \brief Iterator for object and array value. - */ - class ValueIterator : public ValueIteratorBase - { - friend class Value; - public: - typedef unsigned int size_t; - typedef int difference_type; - typedef Value &reference; - typedef Value *pointer; - typedef ValueIterator SelfType; - - ValueIterator(); - ValueIterator( const ValueConstIterator &other ); - ValueIterator( const ValueIterator &other ); - private: - /*! \internal Use by Value to create an iterator. - */ -#ifndef JSON_VALUE_USE_INTERNAL_MAP - explicit ValueIterator( const Value::ObjectValues::iterator ¤t ); -#else - ValueIterator( const ValueInternalArray::IteratorState &state ); - ValueIterator( const ValueInternalMap::IteratorState &state ); -#endif - public: - - SelfType &operator =( const SelfType &other ); - - SelfType operator++( int ) - { - SelfType temp( *this ); - ++*this; - return temp; - } - - SelfType operator--( int ) - { - SelfType temp( *this ); - --*this; - return temp; - } - - SelfType &operator--() - { - decrement(); - return *this; - } - - SelfType &operator++() - { - increment(); - return *this; - } - - reference operator *() const - { - return deref(); - } - }; - - -} // namespace Json - - -#endif // CPPTL_JSON_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/value.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/reader.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef CPPTL_JSON_READER_H_INCLUDED -# define CPPTL_JSON_READER_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -# include "features.h" -# include "value.h" -#endif // if !defined(JSON_IS_AMALGAMATION) -# include -# include -# include -# include - -namespace Json { - - /** \brief Unserialize a JSON document into a Value. - * - */ - class JSON_API Reader - { - public: - typedef char Char; - typedef const Char *Location; - - /** \brief Constructs a Reader allowing all features - * for parsing. - */ - Reader(); - - /** \brief Constructs a Reader allowing the specified feature set - * for parsing. - */ - Reader( const Features &features ); - - /** \brief Read a Value from a JSON document. - * \param document UTF-8 encoded string containing the document to read. - * \param root [out] Contains the root value of the document if it was - * successfully parsed. - * \param collectComments \c true to collect comment and allow writing them back during - * serialization, \c false to discard comments. - * This parameter is ignored if Features::allowComments_ - * is \c false. - * \return \c true if the document was successfully parsed, \c false if an error occurred. - */ - bool parse( const std::string &document, - Value &root, - bool collectComments = true ); - - /** \brief Read a Value from a JSON document. - * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the document to read. - * \param endDoc Pointer on the end of the UTF-8 encoded string of the document to read. - \ Must be >= beginDoc. - * \param root [out] Contains the root value of the document if it was - * successfully parsed. - * \param collectComments \c true to collect comment and allow writing them back during - * serialization, \c false to discard comments. - * This parameter is ignored if Features::allowComments_ - * is \c false. - * \return \c true if the document was successfully parsed, \c false if an error occurred. - */ - bool parse( const char *beginDoc, const char *endDoc, - Value &root, - bool collectComments = true ); - - /// \brief Parse from input stream. - /// \see Json::operator>>(std::istream&, Json::Value&). - bool parse( std::istream &is, - Value &root, - bool collectComments = true ); - - /** \brief Returns a user friendly string that list errors in the parsed document. - * \return Formatted error message with the list of errors with their location in - * the parsed document. An empty string is returned if no error occurred - * during parsing. - * \deprecated Use getFormattedErrorMessages() instead (typo fix). - */ - JSONCPP_DEPRECATED("Use getFormattedErrorMessages instead") - std::string getFormatedErrorMessages() const; - - /** \brief Returns a user friendly string that list errors in the parsed document. - * \return Formatted error message with the list of errors with their location in - * the parsed document. An empty string is returned if no error occurred - * during parsing. - */ - std::string getFormattedErrorMessages() const; - - private: - enum TokenType - { - tokenEndOfStream = 0, - tokenObjectBegin, - tokenObjectEnd, - tokenArrayBegin, - tokenArrayEnd, - tokenString, - tokenNumber, - tokenTrue, - tokenFalse, - tokenNull, - tokenArraySeparator, - tokenMemberSeparator, - tokenComment, - tokenError - }; - - class Token - { - public: - TokenType type_; - Location start_; - Location end_; - }; - - class ErrorInfo - { - public: - Token token_; - std::string message_; - Location extra_; - }; - - typedef std::deque Errors; - - bool expectToken( TokenType type, Token &token, const char *message ); - bool readToken( Token &token ); - void skipSpaces(); - bool match( Location pattern, - int patternLength ); - bool readComment(); - bool readCStyleComment(); - bool readCppStyleComment(); - bool readString(); - void readNumber(); - bool readValue(); - bool readObject( Token &token ); - bool readArray( Token &token ); - bool decodeNumber( Token &token ); - bool decodeString( Token &token ); - bool decodeString( Token &token, std::string &decoded ); - bool decodeDouble( Token &token ); - bool decodeUnicodeCodePoint( Token &token, - Location ¤t, - Location end, - unsigned int &unicode ); - bool decodeUnicodeEscapeSequence( Token &token, - Location ¤t, - Location end, - unsigned int &unicode ); - bool addError( const std::string &message, - Token &token, - Location extra = 0 ); - bool recoverFromError( TokenType skipUntilToken ); - bool addErrorAndRecover( const std::string &message, - Token &token, - TokenType skipUntilToken ); - void skipUntilSpace(); - Value ¤tValue(); - Char getNextChar(); - void getLocationLineAndColumn( Location location, - int &line, - int &column ) const; - std::string getLocationLineAndColumn( Location location ) const; - void addComment( Location begin, - Location end, - CommentPlacement placement ); - void skipCommentTokens( Token &token ); - - typedef std::stack Nodes; - Nodes nodes_; - Errors errors_; - std::string document_; - Location begin_; - Location end_; - Location current_; - Location lastValueEnd_; - Value *lastValue_; - std::string commentsBefore_; - Features features_; - bool collectComments_; - }; - - /** \brief Read from 'sin' into 'root'. - - Always keep comments from the input JSON. - - This can be used to read a file into a particular sub-object. - For example: - \code - Json::Value root; - cin >> root["dir"]["file"]; - cout << root; - \endcode - Result: - \verbatim - { - "dir": { - "file": { - // The input stream JSON would be nested here. - } - } - } - \endverbatim - \throw std::exception on parse error. - \see Json::operator<<() - */ - std::istream& operator>>( std::istream&, Value& ); - -} // namespace Json - -#endif // CPPTL_JSON_READER_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/reader.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/writer.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSON_WRITER_H_INCLUDED -# define JSON_WRITER_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -# include "value.h" -#endif // if !defined(JSON_IS_AMALGAMATION) -# include -# include -# include - -namespace Json { - - class Value; - - /** \brief Abstract class for writers. - */ - class JSON_API Writer - { - public: - virtual ~Writer(); - - virtual std::string write( const Value &root ) = 0; - }; - - /** \brief Outputs a Value in JSON format without formatting (not human friendly). - * - * The JSON document is written in a single line. It is not intended for 'human' consumption, - * but may be usefull to support feature such as RPC where bandwith is limited. - * \sa Reader, Value - */ - class JSON_API FastWriter : public Writer - { - public: - FastWriter(); - virtual ~FastWriter(){} - - void enableYAMLCompatibility(); - - public: // overridden from Writer - virtual std::string write( const Value &root ); - - private: - void writeValue( const Value &value ); - - std::string document_; - bool yamlCompatiblityEnabled_; - }; - - /** \brief Writes a Value in JSON format in a human friendly way. - * - * The rules for line break and indent are as follow: - * - Object value: - * - if empty then print {} without indent and line break - * - if not empty the print '{', line break & indent, print one value per line - * and then unindent and line break and print '}'. - * - Array value: - * - if empty then print [] without indent and line break - * - if the array contains no object value, empty array or some other value types, - * and all the values fit on one lines, then print the array on a single line. - * - otherwise, it the values do not fit on one line, or the array contains - * object or non empty array, then print one value per line. - * - * If the Value have comments then they are outputed according to their #CommentPlacement. - * - * \sa Reader, Value, Value::setComment() - */ - class JSON_API StyledWriter: public Writer - { - public: - StyledWriter(); - virtual ~StyledWriter(){} - - public: // overridden from Writer - /** \brief Serialize a Value in JSON format. - * \param root Value to serialize. - * \return String containing the JSON document that represents the root value. - */ - virtual std::string write( const Value &root ); - - private: - void writeValue( const Value &value ); - void writeArrayValue( const Value &value ); - bool isMultineArray( const Value &value ); - void pushValue( const std::string &value ); - void writeIndent(); - void writeWithIndent( const std::string &value ); - void indent(); - void unindent(); - void writeCommentBeforeValue( const Value &root ); - void writeCommentAfterValueOnSameLine( const Value &root ); - bool hasCommentForValue( const Value &value ); - static std::string normalizeEOL( const std::string &text ); - - typedef std::vector ChildValues; - - ChildValues childValues_; - std::string document_; - std::string indentString_; - int rightMargin_; - int indentSize_; - bool addChildValues_; - }; - - /** \brief Writes a Value in JSON format in a human friendly way, - to a stream rather than to a string. - * - * The rules for line break and indent are as follow: - * - Object value: - * - if empty then print {} without indent and line break - * - if not empty the print '{', line break & indent, print one value per line - * and then unindent and line break and print '}'. - * - Array value: - * - if empty then print [] without indent and line break - * - if the array contains no object value, empty array or some other value types, - * and all the values fit on one lines, then print the array on a single line. - * - otherwise, it the values do not fit on one line, or the array contains - * object or non empty array, then print one value per line. - * - * If the Value have comments then they are outputed according to their #CommentPlacement. - * - * \param indentation Each level will be indented by this amount extra. - * \sa Reader, Value, Value::setComment() - */ - class JSON_API StyledStreamWriter - { - public: - StyledStreamWriter( std::string indentation="\t" ); - ~StyledStreamWriter(){} - - public: - /** \brief Serialize a Value in JSON format. - * \param out Stream to write to. (Can be ostringstream, e.g.) - * \param root Value to serialize. - * \note There is no point in deriving from Writer, since write() should not return a value. - */ - void write( std::ostream &out, const Value &root ); - - private: - void writeValue( const Value &value ); - void writeArrayValue( const Value &value ); - bool isMultineArray( const Value &value ); - void pushValue( const std::string &value ); - void writeIndent(); - void writeWithIndent( const std::string &value ); - void indent(); - void unindent(); - void writeCommentBeforeValue( const Value &root ); - void writeCommentAfterValueOnSameLine( const Value &root ); - bool hasCommentForValue( const Value &value ); - static std::string normalizeEOL( const std::string &text ); - - typedef std::vector ChildValues; - - ChildValues childValues_; - std::ostream* document_; - std::string indentString_; - int rightMargin_; - std::string indentation_; - bool addChildValues_; - }; - -# if defined(JSON_HAS_INT64) - std::string JSON_API valueToString( Int value ); - std::string JSON_API valueToString( UInt value ); -# endif // if defined(JSON_HAS_INT64) - std::string JSON_API valueToString( LargestInt value ); - std::string JSON_API valueToString( LargestUInt value ); - std::string JSON_API valueToString( double value ); - std::string JSON_API valueToString( bool value ); - std::string JSON_API valueToQuotedString( const char *value ); - - /// \brief Output using the StyledStreamWriter. - /// \see Json::operator>>() - std::ostream& operator<<( std::ostream&, const Value &root ); - -} // namespace Json - - - -#endif // JSON_WRITER_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/writer.h -// ////////////////////////////////////////////////////////////////////// - - - - - -#endif //ifndef JSON_AMALGATED_H_INCLUDED diff --git a/ui/webserver/jsoncpp.cpp b/ui/webserver/jsoncpp.cpp deleted file mode 100644 index 0cc124401f9ba..0000000000000 --- a/ui/webserver/jsoncpp.cpp +++ /dev/null @@ -1,4230 +0,0 @@ -/// Json-cpp amalgated source (http://jsoncpp.sourceforge.net/). -/// It is intented to be used with #include - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: LICENSE -// ////////////////////////////////////////////////////////////////////// - -/* -The JsonCpp library's source code, including accompanying documentation, -tests and demonstration applications, are licensed under the following -conditions... - -The author (Baptiste Lepilleur) explicitly disclaims copyright in all -jurisdictions which recognize such a disclaimer. In such jurisdictions, -this software is released into the Public Domain. - -In jurisdictions which do not recognize Public Domain property (e.g. Germany as of -2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is -released under the terms of the MIT License (see below). - -In jurisdictions which recognize Public Domain property, the user of this -software may choose to accept it either as 1) Public Domain, 2) under the -conditions of the MIT License (see below), or 3) under the terms of dual -Public Domain/MIT License conditions described here, as they choose. - -The MIT License is about as close to Public Domain as a license can get, and is -described in clear, concise terms at: - - http://en.wikipedia.org/wiki/MIT_License - -The full text of the MIT License follows: - -======================================================================== -Copyright (c) 2007-2010 Baptiste Lepilleur - -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. -======================================================================== -(END LICENSE TEXT) - -The MIT license is compatible with both the GPL and commercial -software, affording one all of the rights of Public Domain with the -minor nuisance of being required to keep the above copyright notice -and license text in the source code. Note also that by accepting the -Public Domain "license" you can re-license your copy using whatever -license you like. - -*/ - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: LICENSE -// ////////////////////////////////////////////////////////////////////// - - - - - - -#include "json.h" - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: src/lib_json/json_tool.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED -# define LIB_JSONCPP_JSON_TOOL_H_INCLUDED - -/* This header provides common string manipulation support, such as UTF-8, - * portable conversion from/to string... - * - * It is an internal header that must not be exposed. - */ - -namespace Json { - -/// Converts a unicode code-point to UTF-8. -static inline std::string -codePointToUTF8(unsigned int cp) -{ - std::string result; - - // based on description from http://en.wikipedia.org/wiki/UTF-8 - - if (cp <= 0x7f) - { - result.resize(1); - result[0] = static_cast(cp); - } - else if (cp <= 0x7FF) - { - result.resize(2); - result[1] = static_cast(0x80 | (0x3f & cp)); - result[0] = static_cast(0xC0 | (0x1f & (cp >> 6))); - } - else if (cp <= 0xFFFF) - { - result.resize(3); - result[2] = static_cast(0x80 | (0x3f & cp)); - result[1] = 0x80 | static_cast((0x3f & (cp >> 6))); - result[0] = 0xE0 | static_cast((0xf & (cp >> 12))); - } - else if (cp <= 0x10FFFF) - { - result.resize(4); - result[3] = static_cast(0x80 | (0x3f & cp)); - result[2] = static_cast(0x80 | (0x3f & (cp >> 6))); - result[1] = static_cast(0x80 | (0x3f & (cp >> 12))); - result[0] = static_cast(0xF0 | (0x7 & (cp >> 18))); - } - - return result; -} - - -/// Returns true if ch is a control character (in range [0,32[). -static inline bool -isControlCharacter(char ch) -{ - return ch > 0 && ch <= 0x1F; -} - - -enum { - /// Constant that specify the size of the buffer that must be passed to uintToString. - uintToStringBufferSize = 3*sizeof(LargestUInt)+1 -}; - -// Defines a char buffer for use with uintToString(). -typedef char UIntToStringBuffer[uintToStringBufferSize]; - - -/** Converts an unsigned integer to string. - * @param value Unsigned interger to convert to string - * @param current Input/Output string buffer. - * Must have at least uintToStringBufferSize chars free. - */ -static inline void -uintToString( LargestUInt value, - char *¤t ) -{ - *--current = 0; - do - { - *--current = char(value % 10) + '0'; - value /= 10; - } - while ( value != 0 ); -} - -} // namespace Json { - -#endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: src/lib_json/json_tool.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: src/lib_json/json_reader.cpp -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#if !defined(JSON_IS_AMALGAMATION) -# include -# include -# include "json_tool.h" -#endif // if !defined(JSON_IS_AMALGAMATION) -#include -#include -#include -#include -#include -#include - -#if _MSC_VER >= 1400 // VC++ 8.0 -#pragma warning( disable : 4996 ) // disable warning about strdup being deprecated. -#endif - -namespace Json { - -// Implementation of class Features -// //////////////////////////////// - -Features::Features() - : allowComments_( true ) - , strictRoot_( false ) -{ -} - - -Features -Features::all() -{ - return Features(); -} - - -Features -Features::strictMode() -{ - Features features; - features.allowComments_ = false; - features.strictRoot_ = true; - return features; -} - -// Implementation of class Reader -// //////////////////////////////// - - -static inline bool -in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4 ) -{ - return c == c1 || c == c2 || c == c3 || c == c4; -} - -static inline bool -in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4, Reader::Char c5 ) -{ - return c == c1 || c == c2 || c == c3 || c == c4 || c == c5; -} - - -static bool -containsNewLine( Reader::Location begin, - Reader::Location end ) -{ - for ( ;begin < end; ++begin ) - if ( *begin == '\n' || *begin == '\r' ) - return true; - return false; -} - - -// Class Reader -// ////////////////////////////////////////////////////////////////// - -Reader::Reader() - : features_( Features::all() ) -{ -} - - -Reader::Reader( const Features &features ) - : features_( features ) -{ -} - - -bool -Reader::parse( const std::string &document, - Value &root, - bool collectComments ) -{ - document_ = document; - const char *begin = document_.c_str(); - const char *end = begin + document_.length(); - return parse( begin, end, root, collectComments ); -} - - -bool -Reader::parse( std::istream& sin, - Value &root, - bool collectComments ) -{ - //std::istream_iterator begin(sin); - //std::istream_iterator end; - // Those would allow streamed input from a file, if parse() were a - // template function. - - // Since std::string is reference-counted, this at least does not - // create an extra copy. - std::string doc; - std::getline(sin, doc, (char)EOF); - return parse( doc, root, collectComments ); -} - -bool -Reader::parse( const char *beginDoc, const char *endDoc, - Value &root, - bool collectComments ) -{ - if ( !features_.allowComments_ ) - { - collectComments = false; - } - - begin_ = beginDoc; - end_ = endDoc; - collectComments_ = collectComments; - current_ = begin_; - lastValueEnd_ = 0; - lastValue_ = 0; - commentsBefore_ = ""; - errors_.clear(); - while ( !nodes_.empty() ) - nodes_.pop(); - nodes_.push( &root ); - - bool successful = readValue(); - Token token; - skipCommentTokens( token ); - if ( collectComments_ && !commentsBefore_.empty() ) - root.setComment( commentsBefore_, commentAfter ); - if ( features_.strictRoot_ ) - { - if ( !root.isArray() && !root.isObject() ) - { - // Set error location to start of doc, ideally should be first token found in doc - token.type_ = tokenError; - token.start_ = beginDoc; - token.end_ = endDoc; - addError( "A valid JSON document must be either an array or an object value.", - token ); - return false; - } - } - return successful; -} - - -bool -Reader::readValue() -{ - Token token; - skipCommentTokens( token ); - bool successful = true; - - if ( collectComments_ && !commentsBefore_.empty() ) - { - currentValue().setComment( commentsBefore_, commentBefore ); - commentsBefore_ = ""; - } - - - switch ( token.type_ ) - { - case tokenObjectBegin: - successful = readObject( token ); - break; - case tokenArrayBegin: - successful = readArray( token ); - break; - case tokenNumber: - successful = decodeNumber( token ); - break; - case tokenString: - successful = decodeString( token ); - break; - case tokenTrue: - currentValue() = true; - break; - case tokenFalse: - currentValue() = false; - break; - case tokenNull: - currentValue() = Value(); - break; - default: - return addError( "Syntax error: value, object or array expected.", token ); - } - - if ( collectComments_ ) - { - lastValueEnd_ = current_; - lastValue_ = ¤tValue(); - } - - return successful; -} - - -void -Reader::skipCommentTokens( Token &token ) -{ - if ( features_.allowComments_ ) - { - do - { - readToken( token ); - } - while ( token.type_ == tokenComment ); - } - else - { - readToken( token ); - } -} - - -bool -Reader::expectToken( TokenType type, Token &token, const char *message ) -{ - readToken( token ); - if ( token.type_ != type ) - return addError( message, token ); - return true; -} - - -bool -Reader::readToken( Token &token ) -{ - skipSpaces(); - token.start_ = current_; - Char c = getNextChar(); - bool ok = true; - switch ( c ) - { - case '{': - token.type_ = tokenObjectBegin; - break; - case '}': - token.type_ = tokenObjectEnd; - break; - case '[': - token.type_ = tokenArrayBegin; - break; - case ']': - token.type_ = tokenArrayEnd; - break; - case '"': - token.type_ = tokenString; - ok = readString(); - break; - case '/': - token.type_ = tokenComment; - ok = readComment(); - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '-': - token.type_ = tokenNumber; - readNumber(); - break; - case 't': - token.type_ = tokenTrue; - ok = match( "rue", 3 ); - break; - case 'f': - token.type_ = tokenFalse; - ok = match( "alse", 4 ); - break; - case 'n': - token.type_ = tokenNull; - ok = match( "ull", 3 ); - break; - case ',': - token.type_ = tokenArraySeparator; - break; - case ':': - token.type_ = tokenMemberSeparator; - break; - case 0: - token.type_ = tokenEndOfStream; - break; - default: - ok = false; - break; - } - if ( !ok ) - token.type_ = tokenError; - token.end_ = current_; - return true; -} - - -void -Reader::skipSpaces() -{ - while ( current_ != end_ ) - { - Char c = *current_; - if ( c == ' ' || c == '\t' || c == '\r' || c == '\n' ) - ++current_; - else - break; - } -} - - -bool -Reader::match( Location pattern, - int patternLength ) -{ - if ( end_ - current_ < patternLength ) - return false; - int index = patternLength; - while ( index-- ) - if ( current_[index] != pattern[index] ) - return false; - current_ += patternLength; - return true; -} - - -bool -Reader::readComment() -{ - Location commentBegin = current_ - 1; - Char c = getNextChar(); - bool successful = false; - if ( c == '*' ) - successful = readCStyleComment(); - else if ( c == '/' ) - successful = readCppStyleComment(); - if ( !successful ) - return false; - - if ( collectComments_ ) - { - CommentPlacement placement = commentBefore; - if ( lastValueEnd_ && !containsNewLine( lastValueEnd_, commentBegin ) ) - { - if ( c != '*' || !containsNewLine( commentBegin, current_ ) ) - placement = commentAfterOnSameLine; - } - - addComment( commentBegin, current_, placement ); - } - return true; -} - - -void -Reader::addComment( Location begin, - Location end, - CommentPlacement placement ) -{ - assert( collectComments_ ); - if ( placement == commentAfterOnSameLine ) - { - assert( lastValue_ != 0 ); - lastValue_->setComment( std::string( begin, end ), placement ); - } - else - { - if ( !commentsBefore_.empty() ) - commentsBefore_ += "\n"; - commentsBefore_ += std::string( begin, end ); - } -} - - -bool -Reader::readCStyleComment() -{ - while ( current_ != end_ ) - { - Char c = getNextChar(); - if ( c == '*' && *current_ == '/' ) - break; - } - return getNextChar() == '/'; -} - - -bool -Reader::readCppStyleComment() -{ - while ( current_ != end_ ) - { - Char c = getNextChar(); - if ( c == '\r' || c == '\n' ) - break; - } - return true; -} - - -void -Reader::readNumber() -{ - while ( current_ != end_ ) - { - if ( !(*current_ >= '0' && *current_ <= '9') && - !in( *current_, '.', 'e', 'E', '+', '-' ) ) - break; - ++current_; - } -} - -bool -Reader::readString() -{ - Char c = 0; - while ( current_ != end_ ) - { - c = getNextChar(); - if ( c == '\\' ) - getNextChar(); - else if ( c == '"' ) - break; - } - return c == '"'; -} - - -bool -Reader::readObject( Token &/*tokenStart*/ ) -{ - Token tokenName; - std::string name; - currentValue() = Value( objectValue ); - while ( readToken( tokenName ) ) - { - bool initialTokenOk = true; - while ( tokenName.type_ == tokenComment && initialTokenOk ) - initialTokenOk = readToken( tokenName ); - if ( !initialTokenOk ) - break; - if ( tokenName.type_ == tokenObjectEnd && name.empty() ) // empty object - return true; - if ( tokenName.type_ != tokenString ) - break; - - name = ""; - if ( !decodeString( tokenName, name ) ) - return recoverFromError( tokenObjectEnd ); - - Token colon; - if ( !readToken( colon ) || colon.type_ != tokenMemberSeparator ) - { - return addErrorAndRecover( "Missing ':' after object member name", - colon, - tokenObjectEnd ); - } - Value &value = currentValue()[ name ]; - nodes_.push( &value ); - bool ok = readValue(); - nodes_.pop(); - if ( !ok ) // error already set - return recoverFromError( tokenObjectEnd ); - - Token comma; - if ( !readToken( comma ) - || ( comma.type_ != tokenObjectEnd && - comma.type_ != tokenArraySeparator && - comma.type_ != tokenComment ) ) - { - return addErrorAndRecover( "Missing ',' or '}' in object declaration", - comma, - tokenObjectEnd ); - } - bool finalizeTokenOk = true; - while ( comma.type_ == tokenComment && - finalizeTokenOk ) - finalizeTokenOk = readToken( comma ); - if ( comma.type_ == tokenObjectEnd ) - return true; - } - return addErrorAndRecover( "Missing '}' or object member name", - tokenName, - tokenObjectEnd ); -} - - -bool -Reader::readArray( Token &/*tokenStart*/ ) -{ - currentValue() = Value( arrayValue ); - skipSpaces(); - if ( *current_ == ']' ) // empty array - { - Token endArray; - readToken( endArray ); - return true; - } - int index = 0; - for (;;) - { - Value &value = currentValue()[ index++ ]; - nodes_.push( &value ); - bool ok = readValue(); - nodes_.pop(); - if ( !ok ) // error already set - return recoverFromError( tokenArrayEnd ); - - Token token; - // Accept Comment after last item in the array. - ok = readToken( token ); - while ( token.type_ == tokenComment && ok ) - { - ok = readToken( token ); - } - bool badTokenType = ( token.type_ != tokenArraySeparator && - token.type_ != tokenArrayEnd ); - if ( !ok || badTokenType ) - { - return addErrorAndRecover( "Missing ',' or ']' in array declaration", - token, - tokenArrayEnd ); - } - if ( token.type_ == tokenArrayEnd ) - break; - } - return true; -} - - -bool -Reader::decodeNumber( Token &token ) -{ - bool isDouble = false; - for ( Location inspect = token.start_; inspect != token.end_; ++inspect ) - { - isDouble = isDouble - || in( *inspect, '.', 'e', 'E', '+' ) - || ( *inspect == '-' && inspect != token.start_ ); - } - if ( isDouble ) - return decodeDouble( token ); - // Attempts to parse the number as an integer. If the number is - // larger than the maximum supported value of an integer then - // we decode the number as a double. - Location current = token.start_; - bool isNegative = *current == '-'; - if ( isNegative ) - ++current; - Value::LargestUInt maxIntegerValue = isNegative ? Value::LargestUInt(-Value::minLargestInt) - : Value::maxLargestUInt; - Value::LargestUInt threshold = maxIntegerValue / 10; - Value::UInt lastDigitThreshold = Value::UInt( maxIntegerValue % 10 ); - assert( lastDigitThreshold >=0 && lastDigitThreshold <= 9 ); - Value::LargestUInt value = 0; - while ( current < token.end_ ) - { - Char c = *current++; - if ( c < '0' || c > '9' ) - return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token ); - Value::UInt digit(c - '0'); - if ( value >= threshold ) - { - // If the current digit is not the last one, or if it is - // greater than the last digit of the maximum integer value, - // the parse the number as a double. - if ( current != token.end_ || digit > lastDigitThreshold ) - { - return decodeDouble( token ); - } - } - value = value * 10 + digit; - } - if ( isNegative ) - currentValue() = -Value::LargestInt( value ); - else if ( value <= Value::LargestUInt(Value::maxInt) ) - currentValue() = Value::LargestInt( value ); - else - currentValue() = value; - return true; -} - - -bool -Reader::decodeDouble( Token &token ) -{ - double value = 0; - const int bufferSize = 32; - int count; - int length = int(token.end_ - token.start_); - if ( length <= bufferSize ) - { - Char buffer[bufferSize+1]; - memcpy( buffer, token.start_, length ); - buffer[length] = 0; - count = sscanf( buffer, "%lf", &value ); - } - else - { - std::string buffer( token.start_, token.end_ ); - count = sscanf( buffer.c_str(), "%lf", &value ); - } - - if ( count != 1 ) - return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token ); - currentValue() = value; - return true; -} - - -bool -Reader::decodeString( Token &token ) -{ - std::string decoded; - if ( !decodeString( token, decoded ) ) - return false; - currentValue() = decoded; - return true; -} - - -bool -Reader::decodeString( Token &token, std::string &decoded ) -{ - decoded.reserve( token.end_ - token.start_ - 2 ); - Location current = token.start_ + 1; // skip '"' - Location end = token.end_ - 1; // do not include '"' - while ( current != end ) - { - Char c = *current++; - if ( c == '"' ) - break; - else if ( c == '\\' ) - { - if ( current == end ) - return addError( "Empty escape sequence in string", token, current ); - Char escape = *current++; - switch ( escape ) - { - case '"': decoded += '"'; break; - case '/': decoded += '/'; break; - case '\\': decoded += '\\'; break; - case 'b': decoded += '\b'; break; - case 'f': decoded += '\f'; break; - case 'n': decoded += '\n'; break; - case 'r': decoded += '\r'; break; - case 't': decoded += '\t'; break; - case 'u': - { - unsigned int unicode; - if ( !decodeUnicodeCodePoint( token, current, end, unicode ) ) - return false; - decoded += codePointToUTF8(unicode); - } - break; - default: - return addError( "Bad escape sequence in string", token, current ); - } - } - else - { - decoded += c; - } - } - return true; -} - -bool -Reader::decodeUnicodeCodePoint( Token &token, - Location ¤t, - Location end, - unsigned int &unicode ) -{ - - if ( !decodeUnicodeEscapeSequence( token, current, end, unicode ) ) - return false; - if (unicode >= 0xD800 && unicode <= 0xDBFF) - { - // surrogate pairs - if (end - current < 6) - return addError( "additional six characters expected to parse unicode surrogate pair.", token, current ); - unsigned int surrogatePair; - if (*(current++) == '\\' && *(current++)== 'u') - { - if (decodeUnicodeEscapeSequence( token, current, end, surrogatePair )) - { - unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); - } - else - return false; - } - else - return addError( "expecting another \\u token to begin the second half of a unicode surrogate pair", token, current ); - } - return true; -} - -bool -Reader::decodeUnicodeEscapeSequence( Token &token, - Location ¤t, - Location end, - unsigned int &unicode ) -{ - if ( end - current < 4 ) - return addError( "Bad unicode escape sequence in string: four digits expected.", token, current ); - unicode = 0; - for ( int index =0; index < 4; ++index ) - { - Char c = *current++; - unicode *= 16; - if ( c >= '0' && c <= '9' ) - unicode += c - '0'; - else if ( c >= 'a' && c <= 'f' ) - unicode += c - 'a' + 10; - else if ( c >= 'A' && c <= 'F' ) - unicode += c - 'A' + 10; - else - return addError( "Bad unicode escape sequence in string: hexadecimal digit expected.", token, current ); - } - return true; -} - - -bool -Reader::addError( const std::string &message, - Token &token, - Location extra ) -{ - ErrorInfo info; - info.token_ = token; - info.message_ = message; - info.extra_ = extra; - errors_.push_back( info ); - return false; -} - - -bool -Reader::recoverFromError( TokenType skipUntilToken ) -{ - int errorCount = int(errors_.size()); - Token skip; - for (;;) - { - if ( !readToken(skip) ) - errors_.resize( errorCount ); // discard errors caused by recovery - if ( skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream ) - break; - } - errors_.resize( errorCount ); - return false; -} - - -bool -Reader::addErrorAndRecover( const std::string &message, - Token &token, - TokenType skipUntilToken ) -{ - addError( message, token ); - return recoverFromError( skipUntilToken ); -} - - -Value & -Reader::currentValue() -{ - return *(nodes_.top()); -} - - -Reader::Char -Reader::getNextChar() -{ - if ( current_ == end_ ) - return 0; - return *current_++; -} - - -void -Reader::getLocationLineAndColumn( Location location, - int &line, - int &column ) const -{ - Location current = begin_; - Location lastLineStart = current; - line = 0; - while ( current < location && current != end_ ) - { - Char c = *current++; - if ( c == '\r' ) - { - if ( *current == '\n' ) - ++current; - lastLineStart = current; - ++line; - } - else if ( c == '\n' ) - { - lastLineStart = current; - ++line; - } - } - // column & line start at 1 - column = int(location - lastLineStart) + 1; - ++line; -} - - -std::string -Reader::getLocationLineAndColumn( Location location ) const -{ - int line, column; - getLocationLineAndColumn( location, line, column ); - char buffer[18+16+16+1]; - sprintf( buffer, "Line %d, Column %d", line, column ); - return buffer; -} - - -// Deprecated. Preserved for backward compatibility -std::string -Reader::getFormatedErrorMessages() const -{ - return getFormattedErrorMessages(); -} - - -std::string -Reader::getFormattedErrorMessages() const -{ - std::string formattedMessage; - for ( Errors::const_iterator itError = errors_.begin(); - itError != errors_.end(); - ++itError ) - { - const ErrorInfo &error = *itError; - formattedMessage += "* " + getLocationLineAndColumn( error.token_.start_ ) + "\n"; - formattedMessage += " " + error.message_ + "\n"; - if ( error.extra_ ) - formattedMessage += "See " + getLocationLineAndColumn( error.extra_ ) + " for detail.\n"; - } - return formattedMessage; -} - - -std::istream& operator>>( std::istream &sin, Value &root ) -{ - Json::Reader reader; - bool ok = reader.parse(sin, root, true); - //JSON_ASSERT( ok ); - if (!ok) throw std::runtime_error(reader.getFormattedErrorMessages()); - return sin; -} - - -} // namespace Json - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: src/lib_json/json_reader.cpp -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: src/lib_json/json_batchallocator.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED -# define JSONCPP_BATCHALLOCATOR_H_INCLUDED - -# include -# include - -# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - -namespace Json { - -/* Fast memory allocator. - * - * This memory allocator allocates memory for a batch of object (specified by - * the page size, the number of object in each page). - * - * It does not allow the destruction of a single object. All the allocated objects - * can be destroyed at once. The memory can be either released or reused for future - * allocation. - * - * The in-place new operator must be used to construct the object using the pointer - * returned by allocate. - */ -template -class BatchAllocator -{ -public: - typedef AllocatedType Type; - - BatchAllocator( unsigned int objectsPerPage = 255 ) - : freeHead_( 0 ) - , objectsPerPage_( objectsPerPage ) - { -// printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() ); - assert( sizeof(AllocatedType) * objectPerAllocation >= sizeof(AllocatedType *) ); // We must be able to store a slist in the object free space. - assert( objectsPerPage >= 16 ); - batches_ = allocateBatch( 0 ); // allocated a dummy page - currentBatch_ = batches_; - } - - ~BatchAllocator() - { - for ( BatchInfo *batch = batches_; batch; ) - { - BatchInfo *nextBatch = batch->next_; - free( batch ); - batch = nextBatch; - } - } - - /// allocate space for an array of objectPerAllocation object. - /// @warning it is the responsability of the caller to call objects constructors. - AllocatedType *allocate() - { - if ( freeHead_ ) // returns node from free list. - { - AllocatedType *object = freeHead_; - freeHead_ = *(AllocatedType **)object; - return object; - } - if ( currentBatch_->used_ == currentBatch_->end_ ) - { - currentBatch_ = currentBatch_->next_; - while ( currentBatch_ && currentBatch_->used_ == currentBatch_->end_ ) - currentBatch_ = currentBatch_->next_; - - if ( !currentBatch_ ) // no free batch found, allocate a new one - { - currentBatch_ = allocateBatch( objectsPerPage_ ); - currentBatch_->next_ = batches_; // insert at the head of the list - batches_ = currentBatch_; - } - } - AllocatedType *allocated = currentBatch_->used_; - currentBatch_->used_ += objectPerAllocation; - return allocated; - } - - /// Release the object. - /// @warning it is the responsability of the caller to actually destruct the object. - void release( AllocatedType *object ) - { - assert( object != 0 ); - *(AllocatedType **)object = freeHead_; - freeHead_ = object; - } - -private: - struct BatchInfo - { - BatchInfo *next_; - AllocatedType *used_; - AllocatedType *end_; - AllocatedType buffer_[objectPerAllocation]; - }; - - // disabled copy constructor and assignement operator. - BatchAllocator( const BatchAllocator & ); - void operator =( const BatchAllocator &); - - static BatchInfo *allocateBatch( unsigned int objectsPerPage ) - { - const unsigned int mallocSize = sizeof(BatchInfo) - sizeof(AllocatedType)* objectPerAllocation - + sizeof(AllocatedType) * objectPerAllocation * objectsPerPage; - BatchInfo *batch = static_cast( malloc( mallocSize ) ); - batch->next_ = 0; - batch->used_ = batch->buffer_; - batch->end_ = batch->buffer_ + objectsPerPage; - return batch; - } - - BatchInfo *batches_; - BatchInfo *currentBatch_; - /// Head of a single linked list within the allocated space of freeed object - AllocatedType *freeHead_; - unsigned int objectsPerPage_; -}; - - -} // namespace Json - -# endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION - -#endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED - - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: src/lib_json/json_batchallocator.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: src/lib_json/json_valueiterator.inl -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -// included by json_value.cpp - -namespace Json { - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class ValueIteratorBase -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -ValueIteratorBase::ValueIteratorBase() -#ifndef JSON_VALUE_USE_INTERNAL_MAP - : current_() - , isNull_( true ) -{ -} -#else - : isArray_( true ) - , isNull_( true ) -{ - iterator_.array_ = ValueInternalArray::IteratorState(); -} -#endif - - -#ifndef JSON_VALUE_USE_INTERNAL_MAP -ValueIteratorBase::ValueIteratorBase( const Value::ObjectValues::iterator ¤t ) - : current_( current ) - , isNull_( false ) -{ -} -#else -ValueIteratorBase::ValueIteratorBase( const ValueInternalArray::IteratorState &state ) - : isArray_( true ) -{ - iterator_.array_ = state; -} - - -ValueIteratorBase::ValueIteratorBase( const ValueInternalMap::IteratorState &state ) - : isArray_( false ) -{ - iterator_.map_ = state; -} -#endif - -Value & -ValueIteratorBase::deref() const -{ -#ifndef JSON_VALUE_USE_INTERNAL_MAP - return current_->second; -#else - if ( isArray_ ) - return ValueInternalArray::dereference( iterator_.array_ ); - return ValueInternalMap::value( iterator_.map_ ); -#endif -} - - -void -ValueIteratorBase::increment() -{ -#ifndef JSON_VALUE_USE_INTERNAL_MAP - ++current_; -#else - if ( isArray_ ) - ValueInternalArray::increment( iterator_.array_ ); - ValueInternalMap::increment( iterator_.map_ ); -#endif -} - - -void -ValueIteratorBase::decrement() -{ -#ifndef JSON_VALUE_USE_INTERNAL_MAP - --current_; -#else - if ( isArray_ ) - ValueInternalArray::decrement( iterator_.array_ ); - ValueInternalMap::decrement( iterator_.map_ ); -#endif -} - - -ValueIteratorBase::difference_type -ValueIteratorBase::computeDistance( const SelfType &other ) const -{ -#ifndef JSON_VALUE_USE_INTERNAL_MAP -# ifdef JSON_USE_CPPTL_SMALLMAP - return current_ - other.current_; -# else - // Iterator for null value are initialized using the default - // constructor, which initialize current_ to the default - // std::map::iterator. As begin() and end() are two instance - // of the default std::map::iterator, they can not be compared. - // To allow this, we handle this comparison specifically. - if ( isNull_ && other.isNull_ ) - { - return 0; - } - - - // Usage of std::distance is not portable (does not compile with Sun Studio 12 RogueWave STL, - // which is the one used by default). - // Using a portable hand-made version for non random iterator instead: - // return difference_type( std::distance( current_, other.current_ ) ); - difference_type myDistance = 0; - for ( Value::ObjectValues::iterator it = current_; it != other.current_; ++it ) - { - ++myDistance; - } - return myDistance; -# endif -#else - if ( isArray_ ) - return ValueInternalArray::distance( iterator_.array_, other.iterator_.array_ ); - return ValueInternalMap::distance( iterator_.map_, other.iterator_.map_ ); -#endif -} - - -bool -ValueIteratorBase::isEqual( const SelfType &other ) const -{ -#ifndef JSON_VALUE_USE_INTERNAL_MAP - if ( isNull_ ) - { - return other.isNull_; - } - return current_ == other.current_; -#else - if ( isArray_ ) - return ValueInternalArray::equals( iterator_.array_, other.iterator_.array_ ); - return ValueInternalMap::equals( iterator_.map_, other.iterator_.map_ ); -#endif -} - - -void -ValueIteratorBase::copy( const SelfType &other ) -{ -#ifndef JSON_VALUE_USE_INTERNAL_MAP - current_ = other.current_; -#else - if ( isArray_ ) - iterator_.array_ = other.iterator_.array_; - iterator_.map_ = other.iterator_.map_; -#endif -} - - -Value -ValueIteratorBase::key() const -{ -#ifndef JSON_VALUE_USE_INTERNAL_MAP - const Value::CZString czstring = (*current_).first; - if ( czstring.c_str() ) - { - if ( czstring.isStaticString() ) - return Value( StaticString( czstring.c_str() ) ); - return Value( czstring.c_str() ); - } - return Value( czstring.index() ); -#else - if ( isArray_ ) - return Value( ValueInternalArray::indexOf( iterator_.array_ ) ); - bool isStatic; - const char *memberName = ValueInternalMap::key( iterator_.map_, isStatic ); - if ( isStatic ) - return Value( StaticString( memberName ) ); - return Value( memberName ); -#endif -} - - -UInt -ValueIteratorBase::index() const -{ -#ifndef JSON_VALUE_USE_INTERNAL_MAP - const Value::CZString czstring = (*current_).first; - if ( !czstring.c_str() ) - return czstring.index(); - return Value::UInt( -1 ); -#else - if ( isArray_ ) - return Value::UInt( ValueInternalArray::indexOf( iterator_.array_ ) ); - return Value::UInt( -1 ); -#endif -} - - -const char * -ValueIteratorBase::memberName() const -{ -#ifndef JSON_VALUE_USE_INTERNAL_MAP - const char *name = (*current_).first.c_str(); - return name ? name : ""; -#else - if ( !isArray_ ) - return ValueInternalMap::key( iterator_.map_ ); - return ""; -#endif -} - - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class ValueConstIterator -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -ValueConstIterator::ValueConstIterator() -{ -} - - -#ifndef JSON_VALUE_USE_INTERNAL_MAP -ValueConstIterator::ValueConstIterator( const Value::ObjectValues::iterator ¤t ) - : ValueIteratorBase( current ) -{ -} -#else -ValueConstIterator::ValueConstIterator( const ValueInternalArray::IteratorState &state ) - : ValueIteratorBase( state ) -{ -} - -ValueConstIterator::ValueConstIterator( const ValueInternalMap::IteratorState &state ) - : ValueIteratorBase( state ) -{ -} -#endif - -ValueConstIterator & -ValueConstIterator::operator =( const ValueIteratorBase &other ) -{ - copy( other ); - return *this; -} - - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class ValueIterator -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -ValueIterator::ValueIterator() -{ -} - - -#ifndef JSON_VALUE_USE_INTERNAL_MAP -ValueIterator::ValueIterator( const Value::ObjectValues::iterator ¤t ) - : ValueIteratorBase( current ) -{ -} -#else -ValueIterator::ValueIterator( const ValueInternalArray::IteratorState &state ) - : ValueIteratorBase( state ) -{ -} - -ValueIterator::ValueIterator( const ValueInternalMap::IteratorState &state ) - : ValueIteratorBase( state ) -{ -} -#endif - -ValueIterator::ValueIterator( const ValueConstIterator &other ) - : ValueIteratorBase( other ) -{ -} - -ValueIterator::ValueIterator( const ValueIterator &other ) - : ValueIteratorBase( other ) -{ -} - -ValueIterator & -ValueIterator::operator =( const SelfType &other ) -{ - copy( other ); - return *this; -} - -} // namespace Json - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: src/lib_json/json_valueiterator.inl -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: src/lib_json/json_value.cpp -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#if !defined(JSON_IS_AMALGAMATION) -# include -# include -# ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR -# include "json_batchallocator.h" -# endif // #ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR -#endif // if !defined(JSON_IS_AMALGAMATION) -#include -#include -#include -#include -#include -#ifdef JSON_USE_CPPTL -# include -#endif -#include // size_t - -#define JSON_ASSERT_UNREACHABLE assert( false ) -#define JSON_ASSERT( condition ) assert( condition ); // @todo <= change this into an exception throw -#define JSON_FAIL_MESSAGE( message ) throw std::runtime_error( message ); -#define JSON_ASSERT_MESSAGE( condition, message ) if (!( condition )) JSON_FAIL_MESSAGE( message ) - -namespace Json { - -const Value Value::null; -const Int Value::minInt = Int( ~(UInt(-1)/2) ); -const Int Value::maxInt = Int( UInt(-1)/2 ); -const UInt Value::maxUInt = UInt(-1); -const Int64 Value::minInt64 = Int64( ~(UInt64(-1)/2) ); -const Int64 Value::maxInt64 = Int64( UInt64(-1)/2 ); -const UInt64 Value::maxUInt64 = UInt64(-1); -const LargestInt Value::minLargestInt = LargestInt( ~(LargestUInt(-1)/2) ); -const LargestInt Value::maxLargestInt = LargestInt( LargestUInt(-1)/2 ); -const LargestUInt Value::maxLargestUInt = LargestUInt(-1); - - -/// Unknown size marker -static const unsigned int unknown = (unsigned)-1; - - -/** Duplicates the specified string value. - * @param value Pointer to the string to duplicate. Must be zero-terminated if - * length is "unknown". - * @param length Length of the value. if equals to unknown, then it will be - * computed using strlen(value). - * @return Pointer on the duplicate instance of string. - */ -static inline char * -duplicateStringValue( const char *value, - unsigned int length = unknown ) -{ - if ( length == unknown ) - length = (unsigned int)strlen(value); - char *newString = static_cast( malloc( length + 1 ) ); - JSON_ASSERT_MESSAGE( newString != 0, "Failed to allocate string value buffer" ); - memcpy( newString, value, length ); - newString[length] = 0; - return newString; -} - - -/** Free the string duplicated by duplicateStringValue(). - */ -static inline void -releaseStringValue( char *value ) -{ - if ( value ) - free( value ); -} - -} // namespace Json - - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ValueInternals... -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -#if !defined(JSON_IS_AMALGAMATION) -# ifdef JSON_VALUE_USE_INTERNAL_MAP -# include "json_internalarray.inl" -# include "json_internalmap.inl" -# endif // JSON_VALUE_USE_INTERNAL_MAP - -# include "json_valueiterator.inl" -#endif // if !defined(JSON_IS_AMALGAMATION) - -namespace Json { - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class Value::CommentInfo -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - - -Value::CommentInfo::CommentInfo() - : comment_( 0 ) -{ -} - -Value::CommentInfo::~CommentInfo() -{ - if ( comment_ ) - releaseStringValue( comment_ ); -} - - -void -Value::CommentInfo::setComment( const char *text ) -{ - if ( comment_ ) - releaseStringValue( comment_ ); - JSON_ASSERT( text != 0 ); - JSON_ASSERT_MESSAGE( text[0]=='\0' || text[0]=='/', "Comments must start with /"); - // It seems that /**/ style comments are acceptable as well. - comment_ = duplicateStringValue( text ); -} - - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class Value::CZString -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -# ifndef JSON_VALUE_USE_INTERNAL_MAP - -// Notes: index_ indicates if the string was allocated when -// a string is stored. - -Value::CZString::CZString( ArrayIndex index ) - : cstr_( 0 ) - , index_( index ) -{ -} - -Value::CZString::CZString( const char *cstr, DuplicationPolicy allocate ) - : cstr_( allocate == duplicate ? duplicateStringValue(cstr) - : cstr ) - , index_( allocate ) -{ -} - -Value::CZString::CZString( const CZString &other ) -: cstr_( other.index_ != noDuplication && other.cstr_ != 0 - ? duplicateStringValue( other.cstr_ ) - : other.cstr_ ) - , index_( other.cstr_ ? (other.index_ == noDuplication ? noDuplication : duplicate) - : other.index_ ) -{ -} - -Value::CZString::~CZString() -{ - if ( cstr_ && index_ == duplicate ) - releaseStringValue( const_cast( cstr_ ) ); -} - -void -Value::CZString::swap( CZString &other ) -{ - std::swap( cstr_, other.cstr_ ); - std::swap( index_, other.index_ ); -} - -Value::CZString & -Value::CZString::operator =( const CZString &other ) -{ - CZString temp( other ); - swap( temp ); - return *this; -} - -bool -Value::CZString::operator<( const CZString &other ) const -{ - if ( cstr_ ) - return strcmp( cstr_, other.cstr_ ) < 0; - return index_ < other.index_; -} - -bool -Value::CZString::operator==( const CZString &other ) const -{ - if ( cstr_ ) - return strcmp( cstr_, other.cstr_ ) == 0; - return index_ == other.index_; -} - - -ArrayIndex -Value::CZString::index() const -{ - return index_; -} - - -const char * -Value::CZString::c_str() const -{ - return cstr_; -} - -bool -Value::CZString::isStaticString() const -{ - return index_ == noDuplication; -} - -#endif // ifndef JSON_VALUE_USE_INTERNAL_MAP - - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class Value::Value -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -/*! \internal Default constructor initialization must be equivalent to: - * memset( this, 0, sizeof(Value) ) - * This optimization is used in ValueInternalMap fast allocator. - */ -Value::Value( ValueType type ) - : type_( type ) - , allocated_( 0 ) - , comments_( 0 ) -# ifdef JSON_VALUE_USE_INTERNAL_MAP - , itemIsUsed_( 0 ) -#endif -{ - switch ( type ) - { - case nullValue: - break; - case intValue: - case uintValue: - value_.int_ = 0; - break; - case realValue: - value_.real_ = 0.0; - break; - case stringValue: - value_.string_ = 0; - break; -#ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - case objectValue: - value_.map_ = new ObjectValues(); - break; -#else - case arrayValue: - value_.array_ = arrayAllocator()->newArray(); - break; - case objectValue: - value_.map_ = mapAllocator()->newMap(); - break; -#endif - case booleanValue: - value_.bool_ = false; - break; - default: - JSON_ASSERT_UNREACHABLE; - } -} - - -#if defined(JSON_HAS_INT64) -Value::Value( UInt value ) - : type_( uintValue ) - , comments_( 0 ) -# ifdef JSON_VALUE_USE_INTERNAL_MAP - , itemIsUsed_( 0 ) -#endif -{ - value_.uint_ = value; -} - -Value::Value( Int value ) - : type_( intValue ) - , comments_( 0 ) -# ifdef JSON_VALUE_USE_INTERNAL_MAP - , itemIsUsed_( 0 ) -#endif -{ - value_.int_ = value; -} - -#endif // if defined(JSON_HAS_INT64) - - -Value::Value( Int64 value ) - : type_( intValue ) - , comments_( 0 ) -# ifdef JSON_VALUE_USE_INTERNAL_MAP - , itemIsUsed_( 0 ) -#endif -{ - value_.int_ = value; -} - - -Value::Value( UInt64 value ) - : type_( uintValue ) - , comments_( 0 ) -# ifdef JSON_VALUE_USE_INTERNAL_MAP - , itemIsUsed_( 0 ) -#endif -{ - value_.uint_ = value; -} - -Value::Value( double value ) - : type_( realValue ) - , comments_( 0 ) -# ifdef JSON_VALUE_USE_INTERNAL_MAP - , itemIsUsed_( 0 ) -#endif -{ - value_.real_ = value; -} - -Value::Value( const char *value ) - : type_( stringValue ) - , allocated_( true ) - , comments_( 0 ) -# ifdef JSON_VALUE_USE_INTERNAL_MAP - , itemIsUsed_( 0 ) -#endif -{ - value_.string_ = duplicateStringValue( value ); -} - - -Value::Value( const char *beginValue, - const char *endValue ) - : type_( stringValue ) - , allocated_( true ) - , comments_( 0 ) -# ifdef JSON_VALUE_USE_INTERNAL_MAP - , itemIsUsed_( 0 ) -#endif -{ - value_.string_ = duplicateStringValue( beginValue, - (unsigned int)(endValue - beginValue) ); -} - - -Value::Value( const std::string &value ) - : type_( stringValue ) - , allocated_( true ) - , comments_( 0 ) -# ifdef JSON_VALUE_USE_INTERNAL_MAP - , itemIsUsed_( 0 ) -#endif -{ - value_.string_ = duplicateStringValue( value.c_str(), - (unsigned int)value.length() ); - -} - -Value::Value( const StaticString &value ) - : type_( stringValue ) - , allocated_( false ) - , comments_( 0 ) -# ifdef JSON_VALUE_USE_INTERNAL_MAP - , itemIsUsed_( 0 ) -#endif -{ - value_.string_ = const_cast( value.c_str() ); -} - - -# ifdef JSON_USE_CPPTL -Value::Value( const CppTL::ConstString &value ) - : type_( stringValue ) - , allocated_( true ) - , comments_( 0 ) -# ifdef JSON_VALUE_USE_INTERNAL_MAP - , itemIsUsed_( 0 ) -#endif -{ - value_.string_ = duplicateStringValue( value, value.length() ); -} -# endif - -Value::Value( bool value ) - : type_( booleanValue ) - , comments_( 0 ) -# ifdef JSON_VALUE_USE_INTERNAL_MAP - , itemIsUsed_( 0 ) -#endif -{ - value_.bool_ = value; -} - - -Value::Value( const Value &other ) - : type_( other.type_ ) - , comments_( 0 ) -# ifdef JSON_VALUE_USE_INTERNAL_MAP - , itemIsUsed_( 0 ) -#endif -{ - switch ( type_ ) - { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - value_ = other.value_; - break; - case stringValue: - if ( other.value_.string_ ) - { - value_.string_ = duplicateStringValue( other.value_.string_ ); - allocated_ = true; - } - else - value_.string_ = 0; - break; -#ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - case objectValue: - value_.map_ = new ObjectValues( *other.value_.map_ ); - break; -#else - case arrayValue: - value_.array_ = arrayAllocator()->newArrayCopy( *other.value_.array_ ); - break; - case objectValue: - value_.map_ = mapAllocator()->newMapCopy( *other.value_.map_ ); - break; -#endif - default: - JSON_ASSERT_UNREACHABLE; - } - if ( other.comments_ ) - { - comments_ = new CommentInfo[numberOfCommentPlacement]; - for ( int comment =0; comment < numberOfCommentPlacement; ++comment ) - { - const CommentInfo &otherComment = other.comments_[comment]; - if ( otherComment.comment_ ) - comments_[comment].setComment( otherComment.comment_ ); - } - } -} - - -Value::~Value() -{ - switch ( type_ ) - { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - break; - case stringValue: - if ( allocated_ ) - releaseStringValue( value_.string_ ); - break; -#ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - case objectValue: - delete value_.map_; - break; -#else - case arrayValue: - arrayAllocator()->destructArray( value_.array_ ); - break; - case objectValue: - mapAllocator()->destructMap( value_.map_ ); - break; -#endif - default: - JSON_ASSERT_UNREACHABLE; - } - - if ( comments_ ) - delete[] comments_; -} - -Value & -Value::operator=( const Value &other ) -{ - Value temp( other ); - swap( temp ); - return *this; -} - -void -Value::swap( Value &other ) -{ - ValueType temp = type_; - type_ = other.type_; - other.type_ = temp; - std::swap( value_, other.value_ ); - int temp2 = allocated_; - allocated_ = other.allocated_; - other.allocated_ = temp2; -} - -ValueType -Value::type() const -{ - return type_; -} - - -int -Value::compare( const Value &other ) const -{ - if ( *this < other ) - return -1; - if ( *this > other ) - return 1; - return 0; -} - - -bool -Value::operator <( const Value &other ) const -{ - int typeDelta = type_ - other.type_; - if ( typeDelta ) - return typeDelta < 0 ? true : false; - switch ( type_ ) - { - case nullValue: - return false; - case intValue: - return value_.int_ < other.value_.int_; - case uintValue: - return value_.uint_ < other.value_.uint_; - case realValue: - return value_.real_ < other.value_.real_; - case booleanValue: - return value_.bool_ < other.value_.bool_; - case stringValue: - return ( value_.string_ == 0 && other.value_.string_ ) - || ( other.value_.string_ - && value_.string_ - && strcmp( value_.string_, other.value_.string_ ) < 0 ); -#ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - case objectValue: - { - int delta = int( value_.map_->size() - other.value_.map_->size() ); - if ( delta ) - return delta < 0; - return (*value_.map_) < (*other.value_.map_); - } -#else - case arrayValue: - return value_.array_->compare( *(other.value_.array_) ) < 0; - case objectValue: - return value_.map_->compare( *(other.value_.map_) ) < 0; -#endif - default: - JSON_ASSERT_UNREACHABLE; - } - return false; // unreachable -} - -bool -Value::operator <=( const Value &other ) const -{ - return !(other < *this); -} - -bool -Value::operator >=( const Value &other ) const -{ - return !(*this < other); -} - -bool -Value::operator >( const Value &other ) const -{ - return other < *this; -} - -bool -Value::operator ==( const Value &other ) const -{ - //if ( type_ != other.type_ ) - // GCC 2.95.3 says: - // attempt to take address of bit-field structure member `Json::Value::type_' - // Beats me, but a temp solves the problem. - int temp = other.type_; - if ( type_ != temp ) - return false; - switch ( type_ ) - { - case nullValue: - return true; - case intValue: - return value_.int_ == other.value_.int_; - case uintValue: - return value_.uint_ == other.value_.uint_; - case realValue: - return value_.real_ == other.value_.real_; - case booleanValue: - return value_.bool_ == other.value_.bool_; - case stringValue: - return ( value_.string_ == other.value_.string_ ) - || ( other.value_.string_ - && value_.string_ - && strcmp( value_.string_, other.value_.string_ ) == 0 ); -#ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - case objectValue: - return value_.map_->size() == other.value_.map_->size() - && (*value_.map_) == (*other.value_.map_); -#else - case arrayValue: - return value_.array_->compare( *(other.value_.array_) ) == 0; - case objectValue: - return value_.map_->compare( *(other.value_.map_) ) == 0; -#endif - default: - JSON_ASSERT_UNREACHABLE; - } - return false; // unreachable -} - -bool -Value::operator !=( const Value &other ) const -{ - return !( *this == other ); -} - -const char * -Value::asCString() const -{ - JSON_ASSERT( type_ == stringValue ); - return value_.string_; -} - - -std::string -Value::asString() const -{ - switch ( type_ ) - { - case nullValue: - return ""; - case stringValue: - return value_.string_ ? value_.string_ : ""; - case booleanValue: - return value_.bool_ ? "true" : "false"; - case intValue: - case uintValue: - case realValue: - case arrayValue: - case objectValue: - JSON_FAIL_MESSAGE( "Type is not convertible to string" ); - default: - JSON_ASSERT_UNREACHABLE; - } - return ""; // unreachable -} - -# ifdef JSON_USE_CPPTL -CppTL::ConstString -Value::asConstString() const -{ - return CppTL::ConstString( asString().c_str() ); -} -# endif - - -Value::Int -Value::asInt() const -{ - switch ( type_ ) - { - case nullValue: - return 0; - case intValue: - JSON_ASSERT_MESSAGE( value_.int_ >= minInt && value_.int_ <= maxInt, "unsigned integer out of signed int range" ); - return Int(value_.int_); - case uintValue: - JSON_ASSERT_MESSAGE( value_.uint_ <= UInt(maxInt), "unsigned integer out of signed int range" ); - return Int(value_.uint_); - case realValue: - JSON_ASSERT_MESSAGE( value_.real_ >= minInt && value_.real_ <= maxInt, "Real out of signed integer range" ); - return Int( value_.real_ ); - case booleanValue: - return value_.bool_ ? 1 : 0; - case stringValue: - case arrayValue: - case objectValue: - JSON_FAIL_MESSAGE( "Type is not convertible to int" ); - default: - JSON_ASSERT_UNREACHABLE; - } - return 0; // unreachable; -} - - -Value::UInt -Value::asUInt() const -{ - switch ( type_ ) - { - case nullValue: - return 0; - case intValue: - JSON_ASSERT_MESSAGE( value_.int_ >= 0, "Negative integer can not be converted to unsigned integer" ); - JSON_ASSERT_MESSAGE( value_.int_ <= maxUInt, "signed integer out of UInt range" ); - return UInt(value_.int_); - case uintValue: - JSON_ASSERT_MESSAGE( value_.uint_ <= maxUInt, "unsigned integer out of UInt range" ); - return UInt(value_.uint_); - case realValue: - JSON_ASSERT_MESSAGE( value_.real_ >= 0 && value_.real_ <= maxUInt, "Real out of unsigned integer range" ); - return UInt( value_.real_ ); - case booleanValue: - return value_.bool_ ? 1 : 0; - case stringValue: - case arrayValue: - case objectValue: - JSON_FAIL_MESSAGE( "Type is not convertible to uint" ); - default: - JSON_ASSERT_UNREACHABLE; - } - return 0; // unreachable; -} - - -# if defined(JSON_HAS_INT64) - -Value::Int64 -Value::asInt64() const -{ - switch ( type_ ) - { - case nullValue: - return 0; - case intValue: - return value_.int_; - case uintValue: - JSON_ASSERT_MESSAGE( value_.uint_ <= UInt64(maxInt64), "unsigned integer out of Int64 range" ); - return value_.uint_; - case realValue: - JSON_ASSERT_MESSAGE( value_.real_ >= minInt64 && value_.real_ <= maxInt64, "Real out of Int64 range" ); - return Int( value_.real_ ); - case booleanValue: - return value_.bool_ ? 1 : 0; - case stringValue: - case arrayValue: - case objectValue: - JSON_FAIL_MESSAGE( "Type is not convertible to Int64" ); - default: - JSON_ASSERT_UNREACHABLE; - } - return 0; // unreachable; -} - - -Value::UInt64 -Value::asUInt64() const -{ - switch ( type_ ) - { - case nullValue: - return 0; - case intValue: - JSON_ASSERT_MESSAGE( value_.int_ >= 0, "Negative integer can not be converted to UInt64" ); - return value_.int_; - case uintValue: - return value_.uint_; - case realValue: - JSON_ASSERT_MESSAGE( value_.real_ >= 0 && value_.real_ <= maxUInt64, "Real out of UInt64 range" ); - return UInt( value_.real_ ); - case booleanValue: - return value_.bool_ ? 1 : 0; - case stringValue: - case arrayValue: - case objectValue: - JSON_FAIL_MESSAGE( "Type is not convertible to UInt64" ); - default: - JSON_ASSERT_UNREACHABLE; - } - return 0; // unreachable; -} -# endif // if defined(JSON_HAS_INT64) - - -LargestInt -Value::asLargestInt() const -{ -#if defined(JSON_NO_INT64) - return asInt(); -#else - return asInt64(); -#endif -} - - -LargestUInt -Value::asLargestUInt() const -{ -#if defined(JSON_NO_INT64) - return asUInt(); -#else - return asUInt64(); -#endif -} - - -double -Value::asDouble() const -{ - switch ( type_ ) - { - case nullValue: - return 0.0; - case intValue: - return static_cast( value_.int_ ); - case uintValue: -#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - return static_cast( value_.uint_ ); -#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - return static_cast( Int(value_.uint_/2) ) * 2 + Int(value_.uint_ & 1); -#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - case realValue: - return value_.real_; - case booleanValue: - return value_.bool_ ? 1.0 : 0.0; - case stringValue: - case arrayValue: - case objectValue: - JSON_FAIL_MESSAGE( "Type is not convertible to double" ); - default: - JSON_ASSERT_UNREACHABLE; - } - return 0; // unreachable; -} - -float -Value::asFloat() const -{ - switch ( type_ ) - { - case nullValue: - return 0.0f; - case intValue: - return static_cast( value_.int_ ); - case uintValue: -#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - return static_cast( value_.uint_ ); -#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - return static_cast( Int(value_.uint_/2) ) * 2 + Int(value_.uint_ & 1); -#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - case realValue: - return static_cast( value_.real_ ); - case booleanValue: - return value_.bool_ ? 1.0f : 0.0f; - case stringValue: - case arrayValue: - case objectValue: - JSON_FAIL_MESSAGE( "Type is not convertible to float" ); - default: - JSON_ASSERT_UNREACHABLE; - } - return 0.0f; // unreachable; -} - -bool -Value::asBool() const -{ - switch ( type_ ) - { - case nullValue: - return false; - case intValue: - case uintValue: - return value_.int_ != 0; - case realValue: - return value_.real_ != 0.0; - case booleanValue: - return value_.bool_; - case stringValue: - return value_.string_ && value_.string_[0] != 0; - case arrayValue: - case objectValue: - return value_.map_->size() != 0; - default: - JSON_ASSERT_UNREACHABLE; - } - return false; // unreachable; -} - - -bool -Value::isConvertibleTo( ValueType other ) const -{ - switch ( type_ ) - { - case nullValue: - return true; - case intValue: - return ( other == nullValue && value_.int_ == 0 ) - || other == intValue - || ( other == uintValue && value_.int_ >= 0 ) - || other == realValue - || other == stringValue - || other == booleanValue; - case uintValue: - return ( other == nullValue && value_.uint_ == 0 ) - || ( other == intValue && value_.uint_ <= (unsigned)maxInt ) - || other == uintValue - || other == realValue - || other == stringValue - || other == booleanValue; - case realValue: - return ( other == nullValue && value_.real_ == 0.0 ) - || ( other == intValue && value_.real_ >= minInt && value_.real_ <= maxInt ) - || ( other == uintValue && value_.real_ >= 0 && value_.real_ <= maxUInt ) - || other == realValue - || other == stringValue - || other == booleanValue; - case booleanValue: - return ( other == nullValue && value_.bool_ == false ) - || other == intValue - || other == uintValue - || other == realValue - || other == stringValue - || other == booleanValue; - case stringValue: - return other == stringValue - || ( other == nullValue && (!value_.string_ || value_.string_[0] == 0) ); - case arrayValue: - return other == arrayValue - || ( other == nullValue && value_.map_->size() == 0 ); - case objectValue: - return other == objectValue - || ( other == nullValue && value_.map_->size() == 0 ); - default: - JSON_ASSERT_UNREACHABLE; - } - return false; // unreachable; -} - - -/// Number of values in array or object -ArrayIndex -Value::size() const -{ - switch ( type_ ) - { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - case stringValue: - return 0; -#ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: // size of the array is highest index + 1 - if ( !value_.map_->empty() ) - { - ObjectValues::const_iterator itLast = value_.map_->end(); - --itLast; - return (*itLast).first.index()+1; - } - return 0; - case objectValue: - return ArrayIndex( value_.map_->size() ); -#else - case arrayValue: - return Int( value_.array_->size() ); - case objectValue: - return Int( value_.map_->size() ); -#endif - default: - JSON_ASSERT_UNREACHABLE; - } - return 0; // unreachable; -} - - -bool -Value::empty() const -{ - if ( isNull() || isArray() || isObject() ) - return size() == 0u; - else - return false; -} - - -bool -Value::operator!() const -{ - return isNull(); -} - - -void -Value::clear() -{ - JSON_ASSERT( type_ == nullValue || type_ == arrayValue || type_ == objectValue ); - - switch ( type_ ) - { -#ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - case objectValue: - value_.map_->clear(); - break; -#else - case arrayValue: - value_.array_->clear(); - break; - case objectValue: - value_.map_->clear(); - break; -#endif - default: - break; - } -} - -void -Value::resize( ArrayIndex newSize ) -{ - JSON_ASSERT( type_ == nullValue || type_ == arrayValue ); - if ( type_ == nullValue ) - *this = Value( arrayValue ); -#ifndef JSON_VALUE_USE_INTERNAL_MAP - ArrayIndex oldSize = size(); - if ( newSize == 0 ) - clear(); - else if ( newSize > oldSize ) - (*this)[ newSize - 1 ]; - else - { - for ( ArrayIndex index = newSize; index < oldSize; ++index ) - { - value_.map_->erase( index ); - } - assert( size() == newSize ); - } -#else - value_.array_->resize( newSize ); -#endif -} - - -Value & -Value::operator[]( ArrayIndex index ) -{ - JSON_ASSERT( type_ == nullValue || type_ == arrayValue ); - if ( type_ == nullValue ) - *this = Value( arrayValue ); -#ifndef JSON_VALUE_USE_INTERNAL_MAP - CZString key( index ); - ObjectValues::iterator it = value_.map_->lower_bound( key ); - if ( it != value_.map_->end() && (*it).first == key ) - return (*it).second; - - ObjectValues::value_type defaultValue( key, null ); - it = value_.map_->insert( it, defaultValue ); - return (*it).second; -#else - return value_.array_->resolveReference( index ); -#endif -} - - -Value & -Value::operator[]( int index ) -{ - JSON_ASSERT( index >= 0 ); - return (*this)[ ArrayIndex(index) ]; -} - - -const Value & -Value::operator[]( ArrayIndex index ) const -{ - JSON_ASSERT( type_ == nullValue || type_ == arrayValue ); - if ( type_ == nullValue ) - return null; -#ifndef JSON_VALUE_USE_INTERNAL_MAP - CZString key( index ); - ObjectValues::const_iterator it = value_.map_->find( key ); - if ( it == value_.map_->end() ) - return null; - return (*it).second; -#else - Value *value = value_.array_->find( index ); - return value ? *value : null; -#endif -} - - -const Value & -Value::operator[]( int index ) const -{ - JSON_ASSERT( index >= 0 ); - return (*this)[ ArrayIndex(index) ]; -} - - -Value & -Value::operator[]( const char *key ) -{ - return resolveReference( key, false ); -} - - -Value & -Value::resolveReference( const char *key, - bool isStatic ) -{ - JSON_ASSERT( type_ == nullValue || type_ == objectValue ); - if ( type_ == nullValue ) - *this = Value( objectValue ); -#ifndef JSON_VALUE_USE_INTERNAL_MAP - CZString actualKey( key, isStatic ? CZString::noDuplication - : CZString::duplicateOnCopy ); - ObjectValues::iterator it = value_.map_->lower_bound( actualKey ); - if ( it != value_.map_->end() && (*it).first == actualKey ) - return (*it).second; - - ObjectValues::value_type defaultValue( actualKey, null ); - it = value_.map_->insert( it, defaultValue ); - Value &value = (*it).second; - return value; -#else - return value_.map_->resolveReference( key, isStatic ); -#endif -} - - -Value -Value::get( ArrayIndex index, - const Value &defaultValue ) const -{ - const Value *value = &((*this)[index]); - return value == &null ? defaultValue : *value; -} - - -bool -Value::isValidIndex( ArrayIndex index ) const -{ - return index < size(); -} - - - -const Value & -Value::operator[]( const char *key ) const -{ - JSON_ASSERT( type_ == nullValue || type_ == objectValue ); - if ( type_ == nullValue ) - return null; -#ifndef JSON_VALUE_USE_INTERNAL_MAP - CZString actualKey( key, CZString::noDuplication ); - ObjectValues::const_iterator it = value_.map_->find( actualKey ); - if ( it == value_.map_->end() ) - return null; - return (*it).second; -#else - const Value *value = value_.map_->find( key ); - return value ? *value : null; -#endif -} - - -Value & -Value::operator[]( const std::string &key ) -{ - return (*this)[ key.c_str() ]; -} - - -const Value & -Value::operator[]( const std::string &key ) const -{ - return (*this)[ key.c_str() ]; -} - -Value & -Value::operator[]( const StaticString &key ) -{ - return resolveReference( key, true ); -} - - -# ifdef JSON_USE_CPPTL -Value & -Value::operator[]( const CppTL::ConstString &key ) -{ - return (*this)[ key.c_str() ]; -} - - -const Value & -Value::operator[]( const CppTL::ConstString &key ) const -{ - return (*this)[ key.c_str() ]; -} -# endif - - -Value & -Value::append( const Value &value ) -{ - return (*this)[size()] = value; -} - - -Value -Value::get( const char *key, - const Value &defaultValue ) const -{ - const Value *value = &((*this)[key]); - return value == &null ? defaultValue : *value; -} - - -Value -Value::get( const std::string &key, - const Value &defaultValue ) const -{ - return get( key.c_str(), defaultValue ); -} - -Value -Value::removeMember( const char* key ) -{ - JSON_ASSERT( type_ == nullValue || type_ == objectValue ); - if ( type_ == nullValue ) - return null; -#ifndef JSON_VALUE_USE_INTERNAL_MAP - CZString actualKey( key, CZString::noDuplication ); - ObjectValues::iterator it = value_.map_->find( actualKey ); - if ( it == value_.map_->end() ) - return null; - Value old(it->second); - value_.map_->erase(it); - return old; -#else - Value *value = value_.map_->find( key ); - if (value){ - Value old(*value); - value_.map_.remove( key ); - return old; - } else { - return null; - } -#endif -} - -Value -Value::removeMember( const std::string &key ) -{ - return removeMember( key.c_str() ); -} - -# ifdef JSON_USE_CPPTL -Value -Value::get( const CppTL::ConstString &key, - const Value &defaultValue ) const -{ - return get( key.c_str(), defaultValue ); -} -# endif - -bool -Value::isMember( const char *key ) const -{ - const Value *value = &((*this)[key]); - return value != &null; -} - - -bool -Value::isMember( const std::string &key ) const -{ - return isMember( key.c_str() ); -} - - -# ifdef JSON_USE_CPPTL -bool -Value::isMember( const CppTL::ConstString &key ) const -{ - return isMember( key.c_str() ); -} -#endif - -Value::Members -Value::getMemberNames() const -{ - JSON_ASSERT( type_ == nullValue || type_ == objectValue ); - if ( type_ == nullValue ) - return Value::Members(); - Members members; - members.reserve( value_.map_->size() ); -#ifndef JSON_VALUE_USE_INTERNAL_MAP - ObjectValues::const_iterator it = value_.map_->begin(); - ObjectValues::const_iterator itEnd = value_.map_->end(); - for ( ; it != itEnd; ++it ) - members.push_back( std::string( (*it).first.c_str() ) ); -#else - ValueInternalMap::IteratorState it; - ValueInternalMap::IteratorState itEnd; - value_.map_->makeBeginIterator( it ); - value_.map_->makeEndIterator( itEnd ); - for ( ; !ValueInternalMap::equals( it, itEnd ); ValueInternalMap::increment(it) ) - members.push_back( std::string( ValueInternalMap::key( it ) ) ); -#endif - return members; -} -// -//# ifdef JSON_USE_CPPTL -//EnumMemberNames -//Value::enumMemberNames() const -//{ -// if ( type_ == objectValue ) -// { -// return CppTL::Enum::any( CppTL::Enum::transform( -// CppTL::Enum::keys( *(value_.map_), CppTL::Type() ), -// MemberNamesTransform() ) ); -// } -// return EnumMemberNames(); -//} -// -// -//EnumValues -//Value::enumValues() const -//{ -// if ( type_ == objectValue || type_ == arrayValue ) -// return CppTL::Enum::anyValues( *(value_.map_), -// CppTL::Type() ); -// return EnumValues(); -//} -// -//# endif - - -bool -Value::isNull() const -{ - return type_ == nullValue; -} - - -bool -Value::isBool() const -{ - return type_ == booleanValue; -} - - -bool -Value::isInt() const -{ - return type_ == intValue; -} - - -bool -Value::isUInt() const -{ - return type_ == uintValue; -} - - -bool -Value::isIntegral() const -{ - return type_ == intValue - || type_ == uintValue - || type_ == booleanValue; -} - - -bool -Value::isDouble() const -{ - return type_ == realValue; -} - - -bool -Value::isNumeric() const -{ - return isIntegral() || isDouble(); -} - - -bool -Value::isString() const -{ - return type_ == stringValue; -} - - -bool -Value::isArray() const -{ - return type_ == nullValue || type_ == arrayValue; -} - - -bool -Value::isObject() const -{ - return type_ == nullValue || type_ == objectValue; -} - - -void -Value::setComment( const char *comment, - CommentPlacement placement ) -{ - if ( !comments_ ) - comments_ = new CommentInfo[numberOfCommentPlacement]; - comments_[placement].setComment( comment ); -} - - -void -Value::setComment( const std::string &comment, - CommentPlacement placement ) -{ - setComment( comment.c_str(), placement ); -} - - -bool -Value::hasComment( CommentPlacement placement ) const -{ - return comments_ != 0 && comments_[placement].comment_ != 0; -} - -std::string -Value::getComment( CommentPlacement placement ) const -{ - if ( hasComment(placement) ) - return comments_[placement].comment_; - return ""; -} - - -std::string -Value::toStyledString() const -{ - StyledWriter writer; - return writer.write( *this ); -} - - -Value::const_iterator -Value::begin() const -{ - switch ( type_ ) - { -#ifdef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - if ( value_.array_ ) - { - ValueInternalArray::IteratorState it; - value_.array_->makeBeginIterator( it ); - return const_iterator( it ); - } - break; - case objectValue: - if ( value_.map_ ) - { - ValueInternalMap::IteratorState it; - value_.map_->makeBeginIterator( it ); - return const_iterator( it ); - } - break; -#else - case arrayValue: - case objectValue: - if ( value_.map_ ) - return const_iterator( value_.map_->begin() ); - break; -#endif - default: - break; - } - return const_iterator(); -} - -Value::const_iterator -Value::end() const -{ - switch ( type_ ) - { -#ifdef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - if ( value_.array_ ) - { - ValueInternalArray::IteratorState it; - value_.array_->makeEndIterator( it ); - return const_iterator( it ); - } - break; - case objectValue: - if ( value_.map_ ) - { - ValueInternalMap::IteratorState it; - value_.map_->makeEndIterator( it ); - return const_iterator( it ); - } - break; -#else - case arrayValue: - case objectValue: - if ( value_.map_ ) - return const_iterator( value_.map_->end() ); - break; -#endif - default: - break; - } - return const_iterator(); -} - - -Value::iterator -Value::begin() -{ - switch ( type_ ) - { -#ifdef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - if ( value_.array_ ) - { - ValueInternalArray::IteratorState it; - value_.array_->makeBeginIterator( it ); - return iterator( it ); - } - break; - case objectValue: - if ( value_.map_ ) - { - ValueInternalMap::IteratorState it; - value_.map_->makeBeginIterator( it ); - return iterator( it ); - } - break; -#else - case arrayValue: - case objectValue: - if ( value_.map_ ) - return iterator( value_.map_->begin() ); - break; -#endif - default: - break; - } - return iterator(); -} - -Value::iterator -Value::end() -{ - switch ( type_ ) - { -#ifdef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - if ( value_.array_ ) - { - ValueInternalArray::IteratorState it; - value_.array_->makeEndIterator( it ); - return iterator( it ); - } - break; - case objectValue: - if ( value_.map_ ) - { - ValueInternalMap::IteratorState it; - value_.map_->makeEndIterator( it ); - return iterator( it ); - } - break; -#else - case arrayValue: - case objectValue: - if ( value_.map_ ) - return iterator( value_.map_->end() ); - break; -#endif - default: - break; - } - return iterator(); -} - - -// class PathArgument -// ////////////////////////////////////////////////////////////////// - -PathArgument::PathArgument() - : kind_( kindNone ) -{ -} - - -PathArgument::PathArgument( ArrayIndex index ) - : index_( index ) - , kind_( kindIndex ) -{ -} - - -PathArgument::PathArgument( const char *key ) - : key_( key ) - , kind_( kindKey ) -{ -} - - -PathArgument::PathArgument( const std::string &key ) - : key_( key.c_str() ) - , kind_( kindKey ) -{ -} - -// class Path -// ////////////////////////////////////////////////////////////////// - -Path::Path( const std::string &path, - const PathArgument &a1, - const PathArgument &a2, - const PathArgument &a3, - const PathArgument &a4, - const PathArgument &a5 ) -{ - InArgs in; - in.push_back( &a1 ); - in.push_back( &a2 ); - in.push_back( &a3 ); - in.push_back( &a4 ); - in.push_back( &a5 ); - makePath( path, in ); -} - - -void -Path::makePath( const std::string &path, - const InArgs &in ) -{ - const char *current = path.c_str(); - const char *end = current + path.length(); - InArgs::const_iterator itInArg = in.begin(); - while ( current != end ) - { - if ( *current == '[' ) - { - ++current; - if ( *current == '%' ) - addPathInArg( path, in, itInArg, PathArgument::kindIndex ); - else - { - ArrayIndex index = 0; - for ( ; current != end && *current >= '0' && *current <= '9'; ++current ) - index = index * 10 + ArrayIndex(*current - '0'); - args_.push_back( index ); - } - if ( current == end || *current++ != ']' ) - invalidPath( path, int(current - path.c_str()) ); - } - else if ( *current == '%' ) - { - addPathInArg( path, in, itInArg, PathArgument::kindKey ); - ++current; - } - else if ( *current == '.' ) - { - ++current; - } - else - { - const char *beginName = current; - while ( current != end && !strchr( "[.", *current ) ) - ++current; - args_.push_back( std::string( beginName, current ) ); - } - } -} - - -void -Path::addPathInArg( const std::string &path, - const InArgs &in, - InArgs::const_iterator &itInArg, - PathArgument::Kind kind ) -{ - if ( itInArg == in.end() ) - { - // Error: missing argument %d - } - else if ( (*itInArg)->kind_ != kind ) - { - // Error: bad argument type - } - else - { - args_.push_back( **itInArg ); - } -} - - -void -Path::invalidPath( const std::string &path, - int location ) -{ - // Error: invalid path. -} - - -const Value & -Path::resolve( const Value &root ) const -{ - const Value *node = &root; - for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it ) - { - const PathArgument &arg = *it; - if ( arg.kind_ == PathArgument::kindIndex ) - { - if ( !node->isArray() || node->isValidIndex( arg.index_ ) ) - { - // Error: unable to resolve path (array value expected at position... - } - node = &((*node)[arg.index_]); - } - else if ( arg.kind_ == PathArgument::kindKey ) - { - if ( !node->isObject() ) - { - // Error: unable to resolve path (object value expected at position...) - } - node = &((*node)[arg.key_]); - if ( node == &Value::null ) - { - // Error: unable to resolve path (object has no member named '' at position...) - } - } - } - return *node; -} - - -Value -Path::resolve( const Value &root, - const Value &defaultValue ) const -{ - const Value *node = &root; - for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it ) - { - const PathArgument &arg = *it; - if ( arg.kind_ == PathArgument::kindIndex ) - { - if ( !node->isArray() || node->isValidIndex( arg.index_ ) ) - return defaultValue; - node = &((*node)[arg.index_]); - } - else if ( arg.kind_ == PathArgument::kindKey ) - { - if ( !node->isObject() ) - return defaultValue; - node = &((*node)[arg.key_]); - if ( node == &Value::null ) - return defaultValue; - } - } - return *node; -} - - -Value & -Path::make( Value &root ) const -{ - Value *node = &root; - for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it ) - { - const PathArgument &arg = *it; - if ( arg.kind_ == PathArgument::kindIndex ) - { - if ( !node->isArray() ) - { - // Error: node is not an array at position ... - } - node = &((*node)[arg.index_]); - } - else if ( arg.kind_ == PathArgument::kindKey ) - { - if ( !node->isObject() ) - { - // Error: node is not an object at position... - } - node = &((*node)[arg.key_]); - } - } - return *node; -} - - -} // namespace Json - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: src/lib_json/json_value.cpp -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: src/lib_json/json_writer.cpp -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#if !defined(JSON_IS_AMALGAMATION) -# include -# include "json_tool.h" -#endif // if !defined(JSON_IS_AMALGAMATION) -#include -#include -#include -#include -#include -#include -#include - -#if _MSC_VER >= 1400 // VC++ 8.0 -#pragma warning( disable : 4996 ) // disable warning about strdup being deprecated. -#endif - -namespace Json { - -static bool containsControlCharacter( const char* str ) -{ - while ( *str ) - { - if ( isControlCharacter( *(str++) ) ) - return true; - } - return false; -} - - -std::string valueToString( LargestInt value ) -{ - UIntToStringBuffer buffer; - char *current = buffer + sizeof(buffer); - bool isNegative = value < 0; - if ( isNegative ) - value = -value; - uintToString( LargestUInt(value), current ); - if ( isNegative ) - *--current = '-'; - assert( current >= buffer ); - return current; -} - - -std::string valueToString( LargestUInt value ) -{ - UIntToStringBuffer buffer; - char *current = buffer + sizeof(buffer); - uintToString( value, current ); - assert( current >= buffer ); - return current; -} - -#if defined(JSON_HAS_INT64) - -std::string valueToString( Int value ) -{ - return valueToString( LargestInt(value) ); -} - - -std::string valueToString( UInt value ) -{ - return valueToString( LargestUInt(value) ); -} - -#endif // # if defined(JSON_HAS_INT64) - - -std::string valueToString( double value ) -{ - char buffer[32]; -#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with visual studio 2005 to avoid warning. - sprintf_s(buffer, sizeof(buffer), "%#.16g", value); -#else - sprintf(buffer, "%#.16g", value); -#endif - char* ch = buffer + strlen(buffer) - 1; - if (*ch != '0') return buffer; // nothing to truncate, so save time - while(ch > buffer && *ch == '0'){ - --ch; - } - char* last_nonzero = ch; - while(ch >= buffer){ - switch(*ch){ - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - --ch; - continue; - case '.': - // Truncate zeroes to save bytes in output, but keep one. - *(last_nonzero+2) = '\0'; - return buffer; - default: - return buffer; - } - } - return buffer; -} - - -std::string valueToString( bool value ) -{ - return value ? "true" : "false"; -} - -std::string valueToQuotedString( const char *value ) -{ - // Not sure how to handle unicode... - if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL && !containsControlCharacter( value )) - return std::string("\"") + value + "\""; - // We have to walk value and escape any special characters. - // Appending to std::string is not efficient, but this should be rare. - // (Note: forward slashes are *not* rare, but I am not escaping them.) - std::string::size_type maxsize = strlen(value)*2 + 3; // allescaped+quotes+NULL - std::string result; - result.reserve(maxsize); // to avoid lots of mallocs - result += "\""; - for (const char* c=value; *c != 0; ++c) - { - switch(*c) - { - case '\"': - result += "\\\""; - break; - case '\\': - result += "\\\\"; - break; - case '\b': - result += "\\b"; - break; - case '\f': - result += "\\f"; - break; - case '\n': - result += "\\n"; - break; - case '\r': - result += "\\r"; - break; - case '\t': - result += "\\t"; - break; - //case '/': - // Even though \/ is considered a legal escape in JSON, a bare - // slash is also legal, so I see no reason to escape it. - // (I hope I am not misunderstanding something. - // blep notes: actually escaping \/ may be useful in javascript to avoid (*c); - result += oss.str(); - } - else - { - result += *c; - } - break; - } - } - result += "\""; - return result; -} - -// Class Writer -// ////////////////////////////////////////////////////////////////// -Writer::~Writer() -{ -} - - -// Class FastWriter -// ////////////////////////////////////////////////////////////////// - -FastWriter::FastWriter() - : yamlCompatiblityEnabled_( false ) -{ -} - - -void -FastWriter::enableYAMLCompatibility() -{ - yamlCompatiblityEnabled_ = true; -} - - -std::string -FastWriter::write( const Value &root ) -{ - document_ = ""; - writeValue( root ); - document_ += "\n"; - return document_; -} - - -void -FastWriter::writeValue( const Value &value ) -{ - switch ( value.type() ) - { - case nullValue: - document_ += "null"; - break; - case intValue: - document_ += valueToString( value.asLargestInt() ); - break; - case uintValue: - document_ += valueToString( value.asLargestUInt() ); - break; - case realValue: - document_ += valueToString( value.asDouble() ); - break; - case stringValue: - document_ += valueToQuotedString( value.asCString() ); - break; - case booleanValue: - document_ += valueToString( value.asBool() ); - break; - case arrayValue: - { - document_ += "["; - int size = value.size(); - for ( int index =0; index < size; ++index ) - { - if ( index > 0 ) - document_ += ","; - writeValue( value[index] ); - } - document_ += "]"; - } - break; - case objectValue: - { - Value::Members members( value.getMemberNames() ); - document_ += "{"; - for ( Value::Members::iterator it = members.begin(); - it != members.end(); - ++it ) - { - const std::string &name = *it; - if ( it != members.begin() ) - document_ += ","; - document_ += valueToQuotedString( name.c_str() ); - document_ += yamlCompatiblityEnabled_ ? ": " - : ":"; - writeValue( value[name] ); - } - document_ += "}"; - } - break; - } -} - - -// Class StyledWriter -// ////////////////////////////////////////////////////////////////// - -StyledWriter::StyledWriter() - : rightMargin_( 74 ) - , indentSize_( 3 ) -{ -} - - -std::string -StyledWriter::write( const Value &root ) -{ - document_ = ""; - addChildValues_ = false; - indentString_ = ""; - writeCommentBeforeValue( root ); - writeValue( root ); - writeCommentAfterValueOnSameLine( root ); - document_ += "\n"; - return document_; -} - - -void -StyledWriter::writeValue( const Value &value ) -{ - switch ( value.type() ) - { - case nullValue: - pushValue( "null" ); - break; - case intValue: - pushValue( valueToString( value.asLargestInt() ) ); - break; - case uintValue: - pushValue( valueToString( value.asLargestUInt() ) ); - break; - case realValue: - pushValue( valueToString( value.asDouble() ) ); - break; - case stringValue: - pushValue( valueToQuotedString( value.asCString() ) ); - break; - case booleanValue: - pushValue( valueToString( value.asBool() ) ); - break; - case arrayValue: - writeArrayValue( value); - break; - case objectValue: - { - Value::Members members( value.getMemberNames() ); - if ( members.empty() ) - pushValue( "{}" ); - else - { - writeWithIndent( "{" ); - indent(); - Value::Members::iterator it = members.begin(); - for (;;) - { - const std::string &name = *it; - const Value &childValue = value[name]; - writeCommentBeforeValue( childValue ); - writeWithIndent( valueToQuotedString( name.c_str() ) ); - document_ += " : "; - writeValue( childValue ); - if ( ++it == members.end() ) - { - writeCommentAfterValueOnSameLine( childValue ); - break; - } - document_ += ","; - writeCommentAfterValueOnSameLine( childValue ); - } - unindent(); - writeWithIndent( "}" ); - } - } - break; - } -} - - -void -StyledWriter::writeArrayValue( const Value &value ) -{ - unsigned size = value.size(); - if ( size == 0 ) - pushValue( "[]" ); - else - { - bool isArrayMultiLine = isMultineArray( value ); - if ( isArrayMultiLine ) - { - writeWithIndent( "[" ); - indent(); - bool hasChildValue = !childValues_.empty(); - unsigned index =0; - for (;;) - { - const Value &childValue = value[index]; - writeCommentBeforeValue( childValue ); - if ( hasChildValue ) - writeWithIndent( childValues_[index] ); - else - { - writeIndent(); - writeValue( childValue ); - } - if ( ++index == size ) - { - writeCommentAfterValueOnSameLine( childValue ); - break; - } - document_ += ","; - writeCommentAfterValueOnSameLine( childValue ); - } - unindent(); - writeWithIndent( "]" ); - } - else // output on a single line - { - assert( childValues_.size() == size ); - document_ += "[ "; - for ( unsigned index =0; index < size; ++index ) - { - if ( index > 0 ) - document_ += ", "; - document_ += childValues_[index]; - } - document_ += " ]"; - } - } -} - - -bool -StyledWriter::isMultineArray( const Value &value ) -{ - int size = value.size(); - bool isMultiLine = size*3 >= rightMargin_ ; - childValues_.clear(); - for ( int index =0; index < size && !isMultiLine; ++index ) - { - const Value &childValue = value[index]; - isMultiLine = isMultiLine || - ( (childValue.isArray() || childValue.isObject()) && - childValue.size() > 0 ); - } - if ( !isMultiLine ) // check if line length > max line length - { - childValues_.reserve( size ); - addChildValues_ = true; - int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]' - for ( int index =0; index < size && !isMultiLine; ++index ) - { - writeValue( value[index] ); - lineLength += int( childValues_[index].length() ); - isMultiLine = isMultiLine && hasCommentForValue( value[index] ); - } - addChildValues_ = false; - isMultiLine = isMultiLine || lineLength >= rightMargin_; - } - return isMultiLine; -} - - -void -StyledWriter::pushValue( const std::string &value ) -{ - if ( addChildValues_ ) - childValues_.push_back( value ); - else - document_ += value; -} - - -void -StyledWriter::writeIndent() -{ - if ( !document_.empty() ) - { - char last = document_[document_.length()-1]; - if ( last == ' ' ) // already indented - return; - if ( last != '\n' ) // Comments may add new-line - document_ += '\n'; - } - document_ += indentString_; -} - - -void -StyledWriter::writeWithIndent( const std::string &value ) -{ - writeIndent(); - document_ += value; -} - - -void -StyledWriter::indent() -{ - indentString_ += std::string( indentSize_, ' ' ); -} - - -void -StyledWriter::unindent() -{ - assert( int(indentString_.size()) >= indentSize_ ); - indentString_.resize( indentString_.size() - indentSize_ ); -} - - -void -StyledWriter::writeCommentBeforeValue( const Value &root ) -{ - if ( !root.hasComment( commentBefore ) ) - return; - document_ += normalizeEOL( root.getComment( commentBefore ) ); - document_ += "\n"; -} - - -void -StyledWriter::writeCommentAfterValueOnSameLine( const Value &root ) -{ - if ( root.hasComment( commentAfterOnSameLine ) ) - document_ += " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) ); - - if ( root.hasComment( commentAfter ) ) - { - document_ += "\n"; - document_ += normalizeEOL( root.getComment( commentAfter ) ); - document_ += "\n"; - } -} - - -bool -StyledWriter::hasCommentForValue( const Value &value ) -{ - return value.hasComment( commentBefore ) - || value.hasComment( commentAfterOnSameLine ) - || value.hasComment( commentAfter ); -} - - -std::string -StyledWriter::normalizeEOL( const std::string &text ) -{ - std::string normalized; - normalized.reserve( text.length() ); - const char *begin = text.c_str(); - const char *end = begin + text.length(); - const char *current = begin; - while ( current != end ) - { - char c = *current++; - if ( c == '\r' ) // mac or dos EOL - { - if ( *current == '\n' ) // convert dos EOL - ++current; - normalized += '\n'; - } - else // handle unix EOL & other char - normalized += c; - } - return normalized; -} - - -// Class StyledStreamWriter -// ////////////////////////////////////////////////////////////////// - -StyledStreamWriter::StyledStreamWriter( std::string indentation ) - : document_(NULL) - , rightMargin_( 74 ) - , indentation_( indentation ) -{ -} - - -void -StyledStreamWriter::write( std::ostream &out, const Value &root ) -{ - document_ = &out; - addChildValues_ = false; - indentString_ = ""; - writeCommentBeforeValue( root ); - writeValue( root ); - writeCommentAfterValueOnSameLine( root ); - *document_ << "\n"; - document_ = NULL; // Forget the stream, for safety. -} - - -void -StyledStreamWriter::writeValue( const Value &value ) -{ - switch ( value.type() ) - { - case nullValue: - pushValue( "null" ); - break; - case intValue: - pushValue( valueToString( value.asLargestInt() ) ); - break; - case uintValue: - pushValue( valueToString( value.asLargestUInt() ) ); - break; - case realValue: - pushValue( valueToString( value.asDouble() ) ); - break; - case stringValue: - pushValue( valueToQuotedString( value.asCString() ) ); - break; - case booleanValue: - pushValue( valueToString( value.asBool() ) ); - break; - case arrayValue: - writeArrayValue( value); - break; - case objectValue: - { - Value::Members members( value.getMemberNames() ); - if ( members.empty() ) - pushValue( "{}" ); - else - { - writeWithIndent( "{" ); - indent(); - Value::Members::iterator it = members.begin(); - for (;;) - { - const std::string &name = *it; - const Value &childValue = value[name]; - writeCommentBeforeValue( childValue ); - writeWithIndent( valueToQuotedString( name.c_str() ) ); - *document_ << " : "; - writeValue( childValue ); - if ( ++it == members.end() ) - { - writeCommentAfterValueOnSameLine( childValue ); - break; - } - *document_ << ","; - writeCommentAfterValueOnSameLine( childValue ); - } - unindent(); - writeWithIndent( "}" ); - } - } - break; - } -} - - -void -StyledStreamWriter::writeArrayValue( const Value &value ) -{ - unsigned size = value.size(); - if ( size == 0 ) - pushValue( "[]" ); - else - { - bool isArrayMultiLine = isMultineArray( value ); - if ( isArrayMultiLine ) - { - writeWithIndent( "[" ); - indent(); - bool hasChildValue = !childValues_.empty(); - unsigned index =0; - for (;;) - { - const Value &childValue = value[index]; - writeCommentBeforeValue( childValue ); - if ( hasChildValue ) - writeWithIndent( childValues_[index] ); - else - { - writeIndent(); - writeValue( childValue ); - } - if ( ++index == size ) - { - writeCommentAfterValueOnSameLine( childValue ); - break; - } - *document_ << ","; - writeCommentAfterValueOnSameLine( childValue ); - } - unindent(); - writeWithIndent( "]" ); - } - else // output on a single line - { - assert( childValues_.size() == size ); - *document_ << "[ "; - for ( unsigned index =0; index < size; ++index ) - { - if ( index > 0 ) - *document_ << ", "; - *document_ << childValues_[index]; - } - *document_ << " ]"; - } - } -} - - -bool -StyledStreamWriter::isMultineArray( const Value &value ) -{ - int size = value.size(); - bool isMultiLine = size*3 >= rightMargin_ ; - childValues_.clear(); - for ( int index =0; index < size && !isMultiLine; ++index ) - { - const Value &childValue = value[index]; - isMultiLine = isMultiLine || - ( (childValue.isArray() || childValue.isObject()) && - childValue.size() > 0 ); - } - if ( !isMultiLine ) // check if line length > max line length - { - childValues_.reserve( size ); - addChildValues_ = true; - int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]' - for ( int index =0; index < size && !isMultiLine; ++index ) - { - writeValue( value[index] ); - lineLength += int( childValues_[index].length() ); - isMultiLine = isMultiLine && hasCommentForValue( value[index] ); - } - addChildValues_ = false; - isMultiLine = isMultiLine || lineLength >= rightMargin_; - } - return isMultiLine; -} - - -void -StyledStreamWriter::pushValue( const std::string &value ) -{ - if ( addChildValues_ ) - childValues_.push_back( value ); - else - *document_ << value; -} - - -void -StyledStreamWriter::writeIndent() -{ - /* - Some comments in this method would have been nice. ;-) - - if ( !document_.empty() ) - { - char last = document_[document_.length()-1]; - if ( last == ' ' ) // already indented - return; - if ( last != '\n' ) // Comments may add new-line - *document_ << '\n'; - } - */ - *document_ << '\n' << indentString_; -} - - -void -StyledStreamWriter::writeWithIndent( const std::string &value ) -{ - writeIndent(); - *document_ << value; -} - - -void -StyledStreamWriter::indent() -{ - indentString_ += indentation_; -} - - -void -StyledStreamWriter::unindent() -{ - assert( indentString_.size() >= indentation_.size() ); - indentString_.resize( indentString_.size() - indentation_.size() ); -} - - -void -StyledStreamWriter::writeCommentBeforeValue( const Value &root ) -{ - if ( !root.hasComment( commentBefore ) ) - return; - *document_ << normalizeEOL( root.getComment( commentBefore ) ); - *document_ << "\n"; -} - - -void -StyledStreamWriter::writeCommentAfterValueOnSameLine( const Value &root ) -{ - if ( root.hasComment( commentAfterOnSameLine ) ) - *document_ << " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) ); - - if ( root.hasComment( commentAfter ) ) - { - *document_ << "\n"; - *document_ << normalizeEOL( root.getComment( commentAfter ) ); - *document_ << "\n"; - } -} - - -bool -StyledStreamWriter::hasCommentForValue( const Value &value ) -{ - return value.hasComment( commentBefore ) - || value.hasComment( commentAfterOnSameLine ) - || value.hasComment( commentAfter ); -} - - -std::string -StyledStreamWriter::normalizeEOL( const std::string &text ) -{ - std::string normalized; - normalized.reserve( text.length() ); - const char *begin = text.c_str(); - const char *end = begin + text.length(); - const char *current = begin; - while ( current != end ) - { - char c = *current++; - if ( c == '\r' ) // mac or dos EOL - { - if ( *current == '\n' ) // convert dos EOL - ++current; - normalized += '\n'; - } - else // handle unix EOL & other char - normalized += c; - } - return normalized; -} - - -std::ostream& operator<<( std::ostream &sout, const Value &root ) -{ - Json::StyledStreamWriter writer; - writer.write(sout, root); - return sout; -} - - -} // namespace Json - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: src/lib_json/json_writer.cpp -// ////////////////////////////////////////////////////////////////////// - - - - - diff --git a/ui/webserver/launch-julia-webserver b/ui/webserver/launch-julia-webserver deleted file mode 100755 index d62a8733e7703..0000000000000 --- a/ui/webserver/launch-julia-webserver +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh -cd $(dirname $0) -test -x ../sbin/lighttpd || { echo "Install lighttpd with \"make -C deps install-lighttpd\" " && exit 0; } - - -for CANDIDATE in "../lib/lighttpd" "../lib" -do - if [ -d "$CANDIDATE" ]; then - MODULE_DIRECTORY="$CANDIDATE" - break - fi -done - -if [ -z $MODULE_DIRECTORY ]; then - echo "Could not find module directory."; exit 0 -fi - -echo "Connect to http://localhost:2000/ for the web REPL." -../sbin/lighttpd -D -f ../etc/lighttpd.conf -m $MODULE_DIRECTORY & -./julia-release-webserver -p 2001 diff --git a/ui/webserver/launch-julia-webserver.bat b/ui/webserver/launch-julia-webserver.bat deleted file mode 100644 index af0609695c316..0000000000000 --- a/ui/webserver/launch-julia-webserver.bat +++ /dev/null @@ -1,21 +0,0 @@ -@echo off -cd /d %~dp0 -if exist ..\sbin\lighttpd.exe goto lighttpd -if exist ..\sbin\nginx.exe goto nginx - -:error -echo "Please install either lighttpd or nginx into usr/sbin" - -:nginx -start ..\sbin\nginx -c ..\etc\nginx.conf -goto julia - -:lighttpd -start ..\sbin\lighttpd -D -f ..\etc\lighttpd.conf -m ..\lib -goto julia - -:julia -echo "Connect to http://localhost:2000/ for the web REPL." -julia-release-webserver -p 2001 - -:end \ No newline at end of file diff --git a/ui/webserver/message_types.h b/ui/webserver/message_types.h deleted file mode 100644 index 30f5df8b56ca7..0000000000000 --- a/ui/webserver/message_types.h +++ /dev/null @@ -1,120 +0,0 @@ -#ifndef notdefined -#define This_file_is_used_by_the_SCGI_server_and_the_Julia_back_end -#define NOTE_These_message_types_must_match_those_in_index_dot_js_and_repl_dot_js -#endif - -#ifndef notdefined -#define MSG_INPUT_NULL 0 -#else -__MSG_INPUT_NULL = uint8(0) # {}, null message (should be ignored) -#endif - -#ifndef notdefined -#define MSG_INPUT_START 1 -#else -__MSG_INPUT_START = uint8(1) # {user_name, session_name}, create/join a new session -#endif - -#ifndef notdefined -#define MSG_INPUT_POLL 2 -#else -__MSG_INPUT_POLL = uint8(2) # {}, poll the server -#endif - -#ifndef notdefined -#define MSG_INPUT_EVAL 3 -#else -__MSG_INPUT_EVAL = uint8(3) # {user_name, user_id, input}, evaluate an expression (this message is forwarded to julia) -#endif - -#ifndef notdefined -#define MSG_INPUT_REPLAY_HISTORY 4 -#else -__MSG_INPUT_REPLAY_HISTORY = uint8(4) # {}, ask the server to resend all messages -#endif - -#ifndef notdefined -#define MSG_INPUT_GET_USER 5 -#else -__MSG_INPUT_GET_USER = uint8(5) # {}, ask the server to send back the user -#endif - - - -#ifndef notdefined -#define MSG_OUTPUT_NULL 0 -#else -__MSG_OUTPUT_NULL = uint8(0) # {}, null message (should be ignored) -#endif - -#ifndef notdefined -#define MSG_OUTPUT_WELCOME 1 -#else -__MSG_OUTPUT_WELCOME = uint8(1) # {}, successfully created/joined the session -#endif - -#ifndef notdefined -#define MSG_OUTPUT_READY 2 -#else -__MSG_OUTPUT_READY = uint8(2) # {}, ready for input, sent only when session starts (stored in replay history) -#endif - -#ifndef notdefined -#define MSG_OUTPUT_MESSAGE 3 -#else -__MSG_OUTPUT_MESSAGE = uint8(3) # {message}, send a message to the user (stored in replay history) -#endif - -#ifndef notdefined -#define MSG_OUTPUT_OTHER 4 -#else -__MSG_OUTPUT_OTHER = uint8(4) # {text}, standard output pipe (stored in replay history) -#endif - -#ifndef notdefined -#define MSG_OUTPUT_EVAL_INPUT 5 -#else -__MSG_OUTPUT_EVAL_INPUT = uint8(5) # {user_id, user_name, input}, input from a user (this message comes from julia, stored in replay history) -#endif - -#ifndef notdefined -#define MSG_OUTPUT_FATAL_ERROR 6 -#else -__MSG_OUTPUT_FATAL_ERROR = uint8(6) # {message}, fatal error message (terminates session, stored in replay history) -#endif - -#ifndef notdefined -#define MSG_OUTPUT_EVAL_INCOMPLETE 7 -#else -__MSG_OUTPUT_EVAL_INCOMPLETE = uint8(7) # {user_id}, incomplete expression (this message comes from julia) -#endif - -#ifndef notdefined -#define MSG_OUTPUT_EVAL_RESULT 8 -#else -__MSG_OUTPUT_EVAL_RESULT = uint8(8) # {user_id, result}, expression result (this message comes from julia, stored in replay history) -#endif - -#ifndef notdefined -#define MSG_OUTPUT_EVAL_ERROR 9 -#else -__MSG_OUTPUT_EVAL_ERROR = uint8(9) # {user_id, message}, error evaluating expression (this message comes from julia, stored in replay history) -#endif - -#ifndef notdefined -#define MSG_OUTPUT_PLOT 10 -#else -__MSG_OUTPUT_PLOT = uint8(10) # {type, ...} create a plot, the format of the data depends on the type of plot (this message comes from julia, stored in replay history) -#endif - -#ifndef notdefined -#define MSG_OUTPUT_GET_USER 11 -#else -__MSG_OUTPUT_GET_USER = uint8(11) # {user_name, user_id} response to MSG_GET_USER -#endif - -#ifndef notdefined -#define MSG_OUTPUT_HTML 12 -#else -__MSG_OUTPUT_HTML = uint8(12) # {html} raw html -#endif diff --git a/ui/webserver/server.cpp b/ui/webserver/server.cpp deleted file mode 100755 index a5798e9a5c9c4..0000000000000 --- a/ui/webserver/server.cpp +++ /dev/null @@ -1,669 +0,0 @@ -#include -#include "server.h" -#include "../../deps/libuv/include/uv.h" - -using namespace std; - -namespace scgi -{ -// convert a value to a string -template string to_string(const T& t) -{ - // convert a value to a string - stringstream ss; - ss< T from_string(const string& t) -{ - // parse a value from a string - T ret; - stringstream(t)>>ret; - return ret; -} - -// strip a string of leading and trailing whitespace -string strip(string str) -{ - // remove leading whitespace - while (!str.empty()) - { - if (str[0] == ' ' || str[0] == '\t' || str[0] == '\n' || str[0] == '\r') - str = str.substr(1, str.size()-1); - else - break; - } - // remove trailing whitespace - while (!str.empty()) - { - if (str[str.size()-1] == ' ' || str[str.size()-1] == '\t' || str[str.size()-1] == '\n' || str[str.size()-1] == '\r') - str = str.substr(0, str.size()-1); - else - break; - } - // return the result - return str; -} - -// convert a string to lowercase -string to_lower(string str) -{ - // convert a string to lowercase - for (size_t j = 0; j < str.size(); j++) - str[j] = tolower(str[j]); - return str; -} - -// convert a string to uppercase -string to_upper(string str) -{ - // convert a string to uppercase - for (size_t j = 0; j < str.size(); j++) - str[j] = toupper(str[j]); - return str; -} - -// split strings by a character -vector split(string str, char separator) -{ - // split a string - vector result; - string current_str; - for (size_t i = 0; i < str.size(); i++) - { - if (str[i] == separator) - { - result.push_back(current_str); - current_str = ""; - } - else - current_str += str.substr(i, 1); - } - result.push_back(current_str); - return result; -} - -// decode data of type application/x-www-form-urlencoded -string url_decode(string str) -{ - // replace + characters with spaces - for (size_t i = 0; i < str.size(); i++) - { - if (str[i] == '+') - str[i] = ' '; - } - // escape characters - for (size_t i = 0; i < str.size(); i++) - { - if (str[i] == '%') - { - // get the next two characters - string code = str.substr(i+1, 2); - - // read the value - unsigned int x; - stringstream stream; - stream<>x; - char c = (char)x; - - // replace the character - str = str.substr(0, i)+c+str.substr(i+3, str.size()-(i+3)); - } - } - // return the result - return str; -} -} - -int scgi::request::get_cookie_num() -{ - // return the number of cookies - return (int)cookie_list.size(); -} - -string scgi::request::get_cookie_name(int id) -{ - // get the name of a particular cookie - return cookie_list[id].name; -} - -string scgi::request::get_cookie_value(string name) -{ - // search for the cookie by name - for (size_t i = 0; i < cookie_list.size(); i++) - { - // compare the lowercase names - if (to_lower(name) == to_lower(cookie_list[i].name)) - return cookie_list[i].value; - } - return ""; -} - -bool scgi::request::get_cookie_exists(string name) -{ - // search for the cookie by name - for (size_t i = 0; i < cookie_list.size(); i++) - { - // compare the lowercase names - if (to_lower(name) == to_lower(cookie_list[i].name)) - return true; - } - return false; -} - -using namespace scgi; - -int scgi::request::get_field_num() -{ - // return the number of fields - return (int)field_list.size(); -} - -string scgi::request::get_field_name(int id) -{ - // get the name of a particular field - return field_list[id].name; -} - -string scgi::request::get_field_value(string name) -{ - // search for the field by name - for (size_t i = 0; i < field_list.size(); i++) - { - // compare the lowercase names - if (to_lower(name) == to_lower(field_list[i].name)) - return field_list[i].value; - } - return ""; -} - -string scgi::request::get_field_filename(string name) -{ - // search for the field by name - for (size_t i = 0; i < field_list.size(); i++) - { - // compare the lowercase names - if (to_lower(name) == to_lower(field_list[i].name)) - return field_list[i].filename; - } - return ""; -} - -bool scgi::request::get_field_exists(string name) -{ - // search for the field by name - for (size_t i = 0; i < field_list.size(); i++) - { - // compare the lowercase names - if (to_lower(name) == to_lower(field_list[i].name)) - return true; - } - return false; -} - -namespace scgi -{ - -#define PASS_ON(f) stream->read_cb = &f; \ - uv_buf_t buf2; \ - buf2.base=const_cast(pos); \ - buf2.len=buf.len-nread-(pos-buf.base); \ - f(stream,nread-(pos-buf.base),buf2); - -void request_aborted(uv_handle_t *stream) -{ - std::cout<<"Request Aborted"; - delete (reading_in_progress*)stream->data; - delete (uv_tcp_t*)stream; -} - -void abort_request(uv_stream_t *stream) -{ - uv_close((uv_handle_t*)stream,request_aborted); -} - -void read_body(uv_stream_t* stream, ssize_t nread, uv_buf_t buf) -{ - if(nread<0) { - abort_request(stream); - return; - } - - reading_in_progress *p = (reading_in_progress*)(stream->data); - if(p->isComma) { - buf.base=buf.base+2; - nread-=2; - } - if(p->bufBase==0) p->bufBase=buf.base; - if(p->body_length>p->pos+nread) { - p->body.append(buf.base,nread); - p->pos+=nread; - } else { - p->body.append(buf.base,p->body_length-p->pos); - //do the actual processing - // get the type of request - bool get = true; - - bool request_method_exists = false; - string request_method; - for (size_t i = 0; i < p->header_list.size(); i++) - { - if (to_upper(p->header_list[i].name) == "REQUEST_METHOD") - { - request_method_exists = true; - request_method = p->header_list[i].value; - break; - } - } - - if (request_method_exists) - { - if (to_upper(request_method) == "POST") - get = false; - } - if (get) - { - // the encoding for GET is application/x-www-form-urlencoded - bool query_string_exists = false; - string query_string; - for (size_t i = 0; i < p->header_list.size(); i++) - { - if (to_upper(p->header_list[i].name) == "QUERY_STRING") - { - query_string_exists = true; - query_string = p->header_list[i].value; - break; - } - } - - if (query_string_exists) - { - // get the key=value strings - vector pairs = split(query_string, '&'); - - // construct the values - for (size_t i = 0; i < pairs.size(); i++) - { - vector pair = split(pairs[i], '='); - if (pair.size() == 2) - { - field field_obj; - field_obj.name = url_decode(strip(pair[0])); - field_obj.value = url_decode(strip(pair[1])); - p->request_obj.field_list.push_back(field_obj); - } - } - } - } - else - { - // the encoding for POST can be application/x-www-form-urlencoded or multipart/form-data - bool content_type_exists = false; - string content_type; - for (size_t i = 0; i < p->header_list.size(); i++) - { - if (to_upper(p->header_list[i].name) == "CONTENT_TYPE") - { - content_type_exists = true; - content_type = p->header_list[i].value; - break; - } - } - - if (content_type_exists) - { - // get the subparts of the CONTENT_TYPE header - vector content_type_fields = split(content_type, ';'); - for (size_t i = 0; i < content_type_fields.size(); i++) - content_type_fields[i] = strip(content_type_fields[i]); - - // application/x-www-form-urlencoded - if (to_lower(content_type_fields[0]) == "application/x-www-form-urlencoded") - { - // get the key=value strings - vector pairs = split(p->body, '&'); - - // construct the values - for (size_t i = 0; i < pairs.size(); i++) - { - vector pair = split(pairs[i], '='); - if (pair.size() == 2) - { - field field_obj; - field_obj.name = url_decode(strip(pair[0])); - field_obj.value = url_decode(strip(pair[1])); - p->request_obj.field_list.push_back(field_obj); - } - } - } - - // multipart/form-data - if (to_lower(content_type_fields[0]) == "multipart/form-data") - { - // get the boundary fields - vector boundary_fields = split(content_type_fields[1], '='); - for (size_t i = 0; i < boundary_fields.size(); i++) - boundary_fields[i] = strip(boundary_fields[i]); - if (boundary_fields.size() == 2) - { - // extract the boundary - string boundary = boundary_fields[1]; - - // get the field data from the body - string field_data = p->body; - - // loop through the fields - while (true) - { - // make a new field - field field_obj; - - // skip whitespace - while (!field_data.empty()) - { - if (field_data[0] != ' ' && field_data[0] != '\t' && field_data[0] != '\r' && field_data[0] != '\n') - break; - field_data = field_data.substr(1, field_data.size()-1); - } - - // skip the boundary - if (field_data.size() < boundary.size()+2) - break; - if (field_data.substr(0, boundary.size()+2) != "--"+boundary) - break; - field_data = field_data.substr(boundary.size()+2, field_data.size()-(boundary.size()+2)); - - // skip whitespace - while (!field_data.empty()) - { - if (field_data[0] != ' ' && field_data[0] != '\t' && field_data[0] != '\r' && field_data[0] != '\n') - break; - field_data = field_data.substr(1, field_data.size()-1); - } - - // check if we have reached the end - if (field_data.size() < 2) - break; - if (field_data.substr(0, 2) == "--") - break; - - // start parsing lines - while (true) - { - // get the line - size_t newline_pos = field_data.size(); - for (size_t i = 0; i < field_data.size(); i++) - { - if (field_data[i] == '\n') - { - newline_pos = i; - break; - } - } - string line = strip(field_data.substr(0, newline_pos)); - field_data = field_data.substr(newline_pos+1, field_data.size()-(newline_pos+1)); - - // check if we're done parsing the headers - if (line.empty()) - break; - - // check if this is a "Content-Disposition" header - string disposition_header = "Content-Disposition:"; - if (line.size() >= disposition_header.size()) - { - if (to_lower(line.substr(0, disposition_header.size())) == to_lower(disposition_header)) - { - // take out the "Content-Disposition:" tag - line = line.substr(disposition_header.size(), line.size()-disposition_header.size()); - - // get the disposition fields - vector disposition_fields = split(line, ';'); - for (size_t i = 0; i < disposition_fields.size(); i++) - disposition_fields[i] = strip(disposition_fields[i]); - - // parse the fields - for (size_t i = 0; i < disposition_fields.size(); i++) - { - // get the key=value pair - vector pair = split(disposition_fields[i], '='); - if (pair.size() == 2) - { - // name - if (to_upper(strip(pair[0])) == "NAME") - { - // get the name - field_obj.name = strip(pair[1]); - - // strip the quotes - if (field_obj.name.size() >= 2) - { - if (field_obj.name[0] == '\"' && field_obj.name[field_obj.name.size()-1] == '\"') - field_obj.name = field_obj.name.substr(1, field_obj.name.size()-2); - } - - // move on - continue; - } - - // filename - if (to_upper(strip(pair[0])) == "FILENAME") - { - // get the filename - field_obj.filename = strip(pair[1]); - - // strip the quotes - if (field_obj.filename.size() >= 2) - { - if (field_obj.filename[0] == '\"' && field_obj.filename[field_obj.filename.size()-1] == '\"') - field_obj.filename = field_obj.filename.substr(1, field_obj.filename.size()-2); - } - - // move on - continue; - } - } - } - } - } - } - - // find out how much data to extract - size_t field_size = 0; - for (size_t i = 0; i < field_data.size()-(boundary.size()+2); i++) - { - if (field_data.substr(i, boundary.size()+3) == "\n--"+boundary || field_data.substr(i, boundary.size()+4) == "\r\n--"+boundary) - { - field_size = i; - break; - } - } - - // extract the data - field_obj.value = field_data.substr(0, field_size); - field_data = field_data.substr(field_size, field_data.size()-field_size); - - // add the field to the list - p->request_obj.field_list.push_back(field_obj); - } - } - } - } - } - - // get the response - p->cb(&(p->request_obj),stream); - } - delete[] p->bufBase; - p->bufBase=0; -} - - -void read_header(uv_stream_t* stream, ssize_t nread, uv_buf_t buf) -{ - if(nread<0) { - abort_request(stream); - return; - } - - const char *pos = buf.base; - reading_in_progress *p = (reading_in_progress*)(stream->data); - if(p->bufBase==0)p->bufBase=buf.base; - int i; - if(p->isComma) { - (++(p->pos),++pos); - p->isComma=false; - } - for(i=0; iposheader_length; ++i, ++pos, ++p->pos) - { - if(p->inName) { - if(*pos==0) - p->inName=false; - else - p->current_header.name+=*pos; - } else { - if(*pos!=0) - p->current_header.value+=*pos; - else { - //header complete - - // check if this is the "CONTENT_LENGTH" header - if (p->header_list.empty()) - p->body_length = from_string(p->current_header.value); - - // add the header to the list - p->header_list.push_back(p->current_header); //this creates a copy - p->current_header.name=""; - p->current_header.value=""; - p->inName=true; - } - } - } - if(p->current_header.name!="") - p->header_list.push_back(p->current_header); - if(p->pos>=p->header_length) { - //process cookies - for (size_t j = 0; j < p->header_list.size(); j++) - { - if (to_upper(p->header_list[j].name) == "HTTP_COOKIE") - { - vector crumb_list = split(p->header_list[j].value, ';'); - for (size_t k = 0; k < crumb_list.size(); k++) - { - // get the crumb - vector crumb = split(crumb_list[k], '='); - if (crumb.size() == 2) - { - // create the cookie - cookie cookie_obj; - cookie_obj.name = strip(crumb[0]); - cookie_obj.value = strip(crumb[1]); - - // add the cookie the list - p->request_obj.cookie_list.push_back(cookie_obj); - } - } - } - } - p->pos=0; - p->isComma=true; - PASS_ON(read_body) - } else { - delete[] p->bufBase; - p->bufBase=0; - } -} - -//read the length of the header; -void read_header_length(uv_stream_t* stream, ssize_t nread, uv_buf_t buf) -{ -#ifdef DEBUG_TRACE - cout << "Header Length!\n"; -#endif - if(nread<0) { - abort_request(stream); - return; - } - - const char *pos = buf.base; - reading_in_progress *p = (reading_in_progress*)(stream->data); - if(p->bufBase==0) p->bufBase=buf.base; - int i; - for(i = 0; iheader_length_str+=*pos; - } else - break; - } - if(buf.len>0&&*pos==':') { - //we're done - p->header_length = from_string(p->header_length_str); - PASS_ON(read_header) - } else { - delete[] p->bufBase; - p->bufBase=0; - } -} - -uv_buf_t allocBuffer(uv_handle_t* handle, size_t suggested_size) -{ - uv_buf_t buf; - buf.base = new char[suggested_size]; - buf.len = suggested_size; - return buf; -} - -// handle a single request -void handle_request_and_release_socket(uv_stream_t* server, int status) -{ - uv_tcp_t *client = new uv_tcp_t; - uv_tcp_init(uv_default_loop(),client); - uv_accept((uv_stream_t*)server,(uv_stream_t*)client); - -#ifdef DEBUG_TRACE - std::cout<<"Accepted connection!\n"; -#endif - - // create the request object - - reading_in_progress *p= new reading_in_progress; - p->body_length=0; - p->inName=true; - p->header_length=0; - p->pos=0; - p->isComma=true; - p->cstr=0; - p->cb=(callback)server->data; - p->bufBase=0; - client->data=p; - - uv_read_start((uv_stream_t*)client,&allocBuffer,&read_header_length); -} - -void run_server(int port, callback cb) -{ - struct sockaddr_in addr = uv_ip4_addr("0.0.0.0", port); - uv_tcp_t server; - int err; - - server.data=(void*)cb; - - err = uv_tcp_init(uv_default_loop(), &server); - //assert(err == 0); - err = uv_tcp_bind(&server, addr); - //assert(err == 0); - -#ifdef __WIN32__ - uv_tcp_simultaneous_accepts(&server,0); -#endif - - err = uv_listen((uv_stream_t*)&server, 128, &handle_request_and_release_socket); - //assert(r == 0) - - uv_run(uv_default_loop()); -} - -} diff --git a/ui/webserver/server.h b/ui/webserver/server.h deleted file mode 100755 index 6f82e757707ad..0000000000000 --- a/ui/webserver/server.h +++ /dev/null @@ -1,116 +0,0 @@ -#ifndef INCLUDE_SERVER -#define INCLUDE_SERVER - -#include "../../deps/libuv/include/uv.h" -#include -#include -#include -//#define JULIA_DEBUG_TRACE -//#define CPP_DEBUG_TRACE - -namespace scgi -{ - - - // represents a GET/POST field - class field - { - public: - std::string name; - std::string value; - std::string filename; - }; - - // represents a cookie - class cookie - { - public: - std::string name; - std::string value; - }; - - // represents an HTTP request - class request - { - public: - ///////////////////////////////////////////// - // form fields - ///////////////////////////////////////////// - - // get the number of fields - int get_field_num(); - - // get a field name - std::string get_field_name(int id); - - // get a field value (not case sensitive) - std::string get_field_value(std::string name); - - // get a field filename (for file uploads; not case sensitive) - std::string get_field_filename(std::string name); - - // get whether a field exists (not case sensitive) - bool get_field_exists(std::string name); - - // the form fields - std::vector field_list; - - ///////////////////////////////////////////// - // cookies - ///////////////////////////////////////////// - - // get the number of cookies - int get_cookie_num(); - - // get a cookie name - std::string get_cookie_name(int id); - - // get a cookie value (not case sensitive) - std::string get_cookie_value(std::string name); - - // get a cookie filename (for file uploads; not case sensitive) - std::string get_cookie_filename(std::string name); - - // get whether a cookie exists (not case sensitive) - bool get_cookie_exists(std::string name); - - // the form cookies - std::vector cookie_list; - }; - - // represents an SCGI header - class header - { - public: - std::string name; - std::string value; - }; - - // the callback function for requests: string response = callback(request req); - // if the "multithreaded" parameter of run_server is true, this callback must be - // thread safe! - typedef void (*callback)(request*,uv_stream_t *client); - - struct reading_in_progress { - std::string header_length_str; - int header_length; - int body_length; - int pos; - std::vector
header_list; - header current_header; - bool inName; - bool isComma; - request request_obj; - char *cstr; - std::string body; - callback cb; - const char *bufBase; - }; - - // run the server - this blocks forever - void run_server(int port, callback cb); -} - -struct julia_session; - -#endif diff --git a/ui/webserver/webserver.cpp b/ui/webserver/webserver.cpp deleted file mode 100755 index f60969e7d0877..0000000000000 --- a/ui/webserver/webserver.cpp +++ /dev/null @@ -1,1134 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "server.h" -#include "json.h" -#include "message_types.h" -#ifndef __WIN32__ -#include -#endif - -extern char **environ; //only unistd.h post- POSIX 2008 - -using namespace std; -using namespace scgi; - -///////////////////////////////////////////////////////////////////////////// -// string helper functions -///////////////////////////////////////////////////////////////////////////// - -// convert a value to a string -template std::string to_string(const T& t) -{ - // convert a value to a string - stringstream ss; - ss< T from_string(const std::string& t) -{ - // parse a value from a string - T ret; - stringstream(t)>>ret; - return ret; -} - -///////////////////////////////////////////////////////////////////////////// -// messages -///////////////////////////////////////////////////////////////////////////// - -// a message -class message -{ -public: - // see ui/webserver/julia_web_base.j for documentation - uint8_t type; - vector args; -}; - -///////////////////////////////////////////////////////////////////////////// -// julia_sessions -///////////////////////////////////////////////////////////////////////////// - -// if a julia_session hasn't been queried in this time, it dies -const int WEB_SESSION_TIMEOUT = 20; // in seconds - -// a web julia_session -struct web_session { - // time since watchdog was last "pet" - time_t update_time; - - // to be sent to the client - vector outbox; - - // the user name - string user_name; -}; - -enum julia_session_status -{ - SESSION_WAITING_FOR_PORT_NUM, - SESSION_NORMAL, - SESSION_TERMINATING, - SESSION_KILLED, -}; - -// a julia_session -struct julia_session -{ - // a map from julia_session tokens to web julia_sessions that use this julia julia_session - map web_session_map; - - // the session name - string session_name; - - // to be sent to julia - string inbox_std; - - // to be sent to julia - vector inbox; - - // to be sent to the client as MSG_OTHER_OUTPUT - string outbox_std; - - // to be converted into messages - string outbox_raw; - - //temporary buffer for reading the portnumber - string portbuf; - - // keep track of messages sent to all the clients (not messages sent to particular users) - vector outbox_history; - - //pipes - uv_process_t *proc; - uv_pipe_t *julia_in; - uv_pipe_t *julia_out; - uv_pipe_t *julia_err; - - // the socket for communicating to julia - uv_tcp_t *sock; - - // whether the julia_session should terminate - bool should_terminate; - - // the status of the julia_session - julia_session_status status; - - //notifier - uv_async_t *data_notifier; -}; - -// a list of all julia_sessions -vector julia_session_list; - -void close_process(julia_session *julia_session_ptr); - -///////////////////////////////////////////////////////////////////////////// -// THREAD: inbox_thread (from browser to julia) -///////////////////////////////////////////////////////////////////////////// - -// add to the inbox regularly according to this interval -const int INBOX_INTERVAL = 10000; // in nanoseconds - -void free_socket_write_buffer(uv_write_t* req, int status) -{ - delete[] ((char*)req->data); - delete req; -} - -void free_write_buffer(uv_write_t* req, int status) -{ - delete[] (char*)req->data; - delete req; -} - -static uv_buf_t alloc_buf(uv_handle_t* handle, size_t suggested_size) { - uv_buf_t buf; - buf.len = suggested_size; - buf.base = new char[suggested_size]; - return buf; -} - - -//when data arrives from client (currently async, will be websocket) -void read_client(uv_async_t* handle, int status) -{ - julia_session *julia_session_ptr=(julia_session*)handle->data; - - if(julia_session_ptr->status != SESSION_NORMAL) { - return; - } - - // get the inbox data - string inbox = julia_session_ptr->inbox_std; - - // if there is no inbox data and no messages to send, or if julia isn't ready, wait and try again - if ((inbox == "" && julia_session_ptr->inbox.empty()) || julia_session_ptr->status != SESSION_NORMAL) - { - return; - } - - if(inbox.size()>0) { - char *cstr = new char [inbox.size()]; - memcpy (cstr, inbox.data(), inbox.size()); - - uv_buf_t buffer; - buffer.base = cstr; - buffer.len = inbox.size(); - - uv_write_t *req = new uv_write_s; - req->data=(void*)cstr; - uv_write(req,(uv_stream_t*)julia_session_ptr->julia_in,&buffer,1,&free_write_buffer); - } - - // write messages to julia - for (size_t i = 0; i < julia_session_ptr->inbox.size(); i++) - { - // get the message - message msg = julia_session_ptr->inbox[i]; - - uv_write_t *req2 = new uv_write_s; - - size_t total_size=2+4*msg.args.size(); - for (size_t j = 0; j < msg.args.size(); j++) { - total_size+=msg.args[j].size(); - } - char *msg_buf = new char[total_size]; - uv_buf_t buf; - buf.base=msg_buf; - buf.len=total_size; - req2->data = msg_buf; - - *(msg_buf++)=msg.type; - *(msg_buf++)=msg.args.size(); - - if(msg.args.size()>0) { - - // iterate through the arguments - for (size_t j = 0; j < msg.args.size(); j++) { - // write the size of the argument - *((uint32_t*)(msg_buf)) = (uint32_t)msg.args[j].size(); - memcpy((msg_buf+sizeof(uint32_t)),msg.args[j].data(),msg.args[j].size()); - msg_buf+=sizeof(uint32_t)+msg.args[j].size(); - } - } - - - uv_buf_t buf2; - uv_write(req2,(uv_stream_t*)julia_session_ptr->sock,&buf,1,&free_socket_write_buffer); - } - julia_session_ptr->inbox.clear(); - - // remove the written data from the inbox - julia_session_ptr->inbox_std.clear(); -} - -///////////////////////////////////////////////////////////////////////////// -// THREAD: outbox_thread (from julia to browser) -///////////////////////////////////////////////////////////////////////////// - -// add to the outbox regularly according to this interval -const int OUTBOX_INTERVAL = 10000; // in nanoseconds - -// check for the port number from julia according to this interval -const int PORT_NUM_INTERVAL = 10000; // in nanoseconds - -void socketClosed(uv_handle_t *stream) -{ - delete (uv_tcp_t *)stream; -} - -//read from julia on metadata socket (typically starts at 4444) -void readSocketData(uv_stream_t *sock,ssize_t nread, uv_buf_t buf) -{ - julia_session *julia_session_ptr=(julia_session*)sock->data; - if(nread == -1) - return close_process(julia_session_ptr); - else if(julia_session_ptr->status != SESSION_NORMAL) - return; - - julia_session_ptr->outbox_raw.append(buf.base,nread); - - // try to convert the raw outbox data into messages - string outbox_raw = julia_session_ptr->outbox_raw; - while (outbox_raw.size() >= 2) - { - // construct the message - message msg; - - // get the message type - msg.type = (*((uint8_t*)(&outbox_raw[0]))); - - // get the number of arguments - uint8_t arg_num = *((uint8_t*)(&outbox_raw[1])); - - // try to read the arguments - int pos = 2; - for (uint8_t i = 0; i < arg_num; i++) - { - // make sure there is enough data left to read - if (outbox_raw.size() < pos+4) - goto done; - - // get the size of this argument - uint32_t arg_size = *((uint32_t*)(&outbox_raw[pos])); - pos += 4; - - // make sure there is enough data left to read - if (outbox_raw.size() < pos+arg_size) - goto done; - - // get the argument - msg.args.push_back(outbox_raw.substr(pos, arg_size)); - pos += arg_size; - } - - // check if we have a whole message - if (msg.args.size() == arg_num) - { - // we have a whole message - eat it from outbox_raw - outbox_raw = julia_session_ptr->outbox_raw = outbox_raw.substr(pos, outbox_raw.size()-pos); - - - // add the message to the outbox queue of all the users of this julia session if necessary - if (msg.type == MSG_OUTPUT_EVAL_INPUT || - msg.type == MSG_OUTPUT_EVAL_RESULT || - msg.type == MSG_OUTPUT_EVAL_ERROR || - msg.type == MSG_OUTPUT_PLOT || - msg.type == MSG_OUTPUT_HTML) { - julia_session_ptr->outbox_history.push_back(msg); - for (map::iterator iter = julia_session_ptr->web_session_map.begin(); iter != julia_session_ptr->web_session_map.end(); iter++) - iter->second.outbox.push_back(msg); - } - if (msg.type == MSG_OUTPUT_EVAL_INCOMPLETE) { - for (map::iterator iter = julia_session_ptr->web_session_map.begin(); iter != julia_session_ptr->web_session_map.end(); iter++) { - if (iter->first == msg.args[0]) - iter->second.outbox.push_back(msg); - } - } - } - } - - done: - return; -} - -void cleanup_web_sessions(julia_session *session, time_t t); -void cleanup_session(julia_session *session); - -void connected(uv_connect_t* req, int status) -{ - julia_session *julia_session_ptr=(julia_session*)req->handle->data; - if(status == -1) { - std::cerr << "An error occured during the connection: " << uv_last_error(uv_default_loop()).code; - cleanup_web_sessions(julia_session_ptr,0); //close all web sessions - cleanup_session(julia_session_ptr); - } else { - // switch to normal operation - julia_session_ptr->status = SESSION_NORMAL; - - // send a ready message - message ready_message; - ready_message.type = MSG_OUTPUT_READY; - julia_session_ptr->outbox_history.push_back(ready_message); - for (map::iterator iter = julia_session_ptr->web_session_map.begin(); iter != julia_session_ptr->web_session_map.end(); iter++) - iter->second.outbox.push_back(ready_message); -#ifdef JULIA_DEBUG_TRACE - cout<<"Julia Process Connected\n"; -#endif - uv_read_start((uv_stream_t*)julia_session_ptr->sock,&alloc_buf,readSocketData); - } - delete req; -} - - -#define JL_TCP_LOOP uv_default_loop() - -//read from julia (on stdin) -void julia_incoming(uv_stream_t* stream, ssize_t nread, uv_buf_t buf) -{ -#ifdef JULIA_DEBUG_TRACE - cout<<"Recevied Data from Julia on STDOUT:\n"; - cout<data; - - if(nread==-1) - return close_process(julia_session_ptr); - - // prepare for reading from julia - uv_pipe_t *pipe = julia_session_ptr->julia_out; - - - // send the outbox data to the client - if (julia_session_ptr->status == SESSION_NORMAL) - { - // just dump the output into the julia_session - julia_session_ptr->outbox_std.append(buf.base,nread); - } - - // get the port number - if (julia_session_ptr->status == SESSION_WAITING_FOR_PORT_NUM) - { - if(stream!=(uv_stream_t*)julia_session_ptr->julia_out) //allow debugging tools to print to stderr before startup - return; - julia_session_ptr->portbuf.append(buf.base,nread); - // wait for a newline - size_t newline_pos = julia_session_ptr->portbuf.find("\n"); - if (newline_pos == string::npos) - { - return; - } - - // read the port number - string num_string = julia_session_ptr->portbuf.substr(0, newline_pos); - julia_session_ptr->portbuf = julia_session_ptr->portbuf.substr(newline_pos+1, julia_session_ptr->portbuf.size()-(newline_pos+1)); - int port_num = from_string(num_string); - - // start - julia_session_ptr->sock = new uv_tcp_t; - uv_tcp_init(JL_TCP_LOOP,julia_session_ptr->sock); - uv_connect_t *c=new uv_connect_t; - sockaddr_in address=uv_ip4_addr("127.0.0.1", port_num); - julia_session_ptr->sock->data=julia_session_ptr; - uv_tcp_connect(c, julia_session_ptr->sock,address,&connected); - - cout << "Port number received. Connecting ...\n"; - } - - - delete[] buf.base; -} - -///////////////////////////////////////////////////////////////////////////// -// THREAD: watchdog_thread -///////////////////////////////////////////////////////////////////////////// - -// the watchdog runs regularly according to this interval -const int WATCHDOG_INTERVAL = 10000; // every second - -// this is defined below but we need it here too -std::string create_julia_session(bool idle); - - -void pipes_done(uv_handle_t *pipe) -{ - julia_session *julia_session_ptr = ((julia_session*)pipe->data); - if((uv_pipe_t*)pipe==julia_session_ptr->julia_in) julia_session_ptr->julia_in=0; - else if((uv_pipe_t*)pipe==julia_session_ptr->julia_out) julia_session_ptr->julia_out=0; - else if((uv_pipe_t*)pipe==julia_session_ptr->julia_err) julia_session_ptr->julia_err=0; - delete (uv_pipe_t*)pipe; -} - -void process_exited(uv_handle_t*p) -{ - julia_session *julia_session_ptr = (julia_session*)p->data; - delete (uv_process_t*)p; - julia_session_ptr->proc = 0; - if(julia_session_ptr->status != SESSION_KILLED) { - julia_session_ptr->status = SESSION_TERMINATING; - close_process(julia_session_ptr); - } - cout<<"Process Exited\n"; -} - -void process_exited2(uv_process_t*p, int exit_status, int term_signal) -{ - process_exited((uv_handle_t*)p); -} - -void close_process(julia_session *julia_session_ptr) -{ - if(julia_session_ptr->status==SESSION_KILLED) - return; - - julia_session_ptr->status = SESSION_KILLED; - - // close the pipes - if(julia_session_ptr->julia_in != 0) - uv_close((uv_handle_t*)julia_session_ptr->julia_in,&pipes_done); - if(julia_session_ptr->julia_out != 0) - uv_close((uv_handle_t*)julia_session_ptr->julia_out,&pipes_done); - if(julia_session_ptr->julia_err != 0) - uv_close((uv_handle_t*)julia_session_ptr->julia_err,&pipes_done); - if(julia_session_ptr->sock != 0) - uv_close((uv_handle_t*)julia_session_ptr->sock,&socketClosed); - - if(julia_session_ptr->proc != 0) { - // kill the julia process - uv_process_kill(julia_session_ptr->proc, 9); - uv_close((uv_handle_t*)julia_session_ptr->proc,&process_exited); - } -} - -void cleanup_web_sessions(julia_session *session, time_t t) -{ - vector web_session_zombies; - for (map::iterator iter = session->web_session_map.begin(); iter != session->web_session_map.end(); iter++) - { - if ((t == 0) || (t-(iter->second).update_time >= WEB_SESSION_TIMEOUT)) - web_session_zombies.push_back(iter->first); - } - for (size_t j = 0; j < web_session_zombies.size(); j++) - { - cout<<"User \""<web_session_map[web_session_zombies[j]].user_name<<"\" has left session \""<session_name<<"\".\n"; - session->web_session_map.erase(web_session_zombies[j]); - } -} - -void cleanup_session(julia_session *session) -{ - if(session->status==SESSION_NORMAL) - session->status = SESSION_TERMINATING; - close_process(session); -} - -void watchdog(uv_timer_t* handle, int status) -{ - // get the current time - time_t t = time(0); - - // delete old web sessions and mark julia sessions with no web sessions as terminating - for (size_t i = 0; i < julia_session_list.size(); i++) - { - julia_session* julia_session_ptr = julia_session_list[i]; - cleanup_web_sessions(julia_session_ptr,t); - if (julia_session_ptr->web_session_map.empty()) { - cleanup_session(julia_session_ptr); - } - } - - // remove all sessions that have successfully closed - for (size_t i = 0; i < julia_session_list.size(); i++) - { - julia_session* julia_session_ptr = julia_session_list[i]; - if(julia_session_ptr->status != SESSION_TERMINATING && julia_session_ptr->status != SESSION_KILLED) - continue; - if(julia_session_ptr->proc==0&&julia_session_ptr->julia_in==0&&julia_session_ptr->julia_out==0&&julia_session_ptr->julia_err==0) { - // print a message - cout<<"Session \""<session_name<<"\" is terminating because it has no more users.\n"; - - // remove the session from the map - delete julia_session_ptr; - julia_session_list.erase(julia_session_list.begin()+i); - - // print the number of open sessions - if (julia_session_list.size() == 1) - cout<session_name == session_name && session_name != "") - { - // create a user for this session - web_session ws; - ws.update_time = time(0); - ws.user_name = user_name; - message welcome_message; - welcome_message.type = MSG_OUTPUT_WELCOME; - ws.outbox.push_back(welcome_message); - julia_session_list[i]->web_session_map[session_token] = ws; - - // print a message - cout<<"New user \""<= MAX_CONCURRENT_SESSIONS) - return ""; - - // create the session - julia_session* session_data = new julia_session; - - session_data->sock = NULL; - - // generate the web session - web_session ws; - ws.update_time = time(0); - ws.user_name = user_name; - message welcome_message; - welcome_message.type = MSG_OUTPUT_WELCOME; - ws.outbox.push_back(welcome_message); - session_data->web_session_map[session_token] = ws; - - // session name - session_data->session_name = session_name; - - // keep the julia_session alive for now - //session_data->inbox_thread_alive = true; - //session_data->outbox_thread_alive = true; - session_data->should_terminate = false; - session_data->status = SESSION_WAITING_FOR_PORT_NUM; - - session_data->proc=new uv_process_t; - -//-------------- SPAWN ------------------------------// - //------------- ALLOCATE PIPES-------------------// - session_data->julia_in = new uv_pipe_t; - session_data->julia_out = new uv_pipe_t; -#ifdef READ_STDERR - session_data->julia_err = new uv_pipe_t; -#else - session_data->julia_err = NULL; -#endif - session_data->julia_in->data = session_data->julia_out->data = -#ifdef READ_STDERR - session_data->julia_err->data = -#endif - session_data; - uv_pipe_t child_pipes[3]; - - //------------- SETUP PIPES---------------------// - - uv_pipe_init(uv_default_loop(), session_data->julia_in, UV_PIPE_WRITEABLE); - uv_pipe_init(uv_default_loop(), session_data->julia_out, UV_PIPE_READABLE); -#ifdef READ_STDERR - uv_pipe_init(uv_default_loop(), session_data->julia_err, UV_PIPE_READABLE); -#endif - uv_pipe_init(uv_default_loop(), &child_pipes[0], UV_PIPE_SPAWN_SAFE|UV_PIPE_READABLE); - uv_pipe_init(uv_default_loop(), &child_pipes[1], UV_PIPE_SPAWN_SAFE|UV_PIPE_WRITEABLE); -#ifdef READ_STDERR - uv_pipe_init(uv_default_loop(), &child_pipes[2], UV_PIPE_SPAWN_SAFE|UV_PIPE_WRITEABLE); -#endif - - uv_pipe_link(&child_pipes[0],session_data->julia_in); - uv_pipe_link(session_data->julia_out,&child_pipes[1]); -#ifdef READ_STDERR - uv_pipe_link(session_data->julia_err,&child_pipes[2]); -#endif - //-------------- SETUP PROCESS OPTIONS ---------// - uv_process_options_t opts; - int r; - - //------------------ STDIO ---------------------// - uv_stdio_container_t stdio[STDIO_COUNT]; - stdio[0].type = UV_STREAM; - stdio[1].type = UV_STREAM; - stdio[0].data.stream = (uv_stream_t*)&child_pipes[0]; - stdio[1].data.stream = (uv_stream_t*)&child_pipes[1]; - stdio[2].type = UV_STREAM; -#ifdef READ_STDERR - stdio[2].data.stream = (uv_stream_t*)&child_pipes[2]; -#endif - opts.stdio_count = STDIO_COUNT; - opts.stdio = stdio; - - //------------------ ARGUMENTS ----------------// -#if 0 - char *argv[5] = {"gdbserver","localhost:2222","./julia-debug-readline", "../share/julia/extras/julia_web_base.jl", NULL}; -#else - char arg0[]="./julia-release-readline"; - char arg1[]="--no-history"; - char arg2[]="../share/julia/extras/julia_web_base.jl"; - char *argv[4]={arg0,arg1,arg2,NULL}; -#endif - opts.exit_cb=&process_exited2; - opts.cwd=NULL; //cwd -#ifndef __WIN32__ - opts.env=environ; - #else - opts.env=NULL; - #endif - opts.args=argv; - opts.file=argv[0]; - opts.flags=0; - - - int err = uv_spawn(uv_default_loop(),session_data->proc,opts); - - //------------------ CLEAN UP ---------------// - uv_pipe_close_sync(&child_pipes[0]); - uv_pipe_close_sync(&child_pipes[1]); -#ifdef READ_STDERR - uv_pipe_close_sync(&child_pipes[2]); -#endif - - if(err!=0) - return ""; - session_data->data_notifier = new uv_async_t; - session_data->data_notifier->data = session_data; - uv_async_init(uv_default_loop(),session_data->data_notifier,read_client); - - session_data->proc->data = session_data; - - //start reading - cout << "Started Reading from Julia stdout"; - uv_read_start((uv_stream_t*)session_data->julia_out,&alloc_buf,&julia_incoming); -#ifdef READ_STDERR - uv_read_start((uv_stream_t*)session_data->julia_err,&alloc_buf,&julia_incoming); -#endif - - /* - // start the inbox thread - if (pthread_create(&session_data->inbox_proc, 0, inbox_thread, (void*)session_data)) - session_data->inbox_proc = 0; - - // start the outbox thread - if (pthread_create(&session_data->outbox_proc, 0, outbox_thread, (void*)session_data)) - session_data->outbox_proc = 0; */ - - // store the session - julia_session_list.push_back(session_data); - - // print a message - cout<<"New user \""<data; - delete (uv_tcp_t*)(handle); -} - -void close_stream(uv_shutdown_t* req, int status) -{ - uv_close((uv_handle_t*)req->handle,&requestDone); - delete req; -#ifdef CPP_DEBUG_TRACE - cout << "Closing connection " -#ifdef __WIN32__ -<get_cookie_exists("SESSION_TOKEN")) - session_token = req->get_cookie_value("SESSION_TOKEN"); - -#ifdef CPP_DEBUG_TRACE - cout << "Request from user " << session_token << "\n"; -#endif - - // get the julia session if there is one - julia_session* julia_session_ptr = 0; - if (session_token != "") - { - for (size_t i = 0; i < julia_session_list.size(); i++) - { - if (julia_session_list[i]->web_session_map.find(session_token) != julia_session_list[i]->web_session_map.end()) - { - // store this session - julia_session_ptr = julia_session_list[i]; - break; - } - } - if (julia_session_ptr == 0) - session_token = ""; - } - - // the response - vector response_messages; - - // whether we are waiting for an eval - bool waiting_for_eval = false; - - // process input if there is any - if (req->get_field_exists("request")) - { - // parse the request - Json::Value request_root; - Json::Reader reader; - if (reader.parse(req->get_field_value("request"), request_root)) - { - // iterate through the messages - for (int i = 0; i < request_root.size(); i++) - { - // make sure the message has at least a type - if (request_root[i].size() > 0) - { - // extract the message from the request - message request_message; - request_message.type = request_root[i][0].asInt(); - for (int j = 1; j < request_root[i].size(); j++) - request_message.args.push_back(request_root[i][j].asString()); - - // MSG_INPUT_START - if (request_message.type == MSG_INPUT_START) - { - // make sure the message is well-formed - if (request_message.args.size() >= 2) - { - // get the user name and session name - string user_name = request_message.args[0]; - if (user_name == "") - user_name = "julia"; - string session_name = request_message.args[1]; - - // try to create/join a new session - session_token = get_session(user_name, session_name); - if (session_token == "") - { - // too many sessions - message msg; - msg.type = MSG_OUTPUT_FATAL_ERROR; - msg.args.push_back("the server is currently at maximum capacity"); - response_messages.push_back(msg); - } - - // get the new session pointer - julia_session_ptr = 0; - for (size_t j = 0; j < julia_session_list.size(); j++) - { - if (julia_session_list[j]->web_session_map.find(session_token) != julia_session_list[j]->web_session_map.end()) - { - // store this session - julia_session_ptr = julia_session_list[j]; - break; - } - } - } - - // don't send this message to julia - continue; - } - - // MSG_INPUT_POLL - if (request_message.type == MSG_INPUT_POLL) - { - if (julia_session_ptr == 0) - { - // if not, send an error message - message msg; - msg.type = MSG_OUTPUT_FATAL_ERROR; - msg.args.push_back("session expired"); - response_messages.push_back(msg); - } - - // don't send this message to julia - continue; - } - - // MSG_INPUT_EVAL - if (request_message.type == MSG_INPUT_EVAL) - { - // make sure we have a valid session - if (session_token == "") - { - // if not, send an error message - message msg; - msg.type = MSG_OUTPUT_FATAL_ERROR; - msg.args.push_back("session expired"); - response_messages.push_back(msg); - } - else - { - // forward the message to this julia session - julia_session_ptr->inbox.push_back(request_message); - uv_async_send(julia_session_ptr->data_notifier); - } - } - - // MSG_INPUT_REPLAY_HISTORY - if (request_message.type == MSG_INPUT_REPLAY_HISTORY) - { - if (julia_session_ptr == 0) - { - // if not, send an error message - message msg; - msg.type = MSG_OUTPUT_FATAL_ERROR; - msg.args.push_back("session expired"); - response_messages.push_back(msg); - } - else - { - // send the entire outbox history to the client - for (size_t i = 0; i < julia_session_ptr->outbox_history.size(); i++) - response_messages.push_back(julia_session_ptr->outbox_history[i]); - - // the outbox history includes messages that were already going to be sent, so delete those - julia_session_ptr->web_session_map[session_token].outbox.clear(); - } - - // don't send this message to julia - continue; - } - - // MSG_INPUT_GET_USER - if (request_message.type == MSG_INPUT_GET_USER) - { - if (julia_session_ptr == 0) - { - // if not, send an error message - message msg; - msg.type = MSG_OUTPUT_FATAL_ERROR; - msg.args.push_back("session expired"); - response_messages.push_back(msg); - } - else - { - // send back the user name - message msg; - msg.type = MSG_OUTPUT_GET_USER; - msg.args.push_back(julia_session_ptr->web_session_map[session_token].user_name); - msg.args.push_back(session_token); - response_messages.push_back(msg); - } - - // don't send this message to julia - continue; - } - - // bad message, just ignore it - } - } - } - } - - // perform maintenance on the session if there is one - if (julia_session_ptr != 0) - { - // pet the watchdog - julia_session_ptr->web_session_map[session_token].update_time = time(0); - - // catch any extra output from julia during normal operation - if (julia_session_ptr->outbox_std != "" && julia_session_ptr->status == SESSION_NORMAL) - { - // construct the output message - message output_message; - output_message.type = MSG_OUTPUT_OTHER; - output_message.args.push_back(julia_session_ptr->outbox_std); - - // eat the outbox contents - julia_session_ptr->outbox_std = ""; - - // add the message to the outbox queue of all the users of this julia session - julia_session_ptr->outbox_history.push_back(output_message); - for (map::iterator iter = julia_session_ptr->web_session_map.begin(); iter != julia_session_ptr->web_session_map.end(); iter++) - iter->second.outbox.push_back(output_message); - } - - // get any output messages from julia - for (size_t i = 0; i < julia_session_ptr->web_session_map[session_token].outbox.size(); i++) - response_messages.push_back(julia_session_ptr->web_session_map[session_token].outbox[i]); - julia_session_ptr->web_session_map[session_token].outbox.clear(); - } - - // convert the message to json - Json::Value response_root(Json::arrayValue); - for (size_t i = 0; i < response_messages.size(); i++) - { - Json::Value message_root(Json::arrayValue); - message_root.append(response_messages[i].type); - for (size_t j = 0; j < response_messages[i].args.size(); j++) - message_root.append(response_messages[i].args[j]); -#ifdef CPP_DEBUG_TRACE - cout<<"Sending message "<<(int)response_messages[i].type<<" to user "<data; - p->cstr = new char [response.size()]; -#ifdef VERY_VERBOSE - cout<cstr, response.data(),response.size()); - // write the response - uv_buf_t buf; - buf.base=p->cstr; - buf.len=response.size(); - uv_write_t *wr = new uv_write_t; - wr->data=(void*)buf.base; - uv_write(wr,(uv_stream_t*)client,&buf,1,&free_write_buffer); - - // destroySoon the connection to the client - uv_shutdown_t *sr = new uv_shutdown_t; - uv_shutdown(sr, (uv_stream_t*)client, &close_stream); -} - - -// CTRL+C signal handler -#if defined(__WIN32__) -BOOL WINAPI sigint_handler(DWORD wsig) { //This needs winapi types to guarantee __stdcall -#else -void sigint_handler(int sig, siginfo_t *info, void *context) { -#endif - // print a message - cout<<"cleaning up...\nexiting...\n"; -#if defined(__WIN32__) - cout<<"\nImportant: Please answer N to the following question:\n"; -#endif - - // clean up - for (size_t i = 0; i < julia_session_list.size(); i++) - { - // close the pipes - uv_close((uv_handle_t*)(julia_session_list[i]->julia_in),&pipes_done); - uv_close((uv_handle_t*)(julia_session_list[i]->julia_out),&pipes_done); - uv_close((uv_handle_t*)(julia_session_list[i]->julia_err),&pipes_done); - - // kill the julia process - uv_process_kill(julia_session_list[i]->proc, 9); - //run_event_loop(julia_session_list[i]); - - //uv_loop_delete((julia_session_list[i])->event_loop); - // delete the session - delete julia_session_list[i]; - } - - // terminate - exit(0); -} - -uv_tty_t *stdin_handle; -static void jl_install_sigint_handler() { -#ifdef __WIN32__ - SetConsoleCtrlHandler(NULL,0); //turn on ctrl-c handler - SetConsoleCtrlHandler((PHANDLER_ROUTINE)sigint_handler,1); -#else - struct sigaction act; - memset(&act, 0, sizeof(struct sigaction)); - sigemptyset(&act.sa_mask); - act.sa_sigaction = sigint_handler; - act.sa_flags = SA_SIGINFO; - if (sigaction(SIGINT, &act, NULL) < 0) { - fprintf(stderr, "sigaction: %s\n", strerror(errno)); - exit(1); - } -#endif -} - -// program entrypoint -int main(int argc, char* argv[]) -{ - // set the Ctrl+C handler - jl_install_sigint_handler(); - - // get the command line arguments - int port_num = 1441; - for (int i = 1; i < argc-1; i++) - { - if (string(argv[i]) == "-p") - port_num = from_string(argv[i+1]); - } - - // seed the random number generator for generating julia_session tokens - srand(time(0)); - -#ifndef __WIN32__ - // ignore the SIGPIPE signal (when julia crashes or exits, we don't want to die too) - struct sigaction act; - act.sa_flags = 0; - act.sa_handler = SIG_IGN; - sigemptyset(&act.sa_mask); - sigaction(SIGPIPE, &act, NULL); -#endif - - uv_timer_t wd; - uv_timer_init(uv_default_loop(),&wd); - uv_timer_start(&wd,&watchdog,WATCHDOG_INTERVAL,WATCHDOG_INTERVAL); - - // print a welcome message - cout<<"SCGI server started on port "< b ? 1 : a >= b ? 0 : NaN; -}; -d3.descending = function(a, b) { - return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; -}; -d3.mean = function(array, f) { - var n = array.length, - a, - m = 0, - i = -1, - j = 0; - if (arguments.length === 1) { - while (++i < n) if (d3_number(a = array[i])) m += (a - m) / ++j; - } else { - while (++i < n) if (d3_number(a = f.call(array, array[i], i))) m += (a - m) / ++j; - } - return j ? m : undefined; -}; -d3.median = function(array, f) { - if (arguments.length > 1) array = array.map(f); - array = array.filter(d3_number); - return array.length ? d3.quantile(array.sort(d3.ascending), .5) : undefined; -}; -d3.min = function(array, f) { - var i = -1, - n = array.length, - a, - b; - if (arguments.length === 1) { - while (++i < n && ((a = array[i]) == null || a != a)) a = undefined; - while (++i < n) if ((b = array[i]) != null && a > b) a = b; - } else { - while (++i < n && ((a = f.call(array, array[i], i)) == null || a != a)) a = undefined; - while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b; - } - return a; -}; -d3.max = function(array, f) { - var i = -1, - n = array.length, - a, - b; - if (arguments.length === 1) { - while (++i < n && ((a = array[i]) == null || a != a)) a = undefined; - while (++i < n) if ((b = array[i]) != null && b > a) a = b; - } else { - while (++i < n && ((a = f.call(array, array[i], i)) == null || a != a)) a = undefined; - while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b; - } - return a; -}; -d3.extent = function(array, f) { - var i = -1, - n = array.length, - a, - b, - c; - if (arguments.length === 1) { - while (++i < n && ((a = c = array[i]) == null || a != a)) a = c = undefined; - while (++i < n) if ((b = array[i]) != null) { - if (a > b) a = b; - if (c < b) c = b; - } - } else { - while (++i < n && ((a = c = f.call(array, array[i], i)) == null || a != a)) a = undefined; - while (++i < n) if ((b = f.call(array, array[i], i)) != null) { - if (a > b) a = b; - if (c < b) c = b; - } - } - return [a, c]; -}; -d3.random = { - normal: function(mean, deviation) { - if (arguments.length < 2) deviation = 1; - if (arguments.length < 1) mean = 0; - return function() { - var x, y, r; - do { - x = Math.random() * 2 - 1; - y = Math.random() * 2 - 1; - r = x * x + y * y; - } while (!r || r > 1); - return mean + deviation * x * Math.sqrt(-2 * Math.log(r) / r); - }; - } -}; -function d3_number(x) { - return x != null && !isNaN(x); -} -d3.sum = function(array, f) { - var s = 0, - n = array.length, - a, - i = -1; - - if (arguments.length === 1) { - while (++i < n) if (!isNaN(a = +array[i])) s += a; - } else { - while (++i < n) if (!isNaN(a = +f.call(array, array[i], i))) s += a; - } - - return s; -}; -// R-7 per -d3.quantile = function(values, p) { - var H = (values.length - 1) * p + 1, - h = Math.floor(H), - v = values[h - 1], - e = H - h; - return e ? v + e * (values[h] - v) : v; -}; -d3.transpose = function(matrix) { - return d3.zip.apply(d3, matrix); -}; -d3.zip = function() { - if (!(n = arguments.length)) return []; - for (var i = -1, m = d3.min(arguments, d3_zipLength), zips = new Array(m); ++i < m;) { - for (var j = -1, n, zip = zips[i] = new Array(n); ++j < n;) { - zip[j] = arguments[j][i]; - } - } - return zips; -}; - -function d3_zipLength(d) { - return d.length; -} -// Locate the insertion point for x in a to maintain sorted order. The -// arguments lo and hi may be used to specify a subset of the array which should -// be considered; by default the entire array is used. If x is already present -// in a, the insertion point will be before (to the left of) any existing -// entries. The return value is suitable for use as the first argument to -// `array.splice` assuming that a is already sorted. -// -// The returned insertion point i partitions the array a into two halves so that -// all v < x for v in a[lo:i] for the left side and all v >= x for v in a[i:hi] -// for the right side. -d3.bisectLeft = function(a, x, lo, hi) { - if (arguments.length < 3) lo = 0; - if (arguments.length < 4) hi = a.length; - while (lo < hi) { - var mid = (lo + hi) >> 1; - if (a[mid] < x) lo = mid + 1; - else hi = mid; - } - return lo; -}; - -// Similar to bisectLeft, but returns an insertion point which comes after (to -// the right of) any existing entries of x in a. -// -// The returned insertion point i partitions the array into two halves so that -// all v <= x for v in a[lo:i] for the left side and all v > x for v in a[i:hi] -// for the right side. -d3.bisect = -d3.bisectRight = function(a, x, lo, hi) { - if (arguments.length < 3) lo = 0; - if (arguments.length < 4) hi = a.length; - while (lo < hi) { - var mid = (lo + hi) >> 1; - if (x < a[mid]) hi = mid; - else lo = mid + 1; - } - return lo; -}; -d3.first = function(array, f) { - var i = 0, - n = array.length, - a = array[0], - b; - if (arguments.length === 1) f = d3.ascending; - while (++i < n) { - if (f.call(array, a, b = array[i]) > 0) { - a = b; - } - } - return a; -}; -d3.last = function(array, f) { - var i = 0, - n = array.length, - a = array[0], - b; - if (arguments.length === 1) f = d3.ascending; - while (++i < n) { - if (f.call(array, a, b = array[i]) <= 0) { - a = b; - } - } - return a; -}; -d3.nest = function() { - var nest = {}, - keys = [], - sortKeys = [], - sortValues, - rollup; - - function map(array, depth) { - if (depth >= keys.length) return rollup - ? rollup.call(nest, array) : (sortValues - ? array.sort(sortValues) - : array); - - var i = -1, - n = array.length, - key = keys[depth++], - keyValue, - object, - o = {}; - - while (++i < n) { - if ((keyValue = key(object = array[i])) in o) { - o[keyValue].push(object); - } else { - o[keyValue] = [object]; - } - } - - for (keyValue in o) { - o[keyValue] = map(o[keyValue], depth); - } - - return o; - } - - function entries(map, depth) { - if (depth >= keys.length) return map; - - var a = [], - sortKey = sortKeys[depth++], - key; - - for (key in map) { - a.push({key: key, values: entries(map[key], depth)}); - } - - if (sortKey) a.sort(function(a, b) { - return sortKey(a.key, b.key); - }); - - return a; - } - - nest.map = function(array) { - return map(array, 0); - }; - - nest.entries = function(array) { - return entries(map(array, 0), 0); - }; - - nest.key = function(d) { - keys.push(d); - return nest; - }; - - // Specifies the order for the most-recently specified key. - // Note: only applies to entries. Map keys are unordered! - nest.sortKeys = function(order) { - sortKeys[keys.length - 1] = order; - return nest; - }; - - // Specifies the order for leaf values. - // Applies to both maps and entries array. - nest.sortValues = function(order) { - sortValues = order; - return nest; - }; - - nest.rollup = function(f) { - rollup = f; - return nest; - }; - - return nest; -}; -d3.keys = function(map) { - var keys = []; - for (var key in map) keys.push(key); - return keys; -}; -d3.values = function(map) { - var values = []; - for (var key in map) values.push(map[key]); - return values; -}; -d3.entries = function(map) { - var entries = []; - for (var key in map) entries.push({key: key, value: map[key]}); - return entries; -}; -d3.permute = function(array, indexes) { - var permutes = [], - i = -1, - n = indexes.length; - while (++i < n) permutes[i] = array[indexes[i]]; - return permutes; -}; -d3.merge = function(arrays) { - return Array.prototype.concat.apply([], arrays); -}; -d3.split = function(array, f) { - var arrays = [], - values = [], - value, - i = -1, - n = array.length; - if (arguments.length < 2) f = d3_splitter; - while (++i < n) { - if (f.call(values, value = array[i], i)) { - values = []; - } else { - if (!values.length) arrays.push(values); - values.push(value); - } - } - return arrays; -}; - -function d3_splitter(d) { - return d == null; -} -function d3_collapse(s) { - return s.replace(/(^\s+)|(\s+$)/g, "").replace(/\s+/g, " "); -} -/** - * @param {number} start - * @param {number=} stop - * @param {number=} step - */ -d3.range = function(start, stop, step) { - if (arguments.length < 3) { - step = 1; - if (arguments.length < 2) { - stop = start; - start = 0; - } - } - if ((stop - start) / step == Infinity) throw new Error("infinite range"); - var range = [], - i = -1, - j; - if (step < 0) while ((j = start + step * ++i) > stop) range.push(j); - else while ((j = start + step * ++i) < stop) range.push(j); - return range; -}; -d3.requote = function(s) { - return s.replace(d3_requote_re, "\\$&"); -}; - -var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g; -d3.round = function(x, n) { - return n - ? Math.round(x * Math.pow(10, n)) * Math.pow(10, -n) - : Math.round(x); -}; -d3.xhr = function(url, mime, callback) { - var req = new XMLHttpRequest; - if (arguments.length < 3) callback = mime; - else if (mime && req.overrideMimeType) req.overrideMimeType(mime); - req.open("GET", url, true); - req.onreadystatechange = function() { - if (req.readyState === 4) callback(req.status < 300 ? req : null); - }; - req.send(null); -}; -d3.text = function(url, mime, callback) { - function ready(req) { - callback(req && req.responseText); - } - if (arguments.length < 3) { - callback = mime; - mime = null; - } - d3.xhr(url, mime, ready); -}; -d3.json = function(url, callback) { - d3.text(url, "application/json", function(text) { - callback(text ? JSON.parse(text) : null); - }); -}; -d3.html = function(url, callback) { - d3.text(url, "text/html", function(text) { - if (text != null) { // Treat empty string as valid HTML. - var range = document.createRange(); - range.selectNode(document.body); - text = range.createContextualFragment(text); - } - callback(text); - }); -}; -d3.xml = function(url, mime, callback) { - function ready(req) { - callback(req && req.responseXML); - } - if (arguments.length < 3) { - callback = mime; - mime = null; - } - d3.xhr(url, mime, ready); -}; -var d3_nsPrefix = { - svg: "http://www.w3.org/2000/svg", - xhtml: "http://www.w3.org/1999/xhtml", - xlink: "http://www.w3.org/1999/xlink", - xml: "http://www.w3.org/XML/1998/namespace", - xmlns: "http://www.w3.org/2000/xmlns/" -}; - -d3.ns = { - prefix: d3_nsPrefix, - qualify: function(name) { - var i = name.indexOf(":"); - return i < 0 ? (name in d3_nsPrefix - ? {space: d3_nsPrefix[name], local: name} : name) - : {space: d3_nsPrefix[name.substring(0, i)], local: name.substring(i + 1)}; - } -}; -d3.dispatch = function() { - var dispatch = new d3_dispatch(), - i = -1, - n = arguments.length; - while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(); - return dispatch; -}; - -function d3_dispatch() {} - -d3_dispatch.prototype.on = function(type, listener) { - var i = type.indexOf("."), - name = ""; - - // Extract optional namespace, e.g., "click.foo" - if (i > 0) { - name = type.substring(i + 1); - type = type.substring(0, i); - } - - return arguments.length < 2 - ? this[type].on(name) - : (this[type].on(name, listener), this); -}; - -function d3_dispatch_event() { - var listeners = [], - listenerByName = {}; - - function dispatch() { - var z = listeners, // defensive reference - i = -1, - n = z.length, - l; - while (++i < n) if (l = z[i].on) l.apply(this, arguments); - } - - dispatch.on = function(name, listener) { - var l, i; - - // return the current listener, if any - if (arguments.length < 2) return (l = listenerByName[name]) && l.on; - - // remove the old listener, if any (with copy-on-write) - if (l = listenerByName[name]) { - l.on = null; - listeners = listeners.slice(0, i = listeners.indexOf(l)).concat(listeners.slice(i + 1)); - delete listenerByName[name]; - } - - // add the new listener, if any - if (listener) { - listeners.push(listenerByName[name] = {on: listener}); - } - - return dispatch; - }; - - return dispatch; -}; -// TODO align -d3.format = function(specifier) { - var match = d3_format_re.exec(specifier), - fill = match[1] || " ", - sign = match[3] || "", - zfill = match[5], - width = +match[6], - comma = match[7], - precision = match[8], - type = match[9], - scale = 1, - suffix = "", - integer = false; - - if (precision) precision = +precision.substring(1); - - if (zfill) { - fill = "0"; // TODO align = "="; - if (comma) width -= Math.floor((width - 1) / 4); - } - - switch (type) { - case "n": comma = true; type = "g"; break; - case "%": scale = 100; suffix = "%"; type = "f"; break; - case "p": scale = 100; suffix = "%"; type = "r"; break; - case "d": integer = true; precision = 0; break; - case "s": scale = -1; type = "r"; break; - } - - // If no precision is specified for r, fallback to general notation. - if (type == "r" && !precision) type = "g"; - - type = d3_format_types[type] || d3_format_typeDefault; - - return function(value) { - - // Return the empty string for floats formatted as ints. - if (integer && (value % 1)) return ""; - - // Convert negative to positive, and record the sign prefix. - var negative = (value < 0) && (value = -value) ? "\u2212" : sign; - - // Apply the scale, computing it from the value's exponent for si format. - if (scale < 0) { - var prefix = d3.formatPrefix(value, precision); - value *= prefix.scale; - suffix = prefix.symbol; - } else { - value *= scale; - } - - // Convert to the desired precision. - value = type(value, precision); - - // If the fill character is 0, the sign and group is applied after the fill. - if (zfill) { - var length = value.length + negative.length; - if (length < width) value = new Array(width - length + 1).join(fill) + value; - if (comma) value = d3_format_group(value); - value = negative + value; - } - - // Otherwise (e.g., space-filling), the sign and group is applied before. - else { - if (comma) value = d3_format_group(value); - value = negative + value; - var length = value.length; - if (length < width) value = new Array(width - length + 1).join(fill) + value; - } - - return value + suffix; - }; -}; - -// [[fill]align][sign][#][0][width][,][.precision][type] -var d3_format_re = /(?:([^{])?([<>=^]))?([+\- ])?(#)?(0)?([0-9]+)?(,)?(\.[0-9]+)?([a-zA-Z%])?/; - -var d3_format_types = { - g: function(x, p) { return x.toPrecision(p); }, - e: function(x, p) { return x.toExponential(p); }, - f: function(x, p) { return x.toFixed(p); }, - r: function(x, p) { return d3.round(x, p = d3_format_precision(x, p)).toFixed(Math.max(0, Math.min(20, p))); } -}; - -function d3_format_precision(x, p) { - return p - (x ? 1 + Math.floor(Math.log(x + Math.pow(10, 1 + Math.floor(Math.log(x) / Math.LN10) - p)) / Math.LN10) : 1); -} - -function d3_format_typeDefault(x) { - return x + ""; -} - -// Apply comma grouping for thousands. -function d3_format_group(value) { - var i = value.lastIndexOf("."), - f = i >= 0 ? value.substring(i) : (i = value.length, ""), - t = []; - while (i > 0) t.push(value.substring(i -= 3, i + 3)); - return t.reverse().join(",") + f; -} -var d3_formatPrefixes = ["y","z","a","f","p","n","μ","m","","k","M","G","T","P","E","Z","Y"].map(d3_formatPrefix); - -d3.formatPrefix = function(value, precision) { - var i = 0; - if (value) { - if (value < 0) value *= -1; - if (precision) value = d3.round(value, d3_format_precision(value, precision)); - i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10); - i = Math.max(-24, Math.min(24, Math.floor((i <= 0 ? i + 1 : i - 1) / 3) * 3)); - } - return d3_formatPrefixes[8 + i / 3]; -}; - -function d3_formatPrefix(d, i) { - return { - scale: Math.pow(10, (8 - i) * 3), - symbol: d - }; -} - -/* - * TERMS OF USE - EASING EQUATIONS - * - * Open source under the BSD License. - * - * Copyright 2001 Robert Penner - * 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 author nor the names of 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. - */ - -var d3_ease_quad = d3_ease_poly(2), - d3_ease_cubic = d3_ease_poly(3); - -var d3_ease = { - linear: function() { return d3_ease_linear; }, - poly: d3_ease_poly, - quad: function() { return d3_ease_quad; }, - cubic: function() { return d3_ease_cubic; }, - sin: function() { return d3_ease_sin; }, - exp: function() { return d3_ease_exp; }, - circle: function() { return d3_ease_circle; }, - elastic: d3_ease_elastic, - back: d3_ease_back, - bounce: function() { return d3_ease_bounce; } -}; - -var d3_ease_mode = { - "in": function(f) { return f; }, - "out": d3_ease_reverse, - "in-out": d3_ease_reflect, - "out-in": function(f) { return d3_ease_reflect(d3_ease_reverse(f)); } -}; - -d3.ease = function(name) { - var i = name.indexOf("-"), - t = i >= 0 ? name.substring(0, i) : name, - m = i >= 0 ? name.substring(i + 1) : "in"; - return d3_ease_clamp(d3_ease_mode[m](d3_ease[t].apply(null, Array.prototype.slice.call(arguments, 1)))); -}; - -function d3_ease_clamp(f) { - return function(t) { - return t <= 0 ? 0 : t >= 1 ? 1 : f(t); - }; -} - -function d3_ease_reverse(f) { - return function(t) { - return 1 - f(1 - t); - }; -} - -function d3_ease_reflect(f) { - return function(t) { - return .5 * (t < .5 ? f(2 * t) : (2 - f(2 - 2 * t))); - }; -} - -function d3_ease_linear(t) { - return t; -} - -function d3_ease_poly(e) { - return function(t) { - return Math.pow(t, e); - } -} - -function d3_ease_sin(t) { - return 1 - Math.cos(t * Math.PI / 2); -} - -function d3_ease_exp(t) { - return Math.pow(2, 10 * (t - 1)); -} - -function d3_ease_circle(t) { - return 1 - Math.sqrt(1 - t * t); -} - -function d3_ease_elastic(a, p) { - var s; - if (arguments.length < 2) p = 0.45; - if (arguments.length < 1) { a = 1; s = p / 4; } - else s = p / (2 * Math.PI) * Math.asin(1 / a); - return function(t) { - return 1 + a * Math.pow(2, 10 * -t) * Math.sin((t - s) * 2 * Math.PI / p); - }; -} - -function d3_ease_back(s) { - if (!s) s = 1.70158; - return function(t) { - return t * t * ((s + 1) * t - s); - }; -} - -function d3_ease_bounce(t) { - return t < 1 / 2.75 ? 7.5625 * t * t - : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75 - : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375 - : 7.5625 * (t -= 2.625 / 2.75) * t + .984375; -} -d3.event = null; - -function d3_eventCancel() { - d3.event.stopPropagation(); - d3.event.preventDefault(); -} -d3.interpolate = function(a, b) { - var i = d3.interpolators.length, f; - while (--i >= 0 && !(f = d3.interpolators[i](a, b))); - return f; -}; - -d3.interpolateNumber = function(a, b) { - b -= a; - return function(t) { return a + b * t; }; -}; - -d3.interpolateRound = function(a, b) { - b -= a; - return function(t) { return Math.round(a + b * t); }; -}; - -d3.interpolateString = function(a, b) { - var m, // current match - i, // current index - j, // current index (for coallescing) - s0 = 0, // start index of current string prefix - s1 = 0, // end index of current string prefix - s = [], // string constants and placeholders - q = [], // number interpolators - n, // q.length - o; - - // Reset our regular expression! - d3_interpolate_number.lastIndex = 0; - - // Find all numbers in b. - for (i = 0; m = d3_interpolate_number.exec(b); ++i) { - if (m.index) s.push(b.substring(s0, s1 = m.index)); - q.push({i: s.length, x: m[0]}); - s.push(null); - s0 = d3_interpolate_number.lastIndex; - } - if (s0 < b.length) s.push(b.substring(s0)); - - // Find all numbers in a. - for (i = 0, n = q.length; (m = d3_interpolate_number.exec(a)) && i < n; ++i) { - o = q[i]; - if (o.x == m[0]) { // The numbers match, so coallesce. - if (o.i) { - if (s[o.i + 1] == null) { // This match is followed by another number. - s[o.i - 1] += o.x; - s.splice(o.i, 1); - for (j = i + 1; j < n; ++j) q[j].i--; - } else { // This match is followed by a string, so coallesce twice. - s[o.i - 1] += o.x + s[o.i + 1]; - s.splice(o.i, 2); - for (j = i + 1; j < n; ++j) q[j].i -= 2; - } - } else { - if (s[o.i + 1] == null) { // This match is followed by another number. - s[o.i] = o.x; - } else { // This match is followed by a string, so coallesce twice. - s[o.i] = o.x + s[o.i + 1]; - s.splice(o.i + 1, 1); - for (j = i + 1; j < n; ++j) q[j].i--; - } - } - q.splice(i, 1); - n--; - i--; - } else { - o.x = d3.interpolateNumber(parseFloat(m[0]), parseFloat(o.x)); - } - } - - // Remove any numbers in b not found in a. - while (i < n) { - o = q.pop(); - if (s[o.i + 1] == null) { // This match is followed by another number. - s[o.i] = o.x; - } else { // This match is followed by a string, so coallesce twice. - s[o.i] = o.x + s[o.i + 1]; - s.splice(o.i + 1, 1); - } - n--; - } - - // Special optimization for only a single match. - if (s.length === 1) { - return s[0] == null ? q[0].x : function() { return b; }; - } - - // Otherwise, interpolate each of the numbers and rejoin the string. - return function(t) { - for (i = 0; i < n; ++i) s[(o = q[i]).i] = o.x(t); - return s.join(""); - }; -}; - -d3.interpolateTransform = function(a, b) { - return d3.interpolateString(d3.transform(a) + "", d3.transform(b) + ""); -}; - -d3.interpolateRgb = function(a, b) { - a = d3.rgb(a); - b = d3.rgb(b); - var ar = a.r, - ag = a.g, - ab = a.b, - br = b.r - ar, - bg = b.g - ag, - bb = b.b - ab; - return function(t) { - return "#" - + d3_rgb_hex(Math.round(ar + br * t)) - + d3_rgb_hex(Math.round(ag + bg * t)) - + d3_rgb_hex(Math.round(ab + bb * t)); - }; -}; - -// interpolates HSL space, but outputs RGB string (for compatibility) -d3.interpolateHsl = function(a, b) { - a = d3.hsl(a); - b = d3.hsl(b); - var h0 = a.h, - s0 = a.s, - l0 = a.l, - h1 = b.h - h0, - s1 = b.s - s0, - l1 = b.l - l0; - return function(t) { - return d3_hsl_rgb(h0 + h1 * t, s0 + s1 * t, l0 + l1 * t).toString(); - }; -}; - -d3.interpolateArray = function(a, b) { - var x = [], - c = [], - na = a.length, - nb = b.length, - n0 = Math.min(a.length, b.length), - i; - for (i = 0; i < n0; ++i) x.push(d3.interpolate(a[i], b[i])); - for (; i < na; ++i) c[i] = a[i]; - for (; i < nb; ++i) c[i] = b[i]; - return function(t) { - for (i = 0; i < n0; ++i) c[i] = x[i](t); - return c; - }; -}; - -d3.interpolateObject = function(a, b) { - var i = {}, - c = {}, - k; - for (k in a) { - if (k in b) { - i[k] = d3_interpolateByName(k)(a[k], b[k]); - } else { - c[k] = a[k]; - } - } - for (k in b) { - if (!(k in a)) { - c[k] = b[k]; - } - } - return function(t) { - for (k in i) c[k] = i[k](t); - return c; - }; -} - -var d3_interpolate_number = /[-+]?(?:\d*\.?\d+)(?:[eE][-+]?\d+)?/g; - -function d3_interpolateByName(n) { - return n == "transform" - ? d3.interpolateTransform - : d3.interpolate; -} - -d3.interpolators = [ - d3.interpolateObject, - function(a, b) { return (b instanceof Array) && d3.interpolateArray(a, b); }, - function(a, b) { return (typeof a === "string" || typeof b === "string") && d3.interpolateString(a + "", b + ""); }, - function(a, b) { return (typeof b === "string" ? b in d3_rgb_names || /^(#|rgb\(|hsl\()/.test(b) : b instanceof d3_Rgb || b instanceof d3_Hsl) && d3.interpolateRgb(a, b); }, - function(a, b) { return !isNaN(a = +a) && !isNaN(b = +b) && d3.interpolateNumber(a, b); } -]; -function d3_uninterpolateNumber(a, b) { - b = b - (a = +a) ? 1 / (b - a) : 0; - return function(x) { return (x - a) * b; }; -} - -function d3_uninterpolateClamp(a, b) { - b = b - (a = +a) ? 1 / (b - a) : 0; - return function(x) { return Math.max(0, Math.min(1, (x - a) * b)); }; -} -d3.rgb = function(r, g, b) { - return arguments.length === 1 - ? (r instanceof d3_Rgb ? d3_rgb(r.r, r.g, r.b) - : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb)) - : d3_rgb(~~r, ~~g, ~~b); -}; - -function d3_rgb(r, g, b) { - return new d3_Rgb(r, g, b); -} - -function d3_Rgb(r, g, b) { - this.r = r; - this.g = g; - this.b = b; -} - -d3_Rgb.prototype.brighter = function(k) { - k = Math.pow(0.7, arguments.length ? k : 1); - var r = this.r, - g = this.g, - b = this.b, - i = 30; - if (!r && !g && !b) return d3_rgb(i, i, i); - if (r && r < i) r = i; - if (g && g < i) g = i; - if (b && b < i) b = i; - return d3_rgb( - Math.min(255, Math.floor(r / k)), - Math.min(255, Math.floor(g / k)), - Math.min(255, Math.floor(b / k))); -}; - -d3_Rgb.prototype.darker = function(k) { - k = Math.pow(0.7, arguments.length ? k : 1); - return d3_rgb( - Math.floor(k * this.r), - Math.floor(k * this.g), - Math.floor(k * this.b)); -}; - -d3_Rgb.prototype.hsl = function() { - return d3_rgb_hsl(this.r, this.g, this.b); -}; - -d3_Rgb.prototype.toString = function() { - return "#" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b); -}; - -function d3_rgb_hex(v) { - return v < 0x10 - ? "0" + Math.max(0, v).toString(16) - : Math.min(255, v).toString(16); -} - -function d3_rgb_parse(format, rgb, hsl) { - var r = 0, // red channel; int in [0, 255] - g = 0, // green channel; int in [0, 255] - b = 0, // blue channel; int in [0, 255] - m1, // CSS color specification match - m2, // CSS color specification type (e.g., rgb) - name; - - /* Handle hsl, rgb. */ - m1 = /([a-z]+)\((.*)\)/i.exec(format); - if (m1) { - m2 = m1[2].split(","); - switch (m1[1]) { - case "hsl": { - return hsl( - parseFloat(m2[0]), // degrees - parseFloat(m2[1]) / 100, // percentage - parseFloat(m2[2]) / 100 // percentage - ); - } - case "rgb": { - return rgb( - d3_rgb_parseNumber(m2[0]), - d3_rgb_parseNumber(m2[1]), - d3_rgb_parseNumber(m2[2]) - ); - } - } - } - - /* Named colors. */ - if (name = d3_rgb_names[format]) return rgb(name.r, name.g, name.b); - - /* Hexadecimal colors: #rgb and #rrggbb. */ - if (format != null && format.charAt(0) === "#") { - if (format.length === 4) { - r = format.charAt(1); r += r; - g = format.charAt(2); g += g; - b = format.charAt(3); b += b; - } else if (format.length === 7) { - r = format.substring(1, 3); - g = format.substring(3, 5); - b = format.substring(5, 7); - } - r = parseInt(r, 16); - g = parseInt(g, 16); - b = parseInt(b, 16); - } - - return rgb(r, g, b); -} - -function d3_rgb_hsl(r, g, b) { - var min = Math.min(r /= 255, g /= 255, b /= 255), - max = Math.max(r, g, b), - d = max - min, - h, - s, - l = (max + min) / 2; - if (d) { - s = l < .5 ? d / (max + min) : d / (2 - max - min); - if (r == max) h = (g - b) / d + (g < b ? 6 : 0); - else if (g == max) h = (b - r) / d + 2; - else h = (r - g) / d + 4; - h *= 60; - } else { - s = h = 0; - } - return d3_hsl(h, s, l); -} - -function d3_rgb_parseNumber(c) { // either integer or percentage - var f = parseFloat(c); - return c.charAt(c.length - 1) === "%" ? Math.round(f * 2.55) : f; -} - -var d3_rgb_names = { - aliceblue: "#f0f8ff", - antiquewhite: "#faebd7", - aqua: "#00ffff", - aquamarine: "#7fffd4", - azure: "#f0ffff", - beige: "#f5f5dc", - bisque: "#ffe4c4", - black: "#000000", - blanchedalmond: "#ffebcd", - blue: "#0000ff", - blueviolet: "#8a2be2", - brown: "#a52a2a", - burlywood: "#deb887", - cadetblue: "#5f9ea0", - chartreuse: "#7fff00", - chocolate: "#d2691e", - coral: "#ff7f50", - cornflowerblue: "#6495ed", - cornsilk: "#fff8dc", - crimson: "#dc143c", - cyan: "#00ffff", - darkblue: "#00008b", - darkcyan: "#008b8b", - darkgoldenrod: "#b8860b", - darkgray: "#a9a9a9", - darkgreen: "#006400", - darkgrey: "#a9a9a9", - darkkhaki: "#bdb76b", - darkmagenta: "#8b008b", - darkolivegreen: "#556b2f", - darkorange: "#ff8c00", - darkorchid: "#9932cc", - darkred: "#8b0000", - darksalmon: "#e9967a", - darkseagreen: "#8fbc8f", - darkslateblue: "#483d8b", - darkslategray: "#2f4f4f", - darkslategrey: "#2f4f4f", - darkturquoise: "#00ced1", - darkviolet: "#9400d3", - deeppink: "#ff1493", - deepskyblue: "#00bfff", - dimgray: "#696969", - dimgrey: "#696969", - dodgerblue: "#1e90ff", - firebrick: "#b22222", - floralwhite: "#fffaf0", - forestgreen: "#228b22", - fuchsia: "#ff00ff", - gainsboro: "#dcdcdc", - ghostwhite: "#f8f8ff", - gold: "#ffd700", - goldenrod: "#daa520", - gray: "#808080", - green: "#008000", - greenyellow: "#adff2f", - grey: "#808080", - honeydew: "#f0fff0", - hotpink: "#ff69b4", - indianred: "#cd5c5c", - indigo: "#4b0082", - ivory: "#fffff0", - khaki: "#f0e68c", - lavender: "#e6e6fa", - lavenderblush: "#fff0f5", - lawngreen: "#7cfc00", - lemonchiffon: "#fffacd", - lightblue: "#add8e6", - lightcoral: "#f08080", - lightcyan: "#e0ffff", - lightgoldenrodyellow: "#fafad2", - lightgray: "#d3d3d3", - lightgreen: "#90ee90", - lightgrey: "#d3d3d3", - lightpink: "#ffb6c1", - lightsalmon: "#ffa07a", - lightseagreen: "#20b2aa", - lightskyblue: "#87cefa", - lightslategray: "#778899", - lightslategrey: "#778899", - lightsteelblue: "#b0c4de", - lightyellow: "#ffffe0", - lime: "#00ff00", - limegreen: "#32cd32", - linen: "#faf0e6", - magenta: "#ff00ff", - maroon: "#800000", - mediumaquamarine: "#66cdaa", - mediumblue: "#0000cd", - mediumorchid: "#ba55d3", - mediumpurple: "#9370db", - mediumseagreen: "#3cb371", - mediumslateblue: "#7b68ee", - mediumspringgreen: "#00fa9a", - mediumturquoise: "#48d1cc", - mediumvioletred: "#c71585", - midnightblue: "#191970", - mintcream: "#f5fffa", - mistyrose: "#ffe4e1", - moccasin: "#ffe4b5", - navajowhite: "#ffdead", - navy: "#000080", - oldlace: "#fdf5e6", - olive: "#808000", - olivedrab: "#6b8e23", - orange: "#ffa500", - orangered: "#ff4500", - orchid: "#da70d6", - palegoldenrod: "#eee8aa", - palegreen: "#98fb98", - paleturquoise: "#afeeee", - palevioletred: "#db7093", - papayawhip: "#ffefd5", - peachpuff: "#ffdab9", - peru: "#cd853f", - pink: "#ffc0cb", - plum: "#dda0dd", - powderblue: "#b0e0e6", - purple: "#800080", - red: "#ff0000", - rosybrown: "#bc8f8f", - royalblue: "#4169e1", - saddlebrown: "#8b4513", - salmon: "#fa8072", - sandybrown: "#f4a460", - seagreen: "#2e8b57", - seashell: "#fff5ee", - sienna: "#a0522d", - silver: "#c0c0c0", - skyblue: "#87ceeb", - slateblue: "#6a5acd", - slategray: "#708090", - slategrey: "#708090", - snow: "#fffafa", - springgreen: "#00ff7f", - steelblue: "#4682b4", - tan: "#d2b48c", - teal: "#008080", - thistle: "#d8bfd8", - tomato: "#ff6347", - turquoise: "#40e0d0", - violet: "#ee82ee", - wheat: "#f5deb3", - white: "#ffffff", - whitesmoke: "#f5f5f5", - yellow: "#ffff00", - yellowgreen: "#9acd32" -}; - -for (var d3_rgb_name in d3_rgb_names) { - d3_rgb_names[d3_rgb_name] = d3_rgb_parse( - d3_rgb_names[d3_rgb_name], - d3_rgb, - d3_hsl_rgb); -} -d3.hsl = function(h, s, l) { - return arguments.length === 1 - ? (h instanceof d3_Hsl ? d3_hsl(h.h, h.s, h.l) - : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl)) - : d3_hsl(+h, +s, +l); -}; - -function d3_hsl(h, s, l) { - return new d3_Hsl(h, s, l); -} - -function d3_Hsl(h, s, l) { - this.h = h; - this.s = s; - this.l = l; -} - -d3_Hsl.prototype.brighter = function(k) { - k = Math.pow(0.7, arguments.length ? k : 1); - return d3_hsl(this.h, this.s, this.l / k); -}; - -d3_Hsl.prototype.darker = function(k) { - k = Math.pow(0.7, arguments.length ? k : 1); - return d3_hsl(this.h, this.s, k * this.l); -}; - -d3_Hsl.prototype.rgb = function() { - return d3_hsl_rgb(this.h, this.s, this.l); -}; - -d3_Hsl.prototype.toString = function() { - return this.rgb().toString(); -}; - -function d3_hsl_rgb(h, s, l) { - var m1, - m2; - - /* Some simple corrections for h, s and l. */ - h = h % 360; if (h < 0) h += 360; - s = s < 0 ? 0 : s > 1 ? 1 : s; - l = l < 0 ? 0 : l > 1 ? 1 : l; - - /* From FvD 13.37, CSS Color Module Level 3 */ - m2 = l <= .5 ? l * (1 + s) : l + s - l * s; - m1 = 2 * l - m2; - - function v(h) { - if (h > 360) h -= 360; - else if (h < 0) h += 360; - if (h < 60) return m1 + (m2 - m1) * h / 60; - if (h < 180) return m2; - if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60; - return m1; - } - - function vv(h) { - return Math.round(v(h) * 255); - } - - return d3_rgb(vv(h + 120), vv(h), vv(h - 120)); -} -function d3_selection(groups) { - d3_arraySubclass(groups, d3_selectionPrototype); - return groups; -} - -var d3_select = function(s, n) { return n.querySelector(s); }, - d3_selectAll = function(s, n) { return n.querySelectorAll(s); }; - -// Prefer Sizzle, if available. -if (typeof Sizzle === "function") { - d3_select = function(s, n) { return Sizzle(s, n)[0]; }; - d3_selectAll = function(s, n) { return Sizzle.uniqueSort(Sizzle(s, n)); }; -} - -var d3_selectionPrototype = []; - -d3.selection = function() { - return d3_selectionRoot; -}; - -d3.selection.prototype = d3_selectionPrototype; -d3_selectionPrototype.select = function(selector) { - var subgroups = [], - subgroup, - subnode, - group, - node; - - if (typeof selector !== "function") selector = d3_selection_selector(selector); - - for (var j = -1, m = this.length; ++j < m;) { - subgroups.push(subgroup = []); - subgroup.parentNode = (group = this[j]).parentNode; - for (var i = -1, n = group.length; ++i < n;) { - if (node = group[i]) { - subgroup.push(subnode = selector.call(node, node.__data__, i)); - if (subnode && "__data__" in node) subnode.__data__ = node.__data__; - } else { - subgroup.push(null); - } - } - } - - return d3_selection(subgroups); -}; - -function d3_selection_selector(selector) { - return function() { - return d3_select(selector, this); - }; -} -d3_selectionPrototype.selectAll = function(selector) { - var subgroups = [], - subgroup, - node; - - if (typeof selector !== "function") selector = d3_selection_selectorAll(selector); - - for (var j = -1, m = this.length; ++j < m;) { - for (var group = this[j], i = -1, n = group.length; ++i < n;) { - if (node = group[i]) { - subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i))); - subgroup.parentNode = node; - } - } - } - - return d3_selection(subgroups); -}; - -function d3_selection_selectorAll(selector) { - return function() { - return d3_selectAll(selector, this); - }; -} -d3_selectionPrototype.attr = function(name, value) { - name = d3.ns.qualify(name); - - // If no value is specified, return the first value. - if (arguments.length < 2) { - var node = this.node(); - return name.local - ? node.getAttributeNS(name.space, name.local) - : node.getAttribute(name); - } - - function attrNull() { - this.removeAttribute(name); - } - - function attrNullNS() { - this.removeAttributeNS(name.space, name.local); - } - - function attrConstant() { - this.setAttribute(name, value); - } - - function attrConstantNS() { - this.setAttributeNS(name.space, name.local, value); - } - - function attrFunction() { - var x = value.apply(this, arguments); - if (x == null) this.removeAttribute(name); - else this.setAttribute(name, x); - } - - function attrFunctionNS() { - var x = value.apply(this, arguments); - if (x == null) this.removeAttributeNS(name.space, name.local); - else this.setAttributeNS(name.space, name.local, x); - } - - return this.each(value == null - ? (name.local ? attrNullNS : attrNull) : (typeof value === "function" - ? (name.local ? attrFunctionNS : attrFunction) - : (name.local ? attrConstantNS : attrConstant))); -}; -d3_selectionPrototype.classed = function(name, value) { - var names = name.split(d3_selection_classedWhitespace), - n = names.length, - i = -1; - if (arguments.length > 1) { - while (++i < n) d3_selection_classed.call(this, names[i], value); - return this; - } else { - while (++i < n) if (!d3_selection_classed.call(this, names[i])) return false; - return true; - } -}; - -var d3_selection_classedWhitespace = /\s+/g; - -function d3_selection_classed(name, value) { - var re = new RegExp("(^|\\s+)" + d3.requote(name) + "(\\s+|$)", "g"); - - // If no value is specified, return the first value. - if (arguments.length < 2) { - var node = this.node(); - if (c = node.classList) return c.contains(name); - var c = node.className; - re.lastIndex = 0; - return re.test(c.baseVal != null ? c.baseVal : c); - } - - function classedAdd() { - if (c = this.classList) return c.add(name); - var c = this.className, - cb = c.baseVal != null, - cv = cb ? c.baseVal : c; - re.lastIndex = 0; - if (!re.test(cv)) { - cv = d3_collapse(cv + " " + name); - if (cb) c.baseVal = cv; - else this.className = cv; - } - } - - function classedRemove() { - if (c = this.classList) return c.remove(name); - var c = this.className, - cb = c.baseVal != null, - cv = cb ? c.baseVal : c; - cv = d3_collapse(cv.replace(re, " ")); - if (cb) c.baseVal = cv; - else this.className = cv; - } - - function classedFunction() { - (value.apply(this, arguments) - ? classedAdd - : classedRemove).call(this); - } - - return this.each(typeof value === "function" - ? classedFunction : value - ? classedAdd - : classedRemove); -} -d3_selectionPrototype.style = function(name, value, priority) { - if (arguments.length < 3) priority = ""; - - // If no value is specified, return the first value. - if (arguments.length < 2) return window - .getComputedStyle(this.node(), null) - .getPropertyValue(name); - - function styleNull() { - this.style.removeProperty(name); - } - - function styleConstant() { - this.style.setProperty(name, value, priority); - } - - function styleFunction() { - var x = value.apply(this, arguments); - if (x == null) this.style.removeProperty(name); - else this.style.setProperty(name, x, priority); - } - - return this.each(value == null - ? styleNull : (typeof value === "function" - ? styleFunction : styleConstant)); -}; -d3_selectionPrototype.property = function(name, value) { - - // If no value is specified, return the first value. - if (arguments.length < 2) return this.node()[name]; - - function propertyNull() { - delete this[name]; - } - - function propertyConstant() { - this[name] = value; - } - - function propertyFunction() { - var x = value.apply(this, arguments); - if (x == null) delete this[name]; - else this[name] = x; - } - - return this.each(value == null - ? propertyNull : (typeof value === "function" - ? propertyFunction : propertyConstant)); -}; -d3_selectionPrototype.text = function(value) { - return arguments.length < 1 ? this.node().textContent - : (this.each(typeof value === "function" - ? function() { this.textContent = value.apply(this, arguments); } - : function() { this.textContent = value; })); -}; -d3_selectionPrototype.html = function(value) { - return arguments.length < 1 ? this.node().innerHTML - : (this.each(typeof value === "function" - ? function() { this.innerHTML = value.apply(this, arguments); } - : function() { this.innerHTML = value; })); -}; -// TODO append(node)? -// TODO append(function)? -d3_selectionPrototype.append = function(name) { - name = d3.ns.qualify(name); - - function append() { - return this.appendChild(document.createElementNS(this.namespaceURI, name)); - } - - function appendNS() { - return this.appendChild(document.createElementNS(name.space, name.local)); - } - - return this.select(name.local ? appendNS : append); -}; -// TODO insert(node, function)? -// TODO insert(function, string)? -// TODO insert(function, function)? -d3_selectionPrototype.insert = function(name, before) { - name = d3.ns.qualify(name); - - function insert() { - return this.insertBefore( - document.createElementNS(this.namespaceURI, name), - d3_select(before, this)); - } - - function insertNS() { - return this.insertBefore( - document.createElementNS(name.space, name.local), - d3_select(before, this)); - } - - return this.select(name.local ? insertNS : insert); -}; -// TODO remove(selector)? -// TODO remove(node)? -// TODO remove(function)? -d3_selectionPrototype.remove = function() { - return this.each(function() { - var parent = this.parentNode; - if (parent) parent.removeChild(this); - }); -}; -// TODO data(null) for clearing data? -d3_selectionPrototype.data = function(data, join) { - var enter = [], - update = [], - exit = []; - - function bind(group, groupData) { - var i, - n = group.length, - m = groupData.length, - n0 = Math.min(n, m), - n1 = Math.max(n, m), - updateNodes = [], - enterNodes = [], - exitNodes = [], - node, - nodeData; - - if (join) { - var nodeByKey = {}, - keys = [], - key, - j = groupData.length; - - for (i = -1; ++i < n;) { - key = join.call(node = group[i], node.__data__, i); - if (key in nodeByKey) { - exitNodes[j++] = node; // duplicate key - } else { - nodeByKey[key] = node; - } - keys.push(key); - } - - for (i = -1; ++i < m;) { - node = nodeByKey[key = join.call(groupData, nodeData = groupData[i], i)]; - if (node) { - node.__data__ = nodeData; - updateNodes[i] = node; - enterNodes[i] = exitNodes[i] = null; - } else { - enterNodes[i] = d3_selection_dataNode(nodeData); - updateNodes[i] = exitNodes[i] = null; - } - delete nodeByKey[key]; - } - - for (i = -1; ++i < n;) { - if (keys[i] in nodeByKey) { - exitNodes[i] = group[i]; - } - } - } else { - for (i = -1; ++i < n0;) { - node = group[i]; - nodeData = groupData[i]; - if (node) { - node.__data__ = nodeData; - updateNodes[i] = node; - enterNodes[i] = exitNodes[i] = null; - } else { - enterNodes[i] = d3_selection_dataNode(nodeData); - updateNodes[i] = exitNodes[i] = null; - } - } - for (; i < m; ++i) { - enterNodes[i] = d3_selection_dataNode(groupData[i]); - updateNodes[i] = exitNodes[i] = null; - } - for (; i < n1; ++i) { - exitNodes[i] = group[i]; - enterNodes[i] = updateNodes[i] = null; - } - } - - enterNodes.update - = updateNodes; - - enterNodes.parentNode - = updateNodes.parentNode - = exitNodes.parentNode - = group.parentNode; - - enter.push(enterNodes); - update.push(updateNodes); - exit.push(exitNodes); - } - - var i = -1, - n = this.length, - group; - if (typeof data === "function") { - while (++i < n) { - bind(group = this[i], data.call(group, group.parentNode.__data__, i)); - } - } else { - while (++i < n) { - bind(group = this[i], data); - } - } - - var selection = d3_selection(update); - selection.enter = function() { return d3_selection_enter(enter); }; - selection.exit = function() { return d3_selection(exit); }; - return selection; -}; - -function d3_selection_dataNode(data) { - return {__data__: data}; -} -// TODO preserve null elements to maintain index? -d3_selectionPrototype.filter = function(filter) { - var subgroups = [], - subgroup, - group, - node; - - for (var j = 0, m = this.length; j < m; j++) { - subgroups.push(subgroup = []); - subgroup.parentNode = (group = this[j]).parentNode; - for (var i = 0, n = group.length; i < n; i++) { - if ((node = group[i]) && filter.call(node, node.__data__, i)) { - subgroup.push(node); - } - } - } - - return d3_selection(subgroups); -}; -d3_selectionPrototype.map = function(map) { - return this.each(function() { - this.__data__ = map.apply(this, arguments); - }); -}; -d3_selectionPrototype.sort = function(comparator) { - comparator = d3_selection_sortComparator.apply(this, arguments); - for (var j = 0, m = this.length; j < m; j++) { - for (var group = this[j].sort(comparator), i = 1, n = group.length, prev = group[0]; i < n; i++) { - var node = group[i]; - if (node) { - if (prev) prev.parentNode.insertBefore(node, prev.nextSibling); - prev = node; - } - } - } - return this; -}; - -function d3_selection_sortComparator(comparator) { - if (!arguments.length) comparator = d3.ascending; - return function(a, b) { - return comparator(a && a.__data__, b && b.__data__); - }; -} -// type can be namespaced, e.g., "click.foo" -// listener can be null for removal -d3_selectionPrototype.on = function(type, listener, capture) { - if (arguments.length < 3) capture = false; - - // parse the type specifier - var name = "__on" + type, i = type.indexOf("."); - if (i > 0) type = type.substring(0, i); - - // if called with only one argument, return the current listener - if (arguments.length < 2) return (i = this.node()[name]) && i._; - - // remove the old event listener, and add the new event listener - return this.each(function(d, i) { - var node = this; - - if (node[name]) node.removeEventListener(type, node[name], capture); - if (listener) node.addEventListener(type, node[name] = l, capture); - - // wrapped event listener that preserves i - function l(e) { - var o = d3.event; // Events can be reentrant (e.g., focus). - d3.event = e; - try { - listener.call(node, node.__data__, i); - } finally { - d3.event = o; - } - } - - // stash the unwrapped listener for retrieval - l._ = listener; - }); -}; -d3_selectionPrototype.each = function(callback) { - for (var j = -1, m = this.length; ++j < m;) { - for (var group = this[j], i = -1, n = group.length; ++i < n;) { - var node = group[i]; - if (node) callback.call(node, node.__data__, i, j); - } - } - return this; -}; -// -// Note: assigning to the arguments array simultaneously changes the value of -// the corresponding argument! -// -// TODO The `this` argument probably shouldn't be the first argument to the -// callback, anyway, since it's redundant. However, that will require a major -// version bump due to backwards compatibility, so I'm not changing it right -// away. -// -d3_selectionPrototype.call = function(callback) { - callback.apply(this, (arguments[0] = this, arguments)); - return this; -}; -d3_selectionPrototype.empty = function() { - return !this.node(); -}; -d3_selectionPrototype.node = function(callback) { - for (var j = 0, m = this.length; j < m; j++) { - for (var group = this[j], i = 0, n = group.length; i < n; i++) { - var node = group[i]; - if (node) return node; - } - } - return null; -}; -d3_selectionPrototype.transition = function() { - var subgroups = [], - subgroup, - node; - - for (var j = -1, m = this.length; ++j < m;) { - subgroups.push(subgroup = []); - for (var group = this[j], i = -1, n = group.length; ++i < n;) { - subgroup.push((node = group[i]) ? {node: node, delay: 0, duration: 250} : null); - } - } - - return d3_transition(subgroups, d3_transitionInheritId || ++d3_transitionId, Date.now()); -}; -var d3_selectionRoot = d3_selection([[document]]); - -d3_selectionRoot[0].parentNode = document.documentElement; - -// TODO fast singleton implementation! -// TODO select(function) -d3.select = function(selector) { - return typeof selector === "string" - ? d3_selectionRoot.select(selector) - : d3_selection([[selector]]); // assume node -}; - -// TODO selectAll(function) -d3.selectAll = function(selector) { - return typeof selector === "string" - ? d3_selectionRoot.selectAll(selector) - : d3_selection([d3_array(selector)]); // assume node[] -}; -function d3_selection_enter(selection) { - d3_arraySubclass(selection, d3_selection_enterPrototype); - return selection; -} - -var d3_selection_enterPrototype = []; - -d3_selection_enterPrototype.append = d3_selectionPrototype.append; -d3_selection_enterPrototype.insert = d3_selectionPrototype.insert; -d3_selection_enterPrototype.empty = d3_selectionPrototype.empty; -d3_selection_enterPrototype.node = d3_selectionPrototype.node; -d3_selection_enterPrototype.select = function(selector) { - var subgroups = [], - subgroup, - subnode, - upgroup, - group, - node; - - for (var j = -1, m = this.length; ++j < m;) { - upgroup = (group = this[j]).update; - subgroups.push(subgroup = []); - subgroup.parentNode = group.parentNode; - for (var i = -1, n = group.length; ++i < n;) { - if (node = group[i]) { - subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i)); - subnode.__data__ = node.__data__; - } else { - subgroup.push(null); - } - } - } - - return d3_selection(subgroups); -}; -function d3_transition(groups, id, time) { - d3_arraySubclass(groups, d3_transitionPrototype); - - var tweens = {}, - event = d3.dispatch("start", "end"), - ease = d3_transitionEase; - - groups.id = id; - - groups.time = time; - - groups.tween = function(name, tween) { - if (arguments.length < 2) return tweens[name]; - if (tween == null) delete tweens[name]; - else tweens[name] = tween; - return groups; - }; - - groups.ease = function(value) { - if (!arguments.length) return ease; - ease = typeof value === "function" ? value : d3.ease.apply(d3, arguments); - return groups; - }; - - groups.each = function(type, listener) { - if (arguments.length < 2) return d3_transition_each.call(groups, type); - event.on(type, listener); - return groups; - }; - - d3.timer(function(elapsed) { - groups.each(function(d, i, j) { - var tweened = [], - node = this, - delay = groups[j][i].delay, - duration = groups[j][i].duration, - lock = node.__transition__ || (node.__transition__ = {active: 0, count: 0}); - - ++lock.count; - - delay <= elapsed ? start(elapsed) : d3.timer(start, delay, time); - - function start(elapsed) { - if (lock.active > id) return stop(); - lock.active = id; - - for (var tween in tweens) { - if (tween = tweens[tween].call(node, d, i)) { - tweened.push(tween); - } - } - - event.start.call(node, d, i); - if (!tick(elapsed)) d3.timer(tick, 0, time); - return 1; - } - - function tick(elapsed) { - if (lock.active !== id) return stop(); - - var t = (elapsed - delay) / duration, - e = ease(t), - n = tweened.length; - - while (n > 0) { - tweened[--n].call(node, e); - } - - if (t >= 1) { - stop(); - d3_transitionInheritId = id; - event.end.call(node, d, i); - d3_transitionInheritId = 0; - return 1; - } - } - - function stop() { - if (!--lock.count) delete node.__transition__; - return 1; - } - }); - return 1; - }, 0, time); - - return groups; -} - -var d3_transitionRemove = {}; - -function d3_transitionNull(d, i, a) { - return a != "" && d3_transitionRemove; -} - -function d3_transitionTween(name, b) { - var interpolate = d3_interpolateByName(name); - - function transitionFunction(d, i, a) { - var v = b.call(this, d, i); - return v == null - ? a != "" && d3_transitionRemove - : a != v && interpolate(a, v); - } - - function transitionString(d, i, a) { - return a != b && interpolate(a, b); - } - - return typeof b === "function" ? transitionFunction - : b == null ? d3_transitionNull - : (b += "", transitionString); -} - -var d3_transitionPrototype = [], - d3_transitionId = 0, - d3_transitionInheritId = 0, - d3_transitionEase = d3.ease("cubic-in-out"); - -d3_transitionPrototype.call = d3_selectionPrototype.call; - -d3.transition = function() { - return d3_selectionRoot.transition(); -}; - -d3.transition.prototype = d3_transitionPrototype; -d3_transitionPrototype.select = function(selector) { - var subgroups = [], - subgroup, - subnode, - node; - - if (typeof selector !== "function") selector = d3_selection_selector(selector); - - for (var j = -1, m = this.length; ++j < m;) { - subgroups.push(subgroup = []); - for (var group = this[j], i = -1, n = group.length; ++i < n;) { - if ((node = group[i]) && (subnode = selector.call(node.node, node.node.__data__, i))) { - if ("__data__" in node.node) subnode.__data__ = node.node.__data__; - subgroup.push({node: subnode, delay: node.delay, duration: node.duration}); - } else { - subgroup.push(null); - } - } - } - - return d3_transition(subgroups, this.id, this.time).ease(this.ease()); -}; -d3_transitionPrototype.selectAll = function(selector) { - var subgroups = [], - subgroup, - subnodes, - node; - - if (typeof selector !== "function") selector = d3_selection_selectorAll(selector); - - for (var j = -1, m = this.length; ++j < m;) { - for (var group = this[j], i = -1, n = group.length; ++i < n;) { - if (node = group[i]) { - subnodes = selector.call(node.node, node.node.__data__, i); - subgroups.push(subgroup = []); - for (var k = -1, o = subnodes.length; ++k < o;) { - subgroup.push({node: subnodes[k], delay: node.delay, duration: node.duration}); - } - } - } - } - - return d3_transition(subgroups, this.id, this.time).ease(this.ease()); -}; -d3_transitionPrototype.attr = function(name, value) { - return this.attrTween(name, d3_transitionTween(name, value)); -}; - -d3_transitionPrototype.attrTween = function(nameNS, tween) { - var name = d3.ns.qualify(nameNS); - - function attrTween(d, i) { - var f = tween.call(this, d, i, this.getAttribute(name)); - return f === d3_transitionRemove - ? (this.removeAttribute(name), null) - : f && function(t) { this.setAttribute(name, f(t)); }; - } - - function attrTweenNS(d, i) { - var f = tween.call(this, d, i, this.getAttributeNS(name.space, name.local)); - return f === d3_transitionRemove - ? (this.removeAttributeNS(name.space, name.local), null) - : f && function(t) { this.setAttributeNS(name.space, name.local, f(t)); }; - } - - return this.tween("attr." + nameNS, name.local ? attrTweenNS : attrTween); -}; -d3_transitionPrototype.style = function(name, value, priority) { - if (arguments.length < 3) priority = ""; - return this.styleTween(name, d3_transitionTween(name, value), priority); -}; - -d3_transitionPrototype.styleTween = function(name, tween, priority) { - if (arguments.length < 3) priority = ""; - return this.tween("style." + name, function(d, i) { - var f = tween.call(this, d, i, window.getComputedStyle(this, null).getPropertyValue(name)); - return f === d3_transitionRemove - ? (this.style.removeProperty(name), null) - : f && function(t) { this.style.setProperty(name, f(t), priority); }; - }); -}; -d3_transitionPrototype.text = function(value) { - return this.tween("text", function(d, i) { - this.textContent = typeof value === "function" - ? value.call(this, d, i) - : value; - }); -}; -d3_transitionPrototype.remove = function() { - return this.each("end", function() { - var p; - if (!this.__transition__ && (p = this.parentNode)) p.removeChild(this); - }); -}; -d3_transitionPrototype.delay = function(value) { - var groups = this; - return groups.each(typeof value === "function" - ? function(d, i, j) { groups[j][i].delay = +value.apply(this, arguments); } - : (value = +value, function(d, i, j) { groups[j][i].delay = value; })); -}; -d3_transitionPrototype.duration = function(value) { - var groups = this; - return groups.each(typeof value === "function" - ? function(d, i, j) { groups[j][i].duration = +value.apply(this, arguments); } - : (value = +value, function(d, i, j) { groups[j][i].duration = value; })); -}; -function d3_transition_each(callback) { - for (var j = 0, m = this.length; j < m; j++) { - for (var group = this[j], i = 0, n = group.length; i < n; i++) { - var node = group[i]; - if (node) callback.call(node = node.node, node.__data__, i, j); - } - } - return this; -} -d3_transitionPrototype.transition = function() { - return this.select(d3_this); -}; -var d3_timer_queue = null, - d3_timer_interval, // is an interval (or frame) active? - d3_timer_timeout; // is a timeout active? - -// The timer will continue to fire until callback returns true. -d3.timer = function(callback, delay, then) { - var found = false, - t0, - t1 = d3_timer_queue; - - if (arguments.length < 3) { - if (arguments.length < 2) delay = 0; - else if (!isFinite(delay)) return; - then = Date.now(); - } - - // See if the callback's already in the queue. - while (t1) { - if (t1.callback === callback) { - t1.then = then; - t1.delay = delay; - found = true; - break; - } - t0 = t1; - t1 = t1.next; - } - - // Otherwise, add the callback to the queue. - if (!found) d3_timer_queue = { - callback: callback, - then: then, - delay: delay, - next: d3_timer_queue - }; - - // Start animatin'! - if (!d3_timer_interval) { - d3_timer_timeout = clearTimeout(d3_timer_timeout); - d3_timer_interval = 1; - d3_timer_frame(d3_timer_step); - } -} - -function d3_timer_step() { - var elapsed, - now = Date.now(), - t1 = d3_timer_queue; - - while (t1) { - elapsed = now - t1.then; - if (elapsed >= t1.delay) t1.flush = t1.callback(elapsed); - t1 = t1.next; - } - - var delay = d3_timer_flush() - now; - if (delay > 24) { - if (isFinite(delay)) { - clearTimeout(d3_timer_timeout); - d3_timer_timeout = setTimeout(d3_timer_step, delay); - } - d3_timer_interval = 0; - } else { - d3_timer_interval = 1; - d3_timer_frame(d3_timer_step); - } -} - -d3.timer.flush = function() { - var elapsed, - now = Date.now(), - t1 = d3_timer_queue; - - while (t1) { - elapsed = now - t1.then; - if (!t1.delay) t1.flush = t1.callback(elapsed); - t1 = t1.next; - } - - d3_timer_flush(); -}; - -// Flush after callbacks, to avoid concurrent queue modification. -function d3_timer_flush() { - var t0 = null, - t1 = d3_timer_queue, - then = Infinity; - while (t1) { - if (t1.flush) { - t1 = t0 ? t0.next = t1.next : d3_timer_queue = t1.next; - } else { - then = Math.min(then, t1.then + t1.delay); - t1 = (t0 = t1).next; - } - } - return then; -} - -var d3_timer_frame = window.requestAnimationFrame - || window.webkitRequestAnimationFrame - || window.mozRequestAnimationFrame - || window.oRequestAnimationFrame - || window.msRequestAnimationFrame - || function(callback) { setTimeout(callback, 17); }; -d3.transform = function(string) { - d3_transformG.setAttribute("transform", string); - var t = d3_transformG.transform.baseVal.consolidate(); - return new d3_transform(t ? t.matrix : d3_transformIdentity); -}; - -// Compute x-scale and normalize the first row. -// Compute shear and make second row orthogonal to first. -// Compute y-scale and normalize the second row. -// Finally, compute the rotation. -function d3_transform(m) { - var r0 = [m.a, m.b], - r1 = [m.c, m.d], - kx = d3_transformNormalize(r0), - kz = d3_transformDot(r0, r1), - ky = d3_transformNormalize(d3_transformCombine(r1, r0, -kz)) || 0; - if (r0[0] * r1[1] < r1[0] * r0[1]) { - r0[0] *= -1; - r0[1] *= -1; - kx *= -1; - kz *= -1; - } - this.rotate = (kx ? Math.atan2(r0[1], r0[0]) : Math.atan2(-r1[0], r1[1])) * d3_transformDegrees; - this.translate = [m.e, m.f]; - this.scale = [kx, ky]; - this.skew = ky ? Math.atan2(kz, ky) * d3_transformDegrees : 0; -}; - -d3_transform.prototype.toString = function() { - return "translate(" + this.translate - + ")rotate(" + this.rotate - + ")skewX(" + this.skew - + ")scale(" + this.scale - + ")"; -}; - -function d3_transformDot(a, b) { - return a[0] * b[0] + a[1] * b[1]; -} - -function d3_transformNormalize(a) { - var k = Math.sqrt(d3_transformDot(a, a)); - if (k) { - a[0] /= k; - a[1] /= k; - } - return k; -} - -function d3_transformCombine(a, b, k) { - a[0] += k * b[0]; - a[1] += k * b[1]; - return a; -} - -var d3_transformG = document.createElementNS(d3.ns.prefix.svg, "g"), - d3_transformIdentity = {a: 1, b: 0, c: 0, d: 1, e: 0, f: 0}, - d3_transformDegrees = 180 / Math.PI; -function d3_noop() {} -d3.scale = {}; - -function d3_scaleExtent(domain) { - var start = domain[0], stop = domain[domain.length - 1]; - return start < stop ? [start, stop] : [stop, start]; -} - -function d3_scaleRange(scale) { - return scale.rangeExtent ? scale.rangeExtent() : d3_scaleExtent(scale.range()); -} -function d3_scale_nice(domain, nice) { - var i0 = 0, - i1 = domain.length - 1, - x0 = domain[i0], - x1 = domain[i1], - dx; - - if (x1 < x0) { - dx = i0; i0 = i1; i1 = dx; - dx = x0; x0 = x1; x1 = dx; - } - - if (dx = x1 - x0) { - nice = nice(dx); - domain[i0] = nice.floor(x0); - domain[i1] = nice.ceil(x1); - } - - return domain; -} - -function d3_scale_niceDefault() { - return Math; -} -d3.scale.linear = function() { - return d3_scale_linear([0, 1], [0, 1], d3.interpolate, false); -}; - -function d3_scale_linear(domain, range, interpolate, clamp) { - var output, - input; - - function rescale() { - var linear = domain.length == 2 ? d3_scale_bilinear : d3_scale_polylinear, - uninterpolate = clamp ? d3_uninterpolateClamp : d3_uninterpolateNumber; - output = linear(domain, range, uninterpolate, interpolate); - input = linear(range, domain, uninterpolate, d3.interpolate); - return scale; - } - - function scale(x) { - return output(x); - } - - // Note: requires range is coercible to number! - scale.invert = function(y) { - return input(y); - }; - - scale.domain = function(x) { - if (!arguments.length) return domain; - domain = x.map(Number); - return rescale(); - }; - - scale.range = function(x) { - if (!arguments.length) return range; - range = x; - return rescale(); - }; - - scale.rangeRound = function(x) { - return scale.range(x).interpolate(d3.interpolateRound); - }; - - scale.clamp = function(x) { - if (!arguments.length) return clamp; - clamp = x; - return rescale(); - }; - - scale.interpolate = function(x) { - if (!arguments.length) return interpolate; - interpolate = x; - return rescale(); - }; - - scale.ticks = function(m) { - return d3_scale_linearTicks(domain, m); - }; - - scale.tickFormat = function(m) { - return d3_scale_linearTickFormat(domain, m); - }; - - scale.nice = function() { - d3_scale_nice(domain, d3_scale_linearNice); - return rescale(); - }; - - scale.copy = function() { - return d3_scale_linear(domain, range, interpolate, clamp); - }; - - return rescale(); -}; - -function d3_scale_linearRebind(scale, linear) { - return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp"); -} - -function d3_scale_linearNice(dx) { - dx = Math.pow(10, Math.round(Math.log(dx) / Math.LN10) - 1); - return { - floor: function(x) { return Math.floor(x / dx) * dx; }, - ceil: function(x) { return Math.ceil(x / dx) * dx; } - }; -} - -// TODO Dates? Ugh. -function d3_scale_linearTickRange(domain, m) { - var extent = d3_scaleExtent(domain), - span = extent[1] - extent[0], - step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10)), - err = m / span * step; - - // Filter ticks to get closer to the desired count. - if (err <= .15) step *= 10; - else if (err <= .35) step *= 5; - else if (err <= .75) step *= 2; - - // Round start and stop values to step interval. - extent[0] = Math.ceil(extent[0] / step) * step; - extent[1] = Math.floor(extent[1] / step) * step + step * .5; // inclusive - extent[2] = step; - return extent; -} - -function d3_scale_linearTicks(domain, m) { - return d3.range.apply(d3, d3_scale_linearTickRange(domain, m)); -} - -function d3_scale_linearTickFormat(domain, m) { - return d3.format(",." + Math.max(0, -Math.floor(Math.log(d3_scale_linearTickRange(domain, m)[2]) / Math.LN10 + .01)) + "f"); -} -function d3_scale_bilinear(domain, range, uninterpolate, interpolate) { - var u = uninterpolate(domain[0], domain[1]), - i = interpolate(range[0], range[1]); - return function(x) { - return i(u(x)); - }; -} -function d3_scale_polylinear(domain, range, uninterpolate, interpolate) { - var u = [], - i = [], - j = 0, - n = domain.length; - - while (++j < n) { - u.push(uninterpolate(domain[j - 1], domain[j])); - i.push(interpolate(range[j - 1], range[j])); - } - - return function(x) { - var j = d3.bisect(domain, x, 1, domain.length - 1) - 1; - return i[j](u[j](x)); - }; -} -d3.scale.log = function() { - return d3_scale_log(d3.scale.linear(), d3_scale_logp); -}; - -function d3_scale_log(linear, log) { - var pow = log.pow; - - function scale(x) { - return linear(log(x)); - } - - scale.invert = function(x) { - return pow(linear.invert(x)); - }; - - scale.domain = function(x) { - if (!arguments.length) return linear.domain().map(pow); - log = x[0] < 0 ? d3_scale_logn : d3_scale_logp; - pow = log.pow; - linear.domain(x.map(log)); - return scale; - }; - - scale.nice = function() { - linear.domain(d3_scale_nice(linear.domain(), d3_scale_niceDefault)); - return scale; - }; - - scale.ticks = function() { - var extent = d3_scaleExtent(linear.domain()), - ticks = []; - if (extent.every(isFinite)) { - var i = Math.floor(extent[0]), - j = Math.ceil(extent[1]), - u = pow(extent[0]), - v = pow(extent[1]); - if (log === d3_scale_logn) { - ticks.push(pow(i)); - for (; i++ < j;) for (var k = 9; k > 0; k--) ticks.push(pow(i) * k); - } else { - for (; i < j; i++) for (var k = 1; k < 10; k++) ticks.push(pow(i) * k); - ticks.push(pow(i)); - } - for (i = 0; ticks[i] < u; i++) {} // strip small values - for (j = ticks.length; ticks[j - 1] > v; j--) {} // strip big values - ticks = ticks.slice(i, j); - } - return ticks; - }; - - scale.tickFormat = function(n, format) { - if (arguments.length < 2) format = d3_scale_logFormat; - if (arguments.length < 1) return format; - var k = n / scale.ticks().length, - f = log === d3_scale_logn ? (e = -1e-12, Math.floor) : (e = 1e-12, Math.ceil), - e; - return function(d) { - return d / pow(f(log(d) + e)) < k ? format(d) : ""; - }; - }; - - scale.copy = function() { - return d3_scale_log(linear.copy(), log); - }; - - return d3_scale_linearRebind(scale, linear); -}; - -var d3_scale_logFormat = d3.format(".0e"); - -function d3_scale_logp(x) { - return Math.log(x) / Math.LN10; -} - -function d3_scale_logn(x) { - return -Math.log(-x) / Math.LN10; -} - -d3_scale_logp.pow = function(x) { - return Math.pow(10, x); -}; - -d3_scale_logn.pow = function(x) { - return -Math.pow(10, -x); -}; -d3.scale.pow = function() { - return d3_scale_pow(d3.scale.linear(), 1); -}; - -function d3_scale_pow(linear, exponent) { - var powp = d3_scale_powPow(exponent), - powb = d3_scale_powPow(1 / exponent); - - function scale(x) { - return linear(powp(x)); - } - - scale.invert = function(x) { - return powb(linear.invert(x)); - }; - - scale.domain = function(x) { - if (!arguments.length) return linear.domain().map(powb); - linear.domain(x.map(powp)); - return scale; - }; - - scale.ticks = function(m) { - return d3_scale_linearTicks(scale.domain(), m); - }; - - scale.tickFormat = function(m) { - return d3_scale_linearTickFormat(scale.domain(), m); - }; - - scale.nice = function() { - return scale.domain(d3_scale_nice(scale.domain(), d3_scale_linearNice)); - }; - - scale.exponent = function(x) { - if (!arguments.length) return exponent; - var domain = scale.domain(); - powp = d3_scale_powPow(exponent = x); - powb = d3_scale_powPow(1 / exponent); - return scale.domain(domain); - }; - - scale.copy = function() { - return d3_scale_pow(linear.copy(), exponent); - }; - - return d3_scale_linearRebind(scale, linear); -}; - -function d3_scale_powPow(e) { - return function(x) { - return x < 0 ? -Math.pow(-x, e) : Math.pow(x, e); - }; -} -d3.scale.sqrt = function() { - return d3.scale.pow().exponent(.5); -}; -d3.scale.ordinal = function() { - return d3_scale_ordinal([], {t: "range", x: []}); -}; - -function d3_scale_ordinal(domain, ranger) { - var index, - range, - rangeBand; - - function scale(x) { - return range[((index[x] || (index[x] = domain.push(x))) - 1) % range.length]; - } - - function steps(start, step) { - return d3.range(domain.length).map(function(i) { return start + step * i; }); - } - - scale.domain = function(x) { - if (!arguments.length) return domain; - domain = []; - index = {}; - var i = -1, n = x.length, xi; - while (++i < n) if (!index[xi = x[i]]) index[xi] = domain.push(xi); - return scale[ranger.t](ranger.x, ranger.p); - }; - - scale.range = function(x) { - if (!arguments.length) return range; - range = x; - rangeBand = 0; - ranger = {t: "range", x: x}; - return scale; - }; - - scale.rangePoints = function(x, padding) { - if (arguments.length < 2) padding = 0; - var start = x[0], - stop = x[1], - step = (stop - start) / (domain.length - 1 + padding); - range = steps(domain.length < 2 ? (start + stop) / 2 : start + step * padding / 2, step); - rangeBand = 0; - ranger = {t: "rangePoints", x: x, p: padding}; - return scale; - }; - - scale.rangeBands = function(x, padding) { - if (arguments.length < 2) padding = 0; - var start = x[0], - stop = x[1], - step = (stop - start) / (domain.length + padding); - range = steps(start + step * padding, step); - rangeBand = step * (1 - padding); - ranger = {t: "rangeBands", x: x, p: padding}; - return scale; - }; - - scale.rangeRoundBands = function(x, padding) { - if (arguments.length < 2) padding = 0; - var start = x[0], - stop = x[1], - step = Math.floor((stop - start) / (domain.length + padding)); - range = steps(start + Math.round((stop - start - (domain.length - padding) * step) / 2), step); - rangeBand = Math.round(step * (1 - padding)); - ranger = {t: "rangeRoundBands", x: x, p: padding}; - return scale; - }; - - scale.rangeBand = function() { - return rangeBand; - }; - - scale.rangeExtent = function() { - return ranger.x; - }; - - scale.copy = function() { - return d3_scale_ordinal(domain, ranger); - }; - - return scale.domain(domain); -}; -/* - * This product includes color specifications and designs developed by Cynthia - * Brewer (http://colorbrewer.org/). See lib/colorbrewer for more information. - */ - -d3.scale.category10 = function() { - return d3.scale.ordinal().range(d3_category10); -}; - -d3.scale.category20 = function() { - return d3.scale.ordinal().range(d3_category20); -}; - -d3.scale.category20b = function() { - return d3.scale.ordinal().range(d3_category20b); -}; - -d3.scale.category20c = function() { - return d3.scale.ordinal().range(d3_category20c); -}; - -var d3_category10 = [ - "#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd", - "#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf" -]; - -var d3_category20 = [ - "#1f77b4", "#aec7e8", - "#ff7f0e", "#ffbb78", - "#2ca02c", "#98df8a", - "#d62728", "#ff9896", - "#9467bd", "#c5b0d5", - "#8c564b", "#c49c94", - "#e377c2", "#f7b6d2", - "#7f7f7f", "#c7c7c7", - "#bcbd22", "#dbdb8d", - "#17becf", "#9edae5" -]; - -var d3_category20b = [ - "#393b79", "#5254a3", "#6b6ecf", "#9c9ede", - "#637939", "#8ca252", "#b5cf6b", "#cedb9c", - "#8c6d31", "#bd9e39", "#e7ba52", "#e7cb94", - "#843c39", "#ad494a", "#d6616b", "#e7969c", - "#7b4173", "#a55194", "#ce6dbd", "#de9ed6" -]; - -var d3_category20c = [ - "#3182bd", "#6baed6", "#9ecae1", "#c6dbef", - "#e6550d", "#fd8d3c", "#fdae6b", "#fdd0a2", - "#31a354", "#74c476", "#a1d99b", "#c7e9c0", - "#756bb1", "#9e9ac8", "#bcbddc", "#dadaeb", - "#636363", "#969696", "#bdbdbd", "#d9d9d9" -]; -d3.scale.quantile = function() { - return d3_scale_quantile([], []); -}; - -function d3_scale_quantile(domain, range) { - var thresholds; - - function rescale() { - var k = 0, - n = domain.length, - q = range.length; - thresholds = []; - while (++k < q) thresholds[k - 1] = d3.quantile(domain, k / q); - return scale; - } - - function scale(x) { - if (isNaN(x = +x)) return NaN; - return range[d3.bisect(thresholds, x)]; - } - - scale.domain = function(x) { - if (!arguments.length) return domain; - domain = x.filter(function(d) { return !isNaN(d); }).sort(d3.ascending); - return rescale(); - }; - - scale.range = function(x) { - if (!arguments.length) return range; - range = x; - return rescale(); - }; - - scale.quantiles = function() { - return thresholds; - }; - - scale.copy = function() { - return d3_scale_quantile(domain, range); // copy on write! - }; - - return rescale(); -}; -d3.scale.quantize = function() { - return d3_scale_quantize(0, 1, [0, 1]); -}; - -function d3_scale_quantize(x0, x1, range) { - var kx, i; - - function scale(x) { - return range[Math.max(0, Math.min(i, Math.floor(kx * (x - x0))))]; - } - - function rescale() { - kx = range.length / (x1 - x0); - i = range.length - 1; - return scale; - } - - scale.domain = function(x) { - if (!arguments.length) return [x0, x1]; - x0 = +x[0]; - x1 = +x[x.length - 1]; - return rescale(); - }; - - scale.range = function(x) { - if (!arguments.length) return range; - range = x; - return rescale(); - }; - - scale.copy = function() { - return d3_scale_quantize(x0, x1, range); // copy on write - }; - - return rescale(); -}; -d3.svg = {}; -d3.svg.arc = function() { - var innerRadius = d3_svg_arcInnerRadius, - outerRadius = d3_svg_arcOuterRadius, - startAngle = d3_svg_arcStartAngle, - endAngle = d3_svg_arcEndAngle; - - function arc() { - var r0 = innerRadius.apply(this, arguments), - r1 = outerRadius.apply(this, arguments), - a0 = startAngle.apply(this, arguments) + d3_svg_arcOffset, - a1 = endAngle.apply(this, arguments) + d3_svg_arcOffset, - da = (a1 < a0 && (da = a0, a0 = a1, a1 = da), a1 - a0), - df = da < Math.PI ? "0" : "1", - c0 = Math.cos(a0), - s0 = Math.sin(a0), - c1 = Math.cos(a1), - s1 = Math.sin(a1); - return da >= d3_svg_arcMax - ? (r0 - ? "M0," + r1 - + "A" + r1 + "," + r1 + " 0 1,1 0," + (-r1) - + "A" + r1 + "," + r1 + " 0 1,1 0," + r1 - + "M0," + r0 - + "A" + r0 + "," + r0 + " 0 1,0 0," + (-r0) - + "A" + r0 + "," + r0 + " 0 1,0 0," + r0 - + "Z" - : "M0," + r1 - + "A" + r1 + "," + r1 + " 0 1,1 0," + (-r1) - + "A" + r1 + "," + r1 + " 0 1,1 0," + r1 - + "Z") - : (r0 - ? "M" + r1 * c0 + "," + r1 * s0 - + "A" + r1 + "," + r1 + " 0 " + df + ",1 " + r1 * c1 + "," + r1 * s1 - + "L" + r0 * c1 + "," + r0 * s1 - + "A" + r0 + "," + r0 + " 0 " + df + ",0 " + r0 * c0 + "," + r0 * s0 - + "Z" - : "M" + r1 * c0 + "," + r1 * s0 - + "A" + r1 + "," + r1 + " 0 " + df + ",1 " + r1 * c1 + "," + r1 * s1 - + "L0,0" - + "Z"); - } - - arc.innerRadius = function(v) { - if (!arguments.length) return innerRadius; - innerRadius = d3.functor(v); - return arc; - }; - - arc.outerRadius = function(v) { - if (!arguments.length) return outerRadius; - outerRadius = d3.functor(v); - return arc; - }; - - arc.startAngle = function(v) { - if (!arguments.length) return startAngle; - startAngle = d3.functor(v); - return arc; - }; - - arc.endAngle = function(v) { - if (!arguments.length) return endAngle; - endAngle = d3.functor(v); - return arc; - }; - - arc.centroid = function() { - var r = (innerRadius.apply(this, arguments) - + outerRadius.apply(this, arguments)) / 2, - a = (startAngle.apply(this, arguments) - + endAngle.apply(this, arguments)) / 2 + d3_svg_arcOffset; - return [Math.cos(a) * r, Math.sin(a) * r]; - }; - - return arc; -}; - -var d3_svg_arcOffset = -Math.PI / 2, - d3_svg_arcMax = 2 * Math.PI - 1e-6; - -function d3_svg_arcInnerRadius(d) { - return d.innerRadius; -} - -function d3_svg_arcOuterRadius(d) { - return d.outerRadius; -} - -function d3_svg_arcStartAngle(d) { - return d.startAngle; -} - -function d3_svg_arcEndAngle(d) { - return d.endAngle; -} -function d3_svg_line(projection) { - var x = d3_svg_lineX, - y = d3_svg_lineY, - interpolate = "linear", - interpolator = d3_svg_lineInterpolators[interpolate], - tension = .7; - - function line(d) { - return d.length < 1 ? null : "M" + interpolator(projection(d3_svg_linePoints(this, d, x, y)), tension); - } - - line.x = function(v) { - if (!arguments.length) return x; - x = v; - return line; - }; - - line.y = function(v) { - if (!arguments.length) return y; - y = v; - return line; - }; - - line.interpolate = function(v) { - if (!arguments.length) return interpolate; - interpolator = d3_svg_lineInterpolators[interpolate = v]; - return line; - }; - - line.tension = function(v) { - if (!arguments.length) return tension; - tension = v; - return line; - }; - - return line; -} - -d3.svg.line = function() { - return d3_svg_line(Object); -}; - -// Converts the specified array of data into an array of points -// (x-y tuples), by evaluating the specified `x` and `y` functions on each -// data point. The `this` context of the evaluated functions is the specified -// "self" object; each function is passed the current datum and index. -function d3_svg_linePoints(self, d, x, y) { - var points = [], - i = -1, - n = d.length, - fx = typeof x === "function", - fy = typeof y === "function", - value; - if (fx && fy) { - while (++i < n) points.push([ - x.call(self, value = d[i], i), - y.call(self, value, i) - ]); - } else if (fx) { - while (++i < n) points.push([x.call(self, d[i], i), y]); - } else if (fy) { - while (++i < n) points.push([x, y.call(self, d[i], i)]); - } else { - while (++i < n) points.push([x, y]); - } - return points; -} - -// The default `x` property, which references d[0]. -function d3_svg_lineX(d) { - return d[0]; -} - -// The default `y` property, which references d[1]. -function d3_svg_lineY(d) { - return d[1]; -} - -// The various interpolators supported by the `line` class. -var d3_svg_lineInterpolators = { - "linear": d3_svg_lineLinear, - "step-before": d3_svg_lineStepBefore, - "step-after": d3_svg_lineStepAfter, - "basis": d3_svg_lineBasis, - "basis-open": d3_svg_lineBasisOpen, - "basis-closed": d3_svg_lineBasisClosed, - "bundle": d3_svg_lineBundle, - "cardinal": d3_svg_lineCardinal, - "cardinal-open": d3_svg_lineCardinalOpen, - "cardinal-closed": d3_svg_lineCardinalClosed, - "monotone": d3_svg_lineMonotone -}; - -// Linear interpolation; generates "L" commands. -function d3_svg_lineLinear(points) { - var i = 0, - n = points.length, - p = points[0], - path = [p[0], ",", p[1]]; - while (++i < n) path.push("L", (p = points[i])[0], ",", p[1]); - return path.join(""); -} - -// Step interpolation; generates "H" and "V" commands. -function d3_svg_lineStepBefore(points) { - var i = 0, - n = points.length, - p = points[0], - path = [p[0], ",", p[1]]; - while (++i < n) path.push("V", (p = points[i])[1], "H", p[0]); - return path.join(""); -} - -// Step interpolation; generates "H" and "V" commands. -function d3_svg_lineStepAfter(points) { - var i = 0, - n = points.length, - p = points[0], - path = [p[0], ",", p[1]]; - while (++i < n) path.push("H", (p = points[i])[0], "V", p[1]); - return path.join(""); -} - -// Open cardinal spline interpolation; generates "C" commands. -function d3_svg_lineCardinalOpen(points, tension) { - return points.length < 4 - ? d3_svg_lineLinear(points) - : points[1] + d3_svg_lineHermite(points.slice(1, points.length - 1), - d3_svg_lineCardinalTangents(points, tension)); -} - -// Closed cardinal spline interpolation; generates "C" commands. -function d3_svg_lineCardinalClosed(points, tension) { - return points.length < 3 - ? d3_svg_lineLinear(points) - : points[0] + d3_svg_lineHermite((points.push(points[0]), points), - d3_svg_lineCardinalTangents([points[points.length - 2]] - .concat(points, [points[1]]), tension)); -} - -// Cardinal spline interpolation; generates "C" commands. -function d3_svg_lineCardinal(points, tension, closed) { - return points.length < 3 - ? d3_svg_lineLinear(points) - : points[0] + d3_svg_lineHermite(points, - d3_svg_lineCardinalTangents(points, tension)); -} - -// Hermite spline construction; generates "C" commands. -function d3_svg_lineHermite(points, tangents) { - if (tangents.length < 1 - || (points.length != tangents.length - && points.length != tangents.length + 2)) { - return d3_svg_lineLinear(points); - } - - var quad = points.length != tangents.length, - path = "", - p0 = points[0], - p = points[1], - t0 = tangents[0], - t = t0, - pi = 1; - - if (quad) { - path += "Q" + (p[0] - t0[0] * 2 / 3) + "," + (p[1] - t0[1] * 2 / 3) - + "," + p[0] + "," + p[1]; - p0 = points[1]; - pi = 2; - } - - if (tangents.length > 1) { - t = tangents[1]; - p = points[pi]; - pi++; - path += "C" + (p0[0] + t0[0]) + "," + (p0[1] + t0[1]) - + "," + (p[0] - t[0]) + "," + (p[1] - t[1]) - + "," + p[0] + "," + p[1]; - for (var i = 2; i < tangents.length; i++, pi++) { - p = points[pi]; - t = tangents[i]; - path += "S" + (p[0] - t[0]) + "," + (p[1] - t[1]) - + "," + p[0] + "," + p[1]; - } - } - - if (quad) { - var lp = points[pi]; - path += "Q" + (p[0] + t[0] * 2 / 3) + "," + (p[1] + t[1] * 2 / 3) - + "," + lp[0] + "," + lp[1]; - } - - return path; -} - -// Generates tangents for a cardinal spline. -function d3_svg_lineCardinalTangents(points, tension) { - var tangents = [], - a = (1 - tension) / 2, - p0, - p1 = points[0], - p2 = points[1], - i = 1, - n = points.length; - while (++i < n) { - p0 = p1; - p1 = p2; - p2 = points[i]; - tangents.push([a * (p2[0] - p0[0]), a * (p2[1] - p0[1])]); - } - return tangents; -} - -// B-spline interpolation; generates "C" commands. -function d3_svg_lineBasis(points) { - if (points.length < 3) return d3_svg_lineLinear(points); - var i = 1, - n = points.length, - pi = points[0], - x0 = pi[0], - y0 = pi[1], - px = [x0, x0, x0, (pi = points[1])[0]], - py = [y0, y0, y0, pi[1]], - path = [x0, ",", y0]; - d3_svg_lineBasisBezier(path, px, py); - while (++i < n) { - pi = points[i]; - px.shift(); px.push(pi[0]); - py.shift(); py.push(pi[1]); - d3_svg_lineBasisBezier(path, px, py); - } - i = -1; - while (++i < 2) { - px.shift(); px.push(pi[0]); - py.shift(); py.push(pi[1]); - d3_svg_lineBasisBezier(path, px, py); - } - return path.join(""); -} - -// Open B-spline interpolation; generates "C" commands. -function d3_svg_lineBasisOpen(points) { - if (points.length < 4) return d3_svg_lineLinear(points); - var path = [], - i = -1, - n = points.length, - pi, - px = [0], - py = [0]; - while (++i < 3) { - pi = points[i]; - px.push(pi[0]); - py.push(pi[1]); - } - path.push(d3_svg_lineDot4(d3_svg_lineBasisBezier3, px) - + "," + d3_svg_lineDot4(d3_svg_lineBasisBezier3, py)); - --i; while (++i < n) { - pi = points[i]; - px.shift(); px.push(pi[0]); - py.shift(); py.push(pi[1]); - d3_svg_lineBasisBezier(path, px, py); - } - return path.join(""); -} - -// Closed B-spline interpolation; generates "C" commands. -function d3_svg_lineBasisClosed(points) { - var path, - i = -1, - n = points.length, - m = n + 4, - pi, - px = [], - py = []; - while (++i < 4) { - pi = points[i % n]; - px.push(pi[0]); - py.push(pi[1]); - } - path = [ - d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", - d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) - ]; - --i; while (++i < m) { - pi = points[i % n]; - px.shift(); px.push(pi[0]); - py.shift(); py.push(pi[1]); - d3_svg_lineBasisBezier(path, px, py); - } - return path.join(""); -} - -function d3_svg_lineBundle(points, tension) { - var n = points.length - 1, - x0 = points[0][0], - y0 = points[0][1], - dx = points[n][0] - x0, - dy = points[n][1] - y0, - i = -1, - p, - t; - while (++i <= n) { - p = points[i]; - t = i / n; - p[0] = tension * p[0] + (1 - tension) * (x0 + t * dx); - p[1] = tension * p[1] + (1 - tension) * (y0 + t * dy); - } - return d3_svg_lineBasis(points); -} - -// Returns the dot product of the given four-element vectors. -function d3_svg_lineDot4(a, b) { - return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; -} - -// Matrix to transform basis (b-spline) control points to bezier -// control points. Derived from FvD 11.2.8. -var d3_svg_lineBasisBezier1 = [0, 2/3, 1/3, 0], - d3_svg_lineBasisBezier2 = [0, 1/3, 2/3, 0], - d3_svg_lineBasisBezier3 = [0, 1/6, 2/3, 1/6]; - -// Pushes a "C" Bézier curve onto the specified path array, given the -// two specified four-element arrays which define the control points. -function d3_svg_lineBasisBezier(path, x, y) { - path.push( - "C", d3_svg_lineDot4(d3_svg_lineBasisBezier1, x), - ",", d3_svg_lineDot4(d3_svg_lineBasisBezier1, y), - ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, x), - ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, y), - ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, x), - ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, y)); -} - -// Computes the slope from points p0 to p1. -function d3_svg_lineSlope(p0, p1) { - return (p1[1] - p0[1]) / (p1[0] - p0[0]); -} - -// Compute three-point differences for the given points. -// http://en.wikipedia.org/wiki/Cubic_Hermite_spline#Finite_difference -function d3_svg_lineFiniteDifferences(points) { - var i = 0, - j = points.length - 1, - m = [], - p0 = points[0], - p1 = points[1], - d = m[0] = d3_svg_lineSlope(p0, p1); - while (++i < j) { - m[i] = d + (d = d3_svg_lineSlope(p0 = p1, p1 = points[i + 1])); - } - m[i] = d; - return m; -} - -// Interpolates the given points using Fritsch-Carlson Monotone cubic Hermite -// interpolation. Returns an array of tangent vectors. For details, see -// http://en.wikipedia.org/wiki/Monotone_cubic_interpolation -function d3_svg_lineMonotoneTangents(points) { - var tangents = [], - d, - a, - b, - s, - m = d3_svg_lineFiniteDifferences(points), - i = -1, - j = points.length - 1; - - // The first two steps are done by computing finite-differences: - // 1. Compute the slopes of the secant lines between successive points. - // 2. Initialize the tangents at every point as the average of the secants. - - // Then, for each segment… - while (++i < j) { - d = d3_svg_lineSlope(points[i], points[i + 1]); - - // 3. If two successive yk = y{k + 1} are equal (i.e., d is zero), then set - // mk = m{k + 1} = 0 as the spline connecting these points must be flat to - // preserve monotonicity. Ignore step 4 and 5 for those k. - - if (Math.abs(d) < 1e-6) { - m[i] = m[i + 1] = 0; - } else { - // 4. Let ak = mk / dk and bk = m{k + 1} / dk. - a = m[i] / d; - b = m[i + 1] / d; - - // 5. Prevent overshoot and ensure monotonicity by restricting the - // magnitude of vector to a circle of radius 3. - s = a * a + b * b; - if (s > 9) { - s = d * 3 / Math.sqrt(s); - m[i] = s * a; - m[i + 1] = s * b; - } - } - } - - // Compute the normalized tangent vector from the slopes. Note that if x is - // not monotonic, it's possible that the slope will be infinite, so we protect - // against NaN by setting the coordinate to zero. - i = -1; while (++i <= j) { - s = (points[Math.min(j, i + 1)][0] - points[Math.max(0, i - 1)][0]) - / (6 * (1 + m[i] * m[i])); - tangents.push([s || 0, m[i] * s || 0]); - } - - return tangents; -} - -function d3_svg_lineMonotone(points) { - return points.length < 3 - ? d3_svg_lineLinear(points) - : points[0] + - d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points)); -} -d3.svg.line.radial = function() { - var line = d3_svg_line(d3_svg_lineRadial); - line.radius = line.x, delete line.x; - line.angle = line.y, delete line.y; - return line; -}; - -function d3_svg_lineRadial(points) { - var point, - i = -1, - n = points.length, - r, - a; - while (++i < n) { - point = points[i]; - r = point[0]; - a = point[1] + d3_svg_arcOffset; - point[0] = r * Math.cos(a); - point[1] = r * Math.sin(a); - } - return points; -} -function d3_svg_area(projection) { - var x0 = d3_svg_lineX, - x1 = d3_svg_lineX, - y0 = 0, - y1 = d3_svg_lineY, - interpolate, - i0, - i1, - tension = .7; - - function area(d) { - if (d.length < 1) return null; - var points0 = d3_svg_linePoints(this, d, x0, y0), - points1 = d3_svg_linePoints(this, d, x0 === x1 ? d3_svg_areaX(points0) : x1, y0 === y1 ? d3_svg_areaY(points0) : y1); - return "M" + i0(projection(points1), tension) - + "L" + i1(projection(points0.reverse()), tension) - + "Z"; - } - - area.x = function(x) { - if (!arguments.length) return x1; - x0 = x1 = x; - return area; - }; - - area.x0 = function(x) { - if (!arguments.length) return x0; - x0 = x; - return area; - }; - - area.x1 = function(x) { - if (!arguments.length) return x1; - x1 = x; - return area; - }; - - area.y = function(y) { - if (!arguments.length) return y1; - y0 = y1 = y; - return area; - }; - - area.y0 = function(y) { - if (!arguments.length) return y0; - y0 = y; - return area; - }; - - area.y1 = function(y) { - if (!arguments.length) return y1; - y1 = y; - return area; - }; - - area.interpolate = function(x) { - if (!arguments.length) return interpolate; - i0 = d3_svg_lineInterpolators[interpolate = x]; - i1 = i0.reverse || i0; - return area; - }; - - area.tension = function(x) { - if (!arguments.length) return tension; - tension = x; - return area; - }; - - return area.interpolate("linear"); -} - -d3_svg_lineStepBefore.reverse = d3_svg_lineStepAfter; -d3_svg_lineStepAfter.reverse = d3_svg_lineStepBefore; - -d3.svg.area = function() { - return d3_svg_area(Object); -}; - -function d3_svg_areaX(points) { - return function(d, i) { - return points[i][0]; - }; -} - -function d3_svg_areaY(points) { - return function(d, i) { - return points[i][1]; - }; -} -d3.svg.area.radial = function() { - var area = d3_svg_area(d3_svg_lineRadial); - area.radius = area.x, delete area.x; - area.innerRadius = area.x0, delete area.x0; - area.outerRadius = area.x1, delete area.x1; - area.angle = area.y, delete area.y; - area.startAngle = area.y0, delete area.y0; - area.endAngle = area.y1, delete area.y1; - return area; -}; -d3.svg.chord = function() { - var source = d3_svg_chordSource, - target = d3_svg_chordTarget, - radius = d3_svg_chordRadius, - startAngle = d3_svg_arcStartAngle, - endAngle = d3_svg_arcEndAngle; - - // TODO Allow control point to be customized. - - function chord(d, i) { - var s = subgroup(this, source, d, i), - t = subgroup(this, target, d, i); - return "M" + s.p0 - + arc(s.r, s.p1) + (equals(s, t) - ? curve(s.r, s.p1, s.r, s.p0) - : curve(s.r, s.p1, t.r, t.p0) - + arc(t.r, t.p1) - + curve(t.r, t.p1, s.r, s.p0)) - + "Z"; - } - - function subgroup(self, f, d, i) { - var subgroup = f.call(self, d, i), - r = radius.call(self, subgroup, i), - a0 = startAngle.call(self, subgroup, i) + d3_svg_arcOffset, - a1 = endAngle.call(self, subgroup, i) + d3_svg_arcOffset; - return { - r: r, - a0: a0, - a1: a1, - p0: [r * Math.cos(a0), r * Math.sin(a0)], - p1: [r * Math.cos(a1), r * Math.sin(a1)] - }; - } - - function equals(a, b) { - return a.a0 == b.a0 && a.a1 == b.a1; - } - - function arc(r, p) { - return "A" + r + "," + r + " 0 0,1 " + p; - } - - function curve(r0, p0, r1, p1) { - return "Q 0,0 " + p1; - } - - chord.radius = function(v) { - if (!arguments.length) return radius; - radius = d3.functor(v); - return chord; - }; - - chord.source = function(v) { - if (!arguments.length) return source; - source = d3.functor(v); - return chord; - }; - - chord.target = function(v) { - if (!arguments.length) return target; - target = d3.functor(v); - return chord; - }; - - chord.startAngle = function(v) { - if (!arguments.length) return startAngle; - startAngle = d3.functor(v); - return chord; - }; - - chord.endAngle = function(v) { - if (!arguments.length) return endAngle; - endAngle = d3.functor(v); - return chord; - }; - - return chord; -}; - -function d3_svg_chordSource(d) { - return d.source; -} - -function d3_svg_chordTarget(d) { - return d.target; -} - -function d3_svg_chordRadius(d) { - return d.radius; -} - -function d3_svg_chordStartAngle(d) { - return d.startAngle; -} - -function d3_svg_chordEndAngle(d) { - return d.endAngle; -} -d3.svg.diagonal = function() { - var source = d3_svg_chordSource, - target = d3_svg_chordTarget, - projection = d3_svg_diagonalProjection; - - function diagonal(d, i) { - var p0 = source.call(this, d, i), - p3 = target.call(this, d, i), - m = (p0.y + p3.y) / 2, - p = [p0, {x: p0.x, y: m}, {x: p3.x, y: m}, p3]; - p = p.map(projection); - return "M" + p[0] + "C" + p[1] + " " + p[2] + " " + p[3]; - } - - diagonal.source = function(x) { - if (!arguments.length) return source; - source = d3.functor(x); - return diagonal; - }; - - diagonal.target = function(x) { - if (!arguments.length) return target; - target = d3.functor(x); - return diagonal; - }; - - diagonal.projection = function(x) { - if (!arguments.length) return projection; - projection = x; - return diagonal; - }; - - return diagonal; -}; - -function d3_svg_diagonalProjection(d) { - return [d.x, d.y]; -} -d3.svg.diagonal.radial = function() { - var diagonal = d3.svg.diagonal(), - projection = d3_svg_diagonalProjection, - projection_ = diagonal.projection; - - diagonal.projection = function(x) { - return arguments.length - ? projection_(d3_svg_diagonalRadialProjection(projection = x)) - : projection; - }; - - return diagonal; -}; - -function d3_svg_diagonalRadialProjection(projection) { - return function() { - var d = projection.apply(this, arguments), - r = d[0], - a = d[1] + d3_svg_arcOffset; - return [r * Math.cos(a), r * Math.sin(a)]; - }; -} -d3.svg.mouse = function(container) { - return d3_svg_mousePoint(container, d3.event); -}; - -// https://bugs.webkit.org/show_bug.cgi?id=44083 -var d3_mouse_bug44083 = /WebKit/.test(navigator.userAgent) ? -1 : 0; - -function d3_svg_mousePoint(container, e) { - var point = (container.ownerSVGElement || container).createSVGPoint(); - if ((d3_mouse_bug44083 < 0) && (window.scrollX || window.scrollY)) { - var svg = d3.select(document.body) - .append("svg") - .style("position", "absolute") - .style("top", 0) - .style("left", 0); - var ctm = svg[0][0].getScreenCTM(); - d3_mouse_bug44083 = !(ctm.f || ctm.e); - svg.remove(); - } - if (d3_mouse_bug44083) { - point.x = e.pageX; - point.y = e.pageY; - } else { - point.x = e.clientX; - point.y = e.clientY; - } - point = point.matrixTransform(container.getScreenCTM().inverse()); - return [point.x, point.y]; -}; -d3.svg.touches = function(container, touches) { - if (arguments.length < 2) touches = d3.event.touches; - - return touches ? d3_array(touches).map(function(touch) { - var point = d3_svg_mousePoint(container, touch); - point.identifier = touch.identifier; - return point; - }) : []; -}; -d3.svg.symbol = function() { - var type = d3_svg_symbolType, - size = d3_svg_symbolSize; - - function symbol(d, i) { - return (d3_svg_symbols[type.call(this, d, i)] - || d3_svg_symbols.circle) - (size.call(this, d, i)); - } - - symbol.type = function(x) { - if (!arguments.length) return type; - type = d3.functor(x); - return symbol; - }; - - // size of symbol in square pixels - symbol.size = function(x) { - if (!arguments.length) return size; - size = d3.functor(x); - return symbol; - }; - - return symbol; -}; - -function d3_svg_symbolSize() { - return 64; -} - -function d3_svg_symbolType() { - return "circle"; -} - -// TODO cross-diagonal? -var d3_svg_symbols = { - "circle": function(size) { - var r = Math.sqrt(size / Math.PI); - return "M0," + r - + "A" + r + "," + r + " 0 1,1 0," + (-r) - + "A" + r + "," + r + " 0 1,1 0," + r - + "Z"; - }, - "cross": function(size) { - var r = Math.sqrt(size / 5) / 2; - return "M" + -3 * r + "," + -r - + "H" + -r - + "V" + -3 * r - + "H" + r - + "V" + -r - + "H" + 3 * r - + "V" + r - + "H" + r - + "V" + 3 * r - + "H" + -r - + "V" + r - + "H" + -3 * r - + "Z"; - }, - "diamond": function(size) { - var ry = Math.sqrt(size / (2 * d3_svg_symbolTan30)), - rx = ry * d3_svg_symbolTan30; - return "M0," + -ry - + "L" + rx + ",0" - + " 0," + ry - + " " + -rx + ",0" - + "Z"; - }, - "square": function(size) { - var r = Math.sqrt(size) / 2; - return "M" + -r + "," + -r - + "L" + r + "," + -r - + " " + r + "," + r - + " " + -r + "," + r - + "Z"; - }, - "triangle-down": function(size) { - var rx = Math.sqrt(size / d3_svg_symbolSqrt3), - ry = rx * d3_svg_symbolSqrt3 / 2; - return "M0," + ry - + "L" + rx +"," + -ry - + " " + -rx + "," + -ry - + "Z"; - }, - "triangle-up": function(size) { - var rx = Math.sqrt(size / d3_svg_symbolSqrt3), - ry = rx * d3_svg_symbolSqrt3 / 2; - return "M0," + -ry - + "L" + rx +"," + ry - + " " + -rx + "," + ry - + "Z"; - } -}; - -d3.svg.symbolTypes = d3.keys(d3_svg_symbols); - -var d3_svg_symbolSqrt3 = Math.sqrt(3), - d3_svg_symbolTan30 = Math.tan(30 * Math.PI / 180); -d3.svg.axis = function() { - var scale = d3.scale.linear(), - orient = "bottom", - tickMajorSize = 6, - tickMinorSize = 6, - tickEndSize = 6, - tickPadding = 3, - tickArguments_ = [10], - tickFormat_, - tickSubdivide = 0; - - function axis(selection) { - selection.each(function(d, i, j) { - var g = d3.select(this); - - // If selection is a transition, create subtransitions. - var transition = selection.delay ? function(o) { - var id = d3_transitionInheritId; - try { - d3_transitionInheritId = selection.id; - return o.transition() - .delay(selection[j][i].delay) - .duration(selection[j][i].duration) - .ease(selection.ease()); - } finally { - d3_transitionInheritId = id; - } - } : Object; - - // Ticks, or domain values for ordinal scales. - var ticks = scale.ticks ? scale.ticks.apply(scale, tickArguments_) : scale.domain(), - tickFormat = tickFormat_ == null ? (scale.tickFormat ? scale.tickFormat.apply(scale, tickArguments_) : String) : tickFormat_; - - // Minor ticks. - var subticks = d3_svg_axisSubdivide(scale, ticks, tickSubdivide), - subtick = g.selectAll(".minor").data(subticks, String), - subtickEnter = subtick.enter().insert("line", "g").attr("class", "tick minor").style("opacity", 1e-6), - subtickExit = transition(subtick.exit()).style("opacity", 1e-6).remove(), - subtickUpdate = transition(subtick).style("opacity", 1); - - // Major ticks. - var tick = g.selectAll("g").data(ticks, String), - tickEnter = tick.enter().insert("g", "path").style("opacity", 1e-6), - tickExit = transition(tick.exit()).style("opacity", 1e-6).remove(), - tickUpdate = transition(tick).style("opacity", 1), - tickTransform; - - // Domain. - var range = d3_scaleRange(scale), - path = g.selectAll(".domain").data([0]), - pathEnter = path.enter().append("path").attr("class", "domain"), - pathUpdate = transition(path); - - // Stash a snapshot of the new scale, and retrieve the old snapshot. - var scale1 = scale.copy(), - scale0 = this.__chart__ || scale1; - this.__chart__ = scale1; - - tickEnter.append("line").attr("class", "tick"); - tickEnter.append("text"); - tickUpdate.select("text").text(tickFormat); - - switch (orient) { - case "bottom": { - tickTransform = d3_svg_axisX; - subtickUpdate.attr("x2", 0).attr("y2", tickMinorSize); - tickUpdate.select("line").attr("x2", 0).attr("y2", tickMajorSize); - tickUpdate.select("text").attr("x", 0).attr("y", Math.max(tickMajorSize, 0) + tickPadding).attr("dy", ".71em").attr("text-anchor", "middle"); - pathUpdate.attr("d", "M" + range[0] + "," + tickEndSize + "V0H" + range[1] + "V" + tickEndSize); - break; - } - case "top": { - tickTransform = d3_svg_axisX; - subtickUpdate.attr("x2", 0).attr("y2", -tickMinorSize); - tickUpdate.select("line").attr("x2", 0).attr("y2", -tickMajorSize); - tickUpdate.select("text").attr("x", 0).attr("y", -(Math.max(tickMajorSize, 0) + tickPadding)).attr("dy", "0em").attr("text-anchor", "middle"); - pathUpdate.attr("d", "M" + range[0] + "," + -tickEndSize + "V0H" + range[1] + "V" + -tickEndSize); - break; - } - case "left": { - tickTransform = d3_svg_axisY; - subtickUpdate.attr("x2", -tickMinorSize).attr("y2", 0); - tickUpdate.select("line").attr("x2", -tickMajorSize).attr("y2", 0); - tickUpdate.select("text").attr("x", -(Math.max(tickMajorSize, 0) + tickPadding)).attr("y", 0).attr("dy", ".32em").attr("text-anchor", "end"); - pathUpdate.attr("d", "M" + -tickEndSize + "," + range[0] + "H0V" + range[1] + "H" + -tickEndSize); - break; - } - case "right": { - tickTransform = d3_svg_axisY; - subtickUpdate.attr("x2", tickMinorSize).attr("y2", 0); - tickUpdate.select("line").attr("x2", tickMajorSize).attr("y2", 0); - tickUpdate.select("text").attr("x", Math.max(tickMajorSize, 0) + tickPadding).attr("y", 0).attr("dy", ".32em").attr("text-anchor", "start"); - pathUpdate.attr("d", "M" + tickEndSize + "," + range[0] + "H0V" + range[1] + "H" + tickEndSize); - break; - } - } - - // For quantitative scales: - // - enter new ticks from the old scale - // - exit old ticks to the new scale - if (scale.ticks) { - tickEnter.call(tickTransform, scale0); - tickUpdate.call(tickTransform, scale1); - tickExit.call(tickTransform, scale1); - subtickEnter.call(tickTransform, scale0); - subtickUpdate.call(tickTransform, scale1); - subtickExit.call(tickTransform, scale1); - } - - // For ordinal scales: - // - any entering ticks are undefined in the old scale - // - any exiting ticks are undefined in the new scale - // Therefore, we only need to transition updating ticks. - else { - var dx = scale1.rangeBand() / 2, x = function(d) { return scale1(d) + dx; }; - tickEnter.call(tickTransform, x); - tickUpdate.call(tickTransform, x); - } - }); - } - - axis.scale = function(x) { - if (!arguments.length) return scale; - scale = x; - return axis; - }; - - axis.orient = function(x) { - if (!arguments.length) return orient; - orient = x; - return axis; - }; - - axis.ticks = function() { - if (!arguments.length) return tickArguments_; - tickArguments_ = arguments; - return axis; - }; - - axis.tickFormat = function(x) { - if (!arguments.length) return tickFormat_; - tickFormat_ = x; - return axis; - }; - - axis.tickSize = function(x, y, z) { - if (!arguments.length) return tickMajorSize; - var n = arguments.length - 1; - tickMajorSize = +x; - tickMinorSize = n > 1 ? +y : tickMajorSize; - tickEndSize = n > 0 ? +arguments[n] : tickMajorSize; - return axis; - }; - - axis.tickPadding = function(x) { - if (!arguments.length) return tickPadding; - tickPadding = +x; - return axis; - }; - - axis.tickSubdivide = function(x) { - if (!arguments.length) return tickSubdivide; - tickSubdivide = +x; - return axis; - }; - - return axis; -}; - -function d3_svg_axisX(selection, x) { - selection.attr("transform", function(d) { return "translate(" + x(d) + ",0)"; }); -} - -function d3_svg_axisY(selection, y) { - selection.attr("transform", function(d) { return "translate(0," + y(d) + ")"; }); -} - -function d3_svg_axisSubdivide(scale, ticks, m) { - subticks = []; - if (m && ticks.length > 1) { - var extent = d3_scaleExtent(scale.domain()), - subticks, - i = -1, - n = ticks.length, - d = (ticks[1] - ticks[0]) / ++m, - j, - v; - while (++i < n) { - for (j = m; --j > 0;) { - if ((v = +ticks[i] - j * d) >= extent[0]) { - subticks.push(v); - } - } - } - for (--i, j = 0; ++j < m && (v = +ticks[i] + j * d) < extent[1];) { - subticks.push(v); - } - } - return subticks; -} -d3.svg.brush = function() { - var event = d3.dispatch("brushstart", "brush", "brushend"), - x, // x-scale, optional - y, // y-scale, optional - extent = [[0, 0], [0, 0]]; // [x0, y0], [x1, y1] - - function brush(g) { - var resizes = x && y ? ["n", "e", "s", "w", "nw", "ne", "se", "sw"] - : x ? ["e", "w"] - : y ? ["n", "s"] - : []; - - g.each(function() { - var g = d3.select(this).on("mousedown.brush", down), - bg = g.selectAll(".background").data([,]), - fg = g.selectAll(".extent").data([,]), - tz = g.selectAll(".resize").data(resizes, String), - e; - - // An invisible, mouseable area for starting a new brush. - bg.enter().append("rect") - .attr("class", "background") - .style("visibility", "hidden") - .style("pointer-events", "all") - .style("cursor", "crosshair"); - - // The visible brush extent; style this as you like! - fg.enter().append("rect") - .attr("class", "extent") - .style("cursor", "move"); - - // More invisible rects for resizing the extent. - tz.enter().append("rect") - .attr("class", function(d) { return "resize " + d; }) - .attr("width", 6) - .attr("height", 6) - .style("visibility", "hidden") - .style("pointer-events", brush.empty() ? "none" : "all") - .style("cursor", function(d) { return d3_svg_brushCursor[d]; }); - - // Remove any superfluous resizers. - tz.exit().remove(); - - // Initialize the background to fill the defined range. - // If the range isn't defined, you can post-process. - if (x) { - e = d3_scaleRange(x); - bg.attr("x", e[0]).attr("width", e[1] - e[0]); - d3_svg_brushRedrawX(g, extent); - } - if (y) { - e = d3_scaleRange(y); - bg.attr("y", e[0]).attr("height", e[1] - e[0]); - d3_svg_brushRedrawY(g, extent); - } - }); - } - - function down() { - var target = d3.select(d3.event.target); - - // Store some global state for the duration of the brush gesture. - d3_svg_brush = brush; - d3_svg_brushTarget = this; - d3_svg_brushExtent = extent; - d3_svg_brushOffset = d3.svg.mouse(d3_svg_brushTarget); - - // If the extent was clicked on, drag rather than brush; - // store the offset between the mouse and extent origin instead. - if (d3_svg_brushDrag = target.classed("extent")) { - d3_svg_brushOffset[0] = extent[0][0] - d3_svg_brushOffset[0]; - d3_svg_brushOffset[1] = extent[0][1] - d3_svg_brushOffset[1]; - } - - // If a resizer was clicked on, record which side is to be resized. - // Also, set the offset to the opposite side. - else if (target.classed("resize")) { - d3_svg_brushResize = d3.event.target.__data__; - d3_svg_brushOffset[0] = extent[+/w$/.test(d3_svg_brushResize)][0]; - d3_svg_brushOffset[1] = extent[+/^n/.test(d3_svg_brushResize)][1]; - } - - // If the ALT key is down when starting a brush, the center is at the mouse. - else if (d3.event.altKey) { - d3_svg_brushCenter = d3_svg_brushOffset.slice(); - } - - // Restrict which dimensions are resized. - d3_svg_brushX = !/^(n|s)$/.test(d3_svg_brushResize) && x; - d3_svg_brushY = !/^(e|w)$/.test(d3_svg_brushResize) && y; - - // Notify listeners. - d3_svg_brushDispatch = dispatcher(this, arguments); - d3_svg_brushDispatch("brushstart"); - d3_svg_brushMove(); - d3_eventCancel(); - } - - function dispatcher(that, argumentz) { - return function(type) { - var e = d3.event; - try { - d3.event = {type: type, target: brush}; - event[type].apply(that, argumentz); - } finally { - d3.event = e; - } - }; - } - - brush.x = function(z) { - if (!arguments.length) return x; - x = z; - return brush; - }; - - brush.y = function(z) { - if (!arguments.length) return y; - y = z; - return brush; - }; - - brush.extent = function(z) { - var x0, x1, y0, y1, t; - - // Invert the pixel extent to data-space. - if (!arguments.length) { - if (x) { - x0 = extent[0][0], x1 = extent[1][0]; - if (x.invert) x0 = x.invert(x0), x1 = x.invert(x1); - if (x1 < x0) t = x0, x0 = x1, x1 = t; - } - if (y) { - y0 = extent[0][1], y1 = extent[1][1]; - if (y.invert) y0 = y.invert(y0), y1 = y.invert(y1); - if (y1 < y0) t = y0, y0 = y1, y1 = t; - } - return x && y ? [[x0, y0], [x1, y1]] : x ? [x0, x1] : y && [y0, y1]; - } - - // Scale the data-space extent to pixels. - if (x) { - x0 = z[0], x1 = z[1]; - if (y) x0 = x0[0], x1 = x1[0]; - if (x.invert) x0 = x(x0), x1 = x(x1); - if (x1 < x0) t = x0, x0 = x1, x1 = t; - extent[0][0] = x0, extent[1][0] = x1; - } - if (y) { - y0 = z[0], y1 = z[1]; - if (x) y0 = y0[1], y1 = y1[1]; - if (y.invert) y0 = y(y0), y1 = y(y1); - if (y1 < y0) t = y0, y0 = y1, y1 = t; - extent[0][1] = y0, extent[1][1] = y1; - } - - return brush; - }; - - brush.clear = function() { - extent[0][0] = - extent[0][1] = - extent[1][0] = - extent[1][1] = 0; - return brush; - }; - - brush.empty = function() { - return (x && extent[0][0] === extent[1][0]) - || (y && extent[0][1] === extent[1][1]); - }; - - d3.select(window) - .on("mousemove.brush", d3_svg_brushMove) - .on("mouseup.brush", d3_svg_brushUp) - .on("keydown.brush", d3_svg_brushKeydown) - .on("keyup.brush", d3_svg_brushKeyup); - - return d3.rebind(brush, event, "on"); -}; - -var d3_svg_brush, - d3_svg_brushDispatch, - d3_svg_brushTarget, - d3_svg_brushX, - d3_svg_brushY, - d3_svg_brushExtent, - d3_svg_brushDrag, - d3_svg_brushResize, - d3_svg_brushCenter, - d3_svg_brushOffset; - -function d3_svg_brushRedrawX(g, extent) { - g.select(".extent").attr("x", extent[0][0]); - g.selectAll(".n,.s,.w,.nw,.sw").attr("x", extent[0][0] - 2); - g.selectAll(".e,.ne,.se").attr("x", extent[1][0] - 3); - g.selectAll(".extent,.n,.s").attr("width", extent[1][0] - extent[0][0]); -} - -function d3_svg_brushRedrawY(g, extent) { - g.select(".extent").attr("y", extent[0][1]); - g.selectAll(".n,.e,.w,.nw,.ne").attr("y", extent[0][1] - 3); - g.selectAll(".s,.se,.sw").attr("y", extent[1][1] - 4); - g.selectAll(".extent,.e,.w").attr("height", extent[1][1] - extent[0][1]); -} - -function d3_svg_brushKeydown() { - if (d3.event.keyCode == 32 && d3_svg_brushTarget && !d3_svg_brushDrag) { - d3_svg_brushCenter = null; - d3_svg_brushOffset[0] -= d3_svg_brushExtent[1][0]; - d3_svg_brushOffset[1] -= d3_svg_brushExtent[1][1]; - d3_svg_brushDrag = 2; - d3_eventCancel(); - } -} - -function d3_svg_brushKeyup() { - if (d3.event.keyCode == 32 && d3_svg_brushDrag == 2) { - d3_svg_brushOffset[0] += d3_svg_brushExtent[1][0]; - d3_svg_brushOffset[1] += d3_svg_brushExtent[1][1]; - d3_svg_brushDrag = 0; - d3_eventCancel(); - } -} - -function d3_svg_brushMove() { - if (d3_svg_brushOffset) { - var mouse = d3.svg.mouse(d3_svg_brushTarget), - g = d3.select(d3_svg_brushTarget); - - if (!d3_svg_brushDrag) { - - // If needed, determine the center from the current extent. - if (d3.event.altKey) { - if (!d3_svg_brushCenter) { - d3_svg_brushCenter = [ - (d3_svg_brushExtent[0][0] + d3_svg_brushExtent[1][0]) / 2, - (d3_svg_brushExtent[0][1] + d3_svg_brushExtent[1][1]) / 2 - ]; - } - - // Update the offset, for when the ALT key is released. - d3_svg_brushOffset[0] = d3_svg_brushExtent[+(mouse[0] < d3_svg_brushCenter[0])][0]; - d3_svg_brushOffset[1] = d3_svg_brushExtent[+(mouse[1] < d3_svg_brushCenter[1])][1]; - } - - // When the ALT key is released, we clear the center. - else d3_svg_brushCenter = null; - } - - // Update the brush extent for each dimension. - if (d3_svg_brushX) { - d3_svg_brushMove1(mouse, d3_svg_brushX, 0); - d3_svg_brushRedrawX(g, d3_svg_brushExtent); - } - if (d3_svg_brushY) { - d3_svg_brushMove1(mouse, d3_svg_brushY, 1); - d3_svg_brushRedrawY(g, d3_svg_brushExtent); - } - - // Notify listeners. - d3_svg_brushDispatch("brush"); - } -} - -function d3_svg_brushMove1(mouse, scale, i) { - var range = d3_scaleRange(scale), - r0 = range[0], - r1 = range[1], - offset = d3_svg_brushOffset[i], - size = d3_svg_brushExtent[1][i] - d3_svg_brushExtent[0][i], - min, - max; - - // When dragging, reduce the range by the extent size and offset. - if (d3_svg_brushDrag) { - r0 -= offset; - r1 -= size + offset; - } - - // Clamp the mouse so that the extent fits within the range extent. - min = Math.max(r0, Math.min(r1, mouse[i])); - - // Compute the new extent bounds. - if (d3_svg_brushDrag) { - max = (min += offset) + size; - } else { - - // If the ALT key is pressed, then preserve the center of the extent. - if (d3_svg_brushCenter) offset = Math.max(r0, Math.min(r1, 2 * d3_svg_brushCenter[i] - min)); - - // Compute the min and max of the offset and mouse. - if (offset < min) { - max = min; - min = offset; - } else { - max = offset; - } - } - - // Update the stored bounds. - d3_svg_brushExtent[0][i] = min; - d3_svg_brushExtent[1][i] = max; -} - -function d3_svg_brushUp() { - if (d3_svg_brushOffset) { - d3_svg_brushMove(); - d3.select(d3_svg_brushTarget).selectAll(".resize").style("pointer-events", d3_svg_brush.empty() ? "none" : "all"); - d3_svg_brushDispatch("brushend"); - d3_svg_brush = - d3_svg_brushDispatch = - d3_svg_brushTarget = - d3_svg_brushX = - d3_svg_brushY = - d3_svg_brushExtent = - d3_svg_brushDrag = - d3_svg_brushResize = - d3_svg_brushCenter = - d3_svg_brushOffset = null; - d3_eventCancel(); - } -} - -var d3_svg_brushCursor = { - n: "ns-resize", - e: "ew-resize", - s: "ns-resize", - w: "ew-resize", - nw: "nwse-resize", - ne: "nesw-resize", - se: "nwse-resize", - sw: "nesw-resize" -}; -d3.behavior = {}; -// TODO Track touch points by identifier. - -d3.behavior.drag = function() { - var event = d3.dispatch("drag", "dragstart", "dragend"), - origin = null; - - function drag() { - this - .on("mousedown.drag", mousedown) - .on("touchstart.drag", mousedown); - - d3.select(window) - .on("mousemove.drag", d3_behavior_dragMove) - .on("touchmove.drag", d3_behavior_dragMove) - .on("mouseup.drag", d3_behavior_dragUp, true) - .on("touchend.drag", d3_behavior_dragUp, true) - .on("click.drag", d3_behavior_dragClick, true); - } - - // snapshot the local context for subsequent dispatch - function start() { - d3_behavior_dragEvent = event; - d3_behavior_dragEventTarget = d3.event.target; - d3_behavior_dragTarget = this; - d3_behavior_dragArguments = arguments; - d3_behavior_dragOrigin = d3_behavior_dragPoint(); - if (origin) { - d3_behavior_dragOffset = origin.apply(d3_behavior_dragTarget, d3_behavior_dragArguments); - d3_behavior_dragOffset = [d3_behavior_dragOffset.x - d3_behavior_dragOrigin[0], d3_behavior_dragOffset.y - d3_behavior_dragOrigin[1]]; - } else { - d3_behavior_dragOffset = [0, 0]; - } - d3_behavior_dragMoved = 0; - } - - function mousedown() { - start.apply(this, arguments); - d3_behavior_dragDispatch("dragstart"); - } - - drag.origin = function(x) { - if (!arguments.length) return origin; - origin = x; - return drag; - }; - - return d3.rebind(drag, event, "on"); -}; - -var d3_behavior_dragEvent, - d3_behavior_dragEventTarget, - d3_behavior_dragTarget, - d3_behavior_dragArguments, - d3_behavior_dragOffset, - d3_behavior_dragOrigin, - d3_behavior_dragMoved; - -function d3_behavior_dragDispatch(type) { - var p = d3_behavior_dragPoint(), - o = d3.event, - e = d3.event = {type: type}; - - if (p) { - e.x = p[0] + d3_behavior_dragOffset[0]; - e.y = p[1] + d3_behavior_dragOffset[1]; - e.dx = p[0] - d3_behavior_dragOrigin[0]; - e.dy = p[1] - d3_behavior_dragOrigin[1]; - d3_behavior_dragMoved |= e.dx | e.dy; - d3_behavior_dragOrigin = p; - } - - try { - d3_behavior_dragEvent[type].apply(d3_behavior_dragTarget, d3_behavior_dragArguments); - } finally { - d3.event = o; - } - - o.stopPropagation(); - o.preventDefault(); -} - -function d3_behavior_dragPoint() { - var p = d3_behavior_dragTarget.parentNode, - t = d3.event.changedTouches; - return p && (t - ? d3.svg.touches(p, t)[0] - : d3.svg.mouse(p)); -} - -function d3_behavior_dragMove() { - if (!d3_behavior_dragTarget) return; - var parent = d3_behavior_dragTarget.parentNode; - - // O NOES! The drag element was removed from the DOM. - if (!parent) return d3_behavior_dragUp(); - - d3_behavior_dragDispatch("drag"); - d3_eventCancel(); -} - -function d3_behavior_dragUp() { - if (!d3_behavior_dragTarget) return; - d3_behavior_dragDispatch("dragend"); - - // If the node was moved, prevent the mouseup from propagating. - // Also prevent the subsequent click from propagating (e.g., for anchors). - if (d3_behavior_dragMoved) { - d3_eventCancel(); - d3_behavior_dragMoved = d3.event.target === d3_behavior_dragEventTarget; - } - - d3_behavior_dragEvent = - d3_behavior_dragEventTarget = - d3_behavior_dragTarget = - d3_behavior_dragArguments = - d3_behavior_dragOffset = - d3_behavior_dragOrigin = null; -} - -function d3_behavior_dragClick() { - if (d3_behavior_dragMoved) { - d3_eventCancel(); - d3_behavior_dragMoved = 0; - } -} -// TODO unbind zoom behavior? -d3.behavior.zoom = function() { - var xyz = [0, 0, 0], - event = d3.dispatch("zoom"), - extent = d3_behavior_zoomInfiniteExtent; - - function zoom() { - this - .on("mousedown.zoom", mousedown) - .on("mousewheel.zoom", mousewheel) - .on("DOMMouseScroll.zoom", mousewheel) - .on("dblclick.zoom", dblclick) - .on("touchstart.zoom", touchstart); - - d3.select(window) - .on("mousemove.zoom", d3_behavior_zoomMousemove) - .on("mouseup.zoom", d3_behavior_zoomMouseup) - .on("touchmove.zoom", d3_behavior_zoomTouchmove) - .on("touchend.zoom", d3_behavior_zoomTouchup) - .on("click.zoom", d3_behavior_zoomClick, true); - } - - // snapshot the local context for subsequent dispatch - function start() { - d3_behavior_zoomXyz = xyz; - d3_behavior_zoomExtent = extent; - d3_behavior_zoomDispatch = event.zoom; - d3_behavior_zoomEventTarget = d3.event.target; - d3_behavior_zoomTarget = this; - d3_behavior_zoomArguments = arguments; - } - - function mousedown() { - start.apply(this, arguments); - d3_behavior_zoomPanning = d3_behavior_zoomLocation(d3.svg.mouse(d3_behavior_zoomTarget)); - d3_behavior_zoomMoved = 0; - d3.event.preventDefault(); - window.focus(); - } - - // store starting mouse location - function mousewheel() { - start.apply(this, arguments); - if (!d3_behavior_zoomZooming) d3_behavior_zoomZooming = d3_behavior_zoomLocation(d3.svg.mouse(d3_behavior_zoomTarget)); - d3_behavior_zoomTo(d3_behavior_zoomDelta() + xyz[2], d3.svg.mouse(d3_behavior_zoomTarget), d3_behavior_zoomZooming); - } - - function dblclick() { - start.apply(this, arguments); - var mouse = d3.svg.mouse(d3_behavior_zoomTarget); - d3_behavior_zoomTo(d3.event.shiftKey ? Math.ceil(xyz[2] - 1) : Math.floor(xyz[2] + 1), mouse, d3_behavior_zoomLocation(mouse)); - } - - // doubletap detection - function touchstart() { - start.apply(this, arguments); - var touches = d3_behavior_zoomTouchup(), - touch, - now = Date.now(); - if ((touches.length === 1) && (now - d3_behavior_zoomLast < 300)) { - d3_behavior_zoomTo(1 + Math.floor(xyz[2]), touch = touches[0], d3_behavior_zoomLocations[touch.identifier]); - } - d3_behavior_zoomLast = now; - } - - zoom.extent = function(x) { - if (!arguments.length) return extent; - extent = x == null ? d3_behavior_zoomInfiniteExtent : x; - return zoom; - }; - - return d3.rebind(zoom, event, "on"); -}; - -var d3_behavior_zoomDiv, - d3_behavior_zoomPanning, - d3_behavior_zoomZooming, - d3_behavior_zoomLocations = {}, // identifier -> location - d3_behavior_zoomLast = 0, - d3_behavior_zoomXyz, - d3_behavior_zoomExtent, - d3_behavior_zoomDispatch, - d3_behavior_zoomEventTarget, - d3_behavior_zoomTarget, - d3_behavior_zoomArguments, - d3_behavior_zoomMoved; - -function d3_behavior_zoomLocation(point) { - return [ - point[0] - d3_behavior_zoomXyz[0], - point[1] - d3_behavior_zoomXyz[1], - d3_behavior_zoomXyz[2] - ]; -} - -// detect the pixels that would be scrolled by this wheel event -function d3_behavior_zoomDelta() { - - // mousewheel events are totally broken! - // https://bugs.webkit.org/show_bug.cgi?id=40441 - // not only that, but Chrome and Safari differ in re. to acceleration! - if (!d3_behavior_zoomDiv) { - d3_behavior_zoomDiv = d3.select("body").append("div") - .style("visibility", "hidden") - .style("top", 0) - .style("height", 0) - .style("width", 0) - .style("overflow-y", "scroll") - .append("div") - .style("height", "2000px") - .node().parentNode; - } - - var e = d3.event, delta; - try { - d3_behavior_zoomDiv.scrollTop = 1000; - d3_behavior_zoomDiv.dispatchEvent(e); - delta = 1000 - d3_behavior_zoomDiv.scrollTop; - } catch (error) { - delta = e.wheelDelta || (-e.detail * 5); - } - - return delta * .005; -} - -// Note: Since we don't rotate, it's possible for the touches to become -// slightly detached from their original positions. Thus, we recompute the -// touch points on touchend as well as touchstart! -function d3_behavior_zoomTouchup() { - var touches = d3.svg.touches(d3_behavior_zoomTarget), - i = -1, - n = touches.length, - touch; - while (++i < n) d3_behavior_zoomLocations[(touch = touches[i]).identifier] = d3_behavior_zoomLocation(touch); - return touches; -} - -function d3_behavior_zoomTouchmove() { - var touches = d3.svg.touches(d3_behavior_zoomTarget); - switch (touches.length) { - - // single-touch pan - case 1: { - var touch = touches[0]; - d3_behavior_zoomTo(d3_behavior_zoomXyz[2], touch, d3_behavior_zoomLocations[touch.identifier]); - break; - } - - // double-touch pan + zoom - case 2: { - var p0 = touches[0], - p1 = touches[1], - p2 = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2], - l0 = d3_behavior_zoomLocations[p0.identifier], - l1 = d3_behavior_zoomLocations[p1.identifier], - l2 = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2, l0[2]]; - d3_behavior_zoomTo(Math.log(d3.event.scale) / Math.LN2 + l0[2], p2, l2); - break; - } - } -} - -function d3_behavior_zoomMousemove() { - d3_behavior_zoomZooming = null; - if (d3_behavior_zoomPanning) { - d3_behavior_zoomMoved = 1; - d3_behavior_zoomTo(d3_behavior_zoomXyz[2], d3.svg.mouse(d3_behavior_zoomTarget), d3_behavior_zoomPanning); - } -} - -function d3_behavior_zoomMouseup() { - if (d3_behavior_zoomPanning) { - if (d3_behavior_zoomMoved) { - d3_eventCancel(); - d3_behavior_zoomMoved = d3_behavior_zoomEventTarget === d3.event.target; - } - - d3_behavior_zoomXyz = - d3_behavior_zoomExtent = - d3_behavior_zoomDispatch = - d3_behavior_zoomEventTarget = - d3_behavior_zoomTarget = - d3_behavior_zoomArguments = - d3_behavior_zoomPanning = null; - } -} - -function d3_behavior_zoomClick() { - if (d3_behavior_zoomMoved) { - d3_eventCancel(); - d3_behavior_zoomMoved = 0; - } -} - -function d3_behavior_zoomTo(z, x0, x1) { - z = d3_behavior_zoomExtentClamp(z, 2); - var j = Math.pow(2, d3_behavior_zoomXyz[2]), - k = Math.pow(2, z), - K = Math.pow(2, (d3_behavior_zoomXyz[2] = z) - x1[2]), - x_ = d3_behavior_zoomXyz[0], - y_ = d3_behavior_zoomXyz[1], - x = d3_behavior_zoomXyz[0] = d3_behavior_zoomExtentClamp((x0[0] - x1[0] * K), 0, k), - y = d3_behavior_zoomXyz[1] = d3_behavior_zoomExtentClamp((x0[1] - x1[1] * K), 1, k), - o = d3.event; // Events can be reentrant (e.g., focus). - - d3.event = { - scale: k, - translate: [x, y], - transform: function(sx, sy) { - if (sx) transform(sx, x_, x); - if (sy) transform(sy, y_, y); - } - }; - - function transform(scale, a, b) { - scale.domain(scale.range().map(function(v) { return scale.invert(((v - b) * j) / k + a); })); - } - - try { - d3_behavior_zoomDispatch.apply(d3_behavior_zoomTarget, d3_behavior_zoomArguments); - } finally { - d3.event = o; - } - - o.preventDefault(); -} - -var d3_behavior_zoomInfiniteExtent = [ - [-Infinity, Infinity], - [-Infinity, Infinity], - [-Infinity, Infinity] -]; - -function d3_behavior_zoomExtentClamp(x, i, k) { - var range = d3_behavior_zoomExtent[i], - r0 = range[0], - r1 = range[1]; - return arguments.length === 3 - ? Math.max(r1 * (r1 === Infinity ? -Infinity : 1 / k - 1), - Math.min(r0 === -Infinity ? Infinity : r0, x / k)) * k - : Math.max(r0, Math.min(r1, x)); -} -})(); diff --git a/ui/website/favicon.ico b/ui/website/favicon.ico deleted file mode 100755 index 95ed4076ea008..0000000000000 Binary files a/ui/website/favicon.ico and /dev/null differ diff --git a/ui/website/images/banner.png b/ui/website/images/banner.png deleted file mode 100755 index ec67051a5cdad..0000000000000 Binary files a/ui/website/images/banner.png and /dev/null differ diff --git a/ui/website/images/bullet.png b/ui/website/images/bullet.png deleted file mode 100755 index 70322f0a234e5..0000000000000 Binary files a/ui/website/images/bullet.png and /dev/null differ diff --git a/ui/website/images/logo.png b/ui/website/images/logo.png deleted file mode 100755 index 4f726a31fa7a9..0000000000000 Binary files a/ui/website/images/logo.png and /dev/null differ diff --git a/ui/website/images/slogan.png b/ui/website/images/slogan.png deleted file mode 100755 index 8d4faa6542e0c..0000000000000 Binary files a/ui/website/images/slogan.png and /dev/null differ diff --git a/ui/website/index.css b/ui/website/index.css deleted file mode 100755 index 77b895acfc1d1..0000000000000 --- a/ui/website/index.css +++ /dev/null @@ -1,100 +0,0 @@ -body { - font: 100% 'Arial', sans-serif; - color: #666; - background-color: #eee; -} - -div#main { - width: 960px; - margin-left: auto; - margin-right: auto; -} - -h1 { - text-align: center; - font-size: 400%; - font-weight: bold; - margin-top: 50px; - margin-bottom: 10px; - text-shadow: 1px 1px 1px #fff; - color: #666; -} - -h2 { - text-align: center; - font-size: 210%; - font-weight: bold; - margin-top: 10px; - margin-bottom: 50px; - text-shadow: 1px 1px 1px #fff; - color: #999; -} - -span.light { - color: #999; -} - -div#user_name_container, div#session_name_container { - position: relative; - margin-top: 20px; - padding-top: 20px; - padding-bottom: 20px; - padding-left: 20px; - padding-right: 20px; - font-size: 200%; - font-weight: bold; - text-shadow: 1px 1px 1px #fff; - color: #666; - background-color: #ddd; - -moz-box-shadow: 0px 1px 6px #bbb; - -webkit-box-shadow: 0px 1px 6px #bbb; - box-shadow: 0px 1px 6px #bbb; -} - -a#submit_button { - display: block; - width: 960px; - margin-top: 20px; - text-decoration: none; - padding-top: 20px; - padding-bottom: 20px; - font-size: 200%; - font-weight: bold; - text-shadow: 1px 1px 1px #fff; - color: #666; - background-color: #ddd; - -moz-box-shadow: 0px 1px 6px #bbb; - -webkit-box-shadow: 0px 1px 6px #bbb; - box-shadow: 0px 1px 6px #bbb; - text-align: center; -} - -a#submit_button:hover { - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f9f9f9', endColorstr='#f2f2f2'); - background: -webkit-gradient(linear, left top, left bottom, from(#f9f9f9), to(#f2f2f2)); - background: -moz-linear-gradient(top, #f9f9f9, #f2f2f2); -} - -input { - width: 360px; - display: block; - position: absolute; - left: 299px; - top: 15px; - font-size: 90%; - padding: 5px; - background-color: #eee; - color: #666; - border: 0px solid #fff; - margin-left: 20px; - outline: none; -} - -div.clear { - clear: both; -} - -/* for Internet Explorer */ -a img { - border: none; -} diff --git a/ui/website/index.htm b/ui/website/index.htm deleted file mode 100755 index 41bd7104a70cf..0000000000000 --- a/ui/website/index.htm +++ /dev/null @@ -1,36 +0,0 @@ - - - - - Julia - A fresh approach to technical computing. - - - - - - - - - - - - - -
-

The Julia Language

-

Web Interface

-
-
-
- -

Your Name:

-
-
- -

Session Name:

-
- Try Julia Now - -
- - diff --git a/ui/website/index.js b/ui/website/index.js deleted file mode 100644 index 0dc5a3184f8a6..0000000000000 --- a/ui/website/index.js +++ /dev/null @@ -1,167 +0,0 @@ -(function() { - -// when the DOM loads -$(document).ready(function() { - // click handler for "Try Julia Now" button - $("a#submit_button").click(function() { - // submit the form - $("form#session_form").submit(); - }); - - // submit the form when the user hits enter - $("input#user_name").keydown(function(e) { - if (e.keyCode == 13) { - $("form#session_form").submit(); - return false; - } - }); - $("input#session_name").keydown(function(e) { - if (e.keyCode == 13) { - $("form#session_form").submit(); - return false; - } - }); - - // form handler - $("form#session_form").submit(function() { - // send a start message - outbox_queue.push([MSG_INPUT_START, $("input#user_name").val(), $("input#session_name").val()]); - process_outbox(); - return false; - }); - - // focus the first input box - $("input#user_name").focus(); -}); - -/* - Network Protol - - This needs to match the message - types listed in ui/webserver/message_types.h. -*/ - -// input messages (to julia) -var MSG_INPUT_NULL = 0; -var MSG_INPUT_START = 1; -var MSG_INPUT_POLL = 2; -var MSG_INPUT_EVAL = 3; -var MSG_INPUT_REPLAY_HISTORY = 4; -var MSG_INPUT_GET_USER = 5; - -// output messages (to the browser) -var MSG_OUTPUT_NULL = 0; -var MSG_OUTPUT_WELCOME = 1; -var MSG_OUTPUT_READY = 2; -var MSG_OUTPUT_MESSAGE = 3; -var MSG_OUTPUT_OTHER = 4; -var MSG_OUTPUT_EVAL_INPUT = 5; -var MSG_OUTPUT_FATAL_ERROR = 6; -var MSG_OUTPUT_EVAL_INCOMPLETE = 7; -var MSG_OUTPUT_EVAL_RESULT = 8; -var MSG_OUTPUT_EVAL_ERROR = 9; -var MSG_OUTPUT_PLOT = 10; -var MSG_OUTPUT_GET_USER = 11; -var MSG_OUTPUT_HTML = 12; - -// how long we delay in ms before polling the server again -var poll_interval = 200; - -// keep track of whether we are waiting for a message (and don't send more if we are) -var waiting_for_response = false; - -// a queue of messages to be sent to the server -var outbox_queue = []; - -// a queue of messages from the server to be processed -var inbox_queue = []; - -// keep track of whether we have received a fatal message -var dead = false; - -// an array of message handlers -var message_handlers = []; - -message_handlers[MSG_OUTPUT_WELCOME] = function(msg) { - // redirect to the REPL page - window.location = "repl.htm"; -}; - -message_handlers[MSG_OUTPUT_MESSAGE] = function(msg) { - // crappy way to show the user a message for now - alert(msg[0]); -}; - -message_handlers[MSG_OUTPUT_FATAL_ERROR] = function(msg) { - // crappy way to show the user a message for now - alert(msg[0]); - - // stop processing new messages - dead = true; - inbox_queue = []; - outbox_queue = []; -}; - -// check the server for data -function poll() { - // send a poll message - outbox_queue.push([MSG_INPUT_POLL]); - process_outbox(); -} - -// called when the server has responded -function callback(data, textStatus, jqXHR) { - // if we are dead, don't keep polling the server - if (dead) - return; - - // allow sending new messages - waiting_for_response = false; - - // add the messages to the inbox - inbox_queue = inbox_queue.concat(data); - - // process the inbox - process_inbox(); - - // send any new messages - process_outbox(); - - // poll the server again shortly - setTimeout(poll, poll_interval); -} - -// send the messages in the outbox -function process_outbox() { - // don't make new requests if we're waiting for old ones - if (!waiting_for_response) { - // don't send a request if there are no messages - if (outbox_queue.length > 0) { - // don't send any more requests while we're waiting for this one - waiting_for_response = true; - - // send the messages - $.post("/repl.scgi", {"request": $.toJSON(outbox_queue)}, callback, "json"); - } - - // we sent all the messages at once so clear the outbox - outbox_queue = []; - } -} - -// process the messages in the inbox -function process_inbox() { - // iterate through the messages - for (var id in inbox_queue) { - var msg = inbox_queue[id], - type = msg[0], msg = msg.slice(1), - handler = message_handlers[type]; - if (typeof handler == "function") - handler(msg); - } - - // we handled all the messages so clear the inbox - inbox_queue = []; -} - -})(); diff --git a/ui/website/jquery.autoresize.js b/ui/website/jquery.autoresize.js deleted file mode 100644 index 96202ce921a3a..0000000000000 --- a/ui/website/jquery.autoresize.js +++ /dev/null @@ -1,274 +0,0 @@ -/* - * jQuery.fn.autoResize 1.14 - * -- - * https://github.com/jamespadolsey/jQuery.fn.autoResize - * -- - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://sam.zoy.org/wtfpl/COPYING for more details. */ - -(function($){ - - var uid = 'ar' + +new Date, - - defaults = autoResize.defaults = { - onResize: function(){}, - onBeforeResize: function(){return 123}, - onAfterResize: function(){return 555}, - animate: { - duration: 200, - complete: function(){} - }, - extraSpace: 50, - minHeight: 'original', - maxHeight: 500, - minWidth: 'original', - maxWidth: 500 - }; - - autoResize.cloneCSSProperties = [ - 'lineHeight', 'textDecoration', 'letterSpacing', - 'fontSize', 'fontFamily', 'fontStyle', 'fontWeight', - 'textTransform', 'textAlign', 'direction', 'wordSpacing', 'fontSizeAdjust', - 'paddingTop', 'paddingLeft', 'paddingBottom', 'paddingRight', 'width' - ]; - - autoResize.cloneCSSValues = { - position: 'absolute', - top: -9999, - left: -9999, - opacity: 0, - overflow: 'hidden' - }; - - autoResize.resizableFilterSelector = [ - 'textarea:not(textarea.' + uid + ')', - 'input:not(input[type])', - 'input[type=text]', - 'input[type=password]', - 'input[type=email]', - 'input[type=url]' - ].join(','); - - autoResize.AutoResizer = AutoResizer; - - $.fn.autoResize = autoResize; - - function autoResize(config) { - this.filter(autoResize.resizableFilterSelector).each(function(){ - new AutoResizer( $(this), config ); - }); - return this; - } - - function AutoResizer(el, config) { - - if (el.data('AutoResizer')) { - el.data('AutoResizer').destroy(); - } - - config = this.config = $.extend({}, autoResize.defaults, config); - this.el = el; - - this.nodeName = el[0].nodeName.toLowerCase(); - - this.originalHeight = el.height(); - this.previousScrollTop = null; - - this.value = el.val(); - - if (config.maxWidth === 'original') config.maxWidth = el.width(); - if (config.minWidth === 'original') config.minWidth = el.width(); - if (config.maxHeight === 'original') config.maxHeight = el.height(); - if (config.minHeight === 'original') config.minHeight = el.height(); - - if (this.nodeName === 'textarea') { - el.css({ - resize: 'none', - overflowY: 'hidden' - }); - } - - el.data('AutoResizer', this); - - // Make sure onAfterResize is called upon animation completion - config.animate.complete = (function(f){ - return function() { - config.onAfterResize.call(el); - return f.apply(this, arguments); - }; - }(config.animate.complete)); - - this.bind(); - - } - - AutoResizer.prototype = { - - bind: function() { - - var check = $.proxy(function(){ - this.check(); - return true; - }, this); - - this.unbind(); - - this.el - .bind('keyup.autoResize', check) - //.bind('keydown.autoResize', check) - .bind('change.autoResize', check) - .bind('paste.autoResize', function() { - setTimeout(function() { check(); }, 0); - }); - - if (!this.el.is(':hidden')) { - this.check(null, true); - } - - }, - - unbind: function() { - this.el.unbind('.autoResize'); - }, - - createClone: function() { - - var el = this.el, - clone = this.nodeName === 'textarea' ? el.clone() : $(''); - - this.clone = clone; - - $.each(autoResize.cloneCSSProperties, function(i, p){ - clone[0].style[p] = el.css(p); - }); - - clone - .removeAttr('name') - .removeAttr('id') - .addClass(uid) - .attr('tabIndex', -1) - .css(autoResize.cloneCSSValues); - - if (this.nodeName === 'textarea') { - clone.height('auto'); - } else { - clone.width('auto').css({ - whiteSpace: 'nowrap' - }); - } - - }, - - check: function(e, immediate) { - - if (!this.clone) { - this.createClone(); - this.injectClone(); - } - - var config = this.config, - clone = this.clone, - el = this.el, - value = el.val(); - - // Do nothing if value hasn't changed - if (value === this.prevValue) { return true; } - this.prevValue = value; - - if (this.nodeName === 'input') { - - clone.text(value); - - // Calculate new width + whether to change - var cloneWidth = clone.width(), - newWidth = (cloneWidth + config.extraSpace) >= config.minWidth ? - cloneWidth + config.extraSpace : config.minWidth, - currentWidth = el.width(); - - newWidth = Math.min(newWidth, config.maxWidth); - - if ( - (newWidth < currentWidth && newWidth >= config.minWidth) || - (newWidth >= config.minWidth && newWidth <= config.maxWidth) - ) { - - config.onBeforeResize.call(el); - config.onResize.call(el); - - el.scrollLeft(0); - - if (config.animate && !immediate) { - el.stop(1,1).animate({ - width: newWidth - }, config.animate); - } else { - el.width(newWidth); - config.onAfterResize.call(el); - } - - } - - return; - - } - - // TEXTAREA - - clone.width(el.width()).height(0).val(value).scrollTop(10000); - - var scrollTop = clone[0].scrollTop; - - // Don't do anything if scrollTop hasen't changed: - if (this.previousScrollTop === scrollTop) { - return; - } - - this.previousScrollTop = scrollTop; - - if (scrollTop + config.extraSpace >= config.maxHeight) { - el.css('overflowY', ''); - scrollTop = config.maxHeight; - immediate = true; - } else if (scrollTop <= config.minHeight) { - scrollTop = config.minHeight; - } else { - el.css('overflowY', 'hidden'); - scrollTop += config.extraSpace; - } - - config.onBeforeResize.call(el); - config.onResize.call(el); - - // Either animate or directly apply height: - if (config.animate && !immediate) { - el.stop(1,1).animate({ - height: scrollTop - }, config.animate); - } else { - el.height(scrollTop); - config.onAfterResize.call(el); - } - - }, - - destroy: function() { - this.unbind(); - this.el.removeData('AutoResizer'); - this.clone.remove(); - delete this.el; - delete this.clone; - }, - - injectClone: function() { - ( - autoResize.cloneContainer || - (autoResize.cloneContainer = $('').appendTo('body')) - ).append(this.clone); - } - - }; - -})(jQuery); diff --git a/ui/website/jquery.js b/ui/website/jquery.js deleted file mode 100755 index 198b3ff07d801..0000000000000 --- a/ui/website/jquery.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! jQuery v1.7.1 jquery.com | jquery.org/license */ -(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!ck[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){cl||(cl=c.createElement("iframe"),cl.frameBorder=cl.width=cl.height=0),b.appendChild(cl);if(!cm||!cl.createElement)cm=(cl.contentWindow||cl.contentDocument).document,cm.write((c.compatMode==="CSS1Compat"?"":"")+""),cm.close();d=cm.createElement(a),cm.body.appendChild(d),e=f.css(d,"display"),b.removeChild(cl)}ck[a]=e}return ck[a]}function cu(a,b){var c={};f.each(cq.concat.apply([],cq.slice(0,b)),function(){c[this]=a});return c}function ct(){cr=b}function cs(){setTimeout(ct,0);return cr=f.now()}function cj(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ci(){try{return new a.XMLHttpRequest}catch(b){}}function cc(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g0){if(c!=="border")for(;g=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?parseFloat(d):j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c
a",d=q.getElementsByTagName("*"),e=q.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=q.getElementsByTagName("input")[0],b={leadingWhitespace:q.firstChild.nodeType===3,tbody:!q.getElementsByTagName("tbody").length,htmlSerialize:!!q.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:q.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete q.test}catch(s){b.deleteExpando=!1}!q.addEventListener&&q.attachEvent&&q.fireEvent&&(q.attachEvent("onclick",function(){b.noCloneEvent=!1}),q.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),q.appendChild(i),k=c.createDocumentFragment(),k.appendChild(q.lastChild),b.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,k.removeChild(i),k.appendChild(q),q.innerHTML="",a.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",q.style.width="2px",q.appendChild(j),b.reliableMarginRight=(parseInt((a.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0);if(q.attachEvent)for(o in{submit:1,change:1,focusin:1})n="on"+o,p=n in q,p||(q.setAttribute(n,"return;"),p=typeof q[n]=="function"),b[o+"Bubbles"]=p;k.removeChild(q),k=g=h=j=q=i=null,f(function(){var a,d,e,g,h,i,j,k,m,n,o,r=c.getElementsByTagName("body")[0];!r||(j=1,k="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;",m="visibility:hidden;border:0;",n="style='"+k+"border:5px solid #000;padding:0;'",o="
"+""+"
",a=c.createElement("div"),a.style.cssText=m+"width:0;height:0;position:static;top:0;margin-top:"+j+"px",r.insertBefore(a,r.firstChild),q=c.createElement("div"),a.appendChild(q),q.innerHTML="
t
",l=q.getElementsByTagName("td"),p=l[0].offsetHeight===0,l[0].style.display="",l[1].style.display="none",b.reliableHiddenOffsets=p&&l[0].offsetHeight===0,q.innerHTML="",q.style.width=q.style.paddingLeft="1px",f.boxModel=b.boxModel=q.offsetWidth===2,typeof q.style.zoom!="undefined"&&(q.style.display="inline",q.style.zoom=1,b.inlineBlockNeedsLayout=q.offsetWidth===2,q.style.display="",q.innerHTML="
",b.shrinkWrapBlocks=q.offsetWidth!==2),q.style.cssText=k+m,q.innerHTML=o,d=q.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,i={doesNotAddBorder:e.offsetTop!==5,doesAddBorderForTableAndCells:h.offsetTop===5},e.style.position="fixed",e.style.top="20px",i.fixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",i.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,i.doesNotIncludeMarginInBodyOffset=r.offsetTop!==j,r.removeChild(a),q=a=null,f.extend(b,i))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.nodeName.toLowerCase()]||f.valHooks[g.type];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;h=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/\bhover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")}; -f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;le&&i.push({elem:this,matches:d.slice(e)});for(j=0;j0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="
";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h0)for(h=g;h=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div
","
"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function() -{for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1>");try{for(var c=0,d=this.length;c1&&l0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||!bc.test("<"+a.nodeName)?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!_.test(k))k=b.createTextNode(k);else{k=k.replace(Y,"<$1>");var l=(Z.exec(k)||["",""])[1].toLowerCase(),m=bg[l]||bg._default,n=m[0],o=b.createElement("div");b===c?bh.appendChild(o):U(b).appendChild(o),o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=$.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]===""&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&X.test(k)&&o.insertBefore(b.createTextNode(X.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return br.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bq,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bq.test(g)?g.replace(bq,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bz(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bA=function(a,b){var c,d,e;b=b.replace(bs,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b)));return c}),c.documentElement.currentStyle&&(bB=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f===null&&g&&(e=g[b])&&(f=e),!bt.test(f)&&bu.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f||0,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),bz=bA||bB,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bD=/%20/g,bE=/\[\]$/,bF=/\r?\n/g,bG=/#.*$/,bH=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bI=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bJ=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bK=/^(?:GET|HEAD)$/,bL=/^\/\//,bM=/\?/,bN=/)<[^<]*)*<\/script>/gi,bO=/^(?:select|textarea)/i,bP=/\s+/,bQ=/([?&])_=[^&]*/,bR=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bS=f.fn.load,bT={},bU={},bV,bW,bX=["*/"]+["*"];try{bV=e.href}catch(bY){bV=c.createElement("a"),bV.href="",bV=bV.href}bW=bR.exec(bV.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bS)return bS.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("
").append(c.replace(bN,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bO.test(this.nodeName)||bI.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bF,"\r\n")}}):{name:b.name,value:c.replace(bF,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b_(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b_(a,b);return a},ajaxSettings:{url:bV,isLocal:bJ.test(bW[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bX},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bZ(bT),ajaxTransport:bZ(bU),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?cb(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cc(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bH.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bG,"").replace(bL,bW[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bP),d.crossDomain==null&&(r=bR.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bW[1]&&r[2]==bW[2]&&(r[3]||(r[1]==="http:"?80:443))==(bW[3]||(bW[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),b$(bT,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bK.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bM.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bQ,"$1_="+x);d.url=y+(y===d.url?(bM.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bX+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=b$(bU,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)ca(g,a[g],c,e);return d.join("&").replace(bD,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cd=f.now(),ce=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cd++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ce.test(b.url)||e&&ce.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ce,l),b.url===j&&(e&&(k=k.replace(ce,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cf=a.ActiveXObject?function(){for(var a in ch)ch[a](0,1)}:!1,cg=0,ch;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ci()||cj()}:ci,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cf&&delete ch[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cg,cf&&(ch||(ch={},f(a).unload(cf)),ch[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var ck={},cl,cm,cn=/^(?:toggle|show|hide)$/,co=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cp,cq=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cr;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cu("show",3),a,b,c);for(var g=0,h=this.length;g=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cy(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cy(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,d,"padding")):this[d]():null},f.fn["outer"+c]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,d,a?"margin":"border")):this[d]():null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNumeric(j)?j:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window); \ No newline at end of file diff --git a/ui/website/jquery.json.js b/ui/website/jquery.json.js deleted file mode 100644 index 4e4e38680d220..0000000000000 --- a/ui/website/jquery.json.js +++ /dev/null @@ -1,23 +0,0 @@ - -(function($){var escapeable=/["\\\x00-\x1f\x7f-\x9f]/g,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'};$.toJSON=typeof JSON==='object'&&JSON.stringify?JSON.stringify:function(o){if(o===null){return'null';} -var type=typeof o;if(type==='undefined'){return undefined;} -if(type==='number'||type==='boolean'){return''+o;} -if(type==='string'){return $.quoteString(o);} -if(type==='object'){if(typeof o.toJSON==='function'){return $.toJSON(o.toJSON());} -if(o.constructor===Date){var month=o.getUTCMonth()+1,day=o.getUTCDate(),year=o.getUTCFullYear(),hours=o.getUTCHours(),minutes=o.getUTCMinutes(),seconds=o.getUTCSeconds(),milli=o.getUTCMilliseconds();if(month<10){month='0'+month;} -if(day<10){day='0'+day;} -if(hours<10){hours='0'+hours;} -if(minutes<10){minutes='0'+minutes;} -if(seconds<10){seconds='0'+seconds;} -if(milli<100){milli='0'+milli;} -if(milli<10){milli='0'+milli;} -return'"'+year+'-'+month+'-'+day+'T'+ -hours+':'+minutes+':'+seconds+'.'+milli+'Z"';} -if(o.constructor===Array){var ret=[];for(var i=0;i elements in IE6-9 are considered 'NoScope' elements and therefore will be removed - // when injected with innerHTML. To get around this you need to prepend the 'NoScope' element - // with a 'scoped' element, in our case the soft-hyphen entity as it won't mess with our measurements. - // msdn.microsoft.com/en-us/library/ms533897%28VS.85%29.aspx - // Documents served as xml will throw if using ­ so use xml friendly encoded version. See issue #277 - style = ['­',''].join(''); - div.id = mod; - // IE6 will false positive on some tests due to the style element inside the test div somehow interfering offsetHeight, so insert it into body or fakebody. - // Opera will act all quirky when injecting elements in documentElement when page is served as xml, needs fakebody too. #270 - fakeBody.innerHTML += style; - fakeBody.appendChild(div); - if(!body){ - //avoid crashing IE8, if background image is used - fakeBody.style.background = ""; - docElement.appendChild(fakeBody); - } - - ret = callback(div, rule); - // If this is done after page load we don't want to remove the body so check if body exists - !body ? fakeBody.parentNode.removeChild(fakeBody) : div.parentNode.removeChild(div); - - return !!ret; - - }, - - - // adapted from matchMedia polyfill - // by Scott Jehl and Paul Irish - // gist.github.com/786768 - testMediaQuery = function( mq ) { - - var matchMedia = window.matchMedia || window.msMatchMedia; - if ( matchMedia ) { - return matchMedia(mq).matches; - } - - var bool; - - injectElementWithStyles('@media ' + mq + ' { #' + mod + ' { position: absolute; } }', function( node ) { - bool = (window.getComputedStyle ? - getComputedStyle(node, null) : - node.currentStyle)['position'] == 'absolute'; - }); - - return bool; - - }, - - - /** - * isEventSupported determines if a given element supports the given event - * function from yura.thinkweb2.com/isEventSupported/ - */ - isEventSupported = (function() { - - var TAGNAMES = { - 'select': 'input', 'change': 'input', - 'submit': 'form', 'reset': 'form', - 'error': 'img', 'load': 'img', 'abort': 'img' - }; - - function isEventSupported( eventName, element ) { - - element = element || document.createElement(TAGNAMES[eventName] || 'div'); - eventName = 'on' + eventName; - - // When using `setAttribute`, IE skips "unload", WebKit skips "unload" and "resize", whereas `in` "catches" those - var isSupported = eventName in element; - - if ( !isSupported ) { - // If it has no `setAttribute` (i.e. doesn't implement Node interface), try generic element - if ( !element.setAttribute ) { - element = document.createElement('div'); - } - if ( element.setAttribute && element.removeAttribute ) { - element.setAttribute(eventName, ''); - isSupported = is(element[eventName], 'function'); - - // If property was created, "remove it" (by setting value to `undefined`) - if ( !is(element[eventName], 'undefined') ) { - element[eventName] = undefined; - } - element.removeAttribute(eventName); - } - } - - element = null; - return isSupported; - } - return isEventSupported; - })(); - - // hasOwnProperty shim by kangax needed for Safari 2.0 support - var _hasOwnProperty = ({}).hasOwnProperty, hasOwnProperty; - if ( !is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined') ) { - hasOwnProperty = function (object, property) { - return _hasOwnProperty.call(object, property); - }; - } - else { - hasOwnProperty = function (object, property) { /* yes, this can give false positives/negatives, but most of the time we don't care about those */ - return ((property in object) && is(object.constructor.prototype[property], 'undefined')); - }; - } - - // Taken from ES5-shim https://github.com/kriskowal/es5-shim/blob/master/es5-shim.js - // ES-5 15.3.4.5 - // http://es5.github.com/#x15.3.4.5 - - if (!Function.prototype.bind) { - - Function.prototype.bind = function bind(that) { - - var target = this; - - if (typeof target != "function") { - throw new TypeError(); - } - - var args = slice.call(arguments, 1), - bound = function () { - - if (this instanceof bound) { - - var F = function(){}; - F.prototype = target.prototype; - var self = new F; - - var result = target.apply( - self, - args.concat(slice.call(arguments)) - ); - if (Object(result) === result) { - return result; - } - return self; - - } else { - - return target.apply( - that, - args.concat(slice.call(arguments)) - ); - - } - - }; - - return bound; - }; - } - - /** - * setCss applies given styles to the Modernizr DOM node. - */ - function setCss( str ) { - mStyle.cssText = str; - } - - /** - * setCssAll extrapolates all vendor-specific css strings. - */ - function setCssAll( str1, str2 ) { - return setCss(prefixes.join(str1 + ';') + ( str2 || '' )); - } - - /** - * is returns a boolean for if typeof obj is exactly type. - */ - function is( obj, type ) { - return typeof obj === type; - } - - /** - * contains returns a boolean for if substr is found within str. - */ - function contains( str, substr ) { - return !!~('' + str).indexOf(substr); - } - - /** - * testProps is a generic CSS / DOM property test; if a browser supports - * a certain property, it won't return undefined for it. - * A supported CSS property returns empty string when its not yet set. - */ - function testProps( props, prefixed ) { - for ( var i in props ) { - if ( mStyle[ props[i] ] !== undefined ) { - return prefixed == 'pfx' ? props[i] : true; - } - } - return false; - } - - /** - * testDOMProps is a generic DOM property test; if a browser supports - * a certain property, it won't return undefined for it. - */ - function testDOMProps( props, obj, elem ) { - for ( var i in props ) { - var item = obj[props[i]]; - if ( item !== undefined) { - - // return the property name as a string - if (elem === false) return props[i]; - - // let's bind a function - if (is(item, 'function')){ - // default to autobind unless override - return item.bind(elem || obj); - } - - // return the unbound function or obj or value - return item; - } - } - return false; - } - - /** - * testPropsAll tests a list of DOM properties we want to check against. - * We specify literally ALL possible (known and/or likely) properties on - * the element including the non-vendor prefixed one, for forward- - * compatibility. - */ - function testPropsAll( prop, prefixed, elem ) { - - var ucProp = prop.charAt(0).toUpperCase() + prop.substr(1), - props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' '); - - // did they call .prefixed('boxSizing') or are we just testing a prop? - if(is(prefixed, "string") || is(prefixed, "undefined")) { - return testProps(props, prefixed); - - // otherwise, they called .prefixed('requestAnimationFrame', window[, elem]) - } else { - props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' '); - return testDOMProps(props, prefixed, elem); - } - } - - /** - * testBundle tests a list of CSS features that require element and style injection. - * By bundling them together we can reduce the need to touch the DOM multiple times. - */ - /*>>testBundle*/ - var testBundle = (function( styles, tests ) { - var style = styles.join(''), - len = tests.length; - - injectElementWithStyles(style, function( node, rule ) { - var style = document.styleSheets[document.styleSheets.length - 1], - // IE8 will bork if you create a custom build that excludes both fontface and generatedcontent tests. - // So we check for cssRules and that there is a rule available - // More here: github.com/Modernizr/Modernizr/issues/288 & github.com/Modernizr/Modernizr/issues/293 - cssText = style ? (style.cssRules && style.cssRules[0] ? style.cssRules[0].cssText : style.cssText || '') : '', - children = node.childNodes, hash = {}; - - while ( len-- ) { - hash[children[len].id] = children[len]; - } - - /*>>touch*/ Modernizr['touch'] = ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch || (hash['touch'] && hash['touch'].offsetTop) === 9; /*>>touch*/ - /*>>csstransforms3d*/ Modernizr['csstransforms3d'] = (hash['csstransforms3d'] && hash['csstransforms3d'].offsetLeft) === 9 && hash['csstransforms3d'].offsetHeight === 3; /*>>csstransforms3d*/ - /*>>generatedcontent*/Modernizr['generatedcontent'] = (hash['generatedcontent'] && hash['generatedcontent'].offsetHeight) >= 1; /*>>generatedcontent*/ - /*>>fontface*/ Modernizr['fontface'] = /src/i.test(cssText) && - cssText.indexOf(rule.split(' ')[0]) === 0; /*>>fontface*/ - }, len, tests); - - })([ - // Pass in styles to be injected into document - /*>>fontface*/ '@font-face {font-family:"font";src:url("https://")}' /*>>fontface*/ - - /*>>touch*/ ,['@media (',prefixes.join('touch-enabled),('),mod,')', - '{#touch{top:9px;position:absolute}}'].join('') /*>>touch*/ - - /*>>csstransforms3d*/ ,['@media (',prefixes.join('transform-3d),('),mod,')', - '{#csstransforms3d{left:9px;position:absolute;height:3px;}}'].join('')/*>>csstransforms3d*/ - - /*>>generatedcontent*/,['#generatedcontent:after{content:"',smile,'";visibility:hidden}'].join('') /*>>generatedcontent*/ - ], - [ - /*>>fontface*/ 'fontface' /*>>fontface*/ - /*>>touch*/ ,'touch' /*>>touch*/ - /*>>csstransforms3d*/ ,'csstransforms3d' /*>>csstransforms3d*/ - /*>>generatedcontent*/,'generatedcontent' /*>>generatedcontent*/ - - ]);/*>>testBundle*/ - - - /** - * Tests - * ----- - */ - - // The *new* flexbox - // dev.w3.org/csswg/css3-flexbox - - tests['flexbox'] = function() { - return testPropsAll('flexOrder'); - }; - - // The *old* flexbox - // www.w3.org/TR/2009/WD-css3-flexbox-20090723/ - - tests['flexbox-legacy'] = function() { - return testPropsAll('boxDirection'); - }; - - // On the S60 and BB Storm, getContext exists, but always returns undefined - // so we actually have to call getContext() to verify - // github.com/Modernizr/Modernizr/issues/issue/97/ - - tests['canvas'] = function() { - var elem = document.createElement('canvas'); - return !!(elem.getContext && elem.getContext('2d')); - }; - - tests['canvastext'] = function() { - return !!(Modernizr['canvas'] && is(document.createElement('canvas').getContext('2d').fillText, 'function')); - }; - - // this test initiates a new webgl context. - // webk.it/70117 is tracking a legit feature detect proposal - - tests['webgl'] = function() { - try { - var canvas = document.createElement('canvas'), - ret; - ret = !!(window.WebGLRenderingContext && (canvas.getContext('experimental-webgl') || canvas.getContext('webgl'))); - canvas = undefined; - } catch (e){ - ret = false; - } - return ret; - }; - - /* - * The Modernizr.touch test only indicates if the browser supports - * touch events, which does not necessarily reflect a touchscreen - * device, as evidenced by tablets running Windows 7 or, alas, - * the Palm Pre / WebOS (touch) phones. - * - * Additionally, Chrome (desktop) used to lie about its support on this, - * but that has since been rectified: crbug.com/36415 - * - * We also test for Firefox 4 Multitouch Support. - * - * For more info, see: modernizr.github.com/Modernizr/touch.html - */ - - tests['touch'] = function() { - return Modernizr['touch']; - }; - - /** - * geolocation tests for the new Geolocation API specification. - * This test is a standards compliant-only test; for more complete - * testing, including a Google Gears fallback, please see: - * code.google.com/p/geo-location-javascript/ - * or view a fallback solution using google's geo API: - * gist.github.com/366184 - */ - tests['geolocation'] = function() { - return !!navigator.geolocation; - }; - - // Per 1.6: - // This used to be Modernizr.crosswindowmessaging but the longer - // name has been deprecated in favor of a shorter and property-matching one. - // The old API is still available in 1.6, but as of 2.0 will throw a warning, - // and in the first release thereafter disappear entirely. - tests['postmessage'] = function() { - return !!window.postMessage; - }; - - - // Chrome incognito mode used to throw an exception when using openDatabase - // It doesn't anymore. - tests['websqldatabase'] = function() { - return !!window.openDatabase; - }; - - // Vendors had inconsistent prefixing with the experimental Indexed DB: - // - Webkit's implementation is accessible through webkitIndexedDB - // - Firefox shipped moz_indexedDB before FF4b9, but since then has been mozIndexedDB - // For speed, we don't test the legacy (and beta-only) indexedDB - tests['indexedDB'] = function() { - return !!testPropsAll("indexedDB",window); - }; - - // documentMode logic from YUI to filter out IE8 Compat Mode - // which false positives. - tests['hashchange'] = function() { - return isEventSupported('hashchange', window) && (document.documentMode === undefined || document.documentMode > 7); - }; - - // Per 1.6: - // This used to be Modernizr.historymanagement but the longer - // name has been deprecated in favor of a shorter and property-matching one. - // The old API is still available in 1.6, but as of 2.0 will throw a warning, - // and in the first release thereafter disappear entirely. - tests['history'] = function() { - return !!(window.history && history.pushState); - }; - - tests['draganddrop'] = function() { - var div = document.createElement('div'); - return ('draggable' in div) || ('ondragstart' in div && 'ondrop' in div); - }; - - // FIXME: Once FF10 is sunsetted, we can drop prefixed MozWebSocket - // bugzil.la/695635 - tests['websockets'] = function() { - for ( var i = -1, len = cssomPrefixes.length; ++i < len; ){ - if ( window[cssomPrefixes[i] + 'WebSocket'] ){ - return true; - } - } - return 'WebSocket' in window; - }; - - - // css-tricks.com/rgba-browser-support/ - tests['rgba'] = function() { - // Set an rgba() color and check the returned value - - setCss('background-color:rgba(150,255,150,.5)'); - - return contains(mStyle.backgroundColor, 'rgba'); - }; - - tests['hsla'] = function() { - // Same as rgba(), in fact, browsers re-map hsla() to rgba() internally, - // except IE9 who retains it as hsla - - setCss('background-color:hsla(120,40%,100%,.5)'); - - return contains(mStyle.backgroundColor, 'rgba') || contains(mStyle.backgroundColor, 'hsla'); - }; - - tests['multiplebgs'] = function() { - // Setting multiple images AND a color on the background shorthand property - // and then querying the style.background property value for the number of - // occurrences of "url(" is a reliable method for detecting ACTUAL support for this! - - setCss('background:url(https://),url(https://),red url(https://)'); - - // If the UA supports multiple backgrounds, there should be three occurrences - // of the string "url(" in the return value for elemStyle.background - - return /(url\s*\(.*?){3}/.test(mStyle.background); - }; - - - // In testing support for a given CSS property, it's legit to test: - // `elem.style[styleName] !== undefined` - // If the property is supported it will return an empty string, - // if unsupported it will return undefined. - - // We'll take advantage of this quick test and skip setting a style - // on our modernizr element, but instead just testing undefined vs - // empty string. - - - tests['backgroundsize'] = function() { - return testPropsAll('backgroundSize'); - }; - - tests['borderimage'] = function() { - return testPropsAll('borderImage'); - }; - - - // Super comprehensive table about all the unique implementations of - // border-radius: muddledramblings.com/table-of-css3-border-radius-compliance - - tests['borderradius'] = function() { - return testPropsAll('borderRadius'); - }; - - // WebOS unfortunately false positives on this test. - tests['boxshadow'] = function() { - return testPropsAll('boxShadow'); - }; - - // FF3.0 will false positive on this test - tests['textshadow'] = function() { - return document.createElement('div').style.textShadow === ''; - }; - - - tests['opacity'] = function() { - // Browsers that actually have CSS Opacity implemented have done so - // according to spec, which means their return values are within the - // range of [0.0,1.0] - including the leading zero. - - setCssAll('opacity:.55'); - - // The non-literal . in this regex is intentional: - // German Chrome returns this value as 0,55 - // github.com/Modernizr/Modernizr/issues/#issue/59/comment/516632 - return /^0.55$/.test(mStyle.opacity); - }; - - - // Note, Android < 4 will pass this test, but can only animate - // a single property at a time - // daneden.me/2011/12/putting-up-with-androids-bullshit/ - tests['cssanimations'] = function() { - return testPropsAll('animationName'); - }; - - - tests['csscolumns'] = function() { - return testPropsAll('columnCount'); - }; - - - tests['cssgradients'] = function() { - /** - * For CSS Gradients syntax, please see: - * webkit.org/blog/175/introducing-css-gradients/ - * developer.mozilla.org/en/CSS/-moz-linear-gradient - * developer.mozilla.org/en/CSS/-moz-radial-gradient - * dev.w3.org/csswg/css3-images/#gradients- - */ - - var str1 = 'background-image:', - str2 = 'gradient(linear,left top,right bottom,from(#9f9),to(white));', - str3 = 'linear-gradient(left top,#9f9, white);'; - - setCss( - // legacy webkit syntax (FIXME: remove when syntax not in use anymore) - (str1 + '-webkit- '.split(' ').join(str2 + str1) - // standard syntax // trailing 'background-image:' - + prefixes.join(str3 + str1)).slice(0, -str1.length) - ); - - return contains(mStyle.backgroundImage, 'gradient'); - }; - - - tests['cssreflections'] = function() { - return testPropsAll('boxReflect'); - }; - - - tests['csstransforms'] = function() { - return !!testPropsAll('transform'); - }; - - - tests['csstransforms3d'] = function() { - - var ret = !!testPropsAll('perspective'); - - // Webkit's 3D transforms are passed off to the browser's own graphics renderer. - // It works fine in Safari on Leopard and Snow Leopard, but not in Chrome in - // some conditions. As a result, Webkit typically recognizes the syntax but - // will sometimes throw a false positive, thus we must do a more thorough check: - if ( ret && 'webkitPerspective' in docElement.style ) { - - // Webkit allows this media query to succeed only if the feature is enabled. - // `@media (transform-3d),(-o-transform-3d),(-moz-transform-3d),(-ms-transform-3d),(-webkit-transform-3d),(modernizr){ ... }` - ret = Modernizr['csstransforms3d']; - } - return ret; - }; - - - tests['csstransitions'] = function() { - return testPropsAll('transition'); - }; - - - /*>>fontface*/ - // @font-face detection routine by Diego Perini - // javascript.nwbox.com/CSSSupport/ - - // false positives in WebOS: github.com/Modernizr/Modernizr/issues/342 - tests['fontface'] = function() { - return Modernizr['fontface']; - }; - /*>>fontface*/ - - // CSS generated content detection - tests['generatedcontent'] = function() { - return Modernizr['generatedcontent']; - }; - - - - // These tests evaluate support of the video/audio elements, as well as - // testing what types of content they support. - // - // We're using the Boolean constructor here, so that we can extend the value - // e.g. Modernizr.video // true - // Modernizr.video.ogg // 'probably' - // - // Codec values from : github.com/NielsLeenheer/html5test/blob/9106a8/index.html#L845 - // thx to NielsLeenheer and zcorpan - - // Note: in some older browsers, "no" was a return value instead of empty string. - // It was live in FF3.5.0 and 3.5.1, but fixed in 3.5.2 - // It was also live in Safari 4.0.0 - 4.0.4, but fixed in 4.0.5 - - tests['video'] = function() { - var elem = document.createElement('video'), - bool = false; - - // IE9 Running on Windows Server SKU can cause an exception to be thrown, bug #224 - try { - if ( bool = !!elem.canPlayType ) { - bool = new Boolean(bool); - bool.ogg = elem.canPlayType('video/ogg; codecs="theora"') .replace(/^no$/,''); - - bool.h264 = elem.canPlayType('video/mp4; codecs="avc1.42E01E"') .replace(/^no$/,''); - - bool.webm = elem.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,''); - } - - } catch(e) { } - - return bool; - }; - - tests['audio'] = function() { - var elem = document.createElement('audio'), - bool = false; - - try { - if ( bool = !!elem.canPlayType ) { - bool = new Boolean(bool); - bool.ogg = elem.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,''); - bool.mp3 = elem.canPlayType('audio/mpeg;') .replace(/^no$/,''); - - // Mimetypes accepted: - // developer.mozilla.org/En/Media_formats_supported_by_the_audio_and_video_elements - // bit.ly/iphoneoscodecs - bool.wav = elem.canPlayType('audio/wav; codecs="1"') .replace(/^no$/,''); - bool.m4a = ( elem.canPlayType('audio/x-m4a;') || - elem.canPlayType('audio/aac;')) .replace(/^no$/,''); - } - } catch(e) { } - - return bool; - }; - - - // In FF4, if disabled, window.localStorage should === null. - - // Normally, we could not test that directly and need to do a - // `('localStorage' in window) && ` test first because otherwise Firefox will - // throw bugzil.la/365772 if cookies are disabled - - // Also in iOS5 Private Browsing mode, attepting to use localStorage.setItem - // will throw the exception: - // QUOTA_EXCEEDED_ERRROR DOM Exception 22. - // Peculiarly, getItem and removeItem calls do not throw. - - // Because we are forced to try/catch this, we'll go aggressive. - - // Just FWIW: IE8 Compat mode supports these features completely: - // www.quirksmode.org/dom/html5.html - // But IE8 doesn't support either with local files - - tests['localstorage'] = function() { - try { - localStorage.setItem(mod, mod); - localStorage.removeItem(mod); - return true; - } catch(e) { - return false; - } - }; - - tests['sessionstorage'] = function() { - try { - sessionStorage.setItem(mod, mod); - sessionStorage.removeItem(mod); - return true; - } catch(e) { - return false; - } - }; - - - tests['webworkers'] = function() { - return !!window.Worker; - }; - - - tests['applicationcache'] = function() { - return !!window.applicationCache; - }; - - - // Thanks to Erik Dahlstrom - tests['svg'] = function() { - return !!document.createElementNS && !!document.createElementNS(ns.svg, 'svg').createSVGRect; - }; - - // specifically for SVG inline in HTML, not within XHTML - // test page: paulirish.com/demo/inline-svg - tests['inlinesvg'] = function() { - var div = document.createElement('div'); - div.innerHTML = ''; - return (div.firstChild && div.firstChild.namespaceURI) == ns.svg; - }; - - // SVG SMIL animation - tests['smil'] = function() { - return !!document.createElementNS && /SVGAnimate/.test(toString.call(document.createElementNS(ns.svg, 'animate'))); - }; - - // This test is only for clip paths in SVG proper, not clip paths on HTML content - // demo: srufaculty.sru.edu/david.dailey/svg/newstuff/clipPath4.svg - - // However read the comments to dig into applying SVG clippaths to HTML content here: - // github.com/Modernizr/Modernizr/issues/213#issuecomment-1149491 - tests['svgclippaths'] = function() { - return !!document.createElementNS && /SVGClipPath/.test(toString.call(document.createElementNS(ns.svg, 'clipPath'))); - }; - - // input features and input types go directly onto the ret object, bypassing the tests loop. - // Hold this guy to execute in a moment. - function webforms() { - // Run through HTML5's new input attributes to see if the UA understands any. - // We're using f which is the element created early on - // Mike Taylr has created a comprehensive resource for testing these attributes - // when applied to all input types: - // miketaylr.com/code/input-type-attr.html - // spec: www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary - - // Only input placeholder is tested while textarea's placeholder is not. - // Currently Safari 4 and Opera 11 have support only for the input placeholder - // Both tests are available in feature-detects/forms-placeholder.js - Modernizr['input'] = (function( props ) { - for ( var i = 0, len = props.length; i < len; i++ ) { - attrs[ props[i] ] = !!(props[i] in inputElem); - } - if (attrs.list){ - // safari false positive's on datalist: webk.it/74252 - // see also github.com/Modernizr/Modernizr/issues/146 - attrs.list = !!(document.createElement('datalist') && window.HTMLDataListElement); - } - return attrs; - })('autocomplete autofocus list placeholder max min multiple pattern required step'.split(' ')); - - // Run through HTML5's new input types to see if the UA understands any. - // This is put behind the tests runloop because it doesn't return a - // true/false like all the other tests; instead, it returns an object - // containing each input type with its corresponding true/false value - - // Big thanks to @miketaylr for the html5 forms expertise. miketaylr.com/ - Modernizr['inputtypes'] = (function(props) { - - for ( var i = 0, bool, inputElemType, defaultView, len = props.length; i < len; i++ ) { - - inputElem.setAttribute('type', inputElemType = props[i]); - bool = inputElem.type !== 'text'; - - // We first check to see if the type we give it sticks.. - // If the type does, we feed it a textual value, which shouldn't be valid. - // If the value doesn't stick, we know there's input sanitization which infers a custom UI - if ( bool ) { - - inputElem.value = smile; - inputElem.style.cssText = 'position:absolute;visibility:hidden;'; - - if ( /^range$/.test(inputElemType) && inputElem.style.WebkitAppearance !== undefined ) { - - docElement.appendChild(inputElem); - defaultView = document.defaultView; - - // Safari 2-4 allows the smiley as a value, despite making a slider - bool = defaultView.getComputedStyle && - defaultView.getComputedStyle(inputElem, null).WebkitAppearance !== 'textfield' && - // Mobile android web browser has false positive, so must - // check the height to see if the widget is actually there. - (inputElem.offsetHeight !== 0); - - docElement.removeChild(inputElem); - - } else if ( /^(search|tel)$/.test(inputElemType) ){ - // Spec doesnt define any special parsing or detectable UI - // behaviors so we pass these through as true - - // Interestingly, opera fails the earlier test, so it doesn't - // even make it here. - - } else if ( /^(url|email)$/.test(inputElemType) ) { - // Real url and email support comes with prebaked validation. - bool = inputElem.checkValidity && inputElem.checkValidity() === false; - - } else if ( /^color$/.test(inputElemType) ) { - // chuck into DOM and force reflow for Opera bug in 11.00 - // github.com/Modernizr/Modernizr/issues#issue/159 - docElement.appendChild(inputElem); - docElement.offsetWidth; - bool = inputElem.value != smile; - docElement.removeChild(inputElem); - - } else { - // If the upgraded input compontent rejects the :) text, we got a winner - bool = inputElem.value != smile; - } - } - - inputs[ props[i] ] = !!bool; - } - return inputs; - })('search tel url email datetime date month week time datetime-local number range color'.split(' ')); - } - - - // End of test definitions - // ----------------------- - - - - // Run through all tests and detect their support in the current UA. - // todo: hypothetically we could be doing an array of tests and use a basic loop here. - for ( var feature in tests ) { - if ( hasOwnProperty(tests, feature) ) { - // run the test, throw the return value into the Modernizr, - // then based on that boolean, define an appropriate className - // and push it into an array of classes we'll join later. - featureName = feature.toLowerCase(); - Modernizr[featureName] = tests[feature](); - - classes.push((Modernizr[featureName] ? '' : 'no-') + featureName); - } - } - - // input tests need to run. - Modernizr.input || webforms(); - - - /** - * addTest allows the user to define their own feature tests - * the result will be added onto the Modernizr object, - * as well as an appropriate className set on the html element - * - * @param feature - String naming the feature - * @param test - Function returning true if feature is supported, false if not - */ - Modernizr.addTest = function ( feature, test ) { - if ( typeof feature == 'object' ) { - for ( var key in feature ) { - if ( hasOwnProperty( feature, key ) ) { - Modernizr.addTest( key, feature[ key ] ); - } - } - } else { - - feature = feature.toLowerCase(); - - if ( Modernizr[feature] !== undefined ) { - // we're going to quit if you're trying to overwrite an existing test - // if we were to allow it, we'd do this: - // var re = new RegExp("\\b(no-)?" + feature + "\\b"); - // docElement.className = docElement.className.replace( re, '' ); - // but, no rly, stuff 'em. - return Modernizr; - } - - test = typeof test == 'function' ? test() : test; - - docElement.className += ' ' + (test ? '' : 'no-') + feature; - Modernizr[feature] = test; - - } - - return Modernizr; // allow chaining. - }; - - - // Reset modElem.cssText to nothing to reduce memory footprint. - setCss(''); - modElem = inputElem = null; - - //>>BEGIN IEPP - // Enable HTML 5 elements for styling in IE & add HTML5 css - /*! HTML5 Shiv v3.4 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed */ - ;(function(window, document) { - - /** Preset options */ - var options = window.html5 || {}; - - /** Used to skip problem elements */ - var reSkip = /^<|^(?:button|form|map|select|textarea)$/i; - - /** Detect whether the browser supports default html5 styles */ - var supportsHtml5Styles; - - /** Detect whether the browser supports unknown elements */ - var supportsUnknownElements; - - (function() { - var a = document.createElement('a'); - - a.innerHTML = ''; - - //if the hidden property is implemented we can assume, that the browser supports HTML5 Styles - supportsHtml5Styles = ('hidden' in a); - supportsUnknownElements = a.childNodes.length == 1 || (function() { - // assign a false positive if unable to shiv - try { - (document.createElement)('a'); - } catch(e) { - return true; - } - var frag = document.createDocumentFragment(); - return ( - typeof frag.cloneNode == 'undefined' || - typeof frag.createDocumentFragment == 'undefined' || - typeof frag.createElement == 'undefined' - ); - }()); - - }()); - - /*--------------------------------------------------------------------------*/ - - /** - * Creates a style sheet with the given CSS text and adds it to the document. - * @private - * @param {Document} ownerDocument The document. - * @param {String} cssText The CSS text. - * @returns {StyleSheet} The style element. - */ - function addStyleSheet(ownerDocument, cssText) { - var p = ownerDocument.createElement('p'), - parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement; - - p.innerHTML = 'x'; - return parent.insertBefore(p.lastChild, parent.firstChild); - } - - /** - * Returns the value of `html5.elements` as an array. - * @private - * @returns {Array} An array of shived element node names. - */ - function getElements() { - var elements = html5.elements; - return typeof elements == 'string' ? elements.split(' ') : elements; - } - - /** - * Shivs the `createElement` and `createDocumentFragment` methods of the document. - * @private - * @param {Document|DocumentFragment} ownerDocument The document. - */ - function shivMethods(ownerDocument) { - var cache = {}, - docCreateElement = ownerDocument.createElement, - docCreateFragment = ownerDocument.createDocumentFragment, - frag = docCreateFragment(); - - ownerDocument.createElement = function(nodeName) { - // Avoid adding some elements to fragments in IE < 9 because - // * Attributes like `name` or `type` cannot be set/changed once an element - // is inserted into a document/fragment - // * Link elements with `src` attributes that are inaccessible, as with - // a 403 response, will cause the tab/window to crash - // * Script elements appended to fragments will execute when their `src` - // or `text` property is set - var node = (cache[nodeName] || (cache[nodeName] = docCreateElement(nodeName))).cloneNode(); - return html5.shivMethods && node.canHaveChildren && !reSkip.test(nodeName) ? frag.appendChild(node) : node; - }; - - ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' + - 'var n=f.cloneNode(),c=n.createElement;' + - 'h.shivMethods&&(' + - // unroll the `createElement` calls - getElements().join().replace(/\w+/g, function(nodeName) { - cache[nodeName] = docCreateElement(nodeName); - frag.createElement(nodeName); - return 'c("' + nodeName + '")'; - }) + - ');return n}' - )(html5, frag); - } - - /*--------------------------------------------------------------------------*/ - - /** - * Shivs the given document. - * @memberOf html5 - * @param {Document} ownerDocument The document to shiv. - * @returns {Document} The shived document. - */ - function shivDocument(ownerDocument) { - var shived; - if (ownerDocument.documentShived) { - return ownerDocument; - } - if (html5.shivCSS && !supportsHtml5Styles) { - shived = !!addStyleSheet(ownerDocument, - // corrects block display not defined in IE6/7/8/9 - 'article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}' + - // corrects audio display not defined in IE6/7/8/9 - 'audio{display:none}' + - // corrects canvas and video display not defined in IE6/7/8/9 - 'canvas,video{display:inline-block;*display:inline;*zoom:1}' + - // corrects 'hidden' attribute and audio[controls] display not present in IE7/8/9 - '[hidden]{display:none}audio[controls]{display:inline-block;*display:inline;*zoom:1}' + - // adds styling not present in IE6/7/8/9 - 'mark{background:#FF0;color:#000}' - ); - } - if (!supportsUnknownElements) { - shived = !shivMethods(ownerDocument); - } - if (shived) { - ownerDocument.documentShived = shived; - } - return ownerDocument; - } - - /*--------------------------------------------------------------------------*/ - - /** - * The `html5` object is exposed so that more elements can be shived and - * existing shiving can be detected on iframes. - * @type Object - * @example - * - * // options can be changed before the script is included - * html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false }; - */ - var html5 = { - - /** - * An array or space separated string of node names of the elements to shiv. - * @memberOf html5 - * @type Array|String - */ - 'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video', - - /** - * A flag to indicate that the HTML5 style sheet should be inserted. - * @memberOf html5 - * @type Boolean - */ - 'shivCSS': !(options.shivCSS === false), - - /** - * A flag to indicate that the document's `createElement` and `createDocumentFragment` - * methods should be overwritten. - * @memberOf html5 - * @type Boolean - */ - 'shivMethods': !(options.shivMethods === false), - - /** - * A string to describe the type of `html5` object ("default" or "default print"). - * @memberOf html5 - * @type String - */ - 'type': 'default', - - // shivs the document according to the specified `html5` object options - 'shivDocument': shivDocument - }; - - /*--------------------------------------------------------------------------*/ - - // expose html5 - window.html5 = html5; - - // shiv the document - shivDocument(document); - - }(this, document)); - - //>>END IEPP - - // Assign private properties to the return object with prefix - Modernizr._version = version; - - // expose these for the plugin API. Look in the source for how to join() them against your input - Modernizr._prefixes = prefixes; - Modernizr._domPrefixes = domPrefixes; - Modernizr._cssomPrefixes = cssomPrefixes; - - // Modernizr.mq tests a given media query, live against the current state of the window - // A few important notes: - // * If a browser does not support media queries at all (eg. oldIE) the mq() will always return false - // * A max-width or orientation query will be evaluated against the current state, which may change later. - // * You must specify values. Eg. If you are testing support for the min-width media query use: - // Modernizr.mq('(min-width:0)') - // usage: - // Modernizr.mq('only screen and (max-width:768)') - Modernizr.mq = testMediaQuery; - - // Modernizr.hasEvent() detects support for a given event, with an optional element to test on - // Modernizr.hasEvent('gesturestart', elem) - Modernizr.hasEvent = isEventSupported; - - // Modernizr.testProp() investigates whether a given style property is recognized - // Note that the property names must be provided in the camelCase variant. - // Modernizr.testProp('pointerEvents') - Modernizr.testProp = function(prop){ - return testProps([prop]); - }; - - // Modernizr.testAllProps() investigates whether a given style property, - // or any of its vendor-prefixed variants, is recognized - // Note that the property names must be provided in the camelCase variant. - // Modernizr.testAllProps('boxSizing') - Modernizr.testAllProps = testPropsAll; - - - - // Modernizr.testStyles() allows you to add custom styles to the document and test an element afterwards - // Modernizr.testStyles('#modernizr { position:absolute }', function(elem, rule){ ... }) - Modernizr.testStyles = injectElementWithStyles; - - - // Modernizr.prefixed() returns the prefixed or nonprefixed property name variant of your input - // Modernizr.prefixed('boxSizing') // 'MozBoxSizing' - - // Properties must be passed as dom-style camelcase, rather than `box-sizing` hypentated style. - // Return values will also be the camelCase variant, if you need to translate that to hypenated style use: - // - // str.replace(/([A-Z])/g, function(str,m1){ return '-' + m1.toLowerCase(); }).replace(/^ms-/,'-ms-'); - - // If you're trying to ascertain which transition end event to bind to, you might do something like... - // - // var transEndEventNames = { - // 'WebkitTransition' : 'webkitTransitionEnd', - // 'MozTransition' : 'transitionend', - // 'OTransition' : 'oTransitionEnd', - // 'msTransition' : 'MsTransitionEnd', - // 'transition' : 'transitionend' - // }, - // transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ]; - - Modernizr.prefixed = function(prop, obj, elem){ - if(!obj) { - return testPropsAll(prop, 'pfx'); - } else { - // Testing DOM property e.g. Modernizr.prefixed('requestAnimationFrame', window) // 'mozRequestAnimationFrame' - return testPropsAll(prop, obj, elem); - } - }; - - - - // Remove "no-js" class from element, if it exists: - docElement.className = docElement.className.replace(/(^|\s)no-js(\s|$)/, '$1$2') + - - // Add the new classes to the element. - (enableClasses ? ' js ' + classes.join(' ') : ''); - - return Modernizr; - -})(this, this.document); diff --git a/ui/website/repl.css b/ui/website/repl.css deleted file mode 100755 index 3138f61880271..0000000000000 --- a/ui/website/repl.css +++ /dev/null @@ -1,170 +0,0 @@ -/* main styles */ - -* { - margin: 0px; - padding: 0px; -} - -body { - font: 100% 'Arial', sans-serif; - color: #666; - background-color: #eee; -} - -div#main { -} - -div#left-column { - width: 189px; - float: left; - font-size: 90%; - padding-left: 20px; - padding-right: 20px; -} - -div#left-column ul { - padding-left: 20px; -} - -div#left-column ul li { - list-style-image: url("images/bullet.png"); - padding: 5px; - cursor: pointer; -} - -div#left-column a { - text-decoration: none; - color: #666; - font-size: 14px; -} - -div#left-column a strong { - font-weight: bolder; -} - -div#left-column a.current-page { - font-weight: bold; -} - -div#left-column a:hover, div#left-column li:hover { - background-color: #f6f6f6; -} - -div#right-column { - float: left; -} - -img.bullet { - padding-bottom: 3px; - padding-right: 6px; -} - -ul { - list-style-type: none; - line-height: 1.3; -} - -h1 { - font-size: 130%; - font-weight: bold; - margin-top: 20px; - margin-bottom: 10px; - text-shadow: 1px 1px 1px #fff; - color: #666; -} - -h2 { - font-size: 110%; - font-weight: bold; - margin-top: 20px; - margin-bottom: 10px; - text-shadow: 1px 1px 1px #fff; - color: #999; -} - -p { - margin-top: 10px; - margin-bottom: 10px; -} - -code { - font: 85% "Droid Sans Mono", "Consolas", "Courier", "Courier New", monospace; - background-color: #f6f6f6; -} - -form#terminal-form { - border-left: 1px solid #d9d9d9; - padding: 20px; - overflow: auto; - cursor: text; -} - -div#terminal { - border: none; - outline: none; - overflow-x: hidden; - font: 85% "Droid Sans Mono", "Consolas", "Courier", "Courier New", monospace; -} - -div#prompt { - float: left; - font: 85% "Droid Sans Mono", "Consolas", "Courier", "Courier New", monospace; - display: none; -} - -textarea#terminal-input { - width: 500px; - background-color: transparent; - border: none; - outline: none; - display: block; - font: 85% "Droid Sans Mono", "Consolas", "Courier", "Courier New", monospace; - resize: none; - overflow: hidden; -} - -div.float-clear { - clear: left; -} - -span.strong { - font-weight: bold; -} - -/* color scheme */ - -span.color-scheme-message { -} - -span.color-scheme-error { -} - -span.color-scheme-prompt { -} - -select#color-scheme-picker { - width: 189px; -} - -/* for plotting */ - -svg .hrule line, svg .vrule line { - shape-rendering: crispEdges; -} - -svg .hrule2 line, svg .vrule2 line { - shape-rendering: crispEdges; -} - -svg .line { - fill: none; - stroke-width: 1.5px; -} - -svg text { -} - -/* for Internet Explorer */ -a img { - border: none; -} diff --git a/ui/website/repl.htm b/ui/website/repl.htm deleted file mode 100755 index 87136aaf59298..0000000000000 --- a/ui/website/repl.htm +++ /dev/null @@ -1,52 +0,0 @@ - - - - - Julia - A fresh approach to technical computing. - - - - - - - - - - - - - - -
-
-

The Julia Language

- - - -

Color Scheme

- -

Quick Reference

-

For help, try one of these:

- help()
- help(function)
- apropos("string") -
-
-
-
<initializing>

-
-
julia> 
- -
- -
-
-
- - diff --git a/ui/website/repl.js b/ui/website/repl.js deleted file mode 100644 index dee29bd631f08..0000000000000 --- a/ui/website/repl.js +++ /dev/null @@ -1,904 +0,0 @@ -(function() { - -/* - Color Schemes -*/ - -// array of color schemes -var color_schemes = [ - ["Dark", { - background_color: "#000000", - text_color: "#dddddd", - message_color: "#0000aa", - error_color: "#ff0000", - prompt_color: "#00bb00", - plot_grid_color: "#333333", - plot_axis_color: "#666666", - plot_text_color: "#dddddd", - plot_line_color: "#4d87c7", - plot_rect_color: "#4d87c7", - plot_rect_stroke_width: "0", - plot_rect_stroke_color: "#FFFFFF", - }], - ["Light", { - background_color: "#f8f8f8", - text_color: "#444444", - message_color: "#0000aa", - error_color: "#ff0000", - prompt_color: "#00aa00", - plot_grid_color: "#dadada", - plot_axis_color: "#aaaaaa", - plot_text_color: "#444444", - plot_line_color: "#4d87b7", - plot_rect_color: "#4d87c7", - plot_rect_stroke_width: "0", - plot_rect_stroke_color: "#FFFFFF", - }], -]; - -// the current color scheme -var current_color_scheme = 0; - -// Fetch items out of local storage if they exist -if (Modernizr.localstorage) { - if (localStorage.getItem("current_color_scheme")) { - current_color_scheme = localStorage.getItem("current_color_scheme"); - } -} - -// apply a particular color scheme -- call this every time the terminal content changes -function apply_color_scheme() { - $("form#terminal-form").css("background-color", color_schemes[current_color_scheme][1].background_color); - $("div#terminal").css("color", color_schemes[current_color_scheme][1].text_color); - $("textarea#terminal-input").css("color", color_schemes[current_color_scheme][1].text_color); - $("span.color-scheme-message").css("color", color_schemes[current_color_scheme][1].message_color); - $("span.color-scheme-error").css("color", color_schemes[current_color_scheme][1].error_color); - $("span.color-scheme-prompt").css("color", color_schemes[current_color_scheme][1].prompt_color); - $("svg .hrule line, svg .vrule line").css("stroke", color_schemes[current_color_scheme][1].plot_grid_color); - $("svg .hrule2 line, svg .vrule2 line").css("stroke", color_schemes[current_color_scheme][1].plot_axis_color); - $("svg text").css("fill", color_schemes[current_color_scheme][1].plot_text_color); - $("svg .line").css("stroke", color_schemes[current_color_scheme][1].plot_line_color); - $("svg .rect").css("fill", color_schemes[current_color_scheme][1].plot_rect_color); - $("svg .rect").css("stroke", color_schemes[current_color_scheme][1].plot_rect_stroke_width); - - if (Modernizr.localstorage) { - localStorage.setItem("current_color_scheme", current_color_scheme); - } -} - -// when the DOM loads -$(document).ready(function() { - // add the color scheme options to the picker - var options_str = ""; - for (var i in color_schemes) - options_str += ""; - $("select#color-scheme-picker").html(options_str); - - // add a hook to the change event of the color picker - $("select#color-scheme-picker").change(function() { - // determine which color scheme was selected - var scheme_name = $("select#color-scheme-picker option:selected").html(); - for (var i in color_schemes) { - if (color_schemes[i][0] == scheme_name) { - current_color_scheme = i; - break; - } - } - - // apply the color scheme - apply_color_scheme(); - }); - - // apply the current color scheme - apply_color_scheme(); -}); - -/* - Network Protol - - This needs to match the message - types listed in ui/webserver/message_types.h. -*/ - -// input messages (to julia) -var MSG_INPUT_NULL = 0; -var MSG_INPUT_START = 1; -var MSG_INPUT_POLL = 2; -var MSG_INPUT_EVAL = 3; -var MSG_INPUT_REPLAY_HISTORY = 4; -var MSG_INPUT_GET_USER = 5; - -// output messages (to the browser) -var MSG_OUTPUT_NULL = 0; -var MSG_OUTPUT_WELCOME = 1; -var MSG_OUTPUT_READY = 2; -var MSG_OUTPUT_MESSAGE = 3; -var MSG_OUTPUT_OTHER = 4; -var MSG_OUTPUT_EVAL_INPUT = 5; -var MSG_OUTPUT_FATAL_ERROR = 6; -var MSG_OUTPUT_EVAL_INCOMPLETE = 7; -var MSG_OUTPUT_EVAL_RESULT = 8; -var MSG_OUTPUT_EVAL_ERROR = 9; -var MSG_OUTPUT_PLOT = 10; -var MSG_OUTPUT_GET_USER = 11; -var MSG_OUTPUT_HTML = 12; - -/* - REPL implementation. -*/ - -// the user name -var user_name = "julia"; - -// the user id -var user_id = ""; - -// indent string -var indent_str = " "; - -// how long we delay in ms before polling the server again -var poll_interval = 300; - -// keep track of whether we are waiting for a message (and don't send more if we are) -var waiting_for_response = false; - -// a queue of messages to be sent to the server -var outbox_queue = []; - -// a queue of messages from the server to be processed -var inbox_queue = []; - -// keep track of whether new terminal data will appear on a new line -var new_line = true; - -// keep track of whether we have received a fatal message -var dead = false; - -// keep track of terminal history -var input_history = []; -var input_history_current = [""]; -var input_history_id = 0; -var input_history_size = 1000; - -// Fetch items out of local storage if they exist -if (Modernizr.localstorage) { - if (localStorage.getItem("input_history")) { - input_history = JSON.parse(localStorage.getItem("input_history")); - input_history_id = input_history.length - 1; - } - - if (localStorage.getItem("input_history_current")) { - input_history_current = JSON.parse(localStorage.getItem("input_history_current")); - } -} - -// reset the width of the terminal input -function set_input_width() { - // resize the input box (the -1 is for Internet Explorer) - $("#terminal-input").width($("#terminal").width()-$("#prompt").width()-1); -} - -// set the width of the terminal -function set_terminal_width() { - // set the width of the terminal - var new_terminal_width = Math.max($(window).width()-229, 200); - $("div#right-column").width(new_terminal_width); - - // resize the page container as well - $("div#main").width($("div#left-column").outerWidth(true)+$("div#right-column").outerWidth(true)); - - // reset the width of the terminal input - set_input_width(); -} - -// set the width of the terminal when the window is resized -$(window).resize(set_terminal_width); - -// jQuery extensions -jQuery.fn.extend({ - // inset some text into a textarea at the cursor position - insert_at_caret: function(str) { - // apply this function to all elements that match the selector - return this.each(function(i) { - // if text is selected, then just replace it - if (document.selection) { - // replace the selection with str - this.focus(); - sel = document.selection.createRange(); - sel.text = str; - this.focus(); - } else if (this.selectionStart || this.selectionStart == "0") { - // replace the selection with str - var start_pos = this.selectionStart; - var end_pos = this.selectionEnd; - var scroll_top = this.scrollTop; - this.value = this.value.substring(0, start_pos)+str+this.value.substring(end_pos, this.value.length); - this.focus(); - this.selectionStart = start_pos+str.length; - this.selectionEnd = start_pos+str.length; - this.scrollTop = scroll_top; - } else { - // just add str to the end - this.value += str; - this.focus(); - } - }) - }, - - // remove the character in a textarea before the cursor position or de-indent - backspace_at_caret: function() { - // apply this function to all elements that match the selector - return this.each(function(i) { - // if text is selected, then just delete it - if (document.selection) { - this.focus(); - sel = document.selection.createRange(); - sel.text = ""; - this.focus(); - } else if (this.selectionStart || this.selectionStart == "0") { - // get the selection - var start_pos = this.selectionStart; - var end_pos = this.selectionEnd; - var scroll_top = this.scrollTop; - - // check if nothing is selected - if (start_pos == end_pos) { - // only backspace if we aren't at the beginning - if (start_pos > 0) { - // check if we are far enough that we might want to de-indent - if (start_pos > indent_str.length-1) { - // check if there is indentation right before the cursor - if (this.value.substring(start_pos-indent_str.length, start_pos) == indent_str) { - // delete the indentation - this.value = this.value.substring(0, start_pos-indent_str.length)+this.value.substring(end_pos, this.value.length); - this.selectionStart = start_pos-indent_str.length; - this.selectionEnd = start_pos-indent_str.length; - } else { - // just delete the character before the cursor - this.value = this.value.substring(0, start_pos-1)+this.value.substring(end_pos, this.value.length); - this.selectionStart = start_pos-1; - this.selectionEnd = start_pos-1; - } - } else { - // just delete the character before the cursor - this.value = this.value.substring(0, start_pos-1)+this.value.substring(end_pos, this.value.length); - this.selectionStart = start_pos-1; - this.selectionEnd = start_pos-1; - } - } - } else { - // just delete the selection - this.value = this.value.substring(0, start_pos)+this.value.substring(end_pos, this.value.length); - this.selectionStart = start_pos; - this.selectionEnd = start_pos; - } - - // focus the element and scroll it appropriately - this.focus(); - this.scrollTop = scroll_top; - } - }) - }, - - // insert a newline in a textarea at the cursor position and auto-indent - newline_at_caret: function() { - // apply this function to all elements that match the selector - return this.each(function(i) { - // determine the indentation for this line - var indent = ""; - if (this.selectionStart || this.selectionStart == "0") { - // determine the start of the indentation - var start_pos = this.selectionStart; - while (start_pos > 0) { - if (this.value[start_pos-1] == "\n") - break; - start_pos -= 1; - } - - // determine the end of the indentation - var end_pos = start_pos; - while (end_pos < this.value.length) { - if (this.value[end_pos] != " ") - break; - end_pos += 1; - } - - // get the indentation - indent = this.value.substring(start_pos, end_pos); - } - - // insert a newline and auto-indent - $(this).insert_at_caret("\n"+indent); - }) - }, -}); - -// escape html -function escape_html(str) { - // escape ampersands, angle brackets, tabs, and newlines - return str.replace(/\t/g, " ").replace(/&/g, "&").replace(//g, ">").replace(/\n/g, "
"); -} - -// indent and escape html -function indent_and_escape_html(str) { - // indent newlines to line up with the end of the julia prompt - return escape_html(str.replace(/\n/g, "\n ")); -} - -function add_html_to_terminal(data) { - // update the html - $("#terminal").append(data); - - // apply the color scheme to the new content - apply_color_scheme(); - - // reset the size of the input box - set_input_width(); - - // scroll to the new data - $("#terminal-form").prop("scrollTop", $("#terminal-form").prop("scrollHeight")); - - new_line = false; -} - -// add html to the terminal (preserving whitespace) -function add_to_terminal(data) { - // preserve whitespace with non-breaking spaces - var new_data = ""; - var tag_depth = 0; - for (var i = 0; i < data.length; i += 1) { - if (data[i] == "<") - tag_depth += 1; - if (data[i] == ">") - tag_depth -= 1; - if (tag_depth == 0 && i < data.length-1) { - if (data[i] == " " && data[i+1] == " ") - new_data += " "; - else - new_data += data[i]; - } else { - new_data += data[i]; - } - } - - add_html_to_terminal(new_data); - - // determine whether the last thing added was a newline - if (new_data.length >= 6) - new_line = (new_data.substr(new_data.length-6, 6) == "
"); -} - -// the first request -function init_session() { - // send a start message - outbox_queue.push([MSG_INPUT_GET_USER]); - outbox_queue.push([MSG_INPUT_REPLAY_HISTORY]); - process_outbox(); -} - -// check the server for data -function poll() { - // send a poll message - outbox_queue.push([MSG_INPUT_POLL]); - process_outbox(); -} - -// send the messages in the outbox -function process_outbox() { - // don't make new requests if we're waiting for old ones - if (!waiting_for_response) { - // don't send a request if there are no messages - if (outbox_queue.length > 0) { - // don't send any more requests while we're waiting for this one - waiting_for_response = true; - - // send the messages - $.post("/repl.scgi", {"request": $.toJSON(outbox_queue)}, callback, "json"); - } - - // we sent all the messages at once so clear the outbox - outbox_queue = []; - } -} - -// an array of message handlers -var message_handlers = []; - -message_handlers[MSG_OUTPUT_NULL] = function(msg) {}; // do nothing - -message_handlers[MSG_OUTPUT_READY] = function(msg) { - // remove the initializing message - $("#terminal").html(""); - - // enable input - $("#prompt").show(); - $("#terminal-input").removeAttr("disabled"); - $("#terminal-input").show(); - $("#terminal-input").focus(); - - // reset the size of the input box - set_input_width(); -}; - -message_handlers[MSG_OUTPUT_MESSAGE] = function(msg) { - // print the message - add_to_terminal(""+escape_html(msg[0])+"

"); -}; - -message_handlers[MSG_OUTPUT_OTHER] = function(msg) { - // just print the output - add_to_terminal(escape_html(msg[0])); -}; - -message_handlers[MSG_OUTPUT_FATAL_ERROR] = function(msg) { - // print the error message - add_to_terminal(""+escape_html(msg[0])+"

"); - - // stop processing new messages - dead = true; - inbox_queue = []; - outbox_queue = []; -}; - -message_handlers[MSG_OUTPUT_EVAL_INPUT] = function(msg) { - // check if this was from us - if (msg[0] == user_id) { - // get the input from form - var input = $("#terminal-input").val(); - - // input history - if (input.replace(/^\s+|\s+$/g, '') != "") - input_history.push(input); - if (input_history.length > input_history_size) - input_history = input_history.slice(input_history.length-input_history_size); - input_history_current = input_history.slice(0); - input_history_current.push(""); - input_history_id = input_history_current.length-1; - - // Save the changed values to localstorage - if (Modernizr.localstorage) { - localStorage.setItem("input_history", JSON.stringify(input_history)); - localStorage.setItem("input_history_current", JSON.stringify(input_history_current)); - } - - // clear the input field (it is disabled at this point) - $("#terminal-input").val(""); - - // hide the prompt until the result comes in - $("#prompt").hide(); - } - - // add the prompt and the input to the log - add_to_terminal(""+indent_and_escape_html(msg[1])+"> "+indent_and_escape_html(msg[2])+"
"); -} - -message_handlers[MSG_OUTPUT_EVAL_INCOMPLETE] = function(msg) { - // re-enable the input field - $("#terminal-input").removeAttr("disabled"); - - // focus the input field - $("#terminal-input").focus(); - - // add a newline for the user - $("#terminal-input").newline_at_caret(); -}; - -function enable_prompt() { - // show the prompt - $("#prompt").show(); - - // re-enable the input field - $("#terminal-input").removeAttr("disabled"); - - // focus the input field - $("#terminal-input").focus(); -} - -message_handlers[MSG_OUTPUT_EVAL_ERROR] = function(msg) { - // print the error message - add_to_terminal(""+escape_html(msg[1])+"

"); - - // check if this was from us - if (msg[0] == user_id) { - enable_prompt(); - } -}; - -message_handlers[MSG_OUTPUT_EVAL_RESULT] = function(msg) { - // print the result - if ($.trim(msg[1]) == "") - add_to_terminal("
"); - else - add_to_terminal(escape_html(msg[1])+"

"); - - if (msg[0] == user_id) { - enable_prompt(); - } -}; - -message_handlers[MSG_OUTPUT_HTML] = function(msg) { - add_html_to_terminal(msg[1]); - if (msg[0] == user_id) { - enable_prompt(); - } -} - -message_handlers[MSG_OUTPUT_GET_USER] = function(msg) { - // set the user name - user_name = indent_and_escape_html(msg[0]); - user_id = indent_and_escape_html(msg[1]); - $("#prompt").html(""+user_name+"> "); - apply_color_scheme(); -} - -var plotters = {}; - -plotters["line"] = function(plot) { - // local variables - var xpad = 0, - ypad = (plot.y_max-plot.y_min)*0.1, - x = d3.scale.linear().domain([plot.x_min - xpad, plot.x_max + xpad]).range([0, plot.w]), - y = d3.scale.linear().domain([plot.y_min - ypad, plot.y_max + ypad]).range([plot.h, 0]), - xticks = x.ticks(8), - yticks = y.ticks(8); - - // create an SVG canvas and a group to represent the plot area - var vis = d3.select("#terminal") - .append("svg") - .data([d3.zip(plot.x_data, plot.y_data)]) // coordinate pairs - .attr("width", plot.w+plot.p*2) - .attr("height", plot.h+plot.p*2) - .append("g") - .attr("transform", "translate("+String(plot.p)+","+String(plot.p)+")"); - - // vertical tics - var vrules = vis.selectAll("g.vrule") - .data(xticks) - .enter().append("g") - .attr("class", "vrule"); - - // horizontal tics - var hrules = vis.selectAll("g.hrule") - .data(yticks) - .enter().append("g") - .attr("class", "hrule"); - - // vertical lines - vrules.filter(function(d) { return (d != 0); }).append("line") - .attr("x1", x) - .attr("x2", x) - .attr("y1", 0) - .attr("y2", plot.h - 1); - - // horizontal lines - hrules.filter(function(d) { return (d != 0); }).append("line") - .attr("y1", y) - .attr("y2", y) - .attr("x1", 0) - .attr("x2", plot.w + 1); - - // x-axis labels - vrules.append("text") - .attr("x", x) - .attr("y", plot.h + 10) - .attr("dy", ".71em") - .attr("text-anchor", "middle") - .text(x.tickFormat(10)); - - // y-axis labels - hrules.append("text") - .attr("y", y) - .attr("x", -5) - .attr("dy", ".35em") - .attr("text-anchor", "end") - .text(y.tickFormat(10)); - - // y-axis - var vrules2 = vis.selectAll("g.vrule2") - .data(xticks) - .enter().append("g") - .attr("class", "vrule2"); - - // x-axis - var hrules2 = vis.selectAll("g.hrule2") - .data(yticks) - .enter().append("g") - .attr("class", "hrule2"); - - // y-axis line - vrules2.filter(function(d) { return (d == 0); }).append("line") - .attr("x1", x) - .attr("x2", x) - .attr("y1", 0) - .attr("y2", plot.h - 1); - - // x-axis line - hrules2.filter(function(d) { return (d == 0); }).append("line") - .attr("y1", y) - .attr("y2", y) - .attr("x1", 0) - .attr("x2", plot.w + 1); - - // actual plot curve - vis.append("path") - .attr("class", "line") - .attr("d", d3.svg.line() - .x(function(d) { return x(d[0]); }) - .y(function(d) { return y(d[1]); })); - - // newline - add_to_terminal("
"); - - // scroll to the new plot - $("#terminal-form").prop("scrollTop", $("#terminal-form").prop("scrollHeight")); -}; - -plotters["bar"] = function(plot) { - var data = d3.zip(plot.x_data, plot.y_data); // coordinate pairs - - // local variables - var x = d3.scale.linear().domain(d3.extent(plot.x_data)).range([0, plot.w]), - y = d3.scale.linear().domain([0, d3.max(plot.y_data)]).range([0, plot.h]), - xticks = x.ticks(8), - yticks = y.ticks(8); - - // create an SVG canvas and a group to represent the plot area - var vis = d3.select("#terminal") - .append("svg") - .data([data]) - .attr("width", plot.w+plot.p*2) - .attr("height", plot.h+plot.p*2) - .append("g") - .attr("transform", "translate("+String(plot.p)+","+String(plot.p)+")"); - - // horizontal ticks - var hrules = vis.selectAll("g.hrule") - .data(yticks) - .enter().append("g") - .attr("class", "hrule") - .attr("transform", function(d) { return "translate(0," + (plot.h-y(d)) + ")"; }); - - // horizontal lines - hrules.append("line") - .attr("x1", 0) - .attr("x2", plot.w); - - // y-axis labels - hrules.append("text") - .attr("x", -5) - .attr("dy", ".35em") - .attr("text-anchor", "end") - .text(y.tickFormat(10)); - - // x-axis rules container - var vrules = vis.selectAll("g.vrule") - .data(xticks) - .enter().append("g") - .attr("class", "vrule") - .attr("transform", function(d) { return "translate(" + (x(d)) + ",0)"; }); - - // x-axis labels - vrules.append("text") - .attr("y", plot.h + 20) - .attr("dx", "0") - .attr("text-anchor", "middle") - .text(x.tickFormat(10)); - - // Redfining domain/range to fit the bars within the width - x.domain([0, 1]).range([0, plot.w/data.length]); - - // actual plot curve - vis.selectAll("rect") - .data(data) - .enter().append("rect") - .attr("class", "rect") - .attr("x", function(d, i) { return x(i); }) - .attr("y", function(d) { return plot.h - y(d[1]); }) - .attr("width", (plot.w - plot.p*2) / data.length) - .attr("height", function(d) { return y(d[1]); }); - - // newline - add_to_terminal("
"); - - // scroll to the new plot - $("#terminal-form").prop("scrollTop", $("#terminal-form").prop("scrollHeight")); -}; - -message_handlers[MSG_OUTPUT_PLOT] = function(msg) { - var plottype = msg[0], - plot = { - "x_data": eval(msg[1]), - "y_data": eval(msg[2]), - "x_min": eval(msg[3]), - "x_max": eval(msg[4]), - "y_min": eval(msg[5]), - "y_max": eval(msg[6]) - }, - plotter = plotters[plottype]; - - // TODO: - // * calculate dynamically based on window size - // * update above calculation with window resize - // * allow user to resize - plot.w = 450; - plot.h = 275; - plot.p = 40; - - if (typeof plotter == "function") - plotter(plot); -}; - -// process the messages in the inbox -function process_inbox() { - // iterate through the messages - for (var id in inbox_queue) { - var msg = inbox_queue[id], - type = msg[0], msg = msg.slice(1), - handler = message_handlers[type]; - if (typeof handler == "function") - handler(msg); - if (dead) - break; - } - - // we handled all the messages so clear the inbox - inbox_queue = []; -} - -// called when the server has responded -function callback(data, textStatus, jqXHR) { - // if we are dead, don't keep polling the server - if (dead) - return; - - // allow sending new messages - waiting_for_response = false; - - // add the messages to the inbox - inbox_queue = inbox_queue.concat(data); - - // process the inbox - process_inbox(); - - // send any new messages - process_outbox(); - - // poll the server again shortly - setTimeout(poll, poll_interval); -} - -// called on page load -$(document).ready(function() { - // apply the autoresize plugin to the textarea - $("#terminal-input").autoResize({ animate: false, maxHeight: 1000, onAfterResize: function() { - setTimeout(function() { $("#terminal-form").prop("scrollTop", $("#terminal-form").prop("scrollHeight")); }, 100); - set_input_width(); - } }); - - // clear the textarea in case the browser decides to pre-populate it - $("#terminal-input").val(""); - - // set the width of the terminal - set_terminal_width(); - - // record the cursor position when the user clicks anywhere - var mouse_x, mouse_y; - $(window).mousedown(function(evt) { - mouse_x = evt.pageX; - mouse_y = evt.pageY; - }); - - // focus the terminal input when the user clicks on the terminal (but not drags) - $("#terminal-form").click(function(evt) { - if ((mouse_x-evt.pageX)*(mouse_x-evt.pageX)+(mouse_y == evt.pageY)*(mouse_y == evt.pageY) < 4) - $("#terminal-input").focus(); - }); - - // hook keyboard events for the input field - $("#terminal-input").keydown(function(evt) { - // determine which key was pressed - switch (evt.keyCode) { - case 8: - // user pressed the backspace key -- make sure the terminal input was enabled - if (!$("#terminal-input").attr("disabled")) { - // backspace - $("#terminal-input").backspace_at_caret(); - $("#terminal-form").prop("scrollTop", $("#terminal-form").prop("scrollHeight")); - } - return false; - - case 9: - // user pressed the tab key -- make sure the terminal input was enabled - if (!$("#terminal-input").attr("disabled")) { - // indent - $("#terminal-input").insert_at_caret(indent_str); - $("#terminal-form").prop("scrollTop", $("#terminal-form").prop("scrollHeight")); - } - return false; - - case 38: - // user pressed the up key -- make sure the terminal input was enabled - if (!$("#terminal-input").attr("disabled")) { - // terminal input history - input_history_current[input_history_id] = $("#terminal-input").val(); - input_history_id -= 1; - if (input_history_id < 0) - input_history_id = 0; - - // Save values to localstorage - if (Modernizr.localstorage) { - localStorage.setItem("input_history_current", JSON.stringify(input_history_current)); - } - - $("#terminal-input").val(input_history_current[input_history_id]); - $("#terminal-form").prop("scrollTop", $("#terminal-form").prop("scrollHeight")); - } - return false; - - case 40: - // user pressed the down key -- make sure the terminal input was enabled - if (!$("#terminal-input").attr("disabled")) { - // terminal input history - input_history_current[input_history_id] = $("#terminal-input").val(); - input_history_id += 1; - if (input_history_id > input_history_current.length-1) - input_history_id = input_history_current.length-1; - - // Save values to localstorage - if (Modernizr.localstorage) { - localStorage.setItem("input_history_current", JSON.stringify(input_history_current)); - } - - $("#terminal-input").val(input_history_current[input_history_id]); - $("#terminal-form").prop("scrollTop", $("#terminal-form").prop("scrollHeight")); - } - return false; - - case 13: - // user pressed the enter key -- make sure the terminal input was enabled - if (!$("#terminal-input").attr("disabled")) { - // disable the terminal input - $("#terminal-input").attr("disabled", "disabled"); - - // get the input - var input = $("#terminal-input").val(); - - // send the input to the server via AJAX - outbox_queue.push([MSG_INPUT_EVAL, user_name, user_id, input]); - process_outbox(); - } - - // prevent the form from actually submitting - return false; - - case 67: - // C key pressed - if (evt.ctrlKey) { - // ctrl-c to cancel a command - - add_to_terminal("Process Killed

"); - - // show the prompt - $("#prompt").show(); - - // re-enable the input field - $("#terminal-input").removeAttr("disabled"); - - // focus the input field - $("#terminal-input").focus(); - - waiting_for_message = false; - } - - //return false; - } - }); - - // scroll to the input field - $("#terminal-form").prop("scrollTop", $("#terminal-form").prop("scrollHeight")); - - // start polling the server - init_session(); -}); - -})(); diff --git a/ui/website/repl.scgi b/ui/website/repl.scgi deleted file mode 100644 index f7ab2b3b255f2..0000000000000 --- a/ui/website/repl.scgi +++ /dev/null @@ -1 +0,0 @@ -This file exists so Lighttpd doesn't return a 404 for this request. A request to this resource is actually handled by the SCGI server. diff --git a/ui/website/reset.css b/ui/website/reset.css deleted file mode 100755 index af944401f75ea..0000000000000 --- a/ui/website/reset.css +++ /dev/null @@ -1,48 +0,0 @@ -/* http://meyerweb.com/eric/tools/css/reset/ - v2.0 | 20110126 - License: none (public domain) -*/ - -html, body, div, span, applet, object, iframe, -h1, h2, h3, h4, h5, h6, p, blockquote, pre, -a, abbr, acronym, address, big, cite, code, -del, dfn, em, img, ins, kbd, q, s, samp, -small, strike, strong, sub, sup, tt, var, -b, u, i, center, -dl, dt, dd, ol, ul, li, -fieldset, form, label, legend, -table, caption, tbody, tfoot, thead, tr, th, td, -article, aside, canvas, details, embed, -figure, figcaption, footer, header, hgroup, -menu, nav, output, ruby, section, summary, -time, mark, audio, video { - margin: 0; - padding: 0; - border: 0; - font-size: 100%; - font: inherit; - vertical-align: baseline; -} -/* HTML5 display-role reset for older browsers */ -article, aside, details, figcaption, figure, -footer, header, hgroup, menu, nav, section { - display: block; -} -body { - line-height: 1; -} -ol, ul { - list-style: none; -} -blockquote, q { - quotes: none; -} -blockquote:before, blockquote:after, -q:before, q:after { - content: ''; - content: none; -} -table { - border-collapse: collapse; - border-spacing: 0; -} \ No newline at end of file