.. py:currentmodule:: drjit .. _basics: Basics ====== This fast-paced section reviews a wide range of standard operations. It assumes the following import declarations .. code-block:: python import drjit as dr from drjit.auto import Float, Array3f, UInt Creating arrays --------------- Recall that Dr.Jit array types are dynamically sized--for example, :py:class:`Float ` refers to a 1D array of single precision variables. The simplest way to create such an array is to call its constructor with a list of explicit values: .. code-block:: python a = Float(1, 2, 3, 4) print(a) # [1, 2, 3, 4] The constructor also accepts ``Sequence`` types (e.g. lists, tuples, NumPy arrays, PyTorch tensors, etc.): .. code-block:: python x = Float([1, 2, 3, 4]) Nested array types store several variables---for example, :py:class:`Array3f ` is just a wrapper around 3 :py:class:`Float ` instances. They can be passed to the constructor explicitly, or via implicit conversion from constants, lists, etc. .. code-block:: python a = Array3f([1, 2], 0, Float(10, 20)) print(a) # Prints (with 'y' component broadcast to full size) # [[1, 0, 10], # [2, 0, 20]] Various functions can also create default-initialized arrays: - :py:func:`dr.zeros() `: ``[0, 0, ...]``. - :py:func:`dr.ones() `: ``[1, 1, ...]``. - :py:func:`dr.full() `: ``[x, x, ...]`` given ``x``. - :py:func:`dr.arange() `: ``[0, 1, 2, ...]``. - :py:func:`dr.linspace() `: linear interpolation of two endpoints. - :py:func:`dr.empty() `: allocate uninitialized memory. These always take the desired output type as first argument. You can optionally request a given size along the dynamic axis, e.g.: .. code-block:: python b = dr.zeros(Array3f) print(b.shape) # Prints: (3, 1) b = dr.zeros(Array3f, shape=(3, 1000)) print(b.shape) # Prints: (3, 1000) Element access -------------- Use the default ``array[index]`` syntax to read/write array entries. Nested static 1-4D arrays further expose equivalent ``.x`` / ``.y`` / ``.z`` / ``.w`` members: .. code-block:: python a = Array3f(1, 2, 3) a.x += a.z + a[1] Static 1-4D arrays also support `swizzling `__, which arbitrarily reorders elements: .. code-block:: python a.xy = a.xx + a.yx Arithmetic operations --------------------- Except for a few special cases (e.g., matrix multiplication), arithmetic operations transform arrays element-wise. If needed, the system will implicitly broadcast the operands and promote types. .. code-block:: pycon >>> a = abs(Float(-1.25, 2) + UInt32(1)) >>> type(a) >>> a [0.25, 3] In the above example, *broadcasting* automatically extended the size of the *scalar* (size-1) array, and the :py:class:`UInt32 ` type was *promoted* to :py:class:`Float `. Type promotion follows the rules of the C programming language. Besides built-in arithmetic operators, the following standard functions are available: - :py:func:`dr.abs() `: Absolute value. - :py:func:`dr.fma() `: Fused multiply-add. - :py:func:`dr.minimum() `, :py:func:`dr.maximum() `: Element-wise minimum/maximum of two arrays. - :py:func:`dr.ceil() `, :py:func:`dr.floor() `, :py:func:`dr.round() `, :py:func:`dr.trunc() `: Round up, down, to nearest, or to zero. - :py:func:`dr.sqrt() `, :py:func:`dr.cbrt() `: Square and cube root. - :py:func:`dr.rcp() `: Reciprocal. - :py:func:`dr.rsqrt() `: Reciprocal square root. - :py:func:`dr.sign() `: Extract the sign. - :py:func:`dr.copysign() `: Copy sign from one value to another. - :py:func:`dr.clip() `: Clip a value to an interval. - :py:func:`dr.lerp() `: Linearly interpolate. The library implements common transcendental functions: - :py:func:`dr.sin() `, :py:func:`dr.cos() `, :py:func:`dr.tan() `: Trigonometric functions. - :py:func:`dr.asin() `, :py:func:`dr.acos() `, :py:func:`dr.atan() `, :py:func:`dr.atan2() `: .. and their inverses. - :py:func:`dr.sinh() `, :py:func:`dr.cosh() `, :py:func:`dr.tanh() `: Hyperbolic trigonometric functions. - :py:func:`dr.asinh() `, :py:func:`dr.acosh() `, :py:func:`dr.atanh() `: .. and their inverses. - :py:func:`dr.sincos() `, :py:func:`dr.sincosh() `: Fast combined evaluation. - :py:func:`dr.erf() `, :py:func:`dr.erfinv() `: Error function. - :py:func:`dr.exp() `, :py:func:`dr.log() `, :py:func:`dr.exp2() `, :py:func:`dr.log2() `: Exponentials and logarithms. - :py:func:`dr.power() `: Power function. - :py:func:`dr.lgamma() `: Gamma function. Most of these support real and complex-valued inputs. A subset accepts quaternions (see the section on :ref:`array types ` for details). Integer arrays further support the following bit-level operations - :py:func:`dr.lzcnt() `, :py:func:`dr.tzcnt() `: Leading/trailing zero count. - :py:func:`dr.popcnt() `: Population count. - :py:func:`dr.brev() `: Bit reverse. Mask operations --------------- Equality and inequality comparisons produce *masks* (i.e., boolean-valued arrays) with support for binary arithmetic. The :py:func:`dr.select()