From d2e4af5815d8963f6ace09f3427e69ff41272791 Mon Sep 17 00:00:00 2001 From: michaeleg21 Date: Thu, 20 Jun 2024 11:24:11 -0400 Subject: [PATCH 01/11] added docs directory --- docs/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/__init__.py diff --git a/docs/__init__.py b/docs/__init__.py new file mode 100644 index 0000000..e69de29 From c8b716378b620747972e97ff56c3695e4e6b7d6c Mon Sep 17 00:00:00 2001 From: michaeleg21 Date: Mon, 22 Jul 2024 11:38:15 -0400 Subject: [PATCH 02/11] Initial documentation commit initial python arrayfire documentation with overview and tutorial. This includes tests for all snippets used in the documentation. --- dev-requirements.txt | 4 + docs/__init__.py | 0 docs/_static/custom.css | 8 + docs/afjit.py | 24 ++ docs/arrayandmatrixmanipulation.py | 142 ++++++++++++ docs/arrayandmatrixmanipulation.rst | 144 ++++++++++++ docs/arrayfirejitcodegeneration.rst | 45 ++++ docs/conf.py | 41 ++++ docs/configuringarrayfireenvironment.rst | 9 + docs/debuggingarrayfirecode.rst | 9 + docs/examples.rst | 35 +++ docs/functions.rst | 35 +++ docs/gettingstarted.py | 277 +++++++++++++++++++++++ docs/gettingstarted.rst | 209 +++++++++++++++++ docs/index.rst | 43 ++++ docs/indexing.py | 129 +++++++++++ docs/indexing.rst | 208 +++++++++++++++++ docs/installation.rst | 131 +++++++++++ docs/introductiontovectorization.py | 195 ++++++++++++++++ docs/introductiontovectorization.rst | 126 +++++++++++ docs/linux.rst | 120 ++++++++++ docs/overview.py | 16 ++ docs/overview.rst | 121 ++++++++++ docs/releasenotes.rst | 35 +++ docs/tutorial.rst | 20 ++ 25 files changed, 2126 insertions(+) delete mode 100644 docs/__init__.py create mode 100644 docs/_static/custom.css create mode 100644 docs/afjit.py create mode 100644 docs/arrayandmatrixmanipulation.py create mode 100644 docs/arrayandmatrixmanipulation.rst create mode 100644 docs/arrayfirejitcodegeneration.rst create mode 100644 docs/conf.py create mode 100644 docs/configuringarrayfireenvironment.rst create mode 100644 docs/debuggingarrayfirecode.rst create mode 100644 docs/examples.rst create mode 100644 docs/functions.rst create mode 100644 docs/gettingstarted.py create mode 100644 docs/gettingstarted.rst create mode 100644 docs/index.rst create mode 100644 docs/indexing.py create mode 100644 docs/indexing.rst create mode 100644 docs/installation.rst create mode 100644 docs/introductiontovectorization.py create mode 100644 docs/introductiontovectorization.rst create mode 100644 docs/linux.rst create mode 100644 docs/overview.py create mode 100644 docs/overview.rst create mode 100644 docs/releasenotes.rst create mode 100644 docs/tutorial.rst diff --git a/dev-requirements.txt b/dev-requirements.txt index 31e4b98..ae38ba6 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -18,3 +18,7 @@ pytest-cov>=5.0.0 # Allows codecov to generate coverage reports coverage[toml]>=6.4 codecov>=2.1.12 + +# Allows documentation +sphinx>=7.3.7 +sphinxawesome_theme>=5.2.0 diff --git a/docs/__init__.py b/docs/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/docs/_static/custom.css b/docs/_static/custom.css new file mode 100644 index 0000000..e56b184 --- /dev/null +++ b/docs/_static/custom.css @@ -0,0 +1,8 @@ +a { + color: blue; /* Set the color of links to blue */ + text-decoration: underline; /* Underline links */ +} + +a:hover { + color: darkblue; /* Change link color to dark blue on hover */ +} diff --git a/docs/afjit.py b/docs/afjit.py new file mode 100644 index 0000000..97f3163 --- /dev/null +++ b/docs/afjit.py @@ -0,0 +1,24 @@ +# [jit-snippet] + +# As JIT is automatically enabled in ArrayFire, this version of the function +# forces each expression to be evaluated. If the eval() function calls are +# removed, then the execution of this code would be equivalent to the +# following function. + +def pi_no_jit(x, y, temp, samples): + temp = x * x + temp.eval() + temp += y * y + temp.eval() + temp = sqrt(temp) + temp.eval() + temp = temp < 1 + temp.eval() + return 4.0 * sum(temp) / samples + +def pi_jit(x, y, temp, samples): + temp = sqrt(x * x + y * y) < 1 + temp.eval() + return 4.0 * sum(temp) / samples + +# [jit-endsnippet] \ No newline at end of file diff --git a/docs/arrayandmatrixmanipulation.py b/docs/arrayandmatrixmanipulation.py new file mode 100644 index 0000000..55d5f77 --- /dev/null +++ b/docs/arrayandmatrixmanipulation.py @@ -0,0 +1,142 @@ +# [manipulation1-snippet] + +import arrayfire as af + +# Creates a 3x3 array filled with random numbers between [0, 1) +a = af.randu((3, 3)) + +# Flattens the array 'a' into a 1-dimensional column vector +flat_a = af.flat(a) + +# Display the original array 'a' +print(a) + +# [manipulation1-endsnippet] + + +# [manipulation2-snippet] + + +import arrayfire as af + +# Generate a 5x2 array of uniformly distributed random numbers between [0, 1) +a = af.randu((5, 2)) + +# Print the original array 'a' +print("Original array 'a' [5 2 1 1]") +print(a) + +# Flip the array 'a' along both axes (rows and columns) +flip_a = af.flip(a) + +# Print the flipped array 'flip_a' +print("\nFlipped array 'flip_a' [5 2 1 1]") +print(flip_a) + +# [manipulation2-endsnippet] + + +# [manipulation3-snippet] + +import arrayfire as af + +# Generate a 1-dimensional array 'a' of size 5 filled with uniformly distributed random numbers between [0, 1) +a = af.randu((5,)) + +# Print the original array 'a' +print("Original array 'a' [5 1 1 1]") +print(a) + +# Join the array 'a' with itself along axis 0 +a_join = af.join(0, a, a) + +# Print the joined array 'a_join' +print("\nJoined array 'a_join' [10 1 1 1]") +print(a_join) +# [manipulation3-endsnippet] + + +# [manipulation4-snippet] + +import arrayfire as af + +a = af.randu((8,)) + +print(a) + +moddims_a = af.moddims(a,(2,4)) + +print(moddims_a) + +moddims_b = af.moddims(a,(len(a),)) +print(moddims_b) + +# [manipulation4-endsnippet] + + +# [manipulation5-snippet] + + +import arrayfire as af + +a = af.randu((2,2,3,1)) + +print(a) + +a_reorder = af.reorder(a,()) +# [manipulation5-endsnippet] + +# [manipulation6-snippet] + +import arrayfire as af + +a = af.randu((3,5)) +print(a) + +a_shift = af.shift(a,(0,2)) +print(a_shift) + +a_shift1 = af.shift(a,(-1,2)) +print(a_shift1) + +# [manipulation6-endsnippet] + + +# [manipulation7-snippet] + +import arrayfire as af + +a = af.randu((3,)) #[3,1,1,1] + +print (a) + +a_tile = af.tile(a,(2,)) +print(a_tile) + +a_tile1 = af.tile(a,(2,2)) +print(a_tile1) + +a_tile2 = af.tile(a,(1,2,3)) +print(a_tile2) +# [manipulation7-endsnippet] + + +# [manipulation8-snippet] + +import arrayfire as af + +a = af.randu((3,3)) +print(a) #[3 3 1 1] + +''' 0.3949 0.8465 0.3709 + 0.3561 0.9399 0.2751 + 0.6097 0.6802 0.2720''' + + +a_transpose = af.transpose(a) +print(a_transpose) #[3 3 1 1] + +''' 0.3949 0.3561 0.6097 + 0.8465 0.9399 0.6802 + 0.3709 0.2751 0.2720''' +# [manipulation8-endsnippet] diff --git a/docs/arrayandmatrixmanipulation.rst b/docs/arrayandmatrixmanipulation.rst new file mode 100644 index 0000000..ef691e4 --- /dev/null +++ b/docs/arrayandmatrixmanipulation.rst @@ -0,0 +1,144 @@ +Array and Matrix Manipulation +============================= +ArrayFire provides several different methods for manipulating arrays and matrices. The functionality includes: + +* moddims() - change the dimensions of an array without changing the data +* array() - create a (shallow) copy of an array with different dimensions. +* flat() - flatten an array to one dimension +* flip() - flip an array along a dimension +* join() - join up to 4 arrays +* reorder() - changes the dimension order within the array +* shift() - shifts data along a dimension +* tile() - repeats an array along a dimension +* transpose() - performs a matrix transpose +* T() - transpose a matrix or vector (shorthand notation) +* H() - Hermitian Transpose (conjugate-transpose) a matrix + +Below we provide several examples of these functions and their use. + +flat() +====== +The **flat()** function flattens an array to one dimension: + +.. literalinclude:: arrayandmatrixmanipulation.py + :language: python + :start-after: [manipulation1-snippet] + :end-before: [manipulation1-endsnippet] + +The **flat** function can be called from Python as follows: + +.. admonition:: Function + + af.flat(array) - Python function for flattening an array + +flip() +====== +The **flip()** function flips the contents of an array along a chosen dimension. In the example below, we show the 5x2 array flipped along the zeroth (i.e. within a column) and first (e.g. across rows) axes: + + +.. literalinclude:: arrayandmatrixmanipulation.py + :language: python + :start-after: [manipulation2-snippet] + :end-before: [manipulation2-endsnippet] + +The **flip** function can be called from Python as follows: + +.. admonition:: Function + + af.flip(array) - Python function for flipping an array + + +join() +====== + +The **join()** function joins arrays along a specific dimension. The C++ interface can join up to four arrays whereas the C interface supports up to 10 arrays. Here is an example of how to use join an array to itself: + +.. literalinclude:: arrayandmatrixmanipulation.py + :language: python + :start-after: [manipulation3-snippet] + :end-before: [manipulation3-endsnippet] + + +The **join** function can be called from Python as follows: + +.. admonition:: Function + + af.join(0, array, array1) - Python function for joining arrays along a specified axis + +moddims() +========= + +The **moddims()** function changes the dimensions of an array without changing its data or order. Note that this function modifies only the metadata associated with the array. It does not modify the content of the array. Here is an example of moddims() converting an 8x1 array into a 2x4 and then back to a 8x1: + +.. literalinclude:: arrayandmatrixmanipulation.py + :language: python + :start-after: [manipulation4-snippet] + :end-before: [manipulation4-endsnippet] + +The moddims function has a single form in the Python API: + +.. admonition:: Function + + af.moddims(array, (3,2)) - Python function for modifying dimensions of an array + + +reorder() +========= +The **reorder()** function modifies the order of data within an array by exchanging data according to the change in dimensionality. The linear ordering of data within the array is preserved. + +.. literalinclude:: arrayandmatrixmanipulation.py + :language: python + :start-after: [manipulation5-snippet] + :end-before: [manipulation5-endsnippet] + +shift() +======= +The **shift()** function shifts data in a circular buffer fashion along a chosen dimension. Consider the following example: + + +.. literalinclude:: arrayandmatrixmanipulation.py + :language: python + :start-after: [manipulation6-snippet] + :end-before: [manipulation6-endsnippet] + +The shift function can be called from Python as follows: +.. admonition:: Function + + af.shift(array, (3,2)) - Python function for shifting arrays along specified dimension + +tile() +====== +The **tile()** function repeats an array along the specified dimension. For example below we show how to tile an array along the zeroth and first dimensions of an array: + +.. literalinclude:: arrayandmatrixmanipulation.py + :language: python + :start-after: [manipulation7-snippet] + :end-before: [manipulation7-endsnippet] + +.. admonition:: Function + + af.tile(array, (3,2)) - Python function that tiles arrays along specified dimensions + + +transpose() +=========== +The **transpose()** function performs a standard matrix transpose. The input array must have the dimensions of a 2D-matrix. + +.. literalinclude:: arrayandmatrixmanipulation.py + :language: python + :start-after: [manipulation8-snippet] + :end-before: [manipulation8-endsnippet] + + +The python interface for transpose is as follows: + +.. admonition:: Function + + af.transpose(array) - Python function to transpose matrix in place + + + +array() +======= +**array()** can be used to create a (shallow) copy of a matrix with different dimensions. The total number of elements must remain the same. This function is a wrapper over the moddims() function discussed earlier. + diff --git a/docs/arrayfirejitcodegeneration.rst b/docs/arrayfirejitcodegeneration.rst new file mode 100644 index 0000000..d536368 --- /dev/null +++ b/docs/arrayfirejitcodegeneration.rst @@ -0,0 +1,45 @@ +ArrayFire JIT Code Generation +============================= +The ArrayFire library offers JIT (Just In Time) compiling for elementwise arithmetic operations. This includes trigonometric functions, comparisons, and element-wise operations. + +At runtime, ArrayFire aggregates these function calls using an Abstract Syntax Tree (AST) data structure such that whenever a JIT-supported function is called, it is added into the AST for a given variable instance. The AST of the variable is computed if one of the following conditions is met: + +* an explication evaluation is required by the programmer using the eval function, or +* the variable is required to compute a different variable that is not JIT-supported. + +When the above occurs, and the variable needs to be evaluated, the functions and variables in the AST data structure are used to create a single kernel. This is done by creating a customized kernel on-the-fly that is made up of all the functions in the AST. The customized function is then executed. + +This JIT compilation technique has multiple benefits: + +* A reduced number of kernel calls – a kernel call can be a significant overhead for small data sets. +* Better cache performance – there are many instances in which the memory required by a single element in the array can be reused multiple times, or the temporary value of a computation can be stored in the cache and reused by future computations. +* Temporary memory allocation and write-back can be reduced – when multiple expressions are evaluated and stored into temporary arrays, these arrays need to be allocated and the results written back to main memory. +* Avoid computing elements that are not used – there are cases in which the AST is created for a variable; however, the expression is not used later in the computation. Thus, its evaluation can be avoided. +* Better performance – all the above can help reduce the total execution time. + +.. literalinclude:: afjit.py + :language: python + :start-after: [jit-snippet] + :end-before: [jit-endsnippet] + + +The above code computes the value of π using a Monte-Carlo simulation where points are randomly generated within the unit square. Each point is tested to see if it is within the unit circle. The ratio of points within the circle and square approximate the value π. The accuracy of π improves as the number of samples is increased, which motivates using additional samples. + +There are two implementations above: + +1. an implementation that does not benefit from the JIT (pi_no_jit), and +2. an implementation that takes advantage of the JIT feature (pi_jit). + +Specifically, as JIT is an integral feature of the ArrayFire library, it cannot simply be turned on and off. The only way for a programmer to sidestep the JIT operations is to manually force the evaluation of expressions. This is done in the non-JIT-supported implementation. + +Timing these two implementations results in the following performance benchmark: + +**Add Picture** + +The above figure depicts the execution time (abscissa) as a function of the number of samples (ordinate) for the two implementations discussed above. + +When the number of samples is small, the execution time of pi_no_jit is dominated by the launch of multiple kernels and the execution time pi_jit is dominated by on-the-fly compilation of the JIT code required to launch a single kernel. Even with this JIT compilation time, pi_jit outperforms pi_no_jit by 1.4-2.0X for smaller sample sizes. + +When the number of samples is large, both the kernel launch overhead and the JIT code creation are no longer the limiting factors – the kernel’s computational load dominates the execution time. Here, the pi_jit outperforms pi_no_jit by 2.0-2.7X. + +The number of applications that benefit from the JIT code generation is significant. The actual performance benefits are also application-dependent. \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..8c1aa89 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,41 @@ +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html +import sys +import os +sys.path.insert(0, os.path.abspath('../..')) + + + +# -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information + +project = 'ArrayFire' +copyright = '2024, Michael Egwuatu' +author = 'Michael Egwuatu' +release = '6/11/2024' + +# -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration + +extensions = [ + 'sphinx.ext.duration', + 'sphinx.ext.doctest', + 'sphinx.ext.autodoc', + 'sphinx.ext.mathjax', +] + +templates_path = ['_templates'] +exclude_patterns = [] + + + +# -- Options for HTML output ------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output + +html_theme = 'sphinxawesome_theme' +html_static_path = ['_static'] + + + diff --git a/docs/configuringarrayfireenvironment.rst b/docs/configuringarrayfireenvironment.rst new file mode 100644 index 0000000..00754e6 --- /dev/null +++ b/docs/configuringarrayfireenvironment.rst @@ -0,0 +1,9 @@ +Configuring ArrayFire Environment +================================= +This page lists environment and runtime configurations that will help enhance your experience with ArrayFire. + +Environment Variables +===================== +The following are useful environment variable that can be used with ArrayFire. + + diff --git a/docs/debuggingarrayfirecode.rst b/docs/debuggingarrayfirecode.rst new file mode 100644 index 0000000..cb36d03 --- /dev/null +++ b/docs/debuggingarrayfirecode.rst @@ -0,0 +1,9 @@ +Debugging ArrayFire Issues +========================== +Python +~~~~~~ +* :literal:`arrayfire.device.print_mem_info("message")`: Print table of memory used by ArrayFire on the active GPU + +Further Reading +=============== +See the `ArrayFire README `_ for support information. \ No newline at end of file diff --git a/docs/examples.rst b/docs/examples.rst new file mode 100644 index 0000000..acccf46 --- /dev/null +++ b/docs/examples.rst @@ -0,0 +1,35 @@ +Examples +======== + + + +Introduction +------------ + +This is the introductory section of File 1. + +Modules +------- + +Here is some content for the first section. + +Mod +~~~ + +This is a subsection under Section 1. + +Mod1 +~~~~ + +More content for the second section. + +Mod2 +~~~~ + +This concludes the content of File 1. + +Mod3 +~~~~ + +Mod4 +~~~~ diff --git a/docs/functions.rst b/docs/functions.rst new file mode 100644 index 0000000..17d1235 --- /dev/null +++ b/docs/functions.rst @@ -0,0 +1,35 @@ +Functions +========= + + + +Introduction +------------ + +This is the introductory section of File 1. + +Modules +------- + +Here is some content for the first section. + +Mod +~~~ + +This is a subsection under Section 1. + +Mod1 +~~~~ + +More content for the second section. + +Mod2 +~~~~ + +This concludes the content of File 1. + +Mod3 +~~~~ + +Mod4 +~~~~ diff --git a/docs/gettingstarted.py b/docs/gettingstarted.py new file mode 100644 index 0000000..0c90338 --- /dev/null +++ b/docs/gettingstarted.py @@ -0,0 +1,277 @@ + +# [gettingstarted1-snippet] +# Arrays may be created using the array constructor and dimensioned +# as 1D, 2D, 3D; however, the values in these arrays will be undefined +import arrayfire as af + +array = af.constant(0,(100,)) +array_2d = af.constant(0, (10, 100)) +array_3d = af.constant(0, (10, 10, 10)) +# [gettingstarted1-endsnippet] + + + +# [gettingstarted2-snippet] +import arrayfire as af + +# Generate an array of size three filled with zeros. +# If no data type is specified, ArrayFire defaults to f32. +# The constant function generates the data on the device. +zeroes = af.constant(0,(3,)) + +# Generate a 1x4 array of uniformly distributed [0,1] random numbers +# The randu function generates the data on the device. +rand1 = af.randu((1,4)) + +# Generate a 2x2 array (or matrix, if you prefer) of random numbers +# sampled from a normal distribution. +# The randn function generates data on the device. +rand2 = af.randu((2,2)) + +# Generate a 3x3 identity matrix. The data is generated on the device. +iden = af.identity((3,3)) + +# Lastly, create a 2x1 array (column vector) of uniformly distributed +# 32-bit complex numbers (c32 data type): +randcplx = af.randu((2,1)) +# [gettingstarted2-endsnippet] + + +# [gettingstarted3-snippet] +import arrayFire as af +# Create a six-element array on the host +hA = ([0, 1, 2, 3, 4, 5]) + +# Which can be copied into an ArrayFire Array using the pointer copy +# constructor. Here we copy the data into a 2x3 matrix: +A = af.moddims(af.Array(hA),(2,3)) + + +# ArrayFire provides a convenince function for printing array +# objects in case you wish to see how the data is stored: +print(A) + +#todo how to create complex numbers +# [gettingstarted3-endsnippet] + + + +# [gettingstarted4-snippet] + +import arrayfire as af +import pycuda.driver as cuda +import numpy as np + +# Create an array on the host +host_ptr = af.Array([0, 1, 2, 3, 4, 5]) + + +# Create an ArrayFire array 'a' from host_ptr (2x3 matrix) +A = af.moddims(host_ptr,(2,3)) + +# Allocate CUDA device memory and copy data from host to device +device_ptr = cuda.mem_alloc(host_ptr.nbytes) +cuda.memcpy_htod(device_ptr, host_ptr) + +# Create an ArrayFire array 'b' from CUDA-allocated device memory (2x3 matrix) +b = af.Array(device_ptr, dims=(2, 3), is_device=True) + +# Note: ArrayFire takes ownership of `device_ptr`, so no need to free it manually + +# Clean up CUDA resources (not necessary due to Python's automatic memory management) +# cuda.mem_free(device_ptr) +# [gettingstarted4-endsnippet] + + + +# [gettingstarted5-snippet] + +import arrayfire as af + +# Generate two arrays +a= af.randu((2,2)) # Create a 2x2 array with random numbers between [0, 1] +b = af.constant(1,(2,1)) # Create a 2x1 array filled with constant value 1 + +# Print arrays 'a' and 'b' to the console +print("Array 'a':", a) + +print("Array 'b':",b) + +# Print the results of an expression involving arrays +result = a.col(0) + b + 0.4 # Perform operation: first column of 'a' + 'b' + 0.4 +print("Result of expression (a.col(0) + b + 0.4):") +print(result) +# [gettingstarted5-endsnippet] + + +# [gettingstarted6-snippet] + +import arrayfire as af + +# Create a 4x5x2 array of uniformly distributed random numbers +a = af.randu((4,5,2)) + +# Determine the number of dimensions using the `numdims()` function +print("numdims(a):", a.numdims()) # Print the number of dimensions (should be 3) + +# Print the size of the individual dimensions using the `dims()` function +print("dims =", a.dims()) # Print dimensions as a tuple (4, 5, 2) + +# Alternatively, access dimensions using a dim4 object +dims = a.dims() +print("dims =", dims[0], dims[1]) # Print dimensions separately (4, 5) +# [gettingstarted6-endsnippet] + + +# [gettingstarted7-snippet] + +import arrayfire as af + +# Create an example ArrayFire array 'a' +a = af.randu((4, 5)) # Example array of dtype float32 + +# Get the type stored in the array +print("underlying type:", a.type()) + +# Check if the array contains complex or real values +print("is complex?", a.iscomplex(), " is real?", a.isreal()) + +# Check if the array is a vector, column vector, or row vector +print("is vector?", a.isvector(), " column?", a.iscolumn(), " row?", a.isrow()) + +# Check if the array is empty, and determine its total elements and memory usage +print("empty?", a.isempty(), " total elements:", a.elements(), " bytes:", a.bytes()) +# [gettingstarted7-endsnippet] + + +# [gettingstarted8-snippet] + +import arrayfire as af + +# Generate a 3x3 array of uniformly distributed random numbers +R = af.randu((3, 3)) +print(af.constant(1,( 3, 3)) + af.join(af.sin(R))) # will be c32 + +# Rescale complex values to unit circle +a = af.randn(5) +print(a / af.abs(a)) + +# Calculate L2 norm of vectors +X = af.randn((3, 4)) +print(af.sqrt(af.sum(af.pow(X, 2)))) # norm of every column vector +print(af.sqrt(af.sum(af.pow(X, 2), 0))) # same as above +print(af.sqrt(af.sum(af.pow(X, 2), 1))) # norm of every row vector + +# [gettingstarted8-endsnippet] + + +# [gettingstarted9-snippet] + +import arrayfire as af +import math + +# Generate a 5x5 array of uniformly distributed random numbers +A = af.randu((5, 5)) + +# Set elements in A greater than 0.5 to NaN +A[af.where(A > 0.5)] = af.NaN + +# Generate arrays x and y with 10 million random numbers each +x = af.randu(int(10e6)) +y = af.randu(int(10e6)) + +# Estimate Pi using Monte Carlo method +pi_est = 4 * af.sum(af.hypot(x, y) < 1) / 10e6 + +# Print the estimation error compared to math.pi +print("estimation error:", abs(math.pi - pi_est)) +# [gettingstarted9-endsnippet] + + + +# [gettingstarted10-snippet] + +import arrayfire as af + +# Create an array consisting of 3 random numbers of type f32 (float) +a = af.randu(3) + +# Copy array data from device to host +host_a = a.host_ptr() # Get host pointer +print("host_a[2] =", host_a[2]) # Access host data as a normal array +a.unlock() # Unlock array to allow garbage collection if necessary + +# Access device memory for CUDA kernel +d_cuda = a.device_ptr() # Get device pointer (no need to free) +value = af.sum(d_cuda[2]) # Access device memory data +print("d_cuda[2] =", value) + +# For OpenCL, accessing memory is similar but with a different syntax +# Note: ArrayFire handles these details internally, no explicit OpenCL handling in Python + +# No need to free pointers in ArrayFire Python interface as memory management is automatic +# [gettingstarted10-endsnippet] + + +# [gettingstarted11-snippet] + +import arrayfire as af + +# Create an array consisting of 3 random numbers +a = af.randu(3) + +# Get the scalar value of the array +val = a.scalar() + +# Print the scalar value +print(f"scalar value: {val}") +# [gettingstarted11-endsnippet] + + +# [gettingstarted12-snippet] + +import arrayfire as af + +# Define host arrays +h_A = ([1, 1, 0, 0, 4, 0, 0, 2, 0]) +h_B = ([1, 0, 1, 0, 1, 0, 1, 1, 1]) + +# Create ArrayFire arrays A and B from host arrays +A = af.Array(h_A, dims=(3, 3)) +B = af.Array(h_B, dims=(3, 3)) + +# Print arrays A and B +print(A) +print(B) + +# Perform bitwise operations +A_and_B = A & B +A_or_B = A | B +A_xor_B = A ^ B + +# Print results of bitwise operations +print(A_and_B) +print(A_or_B) +print(A_xor_B) +# [gettingstarted12-endsnippet] + + + +# [gettingstarted13-snippet] + +import arrayfire as af + +def main(): + # Generate random values + a = af.randu(10000, dtype=af.Dtype.f32) + + # Sum all the values + result = af.sum(a) + print(f"sum: {result}\n") + +if __name__ == "__main__": + main() + +# [gettingstarted13-endsnippet] + + diff --git a/docs/gettingstarted.rst b/docs/gettingstarted.rst new file mode 100644 index 0000000..11bc104 --- /dev/null +++ b/docs/gettingstarted.rst @@ -0,0 +1,209 @@ +Getting Started +======================== + +Introduction +============ + +ArrayFire is a high performance software library for parallel computing with an easy-to-use API. ArrayFire abstracts away much of the details of programming parallel architectures by providing a high-level container object, the array, that represents data stored on a CPU, GPU, FPGA, or other type of accelerator. This abstraction permits developers to write massively parallel applications in a high-level language where they need not be concerned about low-level optimizations that are frequently required to achieve high throughput on most parallel architectures. + +Supported data types +==================== + +ArrayFire provides one generic container object, the array on which functions and mathematical operations are performed. The :literal:`array` can represent one of many different basic data types: + +* f32 real single-precision (:literal:`float`) +* c32 complex single-precision (:literal:`cfloat`) +* f64 real double-precision (:literal:`double`) +* c64 complex double-precision (:literal:`cdouble`) +* f16 real half-precision (:literal:`half_float::half`) +* b8 8-bit boolean values (:literal:`bool`) +* s32 32-bit signed integer (:literal:`int`) +* u32 32-bit unsigned integer (:literal:`unsigned`) +* u8 8-bit unsigned values (:literal:`unsigned char`) +* s64 64-bit signed integer (:literal:`intl`) +* u64 64-bit unsigned integer (:literal:`uintl`) +* s16 16-bit signed integer (:literal:`short`) +* u16 16-bit unsigned integer (:literal:`unsigned short`) +Most of these data types are supported on all modern GPUs; however, some older devices may lack support for double precision arrays. In this case, a runtime error will be generated when the array is constructed. + +If not specified otherwise, :literal:`array`s are created as single precision floating point numbers (:literal:`f32`). + +Creating and populating an ArrayFire array +========================================== + +ArrayFire arrays represent memory stored on the device. As such, creation and population of an array will consume memory on the device which cannot freed until the :literal:`array` object goes out of scope. As device memory allocation can be expensive, ArrayFire also includes a memory manager which will re-use device memory whenever possible. + +Arrays can be created using one of the array constructors. Below we show how to create 1D, 2D, and 3D arrays with uninitialized values: + +.. literalinclude:: gettingstarted.py + :language: python + :start-after: [gettingstarted1-snippet] + :end-before: [gettingstarted1-endsnippet] + + + +However, uninitialized memory is likely not useful in your application. ArrayFire provides several convenient functions for creating arrays that contain pre-populated values including constants, uniform random numbers, uniform normally distributed numbers, and the identity matrix: + +.. literalinclude:: gettingstarted.py + :language: python + :start-after: [gettingstarted2-snippet] + :end-before: [gettingstarted2-endsnippet] + + +A complete list of ArrayFire functions that automatically generate data on the device may be found on the functions to create arrays page. As stated above, the default data type for arrays is f32 (a 32-bit floating point number) unless specified otherwise. + +ArrayFire arrays may also be populated from data found on the host. For example: + +.. literalinclude:: gettingstarted.py + :language: python + :start-after: [gettingstarted3-snippet] + :end-before: [gettingstarted3-endsnippet] + +ArrayFire also supports array initialization from memory already on the GPU. For example, with CUDA one can populate an :literal:`array` directly using a call to :literal:`cudaMemcpy`: + +.. literalinclude:: gettingstarted.py + :language: python + :start-after: [gettingstarted4-snippet] + :end-before: [gettingstarted4-endsnippet] + +Similar functionality exists for OpenCL too. If you wish to intermingle ArrayFire with CUDA or OpenCL code, we suggest you consult the CUDA interoperability or OpenCL interoperability pages for detailed instructions. + +ArrayFire array contents, dimensions, and properties +==================================================== + +ArrayFire provides several functions to determine various aspects of arrays. This includes functions to print the contents, query the dimensions, and determine various other aspects of arrays. + +The print function can be used to print arrays that have already been generated or any expression involving arrays: + +.. literalinclude:: gettingstarted.py + :language: python + :start-after: [gettingstarted5-snippet] + :end-before: [gettingstarted5-endsnippet] + +The dimensions of an array may be determined using either a dim4 object or by accessing the dimensions directly using the dims() and numdims() functions: + + +.. literalinclude:: gettingstarted.py + :language: python + :start-after: [gettingstarted6-snippet] + :end-before: [gettingstarted6-endsnippet] + + + +In addition to dimensions, arrays also carry several properties including methods to determine the underlying type and size (in bytes). You can even determine whether the array is empty, real/complex, a row/column, or a scalar or a vector: + +.. literalinclude:: gettingstarted.py + :language: python + :start-after: [gettingstarted7-snippet] + :end-before: [gettingstarted7-endsnippet] + +For further information on these capabilities, we suggest you consult the full documentation on the array. + + +Writing mathematical expressions in ArrayFire +============================================= + +ArrayFire leverages an advanced Just-In-Time (JIT) compilation engine that optimizes array operations by minimizing the number of CUDA/OpenCL kernels used. In Python, ArrayFire functions operate similarly to a vector library. This means that typical element-wise operations, such as :literal:`c[i] = a[i] + b[i]` in C, can be expressed more succinctly as :literal:`c = a + b`, eliminating the need for explicit indexing. + +When multiple array operations are involved, ArrayFire's JIT engine consolidates them through "kernel fusion". This technique not only reduces the frequency of kernel invocations but also optimizes memory usage by eliminating redundant global memory operations. The JIT functionality extends seamlessly across Python function boundaries, continuing until a non-JIT function is encountered or a synchronization operation is explicitly invoked in the code. + +ArrayFire provides a broad spectrum of functions tailored for element-wise operations. It supports standard arithmetic operators (+, -, *, /) as well as a variety of transcendental functions (sin, cos, log, sqrt, etc.). These capabilities empower users to perform complex computations efficiently and effectively. + +.. literalinclude:: gettingstarted.py + :language: python + :start-after: [gettingstarted8-snippet] + :end-before: [gettingstarted8-endsnippet] + +To see the complete list of functions please consult the documentation on mathematical, linear algebra, signal processing, and statistics. + +Mathematical constants +====================== + +In Python, ArrayFire provides several platform-independent constants such as Pi, NaN, and Inf. If ArrayFire lacks a specific constant you require, you can create it using the `af.constant` array constructor. + +These constants are universally applicable across all ArrayFire functions. Below, we illustrate their usage in element selection and a mathematical expression: + +.. literalinclude:: gettingstarted.py + :language: python + :start-after: [gettingstarted9-snippet] + :end-before: [gettingstarted9-endsnippet] + +Please note that our constants may, at times, conflict with macro definitions in standard header files. When this occurs, please refer to our constants using the :literal:`af::` namespace. + +Indexing +======== +Like all functions in ArrayFire, indexing is also executed in parallel on the OpenCL/CUDA devices. Because of this, indexing becomes part of a JIT operation and is accomplished using parentheses instead of square brackets (i.e. as :literal:`A(0)` instead of :literal:`A[0]`). To index :literal:`af::` arrays you may use one or a combination of the following functions: + +* integer scalars +* seq() representing a linear sequence +* end representing the last element of a dimension +* span representing the entire description +* row(i) or col(i) specifying a single row/column +* rows(first,last) or cols(first,last) specifying a span of rows or columns + +Please see the indexing page for several examples of how to use these functions. + +Getting access to ArrayFire array memory on the host and device +=============================================================== + +Memory in :literal:`af::arrays` may be accessed using the host() and device() functions. The :literal:`host` function copies the data from the device and makes it available in a C-style array on the host. As such, it is up to the developer to manage any memory returned by :literal:`host`. The :literal:`device` function returns a pointer/reference to device memory for interoperability with external CUDA/OpenCL kernels. As this memory belongs to ArrayFire, the programmer should not attempt to free/deallocate the pointer. For example, here is how we can interact with both OpenCL and CUDA: + +.. literalinclude:: gettingstarted.py + :language: python + :start-after: [gettingstarted10-snippet] + :end-before: [gettingstarted10-endsnippet] + + +ArrayFire also provides several helper functions for creating :literal:`af::arrays` from OpenCL :literal:`cl_mem` references and :literal:`cl::Buffer` objects. See the :literal:`include/af/opencl.h` file for further information. + +Lastly, if you want only the first value from an :literal:`af::array` you can use get it using the scalar() function: + +.. literalinclude:: gettingstarted.py + :language: python + :start-after: [gettingstarted11-snippet] + :end-before: [gettingstarted11-endsnippet] + + +Bitwise operators +================= +In addition to supporting standard mathematical functions, arrays that contain integer data types also support bitwise operators including and, or, and shift: + +.. literalinclude:: gettingstarted.py + :language: python + :start-after: [gettingstarted12-snippet] + :end-before: [gettingstarted12-endsnippet] + + +Using the ArrayFire API in Python +================================= + +The ArrayFire library in Python is seamlessly integrated into the Python environment. To start using the library, simply :literal:`import arrayfire` and begin coding! + +# todo @stf talk about arrayapi implementation + +Sample using Python API +~~~~~~~~~~~~~~~~~~~~~~~ + +.. literalinclude:: gettingstarted.py + :language: python + :start-after: [gettingstarted13-snippet] + :end-before: [gettingstarted13-endsnippet] + + + +What to read next? +================== + +Now that you have a general introduction to ArrayFire, where do you go from here? In particular you might find these documents useful + +* Building an ArrayFire program on Linux +* Building an ArrayFire program on Windows +* Timing ArrayFire code + +Where to go for help? +===================== + +* Google Groups: https://groups.google.com/forum/#!forum/arrayfire-users +* ArrayFire Services: `Consulting `_ | `Support `_ | `Training `_ +* ArrayFire Blogs: http://arrayfire.com/blog/ +* Email: technical@arrayfire.com \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..28e8767 --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,43 @@ +.. TestProject2 documentation master file, created by + sphinx-quickstart on Mon Jun 24 10:53:47 2024. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to TestProject2's documentation! +======================================== + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + overview + tutorial + functions + releasenotes + examples + +Indices and tables +================== + * :ref:`genindex` + * :ref:`modindex` + * :ref:`search` + + + +.. automodule:: pkg.sub_pkg1 + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: pkg.sub_pkg2 + :members: + :undoc-members: + :show-inheritance: + + + + + + + + diff --git a/docs/indexing.py b/docs/indexing.py new file mode 100644 index 0000000..754faa9 --- /dev/null +++ b/docs/indexing.py @@ -0,0 +1,129 @@ +# [indexing1-snippet] + +import arrayfire as af + +data = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15] + +A = af.Array(data) +A = af.moddims(A,(4,4)) + +# [indexing1-endsnippet] + + +# [indexing2-snippet] + +A[0,0] #Returns an array pointing to the first element + + +A[2,3] #WARN: avoid doing this. Demo only +# [indexing2-endsnippet] + + +# [indexing3-snippet] + +ref0 = A[2,-1] # 14 second row last column +ref1 = A[2,-2] # 10 Second row, second to last(third) column +# [indexing3-endsnippet] + + +# [indexing4-snippet] + +#Returns an array pointing to the third column +A[:,2] +# [indexing4-endsnippet] + + + +# [indexing5-snippet] + +#Returns an array pointing to the second row +A[1, :] +# [indexing5-endsnippet] + + + +# [indexing6-snippet] + + #Returns an array pointing to the first two columns +A[:, 0:2] + +# [indexing6-endsnippet] + + +# [indexing7-snippet] + +reference = A[:, 1] +reference2 = A[0:3, 1] +reference3 = A[0:2, :] +# [indexing7-endsnippet] + + +# [indexing8-snippet] + +copy = A[2, :] +copy2 = A[1:3:2, :] + +hidx = [0, 1, 2] +idx = af.Array(hidx) +copy3 = A[idx, :] + +# [indexing8-endsnippet] + + +# [indexing9-snippet] + +inputA = af.constant(3,(10,10)) +inputB = af.constant(2,(10,10)) +data = af.constant(1,(10,10)) + +#Points to the second column of data. Does not allocate memory +ref = data[:,1] + +# This call does NOT update data. Memory allocated in matmul +ref = af.matmul(inputA, inputB) +# reference does not point to the same memory as the data array + +# [indexing9-endsnippet] + + +# [indexing10-snippet] + +reference = A[:, 2] + +a[:, 2] = 3.14 +# [indexing10-endsnippet] + + +# [indexing11-snippet] + +ref = A[:, 2] + +A[:, 2] = 3.14 +# [indexing11-endsnippet] + + +# [indexing11-snippet] + +hidx = [4, 3, 4, 0] +hvals = [9.0, 8.0, 7.0, 6.0] + +idx = af.Array(hidx) +vals = af.Array(hvals) +# [indexing12-endsnippet] + + +# [indexing13-snippet] + +A = af.Array[1,2,3,4,5,6,7,8,9] +A = af.moddims(A,(3,3)) +# 1.0000 4.0000 7.0000 +# 2.0000 5.0000 8.0000 +# 3.0000 6.0000 9.0000 + +print(A[0,0]) # first element +# 1.0000 + +print(A[0,1]) # first row, second column +# 4.0000 +# [indexing13-endsnippet] + diff --git a/docs/indexing.rst b/docs/indexing.rst new file mode 100644 index 0000000..07991c2 --- /dev/null +++ b/docs/indexing.rst @@ -0,0 +1,208 @@ +Indexing +======== +Indexing in ArrayFire is a powerful but easy to abuse feature of the af::array class. This feature allows you to reference or copy subsections of a larger array and perform operations on only a subset of elements. + +Indexing in ArrayFire can be performed using the parenthesis operator or one of the member functions of the af::array class. These functions allow you to reference one or a range of elements from the original array. + +Here we will demonstrate some of the ways you can use indexing in ArrayFire and discuss ways to minimize the memory and performance impact of these operations. + +Lets start by creating a new 4x4 matrix of floating point numbers: + +.. literalinclude:: indexing.py + :language: python + :start-after: [indexing1-snippet] + :end-before: [indexing1-endsnippet] + +ArrayFire is column-major so the resulting A array will look like this: + +.. math:: + + \begin{bmatrix} + 0 & 4 & 8 & 12 \\ + 1 & 5 & 9 & 13 \\ + 2 & 6 & 10 & 14 \\ + 3 & 7 & 11 & 15 + \end{bmatrix} + +In Python, for a two-dimensional array like a matrix, you can access its first element by providing the indices 0, 0 within the indexing operator of the af.array object. + +.. literalinclude:: indexing.py + :language: python + :start-after: [indexing2-snippet] + :end-before: [indexing2-endsnippet] + +.. math:: + + + A[0,0] = [0] + + A[2,3] = [14] + +.. note:: + :class: warning + + Normally you want to avoid accessing individual elements of the array like this for performance reasons. + + This is a warning note regarding accessing individual elements of arrays. + + + + +Indexing with negative values will access from the end of the array. For example, the value negative one and negative two(-2) will return the last and second to last element of the array, respectively. ArrayFire provides the end alias for this which also allows you to index the last element of the array. + +.. literalinclude:: indexing.py + :language: python + :start-after: [indexing3-snippet] + :end-before: [indexing3-endsnippet] + + +Indexing slices and subarrays* +============================== +You can access regions of the array via the af::seq and af::span objects. The span objects allows you to select the entire set of elements across a particular dimension/axis of an array. For example, we can select the third column of the array by passing span as the first argument and 2 as the second argument to the parenthesis operator. + +.. literalinclude:: indexing.py + :language: python + :start-after: [indexing4-snippet] + :end-before: [indexing4-endsnippet] + +.. math:: + + A[:, 2]=\begin{bmatrix} + 8 \\ + 9 \\ + 10 \\ + 11 \\ + \end{bmatrix} + +You can read that as saying that you want all values across the first dimension, but only from index 2 of the second dimension. + +You can access the second row by passing [1, :] to the array + +.. literalinclude:: indexing.py + :language: python + :start-after: [indexing5-snippet] + :end-before: [indexing5-endsnippet] + +.. math:: + + A[1, :]=\begin{bmatrix} + 1,5,9,13\\ + \end{bmatrix} + +You can use Python's slicing notation to define a range when indexing in **arrayfire**. For example, if you want to get the first two columns of an array, you can access the array by specifying **':'** for the rows (to select all rows), and **0:2** for the columns (to select columns from index 0 to 1). + +.. literalinclude:: indexing.py + :language: python + :start-after: [indexing6-snippet] + :end-before: [indexing6-endsnippet] + +.. math:: + + A[:, 0:2]= \begin{bmatrix} + 0 & 4\\ + 1 & 5\\ + 2 & 6\\ + 3 & 7\\ + \end{bmatrix} + + +Indexing using af.Array ? (Does the python wrapper support cartesian products) TODO STF +======================================================================================= + + +In Python with arrayfire, you can also index arrays using other **af.array** objects. arrayfire performs a Cartesian product of the input arrays. + +References and copies +===================== +All indexing operations in ArrayFire return **af.array** objects, which are instances of the array_proxy class. These objects can either be newly created arrays or references to the original array, depending on the type of indexing operation applied to them + +* When an array is indexed using another **af.array** , a new array is created instead of referencing the original data. +* If an array was indexed using a scalar, **sequential '0:2'** or **span ':'**, then the resulting array will reference the original data IF the first dimension is continuous. The following lines will not allocate additional memory. + +.. note:: + :class: warning + + The new arrays wither references or newly allocated arrays, are independent of the original data. Meaning that any changes to the original array will not propagate to the references. Likewise, any changes to the reference arrays will not modify the original data. + +.. literalinclude:: indexing.py + :language: python + :start-after: [indexing7-snippet] + :end-before: [indexing7-endsnippet] + +The following code snippet shows some examples of indexing that will allocate new memory. + +.. literalinclude:: indexing.py + :language: python + :start-after: [indexing8-snippet] + :end-before: [indexing8-endsnippet] + +Even though the copy3 array references continuous memory in the original array, using an **af.array** for indexing in ArrayFire results in the creation of a new array + +Assignment +========== +In Python with ArrayFire, assigning an **af.array** replaces the array on the left-hand side of :literal:`=` with the result from the right-hand side. This can lead to changes in type and shape compared to the original array. Notably, assignments do not update arrays previously referenced through indexing operations. + +.. literalinclude:: indexing.py + :language: python + :start-after: [indexing9-snippet] + :end-before: [indexing9-endsnippet] + + +The :literal:`ref` array is created by indexing into the data array. The initialized :literal:`ref` array points to the data array and does not allocate memory when it is created. After the matmul call, the :literal:`ref` array will not be pointing to the data array. The matmul call will not update the values of the data array. + +You can update the contents of an **af.Array** by assigning with the operator parenthesis. For example, if you wanted to change the third column of the :literal:`A` array you can do that by assigning to :literal:`A[:, 2]`. + +.. literalinclude:: indexing.py + :language: python + :start-after: [indexing10-snippet] + :end-before: [indexing10-endsnippet] + +.. math:: + + ref= \begin{bmatrix} + 8\\ + 9\\ + 10\\ + 11\\ + \end{bmatrix} A = \begin{bmatrix} + 0 & 4 & 3.14 & 12\\ + 1 & 5 & 3.14 & 13\\ + 2 & 6 & 3.14 & 14\\ + 3 & 7 & 3.14 & 15\\ + \end{bmatrix} + +This will update only the array being modified. If there are arrays that are referring to this array because of an indexing operation, those values will remain unchanged. + +Allocation will only be performed if there are other arrays referencing the data at the point of assignment. In the previous example, an allocation will be performed when assigning to the :literal:`A` array because the :literal:`ref` array is pointing to the original data. Here is another example demonstrating when an allocation will occur: + +.. literalinclude:: indexing.py + :language: python + :start-after: [indexing11-snippet] + :end-before: [indexing11-endsnippet] + + +In this example, no allocation will take place because when the :literal:`ref` object is created, it is pointing to :literal:`A`'s data. Once it goes out of scope, no data points to A, therefore when the assignment takes place, the data is modified in place instead of being copied to a new address. + +You can also assign to arrays using another af::arrays as an indexing array. This works in a similar way to the other types of assignment but care must be taken to assure that the indexes are unique. Non-unique indexes will result in a race condition which will cause non-deterministic values. + +.. literalinclude:: indexing.py + :language: python + :start-after: [indexing12-snippet] + :end-before: [indexing12-endsnippet] + + + +**TODO STF** + +Member Functions TODO STF +========================= + +Additional examples +=================== +See Assignment & Indexing operation on arrays for the full listing. + +.. literalinclude:: indexing.py + :language: python + :start-after: [indexing13-snippet] + :end-before: [indexing13-endsnippet] + \ No newline at end of file diff --git a/docs/installation.rst b/docs/installation.rst new file mode 100644 index 0000000..0d6d17c --- /dev/null +++ b/docs/installation.rst @@ -0,0 +1,131 @@ +ArrayFire Installer +=================== + +Installing ArrayFire couldn't be easier. Navigate to https://arrayfire.com/download and download the appropriate installer for the target architecture and operating system. Although ArrayFire can be `built from source `_, the installers conveniently package necessary dependencies. + +Install the latest device drivers before using ArrayFire. Drivers and runtimes should be downloaded and installed from each device vendor's website. + +Install Instructions +==================== + +* :ref:`Windows ` +* :ref:`Linux ` +* :ref:`macOs ` + +.. _Windows: +Windows +======= +Once the ArrayFire has been downloaded, run the installer. + +The installer offers the option to automatically add ArrayFire to the path for all users. If the installer did not do this, simply append :literal:`%AF_PATH%/lib` to the PATH variable so that the loader can find ArrayFire DLLs. + +For more information on using ArrayFire on Windows, visit the following page. + + +.. _Linux: +Linux +===== + +There are two ways to install ArrayFire on Linux. + +Package Manager +Using the ArrayFire Linux Installer +As of today, approach (1) is only supported for Ubuntu 18.04 and 20.04. Please go through the GitHub wiki `page `_ for detailed instructions. + +For approach (2), once the ArrayFire installer is downloaded, execute the installer from the terminal as shown below. Set the :literal:`--prefix` argument to the target install directory; we recommend :literal:`/opt`. + +.. code-block:: text + + ./ArrayFire_*_Linux_x86_64.sh --include-subdir --prefix=/opt + +Given sudo permissions, the ArrayFire libraries can be added to the path via :literal:`ldconfig` like so: + +.. code-block:: text + + echo /opt/arrayfire/lib64 > /etc/ld.so.conf.d/arrayfire.conf + sudo ldconfig +Otherwise, the :literal:`LD_LIBRARY_PATH` environment variable can be set so that the shared library loader can find the ArrayFire libraries. + +For more information on using ArrayFire on Linux, visit the following page*. + +Graphics support +~~~~~~~~~~~~~~~~ + +ArrayFire enables high-performance visualizations via the `Forge `_ library. On Linux, there are a few dependencies to install to enable graphics support: + +* FreeImage +* Fontconfig +* GLU (OpenGL Utility Library) + +To install these dependencies on common Linux distributions: + +**Debian, Ubuntu (14.04 and above), and other Debian derivatives** + +.. code-block:: text + + apt install build-essential libfreeimage3 libfontconfig1 libglu1-mesa + + +**Fedora, Redhat, CentOS** + +.. code-block:: text + + yum install freeimage fontconfig mesa-libGLU + + +.. _macOS: +macOS +===== + +Once the ArrayFire installer has been downloaded, execute the installer by either double-clicking on the ArrayFire :literal:`pkg` file or running the following command: + +.. code-block:: text + + sudo installer -pkg Arrayfire-*_OSX.pkg -target / + +For more information on using ArrayFire on macOS, visit the following page*. + + +NVIDIA Tegra devices +~~~~~~~~~~~~~~~~~~~~ + +ArrayFire is capable of running TX2 devices. + +Before installing ArrayFire, make sure the latest version of JetPack (v2.3 and above) or L4T (v24.2 and above) is installed. + +Tegra prerequisites +~~~~~~~~~~~~~~~~~~~ + +The following dependencies are required for Tegra devices: + +.. code-block:: text + + sudo apt install libopenblas-dev liblapacke-dev + +Testing installation +==================== + +After ArrayFire is finished installing, we recommend building and running a few of the provided examples to verify things are working as expected. + +On Windows, open the CMakeLists.txt file from CMake-GUI. Once the project is configured and generated, build and run the examples from Visual Studio. + +On Linux, run the following commands: + +.. code-block:: text + + cp -r /opt/arrayfire/share/ArrayFire/examples /tmp/examples + cd /tmp/examples + mkdir build + cd build + cmake .. + make + ./helloworld/helloworld_{cpu,cuda,oneapi,opencl} + +Getting help +~~~~~~~~~~~~ + +* Google Groups: https://groups.google.com/forum/#!forum/arrayfire-users +* ArrayFire Services: `Consulting `_ | `Training `_ +* ArrayFire Blogs: http://arrayfire.com/blog/ +* Email: support@arrayfire.com + diff --git a/docs/introductiontovectorization.py b/docs/introductiontovectorization.py new file mode 100644 index 0000000..91e8acd --- /dev/null +++ b/docs/introductiontovectorization.py @@ -0,0 +1,195 @@ + +# [vectorization1-snippet] +import arrayfire as af + +# Create an ArrayFire array 'a' using af.range() +a = af.range(10) # Creates an array [0, 1, 2, ..., 9] + +# Loop through the elements of 'a' and increment each element by 1 +for i in range(a.dims()[0]): + a[i] = a[i] + 1 # Increment each element by 1 + +# Print the modified array 'a' +print("Modified array 'a':") +print(a) +# [vectorization1-endsnippet] + + +# [vectorization2-snippet] + +import arrayfire as af + +#[0, 9] +a = af.range(10) + +# [1, 10] +a = a+ 1 +# [vectorization2-endsnippet] + + +# [vectorization3-snippet] + +import arrayfire as af + +# Define the filter coefficients as a list +g_coef = [1, 2, 1, + 2, 4, 2, + 1, 2, 1] + +# Convert the coefficients list to an ArrayFire array and scale it +filter = (1.0 / 16.0) * af.Array(3, 3, g_coef) + +# Generate a random signal array of dimensions WIDTH x HEIGHT x NUM +WIDTH = 100 +HEIGHT = 100 +NUM = 3 +signal = af.randu(WIDTH, HEIGHT, NUM) + +# Perform 2D convolution of signal with filter +conv = af.convolve2(signal, filter) + +# Print the result if needed +print("Convolution result:") +af.af_print(conv) +# [vectorization3-endsnippet] + + +# [vectorization4-snippet] + +import arrayfire as af + +# Define dimensions +WIDTH = 256 +HEIGHT = 256 +NUM_IMAGES = 100 + +# Generate an array of 100 WIDTH x HEIGHT images of random numbers +imgs = af.randu(WIDTH, HEIGHT, NUM_IMAGES) + +# Rotate all of the images in a single command (rotate by 45 degrees) +rot_imgs = af.rotate(imgs, 45) + +# Print the shape of rot_imgs to verify the result +print("Shape of rotated images:", rot_imgs.shape()) + +# Optionally, print the rotated images +# af.af_print(rot_imgs) + +# Optionally, display or further process `rot_imgs` as needed + +# [vectorization4-endsnippet] + + +# [vectorization5-snippet] + +import arrayfire as af + +# Create an ArrayFire array 'a' using af.range() +a = af.range(10) # Creates an array [0, 1, 2, ..., 9] + +# Perform element-wise addition using vectorized operations +a = a + 1 # Increment each element by 1 + +# Print the modified array 'a' +print("Modified array 'a':") +print(a) +# [vectorization5-endsnippet] + + + +# [vectorization6-snippet] + +import arrayfire as af + +# Example data dimensions +N = 10 +SPAN = af.span + +# Example arrays A and B +A = af.randu(100, N) # Example array A of size 100xN filled with random numbers +B = af.constant(0, 100, N) # Example array B initialized with zeros + +# Parallel execution using gfor loop +af.gfor(seq_i, N): +B[SPAN, seq_i] = af.accum(A[SPAN, seq_i]) + +# Print array B after parallel accumulations +print("Array B after parallel accumulations:") +af.af_print(B) +# [vectorization6-endsnippet] + + +# [vectorization7-snippet] + +import arrayfire as af + +# Calculate accumulative sum along columns of A +B = af.accum(A) + + +# [vectorization7-endsnippet] + + +# [vectorization8-snippet] + +import arrayfire as af + +# Define constants +p = 4 +n = 1000 + +# Generate constants array and variable terms array +consts = af.randu(p) +var_terms = af.randn(p, n) + +# Initialize combination array +combination = af.constant(0, p, n) + +# Perform element-wise multiplication using gfor loop +af.gfor(seq_i, n): +combination[:, seq_i] = consts * var_terms[:, seq_i] + +# Print the combination array after computation +print("Combination array:") +af.af_print(combination) +# [vectorization8-endsnippet] + + + +# [vectorization9-snippet] + +import arrayfire as af + +# Create the filter and weight vectors +filter = af.randn(1, 5) +weights = af.randu(5, 5) + +# Apply the filter using a for-loop equivalent +filtered_weights = af.constant(0, 5, 5) +for i in range(weights.dims()[1]): + filtered_weights[:, i] = af.matmul(filter, weights[:, i]) + +# Print the filtered weights array +print("Filtered weights:") +af.af_print(filtered_weights) +# [vectorization9-endsnippet] + + +# [vectorization10-snippet] + +import arrayfire as af + +# Create the filter and weight vectors +filter = af.randn(1, 5) # Shape: 1x5 +weights = af.randu(5, 5) # Shape: 5x5 + +# Transpose the filter to align dimensions for broadcasting +filter_transposed = af.transpose(filter) # Shape: 5x1 + +# Element-wise multiplication with broadcasting +filtered_weights = filter_transposed * weights + +# Print the filtered weights array +print("Filtered weights:") +af.af_print(filtered_weights) +# [vectorization10-endsnippet] diff --git a/docs/introductiontovectorization.rst b/docs/introductiontovectorization.rst new file mode 100644 index 0000000..18b1853 --- /dev/null +++ b/docs/introductiontovectorization.rst @@ -0,0 +1,126 @@ +Introduction to Vectorization +============================= +Programmers and Data Scientists want to take advantage of fast and parallel computational devices. Writing vectorized code is necessary to get the best performance out of the current generation parallel hardware and scientific computing software. However, writing vectorized code may not be immediately intuitive. ArrayFire provides many ways to vectorize a given code segment. In this tutorial, we present several methods to vectorize code using ArrayFire and discuss the benefits and drawbacks associated with each method. + +Generic/Default Vectorization +============================= +By its very nature, ArrayFire is a vectorized library. Most functions operate on arrays as a whole – on all elements in parallel. Wherever possible, existing vectorized functions should be used opposed to manually indexing into arrays. For example consider the following code: + +.. literalinclude:: introductiontovectorization.py + :language: python + :start-after: [vectorization1-snippet] + :end-before: [vectorization1-endsnippet] + +Although completely valid, the code is very inefficient as it results in a kernel kernels that operate on one datum. Instead, the developer should have used ArrayFire's overload of the + operator: + +.. literalinclude:: introductiontovectorization.py + :language: python + :start-after: [vectorization2-snippet] + :end-before: [vectorization2-endsnippet] + +This code will result in a single kernel that operates on all 10 elements of :literal:`a` in parallel. + +Most ArrayFire functions are vectorized. A small subset of these include: + ++---------------------------------------+--------------------------------------------+ +| Operator Category | Functions | ++=======================================+============================================+ +| Arithmetic Operations | +, -, *, /, %, >, < | ++---------------------------------------+--------------------------------------------+ +| Logical Operations | &&, ||(or), <, >, ==, != etc. | ++---------------------------------------+--------------------------------------------+ +| Numeric functions | abs(), floor(), round(), min(), max(), etc.| ++---------------------------------------+--------------------------------------------+ +| Complex Operations | real(), imag(), conj(), etc. | ++---------------------------------------+--------------------------------------------+ +| Exponential and logarithmic functions | exp(), log(), expm1(), log1p(), etc. | ++---------------------------------------+--------------------------------------------+ +| Logical Operations | sin(), cos(), tan(), etc. | ++---------------------------------------+--------------------------------------------+ +| Hyperbolic Functions | sinh(), cosh(), tanh(), etc. | ++---------------------------------------+--------------------------------------------+ + +In addition to element-wise operations, many other functions are also vectorized in ArrayFire. + +Notice that even that perform some form of aggregation (e.g. :literal:`sum()` or :literal:`min()`), signal processing (like :literal:`convolve()`), and even image processing functions (i.e. :literal:`rotate()`) all support vectorization on different columns or images. For example, if we have :literal:`NUM` images of size :literal:`WIDTH` by :literal:`HEIGHT`, one could convolve each image in a vector fashion as follows: + +.. literalinclude:: introductiontovectorization.py + :language: python + :start-after: [vectorization3-snippet] + :end-before: [vectorization3-endsnippet] + + +Similarly, one can rotate 100 images by 45 degrees in a single call using code like the following: + +.. literalinclude:: introductiontovectorization.py + :language: python + :start-after: [vectorization4-snippet] + :end-before: [vectorization4-endsnippet] + +Although most functions in ArrayFire do support vectorization, some do not. Most notably, all linear algebra functions. Even though they are not vectorized linear algebra operations still execute in parallel on your hardware. + +Using the built in vectorized operations should be the first and preferred method of vectorizing any code written with ArrayFire. + +GFOR: Parallel for-loops +======================== +Another novel method of vectorization present in ArrayFire is the GFOR loop replacement construct. GFOR allows launching all iterations of a loop in parallel on the GPU or device, as long as the iterations are independent. While the standard for-loop performs each iteration sequentially, ArrayFire's gfor-loop performs each iteration at the same time (in parallel). ArrayFire does this by tiling out the values of all loop iterations and then performing computation on those tiles in one pass. You can think of gfor as performing auto-vectorization of your code, e.g. you write a gfor-loop that increments every element of a vector but behind the scenes ArrayFire rewrites it to operate on the entire vector in parallel. + +The original for-loop example at the beginning of this document could be rewritten using GFOR as follows: + +.. literalinclude:: introductiontovectorization.py + :language: python + :start-after: [vectorization5-snippet] + :end-before: [vectorization5-endsnippet] + +In this case, each instance of the gfor loop is independent, thus ArrayFire will automatically tile out the :literal:`a` array in device memory and execute the increment kernels in parallel. + +To see another example, you could run an accum() on every slice of a matrix in a for-loop, or you could "vectorize" and simply do it all in one gfor-loop operation: + +.. literalinclude:: introductiontovectorization.py + :language: python + :start-after: [vectorization6-snippet] + :end-before: [vectorization6-endsnippet] + +However, returning to our previous vectorization technique, accum() is already vectorized and the operation could be completely replaced with merely: + +.. literalinclude:: introductiontovectorization.py + :language: python + :start-after: [vectorization7-snippet] + :end-before: [vectorization7-endsnippet] + +It is best to vectorize computation as much as possible to avoid the overhead in both for-loops and gfor-loops. However, the gfor-loop construct is most effective in the narrow case of broadcast-style operations. Consider the case when we have a vector of constants that we wish to apply to a collection of variables, such as expressing the values of a linear combination for multiple vectors. The broadcast of one set of constants to many vectors works well with gfor-loops: + +.. literalinclude:: introductiontovectorization.py + :language: python + :start-after: [vectorization8-snippet] + :end-before: [vectorization8-endsnippet] + +Using GFOR requires following several rules and multiple guidelines for optimal performance. The details of this vectorization method can be found in the GFOR documentation. + + +Batching +======== +The batchFunc() function allows the broad application of existing ArrayFire functions to multiple sets of data. Effectively, batchFunc() allows ArrayFire functions to execute in "batch processing" mode. In this mode, functions will find a dimension which contains "batches" of data to be processed and will parallelize the procedure. + +Consider the following example. Here we create a filter which we would like to apply to each of the weight vectors. The naive solution would be using a for-loop as we have seen previously: + +.. literalinclude:: introductiontovectorization.py + :language: python + :start-after: [vectorization9-snippet] + :end-before: [vectorization9-endsnippet] + +However, as we have discussed above, this solution will be very inefficient. One may be tempted to implement a vectorized solution as follows: + +.. literalinclude:: introductiontovectorization.py + :language: python + :start-after: [vectorization10-snippet] + :end-before: [vectorization10-endsnippet] + + +However, the dimensions of :literal:`filter` and :literal:`weights` do not match, thus ArrayFire will generate a runtime error. + +Advanced Vectorization +====================== +We have seen the different methods ArrayFire provides to vectorize our code. Tying them all together is a slightly more involved process that needs to consider data dimensionality and layout, memory usage, nesting order, etc. An excellent example and discussion of these factors can be found on our blog: + +http://arrayfire.com/how-to-write-vectorized-code/ \ No newline at end of file diff --git a/docs/linux.rst b/docs/linux.rst new file mode 100644 index 0000000..050ecad --- /dev/null +++ b/docs/linux.rst @@ -0,0 +1,120 @@ +Using ArrayFire on Linux +======================== + +Once you have :ref:`installed ` ArrayFire on your system, the next thing to do is set up your build system. On Linux, you can create ArrayFire projects using almost any editor, compiler, or build system. The only requirements are that you include the ArrayFire header directories and link with the ArrayFire library you intend to use i.e. CUDA, OpenCL, oneAPI, CPU, or Unified backends. + +.. _bigpicture: +The big picture +=============== + +On Linux, we recommend installing ArrayFire to :literal:`/opt/arrayfire` directory. The installer will populate files in the following sub-directories: + +.. code-block:: text + + include/arrayfire.h - Primary ArrayFire include file + include/af/*.h - Additional include files + lib/libaf* - CPU, CUDA, oneAPI, and OpenCL libraries (.a, .so) + lib/libforge* - Visualization library + lib/libcu* - CUDA backend dependencies + lib/libOpenCL.so - OpenCL ICD Loader library + share/ArrayFire/cmake/* - CMake config (find) scripts + share/ArrayFire/examples/* - All ArrayFire examples + +Because ArrayFire follows standard installation practices, you can use basically any build system to create and compile projects that use ArrayFire. Among the many possible build systems on Linux we suggest using ArrayFire with either CMake or Makefiles with CMake being our preferred build system. + +Prerequisite software +===================== + +To build ArrayFire projects you will need a compiler + +**Fedora, Centos and Redhat** + +Install EPEL repo (not required for Fedora) + +.. code-block:: text + + yum install epel-release + yum update + +Install build dependencies + +.. code-block:: text + + yum install gcc gcc-c++ cmake3 make + +**Debian and its derivatives** + +Install common dependencies + +.. code-block:: text + + apt install build-essential cmake cmake-curses-gui + +CMake +We recommend that the CMake build system be used to create ArrayFire projects. As `discussed above `, ArrayFire ships with a series of CMake scripts to make finding and using our library easy. + +First create a file called :literal:`CMakeLists.txt` in your project directory: + +.. code-block:: text + + cd your-project-directory + touch CMakeLists.txt + +and populate it with the following code: + +.. code-block:: text + + find_package(ArrayFire) + add_executable( [list your source files here]) + + # To use Unified backend, do the following. + # Unified backend lets you choose the backend at runtime + target_link_libraries( ArrayFire::af) + +where :literal:`my_executable` is the name of the executable you wish to create. See the `CMake documentation `_ for more information on how to use CMake. To link with a specific backend directly, replace the :literal:`ArrayFire::af` with the following for their respective backends. + +* :literal:`ArrayFire::afcpu` for CPU backend. +* :literal:`ArrayFire::afcuda` for CUDA backend. +* :literal:`ArrayFire::afoneapi` for oneAPI backend. +* :literal:`ArrayFire::afopencl` for OpenCL backend. + +Next we need to instruct CMake to create build instructions and then compile. We suggest using CMake's out-of-source build functionality to keep your build and source files cleanly separated. To do this open the CMake GUI. + +.. code-block:: text + + cd your-project-directory + mkdir build + cd build + cmake .. + make +NOTE: If you have installed ArrayFire to a non-standard location, CMake can still help you out. When you execute CMake specify the path to ArrayFire installation root as :literal:`ArrayFire_DIR` variable. + +For example, if ArrayFire were installed locally to :literal:`/home/user/ArrayFire` then you would modify the :literal:`cmake` command above to contain the following definition: + +.. code-block:: text + + cmake -DArrayFire_DIR=/home/user/ArrayFire .. +You can also specify this information in the :literal:`ccmake` command-line interface. + + +Makefiles +========= + +Building ArrayFire projects with Makefiles is fairly similar to CMake except you must specify all paths and libraries manually. + +As with any :literal:`make` project, you need to specify the include path to the directory containing :literal:`arrayfire.h` file. This should be :literal`-I /opt/arrayfire/include` if you followed our installation instructions. + +Similarly, you will need to specify the path to the ArrayFire library using the :literal:`-L` option (e.g. :literal:`-L/opt/arrayfire/lib`) followed by the specific ArrayFire library you wish to use using the :literal:`-l` option (for example :literal:`-lafcpu`, :literal:`-lafopencl`, :literal:`-lafoneapi`, :literal:`-lafcuda`, or :literal:`-laf` for the CPU, OpenCL, oneAPI, and CUDA, and unified backends, respectively. + +Here is a minimal example Makefile which uses ArrayFire's CPU backend: + +.. code-block:: text + + LIBS=-lafcpu + LIB_PATHS=-L/opt/arrayfire/lib + INCLUDES=-I/opt/arrayfire/include + CC=g++ $(COMPILER_OPTIONS) + COMPILER_OPTIONS=-std=c++11 -g + + all: main.cpp Makefile + $(CC) main.cpp -o test $(INCLUDES) $(LIBS) $(LIB_PATHS) \ No newline at end of file diff --git a/docs/overview.py b/docs/overview.py new file mode 100644 index 0000000..2b38a3e --- /dev/null +++ b/docs/overview.py @@ -0,0 +1,16 @@ +import arrayfire as af + +# [pi-example-simple-snippet] +# Monte Carlo estimation of pi +def calc_pi_device(samples): + # Simple, array based API + # Generate uniformly distributed random numers + x = af.randu(samples) + y = af.randu(samples) + # Supports Just In Time Compilation + # The following line generates a single kernel + within_unit_circle = (x * x + y * y) < 1 + # Intuitive function names + return 4 * af.count(within_unit_circle) / samples +# [pi-example-simple-endsnippet] + diff --git a/docs/overview.rst b/docs/overview.rst new file mode 100644 index 0000000..39385fb --- /dev/null +++ b/docs/overview.rst @@ -0,0 +1,121 @@ +Overview +======== + + + +About Array Fire +---------------- + +`ArrayFire `_ is a high performance library for parallel computing with an easy-to-use API. It enables users to write scientific computing code that is portable across CUDA, OpenCL and CPU devices. This project provides Python bindings for the ArrayFire library. + +Installing ArrayFire +-------------------- + +Install ArrayFire using either a binary installer for Windows, OSX, or Linux or download it from source: + * `Download and install Binaries `_ + * `Build from source `_ + +Easy to use +----------- + +The array object is beautifully simple. + +Array-based notation effectively expresses computational algorithms in readable math-resembling notation. Expertise in parallel programming is not required to use ArrayFire. + +A few lines of ArrayFire code accomplishes what can take 100s of complicated lines in CUDA, oneAPI, or OpenCL kernels. + +ArrayFire is extensive! +----------------------- +Support for multiple domains +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +ArrayFire contains hundreds of functions across various domains including: + +Vector Algorithms +Image Processing +Computer Vision +Signal Processing +Linear Algebra +Statistics +and more. +Each function is hand-tuned by ArrayFire developers with all possible low-level optimizations. + +Support for various data types and sizes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +ArrayFire operates on common data shapes and sizes, including vectors, matrices, volumes, and + +It supports common data types, including single and double precision floating point values, complex numbers, booleans, and 32-bit signed and unsigned integers. + +Extending ArrayFire +~~~~~~~~~~~~~~~~~~~ + +ArrayFire can be used as a stand-alone application or integrated with existing CUDA, oneAPI, or OpenCL code. + +Code once, run anywhere! +------------------------ + +With support for x86, ARM, CUDA, oneAPI, and OpenCL devices, ArrayFire supports for a comprehensive list of devices. + +Each ArrayFire installation comes with: + + * a CUDA backend (named 'libafcuda') for `NVIDIA GPUs `_ + * a oneAPI backend (named 'libafoneapi') for `oneAPI devices `_ + * an OpenCL backend (named 'libafopencl') for `OpenCL devices `_, + * a CPU backend (named 'libafcpu') to fall back to when CUDA, oneAPI, or OpenCL devices are unavailable. + +ArrayFire is highly efficient +----------------------------- +Vectorized and Batched Operations +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +ArrayFire supports batched operations on N-dimensional arrays. Batch operations in ArrayFire are run in parallel ensuring an optimal usage of CUDA, oneAPI, or OpenCL devices. + +Best performance with ArrayFire is achieved using vectorization techniques. + +ArrayFire can also execute loop iterations in parallel with the gfor function. + +Just in Time compilation +~~~~~~~~~~~~~~~~~~~~~~~~ +ArrayFire performs run-time analysis of code to increase arithmetic intensity and memory throughput, while avoiding unnecessary temporary allocations. It has an awesome internal JIT compiler to make important optimizations. + +Read more about how ArrayFire JIT. can improve the performance in your application. + + +Simple Example +-------------- + +Here is an example of ArrayFire code that performs a Monte Carlo estimation of PI. + +.. literalinclude:: overview.py + :language: python + :start-after: [pi-example-simple-snippet] + :end-before: [pi-example-simple-endsnippet] + + + + +Product Support +--------------- +Free Community Options +~~~~~~~~~~~~~~~~~~~~~~ + * `ArrayFire Mailing List `_ (recommended) + * `StackOverFlow `_ + +Premium Support +~~~~~~~~~~~~~~~ + * Phone Support - available for purchase(request a quote) + +Contact Us +~~~~~~~~~~ + * If you need to contact us, visit our `contact us page `_. + +Email +~~~~~ + * Engineering: technical@arrayfire.com + * Sales: sales@arrayfire.com + +Citations and Acknowledgements +------------------------------ + +If you redistribute ArrayFire, please follow the terms established in `the license `_. If you wish to cite ArrayFire in an academic publication, please use the following reference: \ No newline at end of file diff --git a/docs/releasenotes.rst b/docs/releasenotes.rst new file mode 100644 index 0000000..1997d71 --- /dev/null +++ b/docs/releasenotes.rst @@ -0,0 +1,35 @@ +Release Notes +============= + + + +Introduction +------------ + +This is the introductory section of File 1. + +Modules +------- + +Here is some content for the first section. + +Mod +~~~ + +This is a subsection under Section 1. + +Mod1 +~~~~ + +More content for the second section. + +Mod2 +~~~~ + +This concludes the content of File 1. + +Mod3 +~~~~ + +Mod4 +~~~~ diff --git a/docs/tutorial.rst b/docs/tutorial.rst new file mode 100644 index 0000000..3ffe64c --- /dev/null +++ b/docs/tutorial.rst @@ -0,0 +1,20 @@ +Tutorial +======== + +* :doc:`Installation ` +* :doc:`Using on Linux ` +* Using on Windows +* Using on OSX +* :doc:`Getting Started ` +* :doc:`Introduction to Vectorization ` +* :doc:`Array and Matrix Manipulation ` +* CUDA Interoperability +* OpenCL Interoperability +* Unified Backend +* Forge Visualization +* :doc:`Indexing ` +* Timing ArrayFire +* :doc:`Configuring ArrayFire Environment ` +* :doc:`Debugging ArrayFire Code ` +* :doc:`ArrayFire JIT Code Generation ` +* GFOR Usage \ No newline at end of file From 118b53d95606cb7bb239885bf94bf8e10b00f8aa Mon Sep 17 00:00:00 2001 From: michaeleg21 Date: Mon, 29 Jul 2024 13:28:26 -0400 Subject: [PATCH 03/11] Added pytests for documentation snippets. --- docs/gettingstarted.py | 4 +- docs/indexing.py | 2 +- docs/introductiontovectorization.py | 22 +- tests/test_documentation/__init__.py | 0 .../test_documentation/test_documentation.py | 402 ++++++++++++++++++ 5 files changed, 415 insertions(+), 15 deletions(-) create mode 100644 tests/test_documentation/__init__.py create mode 100644 tests/test_documentation/test_documentation.py diff --git a/docs/gettingstarted.py b/docs/gettingstarted.py index 0c90338..7d6a092 100644 --- a/docs/gettingstarted.py +++ b/docs/gettingstarted.py @@ -38,7 +38,7 @@ # [gettingstarted3-snippet] -import arrayFire as af +import arrayfire as af # Create a six-element array on the host hA = ([0, 1, 2, 3, 4, 5]) @@ -269,8 +269,6 @@ def main(): result = af.sum(a) print(f"sum: {result}\n") -if __name__ == "__main__": - main() # [gettingstarted13-endsnippet] diff --git a/docs/indexing.py b/docs/indexing.py index 754faa9..52406b5 100644 --- a/docs/indexing.py +++ b/docs/indexing.py @@ -90,7 +90,7 @@ reference = A[:, 2] -a[:, 2] = 3.14 +A[:, 2] = 3.14 # [indexing10-endsnippet] diff --git a/docs/introductiontovectorization.py b/docs/introductiontovectorization.py index 91e8acd..f44c63a 100644 --- a/docs/introductiontovectorization.py +++ b/docs/introductiontovectorization.py @@ -50,7 +50,7 @@ # Print the result if needed print("Convolution result:") -af.af_print(conv) +print(conv) # [vectorization3-endsnippet] @@ -64,7 +64,7 @@ NUM_IMAGES = 100 # Generate an array of 100 WIDTH x HEIGHT images of random numbers -imgs = af.randu(WIDTH, HEIGHT, NUM_IMAGES) +imgs = af.randu((NUM_IMAGES, (WIDTH, HEIGHT))) # Rotate all of the images in a single command (rotate by 45 degrees) rot_imgs = af.rotate(imgs, 45) @@ -96,7 +96,7 @@ # [vectorization5-endsnippet] - +#NOT WORKING # [vectorization6-snippet] import arrayfire as af @@ -129,7 +129,7 @@ # [vectorization7-endsnippet] - +#NOT WORKING # [vectorization8-snippet] import arrayfire as af @@ -161,12 +161,12 @@ import arrayfire as af # Create the filter and weight vectors -filter = af.randn(1, 5) -weights = af.randu(5, 5) +filter = af.randu((1, 5)) +weights = af.randu((5, 5)) # Apply the filter using a for-loop equivalent -filtered_weights = af.constant(0, 5, 5) -for i in range(weights.dims()[1]): +filtered_weights = af.constant(0, (5, 5)) +for i in range(weights.shape[1]): filtered_weights[:, i] = af.matmul(filter, weights[:, i]) # Print the filtered weights array @@ -180,8 +180,8 @@ import arrayfire as af # Create the filter and weight vectors -filter = af.randn(1, 5) # Shape: 1x5 -weights = af.randu(5, 5) # Shape: 5x5 +filter = af.randu((1, 5)) # Shape: 1x5 +weights = af.randu((5, 5)) # Shape: 5x5 # Transpose the filter to align dimensions for broadcasting filter_transposed = af.transpose(filter) # Shape: 5x1 @@ -191,5 +191,5 @@ # Print the filtered weights array print("Filtered weights:") -af.af_print(filtered_weights) +print(filtered_weights) # [vectorization10-endsnippet] diff --git a/tests/test_documentation/__init__.py b/tests/test_documentation/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_documentation/test_documentation.py b/tests/test_documentation/test_documentation.py new file mode 100644 index 0000000..ddbb0de --- /dev/null +++ b/tests/test_documentation/test_documentation.py @@ -0,0 +1,402 @@ +import pytest +import arrayfire as af +import math + + + + +def test_array_shapes(): + # [gettingstarted1-snippet] + # Arrays may be created using the array constructor and dimensioned + # as 1D, 2D, 3D; however, the values in these arrays will be undefined + import arrayfire as af + + array = af.constant(0, (100,)) + array_2d = af.constant(0, (10, 100)) + array_3d = af.constant(0, (10, 10, 10)) + # [gettingstarted1-endsnippet] + assert array.shape == (100,) # Check shape of 1D array + assert array_2d.shape == (10, 100) # Check shape of 2D array + assert array_3d.shape == (10, 10, 10) # Check shape of 3D array + + + # [pi-example-simple-snippet] + # Monte Carlo estimation of pi +def calc_pi_device(samples) -> float: + # Simple, array based API + # Generate uniformly distributed random numers + x = af.randu(samples) + y = af.randu(samples) + # Supports Just In Time Compilation + # The following line generates a single kernel + within_unit_circle = (x * x + y * y) < 1 + # Intuitive function names + return 4 * af.count(within_unit_circle) / samples + # [pi-example-simple-endsnippet] + +def test_calc_pi_device(): + samples = 100000 + x = af.randu(samples) + y = af.randu(samples) + within_unit_circle = (x * x + y * y) < 1 + result = 4 * af.count(within_unit_circle) / samples + assert isinstance(result, float) + error = abs(result - math.pi) + tolerance = 0.01 + assert error < tolerance, f"Error ({error}) exceeds tolerance ({tolerance})" + + +# [gettingstarted2-snippet] +import arrayfire as af + +# Generate an array of size three filled with zeros. +# If no data type is specified, ArrayFire defaults to f32. +# The constant function generates the data on the device. +zeroes = af.constant(0,(3,)) + +# Generate a 1x4 array of uniformly distributed [0,1] random numbers +# The randu function generates the data on the device. +rand1 = af.randu((1,4)) + +# Generate a 2x2 array (or matrix, if you prefer) of random numbers +# sampled from a normal distribution. +# The randn function generates data on the device. +rand2 = af.randu((2,2)) + +# Generate a 3x3 identity matrix. The data is generated on the device. +iden = af.identity((3,3)) + +# Lastly, create a 2x1 array (column vector) of uniformly distributed +# 32-bit complex numbers (c32 data type): +randcplx = af.randu((2,1)) +# [gettingstarted2-endsnippet] + +import pytest +import arrayfire as af + +def test_arrayfire_operations(): + # Generate an array of size three filled with zeros + zeroes = af.constant(0, (3,)) + assert zeroes.shape == (3,) # Check shape + + # Generate a 1x4 array of uniformly distributed [0,1] random numbers + rand1 = af.randu((1, 4)) + assert rand1.shape == (1, 4) # Check shape + + # Generate a 2x2 array of random numbers sampled from a normal distribution + rand2 = af.randn((2, 2)) + assert rand2.shape == (2, 2) # Check shape + + # Generate a 3x3 identity matrix + iden = af.identity((3,3)) + assert iden.shape == (3, 3) # Check shape + + # Generate a 2x1 array (column vector) of uniformly distributed 32-bit complex numbers + randcplx = af.randu((2, 1)) + assert randcplx.shape == (2, ) # Check shape + +# [gettingstarted3-snippet] +import arrayfire as af +# Create a six-element array on the host +hA = ([0, 1, 2, 3, 4, 5]) + +# Which can be copied into an ArrayFire Array using the pointer copy +# constructor. Here we copy the data into a 2x3 matrix: +A = af.moddims(af.Array(hA),(2,3)) + + +# ArrayFire provides a convenince function for printing array +# objects in case you wish to see how the data is stored: +print(A) + +#todo how to create complex numbers +# [gettingstarted3-endsnippet] + + +def test_arrayfire_conversion(): + # Create a six-element array on the host + hA = ([0, 1, 2, 3, 4, 5]) + + # Copy data from host array to an ArrayFire array and reshape to 2x3 matrix + A = af.moddims(af.Array(hA),(2,3)) + + # Assert that the shape of A is (2, 3) + assert A.shape == (2, 3) + + # Assert that the elements in A match hA + for i in range(2): + for j in range(3): + assert A[i, j] == hA[i * 3 + j] + +# [gettingstarted11-snippet] + +import arrayfire as af + +# Create an array consisting of 3 random numbers +a = af.randu(3) + +# Get the scalar value of the array +val = a.scalar() + +# Print the scalar value +print(f"scalar value: {val}") +# [gettingstarted11-endsnippet] + + +import pytest +import arrayfire as af + +def test_arrayfire_scalar_value(): + # Create an array consisting of 3 random numbers + a = af.randu(3) + + # Get the scalar value of the array + val = a.scalar() + + # Assert that the scalar value is a float + assert isinstance(val, float) + + # Assert that the scalar value is between 0 and 1 (inclusive) + assert 0 <= val <= 1 + +def test_vectorization(): + + # [vectorization2-snippet] + + import arrayfire as af + + #[0, 9] + a = af.range(10) + + # [1, 10] + a = a+ 1 + # [vectorization2-endsnippet] + # Assertion: Verify the elements of the array 'a' + expected_result = af.Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) + assert a == expected_result + +def test_apply_filter(): + # [vectorization9-snippet] + + import arrayfire as af + + # Create the filter and weight vectors + filter = af.randu((1, 5)) + weights = af.randu((5, 5)) + + # Apply the filter using a for-loop equivalent + filtered_weights = af.constant(0, (5, 5)) + for i in range(weights.shape[1]): + filtered_weights[:, i] = af.matmul(filter, weights[:, i]) + + # Print the filtered weights array + print("Filtered weights:") + print(filtered_weights) + # [vectorization9-endsnippet] + assert filtered_weights.shape == (5, 5) + + + + +def test_filtered_weights(): + # [vectorization10-snippet] + + import arrayfire as af + + # Create the filter and weight vectors + filter = af.randu((1, 5)) # Shape: 1x5 + weights = af.randu((5, 5)) # Shape: 5x5 + + # Transpose the filter to align dimensions for broadcasting + filter_transposed = af.transpose(filter) # Shape: 5x1 + + # Element-wise multiplication with broadcasting + filtered_weights = filter_transposed * weights + + expected_shape = (5, 5) # Expected shape of filtered_weights + + # Assertions + assert filtered_weights.shape == expected_shape + + # Print the filtered weights array + print("Filtered weights:") + print(filtered_weights) + # [vectorization10-endsnippet] + +def test_flatten_array(): + # [manipulation1-snippet] + + import arrayfire as af + + # Creates a 3x3 array filled with random numbers between [0, 1) + a = af.randu((3, 3)) + + # Flattens the array 'a' into a 1-dimensional column vector + flat_a = af.flat(a) + + # Display the original array 'a' + print(a) + + # [manipulation1-endsnippet] + assert flat_a.shape == (9,) # Check if it's a 1-dimensional array + assert len(flat_a) == 9 # Check if it has 9 elements (3x3 array) + + +def test_flip_array(): + + # [manipulation2-snippet] + + import arrayfire as af + + # Generate a 5x2 array of uniformly distributed random numbers between [0, 1) + a = af.randu((5, 2)) + + # Print the original array 'a' + print("Original array 'a' [5 2 1 1]") + print(a) + + # Flip the array 'a' along both axes (rows and columns) + flip_a = af.flip(a) + + # Print the flipped array 'flip_a' + print("\nFlipped array 'flip_a' [5 2 1 1]") + print(flip_a) + + # [manipulation2-endsnippet] + assert flip_a.shape == a.shape + assert af.flip(flip_a) == a + assert af.min(a) >= 0 + assert af.max(a) < 1 + assert af.min(flip_a) >= 0 + assert af.max(flip_a) < 1 + +def test_join_array(): + # [manipulation3-snippet] + + import arrayfire as af + + # Generate a 1-dimensional array 'a' of size 5 filled with uniformly distributed random numbers between [0, 1) + a = af.randu((5,)) + + # Print the original array 'a' + print("Original array 'a' [5 1 1 1]") + print(a) + + # Join the array 'a' with itself along axis 0 + a_join = af.join(0, a, a) + + # Print the joined array 'a_join' + print("\nJoined array 'a_join' [10 1 1 1]") + print(a_join) + # [manipulation3-endsnippet] + assert a_join.shape == (10,) + + + +def test_moddims_operations(): + # [manipulation4-snippet] + + import arrayfire as af + + a = af.randu((8,)) + + print(a) + + moddims_a = af.moddims(a,(2,4)) + + print(moddims_a) + + moddims_b = af.moddims(a,(len(a),)) + print(moddims_b) + + # [manipulation4-endsnippet] + assert moddims_a.shape == (2, 4) + assert moddims_b.shape == (8,) + assert a == af.moddims(moddims_a, (8,)) + assert a == moddims_b + + + +def test_arrayfire_shift(): + # [manipulation6-snippet] + + import arrayfire as af + + a = af.randu((3,5)) + print(a) + + a_shift = af.shift(a,(0,2)) + print(a_shift) + + a_shift1 = af.shift(a,(-1,2)) + print(a_shift1) + + # [manipulation6-endsnippet] + + # Check if arrays are equal by comparing element-wise + assert a != a_shift + assert a != a_shift1 + assert a_shift.shape == (3,5) + assert a_shift1.shape == (3,5) + + +def transpose_arrayifre(): + # [manipulation8-snippet] + + import arrayfire as af + + a = af.randu((3,3)) + print(a) #[3 3 1 1] + + ''' 0.3949 0.8465 0.3709 + 0.3561 0.9399 0.2751 + 0.6097 0.6802 0.2720''' + + + a_transpose = af.transpose(a) + print(a_transpose) #[3 3 1 1] + + ''' 0.3949 0.3561 0.6097 + 0.8465 0.9399 0.6802 + 0.3709 0.2751 0.2720''' + # [manipulation8-endsnippet] + # Convert arrays to Python lists for comparison + a_list = a.to_array().tolist() + a_transpose_list = a_transpose.to_array().tolist() + + # Compute the expected transpose manually + expected_a_transpose = list(zip(*a_list)) + + # Check if the transpose operation is correct + assert a_transpose_list == expected_a_transpose + + + + +def test_moddims(): + # [indexing1-snippet] + + import arrayfire as af + + data = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15] + + A = af.Array(data) + A = af.moddims(A,(4,4)) + +# [indexing1-endsnippet] + expected_result = [ + [0, 1, 2, 3], + [4, 5, 6, 7], + [8, 9, 10, 11], + [12, 13, 14, 15] + ] + + dims = A.shape + A_list = [[A[i, j] for j in range(dims[1])] for i in range(dims[0])] + + # Check if the reshaped array matches the expected result + assert A_list == expected_result + + + + From 5012e31d87d09794aaee506dffaf1c8fb7f2aafe Mon Sep 17 00:00:00 2001 From: michaeleg21 Date: Wed, 28 Aug 2024 12:55:15 -0400 Subject: [PATCH 04/11] Added functions documentation pages. --- docs/conf.py | 3 +- docs/functions.rst | 125 ++++++++++++++++++++++++++++------ docs/functions/add.rst | 30 ++++++++ docs/functions/array.rst | 30 ++++++++ docs/functions/det.rst | 25 +++++++ docs/functions/device.rst | 42 ++++++++++++ docs/functions/divide.rst | 36 ++++++++++ docs/functions/dot.rst | 31 +++++++++ docs/functions/eig.rst | 37 ++++++++++ docs/functions/exp.rst | 32 +++++++++ docs/functions/fft.rst | 39 +++++++++++ docs/functions/get.rst | 31 +++++++++ docs/functions/get_device.rst | 27 ++++++++ docs/functions/ifft.rst | 27 ++++++++ docs/functions/inv.rst | 30 ++++++++ docs/functions/join.rst | 27 ++++++++ docs/functions/log.rst | 26 +++++++ docs/functions/matmul.rst | 27 ++++++++ docs/functions/max.rst | 31 +++++++++ docs/functions/mean.rst | 27 ++++++++ docs/functions/median.rst | 27 ++++++++ docs/functions/min.rst | 25 +++++++ docs/functions/multiply.rst | 32 +++++++++ docs/functions/ones.rst | 26 +++++++ docs/functions/prod.rst | 27 ++++++++ docs/functions/randn.rst | 26 +++++++ docs/functions/randu.rst | 29 ++++++++ docs/functions/reorder.rst | 27 ++++++++ docs/functions/reshape.rst | 25 +++++++ docs/functions/set_device.rst | 25 +++++++ docs/functions/slice.rst | 27 ++++++++ docs/functions/sqrt.rst | 25 +++++++ docs/functions/sttdev.rst | 26 +++++++ docs/functions/subtract.rst | 29 ++++++++ docs/functions/sum.rst | 26 +++++++ docs/functions/transpose.rst | 27 ++++++++ docs/functions/zeros.rst | 27 ++++++++ docs/overview.py | 2 +- 38 files changed, 1120 insertions(+), 21 deletions(-) create mode 100644 docs/functions/add.rst create mode 100644 docs/functions/array.rst create mode 100644 docs/functions/det.rst create mode 100644 docs/functions/device.rst create mode 100644 docs/functions/divide.rst create mode 100644 docs/functions/dot.rst create mode 100644 docs/functions/eig.rst create mode 100644 docs/functions/exp.rst create mode 100644 docs/functions/fft.rst create mode 100644 docs/functions/get.rst create mode 100644 docs/functions/get_device.rst create mode 100644 docs/functions/ifft.rst create mode 100644 docs/functions/inv.rst create mode 100644 docs/functions/join.rst create mode 100644 docs/functions/log.rst create mode 100644 docs/functions/matmul.rst create mode 100644 docs/functions/max.rst create mode 100644 docs/functions/mean.rst create mode 100644 docs/functions/median.rst create mode 100644 docs/functions/min.rst create mode 100644 docs/functions/multiply.rst create mode 100644 docs/functions/ones.rst create mode 100644 docs/functions/prod.rst create mode 100644 docs/functions/randn.rst create mode 100644 docs/functions/randu.rst create mode 100644 docs/functions/reorder.rst create mode 100644 docs/functions/reshape.rst create mode 100644 docs/functions/set_device.rst create mode 100644 docs/functions/slice.rst create mode 100644 docs/functions/sqrt.rst create mode 100644 docs/functions/sttdev.rst create mode 100644 docs/functions/subtract.rst create mode 100644 docs/functions/sum.rst create mode 100644 docs/functions/transpose.rst create mode 100644 docs/functions/zeros.rst diff --git a/docs/conf.py b/docs/conf.py index 8c1aa89..2b36bb2 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -24,6 +24,7 @@ 'sphinx.ext.doctest', 'sphinx.ext.autodoc', 'sphinx.ext.mathjax', + 'sphinx_collapse', ] templates_path = ['_templates'] @@ -36,6 +37,6 @@ html_theme = 'sphinxawesome_theme' html_static_path = ['_static'] - +html_permalinks = False diff --git a/docs/functions.rst b/docs/functions.rst index 17d1235..8fa82ee 100644 --- a/docs/functions.rst +++ b/docs/functions.rst @@ -1,35 +1,122 @@ Functions ========= +Documentation grouped by category: -Introduction ------------- +.. collapse:: Arrayfire Classes -This is the introductory section of File 1. + .. list-table:: -Modules -------- + * - Class 1 + - Description of Class 1 -Here is some content for the first section. -Mod -~~~ +.. collapse:: Arrayfire Functions -This is a subsection under Section 1. + .. list-table:: -Mod1 -~~~~ + * - :doc:`af.array() ` + - Creates an array from a list or other data structure. + * - :doc:`af.zeros() ` + - Creates an array filled with zeros. + * - :doc:`af.ones() ` + - Creates an array filled with ones. + * - :doc:`af.randu() ` + - Creates an array with random uniform values. + * - :doc:`af.randn() ` + - Creates an array with random normal values. + * - :doc:`af.transpose() ` + - Transposes an array. + * - :doc:`af.reshape() ` + - Reshapes an array. + * - :doc:`af.reorder() ` + - Reorders dimensions of an array. + * - :doc:`af.slice() ` + - Extracts a slice of an array. + * - :doc:`af.join() ` + - Joins arrays along a specified dimension. + * - :doc:`af.add() ` + - Performs element-wise addition. + * - :doc:`af.subtract() ` + - Performs element-wise subtraction. + * - :doc:`af.multiply() ` + - Performs element-wise multiplication. + * - :doc:`af.divide() ` + - Performs element-wise division. + * - :doc:`af.dot() ` + - Computes the dot product of two arrays. + * - :doc:`af.exp() ` + - Computes the exponential of each element. + * - :doc:`af.log() ` + - Computes the natural logarithm of each element. + * - :doc:`af.sqrt() ` + - Computes the square root of each element. + * - :doc:`af.matmul() ` + - Matrix multiplication. + * - :doc:`af.inv() ` + - Computes the inverse of a matrix. + * - :doc:`af.det() ` + - Computes the determinant of a matrix. + * - :doc:`af.eig() ` + - Computes eigenvalues and eigenvectors. + * - :doc:`af.fft() ` + - Computes the Fast Fourier Transform. + * - :doc:`af.ifft() ` + - Computes the Inverse Fast Fourier Transform. + * - :doc:`af.mean() ` + - Computes the mean of elements. + * - :doc:`af.stdev() ` + - Computes the standard deviation. + * - :doc:`af.median() ` + - Computes the median value. + * - :doc:`af.sum() ` + - Computes the sum of elements. + * - :doc:`af.prod() ` + - Computes the product of elements. + * - :doc:`af.device() ` + - Returns the device identifier. + * - :doc:`af.get_device() ` + - Matrix multiplication. + * - :doc:`af.set_device() ` + - Gets the current device. + * - :doc:`af.get() ` + - Copies data from the GPU to the CPU. + * - :doc:`af.min() ` + - Finds the minimum value. + * - :doc:`af.max() ` + - Finds the maximum value. -More content for the second section. -Mod2 -~~~~ +.. collapse:: Arrayfire Functions by Category -This concludes the content of File 1. + .. list-table:: -Mod3 -~~~~ + * - **Array Creation** + - Functions in this category are used to initialize arrays with specific values or patterns. + * - **Array Manipulation** + - These functions help modify the structure or arrangement of arrays. + * - **Mathematical Operations** + - Functions for performing fundamental arithmetic and mathematical operations on arrays. + * - **Linear Algebra** + - Functions for performing linear algebra operations, essential in many scientific and engineering tasks. + * - **Fourier Transforms** + - Functions for performing Fourier analysis, essential for signal processing and frequency analysis. + * - **Statistics** + - Functions for computing statistical metrics and analyzing data distributions. + * - **Data Reduction** + - Functions for aggregating and reducing data to summarize or condense information. + * - **Utilities** + - General-purpose functions for managing arrays and devices. + * - **Special Functions** + - Functions for creating and applying specific types of filters, commonly used in signal processing and analysis. -Mod4 -~~~~ + +.. collapse:: Graphics + + .. list-table:: + + * - **Rendering Function** + - Rendering Function to draw images, plots etc + * - **Window Function** + - Window Creation, modification and destruction of functions diff --git a/docs/functions/add.rst b/docs/functions/add.rst new file mode 100644 index 0000000..05d70fa --- /dev/null +++ b/docs/functions/add.rst @@ -0,0 +1,30 @@ +add +=== +The 'af.add()' function in ArrayFire is used to perform element-wise addition between arrays. This function enables you to add corresponding elements of two arrays or an array and a scalar, resulting in a new array where each element is the sum of the respective elements from the input arrays or the scalar. + + +Function +-------- +:literal:`af.add()` + - Python interface used to perform element-wise addition. + +Detailed Description +-------------------- +The 'af.add()' function computes the sum of two arrays or an array and a scalar, element by element. When adding two arrays, both must have the same dimensions, or be broadcastable to a common shape. For array-scalar addition, the scalar value is added to each element of the array. This function is particularly useful for operations requiring element-wise arithmetic. + +Function Documentation +---------------------- +.. sidebar:: af.add() + + Syntax: + af.add(array1, array2) + af.add(array, scalar) + + Parameters: + 'array1': The first ArrayFire array in the addition operation. + 'array2': The second ArrayFire array with the same dimensions as 'array1', or compatible for broadcasting. + 'array': An ArrayFire array to which the scalar is added. + 'scalar': A scalar value to be added to each element of 'array'. + + Returns: + An ArrayFire array containing the element-wise sum of the inputs. diff --git a/docs/functions/array.rst b/docs/functions/array.rst new file mode 100644 index 0000000..9605817 --- /dev/null +++ b/docs/functions/array.rst @@ -0,0 +1,30 @@ +array +===== +The 'af.array()' function is part of the ArrayFire library, which provides a powerful framework for performing high-performance numerical computations. This function is designed to create an ArrayFire array from various data structures, such as Python lists or other iterable collections. + +Function +-------- +:literal:`af.array()` + - Python interface to form an array. + + +Detailed Description +-------------------- +The 'af.array()' function allows you to convert a data structure, such as a Python list or tuple, into an ArrayFire array. This conversion is essential for leveraging ArrayFire's optimized computational capabilities. By creating an array from a list or another iterable, you can perform efficient mathematical operations, matrix manipulations, and other numerical computations using ArrayFire's APIs. + +The function supports multiple data types and can handle multi-dimensional arrays. The ability to create an ArrayFire array from native Python structures makes it easier to integrate ArrayFire into Python-based workflows. + +Function Documentation +---------------------- +.. sidebar:: af.array() + + Syntax: + af.array(data) + + Parameters: + 'data': A list, tuple, or another iterable containing the elements to be converted into an ArrayFire array. The data should be in a format that ArrayFire can interpret, such as nested lists for multi-dimensional arrays. + + Returns: + An ArrayFire array containing the elements from the input data structure. + + diff --git a/docs/functions/det.rst b/docs/functions/det.rst new file mode 100644 index 0000000..f2acfda --- /dev/null +++ b/docs/functions/det.rst @@ -0,0 +1,25 @@ +det +=== +The 'af.det()' function in ArrayFire computes the determinant of a square matrix. The determinant is a scalar value that provides important properties of the matrix, such as whether it is invertible. It is a fundamental operation in linear algebra with applications in areas such as system of equations, matrix inversion, and eigenvalue problems. + +Function +-------- +:literal:`af.det()` + - Python interface to find determinant of a square matrix. + +Detailed Description +-------------------- +The 'af.det()' function calculates the determinant of a square matrix. The matrix must be square, meaning the number of rows must be equal to the number of columns. The determinant of a matrix is a scalar that can provide information about the matrix, such as its invertibility. If the determinant is zero, the matrix is singular (non-invertible); if it is non-zero, the matrix is invertible. + +Function Documentation +---------------------- +.. sidebar:: af.det() + + Syntax: + af.det(matrix) + + Parameters: + 'matrix': A 2D ArrayFire array (matrix) whose determinant is to be calculated. The matrix must be square, i.e., the number of rows must be equal to the number of columns. + + Returns: + A scalar value representing the determinant of the input matrix. The type of the result will be the same as the input matrix data type. diff --git a/docs/functions/device.rst b/docs/functions/device.rst new file mode 100644 index 0000000..31db655 --- /dev/null +++ b/docs/functions/device.rst @@ -0,0 +1,42 @@ +device +====== +The 'af.device()' function in the ArrayFire library is used to get or set the current device or device properties. This function provides an interface to interact with the GPU or CPU device being used for computations. It allows you to select a particular device from available options or query the properties of the current device. + +Function +-------- +:literal:`af.device()` + - Python interface to get or set device properties. + +Detailed Description +-------------------- +The 'af.device()' function is useful for managing and querying the device that ArrayFire is using for computations. This function can perform various tasks related to device management, such as: + +- Getting the Current Device: Retrieve the index of the currently selected device. +- Setting the Current Device: Select a specific device for computations. +- Querying Device Properties: Obtain information about the current device. +This functionality is important for applications that need to explicitly choose between multiple GPUs or check device capabilities. + +Function Documentation +---------------------- +.. sidebar:: af.device() + + Syntax: + af.device(option=None, value=None) + + Parameters: + 'option' (optional): Specifies the type of information or action. Can be one of the following: + + - "device": Get the current device index. + - "set": Set the current device index. + - "count": Get the number of available devices. + - "name": Get the name of the current device. + - "info": Get detailed information about the current device. + + 'value (optional)': The index of the device to set. Used only when the option is "set". If option is "set", this parameter should be an integer representing the device index. + + Returns: + Depending on the option, the function returns various types of information: + - If 'option' is "device": The index of the current device. + - If 'option' is "count": The number of available devices. + - If 'option' is "name": The name of the current device. + - If 'option' is "info": Detailed information about the current device. diff --git a/docs/functions/divide.rst b/docs/functions/divide.rst new file mode 100644 index 0000000..74d7880 --- /dev/null +++ b/docs/functions/divide.rst @@ -0,0 +1,36 @@ +divide +====== +The 'af.divide()' function in the ArrayFire library performs element-wise division of two arrays. This function allows you to divide one array by another, or to divide each element of an array by a scalar value. It supports operations on arrays of the same shape or on a scalar and an array. + +Function +-------- +:literal:`af.divide` + - Python interface for dividing one array by another. + +Detailed Description +-------------------- +The af.divide() function is used to perform element-wise division of arrays or between an array and a scalar. This operation divides each element of the first array by the corresponding element of the second array, or divides each element of the array by the scalar value. + +**Element-wise Division:** When dividing two arrays, the function performs the division for each corresponding element of the arrays. + +**Scalar Division:** When dividing an array by a scalar, the function divides each element of the array by the scalar value. + +The function handles broadcasting automatically when the dimensions of the arrays are compatible. + +Function Documentation +---------------------- +.. sidebar:: af.divide + + Syntax: + af.divide(array1, array2) + af.divide(array, scalar) + + + Parameters: + - array1: The first ArrayFire array (numerator) in the division operation. + - array2: The second ArrayFire array (denominator) in the division operation. Must have the same shape as array1 or be a scalar. + - array: The ArrayFire array to be divided by a scalar. + - scalar: The scalar value used to divide each element of array. + + Returns: + An ArrayFire array containing the results of the element-wise division. The resulting array will have the same shape as the input arrays. diff --git a/docs/functions/dot.rst b/docs/functions/dot.rst new file mode 100644 index 0000000..c776872 --- /dev/null +++ b/docs/functions/dot.rst @@ -0,0 +1,31 @@ +dot +=== +The 'af.dot()' function in ArrayFire computes the dot product of two arrays. This function is used for calculating the scalar product of two vectors or the matrix multiplication when applied to matrices. It is a fundamental operation in linear algebra with applications in various fields such as machine learning, physics, and numerical computing. + +Function +-------- +:literal:`af.dot()` + - Python interface to compute dot product of two arrays. + +Detailed Description +-------------------- +The af.dot() function computes the dot product, which can refer to different operations depending on the type of input: + +**Dot Product of Two Vectors:** For 1D arrays (vectors), the function calculates the scalar product. This is the sum of the products of corresponding elements of the vectors. + +**Matrix Multiplication:** For 2D arrays (matrices), it performs matrix multiplication, which is also referred to as the dot product in this context. + +Function Documentation +---------------------- +.. sidebar:: af.dot() + + Syntax: + af.dot(array1, array2) + + Parameters: + 'array1': The first ArrayFire array (vector or matrix) in the dot product operation. + 'array2': The second ArrayFire array (vector or matrix) in the dot product operation. Must be compatible with 'array1' for dot product or matrix multiplication. + + Returns: + - For vectors: A scalar value representing the dot product of the vectors. + - For matrices: An ArrayFire array representing the result of matrix multiplication. \ No newline at end of file diff --git a/docs/functions/eig.rst b/docs/functions/eig.rst new file mode 100644 index 0000000..250547a --- /dev/null +++ b/docs/functions/eig.rst @@ -0,0 +1,37 @@ +eig +=== +The 'af.eig()' function in ArrayFire computes the eigenvalues and eigenvectors of a square matrix. This function is essential in linear algebra for analyzing matrices and is used in various applications including machine learning, physics, and numerical analysis. + +Function +-------- +:literal:`af.eig()` + - Python interface for computing the eigenvalues and eigenvectors of a square matrix. + +Detailed Description +-------------------- +The 'af.eig()' function computes the eigenvalues and eigenvectors of a square matrix. For a given matrix +A, eigenvalues and eigenvectors are defined such that: + +𝐴𝑣 = 𝜆𝑣 + + +where: +- λ represents an eigenvalue. +- v represents the corresponding eigenvector. +The function returns two arrays: +- An array containing the eigenvalues of the matrix. +- An array containing the eigenvectors of the matrix. Each column in this array corresponds to an eigenvector. + +Function Documentation +---------------------- +.. sidebar:: af.eig() + + Syntax: + eigenvalues, eigenvectors = af.eig(matrix) + + Parameters: + 'matrix': A 2D ArrayFire array (matrix) for which eigenvalues and eigenvectors are to be computed. The matrix must be square (i.e., the number of rows must be equal to the number of columns). + + Returns: + - eigenvalues: An ArrayFire array containing the eigenvalues of the input matrix. + - eigenvectors: An ArrayFire array containing the eigenvectors of the input matrix. Each column of this array is an eigenvector corresponding to the eigenvalues. diff --git a/docs/functions/exp.rst b/docs/functions/exp.rst new file mode 100644 index 0000000..5d06ec0 --- /dev/null +++ b/docs/functions/exp.rst @@ -0,0 +1,32 @@ +exp +=== +The 'af.exp()' function in ArrayFire computes the element-wise exponential of an array. This function calculates the exponential of each element in the input array, using the base of the natural logarithm (e ≈ 2.71828). It is commonly used in scientific computing, machine learning, and numerical analysis where exponential transformations are required. + +Function +-------- +:literal:`af.exp()` + - Python interface used to compute the exponential of each element in an array. + +Detailed Description +-------------------- +The af.exp() function performs the exponential operation on each element of the input array. If +𝑥 is an element in the array, then exp⁡(𝑥) computes 𝑒𝑥, where 𝑒 is the base of the natural logarithm. + +This function supports: + +- **Element-wise Operations:** Applying the exponential function to each element of the array independently. +- **Broadcasting:** Automatically handling arrays of different shapes for operations where applicable. + +Function Documentation +---------------------- +.. sidebar:: af.exp() + + Syntax: + af.exp(array) + + Parameters: + 'array': An ArrayFire array (1D, 2D, or higher-dimensional) for which the exponential is to be computed. + + Returns: + An ArrayFire array with the same shape as the input array, where each element is the exponential of the corresponding element in the input array. + diff --git a/docs/functions/fft.rst b/docs/functions/fft.rst new file mode 100644 index 0000000..e365127 --- /dev/null +++ b/docs/functions/fft.rst @@ -0,0 +1,39 @@ +fft +=== +The 'af.fft()' function in ArrayFire computes the Fast Fourier Transform (FFT) of an array. The FFT is an efficient algorithm to compute the discrete Fourier transform (DFT) and its inverse. The function is used to transform signals from the time domain to the frequency domain, which is essential in signal processing, image analysis, and many other fields. + +Function +-------- +:literal:`af.fft()` + - Python interface for transforming signals from the time domain to the frequency domain. + +Detailed Description +-------------------- +The 'af.fft()' function performs a discrete Fourier transform of the input array. The FFT is commonly used for: + +- Signal Processing: Analyzing the frequency components of a signal. +- Image Processing: Transforming images to the frequency domain for various processing tasks. +- Numerical Analysis: Solving differential equations and other problems where Fourier methods are applicable. +The function supports: + +- 1D FFT: Transforming 1D arrays (vectors). +- 2D FFT: Transforming 2D arrays (matrices). +- 3D FFT: Transforming 3D arrays (volumes). +- Multi-dimensional FFTs: Transforming arrays of higher dimensions. +The FFT can be computed along specified dimensions or all dimensions of the input array. + +Function Documentation +---------------------- +.. sidebar:: af.fft() + + Syntax: + af.fft(array, dim=None, is_inverse=False) + + Parameters: + - array: The ArrayFire array (1D, 2D, or higher-dimensional) to transform. + - dim (optional): The dimension along which to compute the FFT. If not specified, the FFT is computed along all dimensions. + - is_inverse (optional): A boolean flag indicating whether to compute the inverse FFT. If True, the function computes the inverse FFT; otherwise, it computes the forward FFT. + + Returns: + An ArrayFire array of the same shape as the input array containing the FFT of the input array. + diff --git a/docs/functions/get.rst b/docs/functions/get.rst new file mode 100644 index 0000000..f7d8956 --- /dev/null +++ b/docs/functions/get.rst @@ -0,0 +1,31 @@ +get +=== +The af.get() function in ArrayFire is used to retrieve data from an ArrayFire array and copy it into a standard Python data structure, such as a NumPy array or a Python list. This function is useful for accessing and manipulating the data stored in ArrayFire arrays within the Python environment. + +Function +-------- +:literal:`af.get()` + - Python interface used to retrieve data from an ArrayFire array and copy it into a standard Python data structure. + +Detailed Description +-------------------- +The 'af.get()' function is used to copy the data from an ArrayFire array into a standard Python data structure. This function is typically used when you need to work with the data in a format that is compatible with other Python libraries or for further analysis and manipulation in Python. + +Key Points: + +- Conversion to NumPy Arrays: You can convert ArrayFire arrays to NumPy arrays for use with libraries that do not support ArrayFire arrays directly. +- Conversion to Python Lists: You can convert ArrayFire arrays to Python lists for ease of use in general Python code. + +Function Documentation +---------------------- +.. sidebar:: af.get() + + Syntax: + af.get(array) + + + Parameters: + 'array': The ArrayFire array from which to retrieve data. + + Returns: + A standard Python data structure (e.g., NumPy array or Python list) containing the data from the ArrayFire array. diff --git a/docs/functions/get_device.rst b/docs/functions/get_device.rst new file mode 100644 index 0000000..953b0c2 --- /dev/null +++ b/docs/functions/get_device.rst @@ -0,0 +1,27 @@ +get_device +========== +The 'af.get_device()' function in ArrayFire is used to retrieve the device object associated with the ArrayFire context. This function provides information about the current active device, such as its ID, name, and properties. It is useful for managing and querying the status of devices in a multi-device environment. + +Function +-------- +:literal:`af.get_device()` + - Python interface used to retrieve the device object associated with the ArrayFire context. + +Detailed Description +-------------------- +The 'af.get_device()' function provides access to the device object in ArrayFire. This device object contains various details about the GPU or other computational device that ArrayFire is using for computations. This function is particularly useful in environments where multiple devices are available and you need to query or manage device-specific information. + +Function Documentation +---------------------- +.. sidebar:: af.get_device() + + Syntax: + device = af.get_device() + + + Parameters: + This function does not take any parameters. + + Returns: + An ArrayFire device object representing the current active device in the ArrayFire context. + diff --git a/docs/functions/ifft.rst b/docs/functions/ifft.rst new file mode 100644 index 0000000..991576c --- /dev/null +++ b/docs/functions/ifft.rst @@ -0,0 +1,27 @@ +ifft +==== +The 'af.ifft()' function in ArrayFire computes the inverse Fast Fourier Transform (IFFT) of an array. The IFFT is used to transform data from the frequency domain back to the time domain, which is crucial in many signal processing, image analysis, and scientific computing applications. + +Function +-------- +:literal:`af.ifft()` + - Python interface used to compute the inverse Fast Fourier Transform of an array. + +Detailed Description +-------------------- +The 'af.ifft()' function performs an inverse discrete Fourier transform of the input array. It is essentially the reverse operation of the Fast Fourier Transform (FFT), converting frequency domain data back into the time domain. + +Function Documentation +---------------------- +.. sidebar:: af.ifft() + + Syntax: + af.ifft(array, dim=None) + + Parameters: + 'array': The ArrayFire array (1D, 2D, or higher-dimensional) to which the inverse FFT is to be applied. + 'dim (optional)'': The dimension along which to compute the inverse FFT. If not specified, the IFFT is computed along all dimensions. + + Returns: + An ArrayFire array of the same shape as the input array containing the result of the inverse FFT. + diff --git a/docs/functions/inv.rst b/docs/functions/inv.rst new file mode 100644 index 0000000..37969b1 --- /dev/null +++ b/docs/functions/inv.rst @@ -0,0 +1,30 @@ +inv +=== +The 'af.inv()' function in ArrayFire computes the inverse of a square matrix. Matrix inversion is a fundamental operation in linear algebra with applications in solving systems of linear equations, optimization problems, and various computational tasks. + +Function +-------- +:literal:`af.inv()` + - Python interface used to find inverse of a square matrix. + +Detailed Description +-------------------- +The af.inv() function calculates the inverse of a given square matrix. For a matrix +𝐴, the inverse is denoted as 𝐴−1, and it satisfies the following property: + +A⋅A−1=I +where I is the identity matrix. The matrix A must be square (i.e., the number of rows must be equal to the number of columns) for its inverse to exist. + +Function Documentation +---------------------- +.. sidebar:: af.inv() + + Syntax: + af.inv(matrix) + + Parameters: + 'matrix:'' A 2D ArrayFire array representing the square matrix for which the inverse is to be computed. The matrix must be square. + + Returns: + An ArrayFire array of the same shape as the input matrix, containing the inverse of the input matrix. + diff --git a/docs/functions/join.rst b/docs/functions/join.rst new file mode 100644 index 0000000..9f7d1fc --- /dev/null +++ b/docs/functions/join.rst @@ -0,0 +1,27 @@ +join +==== +The 'af.join()' function in ArrayFire is used to concatenate multiple arrays along a specified dimension. This operation is useful for combining data from different arrays into a single array, which can be particularly useful in data processing, machine learning, and numerical analysis. + + + +Function +-------- +:literal:`af.join` + - Python interface used to concatenate multiple arrays along a specified dimension. + +Detailed Description +-------------------- +The 'af.join()' function allows you to concatenate multiple arrays along a specified dimension. The arrays being concatenated must have compatible shapes along all dimensions except for the dimension along which concatenation is performed. + +Function Documentation +---------------------- +.. sidebar:: af.join() + + Syntax: + af.join(dim, *arrays) + + Parameters: + 'dim': The dimension along which the arrays will be concatenated. This is an integer indicating the axis along which the join operation will take place. + '*arrays': The arrays to be concatenated. These can be 1D, 2D, or higher-dimensional arrays, and they must be compatible in all dimensions except the specified dimension. + Returns: + An ArrayFire array that is the result of concatenating the input arrays along the specified dimension. diff --git a/docs/functions/log.rst b/docs/functions/log.rst new file mode 100644 index 0000000..3477898 --- /dev/null +++ b/docs/functions/log.rst @@ -0,0 +1,26 @@ +log +=== +The 'af.log()' function in ArrayFire computes the natural logarithm (base 𝑒) of each element in the input array. This function is commonly used in mathematical and scientific computing for transformations, normalization, and statistical analysis. + +Function +-------- +:literal:`af.log()` + - Python interface used to compute the natural logarithm of each base element in the input array. + +Detailed Description +-------------------- +The af.log() function applies the natural logarithm operation element-wise to the input array. The natural logarithm is the logarithm to the base +𝑒, where 𝑒 is approximately equal to 2.71828. The function operates on each element of the array independently. + +Function Documentation +---------------------- +.. sidebar:: af.log() + + Syntax: + af.log(array) + + Parameters: + 'array': An ArrayFire array (1D, 2D, or higher-dimensional) containing the values for which the natural logarithm is to be computed. + + Returns: + An ArrayFire array of the same shape as the input array, with each element replaced by its natural logarithm. diff --git a/docs/functions/matmul.rst b/docs/functions/matmul.rst new file mode 100644 index 0000000..e36f41b --- /dev/null +++ b/docs/functions/matmul.rst @@ -0,0 +1,27 @@ +matmul +====== +The 'af.matmul()' function in ArrayFire performs matrix multiplication between two arrays. Matrix multiplication is a fundamental operation in linear algebra and is widely used in various scientific and engineering computations. + +Function +-------- +:literal:`af.matmul()` + - Python interface used to perform matrix multiplication between two arrays. + +Detailed Description +-------------------- +The af.matmul() function computes the matrix product of two input arrays. Matrix multiplication is defined for two matrices 𝐴 and 𝐵 where the number of columns in 𝐴 is equal to the number of rows in 𝐵. The result is a matrix where each element is computed as the dot product of rows of +𝐴 with columns of 𝐵. + +Function Documentation +---------------------- +.. sidebar:: af.matmul() + + Syntax: + af.matmul(A, B) + + Parameters: + 'A': The first input array (matrix) to be multiplied. + 'B': The second input array (matrix) to be multiplied. + + Returns: + An ArrayFire array representing the result of the matrix multiplication. diff --git a/docs/functions/max.rst b/docs/functions/max.rst new file mode 100644 index 0000000..091719a --- /dev/null +++ b/docs/functions/max.rst @@ -0,0 +1,31 @@ +max +=== +The 'af.max()' function in ArrayFire is used to find the maximum value within an array or along a specific dimension. It can also return the indices of the maximum values if requested. + + + +Function +-------- +:literal:`af.max()` + - Python interface used to find the maximum value within an array or specific dimension. + +Detailed Description +-------------------- +The af.max() function performs one of the following operations: + +- Finds the maximum value in the entire array. +- Finds the maximum value along a specified dimension. +- Returns both the maximum values and their indices if requested. + +Function Documentation +---------------------- +.. sidebar:: af.max() + + Syntax: + af.max(array) + + Parameters: + 'array': The ArrayFire array from which to find the maximum values. + + Returns: + An ArrayFire array containing the maximum element from the input data structure. diff --git a/docs/functions/mean.rst b/docs/functions/mean.rst new file mode 100644 index 0000000..a900ee0 --- /dev/null +++ b/docs/functions/mean.rst @@ -0,0 +1,27 @@ +mean +==== +The 'af.mean()' function in ArrayFire computes the mean (average) value of elements in an array or along a specified dimension. It is a fundamental statistical operation used in various data analysis and processing tasks. + +Function +-------- +:literal:`af.mean()` + - Python interface used to compute the average value of elements in an array or specified dimension. + +Detailed Description +-------------------- +The 'af.mean()' function calculates the average value of elements in the input array. The mean is computed by summing all elements and dividing by the number of elements. The function can compute the mean over the entire array or along a specified dimension. + +Function Documentation +---------------------- +.. sidebar:: af.mean() + + Syntax: + af.mean(array) + + + Parameters: + 'array': The ArrayFire array for which the mean is to be computed. + + Returns: + An ArrayFire array containing the mean values. If 'axis' is specified, the result will have the specified dimension reduced. + diff --git a/docs/functions/median.rst b/docs/functions/median.rst new file mode 100644 index 0000000..4ee1417 --- /dev/null +++ b/docs/functions/median.rst @@ -0,0 +1,27 @@ +median +====== +The af.median() function in ArrayFire computes the median value of elements in an array or along a specified dimension. The median is a measure of central tendency that provides a robust statistic by identifying the middle value in a sorted list of numbers. + +Function +-------- +:literal:`af.median()` + - Python interface used to compute the median value of elements in an array or specified dimension. + +Detailed Description +-------------------- +The 'af.median()' function finds the median value of elements in the input array. The median is defined as the middle value in a sorted sequence of numbers. If the number of elements is even, it is the average of the two middle numbers. The function can compute the median over the entire array or along a specified dimension. + +Function Documentation +---------------------- +.. sidebar:: af.median() + + Syntax: + af.median(array) + + + Parameters: + 'array': The ArrayFire array for which the median is to be computed. + + Returns: + An ArrayFire array containing the median values. If 'axis' is specified, the result will have the specified dimension reduced. + diff --git a/docs/functions/min.rst b/docs/functions/min.rst new file mode 100644 index 0000000..6ee6556 --- /dev/null +++ b/docs/functions/min.rst @@ -0,0 +1,25 @@ +min +=== +The af.min() function in ArrayFire is used to compute the minimum value within an array or along a specific dimension. This operation helps in identifying the smallest value in a dataset or reducing multi-dimensional arrays to a lower dimension based on the minimum values. + +Function +-------- +:literal:`af.min()` + - Python interface used to compute the minimum value within an array or specified dimension. + +Detailed Description +-------------------- +The 'af.min()' function finds the minimum value of elements in the input array. The minimum value is the smallest element in the array. The function can compute the minimum over the entire array or along a specified dimension. + +Function Documentation +---------------------- +.. sidebar:: af.min() + + Syntax: + af.min(array) + + Parameters: + 'array': The ArrayFire array from which to find the minimum values. + + Returns: + An ArrayFire array containing the minimum values from the input data structure. diff --git a/docs/functions/multiply.rst b/docs/functions/multiply.rst new file mode 100644 index 0000000..623b01c --- /dev/null +++ b/docs/functions/multiply.rst @@ -0,0 +1,32 @@ +multiply +======== +The 'af.multiply()' function in ArrayFire performs element-wise multiplication between two arrays. This means each element of the first array is multiplied by the corresponding element of the second array. It supports both scalar and array inputs for flexible use. + +Function +-------- +:literal:`af.multiply()` + - Python interface used to perform element-wise multiplication between two arrays. + +Detailed Description +-------------------- +The 'af.multiply()' function computes the product of two input arrays element-wise. If the inputs are arrays, they must have the same dimensions or be broadcastable to compatible dimensions. If one of the inputs is a scalar, it multiplies each element of the other array by that scalar. + +Function Documentation +---------------------- +.. sidebar:: af.multiply() + + Syntax: + af.multiply(array1, array2) + af.multiply(array, scalar) + af.multiply(scalar, array) + + + Parameters: + 'array1': The first input array. + 'array2': The second input array. Must have the same dimensions as array1 or be broadcastable to the dimensions of array1. + 'array': The input array if using scalar multiplication. + 'scalar': The scalar value to multiply with the array. + + Returns: + An ArrayFire array containing the result of the element-wise multiplication. + diff --git a/docs/functions/ones.rst b/docs/functions/ones.rst new file mode 100644 index 0000000..fbf78af --- /dev/null +++ b/docs/functions/ones.rst @@ -0,0 +1,26 @@ +ones +==== +The 'af.ones()' function in the ArrayFire library is used to create arrays where every element is initialized to one. This function is useful for various numerical and scientific computing tasks where you need an array filled with ones, such as initializing weights in machine learning algorithms or setting up identity matrices. + +Function +-------- +:literal:`af.ones()` + - Pyhton interface to create an array filled with ones. + +Detailed Description +-------------------- +The 'af.ones()' function creates an ArrayFire array in which all the elements are set to one. This function is versatile and can create arrays of different shapes and data types. By default, the function creates arrays with single precision floating-point numbers (float), but you can specify different data types as needed. + +The dimensions of the array are specified as arguments to the function, allowing you to create both one-dimensional and multi-dimensional arrays. + +Function Documentation +---------------------- +.. sidebar:: af.ones() + + Syntax: + af.ones(dim0, dim1) + + Parameters: + 'dim0, dim1': Integers representing the dimensions of the array. You can provide multiple dimensions to create multi-dimensional arrays. For instance, 'dim0' represents the number of rows, and 'dim1' represents the number of columns for a 2D array. + Returns: + An ArrayFire array with the specified dimensions and data type, where all elements are initialized to one. diff --git a/docs/functions/prod.rst b/docs/functions/prod.rst new file mode 100644 index 0000000..6922383 --- /dev/null +++ b/docs/functions/prod.rst @@ -0,0 +1,27 @@ +prod +==== +The 'af.prod()' function in ArrayFire computes the product of elements in an array or along a specified dimension. It aggregates elements by multiplying them together, which is useful in various mathematical and data processing applications. + +Function +-------- +:literal:`af.prod()` + - Python interface used to compute the product of elements in an array or along a specified dimension + +Detailed Description +-------------------- +The 'af.prod()' function calculates the product of all elements in the input array or along a specified dimension. If no dimension is specified, it computes the product of all elements in the array. This function can also handle multi-dimensional arrays, where you can specify the dimension along which to compute the product. + +Function Documentation +---------------------- +.. sidebar:: af.prod() + + Syntax: + af.prod(array) + + + Parameters: + 'array': The ArrayFire array for which the product is to be computed. + + Returns: + An ArrayFire array containing the product of elements. If axis is specified, the result will have the specified dimension reduced. + diff --git a/docs/functions/randn.rst b/docs/functions/randn.rst new file mode 100644 index 0000000..43ff957 --- /dev/null +++ b/docs/functions/randn.rst @@ -0,0 +1,26 @@ +randn +===== +The 'af.randn()' function in the ArrayFire library is used to generate arrays filled with random numbers drawn from a normal (Gaussian) distribution with mean 0 and standard deviation 1. This is useful in statistical simulations, machine learning, and other applications where normally distributed random values are required. + +Function +-------- +:literal:`af.python()` + - Python interface to form an array filled with numbers. + +Detailed Description +-------------------- +The 'af.randn()' function creates an ArrayFire array where each element is a random number sampled from a standard normal distribution, also known as a Gaussian distribution. The distribution has a mean of 0 and a standard deviation of 1. This function allows you to specify the dimensions of the array and optionally the data type. By default, the function generates numbers in single precision floating-point format (float), but other data types can be specified if needed. + +Function Documentation +---------------------- +.. sidebar:: af.randn() + + Syntax: + af.randn(dim0, dim1) + + + Parameters: + 'dim0, dim1': Integers representing the dimensions of the array. You can specify multiple dimensions to create multi-dimensional arrays. For example, dim0 represents the number of rows, and dim1 represents the number of columns for a 2D array. + + Returns: + An ArrayFire array with the specified dimensions and data type, where all elements are initialized with random values sampled from a normal distribution with mean 0 and standard deviation 1. diff --git a/docs/functions/randu.rst b/docs/functions/randu.rst new file mode 100644 index 0000000..16de0df --- /dev/null +++ b/docs/functions/randu.rst @@ -0,0 +1,29 @@ +randu +===== +The af.randu() function in ArrayFire is used to generate arrays with uniformly distributed random numbers. The numbers are drawn from a uniform distribution in the interval +[0,1). This function is useful for initializing random data for simulations, stochastic processes, or for testing algorithms that require random inputs. + +Function +-------- +:literal:`af.randu()` + - Python interface for making a rray with random units. + +Detailed Description +-------------------- +The 'af.randu()' function creates an ArrayFire array filled with random numbers that follow a uniform distribution between 0 and 1 (excluding 1). This function allows you to specify the dimensions of the array and optionally the data type. By default, the generated numbers are single-precision floating-point values (float), but other data types can be specified if needed. + +Random number generation is a fundamental aspect of many computational tasks, and 'af.randu()' provides an efficient way to create random datasets with uniform distribution. + +Function Documentation +---------------------- +.. sidebar:: af.randu() + + Syntax: + af.randu(dim0, dim1) + + Parameters: + 'dim0, dim1': Integers representing the dimensions of the array. You can provide multiple dimensions to create multi-dimensional arrays. For example, dim0 represents the number of rows, and dim1 represents the number of columns for a 2D array. + + Returns: + An ArrayFire array with the specified dimensions and data type, where all elements are initialized with random values uniformly distributed between 0 and 1. + diff --git a/docs/functions/reorder.rst b/docs/functions/reorder.rst new file mode 100644 index 0000000..3f03e49 --- /dev/null +++ b/docs/functions/reorder.rst @@ -0,0 +1,27 @@ +reorder +======= +The 'af.reorder()' function in ArrayFire is used to rearrange the dimensions of an array. This is useful for changing the order of dimensions to align with the requirements of different operations or to facilitate certain types of computations. + +Function +-------- +:literal:`af.reorder()` + - Python interface used to rearrange the dimensions of an array. + +Detailed Description +-------------------- +The 'af.reorder()' function changes the order of dimensions of the input array. It is often used in conjunction with other functions that require specific data layouts. Reordering dimensions can help optimize performance or compatibility with other libraries and tools. + +Function Documentation +---------------------- +.. sidebar:: af.reorder() + + Syntax: + af.reorder(array, *order) + + Parameters: + 'array': The ArrayFire array whose dimensions are to be reordered. + '*order': The new order of dimensions specified as a sequence of integers. Each integer represents the index of the dimension in the new order. + + Returns: + An ArrayFire array with the dimensions reordered according to the specified order. + diff --git a/docs/functions/reshape.rst b/docs/functions/reshape.rst new file mode 100644 index 0000000..4f5a442 --- /dev/null +++ b/docs/functions/reshape.rst @@ -0,0 +1,25 @@ +reshape +======= +The 'af.reshape()' function in ArrayFire is used to change the shape of an array. This function allows you to rearrange the dimensions of an array while keeping the underlying data intact. It is particularly useful for preparing data for operations that require specific shapes or for transforming data between different formats. + +Function +-------- +:literal:`af.reshape()` + - Python interface used to change the shape of an array. + +Detailed Description +-------------------- +The 'af.reshape()' function changes the shape of an existing array to a new shape specified by the user. The total number of elements in the original array must match the total number of elements in the reshaped array. The function does not alter the data but reinterprets it under a new shape. + +Function Documentation +---------------------- +.. sidebar:: af.reshape() + + Syntax: + af.reshape(array,*new_shape) + + Parameters: + 'array': The ArrayFire array to be reshaped. + '*new_shape': The new shape for the array, specified as a sequence of integers. The product of these dimensions must equal the total number of elements in the original array. + Returns: + An ArrayFire array with the specified new shape. \ No newline at end of file diff --git a/docs/functions/set_device.rst b/docs/functions/set_device.rst new file mode 100644 index 0000000..10007ae --- /dev/null +++ b/docs/functions/set_device.rst @@ -0,0 +1,25 @@ +set_device +========== +The 'af.set_device()' function in ArrayFire is used to specify which device (GPU or CPU) will be used for subsequent ArrayFire operations. This is particularly useful when working with multiple devices or GPUs to ensure that computations are directed to the desired hardware. + +Function +-------- +:literal:`af.set_device()` + - Python interface used to specify which device will be used for subsequent arrayfire operations. + +Detailed Description +-------------------- +The 'af.set_device()' function sets the device ID for ArrayFire operations. By default, ArrayFire uses the first available device (usually device ID 0). When you have multiple GPUs or devices, you can use this function to select which device ArrayFire should use for subsequent operations. + +Function Documentation +---------------------- +.. sidebar:: af.set_device() + + Syntax: + af.set_device(device_id) + + Parameters: + 'device_id': An integer representing the ID of the device to be set. This ID corresponds to the device index in the ArrayFire device list. + + Returns: + None diff --git a/docs/functions/slice.rst b/docs/functions/slice.rst new file mode 100644 index 0000000..9d4a5c8 --- /dev/null +++ b/docs/functions/slice.rst @@ -0,0 +1,27 @@ +slice +===== +The 'af.slice()' function in ArrayFire is used to extract a subarray from a larger array by specifying the start and end indices along each dimension. This function is useful for accessing a portion of an array, which is essential for tasks such as data manipulation, cropping, and partitioning. + +Function +-------- +:literal:`af.slice()` + - Python interface used to extract a subarray from a larger array by specifying the start and end indices along each dimension. + +Detailed Description +-------------------- +The 'af.slice()' function allows you to extract a contiguous subarray from the original array. You specify the starting and ending indices for each dimension to define the subarray. This function provides a way to access specific regions of multi-dimensional arrays efficiently. + +Function Documentation +---------------------- +.. sidebar:: af.slice() + + Syntax: + af.slice(array, *start_indices, *end_indices) + + Parameters: + 'array': The ArrayFire array from which the subarray will be extracted. + '*start_indices': A sequence of integers specifying the starting indices for each dimension. + '*end_indices': A sequence of integers specifying the ending indices for each dimension. + + Returns: + An ArrayFire array containing the extracted subarray. diff --git a/docs/functions/sqrt.rst b/docs/functions/sqrt.rst new file mode 100644 index 0000000..4fb397f --- /dev/null +++ b/docs/functions/sqrt.rst @@ -0,0 +1,25 @@ +sqrt +==== +The 'af.sqrt()' function in ArrayFire is used to compute the square root of each element in an array. This is a common mathematical operation used in various computational tasks, including normalization, scaling, and feature extraction. + +Function +-------- +:literal:`af.sqrt()` + - Python interface used to compute the square root of each element in an array. + +Detailed Description +-------------------- +The 'af.sqrt()' function calculates the square root of every element in the input array. The result is an array of the same shape, where each element is the square root of the corresponding element in the input array. + +Function Documentation +---------------------- +.. sidebar:: af.sqrt() + + Syntax: + af.sqrt(array) + + Parameters: + 'array': The ArrayFire array for which the square root will be computed. + + Returns: + An ArrayFire array where each element is the square root of the corresponding element in the input array. diff --git a/docs/functions/sttdev.rst b/docs/functions/sttdev.rst new file mode 100644 index 0000000..11fb80e --- /dev/null +++ b/docs/functions/sttdev.rst @@ -0,0 +1,26 @@ +stdev +===== +The 'af.stdev()' function in ArrayFire computes the standard deviation of elements in an array. The standard deviation is a measure of the amount of variation or dispersion in a set of values. This function can compute the standard deviation across all elements or along a specified dimension of the array. + +Function +-------- +:literal:`af.stdev()` + - Python interface used to compute the standard deviation of elements in an array. + +Detailed Description +-------------------- +The 'af.stdev()' function calculates the standard deviation of the values in an array. It can operate over all elements of the array or along a specified dimension. This function helps in understanding the spread or variability of data points. + +Function Documentation +---------------------- +.. sidebar:: af.stdev() + + Syntax: + af.stdev(array) + + + Parameters: + 'array': The ArrayFire array for which the standard deviation will be computed. + + Returns: + An ArrayFire array containing the computed standard deviation. diff --git a/docs/functions/subtract.rst b/docs/functions/subtract.rst new file mode 100644 index 0000000..b92b0ea --- /dev/null +++ b/docs/functions/subtract.rst @@ -0,0 +1,29 @@ +subtract +======== +The 'af.subtract()' function in ArrayFire is used to perform element-wise subtraction between two arrays or between an array and a scalar. This operation is fundamental in many computational tasks, including data manipulation, feature scaling, and mathematical operations. + +Function +-------- +:literal:`af.subtract()` + - Python interface used to perform element-wise subtraction between two arrays or between an array and a scalar. + +Detailed Description +-------------------- +The 'af.subtract()' function subtracts the elements of one array from the corresponding elements of another array, or subtracts a scalar value from each element of an array. The function performs this operation element-wise, meaning that each element of the first operand is subtracted by the corresponding element of the second operand. + +Function Documentation +---------------------- +.. sidebar:: af.subtract() + + Syntax: + af.subtract(array1, array2) + af.subtract(array, scalar) + + Parameters: + 'array1': The ArrayFire array from which elements will be subtracted. + 'array2': The ArrayFire array to subtract from array1. This should have the same shape as array1 or be broadcast-compatible. + 'scalar': A scalar value to subtract from each element of array. + + Returns: + An ArrayFire array containing the result of the subtraction. + diff --git a/docs/functions/sum.rst b/docs/functions/sum.rst new file mode 100644 index 0000000..13407e5 --- /dev/null +++ b/docs/functions/sum.rst @@ -0,0 +1,26 @@ +sum +=== +The 'af.sum()' function in ArrayFire computes the sum of the elements in an array. This function can perform the summation over all elements or along a specified dimension. It is useful for aggregating data, calculating totals, and summarizing results in numerical computations. + +Function +-------- +:literal:`af.sum()` + - Python interface used to compute the sum of the elements in an array. + +Detailed Description +-------------------- +The 'af.sum()' function calculates the sum of array elements. You can choose to compute the sum across all elements of the array or along a specific dimension. This function supports both reducing the array to a single value and computing sums along specified axes. + +Function Documentation +---------------------- +.. sidebar:: af.sum() + + Syntax: + af.sum(array) + + Parameters: + 'array': The ArrayFire array for which the sum will be computed. + 'dim': An optional integer specifying the dimension along which to compute the sum. By default, it is set to 0, which means the function will sum along the first dimension. + + Returns: + An ArrayFire array containing the sum of the elements. diff --git a/docs/functions/transpose.rst b/docs/functions/transpose.rst new file mode 100644 index 0000000..747ecf2 --- /dev/null +++ b/docs/functions/transpose.rst @@ -0,0 +1,27 @@ +transpose +========= +The 'af.transpose()' function in ArrayFire is used to compute the transpose of a matrix or higher-dimensional array. Transposing a matrix involves swapping its rows and columns. This function is fundamental in linear algebra operations and many computational tasks. + +Function +-------- +:literal:`af.transpose()` + - Python interface used to compute the transpose of a matrix or higher-dimensional array. + +Detailed Description +-------------------- +The 'af.transpose()' function computes the transpose of a given array. For 2D matrices, this means converting rows into columns and columns into rows. For higher-dimensional arrays, the function permutes dimensions according to the specified order. + +Function Documentation +---------------------- +.. sidebar:: af.transpose() + + Syntax: + af.transpose(array, *permutation) + + Parameters: + 'array': The ArrayFire array to be transposed. + '*permutation': An optional sequence of integers specifying the new order of dimensions. If not provided, the function defaults to transposing the last two dimensions. + + Returns: + An ArrayFire array that is the transpose of the input array, with dimensions permuted according to the provided permutation. + diff --git a/docs/functions/zeros.rst b/docs/functions/zeros.rst new file mode 100644 index 0000000..a631c2c --- /dev/null +++ b/docs/functions/zeros.rst @@ -0,0 +1,27 @@ +zeros +===== +The 'af.zeros()' function in the ArrayFire library is used to create arrays filled with zeros. This is a common operation when initializing arrays that will be updated or manipulated later in numerical computations. The function allows you to specify the dimensions and data type of the array, making it flexible for various use cases. + +Function +-------- +:literal:`af.zeros()` + - Python interface to create array filled with zeros. +Detailed Description +-------------------- +The 'af.zeros()' function creates an ArrayFire array where every element is initialized to zero. It is particularly useful when you need to allocate space for an array but want to ensure that all values start from zero. This is often used in numerical methods, data processing, and initialization of variables in scientific computing. + +You can specify the dimensions of the array as well as its data type. By default, the function creates arrays with a single precision floating-point type (float), but you can specify other data types if needed. + +Function Documentation +---------------------- +.. sidebar:: af.zero() + + Syntax: + af.zeros(dim0, dim1) + + Parameters: + 'dim0, dim1': Integers representing the dimensions of the array. You can specify multiple dimensions to create multi-dimensional arrays. For example, dim0 is the number of rows, and dim1 is the number of columns for a 2D array. + Returns: + An ArrayFire array with the specified dimensions and data type, where all elements are initialized to zero. + + diff --git a/docs/overview.py b/docs/overview.py index 2b38a3e..18ee70a 100644 --- a/docs/overview.py +++ b/docs/overview.py @@ -2,7 +2,7 @@ # [pi-example-simple-snippet] # Monte Carlo estimation of pi -def calc_pi_device(samples): +def calc_pi_device(samples) -> float: # Simple, array based API # Generate uniformly distributed random numers x = af.randu(samples) From 0aa74563a3b5d98408c06438b6d1d9e52580b72d Mon Sep 17 00:00:00 2001 From: michaeleg21 Date: Thu, 29 Aug 2024 15:56:05 -0400 Subject: [PATCH 05/11] Fixed warnings, minor updates --- dev-requirements.txt | 1 + docs/conf.py | 10 ++++--- docs/examples.rst | 34 +++--------------------- docs/functions/device.rst | 1 + docs/functions/fft.rst | 2 ++ docs/functions/index.rst | 39 ++++++++++++++++++++++++++++ docs/functions/join.rst | 4 +-- docs/functions/reorder.rst | 4 +-- docs/functions/reshape.rst | 4 +-- docs/functions/slice.rst | 6 ++--- docs/functions/transpose.rst | 4 +-- docs/functions/zeros.rst | 1 + docs/gettingstarted.rst | 1 + docs/index.rst | 30 ++++++++++----------- docs/indexing.py | 2 +- docs/installation.rst | 4 +++ docs/introductiontovectorization.rst | 2 +- docs/linux.rst | 3 +++ docs/releasenotes.rst | 32 +++-------------------- 19 files changed, 92 insertions(+), 92 deletions(-) create mode 100644 docs/functions/index.rst diff --git a/dev-requirements.txt b/dev-requirements.txt index ae38ba6..7c3e0e6 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -22,3 +22,4 @@ codecov>=2.1.12 # Allows documentation sphinx>=7.3.7 sphinxawesome_theme>=5.2.0 +sphinx_collapse>=0.1.3 diff --git a/docs/conf.py b/docs/conf.py index 2b36bb2..256a621 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -12,9 +12,9 @@ # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information project = 'ArrayFire' -copyright = '2024, Michael Egwuatu' -author = 'Michael Egwuatu' -release = '6/11/2024' +copyright = '2024, ArrayFire' +author = 'ArrayFire' +release = '' # -- General configuration --------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration @@ -39,4 +39,8 @@ html_static_path = ['_static'] html_permalinks = False +# -- Suppress specific warnings -------------------------------------------- +suppress_warnings = [ + 'ref.include_missing', +] diff --git a/docs/examples.rst b/docs/examples.rst index acccf46..b78d09a 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -2,34 +2,6 @@ Examples ======== - -Introduction ------------- - -This is the introductory section of File 1. - -Modules -------- - -Here is some content for the first section. - -Mod -~~~ - -This is a subsection under Section 1. - -Mod1 -~~~~ - -More content for the second section. - -Mod2 -~~~~ - -This concludes the content of File 1. - -Mod3 -~~~~ - -Mod4 -~~~~ +TO DO +----- +ADD LIST OF EXAMPLES \ No newline at end of file diff --git a/docs/functions/device.rst b/docs/functions/device.rst index 31db655..318547b 100644 --- a/docs/functions/device.rst +++ b/docs/functions/device.rst @@ -14,6 +14,7 @@ The 'af.device()' function is useful for managing and querying the device that A - Getting the Current Device: Retrieve the index of the currently selected device. - Setting the Current Device: Select a specific device for computations. - Querying Device Properties: Obtain information about the current device. + This functionality is important for applications that need to explicitly choose between multiple GPUs or check device capabilities. Function Documentation diff --git a/docs/functions/fft.rst b/docs/functions/fft.rst index e365127..e648438 100644 --- a/docs/functions/fft.rst +++ b/docs/functions/fft.rst @@ -14,12 +14,14 @@ The 'af.fft()' function performs a discrete Fourier transform of the input array - Signal Processing: Analyzing the frequency components of a signal. - Image Processing: Transforming images to the frequency domain for various processing tasks. - Numerical Analysis: Solving differential equations and other problems where Fourier methods are applicable. + The function supports: - 1D FFT: Transforming 1D arrays (vectors). - 2D FFT: Transforming 2D arrays (matrices). - 3D FFT: Transforming 3D arrays (volumes). - Multi-dimensional FFTs: Transforming arrays of higher dimensions. + The FFT can be computed along specified dimensions or all dimensions of the input array. Function Documentation diff --git a/docs/functions/index.rst b/docs/functions/index.rst new file mode 100644 index 0000000..03a66e4 --- /dev/null +++ b/docs/functions/index.rst @@ -0,0 +1,39 @@ +.. toctree:: + :maxdepth: 2 + :caption: Functions: + + transpose + array + ones + zeros + sum + subtract + sttdev + randu + randn + det + device + divide + dot + eig + fft + get + get_device + inv + join + matmul + max + mean + median + min + multiply + prod + reorder + set_device + slice + sqrt + add + exp + log + ifft + reshape diff --git a/docs/functions/join.rst b/docs/functions/join.rst index 9f7d1fc..18906f7 100644 --- a/docs/functions/join.rst +++ b/docs/functions/join.rst @@ -18,10 +18,10 @@ Function Documentation .. sidebar:: af.join() Syntax: - af.join(dim, *arrays) + af.join(dim, \*arrays) Parameters: 'dim': The dimension along which the arrays will be concatenated. This is an integer indicating the axis along which the join operation will take place. - '*arrays': The arrays to be concatenated. These can be 1D, 2D, or higher-dimensional arrays, and they must be compatible in all dimensions except the specified dimension. + '\*arrays': The arrays to be concatenated. These can be 1D, 2D, or higher-dimensional arrays, and they must be compatible in all dimensions except the specified dimension. Returns: An ArrayFire array that is the result of concatenating the input arrays along the specified dimension. diff --git a/docs/functions/reorder.rst b/docs/functions/reorder.rst index 3f03e49..d51f9a8 100644 --- a/docs/functions/reorder.rst +++ b/docs/functions/reorder.rst @@ -16,11 +16,11 @@ Function Documentation .. sidebar:: af.reorder() Syntax: - af.reorder(array, *order) + af.reorder(array, \*order) Parameters: 'array': The ArrayFire array whose dimensions are to be reordered. - '*order': The new order of dimensions specified as a sequence of integers. Each integer represents the index of the dimension in the new order. + '\*order': The new order of dimensions specified as a sequence of integers. Each integer represents the index of the dimension in the new order. Returns: An ArrayFire array with the dimensions reordered according to the specified order. diff --git a/docs/functions/reshape.rst b/docs/functions/reshape.rst index 4f5a442..8f9ec78 100644 --- a/docs/functions/reshape.rst +++ b/docs/functions/reshape.rst @@ -16,10 +16,10 @@ Function Documentation .. sidebar:: af.reshape() Syntax: - af.reshape(array,*new_shape) + af.reshape(array,\*new_shape) Parameters: 'array': The ArrayFire array to be reshaped. - '*new_shape': The new shape for the array, specified as a sequence of integers. The product of these dimensions must equal the total number of elements in the original array. + '\*new_shape': The new shape for the array, specified as a sequence of integers. The product of these dimensions must equal the total number of elements in the original array. Returns: An ArrayFire array with the specified new shape. \ No newline at end of file diff --git a/docs/functions/slice.rst b/docs/functions/slice.rst index 9d4a5c8..3832e45 100644 --- a/docs/functions/slice.rst +++ b/docs/functions/slice.rst @@ -16,12 +16,12 @@ Function Documentation .. sidebar:: af.slice() Syntax: - af.slice(array, *start_indices, *end_indices) + af.slice(array, \*start_indices, \*end_indices) Parameters: 'array': The ArrayFire array from which the subarray will be extracted. - '*start_indices': A sequence of integers specifying the starting indices for each dimension. - '*end_indices': A sequence of integers specifying the ending indices for each dimension. + '\*start_indices': A sequence of integers specifying the starting indices for each dimension. + '\*end_indices': A sequence of integers specifying the ending indices for each dimension. Returns: An ArrayFire array containing the extracted subarray. diff --git a/docs/functions/transpose.rst b/docs/functions/transpose.rst index 747ecf2..5f41466 100644 --- a/docs/functions/transpose.rst +++ b/docs/functions/transpose.rst @@ -16,11 +16,11 @@ Function Documentation .. sidebar:: af.transpose() Syntax: - af.transpose(array, *permutation) + af.transpose(array, \*permutation) Parameters: 'array': The ArrayFire array to be transposed. - '*permutation': An optional sequence of integers specifying the new order of dimensions. If not provided, the function defaults to transposing the last two dimensions. + '\*permutation': An optional sequence of integers specifying the new order of dimensions. If not provided, the function defaults to transposing the last two dimensions. Returns: An ArrayFire array that is the transpose of the input array, with dimensions permuted according to the provided permutation. diff --git a/docs/functions/zeros.rst b/docs/functions/zeros.rst index a631c2c..90ead5f 100644 --- a/docs/functions/zeros.rst +++ b/docs/functions/zeros.rst @@ -6,6 +6,7 @@ Function -------- :literal:`af.zeros()` - Python interface to create array filled with zeros. + Detailed Description -------------------- The 'af.zeros()' function creates an ArrayFire array where every element is initialized to zero. It is particularly useful when you need to allocate space for an array but want to ensure that all values start from zero. This is often used in numerical methods, data processing, and initialization of variables in scientific computing. diff --git a/docs/gettingstarted.rst b/docs/gettingstarted.rst index 11bc104..69a2f70 100644 --- a/docs/gettingstarted.rst +++ b/docs/gettingstarted.rst @@ -24,6 +24,7 @@ ArrayFire provides one generic container object, the array on which functions an * u64 64-bit unsigned integer (:literal:`uintl`) * s16 16-bit signed integer (:literal:`short`) * u16 16-bit unsigned integer (:literal:`unsigned short`) + Most of these data types are supported on all modern GPUs; however, some older devices may lack support for double precision arrays. In this case, a runtime error will be generated when the array is constructed. If not specified otherwise, :literal:`array`s are created as single precision floating point numbers (:literal:`f32`). diff --git a/docs/index.rst b/docs/index.rst index 28e8767..ff4004b 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -3,11 +3,11 @@ You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. -Welcome to TestProject2's documentation! -======================================== +Welcome to ArrayFire's documentation! +===================================== .. toctree:: - :maxdepth: 2 + :maxdepth: 4 :caption: Contents: overview @@ -15,6 +15,17 @@ Welcome to TestProject2's documentation! functions releasenotes examples + arrayandmatrixmanipulation + arrayfirejitcodegeneration + configuringarrayfireenvironment + debuggingarrayfirecode + gettingstarted + indexing + installation + introductiontovectorization + linux + functions/index + Indices and tables ================== @@ -24,19 +35,6 @@ Indices and tables -.. automodule:: pkg.sub_pkg1 - :members: - :undoc-members: - :show-inheritance: - -.. automodule:: pkg.sub_pkg2 - :members: - :undoc-members: - :show-inheritance: - - - - diff --git a/docs/indexing.py b/docs/indexing.py index 52406b5..e5d2364 100644 --- a/docs/indexing.py +++ b/docs/indexing.py @@ -102,7 +102,7 @@ # [indexing11-endsnippet] -# [indexing11-snippet] +# [indexing12-snippet] hidx = [4, 3, 4, 0] hvals = [9.0, 8.0, 7.0, 6.0] diff --git a/docs/installation.rst b/docs/installation.rst index 0d6d17c..edd9cc5 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -13,6 +13,7 @@ Install Instructions * :ref:`macOs ` .. _Windows: + Windows ======= Once the ArrayFire has been downloaded, run the installer. @@ -23,6 +24,7 @@ For more information on using ArrayFire on Windows, visit the following page. .. _Linux: + Linux ===== @@ -44,6 +46,7 @@ Given sudo permissions, the ArrayFire libraries can be added to the path via :li echo /opt/arrayfire/lib64 > /etc/ld.so.conf.d/arrayfire.conf sudo ldconfig + Otherwise, the :literal:`LD_LIBRARY_PATH` environment variable can be set so that the shared library loader can find the ArrayFire libraries. For more information on using ArrayFire on Linux, visit the following page*. @@ -74,6 +77,7 @@ To install these dependencies on common Linux distributions: .. _macOS: + macOS ===== diff --git a/docs/introductiontovectorization.rst b/docs/introductiontovectorization.rst index 18b1853..dcf8455 100644 --- a/docs/introductiontovectorization.rst +++ b/docs/introductiontovectorization.rst @@ -25,7 +25,7 @@ Most ArrayFire functions are vectorized. A small subset of these include: +---------------------------------------+--------------------------------------------+ | Operator Category | Functions | +=======================================+============================================+ -| Arithmetic Operations | +, -, *, /, %, >, < | +| Arithmetic Operations | +, -, \*, /, %, >, < | +---------------------------------------+--------------------------------------------+ | Logical Operations | &&, ||(or), <, >, ==, != etc. | +---------------------------------------+--------------------------------------------+ diff --git a/docs/linux.rst b/docs/linux.rst index 050ecad..b9f86d6 100644 --- a/docs/linux.rst +++ b/docs/linux.rst @@ -4,6 +4,7 @@ Using ArrayFire on Linux Once you have :ref:`installed ` ArrayFire on your system, the next thing to do is set up your build system. On Linux, you can create ArrayFire projects using almost any editor, compiler, or build system. The only requirements are that you include the ArrayFire header directories and link with the ArrayFire library you intend to use i.e. CUDA, OpenCL, oneAPI, CPU, or Unified backends. .. _bigpicture: + The big picture =============== @@ -87,6 +88,7 @@ Next we need to instruct CMake to create build instructions and then compile. We cd build cmake .. make + NOTE: If you have installed ArrayFire to a non-standard location, CMake can still help you out. When you execute CMake specify the path to ArrayFire installation root as :literal:`ArrayFire_DIR` variable. For example, if ArrayFire were installed locally to :literal:`/home/user/ArrayFire` then you would modify the :literal:`cmake` command above to contain the following definition: @@ -94,6 +96,7 @@ For example, if ArrayFire were installed locally to :literal:`/home/user/ArrayFi .. code-block:: text cmake -DArrayFire_DIR=/home/user/ArrayFire .. + You can also specify this information in the :literal:`ccmake` command-line interface. diff --git a/docs/releasenotes.rst b/docs/releasenotes.rst index 1997d71..1dbe412 100644 --- a/docs/releasenotes.rst +++ b/docs/releasenotes.rst @@ -3,33 +3,7 @@ Release Notes -Introduction ------------- +TO DO +----- +Add Release Notes -This is the introductory section of File 1. - -Modules -------- - -Here is some content for the first section. - -Mod -~~~ - -This is a subsection under Section 1. - -Mod1 -~~~~ - -More content for the second section. - -Mod2 -~~~~ - -This concludes the content of File 1. - -Mod3 -~~~~ - -Mod4 -~~~~ From 4e0f3c6e3262aff2a18c1870772a9e380f42424e Mon Sep 17 00:00:00 2001 From: Edwin Solis Date: Thu, 14 Aug 2025 12:47:12 -0700 Subject: [PATCH 06/11] Added instructions to build docs with sphinx --- .gitignore | 2 -- docs/README.md | 17 +++++++++++++++++ docs/afjit.py | 14 ++++++++------ 3 files changed, 25 insertions(+), 8 deletions(-) create mode 100644 docs/README.md diff --git a/.gitignore b/.gitignore index f1a00b9..f5d0a35 100644 --- a/.gitignore +++ b/.gitignore @@ -40,8 +40,6 @@ coverage.xml .pytest_cache/ # documentation build artifacts - -docs/*.md docs/api site/ mkdocs.yml diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..d147f5e --- /dev/null +++ b/docs/README.md @@ -0,0 +1,17 @@ +Documentation +========== + +We use [`Sphinx`](https://www.sphinx-doc.org/en/master/index.html) for presenting our documentation. + +To build the docs follow these steps: + +1. Install the required sphinx packages and extensions from the [requirements.txt](../requirements.txt) +```sh +pip install -r requirements.txt # install sphinx and its extensions +``` +2. Build docs using sphinx +```sh +sphinx-build -M html docs/ output-docs/ # builds docs as html files stored in output-docs +``` +3. Explore the docs starting at `output-docs/index.html` + diff --git a/docs/afjit.py b/docs/afjit.py index 97f3163..cf49a9f 100644 --- a/docs/afjit.py +++ b/docs/afjit.py @@ -5,20 +5,22 @@ # removed, then the execution of this code would be equivalent to the # following function. -def pi_no_jit(x, y, temp, samples): +import arrayfire as af + +def pi_no_jit(x, y, samples): temp = x * x temp.eval() temp += y * y temp.eval() - temp = sqrt(temp) + temp = af.sqrt(temp) temp.eval() temp = temp < 1 temp.eval() - return 4.0 * sum(temp) / samples + return 4.0 * af.sum(temp) / samples -def pi_jit(x, y, temp, samples): - temp = sqrt(x * x + y * y) < 1 +def pi_jit(x, y, samples): + temp = af.sqrt(x * x + y * y) < 1 temp.eval() - return 4.0 * sum(temp) / samples + return 4.0 * af.sum(temp) / samples # [jit-endsnippet] \ No newline at end of file From e08e151a1128e66f8bb0849f0436f774b2180a81 Mon Sep 17 00:00:00 2001 From: Edwin Solis Date: Fri, 15 Aug 2025 12:14:12 -0700 Subject: [PATCH 07/11] Added descriptions to more functions and examples --- docs/README.md | 8 +++-- docs/configuringarrayfireenvironment.rst | 7 ++++- docs/examples.rst | 40 ++++++++++++++++++++++-- docs/functions.rst | 12 +++++++ docs/functions/constant.rst | 31 ++++++++++++++++++ docs/functions/gemm.rst | 31 ++++++++++++++++++ docs/functions/get_backend.rst | 25 +++++++++++++++ docs/functions/iota.rst | 28 +++++++++++++++++ docs/functions/range.rst | 29 +++++++++++++++++ docs/functions/set_backend.rst | 26 +++++++++++++++ docs/introductiontovectorization.rst | 2 +- docs/releasenotes.rst | 24 ++++++++++---- 12 files changed, 249 insertions(+), 14 deletions(-) create mode 100644 docs/functions/constant.rst create mode 100644 docs/functions/gemm.rst create mode 100644 docs/functions/get_backend.rst create mode 100644 docs/functions/iota.rst create mode 100644 docs/functions/range.rst create mode 100644 docs/functions/set_backend.rst diff --git a/docs/README.md b/docs/README.md index d147f5e..76f4f32 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,13 +1,15 @@ -Documentation +Documentation (WIP) ========== +**This documentation is a work in progress and may not contain all currently supported operations. Please check the functions signature and description for more info on it** + We use [`Sphinx`](https://www.sphinx-doc.org/en/master/index.html) for presenting our documentation. To build the docs follow these steps: -1. Install the required sphinx packages and extensions from the [requirements.txt](../requirements.txt) +1. Install the required sphinx packages and extensions from the [dev-requirements.txt](../dev-requirements.txt) ```sh -pip install -r requirements.txt # install sphinx and its extensions +pip install -r dev-requirements.txt # install sphinx and its extensions ``` 2. Build docs using sphinx ```sh diff --git a/docs/configuringarrayfireenvironment.rst b/docs/configuringarrayfireenvironment.rst index 00754e6..4f411b9 100644 --- a/docs/configuringarrayfireenvironment.rst +++ b/docs/configuringarrayfireenvironment.rst @@ -6,4 +6,9 @@ Environment Variables ===================== The following are useful environment variable that can be used with ArrayFire. - +* `AF_VERBOSE_LOADS` +* `AF_CUDA_DEFAULT_DEVICE` +* `AF_OPENCL_DEFAULT_DEVICE` +* `AF_ONEAPI_DEFAULT_DEVICE` +* `AF_TRACE` +* `AF_PRINT_ERRORS` diff --git a/docs/examples.rst b/docs/examples.rst index b78d09a..b4dc9c6 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -2,6 +2,40 @@ Examples ======== -TO DO ------ -ADD LIST OF EXAMPLES \ No newline at end of file +.. collapse:: Getting Started + + .. list-table:: + + * - :doc:`intro.py` + - Shows how to set a device, initialize arrays, and do some array operations + * - :doc:`convolve.py` + - Shows how to do convolutions on 2D images + +.. collapse:: Linear Algebra + + .. list-table:: + + * - :doc:`cholesky.py` + - Shows Cholesky decomposition in/out of place + * - :doc:`lu.py` + - Shows LU factorization in/out of place + * - :doc:`qr.py` + - Shows QR factorization in/out of place + +.. collapse:: Financial + + .. list-table:: + + * - :doc:`black_scholes_options.py` + - Recreates black scholes options model utilizing ArrayFire's random and vectorization operations + * - :doc:`heston_model.py` + - Recreates heston model simultation utilizing ArrayFire's random and vectorization operations + * - :doc:`monte_carlo_options.py` + - Simulates monte carlo options model utilizing ArrayFire's random and vectorization operations + +.. collapse:: Benchmarks + + .. list-table:: + + * - :doc:`monte_carlo_pi.py` + - Recreates a monte carlo method of calculating the digits of pi ArrayFire's random and vectorization operations \ No newline at end of file diff --git a/docs/functions.rst b/docs/functions.rst index 8fa82ee..b60197f 100644 --- a/docs/functions.rst +++ b/docs/functions.rst @@ -22,6 +22,12 @@ Documentation grouped by category: - Creates an array filled with zeros. * - :doc:`af.ones() ` - Creates an array filled with ones. + * - :doc:`af.constant() ` + - Creates an array filled with a scalar value. + * - :doc:`af.range() ` + - Creates an array filled with a range of linear indices along a dimension. + * - :doc:`af.iota() ` + - Creates an array filled with a range of linear indices along multiple dimensions * - :doc:`af.randu() ` - Creates an array with random uniform values. * - :doc:`af.randn() ` @@ -54,6 +60,8 @@ Documentation grouped by category: - Computes the square root of each element. * - :doc:`af.matmul() ` - Matrix multiplication. + * - :doc:`af.gemm() ` + - General matrix multiplication. * - :doc:`af.inv() ` - Computes the inverse of a matrix. * - :doc:`af.det() ` @@ -80,6 +88,10 @@ Documentation grouped by category: - Matrix multiplication. * - :doc:`af.set_device() ` - Gets the current device. + * - :doc:`af.set_backend() ` + - Sets the current backend. + * - :doc:`af.get_backend() ` + - Gets the current backend. * - :doc:`af.get() ` - Copies data from the GPU to the CPU. * - :doc:`af.min() ` diff --git a/docs/functions/constant.rst b/docs/functions/constant.rst new file mode 100644 index 0000000..69a293e --- /dev/null +++ b/docs/functions/constant.rst @@ -0,0 +1,31 @@ +constant +======== +The 'af.constant()' function in the ArrayFire library is used to create arrays filled with a specific scalar value. This is a common operation when initializing arrays that will be updated or manipulated later in numerical computations. The function allows you to specify the dimensions and data type of the array, making it flexible for various use cases. + +Function +-------- +:literal:`af.constant()` + - Python interface to create a multi-dimensional array filled with a constant value. + +Detailed Description +-------------------- +The 'af.constant()' function creates an ArrayFire array where every element is initialized to the scalar (integer, floating point, or complex) value specified. It is particularly useful when you need to allocate space for an array but want to ensure that all values start from zero. This is often used in numerical methods, data processing, and initialization of variables in scientific computing. + +You can specify the dimensions of the array as well as its data type. By default, the function creates arrays with a single precision floating-point type (float), but you can specify other data types if needed. + +Function Documentation +---------------------- +.. sidebar:: af.constant() + + Syntax: + af.constant(scalar, dims, dtype) + + Parameters: + 'scalar': value that will be used to initialize + 'dims': List of integers representing the dimensions of the array. You can specify multiple dimensions to create multi-dimensional arrays. For example, dim0 is the number of rows, and dim1 is the number of columns for a 2D array, etc. + 'dtype': type that will be used to store the value internally. For example, af.int64 for signed 64-bit integer, af.float32 for 32-bit floating-point, and af.float64 for 64-bit floating-point + + Returns: + An ArrayFire array with the specified dimensions and data type, where all elements are initialized to a scalar value. + + diff --git a/docs/functions/gemm.rst b/docs/functions/gemm.rst new file mode 100644 index 0000000..2906839 --- /dev/null +++ b/docs/functions/gemm.rst @@ -0,0 +1,31 @@ +gemm +====== +The 'af.matmul()' function in ArrayFire performs general matrix multiplication. General Matrix multiplication is a fundamental operation in linear algebra and is widely used in various neural networks, scientific and engineering computations. + +Function +-------- +:literal:`af.gemm()` + - Python interface used to perform general matrix multiplication + +Detailed Description +-------------------- +The af.gemm() function computes the general matrix product of various input arrays. General Matrix multiplication is defined for three matrices A, B, C and two scalars alpha and beta as the operation alpha * A * B + beta * C where the number of columns in A is equal to the number of rows in B, while C has the same number of columns as B and same number of rows as A. The result is that is a weighted average of the matrix multiplication between A and B, and the accumulator matrix C. + +Function Documentation +---------------------- +.. sidebar:: af.gemm() + + Syntax: + af.matmul(A, B, alpha=alpha, beta=beta, accum=C, lhs_opts=lhs_opts, rhs_opts=rhs_opts) + + Parameters: + 'A': The first input array (matrix) to be multiplied. + 'B': The second input array (matrix) to be multiplied. + 'alpha': scalar that will be multiplied with the matrix multiplication. If not specified, this is taken to be one and the output is the same as 'matmul' + 'beta': scalar that will be multiplied with the accumulator. If not specified, this is taken to be zero and the output is the same as 'matmul' + 'C': The accumulator input array that will be added to the matrix multiplication. If not specified, this behaves as array full of zeros and the output is the same as 'matmul' + 'lhs_opts': specifies any type of transpose operation should be executed on 'A' prior to the matrix multiplication + 'rhs_opts': specifies any type of transpose operation should be executed on 'B' prior to the matrix multiplication + + Returns: + An ArrayFire array representing the result of the general matrix multiplication: diff --git a/docs/functions/get_backend.rst b/docs/functions/get_backend.rst new file mode 100644 index 0000000..2608d13 --- /dev/null +++ b/docs/functions/get_backend.rst @@ -0,0 +1,25 @@ +get_backend +=========== +The 'af.get_backend()' function in ArrayFire is used to retrieve the BackendType object associated with the ArrayFire context. This function provides information about the current active backend. It is useful for managing and querying the status of a compute backend in a multi-device environment. + +Function +-------- +:literal:`af.get_backend()` + - Python interface used to retrieve the BackendType object associated with the ArrayFire context. + +Detailed Description +-------------------- +The 'af.get_backend()' function provides access to the BackendType object in ArrayFire. The possible return values are BackendType.cpu, BackendType.opencl, BackendType.cuda, BackendType.oneapi. This function is particularly useful in environments where multiple devices are available and you need to query or manage backend-specific information. + +Function Documentation +---------------------- +.. sidebar:: af.get_backend() + + Syntax: + device = af.get_backend() + + Parameters: + This function does not take any parameters. + + Returns: + An ArrayFire device object representing the current active backend in the ArrayFire context. diff --git a/docs/functions/iota.rst b/docs/functions/iota.rst new file mode 100644 index 0000000..3eb25eb --- /dev/null +++ b/docs/functions/iota.rst @@ -0,0 +1,28 @@ +iota +======= +The 'af.iota()' function in ArrayFire generates a multi-dimensional ArrayFire array with values populated based on their linear index within the array, optionally tiling the result to create larger arrays. + +Function +-------- +:literal:`af.iota()` + - Python interface used to generate linear indices with optional tiling + +Detailed Description +-------------------- +The 'af.iota()' function is used to generate array of a sequence of indices starting at 0 and ending at (exclusive) the size of the 'shape' dimensions specified, filling the array in column major ordering to the 'shape' specified that it is then duplicated as specified by the 'tile_shape'. + +Function Documentation +---------------------- +.. sidebar:: af.iota() + + Syntax: + af.iota(shape, tile_shape, dtype) + + Parameters: + 'shape': List of Integers specifying the dimensions for which the sequence of integers is generated. + 'tile_shape': List of integers specifying the number of times the indices should be tiled in each dimension. + 'dtype': type that will be used to store the value internally. For example, af.int64 for signed 64-bit integer, af.float32 for 32-bit floating-point, and af.float64 for 64-bit floating-point + + Returns: + An ArrayFire array of linear indices with the dimensions 'shape * tile_shape' + diff --git a/docs/functions/range.rst b/docs/functions/range.rst new file mode 100644 index 0000000..d2e9315 --- /dev/null +++ b/docs/functions/range.rst @@ -0,0 +1,29 @@ +range +======= +The 'af.range()' function in ArrayFire generates a multi-dimensional ArrayFire array of linear indices using the length of a dimension as a range, tiling the indices on the other dimensions. + +Function +-------- +:literal:`af.range()` + - Python interface used to generate a range in one dimension while tiling other dimensions + +Detailed Description +-------------------- +The 'af.range()' function is used to generate array of a sequence of indices starting at 0 and ending at (exclusive) the size of the length of the dimension specified, then it is duplicated on the remaining dimensions specified by 'shape'. + +Function Documentation +---------------------- +.. sidebar:: af.range() + + Syntax: + af.range(shape, tile_shape, dtype) + + Parameters: + 'shape': List of Integers specifying the dimensions for which the sequence of integers is generated. + 'axis': Integer from 0 to 3 (by default 0) specifying the dimension to use to generate the linear index range + 'dtype': type that will be used to store the value internally. For example, af.int64 for signed 64-bit integer, af.float32 for 32-bit floating-point, and af.float64 for 64-bit floating-point + + Returns: + An ArrayFire array of linear indices along 'axis' with the dimensions of 'shape' + + diff --git a/docs/functions/set_backend.rst b/docs/functions/set_backend.rst new file mode 100644 index 0000000..cfe3e49 --- /dev/null +++ b/docs/functions/set_backend.rst @@ -0,0 +1,26 @@ +set_backend +=========== +The 'af.set_backend()' function in ArrayFire is used to specify which backend will be used for subsequent ArrayFire operations. This is useful when working with multiple devices or GPUs to ensure that computations are directed to the desired hardware and software libraries. + +Function +-------- +:literal:`af.set_backend()` + - Python interface used to specify which backend will be used for subsequent arrayfire operations. + +Detailed Description +-------------------- +The 'af.set_backend()' function sets the backend for ArrayFire operations. By default, ArrayFire uses the first available backend in order of priority: 'cuda', 'opencl', 'oneapi', 'cpu' from highest to lowest priority. When you have multiple GPUs or devices, you can use this function to select which backend ArrayFire should use for subsequent operations. +Note that previous instantiated af.Array's or results from functions before the backend has been set will not be migrated to the new backend and device. + +Function Documentation +---------------------- +.. sidebar:: af.set_backend() + + Syntax: + af.set_backend(backend) + + Parameters: + 'backend': af.BackendType value that corresponds to the ArrayFire backend to be set. Available values are af.BackendType.cuda, af.BackendType.opencl, af.BackendType.oneapi, and af.BackendType.cpu + + Returns: + None diff --git a/docs/introductiontovectorization.rst b/docs/introductiontovectorization.rst index dcf8455..276a0d1 100644 --- a/docs/introductiontovectorization.rst +++ b/docs/introductiontovectorization.rst @@ -25,7 +25,7 @@ Most ArrayFire functions are vectorized. A small subset of these include: +---------------------------------------+--------------------------------------------+ | Operator Category | Functions | +=======================================+============================================+ -| Arithmetic Operations | +, -, \*, /, %, >, < | +| Arithmetic Operations | +, -, \*, /, %, >, < | +---------------------------------------+--------------------------------------------+ | Logical Operations | &&, ||(or), <, >, ==, != etc. | +---------------------------------------+--------------------------------------------+ diff --git a/docs/releasenotes.rst b/docs/releasenotes.rst index 1dbe412..d7c9f9b 100644 --- a/docs/releasenotes.rst +++ b/docs/releasenotes.rst @@ -1,9 +1,21 @@ Release Notes -============= +============== +v0.1.0 +====== +Welcome to the ArrayFire Python Bindings! These are the currently supported features: - -TO DO ------ -Add Release Notes - +- Support for all backends (cpu, opencl, oneapi, cuda) +- Computer Vision +- Functions to Create and Modify Arrays +- Functions to Work with Internal Array Layout +- Image Processing with Features +- Input and Output Functions +- Interface Functions +- Linear Algebra +- Machine Learning +- Mathematical Functions +- Signal Processing +- Statistics +- Unified API Functions +- Vector Algorithms \ No newline at end of file From 7b2fbdd00eaada01be25c155c8a8f984bb01f8a4 Mon Sep 17 00:00:00 2001 From: Edwin Date: Mon, 18 Aug 2025 17:22:54 -0700 Subject: [PATCH 08/11] Added sphinx docstring, documented more functions, restructured sidebar --- .gitignore | 1 + arrayfire/library/computer_vision.py | 4 +- docs/_static/custom.css | 5 + docs/arrayandmatrixmanipulation.rst | 18 +- docs/conf.py | 7 +- docs/configuringarrayfireenvironment.rst | 258 ++++++++++++++++++++++- docs/debuggingarrayfirecode.rst | 2 +- docs/examples.rst | 19 +- docs/functions.rst | 138 ++++++++---- docs/functions/ArrayFire.rst | 4 + docs/functions/accum.rst | 4 + docs/functions/all_true.rst | 4 + docs/functions/any_true.rst | 4 + docs/functions/array.rst | 3 + docs/functions/constant.rst | 29 +-- docs/functions/count.rst | 4 + docs/functions/diag.rst | 4 + docs/functions/diff1.rst | 4 + docs/functions/diff2.rst | 4 + docs/functions/dog.rst | 4 + docs/functions/dot.rst | 29 +-- docs/functions/fast.rst | 4 + docs/functions/gemm.rst | 29 +-- docs/functions/gloh.rst | 4 + docs/functions/gradient.rst | 4 + docs/functions/hamming_matcher.rst | 4 + docs/functions/harris.rst | 4 + docs/functions/identity.rst | 4 + docs/functions/imax.rst | 4 + docs/functions/imin.rst | 4 + docs/functions/index.rst | 86 ++++++-- docs/functions/iota.rst | 26 +-- docs/functions/isinf.rst | 4 + docs/functions/lower.rst | 4 + docs/functions/matmul.rst | 25 +-- docs/functions/mod.rst | 4 + docs/functions/nearest_neighbour.rst | 4 + docs/functions/orb.rst | 4 + docs/functions/pad.rst | 4 + docs/functions/prod.rst | 27 --- docs/functions/product.rst | 4 + docs/functions/range.rst | 27 +-- docs/functions/set_intersect.rst | 4 + docs/functions/set_union.rst | 4 + docs/functions/set_unique.rst | 4 + docs/functions/sift.rst | 4 + docs/functions/sort.rst | 4 + docs/functions/susan.rst | 4 + docs/functions/upper.rst | 4 + docs/gettingstarted.rst | 28 +-- docs/images/arrayfire_icon.png | Bin 0 -> 6757 bytes docs/images/arrayfire_logo.png | Bin 0 -> 62056 bytes docs/index.rst | 48 +++-- docs/indexing.rst | 12 +- docs/installation.rst | 10 +- docs/introductiontovectorization.rst | 9 +- docs/linux.rst | 6 +- docs/overview.rst | 27 ++- docs/releasenotes.rst | 2 +- docs/timing_arrayfire.rst | 62 ++++++ docs/tutorial.rst | 2 +- 61 files changed, 715 insertions(+), 348 deletions(-) create mode 100644 docs/functions/ArrayFire.rst create mode 100644 docs/functions/accum.rst create mode 100644 docs/functions/all_true.rst create mode 100644 docs/functions/any_true.rst create mode 100644 docs/functions/count.rst create mode 100644 docs/functions/diag.rst create mode 100644 docs/functions/diff1.rst create mode 100644 docs/functions/diff2.rst create mode 100644 docs/functions/dog.rst create mode 100644 docs/functions/fast.rst create mode 100644 docs/functions/gloh.rst create mode 100644 docs/functions/gradient.rst create mode 100644 docs/functions/hamming_matcher.rst create mode 100644 docs/functions/harris.rst create mode 100644 docs/functions/identity.rst create mode 100644 docs/functions/imax.rst create mode 100644 docs/functions/imin.rst create mode 100644 docs/functions/isinf.rst create mode 100644 docs/functions/lower.rst create mode 100644 docs/functions/mod.rst create mode 100644 docs/functions/nearest_neighbour.rst create mode 100644 docs/functions/orb.rst create mode 100644 docs/functions/pad.rst delete mode 100644 docs/functions/prod.rst create mode 100644 docs/functions/product.rst create mode 100644 docs/functions/set_intersect.rst create mode 100644 docs/functions/set_union.rst create mode 100644 docs/functions/set_unique.rst create mode 100644 docs/functions/sift.rst create mode 100644 docs/functions/sort.rst create mode 100644 docs/functions/susan.rst create mode 100644 docs/functions/upper.rst create mode 100644 docs/images/arrayfire_icon.png create mode 100644 docs/images/arrayfire_logo.png create mode 100644 docs/timing_arrayfire.rst diff --git a/.gitignore b/.gitignore index f5d0a35..8019809 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,4 @@ coverage.xml docs/api site/ mkdocs.yml +output-docs/ \ No newline at end of file diff --git a/arrayfire/library/computer_vision.py b/arrayfire/library/computer_vision.py index 95f25d4..6683c5b 100644 --- a/arrayfire/library/computer_vision.py +++ b/arrayfire/library/computer_vision.py @@ -53,7 +53,7 @@ def gloh( A tuple containing two elements: - `Features`: An object holding the detected features, including their locations and scales. - `Array`: An ArrayFire array containing the GLOH descriptors for the detected features, with each descriptor - having 272 elements. + having 272 elements. Note ---- @@ -165,7 +165,7 @@ def sift( A tuple containing: - An ArrayFire Features object encapsulating the detected keypoints. - An ArrayFire Array containing the corresponding descriptors for each keypoint. The descriptors are - 128-dimensional vectors describing the local appearance around each keypoint. + 128-dimensional vectors describing the local appearance around each keypoint. Note ---- diff --git a/docs/_static/custom.css b/docs/_static/custom.css index e56b184..0ba166f 100644 --- a/docs/_static/custom.css +++ b/docs/_static/custom.css @@ -6,3 +6,8 @@ a { a:hover { color: darkblue; /* Change link color to dark blue on hover */ } + +.responsive-img { + max-width: 100%; + height: auto; +} \ No newline at end of file diff --git a/docs/arrayandmatrixmanipulation.rst b/docs/arrayandmatrixmanipulation.rst index ef691e4..bf73261 100644 --- a/docs/arrayandmatrixmanipulation.rst +++ b/docs/arrayandmatrixmanipulation.rst @@ -17,7 +17,7 @@ ArrayFire provides several different methods for manipulating arrays and matrice Below we provide several examples of these functions and their use. flat() -====== +****** The **flat()** function flattens an array to one dimension: .. literalinclude:: arrayandmatrixmanipulation.py @@ -32,7 +32,7 @@ The **flat** function can be called from Python as follows: af.flat(array) - Python function for flattening an array flip() -====== +****** The **flip()** function flips the contents of an array along a chosen dimension. In the example below, we show the 5x2 array flipped along the zeroth (i.e. within a column) and first (e.g. across rows) axes: @@ -49,7 +49,7 @@ The **flip** function can be called from Python as follows: join() -====== +****** The **join()** function joins arrays along a specific dimension. The C++ interface can join up to four arrays whereas the C interface supports up to 10 arrays. Here is an example of how to use join an array to itself: @@ -66,7 +66,7 @@ The **join** function can be called from Python as follows: af.join(0, array, array1) - Python function for joining arrays along a specified axis moddims() -========= +********* The **moddims()** function changes the dimensions of an array without changing its data or order. Note that this function modifies only the metadata associated with the array. It does not modify the content of the array. Here is an example of moddims() converting an 8x1 array into a 2x4 and then back to a 8x1: @@ -83,7 +83,7 @@ The moddims function has a single form in the Python API: reorder() -========= +********* The **reorder()** function modifies the order of data within an array by exchanging data according to the change in dimensionality. The linear ordering of data within the array is preserved. .. literalinclude:: arrayandmatrixmanipulation.py @@ -92,7 +92,7 @@ The **reorder()** function modifies the order of data within an array by exchang :end-before: [manipulation5-endsnippet] shift() -======= +******* The **shift()** function shifts data in a circular buffer fashion along a chosen dimension. Consider the following example: @@ -107,7 +107,7 @@ The shift function can be called from Python as follows: af.shift(array, (3,2)) - Python function for shifting arrays along specified dimension tile() -====== +****** The **tile()** function repeats an array along the specified dimension. For example below we show how to tile an array along the zeroth and first dimensions of an array: .. literalinclude:: arrayandmatrixmanipulation.py @@ -121,7 +121,7 @@ The **tile()** function repeats an array along the specified dimension. For exam transpose() -=========== +*********** The **transpose()** function performs a standard matrix transpose. The input array must have the dimensions of a 2D-matrix. .. literalinclude:: arrayandmatrixmanipulation.py @@ -139,6 +139,6 @@ The python interface for transpose is as follows: array() -======= +******* **array()** can be used to create a (shallow) copy of a matrix with different dimensions. The total number of elements must remain the same. This function is a wrapper over the moddims() function discussed earlier. diff --git a/docs/conf.py b/docs/conf.py index 256a621..fbbf089 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -4,15 +4,13 @@ # https://www.sphinx-doc.org/en/master/usage/configuration.html import sys import os -sys.path.insert(0, os.path.abspath('../..')) - - +sys.path.insert(0, os.path.abspath('..')) # -- Project information ----------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information project = 'ArrayFire' -copyright = '2024, ArrayFire' +copyright = '2025, ArrayFire' author = 'ArrayFire' release = '' @@ -38,6 +36,7 @@ html_theme = 'sphinxawesome_theme' html_static_path = ['_static'] html_permalinks = False +html_logo = "_static/../images/arrayfire_icon.png" # -- Suppress specific warnings -------------------------------------------- diff --git a/docs/configuringarrayfireenvironment.rst b/docs/configuringarrayfireenvironment.rst index 4f411b9..da654a4 100644 --- a/docs/configuringarrayfireenvironment.rst +++ b/docs/configuringarrayfireenvironment.rst @@ -1,14 +1,254 @@ Configuring ArrayFire Environment ================================= This page lists environment and runtime configurations that will help enhance your experience with ArrayFire. - -Environment Variables -===================== The following are useful environment variable that can be used with ArrayFire. -* `AF_VERBOSE_LOADS` -* `AF_CUDA_DEFAULT_DEVICE` -* `AF_OPENCL_DEFAULT_DEVICE` -* `AF_ONEAPI_DEFAULT_DEVICE` -* `AF_TRACE` -* `AF_PRINT_ERRORS` +For Device Execution +#################### + +`AF_CUDA_DEFAULT_DEVICE` +************************ + +Use this variable to set the default CUDA device. Valid values for this +variable are the device identifiers shown when af::info is run. + +.. code-block:: bash + + AF_CUDA_DEFAULT_DEVICE=1 python myprogram_cuda.py + + +`AF_ONEAPI_DEFAULT_DEVICE` +*************************** + +Use this variable to set the default oneAPI device. Valid values for this +variable are the device identifiers shown when af::info is run. + +.. code-block:: bash + + AF_ONEAPI_DEFAULT_DEVICE=1 python myprogram_oneapi.py + + +Note: af::setDevice call in the source code will take precedence over this +variable. + +`AF_OPENCL_DEFAULT_DEVICE` +************************** + +Use this variable to set the default OpenCL device. Valid values for this +variable are the device identifiers shown when af::info is run. + +.. code-block:: bash + + AF_OPENCL_DEFAULT_DEVICE=1 python myprogram_opencl.py + + +Note: af::setDevice call in the source code will take precedence over this +variable. + +`AF_OPENCL_DEFAULT_DEVICE_TYPE` +******************************* + +Use this variable to set the default OpenCL device type. Valid values for this +variable are: CPU, GPU, ACC (Accelerators). + +When set, the first device of the specified type is chosen as default device. + +.. code-block:: bash + + AF_OPENCL_DEFAULT_DEVICE_TYPE=CPU python myprogram_opencl.py + + +Note: `AF_OPENCL_DEFAULT_DEVICE` and af::setDevice takes precedence over this variable. + +`AF_OPENCL_DEVICE_TYPE` +*********************** + +Use this variable to only choose OpenCL devices of specified type. Valid values for this +variable are: + +- ALL: All OpenCL devices. (Default behavior). +- CPU: CPU devices only. +- GPU: GPU devices only. +- ACC: Accelerator devices only. + +When set, the remaining OpenCL device types are ignored by the OpenCL backend. + +.. code-block:: bash + + AF_OPENCL_DEVICE_TYPE=CPU python myprogram_opencl.py + + +`AF_OPENCL_CPU_OFFLOAD` +************************ + +When ArrayFire runs on devices with unified memory with the host (ie. +`CL_DEVICE_HOST_UNIFIED_MENORY` is true for the device) then certain functions +are offloaded to run on the CPU using mapped buffers. + +ArrayFire takes advantage of fast libraries such as MKL while spending no time +copying memory from device to host. The device memory is mapped to a host +pointer which can be used in the offloaded functions. + +This functionality can be disabled by using the environment variable +`AF_OPENCL_CPU_OFFLOAD=0`. + +The default bevaior of this has changed in version 3.4. + +Prior to v3.4, CPU Offload functionality was used only when the user set +`AF_OPENCL_CPU_OFFLOAD=1` and disabled otherwise. + +From v3.4 onwards, CPU Offload is enabled by default and is disabled only when +`AF_OPENCL_CPU_OFFLOAD=0` is set. + +For Debugging +############# + +`AF_VERBOSE_LOADS` +******************* + +The arrayfire binary python wrapper (`arrayfire_wrapper` package) searches for default locations where +the arrayfire binaries may be located for loading. When set to 1, ArrayFire will print the locations +where the backend binaries are being searched and if loading the library at the location was successful. + +.. code-block:: bash + + AF_VERBOSE_LOADS=1 python myprogram.py + +`AF_PRINT_ERRORS` +****************** + +When AF_PRINT_ERRORS is set to 1, the exceptions thrown are more verbose and +detailed. This helps in locating the exact failure. + +.. code-block:: bash + + AF_PRINT_ERRORS=1 python myprogram.py + + +`AF_TRACE` +********** +This is a comma separated +list of modules to trace. If enabled, ArrayFire will print relevant information +to stdout. Currently the following modules are supported: + +- all: All trace outputs +- jit: Logs kernel fetch & respective compile options and any errors. +- mem: Memory management allocation, free and garbage collection information +- platform: Device management information +- unified: Unified backend dynamic loading information + +Tracing displays the information that could be useful when debugging or +optimizing your application. Here is how you would use this variable: + +.. code-block:: bash + + AF_TRACE=mem,unified python myprogram.py + +This will print information about memory operations such as allocations, +deallocations, and garbage collection. + +All trace statements printed to the console have a suffix with the following +pattern. + +**[category][Seconds since Epoch][Thread Id][source file relative path] \** + +`AF_OPENCL_SHOW_BUILD_INFO` +*************************** + +This variable is useful when debugging OpenCL kernel compilation failures. When +this variable is set to 1, and an error occurs during a OpenCL kernel +compilation, then the log and kernel are printed to screen. + +`AF_MEM_DEBUG` +************** + +When AF_MEM_DEBUG is set to 1 (or anything not equal to 0), the caching +mechanism in the memory manager is disabled. The device buffers are allocated +using native functions as needed and freed when going out of scope. + +When the environment variable is not set, it is treated to be zero. + +.. code-block:: + + AF_MEM_DEBUG=1 python myprogram.py + +`AF_MAX_BUFFERS` +***************** + +When AF_MAX_BUFFERS is set, this environment variable specifies the maximum +number of buffers allocated before garbage collection kicks in. + +Please note that the total number of buffers that can exist simultaneously can +be higher than this number. This variable tells the garbage collector that it +should free any available buffers immediately if the treshold is reached. + +When not set, the default value is 1000. + +`AF_OPENCL_MAX_JIT_LEN` +************************* + +When set, this environment variable specifies the maximum height of the OpenCL +JIT tree after which evaluation is forced. + +The default value, as of v3.4, is 50 on OSX, 100 everywhere else. This value was +20 for older versions. + +`AF_CUDA_MAX_JIT_LEN` +********************* + +When set, this environment variable specifies the maximum height of the CUDA JIT +tree after which evaluation is forced. + +The default value, as of v3.4, 100. This value was 20 for older versions. + +`AF_CPU_MAX_JIT_LEN` +******************** + +When set, this environment variable specifies the maximum length of the CPU JIT +tree after which evaluation is forced. + +The default value, as of v3.4, 100. This value was 20 for older versions. + +`AF_BUILD_LIB_CUSTOM_PATH` +************************** + +When set, this environment variable specifies a custom path along which the +symbol manager will search for dynamic (shared library) backends to load. This +is useful for specialized build configurations that use the unified backend and +build shared libraries separately. + +By default, no additional path will be searched for an empty value. + + +`AF_JIT_KERNEL_TRACE` +********************** + +When set, this environment variable has to be set to one of the following +three values: + +- stdout : generated kernels will be printed to standard output +- stderr : generated kernels will be printed to standard error stream +- absolute path to a folder on the disk where generated kernels will be stored + +CUDA backend kernels are stored in files with cu file extension. + +OpenCL backend kernels are stored in files with cl file extension. + +`AF_JIT_KERNEL_CACHE_DIRECTORY` +******************************* + +This variable sets the path to the ArrayFire cache on the filesystem. If set +ArrayFire will write the kernels that are compiled at runtime to this directory. +If the path is not writeable, the default path is used. + +This path is different from AF_JIT_KERNEL_TRACE which stores strings. These +kernels will store binaries and the content will be dependent on the +backend and platforms used. + +The default path is determined in the following order: + Unix: + 1. $HOME/.arrayfire + 2. /tmp/arrayfire + Windows: + 1. ArrayFire application Temp folder(Usually + C:\\Users\\\\\AppData\\Local\\Temp\\ArrayFire) \ No newline at end of file diff --git a/docs/debuggingarrayfirecode.rst b/docs/debuggingarrayfirecode.rst index cb36d03..800fdd6 100644 --- a/docs/debuggingarrayfirecode.rst +++ b/docs/debuggingarrayfirecode.rst @@ -5,5 +5,5 @@ Python * :literal:`arrayfire.device.print_mem_info("message")`: Print table of memory used by ArrayFire on the active GPU Further Reading -=============== +############### See the `ArrayFire README `_ for support information. \ No newline at end of file diff --git a/docs/examples.rst b/docs/examples.rst index b4dc9c6..cae41e7 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -1,41 +1,40 @@ Examples ======== - .. collapse:: Getting Started .. list-table:: - * - :doc:`intro.py` + * - :download:`intro.py <../examples/getting_started/intro.py>` - Shows how to set a device, initialize arrays, and do some array operations - * - :doc:`convolve.py` + * - :download:`convolve.py <../examples/getting_started/convolve.py>` - Shows how to do convolutions on 2D images .. collapse:: Linear Algebra .. list-table:: - * - :doc:`cholesky.py` + * - :download:`cholesky.py <../examples/linear_algebra/cholesky.py>` - Shows Cholesky decomposition in/out of place - * - :doc:`lu.py` + * - :download:`lu.py <../examples/linear_algebra/lu.py>` - Shows LU factorization in/out of place - * - :doc:`qr.py` + * - :download:`qr.py <../examples/linear_algebra/qr.py>` - Shows QR factorization in/out of place .. collapse:: Financial .. list-table:: - * - :doc:`black_scholes_options.py` + * - :download:`black_scholes_options.py <../examples/financial/black_scholes_options.py>` - Recreates black scholes options model utilizing ArrayFire's random and vectorization operations - * - :doc:`heston_model.py` + * - :download:`heston_model.py <../examples/financial/heston_model.py>` - Recreates heston model simultation utilizing ArrayFire's random and vectorization operations - * - :doc:`monte_carlo_options.py` + * - :download:`monte_carlo_options.py <../examples/financial/monte_carlo_options.py>` - Simulates monte carlo options model utilizing ArrayFire's random and vectorization operations .. collapse:: Benchmarks .. list-table:: - * - :doc:`monte_carlo_pi.py` + * - :download:`monte_carlo_pi.py <../examples/benchmarks/monte_carlo_pi.py>` - Recreates a monte carlo method of calculating the digits of pi ArrayFire's random and vectorization operations \ No newline at end of file diff --git a/docs/functions.rst b/docs/functions.rst index b60197f..7351f55 100644 --- a/docs/functions.rst +++ b/docs/functions.rst @@ -8,8 +8,8 @@ Documentation grouped by category: .. list-table:: - * - Class 1 - - Description of Class 1 + * - `af.Array` + - Represents an ArrayFire array .. collapse:: Arrayfire Functions @@ -24,24 +24,12 @@ Documentation grouped by category: - Creates an array filled with ones. * - :doc:`af.constant() ` - Creates an array filled with a scalar value. - * - :doc:`af.range() ` - - Creates an array filled with a range of linear indices along a dimension. * - :doc:`af.iota() ` - Creates an array filled with a range of linear indices along multiple dimensions - * - :doc:`af.randu() ` - - Creates an array with random uniform values. - * - :doc:`af.randn() ` - - Creates an array with random normal values. - * - :doc:`af.transpose() ` - - Transposes an array. - * - :doc:`af.reshape() ` - - Reshapes an array. - * - :doc:`af.reorder() ` - - Reorders dimensions of an array. - * - :doc:`af.slice() ` - - Extracts a slice of an array. - * - :doc:`af.join() ` - - Joins arrays along a specified dimension. + * - :doc:`af.range() ` + - Creates an array filled with a range of linear indices along a dimension. + * - :doc:`af.identity() ` + - Creates an identity matrix or batch of identity matrices. * - :doc:`af.add() ` - Performs element-wise addition. * - :doc:`af.subtract() ` @@ -50,38 +38,112 @@ Documentation grouped by category: - Performs element-wise multiplication. * - :doc:`af.divide() ` - Performs element-wise division. - * - :doc:`af.dot() ` - - Computes the dot product of two arrays. + * - :doc:`af.mod() ` + - Calculate the modulus of two arrays or a scalar and an array. + * - :doc:`af.sqrt() ` + - Computes the square root of each element. * - :doc:`af.exp() ` - Computes the exponential of each element. * - :doc:`af.log() ` - Computes the natural logarithm of each element. - * - :doc:`af.sqrt() ` - - Computes the square root of each element. + * - :doc:`af.accum() ` + - Calculate the cumulative sum of elements along a specified dimension. + * - :doc:`af.sum() ` + - Computes the sum of elements. + * - :doc:`af.product() ` + - Computes the product of elements. + * - :doc:`af.diff1() ` + - Computes the first-order differences of an ArrayFire array along a specified dimension. + * - :doc:`af.diff2() ` + - Computes the second-order differences of an ArrayFire array along a specified dimension. + * - :doc:`af.gradient() ` + - Computes the horizontal and vertical gradients of a 2D ArrayFire array or a batch of 2D arrays. + * - :doc:`af.mean() ` + - Computes the mean of elements. + * - :doc:`af.median() ` + - Computes the median value. + * - :doc:`af.stdev() ` + - Computes the standard deviation. + * - :doc:`af.min() ` + - Finds the minimum value. + * - :doc:`af.max() ` + - Finds the maximum value. + * - :doc:`af.imin() ` + - Finds the minimum value. + * - :doc:`af.imax() ` + - Finds the maximum value. + * - :doc:`af.all_true() ` + - Check if all the elements along a specified dimension are true. + * - :doc:`af.any_true() ` + - Check if any of the elements along a specified dimension are true. + * - :doc:`af.isinf() ` + - Returns a boolean array with entries as the boolean result from checking for infinity + * - :doc:`af.randu() ` + - Creates an array with random uniform values. + * - :doc:`af.randn() ` + - Creates an array with random normal values. + * - :doc:`af.inv() ` + - Computes the inverse of a matrix. + * - :doc:`af.dot() ` + - Computes the dot product of two arrays. * - :doc:`af.matmul() ` - Matrix multiplication. * - :doc:`af.gemm() ` - General matrix multiplication. - * - :doc:`af.inv() ` - - Computes the inverse of a matrix. - * - :doc:`af.det() ` - - Computes the determinant of a matrix. * - :doc:`af.eig() ` - Computes eigenvalues and eigenvectors. + * - :doc:`af.det() ` + - Computes the determinant of a matrix. * - :doc:`af.fft() ` - Computes the Fast Fourier Transform. * - :doc:`af.ifft() ` - Computes the Inverse Fast Fourier Transform. - * - :doc:`af.mean() ` - - Computes the mean of elements. - * - :doc:`af.stdev() ` - - Computes the standard deviation. - * - :doc:`af.median() ` - - Computes the median value. - * - :doc:`af.sum() ` - - Computes the sum of elements. - * - :doc:`af.prod() ` - - Computes the product of elements. + * - :doc:`af.count() ` + - Count the number of non-zero elements in an ArrayFire array along a specified dimension. + * - :doc:`af.sort() ` + - Sorts the elements of an ArrayFire array along a specified dimension. + * - :doc:`af.set_intersect() ` + - Calculates the intersection of two ArrayFire arrays, returning elements common to both arrays. + * - :doc:`af.set_union() ` + - Computes the union of two 1D ArrayFire arrays, effectively combining the elements from both arrays and removing duplicates. + * - :doc:`af.set_unique() ` + - Extracts unique elements from a 1D ArrayFire array. + * - :doc:`af.pad() ` + - Pads an ArrayFire array with specified sizes of padding around its edges and fills the padding with a specified value. + * - :doc:`af.orb() ` + - Extracts ORB features and their descriptors from an image. + * - :doc:`af.sift() ` + - Extracts SIFT features and their descriptors from an image using the ArrayFire library. + * - :doc:`af.fast() ` + - Detects corners and interest points in an image using the Features from Accelerated Segment Test algorithm. + * - :doc:`af.dog() ` + - Performs the Difference of Gaussians (DoG) operation on an image. + * - :doc:`af.gloh() ` + - Implements the GLOH (Gradient Location and Orientation Histogram) feature detection and descriptor extraction for images. + * - :doc:`af.harris() ` + - Detects corners in an image using the Harris corner detection algorithm. + * - :doc:`af.susan() ` + - Detects corners and edges in an image using the SUSAN corner detection algorithm. + * - :doc:`af.hamming_matcher() ` + - Finds the nearest neighbors for each descriptor in a query set from a training set, based on the Hamming distance. + * - :doc:`af.nearest_neighbour() ` + - Finds the nearest neighbors for each descriptor in a query set from a training set based on a specified metric. + * - :doc:`af.upper() ` + - Extract the upper triangular part of a given multi-dimensional ArrayFire array. + * - :doc:`af.lower() ` + - Extract the lower triangular part of a given multi-dimensional ArrayFire array. + * - :doc:`af.diag() ` + - Extract a diagonal from or create a diagonal matrix based on an input array. + * - :doc:`af.transpose() ` + - Transposes an array. + * - :doc:`af.join() ` + - Joins arrays along a specified dimension. + * - :doc:`af.reorder() ` + - Reorders dimensions of an array. + * - :doc:`af.slice() ` + - Extracts a slice of an array. + * - :doc:`af.reshape() ` + - Reshapes an array. * - :doc:`af.device() ` - Returns the device identifier. * - :doc:`af.get_device() ` @@ -94,10 +156,6 @@ Documentation grouped by category: - Gets the current backend. * - :doc:`af.get() ` - Copies data from the GPU to the CPU. - * - :doc:`af.min() ` - - Finds the minimum value. - * - :doc:`af.max() ` - - Finds the maximum value. .. collapse:: Arrayfire Functions by Category diff --git a/docs/functions/ArrayFire.rst b/docs/functions/ArrayFire.rst new file mode 100644 index 0000000..cb959a9 --- /dev/null +++ b/docs/functions/ArrayFire.rst @@ -0,0 +1,4 @@ +ArrayFire Package +================= + +.. automodule:: arrayfire \ No newline at end of file diff --git a/docs/functions/accum.rst b/docs/functions/accum.rst new file mode 100644 index 0000000..b2d634a --- /dev/null +++ b/docs/functions/accum.rst @@ -0,0 +1,4 @@ +accum +===== + +.. autofunction:: arrayfire.accum \ No newline at end of file diff --git a/docs/functions/all_true.rst b/docs/functions/all_true.rst new file mode 100644 index 0000000..1006674 --- /dev/null +++ b/docs/functions/all_true.rst @@ -0,0 +1,4 @@ +all_true +======== + +.. autofunction:: arrayfire.all_true \ No newline at end of file diff --git a/docs/functions/any_true.rst b/docs/functions/any_true.rst new file mode 100644 index 0000000..8341323 --- /dev/null +++ b/docs/functions/any_true.rst @@ -0,0 +1,4 @@ +any_true +======== + +.. autofunction:: arrayfire.any_true \ No newline at end of file diff --git a/docs/functions/array.rst b/docs/functions/array.rst index 9605817..ef34cb3 100644 --- a/docs/functions/array.rst +++ b/docs/functions/array.rst @@ -1,5 +1,8 @@ array ===== + +.. autoclass:: arrayfire.Array + The 'af.array()' function is part of the ArrayFire library, which provides a powerful framework for performing high-performance numerical computations. This function is designed to create an ArrayFire array from various data structures, such as Python lists or other iterable collections. Function diff --git a/docs/functions/constant.rst b/docs/functions/constant.rst index 69a293e..180c6fb 100644 --- a/docs/functions/constant.rst +++ b/docs/functions/constant.rst @@ -1,31 +1,4 @@ constant ======== -The 'af.constant()' function in the ArrayFire library is used to create arrays filled with a specific scalar value. This is a common operation when initializing arrays that will be updated or manipulated later in numerical computations. The function allows you to specify the dimensions and data type of the array, making it flexible for various use cases. - -Function --------- -:literal:`af.constant()` - - Python interface to create a multi-dimensional array filled with a constant value. - -Detailed Description --------------------- -The 'af.constant()' function creates an ArrayFire array where every element is initialized to the scalar (integer, floating point, or complex) value specified. It is particularly useful when you need to allocate space for an array but want to ensure that all values start from zero. This is often used in numerical methods, data processing, and initialization of variables in scientific computing. - -You can specify the dimensions of the array as well as its data type. By default, the function creates arrays with a single precision floating-point type (float), but you can specify other data types if needed. - -Function Documentation ----------------------- -.. sidebar:: af.constant() - - Syntax: - af.constant(scalar, dims, dtype) - - Parameters: - 'scalar': value that will be used to initialize - 'dims': List of integers representing the dimensions of the array. You can specify multiple dimensions to create multi-dimensional arrays. For example, dim0 is the number of rows, and dim1 is the number of columns for a 2D array, etc. - 'dtype': type that will be used to store the value internally. For example, af.int64 for signed 64-bit integer, af.float32 for 32-bit floating-point, and af.float64 for 64-bit floating-point - - Returns: - An ArrayFire array with the specified dimensions and data type, where all elements are initialized to a scalar value. - +.. autofunction:: arrayfire.constant \ No newline at end of file diff --git a/docs/functions/count.rst b/docs/functions/count.rst new file mode 100644 index 0000000..1ec2cde --- /dev/null +++ b/docs/functions/count.rst @@ -0,0 +1,4 @@ +count +===== + +.. autofunction:: arrayfire.count \ No newline at end of file diff --git a/docs/functions/diag.rst b/docs/functions/diag.rst new file mode 100644 index 0000000..3958e84 --- /dev/null +++ b/docs/functions/diag.rst @@ -0,0 +1,4 @@ +diag +==== + +.. autofunction:: arrayfire.diag \ No newline at end of file diff --git a/docs/functions/diff1.rst b/docs/functions/diff1.rst new file mode 100644 index 0000000..862f2cc --- /dev/null +++ b/docs/functions/diff1.rst @@ -0,0 +1,4 @@ +diff1 +===== + +.. autofunction:: arrayfire.diff1 \ No newline at end of file diff --git a/docs/functions/diff2.rst b/docs/functions/diff2.rst new file mode 100644 index 0000000..723e367 --- /dev/null +++ b/docs/functions/diff2.rst @@ -0,0 +1,4 @@ +diff2 +===== + +.. autofunction:: arrayfire.diff2 \ No newline at end of file diff --git a/docs/functions/dog.rst b/docs/functions/dog.rst new file mode 100644 index 0000000..dfe52e0 --- /dev/null +++ b/docs/functions/dog.rst @@ -0,0 +1,4 @@ +dog +=== + +.. autofunction:: arrayfire.dog \ No newline at end of file diff --git a/docs/functions/dot.rst b/docs/functions/dot.rst index c776872..5717259 100644 --- a/docs/functions/dot.rst +++ b/docs/functions/dot.rst @@ -1,31 +1,4 @@ dot === -The 'af.dot()' function in ArrayFire computes the dot product of two arrays. This function is used for calculating the scalar product of two vectors or the matrix multiplication when applied to matrices. It is a fundamental operation in linear algebra with applications in various fields such as machine learning, physics, and numerical computing. -Function --------- -:literal:`af.dot()` - - Python interface to compute dot product of two arrays. - -Detailed Description --------------------- -The af.dot() function computes the dot product, which can refer to different operations depending on the type of input: - -**Dot Product of Two Vectors:** For 1D arrays (vectors), the function calculates the scalar product. This is the sum of the products of corresponding elements of the vectors. - -**Matrix Multiplication:** For 2D arrays (matrices), it performs matrix multiplication, which is also referred to as the dot product in this context. - -Function Documentation ----------------------- -.. sidebar:: af.dot() - - Syntax: - af.dot(array1, array2) - - Parameters: - 'array1': The first ArrayFire array (vector or matrix) in the dot product operation. - 'array2': The second ArrayFire array (vector or matrix) in the dot product operation. Must be compatible with 'array1' for dot product or matrix multiplication. - - Returns: - - For vectors: A scalar value representing the dot product of the vectors. - - For matrices: An ArrayFire array representing the result of matrix multiplication. \ No newline at end of file +.. autofunction:: arrayfire.dot \ No newline at end of file diff --git a/docs/functions/fast.rst b/docs/functions/fast.rst new file mode 100644 index 0000000..f0b1bb2 --- /dev/null +++ b/docs/functions/fast.rst @@ -0,0 +1,4 @@ +fast +==== + +.. autofunction:: arrayfire.fast \ No newline at end of file diff --git a/docs/functions/gemm.rst b/docs/functions/gemm.rst index 2906839..0e53480 100644 --- a/docs/functions/gemm.rst +++ b/docs/functions/gemm.rst @@ -1,31 +1,4 @@ gemm ====== -The 'af.matmul()' function in ArrayFire performs general matrix multiplication. General Matrix multiplication is a fundamental operation in linear algebra and is widely used in various neural networks, scientific and engineering computations. -Function --------- -:literal:`af.gemm()` - - Python interface used to perform general matrix multiplication - -Detailed Description --------------------- -The af.gemm() function computes the general matrix product of various input arrays. General Matrix multiplication is defined for three matrices A, B, C and two scalars alpha and beta as the operation alpha * A * B + beta * C where the number of columns in A is equal to the number of rows in B, while C has the same number of columns as B and same number of rows as A. The result is that is a weighted average of the matrix multiplication between A and B, and the accumulator matrix C. - -Function Documentation ----------------------- -.. sidebar:: af.gemm() - - Syntax: - af.matmul(A, B, alpha=alpha, beta=beta, accum=C, lhs_opts=lhs_opts, rhs_opts=rhs_opts) - - Parameters: - 'A': The first input array (matrix) to be multiplied. - 'B': The second input array (matrix) to be multiplied. - 'alpha': scalar that will be multiplied with the matrix multiplication. If not specified, this is taken to be one and the output is the same as 'matmul' - 'beta': scalar that will be multiplied with the accumulator. If not specified, this is taken to be zero and the output is the same as 'matmul' - 'C': The accumulator input array that will be added to the matrix multiplication. If not specified, this behaves as array full of zeros and the output is the same as 'matmul' - 'lhs_opts': specifies any type of transpose operation should be executed on 'A' prior to the matrix multiplication - 'rhs_opts': specifies any type of transpose operation should be executed on 'B' prior to the matrix multiplication - - Returns: - An ArrayFire array representing the result of the general matrix multiplication: +.. autofunction:: arrayfire.gemm \ No newline at end of file diff --git a/docs/functions/gloh.rst b/docs/functions/gloh.rst new file mode 100644 index 0000000..a0c4009 --- /dev/null +++ b/docs/functions/gloh.rst @@ -0,0 +1,4 @@ +gloh +==== + +.. autofunction:: arrayfire.gloh \ No newline at end of file diff --git a/docs/functions/gradient.rst b/docs/functions/gradient.rst new file mode 100644 index 0000000..22ffaed --- /dev/null +++ b/docs/functions/gradient.rst @@ -0,0 +1,4 @@ +gradient +======== + +.. autofunction:: arrayfire.gradient \ No newline at end of file diff --git a/docs/functions/hamming_matcher.rst b/docs/functions/hamming_matcher.rst new file mode 100644 index 0000000..a4b5747 --- /dev/null +++ b/docs/functions/hamming_matcher.rst @@ -0,0 +1,4 @@ +hamming_matcher +=============== + +.. autofunction:: arrayfire.hamming_matcher \ No newline at end of file diff --git a/docs/functions/harris.rst b/docs/functions/harris.rst new file mode 100644 index 0000000..32e5ef6 --- /dev/null +++ b/docs/functions/harris.rst @@ -0,0 +1,4 @@ +harris +====== + +.. autofunction:: arrayfire.harris \ No newline at end of file diff --git a/docs/functions/identity.rst b/docs/functions/identity.rst new file mode 100644 index 0000000..e297bb6 --- /dev/null +++ b/docs/functions/identity.rst @@ -0,0 +1,4 @@ +identity +========= + +.. autofunction:: arrayfire.identity \ No newline at end of file diff --git a/docs/functions/imax.rst b/docs/functions/imax.rst new file mode 100644 index 0000000..c84a23a --- /dev/null +++ b/docs/functions/imax.rst @@ -0,0 +1,4 @@ +imax +===== + +.. autofunction:: arrayfire.imax \ No newline at end of file diff --git a/docs/functions/imin.rst b/docs/functions/imin.rst new file mode 100644 index 0000000..642af25 --- /dev/null +++ b/docs/functions/imin.rst @@ -0,0 +1,4 @@ +imin +==== + +.. autofunction:: arrayfire.imin \ No newline at end of file diff --git a/docs/functions/index.rst b/docs/functions/index.rst index 03a66e4..f1a20f5 100644 --- a/docs/functions/index.rst +++ b/docs/functions/index.rst @@ -1,39 +1,79 @@ +Function List +============== + .. toctree:: - :maxdepth: 2 - :caption: Functions: + :hidden: + :maxdepth: 1 + :caption: Function List: - transpose + ArrayFire array ones zeros - sum + constant + iota + range + identity + add + multiply subtract + divide + mod + sqrt + exp + log + accum + sum + product + diff1 + diff2 + gradient + mean + median sttdev + min + max + imin + imax + all_true + any_true + isinf randu randn - det - device - divide + inv dot + matmul + gemm eig + det fft - get - get_device - inv + ifft + count + sort + set_intersect + set_union + set_unique + pad + orb + sift + fast + dog + gloh + harris + susan + hamming_matcher + nearest_neighbour + upper + lower + diag + transpose join - matmul - max - mean - median - min - multiply - prod reorder - set_device slice - sqrt - add - exp - log - ifft reshape + device + set_device + set_backend + get_device + get_backend + get diff --git a/docs/functions/iota.rst b/docs/functions/iota.rst index 3eb25eb..fc11731 100644 --- a/docs/functions/iota.rst +++ b/docs/functions/iota.rst @@ -1,28 +1,4 @@ iota ======= -The 'af.iota()' function in ArrayFire generates a multi-dimensional ArrayFire array with values populated based on their linear index within the array, optionally tiling the result to create larger arrays. - -Function --------- -:literal:`af.iota()` - - Python interface used to generate linear indices with optional tiling - -Detailed Description --------------------- -The 'af.iota()' function is used to generate array of a sequence of indices starting at 0 and ending at (exclusive) the size of the 'shape' dimensions specified, filling the array in column major ordering to the 'shape' specified that it is then duplicated as specified by the 'tile_shape'. - -Function Documentation ----------------------- -.. sidebar:: af.iota() - - Syntax: - af.iota(shape, tile_shape, dtype) - - Parameters: - 'shape': List of Integers specifying the dimensions for which the sequence of integers is generated. - 'tile_shape': List of integers specifying the number of times the indices should be tiled in each dimension. - 'dtype': type that will be used to store the value internally. For example, af.int64 for signed 64-bit integer, af.float32 for 32-bit floating-point, and af.float64 for 64-bit floating-point - - Returns: - An ArrayFire array of linear indices with the dimensions 'shape * tile_shape' +.. autofunction:: arrayfire.iota \ No newline at end of file diff --git a/docs/functions/isinf.rst b/docs/functions/isinf.rst new file mode 100644 index 0000000..a6dc653 --- /dev/null +++ b/docs/functions/isinf.rst @@ -0,0 +1,4 @@ +isinf +===== + +.. autofunction:: arrayfire.isinf \ No newline at end of file diff --git a/docs/functions/lower.rst b/docs/functions/lower.rst new file mode 100644 index 0000000..2250b9d --- /dev/null +++ b/docs/functions/lower.rst @@ -0,0 +1,4 @@ +lower +====== + +.. autofunction:: arrayfire.lower \ No newline at end of file diff --git a/docs/functions/matmul.rst b/docs/functions/matmul.rst index e36f41b..40329d3 100644 --- a/docs/functions/matmul.rst +++ b/docs/functions/matmul.rst @@ -1,27 +1,4 @@ matmul ====== -The 'af.matmul()' function in ArrayFire performs matrix multiplication between two arrays. Matrix multiplication is a fundamental operation in linear algebra and is widely used in various scientific and engineering computations. -Function --------- -:literal:`af.matmul()` - - Python interface used to perform matrix multiplication between two arrays. - -Detailed Description --------------------- -The af.matmul() function computes the matrix product of two input arrays. Matrix multiplication is defined for two matrices 𝐴 and 𝐵 where the number of columns in 𝐴 is equal to the number of rows in 𝐵. The result is a matrix where each element is computed as the dot product of rows of -𝐴 with columns of 𝐵. - -Function Documentation ----------------------- -.. sidebar:: af.matmul() - - Syntax: - af.matmul(A, B) - - Parameters: - 'A': The first input array (matrix) to be multiplied. - 'B': The second input array (matrix) to be multiplied. - - Returns: - An ArrayFire array representing the result of the matrix multiplication. +.. autofunction:: arrayfire.matmul \ No newline at end of file diff --git a/docs/functions/mod.rst b/docs/functions/mod.rst new file mode 100644 index 0000000..85f8148 --- /dev/null +++ b/docs/functions/mod.rst @@ -0,0 +1,4 @@ +mod +=== + +.. autofunction:: arrayfire.mod \ No newline at end of file diff --git a/docs/functions/nearest_neighbour.rst b/docs/functions/nearest_neighbour.rst new file mode 100644 index 0000000..a617e53 --- /dev/null +++ b/docs/functions/nearest_neighbour.rst @@ -0,0 +1,4 @@ +nearest_neighbour +================= + +.. autofunction:: arrayfire.nearest_neighbour \ No newline at end of file diff --git a/docs/functions/orb.rst b/docs/functions/orb.rst new file mode 100644 index 0000000..4b671bc --- /dev/null +++ b/docs/functions/orb.rst @@ -0,0 +1,4 @@ +orb +=== + +.. autofunction:: arrayfire.orb \ No newline at end of file diff --git a/docs/functions/pad.rst b/docs/functions/pad.rst new file mode 100644 index 0000000..b89fe9c --- /dev/null +++ b/docs/functions/pad.rst @@ -0,0 +1,4 @@ +pad +=== + +.. autofunction:: arrayfire.pad \ No newline at end of file diff --git a/docs/functions/prod.rst b/docs/functions/prod.rst deleted file mode 100644 index 6922383..0000000 --- a/docs/functions/prod.rst +++ /dev/null @@ -1,27 +0,0 @@ -prod -==== -The 'af.prod()' function in ArrayFire computes the product of elements in an array or along a specified dimension. It aggregates elements by multiplying them together, which is useful in various mathematical and data processing applications. - -Function --------- -:literal:`af.prod()` - - Python interface used to compute the product of elements in an array or along a specified dimension - -Detailed Description --------------------- -The 'af.prod()' function calculates the product of all elements in the input array or along a specified dimension. If no dimension is specified, it computes the product of all elements in the array. This function can also handle multi-dimensional arrays, where you can specify the dimension along which to compute the product. - -Function Documentation ----------------------- -.. sidebar:: af.prod() - - Syntax: - af.prod(array) - - - Parameters: - 'array': The ArrayFire array for which the product is to be computed. - - Returns: - An ArrayFire array containing the product of elements. If axis is specified, the result will have the specified dimension reduced. - diff --git a/docs/functions/product.rst b/docs/functions/product.rst new file mode 100644 index 0000000..99a4efe --- /dev/null +++ b/docs/functions/product.rst @@ -0,0 +1,4 @@ +product +======= + +.. autofunction:: arrayfire.product \ No newline at end of file diff --git a/docs/functions/range.rst b/docs/functions/range.rst index d2e9315..57448e0 100644 --- a/docs/functions/range.rst +++ b/docs/functions/range.rst @@ -1,29 +1,4 @@ range ======= -The 'af.range()' function in ArrayFire generates a multi-dimensional ArrayFire array of linear indices using the length of a dimension as a range, tiling the indices on the other dimensions. - -Function --------- -:literal:`af.range()` - - Python interface used to generate a range in one dimension while tiling other dimensions - -Detailed Description --------------------- -The 'af.range()' function is used to generate array of a sequence of indices starting at 0 and ending at (exclusive) the size of the length of the dimension specified, then it is duplicated on the remaining dimensions specified by 'shape'. - -Function Documentation ----------------------- -.. sidebar:: af.range() - - Syntax: - af.range(shape, tile_shape, dtype) - - Parameters: - 'shape': List of Integers specifying the dimensions for which the sequence of integers is generated. - 'axis': Integer from 0 to 3 (by default 0) specifying the dimension to use to generate the linear index range - 'dtype': type that will be used to store the value internally. For example, af.int64 for signed 64-bit integer, af.float32 for 32-bit floating-point, and af.float64 for 64-bit floating-point - - Returns: - An ArrayFire array of linear indices along 'axis' with the dimensions of 'shape' - +.. autofunction:: arrayfire.range \ No newline at end of file diff --git a/docs/functions/set_intersect.rst b/docs/functions/set_intersect.rst new file mode 100644 index 0000000..da03b64 --- /dev/null +++ b/docs/functions/set_intersect.rst @@ -0,0 +1,4 @@ +set_intersect +============== + +.. autofunction:: arrayfire.set_intersect \ No newline at end of file diff --git a/docs/functions/set_union.rst b/docs/functions/set_union.rst new file mode 100644 index 0000000..21fc129 --- /dev/null +++ b/docs/functions/set_union.rst @@ -0,0 +1,4 @@ +set_union +========= + +.. autofunction:: arrayfire.set_union \ No newline at end of file diff --git a/docs/functions/set_unique.rst b/docs/functions/set_unique.rst new file mode 100644 index 0000000..d1b72e6 --- /dev/null +++ b/docs/functions/set_unique.rst @@ -0,0 +1,4 @@ +set_unique +========== + +.. autofunction:: arrayfire.set_unique \ No newline at end of file diff --git a/docs/functions/sift.rst b/docs/functions/sift.rst new file mode 100644 index 0000000..9f6ab86 --- /dev/null +++ b/docs/functions/sift.rst @@ -0,0 +1,4 @@ +sift +==== + +.. autofunction:: arrayfire.sift \ No newline at end of file diff --git a/docs/functions/sort.rst b/docs/functions/sort.rst new file mode 100644 index 0000000..3860c0b --- /dev/null +++ b/docs/functions/sort.rst @@ -0,0 +1,4 @@ +sort +===== + +.. autofunction:: arrayfire.sort \ No newline at end of file diff --git a/docs/functions/susan.rst b/docs/functions/susan.rst new file mode 100644 index 0000000..f1b5303 --- /dev/null +++ b/docs/functions/susan.rst @@ -0,0 +1,4 @@ +susan +===== + +.. autofunction:: arrayfire.susan \ No newline at end of file diff --git a/docs/functions/upper.rst b/docs/functions/upper.rst new file mode 100644 index 0000000..7e8ebc3 --- /dev/null +++ b/docs/functions/upper.rst @@ -0,0 +1,4 @@ +upper +===== + +.. autofunction:: arrayfire.upper \ No newline at end of file diff --git a/docs/gettingstarted.rst b/docs/gettingstarted.rst index 69a2f70..a180b49 100644 --- a/docs/gettingstarted.rst +++ b/docs/gettingstarted.rst @@ -1,13 +1,13 @@ Getting Started -======================== +=============== Introduction -============ +************ ArrayFire is a high performance software library for parallel computing with an easy-to-use API. ArrayFire abstracts away much of the details of programming parallel architectures by providing a high-level container object, the array, that represents data stored on a CPU, GPU, FPGA, or other type of accelerator. This abstraction permits developers to write massively parallel applications in a high-level language where they need not be concerned about low-level optimizations that are frequently required to achieve high throughput on most parallel architectures. Supported data types -==================== +******************** ArrayFire provides one generic container object, the array on which functions and mathematical operations are performed. The :literal:`array` can represent one of many different basic data types: @@ -30,7 +30,7 @@ Most of these data types are supported on all modern GPUs; however, some older d If not specified otherwise, :literal:`array`s are created as single precision floating point numbers (:literal:`f32`). Creating and populating an ArrayFire array -========================================== +****************************************** ArrayFire arrays represent memory stored on the device. As such, creation and population of an array will consume memory on the device which cannot freed until the :literal:`array` object goes out of scope. As device memory allocation can be expensive, ArrayFire also includes a memory manager which will re-use device memory whenever possible. @@ -70,7 +70,7 @@ ArrayFire also supports array initialization from memory already on the GPU. For Similar functionality exists for OpenCL too. If you wish to intermingle ArrayFire with CUDA or OpenCL code, we suggest you consult the CUDA interoperability or OpenCL interoperability pages for detailed instructions. ArrayFire array contents, dimensions, and properties -==================================================== +**************************************************** ArrayFire provides several functions to determine various aspects of arrays. This includes functions to print the contents, query the dimensions, and determine various other aspects of arrays. @@ -102,13 +102,13 @@ For further information on these capabilities, we suggest you consult the full d Writing mathematical expressions in ArrayFire -============================================= +********************************************* ArrayFire leverages an advanced Just-In-Time (JIT) compilation engine that optimizes array operations by minimizing the number of CUDA/OpenCL kernels used. In Python, ArrayFire functions operate similarly to a vector library. This means that typical element-wise operations, such as :literal:`c[i] = a[i] + b[i]` in C, can be expressed more succinctly as :literal:`c = a + b`, eliminating the need for explicit indexing. When multiple array operations are involved, ArrayFire's JIT engine consolidates them through "kernel fusion". This technique not only reduces the frequency of kernel invocations but also optimizes memory usage by eliminating redundant global memory operations. The JIT functionality extends seamlessly across Python function boundaries, continuing until a non-JIT function is encountered or a synchronization operation is explicitly invoked in the code. -ArrayFire provides a broad spectrum of functions tailored for element-wise operations. It supports standard arithmetic operators (+, -, *, /) as well as a variety of transcendental functions (sin, cos, log, sqrt, etc.). These capabilities empower users to perform complex computations efficiently and effectively. +ArrayFire provides a broad spectrum of functions tailored for element-wise operations. It supports standard arithmetic operators (+, \-, \*, /) as well as a variety of transcendental functions (sin, cos, log, sqrt, etc.). These capabilities empower users to perform complex computations efficiently and effectively. .. literalinclude:: gettingstarted.py :language: python @@ -118,7 +118,7 @@ ArrayFire provides a broad spectrum of functions tailored for element-wise opera To see the complete list of functions please consult the documentation on mathematical, linear algebra, signal processing, and statistics. Mathematical constants -====================== +********************** In Python, ArrayFire provides several platform-independent constants such as Pi, NaN, and Inf. If ArrayFire lacks a specific constant you require, you can create it using the `af.constant` array constructor. @@ -132,7 +132,7 @@ These constants are universally applicable across all ArrayFire functions. Below Please note that our constants may, at times, conflict with macro definitions in standard header files. When this occurs, please refer to our constants using the :literal:`af::` namespace. Indexing -======== +******** Like all functions in ArrayFire, indexing is also executed in parallel on the OpenCL/CUDA devices. Because of this, indexing becomes part of a JIT operation and is accomplished using parentheses instead of square brackets (i.e. as :literal:`A(0)` instead of :literal:`A[0]`). To index :literal:`af::` arrays you may use one or a combination of the following functions: * integer scalars @@ -145,7 +145,7 @@ Like all functions in ArrayFire, indexing is also executed in parallel on the Op Please see the indexing page for several examples of how to use these functions. Getting access to ArrayFire array memory on the host and device -=============================================================== +*************************************************************** Memory in :literal:`af::arrays` may be accessed using the host() and device() functions. The :literal:`host` function copies the data from the device and makes it available in a C-style array on the host. As such, it is up to the developer to manage any memory returned by :literal:`host`. The :literal:`device` function returns a pointer/reference to device memory for interoperability with external CUDA/OpenCL kernels. As this memory belongs to ArrayFire, the programmer should not attempt to free/deallocate the pointer. For example, here is how we can interact with both OpenCL and CUDA: @@ -166,7 +166,7 @@ Lastly, if you want only the first value from an :literal:`af::array` you can us Bitwise operators -================= +***************** In addition to supporting standard mathematical functions, arrays that contain integer data types also support bitwise operators including and, or, and shift: .. literalinclude:: gettingstarted.py @@ -176,7 +176,7 @@ In addition to supporting standard mathematical functions, arrays that contain i Using the ArrayFire API in Python -================================= +********************************* The ArrayFire library in Python is seamlessly integrated into the Python environment. To start using the library, simply :literal:`import arrayfire` and begin coding! @@ -193,7 +193,7 @@ Sample using Python API What to read next? -================== +################## Now that you have a general introduction to ArrayFire, where do you go from here? In particular you might find these documents useful @@ -202,7 +202,7 @@ Now that you have a general introduction to ArrayFire, where do you go from here * Timing ArrayFire code Where to go for help? -===================== +##################### * Google Groups: https://groups.google.com/forum/#!forum/arrayfire-users * ArrayFire Services: `Consulting `_ | `Support `_ | `Training `_ diff --git a/docs/images/arrayfire_icon.png b/docs/images/arrayfire_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a9738780d67d052b552e9e2b64c30a6b808f61a9 GIT binary patch literal 6757 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�$NX(4GR`tF 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�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 * :ref:`Linux ` @@ -15,7 +15,7 @@ Install Instructions .. _Windows: Windows -======= +******* Once the ArrayFire has been downloaded, run the installer. The installer offers the option to automatically add ArrayFire to the path for all users. If the installer did not do this, simply append :literal:`%AF_PATH%/lib` to the PATH variable so that the loader can find ArrayFire DLLs. @@ -26,7 +26,7 @@ For more information on using ArrayFire on Windows, visit the following page. .. _Linux: Linux -===== +***** There are two ways to install ArrayFire on Linux. @@ -79,7 +79,7 @@ To install these dependencies on common Linux distributions: .. _macOS: macOS -===== +***** Once the ArrayFire installer has been downloaded, execute the installer by either double-clicking on the ArrayFire :literal:`pkg` file or running the following command: @@ -107,7 +107,7 @@ The following dependencies are required for Tegra devices: sudo apt install libopenblas-dev liblapacke-dev Testing installation -==================== +******************** After ArrayFire is finished installing, we recommend building and running a few of the provided examples to verify things are working as expected. diff --git a/docs/introductiontovectorization.rst b/docs/introductiontovectorization.rst index 276a0d1..a38e068 100644 --- a/docs/introductiontovectorization.rst +++ b/docs/introductiontovectorization.rst @@ -3,7 +3,8 @@ Introduction to Vectorization Programmers and Data Scientists want to take advantage of fast and parallel computational devices. Writing vectorized code is necessary to get the best performance out of the current generation parallel hardware and scientific computing software. However, writing vectorized code may not be immediately intuitive. ArrayFire provides many ways to vectorize a given code segment. In this tutorial, we present several methods to vectorize code using ArrayFire and discuss the benefits and drawbacks associated with each method. Generic/Default Vectorization -============================= +***************************** + By its very nature, ArrayFire is a vectorized library. Most functions operate on arrays as a whole – on all elements in parallel. Wherever possible, existing vectorized functions should be used opposed to manually indexing into arrays. For example consider the following code: .. literalinclude:: introductiontovectorization.py @@ -62,7 +63,7 @@ Although most functions in ArrayFire do support vectorization, some do not. Most Using the built in vectorized operations should be the first and preferred method of vectorizing any code written with ArrayFire. GFOR: Parallel for-loops -======================== +************************ Another novel method of vectorization present in ArrayFire is the GFOR loop replacement construct. GFOR allows launching all iterations of a loop in parallel on the GPU or device, as long as the iterations are independent. While the standard for-loop performs each iteration sequentially, ArrayFire's gfor-loop performs each iteration at the same time (in parallel). ArrayFire does this by tiling out the values of all loop iterations and then performing computation on those tiles in one pass. You can think of gfor as performing auto-vectorization of your code, e.g. you write a gfor-loop that increments every element of a vector but behind the scenes ArrayFire rewrites it to operate on the entire vector in parallel. The original for-loop example at the beginning of this document could be rewritten using GFOR as follows: @@ -99,7 +100,7 @@ Using GFOR requires following several rules and multiple guidelines for optimal Batching -======== +******** The batchFunc() function allows the broad application of existing ArrayFire functions to multiple sets of data. Effectively, batchFunc() allows ArrayFire functions to execute in "batch processing" mode. In this mode, functions will find a dimension which contains "batches" of data to be processed and will parallelize the procedure. Consider the following example. Here we create a filter which we would like to apply to each of the weight vectors. The naive solution would be using a for-loop as we have seen previously: @@ -120,7 +121,7 @@ However, as we have discussed above, this solution will be very inefficient. One However, the dimensions of :literal:`filter` and :literal:`weights` do not match, thus ArrayFire will generate a runtime error. Advanced Vectorization -====================== +********************** We have seen the different methods ArrayFire provides to vectorize our code. Tying them all together is a slightly more involved process that needs to consider data dimensionality and layout, memory usage, nesting order, etc. An excellent example and discussion of these factors can be found on our blog: http://arrayfire.com/how-to-write-vectorized-code/ \ No newline at end of file diff --git a/docs/linux.rst b/docs/linux.rst index b9f86d6..8451b86 100644 --- a/docs/linux.rst +++ b/docs/linux.rst @@ -6,7 +6,7 @@ Once you have :ref:`installed ` ArrayFire on your system, the next thing .. _bigpicture: The big picture -=============== +############### On Linux, we recommend installing ArrayFire to :literal:`/opt/arrayfire` directory. The installer will populate files in the following sub-directories: @@ -24,7 +24,7 @@ On Linux, we recommend installing ArrayFire to :literal:`/opt/arrayfire` directo Because ArrayFire follows standard installation practices, you can use basically any build system to create and compile projects that use ArrayFire. Among the many possible build systems on Linux we suggest using ArrayFire with either CMake or Makefiles with CMake being our preferred build system. Prerequisite software -===================== +##################### To build ArrayFire projects you will need a compiler @@ -101,7 +101,7 @@ You can also specify this information in the :literal:`ccmake` command-line inte Makefiles -========= +######### Building ArrayFire projects with Makefiles is fairly similar to CMake except you must specify all paths and libraries manually. diff --git a/docs/overview.rst b/docs/overview.rst index 39385fb..45d45f3 100644 --- a/docs/overview.rst +++ b/docs/overview.rst @@ -1,22 +1,25 @@ Overview ======== +About ArrayFire +*************** - -About Array Fire ----------------- +.. image:: images/arrayfire_logo.png + :alt: ArrayFire Logo + :align: center + :class: responsive-img `ArrayFire `_ is a high performance library for parallel computing with an easy-to-use API. It enables users to write scientific computing code that is portable across CUDA, OpenCL and CPU devices. This project provides Python bindings for the ArrayFire library. Installing ArrayFire --------------------- +******************** Install ArrayFire using either a binary installer for Windows, OSX, or Linux or download it from source: * `Download and install Binaries `_ * `Build from source `_ -Easy to use ------------ +Using ArrayFire +*************** The array object is beautifully simple. @@ -24,8 +27,6 @@ Array-based notation effectively expresses computational algorithms in readable A few lines of ArrayFire code accomplishes what can take 100s of complicated lines in CUDA, oneAPI, or OpenCL kernels. -ArrayFire is extensive! ------------------------ Support for multiple domains ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -52,9 +53,6 @@ Extending ArrayFire ArrayFire can be used as a stand-alone application or integrated with existing CUDA, oneAPI, or OpenCL code. -Code once, run anywhere! ------------------------- - With support for x86, ARM, CUDA, oneAPI, and OpenCL devices, ArrayFire supports for a comprehensive list of devices. Each ArrayFire installation comes with: @@ -64,8 +62,6 @@ Each ArrayFire installation comes with: * an OpenCL backend (named 'libafopencl') for `OpenCL devices `_, * a CPU backend (named 'libafcpu') to fall back to when CUDA, oneAPI, or OpenCL devices are unavailable. -ArrayFire is highly efficient ------------------------------ Vectorized and Batched Operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -96,7 +92,8 @@ Here is an example of ArrayFire code that performs a Monte Carlo estimation of P Product Support ---------------- +*************** + Free Community Options ~~~~~~~~~~~~~~~~~~~~~~ * `ArrayFire Mailing List `_ (recommended) @@ -116,6 +113,6 @@ Email * Sales: sales@arrayfire.com Citations and Acknowledgements ------------------------------- +****************************** If you redistribute ArrayFire, please follow the terms established in `the license `_. If you wish to cite ArrayFire in an academic publication, please use the following reference: \ No newline at end of file diff --git a/docs/releasenotes.rst b/docs/releasenotes.rst index d7c9f9b..c97ec5e 100644 --- a/docs/releasenotes.rst +++ b/docs/releasenotes.rst @@ -2,7 +2,7 @@ Release Notes ============== v0.1.0 -====== +****** Welcome to the ArrayFire Python Bindings! These are the currently supported features: - Support for all backends (cpu, opencl, oneapi, cuda) diff --git a/docs/timing_arrayfire.rst b/docs/timing_arrayfire.rst new file mode 100644 index 0000000..b3a8cc7 --- /dev/null +++ b/docs/timing_arrayfire.rst @@ -0,0 +1,62 @@ +Timing ArrayFire +================= + +Preamble +######## + +As shown in other sections, ArrayFire leverages Just-in-Time (JIT) compilation of kernels to speedup many array operations. +This means that after a function is called, the operation may not have finished (or even started) after execution continues +to the next line. Furthermore, the first time an operation is done, as it may be slowed down due to the JIT compilation of +the combined operations; later operations will not have this problem as the compiled kernel is cached. + +So benchmarking ArrayFire is not as straight forward as just wrapping an operation in between timers. + +Setup +####### + +For benchmarking we will utilize two functions: `af.sync()` and `af.eval(arr)`. + +- `af.sync`: The purpose of this function is to stall the current thread until all awaiting operations have finished and the result is accessable by the host. It synchronizes the host and the device, similar to what cuda.Stream.synchronize() does in cupy. + +- `af.eval`: This function takes in an array which will be forced to be evaluated immediately. This forces the JIT tree to be cut at the point of this function calls and any later operations will not be considered in this current JIT tree. + + +Using these two function we can make sure that we are benchmarking the correct operations by making sure that no operation is running +before or after we want our timers to measure. + +Example +########## + +The following is an examples of timing how long an addition takes + +.. code-block:: python + + import arrayfire as af + import time + + # Generate a random array + x = af.randn(1000000) + + # Make sure the numbers have been generated before the timing starts + af.eval(x) + af.sync() + + # Start timer + start = time.perf_counter() + y = x + x + + # Make sure the computation has finished before the timing ends + af.eval(y) + af.sync() + + # End timer + end = time.perf_counter() + + print(f"Elapsed time: {end - start:.6f} seconds") + + +Benchmarking JIT vs non-JIT +############################ + +For timing JIT operations against non-JIT operations, please take a look at page on JIT :doc:`arrayfirejitcodegeneration` and +the code in :download:`afjit.py`. \ No newline at end of file diff --git a/docs/tutorial.rst b/docs/tutorial.rst index 3ffe64c..3ea2d29 100644 --- a/docs/tutorial.rst +++ b/docs/tutorial.rst @@ -13,7 +13,7 @@ Tutorial * Unified Backend * Forge Visualization * :doc:`Indexing ` -* Timing ArrayFire +* :doc:`Timing ArrayFire ` * :doc:`Configuring ArrayFire Environment ` * :doc:`Debugging ArrayFire Code ` * :doc:`ArrayFire JIT Code Generation ` From 3b17c77cd73ec7c619fb49e7497a6c4d9f9852dc Mon Sep 17 00:00:00 2001 From: Edwin Date: Fri, 22 Aug 2025 11:44:36 -0700 Subject: [PATCH 09/11] Added more functions docs, added classes, constants, implemented reshape --- arrayfire/__init__.py | 6 + arrayfire/array_object.py | 55 +- arrayfire/library/array_functions.py | 96 ++- arrayfire/library/computer_vision.py | 3 +- docs/README.md | 1 + docs/array_creation_functions.rst | 50 ++ docs/array_manipulation_functions.rst | 55 ++ docs/arrayandmatrixmanipulation.rst | 27 +- docs/classes/Features.rst | 4 + docs/classes/RandomEngine.rst | 7 + docs/classes/array.rst | 37 + docs/classes/index.rst | 10 + docs/conf.py | 5 +- docs/constants/BinaryOperator.rst | 7 + docs/constants/CSpace.rst | 7 + docs/constants/CannyThreshold.rst | 7 + docs/constants/Connectivity.rst | 7 + docs/constants/ConvDomain.rst | 7 + docs/constants/ConvGradient.rst | 7 + docs/constants/ConvMode.rst | 7 + docs/constants/Diffusion.rst | 7 + docs/constants/Dtype.rst | 28 + docs/constants/Flux.rst | 7 + docs/constants/ImageFormat.rst | 7 + docs/constants/Interp.rst | 7 + docs/constants/IterativeDeconv.rst | 7 + docs/constants/MatProp.rst | 7 + docs/constants/Match.rst | 7 + docs/constants/Norm.rst | 7 + docs/constants/Pad.rst | 7 + docs/constants/RandomEngineType.rst | 7 + docs/constants/TopK.rst | 7 + docs/constants/VarianceBias.rst | 7 + docs/constants/YCCStd.rst | 7 + docs/constants/index.rst | 28 + docs/data_reduction_functions.rst | 41 ++ docs/debuggingarrayfirecode.rst | 70 +- docs/fourier_transforms_functions.rst | 41 ++ docs/functions.rst | 667 ++++++++++++++---- docs/functions/ArrayFire.rst | 4 - docs/functions/abs.rst | 4 + docs/functions/acos.rst | 4 + docs/functions/acosh.rst | 4 + docs/functions/alloc_device.rst | 4 + docs/functions/alloc_host.rst | 4 + docs/functions/alloc_pinned.rst | 4 + docs/functions/anisotropic_diffusion.rst | 4 + docs/functions/approx1.rst | 4 + docs/functions/approx1_uniform.rst | 4 + docs/functions/approx2.rst | 4 + docs/functions/approx2_uniform.rst | 4 + docs/functions/arg.rst | 4 + docs/functions/array.rst | 33 - docs/functions/asin.rst | 4 + docs/functions/asinh.rst | 4 + docs/functions/atan.rst | 4 + docs/functions/atan2.rst | 4 + docs/functions/atanh.rst | 4 + docs/functions/bilateral.rst | 4 + docs/functions/bitand.rst | 4 + docs/functions/bitnot.rst | 4 + docs/functions/bitor.rst | 4 + docs/functions/bitshiftl.rst | 4 + docs/functions/bitshiftr.rst | 4 + docs/functions/bitxor.rst | 4 + docs/functions/canny.rst | 4 + docs/functions/cast.rst | 4 + docs/functions/cbrt.rst | 4 + docs/functions/ceil.rst | 4 + docs/functions/cholesky.rst | 4 + docs/functions/clamp.rst | 4 + docs/functions/color_space.rst | 4 + docs/functions/confidence_cc.rst | 4 + docs/functions/conjg.rst | 4 + docs/functions/convolve1.rst | 4 + docs/functions/convolve2.rst | 4 + docs/functions/convolve2_gradient_nn.rst | 4 + docs/functions/convolve2_nn.rst | 4 + docs/functions/convolve2_separable.rst | 4 + docs/functions/convolve3.rst | 4 + docs/functions/copy_array.rst | 4 + docs/functions/cos.rst | 4 + docs/functions/cosh.rst | 4 + docs/functions/cplx.rst | 4 + docs/functions/cublas_set_math_mode.rst | 4 + docs/functions/delete_image_memory.rst | 4 + docs/functions/device.rst | 43 -- docs/functions/device_gc.rst | 4 + docs/functions/device_info.rst | 4 + docs/functions/device_mem_info.rst | 4 + docs/functions/dilate.rst | 4 + docs/functions/div.rst | 4 + docs/functions/divide.rst | 36 - docs/functions/eig.rst | 37 - docs/functions/eq.rst | 4 + docs/functions/erf.rst | 4 + docs/functions/erfc.rst | 4 + docs/functions/erode.rst | 4 + docs/functions/eval.rst | 4 + docs/functions/expm1.rst | 4 + docs/functions/factorial.rst | 4 + docs/functions/fft2.rst | 4 + docs/functions/fft2_c2r.rst | 4 + docs/functions/fft2_r2c.rst | 4 + docs/functions/fft3.rst | 4 + docs/functions/fft3_c2r.rst | 4 + docs/functions/fft3_r2c.rst | 4 + docs/functions/fft_c2r.rst | 4 + docs/functions/fft_convolve1.rst | 4 + docs/functions/fft_convolve2.rst | 4 + docs/functions/fft_convolve3.rst | 4 + docs/functions/fft_r2c.rst | 4 + docs/functions/fir.rst | 4 + docs/functions/flat.rst | 4 + docs/functions/flip.rst | 4 + docs/functions/floor.rst | 4 + docs/functions/free_device.rst | 4 + docs/functions/free_host.rst | 4 + docs/functions/free_pinned.rst | 4 + docs/functions/gaussian_kernel.rst | 4 + docs/functions/ge.rst | 4 + docs/functions/get_dbl_support.rst | 4 + docs/functions/get_device.rst | 25 +- docs/functions/get_device_count.rst | 4 + docs/functions/get_half_support.rst | 4 + docs/functions/get_kernel_cache_directory.rst | 4 + docs/functions/get_mem_step_size.rst | 4 + docs/functions/get_native_id.rst | 4 + docs/functions/get_stream.rst | 4 + docs/functions/gray2rgb.rst | 4 + docs/functions/gt.rst | 4 + docs/functions/hist_equal.rst | 4 + docs/functions/histogram.rst | 4 + docs/functions/hsv2rgb.rst | 4 + docs/functions/hypot.rst | 4 + docs/functions/ifft2.rst | 4 + docs/functions/ifft3.rst | 4 + docs/functions/iir.rst | 4 + docs/functions/imag.rst | 4 + docs/functions/index.rst | 292 ++++++-- docs/functions/info.rst | 4 + docs/functions/info_string.rst | 4 + docs/functions/init.rst | 4 + docs/functions/inverse.rst | 4 + docs/functions/inverse_deconv.rst | 4 + docs/functions/is_image_io_available.rst | 4 + docs/functions/is_lapack_available.rst | 4 + docs/functions/isnan.rst | 4 + docs/functions/iszero.rst | 4 + docs/functions/iterative_deconv.rst | 4 + docs/functions/le.rst | 4 + docs/functions/lgamma.rst | 4 + docs/functions/load_image.rst | 4 + docs/functions/load_image_memory.rst | 4 + docs/functions/load_image_native.rst | 4 + docs/functions/log10.rst | 4 + docs/functions/log1p.rst | 4 + docs/functions/log2.rst | 4 + docs/functions/logical_and.rst | 4 + docs/functions/logical_not.rst | 4 + docs/functions/logical_or.rst | 4 + docs/functions/lookup.rst | 4 + docs/functions/lt.rst | 4 + docs/functions/lu.rst | 4 + docs/functions/maxfilt.rst | 4 + docs/functions/maxof.rst | 4 + docs/functions/mean_shift.rst | 4 + docs/functions/medfilt.rst | 4 + docs/functions/medfilt1.rst | 4 + docs/functions/medfilt2.rst | 4 + docs/functions/minfilt.rst | 4 + docs/functions/minof.rst | 4 + docs/functions/moddims.rst | 4 + docs/functions/mul.rst | 4 + docs/functions/multiply.rst | 32 - docs/functions/neg.rst | 4 + docs/functions/neq.rst | 4 + docs/functions/norm.rst | 4 + docs/functions/pinverse.rst | 4 + docs/functions/pow.rst | 4 + docs/functions/pow2.rst | 4 + docs/functions/print_mem_info.rst | 4 + docs/functions/qr.rst | 4 + docs/functions/rank.rst | 4 + docs/functions/read_array.rst | 8 + docs/functions/real.rst | 4 + docs/functions/regions.rst | 4 + docs/functions/rem.rst | 4 + docs/functions/replace.rst | 4 + docs/functions/resize.rst | 4 + docs/functions/rgb2gray.rst | 4 + docs/functions/rgb2hsv.rst | 4 + docs/functions/rgb2ycbcr.rst | 4 + docs/functions/root.rst | 4 + docs/functions/rotate.rst | 4 + docs/functions/round.rst | 4 + docs/functions/rsqrt.rst | 4 + docs/functions/sat.rst | 4 + docs/functions/save_array.rst | 4 + docs/functions/save_image.rst | 4 + docs/functions/save_image_memory.rst | 4 + docs/functions/save_image_native.rst | 4 + docs/functions/scale.rst | 4 + docs/functions/scan.rst | 4 + docs/functions/select.rst | 4 + docs/functions/set_device.rst | 23 +- docs/functions/set_fft_plan_cache_size.rst | 4 + docs/functions/set_kernel_cache_directory.rst | 4 + docs/functions/set_mem_step_size.rst | 4 + docs/functions/set_native_id.rst | 4 + docs/functions/shift.rst | 4 + docs/functions/sign.rst | 4 + docs/functions/sin.rst | 4 + docs/functions/sinh.rst | 4 + docs/functions/skew.rst | 4 + docs/functions/slice.rst | 27 - docs/functions/sobel_operator.rst | 4 + docs/functions/solve.rst | 4 + docs/functions/sub.rst | 4 + docs/functions/subtract.rst | 29 - docs/functions/svd.rst | 4 + docs/functions/sync.rst | 4 + docs/functions/tan.rst | 4 + docs/functions/tanh.rst | 4 + docs/functions/tgamma.rst | 4 + docs/functions/tile.rst | 4 + docs/functions/transform.rst | 4 + docs/functions/transform_coordinates.rst | 4 + docs/functions/translate.rst | 4 + docs/functions/trunc.rst | 4 + docs/functions/unwrap.rst | 4 + docs/functions/where.rst | 4 + docs/functions/wrap.rst | 4 + docs/gettingstarted.rst | 60 +- docs/index.rst | 28 +- docs/indexing.rst | 51 +- docs/introductiontovectorization.py | 76 +- docs/introductiontovectorization.rst | 55 +- docs/license.rst | 69 ++ docs/linear_algebra_functions.rst | 35 + docs/linux.rst | 123 ---- docs/mathematical_operations_functions.rst | 148 ++++ docs/overview.rst | 7 +- docs/product_support.rst | 9 + docs/special_functions.rst | 125 ++++ docs/statistics_functions.rst | 35 + docs/timing_arrayfire.rst | 4 +- docs/tutorial.rst | 16 +- docs/utilities_functions.rst | 89 +++ 249 files changed, 2785 insertions(+), 833 deletions(-) create mode 100644 docs/array_creation_functions.rst create mode 100644 docs/array_manipulation_functions.rst create mode 100644 docs/classes/Features.rst create mode 100644 docs/classes/RandomEngine.rst create mode 100644 docs/classes/array.rst create mode 100644 docs/classes/index.rst create mode 100644 docs/constants/BinaryOperator.rst create mode 100644 docs/constants/CSpace.rst create mode 100644 docs/constants/CannyThreshold.rst create mode 100644 docs/constants/Connectivity.rst create mode 100644 docs/constants/ConvDomain.rst create mode 100644 docs/constants/ConvGradient.rst create mode 100644 docs/constants/ConvMode.rst create mode 100644 docs/constants/Diffusion.rst create mode 100644 docs/constants/Dtype.rst create mode 100644 docs/constants/Flux.rst create mode 100644 docs/constants/ImageFormat.rst create mode 100644 docs/constants/Interp.rst create mode 100644 docs/constants/IterativeDeconv.rst create mode 100644 docs/constants/MatProp.rst create mode 100644 docs/constants/Match.rst create mode 100644 docs/constants/Norm.rst create mode 100644 docs/constants/Pad.rst create mode 100644 docs/constants/RandomEngineType.rst create mode 100644 docs/constants/TopK.rst create mode 100644 docs/constants/VarianceBias.rst create mode 100644 docs/constants/YCCStd.rst create mode 100644 docs/constants/index.rst create mode 100644 docs/data_reduction_functions.rst create mode 100644 docs/fourier_transforms_functions.rst delete mode 100644 docs/functions/ArrayFire.rst create mode 100644 docs/functions/abs.rst create mode 100644 docs/functions/acos.rst create mode 100644 docs/functions/acosh.rst create mode 100644 docs/functions/alloc_device.rst create mode 100644 docs/functions/alloc_host.rst create mode 100644 docs/functions/alloc_pinned.rst create mode 100644 docs/functions/anisotropic_diffusion.rst create mode 100644 docs/functions/approx1.rst create mode 100644 docs/functions/approx1_uniform.rst create mode 100644 docs/functions/approx2.rst create mode 100644 docs/functions/approx2_uniform.rst create mode 100644 docs/functions/arg.rst delete mode 100644 docs/functions/array.rst create mode 100644 docs/functions/asin.rst create mode 100644 docs/functions/asinh.rst create mode 100644 docs/functions/atan.rst create mode 100644 docs/functions/atan2.rst create mode 100644 docs/functions/atanh.rst create mode 100644 docs/functions/bilateral.rst create mode 100644 docs/functions/bitand.rst create mode 100644 docs/functions/bitnot.rst create mode 100644 docs/functions/bitor.rst create mode 100644 docs/functions/bitshiftl.rst create mode 100644 docs/functions/bitshiftr.rst create mode 100644 docs/functions/bitxor.rst create mode 100644 docs/functions/canny.rst create mode 100644 docs/functions/cast.rst create mode 100644 docs/functions/cbrt.rst create mode 100644 docs/functions/ceil.rst create mode 100644 docs/functions/cholesky.rst create mode 100644 docs/functions/clamp.rst create mode 100644 docs/functions/color_space.rst create mode 100644 docs/functions/confidence_cc.rst create mode 100644 docs/functions/conjg.rst create mode 100644 docs/functions/convolve1.rst create mode 100644 docs/functions/convolve2.rst create mode 100644 docs/functions/convolve2_gradient_nn.rst create mode 100644 docs/functions/convolve2_nn.rst create mode 100644 docs/functions/convolve2_separable.rst create mode 100644 docs/functions/convolve3.rst create mode 100644 docs/functions/copy_array.rst create mode 100644 docs/functions/cos.rst create mode 100644 docs/functions/cosh.rst create mode 100644 docs/functions/cplx.rst create mode 100644 docs/functions/cublas_set_math_mode.rst create mode 100644 docs/functions/delete_image_memory.rst delete mode 100644 docs/functions/device.rst create mode 100644 docs/functions/device_gc.rst create mode 100644 docs/functions/device_info.rst create mode 100644 docs/functions/device_mem_info.rst create mode 100644 docs/functions/dilate.rst create mode 100644 docs/functions/div.rst delete mode 100644 docs/functions/divide.rst delete mode 100644 docs/functions/eig.rst create mode 100644 docs/functions/eq.rst create mode 100644 docs/functions/erf.rst create mode 100644 docs/functions/erfc.rst create mode 100644 docs/functions/erode.rst create mode 100644 docs/functions/eval.rst create mode 100644 docs/functions/expm1.rst create mode 100644 docs/functions/factorial.rst create mode 100644 docs/functions/fft2.rst create mode 100644 docs/functions/fft2_c2r.rst create mode 100644 docs/functions/fft2_r2c.rst create mode 100644 docs/functions/fft3.rst create mode 100644 docs/functions/fft3_c2r.rst create mode 100644 docs/functions/fft3_r2c.rst create mode 100644 docs/functions/fft_c2r.rst create mode 100644 docs/functions/fft_convolve1.rst create mode 100644 docs/functions/fft_convolve2.rst create mode 100644 docs/functions/fft_convolve3.rst create mode 100644 docs/functions/fft_r2c.rst create mode 100644 docs/functions/fir.rst create mode 100644 docs/functions/flat.rst create mode 100644 docs/functions/flip.rst create mode 100644 docs/functions/floor.rst create mode 100644 docs/functions/free_device.rst create mode 100644 docs/functions/free_host.rst create mode 100644 docs/functions/free_pinned.rst create mode 100644 docs/functions/gaussian_kernel.rst create mode 100644 docs/functions/ge.rst create mode 100644 docs/functions/get_dbl_support.rst create mode 100644 docs/functions/get_device_count.rst create mode 100644 docs/functions/get_half_support.rst create mode 100644 docs/functions/get_kernel_cache_directory.rst create mode 100644 docs/functions/get_mem_step_size.rst create mode 100644 docs/functions/get_native_id.rst create mode 100644 docs/functions/get_stream.rst create mode 100644 docs/functions/gray2rgb.rst create mode 100644 docs/functions/gt.rst create mode 100644 docs/functions/hist_equal.rst create mode 100644 docs/functions/histogram.rst create mode 100644 docs/functions/hsv2rgb.rst create mode 100644 docs/functions/hypot.rst create mode 100644 docs/functions/ifft2.rst create mode 100644 docs/functions/ifft3.rst create mode 100644 docs/functions/iir.rst create mode 100644 docs/functions/imag.rst create mode 100644 docs/functions/info.rst create mode 100644 docs/functions/info_string.rst create mode 100644 docs/functions/init.rst create mode 100644 docs/functions/inverse.rst create mode 100644 docs/functions/inverse_deconv.rst create mode 100644 docs/functions/is_image_io_available.rst create mode 100644 docs/functions/is_lapack_available.rst create mode 100644 docs/functions/isnan.rst create mode 100644 docs/functions/iszero.rst create mode 100644 docs/functions/iterative_deconv.rst create mode 100644 docs/functions/le.rst create mode 100644 docs/functions/lgamma.rst create mode 100644 docs/functions/load_image.rst create mode 100644 docs/functions/load_image_memory.rst create mode 100644 docs/functions/load_image_native.rst create mode 100644 docs/functions/log10.rst create mode 100644 docs/functions/log1p.rst create mode 100644 docs/functions/log2.rst create mode 100644 docs/functions/logical_and.rst create mode 100644 docs/functions/logical_not.rst create mode 100644 docs/functions/logical_or.rst create mode 100644 docs/functions/lookup.rst create mode 100644 docs/functions/lt.rst create mode 100644 docs/functions/lu.rst create mode 100644 docs/functions/maxfilt.rst create mode 100644 docs/functions/maxof.rst create mode 100644 docs/functions/mean_shift.rst create mode 100644 docs/functions/medfilt.rst create mode 100644 docs/functions/medfilt1.rst create mode 100644 docs/functions/medfilt2.rst create mode 100644 docs/functions/minfilt.rst create mode 100644 docs/functions/minof.rst create mode 100644 docs/functions/moddims.rst create mode 100644 docs/functions/mul.rst delete mode 100644 docs/functions/multiply.rst create mode 100644 docs/functions/neg.rst create mode 100644 docs/functions/neq.rst create mode 100644 docs/functions/norm.rst create mode 100644 docs/functions/pinverse.rst create mode 100644 docs/functions/pow.rst create mode 100644 docs/functions/pow2.rst create mode 100644 docs/functions/print_mem_info.rst create mode 100644 docs/functions/qr.rst create mode 100644 docs/functions/rank.rst create mode 100644 docs/functions/read_array.rst create mode 100644 docs/functions/real.rst create mode 100644 docs/functions/regions.rst create mode 100644 docs/functions/rem.rst create mode 100644 docs/functions/replace.rst create mode 100644 docs/functions/resize.rst create mode 100644 docs/functions/rgb2gray.rst create mode 100644 docs/functions/rgb2hsv.rst create mode 100644 docs/functions/rgb2ycbcr.rst create mode 100644 docs/functions/root.rst create mode 100644 docs/functions/rotate.rst create mode 100644 docs/functions/round.rst create mode 100644 docs/functions/rsqrt.rst create mode 100644 docs/functions/sat.rst create mode 100644 docs/functions/save_array.rst create mode 100644 docs/functions/save_image.rst create mode 100644 docs/functions/save_image_memory.rst create mode 100644 docs/functions/save_image_native.rst create mode 100644 docs/functions/scale.rst create mode 100644 docs/functions/scan.rst create mode 100644 docs/functions/select.rst create mode 100644 docs/functions/set_fft_plan_cache_size.rst create mode 100644 docs/functions/set_kernel_cache_directory.rst create mode 100644 docs/functions/set_mem_step_size.rst create mode 100644 docs/functions/set_native_id.rst create mode 100644 docs/functions/shift.rst create mode 100644 docs/functions/sign.rst create mode 100644 docs/functions/sin.rst create mode 100644 docs/functions/sinh.rst create mode 100644 docs/functions/skew.rst delete mode 100644 docs/functions/slice.rst create mode 100644 docs/functions/sobel_operator.rst create mode 100644 docs/functions/solve.rst create mode 100644 docs/functions/sub.rst delete mode 100644 docs/functions/subtract.rst create mode 100644 docs/functions/svd.rst create mode 100644 docs/functions/sync.rst create mode 100644 docs/functions/tan.rst create mode 100644 docs/functions/tanh.rst create mode 100644 docs/functions/tgamma.rst create mode 100644 docs/functions/tile.rst create mode 100644 docs/functions/transform.rst create mode 100644 docs/functions/transform_coordinates.rst create mode 100644 docs/functions/translate.rst create mode 100644 docs/functions/trunc.rst create mode 100644 docs/functions/unwrap.rst create mode 100644 docs/functions/where.rst create mode 100644 docs/functions/wrap.rst create mode 100644 docs/license.rst create mode 100644 docs/linear_algebra_functions.rst delete mode 100644 docs/linux.rst create mode 100644 docs/mathematical_operations_functions.rst create mode 100644 docs/product_support.rst create mode 100644 docs/special_functions.rst create mode 100644 docs/statistics_functions.rst create mode 100644 docs/utilities_functions.rst diff --git a/arrayfire/__init__.py b/arrayfire/__init__.py index e5f2079..7a5c4a3 100755 --- a/arrayfire/__init__.py +++ b/arrayfire/__init__.py @@ -72,6 +72,8 @@ __all__ += [ "constant", + "zeros", + "ones", "diag", "identity", "iota", @@ -89,6 +91,7 @@ "flip", "join", "moddims", + "reshape", "reorder", "replace", "select", @@ -100,6 +103,8 @@ from arrayfire.library.array_functions import ( constant, + zeros, + ones, copy_array, diag, eval, @@ -114,6 +119,7 @@ lookup, lower, moddims, + reshape, pad, range, reorder, diff --git a/arrayfire/array_object.py b/arrayfire/array_object.py index d44ee29..9b715b1 100755 --- a/arrayfire/array_object.py +++ b/arrayfire/array_object.py @@ -869,8 +869,8 @@ def T(self) -> Array: Note ---- - - The array instance must be two-dimensional. If the array instance is not two-dimensional, an error - should be raised. + - The array instance must be two-dimensional. If the array instance is not two-dimensional, an error should be raised. + """ if self.ndim < 2: raise TypeError(f"Array should be at least 2-dimensional. Got {self.ndim}-dimensional array") @@ -881,6 +881,24 @@ def T(self) -> Array: @property @afarray_as_array def H(self) -> Array: + """ + Hermitian Conjugate of the array. + + Returns + ------- + Array + Two-dimensional array whose first and last dimensions (axes) are permuted in reverse order relative to + original array with its elements complex conjugated. The returned array must have the same data type as the original array. + + Note + ---- + - The array instance must be two-dimensional. If the array instance is not two-dimensional, an error should be raised. + + """ + if self.ndim < 2: + raise TypeError(f"Array should be at least 2-dimensional. Got {self.ndim}-dimensional array") + + # TODO add check if out.dtype == self.dtype return cast(Array, wrapper.transpose(self._arr, True)) @property @@ -1096,6 +1114,39 @@ def device_pointer(self) -> int: def is_locked_array(self) -> bool: return wrapper.is_locked_array(self._arr) + @afarray_as_array + def reshape(self, shape) -> Array: + """ + Return a copy of this array with the specified shape without changing the data layout. + + Parameters + ---------- + shape : tuple of int + The desired shape of the output array. It should be a tuple of integers + representing the dimensions of the output array. The product of these + dimensions must match the total number of elements in the input array. + + Returns + ------- + out : af.Array + - An array containing the same data as `array` with the specified shape. + - The total number of elements in `array` must match the product of the dimensions specified in the `shape` tuple. + + Raises + ------ + ValueError + If the total number of elements in the input array does not match the + product of the dimensions specified in the `shape` tuple. + + Notes + ----- + This function modifies the shape of the input array without changing the + data layout. The resulting array will have the same data, but with a + different shape as specified by the `shape` parameter. + """ + # TODO add examples to doc + return cast(Array, wrapper.moddims(self._arr, shape)) + def lock_array(self) -> None: return wrapper.lock_array(self._arr) diff --git a/arrayfire/library/array_functions.py b/arrayfire/library/array_functions.py index e8028e5..ba78c5a 100644 --- a/arrayfire/library/array_functions.py +++ b/arrayfire/library/array_functions.py @@ -1,5 +1,7 @@ __all__ = [ "constant", + "zeros", + "ones", "diag", "identity", "iota", @@ -17,6 +19,7 @@ "flip", "join", "moddims", + "reshape", "reorder", "replace", "select", @@ -70,6 +73,59 @@ def constant(scalar: int | float | complex, shape: tuple[int, ...] = (1,), dtype """ return cast(Array, wrapper.create_constant_array(scalar, shape, dtype)) +def zeros(shape: tuple[int, ...], dtype: Dtype = float32) -> Array: + """ + Create a multi-dimensional array filled with zeros + + Parameters + ---------- + shape : tuple[int, ...], optional, default: (1,) + The shape of the constant array. + + dtype : Dtype, optional, default: float32 + Data type of the array. + + Returns + ------- + Array + A multi-dimensional ArrayFire array filled zeros + + Notes + ----- + The shape parameter determines the dimensions of the resulting array: + - If shape is (x1,), the output is a 1D array of size (x1,). + - If shape is (x1, x2), the output is a 2D array of size (x1, x2). + - If shape is (x1, x2, x3), the output is a 3D array of size (x1, x2, x3). + - If shape is (x1, x2, x3, x4), the output is a 4D array of size (x1, x2, x3, x4). + """ + return constant(0, shape, dtype) + +def ones(shape: tuple[int, ...], dtype: Dtype = float32) -> Array: + """ + Create a multi-dimensional array filled with ones + + Parameters + ---------- + shape : tuple[int, ...], optional, default: (1,) + The shape of the constant array. + + dtype : Dtype, optional, default: float32 + Data type of the array. + + Returns + ------- + Array + A multi-dimensional ArrayFire array filled ones + + Notes + ----- + The shape parameter determines the dimensions of the resulting array: + - If shape is (x1,), the output is a 1D array of size (x1,). + - If shape is (x1, x2), the output is a 2D array of size (x1, x2). + - If shape is (x1, x2, x3), the output is a 3D array of size (x1, x2, x3). + - If shape is (x1, x2, x3, x4), the output is a 4D array of size (x1, x2, x3, x4). + """ + return constant(1, shape, dtype) @afarray_as_array def diag(array: Array, /, *, diag_index: int = 0, extract: bool = True) -> Array: @@ -255,8 +311,7 @@ def lower(array: Array, /, *, is_unit_diag: bool = False) -> Array: Notes ----- - The function does not alter the elements above the main diagonal; it simply does not include them in the output. - - This function can be useful for mathematical operations that require lower triangular matrices, such as certain - types of matrix factorizations. + - This function can be useful for mathematical operations that require lower triangular matrices, such as certain types of matrix factorizations. Examples -------- @@ -312,8 +367,7 @@ def upper(array: Array, /, *, is_unit_diag: bool = False) -> Array: Notes ----- - The function does not alter the elements below the main diagonal; it simply does not include them in the output. - - This function can be useful for mathematical operations that require upper triangular matrices, such as certain - types of matrix factorizations. + - This function can be useful for mathematical operations that require upper triangular matrices, such as certain types of matrix factorizations. Examples -------- @@ -818,6 +872,40 @@ def moddims(array: Array, shape: tuple[int, ...], /) -> Array: # TODO add examples to doc return cast(Array, wrapper.moddims(array.arr, shape)) +def reshape(array: Array, shape: tuple[int, ...], /) -> Array: + """ + Modify the shape of the array without changing the data layout. + + Parameters + ---------- + array : af.Array + Multi-dimensional array to be reshaped. + + shape : tuple of int + The desired shape of the output array. It should be a tuple of integers + representing the dimensions of the output array. The product of these + dimensions must match the total number of elements in the input array. + + Returns + ------- + out : af.Array + - An array containing the same data as `array` with the specified shape. + - The total number of elements in `array` must match the product of the + dimensions specified in the `shape` tuple. + + Raises + ------ + ValueError + If the total number of elements in the input array does not match the + product of the dimensions specified in the `shape` tuple. + + Notes + ----- + This function modifies the shape of the input array without changing the + data layout. The resulting array will have the same data, but with a + different shape as specified by the `shape` parameter. + """ + return moddims(array, shape) @afarray_as_array def reorder(array: Array, /, *, shape: tuple[int, ...] = (1, 0, 2, 3)) -> Array: diff --git a/arrayfire/library/computer_vision.py b/arrayfire/library/computer_vision.py index 6683c5b..2e6de41 100644 --- a/arrayfire/library/computer_vision.py +++ b/arrayfire/library/computer_vision.py @@ -164,8 +164,7 @@ def sift( tuple[Features, Array] A tuple containing: - An ArrayFire Features object encapsulating the detected keypoints. - - An ArrayFire Array containing the corresponding descriptors for each keypoint. The descriptors are - 128-dimensional vectors describing the local appearance around each keypoint. + - An ArrayFire Array containing the corresponding descriptors for each keypoint. The descriptors are 128-dimensional vectors describing the local appearance around each keypoint. Note ---- diff --git a/docs/README.md b/docs/README.md index 76f4f32..3fd2f2f 100644 --- a/docs/README.md +++ b/docs/README.md @@ -10,6 +10,7 @@ To build the docs follow these steps: 1. Install the required sphinx packages and extensions from the [dev-requirements.txt](../dev-requirements.txt) ```sh pip install -r dev-requirements.txt # install sphinx and its extensions +pip install -r requirements.txt # install arrayfire-binary-python-wrapper ``` 2. Build docs using sphinx ```sh diff --git a/docs/array_creation_functions.rst b/docs/array_creation_functions.rst new file mode 100644 index 0000000..aaef83d --- /dev/null +++ b/docs/array_creation_functions.rst @@ -0,0 +1,50 @@ +Array Creation Functions +========================== + +Functions in this category are used to initialize arrays with specific values or patterns. + +.. list-table:: Functions + + * - :doc:`af.cast() ` + - Cast an array from one type to another. + * - :doc:`af.constant() ` + - Create an array from a scalar input value. + * - :doc:`af.copy_array() ` + - Performs a deep copy of the array. + * - :doc:`af.cplx() ` + - Creates complex arrays from real and imaginary parts + * - :doc:`af.diag() ` + - Extract the diagonal from an array. + * - :doc:`af.eval() ` + - Evaluate an expression (nonblocking). + * - :doc:`af.gaussian_kernel() ` + - Creates a Gaussian Kernel. + * - :doc:`af.identity() ` + - Generate an identity matrix. + * - :doc:`af.iota() ` + - Generate an array with [0, n-1] values modified to specified dimensions and tiling. + * - :doc:`af.isinf() ` + - Check if values are infinite. + * - :doc:`af.isnan() ` + - Check if values are NaN. + * - :doc:`af.iszero() ` + - Check if values are zero. + * - :doc:`af.lookup() ` + - Lookup values of an array by indexing with another array. + * - :doc:`af.lower() ` + - Return the lower triangular matrix from an input array. + - Find maximum value from a window. + * - :doc:`af.ones() ` + - Creates an array filled with ones.\ + * - :doc:`af.randn() ` + - Create a random array sampled from normal distribution. + * - :doc:`af.randu() ` + - Create a random array sampled from uniform distribution. + * - :doc:`af.range() ` + - Generate an array with [0, n-1] values along the a specified dimension and tiled across other dimensions. + * - :doc:`af.upper() ` + - Return the upper triangular matrix from an input array. + * - :doc:`af.where() ` + - Locate the indices of the non-zero values in an array. + * - :doc:`af.zeros() ` + - Creates an array filled with zeros. \ No newline at end of file diff --git a/docs/array_manipulation_functions.rst b/docs/array_manipulation_functions.rst new file mode 100644 index 0000000..73fbf76 --- /dev/null +++ b/docs/array_manipulation_functions.rst @@ -0,0 +1,55 @@ +Array Manipulation +=================== + +These functions help modify the structure or arrangement of arrays. + +.. list-table:: Functions + + * - :doc:`af.approx1() ` + - Interpolation across a single dimension. + * - :doc:`af.approx1_uniform() ` + - Interpolation across a single dimension in uniform steps + * - :doc:`af.approx2() ` + - Interpolation along two dimensions. + * - :doc:`af.approx2_uniform() ` + - Interpolation along two dimensions in uniform steps + * - :doc:`af.flat() ` + - Flatten an array. + * - :doc:`af.flip() ` + - Flip the input along a specified dimension. + * - :doc:`af.join() ` + - Join up to 4 arrays along specified dimension. + * - :doc:`af.pad() ` + - Pad an array. + * - :doc:`af.reorder() ` + - Reorder an array. + * - :doc:`af.replace() ` + - Replace elements of an array with elements of another array. + * - :doc:`af.reshape() ` + - Modify the dimensions of an array without changing the order of its elements + * - :doc:`af.resize() ` + - Resize an input image. + * - :doc:`af.rotate() ` + - Rotate an input image or array. + * - :doc:`af.scale() ` + - Scale an input image. + * - :doc:`af.select() ` + - Select elements based on a conditional array. + * - :doc:`af.set_intersect() ` + - Evaluate the intersection of two arrays + * - :doc:`af.set_union() ` + - Evaluate the union of two arrays + * - :doc:`af.set_unique() ` + - Return the unique values in an array + * - :doc:`af.shift() ` + - Shift an array. + * - :doc:`af.sort() ` + - Sort an array over a given dimension + * - :doc:`af.tile() ` + - Generate a tiled array by repeating an array's contents along a specified dimension. + * - :doc:`af.transpose() ` + - Transpose a matrix. + * - :doc:`af.unwrap() ` + - Rearrange windowed sections of an array into columns (or rows) + * - :doc:`af.wrap() ` + - Performs the opposite of af::unwrap(). \ No newline at end of file diff --git a/docs/arrayandmatrixmanipulation.rst b/docs/arrayandmatrixmanipulation.rst index bf73261..fbc0fc2 100644 --- a/docs/arrayandmatrixmanipulation.rst +++ b/docs/arrayandmatrixmanipulation.rst @@ -2,17 +2,17 @@ Array and Matrix Manipulation ============================= ArrayFire provides several different methods for manipulating arrays and matrices. The functionality includes: -* moddims() - change the dimensions of an array without changing the data -* array() - create a (shallow) copy of an array with different dimensions. -* flat() - flatten an array to one dimension -* flip() - flip an array along a dimension -* join() - join up to 4 arrays -* reorder() - changes the dimension order within the array -* shift() - shifts data along a dimension -* tile() - repeats an array along a dimension -* transpose() - performs a matrix transpose -* T() - transpose a matrix or vector (shorthand notation) -* H() - Hermitian Transpose (conjugate-transpose) a matrix +* :doc:`moddims() ` - change the dimensions of an array without changing the data +* :doc:`Array() ` - create a (shallow) copy of an array with different dimensions. +* :doc:`flat() ` - flatten an array to one dimension +* :doc:`flip() ` - flip an array along a dimension +* :doc:`join() ` - join up to 4 arrays +* :doc:`reorder() ` - changes the dimension order within the array +* :doc:`shift() ` - shifts data along a dimension +* :doc:`tile() ` - repeats an array along a dimension +* :doc:`transpose() ` - performs a matrix transpose +* :doc:`Array property T ` - transpose a matrix or vector (shorthand notation) +* :doc:`Array property H ` - Hermitian Transpose (conjugate-transpose) a matrix Below we provide several examples of these functions and their use. @@ -138,7 +138,8 @@ The python interface for transpose is as follows: -array() +Array() ******* -**array()** can be used to create a (shallow) copy of a matrix with different dimensions. The total number of elements must remain the same. This function is a wrapper over the moddims() function discussed earlier. +**Array()** can be used to create a (shallow) copy of another Array with dimensions different to the original. +The total number of elements must remain the same. This function is a wrapper over the moddims() function discussed earlier. diff --git a/docs/classes/Features.rst b/docs/classes/Features.rst new file mode 100644 index 0000000..b977887 --- /dev/null +++ b/docs/classes/Features.rst @@ -0,0 +1,4 @@ +Features +========== + +.. autoclass:: arrayfire.library.features.Features \ No newline at end of file diff --git a/docs/classes/RandomEngine.rst b/docs/classes/RandomEngine.rst new file mode 100644 index 0000000..e44f2c6 --- /dev/null +++ b/docs/classes/RandomEngine.rst @@ -0,0 +1,7 @@ +Random Engine +============== + +.. autoclass:: arrayfire.library.random.RandomEngine + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/classes/array.rst b/docs/classes/array.rst new file mode 100644 index 0000000..75339ad --- /dev/null +++ b/docs/classes/array.rst @@ -0,0 +1,37 @@ +Array +===== + +The 'af.Array()' class provides a powerful framework for performing high-performance numerical computations. It is designed to create an ArrayFire array from various data structures, such as Python lists or other iterable collections. + +Function +-------- +:literal:`af.Array()` + - Python interface to form an array. + + +Detailed Description +-------------------- +The 'af.Array()' object allows you to convert a data structure, such as a Python list or tuple, into an ArrayFire array. This conversion is essential for leveraging ArrayFire's optimized computational capabilities. By creating an array from a list or another iterable, you can perform efficient mathematical operations, matrix manipulations, and other numerical computations using ArrayFire's APIs. + +It supports multiple data types and can handle multi-dimensional arrays. The ability to create an ArrayFire array from native Python structures makes it easier to integrate ArrayFire into Python-based workflows. + +Function Documentation +---------------------- +.. sidebar:: af.Array() + + Syntax: + af.Array(data) + + Parameters: + 'data': A list, tuple, or another iterable containing the elements to be converted into an ArrayFire array. The data should be in a format that ArrayFire can interpret, such as nested lists for multi-dimensional arrays. + + Returns: + An ArrayFire array containing the elements from the input data structure. + +.. autoclass:: arrayfire.Array + :members: + :undoc-members: + :show-inheritance: + + + diff --git a/docs/classes/index.rst b/docs/classes/index.rst new file mode 100644 index 0000000..0fa4715 --- /dev/null +++ b/docs/classes/index.rst @@ -0,0 +1,10 @@ +:orphan: + +.. toctree:: + :hidden: + :maxdepth: 1 + :caption: Classes List: + + Features + RandomEngine + array diff --git a/docs/conf.py b/docs/conf.py index fbbf089..ca827f1 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -36,7 +36,10 @@ html_theme = 'sphinxawesome_theme' html_static_path = ['_static'] html_permalinks = False -html_logo = "_static/../images/arrayfire_icon.png" +html_theme_options = { + "logo_light": "_static/../images/arrayfire_icon.png", + "logo_dark": "_static/../images/arrayfire_icon.png" +} # -- Suppress specific warnings -------------------------------------------- diff --git a/docs/constants/BinaryOperator.rst b/docs/constants/BinaryOperator.rst new file mode 100644 index 0000000..3cc695f --- /dev/null +++ b/docs/constants/BinaryOperator.rst @@ -0,0 +1,7 @@ +BinaryOperator Enum +==================== + +.. autoclass:: arrayfire_wrapper.lib.BinaryOperator + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/constants/CSpace.rst b/docs/constants/CSpace.rst new file mode 100644 index 0000000..84bfea7 --- /dev/null +++ b/docs/constants/CSpace.rst @@ -0,0 +1,7 @@ +CSpace Enum +============ + +.. autoclass:: arrayfire_wrapper.lib.CSpace + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/constants/CannyThreshold.rst b/docs/constants/CannyThreshold.rst new file mode 100644 index 0000000..1929d9a --- /dev/null +++ b/docs/constants/CannyThreshold.rst @@ -0,0 +1,7 @@ +CannyThreshold Enum +==================== + +.. autoclass:: arrayfire_wrapper.lib.CannyThreshold + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/constants/Connectivity.rst b/docs/constants/Connectivity.rst new file mode 100644 index 0000000..045165b --- /dev/null +++ b/docs/constants/Connectivity.rst @@ -0,0 +1,7 @@ +Connectivity Enum +================== + +.. autoclass:: arrayfire_wrapper.lib.Connectivity + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/constants/ConvDomain.rst b/docs/constants/ConvDomain.rst new file mode 100644 index 0000000..e7032ca --- /dev/null +++ b/docs/constants/ConvDomain.rst @@ -0,0 +1,7 @@ +ConvDomain Enum +================ + +.. autoclass:: arrayfire_wrapper.lib.ConvDomain + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/constants/ConvGradient.rst b/docs/constants/ConvGradient.rst new file mode 100644 index 0000000..32d7680 --- /dev/null +++ b/docs/constants/ConvGradient.rst @@ -0,0 +1,7 @@ +ConvGradient Enum +================== + +.. autoclass:: arrayfire_wrapper.lib.ConvGradient + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/constants/ConvMode.rst b/docs/constants/ConvMode.rst new file mode 100644 index 0000000..73465fa --- /dev/null +++ b/docs/constants/ConvMode.rst @@ -0,0 +1,7 @@ +ConvMode Enum +============== + +.. autoclass:: arrayfire_wrapper.lib.ConvMode + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/constants/Diffusion.rst b/docs/constants/Diffusion.rst new file mode 100644 index 0000000..1d594c7 --- /dev/null +++ b/docs/constants/Diffusion.rst @@ -0,0 +1,7 @@ +Diffusion Enum +=============== + +.. autoclass:: arrayfire_wrapper.lib.Diffusion + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/constants/Dtype.rst b/docs/constants/Dtype.rst new file mode 100644 index 0000000..a1f6200 --- /dev/null +++ b/docs/constants/Dtype.rst @@ -0,0 +1,28 @@ +Supported Data Types +===================== + +.. autodata:: arrayfire_wrapper.b8 + +.. autodata:: arrayfire_wrapper.u8 + +.. autodata:: arrayfire_wrapper.u16 + +.. autodata:: arrayfire_wrapper.u32 + +.. autodata:: arrayfire_wrapper.u64 + +.. autodata:: arrayfire_wrapper.s16 + +.. autodata:: arrayfire_wrapper.s32 + +.. autodata:: arrayfire_wrapper.s64 + +.. autodata:: arrayfire_wrapper.f16 + +.. autodata:: arrayfire_wrapper.f32 + +.. autodata:: arrayfire_wrapper.f64 + +.. autodata:: arrayfire_wrapper.c32 + +.. autodata:: arrayfire_wrapper.c64 \ No newline at end of file diff --git a/docs/constants/Flux.rst b/docs/constants/Flux.rst new file mode 100644 index 0000000..ff66c20 --- /dev/null +++ b/docs/constants/Flux.rst @@ -0,0 +1,7 @@ +Flux Enum +========== + +.. autoclass:: arrayfire_wrapper.lib.Flux + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/constants/ImageFormat.rst b/docs/constants/ImageFormat.rst new file mode 100644 index 0000000..6d704bc --- /dev/null +++ b/docs/constants/ImageFormat.rst @@ -0,0 +1,7 @@ +ImageFormat Enum +================= + +.. autoclass:: arrayfire_wrapper.lib.ImageFormat + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/constants/Interp.rst b/docs/constants/Interp.rst new file mode 100644 index 0000000..63d40bc --- /dev/null +++ b/docs/constants/Interp.rst @@ -0,0 +1,7 @@ +Interp Enum +============ + +.. autoclass:: arrayfire_wrapper.lib.Interp + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/constants/IterativeDeconv.rst b/docs/constants/IterativeDeconv.rst new file mode 100644 index 0000000..bab1a17 --- /dev/null +++ b/docs/constants/IterativeDeconv.rst @@ -0,0 +1,7 @@ +IterativeDeconv Enum +===================== + +.. autoclass:: arrayfire_wrapper.lib.IterativeDeconv + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/constants/MatProp.rst b/docs/constants/MatProp.rst new file mode 100644 index 0000000..8c0e693 --- /dev/null +++ b/docs/constants/MatProp.rst @@ -0,0 +1,7 @@ +MatProp Enum +============= + +.. autoclass:: arrayfire_wrapper.lib.MatProp + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/constants/Match.rst b/docs/constants/Match.rst new file mode 100644 index 0000000..0802fd0 --- /dev/null +++ b/docs/constants/Match.rst @@ -0,0 +1,7 @@ +Match Enum +=========== + +.. autoclass:: arrayfire_wrapper.lib.Match + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/constants/Norm.rst b/docs/constants/Norm.rst new file mode 100644 index 0000000..7b96d28 --- /dev/null +++ b/docs/constants/Norm.rst @@ -0,0 +1,7 @@ +Norm Enum +========== + +.. autoclass:: arrayfire_wrapper.lib.Norm + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/constants/Pad.rst b/docs/constants/Pad.rst new file mode 100644 index 0000000..fdf2b4c --- /dev/null +++ b/docs/constants/Pad.rst @@ -0,0 +1,7 @@ +Pad Enum +========= + +.. autoclass:: arrayfire_wrapper.lib.Pad + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/constants/RandomEngineType.rst b/docs/constants/RandomEngineType.rst new file mode 100644 index 0000000..4091fdb --- /dev/null +++ b/docs/constants/RandomEngineType.rst @@ -0,0 +1,7 @@ +RandomEngineType Enum +====================== + +.. autoclass:: arrayfire.library.random.RandomEngineType + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/constants/TopK.rst b/docs/constants/TopK.rst new file mode 100644 index 0000000..3f51fcc --- /dev/null +++ b/docs/constants/TopK.rst @@ -0,0 +1,7 @@ +TopK Enum +========== + +.. autoclass:: arrayfire_wrapper.lib.TopK + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/constants/VarianceBias.rst b/docs/constants/VarianceBias.rst new file mode 100644 index 0000000..6b1c13c --- /dev/null +++ b/docs/constants/VarianceBias.rst @@ -0,0 +1,7 @@ +VarianceBias Enum +================== + +.. autoclass:: arrayfire_wrapper.lib.VarianceBias + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/constants/YCCStd.rst b/docs/constants/YCCStd.rst new file mode 100644 index 0000000..0041f55 --- /dev/null +++ b/docs/constants/YCCStd.rst @@ -0,0 +1,7 @@ +YCCStd Enum +============ + +.. autoclass:: arrayfire_wrapper.lib.YCCStd + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/constants/index.rst b/docs/constants/index.rst new file mode 100644 index 0000000..d0f6e51 --- /dev/null +++ b/docs/constants/index.rst @@ -0,0 +1,28 @@ +:orphan: + +.. toctree:: + :hidden: + :maxdepth: 1 + :caption: Constants List: + + BinaryOperator + CSpace + CannyThreshold + Connectivity + ConvDomain + ConvGradient + ConvMode + Diffusion + Dtype + Flux + ImageFormat + Interp + IterativeDeconv + MatProp + Match + Norm + Pad + RandomEngineType + TopK + VarianceBias + YCCStd diff --git a/docs/data_reduction_functions.rst b/docs/data_reduction_functions.rst new file mode 100644 index 0000000..7544ce6 --- /dev/null +++ b/docs/data_reduction_functions.rst @@ -0,0 +1,41 @@ +Data Reduction +=============== + +Functions for aggregating and reducing data to summarize or condense information. + +.. list-table:: + + * - :doc:`af.accum() ` + - Evaluate the cumulative sum (inclusive) along a given dimension. + * - :doc:`af.all_true() ` + - Check if all values along a given dimension are true. + * - :doc:`af.any_true() ` + - Check if any values along a given dimension are true. + * - :doc:`af.count() ` + - Count non-zero values in an array along a given dimension. + * - :doc:`af.dot() ` + - Compute the dot product. + * - :doc:`af.imax() ` + - Finds the maximum value. + * - :doc:`af.imin() ` + - Finds the minimum value. + * - :doc:`af.max() ` + - Return the maximum along a given dimension. + * - :doc:`af.maxof() ` + - Elementwise maximum between two arrays + * - :doc:`af.mean() ` + - Find the mean of values in the input. + * - :doc:`af.median() ` + - Find the median of values in the input. + * - :doc:`af.min() ` + - Return the minimum along a given dimension. + * - :doc:`af.minof() ` + - Elementwise minimum between two arrays + * - :doc:`af.product() ` + - Multiply array elements over a given dimension. + * - :doc:`af.scan() ` + - Scan an array (generalized) over a given dimension. + * - :doc:`af.sttdev() ` + - Find the standard deviation of values in the input. + * - :doc:`af.sum() ` + - Sum array elements over a given dimension. \ No newline at end of file diff --git a/docs/debuggingarrayfirecode.rst b/docs/debuggingarrayfirecode.rst index 800fdd6..c87c7d4 100644 --- a/docs/debuggingarrayfirecode.rst +++ b/docs/debuggingarrayfirecode.rst @@ -1,9 +1,71 @@ Debugging ArrayFire Issues ========================== -Python -~~~~~~ -* :literal:`arrayfire.device.print_mem_info("message")`: Print table of memory used by ArrayFire on the active GPU + +Using Exceptions +################# + +When an error is encountered (incorrect arguments or some calculation error), ArrayFire will raise an exception. This exception +contains a stacktrace on which arrayfire function is raising the error and what is the cause for it. For example, this code will raise +an print an exception: + +.. code-block:: python + + import arrayfire as af + x = af.randu(10) + y = af.randu(5) + + try: + # Arrays have non-broadcastable shapes + res = x + y + catch Exception as e: + print(e) + +This may produce the following output + +.. code-block:: bash + + In function arithOpBroadcast + In file src\api\c\binary.cpp:81 + Invalid dimension for argument 1 + Expected: ((lshape[d] == rshape[d]) || (lshape[d] == 1 && rshape[d] > 1) || (lshape[d] > 1 && rshape[d] == 1)) + 0# af::exception::~exception in afcuda + 1# af_bilateral in afcuda + 2# af_bilateral in afcuda + 3# af_add in afcuda + 4# ffi_prep_go_closure in libffi_8 + 5# ffi_call_go in libffi_8 + 6# ffi_call in libffi_8 + 7# 0x00007FFCD2833C05 in _ctypes + 8# 0x00007FFCD2832ACA in _ctypes + 9# 0x00007FFCD28326C8 in _ctypes + + +Using ArrayFire Debug/Utility Functions +######################################## + +For issues with specific devices or memory limitations, ArrayFire provides functions to inform the user the current +device and allocations. + +For checking device information we have the functions: + +* :doc:`get_device() ` and :doc:`get_device_count()` gets the devices on the current backend +* :doc:`get_dbl_support(device_id)` and :doc:`get_half_support(device_id)` provides information for f64 and f16 type support +* :doc:`device_info(device_id)`, :doc:`info()`, :doc:`info_string()` provides backend, vendor, and version of device +* :doc:`device_gc()` forces garbage collection of unused arrays on current device +* :doc:`get_mem_step_size()` and :doc:`set_mem_step_size(mem_size)` allows getting and setting the size of allocation groups +* :doc:`print_mem_info(prepend_message, device_id)`: Print table of memory used by ArrayFire on the selected device + +Using ArrayFire's environment variables +####################################### + +For internal information related to the kernels generated by the JIT, allocation triggers, and extra information, ArrayFire +provides environment variables that enable extra tracing information that will be printed into stdout. + +Please check the section of +:doc:`Debugging Environment Variables in Configuring ArrayFire Environment` +for a list of all the debug variables and their usage. Further Reading ############### -See the `ArrayFire README `_ for support information. \ No newline at end of file +For outstanding issues related to ArrayFire, you may visit the Github Issues in `ArrayFire Python `_ +and `ArrayFire C/C++ Libraries `_ \ No newline at end of file diff --git a/docs/fourier_transforms_functions.rst b/docs/fourier_transforms_functions.rst new file mode 100644 index 0000000..4e72042 --- /dev/null +++ b/docs/fourier_transforms_functions.rst @@ -0,0 +1,41 @@ +Fourier Transform +=================== + +Functions for performing Fourier analysis, essential for signal processing and frequency analysis. + +.. list-table:: Functions + + * - :doc:`af.fast() ` + - FAST feature detector. + * - :doc:`af.fft() ` + - Fast Fourier Transform. + * - :doc:`af.fft2() ` + - Fast Fourier Transform. + * - :doc:`af.fft2_c2r() ` + - Fast fourier transform on two dimensional real signals producing complex output + * - :doc:`af.fft2_r2c() ` + - Fast fourier transform on two dimensional real signals producing complex output + * - :doc:`af.fft3() ` + - Fast Fourier Transform. + * - :doc:`af.fft3_c2r() ` + - Fast fourier transform on three dimensional real signals producing complex output + * - :doc:`af.fft3_r2c() ` + - Fast fourier transform on three dimensional real signals producing complex output + * - :doc:`af.fft_c2r() ` + - Fast fourier transform on complex signals producing real output + * - :doc:`af.fft_convolve1() ` + - FFT-based convolution for one dimensional signals + * - :doc:`af.fft_convolve2() ` + - FFT-based convolution for two dimensional signals + * - :doc:`af.fft_convolve3() ` + - FFT-based convolution for three dimensional signals + * - :doc:`af.fft_r2c() ` + - Fast fourier transform on real signals producing complex output + * - :doc:`af.ifft() ` + - Fast Fourier Transform. + * - :doc:`af.ifft2() ` + - Fast Fourier Transform. + * - :doc:`af.ifft3() ` + - Fast Fourier Transform. + * - :doc:`af.set_fft_plan_cache_size() ` + - Sets fft plan cache size \ No newline at end of file diff --git a/docs/functions.rst b/docs/functions.rst index 7351f55..d809160 100644 --- a/docs/functions.rst +++ b/docs/functions.rst @@ -1,6 +1,23 @@ Functions ========= +.. include:: classes/index +.. include:: functions/index +.. include:: constants/index + +.. toctree:: + :hidden: + + array_creation_functions + array_manipulation_functions + fourier_transforms_functions + data_reduction_functions + linear_algebra_functions + mathematical_operations_functions + special_functions + statistics_functions + utilities_functions + Documentation grouped by category: @@ -8,181 +25,560 @@ Documentation grouped by category: .. list-table:: - * - `af.Array` + * - :doc:`af.Array ` - Represents an ArrayFire array + * - :doc:`af.library.random.RandomEngine ` + - Reperesents an ArrayFire custom random engine + * - :doc:`af.library.features.Features ` + - Represents an ArrayFire Feature Extraction class .. collapse:: Arrayfire Functions .. list-table:: - * - :doc:`af.array() ` - - Creates an array from a list or other data structure. - * - :doc:`af.zeros() ` - - Creates an array filled with zeros. - * - :doc:`af.ones() ` - - Creates an array filled with ones. - * - :doc:`af.constant() ` - - Creates an array filled with a scalar value. - * - :doc:`af.iota() ` - - Creates an array filled with a range of linear indices along multiple dimensions - * - :doc:`af.range() ` - - Creates an array filled with a range of linear indices along a dimension. - * - :doc:`af.identity() ` - - Creates an identity matrix or batch of identity matrices. - * - :doc:`af.add() ` - - Performs element-wise addition. - * - :doc:`af.subtract() ` - - Performs element-wise subtraction. - * - :doc:`af.multiply() ` - - Performs element-wise multiplication. - * - :doc:`af.divide() ` - - Performs element-wise division. - * - :doc:`af.mod() ` - - Calculate the modulus of two arrays or a scalar and an array. - * - :doc:`af.sqrt() ` - - Computes the square root of each element. - * - :doc:`af.exp() ` - - Computes the exponential of each element. - * - :doc:`af.log() ` - - Computes the natural logarithm of each element. + * - :doc:`af.abs() ` + - Calculate the absolute value. * - :doc:`af.accum() ` - - Calculate the cumulative sum of elements along a specified dimension. - * - :doc:`af.sum() ` - - Computes the sum of elements. - * - :doc:`af.product() ` - - Computes the product of elements. + - Evaluate the cumulative sum (inclusive) along a given dimension. + * - :doc:`af.acos() ` + - Evaluate the inverse cosine function (arc cosine). + * - :doc:`af.acosh() ` + - Evaluate the inverse hyperbolic cosine function (area hyperbolic cosine). + * - :doc:`af.add() ` + - Elementwise addition. + * - :doc:`af.all_true() ` + - Check if all values along a given dimension are true. + * - :doc:`af.alloc_device() ` + - Allocate memory on device + * - :doc:`af.alloc_host() ` + - Allocate memory on host. + * - :doc:`af.alloc_pinned() ` + - Allocate pinned memory on device. + * - :doc:`af.anisotropic_diffusion() ` + - Anisotropic Smoothing Filter. + * - :doc:`af.any_true() ` + - Check if any values along a given dimension are true. + * - :doc:`af.approx1() ` + - Interpolation across a single dimension. + * - :doc:`af.approx1_uniform() ` + - Interpolation across a single dimension in uniform steps + * - :doc:`af.approx2() ` + - Interpolation along two dimensions. + * - :doc:`af.approx2_uniform() ` + - Interpolation along two dimensions in uniform steps + * - :doc:`af.arg() ` + - Calculate the phase angle (in radians) of a complex array. + * - :doc:`af.asin() ` + - Evaluate the inverse sine function (arc sine). + * - :doc:`af.asinh() ` + - Evaluate the inverse hyperbolic sine function (area hyperbolic sine). + * - :doc:`af.atan() ` + - Evaluate the inverse tangent function (arc tangent). + * - :doc:`af.atan2() ` + - Evaluate the inverse tangent function (arc tangent). + * - :doc:`af.atanh() ` + - Evaluate the inverse hyperbolic tangent function (area hyperbolic tangent). + * - :doc:`af.bilateral() ` + - Bilateral Filter. + * - :doc:`af.bitand() ` + - Evaluate the bitwise AND of two arrays. + * - :doc:`af.bitnot() ` + - Evaluate the bitwise NOT of an array. + * - :doc:`af.bitor() ` + - Evaluate the bitwise OR of two arrays. + * - :doc:`af.bitshiftl() ` + - Shift the bits of integer arrays left. + * - :doc:`af.bitshiftr() ` + - Shift the bits of integer arrays right. + * - :doc:`af.bitxor() ` + - Evaluate the bitwise XOR of two arrays. + * - :doc:`af.canny() ` + - Canny Edge Detector. + * - :doc:`af.cast() ` + - Cast an array from one type to another. + * - :doc:`af.cbrt() ` + - Evaluate the cube root. + * - :doc:`af.ceil() ` + - Rounds up to the least integer greater than or equal to x. + * - :doc:`af.cholesky() ` + - Perform Cholesky decomposition. + * - :doc:`af.clamp() ` + - Clamp an array between an upper and a lower limit. + * - :doc:`af.color_space() ` + - Colorspace conversion function. + * - :doc:`af.confidence_cc() ` + - Segment image based on similar pixel characteristics. + * - :doc:`af.conjg() ` + - Evaluate the complex conjugate of an input array. + * - :doc:`af.constant() ` + - Create an array from a scalar input value. + * - :doc:`af.convolve1() ` + - Convolution Integral for one dimensional data. + * - :doc:`af.convolve2() ` + - Convolution Integral for two dimensional data. + * - :doc:`af.convolve2_gradient_nn() ` + - Version of convolution that is consistent with the machine learning formulation that will spatially convolve a filter on 2-dimensions against a signal. + * - :doc:`af.convolve2_nn() ` + - Version of convolution that is consistent with the machine learning formulation that will spatially convolve a filter on 2-dimensions against a signal. + * - :doc:`af.convolve2_separable() ` + - Faster equivalent of the canonical 2D convolution for filters/kernels that can be decomposed into two separate spatial vectors. + * - :doc:`af.convolve3() ` + - Convolution Integral for three dimensional data. + * - :doc:`af.copy_array() ` + - Performs a deep copy of the array. + * - :doc:`af.cos() ` + - Evaluate the cosine function. + * - :doc:`af.cosh() ` + - Evaluate the hyperbolic cosine function. + * - :doc:`af.count() ` + - Count non-zero values in an array along a given dimension. + * - :doc:`af.cplx() ` + - Creates complex arrays from real and imaginary parts + * - :doc:`af.cublas_set_math_mode() ` + - Sets the cuBLAS math mode for the internal handle + * - :doc:`af.delete_image_memory() ` + - Delete memory created by saveImageMem + * - :doc:`af.det() ` + - Find the determinant of a matrix. + * - :doc:`af.device_gc() ` + - Call the garbage collection routine + * - :doc:`af.device_info() ` + - Gets the information about device and platform as strings. + * - :doc:`af.device_mem_info() ` + - Gets information about the memory manager + * - :doc:`af.diag() ` + - Extract the diagonal from an array. * - :doc:`af.diff1() ` - - Computes the first-order differences of an ArrayFire array along a specified dimension. + - Calculate the first order difference in an array over a given dimension. * - :doc:`af.diff2() ` - - Computes the second-order differences of an ArrayFire array along a specified dimension. + - Calculate the second order difference in an array over a given dimension. + * - :doc:`af.dilate() ` + - Dilation(morphological operator) for images. + * - :doc:`af.div() ` + - Elementwise division. + * - :doc:`af.dog() ` + - Difference of Gaussians. + * - :doc:`af.dot() ` + - Compute the dot product. + * - :doc:`af.eq() ` + - Equal to, an elementwise comparison of two arrays. + * - :doc:`af.erf() ` + - Evaluate the error function. + * - :doc:`af.erfc() ` + - Evaluate the complementary error function. + * - :doc:`af.erode() ` + - Erosion(morphological operator) for images. + * - :doc:`af.eval() ` + - Evaluate an expression (nonblocking). + * - :doc:`af.exp() ` + - Evaluate the exponential function. + * - :doc:`af.expm1() ` + - Evaluate the exponential function of an array minus 1, exp(in) - 1. + * - :doc:`af.factorial() ` + - Evaluate the factorial. + * - :doc:`af.fast() ` + - FAST feature detector. + * - :doc:`af.fft() ` + - Fast Fourier Transform. + * - :doc:`af.fft2() ` + - Fast Fourier Transform. + * - :doc:`af.fft2_c2r() ` + - Fast fourier transform on two dimensional real signals producing complex output + * - :doc:`af.fft2_r2c() ` + - Fast fourier transform on two dimensional real signals producing complex output + * - :doc:`af.fft3() ` + - Fast Fourier Transform. + * - :doc:`af.fft3_c2r() ` + - Fast fourier transform on three dimensional real signals producing complex output + * - :doc:`af.fft3_r2c() ` + - Fast fourier transform on three dimensional real signals producing complex output + * - :doc:`af.fft_c2r() ` + - Fast fourier transform on complex signals producing real output + * - :doc:`af.fft_convolve1() ` + - FFT-based convolution for one dimensional signals + * - :doc:`af.fft_convolve2() ` + - FFT-based convolution for two dimensional signals + * - :doc:`af.fft_convolve3() ` + - FFT-based convolution for three dimensional signals + * - :doc:`af.fft_r2c() ` + - Fast fourier transform on real signals producing complex output + * - :doc:`af.fir() ` + - This function implements a Finite Impulse Filter. + * - :doc:`af.flat() ` + - Flatten an array. + * - :doc:`af.flip() ` + - Flip the input along a specified dimension. + * - :doc:`af.floor() ` + - Rounds down to the greatest integer less than or equal to x. + * - :doc:`af.free_device() ` + - Free memory allocated on device internally by ArrayFire. + * - :doc:`af.free_host() ` + - Free memory allocated on host internally by ArrayFire. + * - :doc:`af.free_pinned() ` + - Free pinned memory allocated by ArrayFire's memory manager. + * - :doc:`af.gaussian_kernel() ` + - Creates a Gaussian Kernel. + * - :doc:`af.ge() ` + - Greater than or equal to, an elementwise comparison of two arrays. + * - :doc:`af.gemm() ` + - General matrix multiplication. + * - :doc:`af.get_backend() ` + - Gets the backend enum for the active backend. + * - :doc:`af.get_dbl_support() ` + - Gets if the device supports double floating point + * - :doc:`af.get_device() ` + - Get the current device ID. + * - :doc:`af.get_device_count() ` + - Gets the number of compute devices on the system. + * - :doc:`af.get_half_support() ` + - Gets if the device supports half floating point + * - :doc:`af.get_kernel_cache_directory() ` + - Returns directory where ArrayFire JIT kernels are being stored + * - :doc:`af.get_mem_step_size() ` + - Get the minimum memory chunk size. + * - :doc:`af.get_native_id() ` + - Get the native device id of the CUDA device with id in ArrayFire context + * - :doc:`af.get_stream() ` + - Returns the current cuda stream + * - :doc:`af.gloh() ` + - SIFT feature detector and GLOH descriptor extractor. * - :doc:`af.gradient() ` - - Computes the horizontal and vertical gradients of a 2D ArrayFire array or a batch of 2D arrays. - * - :doc:`af.mean() ` - - Computes the mean of elements. - * - :doc:`af.median() ` - - Computes the median value. - * - :doc:`af.stdev() ` - - Computes the standard deviation. - * - :doc:`af.min() ` - - Finds the minimum value. - * - :doc:`af.max() ` + - Calculate the gradients of the input + * - :doc:`af.gray2rgb() ` + - Grayscale to RGB colorspace converter. + * - :doc:`af.gt() ` + - Greater than comparison, an elementwise comparison of two arrays. + * - :doc:`af.hamming_matcher() ` + - Calculates Hamming distances between two 2-dimensional arrays + * - :doc:`af.harris() ` + - Harris corner detector. + * - :doc:`af.hist_equal() ` + - Histogram equalization of input image. + * - :doc:`af.histogram() ` + - Histogram of input data. + * - :doc:`af.hsv2rgb() ` + - HSV to RGB colorspace converter. + * - :doc:`af.hypot() ` + - Evaluate the length of the hypotenuse of two inputs. + * - :doc:`af.identity() ` + - Generate an identity matrix. + * - :doc:`af.ifft() ` + - Fast Fourier Transform. + * - :doc:`af.ifft2() ` + - Fast Fourier Transform. + * - :doc:`af.ifft3() ` + - Fast Fourier Transform. + * - :doc:`af.iir() ` + - This function implements a Infinite Impulse Filter. + * - :doc:`af.imag() ` + - Returns the imaginary part of a complex array. + * - :doc:`af.imax() ` - Finds the maximum value. * - :doc:`af.imin() ` - Finds the minimum value. - * - :doc:`af.imax() ` - - Finds the maximum value. - * - :doc:`af.all_true() ` - - Check if all the elements along a specified dimension are true. - * - :doc:`af.any_true() ` - - Check if any of the elements along a specified dimension are true. - * - :doc:`af.isinf() ` - - Returns a boolean array with entries as the boolean result from checking for infinity - * - :doc:`af.randu() ` - - Creates an array with random uniform values. - * - :doc:`af.randn() ` - - Creates an array with random normal values. + * - :doc:`af.info() ` + - Display ArrayFire and device info. + * - :doc:`af.info_string() ` + - Returns a string with information of current device and backend + * - :doc:`af.init() ` + - Initializes ArrayFire * - :doc:`af.inv() ` - Computes the inverse of a matrix. - * - :doc:`af.dot() ` - - Computes the dot product of two arrays. + * - :doc:`af.inverse() ` + - Invert a matrix. + * - :doc:`af.inverse_deconv() ` + - Inverse Deconvolution using linear algebra (non-iterative) methods + * - :doc:`af.iota() ` + - Generate an array with [0, n-1] values modified to specified dimensions and tiling. + * - :doc:`af.is_image_io_available() ` + - Checks if Image IO is available + * - :doc:`af.is_lapack_available() ` + - Check if lapack runtimes are available + * - :doc:`af.isinf() ` + - Check if values are infinite. + * - :doc:`af.isnan() ` + - Check if values are NaN. + * - :doc:`af.iszero() ` + - Check if values are zero. + * - :doc:`af.iterative_deconv() ` + - Inverse Deconvolution using iterative methods + * - :doc:`af.join() ` + - Join up to 4 arrays along specified dimension. + * - :doc:`af.le() ` + - Less than or equal to, an elementwise comparison of two arrays. + * - :doc:`af.lgamma() ` + - Evaluate the logarithm of the absolute value of the gamma function. + * - :doc:`af.load_image() ` + - Load an image from disk to an array + * - :doc:`af.load_image_memory() ` + - Load an image from memory which is stored as a FreeImage stream + * - :doc:`af.load_image_native() ` + - Load an image as is original type. + * - :doc:`af.log() ` + - Evaluate the natural logarithm. + * - :doc:`af.log10() ` + - Evaluate the base 10 logarithm. + * - :doc:`af.log1p() ` + - Evaluate the natural logarithm of 1 + input, ln(1+in). + * - :doc:`af.log2() ` + - Evaluate the base 2 logarithm. + * - :doc:`af.logical_and() ` + - Evaluate the logical and between two arrays + * - :doc:`af.logical_not() ` + - Evaluate the logical not of an array + * - :doc:`af.logical_or() ` + - Evaluate the logical or between two arrays + * - :doc:`af.lookup() ` + - Lookup values of an array by indexing with another array. + * - :doc:`af.lower() ` + - Return the lower triangular matrix from an input array. + * - :doc:`af.lt() ` + - Less than, an elementwise comparison of two arrays. + * - :doc:`af.lu() ` + - Perform LU decomposition. * - :doc:`af.matmul() ` - Matrix multiplication. - * - :doc:`af.gemm() ` - - General matrix multiplication. - * - :doc:`af.eig() ` - - Computes eigenvalues and eigenvectors. - * - :doc:`af.det() ` - - Computes the determinant of a matrix. - * - :doc:`af.fft() ` - - Computes the Fast Fourier Transform. - * - :doc:`af.ifft() ` - - Computes the Inverse Fast Fourier Transform. - * - :doc:`af.count() ` - - Count the number of non-zero elements in an ArrayFire array along a specified dimension. - * - :doc:`af.sort() ` - - Sorts the elements of an ArrayFire array along a specified dimension. + * - :doc:`af.max() ` + - Return the maximum along a given dimension. + * - :doc:`af.maxfilt() ` + - Find maximum value from a window. + * - :doc:`af.maxof() ` + - Elementwise maximum between two arrays + * - :doc:`af.mean() ` + - Find the mean of values in the input. + * - :doc:`af.mean_shift() ` + - Edge-preserving smoothing filter commonly used in object tracking and image segmentation. + * - :doc:`af.medfilt() ` + - Median Filter. + * - :doc:`af.medfilt1() ` + - 1D Median Filter. + * - :doc:`af.medfilt2() ` + - 2D Median Filter. + * - :doc:`af.median() ` + - Find the median of values in the input. + * - :doc:`af.min() ` + - Return the minimum along a given dimension. + * - :doc:`af.minfilt() ` + - Find minimum value from a window. + * - :doc:`af.minof() ` + - Elementwise minimum between two arrays + * - :doc:`af.mod() ` + - Calculate the modulus. + * - :doc:`af.moddims() ` + - Modify the dimensions of an array without changing the order of its elements. + * - :doc:`af.mul() ` + - Elementwise multiply. + * - :doc:`af.nearest_neighbour() ` + - Calculates which points in the train are nearest to each other point + * - :doc:`af.neg() ` + - Negate an array. + * - :doc:`af.neq() ` + - Not equal to, an elementwise comparison of two arrays. + * - :doc:`af.norm() ` + - Find the norm of a matrix. + * - :doc:`af.ones() ` + - Creates an array filled with ones. + * - :doc:`af.orb() ` + - ORB Feature descriptor. + * - :doc:`af.pad() ` + - Pad an array. + * - :doc:`af.pinverse() ` + - Pseudo-invert (Moore-Penrose) a matrix. + * - :doc:`af.pow() ` + - Raise a base to a power (or exponent). + * - :doc:`af.pow2() ` + - Raise 2 to a power (or exponent). + * - :doc:`af.print_mem_info() ` + - Prints buffer details from the ArrayFire Device Manager + * - :doc:`af.product() ` + - Multiply array elements over a given dimension. + * - :doc:`af.qr() ` + - Perform QR decomposition. + * - :doc:`af.randn() ` + - Create a random array sampled from normal distribution. + * - :doc:`af.randu() ` + - Create a random array sampled from uniform distribution. + * - :doc:`af.range() ` + - Generate an array with [0, n-1] values along the a specified dimension and tiled across other dimensions. + * - :doc:`af.rank() ` + - Find the rank of a matrix. + * - :doc:`af.read_array() ` + - Load an array from a file. + * - :doc:`af.real() ` + - Returns the real part of a complex array. + * - :doc:`af.regions() ` + - Find blobs in given image. + * - :doc:`af.rem() ` + - Calculate the remainder of a division. + * - :doc:`af.reorder() ` + - Reorder an array. + * - :doc:`af.replace() ` + - Replace elements of an array with elements of another array. + * - :doc:`af.reshape() ` + - Modify the dimensions of an array without changing the order of its elements + * - :doc:`af.resize() ` + - Resize an input image. + * - :doc:`af.rgb2gray() ` + - RGB to Grayscale colorspace converter. + * - :doc:`af.rgb2hsv() ` + - RGB to HSV colorspace converter. + * - :doc:`af.rgb2ycbcr() ` + - RGB to YCbCr colorspace converter. + * - :doc:`af.root() ` + - Evaluate the nth root. + * - :doc:`af.rotate() ` + - Rotate an input image or array. + * - :doc:`af.round() ` + - Round numbers to the nearest integer. + * - :doc:`af.rsqrt() ` + - Evaluate the reciprocal square root. + * - :doc:`af.sat() ` + - Summed Area Tables. + * - :doc:`af.save_array() ` + - Save an array to a binary file + * - :doc:`af.save_image() ` + - Save an array to disk as an image + * - :doc:`af.save_image_memory() ` + - Save an array to memory as an image using FreeImage stream + * - :doc:`af.save_image_native() ` + - Save an image as is original type. + * - :doc:`af.scale() ` + - Scale an input image. + * - :doc:`af.scan() ` + - Scan an array (generalized) over a given dimension. + * - :doc:`af.select() ` + - Select elements based on a conditional array. + * - :doc:`af.set_backend() ` + - Set the current backend + * - :doc:`af.set_device() ` + - Change current device to specified device. + * - :doc:`af.set_fft_plan_cache_size() ` + - Sets fft plan cache size * - :doc:`af.set_intersect() ` - - Calculates the intersection of two ArrayFire arrays, returning elements common to both arrays. + - Evaluate the intersection of two arrays + * - :doc:`af.set_kernel_cache_directory() ` + - Sets the directory for JIT kernel caching + * - :doc:`af.set_mem_step_size() ` + - Get the minimum memory chunk size. + * - :doc:`af.set_native_id() ` + - Set the CUDA device with given native id as the active device for ArrayFire * - :doc:`af.set_union() ` - - Computes the union of two 1D ArrayFire arrays, effectively combining the elements from both arrays and removing duplicates. + - Evaluate the union of two arrays * - :doc:`af.set_unique() ` - - Extracts unique elements from a 1D ArrayFire array. - * - :doc:`af.pad() ` - - Pads an ArrayFire array with specified sizes of padding around its edges and fills the padding with a specified value. - * - :doc:`af.orb() ` - - Extracts ORB features and their descriptors from an image. + - Return the unique values in an array + * - :doc:`af.shift() ` + - Shift an array. * - :doc:`af.sift() ` - - Extracts SIFT features and their descriptors from an image using the ArrayFire library. - * - :doc:`af.fast() ` - - Detects corners and interest points in an image using the Features from Accelerated Segment Test algorithm. - * - :doc:`af.dog() ` - - Performs the Difference of Gaussians (DoG) operation on an image. - * - :doc:`af.gloh() ` - - Implements the GLOH (Gradient Location and Orientation Histogram) feature detection and descriptor extraction for images. - * - :doc:`af.harris() ` - - Detects corners in an image using the Harris corner detection algorithm. + - SIFT feature detector and descriptor extractor. + * - :doc:`af.sign() ` + - Return the sign of elements in an array. + * - :doc:`af.sin() ` + - Evaluate the sine function. + * - :doc:`af.sinh() ` + - Evaluate the hyperbolic sine function. + * - :doc:`af.skew() ` + - Skew an input image. + * - :doc:`af.sobel_operator() ` + - Perform a 2-D spatial gradient measurement on an image + * - :doc:`af.solve() ` + - Solve a system of equations. + * - :doc:`af.sort() ` + - Sort an array over a given dimension. + * - :doc:`af.sqrt() ` + - Evaluate the square root. + * - :doc:`af.sttdev() ` + - Find the standard deviation of values in the input. + * - :doc:`af.sub() ` + - Elementwise subtraction. + * - :doc:`af.sum() ` + - Sum array elements over a given dimension. * - :doc:`af.susan() ` - - Detects corners and edges in an image using the SUSAN corner detection algorithm. - * - :doc:`af.hamming_matcher() ` - - Finds the nearest neighbors for each descriptor in a query set from a training set, based on the Hamming distance. - * - :doc:`af.nearest_neighbour() ` - - Finds the nearest neighbors for each descriptor in a query set from a training set based on a specified metric. - * - :doc:`af.upper() ` - - Extract the upper triangular part of a given multi-dimensional ArrayFire array. - * - :doc:`af.lower() ` - - Extract the lower triangular part of a given multi-dimensional ArrayFire array. - * - :doc:`af.diag() ` - - Extract a diagonal from or create a diagonal matrix based on an input array. + - SUSAN corner detector. + * - :doc:`af.svd() ` + - Perform singular value decomposition. + * - :doc:`af.sync() ` + - Blocks until all operations on device are finished. + * - :doc:`af.tan() ` + - Evaluate the tangent function. + * - :doc:`af.tanh() ` + - Evaluate the hyperbolic tangent function. + * - :doc:`af.tgamma() ` + - Evaluate the gamma function. + * - :doc:`af.tile() ` + - Generate a tiled array by repeating an array's contents along a specified dimension. + * - :doc:`af.transform() ` + - Transform an input image. + * - :doc:`af.transform_coordinates() ` + - Transform input coordinates to perspective. + * - :doc:`af.translate() ` + - Translate an input image. * - :doc:`af.transpose() ` - - Transposes an array. - * - :doc:`af.join() ` - - Joins arrays along a specified dimension. - * - :doc:`af.reorder() ` - - Reorders dimensions of an array. - * - :doc:`af.slice() ` - - Extracts a slice of an array. - * - :doc:`af.reshape() ` - - Reshapes an array. - * - :doc:`af.device() ` - - Returns the device identifier. - * - :doc:`af.get_device() ` - - Matrix multiplication. - * - :doc:`af.set_device() ` - - Gets the current device. - * - :doc:`af.set_backend() ` - - Sets the current backend. - * - :doc:`af.get_backend() ` - - Gets the current backend. - * - :doc:`af.get() ` - - Copies data from the GPU to the CPU. + - Transpose a matrix. + * - :doc:`af.trunc() ` + - Truncate numbers to nearest integer. + * - :doc:`af.unwrap() ` + - Rearrange windowed sections of an array into columns (or rows) + * - :doc:`af.upper() ` + - Return the upper triangular matrix from an input array. + * - :doc:`af.where() ` + - Locate the indices of the non-zero values in an array. + * - :doc:`af.wrap() ` + - Performs the opposite of af::unwrap(). + * - :doc:`af.zeros() ` + - Creates an array filled with zeros. .. collapse:: Arrayfire Functions by Category .. list-table:: - * - **Array Creation** + * - :doc:`Array Creation ` - Functions in this category are used to initialize arrays with specific values or patterns. - * - **Array Manipulation** + * - :doc:`Array Manipulation ` - These functions help modify the structure or arrangement of arrays. - * - **Mathematical Operations** + * - :doc:`Mathematical Operations ` - Functions for performing fundamental arithmetic and mathematical operations on arrays. - * - **Linear Algebra** + * - :doc:`Linear Algebra ` - Functions for performing linear algebra operations, essential in many scientific and engineering tasks. - * - **Fourier Transforms** + * - :doc:`Fourier Transforms ` - Functions for performing Fourier analysis, essential for signal processing and frequency analysis. - * - **Statistics** + * - :doc:`Statistics ` - Functions for computing statistical metrics and analyzing data distributions. - * - **Data Reduction** + * - :doc:`Data Reduction ` - Functions for aggregating and reducing data to summarize or condense information. - * - **Utilities** + * - :doc:`Utilities ` - General-purpose functions for managing arrays and devices. - * - **Special Functions** - - Functions for creating and applying specific types of filters, commonly used in signal processing and analysis. + * - :doc:`Special Functions ` + - Functions for convolutions, creating and applying specific types of filters, commonly used in signal processing and analysis. +.. collapse:: Arrayfire Constants -.. collapse:: Graphics + .. list-table:: + + * - :doc:`af.BinaryOperator ` + * - :doc:`af.CannyThreshold ` + * - :doc:`af.Connectivity ` + * - :doc:`af.ConvDomain ` + * - :doc:`af.ConvGradient ` + * - :doc:`af.CSpace ` + * - :doc:`af.Diffusion ` + * - :doc:`af.Dtype ` + - ArrayFire supported datatypes + * - :doc:`af.Flux ` + * - :doc:`af.ImageFormat ` + * - :doc:`af.Interp ` + * - :doc:`af.IterativeDeconv ` + * - :doc:`af.Match ` + * - :doc:`af.MatProp ` + * - :doc:`af.Norm ` + * - :doc:`af.Pad ` + * - :doc:`af.RandomEngineType ` + * - :doc:`af.TopK ` + * - :doc:`af.VarianceBias ` + * - :doc:`af.YCCStd ` + +.. collapse:: Graphics (Coming Soon) .. list-table:: @@ -190,3 +586,4 @@ Documentation grouped by category: - Rendering Function to draw images, plots etc * - **Window Function** - Window Creation, modification and destruction of functions + diff --git a/docs/functions/ArrayFire.rst b/docs/functions/ArrayFire.rst deleted file mode 100644 index cb959a9..0000000 --- a/docs/functions/ArrayFire.rst +++ /dev/null @@ -1,4 +0,0 @@ -ArrayFire Package -================= - -.. automodule:: arrayfire \ No newline at end of file diff --git a/docs/functions/abs.rst b/docs/functions/abs.rst new file mode 100644 index 0000000..db018f8 --- /dev/null +++ b/docs/functions/abs.rst @@ -0,0 +1,4 @@ +abs +=== + +.. autofunction:: arrayfire_wrapper.lib.abs_ diff --git a/docs/functions/acos.rst b/docs/functions/acos.rst new file mode 100644 index 0000000..ab5b3ee --- /dev/null +++ b/docs/functions/acos.rst @@ -0,0 +1,4 @@ +acos +==== + +.. autofunction:: arrayfire_wrapper.lib.acos diff --git a/docs/functions/acosh.rst b/docs/functions/acosh.rst new file mode 100644 index 0000000..ce00baa --- /dev/null +++ b/docs/functions/acosh.rst @@ -0,0 +1,4 @@ +acosh +===== + +.. autofunction:: arrayfire_wrapper.lib.acosh diff --git a/docs/functions/alloc_device.rst b/docs/functions/alloc_device.rst new file mode 100644 index 0000000..2078927 --- /dev/null +++ b/docs/functions/alloc_device.rst @@ -0,0 +1,4 @@ +alloc_device +============= + +.. autofunction:: arrayfire_wrapper.lib.alloc_device \ No newline at end of file diff --git a/docs/functions/alloc_host.rst b/docs/functions/alloc_host.rst new file mode 100644 index 0000000..187a2cc --- /dev/null +++ b/docs/functions/alloc_host.rst @@ -0,0 +1,4 @@ +alloc_host +============ + +.. autofunction:: arrayfire_wrapper.lib.alloc_host \ No newline at end of file diff --git a/docs/functions/alloc_pinned.rst b/docs/functions/alloc_pinned.rst new file mode 100644 index 0000000..80538fc --- /dev/null +++ b/docs/functions/alloc_pinned.rst @@ -0,0 +1,4 @@ +alloc_pinned +============== + +.. autofunction:: arrayfire_wrapper.lib.alloc_pinned \ No newline at end of file diff --git a/docs/functions/anisotropic_diffusion.rst b/docs/functions/anisotropic_diffusion.rst new file mode 100644 index 0000000..28435ba --- /dev/null +++ b/docs/functions/anisotropic_diffusion.rst @@ -0,0 +1,4 @@ +anisotropic_diffusion +===================== + +.. autofunction:: arrayfire_wrapper.lib.anisotropic_diffusion diff --git a/docs/functions/approx1.rst b/docs/functions/approx1.rst new file mode 100644 index 0000000..de44fd7 --- /dev/null +++ b/docs/functions/approx1.rst @@ -0,0 +1,4 @@ +approx1 +======= + +.. autofunction:: arrayfire_wrapper.lib.approx1 diff --git a/docs/functions/approx1_uniform.rst b/docs/functions/approx1_uniform.rst new file mode 100644 index 0000000..2b60e2a --- /dev/null +++ b/docs/functions/approx1_uniform.rst @@ -0,0 +1,4 @@ +approx1_uniform +=============== + +.. autofunction:: arrayfire_wrapper.lib.approx1_uniform diff --git a/docs/functions/approx2.rst b/docs/functions/approx2.rst new file mode 100644 index 0000000..eb9c87d --- /dev/null +++ b/docs/functions/approx2.rst @@ -0,0 +1,4 @@ +approx2 +======= + +.. autofunction:: arrayfire_wrapper.lib.approx2 diff --git a/docs/functions/approx2_uniform.rst b/docs/functions/approx2_uniform.rst new file mode 100644 index 0000000..c821dc1 --- /dev/null +++ b/docs/functions/approx2_uniform.rst @@ -0,0 +1,4 @@ +approx2_uniform +=============== + +.. autofunction:: arrayfire_wrapper.lib.approx2_uniform diff --git a/docs/functions/arg.rst b/docs/functions/arg.rst new file mode 100644 index 0000000..aa373ca --- /dev/null +++ b/docs/functions/arg.rst @@ -0,0 +1,4 @@ +arg +=== + +.. autofunction:: arrayfire_wrapper.lib.arg diff --git a/docs/functions/array.rst b/docs/functions/array.rst deleted file mode 100644 index ef34cb3..0000000 --- a/docs/functions/array.rst +++ /dev/null @@ -1,33 +0,0 @@ -array -===== - -.. autoclass:: arrayfire.Array - -The 'af.array()' function is part of the ArrayFire library, which provides a powerful framework for performing high-performance numerical computations. This function is designed to create an ArrayFire array from various data structures, such as Python lists or other iterable collections. - -Function --------- -:literal:`af.array()` - - Python interface to form an array. - - -Detailed Description --------------------- -The 'af.array()' function allows you to convert a data structure, such as a Python list or tuple, into an ArrayFire array. This conversion is essential for leveraging ArrayFire's optimized computational capabilities. By creating an array from a list or another iterable, you can perform efficient mathematical operations, matrix manipulations, and other numerical computations using ArrayFire's APIs. - -The function supports multiple data types and can handle multi-dimensional arrays. The ability to create an ArrayFire array from native Python structures makes it easier to integrate ArrayFire into Python-based workflows. - -Function Documentation ----------------------- -.. sidebar:: af.array() - - Syntax: - af.array(data) - - Parameters: - 'data': A list, tuple, or another iterable containing the elements to be converted into an ArrayFire array. The data should be in a format that ArrayFire can interpret, such as nested lists for multi-dimensional arrays. - - Returns: - An ArrayFire array containing the elements from the input data structure. - - diff --git a/docs/functions/asin.rst b/docs/functions/asin.rst new file mode 100644 index 0000000..883e5f3 --- /dev/null +++ b/docs/functions/asin.rst @@ -0,0 +1,4 @@ +asin +==== + +.. autofunction:: arrayfire_wrapper.lib.asin diff --git a/docs/functions/asinh.rst b/docs/functions/asinh.rst new file mode 100644 index 0000000..1d4b092 --- /dev/null +++ b/docs/functions/asinh.rst @@ -0,0 +1,4 @@ +asinh +===== + +.. autofunction:: arrayfire_wrapper.lib.asinh diff --git a/docs/functions/atan.rst b/docs/functions/atan.rst new file mode 100644 index 0000000..18b856a --- /dev/null +++ b/docs/functions/atan.rst @@ -0,0 +1,4 @@ +atan +==== + +.. autofunction:: arrayfire_wrapper.lib.atan diff --git a/docs/functions/atan2.rst b/docs/functions/atan2.rst new file mode 100644 index 0000000..a393936 --- /dev/null +++ b/docs/functions/atan2.rst @@ -0,0 +1,4 @@ +atan2 +===== + +.. autofunction:: arrayfire_wrapper.lib.atan2 diff --git a/docs/functions/atanh.rst b/docs/functions/atanh.rst new file mode 100644 index 0000000..5c75a98 --- /dev/null +++ b/docs/functions/atanh.rst @@ -0,0 +1,4 @@ +atanh +===== + +.. autofunction:: arrayfire_wrapper.lib.atanh diff --git a/docs/functions/bilateral.rst b/docs/functions/bilateral.rst new file mode 100644 index 0000000..a60a023 --- /dev/null +++ b/docs/functions/bilateral.rst @@ -0,0 +1,4 @@ +bilateral +========= + +.. autofunction:: arrayfire_wrapper.lib.bilateral diff --git a/docs/functions/bitand.rst b/docs/functions/bitand.rst new file mode 100644 index 0000000..f016416 --- /dev/null +++ b/docs/functions/bitand.rst @@ -0,0 +1,4 @@ +bitand +====== + +.. autofunction:: arrayfire_wrapper.lib.bitand diff --git a/docs/functions/bitnot.rst b/docs/functions/bitnot.rst new file mode 100644 index 0000000..db9ce61 --- /dev/null +++ b/docs/functions/bitnot.rst @@ -0,0 +1,4 @@ +bitnot +====== + +.. autofunction:: arrayfire_wrapper.lib.bitnot diff --git a/docs/functions/bitor.rst b/docs/functions/bitor.rst new file mode 100644 index 0000000..2f829eb --- /dev/null +++ b/docs/functions/bitor.rst @@ -0,0 +1,4 @@ +bitor +===== + +.. autofunction:: arrayfire_wrapper.lib.bitor diff --git a/docs/functions/bitshiftl.rst b/docs/functions/bitshiftl.rst new file mode 100644 index 0000000..8478a1e --- /dev/null +++ b/docs/functions/bitshiftl.rst @@ -0,0 +1,4 @@ +bitshiftl +========= + +.. autofunction:: arrayfire_wrapper.lib.bitshiftl diff --git a/docs/functions/bitshiftr.rst b/docs/functions/bitshiftr.rst new file mode 100644 index 0000000..fb17b29 --- /dev/null +++ b/docs/functions/bitshiftr.rst @@ -0,0 +1,4 @@ +bitshiftr +========= + +.. autofunction:: arrayfire_wrapper.lib.bitshiftr diff --git a/docs/functions/bitxor.rst b/docs/functions/bitxor.rst new file mode 100644 index 0000000..a37c252 --- /dev/null +++ b/docs/functions/bitxor.rst @@ -0,0 +1,4 @@ +bitxor +====== + +.. autofunction:: arrayfire_wrapper.lib.bitxor diff --git a/docs/functions/canny.rst b/docs/functions/canny.rst new file mode 100644 index 0000000..da62faf --- /dev/null +++ b/docs/functions/canny.rst @@ -0,0 +1,4 @@ +canny +===== + +.. autofunction:: arrayfire_wrapper.lib.canny diff --git a/docs/functions/cast.rst b/docs/functions/cast.rst new file mode 100644 index 0000000..3fa1c16 --- /dev/null +++ b/docs/functions/cast.rst @@ -0,0 +1,4 @@ +cast +===== + +.. autofunction:: arrayfire.cast \ No newline at end of file diff --git a/docs/functions/cbrt.rst b/docs/functions/cbrt.rst new file mode 100644 index 0000000..384f506 --- /dev/null +++ b/docs/functions/cbrt.rst @@ -0,0 +1,4 @@ +cbrt +==== + +.. autofunction:: arrayfire_wrapper.lib.cbrt diff --git a/docs/functions/ceil.rst b/docs/functions/ceil.rst new file mode 100644 index 0000000..d738a7a --- /dev/null +++ b/docs/functions/ceil.rst @@ -0,0 +1,4 @@ +ceil +==== + +.. autofunction:: arrayfire_wrapper.lib.ceil diff --git a/docs/functions/cholesky.rst b/docs/functions/cholesky.rst new file mode 100644 index 0000000..464ebd5 --- /dev/null +++ b/docs/functions/cholesky.rst @@ -0,0 +1,4 @@ +cholesky +======== + +.. autofunction:: arrayfire_wrapper.lib.cholesky diff --git a/docs/functions/clamp.rst b/docs/functions/clamp.rst new file mode 100644 index 0000000..b1d0559 --- /dev/null +++ b/docs/functions/clamp.rst @@ -0,0 +1,4 @@ +clamp +===== + +.. autofunction:: arrayfire_wrapper.lib.clamp diff --git a/docs/functions/color_space.rst b/docs/functions/color_space.rst new file mode 100644 index 0000000..965e591 --- /dev/null +++ b/docs/functions/color_space.rst @@ -0,0 +1,4 @@ +color_space +=========== + +.. autofunction:: arrayfire_wrapper.lib.color_space diff --git a/docs/functions/confidence_cc.rst b/docs/functions/confidence_cc.rst new file mode 100644 index 0000000..2a9d51a --- /dev/null +++ b/docs/functions/confidence_cc.rst @@ -0,0 +1,4 @@ +confidence_cc +============= + +.. autofunction:: arrayfire_wrapper.lib.confidence_cc diff --git a/docs/functions/conjg.rst b/docs/functions/conjg.rst new file mode 100644 index 0000000..2fbc710 --- /dev/null +++ b/docs/functions/conjg.rst @@ -0,0 +1,4 @@ +conjg +===== + +.. autofunction:: arrayfire_wrapper.lib.conjg diff --git a/docs/functions/convolve1.rst b/docs/functions/convolve1.rst new file mode 100644 index 0000000..cfb9cdb --- /dev/null +++ b/docs/functions/convolve1.rst @@ -0,0 +1,4 @@ +convolve1 +========= + +.. autofunction:: arrayfire_wrapper.lib.convolve1 diff --git a/docs/functions/convolve2.rst b/docs/functions/convolve2.rst new file mode 100644 index 0000000..d88c7ad --- /dev/null +++ b/docs/functions/convolve2.rst @@ -0,0 +1,4 @@ +convolve2 +========= + +.. autofunction:: arrayfire_wrapper.lib.convolve2 diff --git a/docs/functions/convolve2_gradient_nn.rst b/docs/functions/convolve2_gradient_nn.rst new file mode 100644 index 0000000..2f0e302 --- /dev/null +++ b/docs/functions/convolve2_gradient_nn.rst @@ -0,0 +1,4 @@ +convolve2_gradient_nn +====================== + +.. autofunction:: arrayfire_wrapper.lib.convolve2_gradient_nn \ No newline at end of file diff --git a/docs/functions/convolve2_nn.rst b/docs/functions/convolve2_nn.rst new file mode 100644 index 0000000..c8027a3 --- /dev/null +++ b/docs/functions/convolve2_nn.rst @@ -0,0 +1,4 @@ +convolve2_nn +============ + +.. autofunction:: arrayfire_wrapper.lib.convolve2_nn diff --git a/docs/functions/convolve2_separable.rst b/docs/functions/convolve2_separable.rst new file mode 100644 index 0000000..0c97f55 --- /dev/null +++ b/docs/functions/convolve2_separable.rst @@ -0,0 +1,4 @@ +convolve2_separable +=================== + +.. autofunction:: arrayfire_wrapper.lib.convolve2_sep diff --git a/docs/functions/convolve3.rst b/docs/functions/convolve3.rst new file mode 100644 index 0000000..1bd2276 --- /dev/null +++ b/docs/functions/convolve3.rst @@ -0,0 +1,4 @@ +convolve3 +========= + +.. autofunction:: arrayfire_wrapper.lib.convolve3 diff --git a/docs/functions/copy_array.rst b/docs/functions/copy_array.rst new file mode 100644 index 0000000..437c947 --- /dev/null +++ b/docs/functions/copy_array.rst @@ -0,0 +1,4 @@ +copy_array +========== + +.. autofunction:: arrayfire.copy_array diff --git a/docs/functions/cos.rst b/docs/functions/cos.rst new file mode 100644 index 0000000..daf981e --- /dev/null +++ b/docs/functions/cos.rst @@ -0,0 +1,4 @@ +cos +=== + +.. autofunction:: arrayfire_wrapper.lib.cos diff --git a/docs/functions/cosh.rst b/docs/functions/cosh.rst new file mode 100644 index 0000000..258646a --- /dev/null +++ b/docs/functions/cosh.rst @@ -0,0 +1,4 @@ +cosh +==== + +.. autofunction:: arrayfire_wrapper.lib.cosh diff --git a/docs/functions/cplx.rst b/docs/functions/cplx.rst new file mode 100644 index 0000000..07ac775 --- /dev/null +++ b/docs/functions/cplx.rst @@ -0,0 +1,4 @@ +cplx +==== + +.. autofunction:: arrayfire_wrapper.lib.cplx diff --git a/docs/functions/cublas_set_math_mode.rst b/docs/functions/cublas_set_math_mode.rst new file mode 100644 index 0000000..a9418e0 --- /dev/null +++ b/docs/functions/cublas_set_math_mode.rst @@ -0,0 +1,4 @@ +cublas_set_math_mode +==================== + +.. autofunction:: arrayfire_wrapper.lib.cublas_set_math_mode diff --git a/docs/functions/delete_image_memory.rst b/docs/functions/delete_image_memory.rst new file mode 100644 index 0000000..7926cf4 --- /dev/null +++ b/docs/functions/delete_image_memory.rst @@ -0,0 +1,4 @@ +delete_image_memory +=================== + +.. autofunction:: arrayfire_wrapper.lib.delete_image_memory diff --git a/docs/functions/device.rst b/docs/functions/device.rst deleted file mode 100644 index 318547b..0000000 --- a/docs/functions/device.rst +++ /dev/null @@ -1,43 +0,0 @@ -device -====== -The 'af.device()' function in the ArrayFire library is used to get or set the current device or device properties. This function provides an interface to interact with the GPU or CPU device being used for computations. It allows you to select a particular device from available options or query the properties of the current device. - -Function --------- -:literal:`af.device()` - - Python interface to get or set device properties. - -Detailed Description --------------------- -The 'af.device()' function is useful for managing and querying the device that ArrayFire is using for computations. This function can perform various tasks related to device management, such as: - -- Getting the Current Device: Retrieve the index of the currently selected device. -- Setting the Current Device: Select a specific device for computations. -- Querying Device Properties: Obtain information about the current device. - -This functionality is important for applications that need to explicitly choose between multiple GPUs or check device capabilities. - -Function Documentation ----------------------- -.. sidebar:: af.device() - - Syntax: - af.device(option=None, value=None) - - Parameters: - 'option' (optional): Specifies the type of information or action. Can be one of the following: - - - "device": Get the current device index. - - "set": Set the current device index. - - "count": Get the number of available devices. - - "name": Get the name of the current device. - - "info": Get detailed information about the current device. - - 'value (optional)': The index of the device to set. Used only when the option is "set". If option is "set", this parameter should be an integer representing the device index. - - Returns: - Depending on the option, the function returns various types of information: - - If 'option' is "device": The index of the current device. - - If 'option' is "count": The number of available devices. - - If 'option' is "name": The name of the current device. - - If 'option' is "info": Detailed information about the current device. diff --git a/docs/functions/device_gc.rst b/docs/functions/device_gc.rst new file mode 100644 index 0000000..d9a885d --- /dev/null +++ b/docs/functions/device_gc.rst @@ -0,0 +1,4 @@ +device_gc +=========== + +.. autofunction:: arrayfire_wrapper.lib.device_gc \ No newline at end of file diff --git a/docs/functions/device_info.rst b/docs/functions/device_info.rst new file mode 100644 index 0000000..2ccc64f --- /dev/null +++ b/docs/functions/device_info.rst @@ -0,0 +1,4 @@ +device_info +============ + +.. autofunction:: arrayfire_wrapper.lib.device_info \ No newline at end of file diff --git a/docs/functions/device_mem_info.rst b/docs/functions/device_mem_info.rst new file mode 100644 index 0000000..b4a9c3d --- /dev/null +++ b/docs/functions/device_mem_info.rst @@ -0,0 +1,4 @@ +device_mem_info +=============== + +.. autofunction:: arrayfire_wrapper.lib.device_mem_info diff --git a/docs/functions/dilate.rst b/docs/functions/dilate.rst new file mode 100644 index 0000000..7d5f07b --- /dev/null +++ b/docs/functions/dilate.rst @@ -0,0 +1,4 @@ +dilate +====== + +.. autofunction:: arrayfire_wrapper.lib.dilate diff --git a/docs/functions/div.rst b/docs/functions/div.rst new file mode 100644 index 0000000..fa086a5 --- /dev/null +++ b/docs/functions/div.rst @@ -0,0 +1,4 @@ +div +=== + +.. autofunction:: arrayfire_wrapper.lib.div diff --git a/docs/functions/divide.rst b/docs/functions/divide.rst deleted file mode 100644 index 74d7880..0000000 --- a/docs/functions/divide.rst +++ /dev/null @@ -1,36 +0,0 @@ -divide -====== -The 'af.divide()' function in the ArrayFire library performs element-wise division of two arrays. This function allows you to divide one array by another, or to divide each element of an array by a scalar value. It supports operations on arrays of the same shape or on a scalar and an array. - -Function --------- -:literal:`af.divide` - - Python interface for dividing one array by another. - -Detailed Description --------------------- -The af.divide() function is used to perform element-wise division of arrays or between an array and a scalar. This operation divides each element of the first array by the corresponding element of the second array, or divides each element of the array by the scalar value. - -**Element-wise Division:** When dividing two arrays, the function performs the division for each corresponding element of the arrays. - -**Scalar Division:** When dividing an array by a scalar, the function divides each element of the array by the scalar value. - -The function handles broadcasting automatically when the dimensions of the arrays are compatible. - -Function Documentation ----------------------- -.. sidebar:: af.divide - - Syntax: - af.divide(array1, array2) - af.divide(array, scalar) - - - Parameters: - - array1: The first ArrayFire array (numerator) in the division operation. - - array2: The second ArrayFire array (denominator) in the division operation. Must have the same shape as array1 or be a scalar. - - array: The ArrayFire array to be divided by a scalar. - - scalar: The scalar value used to divide each element of array. - - Returns: - An ArrayFire array containing the results of the element-wise division. The resulting array will have the same shape as the input arrays. diff --git a/docs/functions/eig.rst b/docs/functions/eig.rst deleted file mode 100644 index 250547a..0000000 --- a/docs/functions/eig.rst +++ /dev/null @@ -1,37 +0,0 @@ -eig -=== -The 'af.eig()' function in ArrayFire computes the eigenvalues and eigenvectors of a square matrix. This function is essential in linear algebra for analyzing matrices and is used in various applications including machine learning, physics, and numerical analysis. - -Function --------- -:literal:`af.eig()` - - Python interface for computing the eigenvalues and eigenvectors of a square matrix. - -Detailed Description --------------------- -The 'af.eig()' function computes the eigenvalues and eigenvectors of a square matrix. For a given matrix -A, eigenvalues and eigenvectors are defined such that: - -𝐴𝑣 = 𝜆𝑣 - - -where: -- λ represents an eigenvalue. -- v represents the corresponding eigenvector. -The function returns two arrays: -- An array containing the eigenvalues of the matrix. -- An array containing the eigenvectors of the matrix. Each column in this array corresponds to an eigenvector. - -Function Documentation ----------------------- -.. sidebar:: af.eig() - - Syntax: - eigenvalues, eigenvectors = af.eig(matrix) - - Parameters: - 'matrix': A 2D ArrayFire array (matrix) for which eigenvalues and eigenvectors are to be computed. The matrix must be square (i.e., the number of rows must be equal to the number of columns). - - Returns: - - eigenvalues: An ArrayFire array containing the eigenvalues of the input matrix. - - eigenvectors: An ArrayFire array containing the eigenvectors of the input matrix. Each column of this array is an eigenvector corresponding to the eigenvalues. diff --git a/docs/functions/eq.rst b/docs/functions/eq.rst new file mode 100644 index 0000000..1b9c67e --- /dev/null +++ b/docs/functions/eq.rst @@ -0,0 +1,4 @@ +eq +== + +.. autofunction:: arrayfire_wrapper.lib.eq diff --git a/docs/functions/erf.rst b/docs/functions/erf.rst new file mode 100644 index 0000000..5c29a27 --- /dev/null +++ b/docs/functions/erf.rst @@ -0,0 +1,4 @@ +erf +=== + +.. autofunction:: arrayfire_wrapper.lib.erf diff --git a/docs/functions/erfc.rst b/docs/functions/erfc.rst new file mode 100644 index 0000000..f816b96 --- /dev/null +++ b/docs/functions/erfc.rst @@ -0,0 +1,4 @@ +erfc +==== + +.. autofunction:: arrayfire_wrapper.lib.erfc diff --git a/docs/functions/erode.rst b/docs/functions/erode.rst new file mode 100644 index 0000000..56277a2 --- /dev/null +++ b/docs/functions/erode.rst @@ -0,0 +1,4 @@ +erode +===== + +.. autofunction:: arrayfire_wrapper.lib.erode diff --git a/docs/functions/eval.rst b/docs/functions/eval.rst new file mode 100644 index 0000000..a380b16 --- /dev/null +++ b/docs/functions/eval.rst @@ -0,0 +1,4 @@ +eval +==== + +.. autofunction:: arrayfire.eval diff --git a/docs/functions/expm1.rst b/docs/functions/expm1.rst new file mode 100644 index 0000000..6f1a5d6 --- /dev/null +++ b/docs/functions/expm1.rst @@ -0,0 +1,4 @@ +expm1 +===== + +.. autofunction:: arrayfire_wrapper.lib.expm1 diff --git a/docs/functions/factorial.rst b/docs/functions/factorial.rst new file mode 100644 index 0000000..679fe1e --- /dev/null +++ b/docs/functions/factorial.rst @@ -0,0 +1,4 @@ +factorial +========= + +.. autofunction:: arrayfire_wrapper.lib.factorial diff --git a/docs/functions/fft2.rst b/docs/functions/fft2.rst new file mode 100644 index 0000000..bea70a3 --- /dev/null +++ b/docs/functions/fft2.rst @@ -0,0 +1,4 @@ +fft2 +==== + +.. autofunction:: arrayfire_wrapper.lib.fft2 diff --git a/docs/functions/fft2_c2r.rst b/docs/functions/fft2_c2r.rst new file mode 100644 index 0000000..9403a4e --- /dev/null +++ b/docs/functions/fft2_c2r.rst @@ -0,0 +1,4 @@ +fft2_c2r +======== + +.. autofunction:: arrayfire_wrapper.lib.fft2_c2r diff --git a/docs/functions/fft2_r2c.rst b/docs/functions/fft2_r2c.rst new file mode 100644 index 0000000..c11fca4 --- /dev/null +++ b/docs/functions/fft2_r2c.rst @@ -0,0 +1,4 @@ +fft2_r2c +======== + +.. autofunction:: arrayfire_wrapper.lib.fft2_r2c diff --git a/docs/functions/fft3.rst b/docs/functions/fft3.rst new file mode 100644 index 0000000..7fd90a5 --- /dev/null +++ b/docs/functions/fft3.rst @@ -0,0 +1,4 @@ +fft3 +==== + +.. autofunction:: arrayfire_wrapper.lib.fft3 diff --git a/docs/functions/fft3_c2r.rst b/docs/functions/fft3_c2r.rst new file mode 100644 index 0000000..4a0cb97 --- /dev/null +++ b/docs/functions/fft3_c2r.rst @@ -0,0 +1,4 @@ +fft3_c2r +======== + +.. autofunction:: arrayfire_wrapper.lib.fft3_c2r diff --git a/docs/functions/fft3_r2c.rst b/docs/functions/fft3_r2c.rst new file mode 100644 index 0000000..c1d053a --- /dev/null +++ b/docs/functions/fft3_r2c.rst @@ -0,0 +1,4 @@ +fft3_r2c +======== + +.. autofunction:: arrayfire_wrapper.lib.fft3_r2c diff --git a/docs/functions/fft_c2r.rst b/docs/functions/fft_c2r.rst new file mode 100644 index 0000000..834a43a --- /dev/null +++ b/docs/functions/fft_c2r.rst @@ -0,0 +1,4 @@ +fft_c2r +======= + +.. autofunction:: arrayfire_wrapper.lib.fft_c2r diff --git a/docs/functions/fft_convolve1.rst b/docs/functions/fft_convolve1.rst new file mode 100644 index 0000000..ad3277f --- /dev/null +++ b/docs/functions/fft_convolve1.rst @@ -0,0 +1,4 @@ +fft_convolve1 +============= + +.. autofunction:: arrayfire_wrapper.lib.fft_convolve1 diff --git a/docs/functions/fft_convolve2.rst b/docs/functions/fft_convolve2.rst new file mode 100644 index 0000000..11dfe0a --- /dev/null +++ b/docs/functions/fft_convolve2.rst @@ -0,0 +1,4 @@ +fft_convolve2 +============= + +.. autofunction:: arrayfire_wrapper.lib.fft_convolve2 diff --git a/docs/functions/fft_convolve3.rst b/docs/functions/fft_convolve3.rst new file mode 100644 index 0000000..6d18162 --- /dev/null +++ b/docs/functions/fft_convolve3.rst @@ -0,0 +1,4 @@ +fft_convolve3 +============= + +.. autofunction:: arrayfire_wrapper.lib.fft_convolve3 diff --git a/docs/functions/fft_r2c.rst b/docs/functions/fft_r2c.rst new file mode 100644 index 0000000..448b15a --- /dev/null +++ b/docs/functions/fft_r2c.rst @@ -0,0 +1,4 @@ +fft_r2c +======= + +.. autofunction:: arrayfire_wrapper.lib.fft_r2c diff --git a/docs/functions/fir.rst b/docs/functions/fir.rst new file mode 100644 index 0000000..dc5ac6c --- /dev/null +++ b/docs/functions/fir.rst @@ -0,0 +1,4 @@ +fir +=== + +.. autofunction:: arrayfire_wrapper.lib.fir diff --git a/docs/functions/flat.rst b/docs/functions/flat.rst new file mode 100644 index 0000000..cee1184 --- /dev/null +++ b/docs/functions/flat.rst @@ -0,0 +1,4 @@ +flat +==== + +.. autofunction:: arrayfire.flat diff --git a/docs/functions/flip.rst b/docs/functions/flip.rst new file mode 100644 index 0000000..bb75af6 --- /dev/null +++ b/docs/functions/flip.rst @@ -0,0 +1,4 @@ +flip +==== + +.. autofunction:: arrayfire.flip diff --git a/docs/functions/floor.rst b/docs/functions/floor.rst new file mode 100644 index 0000000..349486a --- /dev/null +++ b/docs/functions/floor.rst @@ -0,0 +1,4 @@ +floor +===== + +.. autofunction:: arrayfire_wrapper.lib.floor diff --git a/docs/functions/free_device.rst b/docs/functions/free_device.rst new file mode 100644 index 0000000..7d842f9 --- /dev/null +++ b/docs/functions/free_device.rst @@ -0,0 +1,4 @@ +free_device +=========== + +.. autofunction:: arrayfire_wrapper.lib.free_device diff --git a/docs/functions/free_host.rst b/docs/functions/free_host.rst new file mode 100644 index 0000000..da0b090 --- /dev/null +++ b/docs/functions/free_host.rst @@ -0,0 +1,4 @@ +free_host +========= + +.. autofunction:: arrayfire_wrapper.lib.free_host diff --git a/docs/functions/free_pinned.rst b/docs/functions/free_pinned.rst new file mode 100644 index 0000000..16095b7 --- /dev/null +++ b/docs/functions/free_pinned.rst @@ -0,0 +1,4 @@ +free_pinned +=========== + +.. autofunction:: arrayfire_wrapper.lib.free_pinned diff --git a/docs/functions/gaussian_kernel.rst b/docs/functions/gaussian_kernel.rst new file mode 100644 index 0000000..92a3bef --- /dev/null +++ b/docs/functions/gaussian_kernel.rst @@ -0,0 +1,4 @@ +gaussian_kernel +=============== + +.. autofunction:: arrayfire_wrapper.lib.gaussian_kernel diff --git a/docs/functions/ge.rst b/docs/functions/ge.rst new file mode 100644 index 0000000..9c7d803 --- /dev/null +++ b/docs/functions/ge.rst @@ -0,0 +1,4 @@ +ge +== + +.. autofunction:: arrayfire_wrapper.lib.ge diff --git a/docs/functions/get_dbl_support.rst b/docs/functions/get_dbl_support.rst new file mode 100644 index 0000000..65965d9 --- /dev/null +++ b/docs/functions/get_dbl_support.rst @@ -0,0 +1,4 @@ +get_dbl_support +=============== + +.. autofunction:: arrayfire_wrapper.lib.get_dbl_support diff --git a/docs/functions/get_device.rst b/docs/functions/get_device.rst index 953b0c2..8e64928 100644 --- a/docs/functions/get_device.rst +++ b/docs/functions/get_device.rst @@ -1,27 +1,4 @@ get_device ========== -The 'af.get_device()' function in ArrayFire is used to retrieve the device object associated with the ArrayFire context. This function provides information about the current active device, such as its ID, name, and properties. It is useful for managing and querying the status of devices in a multi-device environment. - -Function --------- -:literal:`af.get_device()` - - Python interface used to retrieve the device object associated with the ArrayFire context. - -Detailed Description --------------------- -The 'af.get_device()' function provides access to the device object in ArrayFire. This device object contains various details about the GPU or other computational device that ArrayFire is using for computations. This function is particularly useful in environments where multiple devices are available and you need to query or manage device-specific information. - -Function Documentation ----------------------- -.. sidebar:: af.get_device() - - Syntax: - device = af.get_device() - - - Parameters: - This function does not take any parameters. - - Returns: - An ArrayFire device object representing the current active device in the ArrayFire context. +.. autofunction:: arrayfire_wrapper.lib.get_device diff --git a/docs/functions/get_device_count.rst b/docs/functions/get_device_count.rst new file mode 100644 index 0000000..d42362a --- /dev/null +++ b/docs/functions/get_device_count.rst @@ -0,0 +1,4 @@ +get_device_count +================ + +.. autofunction:: arrayfire_wrapper.lib.get_device_count diff --git a/docs/functions/get_half_support.rst b/docs/functions/get_half_support.rst new file mode 100644 index 0000000..5befef1 --- /dev/null +++ b/docs/functions/get_half_support.rst @@ -0,0 +1,4 @@ +get_half_support +================ + +.. autofunction:: arrayfire_wrapper.lib.get_half_support diff --git a/docs/functions/get_kernel_cache_directory.rst b/docs/functions/get_kernel_cache_directory.rst new file mode 100644 index 0000000..e6e4123 --- /dev/null +++ b/docs/functions/get_kernel_cache_directory.rst @@ -0,0 +1,4 @@ +get_kernel_cache_directory +========================== + +.. autofunction:: arrayfire_wrapper.lib.get_kernel_cache_directory diff --git a/docs/functions/get_mem_step_size.rst b/docs/functions/get_mem_step_size.rst new file mode 100644 index 0000000..94156a3 --- /dev/null +++ b/docs/functions/get_mem_step_size.rst @@ -0,0 +1,4 @@ +get_mem_step_size +================= + +.. autofunction:: arrayfire_wrapper.lib.get_mem_step_size diff --git a/docs/functions/get_native_id.rst b/docs/functions/get_native_id.rst new file mode 100644 index 0000000..b0ff2e8 --- /dev/null +++ b/docs/functions/get_native_id.rst @@ -0,0 +1,4 @@ +get_native_id +============= + +.. autofunction:: arrayfire_wrapper.lib.get_native_id diff --git a/docs/functions/get_stream.rst b/docs/functions/get_stream.rst new file mode 100644 index 0000000..cb6d152 --- /dev/null +++ b/docs/functions/get_stream.rst @@ -0,0 +1,4 @@ +get_stream +========== + +.. autofunction:: arrayfire_wrapper.lib.get_stream diff --git a/docs/functions/gray2rgb.rst b/docs/functions/gray2rgb.rst new file mode 100644 index 0000000..2b61659 --- /dev/null +++ b/docs/functions/gray2rgb.rst @@ -0,0 +1,4 @@ +gray2rgb +======== + +.. autofunction:: arrayfire_wrapper.lib.gray2rgb diff --git a/docs/functions/gt.rst b/docs/functions/gt.rst new file mode 100644 index 0000000..03a4eea --- /dev/null +++ b/docs/functions/gt.rst @@ -0,0 +1,4 @@ +gt +== + +.. autofunction:: arrayfire_wrapper.lib.gt diff --git a/docs/functions/hist_equal.rst b/docs/functions/hist_equal.rst new file mode 100644 index 0000000..5ac088e --- /dev/null +++ b/docs/functions/hist_equal.rst @@ -0,0 +1,4 @@ +hist_equal +========== + +.. autofunction:: arrayfire_wrapper.lib.hist_equal diff --git a/docs/functions/histogram.rst b/docs/functions/histogram.rst new file mode 100644 index 0000000..bb5018a --- /dev/null +++ b/docs/functions/histogram.rst @@ -0,0 +1,4 @@ +histogram +========= + +.. autofunction:: arrayfire_wrapper.lib.histogram diff --git a/docs/functions/hsv2rgb.rst b/docs/functions/hsv2rgb.rst new file mode 100644 index 0000000..28a0317 --- /dev/null +++ b/docs/functions/hsv2rgb.rst @@ -0,0 +1,4 @@ +hsv2rgb +======= + +.. autofunction:: arrayfire_wrapper.lib.hsv2rgb diff --git a/docs/functions/hypot.rst b/docs/functions/hypot.rst new file mode 100644 index 0000000..4a641fc --- /dev/null +++ b/docs/functions/hypot.rst @@ -0,0 +1,4 @@ +hypot +===== + +.. autofunction:: arrayfire_wrapper.lib.hypot diff --git a/docs/functions/ifft2.rst b/docs/functions/ifft2.rst new file mode 100644 index 0000000..98a0149 --- /dev/null +++ b/docs/functions/ifft2.rst @@ -0,0 +1,4 @@ +ifft2 +===== + +.. autofunction:: arrayfire_wrapper.lib.ifft2 diff --git a/docs/functions/ifft3.rst b/docs/functions/ifft3.rst new file mode 100644 index 0000000..20081dc --- /dev/null +++ b/docs/functions/ifft3.rst @@ -0,0 +1,4 @@ +ifft3 +===== + +.. autofunction:: arrayfire_wrapper.lib.ifft3 diff --git a/docs/functions/iir.rst b/docs/functions/iir.rst new file mode 100644 index 0000000..2c38fd2 --- /dev/null +++ b/docs/functions/iir.rst @@ -0,0 +1,4 @@ +iir +=== + +.. autofunction:: arrayfire_wrapper.lib.iir diff --git a/docs/functions/imag.rst b/docs/functions/imag.rst new file mode 100644 index 0000000..6c39fe5 --- /dev/null +++ b/docs/functions/imag.rst @@ -0,0 +1,4 @@ +imag +==== + +.. autofunction:: arrayfire_wrapper.lib.imag diff --git a/docs/functions/index.rst b/docs/functions/index.rst index f1a20f5..d674e06 100644 --- a/docs/functions/index.rst +++ b/docs/functions/index.rst @@ -1,79 +1,253 @@ -Function List -============== +:orphan: .. toctree:: :hidden: :maxdepth: 1 :caption: Function List: - ArrayFire - array - ones - zeros - constant - iota - range - identity - add - multiply - subtract - divide - mod - sqrt - exp - log + abs accum - sum - product + acos + acosh + add + all_true + alloc_device + alloc_host + alloc_pinned + anisotropic_diffusion + any_true + approx1 + approx1_uniform + approx2 + approx2_uniform + arg + asin + asinh + atan + atan2 + atanh + bilateral + bitand + bitnot + bitor + bitshiftl + bitshiftr + bitxor + canny + cast + cbrt + ceil + cholesky + clamp + color_space + confidence_cc + conjg + constant + convolve1 + convolve2 + convolve2_gradient_nn + convolve2_nn + convolve2_separable + convolve3 + copy_array + cos + cosh + count + cplx + cublas_set_math_mode + delete_image_memory + det + device_gc + device_info + device_mem_info + diag diff1 diff2 + dilate + div + dog + dot + eq + erf + erfc + erode + eval + exp + expm1 + factorial + fast + fft + fft2 + fft2_c2r + fft2_r2c + fft3 + fft3_c2r + fft3_r2c + fft_c2r + fft_convolve1 + fft_convolve2 + fft_convolve3 + fft_r2c + fir + flat + flip + floor + free_device + free_host + free_pinned + gaussian_kernel + ge + gemm + get + get_backend + get_dbl_support + get_device + get_device_count + get_half_support + get_kernel_cache_directory + get_mem_step_size + get_native_id + get_stream + gloh gradient + gray2rgb + gt + hamming_matcher + harris + hist_equal + histogram + hsv2rgb + hypot + identity + ifft + ifft2 + ifft3 + iir + imag + imax + imin + info + info_string + init + inv + inverse + inverse_deconv + iota + is_image_io_available + is_lapack_available + isinf + isnan + iszero + iterative_deconv + join + le + lgamma + load_image + load_image_memory + load_image_native + log + log10 + log1p + log2 + logical_and + logical_not + logical_or + lookup + lower + lt + lu + matmul + max + maxfilt + maxof mean + mean_shift + medfilt + medfilt1 + medfilt2 median - sttdev min - max - imin - imax - all_true - any_true - isinf - randu + minfilt + minof + mod + moddims + mul + nearest_neighbour + neg + neq + norm + ones + orb + pad + pinverse + pow + pow2 + print_mem_info + product + qr randn - inv - dot - matmul - gemm - eig - det - fft - ifft - count - sort + randu + range + rank + read_array + real + regions + rem + reorder + replace + reshape + resize + rgb2gray + rgb2hsv + rgb2ycbcr + root + rotate + round + rsqrt + sat + save_array + save_image + save_image_memory + save_image_native + scale + scan + select + set_backend + set_device + set_fft_plan_cache_size set_intersect + set_kernel_cache_directory + set_mem_step_size + set_native_id set_union set_unique - pad - orb + shift sift - fast - dog - gloh - harris + sign + sin + sinh + skew + sobel_operator + solve + sort + sqrt + sttdev + sub + sum susan - hamming_matcher - nearest_neighbour - upper - lower - diag + svd + sync + tan + tanh + tgamma + tile + transform + transform_coordinates + translate transpose - join - reorder - slice - reshape - device - set_device - set_backend - get_device - get_backend - get + trunc + unwrap + upper + where + wrap + zeros diff --git a/docs/functions/info.rst b/docs/functions/info.rst new file mode 100644 index 0000000..5aa50f8 --- /dev/null +++ b/docs/functions/info.rst @@ -0,0 +1,4 @@ +info +==== + +.. autofunction:: arrayfire_wrapper.lib.info diff --git a/docs/functions/info_string.rst b/docs/functions/info_string.rst new file mode 100644 index 0000000..6d8c14a --- /dev/null +++ b/docs/functions/info_string.rst @@ -0,0 +1,4 @@ +info_string +=========== + +.. autofunction:: arrayfire_wrapper.lib.info_string diff --git a/docs/functions/init.rst b/docs/functions/init.rst new file mode 100644 index 0000000..e72fb38 --- /dev/null +++ b/docs/functions/init.rst @@ -0,0 +1,4 @@ +init +==== + +.. autofunction:: arrayfire_wrapper.lib.init diff --git a/docs/functions/inverse.rst b/docs/functions/inverse.rst new file mode 100644 index 0000000..3a5d08e --- /dev/null +++ b/docs/functions/inverse.rst @@ -0,0 +1,4 @@ +inverse +======= + +.. autofunction:: arrayfire_wrapper.lib.inverse diff --git a/docs/functions/inverse_deconv.rst b/docs/functions/inverse_deconv.rst new file mode 100644 index 0000000..5d0eb48 --- /dev/null +++ b/docs/functions/inverse_deconv.rst @@ -0,0 +1,4 @@ +inverse_deconv +============== + +.. autofunction:: arrayfire_wrapper.lib.inverse_deconv diff --git a/docs/functions/is_image_io_available.rst b/docs/functions/is_image_io_available.rst new file mode 100644 index 0000000..c4ad9a2 --- /dev/null +++ b/docs/functions/is_image_io_available.rst @@ -0,0 +1,4 @@ +is_image_io_available +===================== + +.. autofunction:: arrayfire_wrapper.lib.is_image_io_available diff --git a/docs/functions/is_lapack_available.rst b/docs/functions/is_lapack_available.rst new file mode 100644 index 0000000..ef214e7 --- /dev/null +++ b/docs/functions/is_lapack_available.rst @@ -0,0 +1,4 @@ +is_lapack_available +=================== + +.. autofunction:: arrayfire_wrapper.lib.is_lapack_available diff --git a/docs/functions/isnan.rst b/docs/functions/isnan.rst new file mode 100644 index 0000000..36720ab --- /dev/null +++ b/docs/functions/isnan.rst @@ -0,0 +1,4 @@ +isnan +===== + +.. autofunction:: arrayfire.isnan diff --git a/docs/functions/iszero.rst b/docs/functions/iszero.rst new file mode 100644 index 0000000..bec2a9a --- /dev/null +++ b/docs/functions/iszero.rst @@ -0,0 +1,4 @@ +iszero +====== + +.. autofunction:: arrayfire.iszero diff --git a/docs/functions/iterative_deconv.rst b/docs/functions/iterative_deconv.rst new file mode 100644 index 0000000..0650593 --- /dev/null +++ b/docs/functions/iterative_deconv.rst @@ -0,0 +1,4 @@ +iterative_deconv +================ + +.. autofunction:: arrayfire_wrapper.lib.iterative_deconv diff --git a/docs/functions/le.rst b/docs/functions/le.rst new file mode 100644 index 0000000..180d7b3 --- /dev/null +++ b/docs/functions/le.rst @@ -0,0 +1,4 @@ +le +== + +.. autofunction:: arrayfire_wrapper.lib.le diff --git a/docs/functions/lgamma.rst b/docs/functions/lgamma.rst new file mode 100644 index 0000000..35ea774 --- /dev/null +++ b/docs/functions/lgamma.rst @@ -0,0 +1,4 @@ +lgamma +====== + +.. autofunction:: arrayfire_wrapper.lib.lgamma diff --git a/docs/functions/load_image.rst b/docs/functions/load_image.rst new file mode 100644 index 0000000..3ac5153 --- /dev/null +++ b/docs/functions/load_image.rst @@ -0,0 +1,4 @@ +load_image +========== + +.. autofunction:: arrayfire_wrapper.lib.load_image diff --git a/docs/functions/load_image_memory.rst b/docs/functions/load_image_memory.rst new file mode 100644 index 0000000..c6f4cfe --- /dev/null +++ b/docs/functions/load_image_memory.rst @@ -0,0 +1,4 @@ +load_image_memory +================= + +.. autofunction:: arrayfire_wrapper.lib.load_image_memory diff --git a/docs/functions/load_image_native.rst b/docs/functions/load_image_native.rst new file mode 100644 index 0000000..eb62645 --- /dev/null +++ b/docs/functions/load_image_native.rst @@ -0,0 +1,4 @@ +load_image_native +================= + +.. autofunction:: arrayfire_wrapper.lib.load_image_native diff --git a/docs/functions/log10.rst b/docs/functions/log10.rst new file mode 100644 index 0000000..5ebc650 --- /dev/null +++ b/docs/functions/log10.rst @@ -0,0 +1,4 @@ +log10 +===== + +.. autofunction:: arrayfire_wrapper.lib.log10 diff --git a/docs/functions/log1p.rst b/docs/functions/log1p.rst new file mode 100644 index 0000000..5f5727e --- /dev/null +++ b/docs/functions/log1p.rst @@ -0,0 +1,4 @@ +log1p +===== + +.. autofunction:: arrayfire_wrapper.lib.log1p diff --git a/docs/functions/log2.rst b/docs/functions/log2.rst new file mode 100644 index 0000000..d3e5540 --- /dev/null +++ b/docs/functions/log2.rst @@ -0,0 +1,4 @@ +log2 +==== + +.. autofunction:: arrayfire_wrapper.lib.log2 diff --git a/docs/functions/logical_and.rst b/docs/functions/logical_and.rst new file mode 100644 index 0000000..1bba235 --- /dev/null +++ b/docs/functions/logical_and.rst @@ -0,0 +1,4 @@ +logical_and +=========== + +.. autofunction:: arrayfire_wrapper.lib.and_ diff --git a/docs/functions/logical_not.rst b/docs/functions/logical_not.rst new file mode 100644 index 0000000..4001ea2 --- /dev/null +++ b/docs/functions/logical_not.rst @@ -0,0 +1,4 @@ +logical_not +=========== + +.. autofunction:: arrayfire_wrapper.lib.not_ diff --git a/docs/functions/logical_or.rst b/docs/functions/logical_or.rst new file mode 100644 index 0000000..c469538 --- /dev/null +++ b/docs/functions/logical_or.rst @@ -0,0 +1,4 @@ +logical_or +========== + +.. autofunction:: arrayfire_wrapper.lib.or_ diff --git a/docs/functions/lookup.rst b/docs/functions/lookup.rst new file mode 100644 index 0000000..0f3ac72 --- /dev/null +++ b/docs/functions/lookup.rst @@ -0,0 +1,4 @@ +lookup +====== + +.. autofunction:: arrayfire.lookup diff --git a/docs/functions/lt.rst b/docs/functions/lt.rst new file mode 100644 index 0000000..d67e727 --- /dev/null +++ b/docs/functions/lt.rst @@ -0,0 +1,4 @@ +lt +== + +.. autofunction:: arrayfire_wrapper.lib.lt diff --git a/docs/functions/lu.rst b/docs/functions/lu.rst new file mode 100644 index 0000000..530f3fc --- /dev/null +++ b/docs/functions/lu.rst @@ -0,0 +1,4 @@ +lu +==== + +.. autofunction:: arrayfire_wrapper.lib.lu \ No newline at end of file diff --git a/docs/functions/maxfilt.rst b/docs/functions/maxfilt.rst new file mode 100644 index 0000000..a256e56 --- /dev/null +++ b/docs/functions/maxfilt.rst @@ -0,0 +1,4 @@ +maxfilt +======= + +.. autofunction:: arrayfire_wrapper.lib.maxfilt diff --git a/docs/functions/maxof.rst b/docs/functions/maxof.rst new file mode 100644 index 0000000..b9f1caa --- /dev/null +++ b/docs/functions/maxof.rst @@ -0,0 +1,4 @@ +maxof +===== + +.. autofunction:: arrayfire_wrapper.lib.maxof diff --git a/docs/functions/mean_shift.rst b/docs/functions/mean_shift.rst new file mode 100644 index 0000000..ba07d9f --- /dev/null +++ b/docs/functions/mean_shift.rst @@ -0,0 +1,4 @@ +mean_shift +========== + +.. autofunction:: arrayfire_wrapper.lib.mean_shift diff --git a/docs/functions/medfilt.rst b/docs/functions/medfilt.rst new file mode 100644 index 0000000..1339e5a --- /dev/null +++ b/docs/functions/medfilt.rst @@ -0,0 +1,4 @@ +medfilt +======= + +.. autofunction:: arrayfire_wrapper.lib.medfilt diff --git a/docs/functions/medfilt1.rst b/docs/functions/medfilt1.rst new file mode 100644 index 0000000..580beff --- /dev/null +++ b/docs/functions/medfilt1.rst @@ -0,0 +1,4 @@ +medfilt1 +======== + +.. autofunction:: arrayfire_wrapper.lib.medfilt1 diff --git a/docs/functions/medfilt2.rst b/docs/functions/medfilt2.rst new file mode 100644 index 0000000..2e0bb5f --- /dev/null +++ b/docs/functions/medfilt2.rst @@ -0,0 +1,4 @@ +medfilt2 +======== + +.. autofunction:: arrayfire_wrapper.lib.medfilt2 diff --git a/docs/functions/minfilt.rst b/docs/functions/minfilt.rst new file mode 100644 index 0000000..67ed57f --- /dev/null +++ b/docs/functions/minfilt.rst @@ -0,0 +1,4 @@ +minfilt +======= + +.. autofunction:: arrayfire_wrapper.lib.minfilt diff --git a/docs/functions/minof.rst b/docs/functions/minof.rst new file mode 100644 index 0000000..ab3e338 --- /dev/null +++ b/docs/functions/minof.rst @@ -0,0 +1,4 @@ +minof +===== + +.. autofunction:: arrayfire_wrapper.lib.minof diff --git a/docs/functions/moddims.rst b/docs/functions/moddims.rst new file mode 100644 index 0000000..bb1b23d --- /dev/null +++ b/docs/functions/moddims.rst @@ -0,0 +1,4 @@ +moddims +======= + +.. autofunction:: arrayfire.moddims diff --git a/docs/functions/mul.rst b/docs/functions/mul.rst new file mode 100644 index 0000000..31ac3f4 --- /dev/null +++ b/docs/functions/mul.rst @@ -0,0 +1,4 @@ +mul +=== + +.. autofunction:: arrayfire_wrapper.lib.mul diff --git a/docs/functions/multiply.rst b/docs/functions/multiply.rst deleted file mode 100644 index 623b01c..0000000 --- a/docs/functions/multiply.rst +++ /dev/null @@ -1,32 +0,0 @@ -multiply -======== -The 'af.multiply()' function in ArrayFire performs element-wise multiplication between two arrays. This means each element of the first array is multiplied by the corresponding element of the second array. It supports both scalar and array inputs for flexible use. - -Function --------- -:literal:`af.multiply()` - - Python interface used to perform element-wise multiplication between two arrays. - -Detailed Description --------------------- -The 'af.multiply()' function computes the product of two input arrays element-wise. If the inputs are arrays, they must have the same dimensions or be broadcastable to compatible dimensions. If one of the inputs is a scalar, it multiplies each element of the other array by that scalar. - -Function Documentation ----------------------- -.. sidebar:: af.multiply() - - Syntax: - af.multiply(array1, array2) - af.multiply(array, scalar) - af.multiply(scalar, array) - - - Parameters: - 'array1': The first input array. - 'array2': The second input array. Must have the same dimensions as array1 or be broadcastable to the dimensions of array1. - 'array': The input array if using scalar multiplication. - 'scalar': The scalar value to multiply with the array. - - Returns: - An ArrayFire array containing the result of the element-wise multiplication. - diff --git a/docs/functions/neg.rst b/docs/functions/neg.rst new file mode 100644 index 0000000..546ff47 --- /dev/null +++ b/docs/functions/neg.rst @@ -0,0 +1,4 @@ +neg +=== + +.. autofunction:: arrayfire_wrapper.lib.neg diff --git a/docs/functions/neq.rst b/docs/functions/neq.rst new file mode 100644 index 0000000..f577cd6 --- /dev/null +++ b/docs/functions/neq.rst @@ -0,0 +1,4 @@ +neq +=== + +.. autofunction:: arrayfire_wrapper.lib.neq diff --git a/docs/functions/norm.rst b/docs/functions/norm.rst new file mode 100644 index 0000000..f90124b --- /dev/null +++ b/docs/functions/norm.rst @@ -0,0 +1,4 @@ +norm +==== + +.. autofunction:: arrayfire_wrapper.lib.norm diff --git a/docs/functions/pinverse.rst b/docs/functions/pinverse.rst new file mode 100644 index 0000000..5cca53a --- /dev/null +++ b/docs/functions/pinverse.rst @@ -0,0 +1,4 @@ +pinverse +======== + +.. autofunction:: arrayfire_wrapper.lib.pinverse diff --git a/docs/functions/pow.rst b/docs/functions/pow.rst new file mode 100644 index 0000000..62e6c07 --- /dev/null +++ b/docs/functions/pow.rst @@ -0,0 +1,4 @@ +pow +=== + +.. autofunction:: arrayfire_wrapper.lib.pow diff --git a/docs/functions/pow2.rst b/docs/functions/pow2.rst new file mode 100644 index 0000000..0903c95 --- /dev/null +++ b/docs/functions/pow2.rst @@ -0,0 +1,4 @@ +pow2 +==== + +.. autofunction:: arrayfire_wrapper.lib.pow2 diff --git a/docs/functions/print_mem_info.rst b/docs/functions/print_mem_info.rst new file mode 100644 index 0000000..e520947 --- /dev/null +++ b/docs/functions/print_mem_info.rst @@ -0,0 +1,4 @@ +print_mem_info +============== + +.. autofunction:: arrayfire_wrapper.lib.print_mem_info diff --git a/docs/functions/qr.rst b/docs/functions/qr.rst new file mode 100644 index 0000000..f6315b0 --- /dev/null +++ b/docs/functions/qr.rst @@ -0,0 +1,4 @@ +qr +===== + +.. autofunction:: arrayfire_wrapper.lib.qr \ No newline at end of file diff --git a/docs/functions/rank.rst b/docs/functions/rank.rst new file mode 100644 index 0000000..58ab15e --- /dev/null +++ b/docs/functions/rank.rst @@ -0,0 +1,4 @@ +rank +==== + +.. autofunction:: arrayfire_wrapper.lib.rank diff --git a/docs/functions/read_array.rst b/docs/functions/read_array.rst new file mode 100644 index 0000000..f3c6fce --- /dev/null +++ b/docs/functions/read_array.rst @@ -0,0 +1,8 @@ +read_array +========== + +When using with keys: +.. autofunction:: arrayfire_wrapper.lib.read_array_key + +When using with indices: +.. autofunction:: arrayfire_wrapper.lib.read_array_index diff --git a/docs/functions/real.rst b/docs/functions/real.rst new file mode 100644 index 0000000..3369b5a --- /dev/null +++ b/docs/functions/real.rst @@ -0,0 +1,4 @@ +real +==== + +.. autofunction:: arrayfire_wrapper.lib.real diff --git a/docs/functions/regions.rst b/docs/functions/regions.rst new file mode 100644 index 0000000..e42f466 --- /dev/null +++ b/docs/functions/regions.rst @@ -0,0 +1,4 @@ +regions +======= + +.. autofunction:: arrayfire_wrapper.lib.regions diff --git a/docs/functions/rem.rst b/docs/functions/rem.rst new file mode 100644 index 0000000..13bb279 --- /dev/null +++ b/docs/functions/rem.rst @@ -0,0 +1,4 @@ +rem +=== + +.. autofunction:: arrayfire_wrapper.lib.rem diff --git a/docs/functions/replace.rst b/docs/functions/replace.rst new file mode 100644 index 0000000..1b3a2fd --- /dev/null +++ b/docs/functions/replace.rst @@ -0,0 +1,4 @@ +replace +======= + +.. autofunction:: arrayfire.replace diff --git a/docs/functions/resize.rst b/docs/functions/resize.rst new file mode 100644 index 0000000..bc9b7bd --- /dev/null +++ b/docs/functions/resize.rst @@ -0,0 +1,4 @@ +resize +====== + +.. autofunction:: arrayfire_wrapper.lib.resize diff --git a/docs/functions/rgb2gray.rst b/docs/functions/rgb2gray.rst new file mode 100644 index 0000000..3d48ab1 --- /dev/null +++ b/docs/functions/rgb2gray.rst @@ -0,0 +1,4 @@ +rgb2gray +======== + +.. autofunction:: arrayfire_wrapper.lib.rgb2gray diff --git a/docs/functions/rgb2hsv.rst b/docs/functions/rgb2hsv.rst new file mode 100644 index 0000000..7ef5061 --- /dev/null +++ b/docs/functions/rgb2hsv.rst @@ -0,0 +1,4 @@ +rgb2hsv +======= + +.. autofunction:: arrayfire_wrapper.lib.rgb2hsv diff --git a/docs/functions/rgb2ycbcr.rst b/docs/functions/rgb2ycbcr.rst new file mode 100644 index 0000000..4f33c04 --- /dev/null +++ b/docs/functions/rgb2ycbcr.rst @@ -0,0 +1,4 @@ +rgb2ycbcr +========= + +.. autofunction:: arrayfire_wrapper.lib.rgb2ycbcr diff --git a/docs/functions/root.rst b/docs/functions/root.rst new file mode 100644 index 0000000..d073378 --- /dev/null +++ b/docs/functions/root.rst @@ -0,0 +1,4 @@ +root +==== + +.. autofunction:: arrayfire_wrapper.lib.root diff --git a/docs/functions/rotate.rst b/docs/functions/rotate.rst new file mode 100644 index 0000000..8671fab --- /dev/null +++ b/docs/functions/rotate.rst @@ -0,0 +1,4 @@ +rotate +====== + +.. autofunction:: arrayfire_wrapper.lib.rotate diff --git a/docs/functions/round.rst b/docs/functions/round.rst new file mode 100644 index 0000000..cc28ad9 --- /dev/null +++ b/docs/functions/round.rst @@ -0,0 +1,4 @@ +round +===== + +.. autofunction:: arrayfire_wrapper.lib.round_ diff --git a/docs/functions/rsqrt.rst b/docs/functions/rsqrt.rst new file mode 100644 index 0000000..cc8d01e --- /dev/null +++ b/docs/functions/rsqrt.rst @@ -0,0 +1,4 @@ +rsqrt +===== + +.. autofunction:: arrayfire_wrapper.lib.rsqrt diff --git a/docs/functions/sat.rst b/docs/functions/sat.rst new file mode 100644 index 0000000..5851285 --- /dev/null +++ b/docs/functions/sat.rst @@ -0,0 +1,4 @@ +sat +=== + +.. autofunction:: arrayfire_wrapper.lib.sat diff --git a/docs/functions/save_array.rst b/docs/functions/save_array.rst new file mode 100644 index 0000000..4203a2c --- /dev/null +++ b/docs/functions/save_array.rst @@ -0,0 +1,4 @@ +save_array +========== + +.. autofunction:: arrayfire_wrapper.lib.save_array diff --git a/docs/functions/save_image.rst b/docs/functions/save_image.rst new file mode 100644 index 0000000..8a5e04b --- /dev/null +++ b/docs/functions/save_image.rst @@ -0,0 +1,4 @@ +save_image +========== + +.. autofunction:: arrayfire_wrapper.lib.save_image diff --git a/docs/functions/save_image_memory.rst b/docs/functions/save_image_memory.rst new file mode 100644 index 0000000..d5a9b77 --- /dev/null +++ b/docs/functions/save_image_memory.rst @@ -0,0 +1,4 @@ +save_image_memory +================= + +.. autofunction:: arrayfire_wrapper.lib.save_image_memory diff --git a/docs/functions/save_image_native.rst b/docs/functions/save_image_native.rst new file mode 100644 index 0000000..94489b6 --- /dev/null +++ b/docs/functions/save_image_native.rst @@ -0,0 +1,4 @@ +save_image_native +================= + +.. autofunction:: arrayfire_wrapper.lib.save_image_native diff --git a/docs/functions/scale.rst b/docs/functions/scale.rst new file mode 100644 index 0000000..f8837f0 --- /dev/null +++ b/docs/functions/scale.rst @@ -0,0 +1,4 @@ +scale +===== + +.. autofunction:: arrayfire_wrapper.lib.scale diff --git a/docs/functions/scan.rst b/docs/functions/scan.rst new file mode 100644 index 0000000..8e5070d --- /dev/null +++ b/docs/functions/scan.rst @@ -0,0 +1,4 @@ +scan +===== + +.. autofunction:: arrayfire.scan \ No newline at end of file diff --git a/docs/functions/select.rst b/docs/functions/select.rst new file mode 100644 index 0000000..86224b5 --- /dev/null +++ b/docs/functions/select.rst @@ -0,0 +1,4 @@ +select +====== + +.. autofunction:: arrayfire.select diff --git a/docs/functions/set_device.rst b/docs/functions/set_device.rst index 10007ae..de199c0 100644 --- a/docs/functions/set_device.rst +++ b/docs/functions/set_device.rst @@ -1,25 +1,4 @@ set_device ========== -The 'af.set_device()' function in ArrayFire is used to specify which device (GPU or CPU) will be used for subsequent ArrayFire operations. This is particularly useful when working with multiple devices or GPUs to ensure that computations are directed to the desired hardware. -Function --------- -:literal:`af.set_device()` - - Python interface used to specify which device will be used for subsequent arrayfire operations. - -Detailed Description --------------------- -The 'af.set_device()' function sets the device ID for ArrayFire operations. By default, ArrayFire uses the first available device (usually device ID 0). When you have multiple GPUs or devices, you can use this function to select which device ArrayFire should use for subsequent operations. - -Function Documentation ----------------------- -.. sidebar:: af.set_device() - - Syntax: - af.set_device(device_id) - - Parameters: - 'device_id': An integer representing the ID of the device to be set. This ID corresponds to the device index in the ArrayFire device list. - - Returns: - None +.. autofunction:: arrayfire_wrapper.lib.set_device diff --git a/docs/functions/set_fft_plan_cache_size.rst b/docs/functions/set_fft_plan_cache_size.rst new file mode 100644 index 0000000..3ddf2a6 --- /dev/null +++ b/docs/functions/set_fft_plan_cache_size.rst @@ -0,0 +1,4 @@ +set_fft_plan_cache_size +======================= + +.. autofunction:: arrayfire_wrapper.lib.set_fft_plan_cache_size diff --git a/docs/functions/set_kernel_cache_directory.rst b/docs/functions/set_kernel_cache_directory.rst new file mode 100644 index 0000000..0263993 --- /dev/null +++ b/docs/functions/set_kernel_cache_directory.rst @@ -0,0 +1,4 @@ +set_kernel_cache_directory +========================== + +.. autofunction:: arrayfire_wrapper.lib.set_kernel_cache_directory diff --git a/docs/functions/set_mem_step_size.rst b/docs/functions/set_mem_step_size.rst new file mode 100644 index 0000000..e6d1009 --- /dev/null +++ b/docs/functions/set_mem_step_size.rst @@ -0,0 +1,4 @@ +set_mem_step_size +================= + +.. autofunction:: arrayfire_wrapper.lib.set_mem_step_size diff --git a/docs/functions/set_native_id.rst b/docs/functions/set_native_id.rst new file mode 100644 index 0000000..0aa9a3f --- /dev/null +++ b/docs/functions/set_native_id.rst @@ -0,0 +1,4 @@ +set_native_id +============= + +.. autofunction:: arrayfire_wrapper.lib.set_native_id diff --git a/docs/functions/shift.rst b/docs/functions/shift.rst new file mode 100644 index 0000000..d2ee410 --- /dev/null +++ b/docs/functions/shift.rst @@ -0,0 +1,4 @@ +shift +===== + +.. autofunction:: arrayfire.shift diff --git a/docs/functions/sign.rst b/docs/functions/sign.rst new file mode 100644 index 0000000..217a041 --- /dev/null +++ b/docs/functions/sign.rst @@ -0,0 +1,4 @@ +sign +==== + +.. autofunction:: arrayfire_wrapper.lib.sign diff --git a/docs/functions/sin.rst b/docs/functions/sin.rst new file mode 100644 index 0000000..6d16d7d --- /dev/null +++ b/docs/functions/sin.rst @@ -0,0 +1,4 @@ +sin +=== + +.. autofunction:: arrayfire_wrapper.lib.sin diff --git a/docs/functions/sinh.rst b/docs/functions/sinh.rst new file mode 100644 index 0000000..ee4170c --- /dev/null +++ b/docs/functions/sinh.rst @@ -0,0 +1,4 @@ +sinh +==== + +.. autofunction:: arrayfire_wrapper.lib.sinh diff --git a/docs/functions/skew.rst b/docs/functions/skew.rst new file mode 100644 index 0000000..079d161 --- /dev/null +++ b/docs/functions/skew.rst @@ -0,0 +1,4 @@ +skew +==== + +.. autofunction:: arrayfire_wrapper.lib.skew diff --git a/docs/functions/slice.rst b/docs/functions/slice.rst deleted file mode 100644 index 3832e45..0000000 --- a/docs/functions/slice.rst +++ /dev/null @@ -1,27 +0,0 @@ -slice -===== -The 'af.slice()' function in ArrayFire is used to extract a subarray from a larger array by specifying the start and end indices along each dimension. This function is useful for accessing a portion of an array, which is essential for tasks such as data manipulation, cropping, and partitioning. - -Function --------- -:literal:`af.slice()` - - Python interface used to extract a subarray from a larger array by specifying the start and end indices along each dimension. - -Detailed Description --------------------- -The 'af.slice()' function allows you to extract a contiguous subarray from the original array. You specify the starting and ending indices for each dimension to define the subarray. This function provides a way to access specific regions of multi-dimensional arrays efficiently. - -Function Documentation ----------------------- -.. sidebar:: af.slice() - - Syntax: - af.slice(array, \*start_indices, \*end_indices) - - Parameters: - 'array': The ArrayFire array from which the subarray will be extracted. - '\*start_indices': A sequence of integers specifying the starting indices for each dimension. - '\*end_indices': A sequence of integers specifying the ending indices for each dimension. - - Returns: - An ArrayFire array containing the extracted subarray. diff --git a/docs/functions/sobel_operator.rst b/docs/functions/sobel_operator.rst new file mode 100644 index 0000000..561ed51 --- /dev/null +++ b/docs/functions/sobel_operator.rst @@ -0,0 +1,4 @@ +sobel_operator +============== + +.. autofunction:: arrayfire_wrapper.lib.sobel_operator diff --git a/docs/functions/solve.rst b/docs/functions/solve.rst new file mode 100644 index 0000000..e2e8999 --- /dev/null +++ b/docs/functions/solve.rst @@ -0,0 +1,4 @@ +solve +===== + +.. autofunction:: arrayfire_wrapper.lib.solve diff --git a/docs/functions/sub.rst b/docs/functions/sub.rst new file mode 100644 index 0000000..a43c7bc --- /dev/null +++ b/docs/functions/sub.rst @@ -0,0 +1,4 @@ +sub +=== + +.. autofunction:: arrayfire_wrapper.lib.sub diff --git a/docs/functions/subtract.rst b/docs/functions/subtract.rst deleted file mode 100644 index b92b0ea..0000000 --- a/docs/functions/subtract.rst +++ /dev/null @@ -1,29 +0,0 @@ -subtract -======== -The 'af.subtract()' function in ArrayFire is used to perform element-wise subtraction between two arrays or between an array and a scalar. This operation is fundamental in many computational tasks, including data manipulation, feature scaling, and mathematical operations. - -Function --------- -:literal:`af.subtract()` - - Python interface used to perform element-wise subtraction between two arrays or between an array and a scalar. - -Detailed Description --------------------- -The 'af.subtract()' function subtracts the elements of one array from the corresponding elements of another array, or subtracts a scalar value from each element of an array. The function performs this operation element-wise, meaning that each element of the first operand is subtracted by the corresponding element of the second operand. - -Function Documentation ----------------------- -.. sidebar:: af.subtract() - - Syntax: - af.subtract(array1, array2) - af.subtract(array, scalar) - - Parameters: - 'array1': The ArrayFire array from which elements will be subtracted. - 'array2': The ArrayFire array to subtract from array1. This should have the same shape as array1 or be broadcast-compatible. - 'scalar': A scalar value to subtract from each element of array. - - Returns: - An ArrayFire array containing the result of the subtraction. - diff --git a/docs/functions/svd.rst b/docs/functions/svd.rst new file mode 100644 index 0000000..1b19f90 --- /dev/null +++ b/docs/functions/svd.rst @@ -0,0 +1,4 @@ +svd +==== + +.. autofunction:: arrayfire_wrapper.lib.svd \ No newline at end of file diff --git a/docs/functions/sync.rst b/docs/functions/sync.rst new file mode 100644 index 0000000..59462ba --- /dev/null +++ b/docs/functions/sync.rst @@ -0,0 +1,4 @@ +sync +======== + +.. autofunction:: arrayfire.sync \ No newline at end of file diff --git a/docs/functions/tan.rst b/docs/functions/tan.rst new file mode 100644 index 0000000..c12a06f --- /dev/null +++ b/docs/functions/tan.rst @@ -0,0 +1,4 @@ +tan +=== + +.. autofunction:: arrayfire_wrapper.lib.tan diff --git a/docs/functions/tanh.rst b/docs/functions/tanh.rst new file mode 100644 index 0000000..f6fa790 --- /dev/null +++ b/docs/functions/tanh.rst @@ -0,0 +1,4 @@ +tanh +==== + +.. autofunction:: arrayfire_wrapper.lib.tanh diff --git a/docs/functions/tgamma.rst b/docs/functions/tgamma.rst new file mode 100644 index 0000000..8ef337c --- /dev/null +++ b/docs/functions/tgamma.rst @@ -0,0 +1,4 @@ +tgamma +====== + +.. autofunction:: arrayfire_wrapper.lib.tgamma diff --git a/docs/functions/tile.rst b/docs/functions/tile.rst new file mode 100644 index 0000000..ca8abca --- /dev/null +++ b/docs/functions/tile.rst @@ -0,0 +1,4 @@ +tile +==== + +.. autofunction:: arrayfire.tile diff --git a/docs/functions/transform.rst b/docs/functions/transform.rst new file mode 100644 index 0000000..c30247b --- /dev/null +++ b/docs/functions/transform.rst @@ -0,0 +1,4 @@ +transform +========= + +.. autofunction:: arrayfire_wrapper.lib.transform diff --git a/docs/functions/transform_coordinates.rst b/docs/functions/transform_coordinates.rst new file mode 100644 index 0000000..05e61cf --- /dev/null +++ b/docs/functions/transform_coordinates.rst @@ -0,0 +1,4 @@ +transform_coordinates +===================== + +.. autofunction:: arrayfire_wrapper.lib.transform_coordinates diff --git a/docs/functions/translate.rst b/docs/functions/translate.rst new file mode 100644 index 0000000..a16cda7 --- /dev/null +++ b/docs/functions/translate.rst @@ -0,0 +1,4 @@ +translate +========= + +.. autofunction:: arrayfire_wrapper.lib.translate diff --git a/docs/functions/trunc.rst b/docs/functions/trunc.rst new file mode 100644 index 0000000..783ba23 --- /dev/null +++ b/docs/functions/trunc.rst @@ -0,0 +1,4 @@ +trunc +===== + +.. autofunction:: arrayfire_wrapper.lib.trunc diff --git a/docs/functions/unwrap.rst b/docs/functions/unwrap.rst new file mode 100644 index 0000000..10789f9 --- /dev/null +++ b/docs/functions/unwrap.rst @@ -0,0 +1,4 @@ +unwrap +====== + +.. autofunction:: arrayfire_wrapper.lib.unwrap diff --git a/docs/functions/where.rst b/docs/functions/where.rst new file mode 100644 index 0000000..45614a0 --- /dev/null +++ b/docs/functions/where.rst @@ -0,0 +1,4 @@ +where +======= + +.. autofunction:: arrayfire.where \ No newline at end of file diff --git a/docs/functions/wrap.rst b/docs/functions/wrap.rst new file mode 100644 index 0000000..e66a277 --- /dev/null +++ b/docs/functions/wrap.rst @@ -0,0 +1,4 @@ +wrap +==== + +.. autofunction:: arrayfire_wrapper.lib.wrap diff --git a/docs/gettingstarted.rst b/docs/gettingstarted.rst index a180b49..f199f6b 100644 --- a/docs/gettingstarted.rst +++ b/docs/gettingstarted.rst @@ -6,8 +6,8 @@ Introduction ArrayFire is a high performance software library for parallel computing with an easy-to-use API. ArrayFire abstracts away much of the details of programming parallel architectures by providing a high-level container object, the array, that represents data stored on a CPU, GPU, FPGA, or other type of accelerator. This abstraction permits developers to write massively parallel applications in a high-level language where they need not be concerned about low-level optimizations that are frequently required to achieve high throughput on most parallel architectures. -Supported data types -******************** +:doc:`Supported data types ` +********************************************** ArrayFire provides one generic container object, the array on which functions and mathematical operations are performed. The :literal:`array` can represent one of many different basic data types: @@ -136,34 +136,13 @@ Indexing Like all functions in ArrayFire, indexing is also executed in parallel on the OpenCL/CUDA devices. Because of this, indexing becomes part of a JIT operation and is accomplished using parentheses instead of square brackets (i.e. as :literal:`A(0)` instead of :literal:`A[0]`). To index :literal:`af::` arrays you may use one or a combination of the following functions: * integer scalars -* seq() representing a linear sequence -* end representing the last element of a dimension -* span representing the entire description -* row(i) or col(i) specifying a single row/column -* rows(first,last) or cols(first,last) specifying a span of rows or columns +* :literal:`:` representing the entire description +* :literal:`begin:end:step` representing a linear sequence/slice +* :literal:`row(i)` or :literal:`col(i)` specifying a single row/column +* :literal:`rows(first,last)` or :literal:`cols(first,last)` specifying a span of rows or columns Please see the indexing page for several examples of how to use these functions. -Getting access to ArrayFire array memory on the host and device -*************************************************************** - -Memory in :literal:`af::arrays` may be accessed using the host() and device() functions. The :literal:`host` function copies the data from the device and makes it available in a C-style array on the host. As such, it is up to the developer to manage any memory returned by :literal:`host`. The :literal:`device` function returns a pointer/reference to device memory for interoperability with external CUDA/OpenCL kernels. As this memory belongs to ArrayFire, the programmer should not attempt to free/deallocate the pointer. For example, here is how we can interact with both OpenCL and CUDA: - -.. literalinclude:: gettingstarted.py - :language: python - :start-after: [gettingstarted10-snippet] - :end-before: [gettingstarted10-endsnippet] - - -ArrayFire also provides several helper functions for creating :literal:`af::arrays` from OpenCL :literal:`cl_mem` references and :literal:`cl::Buffer` objects. See the :literal:`include/af/opencl.h` file for further information. - -Lastly, if you want only the first value from an :literal:`af::array` you can use get it using the scalar() function: - -.. literalinclude:: gettingstarted.py - :language: python - :start-after: [gettingstarted11-snippet] - :end-before: [gettingstarted11-endsnippet] - Bitwise operators ***************** @@ -174,14 +153,6 @@ In addition to supporting standard mathematical functions, arrays that contain i :start-after: [gettingstarted12-snippet] :end-before: [gettingstarted12-endsnippet] - -Using the ArrayFire API in Python -********************************* - -The ArrayFire library in Python is seamlessly integrated into the Python environment. To start using the library, simply :literal:`import arrayfire` and begin coding! - -# todo @stf talk about arrayapi implementation - Sample using Python API ~~~~~~~~~~~~~~~~~~~~~~~ @@ -189,22 +160,3 @@ Sample using Python API :language: python :start-after: [gettingstarted13-snippet] :end-before: [gettingstarted13-endsnippet] - - - -What to read next? -################## - -Now that you have a general introduction to ArrayFire, where do you go from here? In particular you might find these documents useful - -* Building an ArrayFire program on Linux -* Building an ArrayFire program on Windows -* Timing ArrayFire code - -Where to go for help? -##################### - -* Google Groups: https://groups.google.com/forum/#!forum/arrayfire-users -* ArrayFire Services: `Consulting `_ | `Support `_ | `Training `_ -* ArrayFire Blogs: http://arrayfire.com/blog/ -* Email: technical@arrayfire.com \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst index f66a304..e101e80 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,16 +1,11 @@ -.. TestProject2 documentation master file, created by - sphinx-quickstart on Mon Jun 24 10:53:47 2024. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -Welcome to ArrayFire's documentation! -===================================== - .. image:: images/arrayfire_logo.png :alt: ArrayFire Logo :align: center :class: responsive-img +Welcome to ArrayFire's documentation! +===================================== + .. toctree:: :maxdepth: 1 :caption: The Basics @@ -25,32 +20,23 @@ Welcome to ArrayFire's documentation! :caption: User Guide configuringarrayfireenvironment - functions introductiontovectorization arrayfirejitcodegeneration arrayandmatrixmanipulation indexing timing_arrayfire debuggingarrayfirecode - linux .. toctree:: :maxdepth: 1 :caption: Reference + functions examples - releasenotes - functions/index - - -.. toctree:: - :maxdepth: 1 - :caption: Catalogue - genindex - modindex - search - + releasenotes + product_support + license diff --git a/docs/indexing.rst b/docs/indexing.rst index 4622ceb..0eb016b 100644 --- a/docs/indexing.rst +++ b/docs/indexing.rst @@ -1,6 +1,6 @@ Indexing ======== -Indexing in ArrayFire is a powerful but easy to abuse feature of the af::array class. This feature allows you to reference or copy subsections of a larger array and perform operations on only a subset of elements. +Indexing in ArrayFire is a powerful but easy to abuse feature of the af.Array class. This feature allows you to reference or copy subsections of a larger array and perform operations on only a subset of elements. Indexing in ArrayFire can be performed using the parenthesis operator or one of the member functions of the af::array class. These functions allow you to reference one or a range of elements from the original array. @@ -24,7 +24,7 @@ ArrayFire is column-major so the resulting A array will look like this: 3 & 7 & 11 & 15 \end{bmatrix} -In Python, for a two-dimensional array like a matrix, you can access its first element by providing the indices 0, 0 within the indexing operator of the af.array object. +In Python, for a two-dimensional array like a matrix, you can access its first element by providing the indices 0, 0 within the indexing operator of the af.Array object. .. literalinclude:: indexing.py :language: python @@ -106,17 +106,43 @@ You can use Python's slicing notation to define a range when indexing in **array \end{bmatrix} -Indexing using af.Array ? (Does the python wrapper support cartesian products) TODO STF -*************************************************************************************** +Indexing using af.Array +*************************** +In Python with arrayfire, you can also index arrays using other **af.Array** objects. Arrayfire flattens the input and treats the elements inside the array +as column major indices to index the original Array as 1D Array. -In Python with arrayfire, you can also index arrays using other **af.array** objects. arrayfire performs a Cartesian product of the input arrays. +.. code-block:: python + + import arrayfire as af + + x = af.randu((10, 10)) + + # indices 1, 3, 5 + indices = af.range((3)) * 2 + 1 + + # returns entries with indices 1, 3, 5 of x.flat() + y = x[indices] + + +You can also index Arrays using boolean Arrays. ArrayFire will return an Array with length of the number of :literal:`True` elements in the indexing arrays +and entries of in column major order of the elements that correspond to :literal:`True` entries: + +.. code-block:: python + + import arrayfire as af + + # Creates a random array + x = af.randu((10, 10)) + + # returns an array with all the entries of x that contain values greater than 0.5 + y = x[x > 0.5] References and copies ********************* -All indexing operations in ArrayFire return **af.array** objects, which are instances of the array_proxy class. These objects can either be newly created arrays or references to the original array, depending on the type of indexing operation applied to them +All indexing operations in ArrayFire return **af.Array** objects, which are instances of the array_proxy class. These objects can either be newly created arrays or references to the original array, depending on the type of indexing operation applied to them -* When an array is indexed using another **af.array** , a new array is created instead of referencing the original data. +* When an array is indexed using another **af.Array** , a new array is created instead of referencing the original data. * If an array was indexed using a scalar, **sequential '0:2'** or **span ':'**, then the resulting array will reference the original data IF the first dimension is continuous. The following lines will not allocate additional memory. .. note:: @@ -136,11 +162,11 @@ The following code snippet shows some examples of indexing that will allocate ne :start-after: [indexing8-snippet] :end-before: [indexing8-endsnippet] -Even though the copy3 array references continuous memory in the original array, using an **af.array** for indexing in ArrayFire results in the creation of a new array +Even though the copy3 array references continuous memory in the original array, using an **af.Array** for indexing in ArrayFire results in the creation of a new array Assignment ********** -In Python with ArrayFire, assigning an **af.array** replaces the array on the left-hand side of :literal:`=` with the result from the right-hand side. This can lead to changes in type and shape compared to the original array. Notably, assignments do not update arrays previously referenced through indexing operations. +In Python with ArrayFire, assigning an **af.Array** replaces the array on the left-hand side of :literal:`=` with the result from the right-hand side. This can lead to changes in type and shape compared to the original array. Notably, assignments do not update arrays previously referenced through indexing operations. .. literalinclude:: indexing.py :language: python @@ -191,11 +217,10 @@ You can also assign to arrays using another af::arrays as an indexing array. Thi :end-before: [indexing12-endsnippet] +Member Functions +********************* -**TODO STF** - -Member Functions TODO STF -************************* +Check the :doc:`Array Class ` for more details on other functions that the Array object provides. Additional examples ******************* diff --git a/docs/introductiontovectorization.py b/docs/introductiontovectorization.py index f44c63a..4551d1b 100644 --- a/docs/introductiontovectorization.py +++ b/docs/introductiontovectorization.py @@ -73,7 +73,7 @@ print("Shape of rotated images:", rot_imgs.shape()) # Optionally, print the rotated images -# af.af_print(rot_imgs) +# print(rot_imgs) # Optionally, display or further process `rot_imgs` as needed @@ -95,30 +95,6 @@ print(a) # [vectorization5-endsnippet] - -#NOT WORKING -# [vectorization6-snippet] - -import arrayfire as af - -# Example data dimensions -N = 10 -SPAN = af.span - -# Example arrays A and B -A = af.randu(100, N) # Example array A of size 100xN filled with random numbers -B = af.constant(0, 100, N) # Example array B initialized with zeros - -# Parallel execution using gfor loop -af.gfor(seq_i, N): -B[SPAN, seq_i] = af.accum(A[SPAN, seq_i]) - -# Print array B after parallel accumulations -print("Array B after parallel accumulations:") -af.af_print(B) -# [vectorization6-endsnippet] - - # [vectorization7-snippet] import arrayfire as af @@ -129,32 +105,6 @@ # [vectorization7-endsnippet] -#NOT WORKING -# [vectorization8-snippet] - -import arrayfire as af - -# Define constants -p = 4 -n = 1000 - -# Generate constants array and variable terms array -consts = af.randu(p) -var_terms = af.randn(p, n) - -# Initialize combination array -combination = af.constant(0, p, n) - -# Perform element-wise multiplication using gfor loop -af.gfor(seq_i, n): -combination[:, seq_i] = consts * var_terms[:, seq_i] - -# Print the combination array after computation -print("Combination array:") -af.af_print(combination) -# [vectorization8-endsnippet] - - # [vectorization9-snippet] @@ -171,7 +121,7 @@ # Print the filtered weights array print("Filtered weights:") -af.af_print(filtered_weights) +print(filtered_weights) # [vectorization9-endsnippet] @@ -184,12 +134,30 @@ weights = af.randu((5, 5)) # Shape: 5x5 # Transpose the filter to align dimensions for broadcasting -filter_transposed = af.transpose(filter) # Shape: 5x1 +filter_transposed = filter.T # Shape: 5x1 # Element-wise multiplication with broadcasting filtered_weights = filter_transposed * weights # Print the filtered weights array print("Filtered weights:") -print(filtered_weights) +print(filtered_weights) # Incorrect # [vectorization10-endsnippet] + +# [vectorization11-snippet] + +import arrayfire as af + +# Create the filter and weight vectors +filter = af.randu((1, 5)) # Shape: 1x5 +batched_filter = af.tile(filter, (1, 1, 5)) # batch on the third dimension +weights = af.randu((5, 5)) # Shape: 5x5 + +# Leverage matmul batching +filtered_weights = af.matmul(batched_filter, weights) # shape 1x5x5 +filtered_weights = af.moddims(filtered_weights, (5, 5)) # reshape to 2d 5x5 + +# Print the filtered weights array +print("Filtered weights:") +print(filtered_weights) +# [vectorization11-endsnippet] diff --git a/docs/introductiontovectorization.rst b/docs/introductiontovectorization.rst index a38e068..7088427 100644 --- a/docs/introductiontovectorization.rst +++ b/docs/introductiontovectorization.rst @@ -62,47 +62,8 @@ Although most functions in ArrayFire do support vectorization, some do not. Most Using the built in vectorized operations should be the first and preferred method of vectorizing any code written with ArrayFire. -GFOR: Parallel for-loops -************************ -Another novel method of vectorization present in ArrayFire is the GFOR loop replacement construct. GFOR allows launching all iterations of a loop in parallel on the GPU or device, as long as the iterations are independent. While the standard for-loop performs each iteration sequentially, ArrayFire's gfor-loop performs each iteration at the same time (in parallel). ArrayFire does this by tiling out the values of all loop iterations and then performing computation on those tiles in one pass. You can think of gfor as performing auto-vectorization of your code, e.g. you write a gfor-loop that increments every element of a vector but behind the scenes ArrayFire rewrites it to operate on the entire vector in parallel. - -The original for-loop example at the beginning of this document could be rewritten using GFOR as follows: - -.. literalinclude:: introductiontovectorization.py - :language: python - :start-after: [vectorization5-snippet] - :end-before: [vectorization5-endsnippet] - -In this case, each instance of the gfor loop is independent, thus ArrayFire will automatically tile out the :literal:`a` array in device memory and execute the increment kernels in parallel. - -To see another example, you could run an accum() on every slice of a matrix in a for-loop, or you could "vectorize" and simply do it all in one gfor-loop operation: - -.. literalinclude:: introductiontovectorization.py - :language: python - :start-after: [vectorization6-snippet] - :end-before: [vectorization6-endsnippet] - -However, returning to our previous vectorization technique, accum() is already vectorized and the operation could be completely replaced with merely: - -.. literalinclude:: introductiontovectorization.py - :language: python - :start-after: [vectorization7-snippet] - :end-before: [vectorization7-endsnippet] - -It is best to vectorize computation as much as possible to avoid the overhead in both for-loops and gfor-loops. However, the gfor-loop construct is most effective in the narrow case of broadcast-style operations. Consider the case when we have a vector of constants that we wish to apply to a collection of variables, such as expressing the values of a linear combination for multiple vectors. The broadcast of one set of constants to many vectors works well with gfor-loops: - -.. literalinclude:: introductiontovectorization.py - :language: python - :start-after: [vectorization8-snippet] - :end-before: [vectorization8-endsnippet] - -Using GFOR requires following several rules and multiple guidelines for optimal performance. The details of this vectorization method can be found in the GFOR documentation. - - Batching ******** -The batchFunc() function allows the broad application of existing ArrayFire functions to multiple sets of data. Effectively, batchFunc() allows ArrayFire functions to execute in "batch processing" mode. In this mode, functions will find a dimension which contains "batches" of data to be processed and will parallelize the procedure. - Consider the following example. Here we create a filter which we would like to apply to each of the weight vectors. The naive solution would be using a for-loop as we have seen previously: .. literalinclude:: introductiontovectorization.py @@ -117,11 +78,19 @@ However, as we have discussed above, this solution will be very inefficient. One :start-after: [vectorization10-snippet] :end-before: [vectorization10-endsnippet] - However, the dimensions of :literal:`filter` and :literal:`weights` do not match, thus ArrayFire will generate a runtime error. +The correct solution is to use `batch operations with matmul `_ +By tiling on the third dimension, matmul is done in the first 2 dimensions and batched on the third to obtain the filtered weights: + +.. literalinclude:: introductiontovectorization.py + :language: python + :start-after: [vectorization11-snippet] + :end-before: [vectorization11-endsnippet] + + Advanced Vectorization ********************** -We have seen the different methods ArrayFire provides to vectorize our code. Tying them all together is a slightly more involved process that needs to consider data dimensionality and layout, memory usage, nesting order, etc. An excellent example and discussion of these factors can be found on our blog: - -http://arrayfire.com/how-to-write-vectorized-code/ \ No newline at end of file +We have seen the different methods ArrayFire provides to vectorize our code. Tying them all together is a slightly more involved process that needs to consider +data dimensionality and layout, memory usage, nesting order, etc. An excellent example and discussion of these factors can be found on our blog: +`How to write vectorized code `_ (Ignore GFOR section as it is not applicable to Python). diff --git a/docs/license.rst b/docs/license.rst new file mode 100644 index 0000000..ccab0bf --- /dev/null +++ b/docs/license.rst @@ -0,0 +1,69 @@ +License +========== + +Copyright (c) 2014-2025, ArrayFire +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +* Neither the name ArrayFire nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Trademark Policy +################ +The literal mark “ArrayFire” and ArrayFire logos are trademarks of ArrayFire. + +Trademarks are used to identify and distinguish the source of goods of one party from those offered by others. As such, a trademark must be used properly and consistently otherwise the mark risks becoming generic, making it impossible to enforce. The following guidelines govern the use of ArrayFire trademarks whether by ArrayFire or third parties, in order to protect the value of ArrayFire trademarks and provide guidance to users on how they should or should not use ArrayFire marks. Unauthorized use of ArrayFire trademarks, or similarly confusing marks, which do not comply with the guidelines below, is prohibited and may constitute trademark infringement. These guidelines do not interfere with your right to use or modify the underlying ArrayFire open source software as permitted under the applicable software license. + +Throughout this Policy, the word “Marks” refers to the following: + +The literal mark “ArrayFire” +The logos and graphic marks displayed and available for download at http://arrayfire.com/trademark +The slogan “If you want faster code, you’ve come to the right place” +Throughout this Policy "ArrayFire Product" refers to software, source code, services, and training content developed by ArrayFire or otherwise contributed to ArrayFire by third-parties. + +Fair Use +******** + +You may use the Marks without prior written permission to refer to an ArrayFire Product when the Marks are used for the purpose of description or identification of an ArrayFire Product where there is no suggestion of endorsement or sponsorship by the trademark owner or use of the Marks in such a way to confuse the consumer. Such use is generally regarded as "fair use" under trademark law. + +A few examples of use cases that are clearly fair use are: + +To refer to the ArrayFire software in substantially unmodified form. +To identify the ArrayFire software as a distinct component of a software offering where the Mark is not being used in a way which suggests sponsorship or endorsement of the project. +To factually refer to an ArrayFire Product. +Use of the Marks without written permission +Subject to the inclusion of the disclaimer at the bottom of this section, we permit the use of the literal mark, "ArrayFire" to refer to projects, services, or communities outside of ArrayFire Product without written permission in the following contexts: + +When referring to the ArrayFire software that is not substantially unmodified, to say that such software is a “derivative of” or “based on” ArrayFire. +When referring to third-party software that provides interoperability between ArrayFire and a programming language (commonly called "language wrappers"), in the format "ArrayFire.[Language]" or "ArrayFire-[Language]" or [Language] for ArrayFire" -- provided that such use case otherwise compiles with the rest of the Policy. +When referring to a third-party software product and/or service that is interoperable with the ArrayFire software, in the format “[Product Name] for ArrayFire” -- provided that such use otherwise complies with the rest of the Policy. +In the above scenarios, the following disclaimer must be prominently displayed: + +"[Your project name] is not affiliated with or endorsed by ArrayFire. The ArrayFire literal mark is used under a limited license granted by ArrayFire the trademark holder in the United States and other countries." + +Prohibited Use +**************** +You may not use the Marks in the following ways: + +In any way likely to cause confusion as to the identity of an ArrayFire Product, the provenance of its software, or the software's license. +In any way that indicates a greater degree of association between you and the ArrayFire Project or ArrayFire than actually exists. +In any way that implies a designated successor to an ArrayFire Product. +To refer to the ArrayFire software, modified by a third party to the point of inoperability with ArrayFire software in substantially unmodified form. +In any other way that dilutes or otherwise infringes upon the trademark rights of ArrayFire. +In addition, you may not use any of the Marks as a syllable in a new word or as part of a portmanteau (e.g., “ArrayFirepedia”) used as a mark for a third-party product or service without explicit written permission from ArrayFire. For the avoidance of doubt, this provision applies even to third-party marks that use the Marks as a syllable or as part of a portmanteau to refer to a product or service's use of ArrayFire code. + +Reservation of Rights +********************** +ArrayFire reserves the sole right to: + +Determine the compliance with this Policy +Modify the Policy in ways consistent with the mission of protecting the public. +Grant exceptions to this Policy, of any kind and for any reason whatsoever, other clauses notwithstanding. +Questions +If you have any questions regarding this Policy, wish to report any misuse of ArrayFire trademarks, or are unsure on whether you require a trademark license, or wish to obtain a license to use ArrayFire Marks, please contact sales@arrayfire.com. \ No newline at end of file diff --git a/docs/linear_algebra_functions.rst b/docs/linear_algebra_functions.rst new file mode 100644 index 0000000..aeab32f --- /dev/null +++ b/docs/linear_algebra_functions.rst @@ -0,0 +1,35 @@ +Linear Algebra +=============== + +Functions for performing linear algebra operations, essential in many scientific and engineering tasks. + +.. list-table:: Functions + + * - :doc:`af.det() ` + - Find the determinant of a matrix. + * - :doc:`af.dot() ` + - Compute the dot product. + * - :doc:`af.gemm() ` + - General matrix multiplication. + * - :doc:`af.inv() ` + - Computes the inverse of a matrix. + * - :doc:`af.inverse() ` + - Invert a matrix. + * - :doc:`af.is_lapack_available() ` + - Check if lapack runtimes are available + * - :doc:`af.lu() ` + - Perform LU decomposition. + * - :doc:`af.matmul() ` + - Matrix multiplication. + * - :doc:`af.norm() ` + - Find the norm of a matrix. + * - :doc:`af.pinverse() ` + - Pseudo-invert (Moore-Penrose) a matrix. + * - :doc:`af.qr() ` + - Perform QR decomposition. + * - :doc:`af.rank() ` + - Find the rank of a matrix. + * - :doc:`af.solve() ` + - Solve a system of equations. + * - :doc:`af.svd() ` + - Perform singular value decomposition. \ No newline at end of file diff --git a/docs/linux.rst b/docs/linux.rst deleted file mode 100644 index 8451b86..0000000 --- a/docs/linux.rst +++ /dev/null @@ -1,123 +0,0 @@ -Using ArrayFire on Linux -======================== - -Once you have :ref:`installed ` ArrayFire on your system, the next thing to do is set up your build system. On Linux, you can create ArrayFire projects using almost any editor, compiler, or build system. The only requirements are that you include the ArrayFire header directories and link with the ArrayFire library you intend to use i.e. CUDA, OpenCL, oneAPI, CPU, or Unified backends. - -.. _bigpicture: - -The big picture -############### - -On Linux, we recommend installing ArrayFire to :literal:`/opt/arrayfire` directory. The installer will populate files in the following sub-directories: - -.. code-block:: text - - include/arrayfire.h - Primary ArrayFire include file - include/af/*.h - Additional include files - lib/libaf* - CPU, CUDA, oneAPI, and OpenCL libraries (.a, .so) - lib/libforge* - Visualization library - lib/libcu* - CUDA backend dependencies - lib/libOpenCL.so - OpenCL ICD Loader library - share/ArrayFire/cmake/* - CMake config (find) scripts - share/ArrayFire/examples/* - All ArrayFire examples - -Because ArrayFire follows standard installation practices, you can use basically any build system to create and compile projects that use ArrayFire. Among the many possible build systems on Linux we suggest using ArrayFire with either CMake or Makefiles with CMake being our preferred build system. - -Prerequisite software -##################### - -To build ArrayFire projects you will need a compiler - -**Fedora, Centos and Redhat** - -Install EPEL repo (not required for Fedora) - -.. code-block:: text - - yum install epel-release - yum update - -Install build dependencies - -.. code-block:: text - - yum install gcc gcc-c++ cmake3 make - -**Debian and its derivatives** - -Install common dependencies - -.. code-block:: text - - apt install build-essential cmake cmake-curses-gui - -CMake -We recommend that the CMake build system be used to create ArrayFire projects. As `discussed above `, ArrayFire ships with a series of CMake scripts to make finding and using our library easy. - -First create a file called :literal:`CMakeLists.txt` in your project directory: - -.. code-block:: text - - cd your-project-directory - touch CMakeLists.txt - -and populate it with the following code: - -.. code-block:: text - - find_package(ArrayFire) - add_executable( [list your source files here]) - - # To use Unified backend, do the following. - # Unified backend lets you choose the backend at runtime - target_link_libraries( ArrayFire::af) - -where :literal:`my_executable` is the name of the executable you wish to create. See the `CMake documentation `_ for more information on how to use CMake. To link with a specific backend directly, replace the :literal:`ArrayFire::af` with the following for their respective backends. - -* :literal:`ArrayFire::afcpu` for CPU backend. -* :literal:`ArrayFire::afcuda` for CUDA backend. -* :literal:`ArrayFire::afoneapi` for oneAPI backend. -* :literal:`ArrayFire::afopencl` for OpenCL backend. - -Next we need to instruct CMake to create build instructions and then compile. We suggest using CMake's out-of-source build functionality to keep your build and source files cleanly separated. To do this open the CMake GUI. - -.. code-block:: text - - cd your-project-directory - mkdir build - cd build - cmake .. - make - -NOTE: If you have installed ArrayFire to a non-standard location, CMake can still help you out. When you execute CMake specify the path to ArrayFire installation root as :literal:`ArrayFire_DIR` variable. - -For example, if ArrayFire were installed locally to :literal:`/home/user/ArrayFire` then you would modify the :literal:`cmake` command above to contain the following definition: - -.. code-block:: text - - cmake -DArrayFire_DIR=/home/user/ArrayFire .. - -You can also specify this information in the :literal:`ccmake` command-line interface. - - -Makefiles -######### - -Building ArrayFire projects with Makefiles is fairly similar to CMake except you must specify all paths and libraries manually. - -As with any :literal:`make` project, you need to specify the include path to the directory containing :literal:`arrayfire.h` file. This should be :literal`-I /opt/arrayfire/include` if you followed our installation instructions. - -Similarly, you will need to specify the path to the ArrayFire library using the :literal:`-L` option (e.g. :literal:`-L/opt/arrayfire/lib`) followed by the specific ArrayFire library you wish to use using the :literal:`-l` option (for example :literal:`-lafcpu`, :literal:`-lafopencl`, :literal:`-lafoneapi`, :literal:`-lafcuda`, or :literal:`-laf` for the CPU, OpenCL, oneAPI, and CUDA, and unified backends, respectively. - -Here is a minimal example Makefile which uses ArrayFire's CPU backend: - -.. code-block:: text - - LIBS=-lafcpu - LIB_PATHS=-L/opt/arrayfire/lib - INCLUDES=-I/opt/arrayfire/include - CC=g++ $(COMPILER_OPTIONS) - COMPILER_OPTIONS=-std=c++11 -g - - all: main.cpp Makefile - $(CC) main.cpp -o test $(INCLUDES) $(LIBS) $(LIB_PATHS) \ No newline at end of file diff --git a/docs/mathematical_operations_functions.rst b/docs/mathematical_operations_functions.rst new file mode 100644 index 0000000..2ec7cbf --- /dev/null +++ b/docs/mathematical_operations_functions.rst @@ -0,0 +1,148 @@ +Mathematical Operations +======================== + +Functions for performing fundamental arithmetic and mathematical operations on arrays. + +.. list-table:: Functions + + * - :doc:`af.abs() ` + - Calculate the absolute value. + * - :doc:`af.acos() ` + - Evaluate the inverse cosine function (arc cosine). + * - :doc:`af.acosh() ` + - Evaluate the inverse hyperbolic cosine function (area hyperbolic cosine). + * - :doc:`af.add() ` + - Elementwise addition. + * - :doc:`af.arg() ` + - Calculate the phase angle (in radians) of a complex array. + * - :doc:`af.asin() ` + - Evaluate the inverse sine function (arc sine). + * - :doc:`af.asinh() ` + - Evaluate the inverse hyperbolic sine function (area hyperbolic sine). + * - :doc:`af.atan() ` + - Evaluate the inverse tangent function (arc tangent). + * - :doc:`af.atan2() ` + - Evaluate the inverse tangent function (arc tangent). + * - :doc:`af.atanh() ` + - Evaluate the inverse hyperbolic tangent function (area hyperbolic tangent). + * - :doc:`af.bitand() ` + - Evaluate the bitwise AND of two arrays. + * - :doc:`af.bitnot() ` + - Evaluate the bitwise NOT of an array. + * - :doc:`af.bitor() ` + - Evaluate the bitwise OR of two arrays. + * - :doc:`af.bitshiftl() ` + - Shift the bits of integer arrays left. + * - :doc:`af.bitshiftr() ` + - Shift the bits of integer arrays right. + * - :doc:`af.bitxor() ` + - Evaluate the bitwise XOR of two arrays. + * - :doc:`af.cbrt() ` + - Evaluate the cube root. + * - :doc:`af.ceil() ` + - Rounds up to the least integer greater than or equal to x. + * - :doc:`af.clamp() ` + - Clamp an array between an upper and a lower limit. + * - :doc:`af.conjg() ` + - Evaluate the complex conjugate of an input array. + * - :doc:`af.cos() ` + - Evaluate the cosine function. + * - :doc:`af.cosh() ` + - Evaluate the hyperbolic cosine function. + * - :doc:`af.div() ` + - Elementwise division. + * - :doc:`af.dot() ` + - Compute the dot product. + * - :doc:`af.eq() ` + - Equal to, an elementwise comparison of two arrays. + * - :doc:`af.erf() ` + - Evaluate the error function. + * - :doc:`af.erfc() ` + - Evaluate the complementary error function. + * - :doc:`af.exp() ` + - Evaluate the exponential function. + * - :doc:`af.expm1() ` + - Evaluate the exponential function of an array minus 1, exp(in) - 1. + * - :doc:`af.factorial() ` + - Evaluate the factorial. + * - :doc:`af.floor() ` + - Rounds down to the greatest integer less than or equal to x. + * - :doc:`af.ge() ` + - Greater than or equal to, an elementwise comparison of two arrays. + * - :doc:`af.gradient() ` + - Calculate the gradients of the input + * - :doc:`af.gray2rgb() ` + - Grayscale to RGB colorspace converter. + * - :doc:`af.gt() ` + - Greater than comparison, an elementwise comparison of two arrays. + * - :doc:`af.hypot() ` + - Evaluate the length of the hypotenuse of two inputs. + * - :doc:`af.imag() ` + - Returns the imaginary part of a complex array. + * - :doc:`af.imax() ` + - Finds the maximum value. + * - :doc:`af.imin() ` + - Finds the minimum value. + * - :doc:`af.le() ` + - Less than or equal to, an elementwise comparison of two arrays. + * - :doc:`af.lgamma() ` + - Evaluate the logarithm of the absolute value of the gamma function. + * - :doc:`af.log() ` + - Evaluate the natural logarithm. + * - :doc:`af.log10() ` + - Evaluate the base 10 logarithm. + * - :doc:`af.log1p() ` + - Evaluate the natural logarithm of 1 + input, ln(1+in). + * - :doc:`af.log2() ` + - Evaluate the base 2 logarithm. + * - :doc:`af.logical_and() ` + - Evaluate the logical and between two arrays + * - :doc:`af.logical_not() ` + - Evaluate the logical not of an array + * - :doc:`af.logical_or() ` + - Evaluate the logical or between two arrays + * - :doc:`af.lt() ` + - Less than, an elementwise comparison of two arrays. + * - :doc:`af.maxof() ` + - Elementwise maximum between two arrays + * - :doc:`af.minof() ` + - Elementwise minimum between two arrays + * - :doc:`af.mod() ` + - Calculate the modulus. + * - :doc:`af.moddims() ` + - Modify the dimensions of an array without changing the order of its elements. + * - :doc:`af.mul() ` + - Elementwise multiply. + * - :doc:`af.neg() ` + - Negate an array. + * - :doc:`af.neq() ` + - Not equal to, an elementwise comparison of two arrays. + * - :doc:`af.pow() ` + - Raise a base to a power (or exponent). + * - :doc:`af.pow2() ` + - Raise 2 to a power (or exponent). + * - :doc:`af.real() ` + - Returns the real part of a complex array. + * - :doc:`af.rem() ` + - Calculate the remainder of a division. + * - :doc:`af.root() ` + - Evaluate the nth root. + * - :doc:`af.round() ` + - Round numbers to the nearest integer. + * - :doc:`af.rsqrt() ` + - Evaluate the reciprocal square root. + * - :doc:`af.sign() ` + - Return the sign of elements in an array. + * - :doc:`af.sin() ` + - Evaluate the sine function. + * - :doc:`af.sinh() ` + - Evaluate the hyperbolic sine function. + * - :doc:`af.sqrt() ` + - Evaluate the square root. + * - :doc:`af.sub() ` + - Elementwise subtraction. + - Evaluate the tangent function. + * - :doc:`af.tanh() ` + - Evaluate the hyperbolic tangent function. + * - :doc:`af.tgamma() ` + - Evaluate the gamma function. \ No newline at end of file diff --git a/docs/overview.rst b/docs/overview.rst index 45d45f3..5a22282 100644 --- a/docs/overview.rst +++ b/docs/overview.rst @@ -16,7 +16,7 @@ Installing ArrayFire Install ArrayFire using either a binary installer for Windows, OSX, or Linux or download it from source: * `Download and install Binaries `_ - * `Build from source `_ + * `Build from source `_ Using ArrayFire *************** @@ -88,9 +88,6 @@ Here is an example of ArrayFire code that performs a Monte Carlo estimation of P :start-after: [pi-example-simple-snippet] :end-before: [pi-example-simple-endsnippet] - - - Product Support *************** @@ -105,7 +102,7 @@ Premium Support Contact Us ~~~~~~~~~~ - * If you need to contact us, visit our `contact us page `_. + * If you need to contact us, visit our `Contact Us page `_. Email ~~~~~ diff --git a/docs/product_support.rst b/docs/product_support.rst new file mode 100644 index 0000000..bcd814a --- /dev/null +++ b/docs/product_support.rst @@ -0,0 +1,9 @@ +Get Help +============ + +* ArrayFire Services: `Consulting `_ | `Support `_ | `Training `_ +* `ArrayFire Blog `_ +* ArrayFire `Contact Us `_ +* Email: support@arrayfire.com +* `Google Groups `_ +* `Slack Group `_ \ No newline at end of file diff --git a/docs/special_functions.rst b/docs/special_functions.rst new file mode 100644 index 0000000..6069020 --- /dev/null +++ b/docs/special_functions.rst @@ -0,0 +1,125 @@ +Special Functions +==================== + +Functions for convolutions, creating and applying specific types of filters, commonly used in signal processing and analysis. + +.. list-table:: Functions + + * - :doc:`af.anisotropic_diffusion() ` + - Anisotropic Smoothing Filter. + * - :doc:`af.approx1() ` + - Interpolation across a single dimension. + * - :doc:`af.approx1_uniform() ` + - Interpolation across a single dimension in uniform steps + * - :doc:`af.approx2() ` + - Interpolation along two dimensions. + * - :doc:`af.approx2_uniform() ` + - Interpolation along two dimensions in uniform steps + * - :doc:`af.canny() ` + - Canny Edge Detector. + * - :doc:`af.convolve1() ` + - Convolution Integral for one dimensional data. + * - :doc:`af.convolve2() ` + - Convolution Integral for two dimensional data. + * - :doc:`af.convolve2_gradient_nn() ` + - Version of convolution that is consistent with the machine learning formulation that will spatially convolve a filter on 2-dimensions against a signal. + * - :doc:`af.convolve2_nn() ` + - Version of convolution that is consistent with the machine learning formulation that will spatially convolve a filter on 2-dimensions against a signal. + * - :doc:`af.convolve2_separable() ` + - Faster equivalent of the canonical 2D convolution for filters/kernels that can be decomposed into two separate spatial vectors. + * - :doc:`af.convolve3() ` + - Convolution Integral for three dimensional data. + * - :doc:`af.color_space() ` + - Colorspace conversion function. + * - :doc:`af.confidence_cc() ` + - Segment image based on similar pixel characteristics. + * - :doc:`af.dilate() ` + - Dilation(morphological operator) for images. + * - :doc:`af.fir() ` + - This function implements a Finite Impulse Filter. + * - :doc:`af.gaussian_kernel() ` + - Creates a Gaussian Kernel. + * - :doc:`af.gloh() ` + - SIFT feature detector and GLOH descriptor extractor. + * - :doc:`af.gradient() ` + - Calculate the gradients of the input + * - :doc:`af.gray2rgb() ` + - Grayscale to RGB colorspace converter. + * - :doc:`af.hamming_matcher() ` + - Calculates Hamming distances between two 2-dimensional arrays + * - :doc:`af.harris() ` + - Harris corner detector. + * - :doc:`af.hsv2rgb() ` + - HSV to RGB colorspace converter. + * - :doc:`af.hypot() ` + - Evaluate the length of the hypotenuse of two inputs. + * - :doc:`af.is_image_io_available() ` + - Checks if Image IO is available + * - :doc:`af.iterative_deconv() ` + - Inverse Deconvolution using iterative methods + * - :doc:`af.load_image() ` + - Load an image from disk to an array + * - :doc:`af.load_image_memory() ` + - Load an image from memory which is stored as a FreeImage stream + * - :doc:`af.load_image_native() ` + - Load an image as is original type. + * - :doc:`af.maxfilt() ` + - Find maximum value from a window. + * - :doc:`af.mean_shift() ` + - Edge-preserving smoothing filter commonly used in object tracking and image segmentation. + * - :doc:`af.medfilt() ` + - Median Filter. + * - :doc:`af.medfilt1() ` + - 1D Median Filter. + * - :doc:`af.medfilt2() ` + - 2D Median Filter. + * - :doc:`af.minfilt() ` + - Find minimum value from a window. + * - :doc:`af.nearest_neighbour() ` + - Calculates which points in the train are nearest to each other point + * - :doc:`af.orb() ` + - ORB Feature descriptor. + * - :doc:`af.pad() ` + - Pad an array. + * - :doc:`af.regions() ` + - Find blobs in given image. + * - :doc:`af.resize() ` + - Resize an input image. + * - :doc:`af.rgb2gray() ` + - RGB to Grayscale colorspace converter. + * - :doc:`af.rgb2hsv() ` + - RGB to HSV colorspace converter. + * - :doc:`af.rgb2ycbcr() ` + - RGB to YCbCr colorspace converter. + * - :doc:`af.rotate() ` + - Rotate an input image or array. + * - :doc:`af.sat() ` + - Summed Area Tables. + * - :doc:`af.save_array() ` + - Save an array to a binary file + * - :doc:`af.save_image() ` + - Save an array to disk as an image + * - :doc:`af.save_image_memory() ` + - Save an array to memory as an image using FreeImage stream + * - :doc:`af.save_image_native() ` + - Save an image as is original type. + * - :doc:`af.scale() ` + - Scale an input image. + * - :doc:`af.sift() ` + - SIFT feature detector and descriptor extractor. + * - :doc:`af.sign() ` + - Return the sign of elements in an array. + * - :doc:`af.sin() ` + - Evaluate the sine function. + * - :doc:`af.skew() ` + - Skew an input image. + * - :doc:`af.sobel_operator() ` + - Perform a 2-D spatial gradient measurement on an image + * - :doc:`af.susan() ` + - SUSAN corner detector. + * - :doc:`af.transform() ` + - Transform an input image. + * - :doc:`af.transform_coordinates() ` + - Transform input coordinates to perspective. + * - :doc:`af.translate() ` + - Translate an input image. \ No newline at end of file diff --git a/docs/statistics_functions.rst b/docs/statistics_functions.rst new file mode 100644 index 0000000..59ad5bc --- /dev/null +++ b/docs/statistics_functions.rst @@ -0,0 +1,35 @@ +Statistics +============ + +Functions for computing statistical metrics and analyzing data distributions. + +.. list-table:: Functions + + * - :doc:`af.count() ` + - Count non-zero values in an array along a given dimension. + * - :doc:`af.hist_equal() ` + - Histogram equalization of input image. + * - :doc:`af.histogram() ` + - Histogram of input data. + * - :doc:`af.imax() ` + - Finds the maximum value. + * - :doc:`af.imin() ` + - Finds the minimum value. + * - :doc:`af.max() ` + - Return the maximum along a given dimension. + * - :doc:`af.maxof() ` + - Elementwise maximum between two arrays + * - :doc:`af.mean() ` + - Find the mean of values in the input. + * - :doc:`af.median() ` + - Find the median of values in the input. + * - :doc:`af.min() ` + - Return the minimum along a given dimension. + * - :doc:`af.minfilt() ` + - Find minimum value from a window. + * - :doc:`af.minof() ` + - Elementwise minimum between two arrays + * - :doc:`af.sttdev() ` + - Find the standard deviation of values in the input. + * - :doc:`af.sum() ` + - Sum array elements over a given dimension. \ No newline at end of file diff --git a/docs/timing_arrayfire.rst b/docs/timing_arrayfire.rst index b3a8cc7..04b1de7 100644 --- a/docs/timing_arrayfire.rst +++ b/docs/timing_arrayfire.rst @@ -16,9 +16,9 @@ Setup For benchmarking we will utilize two functions: `af.sync()` and `af.eval(arr)`. -- `af.sync`: The purpose of this function is to stall the current thread until all awaiting operations have finished and the result is accessable by the host. It synchronizes the host and the device, similar to what cuda.Stream.synchronize() does in cupy. +- :doc:`af.sync `: The purpose of this function is to stall the current thread until all awaiting operations have finished and the result is accessable by the host. It synchronizes the host and the device, similar to what cuda.Stream.synchronize() does in cupy. -- `af.eval`: This function takes in an array which will be forced to be evaluated immediately. This forces the JIT tree to be cut at the point of this function calls and any later operations will not be considered in this current JIT tree. +- :doc:`af.eval `: This function takes in an array which will be forced to be evaluated immediately. This forces the JIT tree to be cut at the point of this function calls and any later operations will not be considered in this current JIT tree. Using these two function we can make sure that we are benchmarking the correct operations by making sure that no operation is running diff --git a/docs/tutorial.rst b/docs/tutorial.rst index 3ea2d29..36bbcaf 100644 --- a/docs/tutorial.rst +++ b/docs/tutorial.rst @@ -2,19 +2,13 @@ Tutorial ======== * :doc:`Installation ` -* :doc:`Using on Linux ` -* Using on Windows -* Using on OSX * :doc:`Getting Started ` +* :doc:`Configuring ArrayFire Environment ` * :doc:`Introduction to Vectorization ` +* :doc:`ArrayFire JIT Code Generation ` * :doc:`Array and Matrix Manipulation ` -* CUDA Interoperability -* OpenCL Interoperability -* Unified Backend -* Forge Visualization * :doc:`Indexing ` +* OpenCL Interoperability (Coming Soon) +* Forge Visualization (Coming Soon) * :doc:`Timing ArrayFire ` -* :doc:`Configuring ArrayFire Environment ` -* :doc:`Debugging ArrayFire Code ` -* :doc:`ArrayFire JIT Code Generation ` -* GFOR Usage \ No newline at end of file +* :doc:`Debugging ArrayFire Code ` \ No newline at end of file diff --git a/docs/utilities_functions.rst b/docs/utilities_functions.rst new file mode 100644 index 0000000..6085b21 --- /dev/null +++ b/docs/utilities_functions.rst @@ -0,0 +1,89 @@ +Utilities +=========== + +General-purpose functions for managing arrays and devices. + +.. list-table:: Functions + + * - :doc:`af.alloc_device() ` + - Allocate memory on device + * - :doc:`af.alloc_host() ` + - Allocate memory on host. + * - :doc:`af.alloc_pinned() ` + - Allocate pinned memory on device. + * - :doc:`af.cublas_set_math_mode() ` + - Sets the cuBLAS math mode for the internal handle + * - :doc:`af.delete_image_memory() ` + - Delete memory created by saveImageMem + * - :doc:`af.det() ` + - Find the determinant of a matrix. + * - :doc:`af.device_gc() ` + - Call the garbage collection routine + * - :doc:`af.device_info() ` + - Gets the information about device and platform as strings. + * - :doc:`af.device_mem_info() ` + - Gets information about the memory manager + * - :doc:`af.free_device() ` + - Free memory allocated on device internally by ArrayFire. + * - :doc:`af.free_host() ` + - Free memory allocated on host internally by ArrayFire. + * - :doc:`af.free_pinned() ` + - Free pinned memory allocated by ArrayFire's memory manager. + * - :doc:`af.get_backend() ` + - Gets the backend enum for the active backend. + * - :doc:`af.get_dbl_support() ` + - Gets if the device supports double floating point + * - :doc:`af.get_device() ` + - Get the current device ID. + * - :doc:`af.get_device_count() ` + - Gets the number of compute devices on the system. + * - :doc:`af.get_half_support() ` + - Gets if the device supports half floating point + * - :doc:`af.get_kernel_cache_directory() ` + - Returns directory where ArrayFire JIT kernels are being stored + * - :doc:`af.get_mem_step_size() ` + - Get the minimum memory chunk size. + * - :doc:`af.get_native_id() ` + - Get the native device id of the CUDA device with id in ArrayFire context + * - :doc:`af.get_stream() ` + - Returns the current cuda stream + * - :doc:`af.info() ` + - Display ArrayFire and device info. + * - :doc:`af.info_string() ` + - Returns a string with information of current device and backend + * - :doc:`af.init() ` + - Initializes ArrayFire + * - :doc:`af.is_image_io_available() ` + - Checks if Image IO is available + * - :doc:`af.is_lapack_available() ` + - Check if lapack runtimes are available + * - :doc:`af.load_image() ` + - Load an image from disk to an array + * - :doc:`af.load_image_memory() ` + - Load an image from memory which is stored as a FreeImage stream + * - :doc:`af.load_image_native() ` + - Load an image as is original type. + * - :doc:`af.print_mem_info() ` + - Prints buffer details from the ArrayFire Device Manager + * - :doc:`af.read_array() ` + - Load an array from a file. + * - :doc:`af.save_array() ` + - Save an array to a binary file + * - :doc:`af.save_image() ` + - Save an array to disk as an image + * - :doc:`af.save_image_memory() ` + - Save an array to memory as an image using FreeImage stream + * - :doc:`af.save_image_native() ` + - Save an image as is original type. + * - :doc:`af.set_backend() ` + - Set the current backend + * - :doc:`af.set_device() ` + - Change current device to specified device. + * - :doc:`af.set_fft_plan_cache_size() ` + - Sets fft plan cache size + * - :doc:`af.set_kernel_cache_directory() ` + - Sets the directory for JIT kernel caching + * - :doc:`af.set_mem_step_size() ` + - Get the minimum memory chunk size. + * - :doc:`af.set_native_id() ` + - Set the CUDA device with given native id as the active device for ArrayFire \ No newline at end of file From 98436bc1e64564974cdd8878dd9bdbc794f0ab03 Mon Sep 17 00:00:00 2001 From: Edwin Date: Mon, 25 Aug 2025 17:45:39 -0700 Subject: [PATCH 10/11] Added jit benchmark image, fixed some format issues --- docs/TODO | 7 +++++ docs/afjit.py | 34 ++++++++++++++++++--- docs/arrayfirejitcodegeneration.rst | 11 ++++--- docs/configuringarrayfireenvironment.rst | 2 +- docs/images/afjit_benchmark.png | Bin 0 -> 44169 bytes docs/index.rst | 2 +- docs/installation.rst | 3 +- docs/mathematical_operations_functions.rst | 3 +- docs/special_functions.rst | 2 +- 9 files changed, 48 insertions(+), 16 deletions(-) create mode 100644 docs/TODO create mode 100644 docs/images/afjit_benchmark.png diff --git a/docs/TODO b/docs/TODO new file mode 100644 index 0000000..f80a47d --- /dev/null +++ b/docs/TODO @@ -0,0 +1,7 @@ +TODO +===== + +- Add docstring to function image processing +- Change to where the Restructured Files for the undocumented functions point to (currently some point to docs in the arrayfire-binary-python-wrapper) +- Add more detail to the constants and classes +- Add more information in the python installation section \ No newline at end of file diff --git a/docs/afjit.py b/docs/afjit.py index cf49a9f..de40c05 100644 --- a/docs/afjit.py +++ b/docs/afjit.py @@ -6,21 +6,45 @@ # following function. import arrayfire as af +import time + +samples = int(9e8) +x = af.randu((samples)) +y = af.randu((samples)) def pi_no_jit(x, y, samples): temp = x * x - temp.eval() + af.eval(temp) temp += y * y - temp.eval() + af.eval(temp) temp = af.sqrt(temp) - temp.eval() + af.eval(temp) temp = temp < 1 - temp.eval() + af.eval(temp) return 4.0 * af.sum(temp) / samples def pi_jit(x, y, samples): temp = af.sqrt(x * x + y * y) < 1 - temp.eval() + af.eval(temp) return 4.0 * af.sum(temp) / samples +# Print device info +af.info() + +# Time JIT code +start = time.perf_counter() +res = pi_jit(x, y, samples) +af.sync() +end = time.perf_counter() + +print("jit:", end - start, res) +af.device_gc() + +# Time no JIT code +start = time.perf_counter() +res = pi_no_jit(x, y, samples) +af.sync() +end = time.perf_counter() +print("no jit:", end - start, res) + # [jit-endsnippet] \ No newline at end of file diff --git a/docs/arrayfirejitcodegeneration.rst b/docs/arrayfirejitcodegeneration.rst index d536368..b09315c 100644 --- a/docs/arrayfirejitcodegeneration.rst +++ b/docs/arrayfirejitcodegeneration.rst @@ -34,12 +34,15 @@ Specifically, as JIT is an integral feature of the ArrayFire library, it cannot Timing these two implementations results in the following performance benchmark: -**Add Picture** +.. image:: images/afjit_benchmark.png + :alt: Benchmark Results + :align: center + :class: responsive-img -The above figure depicts the execution time (abscissa) as a function of the number of samples (ordinate) for the two implementations discussed above. +The above figure depicts the execution time as a function of the number of samples for the two implementations discussed above. -When the number of samples is small, the execution time of pi_no_jit is dominated by the launch of multiple kernels and the execution time pi_jit is dominated by on-the-fly compilation of the JIT code required to launch a single kernel. Even with this JIT compilation time, pi_jit outperforms pi_no_jit by 1.4-2.0X for smaller sample sizes. +When the number of samples is small (less than 100k samples), the execution time of pi_no_jit is dominated by the launch of multiple kernels and the execution time pi_jit is dominated by on-the-fly compilation of the JIT code required to launch a single kernel. Even with this JIT compilation time, pi_jit outperforms pi_no_jit by 1.4-2.0X for smaller sample sizes. -When the number of samples is large, both the kernel launch overhead and the JIT code creation are no longer the limiting factors – the kernel’s computational load dominates the execution time. Here, the pi_jit outperforms pi_no_jit by 2.0-2.7X. +When the number of samples is large (more than 1 million samples), both the kernel launch overhead and the JIT code creation are no longer the limiting factors – the kernel’s computational load dominates the execution time. Here, the pi_jit outperforms pi_no_jit by 3-25X. The number of applications that benefit from the JIT code generation is significant. The actual performance benefits are also application-dependent. \ No newline at end of file diff --git a/docs/configuringarrayfireenvironment.rst b/docs/configuringarrayfireenvironment.rst index da654a4..80ee50b 100644 --- a/docs/configuringarrayfireenvironment.rst +++ b/docs/configuringarrayfireenvironment.rst @@ -150,7 +150,7 @@ deallocations, and garbage collection. All trace statements printed to the console have a suffix with the following pattern. -**[category][Seconds since Epoch][Thread Id][source file relative path] \** +:literal:`[category][Seconds since Epoch][Thread Id][source file relative path] \` `AF_OPENCL_SHOW_BUILD_INFO` *************************** diff --git a/docs/images/afjit_benchmark.png b/docs/images/afjit_benchmark.png new file mode 100644 index 0000000000000000000000000000000000000000..552986229c82ff18058319a825679c52b8e94b21 GIT binary patch literal 44169 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 E21MH`h5!Hn literal 0 HcmV?d00001 diff --git a/docs/index.rst b/docs/index.rst index e101e80..dfbb295 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -11,9 +11,9 @@ Welcome to ArrayFire's documentation! :caption: The Basics overview + tutorial installation gettingstarted - tutorial .. toctree:: :maxdepth: 1 diff --git a/docs/installation.rst b/docs/installation.rst index 50056b1..7986fc5 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -20,8 +20,6 @@ Once the ArrayFire has been downloaded, run the installer. The installer offers the option to automatically add ArrayFire to the path for all users. If the installer did not do this, simply append :literal:`%AF_PATH%/lib` to the PATH variable so that the loader can find ArrayFire DLLs. -For more information on using ArrayFire on Windows, visit the following page. - .. _Linux: @@ -131,5 +129,6 @@ Getting help * Google Groups: https://groups.google.com/forum/#!forum/arrayfire-users * ArrayFire Services: `Consulting `_ | `Training `_ * ArrayFire Blogs: http://arrayfire.com/blog/ +* ArrayFire `Contact Us `_ * Email: support@arrayfire.com diff --git a/docs/mathematical_operations_functions.rst b/docs/mathematical_operations_functions.rst index 2ec7cbf..24b101e 100644 --- a/docs/mathematical_operations_functions.rst +++ b/docs/mathematical_operations_functions.rst @@ -109,8 +109,6 @@ Functions for performing fundamental arithmetic and mathematical operations on a - Elementwise minimum between two arrays * - :doc:`af.mod() ` - Calculate the modulus. - * - :doc:`af.moddims() ` - - Modify the dimensions of an array without changing the order of its elements. * - :doc:`af.mul() ` - Elementwise multiply. * - :doc:`af.neg() ` @@ -141,6 +139,7 @@ Functions for performing fundamental arithmetic and mathematical operations on a - Evaluate the square root. * - :doc:`af.sub() ` - Elementwise subtraction. + * - :doc:`af.tan() ` - Evaluate the tangent function. * - :doc:`af.tanh() ` - Evaluate the hyperbolic tangent function. diff --git a/docs/special_functions.rst b/docs/special_functions.rst index 6069020..4e20311 100644 --- a/docs/special_functions.rst +++ b/docs/special_functions.rst @@ -18,7 +18,7 @@ Functions for convolutions, creating and applying specific types of filters, com * - :doc:`af.canny() ` - Canny Edge Detector. * - :doc:`af.convolve1() ` - - Convolution Integral for one dimensional data. + - Convolution Integral for one dimensional data. * - :doc:`af.convolve2() ` - Convolution Integral for two dimensional data. * - :doc:`af.convolve2_gradient_nn() ` From 6c90d4d181d44d8d636485020c5b6a417bb9f49b Mon Sep 17 00:00:00 2001 From: Edwin Date: Tue, 2 Sep 2025 11:34:06 -0700 Subject: [PATCH 11/11] Updated install docs --- docs/functions.rst | 8 ++++---- docs/indexing.rst | 2 +- docs/installation.rst | 19 +++++++++++++++---- docs/overview.rst | 4 ++-- 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/docs/functions.rst b/docs/functions.rst index d809160..0655771 100644 --- a/docs/functions.rst +++ b/docs/functions.rst @@ -21,7 +21,7 @@ Functions Documentation grouped by category: -.. collapse:: Arrayfire Classes +.. collapse:: ArrayFire Classes .. list-table:: @@ -33,7 +33,7 @@ Documentation grouped by category: - Represents an ArrayFire Feature Extraction class -.. collapse:: Arrayfire Functions +.. collapse:: ArrayFire Functions .. list-table:: @@ -529,7 +529,7 @@ Documentation grouped by category: - Creates an array filled with zeros. -.. collapse:: Arrayfire Functions by Category +.. collapse:: ArrayFire Functions by Category .. list-table:: @@ -552,7 +552,7 @@ Documentation grouped by category: * - :doc:`Special Functions ` - Functions for convolutions, creating and applying specific types of filters, commonly used in signal processing and analysis. -.. collapse:: Arrayfire Constants +.. collapse:: ArrayFire Constants .. list-table:: diff --git a/docs/indexing.rst b/docs/indexing.rst index 0eb016b..dd0ca61 100644 --- a/docs/indexing.rst +++ b/docs/indexing.rst @@ -109,7 +109,7 @@ You can use Python's slicing notation to define a range when indexing in **array Indexing using af.Array *************************** -In Python with arrayfire, you can also index arrays using other **af.Array** objects. Arrayfire flattens the input and treats the elements inside the array +In Python with arrayfire, you can also index arrays using other **af.Array** objects. ArrayFire flattens the input and treats the elements inside the array as column major indices to index the original Array as 1D Array. .. code-block:: python diff --git a/docs/installation.rst b/docs/installation.rst index 7986fc5..017d733 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -1,12 +1,23 @@ ArrayFire Installer =================== -Installing ArrayFire couldn't be easier. Navigate to https://arrayfire.com/download and download the appropriate installer for the target architecture and operating system. Although ArrayFire can be `built from source `_, the installers conveniently package necessary dependencies. +To use ArrayFire-Python you require three things: -Install the latest device drivers before using ArrayFire. Drivers and runtimes should be downloaded and installed from each device vendor's website. +.. list-table:: -Install Instructions -#################### + * - :literal:`arrayfire-python` package + - You may install it through pip :literal:`pip install arrayfire-python` or from `building arrayfire-python wheel <../README.md>`_ + + * - :literal:`arrayfire-binary-python-wrapper` + - You may download and install through pip :literal:`pip install arrayfire_binary_python_wrapper-0.8.0+af3.10.0 -f https://arrayfire.com/python/binaries` which will come with ArrayFire C Libraries as well. You may also `build from source `_ without the C Libraries. + + * - :literal:`ArrayFire C/C++ Libraries` + - If you build the binary wrapper from source or wish to program with ArrayFire in C/C++, navigate to https://arrayfire.com/download and download the appropriate installer for the target architecture and operating system. Although ArrayFire can be `built from source `_, the installers conveniently package necessary dependencies. + +Below we detail more on the ArrayFire C Libraries installation procedure. Install the latest device drivers before using ArrayFire. Drivers and runtimes should be downloaded and installed from each device vendor's website. + +Install Instructions for ArrayFire C Libraries +############################################### * :ref:`Windows ` * :ref:`Linux ` diff --git a/docs/overview.rst b/docs/overview.rst index 5a22282..593a65b 100644 --- a/docs/overview.rst +++ b/docs/overview.rst @@ -16,7 +16,7 @@ Installing ArrayFire Install ArrayFire using either a binary installer for Windows, OSX, or Linux or download it from source: * `Download and install Binaries `_ - * `Build from source `_ + * `Build from source `_ Using ArrayFire *************** @@ -112,4 +112,4 @@ Email Citations and Acknowledgements ****************************** -If you redistribute ArrayFire, please follow the terms established in `the license `_. If you wish to cite ArrayFire in an academic publication, please use the following reference: \ No newline at end of file +If you redistribute ArrayFire, please follow the terms established in `the license `_. If you wish to cite ArrayFire in an academic publication, please use the following reference: \ No newline at end of file