├── .gitignore
├── .travis.yml
├── CMakeLists.txt
├── COPYING
├── LICENSE
├── README.MD
├── config.m4
├── config.w32
├── docs
├── index.md
├── internals
│ ├── carray_api.md
│ └── explanation.md
└── routines
│ ├── arithmetic.md
│ ├── carray_object.md
│ ├── decompositions.md
│ ├── dimensions.md
│ ├── distributions.md
│ ├── eigenvalues.md
│ ├── equations_and_inverse.md
│ ├── exponents_loga.md
│ ├── hyperbolic.md
│ ├── indexing.md
│ ├── ma_norms.md
│ ├── ma_products.md
│ ├── numerical_ranges.md
│ ├── ones_and_zeros.md
│ ├── random.md
│ ├── rearranging.md
│ ├── rounding.md
│ ├── searching.md
│ ├── sorting.md
│ ├── statistics.md
│ ├── sum_products_and_diff.md
│ ├── transpose.md
│ └── trigonometric.md
├── kernel
├── alloc.c
├── alloc.h
├── arraytypes.c
├── arraytypes.h
├── assign.c
├── assign.h
├── assign_scalar.c
├── assign_scalar.h
├── buffer.c
├── buffer.h
├── calculation.c
├── calculation.h
├── carray.c
├── carray.h
├── casting.c
├── casting.h
├── clip.c
├── clip.h
├── common
│ ├── ca_extint128.h
│ ├── cblas_funcs.c
│ ├── cblas_funcs.h
│ ├── clblas_funcs.c
│ ├── clblas_funcs.h
│ ├── common.c
│ ├── common.h
│ ├── compare.c
│ ├── compare.h
│ ├── exceptions.c
│ ├── exceptions.h
│ ├── matmul.c
│ ├── matmul.h
│ ├── mem_overlap.c
│ ├── mem_overlap.h
│ ├── partition.h
│ ├── sort.c
│ ├── sort.h
│ ├── strided_loops.c
│ └── strided_loops.h
├── conversion_utils.c
├── conversion_utils.h
├── convert.c
├── convert.h
├── convert_datatype.c
├── convert_datatype.h
├── convert_type.c
├── convert_type.h
├── ctors.c
├── ctors.h
├── descriptor.c
├── descriptor.h
├── dtype_transfer.c
├── dtype_transfer.h
├── exp_logs.c
├── exp_logs.h
├── flagsobject.c
├── flagsobject.h
├── getset.c
├── getset.h
├── gpu.c
├── gpu.h
├── include
│ └── cpu.h
├── interfaces
│ ├── rubix.c
│ └── rubix.h
├── item_selection.c
├── item_selection.h
├── iterators.c
├── iterators.h
├── join.c
├── join.h
├── linalg.c
├── linalg.h
├── matlib.c
├── matlib.h
├── number.c
├── number.h
├── random.c
├── random.h
├── random
│ ├── distributions.c
│ └── distributions.h
├── range.c
├── range.h
├── round.c
├── round.h
├── scalar.c
├── scalar.h
├── search.c
├── search.h
├── shape.c
├── shape.h
├── simd.c
├── simd.h
├── statistics.c
├── statistics.h
├── storage.c
├── storage.h
├── trigonometric.c
└── trigonometric.h
├── mkdocs.yml
├── phpsci.c
├── phpsci.h
├── tests
├── arithmetics
│ ├── arithmetics_dd_1d_add.phpt
│ ├── arithmetics_di_1d_add.phpt
│ ├── arithmetics_id_1d_add.phpt
│ ├── arithmetics_ii_1d_add.phpt
│ ├── arithmetics_ii_2d_1d_add.phpt
│ └── arithmetics_ii_2d_1d_add_broadcastexception.phpt
└── initializers
│ ├── linspace.basicadd.phpt
│ └── linspace.basicdump.phpt
└── travis
└── compile.sh
/.gitignore:
--------------------------------------------------------------------------------
1 | # TEST
2 | test.php
3 |
4 | # EDITOR
5 | .idea
6 | .libs
7 |
8 | # COMPILER
9 | .lo
10 | autom4te.cache
11 | *.lo
12 | .o
13 | .la
14 | *.la
15 | *.o
16 | ./modules/
17 | ./include/
18 | ./build/
19 | config.h
20 | config.h.in
21 | Makefile
22 | config.log
23 | config.nice
24 | config.status
25 | configure
26 | configure.ac
27 | libtool
28 | Makefile
29 | Makefile.fragments
30 | Makefile.objects
31 | run-tests.php
32 | vgcore.*
33 | config.h*
34 | build*
35 | *.so
36 | *.gch
37 |
38 |
39 | # OS
40 | .DS_Store
41 | .DS_Store?
42 | ._*
43 | .Spotlight-V100
44 | .Trashes
45 | Icon?
46 | ehthumbs.db
47 | Thumbs.db
48 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 | sudo: false
3 |
4 | addons:
5 | apt:
6 | packages:
7 | - libopenblas-dev
8 | - liblapacke-dev
9 |
10 | php:
11 | - 7.0
12 | - 7.1
13 | - 7.2
14 | - 7.3
15 | - 7.4
16 | - nightly
17 |
18 | matrix:
19 | allow_failures:
20 | - php: nightly
21 |
22 | cache:
23 | apt: true
24 | ccache: true
25 |
26 | before_script:
27 | - ccache --version
28 | - ccache --zero-stats
29 | - export USE_CCACHE=1
30 | - phpize
31 | - ./configure
32 | - make
33 | - make install
34 | - echo "extension=carray.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
35 |
36 | script:
37 | - REPORT_EXIT_STATUS=1 php ./run-tests.php -P -q --show-diff
38 |
39 | after_success:
40 | - ccache --show-stats
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.8)
2 | project(carray C)
3 |
4 | add_compile_definitions(HAVE_SKELETON)
5 |
6 | set(SOURCE_FILES phpsci phpsci.c
7 | kernel/interfaces/rubix.c
8 | kernel/common/clblas_funcs.c
9 | kernel/common/exceptions.c
10 | )
11 |
12 | execute_process (
13 | COMMAND php-config --include-dir
14 | OUTPUT_VARIABLE PHP_SOURCE
15 | )
16 | string(REGEX REPLACE "\n$" "" PHP_SOURCE "${PHP_SOURCE}")
17 |
18 | message("Using source directory: ${PHP_SOURCE}")
19 |
20 | include_directories(${PHP_SOURCE})
21 | include_directories(${PHP_SOURCE}/main)
22 | include_directories(${PHP_SOURCE}/Zend)
23 | include_directories(${PHP_SOURCE}/TSRM)
24 | include_directories(${PROJECT_SOURCE_DIR})
25 |
26 | add_custom_target(configure
27 | COMMAND phpize && ./configure
28 | DEPENDS ${SOURCE_FILES}
29 | WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
30 |
31 | add_library(___ EXCLUDE_FROM_ALL ${SOURCE_FILES})
--------------------------------------------------------------------------------
/COPYING:
--------------------------------------------------------------------------------
1 | Copyright © 2005-2019, NumPy Developers.
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
5 | following conditions are met:
6 |
7 | Redistributions of source code must retain the above copyright notice, this list of conditions
8 | and the following disclaimer.
9 |
10 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
11 | following disclaimer in the documentation and/or other materials provided with the distribution.
12 |
13 | Neither the name of the NumPy Developers nor the names of any contributors may be used to endorse or promote
14 | products derived from this software without specific prior written permission.
15 |
16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
17 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
21 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
22 | USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2019 - Henrique Borba
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.MD:
--------------------------------------------------------------------------------
1 |
2 |
3 | # PHPSci CArray Extension
4 |
5 | PHPSci CArray is a high-performance scientific computing library for PHP developed in C and based on the original NumPy code. CArrays offer a solid alternative to PHP arrays as well as compatibility with codes developed using NumPy.
6 |
7 | - High Performance Indexing and Data Access
8 | - Low memory footprint compared to PHP Arrays
9 | - Efficient shape, initializers, linear algebra and mathematical methods.
10 | - Out of the box GPU integration (Cuda)
11 |
12 | --------------------------------------------------------------------------------
13 |
14 | ## Installing
15 |
16 | It's really easy to compile this extension using Linux environments.
17 |
18 | ### Requirements
19 |
20 | - php-devel (php-dev)
21 | - PHP 7.2
22 | - OpenBLAS
23 |
24 | ### Optional
25 |
26 | - cuBLAS (For GPU Integration)
27 |
28 | ### Ubuntu 20.04
29 |
30 | ```commandline
31 | $ sudo add-apt-repository -y ppa:ondrej/php
32 | $ sudo apt-get update
33 | $ sudo apt-get install libopenblas-dev libatlas-base-dev liblapacke-dev php7.4-dev
34 | $ phpize
35 | $ ./configure
36 | $ make test
37 | $ sudo make install
38 | $ echo 'extension=carray' | sudo tee /etc/php/7.4/cli/conf.d/20-carray.ini
39 | $ echo 'extension=carray' | sudo tee /etc/php/7.4/fpm/conf.d/20-carray.ini
40 | $ echo 'extension=carray' | sudo tee /etc/php/7.4/cgi/conf.d/20-carray.ini
41 | $ echo 'extension=carray' | sudo tee /etc/php/7.4/apache2/conf.d/20-carray.ini
42 | ```
43 |
44 | ### Ubuntu 16.04
45 |
46 | ```commandline
47 | $ add-apt-repository -y ppa:ondrej/php
48 | $ apt-get update
49 | $ apt-get install libblas-dev libatlas-base-dev liblapacke-dev php7.2-dev
50 | $ phpize
51 | $ ./configure
52 | $ make test
53 | $ make install
54 | ```
55 |
56 | ### Ubuntu 14.04
57 |
58 | ```commandline
59 | $ add-apt-repository -y ppa:ondrej/php
60 | $ apt-get update
61 | $ apt-get install libopenblas-dev liblapacke-dev php7.2-dev
62 | $ phpize
63 | $ ./configure
64 | $ make test
65 | $ make install
66 | ```
67 |
68 | > Don't forget to check if the extension is enabled in your php.ini file.
69 |
70 | > **Apache/NGINX Users:** Don't forget to restart your services.
71 |
--------------------------------------------------------------------------------
/config.m4:
--------------------------------------------------------------------------------
1 | PHP_ARG_WITH(carray, whether to enable CArray computing library,
2 | [ --with-carray Disable CArray computing library], yes)
3 |
4 | PHP_ARG_ENABLE(avx2, whether to enable AVX2 support,
5 | [ --enable-avx2 whether to enable AVX2 support], no, no)
6 |
7 | PHP_ARG_ENABLE(opencl, whether to enable OpenCL support,
8 | [ --enable-opencl whether to enable OpenCL support], no, no)
9 |
10 | if test "$PHP_CARRAY" != "no"; then
11 | AC_DEFINE([HAVE_CARRAY],1 ,[whether to enable CArray computing library])
12 |
13 | AC_CHECK_HEADERS(
14 | [/opt/OpenBLAS/include/lapacke.h],
15 | [
16 | PHP_ADD_INCLUDE(/opt/OpenBLAS/include/)
17 | ],
18 | ,
19 | [[#include "/opt/OpenBLAS/include/lapacke.h"]]
20 | )
21 | AC_CHECK_HEADERS(
22 | [/usr/include/openblas/lapacke.h],
23 | [
24 | PHP_ADD_INCLUDE(/usr/include/openblas/)
25 | ],
26 | ,
27 | [[#include "/usr/include/openblas/lapacke.h"]]
28 | )
29 | AC_CHECK_HEADERS(
30 | [/usr/include/lapacke.h],
31 | [
32 | PHP_ADD_INCLUDE(/usr/include/)
33 | ],
34 | ,
35 | [[#include "/usr/include/lapacke.h"]]
36 | )
37 |
38 |
39 | AC_CHECK_HEADERS(
40 | [/opt/OpenBLAS/include/cblas.h],
41 | [
42 | PHP_ADD_INCLUDE(/opt/OpenBLAS/include/)
43 | ],
44 | ,
45 | [[#include "/opt/OpenBLAS/include/cblas.h"]]
46 | )
47 | AC_CHECK_HEADERS(
48 | [/usr/include/cblas.h],
49 | [
50 | PHP_ADD_INCLUDE(/usr/include/)
51 | ],
52 | ,
53 | [[#include "/usr/include/cblas.h"]]
54 | )
55 | AC_CHECK_HEADERS(
56 | [/usr/include/atlas/cblas.h],
57 | [
58 | PHP_ADD_INCLUDE(/usr/include/atlas/)
59 | ],
60 | ,
61 | [[#include "/usr/include/atlas/cblas.h"]]
62 | )
63 | AC_CHECK_HEADERS(
64 | [/usr/include/openblas/cblas.h],
65 | [
66 | PHP_ADD_INCLUDE(/usr/include/openblas/)
67 | ],
68 | ,
69 | [[#include "/usr/include/openblas/cblas.h"]]
70 | )
71 |
72 |
73 | AC_CHECK_HEADERS(
74 | [/usr/include/clBLAS.h],
75 | [
76 | PHP_ADD_INCLUDE(/usr/include/)
77 | ],
78 | ,
79 | [[#include "/usr/include/clBLAS.h"]]
80 | )
81 |
82 | if test "$PHP_OPENCL" != "no"; then
83 | PHP_CHECK_LIBRARY(clBLAS,clblasSgemm,
84 | [
85 | PHP_ADD_LIBRARY(clBLAS,,CARRAY_SHARED_LIBADD)
86 | AC_DEFINE(HAVE_CLBLAS,1,[Have CLBLAS support])
87 |
88 | PHP_CHECK_LIBRARY(OpenCL,clGetPlatformIDs,
89 | [
90 | PHP_ADD_LIBRARY(OpenCL,,CARRAY_SHARED_LIBADD)
91 | AC_DEFINE(HAVE_OPENCL,1,[Have OpenCL support])
92 | AC_MSG_RESULT([OpenCL detected ])
93 | ],[
94 | AC_MSG_WARN([OpenCL not detected (OpenCL BLAS not available).])
95 | ],[
96 | -lOpenCL
97 | ])
98 | ],[
99 | AC_MSG_RESULT([clBLAS not detected (OpenCL BLAS not available).])
100 | ],[
101 | -LclBLAS
102 | ])
103 | fi
104 |
105 | if test "$PHP_AVX2" != "no"; then
106 | AC_CHECK_HEADER([immintrin.h],
107 | [
108 | AC_DEFINE(CARRAY_HAVE_AVX2,1,[Have AV2/SSE support])
109 | AC_MSG_RESULT([AVX2/SSE detected ])
110 | CFLAGS+=" -mavx2 "
111 | ],[
112 | AC_DEFINE(CARRAY_HAVE_AVX2,0,[Have AV2/SSE support])
113 | AC_MSG_RESULT([AVX2/SSE not found ])
114 | ], [
115 |
116 | ]
117 | )
118 | fi
119 |
120 | PHP_CHECK_LIBRARY(cblas,cblas_sdot,
121 | [
122 | AC_DEFINE(HAVE_CBLAS,1,[ ])
123 | AC_DEFINE(HAVE_BLAS,1,[ ])
124 | PHP_ADD_LIBRARY(cblas,,CARRAY_SHARED_LIBADD)
125 | AC_MSG_RESULT([CBlas detected ])
126 | ],[
127 | PHP_CHECK_LIBRARY(openblas,cblas_sdot,
128 | [
129 | PHP_ADD_LIBRARY(openblas,,CARRAY_SHARED_LIBADD)
130 | AC_MSG_RESULT([OpenBLAS detected ])
131 | AC_DEFINE(HAVE_BLAS,1,[ ])
132 | ],[
133 | AC_MSG_RESULT([wrong openblas/blas version or library not found.])
134 | ],[
135 | -lopenblas
136 | ])
137 | ],[
138 | -lcblas
139 | ])
140 |
141 | PHP_CHECK_LIBRARY(lapacke,LAPACKE_sgetrf,
142 | [
143 | AC_DEFINE(HAVE_LAPACKE,1,[ ])
144 | PHP_ADD_LIBRARY(lapacke,,CARRAY_SHARED_LIBADD)
145 | ],[
146 | AC_MSG_RESULT([wrong lapacke version or library not found])
147 | ],[
148 | -llapacke
149 | ])
150 |
151 | PHP_CHECK_LIBRARY(omp,omp_get_num_threads,
152 | [
153 | AC_DEFINE(HAVE_OMP,1,[ ])
154 | AC_MSG_RESULT([OpenMP found])
155 | PHP_ADD_LIBRARY(omp,,CARRAY_SHARED_LIBADD)
156 | ],[
157 | AC_MSG_RESULT([OpenMP not found])
158 | ],[
159 | -fopenmp
160 | ])
161 |
162 | PHP_NEW_EXTENSION(carray,
163 | phpsci.c \
164 | kernel/alloc.c \
165 | kernel/carray.c \
166 | kernel/iterators.c \
167 | kernel/flagsobject.c \
168 | kernel/assign.c \
169 | kernel/convert.c \
170 | kernel/casting.c \
171 | kernel/linalg.c \
172 | kernel/calculation.c \
173 | kernel/shape.c \
174 | kernel/common/common.c \
175 | kernel/common/cblas_funcs.c \
176 | kernel/common/clblas_funcs.c \
177 | kernel/common/mem_overlap.c \
178 | kernel/number.c \
179 | kernel/convert_type.c \
180 | kernel/trigonometric.c \
181 | kernel/matlib.c \
182 | kernel/statistics.c \
183 | kernel/arraytypes.c \
184 | kernel/join.c \
185 | kernel/ctors.c \
186 | kernel/simd.c \
187 | kernel/scalar.c \
188 | kernel/round.c \
189 | kernel/getset.c \
190 | kernel/common/strided_loops.c \
191 | kernel/convert_datatype.c \
192 | kernel/dtype_transfer.c \
193 | kernel/assign_scalar.c \
194 | kernel/gpu.c \
195 | kernel/common/exceptions.c \
196 | kernel/item_selection.c \
197 | kernel/clip.c \
198 | kernel/search.c \
199 | kernel/common/sort.c \
200 | kernel/interfaces/rubix.c \
201 | kernel/common/compare.c \
202 | kernel/exp_logs.c \
203 | kernel/random.c \
204 | kernel/storage.c \
205 | kernel/range.c \
206 | kernel/random/distributions.c \
207 | kernel/conversion_utils.c \
208 | kernel/buffer.c ,
209 | $ext_shared)
210 | PHP_INSTALL_HEADERS([ext/carray], [phpsci.h, kernel/carray.h, kernel/types.h, kernel/buffer.h])
211 | PHP_SUBST(CARRAY_SHARED_LIBADD)
212 | fi
213 |
--------------------------------------------------------------------------------
/config.w32:
--------------------------------------------------------------------------------
1 | ARG_ENABLE("carray", "enable carray", "no");
2 |
3 |
4 | if (PHP_CARRAY != "no") {
5 | if (!CHECK_LIB("libopenblas_a.lib", "carray", PHP_PHP_BUILD + "\\libs")) {
6 | ERROR("Unable to find libopenblas.lib");
7 | }
8 | if (CHECK_LIB("libopenblas_a.lib", "carray", PHP_PHP_BUILD + "\\libs") &&
9 | CHECK_HEADER_ADD_INCLUDE("cblas.h", "CFLAGS_OPENBLAS", PHP_PHP_BUILD + "\\include") &&
10 | CHECK_HEADER_ADD_INCLUDE("lapacke.h", "CFLAGS_LAPACKE", PHP_PHP_BUILD + "\\include")) {
11 | EXTENSION("carray", "phpsci.c", PHP_CARRAY_SHARED, "-I"+configure_module_dirname);
12 | ADD_SOURCES(configure_module_dirname + "/kernel",
13 | "exceptions.c"
14 | , "carray");
15 | ADD_SOURCES(configure_module_dirname + "/kernel/carray",
16 | "carray.c tuple.c"
17 | , "carray");
18 | ADD_SOURCES(configure_module_dirname + "/kernel/carray/utils",
19 | "carray_printer.c"
20 | , "carray");
21 | ADD_SOURCES(configure_module_dirname + "/kernel/memory_pointer",
22 | "memory_pointer.c utils.c"
23 | , "carray");
24 | ADD_SOURCES(configure_module_dirname + "/kernel/buffer",
25 | "memory_manager.c"
26 | , "carray");
27 | ADD_SOURCES(configure_module_dirname + "/kernel/php",
28 | "php_array.c"
29 | , "carray");
30 | ADD_SOURCES(configure_module_dirname + "/operations",
31 | "initializers.c linalg.c ranges.c basic_operations.c random.c arithmetic.c exponents.c logarithms.c trigonometric.c hyperbolic.c transformations.c magic_properties.c"
32 | , "carray");
33 | ADD_SOURCES(configure_module_dirname + "/operations/linalg",
34 | "norms.c others.c eigenvalues.c equations.c"
35 | , "carray");
36 |
37 | } else {
38 | ERROR( "OpenBlas not found! " );
39 | }
40 |
41 | }
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | # PHPSci CArray Extension
2 |
3 |
4 |
5 |
6 |
7 | PHPSci CArray is a high-performance scientific computing library for PHP developed in C and based on the original NumPy code. CArrays offer a solid alternative to PHP arrays as well as compatibility with codes developed using NumPy.
8 |
9 | - High Performance Indexing and Data Access
10 | - Low memory footprint compared to PHP Arrays
11 | - Efficient shape, initializers, linear algebra and mathematical methods.
12 | - Out of the box GPU integration (Cuda)
13 |
14 | ---
15 |
16 | ## Installing
17 |
18 | It's really easy to compile this extension using Linux environments.
19 |
20 | #### Requirements
21 |
22 | - php-devel (php-dev)
23 | - PHP 7.2
24 | - OpenBLAS
25 |
26 | #### Optional
27 | - cuBLAS (For GPU Integration)
28 |
29 | #### Ubuntu 16.04
30 | ```commandline
31 | $ add-apt-repository -y ppa:ondrej/php
32 | $ apt-get update
33 | $ apt-get install libblas-dev libatlas-base-dev php7.2-dev
34 | $ phpize
35 | $ ./configure
36 | $ make test
37 | $ make install
38 | ```
39 | #### Ubuntu 14.04
40 | ```commandline
41 | $ add-apt-repository -y ppa:ondrej/php
42 | $ apt-get update
43 | $ apt-get install libopenblas-dev liblapacke-dev php7.2-dev
44 | $ phpize
45 | $ ./configure
46 | $ make test
47 | $ make install
48 | ```
49 |
50 | > Don't forget to check if the extension is enabled in your php.ini file.
51 |
52 | > **Apache/NGINX Users:** Don't forget to restart your services.
53 |
--------------------------------------------------------------------------------
/docs/internals/carray_api.md:
--------------------------------------------------------------------------------
1 | # CArray Internals C Reference
2 |
3 | ## Memory Stack
4 |
5 | The `MemoryStack` struct is a global buffer containing a set of `CArray` pointers. The global buffer
6 | can be accessed calling `PHPSCI_MAIN_MEM_STACK`.
7 |
8 | ```C
9 | struct MemoryStack {
10 | CArray * buffer;
11 | int size;
12 | int capacity;
13 | size_t bsize;
14 | } MemoryStack;
15 | ```
16 |
17 | > #### `CArray *` MemoryStack.buffer
18 | > Dynamic allocated buffer containing all instances of **CArray** during runtime.
19 |
20 | > #### `int` MemoryStack.size
21 | > The number of CArray instances stored within the buffer.
22 |
23 | > #### `int` MemoryStack.capacity
24 | > The maximum capacity of the buffer. When **size** is equal **capacity** the buffer will be reallocated.
25 |
26 | > #### `size_t` MemoryStack.bsize
27 | > The current amount of bytes allocated within **buffer**.
28 |
29 | ## Memory Pointer
30 |
31 | The PHP interpreter performs operations using the MemoryPointer structure. This object contains the
32 | necessary information to relate the current PHP `zval` object with an instance of `CArray`.
33 |
34 | ```C
35 | typedef struct MemoryPointer {
36 | int uuid;
37 | } MemoryPointer;
38 | ```
39 |
40 | > #### `int` MemoryPointer.uuid
41 | > Contains the `uuid` of the related CArray instance within the buffer. Ex: If `uuid`is 0, the CArray instance allocated within `MemoryStack.buffer[0]` is used.
42 |
43 | ## CArray Structure
44 |
45 | The `CArray` object contains all information required for our array. It keep track of the data buffer, and
46 | other array properties like strides, dimensions and so on. All instances of `CArray` within PHP points
47 | to this structure.
48 |
49 | ```C
50 | struct CArray {
51 | int * strides;
52 | int * dimensions;
53 | int ndim;
54 | char * data;
55 | CArray * base;
56 | int flags;
57 | CArrayDescriptor * descriptor;
58 | int refcount;
59 | };
60 | ```
61 |
62 | > #### `int *` CArray.strides
63 | > An vector of integers containing the amount of bytes that must be skipped to get to the next element of that dimension.
64 |
65 | > #### `int *` CArray.dimensions
66 | > An vector of integers containing the amount of elements within each dimension. This could be seen as the shape of this array.
67 |
68 | > #### `int` CArray.ndim
69 | > Integer describing the number of dimensions.
70 |
71 | > #### `char *` CArray.data
72 | > The pointer to the first element of this array
73 |
74 | > #### `CArray *` CArray.base
75 | > Points to the CArray containing the original data. This is useful when one CArray shares the same data
76 | with other (CArray Views).
77 |
78 | > #### `int` CArray.flags
79 | > Some properties are stored as flags. For example, if one CArray contains data from other CArray, them it won't have `CARRAY_ARRAY_OWNDATA` flag.
80 |
81 | > #### `CArrayDescriptor *` CArray.descriptor
82 | > Describes the memory layout and data properties of the CArray. One descriptor may be shared with multiples CArrays.
83 |
84 | > #### `int` CArray.refcount
85 | > CArray reference count. The reference count prevents PHP Gargage Collector from free shared data buffer across different CArray objects.
86 |
87 |
88 | ### CArrayDescriptor
89 | This structure describes the CArray memory layout and data type. CArrayDescriptor can be used for
90 | CArray initialization.
91 |
92 | ```C
93 | typedef struct CArrayDescriptor {
94 | char type; // b = boolean, d = double, i = signer integer, u = unsigned integer, f = floating point, c = char
95 | int flags; // Data related flags
96 | int type_num; // 0 = boolean, 1 = double, 2 = signed integer, 3 = unsigned integer, 4 = floating point, 5 = char
97 | int elsize; // Datatype size
98 | int numElements; // Number of elements
99 | int alignment; // Alignment Information
100 | int refcount;
101 | } CArrayDescriptor;
102 | ```
103 |
104 | ## Creating CArrays
105 |
106 |
107 | #### `CArray *` CArray_NewFromDescr_int
108 | ```C
109 | CArray * CArray_NewFromDescr_int(CArray * self, CArrayDescriptor *descr, int nd, int *dims, int *strides, void *data, int flags, CArray *base, int zeroed, int allow_emptystring);
110 | ```
111 | #### `CArray *` CArray_NewLikeArray
112 | ```C
113 | CArray * CArray_NewLikeArray(CArray *prototype, CARRAY_ORDER order, CArrayDescriptor *dtype, int subok);
114 | ```
115 |
116 | ## CArray Iterators
--------------------------------------------------------------------------------
/docs/internals/explanation.md:
--------------------------------------------------------------------------------
1 | # CArray Internals Explained
2 |
3 | ## Memory Layout
4 |
5 | CArrays are contiguous C arrays direct accessed and stored by the PHP interpreter.
6 |
7 | ```PHP
8 | $array_1d = new CArray([2, 3, 4, 5, 6, 7]);
9 | $array_2d = new CArray([[2, 3], [4, 5], [6, 7]]);
10 | $array_3d = new CArray([[[2, 3], [4, 5], [6, 7]]]);
11 | ```
12 |
13 | In the example above, we allocated 3 `CArrays` with the following shapes `[6]`, `[3, 2]` and `[1, 3, 2]`. As all CArrays are contiguous allocated, the C memory layout for all the CArrays above is the same:
14 |
15 | ```C
16 | int * buffer = {2, 3, 4, 5, 6, 7}
17 | ```
18 |
19 | The extension only knows where to look for your values because it has the dimensions and strides information for each CArray above. This is specially fast if we want to change our CArray shapes
20 | without loop (iterate) over the values.
21 |
22 | ## Data Access
23 |
24 | CArrays are internaly accessed using strides. The strides gives the amount of bytes to jump within
25 | our buffer to find next value for the Nth-dimension.
26 |
27 | ```PHP
28 | $array = new CArray([[[2, 3], [4, 5], [6, 7]], [[2, 3], [4, 5], [6, 7]]]);
29 | ```
30 |
31 | The shape for this array is `[2, 3, 2]` and the type is `int`. Considering `int` as a 4 bytes type
32 | we have the following generated strides vector: `[24, 8 ,4]`. So for each value of the first dimension we jump 24 bytes, the second 2D matrix within this 3D tensor starts at index 6 `(24 bytes / 4 bytes)`.
33 |
34 | ```C
35 | int * buffer = {2, 3, 4, 5, 6, 7, -> 2, 3, 4, 5, 6, 7}
36 | ```
37 |
38 | We jump two more indices `8 bytes / 4 bytes` so we get to the second row of the second internal matrice `[1, 1, 0]`
39 |
40 | ```C
41 | int * buffer = {2, 3, 4, 5, 6, 7, 2, 3, -> 4, 5, 6, 7}
42 | ```
43 |
44 |
--------------------------------------------------------------------------------
/docs/routines/arithmetic.md:
--------------------------------------------------------------------------------
1 | # Arithmetic Routines
2 |
3 | ---
4 |
5 | ## add
6 | ```php
7 | public static add($x1, $x2) : CArray
8 | ```
9 | > Add arguments element-wise.
10 |
11 | ##### Parameters
12 |
13 | `CArray|Array` **$x1** **$x2** Input arrays.
14 |
15 | ##### Returns
16 |
17 | `CArray` The sum of `$x1` and `$x2`, element-wise.
18 |
19 | ##### Examples
20 |
21 | **Example 1**
22 | ```php
23 | $x1 = CArray::arange(9.0);
24 | $x1 = CArray::reshape($x1, [3, 3]);
25 | $x2 = CArray::arange(3.0);
26 |
27 | echo CArray::add($x1, $x2);
28 | ```
29 | ```
30 | [[ 0 2 4 ]
31 | [ 3 5 7 ]
32 | [ 6 8 10 ]]
33 | ```
34 |
35 | **Example 2**
36 | ```php
37 | $a = new CArray([[1, 2], [3, 4]]);
38 | $b = new CArray([[5, 6], [7, 8]]);
39 |
40 | $c = $a + $b; // Same as CArray::add
41 |
42 | echo $c;
43 | ```
44 | ```
45 | [[ 6 8 ]
46 | [ 10 12 ]]
47 | ```
48 |
49 | ---
50 |
51 | ## subtract
52 | ```php
53 | public static subtract($x1, $x2) : CArray
54 | ```
55 | > Subtract arguments element-wise.
56 |
57 | ##### Parameters
58 |
59 | `CArray|Array` **$x1** **$x2** Input arrays.
60 |
61 | ##### Returns
62 |
63 | `CArray` The difference of `$x1` and `$x2`, element-wise.
64 |
65 | ##### Examples
66 |
67 | **Example 1**
68 | ```php
69 | $x1 = CArray::arange(9.0);
70 | $x1 = CArray::reshape($x1, [3, 3]);
71 | $x2 = CArray::arange(3.0);
72 | echo CArray::subtract($x1, $x2);
73 | ```
74 | ```
75 | [[ 0 0 0 ]
76 | [ 3 3 3 ]
77 | [ 6 6 6 ]]
78 | ```
79 |
80 | **Example 2**
81 | ```php
82 | $x1 = CArray::arange(9.0);
83 | $x1 = CArray::reshape($x1, [3, 3]);
84 | $x2 = CArray::arange(3.0);
85 | echo ($x1 - $x2);
86 | ```
87 | ```
88 | [[ 0 0 0 ]
89 | [ 3 3 3 ]
90 | [ 6 6 6 ]]
91 | ```
92 |
93 | ---
94 |
95 | ## multiply
96 | ```php
97 | public static multiply($x1, $x2) : CArray
98 | ```
99 | > Multiply arguments element-wise.
100 |
101 | ##### Parameters
102 |
103 | `CArray|Array` **$x1** **$x2** Input arrays.
104 |
105 | ##### Returns
106 |
107 | `CArray` The multiplication of `$x1` and `$x2`, element-wise.
108 |
109 | ##### Examples
110 |
111 | **Example 1**
112 | ```php
113 | $x1 = CArray::arange(9.0);
114 | $x1 = CArray::reshape($x1, [3, 3]);
115 | $x2 = CArray::arange(3.0);
116 | echo CArray::multiply($x1, $x2);
117 | ```
118 | ```
119 | [[ 0 1 4 ]
120 | [ 0 4 10 ]
121 | [ 0 7 16 ]]
122 | ```
123 |
124 | **Example 2**
125 | ```php
126 | $x1 = CArray::arange(9.0);
127 | $x1 = CArray::reshape($x1, [3, 3]);
128 | $x2 = CArray::arange(3.0);
129 | echo ($x1 * $x2);
130 | ```
131 | ```
132 | [[ 0 1 4 ]
133 | [ 0 4 10 ]
134 | [ 0 7 16 ]]
135 | ```
136 |
137 | ---
138 |
139 | ## divide
140 | ```php
141 | public static divide($x1, $x2) : CArray
142 | ```
143 | > Returns a true division of the inputs, element-wise.
144 |
145 | ##### Parameters
146 |
147 | `CArray|Array` **$x1** Dividend
148 |
149 | `CArray|Array` **$x2** Divisor
150 |
151 | ##### Returns
152 |
153 | `CArray` Return array.
154 |
155 | ##### Examples
156 |
157 | **Example 1**
158 | ```php
159 | echo CArray::divide([1, 2, 3, 4, 5], 4);
160 | ```
161 | ```
162 | [ 0.25000000 0.50000000 0.75000000 1.00000000 1.25000000 ]
163 | ```
164 |
165 | **Example 2**
166 | ```php
167 | $a = new CArray([[1, 2], [3, 4]]);
168 | echo ($a / 4);
169 | ```
170 | ```
171 | [[ 0.25000000 0.50000000 ]
172 | [ 0.75000000 1.00000000 ]]
173 | ```
174 |
175 | ---
176 |
177 | ## power
178 | ```php
179 | public static power($x1, $x2) : CArray
180 | ```
181 | > `$x1` array elements raised to powers from `$x2` array, element-wise.
182 |
183 | ##### Parameters
184 |
185 | `CArray|Array` **$x1** Bases
186 |
187 | `CArray|Array` **$x2** Exponents
188 |
189 | ##### Returns
190 |
191 | `CArray` The bases in `$x1` raised to the exponents in `$x2`.
192 |
193 | ##### Examples
194 |
195 | **Example 1**
196 | ```php
197 | $x1 = CArray::arange(6);
198 | echo CArray::power($x1, 3);
199 | ```
200 | ```
201 | [ 0 1 8 27 64 125 ]
202 | ```
203 |
204 | ---
205 |
206 | ## mod
207 | ```php
208 | public static mod($x1, $x2) : CArray
209 | ```
210 | > Return element-wise remainder of division.
211 |
212 | ##### Parameters
213 |
214 | `CArray|Array` **$x1** Dividend
215 |
216 | `CArray|Array` **$x2** Divisor
217 |
218 | ##### Returns
219 |
220 | `CArray` The element-wise remainder
221 |
222 | ##### Examples
223 |
224 | **Example 1**
225 | ```php
226 | echo CArray::mod([4, 7], [2, 3]);
227 | ```
228 | ```
229 | [ 0. 1. ]
230 | ```
231 |
232 | ---
233 |
234 | ## remainder
235 | ```php
236 | public static remainder($x1, $x2) : CArray
237 | ```
238 | > Return element-wise remainder of division.
239 |
240 | ##### Parameters
241 |
242 | `CArray|Array` **$x1** Dividend
243 |
244 | `CArray|Array` **$x2** Divisor
245 |
246 | ##### Returns
247 |
248 | `CArray` The element-wise remainder
249 |
250 | ##### Examples
251 |
252 | **Example 1**
253 | ```php
254 | echo CArray::remainder([4, 7], [2, 3]);
255 | ```
256 | ```
257 | [ 0. 1. ]
258 | ```
259 |
260 | ---
261 |
262 | ## negative
263 | ```php
264 | public static negative($x) : CArray
265 | ```
266 | > Numerical negative, element-wise.
267 |
268 | ##### Parameters
269 |
270 | `CArray|Array` **$x** Input array.
271 |
272 | ##### Returns
273 |
274 | `CArray` Return array.
275 |
276 | ##### Examples
277 |
278 | **Example 1**
279 | ```php
280 | echo CArray::negative([1, -1]);
281 | ```
282 | ```
283 | [ -1. 1. ]
284 | ```
285 |
286 |
287 | ---
288 |
289 | ## sqrt
290 | ```php
291 | public static sqrt($x) : CArray
292 | ```
293 |
294 | ---
295 |
296 | ## reciprocal
297 | ```php
298 | public static reciprocal($x) : CArray
299 | ```
300 | > Return `1/$x` of the argument, element-wise.
301 |
302 | ##### Parameters
303 |
304 | `CArray|Array` **$x** Input array.
305 |
306 | ##### Returns
307 |
308 | `CArray` Return array.
309 |
310 | ##### Examples
311 |
312 | **Example 1**
313 | ```php
314 | echo CArray::reciprocal([1, 2., 3.33]);
315 | ```
316 | ```
317 | [ 1.00000000 0.50000000 0.33333333 ]
318 | ```
319 |
320 |
321 |
322 |
323 |
--------------------------------------------------------------------------------
/docs/routines/carray_object.md:
--------------------------------------------------------------------------------
1 | # CArray Object
2 |
3 | ---
4 |
5 | ## fill
6 | ```php
7 | public fill($val)
8 | ```
9 | > Fill the array with a scalar value.
10 | >
11 | ##### Parameters
12 |
13 | `int|double|float` **$val** All elements of the CArray will be assigned this value.
--------------------------------------------------------------------------------
/docs/routines/decompositions.md:
--------------------------------------------------------------------------------
1 | # Decomposition Routines
2 |
3 | ---
4 |
5 | ## svd
6 | ```php
7 | public static svd($a) : CArray
8 | ```
9 | > Singular Value Decomposition.
10 |
11 | ##### Parameters
12 |
13 | `CArray|Array` **$a** 2-D Input array.
14 |
15 | ##### Returns
16 |
17 | `Array` Array of CArrays containing the unitary arrays ([0] and [2]) and singular values ([1]).
18 |
19 | ##### Examples
20 |
21 | **Example 1**
22 | ```php
23 | $a = new CArray([[1, 4], [5, 6]]);
24 | $b = CArray::svd($a);
25 |
26 |
27 | print_r($b);
28 | echo "\nUNITARY ARRAYS\n";
29 | echo $b[0];
30 | echo "\nSINGULAR VALUES\n";
31 | echo $b[1];
32 | echo "\nUNITARY ARRAYS\n";
33 | echo $b[2];
34 | ```
35 | ```
36 | Array
37 | (
38 | [0] => CArray Object
39 | (
40 | [uuid] => 1
41 | [ndim] => 2
42 | )
43 |
44 | [1] => CArray Object
45 | (
46 | [uuid] => 2
47 | [ndim] => 1
48 | )
49 |
50 | [2] => CArray Object
51 | (
52 | [uuid] => 3
53 | [ndim] => 2
54 | )
55 |
56 | )
57 |
58 | UNITARY ARRAYS
59 | [[ -0.44475472 -0.89565241 ]
60 | [ -0.89565241 0.44475472 ]]
61 |
62 | SINGULAR VALUES
63 | [ 8.68334898 1.61228116 ]
64 |
65 | UNITARY ARRAYS
66 | [[ -0.56694909 -0.82375283 ]
67 | [ 0.82375283 -0.56694909 ]]
68 | ```
--------------------------------------------------------------------------------
/docs/routines/dimensions.md:
--------------------------------------------------------------------------------
1 | # Dimensions Routines
2 |
3 | ---
4 |
5 | ## atleast_1d
6 | ```php
7 | public static atleast_1d($a ...) : CArray | Array
8 | ```
9 | > Convert inputs to arrays with at least one dimension.
10 | > Scalar inputs are converted to 1-dimensional arrays, whilst higher-dimensional inputs are preserved.
11 |
12 | ##### Parameters
13 |
14 | `CArray|Array` **$a ...** One or more input arrays.
15 |
16 | ##### Returns
17 |
18 | `CArray|Array` An CArray, or array of CArrays, each with NDIM >= 1. Copies are made only if necessary.
19 |
20 | ---
21 |
22 | ## atleast_2d
23 |
24 | ```php
25 | public static atleast_2d($a ...) : CArray | Array
26 | ```
27 | > Convert inputs to arrays with at least two dimensions.
28 |
29 | ##### Parameters
30 |
31 | `CArray|Array` **$a ...** One or more input arrays.
32 |
33 | ##### Returns
34 |
35 | `CArray|Array` An CArray, or array of CArrays, each with NDIM >= 2. Copies are made only if necessary.
36 |
37 | ---
38 |
39 | ## atleast_3d
40 |
41 | ```php
42 | public static atleast_3d($a ...) : CArray | Array
43 | ```
44 | > Convert inputs to arrays with at least three dimensions.
45 |
46 | ##### Parameters
47 |
48 | `CArray|Array` **$a ...** One or more input arrays.
49 |
50 | ##### Returns
51 |
52 | `CArray|Array` An CArray, or array of CArrays, each with NDIM >= 3. Copies are made only if necessary.
53 |
54 | ---
55 |
56 | ## squeeze
57 |
58 | ```php
59 | public static squeeze($a, $axis = NULL) : CArray
60 | ```
61 | > Remove single-dimensional entries from the shape of an array.
62 |
63 | ##### Parameters
64 |
65 | `CArray|Array` **$a** Input data.
66 |
67 | `int` **$axis** Selects a subset of the single-dimensional entries in the shape.
68 |
69 | ##### Returns
70 |
71 | `CArray` The input array, but with all or a subset of the dimensions of length 1 removed. This is always a itself or a view into `$a`.
72 |
73 | ---
74 |
75 | ## expand_dims
76 |
77 | ```php
78 | public static expand_dims($a, $axis = NULL) : CArray
79 | ```
80 | > Expand the shape of an array.
81 |
82 | > Insert a new axis that will appear at the `$axis` position in the expanded array shape.
83 |
84 | ##### Parameters
85 |
86 | `CArray|Array` **$a** Input data.
87 |
88 | `int` **$axis** Position in the expanded axes where the new axis is placed.
89 |
90 | ##### Returns
91 |
92 | `CArray` **View** of `$a` with the number of dimensions increased by one.
93 |
--------------------------------------------------------------------------------
/docs/routines/distributions.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phpsci/phpsci-carray/192a92213200a80006793c932eb0effef1d24b8e/docs/routines/distributions.md
--------------------------------------------------------------------------------
/docs/routines/eigenvalues.md:
--------------------------------------------------------------------------------
1 | ## eig
2 |
3 | ## eigh
4 |
5 | ## eigvals
6 |
7 | ## eigvalsh
8 |
9 |
--------------------------------------------------------------------------------
/docs/routines/equations_and_inverse.md:
--------------------------------------------------------------------------------
1 | # Equations & Inverse Routines
2 |
3 | ---
4 |
5 | ## inv
6 | ```php
7 | public static inv($a) : CArray
8 | ```
9 | > Compute the (multiplicative) inverse of a matrix.
10 |
11 | ##### Parameters
12 |
13 | `CArray|Array` **$a** Input array.
14 |
15 | ##### Returns
16 |
17 | `CArray` (Multiplicative) inverse of the matrix `$a`.
18 |
19 | ##### Examples
20 |
21 | **Example 1**
22 | ```php
23 | $a = new CArray([[1., 2.], [3., 4.]]);
24 | echo CArray::inv($a);
25 | ```
26 | ```
27 | [[ -2.00000000 1.00000000 ]
28 | [ 1.50000000 -0.50000000 ]]
29 | ```
30 |
--------------------------------------------------------------------------------
/docs/routines/exponents_loga.md:
--------------------------------------------------------------------------------
1 | # Exponents and logarithms Routines
2 |
3 | ---
4 |
5 | ## exp
6 | ```php
7 | public static exp($x) : CArray
8 | ```
9 | > Calculate the exponential of all elements.
10 |
11 | ##### Parameters
12 |
13 | `CArray|Array` **$x** Input array.
14 |
15 | ##### Returns
16 |
17 | `CArray` Output array, element-wise exponential of `$x`.
18 |
19 | ---
20 |
21 | ## expm1
22 | ```php
23 | public static expm1($x) : CArray
24 | ```
25 | > Calculate `exp($x) - 1` for all elements in the array.
26 |
27 | ##### Parameters
28 |
29 | `CArray|Array` **$x** Input array.
30 |
31 | ##### Returns
32 |
33 | `CArray` Output array, element-wise `exp($x)-1` of `$x`.
34 |
35 | ---
36 |
37 | ## exp2
38 | ```php
39 | public static exp2($x) : CArray
40 | ```
41 | > Calculate `2**p` for all `p` (value) in the input array.
42 |
43 | ##### Parameters
44 |
45 | `CArray|Array` **$x** Input array.
46 |
47 | ##### Returns
48 |
49 | `CArray` Output array, element-wise `2**p` of `$x`.
50 |
51 | ---
52 |
53 | ## log
54 | ```php
55 | public static log($x) : CArray
56 | ```
57 | > Natural logarithm, element-wise.
58 |
59 | ##### Parameters
60 |
61 | `CArray|Array` **$x** Input array.
62 |
63 | ##### Returns
64 |
65 | `CArray` Output array, element-wise natural logarithm of `$x`.
66 |
67 | ---
68 |
69 | ## log10
70 | ```php
71 | public static log10($x) : CArray
72 | ```
73 | > Return the base 10 logarithm of `$x`, element-wise.
74 |
75 | ##### Parameters
76 |
77 | `CArray|Array` **$x** Input array.
78 |
79 | ##### Returns
80 |
81 | `CArray` Output array, element-wise base 10 logarithm of `$x`.
82 |
83 | ---
84 |
85 | ## log2
86 | ```php
87 | public static log2($x) : CArray
88 | ```
89 | > Base-2 logarithm of `$x`.
90 |
91 | ##### Parameters
92 |
93 | `CArray|Array` **$x** Input array.
94 |
95 | ##### Returns
96 |
97 | `CArray` Output array, element-wise base 2 logarithm of `$x`.
98 |
99 | ---
100 |
101 | ## log1p
102 | ```php
103 | public static log1p($x) : CArray
104 | ```
105 | > Calculates `log(1 + $x)` of `$x`
106 |
107 | ##### Parameters
108 |
109 | `CArray|Array` **$x** Input array.
110 |
111 | ##### Returns
112 |
113 | `CArray` Output array, element-wise `log(1 + $x)` of `$x`.
114 |
--------------------------------------------------------------------------------
/docs/routines/hyperbolic.md:
--------------------------------------------------------------------------------
1 | # Hyperbolic Routines
2 |
3 | ---
4 |
5 | ## sinh
6 | ```php
7 | public static sinh($x) : CArray
8 | ```
9 | > Hyperbolic sine, element-wise.
10 |
11 | ##### Parameters
12 |
13 | `CArray|Array` **$x** Input array.
14 |
15 | ##### Returns
16 |
17 | `CArray` The hyperbolic sine of each element of `$x`.
18 |
19 | ##### Examples
20 |
21 | **Example 1**
22 | ```php
23 | echo CArray::sinh(0);
24 | ```
25 | ```
26 | 0.000000
27 | ```
28 |
29 | ---
30 |
31 | ## cosh
32 | ```php
33 | public static cosh($x) : CArray
34 | ```
35 | > Compute hyperbolic cosine element-wise.
36 |
37 | ##### Parameters
38 |
39 | `CArray|Array` **$x** Input array.
40 |
41 | ##### Returns
42 |
43 | `CArray` The hyperbolic cosine of each element of `$x`.
44 |
45 | ##### Examples
46 |
47 | **Example 1**
48 | ```php
49 | echo CArray::cosh([1, -1, 0]);
50 | ```
51 | ```
52 | [ 1.54308063 1.54308063 1.00000000 ]
53 | ```
54 |
55 | ---
56 |
57 | ## tanh
58 | ```php
59 | public static tanh($x) : CArray
60 | ```
61 | > Compute hyperbolic tangent element-wise.
62 |
63 | ##### Parameters
64 |
65 | `CArray|Array` **$x** Input array.
66 |
67 | ##### Returns
68 |
69 | `CArray` The hyperbolic tangent of each element of `$x`.
70 |
71 | ##### Examples
72 |
73 | **Example 1**
74 | ```php
75 | echo CArray::tanh([-1, 0, 1]);
76 | ```
77 | ```
78 | [ -0.76159416 0.00000000 0.76159416 ]
79 | ```
--------------------------------------------------------------------------------
/docs/routines/indexing.md:
--------------------------------------------------------------------------------
1 | # Indexing Routines
2 |
3 | ---
4 |
5 | ## diagonal
6 |
7 | ```php
8 | public static diagonal($a, int $offset = 0, int $axis1 = 0, int $axis2 = 0) : CArray
9 | ```
10 | > Return specified diagonals.
11 |
12 | > If a is 2-D, returns the diagonal of a with the given offset, i.e., the collection of elements of the
13 | form `$a[i][i+offset]`. If a has more than two dimensions, then the axes specified by axis1 and axis2 are used to
14 | determine the 2-D sub-array whose diagonal is returned. The shape of the resulting array can be determined by
15 | removing axis1 and axis2 and appending an index to the right equal to the size of the resulting diagonals.
16 |
17 | ##### Parameters
18 |
19 | `CArray|Array` **$a** - Input array.
20 |
21 | `CArray|Array` **$offset** (optional) - Offset of the diagonal from the main diagonal. Can be positive or negative. Defaults to
22 | main diagonal (0).
23 |
24 | `CArray|Array` **$axis1** (optional) - Axis to be used as the first axis of the 2-D sub-arrays from which the diagonals should be taken.
25 | Defaults to first axis (0).
26 |
27 | `CArray|Array` **$axis2** (optional) - Axis to be used as the second axis of the 2-D sub-arrays from which the diagonals should be
28 | taken. Defaults to second axis (1).
29 |
30 | ##### Returns
31 |
32 | `CArray` Diagonals of `$a`.
33 |
34 | ##### Examples
35 |
36 | **Example 1**
37 | ```php
38 | $A = CArray::arange(4);
39 | $A = CArray::reshape($A, [2, 2]);
40 | echo CArray::diagonal($A);
41 | ```
42 | ````
43 | [ 0 3 ]
44 | ````
45 |
46 |
--------------------------------------------------------------------------------
/docs/routines/ma_norms.md:
--------------------------------------------------------------------------------
1 | # Matrix Norm Routines
2 |
3 | ---
4 |
5 | ## norm
6 | ```php
7 | public static norm($x) : CArray
8 | ```
9 | > Matrix or vector Frobenius norm.
10 |
11 | ##### Parameters
12 |
13 | `CArray|Array` **$x** Input array.
14 |
15 | ##### Returns
16 |
17 | `CArray` Norm of the matrix or vector.
18 |
19 | ##### Examples
20 |
21 | **Example 1**
22 | ```php
23 | $a = CArray::arange(9) - 4;
24 | $b = CArray::reshape($a, [3, 3]);
25 | echo CArray::norm($b);
26 | ```
27 | ```
28 | 7.745967
29 | ```
30 |
31 | ---
32 |
33 | ## det
34 | ```php
35 | public static det($a) : CArray
36 | ```
37 | > Compute the determinant of an array.
38 |
39 | ##### Parameters
40 |
41 | `CArray|Array` **$a** Input array.
42 |
43 | ##### Returns
44 |
45 | `CArray` Determinant of `$a`.
46 |
47 | ##### Examples
48 |
49 | **Example 1**
50 | ```php
51 | $a = new CArray([[1, 2], [3, 4]]);
52 | echo CArray::det($a);
53 | ```
54 | ```
55 | -2.000000
56 | ```
--------------------------------------------------------------------------------
/docs/routines/ma_products.md:
--------------------------------------------------------------------------------
1 | # Matrix & Vector Products
2 |
3 | ---
4 |
5 | ## vdot
6 | ```php
7 | public static vdot($a, $b) : CArray
8 | ```
9 | > Return the dot product of two vectors.
10 |
11 | > vdot does not perform a matrix product, but flattens input arguments to 1-D
12 | vectors first. Consequently, it should only be used for vectors.
13 |
14 | ##### Parameters
15 |
16 | `CArray|Array` **$a** Input array.
17 |
18 | `CArray|Array` **$b** Input array.
19 |
20 | ##### Returns
21 |
22 | `CArray` Dot product of `$a` and `$b`.
23 |
24 | ##### Examples
25 |
26 | **Example 1**
27 | ```php
28 | $a = new CArray([[1, 4], [5, 6]]);
29 | $b = new CArray([[4, 1], [2, 2]]);
30 |
31 | echo CArray::vdot($a, $b);
32 | ```
33 | ```
34 | 30.0000
35 | ```
36 |
37 | ---
38 |
39 | ## matmul
40 | ```php
41 | public static matmul($a, $b) : CArray
42 | ```
43 | > Matrix product of two arrays.
44 |
45 | ##### Parameters
46 |
47 | `CArray|Array` **$a** Input array.
48 |
49 | `CArray|Array` **$b** Input array.
50 |
51 | ##### Returns
52 |
53 | `CArray` The matrix product of the inputs. This is a scalar only when both `$x1`, `$x2` are 1-d vectors.
54 |
55 | ##### Examples
56 |
57 | **Example 1**
58 | ```php
59 | $a = new CArray([[1, 4], [5, 6]]);
60 | $b = new CArray([[4, 1], [2, 2]]);
61 |
62 | echo CArray::matmul($a, $b);
63 | ```
64 | ```
65 | [[ 12 9 ]
66 | [ 32 17 ]]
67 | ```
68 |
69 | ---
70 |
71 | ## inner
72 | ```php
73 | public static inner($a, $b) : CArray
74 | ```
75 | > Inner product of two arrays.
76 |
77 | ##### Parameters
78 |
79 | `CArray|Array` **$a** Input array.
80 |
81 | `CArray|Array` **$b** Input array.
82 |
83 | ##### Returns
84 |
85 | `CArray` Inner product of the input arrays.
--------------------------------------------------------------------------------
/docs/routines/numerical_ranges.md:
--------------------------------------------------------------------------------
1 | # Numerical Range Methods
2 |
3 | ---
4 |
5 | ## arange
6 |
7 | ```php
8 | public static arange(int $start = 0, int $stop, int $step = 1) : CArray
9 | ```
10 | > Return evenly spaced values within a given interval.
11 |
12 | ##### Parameters
13 |
14 | `int` **$start** (Optional) Start of interval.
15 |
16 | `int` **$stop** End of interval.
17 |
18 | `int` **$step** (Optional) Spacing between values.
19 |
20 | ##### Returns
21 |
22 | `CArray` CArray of evenly spaced values.
23 |
24 | ---
25 |
26 | ## linspace
27 |
28 | ```php
29 | public static linspace($start, $stop, $num = 50, $endpoint = True) : CArray
30 | ```
31 | > Return evenly spaced numbers over a specified interval.
32 |
33 | > Returns `$num` evenly spaced samples, calculated over the interval `[$start, $stop]`.
34 |
35 | ##### Parameters
36 |
37 | `int` **$start** The starting value of the sequence.
38 |
39 | `int` **$stop** The end value of the sequence.
40 |
41 | `int` **$num** (Optional) Number of samples to generate.
42 |
43 | `bool` **$endpoint** (Optional) If True, stop is the last sample. Otherwise, it is not included.
44 |
45 | ##### Returns
46 |
47 | `CArray` There are `$num` equally spaced samples in the closed interval `[$start, $stop]`.
48 |
49 | ---
50 |
51 | ## logspace
52 |
53 | ```php
54 | public static logspace($start, $stop, $num=50, $endpoint=True, $base=10.0) : CArray
55 | ```
56 | > Return numbers spaced evenly on a log scale.
57 |
58 | ##### Parameters
59 |
60 | `int` **$start** The starting value of the sequence.
61 |
62 | `int` **$stop** The end value of the sequence.
63 |
64 | `int` **$num** (Optional) Number of samples to generate.
65 |
66 | `bool` **$endpoint** (Optional) If True, stop is the last sample. Otherwise, it is not included.
67 |
68 | `int|double` **$base** (Optional) The base of the log space.
69 |
70 | ##### Returns
71 |
72 | `CArray` `$num` samples, equally spaced on a log scale.
73 |
74 |
--------------------------------------------------------------------------------
/docs/routines/ones_and_zeros.md:
--------------------------------------------------------------------------------
1 | # Ones and Zeros Routines
2 |
3 | ---
4 |
5 | ## identity
6 |
7 | ```php
8 | public static identity($n) : CArray
9 | ```
10 | > Return the identity array.
11 |
12 | > The identity array is a square array with ones on the main diagonal.
13 |
14 | ##### Parameters
15 |
16 | `CArray|Array` **$n** Number of rows (and columns) in `$n x $n` output.
17 |
18 | ##### Returns
19 |
20 | `CArray` `$n x $n` CArray with its main diagonal set to one, and all other elements 0.
21 |
22 | ##### Examples
23 |
24 | **Example 1**
25 | ```php
26 | echo CArray::identity(4);
27 | ```
28 | ```
29 | [[ 1. 0. 0. 0. ]
30 | [ 0. 1. 0. 0. ]
31 | [ 0. 0. 1. 0. ]
32 | [ 0. 0. 0. 1. ]]
33 | ```
34 |
35 | ---
36 |
37 | ## eye
38 |
39 | ```php
40 | public static eye($n, $m = NULL, $k = 0) : CArray
41 | ```
42 |
43 | > Return a 2-D array with ones on the diagonal and zeros elsewhere.
44 |
45 | ##### Parameters
46 |
47 | `CArray|Array` **$n** Number of rows in the output.
48 |
49 | `CArray|Array` **$m** Number of columns in the output. If NULL, defaults to `$n`.
50 |
51 | `CArray|Array` **$k** Index of the diagonal: 0 (the default) refers to the main diagonal, a positive value refers to
52 | an upper diagonal, and a negative value to a lower diagonal.
53 |
54 | ##### Returns
55 |
56 | `CArray` An array where all elements are equal to zero, except for the `$k`-th diagonal, whose values are equal to one.
57 |
58 | ##### Examples
59 |
60 | **Example 1**
61 | ```php
62 | echo CArray::eye(3, 3, 1);
63 | ```
64 | ```
65 | [[ 0. 1. 0. ]
66 | [ 0. 0. 1. ]
67 | [ 0. 0. 0. ]]
68 | ```
69 |
70 |
71 | ---
72 |
73 | ## ones
74 | ```php
75 | public static ones(array $shape) : CArray
76 | ```
77 | > Return a new CArray of given shape, filled with ones.
78 |
79 | ##### Parameters
80 |
81 | `Array` **$shape** Shape of the new array, e.g., `[2, 3]` or `[2]`.
82 |
83 | ##### Returns
84 |
85 | `CArray` CArray of ones with the given shape.
86 |
87 |
88 | ---
89 |
90 | ## zeros
91 | ```php
92 | public static zeros(array $shape) : CArray
93 | ```
94 |
95 | > Return a new CArray of given shape, filled with zeros.
96 |
97 | ##### Parameters
98 |
99 | `Array` **$shape** Shape of the new array, e.g., `[2, 3]` or `[2]`.
100 |
101 | ##### Returns
102 |
103 | `CArray` CArray of zeros with the given shape.
--------------------------------------------------------------------------------
/docs/routines/random.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phpsci/phpsci-carray/192a92213200a80006793c932eb0effef1d24b8e/docs/routines/random.md
--------------------------------------------------------------------------------
/docs/routines/rearranging.md:
--------------------------------------------------------------------------------
1 | # Rearranging Routines
2 |
3 | ---
4 |
5 | ## reshape
6 |
7 | ```php
8 | public static reshape($a, $newshape) : CArray
9 | ```
10 | > Gives a new shape to an array without changing its data.
11 |
12 | ##### Parameters
13 |
14 | `CArray|Array` **$a** Input array.
15 |
16 | `CArray|Array` **$newshape** The new shape should be compatible with the original shape. If an integer, then the result
17 | will be a 1-D array of that length.
18 |
19 | ##### Returns
20 |
21 | `CArray` This will be a new view of `$a` if possible; otherwise, it will be a copy.
22 |
23 | ##### Examples
24 |
25 | **Example 1**
26 | ```php
27 | $A = CArray::arange(8);
28 | echo CArray::reshape($A, [2, 4]);
29 | ```
30 | ````
31 | [[ 0 1 2 3 ]
32 | [ 4 5 6 7 ]]
33 | ````
34 |
35 | ---
36 |
37 | ## flip
38 |
39 | ```php
40 | public static flip($a) : CArray
41 | ```
42 | > Reverse the order of elements in an array
43 |
44 | ##### Parameters
45 |
46 | `CArray|Array` **$a** Input array.
47 |
48 | ##### Returns
49 |
50 | `CArray` A view of `$a` with the entries of axis reversed.
51 |
52 | ##### Examples
53 |
54 | **Example 1**
55 | ```php
56 | $A = CArray::arange(8);
57 | echo CArray::flip($A);
58 | ```
59 | ```
60 | [ 7 6 5 4 3 2 1 0 ]
61 | ```
--------------------------------------------------------------------------------
/docs/routines/rounding.md:
--------------------------------------------------------------------------------
1 | # Rounding Routines
2 |
3 | ---
4 |
5 | ## ceil
6 | ```php
7 | public static ceil($x) : CArray
8 | ```
9 | > The ceiling of the input, element-wise.
10 |
11 | ##### Parameters
12 |
13 | `CArray|Array` **$x** Input array.
14 |
15 | ##### Returns
16 |
17 | `CArray` The ceiling of each element in `$x`.
18 |
19 | ##### Examples
20 |
21 | **Example 1**
22 | ```php
23 | $a = new CArray([-1.7, -1.5, -0.2, 0.2, 1.5, 1.7, 2.0]);
24 | echo CArray::ceil($a);
25 | ```
26 | ```
27 | [ -1. -1. 0. 1. 2. 2. 2. ]
28 | ```
29 |
30 | ---
31 |
32 | ## floor
33 | ```php
34 | public static floor($x) : CArray
35 | ```
36 | > The floor of the input, element-wise.
37 |
38 | ##### Parameters
39 |
40 | `CArray|Array` **$x** Input array.
41 |
42 | ##### Returns
43 |
44 | `CArray` The floor of each element in `$x`.
45 |
46 | ##### Examples
47 |
48 | **Example 1**
49 | ```php
50 | $a = new CArray([-1.7, -1.5, -0.2, 0.2, 1.5, 1.7, 2.0]);
51 | echo CArray::floor($a);
52 | ```
53 | ```
54 | [ -2. -2. -1. 0. 1. 1. 2. ]
55 | ```
56 |
57 |
58 | ---
59 |
60 | ## around
61 | ```php
62 | public static around($x, int $decimals = 0) : CArray
63 | ```
64 | > Evenly round to the given number of decimals.
65 |
66 | ##### Parameters
67 |
68 | `CArray|Array` **$x** Input array.
69 |
70 | `int` **$decimals** Number of decimal places to round to (default: 0).
71 | If decimals is negative, it specifies the number of positions to the
72 | left of the decimal point.
73 |
74 | ##### Returns
75 |
76 | `CArray` An array of the same type as `$a`, containing the rounded values.
77 |
78 | ##### Examples
79 |
80 | **Example 1**
81 | ```php
82 | $a = CArray::around([0.37, 1.64]);
83 | echo $a;
84 | ```
85 | ```
86 | [ 0. 2. ]
87 | ```
88 |
89 | **Example 2**
90 | ```php
91 | $a = CArray::around([0.37, 1.64], 2);
92 | echo $a;
93 | ```
94 | ```
95 | [ 0.37000000 1.64000000 ]
96 | ```
--------------------------------------------------------------------------------
/docs/routines/searching.md:
--------------------------------------------------------------------------------
1 | # Search Routines
2 |
3 | ---
4 |
5 | ## argmax
6 | ```php
7 | public static argmax($x, $axis = NULL) : CArray
8 | ```
9 | > Returns the indices of the maximum values along an axis.
10 |
11 | ##### Parameters
12 |
13 | `CArray|Array` **$x** Input array.
14 |
15 | `CArray|Array` **$axis** (Optional) The index is into the flattened array, otherwise along the specified axis.
16 |
17 | ##### Returns
18 |
19 | `CArray|Array` **$x** Array of indices into the array. It has the same shape as `$x` with the dimension along `$axis` removed.
20 |
21 | ##### Examples
22 |
23 | **Example 1**
24 | ```php
25 | $a = CArray::arange(6);
26 | $a = CArray::reshape($a, [2, 3]) + 10;
27 | echo CArray::argmax($a);
28 | ```
29 | ```
30 | 5
31 | ```
32 |
33 | **Example 2**
34 | ```php
35 | $a = CArray::arange(6);
36 | $a = CArray::reshape($a, [2, 3]) + 10;
37 | echo CArray::argmax($a, 0);
38 | ```
39 | ```
40 | [ 1 1 1 ]
41 | ```
42 |
43 | ---
44 |
45 | ## argmin
46 | ```php
47 | public static argmin($x, $axis = NULL) : CArray
48 | ```
49 | > Returns the indices of the minimum values along an axis.
50 |
51 | ##### Parameters
52 |
53 | `CArray|Array` **$x** Input array.
54 |
55 | `CArray|Array` **$axis** (Optional) The index is into the flattened array, otherwise along the specified axis.
56 |
57 | ##### Returns
58 |
59 | `CArray|Array` **$x** Array of indices into the array. It has the same shape as `$x` with the dimension along `$axis` removed.
60 |
61 | ##### Examples
62 |
63 | **Example 1**
64 | ```php
65 | $a = CArray::arange(6);
66 | $a = CArray::reshape($a, [2, 3]) + 10;
67 | echo CArray::argmin($a);
68 | ```
69 | ```
70 | 0
71 | ```
72 |
73 | **Example 2**
74 | ```php
75 | $a = CArray::arange(6);
76 | $a = CArray::reshape($a, [2, 3]) + 10;
77 | echo CArray::argmin($a, 0);
78 | ```
79 | ```
80 | [ 0 0 0 ]
81 | ```
--------------------------------------------------------------------------------
/docs/routines/sorting.md:
--------------------------------------------------------------------------------
1 | # Sorting Routines
2 |
3 | ---
4 |
5 | ## sort
6 | ```php
7 | public static sort($x, int $axis = -1, $kind = 'quicksort') : CArray
8 | ```
9 | > Return a sorted copy of an array.
10 |
11 | ##### Parameters
12 |
13 | `CArray|Array` **$x** Input array.
14 |
15 | `int` **$axis** (Optional) Axis along which to sort. The default is -1,
16 | which sorts along the last axis.
17 |
18 | `string` **$kind** (Optional) Sorting Algorithm. Default is `quicksort`. Options:
19 | *quicksort*, *mergesort*, *heapsort* and *stable*.
20 |
21 | ##### Returns
22 |
23 | `CArray` Array of the same type and shape as `$x`.
24 |
25 | ##### Examples
26 |
27 | **Example 1**
28 | ```php
29 | echo CArray::sort([[1 ,4 ],[3 ,1]]);
30 | ```
31 | ```
32 | [[ 1 4 ]
33 | [ 1 3 ]]
34 | ```
35 |
36 | **Example 2**
37 | ```php
38 | echo CArray::sort([[1 ,4 ],[3 ,1]], 0);
39 | ```
40 | ```
41 | [[ 1 1 ]
42 | [ 3 4 ]]
43 | ```
44 |
--------------------------------------------------------------------------------
/docs/routines/statistics.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phpsci/phpsci-carray/192a92213200a80006793c932eb0effef1d24b8e/docs/routines/statistics.md
--------------------------------------------------------------------------------
/docs/routines/sum_products_and_diff.md:
--------------------------------------------------------------------------------
1 | # Sums, products and differences Routines
2 |
3 | ---
4 |
5 | ## prod
6 | ```php
7 | public static prod($x, int $axis = NULL) : CArray
8 | ```
9 | > Return the product of array elements over a given axis.
10 |
11 | ##### Parameters
12 |
13 | `CArray|Array` **$x** Input array.
14 |
15 | `int` **$axis** (optional) Axis or axes along which a product is performed.
16 |
17 | ##### Returns
18 |
19 | `CArray` An array shaped as `$x` but with the specified axis removed.
20 | . If `$axis` is NULL an 0-d CArray is returned.
21 |
22 | ##### Examples
23 |
24 | **Example 1**
25 | ```php
26 | echo CArray::prod([[1.,2.],[3.,4.]]);
27 | ```
28 | ```
29 | 24.000000
30 | ```
31 |
32 | **Example 2**
33 | ```php
34 | echo CArray::prod([[1.,2.],[3.,4.]], 0);
35 | ```
36 | ```
37 | [ 3. 8. ]
38 | ```
39 |
40 |
41 |
42 |
43 | ---
44 |
45 | ## sum
46 | ```php
47 | public static sum($x, int $axis = NULL) : CArray
48 | ```
49 | > Sum of array elements over a given axis.
50 |
51 | ##### Parameters
52 |
53 | `CArray|Array` **$x** Input array.
54 |
55 | `int` **$axis** (optional) Axis or axes along which a sum is performed.
56 |
57 | ##### Returns
58 |
59 | `CArray` An array shaped as `$x` but with the specified axis removed.
60 | . If `$axis` is NULL an 0-d CArray is returned.
61 |
62 | ##### Examples
63 |
64 | **Example 1**
65 | ```php
66 | echo CArray::sum([[1.,2.],[3.,4.]]);
67 | ```
68 | ```
69 | 10.000000
70 | ```
71 |
72 | **Example 2**
73 | ```php
74 | echo CArray::sum([[1.,2.],[3.,4.]]);
75 | ```
76 | ```
77 | [ 4. 6. ]
78 | ```
79 |
80 |
81 | ---
82 |
83 | ## cumprod
84 | ```php
85 | public static cumprod($x, int $axis = 0) : CArray
86 | ```
87 | > Return the cumulative product of elements along a given axis.
88 |
89 | ##### Parameters
90 |
91 | `CArray|Array` **$x** Input array.
92 |
93 | `int` **$axis** (optional) Axis along which the cumulative product is computed.
94 |
95 | ##### Returns
96 |
97 | `CArray` An array shaped as `$x`. If `$axis` is NULL an 0-d CArray is returned.
98 |
99 | ##### Examples
100 |
101 | **Example 1**
102 | ```php
103 | $a = new CArray([1, 2, 3]);
104 | echo CArray::cumprod($a);
105 | ```
106 | ```
107 | [ 1 2 6 ]
108 | ```
109 |
110 | **Example 2**
111 | ```php
112 | $a = new CArray([[1, 2, 3], [4, 5, 6]]);
113 | echo CArray::cumprod($a);
114 | ```
115 | ```
116 | [ 1 2 6 24 120 720 ]
117 | ```
118 |
119 | ---
120 |
121 | ## cumsum
122 | ```php
123 | public static cumsum($x) : CArray
124 | ```
125 | > Return the cumulative sum of elements along a given axis.
126 |
127 | ##### Parameters
128 |
129 | `CArray|Array` **$x** Input array.
130 |
131 | `int` **$axis** (optional) Axis along which the cumulative sum is computed.
132 |
133 | ##### Returns
134 |
135 | `CArray` An array shaped as `$x`. If `$axis` is NULL an 0-d CArray is returned.
136 |
137 | ##### Examples
138 |
139 | **Example 1**
140 | ```php
141 | $a = new CArray([[1, 2, 3], [4, 5, 6]]);
142 | echo CArray::cumsum($a);
143 | ```
144 | ```
145 | [ 1 3 6 10 15 21 ]
146 | ```
147 |
148 | **Example 2**
149 | ```php
150 | echo CArray::cumsum([1, 2, 3]);
151 | ```
152 | ```
153 | [ 1 3 6 ]
154 | ```
--------------------------------------------------------------------------------
/docs/routines/transpose.md:
--------------------------------------------------------------------------------
1 | # Transpose Routines
2 |
3 | ---
4 |
5 | ## moveaxis
6 |
7 | ```php
8 | public static moveaxis($a, $source, $destination) : CArray
9 | ```
10 | > Move axes of an array to new positions.
11 | > Other axes remain in their original order.
12 |
13 | ##### Parameters
14 |
15 | `CArray|Array` **$a** The array whose axes should be reordered.
16 |
17 | `CArray|Array|Scalar` **$source** Original positions of the axes to move. These must be unique.
18 |
19 | `CArray|Array|Scalar` **$destination** Destination positions for each of the original axes. These must also be unique.
20 |
21 |
22 | ##### Returns
23 |
24 | `CArray` Array with moved axes. This array is a view of the input array.
25 |
26 | ##### Examples
27 |
28 | **Example 1**
29 | ```php
30 | echo CArray::moveaxis([[1, 2], [3, 4]], 0, 1);
31 | ```
32 | ```php
33 | [[ 1.0000000000e+0 3.0000000000e+0 ]
34 | [ 2.0000000000e+0 4.0000000000e+0 ]]
35 | ```
36 |
37 | **Example 2**
38 | ```php
39 | Roll the specified axis backwards, until it lies in a given position.
71 |
72 | ##### Parameters
73 |
74 | `CArray|Array` **$a** - Target array.
75 |
76 | `int` **$axis** - The axis to roll backwards. The positions of the other axes do not change relative to one another.
77 |
78 | `int` **$start** (optional) - The axis is rolled until it lies before this position. The default, 0, results in a “complete” roll.
79 |
80 | ##### Returns
81 |
82 | `CArray` A view of `$a` with rolled axis.
83 |
84 |
85 | ----
86 |
87 |
88 | ## swapaxes
89 | ```php
90 | public static swapaxes($a, $axis1, $axis2) : CArray
91 | ```
92 | > Interchange two axes of an array.
93 |
94 | ##### Parameters
95 |
96 | `CArray|Array` **$a** - Target array.
97 |
98 | `int` **$axis1** - First axis.
99 |
100 | `int` **$axis2** - Second axis.
101 |
102 | ##### Returns
103 |
104 | `CArray` A view of `$a` with interchanged axis.
105 |
106 | ---
107 |
108 | ## transpose
109 | ```php
110 | public static transpose($a, $axes = NULL) : CArray
111 | ```
112 | > Permute the dimensions of an array.
113 |
114 | ##### Parameters
115 |
116 | `CArray|Array` **$a** - Target array.
117 |
118 | `CArray|Array|int` **$axes** (optional) - By default, reverse the dimensions, otherwise permute the axes according to
119 | the values given.
120 |
121 | ##### Returns
122 |
123 | `CArray` `$a` with its axes permuted. A view is returned whenever possible.
--------------------------------------------------------------------------------
/docs/routines/trigonometric.md:
--------------------------------------------------------------------------------
1 | # Trigonometric Routines
2 |
3 | ---
4 |
5 | ## sin
6 | ```php
7 | public static sin($x) : CArray
8 | ```
9 | > Trigonometric sine, element-wise.
10 |
11 | ##### Parameters
12 |
13 | `CArray|Array` **$x** Input array.
14 |
15 | ##### Returns
16 |
17 | `CArray` The sine of each element of `$x`.
18 |
19 | ##### Examples
20 |
21 | **Example 1**
22 | ```php
23 | $a = CArray::linspace(-pi(), pi(), 10);
24 | echo CArray::sin($a);
25 | ```
26 | ```
27 | [ -0.00000000 -1.00000000 0.00000000 1.00000000 0.00000000 ]
28 | ```
29 |
30 | ---
31 |
32 | ## tan
33 | ```php
34 | public static tan($x) : CArray
35 | ```
36 | > Compute tangent element-wise.
37 | > Equivalent to CArray::sin(x)/CArray::cos(x).
38 |
39 | ##### Parameters
40 |
41 | `CArray|Array` **$x** Input array.
42 |
43 | ##### Returns
44 |
45 | `CArray` The tangent of each element of `$x`.
46 |
47 | ##### Examples
48 |
49 | **Example 1**
50 | ```php
51 | echo CArray::tan([-pi(), pi()/2, pi()]);
52 | ```
53 | ```
54 | [ 1.224647e-16 1.633124e+16 -1.224647e-16 ]
55 | ```
56 |
57 | ---
58 |
59 | ## arcsin
60 | ```php
61 | public static arcsin($x) : CArray
62 | ```
63 | > Inverse sine, element-wise.
64 |
65 | ##### Parameters
66 |
67 | `CArray|Array` **$x** Input array.
68 |
69 | ##### Returns
70 |
71 | `CArray` The inverse sine of each element in `$x`.
72 |
73 | ##### Examples
74 |
75 | **Example 1**
76 | ```php
77 | echo CArray::arcsin(1);
78 | ```
79 | ```
80 | 1.570796
81 | ```
82 |
83 | ---
84 |
85 | ## arccos
86 | ```php
87 | public static arccos($x) : CArray
88 | ```
89 | > Trigonometric inverse cosine, element-wise.
90 |
91 | ##### Parameters
92 |
93 | `CArray|Array` **$x** Input array.
94 |
95 | ##### Returns
96 |
97 | `CArray` The inverse cosine of each element in `$x`.
98 |
99 | ##### Examples
100 |
101 | **Example 1**
102 | ```php
103 | echo CArray::arccos([1, -1]);
104 | ```
105 | ```
106 | [ 0.00000000 3.14159265 ]
107 | ```
108 |
109 | ---
110 |
111 | ## arctan
112 | ```php
113 | public static arctan($x) : CArray
114 | ```
115 | > Trigonometric inverse tangent, element-wise.
116 |
117 | ##### Parameters
118 |
119 | `CArray|Array` **$x** Input array.
120 |
121 | ##### Returns
122 |
123 | `CArray` The inverse tangent of each element in `$x`.
124 |
125 | ##### Examples
126 |
127 | **Example 1**
128 | ```php
129 | echo CArray::arctan([0, 1]);
130 | ```
131 | ```
132 | [ 0.00000000 0.78539816 ]
133 | ```
--------------------------------------------------------------------------------
/kernel/alloc.c:
--------------------------------------------------------------------------------
1 | #include "alloc.h"
2 | #include "carray.h"
3 | #include "buffer.h"
4 |
5 | /**
6 | * If CARRAY_GC_DEBUG env is True, CArray Garbage Collector
7 | * will print debug messages when destructing objects.
8 | */
9 | static int
10 | CArrayGC_ISDEBUGON()
11 | {
12 | if (getenv("CARRAY_GC_DEBUG") == NULL) {
13 | return 0;
14 | }
15 | if (!strcmp(getenv("CARRAY_GC_DEBUG"), "0")) {
16 | return 0;
17 | }
18 | return 1;
19 | }
20 |
21 | void
22 | CArrayDescriptor_FREE(CArrayDescriptor * descr)
23 | {
24 | if (descr->refcount < 0) {
25 | if (descr->f != NULL) {
26 | efree(descr->f);
27 | descr->f = NULL;
28 | }
29 |
30 | efree(descr);
31 | descr = NULL;
32 | }
33 | }
34 |
35 | /**
36 | * @return
37 | */
38 | void
39 | CArray_INCREF(CArray *target)
40 | {
41 | target->refcount++;
42 | }
43 |
44 | /**
45 | * @return
46 | */
47 | void
48 | CArray_XDECREF(CArray *target)
49 | {
50 | target->refcount--;
51 | }
52 |
53 | /**
54 | * @return
55 | */
56 | void
57 | CArray_DECREF(CArray *target)
58 | {
59 | target->refcount--;
60 | CArray_Free(target);
61 | }
62 |
63 |
64 | /**
65 | * Alocates CArray Data Buffer based on numElements and elsize from
66 | * CArray descriptor.
67 | **/
68 | void
69 | CArray_Data_alloc(CArray * ca)
70 | {
71 | ca->data = emalloc((ca->descriptor->numElements * ca->descriptor->elsize));
72 | }
73 |
74 | /**
75 | * @param size
76 | * @return
77 | */
78 | void *
79 | carray_data_alloc_zeros(int num_elements, int size_element, char type)
80 | {
81 | return (void*)ecalloc(num_elements, size_element);
82 | }
83 |
84 | /**
85 | * @param size
86 | * @return
87 | */
88 | void *
89 | carray_data_alloc(int num_elements, int size_element)
90 | {
91 | return (void*)emalloc(num_elements * size_element);
92 | }
93 |
94 | /**
95 | * @param descriptor
96 | */
97 | void
98 | CArrayDescriptor_INCREF(CArrayDescriptor * descriptor)
99 | {
100 | descriptor->refcount++;
101 | }
102 |
103 | /**
104 | * @param descriptor
105 | */
106 | void
107 | CArrayDescriptor_DECREF(CArrayDescriptor * descriptor)
108 | {
109 | if (descriptor != NULL) {
110 | descriptor->refcount--;
111 | }
112 | }
113 |
114 | void
115 | CArray_Free(CArray * self)
116 | {
117 | if(self->refcount <= 0) {
118 | efree(self->dimensions);
119 | efree(self->strides);
120 | efree(self->data);
121 | efree(self);
122 | } else {
123 | efree(self->dimensions);
124 | efree(self->strides);
125 | efree(self);
126 | }
127 | }
128 |
129 | /**
130 | * Free CArrays owning data buffer
131 | */
132 | void
133 | _free_data_owner(MemoryPointer * ptr)
134 | {
135 | CArray * array = CArray_FromMemoryPointer(ptr);
136 | CArrayDescriptor_DECREF(array->descriptor);
137 |
138 | if(array->descriptor->refcount < 0) {
139 | if (CArrayGC_ISDEBUGON()) {
140 | php_printf("\n[CARRAY_GC_DEBUG][DESCR] Freeing Descriptor from CArray ID %d", ptr->uuid);
141 | }
142 | CArrayDescriptor_FREE(CArray_DESCR(array));
143 | }
144 |
145 | CArray_XDECREF(array);
146 | if (CArrayGC_ISDEBUGON()) {
147 | php_printf("\n[CARRAY_GC_DEBUG] Freeing Dimensions and Strides from CArray ID %d", ptr->uuid);
148 | }
149 | efree(array->dimensions);
150 | efree(array->strides);
151 | if(array->refcount < 0) {
152 | if (CArrayGC_ISDEBUGON()) {
153 | php_printf("\n[CARRAY_GC_DEBUG] Freeing DATA from CArray ID %d", ptr->uuid);
154 | }
155 | efree(array->data);
156 | buffer_remove(ptr);
157 | }
158 | }
159 |
160 | /**
161 | * Free CArrays that refers others CArrays
162 | */
163 | void
164 | _free_data_ref(MemoryPointer * ptr)
165 | {
166 | MemoryPointer tmp;
167 |
168 | CArray * array = CArray_FromMemoryPointer(ptr);
169 |
170 | CArray_XDECREF(array);
171 | CArray_XDECREF(array->base);
172 | CArrayDescriptor_DECREF(array->descriptor);
173 | if(array->descriptor->refcount < 0) {
174 | if (CArrayGC_ISDEBUGON()) {
175 | php_printf("\n[CARRAY_GC_DEBUG][DESCR][VIEW] Freeing Descriptor from CArray ID %d", ptr->uuid);
176 | }
177 | CArrayDescriptor_FREE(CArray_DESCR(array));
178 | }
179 | efree(array->dimensions);
180 | efree(array->strides);
181 |
182 | if(array->refcount < 0 && array->base->refcount < 0) {
183 | if (CArrayGC_ISDEBUGON()) {
184 | php_printf("\n[CARRAY_GC_DEBUG][VIEW] Freeing CArray ID %d", ptr->uuid);
185 | }
186 | if(CArray_CHKFLAGS(array->base, CARRAY_ARRAY_OWNDATA)) {
187 | if (CArrayGC_ISDEBUGON()) {
188 | php_printf("\n[CARRAY_GC_DEBUG][VIEW] Freeing DATA from CArray ID %d", ptr->uuid);
189 | }
190 | efree(array->data);
191 | }
192 | tmp.uuid = array->base->uuid;
193 | buffer_remove(&tmp);
194 | }
195 | if(array->refcount < 0){
196 | if (CArrayGC_ISDEBUGON()) {
197 | php_printf("\n[CARRAY_GC_DEBUG][VIEW] Freeing CArray ID %d", ptr->uuid);
198 | }
199 | buffer_remove(ptr);
200 | }
201 | }
202 |
203 | /**
204 | * Free CArray using MemoryPointer
205 | **/
206 | void
207 | CArray_Alloc_FreeFromMemoryPointer(MemoryPointer * ptr)
208 | {
209 | CArray * array = CArray_FromMemoryPointer(ptr);
210 | if(CArray_CHKFLAGS(array, CARRAY_ARRAY_OWNDATA)){
211 | _free_data_owner(ptr);
212 | } else {
213 | _free_data_ref(ptr);
214 | }
215 | return;
216 | }
217 |
218 | CArray *
219 | CArray_Alloc(CArrayDescriptor *descr, int nd, int* dims,
220 | int is_fortran, void *interfaceData)
221 | {
222 | CArray * target = emalloc(sizeof(CArray));
223 | return CArray_NewFromDescr(target, descr, nd, dims, NULL, NULL,
224 | ( is_fortran ? CARRAY_ARRAY_F_CONTIGUOUS : 0),
225 | interfaceData);
226 | }
227 |
--------------------------------------------------------------------------------
/kernel/alloc.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Henrique Borba on 19/11/2018.
3 | //
4 |
5 | #ifndef PHPSCI_EXT_ALLOC_H
6 | #define PHPSCI_EXT_ALLOC_H
7 |
8 | #include "carray.h"
9 |
10 | void CArray_Data_alloc(CArray * ca);
11 | void * carray_data_alloc_zeros(int num_elements, int size_element, char type);
12 | void * carray_data_alloc(int num_elements, int size_element);
13 |
14 | void CArray_INCREF(CArray * target);
15 | void CArray_XDECREF(CArray * target);
16 | void CArrayDescriptor_INCREF(CArrayDescriptor * descriptor);
17 | void CArrayDescriptor_DECREF(CArrayDescriptor * descriptor);
18 | void CArray_Alloc_FreeFromMemoryPointer(MemoryPointer * ptr);
19 | CArray * CArray_Alloc(CArrayDescriptor *descr, int nd, int* dims, int is_fortran, void *interfaceData);
20 | void CArray_Free(CArray * self);
21 | void CArrayDescriptor_FREE(CArrayDescriptor * descr);
22 | #endif //PHPSCI_EXT_ALLOC_H
23 |
--------------------------------------------------------------------------------
/kernel/arraytypes.h:
--------------------------------------------------------------------------------
1 | #ifndef CARRAY_ARRAYTYPES_H
2 | #define CARRAY_ARRAYTYPES_H
3 |
4 | #include "carray.h"
5 |
6 |
7 | int
8 | small_correlate(const char * d_, int dstride,
9 | int nd, int dtype,
10 | const char * k_, int kstride,
11 | int nk, int ktype,
12 | char * out_, int ostride);
13 | #endif //CARRAY_ARRAYTYPES_H
14 |
--------------------------------------------------------------------------------
/kernel/assign.c:
--------------------------------------------------------------------------------
1 | #include "assign.h"
2 | #include "carray.h"
3 |
4 | int
5 | raw_array_is_aligned(int ndim, int *shape, char *data, int *strides, int alignment)
6 | {
7 |
8 | /*
9 | * The code below expects the following:
10 | * * that alignment is a power of two, as required by the C standard.
11 | * * that casting from pointer to uintp gives a sensible representation
12 | * we can use bitwise operations on (perhaps *not* req. by C std,
13 | * but assumed by glibc so it should be fine)
14 | * * that casting stride from intp to uintp (to avoid dependence on the
15 | * signed int representation) preserves remainder wrt alignment, so
16 | * stride%a is the same as ((unsigned intp)stride)%a. Req. by C std.
17 | *
18 | * The code checks whether the lowest log2(alignment) bits of `data`
19 | * and all `strides` are 0, as this implies that
20 | * (data + n*stride)%alignment == 0 for all integers n.
21 | */
22 |
23 | if (alignment > 1) {
24 | uintptr_t align_check = (uintptr_t)data;
25 | int i;
26 |
27 | for (i = 0; i < ndim; i++) {
28 | /* skip dim == 1 as it is not required to have stride 0 */
29 | if (shape[i] > 1) {
30 | /* if shape[i] == 1, the stride is never used */
31 | align_check |= (uintptr_t)strides[i];
32 | }
33 | else if (shape[i] == 0) {
34 | /* an array with zero elements is always aligned */
35 | return 1;
36 | }
37 | }
38 |
39 | return carray_is_aligned((void *)align_check, alignment);
40 | }
41 | else {
42 | return 1;
43 | }
44 | }
45 |
46 |
47 | int
48 | IsAligned(CArray * array)
49 | {
50 | if (CArray_DESCR(array) == NULL) {
51 | return 0;
52 | }
53 |
54 | return raw_array_is_aligned(CArray_NDIM(array), CArray_DIMS(array),
55 | CArray_DATA(array), CArray_STRIDES(array),
56 | CArray_DESCR(array)->alignment);
57 | }
--------------------------------------------------------------------------------
/kernel/assign.h:
--------------------------------------------------------------------------------
1 | #ifndef PHPSCI_EXT_ASSIGN_H
2 | #define PHPSCI_EXT_ASSIGN_H
3 | #include "carray.h"
4 |
5 | /*
6 | * return true if pointer is aligned to 'alignment'
7 | */
8 | static inline int
9 | carray_is_aligned(void * p, int alignment)
10 | {
11 | /*
12 | * Assumes alignment is a power of two, as required by the C standard.
13 | * Assumes cast from pointer to unsigned integer gives a sensible representation we
14 | * can use bitwise & on (not required by C standard, but used by glibc).
15 | */
16 | return ((uintptr_t)(p) & ((alignment) - 1)) == 0;
17 | }
18 |
19 | int IsAligned(CArray *array);
20 | int raw_array_is_aligned(int ndim, int *shape, char *data, int *strides, int alignment);
21 | #endif //PHPSCI_EXT_ASSIGN_H
--------------------------------------------------------------------------------
/kernel/assign_scalar.c:
--------------------------------------------------------------------------------
1 | #include "carray.h"
2 | #include "assign_scalar.h"
3 | #include "convert_datatype.h"
4 | #include "assign.h"
5 | #include "common/exceptions.h"
6 | #include "common/common.h"
7 | #include "alloc.h"
8 | #include "dtype_transfer.h"
9 |
10 | /*
11 | * Assigns the scalar value to every element of the destination raw array.
12 | *
13 | * Returns 0 on success, -1 on failure.
14 | */
15 | int
16 | raw_array_assign_scalar(int ndim, int *shape,
17 | CArrayDescriptor *dst_dtype, char *dst_data, int *dst_strides,
18 | CArrayDescriptor *src_dtype, char *src_data)
19 | {
20 | int idim;
21 | int * shape_it, * dst_strides_it;
22 | int * coord;
23 |
24 | CArray_StridedUnaryOp *stransfer = NULL;
25 | CArrayAuxData *transferdata = NULL;
26 | int aligned, needs_api = 0;
27 | int src_itemsize = src_dtype->elsize;
28 |
29 | shape_it = emalloc(sizeof(int) * ndim * 2);
30 | dst_strides_it = emalloc(sizeof(int) * ndim * 2);
31 | coord = emalloc(sizeof(int) * ndim * 2);
32 |
33 | /* Check both uint and true alignment */
34 | aligned = raw_array_is_aligned(ndim, shape, dst_data, dst_strides,
35 | carray_uint_alignment(dst_dtype->elsize)) &&
36 | raw_array_is_aligned(ndim, shape, dst_data, dst_strides,
37 | dst_dtype->alignment) &&
38 | carray_is_aligned(src_data, carray_uint_alignment(src_dtype->elsize) &&
39 | carray_is_aligned(src_data, src_dtype->alignment));
40 |
41 | /* Use raw iteration with no heap allocation */
42 | if (CArray_PrepareOneRawArrayIter(
43 | ndim, shape,
44 | dst_data, dst_strides,
45 | &ndim, shape_it,
46 | &dst_data, dst_strides_it) < 0) {
47 | return -1;
48 | }
49 |
50 | /* Get the function to do the casting */
51 | if (CArray_GetDTypeTransferFunction(aligned,
52 | 0, dst_strides_it[0],
53 | src_dtype, dst_dtype,
54 | 0,
55 | &stransfer, &transferdata,
56 | &needs_api) != CARRAY_SUCCEED) {
57 | return -1;
58 | }
59 |
60 | if (!needs_api) {
61 | int nitems = 1, i;
62 | for (i = 0; i < ndim; i++) {
63 | nitems *= shape_it[i];
64 | }
65 | }
66 |
67 | CARRAY_RAW_ITER_START(idim, ndim, coord, shape_it) {
68 | /* Process the innermost dimension */
69 | stransfer(dst_data, dst_strides_it[0], src_data, 0,
70 | shape_it[0], src_itemsize, transferdata);
71 | } CARRAY_RAW_ITER_ONE_NEXT(idim, ndim, coord,
72 | shape_it, dst_data, dst_strides_it);
73 |
74 |
75 | CARRAY_AUXDATA_FREE(transferdata);
76 |
77 | efree(shape_it);
78 | efree(dst_strides_it);
79 | efree(coord);
80 | return (needs_api) ? -1 : 0;
81 | }
82 |
83 | /*
84 | * Assigns a scalar value specified by 'src_dtype' and 'src_data'
85 | * to elements of 'dst'.
86 | *
87 | * dst: The destination array.
88 | * src_dtype: The data type of the source scalar.
89 | * src_data: The memory element of the source scalar.
90 | * wheremask: If non-NULL, a boolean mask specifying where to copy.
91 | * casting: An exception is raised if the assignment violates this
92 | * casting rule.
93 | *
94 | * This function is implemented in array_assign_scalar.c.
95 | *
96 | * Returns 0 on success, -1 on failure.
97 | */
98 | int
99 | CArray_AssignRawScalar(CArray *dst, CArrayDescriptor *src_dtype, char *src_data, CArray *wheremask,
100 | CARRAY_CASTING casting)
101 | {
102 | int allocated_src_data = 0;
103 | long long scalarbuffer[4];
104 |
105 | if (CArray_FailUnlessWriteable(dst, "assignment destination") < 0) {
106 | return -1;
107 | }
108 |
109 | /* Check the casting rule */
110 | if (!can_cast_scalar_to(src_dtype, src_data,
111 | CArray_DESCR(dst), casting)) {
112 | throw_typeerror_exception("Cannot cast scalar");
113 | return -1;
114 | }
115 |
116 | /*
117 | * Make a copy of the src data if it's a different dtype than 'dst'
118 | * or isn't aligned, and the destination we're copying to has
119 | * more than one element. To avoid having to manage object lifetimes,
120 | * we also skip this if 'dst' has an object dtype.
121 | */
122 | if ((!CArray_EquivTypes(CArray_DESCR(dst), src_dtype) ||
123 | !(carray_is_aligned(src_data, carray_uint_alignment(src_dtype->elsize)) &&
124 | carray_is_aligned(src_data, src_dtype->alignment))) &&
125 | CArray_SIZE(dst) > 1) {
126 | char *tmp_src_data;
127 | /*
128 | * Use a static buffer to store the aligned/cast version,
129 | * or allocate some memory if more space is needed.
130 | */
131 | if ((int)sizeof(scalarbuffer) >= CArray_DESCR(dst)->elsize) {
132 | tmp_src_data = (char *)&scalarbuffer[0];
133 | }
134 | else {
135 | tmp_src_data = emalloc(CArray_DESCR(dst)->elsize);
136 | if (tmp_src_data == NULL) {
137 | throw_memory_exception("Memory Error");
138 | goto fail;
139 | }
140 | allocated_src_data = 1;
141 | }
142 | if (CArrayDataType_FLAGCHK(CArray_DESCR(dst), CARRAY_NEEDS_INIT)) {
143 | memset(tmp_src_data, 0, CArray_DESCR(dst)->elsize);
144 | }
145 |
146 | if (CArray_CastRawArrays(1, src_data, tmp_src_data, 0, 0,
147 | src_dtype, CArray_DESCR(dst), 0) != CARRAY_SUCCEED) {
148 | src_data = tmp_src_data;
149 | goto fail;
150 | }
151 |
152 | /* Replace src_data/src_dtype */
153 | src_data = tmp_src_data;
154 | src_dtype = CArray_DESCR(dst);
155 | }
156 |
157 | if (wheremask == NULL) {
158 | /* A straightforward value assignment */
159 | /* Do the assignment with raw array iteration */
160 | if (raw_array_assign_scalar(CArray_NDIM(dst), CArray_DIMS(dst),
161 | CArray_DESCR(dst), CArray_DATA(dst), CArray_STRIDES(dst),
162 | src_dtype, src_data) < 0) {
163 |
164 | goto fail;
165 | }
166 | }
167 | else {
168 | throw_notimplemented_exception();
169 | }
170 |
171 | //if (allocated_src_data) {
172 | // free(src_data);
173 | //}
174 |
175 | return 0;
176 | fail:
177 |
178 | if (allocated_src_data) {
179 | free(src_data);
180 | }
181 | return -1;
182 | }
--------------------------------------------------------------------------------
/kernel/assign_scalar.h:
--------------------------------------------------------------------------------
1 | #ifndef PHPSCI_EXT_ASSIGN_SCALAR_H
2 | #define PHPSCI_EXT_ASSIGN_SCALAR_H
3 |
4 | #include "carray.h"
5 |
6 | int CArray_AssignRawScalar(CArray *dst, CArrayDescriptor *src_dtype, char *src_data, CArray *wheremask,
7 | CARRAY_CASTING casting);
8 |
9 | #endif
--------------------------------------------------------------------------------
/kernel/buffer.c:
--------------------------------------------------------------------------------
1 | #include "../phpsci.h"
2 | #include "buffer.h"
3 | #include "carray.h"
4 |
5 | /**
6 | * MEMORY STACK
7 | *
8 | * CArrays Memory Buffer
9 | */
10 | struct MemoryStack PHPSCI_MAIN_MEM_STACK;
11 |
12 | /**
13 | * If CARRAY_GC_DEBUG env is True, CArray Garbage Collector
14 | * will print debug messages when destructing objects.
15 | */
16 | static int
17 | CArrayBuffer_ISDEBUGON()
18 | {
19 | if (getenv("CARRAY_BUFFER_DEBUG") == NULL) {
20 | return 0;
21 | }
22 | if (!strcmp(getenv("CARRAY_BUFFER_DEBUG"), "0")) {
23 | return 0;
24 | }
25 | return 1;
26 | }
27 |
28 | /**
29 | * Initialize MemoryStack Buffer
30 | *
31 | * @todo Same from buffer_to_capacity
32 | */
33 | void buffer_init(size_t size) {
34 | PHPSCI_MAIN_MEM_STACK.freed = 0;
35 | PHPSCI_MAIN_MEM_STACK.size = 0;
36 | PHPSCI_MAIN_MEM_STACK.capacity = 1;
37 | PHPSCI_MAIN_MEM_STACK.bsize = size;
38 | PHPSCI_MAIN_MEM_STACK.last_free_uuid = -1;
39 | // Allocate first CArray struct to buffer
40 | PHPSCI_MAIN_MEM_STACK.buffer = (struct CArray**)emalloc(sizeof(CArray *));
41 | if (CArrayBuffer_ISDEBUGON()) {
42 | php_printf("\n[CARRAY_BUFFER_DEBUG] Buffer Initialized");
43 | }
44 | }
45 |
46 | void buffer_remove(MemoryPointer * ptr)
47 | {
48 | PHPSCI_MAIN_MEM_STACK.freed = PHPSCI_MAIN_MEM_STACK.freed + 1;
49 | efree(PHPSCI_MAIN_MEM_STACK.buffer[ptr->uuid]);
50 | PHPSCI_MAIN_MEM_STACK.last_free_uuid = ptr->uuid;
51 |
52 | }
53 |
54 | void buffer_free() {
55 | efree(PHPSCI_MAIN_MEM_STACK.buffer);
56 | PHPSCI_MAIN_MEM_STACK.buffer = NULL;
57 | }
58 |
59 | /**
60 | * Grow MemoryStack buffer to new_capacity.
61 | *
62 | * @param new_capacity int New capacity for MemoryStack (Buffer)
63 | *
64 | * @todo Check if this won't fck everything as the computing requirements grow up
65 | */
66 | void buffer_to_capacity(int new_capacity, size_t size) {
67 | PHPSCI_MAIN_MEM_STACK.bsize += size;
68 | PHPSCI_MAIN_MEM_STACK.buffer = (struct CArray**)erealloc(PHPSCI_MAIN_MEM_STACK.buffer, (new_capacity * sizeof(CArray *)));
69 | // Set new capacity to MemoryStack
70 | PHPSCI_MAIN_MEM_STACK.capacity = new_capacity;
71 | }
72 |
73 | /**
74 | * Add CArray to MemoryStack (Buffer) and retrieve MemoryPointer
75 | *
76 | * @param array CArray CArray to add into the stack
77 | * @param size size_t Size of CArray in bytes
78 | */
79 | void add_to_buffer(MemoryPointer * ptr, struct CArray * array, size_t size) {
80 | // If current MemoryStack buffer is empty, initialize it
81 | if(PHPSCI_MAIN_MEM_STACK.buffer == NULL) {
82 | buffer_init(size);
83 | }
84 |
85 | if (PHPSCI_MAIN_MEM_STACK.last_free_uuid == -1) {
86 | // If current capacity is smaller them the requested capacity, grow the MemoryStack
87 | if((PHPSCI_MAIN_MEM_STACK.size+1) > PHPSCI_MAIN_MEM_STACK.capacity) {
88 | buffer_to_capacity((PHPSCI_MAIN_MEM_STACK.capacity+1),size);
89 | }
90 |
91 | PHPSCI_MAIN_MEM_STACK.buffer[PHPSCI_MAIN_MEM_STACK.size] = array;
92 |
93 | // Associate CArray unique id
94 | ptr->uuid = (int)PHPSCI_MAIN_MEM_STACK.size;
95 | array->uuid = ptr->uuid;
96 |
97 | // Set new size for MemoryStack
98 | PHPSCI_MAIN_MEM_STACK.size++;
99 | } else {
100 | PHPSCI_MAIN_MEM_STACK.buffer[PHPSCI_MAIN_MEM_STACK.last_free_uuid] = array;
101 |
102 | // Associate CArray unique id
103 | ptr->uuid = (int)PHPSCI_MAIN_MEM_STACK.last_free_uuid;
104 | array->uuid = ptr->uuid;
105 | PHPSCI_MAIN_MEM_STACK.last_free_uuid = -1;
106 | }
107 |
108 | if (CArrayBuffer_ISDEBUGON()) {
109 | php_printf("\n[CARRAY_BUFFER_DEBUG] Added CArray ID %d", array->uuid);
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/kernel/buffer.h:
--------------------------------------------------------------------------------
1 | #ifndef PHPSCI_EXT_BUFFER_H
2 | #define PHPSCI_EXT_BUFFER_H
3 |
4 | #include "carray.h"
5 |
6 | /**
7 | * MemoryStack : The memory buffer of CArrays
8 | */
9 | struct MemoryStack {
10 | CArray ** buffer;
11 | int size;
12 | int capacity;
13 | int last_free_uuid;
14 | int freed;
15 | size_t bsize;
16 | };
17 |
18 | extern struct MemoryStack PHPSCI_MAIN_MEM_STACK;
19 |
20 | void add_to_buffer(MemoryPointer * ptr, struct CArray * array, size_t size);
21 | void buffer_to_capacity(int new_capacity, size_t size);
22 | void remove_from_buffer(MemoryPointer * ptr);
23 | void buffer_init();
24 | void buffer_remove(MemoryPointer * ptr);
25 | void buffer_free();
26 | #endif //PHPSCI_EXT_BUFFER_H
27 |
--------------------------------------------------------------------------------
/kernel/calculation.h:
--------------------------------------------------------------------------------
1 | #ifndef PHPSCI_EXT_CALCULATION_H
2 | #define PHPSCI_EXT_CALCULATION_H
3 |
4 | #include "carray.h"
5 |
6 | #define CArray_MAX(a,b) (((a)>(b))?(a):(b))
7 | #define CArray_MIN(a,b) (((a)<(b))?(a):(b))
8 |
9 |
10 | CArray * CArray_Sum(CArray * self, int * axis, int rtype, MemoryPointer * out_ptr);
11 | CArray * CArray_Prod(CArray * self, int * axis, int rtype, MemoryPointer * out_ptr);
12 | CArray * CArray_CumProd(CArray * self, int * axis, int rtype, MemoryPointer * out_ptr);
13 | CArray * CArray_CumSum(CArray * self, int * axis, int rtype, MemoryPointer * out_ptr);
14 | CArray * CArray_Any(CArray * target, int * axis, MemoryPointer * out);
15 | #endif
--------------------------------------------------------------------------------
/kernel/casting.c:
--------------------------------------------------------------------------------
1 | #include "carray.h"
2 |
3 | /**
4 | * COPYSWAPN
5 | */
6 | static inline void
7 | _basic_copyn(void *dst, int dstride, void *src, int sstride,
8 | int n, int elsize) {
9 | if (src == NULL) {
10 | return;
11 | }
12 | if (sstride == elsize && dstride == elsize) {
13 | memcpy(dst, src, n*elsize);
14 | }
15 | else {
16 | _unaligned_strided_byte_copy(dst, dstride, src, sstride,
17 | n, elsize, NULL);
18 | }
19 | }
20 |
21 |
22 | /**
23 | * FILL INT
24 | */
25 | int
26 | INT_fill(void * buffer, int length, struct CArray * ap)
27 | {
28 | int i;
29 | int start = ((int*)buffer)[0];
30 | int delta = ((int*)buffer)[1];
31 |
32 | delta -= start;
33 | for (i = 2; i < length; ++i) {
34 | ((int*)buffer)[i] = start + i*delta;
35 | }
36 | }
37 |
38 | /**
39 | * FILL DOUBLE
40 | */
41 | int
42 | DOUBLE_fill(void * buffer, int length, struct CArray * ap)
43 | {
44 | int i;
45 | double start = ((double*)buffer)[0];
46 | double delta = ((double*)buffer)[1];
47 |
48 | delta -= start;
49 | for (i = 2; i < length; ++i) {
50 | ((double*)buffer)[i] = start + i*delta;
51 | }
52 | }
53 |
54 | /**
55 | * SETITEM INT
56 | */
57 | int
58 | INT_setitem (void * op, void * ov, struct CArray * ap)
59 | {
60 | int temp; /* ensures alignment */
61 | temp = *((int *)op);
62 | if (ap == NULL || CArray_ISBEHAVED(ap))
63 | *((int *)ov)=temp;
64 | else {
65 | CArray_DESCR(ap)->f->copyswap(ov, &temp, !CArray_ISNOTSWAPPED(ap), ap);
66 | }
67 | return 0;
68 | }
69 |
70 | /**
71 | * GETITEM INT
72 | */
73 |
74 | /**
75 | * SETITEM DOUBLE
76 | */
77 | int
78 | DOUBLE_setitem (double * op, void * ov, struct CArray * ap)
79 | {
80 | double temp; /* ensures alignment */
81 |
82 | temp = (double)*((double*)op);
83 |
84 | if (ap == NULL || CArray_ISBEHAVED(ap))
85 | *((double *)ov)=temp;
86 | else {
87 | CArray_DESCR(ap)->f->copyswap(ov, &temp, !CArray_ISNOTSWAPPED(ap), ap);
88 | }
89 | return 0;
90 | }
91 |
92 |
93 | /**
94 | * COPYSWAP DOUBLE
95 | **/
96 | void
97 | DOUBLE_copyswap (void *dst, void *src, int swap, void * arr)
98 | {
99 | if (src != NULL) {
100 | /* copy first if needed */
101 | memcpy(dst, src, sizeof(double));
102 | }
103 | /* ignore swap */
104 | }
105 |
106 | /**
107 | * COPYSWAP INT
108 | **/
109 | void
110 | INT_copyswap (void *dst, void *src, int swap, void * arr)
111 | {
112 | if (src != NULL) {
113 | /* copy first if needed */
114 | memcpy(dst, src, sizeof(int));
115 | }
116 | /* ignore swap */
117 | }
118 |
119 | /**
120 | * CAST DOUBLE TO INT
121 | **/
122 | void
123 | DOUBLE_TO_INT(double *ip, int *op, int n,
124 | CArray *aip, CArray *aop) {
125 | while (n--) {
126 | *(op++) = (int)*(ip++);
127 | }
128 | }
129 |
130 | /**
131 | * CAST INT TO DOUBLE
132 | */
133 | void
134 | INT_TO_DOUBLE(int *ip, double *op, int n,
135 | CArray *aip, CArray *aop) {
136 | while (n--) {
137 | *(op++) = (double)*(ip++);
138 | }
139 | }
140 |
141 | void
142 | INT_TO_INT(int *ip, int *op, int n,
143 | CArray *aip, CArray *aop) {
144 | while (n--) {
145 | *op++ = (int)*ip++;
146 | }
147 | }
148 |
149 |
150 | /**
151 | * COPYSWAPN INT
152 | */
153 |
154 | void
155 | INT_copyswapn (void *dst, int dstride, void *src, int sstride,
156 | int n, int swap, void *CARRAY_UNUSED(arr))
157 | {
158 | /* copy first if needed */
159 | _basic_copyn(dst, dstride, src, sstride, n, sizeof(int));
160 | if (swap) {
161 | _strided_byte_swap(dst, dstride, n, sizeof(int));
162 | }
163 | }
164 |
165 | /**
166 | * COPYSWAPN DOUBLE
167 | */
168 | void
169 | DOUBLE_copyswapn (void *dst, int dstride, void *src, int sstride,
170 | int n, int swap, void *CARRAY_UNUSED(arr))
171 | {
172 | /* copy first if needed */
173 | _basic_copyn(dst, dstride, src, sstride, n, sizeof(double));
174 | if (swap) {
175 | _strided_byte_swap(dst, dstride, n, sizeof(double));
176 | }
177 | }
--------------------------------------------------------------------------------
/kernel/casting.h:
--------------------------------------------------------------------------------
1 | #ifndef PHPSCI_EXT_CASTING_H
2 | #define PHPSCI_EXT_CASTING_H
3 |
4 | #include "carray.h"
5 |
6 | void
7 | INT_copyswapn (void *dst, int dstride, void *src, int sstride,
8 | int n, int swap, void *CARRAY_UNUSED(arr));
9 | void
10 | DOUBLE_copyswapn (void *dst, int dstride, void *src, int sstride,
11 | int n, int swap, void *CARRAY_UNUSED(arr));
12 |
13 | void DOUBLE_copyswap (void *dst, void *src, int swap, void * arr);
14 | void INT_copyswap (void *dst, void *src, int swap, void * arr);
15 |
16 | void DOUBLE_TO_INT(int *ip, double *op, int n, CArray *aip, CArray *aop);
17 | void INT_TO_DOUBLE(int *ip, double *op, int n, CArray *aip, CArray *aop);
18 | void INT_TO_INT(int *ip, int *op, int n, CArray *aip, CArray *aop);
19 |
20 | int DOUBLE_setitem (void * op, void * ov, struct CArray * ap);
21 | int INT_setitem (int * op, void * ov, struct CArray * ap);
22 |
23 | int DOUBLE_fill(void * op, void * ov, struct CArray * ap);
24 | int INT_fill(int * op, void * ov, struct CArray * ap);
25 | #endif
--------------------------------------------------------------------------------
/kernel/clip.c:
--------------------------------------------------------------------------------
1 | #include "clip.h"
2 | #include "carray.h"
3 | #include "calculation.h"
4 | #include "alloc.h"
5 | #include "ctors.h"
6 | #include "buffer.h"
7 |
8 | #define _CARRAY_DOUBLE_MIN(a, b) (isnan(a) ? (a) : CArray_MIN(a, b))
9 | #define _CARRAY_DOUBLE_MAX(a, b) (isnan(a) ? (a) : CArray_MAX(a, b))
10 | #define _CARRAY_DCLIP(x, min, max) \
11 | _CARRAY_DOUBLE_MIN(_CARRAY_DOUBLE_MAX((x), (min)), (max))
12 |
13 |
14 | #define _CARRAY_INT_MIN(a, b) CArray_MIN(a, b)
15 | #define _CARRAY_INT_MAX(a, b) CArray_MAX(a, b)
16 | #define _CARRAY_ICLIP(x, min, max) \
17 | _CARRAY_INT_MIN(_CARRAY_INT_MAX((x), (min)), (max))
18 |
19 |
20 | void
21 | INT_clip(int *in, int ni, int *min, int *max, int *out)
22 | {
23 | int i;
24 | int max_val = 0, min_val = 0;
25 |
26 | if (max != NULL) {
27 | max_val = *max;
28 | }
29 | if (min != NULL) {
30 | min_val = *min;
31 | }
32 |
33 | if (max == NULL) {
34 | for (i = 0; i < ni; i++) {
35 | if (in[i] < min_val) {
36 | out[i] = min_val;
37 | }
38 | else {
39 | out[i] = in[i];
40 | }
41 | }
42 | }
43 | else if (min == NULL) {
44 | for (i = 0; i < ni; i++) {
45 | if (in[i] > max_val) {
46 | out[i] = max_val;
47 | }
48 | else {
49 | out[i] = in[i];
50 | }
51 | }
52 | }
53 | else {
54 | /*
55 | * Visual Studio 2015 loop vectorizer handles NaN in an unexpected
56 | * manner, see: https://github.com/numpy/numpy/issues/7601
57 | */
58 | #if (_MSC_VER == 1900)
59 | #pragma loop( no_vector )
60 | #endif
61 | for (i = 0; i < ni; i++) {
62 | if (in[i] < min_val) {
63 | out[i] = min_val;
64 | }
65 | else if (in[i] > max_val) {
66 | out[i] = max_val;
67 | }
68 | else {
69 | out[i] = in[i];
70 | }
71 | }
72 | }
73 | }
74 |
75 | void
76 | DOUBLE_clip(double *in, int ni, double *min, double *max, double *out)
77 | {
78 | int i;
79 | double max_val = 0, min_val = 0;
80 |
81 | if (max != NULL) {
82 | max_val = *max;
83 | }
84 | if (min != NULL) {
85 | min_val = *min;
86 | }
87 |
88 | if (max == NULL) {
89 | for (i = 0; i < ni; i++) {
90 | if (in[i] < min_val) {
91 | out[i] = min_val;
92 | }
93 | else {
94 | out[i] = in[i];
95 | }
96 | }
97 | }
98 | else if (min == NULL) {
99 | for (i = 0; i < ni; i++) {
100 | if (in[i] > max_val) {
101 | out[i] = max_val;
102 | }
103 | else {
104 | out[i] = in[i];
105 | }
106 | }
107 | }
108 | else {
109 | /*
110 | * Visual Studio 2015 loop vectorizer handles NaN in an unexpected
111 | * manner, see: https://github.com/numpy/numpy/issues/7601
112 | */
113 | #if (_MSC_VER == 1900)
114 | #pragma loop( no_vector )
115 | #endif
116 | for (i = 0; i < ni; i++) {
117 | if (in[i] < min_val) {
118 | out[i] = min_val;
119 | }
120 | else if (in[i] > max_val) {
121 | out[i] = max_val;
122 | }
123 | else {
124 | out[i] = in[i];
125 | }
126 | }
127 | }
128 | }
129 |
130 | CArray *
131 | CArray_Clip(CArray * self, CArray * min, CArray * max, MemoryPointer * out_ptr)
132 | {
133 | CArray_FastClipFunc *func;
134 | int outgood = 0, ingood = 0;
135 | CArray *maxa = NULL;
136 | CArray *mina = NULL;
137 | CArray *newout = NULL, *out = NULL, *newin = NULL;
138 | CArrayDescriptor *indescr = NULL, *newdescr = NULL;
139 | char *max_data, *min_data;
140 | CArray *zero;
141 |
142 | if ((max == NULL) && (min == NULL)) {
143 | throw_valueerror_exception("array_clip: must set either max or min");
144 | return NULL;
145 | }
146 |
147 | func = CArray_DESCR(self)->f->fastclip;
148 |
149 | /* First we need to figure out the correct type */
150 | if (min != NULL) {
151 | indescr = CArray_DESCR(min);
152 | if (indescr == NULL) {
153 | goto fail;
154 | }
155 | }
156 | if (max != NULL) {
157 | newdescr = CArray_DESCR(max);
158 | indescr = NULL;
159 | if (newdescr == NULL) {
160 | goto fail;
161 | }
162 | }
163 | else {
164 | /* Steal the reference */
165 | newdescr = indescr;
166 | indescr = NULL;
167 | }
168 |
169 | /*
170 | * Use the scalar descriptor only if it is of a bigger
171 | * KIND than the input array (and then find the
172 | * type that matches both).
173 | */
174 | if (newdescr->type_num > CArray_DESCR(self)->type_num, NULL) {
175 | indescr = CArray_DescrFromType(newdescr->type_num);
176 |
177 | if (indescr == NULL) {
178 | goto fail;
179 | }
180 | func = indescr->f->fastclip;
181 | }
182 | else {
183 | indescr = CArray_DESCR(self);
184 | CArrayDescriptor_INCREF(indescr);
185 | }
186 | newdescr = NULL;
187 |
188 |
189 | if (CArray_ISONESEGMENT(self) &&
190 | CArray_CHKFLAGS(self, CARRAY_ARRAY_ALIGNED) &&
191 | CArray_ISNOTSWAPPED(self) &&
192 | (CArray_DESCR(self) == indescr)) {
193 | ingood = 1;
194 | }
195 |
196 | if (!ingood) {
197 | int flags;
198 |
199 | if (CArray_ISFORTRAN(self)) {
200 | flags = CARRAY_ARRAY_FARRAY;
201 | }
202 | else {
203 | flags = CARRAY_ARRAY_CARRAY;
204 | }
205 |
206 | newin = CArray_FromArray(self, indescr, flags);
207 |
208 | if (newin == NULL) {
209 | goto fail;
210 | }
211 | }
212 | else {
213 | newin = self;
214 | CArray_INCREF(newin);
215 | }
216 |
217 |
218 | /*
219 | * If we have already made a copy of the data, then use
220 | * that as the output array
221 | */
222 | if (out == NULL && !ingood) {
223 | out = newin;
224 | }
225 |
226 | if (out == NULL) {
227 |
228 | out = emalloc(sizeof(CArray));
229 | out = CArray_NewFromDescr(out,
230 | CArray_DESCR(self), CArray_NDIM(self),
231 | CArray_DIMS(self),
232 | NULL, NULL,
233 | CArray_ISFORTRAN(self),
234 | NULL);
235 |
236 | if (out == NULL) {
237 | goto fail;
238 | }
239 |
240 | outgood = 1;
241 | }
242 |
243 | maxa = max;
244 | mina = min;
245 |
246 | /* Now we can call the fast-clip function */
247 | min_data = max_data = NULL;
248 | if (mina != NULL) {
249 | min_data = CArray_DATA(mina);
250 | }
251 | if (maxa != NULL) {
252 | max_data = CArray_DATA(maxa);
253 | }
254 |
255 | func(CArray_DATA(newin), CArray_SIZE(newin), min_data, max_data, CArray_DATA(out));
256 |
257 | if (out_ptr != NULL) {
258 | add_to_buffer(out_ptr, out, sizeof(CArray));
259 | }
260 |
261 | CArray_XDECREF(self);
262 | return out;
263 | fail:
264 | return NULL;
265 | }
266 |
--------------------------------------------------------------------------------
/kernel/clip.h:
--------------------------------------------------------------------------------
1 | #ifndef CARRAY_CLIP_H
2 | #define CARRAY_CLIP_H
3 |
4 | #include "carray.h"
5 |
6 | CArray * CArray_Clip(CArray * self, CArray * min, CArray * max, MemoryPointer * out);
7 | void DOUBLE_clip(double *in, int ni, double *min, double *max, double *out);
8 | void INT_clip(int *in, int ni, int *min, int *max, int *out);
9 |
10 | #endif //CARRAY_CLIP_H
11 |
--------------------------------------------------------------------------------
/kernel/common/cblas_funcs.h:
--------------------------------------------------------------------------------
1 | #ifndef PHPSCI_EXT_CBLAS_FUNC_H
2 | #define PHPSCI_EXT_CBLAS_FUNC_H
3 |
4 | #include "../carray.h"
5 |
6 | typedef enum {
7 | _scalar,
8 | _column,
9 | _row,
10 | _matrix
11 | } MatrixShape;
12 |
13 | CArray * cblas_matrixproduct(int typenum, CArray * ap1, CArray *ap2, CArray *out, MemoryPointer * ptr);
14 |
15 | #endif //PHPSCI_EXT_CBLAS_FUNC_H
--------------------------------------------------------------------------------
/kernel/common/clblas_funcs.h:
--------------------------------------------------------------------------------
1 | #ifndef PHPSCI_EXT_CLBLAS_FUNC_H
2 | #define PHPSCI_EXT_CLBLAS_FUNC_H
3 |
4 | #include "../carray.h"
5 |
6 | CArray * clblas_matrixproduct(int typenum, CArray * ap1, CArray *ap2, CArray *out, MemoryPointer * ptr);
7 |
8 | #endif //PHPSCI_EXT_CLBLAS_FUNC_H
--------------------------------------------------------------------------------
/kernel/common/common.c:
--------------------------------------------------------------------------------
1 | #include "../carray.h"
2 | #include "common.h"
3 | #include "exceptions.h"
4 | #include "../alloc.h"
5 | #include "mem_overlap.h"
6 |
7 | /**
8 | * @param ap
9 | * @return
10 | */
11 | int
12 | _IsWriteable(CArray *ap)
13 | {
14 | CArray * base = CArray_BASE(ap);
15 |
16 | /* If we own our own data, then no-problem */
17 | if ((base == NULL) || (CArray_FLAGS(ap) & CARRAY_ARRAY_OWNDATA)) {
18 | return 1;
19 | }
20 |
21 | /*
22 | * Get to the final base object
23 | * If it is a writeable array, then return TRUE
24 | * If we can find an array object
25 | * or a writeable buffer object as the final base object
26 | */
27 | return 0;
28 | }
29 |
30 | /*
31 | * Make a new empty array, of the passed size, of a type that takes the
32 | * priority of ap1 and ap2 into account.
33 | *
34 | * If `out` is non-NULL, memory overlap is checked with ap1 and ap2, and an
35 | * updateifcopy temporary array may be returned. If `result` is non-NULL, the
36 | * output array to be returned (`out` if non-NULL and the newly allocated array
37 | * otherwise) is incref'd and put to *result.
38 | */
39 | CArray *
40 | new_array_for_sum(CArray *ap1, CArray *ap2, CArray* out,
41 | int nd, int dimensions[], int typenum, CArray **result)
42 | {
43 | CArray *out_buf;
44 | if (out != NULL) {
45 | int d;
46 |
47 | /* verify that out is usable */
48 | if (CArray_NDIM(out) != nd ||
49 | CArray_TYPE(out) != typenum) {
50 | throw_valueerror_exception(
51 | "output array is not acceptable (must have the right datatype, "
52 | "number of dimensions, and be a C-Array)");
53 | return 0;
54 | }
55 | for (d = 0; d < nd; ++d) {
56 | if (dimensions[d] != CArray_DIM(out, d)) {
57 | throw_valueerror_exception(
58 | "output array has wrong dimensions");
59 | return 0;
60 | }
61 | }
62 |
63 | /* check for memory overlap */
64 | if (!(solve_may_share_memory(out, ap1, 1) == 0 &&
65 | solve_may_share_memory(out, ap2, 1) == 0)) {
66 | /* allocate temporary output array */
67 | out_buf = CArray_NewLikeArray(out, CARRAY_CORDER, NULL, 0);
68 | if (out_buf == NULL) {
69 | return NULL;
70 | }
71 |
72 | /* set copy-back */
73 | CArray_INCREF(out);
74 | if (CArray_SetWritebackIfCopyBase(out_buf, out) < 0) {
75 | CArray_XDECREF(out);
76 | CArray_XDECREF(out_buf);
77 | return NULL;
78 | }
79 | }
80 | else {
81 | CArray_INCREF(out);
82 | out_buf = out;
83 | }
84 |
85 | if (result) {
86 | CArray_INCREF(out);
87 | *result = out;
88 | }
89 |
90 | return out_buf;
91 | }
92 | else {
93 | CArray * subtype;
94 | double prior1, prior2;
95 | out_buf = (CArray *)emalloc(sizeof(CArray));
96 |
97 | prior1 = prior2 = 0.0;
98 | subtype = ap1;
99 |
100 | out_buf = CArray_New(out_buf, nd, dimensions,
101 | typenum, NULL, NULL, 0, 0,
102 | NULL);
103 |
104 | return out_buf;
105 | }
106 | }
107 |
108 |
109 |
110 |
--------------------------------------------------------------------------------
/kernel/common/common.h:
--------------------------------------------------------------------------------
1 | #ifndef PHPSCI_EXT_COMMON_H
2 | #define PHPSCI_EXT_COMMON_H
3 |
4 | #include "../carray.h"
5 | #include "../assign.h"
6 |
7 | # define CARRAY_LONGLONG_SUFFIX(x) (x##L)
8 | # define CARRAY_ULONGLONG_SUFFIX(x) (x##UL)
9 |
10 | /*
11 | * numarray-style bit-width typedefs
12 | */
13 | #define CARRAY_MAX_INT8 127
14 | #define CARRAY_MIN_INT8 -128
15 | #define CARRAY_MAX_UINT8 255
16 | #define CARRAY_MAX_INT16 32767
17 | #define CARRAY_MIN_INT16 -32768
18 | #define CARRAY_MAX_UINT16 65535
19 | #define CARRAY_MAX_INT32 2147483647
20 | #define CARRAY_MIN_INT32 (-CARRAY_MAX_INT32 - 1)
21 | #define CARRAY_MAX_UINT32 4294967295U
22 | #define CARRAY_MAX_INT64 CARRAY_LONGLONG_SUFFIX(9223372036854775807)
23 | #define CARRAY_MIN_INT64 (-CARRAY_MAX_INT64 - CARRAY_LONGLONG_SUFFIX(1))
24 | #define CARRAY_MAX_UINT64 CARRAY_ULONGLONG_SUFFIX(18446744073709551615)
25 | #define CARRAY_MAX_INT128 CARRAY_LONGLONG_SUFFIX(85070591730234615865843651857942052864)
26 | #define CARRAY_MIN_INT128 (-CARRAY_MAX_INT128 - CARRAY_LONGLONG_SUFFIX(1))
27 | #define CARRAY_MAX_UINT128 CARRAY_ULONGLONG_SUFFIX(170141183460469231731687303715884105728)
28 | #define CARRAY_MAX_INT256 CARRAY_LONGLONG_SUFFIX(57896044618658097711785492504343953926634992332820282019728792003956564819967)
29 | #define CARRAY_MIN_INT256 (-CARRAY_MAX_INT256 - CARRAY_LONGLONG_SUFFIX(1))
30 | #define CARRAY_MAX_UINT256 CARRAY_ULONGLONG_SUFFIX(115792089237316195423570985008687907853269984665640564039457584007913129639935)
31 | #define CARRAY_MIN_DATETIME CARRAY_MIN_INT64
32 | #define CARRAY_MAX_DATETIME CARRAY_MAX_INT64
33 | #define CARRAY_MIN_TIMEDELTA CARRAY_MIN_INT64
34 | #define CARRAY_MAX_TIMEDELTA CARRAY_MAX_INT64
35 | #define CARRAY_MAX_INT INT_MAX
36 | #define CARRAY_MAX_INTP CARRAY_MAX_INT
37 |
38 |
39 | #if CARRAY_MAX_INTP > INT_MAX
40 | # define CARRAY_CBLAS_CHUNK (INT_MAX / 2 + 1)
41 | #else
42 | # define CARRAY_CBLAS_CHUNK CARRAY_MAX_INTP
43 | #endif
44 |
45 |
46 | /*
47 | * Convert CArray stride to BLAS stride. Returns 0 if conversion cannot be done
48 | * (BLAS won't handle negative or zero strides the way we want).
49 | */
50 | static inline int
51 | blas_stride(int stride, unsigned itemsize)
52 | {
53 | if (stride > 0 && carray_is_aligned((void*)&stride, itemsize)) {
54 | stride /= itemsize;
55 | if (stride <= INT_MAX) {
56 | return stride;
57 | }
58 | }
59 | return 0;
60 | }
61 |
62 | /* used for some alignment checks */
63 | #define _ALIGN(type) offsetof(struct {char c; type v;}, v)
64 | #define _UINT_ALIGN(type) carray_uint_alignment(sizeof(type))
65 |
66 | /* Get equivalent "uint" alignment given an itemsize, for use in copy code */
67 | static inline int
68 | carray_uint_alignment(int itemsize)
69 | {
70 | int alignment = 0; /* return value of 0 means unaligned */
71 |
72 | switch(itemsize){
73 | case 1:
74 | return 1;
75 | case 2:
76 | alignment = _ALIGN(uint16_t);
77 | break;
78 | case 4:
79 | alignment = _ALIGN(uint32_t);
80 | break;
81 | case 8:
82 | alignment = _ALIGN(uint64_t);
83 | break;
84 | case 16:
85 | /*
86 | * 16 byte types are copied using 2 uint64 assignments.
87 | * See the strided copy function in lowlevel_strided_loops.c.
88 | */
89 | alignment = _ALIGN(uint64_t);
90 | break;
91 | default:
92 | break;
93 | }
94 | return alignment;
95 | }
96 |
97 | /*
98 | * Returns -1 and sets an exception if *index is an invalid index for
99 | * an array of size max_item, otherwise adjusts it in place to be
100 | * 0 <= *index < max_item, and returns 0.
101 | * 'axis' should be the array axis that is being indexed over, if known. If
102 | * unknown, use -1.
103 | * If _save is NULL it is assumed the GIL is taken
104 | * If _save is not NULL it is assumed the GIL is not taken and it
105 | * is acquired in the case of an error
106 | */
107 | static inline int
108 | check_and_adjust_index(int *index, int max_item, int axis)
109 | {
110 | /* Check that index is valid, taking into account negative indices */
111 | if (CARRAY_UNLIKELY((*index < -max_item) || (*index >= max_item))) {
112 | /* Try to be as clear as possible about what went wrong. */
113 | if (axis >= 0) {
114 | throw_indexerror_exception("index is out of bounds for axis");
115 | } else {
116 | throw_indexerror_exception("index is out of bounds for size");
117 | }
118 | return -1;
119 | }
120 | /* adjust negative indices */
121 | if (*index < 0) {
122 | *index += max_item;
123 | }
124 | return 0;
125 | }
126 |
127 |
128 |
129 |
130 | CArray * new_array_for_sum(CArray *ap1, CArray *ap2, CArray* out,
131 | int nd, int dimensions[], int typenum, CArray **result);
132 | int _IsWriteable(CArray *ap);
133 | #endif //PHPSCI_EXT_COMMON_H
--------------------------------------------------------------------------------
/kernel/common/compare.c:
--------------------------------------------------------------------------------
1 | #include "compare.h"
2 | #include "../carray.h"
3 |
4 | int
5 | INT_compare (int *pa, int *pb, CArray *CARRAY_UNUSED(ap))
6 | {
7 | const int a = *pa;
8 | const int b = *pb;
9 |
10 | return a < b ? -1 : a == b ? 0 : 1;
11 | }
12 |
13 | #define LT(a,b) ((a) < (b) || ((b) != (b) && (a) ==(a)))
14 |
15 | int
16 | DOUBLE_compare(double *pa, double *pb)
17 | {
18 | const double a = *pa;
19 | const double b = *pb;
20 | int ret;
21 |
22 | if (LT(a,b)) {
23 | ret = -1;
24 | }
25 | else if (LT(b,a)) {
26 | ret = 1;
27 | }
28 | else {
29 | ret = 0;
30 | }
31 | return ret;
32 | }
33 |
--------------------------------------------------------------------------------
/kernel/common/compare.h:
--------------------------------------------------------------------------------
1 | #ifndef CARRAY_COMPARE_H
2 | #define CARRAY_COMPARE_H
3 |
4 | #include "../carray.h"
5 |
6 | int DOUBLE_compare(double *pa, double *pb);
7 | int INT_compare (int *pa, int *pb, CArray *CARRAY_UNUSED(ap));
8 |
9 | #endif //CARRAY_COMPARE_H
10 |
--------------------------------------------------------------------------------
/kernel/common/exceptions.c:
--------------------------------------------------------------------------------
1 | #include "php.h"
2 | #include "exceptions.h"
3 | #include "Zend/zend_exceptions.h"
4 |
5 | static zend_class_entry * phpsci_ce_CArrayAxisException;
6 | static zend_class_entry * phpsci_ce_CArrayValueErrorException;
7 | static zend_class_entry * phpsci_ce_CArrayTypeErrorException;
8 | static zend_class_entry * phpsci_ce_CArrayOverflowException;
9 | static zend_class_entry * phpsci_ce_CArrayMemoryException;
10 | static zend_class_entry * phpsci_ce_CArrayNotImplementedException;
11 | static zend_class_entry * phpsci_ce_CArrayIndexErrorException;
12 |
13 | static const zend_function_entry phpsci_ce_CArrayAxisException_methods[] = {
14 | PHP_FE_END
15 | };
16 | static const zend_function_entry phpsci_ce_CArrayValueErrorException_methods[] = {
17 | PHP_FE_END
18 | };
19 | static const zend_function_entry phpsci_ce_CArrayTypeErrorException_methods[] = {
20 | PHP_FE_END
21 | };
22 |
23 | static const zend_function_entry phpsci_ce_CArrayOverflowException_methods[] = {
24 | PHP_FE_END
25 | };
26 |
27 | static const zend_function_entry phpsci_ce_CArrayMemoryException_methods[] = {
28 | PHP_FE_END
29 | };
30 |
31 | static const zend_function_entry phpsci_ce_CArrayNotImplementedException_methods[] = {
32 | PHP_FE_END
33 | };
34 |
35 | static const zend_function_entry phpsci_ce_CArrayIndexErrorException_methods[] = {
36 | PHP_FE_END
37 | };
38 |
39 | /**
40 | * Initialize Exception Classes
41 | */
42 | void
43 | init_exception_objects()
44 | {
45 | zend_class_entry ce;
46 | INIT_CLASS_ENTRY(ce, "CArrayAxisException", phpsci_ce_CArrayAxisException_methods);
47 | phpsci_ce_CArrayAxisException = zend_register_internal_class_ex(&ce, zend_ce_exception);
48 | INIT_CLASS_ENTRY(ce, "CArrayValueErrorException", phpsci_ce_CArrayAxisException_methods);
49 | phpsci_ce_CArrayValueErrorException = zend_register_internal_class_ex(&ce, zend_ce_exception);
50 | INIT_CLASS_ENTRY(ce, "CArrayTypeErrorException", phpsci_ce_CArrayAxisException_methods);
51 | phpsci_ce_CArrayTypeErrorException = zend_register_internal_class_ex(&ce, zend_ce_exception);
52 | INIT_CLASS_ENTRY(ce, "CArrayOverflowException", phpsci_ce_CArrayOverflowException_methods);
53 | phpsci_ce_CArrayTypeErrorException = zend_register_internal_class_ex(&ce, zend_ce_exception);
54 | INIT_CLASS_ENTRY(ce, "CArrayMemoryException", phpsci_ce_CArrayMemoryException_methods);
55 | phpsci_ce_CArrayMemoryException = zend_register_internal_class_ex(&ce, zend_ce_exception);
56 | INIT_CLASS_ENTRY(ce, "CArrayNotImplementedException", phpsci_ce_CArrayNotImplementedException_methods);
57 | phpsci_ce_CArrayNotImplementedException = zend_register_internal_class_ex(&ce, zend_ce_exception);
58 | INIT_CLASS_ENTRY(ce, "CArrayIndexErrorException", phpsci_ce_CArrayIndexErrorException_methods);
59 | phpsci_ce_CArrayIndexErrorException = zend_register_internal_class_ex(&ce, zend_ce_exception);
60 | }
61 |
62 | /**
63 | * Throw CArrayAxisException
64 | */
65 | void
66 | throw_notimplemented_exception()
67 | {
68 | zend_throw_exception_ex(phpsci_ce_CArrayNotImplementedException, NOTIMPLEMENTED_EXCEPTION, "%s",
69 | "Whoops! Looks like this situation was unexpected.");
70 | }
71 |
72 | /**
73 | * Throw CArrayAxisException
74 | */
75 | void
76 | throw_memory_exception(char * msg)
77 | {
78 | zend_throw_exception_ex(phpsci_ce_CArrayMemoryException, MEMORY_EXCEPTION, "%s", msg);
79 | }
80 |
81 | /**
82 | * Throw CArrayAxisException
83 | */
84 | void
85 | throw_axis_exception(char * msg)
86 | {
87 | zend_throw_exception_ex(phpsci_ce_CArrayAxisException, AXIS_EXCEPTION, "%s", msg);
88 | }
89 |
90 | /**
91 | * Throw ValueErrorException
92 | */
93 | void
94 | throw_valueerror_exception(char * msg)
95 | {
96 | zend_throw_exception_ex(phpsci_ce_CArrayValueErrorException, VALUEERROR_EXCEPTION, "%s", msg);
97 | }
98 |
99 | /**
100 | * Throw TypeErrorException
101 | */
102 | void
103 | throw_typeerror_exception(char * msg)
104 | {
105 | zend_throw_exception_ex(phpsci_ce_CArrayTypeErrorException, TYPEERROR_EXCEPTION, "%s", msg);
106 | }
107 |
108 | /**
109 | * Throw OverflowException
110 | * @param msg
111 | */
112 | void
113 | throw_overflow_exception(char * msg)
114 | {
115 | zend_throw_exception_ex(phpsci_ce_CArrayOverflowException, OVERFLOW_EXCEPTION, "%s", msg);
116 | }
117 |
118 | /**
119 | * Throw IndexErrorException
120 | * @param msg
121 | */
122 | void
123 | throw_indexerror_exception(char * msg)
124 | {
125 | zend_throw_exception_ex(phpsci_ce_CArrayIndexErrorException, INDEXERROR_EXCEPTION, "%s", msg);
126 | }
127 |
128 |
--------------------------------------------------------------------------------
/kernel/common/exceptions.h:
--------------------------------------------------------------------------------
1 | #ifndef PHPSCI_EXT_EXCEPTIONS_H
2 | #define PHPSCI_EXT_EXCEPTIONS_H
3 |
4 | #define AXIS_EXCEPTION 5000
5 | #define VALUEERROR_EXCEPTION 5001
6 | #define TYPEERROR_EXCEPTION 5002
7 | #define OVERFLOW_EXCEPTION 5003
8 | #define MEMORY_EXCEPTION 5004
9 | #define NOTIMPLEMENTED_EXCEPTION 5005
10 | #define INDEXERROR_EXCEPTION 5006
11 |
12 | void init_exception_objects();
13 | void throw_axis_exception(char * msg);
14 | void throw_valueerror_exception(char * msg);
15 | void throw_typeerror_exception(char * msg);
16 | void throw_overflow_exception(char * msg);
17 | void throw_memory_exception(char * msg);
18 | void throw_notimplemented_exception();
19 | void throw_indexerror_exception(char * msg);
20 | #endif //PHPSCI_EXT_EXCEPTIONS_H
--------------------------------------------------------------------------------
/kernel/common/matmul.h:
--------------------------------------------------------------------------------
1 | #ifndef CARRAY_MATMUL_H
2 | #define CARRAY_MATMUL_H
3 |
4 | #include "../carray.h"
5 |
6 | void DOUBLE_matmul(char **args, int *dimensions, int *steps, void *CARRAY_UNUSED(func));
7 | void INT_matmul(char **args, int *dimensions, int *steps, void *CARRAY_UNUSED(func));
8 | #endif //CARRAY_MATMUL_H
9 |
--------------------------------------------------------------------------------
/kernel/common/mem_overlap.h:
--------------------------------------------------------------------------------
1 | /*
2 | Original File
3 | Copyright (c) NumPy (/numpy/core/src/common/mem_overlap.c)
4 |
5 | Edited for CArrays in 2018
6 | Henrique Borba
7 | henrique.borba.dev@gmail.com
8 |
9 | Solving memory overlap integer programs and bounded Diophantine equations with
10 | positive coefficients.
11 | Asking whether two strided arrays `a` and `b` overlap is equivalent to
12 | asking whether there is a solution to the following problem::
13 | sum(stride_a[i] * x_a[i] for i in range(ndim_a))
14 | -
15 | sum(stride_b[i] * x_b[i] for i in range(ndim_b))
16 | ==
17 | base_b - base_a
18 |
19 | 0 <= x_a[i] < shape_a[i]
20 |
21 | 0 <= x_b[i] < shape_b[i]
22 |
23 | for some integer x_a, x_b. Itemsize needs to be considered as an additional
24 | dimension with stride 1 and size itemsize.
25 | Negative strides can be changed to positive (and vice versa) by changing
26 | variables x[i] -> shape[i] - 1 - x[i], and zero strides can be dropped, so
27 | that the problem can be recast into a bounded Diophantine equation with
28 | positive coefficients::
29 |
30 | sum(a[i] * x[i] for i in range(n)) == b
31 |
32 | a[i] > 0
33 |
34 | 0 <= x[i] <= ub[i]
35 |
36 | This problem is NP-hard --- runtime of algorithms grows exponentially with
37 | increasing ndim.
38 | *Algorithm description*
39 | A straightforward algorithm that excludes infeasible solutions using GCD-based
40 | pruning is outlined in Ref. [1]. It is implemented below. A number of other
41 | algorithms exist in the literature; however, this one seems to have
42 | performance satisfactory for the present purpose.
43 | The idea is that an equation::
44 |
45 | a_1 x_1 + a_2 x_2 + ... + a_n x_n = b
46 |
47 | 0 <= x_i <= ub_i, i = 1...n
48 |
49 | implies::
50 |
51 | a_2' x_2' + a_3 x_3 + ... + a_n x_n = b
52 |
53 | 0 <= x_i <= ub_i, i = 2...n
54 |
55 | 0 <= x_1' <= c_1 ub_1 + c_2 ub_2
56 |
57 | with a_2' = gcd(a_1, a_2) and x_2' = c_1 x_1 + c_2 x_2 with c_1 = (a_1/a_1'),
58 | and c_2 = (a_2/a_1'). This procedure can be repeated to obtain::
59 |
60 | a_{n-1}' x_{n-1}' + a_n x_n = b
61 |
62 | 0 <= x_{n-1}' <= ub_{n-1}'
63 |
64 | 0 <= x_n <= ub_n
65 |
66 | Now, one can enumerate all candidate solutions for x_n. For each, one can use
67 | the previous-level equation to enumerate potential solutions for x_{n-1}, with
68 | transformed right-hand side b -> b - a_n x_n. And so forth, until after n-1
69 | nested for loops we either arrive at a candidate solution for x_1 (in which
70 | case we have found one solution to the problem), or find that the equations do
71 | not allow any solutions either for x_1 or one of the intermediate x_i (in
72 | which case we have proved there is no solution for the upper-level candidates
73 | chosen). If no solution is found for any candidate x_n, we have proved the
74 | problem is infeasible --- which for the memory overlap problem means there is
75 | no overlap.
76 | */
77 |
78 | #ifndef PHPSCI_EXT_MEM_OVERLAP_H
79 | #define PHPSCI_EXT_MEM_OVERLAP_H
80 |
81 | #include "../carray.h"
82 |
83 | /* Bounds check only */
84 | #define CARRAY_MAY_SHARE_BOUNDS 0
85 |
86 | /* Exact solution */
87 | #define CARRAY_MAY_SHARE_EXACT -1
88 |
89 |
90 | typedef enum {
91 | MEM_OVERLAP_NO = 0, /* no solution exists */
92 | MEM_OVERLAP_YES = 1, /* solution found */
93 | MEM_OVERLAP_TOO_HARD = -1, /* max_work exceeded */
94 | MEM_OVERLAP_OVERFLOW = -2, /* algorithm failed due to integer overflow */
95 | MEM_OVERLAP_ERROR = -3 /* invalid input */
96 | } mem_overlap_t;
97 |
98 |
99 | typedef struct {
100 | int64_t a;
101 | int64_t ub;
102 | } diophantine_term_t;
103 |
104 | mem_overlap_t solve_may_share_memory(CArray *a, CArray *b, size_t max_work);
105 |
106 | #endif //PHPSCI_EXT_MEM_OVERLAP_H
--------------------------------------------------------------------------------
/kernel/common/partition.h:
--------------------------------------------------------------------------------
1 | #ifndef CARRAY_PARTITION_H
2 | #define CARRAY_PARTITION_H
3 |
4 | #define CARRAY_MAX_PIVOT_STACK 50
5 |
6 | #endif //CARRAY_PARTITION_H
7 |
--------------------------------------------------------------------------------
/kernel/common/sort.c:
--------------------------------------------------------------------------------
1 | #include "sort.h"
2 | #include "../carray.h"
3 |
4 | int
5 | carray_heapsort(void *start, int num, void *varr)
6 | {
7 | CArray *arr = varr;
8 | int elsize = CArray_ITEMSIZE(arr);
9 | CArray_CompareFunc *cmp = CArray_DESCR(arr)->f->compare;
10 | char *tmp = emalloc(elsize);
11 | char *a = (char *)start - elsize;
12 | int i, j, l;
13 |
14 | if (tmp == NULL) {
15 | return -CARRAY_ENOMEM;
16 | }
17 |
18 | for (l = num >> 1; l > 0; --l) {
19 | GENERIC_COPY(tmp, a + l*elsize, elsize);
20 | for (i = l, j = l << 1; j <= num;) {
21 | if (j < num && cmp(a + j*elsize, a + (j+1)*elsize, arr) < 0) {
22 | ++j;
23 | }
24 | if (cmp(tmp, a + j*elsize, arr) < 0) {
25 | GENERIC_COPY(a + i*elsize, a + j*elsize, elsize);
26 | i = j;
27 | j += j;
28 | }
29 | else {
30 | break;
31 | }
32 | }
33 | GENERIC_COPY(a + i*elsize, tmp, elsize);
34 | }
35 |
36 | for (; num > 1;) {
37 | GENERIC_COPY(tmp, a + num*elsize, elsize);
38 | GENERIC_COPY(a + num*elsize, a + elsize, elsize);
39 | num -= 1;
40 | for (i = 1, j = 2; j <= num;) {
41 | if (j < num && cmp(a + j*elsize, a + (j+1)*elsize, arr) < 0) {
42 | ++j;
43 | }
44 | if (cmp(tmp, a + j*elsize, arr) < 0) {
45 | GENERIC_COPY(a + i*elsize, a + j*elsize, elsize);
46 | i = j;
47 | j += j;
48 | }
49 | else {
50 | break;
51 | }
52 | }
53 | GENERIC_COPY(a + i*elsize, tmp, elsize);
54 | }
55 |
56 | efree(tmp);
57 | return 0;
58 | }
59 |
60 | int
61 | carray_quicksort(void *start, int num, void *varr)
62 | {
63 | CArray *arr = varr;
64 | int elsize = CArray_ITEMSIZE(arr);
65 | CArray_CompareFunc *cmp = CArray_DESCR(arr)->f->compare;
66 | char *vp;
67 | char *pl = start;
68 | char *pr = pl + (num - 1)*elsize;
69 | char *stack[QS_STACK];
70 | char **sptr = stack;
71 | char *pm, *pi, *pj, *pk;
72 | int depth[QS_STACK];
73 | int * psdepth = depth;
74 | int cdepth = carray_get_msb(num) * 2;
75 |
76 | /* Items that have zero size don't make sense to sort */
77 | if (elsize == 0) {
78 | return 0;
79 | }
80 |
81 | vp = emalloc(elsize);
82 | if (vp == NULL) {
83 | return -CARRAY_ENOMEM;
84 | }
85 |
86 | for (;;) {
87 |
88 | if (CARRAY_UNLIKELY(cdepth < 0)) {
89 | carray_heapsort(pl, (pr - pl) / elsize + 1, varr);
90 | goto stack_pop;
91 | }
92 | while(pr - pl > SMALL_QUICKSORT*elsize) {
93 |
94 | /* quicksort partition */
95 | pm = pl + (((pr - pl) / elsize) >> 1) * elsize;
96 | if (cmp(pm, pl, arr) < 0) {
97 | GENERIC_SWAP(pm, pl, elsize);
98 | }
99 | if (cmp(pr, pm, arr) < 0) {
100 | GENERIC_SWAP(pr, pm, elsize);
101 | }
102 | if (cmp(pm, pl, arr) < 0) {
103 | GENERIC_SWAP(pm, pl, elsize);
104 | }
105 | GENERIC_COPY(vp, pm, elsize);
106 | pi = pl;
107 | pj = pr - elsize;
108 | GENERIC_SWAP(pm, pj, elsize);
109 | /*
110 | * Generic comparisons may be buggy, so don't rely on the sentinels
111 | * to keep the pointers from going out of bounds.
112 | */
113 | for (;;) {
114 | do {
115 | pi += elsize;
116 | } while (cmp(pi, vp, arr) < 0 && pi < pj);
117 | do {
118 | pj -= elsize;
119 | } while (cmp(vp, pj, arr) < 0 && pi < pj);
120 | if (pi >= pj) {
121 | break;
122 | }
123 | GENERIC_SWAP(pi, pj, elsize);
124 | }
125 | pk = pr - elsize;
126 | GENERIC_SWAP(pi, pk, elsize);
127 | /* push largest partition on stack */
128 | if (pi - pl < pr - pi) {
129 | *sptr++ = pi + elsize;
130 | *sptr++ = pr;
131 | pr = pi - elsize;
132 | }
133 | else {
134 | *sptr++ = pl;
135 | *sptr++ = pi - elsize;
136 | pl = pi + elsize;
137 | }
138 | *psdepth++ = --cdepth;
139 | }
140 |
141 | /* insertion sort */
142 | for (pi = pl + elsize; pi <= pr; pi += elsize) {
143 | GENERIC_COPY(vp, pi, elsize);
144 | pj = pi;
145 | pk = pi - elsize;
146 | while (pj > pl && cmp(vp, pk, arr) < 0) {
147 | GENERIC_COPY(pj, pk, elsize);
148 | pj -= elsize;
149 | pk -= elsize;
150 | }
151 | GENERIC_COPY(pj, vp, elsize);
152 | }
153 | stack_pop:
154 | if (sptr == stack) {
155 | break;
156 | }
157 | pr = *(--sptr);
158 | pl = *(--sptr);
159 | cdepth = *(--psdepth);
160 | }
161 |
162 | efree(vp);
163 | return 0;
164 | }
165 |
166 | static void
167 | carray_mergesort0(char *pl, char *pr, char *pw, char *vp, int elsize,
168 | CArray_CompareFunc *cmp, CArray *arr)
169 | {
170 | char *pi, *pj, *pk, *pm;
171 |
172 | if (pr - pl > SMALL_MERGESORT*elsize) {
173 | /* merge sort */
174 | pm = pl + (((pr - pl)/elsize) >> 1)*elsize;
175 | carray_mergesort0(pl, pm, pw, vp, elsize, cmp, arr);
176 | carray_mergesort0(pm, pr, pw, vp, elsize, cmp, arr);
177 | GENERIC_COPY(pw, pl, pm - pl);
178 | pi = pw + (pm - pl);
179 | pj = pw;
180 | pk = pl;
181 | while (pj < pi && pm < pr) {
182 | if (cmp(pm, pj, arr) < 0) {
183 | GENERIC_COPY(pk, pm, elsize);
184 | pm += elsize;
185 | pk += elsize;
186 | }
187 | else {
188 | GENERIC_COPY(pk, pj, elsize);
189 | pj += elsize;
190 | pk += elsize;
191 | }
192 | }
193 | GENERIC_COPY(pk, pj, pi - pj);
194 | }
195 | else {
196 | /* insertion sort */
197 | for (pi = pl + elsize; pi < pr; pi += elsize) {
198 | GENERIC_COPY(vp, pi, elsize);
199 | pj = pi;
200 | pk = pi - elsize;
201 | while (pj > pl && cmp(vp, pk, arr) < 0) {
202 | GENERIC_COPY(pj, pk, elsize);
203 | pj -= elsize;
204 | pk -= elsize;
205 | }
206 | GENERIC_COPY(pj, vp, elsize);
207 | }
208 | }
209 | }
210 |
211 | int
212 | carray_mergesort(void *start, int num, void *varr)
213 | {
214 | CArray *arr = varr;
215 | int elsize = CArray_ITEMSIZE(arr);
216 | CArray_CompareFunc *cmp = CArray_DESCR(arr)->f->compare;
217 | char *pl = start;
218 | char *pr = pl + num*elsize;
219 | char *pw;
220 | char *vp;
221 | int err = -CARRAY_ENOMEM;
222 |
223 | /* Items that have zero size don't make sense to sort */
224 | if (elsize == 0) {
225 | return 0;
226 | }
227 |
228 | pw = emalloc((num >> 1) *elsize);
229 | vp = emalloc(elsize);
230 |
231 | if (pw != NULL && vp != NULL) {
232 | carray_mergesort0(pl, pr, pw, vp, elsize, cmp, arr);
233 | err = 0;
234 | }
235 |
236 | efree(vp);
237 | efree(pw);
238 |
239 | return err;
240 | }
241 |
--------------------------------------------------------------------------------
/kernel/common/sort.h:
--------------------------------------------------------------------------------
1 | #ifndef CARRAY_SORT_H
2 | #define CARRAY_SORT_H
3 |
4 | #include "stdio.h"
5 | #include "string.h"
6 |
7 | #define QS_STACK 100
8 | #define SMALL_QUICKSORT 15
9 | #define SMALL_MERGESORT 20
10 | #define SMALL_STRING 16
11 |
12 | #define CARRAY_ENOMEM 1
13 | #define CARRAY_ECOMP 2
14 |
15 | static inline int carray_get_msb(int unum)
16 | {
17 | int depth_limit = 0;
18 | while (unum >>= 1) {
19 | depth_limit++;
20 | }
21 | return depth_limit;
22 | }
23 |
24 | inline static void
25 | GENERIC_SWAP(char *a, char *b, size_t len)
26 | {
27 | while(len--) {
28 | const char t = *a;
29 | *a++ = *b;
30 | *b++ = t;
31 | }
32 | }
33 |
34 | inline static void
35 | GENERIC_COPY(char *a, char *b, size_t len)
36 | {
37 | memcpy(a, b, len);
38 | }
39 |
40 |
41 | /*
42 | *****************************************************************************
43 | ** GENERIC SORT **
44 | *****************************************************************************
45 | */
46 | int carray_quicksort(void *vec, int cnt, void *arr);
47 | int carray_heapsort(void *vec, int cnt, void *arr);
48 | int carray_mergesort(void *vec, int cnt, void *arr);
49 | int carray_timsort(void *vec, int cnt, void *arr);
50 | int carray_aquicksort(void *vec, int *ind, int cnt, void *arr);
51 | int carray_aheapsort(void *vec, int *ind, int cnt, void *arr);
52 | int carray_amergesort(void *vec, int *ind, int cnt, void *arr);
53 | int carray_atimsort(void *vec, int *ind, int cnt, void *arr);
54 |
55 | #endif //CARRAY_SORT_H
56 |
--------------------------------------------------------------------------------
/kernel/common/strided_loops.h:
--------------------------------------------------------------------------------
1 | #ifndef PHPSCI_EXT_STRIDE_LOOPS_H
2 | #define PHPSCI_EXT_STRIDE_LOOPS_H
3 |
4 | #include "../carray.h"
5 | #include "common.h"
6 |
7 | /* byte swapping functions */
8 | static inline uint16_t
9 | carray_bswap2(uint16_t x)
10 | {
11 | return ((x & 0xffu) << 8) | (x >> 8);
12 | }
13 |
14 | /*
15 | * treat as int16 and byteswap unaligned memory,
16 | * some cpus don't support unaligned access
17 | */
18 | static inline void
19 | carray_bswap2_unaligned(char * x)
20 | {
21 | char a = x[0];
22 | x[0] = x[1];
23 | x[1] = a;
24 | }
25 |
26 | static inline uint32_t
27 | carray_bswap4(uint32_t x)
28 | {
29 | #ifdef HAVE___BUILTIN_BSWAP32
30 | return __builtin_bswap32(x);
31 | #else
32 | return ((x & 0xffu) << 24) | ((x & 0xff00u) << 8) |
33 | ((x & 0xff0000u) >> 8) | (x >> 24);
34 | #endif
35 | }
36 |
37 | static inline void
38 | carray_bswap4_unaligned(char * x)
39 | {
40 | char a = x[0];
41 | x[0] = x[3];
42 | x[3] = a;
43 | a = x[1];
44 | x[1] = x[2];
45 | x[2] = a;
46 | }
47 |
48 | static inline uint64_t
49 | carray_bswap8(uint64_t x)
50 | {
51 | #ifdef HAVE___BUILTIN_BSWAP64
52 | return __builtin_bswap64(x);
53 | #else
54 | return ((x & 0xffULL) << 56) |
55 | ((x & 0xff00ULL) << 40) |
56 | ((x & 0xff0000ULL) << 24) |
57 | ((x & 0xff000000ULL) << 8) |
58 | ((x & 0xff00000000ULL) >> 8) |
59 | ((x & 0xff0000000000ULL) >> 24) |
60 | ((x & 0xff000000000000ULL) >> 40) |
61 | ( x >> 56);
62 | #endif
63 | }
64 |
65 | static inline void
66 | carray_bswap8_unaligned(char * x)
67 | {
68 | char a = x[0]; x[0] = x[7]; x[7] = a;
69 | a = x[1]; x[1] = x[6]; x[6] = a;
70 | a = x[2]; x[2] = x[5]; x[5] = a;
71 | a = x[3]; x[3] = x[4]; x[4] = a;
72 | }
73 |
74 | /* Start raw iteration */
75 | #define CARRAY_RAW_ITER_START(idim, ndim, coord, shape) \
76 | memset((coord), 0, (ndim) * sizeof(coord[0])); \
77 | do {
78 |
79 |
80 | /* Increment to the next n-dimensional coordinate for one raw array */
81 | #define CARRAY_RAW_ITER_ONE_NEXT(idim, ndim, coord, shape, data, strides) \
82 | for ((idim) = 1; (idim) < (ndim); ++(idim)) { \
83 | if (++(coord)[idim] == (shape)[idim]) { \
84 | (coord)[idim] = 0; \
85 | (data) -= ((shape)[idim] - 1) * (strides)[idim]; \
86 | } \
87 | else { \
88 | (data) += (strides)[idim]; \
89 | break; \
90 | } \
91 | } \
92 | } while ((idim) < (ndim))
93 |
94 | /*
95 | * This function pointer is for unary operations that input an
96 | * arbitrarily strided one-dimensional array segment and output
97 | * an arbitrarily strided array segment of the same size.
98 | * It may be a fully general function, or a specialized function
99 | * when the strides or item size have particular known values.
100 | *
101 | * Examples of unary operations are a straight copy, a byte-swap,
102 | * and a casting operation,
103 | *
104 | * The 'transferdata' parameter is slightly special, following a
105 | * generic auxiliary data pattern defined in carray.h
106 | * Use CARRAY_AUXDATA_CLONE and CARRAY_AUXDATA_FREE to deal with this data.
107 | *
108 | */
109 | typedef void (CArray_StridedUnaryOp)(char *dst, int dst_stride,
110 | char *src, int src_stride,
111 | int N, int src_itemsize,
112 | CArrayAuxData *transferdata);
113 |
114 |
115 | /*
116 | * Gives back a function pointer to a specialized function for copying
117 | * strided memory. Returns NULL if there is a problem with the inputs.
118 | *
119 | * aligned:
120 | * Should be 1 if the src and dst pointers always point to
121 | * locations at which a uint of equal size to dtype->elsize
122 | * would be aligned, 0 otherwise.
123 | * src_stride:
124 | * Should be the src stride if it will always be the same,
125 | * MAX_INT otherwise.
126 | * dst_stride:
127 | * Should be the dst stride if it will always be the same,
128 | * MAX_INT otherwise.
129 | * itemsize:
130 | * Should be the item size if it will always be the same, 0 otherwise.
131 | *
132 | */
133 | CArray_StridedUnaryOp * CArray_GetStridedCopyFn(int aligned, int src_stride, int dst_stride, int itemsize);
134 | CArray_StridedUnaryOp * CArray_GetStridedNumericCastFn(int aligned, int src_stride,
135 | int dst_stride,
136 | int src_type_num, int dst_type_num);
137 | #endif //PHPSCI_EXT_STRIDE_LOOPS_H
--------------------------------------------------------------------------------
/kernel/conversion_utils.c:
--------------------------------------------------------------------------------
1 | #include "carray.h"
2 | #include "conversion_utils.h"
3 |
4 | /*
5 | * Converts an axis parameter into an ndim-length C-array of
6 | * boolean flags, True for each axis specified.
7 | *
8 | * If obj is None or NULL, everything is set to True. If obj is a tuple,
9 | * each axis within the tuple is set to True. If obj is an integer,
10 | * just that axis is set to True.
11 | */
12 | int
13 | CArray_ConvertMultiAxis(int *axis_in, int ndim, int *out_axis_flags)
14 | {
15 | /* INT_MAX means all of the axes */
16 | if (*axis_in == INT_MAX || axis_in == NULL) {
17 | memset(out_axis_flags, 1, ndim);
18 | return CARRAY_SUCCEED;
19 | }
20 | /* Try to interpret axis as an integer */
21 | else {
22 | int axis;
23 | axis = axis_in[0];
24 |
25 | memset(out_axis_flags, 0, ndim);
26 |
27 | /*
28 | * Special case letting axis={-1,0} slip through for scalars,
29 | * for backwards compatibility reasons.
30 | */
31 | if (ndim == 0 && (axis == 0 || axis == -1)) {
32 | return CARRAY_SUCCEED;
33 | }
34 |
35 | if (check_and_adjust_axis(&axis, ndim) < 0) {
36 | return CARRAY_FAIL;
37 | }
38 |
39 | out_axis_flags[axis] = 1;
40 |
41 | return CARRAY_SUCCEED;
42 | }
43 | }
--------------------------------------------------------------------------------
/kernel/conversion_utils.h:
--------------------------------------------------------------------------------
1 | #ifndef PHPSCI_EXT_CONVERSION_UTILS_H
2 | #define PHPSCI_EXT_CONVERSION_UTILS_H
3 |
4 | #include "carray.h"
5 |
6 | int CArray_ConvertMultiAxis(int *axis_in, int ndim, int *out_axis_flags);
7 |
8 | #endif
--------------------------------------------------------------------------------
/kernel/convert.h:
--------------------------------------------------------------------------------
1 | #ifndef PHPSCI_EXT_CONVERT_H
2 | #define PHPSCI_EXT_CONVERT_H
3 |
4 | #include "carray.h"
5 | #include "scalar.h"
6 |
7 | CArray * CArray_Slice_Index(CArray * self, int index, MemoryPointer * out);
8 | CArray * CArray_Slice_Str(CArray * self, char * index, MemoryPointer * out);
9 |
10 | CArray * CArray_View(CArray *self);
11 | CArray * CArray_NewCopy(CArray *obj, CARRAY_ORDER order);
12 | int CArray_CanCastTo(CArrayDescriptor *from, CArrayDescriptor *to);
13 | int CArray_CanCastSafely(int fromtype, int totype);
14 | int CArray_CastTo(CArray *out, CArray *mp);
15 | int CArray_FillWithScalar(CArray * arr, CArrayScalar * sc);
16 | #endif //PHPSCI_EXT_CONVERT_H
17 |
--------------------------------------------------------------------------------
/kernel/convert_datatype.c:
--------------------------------------------------------------------------------
1 | #include "carray.h"
2 | #include "convert_datatype.h"
3 | #include "common/exceptions.h"
4 | #include "convert_type.h"
5 |
6 | int
7 | can_cast_scalar_to(CArrayDescriptor *scal_type, char *scal_data,
8 | CArrayDescriptor *to, CARRAY_CASTING casting)
9 | {
10 | int swap;
11 | int is_small_unsigned = 0, type_num;
12 | int ret;
13 | CArrayDescriptor *dtype;
14 |
15 | /* An aligned memory buffer large enough to hold any type */
16 | long long value[4];
17 |
18 | /*
19 | * If the two dtypes are actually references to the same object
20 | * or if casting type is forced unsafe then always OK.
21 | */
22 | if (scal_type == to || casting == CARRAY_UNSAFE_CASTING ) {
23 | return 1;
24 | }
25 |
26 | swap = !CArray_ISNBO(scal_type->byteorder);
27 | scal_type->f->copyswap(&value, scal_data, swap, NULL);
28 |
29 | type_num = min_scalar_type_num((char *)&value, scal_type->type_num,
30 | &is_small_unsigned);
31 |
32 | /*
33 | * If we've got a small unsigned scalar, and the 'to' type
34 | * is not unsigned, then make it signed to allow the value
35 | * to be cast more appropriately.
36 | */
37 | if (is_small_unsigned && !(CArrayTypeNum_ISUNSIGNED(to->type_num))) {
38 | type_num = type_num_unsigned_to_signed(type_num);
39 | }
40 |
41 | dtype = CArray_DescrFromType(type_num);
42 | if (dtype == NULL) {
43 | return 0;
44 | }
45 |
46 | ret = CArray_CanCastTypeTo(dtype, to, casting);
47 | return ret;
48 | }
49 |
--------------------------------------------------------------------------------
/kernel/convert_datatype.h:
--------------------------------------------------------------------------------
1 | #ifndef PHPSCI_EXT_CONVERT_DATATYPE_H
2 | #define PHPSCI_EXT_CONVERT_DATATYPE_H
3 |
4 | #include "carray.h"
5 |
6 | int can_cast_scalar_to(CArrayDescriptor *scal_type, char *scal_data,
7 | CArrayDescriptor *to, CARRAY_CASTING casting);
8 |
9 | #endif //PHPSCI_EXT_CONVERT_DATATYPE_H
10 |
--------------------------------------------------------------------------------
/kernel/convert_type.c:
--------------------------------------------------------------------------------
1 | #include "convert_type.h"
2 | #include "alloc.h"
3 | #include "carray.h"
4 | #include "convert.h"
5 | #include "convert_datatype.h"
6 |
7 | /**
8 | * @param op
9 | * @param minimum_type
10 | * @return
11 | */
12 | int
13 | CArray_ObjectType(CArray * op, int minimum_type)
14 | {
15 | CArrayDescriptor *dtype = NULL;
16 | int ret;
17 |
18 | if (minimum_type >= 0) {
19 | if (CArray_TYPE(op) <= minimum_type) {
20 | dtype = CArray_DescrFromType(minimum_type);
21 | }
22 | if (CArray_TYPE(op) > minimum_type) {
23 | dtype = CArray_DescrFromType(CArray_TYPE(op));
24 | }
25 |
26 | if (dtype == NULL) {
27 | return TYPE_NOTYPE_INT;
28 | }
29 | }
30 |
31 | if (dtype == NULL) {
32 | ret = TYPE_DEFAULT_INT;
33 | }
34 | else {
35 | ret = dtype->type_num;
36 | }
37 |
38 | if (dtype != NULL) {
39 | CArrayDescriptor_FREE(dtype);
40 | }
41 | return ret;
42 | }
43 |
44 | /*
45 | * Returns true if data of type 'from' may be cast to data of type
46 | * 'to' according to the rule 'casting'.
47 | */
48 | int
49 | CArray_CanCastTypeTo(CArrayDescriptor *from, CArrayDescriptor *to,
50 | CARRAY_CASTING casting)
51 | {
52 | /* Fast path for unsafe casts or basic types */
53 | if (casting == CARRAY_UNSAFE_CASTING ||
54 | (CARRAY_LIKELY(from->type_num == to->type_num) &&
55 | CARRAY_LIKELY(from->byteorder == to->byteorder))) {
56 | return 1;
57 | }
58 | /* Equivalent types can be cast with any value of 'casting' */
59 | else if (CArray_EquivTypes(from, to)) {
60 | switch (from->type_num) {
61 | default:
62 | switch (casting) {
63 | case CARRAY_NO_CASTING:
64 | return CArray_EquivTypes(from, to);
65 | case CARRAY_EQUIV_CASTING:
66 | return (from->elsize == to->elsize);
67 | case CARRAY_SAFE_CASTING:
68 | return (from->elsize <= to->elsize);
69 | default:
70 | return 1;
71 | }
72 | break;
73 | }
74 | }
75 | /* If safe or same-kind casts are allowed */
76 | else if (casting == CARRAY_SAFE_CASTING || casting == CARRAY_SAME_KIND_CASTING) {
77 | if (CArray_CanCastTo(from, to)) {
78 | return 1;
79 | }
80 | else if(casting == CARRAY_SAME_KIND_CASTING) {
81 | throw_notimplemented_exception();
82 | }
83 | else {
84 | return 0;
85 | }
86 | }
87 | /* NPY_NO_CASTING or NPY_EQUIV_CASTING was specified */
88 | else {
89 | return 0;
90 | }
91 |
92 | }
93 |
94 |
95 |
96 | /*
97 | * Returns 1 if the array object may be cast to the given data type using
98 | * the casting rule, 0 otherwise. This differs from CArray_CanCastTo in
99 | * that it handles scalar arrays (0 dimensions) specially, by checking
100 | * their value.
101 | */
102 | int
103 | CArray_CanCastArrayTo(CArray *arr, CArrayDescriptor *to,
104 | CARRAY_CASTING casting)
105 | {
106 | CArrayDescriptor *from = CArray_DESCR(arr);
107 |
108 | /* If it's a scalar, check the value */
109 | if (CArray_NDIM(arr) == 0) {
110 | return can_cast_scalar_to(from, CArray_DATA(arr), to, casting);
111 | }
112 |
113 | /* Otherwise, use the standard rules */
114 | return CArray_CanCastTypeTo(from, to, casting);
115 | }
--------------------------------------------------------------------------------
/kernel/convert_type.h:
--------------------------------------------------------------------------------
1 | #ifndef PHPSCI_EXT_CONVERT_TYPE_H
2 | #define PHPSCI_EXT_CONVERT_TYPE_H
3 |
4 | #include "carray.h"
5 |
6 | /* Converts a type number from unsigned to signed */
7 | static int
8 | type_num_unsigned_to_signed(int type_num)
9 | {
10 | switch (type_num) {
11 | default:
12 | return type_num;
13 | }
14 | }
15 |
16 | /*
17 | * The is_small_unsigned output flag indicates whether it's an unsigned integer,
18 | * and would fit in a signed integer of the same bit size.
19 | */
20 | static
21 | int min_scalar_type_num(char *valueptr, int type_num,
22 | int *is_small_unsigned)
23 | {
24 | switch (type_num) {
25 | case TYPE_INTEGER_INT: {
26 | break;
27 | }
28 | case TYPE_DOUBLE_INT: {
29 | double value = *(double *)valueptr;
30 | if (value > -3.4e38 && value < 3.4e38) {
31 | return TYPE_FLOAT_INT;
32 | }
33 | break;
34 | }
35 | }
36 | return type_num;
37 | }
38 |
39 | int CArray_ObjectType(CArray * op, int minimum_type);
40 | int CArray_CanCastTypeTo(CArrayDescriptor *from, CArrayDescriptor *to, CARRAY_CASTING casting);
41 | int CArray_CanCastArrayTo(CArray *arr, CArrayDescriptor *to, CARRAY_CASTING casting);
42 | #endif //PHPSCI_EXT_CONVERT_TYPE_H
43 |
--------------------------------------------------------------------------------
/kernel/ctors.h:
--------------------------------------------------------------------------------
1 | #ifndef CARRAY_CTORS_H
2 | #define CARRAY_CTORS_H
3 |
4 | #include "carray.h"
5 |
6 | int setArrayFromSequence(CArray *a, CArray *s, int dim, int offset);
7 | CArray * CArray_FromArray(CArray *arr, CArrayDescriptor *newtype, int flags);
8 | void CArray_ToArray(CArray *a, zval * rtn);
9 | #endif //CARRAY_CTORS_H
10 |
--------------------------------------------------------------------------------
/kernel/descriptor.c:
--------------------------------------------------------------------------------
1 | #include "carray.h"
2 | #include "descriptor.h"
3 |
--------------------------------------------------------------------------------
/kernel/descriptor.h:
--------------------------------------------------------------------------------
1 | #ifndef PHPSCI_EXT_DESCRIPTOR_H
2 | #define PHPSCI_EXT_DESCRIPTOR_H
3 |
4 | #include "carray.h"
5 |
6 |
7 |
8 | #endif //PHPSCI_EXT_MATLIB_H
9 |
--------------------------------------------------------------------------------
/kernel/dtype_transfer.h:
--------------------------------------------------------------------------------
1 | #ifndef PHPSCI_EXT_DTYPE_TRANSFER_H
2 | #define PHPSCI_EXT_DTYPE_TRANSFER_H
3 |
4 | #include "carray.h"
5 | #include "common/common.h"
6 | #include "common/strided_loops.h"
7 |
8 | int CArray_CastRawArrays(int count, char *src, char *dst,
9 | int src_stride, int dst_stride,
10 | CArrayDescriptor *src_dtype, CArrayDescriptor *dst_dtype,
11 | int move_references);
12 |
13 | int CArray_GetDTypeTransferFunction(int aligned,
14 | int src_stride, int dst_stride,
15 | CArrayDescriptor *src_dtype, CArrayDescriptor *dst_dtype,
16 | int move_references,
17 | CArray_StridedUnaryOp **out_stransfer,
18 | CArrayAuxData **out_transferdata,
19 | int *out_needs_api);
20 |
21 | int
22 | CArray_PrepareOneRawArrayIter(int ndim, int *shape,
23 | char *data, int *strides,
24 | int *out_ndim, int *out_shape,
25 | char **out_data, int *out_strides);
26 | #endif //PHPSCI_EXT_DTYPE_TRANSFER_H
27 |
--------------------------------------------------------------------------------
/kernel/exp_logs.c:
--------------------------------------------------------------------------------
1 | #include "exp_logs.h"
2 | #include "carray.h"
3 | #include "trigonometric.h"
4 | #include "alloc.h"
5 | #include "buffer.h"
6 |
7 | CArray *
8 | CArray_Exp(CArray * target, MemoryPointer * out)
9 | {
10 | CArray * result;
11 | CArrayDescriptor * descr;
12 | int * new_strides;
13 | result = emalloc(sizeof(CArray));
14 |
15 | descr = CArray_DescrFromType(TYPE_DOUBLE_INT);
16 |
17 | result = CArray_NewFromDescr_int(result, descr, CArray_NDIM(target),
18 | CArray_DIMS(target), NULL, NULL,
19 | CArray_FLAGS(target), NULL, 1, 0);
20 | result->flags = ~CARRAY_ARRAY_F_CONTIGUOUS;
21 |
22 | CArray_ElementWise_CFunc(target, result, &exp);
23 |
24 | if(out != NULL) {
25 | add_to_buffer(out, result, sizeof(CArray *));
26 | }
27 | }
28 |
29 | CArray *
30 | CArray_Expm1(CArray * target, MemoryPointer * out)
31 | {
32 | CArray * result;
33 | CArrayDescriptor * descr;
34 | int * new_strides;
35 | result = emalloc(sizeof(CArray));
36 |
37 | descr = CArray_DescrFromType(TYPE_DOUBLE_INT);
38 |
39 | result = CArray_NewFromDescr_int(result, descr, CArray_NDIM(target),
40 | CArray_DIMS(target), NULL, NULL,
41 | CArray_FLAGS(target), NULL, 1, 0);
42 | result->flags = ~CARRAY_ARRAY_F_CONTIGUOUS;
43 |
44 | CArray_ElementWise_CFunc(target, result, &expm1);
45 |
46 | if(out != NULL) {
47 | add_to_buffer(out, result, sizeof(CArray *));
48 | }
49 | }
50 |
51 | CArray *
52 | CArray_Exp2(CArray * target, MemoryPointer * out)
53 | {
54 | CArray * result;
55 | CArrayDescriptor * descr;
56 | int * new_strides;
57 | result = emalloc(sizeof(CArray));
58 |
59 | descr = CArray_DescrFromType(TYPE_DOUBLE_INT);
60 |
61 | result = CArray_NewFromDescr_int(result, descr, CArray_NDIM(target),
62 | CArray_DIMS(target), NULL, NULL,
63 | CArray_FLAGS(target), NULL, 1, 0);
64 | result->flags = ~CARRAY_ARRAY_F_CONTIGUOUS;
65 |
66 | CArray_ElementWise_CFunc(target, result, &exp2);
67 |
68 | if(out != NULL) {
69 | add_to_buffer(out, result, sizeof(CArray *));
70 | }
71 | }
72 |
73 | CArray *
74 | CArray_Log(CArray * target, MemoryPointer * out)
75 | {
76 | CArray * result;
77 | CArrayDescriptor * descr;
78 | int * new_strides;
79 | result = emalloc(sizeof(CArray));
80 |
81 | descr = CArray_DescrFromType(TYPE_DOUBLE_INT);
82 |
83 | result = CArray_NewFromDescr_int(result, descr, CArray_NDIM(target),
84 | CArray_DIMS(target), NULL, NULL,
85 | CArray_FLAGS(target), NULL, 1, 0);
86 | result->flags = ~CARRAY_ARRAY_F_CONTIGUOUS;
87 |
88 | CArray_ElementWise_CFunc(target, result, &log);
89 |
90 | if(out != NULL) {
91 | add_to_buffer(out, result, sizeof(CArray *));
92 | }
93 | }
94 |
95 | CArray *
96 | CArray_Log10(CArray * target, MemoryPointer * out)
97 | {
98 | CArray * result;
99 | CArrayDescriptor * descr;
100 | int * new_strides;
101 | result = emalloc(sizeof(CArray));
102 |
103 | descr = CArray_DescrFromType(TYPE_DOUBLE_INT);
104 |
105 | result = CArray_NewFromDescr_int(result, descr, CArray_NDIM(target),
106 | CArray_DIMS(target), NULL, NULL,
107 | CArray_FLAGS(target), NULL, 1, 0);
108 | result->flags = ~CARRAY_ARRAY_F_CONTIGUOUS;
109 |
110 | CArray_ElementWise_CFunc(target, result, &log10);
111 |
112 | if(out != NULL) {
113 | add_to_buffer(out, result, sizeof(CArray *));
114 | }
115 | }
116 |
117 | CArray *
118 | CArray_Log2(CArray * target, MemoryPointer * out)
119 | {
120 | CArray * result;
121 | CArrayDescriptor * descr;
122 | int * new_strides;
123 | result = emalloc(sizeof(CArray));
124 |
125 | descr = CArray_DescrFromType(TYPE_DOUBLE_INT);
126 |
127 | result = CArray_NewFromDescr_int(result, descr, CArray_NDIM(target),
128 | CArray_DIMS(target), NULL, NULL,
129 | CArray_FLAGS(target), NULL, 1, 0);
130 | result->flags = ~CARRAY_ARRAY_F_CONTIGUOUS;
131 |
132 | CArray_ElementWise_CFunc(target, result, &log2);
133 |
134 | if(out != NULL) {
135 | add_to_buffer(out, result, sizeof(CArray *));
136 | }
137 | }
138 |
139 | CArray *
140 | CArray_Log1p(CArray * target, MemoryPointer * out)
141 | {
142 | CArray * result;
143 | CArrayDescriptor * descr;
144 | int * new_strides;
145 | result = emalloc(sizeof(CArray));
146 |
147 | descr = CArray_DescrFromType(TYPE_DOUBLE_INT);
148 |
149 | result = CArray_NewFromDescr_int(result, descr, CArray_NDIM(target),
150 | CArray_DIMS(target), NULL, NULL,
151 | CArray_FLAGS(target), NULL, 1, 0);
152 | result->flags = ~CARRAY_ARRAY_F_CONTIGUOUS;
153 |
154 | CArray_ElementWise_CFunc(target, result, &log1p);
155 |
156 | if(out != NULL) {
157 | add_to_buffer(out, result, sizeof(CArray *));
158 | }
159 | }
--------------------------------------------------------------------------------
/kernel/exp_logs.h:
--------------------------------------------------------------------------------
1 | #ifndef CARRAY_EXP_LOGS_H
2 | #define CARRAY_EXP_LOGS_H
3 |
4 | #include "carray.h"
5 |
6 | CArray * CArray_Exp(CArray * target, MemoryPointer * out);
7 | CArray * CArray_Expm1(CArray * target, MemoryPointer * out);
8 | CArray * CArray_Exp2(CArray * target, MemoryPointer * out);
9 | CArray * CArray_Log(CArray * target, MemoryPointer * out);
10 | CArray * CArray_Log10(CArray * target, MemoryPointer * out);
11 | CArray * CArray_Log2(CArray * target, MemoryPointer * out);
12 | CArray * CArray_Log1p(CArray * target, MemoryPointer * out);
13 | #endif //CARRAY_EXP_LOGS_H
14 |
--------------------------------------------------------------------------------
/kernel/flagsobject.c:
--------------------------------------------------------------------------------
1 | #include "flagsobject.h"
2 | #include "carray.h"
3 | #include "assign.h"
4 | #include "common/common.h"
5 |
6 | /**
7 | * Check whether the given array is stored contiguously
8 | **/
9 | static void
10 | _UpdateContiguousFlags(CArray * array)
11 | {
12 | int sd;
13 | int dim;
14 | int i;
15 | int is_c_contig = 1;
16 |
17 | sd = CArray_ITEMSIZE(array);
18 | for (i = CArray_NDIM(array) - 1; i >= 0; --i) {
19 | dim = CArray_DIMS(array)[i];
20 |
21 | if (CArray_STRIDES(array)[i] != sd) {
22 | is_c_contig = 0;
23 | break;
24 | }
25 | /* contiguous, if it got this far */
26 | if (dim == 0) {
27 | break;
28 | }
29 | sd *= dim;
30 | }
31 | if (is_c_contig) {
32 | CArray_ENABLEFLAGS(array, CARRAY_ARRAY_C_CONTIGUOUS);
33 | }
34 | else {
35 | CArray_CLEARFLAGS(array, CARRAY_ARRAY_C_CONTIGUOUS);
36 | }
37 | }
38 |
39 | /**
40 | * Update CArray flags
41 | **/
42 | void
43 | CArray_UpdateFlags(CArray * array, int flagmask)
44 | {
45 | /* Always update both, as its not trivial to guess one from the other */
46 | if (flagmask & (CARRAY_ARRAY_F_CONTIGUOUS | CARRAY_ARRAY_C_CONTIGUOUS)) {
47 | _UpdateContiguousFlags(array);
48 | }
49 |
50 | if (flagmask & CARRAY_ARRAY_ALIGNED) {
51 | if (IsAligned(array)) {
52 | CArray_ENABLEFLAGS(array, CARRAY_ARRAY_ALIGNED);
53 | }
54 | else {
55 | CArray_CLEARFLAGS(array, CARRAY_ARRAY_ALIGNED);
56 | }
57 | }
58 |
59 | if (flagmask & CARRAY_ARRAY_WRITEABLE) {
60 | if (_IsWriteable(array)) {
61 | CArray_ENABLEFLAGS(array, CARRAY_ARRAY_WRITEABLE);
62 | }
63 | else {
64 | CArray_CLEARFLAGS(array, CARRAY_ARRAY_WRITEABLE);
65 | }
66 | }
67 | return;
68 | }
69 |
70 |
--------------------------------------------------------------------------------
/kernel/flagsobject.h:
--------------------------------------------------------------------------------
1 | #ifndef PHPSCI_EXT_FLAGSOBJECT_H
2 | #define PHPSCI_EXT_FLAGSOBJECT_H
3 |
4 | #include "carray.h"
5 |
6 | /*
7 | * Enables the specified array flags.
8 | */
9 | static void
10 | CArray_ENABLEFLAGS(CArray * arr, int flags)
11 | {
12 | (arr)->flags |= flags;
13 | }
14 |
15 | /*
16 | * Clears the specified array flags. Does no checking,
17 | * assumes you know what you're doing.
18 | */
19 | static void
20 | CArray_CLEARFLAGS(CArray *arr, int flags)
21 | {
22 | (arr)->flags &= ~flags;
23 | }
24 |
25 | void CArray_UpdateFlags(CArray * array, int flagmask);
26 |
27 | #endif //PHPSCI_EXT_FLAGSOBJECT_H
--------------------------------------------------------------------------------
/kernel/getset.c:
--------------------------------------------------------------------------------
1 | #include "getset.h"
2 | #include "iterators.h"
3 | #include "carray.h"
4 | #include "alloc.h"
5 |
6 | int
7 | array_flat_set(CArray * self, CArray * val)
8 | {
9 | CArray * arr = NULL;
10 | int retval = -1;
11 | CArrayIterator *self_it, *arr_it;
12 | CArrayDescriptor *typecode;
13 | int swap;
14 | CArray_CopySwapFunc *copyswap;
15 |
16 | typecode = emalloc(sizeof(CArrayDescriptor));
17 | memcpy(typecode, CArray_DESCR(self), sizeof(CArrayDescriptor));
18 | CArrayDescriptor_INCREF(typecode);
19 |
20 | CArrayDescriptor_INCREF(CArray_DESCR(val));
21 | arr = CArray_FromAnyUnwrap(val, typecode, 0, 0, CARRAY_ARRAY_FORCECAST, NULL);
22 |
23 | if(arr == NULL) {
24 | return -1;
25 | }
26 |
27 | arr_it = CArray_NewIter(arr);
28 | if (arr_it == NULL) {
29 | goto exit;
30 | }
31 |
32 | self_it = CArray_NewIter(self);
33 | if (self_it == NULL) {
34 | goto exit;
35 | }
36 |
37 | if (arr_it->size == 0) {
38 | retval = 0;
39 | goto exit;
40 | }
41 |
42 | swap = CArray_ISNOTSWAPPED(self) != CArray_ISNOTSWAPPED(arr);
43 | copyswap = CArray_DESCR(self)->f->copyswap;
44 |
45 | if (CArray_DESCR(self)->refcount) {
46 | while (self_it->index < self_it->size) {
47 | memmove(self_it->data_pointer, arr_it->data_pointer, CArray_SIZE(self));
48 | CArrayIterator_NEXT(self_it);
49 | CArrayIterator_NEXT(arr_it);
50 | if (arr_it->index == arr_it->size) {
51 | CArrayIterator_RESET(arr_it);
52 | }
53 | }
54 | retval = 0;
55 | goto exit;
56 | }
57 |
58 | while(self_it->index < self_it->size) {
59 | memmove(self_it->data_pointer, arr_it->data_pointer, CArray_ITEMSIZE(self));
60 | if (swap) {
61 | copyswap(self_it->data_pointer, NULL, swap, self);
62 | }
63 | CArrayIterator_NEXT(self_it);
64 | CArrayIterator_NEXT(arr_it);
65 |
66 | if (arr_it->index == arr_it->size) {
67 | CArrayIterator_RESET(arr_it);
68 | }
69 | }
70 | retval = 0;
71 | CArrayIterator_FREE(arr_it);
72 | CArrayIterator_FREE(self_it);
73 | efree(typecode);
74 | return retval;
75 | exit:
76 | CArray_XDECREF(arr);
77 | return retval;
78 | }
79 |
--------------------------------------------------------------------------------
/kernel/getset.h:
--------------------------------------------------------------------------------
1 | #ifndef PHPSCI_EXT_GETSET_H
2 | #define PHPSCI_EXT_GETSET_H
3 |
4 | #include "carray.h"
5 |
6 | int array_flat_set(CArray * self, CArray * val);
7 |
8 |
9 | #endif
--------------------------------------------------------------------------------
/kernel/gpu.c:
--------------------------------------------------------------------------------
1 | #include "config.h"
2 |
3 | #ifdef HAVE_CLBLAS
4 | #include "gpu.h"
5 | #include "clBLAS.h"
6 |
7 | cl_context ctx;
8 | cl_command_queue queue;
9 |
10 | void
11 | start_clblas_context() {
12 | cl_context_properties props[3] = { CL_CONTEXT_PLATFORM, 0, 0 };
13 | cl_platform_id platform = 0;
14 | cl_device_id device = 0;
15 | cl_int err;
16 |
17 |
18 | /* Setup OpenCL environment. */
19 | err = clGetPlatformIDs( 1, &platform, NULL );
20 | err = clGetDeviceIDs( platform, CL_DEVICE_TYPE_GPU, 1, &device, NULL );
21 |
22 | props[1] = (cl_context_properties)platform;
23 |
24 | ctx = clCreateContext( props, 1, &device, NULL, NULL, &err );
25 | queue = clCreateCommandQueue( ctx, device, 0, &err );
26 |
27 | /* Setup clBLAS */
28 | err = clblasSetup( );
29 | }
30 |
31 |
32 | cl_context
33 | getCLContext() {
34 | return ctx;
35 | }
36 |
37 | cl_command_queue
38 | getCLQueue() {
39 | return queue;
40 | }
41 |
42 | #endif
43 |
--------------------------------------------------------------------------------
/kernel/gpu.h:
--------------------------------------------------------------------------------
1 | #ifndef PHPSCI_EXT_GPU_H
2 | #define PHPSCI_EXT_GPU_H
3 |
4 | #include "config.h"
5 |
6 | #ifdef HAVE_CLBLAS
7 | #include "clBLAS.h"
8 |
9 | void start_clblas_context();
10 | cl_command_queue getCLQueue();
11 | cl_context getCLContext();
12 | #endif
13 |
14 |
15 | #endif //PHPSCI_EXT_GPU_H
16 |
--------------------------------------------------------------------------------
/kernel/include/cpu.h:
--------------------------------------------------------------------------------
1 | #if defined( __i386__ ) || defined(i386) || defined(_M_IX86)
2 | /*
3 | * __i386__ is defined by gcc and Intel compiler on Linux,
4 | * _M_IX86 by VS compiler,
5 | * i386 by Sun compilers on opensolaris at least
6 | */
7 | #define CARRAY_CPU_X86
8 | #elif defined(__x86_64__) || defined(__amd64__) || defined(__x86_64) || defined(_M_AMD64)
9 | /*
10 | * both __x86_64__ and __amd64__ are defined by gcc
11 | * __x86_64 defined by sun compiler on opensolaris at least
12 | * _M_AMD64 defined by MS compiler
13 | */
14 | #define CARRAY_CPU_AMD64
15 | #endif
16 |
17 | #if (defined(CARRAY_CPU_X86) || defined(CARRAY_CPU_AMD64))
18 | #define CARRAY_CPU_HAVE_UNALIGNED_ACCESS 1
19 | #else
20 | #define CARRAY_CPU_HAVE_UNALIGNED_ACCESS 0
21 | #endif
--------------------------------------------------------------------------------
/kernel/item_selection.h:
--------------------------------------------------------------------------------
1 | #ifndef PHPSCI_EXT_ITEM_SELECTION_H
2 | #define PHPSCI_EXT_ITEM_SELECTION_H
3 |
4 | #include "carray.h"
5 |
6 | int
7 | INT_fasttake(int *dest, int *src, int *indarray,
8 | int nindarray, int n_outer,
9 | int m_middle, int nelem,
10 | CARRAY_CLIPMODE clipmode);
11 | int
12 | DOUBLE_fasttake(double *dest, double *src, int *indarray,
13 | int nindarray, int n_outer,
14 | int m_middle, int nelem,
15 | CARRAY_CLIPMODE clipmode);
16 |
17 |
18 | CArray * CArray_Diagonal(CArray *self, int offset, int axis1, int axis2, MemoryPointer * rtn);
19 | CArray * CArray_TakeFrom(CArray * target, CArray * indices0, int axis, MemoryPointer * out, CARRAY_CLIPMODE clipmode);
20 | CArray * CArray_Sort(CArray * target, int * axis, CARRAY_SORTKIND which, int inplace, MemoryPointer * out);
21 | #endif //PHPSCI_EXT_ITEM_SELECTION_H
--------------------------------------------------------------------------------
/kernel/iterators.h:
--------------------------------------------------------------------------------
1 | #ifndef PHPSCI_EXT_ITERATORS_H
2 | #define PHPSCI_EXT_ITERATORS_H
3 |
4 | #include "carray.h"
5 |
6 | /*** Global flags that may be passed to the iterator constructors ***/
7 |
8 | /* Track an index representing C order */
9 | #define CARRAY_ITER_C_INDEX 0x00000001
10 | /* Track an index representing Fortran order */
11 | #define CARRAY_ITER_F_INDEX 0x00000002
12 | /* Track a multi-index */
13 | #define CARRAY_ITER_MULTI_INDEX 0x00000004
14 | /* User code external to the iterator does the 1-dimensional innermost loop */
15 | #define CARRAY_ITER_EXTERNAL_LOOP 0x00000008
16 | /* Convert all the operands to a common data type */
17 | #define CARRAY_ITER_COMMON_DTYPE 0x00000010
18 | /* Operands may hold references, requiring API access during iteration */
19 | #define CARRAY_ITER_REFS_OK 0x00000020
20 | /* Zero-sized operands should be permitted, iteration checks IterSize for 0 */
21 | #define CARRAY_ITER_ZEROSIZE_OK 0x00000040
22 | /* Permits reductions (size-0 stride with dimension size > 1) */
23 | #define CARRAY_ITER_REDUCE_OK 0x00000080
24 | /* Enables sub-range iteration */
25 | #define CARRAY_ITER_RANGED 0x00000100
26 | /* Enables buffering */
27 | #define CARRAY_ITER_BUFFERED 0x00000200
28 | /* When buffering is enabled, grows the inner loop if possible */
29 | #define CARRAY_ITER_GROWINNER 0x00000400
30 | /* Delay allocation of buffers until first Reset* call */
31 | #define CARRAY_ITER_DELAY_BUFALLOC 0x00000800
32 | /* When CARRAY_KEEPORDER is specified, disable reversing negative-stride axes */
33 | #define CARRAY_ITER_DONT_NEGATE_STRIDES 0x00001000
34 | /*
35 | * If output operands overlap with other operands (based on heuristics that
36 | * has false positives but no false negatives), make temporary copies to
37 | * eliminate overlap.
38 | */
39 | #define CARRAY_ITER_COPY_IF_OVERLAP 0x00002000
40 |
41 | /*** Per-operand flags that may be passed to the iterator constructors ***/
42 |
43 | /* The operand will be read from and written to */
44 | #define CARRAY_ITER_READWRITE 0x00010000
45 | /* The operand will only be read from */
46 | #define CARRAY_ITER_READONLY 0x00020000
47 | /* The operand will only be written to */
48 | #define CARRAY_ITER_WRITEONLY 0x00040000
49 | /* The operand's data must be in native byte order */
50 | #define CARRAY_ITER_NBO 0x00080000
51 | /* The operand's data must be aligned */
52 | #define CARRAY_ITER_ALIGNED 0x00100000
53 | /* The operand's data must be contiguous (within the inner loop) */
54 | #define CARRAY_ITER_CONTIG 0x00200000
55 | /* The operand may be copied to satisfy requirements */
56 | #define CARRAY_ITER_COPY 0x00400000
57 | /* The operand may be copied with WRITEBACKIFCOPY to satisfy requirements */
58 | #define CARRAY_ITER_UPDATEIFCOPY 0x00800000
59 | /* Allocate the operand if it is NULL */
60 | #define CARRAY_ITER_ALLOCATE 0x01000000
61 | /* If an operand is allocated, don't use any subtype */
62 | #define CARRAY_ITER_NO_SUBTYPE 0x02000000
63 | /* This is a virtual array slot, operand is NULL but temporary data is there */
64 | #define CARRAY_ITER_VIRTUAL 0x04000000
65 | /* Require that the dimension match the iterator dimensions exactly */
66 | #define CARRAY_ITER_NO_BROADCAST 0x08000000
67 | /* A mask is being used on this array, affects buffer -> array copy */
68 | #define CARRAY_ITER_WRITEMASKED 0x10000000
69 | /* This array is the mask for all WRITEMASKED operands */
70 | #define CARRAY_ITER_ARRAYMASK 0x20000000
71 | /* Assume iterator order data access for COPY_IF_OVERLAP */
72 | #define CARRAY_ITER_OVERLAP_ASSUME_ELEMENTWISE 0x40000000
73 |
74 | #define CARRAY_ITER_GLOBAL_FLAGS 0x0000ffff
75 | #define CARRAY_ITER_PER_OP_FLAGS 0xffff0000
76 |
77 | typedef struct CArrayIterator
78 | {
79 | int index; // Current 1-d index
80 | int size;
81 | int * coordinates; // Coordinate vectors of index
82 | int * dims_m1; // Size of array minus 1 for each dimension
83 | int ndims_m1;
84 | int * factors; // Factor for ND-index to 1D-index
85 | int * strides; // Array Strides
86 | int * backstrides; // Backstrides
87 | char * data_pointer; // Data pointer to element defined by index
88 | int contiguous; // 1 = Contiguous, 0 = Non-contiguous
89 | int ** bounds;
90 | int ** limits;
91 | int * limits_sizes;
92 | CArray * array; // Pointer to represented CArray
93 | } CArrayIterator;
94 |
95 | typedef int (CArrayIterator_IterNextFunc)(CArrayIterator *iter);
96 |
97 | #define IT_IDATA(it) ((int *)((it)->data_pointer))
98 | #define IT_DDATA(it) ((double *)((it)->data_pointer))
99 | #define CArrayIterator_DATA(it) ((void *)((it)->data_pointer))
100 | #define CArrayIterator_NOTDONE(it) ((it)->index < (it)->size)
101 |
102 | CArrayIterator * CArray_NewIter(CArray * array);
103 | static char* get_ptr(CArrayIterator * iter, uintptr_t * coordinates);
104 | void CArrayIterator_Dump(CArrayIterator * iterator);
105 | void CArrayIterator_GOTO(CArrayIterator * iterator, int * destination);
106 | void CArrayIterator_NEXT(CArrayIterator * iterator);
107 | void CArrayIterator_RESET(CArrayIterator * iterator);
108 | void CArrayIterator_FREE(CArrayIterator * it);
109 |
110 | CArrayIterator * CArray_BroadcastToShape(CArray * target, int * dims, int nd);
111 | CArrayIterator * CArray_IterAllButAxis(CArray *obj, int *inaxis);
112 | #endif //PHPSCI_EXT_ITERATORS_H
--------------------------------------------------------------------------------
/kernel/join.c:
--------------------------------------------------------------------------------
1 | #include "join.h"
2 | #include "carray.h"
3 | #include "alloc.h"
4 | #include "stdio.h"
5 | #include "shape.h"
6 | #include "buffer.h"
7 |
8 | static CArray *
9 | _swap_and_concat(CArray **op, int axis, int n, MemoryPointer * out)
10 | {
11 | CArray **newtup = NULL;
12 | CArray *otmp, *arr;
13 | int i;
14 | int axis2 = 0;
15 |
16 | newtup = emalloc(sizeof(CArray) * n);
17 | if (newtup==NULL) return NULL;
18 | for (i=0; i= CARRAY_MAXDIMS) {
73 | otmp = CArray_Ravel(mps[i],0);
74 | CArray_XDECREF(mps[i]);
75 | mps[i] = otmp;
76 | }
77 | prior2 = 0.0;
78 | if (prior2 > prior1) {
79 | prior1 = prior2;
80 | }
81 | }
82 |
83 | new_dim = 0;
84 | for(i=0; indim;
87 | else {
88 | if (nd != mps[i]->ndim) {
89 | throw_valueerror_exception("arrays must have same "
90 | "number of dimensions");
91 | goto fail;
92 | }
93 | if (!CArray_CompareLists(mps[0]->dimensions+1,
94 | mps[i]->dimensions+1,
95 | nd-1)) {
96 | throw_valueerror_exception("array dimensions must "
97 | "agree except for d_0");
98 | goto fail;
99 | }
100 | }
101 | if (nd == 0) {
102 | throw_valueerror_exception("0-d arrays can't be concatenated");
103 | goto fail;
104 | }
105 | new_dim += mps[i]->dimensions[0];
106 | }
107 |
108 | tmp = mps[0]->dimensions[0];
109 | mps[0]->dimensions[0] = new_dim;
110 | CArrayDescriptor_INCREF(CArray_DESCR(mps[0]));
111 |
112 | ret = (CArray *)CArray_NewFromDescr(ret, CArray_DESCR(mps[0]), nd,
113 | CArray_DIMS(mps[0]),NULL, NULL, 0,
114 | NULL);
115 | mps[0]->dimensions[0] = tmp;
116 |
117 | if (ret == NULL) goto fail;
118 |
119 | data = ret->data;
120 | for(i=0; idata, numbytes);
123 | data += numbytes;
124 | }
125 |
126 | CArray_INCREF(ret);
127 | for(i=0; iobval = emalloc(new_descr->elsize);
32 | sc->type = CHAR_TYPE_INT(type);
33 |
34 | if(type == TYPE_DOUBLE){
35 | *((double *)sc->obval) = (double)0.00;
36 | }
37 | if(type == TYPE_INTEGER){
38 | *((int *)sc->obval) = (int)0;
39 | }
40 | if(type == TYPE_FLOAT){
41 | *((float *)sc->obval) = (float)0;
42 | }
43 |
44 | CArray_FillWithScalar(rtn, sc);
45 |
46 | efree(sc->obval);
47 | efree(sc);
48 |
49 | if(allocated) {
50 | efree(order);
51 | }
52 | return rtn;
53 | }
54 |
55 |
56 | CArray *
57 | CArray_Ones(int * shape, int nd, char * type, char * order, MemoryPointer * rtn_ptr)
58 | {
59 | int is_fortran = 0, order_allocated = 0;
60 | CArrayDescriptor * new_descr;
61 | CArrayScalar * sc = emalloc(sizeof(CArrayScalar));
62 | CArray * rtn;
63 |
64 | if (order == NULL) {
65 | order = emalloc(sizeof(char));
66 | *order = 'C';
67 | order_allocated = 1;
68 | }
69 |
70 | if (*order == 'F') {
71 | is_fortran = 1;
72 | }
73 |
74 | new_descr = CArray_DescrFromType(CHAR_TYPE_INT(*type));
75 | rtn = CArray_Empty(nd, shape, new_descr, is_fortran, rtn_ptr);
76 |
77 | sc->obval = emalloc(new_descr->elsize);
78 | sc->type = CHAR_TYPE_INT(*type);
79 |
80 | if(*type == TYPE_DOUBLE){
81 | *((double *)sc->obval) = (double)1.00;
82 | }
83 | if(*type == TYPE_INTEGER){
84 | *((int *)sc->obval) = (int)1;
85 | }
86 | if(*type == TYPE_FLOAT){
87 | *((float *)sc->obval) = (float)1;
88 | }
89 |
90 | CArray_FillWithScalar(rtn, sc);
91 |
92 | efree(sc->obval);
93 | efree(sc);
94 |
95 | if (order_allocated) {
96 | efree(order);
97 | }
98 | return rtn;
99 | }
100 |
101 | CArray *
102 | CArray_Flip(CArray *a, int * axis, MemoryPointer * out)
103 | {
104 | CArrayIterator * it;
105 | CArray * rtn;
106 |
107 | it = CArray_NewIter(a);
108 | rtn = CArray_NewLikeArray(a, CARRAY_KEEPORDER, CArray_DESCR(a), 0);
109 | CArrayDescriptor_INCREF(CArray_DESCR(a));
110 |
111 | if (axis == NULL) {
112 | switch(CArray_TYPE(a)) {
113 | case TYPE_DOUBLE_INT:
114 | do {
115 | DDATA(rtn)[CArray_DESCR(a)->numElements - it->index - 1] = *IT_DDATA(it);
116 | CArrayIterator_NEXT(it);
117 | } while(CArrayIterator_NOTDONE(it));
118 | break;
119 | case TYPE_INTEGER_INT:
120 | do {
121 | IDATA(rtn)[CArray_DESCR(a)->numElements - it->index - 1] = *IT_IDATA(it);
122 | CArrayIterator_NEXT(it);
123 | } while(CArrayIterator_NOTDONE(it));
124 | break;
125 | }
126 | }
127 | else {
128 | throw_notimplemented_exception();
129 | CArrayIterator_FREE(it);
130 | return NULL;
131 | }
132 |
133 | if (out != NULL) {
134 | add_to_buffer(out, rtn, sizeof(CArray));
135 | }
136 |
137 | CArrayIterator_FREE(it);
138 | return rtn;
139 | }
--------------------------------------------------------------------------------
/kernel/matlib.h:
--------------------------------------------------------------------------------
1 | #ifndef PHPSCI_EXT_MATLIB_H
2 | #define PHPSCI_EXT_MATLIB_H
3 |
4 | #include "carray.h"
5 |
6 | CArray * CArray_Zeros(int * shape, int nd, char type, char * order, MemoryPointer * rtn_ptr);
7 | CArray * CArray_Ones(int * shape, int nd, char * type, char * order, MemoryPointer * rtn_ptr);
8 | CArray * CArray_Flip(CArray *a, int * axis, MemoryPointer * out);
9 | #endif //PHPSCI_EXT_MATLIB_H
10 |
--------------------------------------------------------------------------------
/kernel/number.h:
--------------------------------------------------------------------------------
1 | #ifndef PHPSCI_EXT_NUMBER_H
2 | #define PHPSCI_EXT_NUMBER_H
3 |
4 | #include "carray.h"
5 |
6 | CArray * CArray_Add(CArray *m1, CArray *m2, MemoryPointer * ptr);
7 | CArray * CArray_Subtract(CArray *m1, CArray *m2, MemoryPointer * ptr);
8 | CArray * CArray_Multiply(CArray *m1, CArray *m2, MemoryPointer * ptr);
9 | CArray * CArray_Divide(CArray *m1, CArray *m2, MemoryPointer * ptr);
10 | CArray * CArray_Power(CArray *m1, CArray *m2, MemoryPointer * ptr);
11 | CArray * CArray_Mod(CArray *m1, CArray *m2, MemoryPointer * ptr);
12 | CArray * CArray_Negative(CArray * a, MemoryPointer * out);
13 | CArray * CArray_Sqrt(CArray *a, MemoryPointer *out);
14 | CArray * CArray_Reciprocal(CArray *a, MemoryPointer *out);
15 | CArray * CArray_Absolute(CArray *a, MemoryPointer *out);
16 | #endif //PHPSCI_EXT_NUMBER_H
17 |
--------------------------------------------------------------------------------
/kernel/random.c:
--------------------------------------------------------------------------------
1 | #include "carray.h"
2 | #include "random.h"
3 | #include "matlib.h"
4 |
5 | #ifndef RK_DEV_URANDOM
6 | #define RK_DEV_URANDOM "/dev/urandom"
7 | #endif
8 |
9 | #ifndef RK_DEV_RANDOM
10 | #define RK_DEV_RANDOM "/dev/random"
11 | #endif
12 |
13 | /* Magic Mersenne Twister constants */
14 | #define N 624
15 | #define M 397
16 | #define MATRIX_A 0x9908b0dfUL
17 | #define UPPER_MASK 0x80000000UL
18 | #define LOWER_MASK 0x7fffffffUL
19 |
20 | /* Thomas Wang 32 bits integer hash function */
21 | unsigned long
22 | rk_hash(unsigned long key)
23 | {
24 | key += ~(key << 15);
25 | key ^= (key >> 10);
26 | key += (key << 3);
27 | key ^= (key >> 6);
28 | key += ~(key << 11);
29 | key ^= (key >> 16);
30 | return key;
31 | }
32 |
33 | rk_error
34 | rk_devfill(void *buffer, size_t size, int strong)
35 | {
36 | #ifndef _WIN32
37 | FILE *rfile;
38 | int done;
39 |
40 | if (strong) {
41 | rfile = fopen(RK_DEV_RANDOM, "rb");
42 | }
43 | else {
44 | rfile = fopen(RK_DEV_URANDOM, "rb");
45 | }
46 | if (rfile == NULL) {
47 | return RK_ENODEV;
48 | }
49 | done = fread(buffer, size, 1, rfile);
50 | fclose(rfile);
51 | if (done) {
52 | return RK_NOERR;
53 | }
54 | #else
55 |
56 | #ifndef RK_NO_WINCRYPT
57 | HCRYPTPROV hCryptProv;
58 | BOOL done;
59 |
60 | if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL,
61 | CRYPT_VERIFYCONTEXT) || !hCryptProv) {
62 | return RK_ENODEV;
63 | }
64 | done = CryptGenRandom(hCryptProv, size, (unsigned char *)buffer);
65 | CryptReleaseContext(hCryptProv, 0);
66 | if (done) {
67 | return RK_NOERR;
68 | }
69 | #endif
70 |
71 | #endif
72 | return RK_ENODEV;
73 | }
74 |
75 | /*
76 | * Slightly optimised reference implementation of the Mersenne Twister
77 | * Note that regardless of the precision of long, only 32 bit random
78 | * integers are produced
79 | */
80 | unsigned long
81 | rk_random(rk_state *state)
82 | {
83 | unsigned long y;
84 |
85 | if (state->pos == RK_STATE_LEN) {
86 | int i;
87 |
88 | for (i = 0; i < N - M; i++) {
89 | y = (state->key[i] & UPPER_MASK) | (state->key[i+1] & LOWER_MASK);
90 | state->key[i] = state->key[i+M] ^ (y>>1) ^ (-(y & 1) & MATRIX_A);
91 | }
92 | for (; i < N - 1; i++) {
93 | y = (state->key[i] & UPPER_MASK) | (state->key[i+1] & LOWER_MASK);
94 | state->key[i] = state->key[i+(M-N)] ^ (y>>1) ^ (-(y & 1) & MATRIX_A);
95 | }
96 | y = (state->key[N - 1] & UPPER_MASK) | (state->key[0] & LOWER_MASK);
97 | state->key[N - 1] = state->key[M - 1] ^ (y >> 1) ^ (-(y & 1) & MATRIX_A);
98 |
99 | state->pos = 0;
100 | }
101 | y = state->key[state->pos++];
102 |
103 | /* Tempering */
104 | y ^= (y >> 11);
105 | y ^= (y << 7) & 0x9d2c5680UL;
106 | y ^= (y << 15) & 0xefc60000UL;
107 | y ^= (y >> 18);
108 |
109 | return y;
110 | }
111 |
112 | double
113 | rk_double(rk_state *state)
114 | {
115 | /* shifts : 67108864 = 0x4000000, 9007199254740992 = 0x20000000000000 */
116 | long a = rk_random(state) >> 5, b = rk_random(state) >> 6;
117 | return (a * 67108864.0 + b) / 9007199254740992.0;
118 | }
119 |
120 | void
121 | rk_seed(unsigned long seed, rk_state *state)
122 | {
123 | int pos;
124 | seed &= 0xffffffffUL;
125 |
126 | /* Knuth's PRNG as used in the Mersenne Twister reference implementation */
127 | for (pos = 0; pos < RK_STATE_LEN; pos++) {
128 | state->key[pos] = seed;
129 | seed = (1812433253UL * (seed ^ (seed >> 30)) + pos + 1) & 0xffffffffUL;
130 | }
131 | state->pos = RK_STATE_LEN;
132 | state->gauss = 0;
133 | state->has_gauss = 0;
134 | state->has_binomial = 0;
135 | }
136 |
137 |
138 | rk_error
139 | rk_randomseed(rk_state *state)
140 | {
141 | #ifndef _WIN32
142 | struct timeval tv;
143 | #else
144 | struct _timeb tv;
145 | #endif
146 | int i;
147 |
148 | if (rk_devfill(state->key, sizeof(state->key), 0) == RK_NOERR) {
149 | /* ensures non-zero key */
150 | state->key[0] |= 0x80000000UL;
151 | state->pos = RK_STATE_LEN;
152 | state->gauss = 0;
153 | state->has_gauss = 0;
154 | state->has_binomial = 0;
155 |
156 | for (i = 0; i < 624; i++) {
157 | state->key[i] &= 0xffffffffUL;
158 | }
159 | return RK_NOERR;
160 | }
161 |
162 | #ifndef _WIN32
163 | gettimeofday(&tv, NULL);
164 | rk_seed(rk_hash(getpid()) ^ rk_hash(tv.tv_sec) ^ rk_hash(tv.tv_usec)
165 | ^ rk_hash(clock()), state);
166 | #else
167 | _FTIME(&tv);
168 | rk_seed(rk_hash(tv.time) ^ rk_hash(tv.millitm) ^ rk_hash(clock()), state);
169 | #endif
170 |
171 | return RK_ENODEV;
172 | }
173 |
174 | CArray *
175 | CArray_Rand(int * size, int nd, MemoryPointer * out)
176 | {
177 | rk_state * state = emalloc(sizeof(rk_state));
178 | double * array_data;
179 | CArray * target;
180 | int length;
181 | int i;
182 | target = CArray_Zeros(size, nd, TYPE_DOUBLE, NULL, out);
183 |
184 | length = CArray_SIZE(target);
185 | array_data = (double *)CArray_DATA(target);
186 |
187 | rk_randomseed(state);
188 | for(i = 0; i < length; i++) {
189 | array_data[i] = rk_double(state);
190 | }
191 | efree(state);
192 | return target;
193 | }
--------------------------------------------------------------------------------
/kernel/random.h:
--------------------------------------------------------------------------------
1 | #ifndef PHPSCI_EXT_RANDOM_H
2 | #define PHPSCI_EXT_RANDOM_H
3 |
4 | #include "carray.h"
5 |
6 | #define RK_STATE_LEN 624
7 |
8 | typedef struct rk_state_
9 | {
10 | unsigned long key[RK_STATE_LEN];
11 | int pos;
12 | int has_gauss; /* !=0: gauss contains a gaussian deviate */
13 | double gauss;
14 |
15 | /* The rk_state structure has been extended to store the following
16 | * information for the binomial generator. If the input values of n or p
17 | * are different than nsave and psave, then the other parameters will be
18 | * recomputed. RTK 2005-09-02 */
19 |
20 | int has_binomial; /* !=0: following parameters initialized for
21 | binomial */
22 | double psave;
23 | long nsave;
24 | double r;
25 | double q;
26 | double fm;
27 | long m;
28 | double p1;
29 | double xm;
30 | double xl;
31 | double xr;
32 | double c;
33 | double laml;
34 | double lamr;
35 | double p2;
36 | double p3;
37 | double p4;
38 |
39 | }
40 | rk_state;
41 |
42 | typedef enum {
43 | RK_NOERR = 0, /* no error */
44 | RK_ENODEV = 1, /* no RK_DEV_RANDOM device */
45 | RK_ERR_MAX = 2
46 | } rk_error;
47 |
48 | unsigned long rk_random(rk_state *state);
49 |
50 | /*
51 | * Returns a random double between 0.0 and 1.0, 1.0 excluded.
52 | */
53 | double rk_double(rk_state *state);
54 |
55 | void rk_seed(unsigned long seed, rk_state *state);
56 | CArray * CArray_Rand(int * size, int nd, MemoryPointer * out);
57 |
58 | #endif //PHPSCI_EXT_RANDOM_H
59 |
--------------------------------------------------------------------------------
/kernel/random/distributions.c:
--------------------------------------------------------------------------------
1 | #include "../carray.h"
2 | #include "distributions.h"
3 | #include "../buffer.h"
4 |
5 | /**
6 | * Poisson Random Distribution
7 | *
8 | * @param m
9 | * @param n
10 | * @param lambda
11 | * @return
12 | */
13 | CArray*
14 | CArray_Poisson(int *shape, double lambda, MemoryPointer *out)
15 | {
16 | CArray *result;
17 | CArrayDescriptor *descr;
18 | double max = INT_MAX;
19 | time_t t;
20 | double l = exp(-lambda);
21 | double k;
22 | double p;
23 | int i;
24 |
25 | result = emalloc(sizeof(CArray));
26 | descr = CArray_DescrFromType(TYPE_DOUBLE_INT);
27 | result = CArray_NewFromDescr_int(result, descr, 2, shape, NULL, NULL,
28 | CARRAY_ARRAY_C_CONTIGUOUS, NULL, 1, 0);
29 |
30 | // Random Seed
31 | srand((unsigned) time(&t));
32 |
33 | for (i = 0; i < CArray_DESCR(result)->numElements; i++) {
34 | k = 0.0;
35 | p = 1.0;
36 |
37 | while (p > l) {
38 | k = k + 1.0;
39 | p *= rand() / max;
40 | }
41 | DDATA(result)[i] = (double) k - 1;
42 | }
43 |
44 | if (out != NULL) {
45 | add_to_buffer(out, result, sizeof(result));
46 | }
47 |
48 | return result;
49 | }
50 |
--------------------------------------------------------------------------------
/kernel/random/distributions.h:
--------------------------------------------------------------------------------
1 | #ifndef PHPSCI_CARRAY_DISTRIBUTIONS_H
2 | #define PHPSCI_CARRAY_DISTRIBUTIONS_H
3 |
4 | #include "../carray.h"
5 |
6 | CArray* CArray_Poisson(int *shape, double lambda, MemoryPointer *out);
7 |
8 | #endif //PHPSCI_CARRAY_DISTRIBUTIONS_H
9 |
--------------------------------------------------------------------------------
/kernel/range.c:
--------------------------------------------------------------------------------
1 | #include "carray.h"
2 | #include "alloc.h"
3 | #include "buffer.h"
4 | #include "range.h"
5 | #include "convert.h"
6 | #include "number.h"
7 | #include "shape.h"
8 |
9 | /**
10 | * @param start
11 | * @param stop
12 | * @param step
13 | * @param type_num
14 | * @param ptr
15 | * @todo Fix leak
16 | * @return
17 | */
18 | CArray *
19 | CArray_Arange(double start, double stop, double step, int type_num, MemoryPointer * ptr)
20 | {
21 | int length;
22 | CArray * range;
23 | CArray_ArrFuncs *funcs;
24 | int start_plus_step_i, start_i;
25 | double start_plus_step_d, start_d;
26 | int ret;
27 |
28 | range = emalloc(sizeof(CArray));
29 |
30 | if (_safe_ceil_to_int((stop - start) / step, &length)) {
31 | throw_overflow_exception("arange: overflow while computing length");
32 | }
33 |
34 | if (length <= 0) {
35 | length = 0;
36 | if(ptr != NULL) {
37 | add_to_buffer(ptr, range, sizeof(CArray));
38 | }
39 | return CArray_New(range, 1, &length, type_num,
40 | NULL, NULL, 0, 0, NULL);
41 | }
42 |
43 | range = CArray_New(range, 1, &length, type_num,
44 | NULL, NULL, 0, 0, NULL);
45 |
46 | if (range == NULL) {
47 | return NULL;
48 | }
49 |
50 | funcs = CArray_DESCR(range)->f;
51 |
52 | if(type_num == TYPE_DOUBLE_INT) {
53 | start_d = (double)(start);
54 | ret = funcs->setitem(((double *) &start_d), CArray_BYTES(range), range);
55 | }
56 | if(type_num == TYPE_INTEGER_INT) {
57 | start_i = (int)(start);
58 | ret = funcs->setitem(((int *) &start_i), CArray_BYTES(range), range);
59 | }
60 |
61 | if (ret < 0) {
62 | goto fail;
63 | }
64 |
65 | if(ptr != NULL) {
66 | add_to_buffer(ptr, range, sizeof(CArray));
67 | }
68 |
69 | if (length == 1) {
70 | return range;
71 | }
72 |
73 | if(type_num == TYPE_DOUBLE_INT) {
74 | start_plus_step_d = (double)(start + step);
75 | ret = funcs->setitem(&start_plus_step_d, (CArray_BYTES(range) + CArray_ITEMSIZE(range)), range);
76 | }
77 | if(type_num == TYPE_INTEGER_INT) {
78 | start_plus_step_i = (int)(start + step);
79 | ret = funcs->setitem(&start_plus_step_i, (CArray_BYTES(range) + CArray_ITEMSIZE(range)), range);
80 | }
81 |
82 | if (ret < 0) {
83 | goto fail;
84 | }
85 |
86 | if (length == 2) {
87 | return range;
88 | }
89 |
90 | if (funcs->fill == NULL) {
91 | throw_valueerror_exception("no fill-function for data-type.");
92 | return NULL;
93 | }
94 |
95 | funcs->fill(CArray_BYTES(range), length, range);
96 | return range;
97 | fail:
98 | return NULL;
99 | }
100 |
101 |
102 | CArray *
103 | CArray_Linspace(double start, double stop, int num, int endpoint, int retstep, int * axis, int type, MemoryPointer * out)
104 | {
105 | CArray * y, * tempc = emalloc(sizeof(CArray)), * freec, * rtn;
106 | double div, delta;
107 | CArrayDescriptor * dtype;
108 | double step;
109 | if(num < 0) {
110 | throw_valueerror_exception("Number of samples must be non-negative.");
111 | return NULL;
112 | }
113 |
114 | if(endpoint) {
115 | div = (num - 1);
116 | } else {
117 | div = num;
118 | }
119 |
120 | dtype = CArray_DescrFromType(TYPE_DOUBLE_INT);
121 | tempc = CArray_NewFromDescr(tempc, dtype, 0, NULL, NULL, NULL,
122 | 0, NULL);
123 |
124 | DDATA(tempc)[0] = div;
125 |
126 | delta = stop - start;
127 | y = CArray_Arange(0.0, num, 1.0, type, NULL);
128 | freec = y;
129 |
130 | if(num > 1) {
131 | step = delta / div;
132 | if (step == 0) {
133 | y = CArray_Divide(y, tempc, NULL);
134 | DDATA(tempc)[0] = delta;
135 | y = CArray_Multiply(y, tempc, NULL);
136 | } else {
137 | DDATA(tempc)[0] = step;
138 | y = CArray_Multiply(y, tempc, NULL);
139 | CArray_Free(freec);
140 | }
141 | } else {
142 | DDATA(tempc)[0] = delta;
143 | y = CArray_Multiply(y, tempc, NULL);
144 | }
145 |
146 | freec = y;
147 | DDATA(tempc)[0] = start;
148 |
149 | y = CArray_Add(y, tempc, NULL);
150 | CArray_Free(freec);
151 |
152 | if (endpoint && num > 1) {
153 | if (CArray_TYPE(y) == TYPE_INTEGER_INT) {
154 | IDATA(y)[CArray_DESCR(y)->numElements-1] = (int)stop;
155 | }
156 | if (CArray_TYPE(y) == TYPE_DOUBLE_INT) {
157 | DDATA(y)[CArray_DESCR(y)->numElements-1] = (double)stop;
158 | }
159 | }
160 |
161 | if (axis != NULL) {
162 | if (*axis != 0) {
163 | dtype = CArray_DescrFromType(TYPE_INTEGER_INT);
164 | CArray *axisc = emalloc(sizeof(CArray));
165 | axisc = CArray_NewFromDescr(axisc, dtype, 0, NULL, NULL, NULL, 0, NULL);
166 | IDATA(axisc)[0] = *axis;
167 |
168 | dtype = CArray_DescrFromType(TYPE_INTEGER_INT);
169 | CArray *dst = emalloc(sizeof(CArray));
170 | dst = CArray_NewFromDescr(dst, dtype, 0, NULL, NULL, NULL, 0, NULL);
171 | IDATA(dst)[0] = 0;
172 | y = CArray_Moveaxis(y, dst, axisc, NULL);
173 | }
174 | }
175 |
176 | CArrayDescriptor_FREE(dtype);
177 |
178 |
179 | if (type != TYPE_DOUBLE_INT) {
180 | CArrayDescriptor *descr = CArray_DescrFromType(type);
181 | rtn = CArray_NewLikeArray(y, CARRAY_CORDER, descr, 0);
182 | if(CArray_CastTo(rtn, y) < 0) {
183 | return NULL;
184 | }
185 | CArray_Free(y);
186 | } else {
187 | rtn = y;
188 | }
189 |
190 | if (out != NULL) {
191 | add_to_buffer(out, rtn, sizeof(CArray));
192 | }
193 | efree(tempc->data);
194 | efree(tempc);
195 | return rtn;
196 | }
197 |
198 | CArray *
199 | CArray_Logspace(double start, double stop, int num, int endpoint, double base, int typenum, MemoryPointer * out)
200 | {
201 | int axis = 0;
202 | CArray * baseca, * y, * rtn, * tmp;
203 |
204 |
205 | baseca = emalloc(sizeof(CArray));
206 |
207 | CArrayDescriptor * dtype = CArray_DescrFromType(TYPE_DOUBLE_INT);
208 | baseca = CArray_NewFromDescr(baseca, dtype, 0, NULL, NULL, NULL, 0, NULL);
209 | DDATA(baseca)[0] = base;
210 |
211 | tmp = CArray_Linspace(start, stop, num, endpoint, 1, &axis, TYPE_DOUBLE_INT, NULL);
212 |
213 | y = CArray_Power(baseca, tmp, NULL);
214 |
215 | CArray_Free(tmp);
216 | CArray_Free(baseca);
217 |
218 | if (typenum != TYPE_DOUBLE_INT) {
219 | CArrayDescriptor *descr = CArray_DescrFromType(typenum);
220 | rtn = CArray_NewLikeArray(y, CARRAY_CORDER, descr, 0);
221 | if(CArray_CastTo(rtn, y) < 0) {
222 | return NULL;
223 | }
224 | CArray_Free(y);
225 | } else {
226 | rtn = y;
227 | }
228 |
229 | if (out != NULL) {
230 | add_to_buffer(out, rtn, sizeof(CArray));
231 | }
232 |
233 | return rtn;
234 | }
235 |
236 | CArray *
237 | CArray_Geomspace(double start, double stop, int num, int endpoint, int typenum, MemoryPointer * out)
238 | {
239 |
240 | }
241 |
242 |
--------------------------------------------------------------------------------
/kernel/range.h:
--------------------------------------------------------------------------------
1 | #ifndef CARRAY_RANGE_H
2 | #define CARRAY_RANGE_H
3 |
4 | #include "carray.h"
5 |
6 | CArray * CArray_Linspace(double start, double stop, int num, int endpoint, int retstep, int * axis, int type, MemoryPointer * out);
7 | CArray * CArray_Arange(double start, double stop, double step, int type_num, MemoryPointer * ptr);
8 | CArray * CArray_Logspace(double start, double stop, int num, int endpoint, double base, int typenum, MemoryPointer * out);
9 | CArray * CArray_Geomspace(double start, double stop, int num, int endpoint, int typenum, MemoryPointer * out);
10 |
11 | #endif //CARRAY_RANGE_H
12 |
--------------------------------------------------------------------------------
/kernel/round.c:
--------------------------------------------------------------------------------
1 | #include "carray.h"
2 | #include "round.h"
3 | #include "alloc.h"
4 | #include "buffer.h"
5 | #include "iterators.h"
6 |
7 | CArray *
8 | CArray_Floor(CArray *a, MemoryPointer *out)
9 | {
10 | CArrayIterator * it1, * it2;
11 | CArray * rtn;
12 |
13 | rtn = CArray_NewLikeArray(a, CARRAY_KEEPORDER, NULL, 0);
14 |
15 | it1 = CArray_NewIter(a);
16 | it2 = CArray_NewIter(rtn);
17 |
18 | switch(CArray_TYPE(rtn)) {
19 | case TYPE_DOUBLE_INT:
20 | do {
21 | *IT_DDATA(it2) = floor(*IT_DDATA(it1));
22 | CArrayIterator_NEXT(it1);
23 | CArrayIterator_NEXT(it2);
24 | } while (CArrayIterator_NOTDONE(it1));
25 | break;
26 | case TYPE_INTEGER_INT:
27 | do {
28 | *IT_IDATA(it2) = *IT_IDATA(it1);
29 | CArrayIterator_NEXT(it1);
30 | CArrayIterator_NEXT(it2);
31 | } while (CArrayIterator_NOTDONE(it1));
32 | break;
33 | default:
34 | throw_notimplemented_exception();
35 | goto fail;
36 | }
37 |
38 | if (out != NULL) {
39 | add_to_buffer(out, rtn, sizeof(CArray));
40 | }
41 |
42 | CArrayIterator_FREE(it1);
43 | CArrayIterator_FREE(it2);
44 | return rtn;
45 | fail:
46 | CArrayIterator_FREE(it1);
47 | CArrayIterator_FREE(it2);
48 | return NULL;
49 | }
50 |
51 | CArray *
52 | CArray_Ceil(CArray *a, MemoryPointer *out)
53 | {
54 | CArrayIterator * it1, * it2;
55 | CArray * rtn;
56 |
57 | rtn = CArray_NewLikeArray(a, CARRAY_KEEPORDER, NULL, 0);
58 |
59 | it1 = CArray_NewIter(a);
60 | it2 = CArray_NewIter(rtn);
61 |
62 | switch(CArray_TYPE(rtn)) {
63 | case TYPE_DOUBLE_INT:
64 | do {
65 | *IT_DDATA(it2) = ceil(*IT_DDATA(it1));
66 | CArrayIterator_NEXT(it1);
67 | CArrayIterator_NEXT(it2);
68 | } while (CArrayIterator_NOTDONE(it1));
69 | break;
70 | case TYPE_INTEGER_INT:
71 | do {
72 | *IT_IDATA(it2) = (int)ceil((double)*IT_IDATA(it1));
73 | CArrayIterator_NEXT(it1);
74 | CArrayIterator_NEXT(it2);
75 | } while (CArrayIterator_NOTDONE(it1));
76 | break;
77 | default:
78 | throw_notimplemented_exception();
79 | goto fail;
80 | }
81 |
82 | if (out != NULL) {
83 | add_to_buffer(out, rtn, sizeof(CArray));
84 | }
85 |
86 | CArrayIterator_FREE(it1);
87 | CArrayIterator_FREE(it2);
88 | return rtn;
89 | fail:
90 | CArrayIterator_FREE(it1);
91 | CArrayIterator_FREE(it2);
92 | return NULL;
93 | }
94 |
95 | CArray *
96 | CArray_Round(CArray *a, int decimals, MemoryPointer *out)
97 | {
98 | CArrayIterator * it1, * it2;
99 | CArray * rtn;
100 | int multiplier = 1, negative_decimals = 0, i;
101 |
102 | rtn = CArray_NewLikeArray(a, CARRAY_KEEPORDER, NULL, 0);
103 |
104 | it1 = CArray_NewIter(a);
105 | it2 = CArray_NewIter(rtn);
106 |
107 | if (decimals >= 0) {
108 | for (i = 0; i <= decimals; i++) {
109 | multiplier = multiplier * 10;
110 | }
111 | } else {
112 | negative_decimals = 1;
113 | for (i = 0; i > decimals; i--) {
114 | multiplier = multiplier * 10;
115 | }
116 | }
117 |
118 | switch(CArray_TYPE(rtn)) {
119 | case TYPE_DOUBLE_INT:
120 | if (negative_decimals) {
121 | do {
122 | *IT_DDATA(it2) = ceil(*IT_DDATA(it1) / multiplier) * multiplier;
123 | CArrayIterator_NEXT(it1);
124 | CArrayIterator_NEXT(it2);
125 | } while (CArrayIterator_NOTDONE(it1));
126 | } else {
127 | do {
128 | if ((*IT_DDATA(it1) - (int)*IT_DDATA(it1)) >= 0.5) {
129 | *IT_DDATA(it2) = ceil(pow(10,decimals)* *IT_DDATA(it1))/pow(10,decimals);
130 | } else {
131 | *IT_DDATA(it2) = floor(pow(10,decimals)* *IT_DDATA(it1))/pow(10,decimals);
132 | }
133 |
134 | CArrayIterator_NEXT(it1);
135 | CArrayIterator_NEXT(it2);
136 | } while (CArrayIterator_NOTDONE(it1));
137 | }
138 | break;
139 | case TYPE_INTEGER_INT:
140 | if (negative_decimals) {
141 | do {
142 | *IT_IDATA(it2) = (int)(ceil(((double)(*IT_IDATA(it1))/multiplier)) * multiplier);
143 | CArrayIterator_NEXT(it1);
144 | CArrayIterator_NEXT(it2);
145 | } while (CArrayIterator_NOTDONE(it1));
146 | } else {
147 | do {
148 | *IT_IDATA(it2) = *IT_IDATA(it1);
149 | CArrayIterator_NEXT(it1);
150 | CArrayIterator_NEXT(it2);
151 | } while (CArrayIterator_NOTDONE(it1));
152 | }
153 | break;
154 | default:
155 | throw_notimplemented_exception();
156 | goto fail;
157 | }
158 |
159 | if (out != NULL) {
160 | add_to_buffer(out, rtn, sizeof(CArray));
161 | }
162 |
163 | CArrayIterator_FREE(it1);
164 | CArrayIterator_FREE(it2);
165 | return rtn;
166 | fail:
167 | CArrayIterator_FREE(it1);
168 | CArrayIterator_FREE(it2);
169 | return NULL;
170 | }
171 |
--------------------------------------------------------------------------------
/kernel/round.h:
--------------------------------------------------------------------------------
1 | #ifndef CARRAY_ROUND_H
2 | #define CARRAY_ROUND_H
3 |
4 | #include "carray.h"
5 |
6 | CArray * CArray_Floor(CArray *a, MemoryPointer *out);
7 | CArray * CArray_Ceil(CArray *a, MemoryPointer *out);
8 | CArray * CArray_Round(CArray *a, int decimals, MemoryPointer *out);
9 |
10 | #endif //CARRAY_ROUND_H
11 |
--------------------------------------------------------------------------------
/kernel/scalar.c:
--------------------------------------------------------------------------------
1 | #include "carray.h"
2 | #include "scalar.h"
3 | #include "php.h"
4 | #include "alloc.h"
5 | #include "buffer.h"
6 |
7 | CArrayScalar *
8 | CArrayScalar_NewLong(long sc)
9 | {
10 | CArrayScalar * ret = NULL;
11 | ret = emalloc(sizeof(CArrayScalar));
12 | ret->obval = emalloc(sizeof(long));
13 | ret->type = TYPE_LONG_INT;
14 | *((long*)ret->obval) = sc;
15 | return ret;
16 | }
17 |
18 | CArrayScalar *
19 | CArrayScalar_NewFloat(float sc)
20 | {
21 | CArrayScalar * ret = NULL;
22 | ret = emalloc(sizeof(CArrayScalar));
23 | ret->obval = emalloc(sizeof(float));
24 | ret->type = TYPE_FLOAT_INT;
25 | *((float*)ret->obval) = sc;
26 | return ret;
27 | }
28 |
29 | CArrayScalar *
30 | CArrayScalar_NewDouble(double sc)
31 | {
32 | CArrayScalar * ret = NULL;
33 | ret = emalloc(sizeof(CArrayScalar));
34 | ret->obval = emalloc(sizeof(double));
35 | ret->type = TYPE_DOUBLE_INT;
36 | *((double*)ret->obval) = sc;
37 | return ret;
38 | }
39 |
40 | CArrayScalar *
41 | CArrayScalar_NewInt(int sc)
42 | {
43 | CArrayScalar * ret = NULL;
44 | ret = emalloc(sizeof(CArrayScalar));
45 | ret->obval = emalloc(sizeof(int));
46 | ret->type = TYPE_INTEGER_INT;
47 | *((int*)ret->obval) = sc;
48 | return ret;
49 | }
50 |
51 | void
52 | CArrayScalar_FREE(CArrayScalar * sc)
53 | {
54 | efree(sc->obval);
55 | efree(sc);
56 | }
57 |
58 | CArrayScalar *
59 | CArrayScalar_FromZval(PHPObject * obj, int is_double, int is_long)
60 | {
61 | if(Z_TYPE_P(obj) == IS_DOUBLE) {
62 | /**
63 | * PHP assumes FLOAT and DOUBLE as same type, user
64 | * must identify wich one will be used.
65 | **/
66 | if(!is_double) {
67 | return CArrayScalar_NewFloat((float)Z_DVAL_P(obj));
68 | }
69 | return CArrayScalar_NewDouble(Z_DVAL_P(obj));
70 | }
71 | if(Z_TYPE_P(obj) == IS_LONG) {
72 | /**
73 | * PHP assumes LONG and INTEGER as same type, user
74 | * must identify wich one will be used.
75 | */
76 | if(!is_long) {
77 | return CArrayScalar_NewInt((int)Z_LVAL_P(obj));
78 | }
79 | return CArrayScalar_NewLong((long)Z_LVAL_P(obj));
80 | }
81 | }
82 |
83 | void *
84 | scalar_value(CArrayScalar *scalar, CArrayDescriptor *descr)
85 | {
86 | int type_num;
87 | int align;
88 | int memloc;
89 |
90 | if (descr == NULL) {
91 | descr = CArray_DescrFromScalar(scalar);
92 | type_num = descr->type_num;
93 | CArrayDescriptor_DECREF(descr);
94 | }
95 | else {
96 | type_num = descr->type_num;
97 | }
98 |
99 | switch(type_num)
100 | {
101 | case TYPE_DOUBLE_INT:
102 | return (double *) scalar->obval;
103 | break;
104 | case TYPE_INTEGER_INT:
105 | return (int *) scalar->obval;
106 | break;
107 | case TYPE_FLOAT_INT:
108 | return (float *) scalar->obval;
109 | break;
110 | }
111 |
112 | /**switch (type_num) {
113 | #define CASE(ut,lt) case TYPE_##ut: return &(((CArray##lt##ScalarObject *)scalar)->obval)
114 | CASE(INTEGER, Integer);
115 | CASE(LONG, Long);
116 | CASE(FLOAT, Float);
117 | CASE(DOUBLE, Double);
118 | }**/
119 | }
120 |
121 | CArrayDescriptor *
122 | CArray_DescrFromScalar(CArrayScalar *sc)
123 | {
124 | return CArray_DescrFromType(sc->type);
125 | }
--------------------------------------------------------------------------------
/kernel/scalar.h:
--------------------------------------------------------------------------------
1 | #ifndef PHPSCI_EXT_SCALAR_H
2 | #define PHPSCI_EXT_SCALAR_H
3 |
4 | #include "carray.h"
5 |
6 | /**
7 | * SCALARS STRUCTURES
8 | */
9 | typedef struct {
10 | int type;
11 | int obval;
12 | } CArrayIntegerScalarObject;
13 |
14 | typedef struct {
15 | int type;
16 | float obval;
17 | } CArrayFloatScalarObject;
18 |
19 | typedef struct {
20 | int type;
21 | double obval;
22 | } CArrayDoubleScalarObject;
23 |
24 | typedef struct {
25 | int type;
26 | double obval;
27 | } CArrayLongScalarObject;
28 |
29 | typedef struct {
30 | int type;
31 | char * obval;
32 | } CArrayScalar;
33 |
34 | CArrayDescriptor * CArray_DescrFromScalar(CArrayScalar *sc);
35 | CArrayScalar * CArrayScalar_FromZval(PHPObject * obj, int is_double, int is_long);
36 | void CArrayScalar_FREE(CArrayScalar * sc);
37 | CArrayScalar * CArrayScalar_NewInt(int sc);
38 | CArrayScalar * CArrayScalar_NewDouble(double sc);
39 | CArrayScalar * CArrayScalar_NewFloat(float sc);
40 | CArrayScalar * CArrayScalar_NewLong(long sc);
41 | void * scalar_value(CArrayScalar *scalar, CArrayDescriptor *descr);
42 | #endif //PHPSCI_EXT_SCALAR_H
43 |
--------------------------------------------------------------------------------
/kernel/search.h:
--------------------------------------------------------------------------------
1 | #ifndef CARRAY_SEARCH_H
2 | #define CARRAY_SEARCH_H
3 |
4 | #include "carray.h"
5 |
6 | int INT_argmax(int *ip, int n, int *max_ind, CArray *CARRAY_UNUSED(aip));
7 | int DOUBLE_argmax(double *ip, int n, int *max_ind, CArray *CARRAY_UNUSED(aip));
8 | int INT_argmin(int *ip, int n, int *max_ind, CArray *CARRAY_UNUSED(aip));
9 | int DOUBLE_argmin(double *ip, int n, int *max_ind, CArray *CARRAY_UNUSED(aip));
10 |
11 |
12 | CArray * CArray_Argmax(CArray * target, int * axis, MemoryPointer * out);
13 | CArray * CArray_Argmin(CArray * target, int * axis, MemoryPointer * out);
14 | #endif //CARRAY_SEARCH_H
15 |
--------------------------------------------------------------------------------
/kernel/shape.h:
--------------------------------------------------------------------------------
1 | #ifndef PHPSCI_EXT_SHAPE_H
2 | #define PHPSCI_EXT_SHAPE_H
3 |
4 | #include "carray.h"
5 |
6 | CArray * normalize_axis_tuple(CArray * axis, int ndim, int allow_duplicate);
7 |
8 | CArray * CArray_Newshape(CArray * self, int *newdims, int new_ndim, CARRAY_ORDER order, MemoryPointer * ptr);
9 | CArray * CArray_Transpose(CArray * target, CArray_Dims * permute, MemoryPointer * ptr);
10 | CArray * CArray_SwapAxes(CArray * ap, int a1, int a2, MemoryPointer * out);
11 | CArray * CArray_Rollaxis(CArray * arr, int axis, int start, MemoryPointer * out);
12 | CArray * CArray_Moveaxis(CArray * target, CArray * source, CArray * destination, MemoryPointer * out);
13 | void CArray_CreateSortedStridePerm(int ndim, int *strides, ca_stride_sort_item *out_strideperm);
14 | CArray * CArray_Ravel(CArray *arr, CARRAY_ORDER order);
15 | CArray * CArray_atleast1d(CArray * self, MemoryPointer * out);
16 | CArray * CArray_atleast2d(CArray * self, MemoryPointer * out);
17 | CArray * CArray_atleast3d(CArray * self, MemoryPointer * out);
18 | CArray * CArray_Squeeze(CArray * self, int * axis, MemoryPointer * out);
19 | CArray * CArray_SqueezeSelected(CArray * self, int *axis_flags, int n_axis);
20 | void CArray_RemoveAxesInPlace(CArray *arr, int *flags);
21 | CArray * CArray_ExpandDims(CArray * target, int axis, MemoryPointer * out);
22 | #endif //PHPSCI_EXT_SHAPE_H
23 |
--------------------------------------------------------------------------------
/kernel/simd.h:
--------------------------------------------------------------------------------
1 | #ifndef CARRAY_SIMD_H
2 | #define CARRAY_SIMD_H
3 |
4 |
5 | int run_binary_simd_multiply_DOUBLE(char **args, int const *dimensions, int const *steps);
6 | int run_unary_simd_sqrt_DOUBLE(char **args, int const *dimensions, int const *steps);
7 |
8 | #endif //CARRAY_SIMD_H
9 |
--------------------------------------------------------------------------------
/kernel/statistics.c:
--------------------------------------------------------------------------------
1 | #include "statistics.h"
2 | #include "carray.h"
3 | #include "convert_type.h"
4 | #include "alloc.h"
5 | #include "buffer.h"
6 | #include "common/common.h"
7 | #include "arraytypes.h"
8 |
9 | /*
10 | * Implementation which is common between CArray_Correlate
11 | * and CArray_Correlate2.
12 | *
13 | * inverted is set to 1 if computed correlate(ap2, ap1), 0 otherwise
14 | */
15 | static CArray*
16 | _carray_correlate(CArray *ap1, CArray *ap2, int typenum,
17 | int mode, int *inverted)
18 | {
19 | CArray *ret;
20 | int length;
21 | int i, n1, n2, n, n_left, n_right;
22 | int is1, is2, os;
23 | char *ip1, *ip2, *op;
24 | CArray_DotFunc *dot;
25 |
26 | n1 = CArray_DIMS(ap1)[0];
27 | n2 = CArray_DIMS(ap2)[0];
28 | if (n1 < n2) {
29 | ret = ap1;
30 | ap1 = ap2;
31 | ap2 = ret;
32 | ret = NULL;
33 | i = n1;
34 | n1 = n2;
35 | n2 = i;
36 | *inverted = 1;
37 | } else {
38 | *inverted = 0;
39 | }
40 |
41 | length = n1;
42 | n = n2;
43 | switch(mode) {
44 | case 0:
45 | length = length - n + 1;
46 | n_left = n_right = 0;
47 | break;
48 | case 1:
49 | n_left = (int)(n/2);
50 | n_right = n - n_left - 1;
51 | break;
52 | case 2:
53 | n_right = n - 1;
54 | n_left = n - 1;
55 | length = length + n - 1;
56 | break;
57 | default:
58 | throw_valueerror_exception("mode must be 0, 1, or 2");
59 | return NULL;
60 | }
61 |
62 | /*
63 | * Need to choose an output array that can hold a sum
64 | * -- use priority to determine which subtype.
65 | */
66 | ret = new_array_for_sum(ap1, ap2, NULL, 1, &length, typenum, NULL);
67 | if (ret == NULL) {
68 | return NULL;
69 | }
70 | dot = CArray_DESCR(ret)->f->dotfunc;
71 | if (dot == NULL) {
72 | throw_valueerror_exception("function not available for this data type");
73 | goto clean_ret;
74 | }
75 |
76 | is1 = CArray_STRIDES(ap1)[0];
77 | is2 = CArray_STRIDES(ap2)[0];
78 | op = CArray_DATA(ret);
79 | os = CArray_DESCR(ret)->elsize;
80 | ip1 = CArray_DATA(ap1);
81 | ip2 = CArray_BYTES(ap2) + n_left*is2;
82 | n = n - n_left;
83 | for (i = 0; i < n_left; i++) {
84 | dot(ip1, is1, ip2, is2, op, n);
85 | n++;
86 | ip2 -= is2;
87 | op += os;
88 | }
89 | if (small_correlate(ip1, is1, n1 - n2 + 1, CArray_TYPE(ap1),
90 | ip2, is2, n, CArray_TYPE(ap2),
91 | op, os)) {
92 | ip1 += is1 * (n1 - n2 + 1);
93 | op += os * (n1 - n2 + 1);
94 | }
95 | else {
96 | for (i = 0; i < (n1 - n2 + 1); i++) {
97 | dot(ip1, is1, ip2, is2, op, n);
98 | ip1 += is1;
99 | op += os;
100 | }
101 | }
102 | for (i = 0; i < n_right; i++) {
103 | n--;
104 | dot(ip1, is1, ip2, is2, op, n);
105 | ip1 += is1;
106 | op += os;
107 | }
108 |
109 | return ret;
110 |
111 | clean_ret:
112 | CArray_XDECREF(ret);
113 | return NULL;
114 | }
115 |
116 |
117 | CArray *
118 | CArray_Correlate(CArray * op1, CArray * op2, int mode, MemoryPointer * out)
119 | {
120 | CArray *ap1, *ap2, *ret = NULL;
121 | int typenum;
122 | int unused;
123 | CArrayDescriptor *typec;
124 |
125 | typenum = CArray_ObjectType(op1, 0);
126 | typenum = CArray_ObjectType(op2, typenum);
127 |
128 | typec = CArray_DescrFromType(typenum);
129 | CArrayDescriptor_INCREF(typec);
130 |
131 | ap1 = CArray_FromAny(op1, typec, 1, 1, CARRAY_ARRAY_DEFAULT);
132 | if (ap1 == NULL) {
133 | CArrayDescriptor_DECREF(typec);
134 | return NULL;
135 | }
136 | ap2 = CArray_FromAny(op2, typec, 1, 1, CARRAY_ARRAY_DEFAULT);
137 | if (ap2 == NULL) {
138 | goto fail;
139 | }
140 |
141 | ret = _carray_correlate(ap1, ap2, typenum, mode, &unused);
142 | if (ret == NULL) {
143 | goto fail;
144 | }
145 |
146 | if (out != NULL) {
147 | add_to_buffer(out, ret, sizeof(CArray));
148 | }
149 |
150 | CArrayDescriptor_FREE(typec);
151 | return ret;
152 |
153 | fail:
154 | CArray_XDECREF(ap1);
155 | CArray_XDECREF(ap2);
156 | CArray_XDECREF(ret);
157 | return NULL;
158 | }
159 |
160 |
161 | CArray *
162 | CArray_Correlate2(CArray * op1, CArray * op2, int mode, MemoryPointer * out)
163 | {
164 | CArray *ap1, *ap2, *ret = NULL;
165 | int typenum;
166 | CArrayDescriptor *typec;
167 | int inverted;
168 | int st;
169 |
170 | typenum = CArray_ObjectType(op1, 0);
171 | typenum = CArray_ObjectType(op2, typenum);
172 |
173 | typec = CArray_DescrFromType(typenum);
174 | CArrayDescriptor_INCREF(typec);
175 |
176 | ap1 = CArray_FromAny(op1, typec, 1, 1, CARRAY_ARRAY_DEFAULT);
177 | if (ap1 == NULL) {
178 | CArrayDescriptor_DECREF(typec);
179 | CArrayDescriptor_FREE(typec);
180 | return NULL;
181 | }
182 | ap2 = CArray_FromAny(op2, typec, 1, 1, CARRAY_ARRAY_DEFAULT);
183 | if (ap2 == NULL) {
184 | goto clean_ap1;
185 | }
186 |
187 | ret = _carray_correlate(ap1, ap2, typenum, mode, &inverted);
188 | if (ret == NULL) {
189 | goto clean_ap2;
190 | }
191 |
192 | /*
193 | * If we inverted input orders, we need to reverse the output array (i.e.
194 | * ret = ret[::-1])
195 | */
196 | if (inverted) {
197 | //st = _carray_revert(ret);
198 | if (st) {
199 | goto clean_ret;
200 | }
201 | }
202 |
203 | if (out != NULL) {
204 | add_to_buffer(out, ret, sizeof(CArray));
205 | }
206 |
207 | CArrayDescriptor_DECREF(typec);
208 |
209 | if (ap1->data != op1->data) {
210 | CArray_Free(ap1);
211 | }
212 |
213 | if (ap2->data != op2->data) {
214 | CArray_Free(ap2);
215 | }
216 |
217 | return ret;
218 | clean_ret:
219 | CArray_XDECREF(ret);
220 | clean_ap2:
221 | CArray_XDECREF(ap2);
222 | clean_ap1:
223 | CArray_XDECREF(ap1);
224 | return NULL;
225 | }
--------------------------------------------------------------------------------
/kernel/statistics.h:
--------------------------------------------------------------------------------
1 | #ifndef CARRAY_STATISTICS_H
2 | #define CARRAY_STATISTICS_H
3 |
4 | #include "carray.h"
5 |
6 | CArray * CArray_Correlate2(CArray * op1, CArray * op2, int mode, MemoryPointer * out);
7 | CArray * CArray_Correlate(CArray * op1, CArray * op2, int mode, MemoryPointer * out);
8 |
9 | #endif //CARRAY_STATISTICS_H
10 |
--------------------------------------------------------------------------------
/kernel/storage.c:
--------------------------------------------------------------------------------
1 | #include "carray.h"
2 | #include "storage.h"
3 | #include "buffer.h"
4 |
5 | /**
6 | * Save CArrray to binary file
7 | *
8 | * @param filename
9 | * @param target
10 | * @return 1 - Success or 0 error
11 | */
12 | int
13 | CArrayStorage_SaveBin(char * filename, CArray *target)
14 | {
15 | char * fullname = emalloc(sizeof(char) * (strlen(filename) + 4));
16 |
17 | strcpy(fullname, filename);
18 | strcat(fullname, ".carray");
19 |
20 | FILE* fp = fopen(fullname, "wb");
21 |
22 | if (fp == NULL || fp == 0) {
23 | return 0;
24 | }
25 |
26 | assert(fp != 0);
27 |
28 | fwrite(&(target->ndim), sizeof(int), 1, fp);
29 | fwrite(target->dimensions, sizeof(int) * CArray_NDIM(target), 1, fp);
30 | fwrite(target->strides, sizeof(int), CArray_NDIM(target), fp);
31 | fwrite(&(target->flags), sizeof(int), 1, fp);
32 | fwrite(&(target->descriptor->type_num), sizeof(int), 1, fp);
33 | fwrite(target->data, CArray_DESCR(target)->elsize, CArray_MultiplyList(CArray_DIMS(target), CArray_NDIM(target)), fp);
34 |
35 | fclose(fp);
36 | efree(fullname);
37 |
38 | return 1;
39 | }
40 |
41 | int
42 | CArrayStorage_LoadBin(char *filename, MemoryPointer *out)
43 | {
44 | CArrayDescriptor *descr;
45 | CArray *array;
46 | char * fullname = emalloc(sizeof(char) * (strlen(filename) + 4));
47 | int type_num;
48 |
49 | strcpy(fullname, filename);
50 | strcat(fullname, ".carray");
51 |
52 | FILE* fp = fopen(fullname, "r");
53 |
54 | if (fp == NULL || fp == 0) {
55 | return 0;
56 | }
57 |
58 | assert(fp != 0);
59 |
60 | array = emalloc(sizeof(CArray));
61 | fread(&(array->ndim), sizeof(int), 1, fp);
62 |
63 | array->dimensions = emalloc(sizeof(int) * array->ndim);
64 | fread(array->dimensions, sizeof(int) * array->ndim, 1, fp);
65 |
66 | array->strides = emalloc(sizeof(int) * array->ndim);
67 | fread(array->strides, sizeof(int), array->ndim, fp);
68 | fread(&(array->flags), sizeof(int), 1, fp);
69 | fread(&type_num, sizeof(int), 1, fp);
70 |
71 | descr = CArray_DescrFromType(type_num);
72 | array->descriptor = descr;
73 |
74 | array->data = emalloc(array->descriptor->elsize * CArray_MultiplyList(CArray_DIMS(array), CArray_NDIM(array)));
75 | fread(array->data, array->descriptor->elsize, CArray_MultiplyList(CArray_DIMS(array), CArray_NDIM(array)), fp);
76 |
77 | array->descriptor->numElements = CArray_MultiplyList(CArray_DIMS(array), CArray_NDIM(array));
78 | array->refcount = 0;
79 |
80 |
81 | array->flags |= CARRAY_ARRAY_OWNDATA;
82 |
83 | add_to_buffer(out, array, sizeof(CArray));
84 | efree(fullname);
85 | return 1;
86 | }
--------------------------------------------------------------------------------
/kernel/storage.h:
--------------------------------------------------------------------------------
1 | #ifndef CARRAY_STORAGE_H
2 | #define CARRAY_STORAGE_H
3 |
4 | #include "carray.h"
5 |
6 | int CArrayStorage_SaveBin(char * filename, CArray *target);
7 | int CArrayStorage_LoadBin(char * filename, MemoryPointer * out);
8 | #endif //CARRAY_STORAGE_H
9 |
--------------------------------------------------------------------------------
/kernel/trigonometric.h:
--------------------------------------------------------------------------------
1 | #ifndef PHPSCI_EXT_TRIGONOMETRIC_H
2 | #define PHPSCI_EXT_TRIGONOMETRIC_H
3 |
4 | #include "carray.h"
5 |
6 | typedef double (CArray_CFunc_ElementWise) (double x);
7 | void CArray_ElementWise_CFunc_Int(CArray * target, CArray * result, CArray_CFunc_ElementWise * func);
8 | void CArray_ElementWise_CFunc_Double(CArray * target, CArray * result, CArray_CFunc_ElementWise * func);
9 | void CArray_ElementWise_CFunc(CArray * target, CArray * result, CArray_CFunc_ElementWise * func);
10 |
11 | CArray * CArray_Sin(CArray * target, MemoryPointer * out);
12 | CArray * CArray_Cos(CArray * target, MemoryPointer * out);
13 | CArray * CArray_Tan(CArray * target, MemoryPointer * out);
14 | CArray * CArray_Arcsin(CArray * target, MemoryPointer * out);
15 | CArray * CArray_Arccos(CArray * target, MemoryPointer * out);
16 | CArray * CArray_Arctan(CArray * target, MemoryPointer * out);
17 | CArray * CArray_Sinh(CArray * target, MemoryPointer * out);
18 | CArray * CArray_Cosh(CArray * target, MemoryPointer * out);
19 | CArray * CArray_Tanh(CArray * target, MemoryPointer * out);
20 | CArray * CArray_Arcsinh(CArray * target, MemoryPointer * out);
21 | CArray * CArray_Arccosh(CArray * target, MemoryPointer * out);
22 | CArray * CArray_Arctanh(CArray * target, MemoryPointer * out);
23 | #endif //PHPSCI_EXT_TRIGONOMETRIC_H
24 |
--------------------------------------------------------------------------------
/mkdocs.yml:
--------------------------------------------------------------------------------
1 | site_name: PHPSci CArray
2 | theme: readthedocs
3 | repo_url: http://github.com/phpsci/phpsci-ext
4 | site_url: http://phpsci-carray.readthedocs.io/
5 | site_description: 'Documentation for PHPSci CArray Extension for PHP.'
6 | docs_dir: docs/
7 | dev_addr: '0.0.0.0:8000'
8 |
9 | pages:
10 | - Home: index.md
11 | - Routines:
12 | - CArray Object: routines/carray_object.md
13 | - Ones and Zeros: routines/ones_and_zeros.md
14 | - Numerical Ranges: routines/numerical_ranges.md
15 | - Transpose: routines/transpose.md
16 | - Dimensions: routines/dimensions.md
17 | - Indexing: routines/indexing.md
18 | - Matrix & Vector Products: routines/ma_products.md
19 | - Decompositions: routines/decompositions.md
20 | - Matrix Norms: routines/ma_norms.md
21 | - Equations & Inverse: routines/equations_and_inverse.md
22 | - Trigonometric: routines/trigonometric.md
23 | - Hyperbolic: routines/hyperbolic.md
24 | - Rounding: routines/rounding.md
25 | - Sums, products, differences: routines/sum_products_and_diff.md
26 | - Exponents and logarithms: routines/exponents_loga.md
27 | - Arithmetic: routines/arithmetic.md
28 | - Sorting: routines/sorting.md
29 | - Searching: routines/searching.md
30 | - Random Sampling: routines/random.md
31 | - Rearranging: routines/rearranging.md
32 | - Distributions: routines/distributions.md
33 | - Statistics: routines/statistics.md
34 | - CArray Internals:
35 | - Internals Explanation: internals/explanation.md
36 | - C Reference: internals/carray_api.md
37 |
--------------------------------------------------------------------------------
/phpsci.h:
--------------------------------------------------------------------------------
1 | /*
2 | +----------------------------------------------------------------------+
3 | | PHPSci CArray |
4 | +----------------------------------------------------------------------+
5 | | Copyright (c) 2018 PHPSci Team |
6 | +----------------------------------------------------------------------+
7 | | Licensed under the Apache License, Version 2.0 (the "License"); |
8 | | you may not use this file except in compliance with the License. |
9 | | You may obtain a copy of the License at |
10 | | |
11 | | http://www.apache.org/licenses/LICENSE-2.0 |
12 | | |
13 | | Unless required by applicable law or agreed to in writing, software |
14 | | distributed under the License is distributed on an "AS IS" BASIS, |
15 | | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
16 | | implied. |
17 | | See the License for the specific language governing permissions and |
18 | | limitations under the License. |
19 | +----------------------------------------------------------------------+
20 | | Authors: Henrique Borba |
21 | +----------------------------------------------------------------------+
22 | */
23 |
24 | #ifndef CARRAY_EXT_PHPSCI_H
25 | #define CARRAY_EXT_PHPSCI_H
26 |
27 | #define PHP_CARRAY_EXTNAME "CArray"
28 | #define PHP_CARRAY_VERSION "0.0.1"
29 |
30 | #ifdef ZTS
31 | #include "TSRM.h"
32 | #endif
33 | #include "php.h"
34 | #include "kernel/carray.h"
35 |
36 |
37 | static zend_class_entry *carray_sc_entry;
38 | static zend_object_handlers carray_object_handlers;
39 | static zend_class_entry *carray_exception_sc_entry;
40 | static zend_class_entry *carray_iterator_sc_entry;
41 |
42 | extern zend_module_entry carray_module_entry;
43 |
44 | #define phpext_carray_ptr &carray_module_entry
45 |
46 | void RETURN_MEMORYPOINTER(zval * return_value, MemoryPointer * ptr);
47 | int * ZVAL_TO_TUPLE(zval * obj, int * size);
48 | void ZVAL_TO_MEMORYPOINTER(zval * obj, MemoryPointer * ptr, char * type);
49 | void RETURN_RUBIX_MEMORYPOINTER(zval * return_value, MemoryPointer * ptr);
50 | void FREE_FROM_MEMORYPOINTER(MemoryPointer * ptr);
51 | void * FREE_TUPLE(int * tuple);
52 | zval * MEMORYPOINTER_TO_ZVAL(MemoryPointer * ptr);
53 | #endif //PHPSCI_EXT_PHPSCI_H
54 |
--------------------------------------------------------------------------------
/tests/arithmetics/arithmetics_dd_1d_add.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | CArray Arithmetics ([DOUBLE] + DOUBLE): new CArray([1.0, 2.0, 3.0]) plus 1.5
3 | --FILE--
4 | getMessage();
11 | }
12 | --EXPECT--
13 | array is not broadcastable to correct shape
--------------------------------------------------------------------------------
/tests/initializers/linspace.basicadd.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | CArray::linspace(2.0, 3.0, 5) plus 1
3 | --FILE--
4 |
11 | int(2)
12 | ["ndim"]=>
13 | int(1)
14 | }
--------------------------------------------------------------------------------
/tests/initializers/linspace.basicdump.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | CArray::linspace(2.0, 3.0, 5) basic dump
3 | --FILE--
4 | 0
11 | [ndim] => 1
12 | )
13 |
--------------------------------------------------------------------------------
/travis/compile.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 |
4 | phpize
5 | ./configure
6 | make clean
7 | make
8 | make install
--------------------------------------------------------------------------------