Files
mlx/docs/build/doctrees/usage/indexing.doctree

121 lines
16 KiB
Plaintext
Raw Normal View History

2024-01-17 17:15:29 -08:00
<EFBFBD><05> B<00>sphinx.addnodes<65><73>document<6E><74><EFBFBD>)<29><>}<7D>(<28> rawsource<63><65><00><>children<65>]<5D>(<28>docutils.nodes<65><73>target<65><74><EFBFBD>)<29><>}<7D>(h<05> .. _indexing:<3A>h]<5D><>
attributes<EFBFBD>}<7D>(<28>ids<64>]<5D><>classes<65>]<5D><>names<65>]<5D><>dupnames<65>]<5D><>backrefs<66>]<5D><>refid<69><64>indexing<6E>u<EFBFBD>tagname<6D>h
<EFBFBD>line<6E>K<01>parent<6E>h<03> _document<6E>h<03>source<63><65>7/Users/awnihannun/repos/mlx/docs/src/usage/indexing.rst<73>ubh <09>section<6F><6E><EFBFBD>)<29><>}<7D>(hhh]<5D>(h <09>title<6C><65><EFBFBD>)<29><>}<7D>(h<05>Indexing Arrays<79>h]<5D>h <09>Text<78><74><EFBFBD><EFBFBD>Indexing Arrays<79><73><EFBFBD><EFBFBD><EFBFBD>}<7D>(h h+h!hh"NhNubah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D>uhh)h h&h!hh"h#hKubh <09> paragraph<70><68><EFBFBD>)<29><>}<7D>(h<05><>For the most part, indexing an MLX :obj:`array` works the same as indexing a
NumPy :obj:`numpy.ndarray`. See the `NumPy documentation
<https://numpy.org/doc/stable/user/basics.indexing.html>`_ for more details on
how that works.<2E>h]<5D>(h0<68>#For the most part, indexing an MLX <20><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h h=h!hh"NhNubh<00> pending_xref<65><66><EFBFBD>)<29><>}<7D>(h<05> :obj:`array`<60>h]<5D>h <09>literal<61><6C><EFBFBD>)<29><>}<7D>(hhIh]<5D>h0<68>array<61><79><EFBFBD><EFBFBD><EFBFBD>}<7D>(h hMh!hh"NhNubah}<7D>(h]<5D>h]<5D>(<28>xref<65><66>py<70><79>py-obj<62>eh]<5D>h]<5D>h]<5D>uhhKh hGubah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D><>refdoc<6F><63>usage/indexing<6E><67> refdomain<69>hX<68>reftype<70><65>obj<62><6A> refexplicit<69><74><EFBFBD>refwarn<72><6E><EFBFBD> py:module<6C><65>mlx.core<72><65>py:class<73>N<EFBFBD> reftarget<65><74>array<61>uhhEh"h#hKh h=ubh0<68>$ works the same as indexing a
NumPy <20><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h h=h!hh"NhNubhF)<29><>}<7D>(h<05>:obj:`numpy.ndarray`<60>h]<5D>hL)<29><>}<7D>(hhuh]<5D>h0<68> numpy.ndarray<61><79><EFBFBD><EFBFBD><EFBFBD>}<7D>(h hwh!hh"NhNubah}<7D>(h]<5D>h]<5D>(hW<68>py<70><79>py-obj<62>eh]<5D>h]<5D>h]<5D>uhhKh hsubah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D><>refdoc<6F>hd<68> refdomain<69>h<EFBFBD><68>reftype<70><65>obj<62><6A> refexplicit<69><74><EFBFBD>refwarn<72><6E>hjhkhlNhm<68> numpy.ndarray<61>uhhEh"h#hKh h=ubh0<68>
. See the <20><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h h=h!hh"NhNubh <09> reference<63><65><EFBFBD>)<29><>}<7D>(h<05>O`NumPy documentation
<https://numpy.org/doc/stable/user/basics.indexing.html>`_<>h]<5D>h0<68>NumPy documentation<6F><6E><EFBFBD><EFBFBD><EFBFBD>}<7D>(h h<>h!hh"NhNubah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D><>name<6D><65>NumPy documentation<6F><6E>refuri<72><69>6https://numpy.org/doc/stable/user/basics.indexing.html<6D>uhh<>h h=ubh )<29><>}<7D>(h<05>9
<https://numpy.org/doc/stable/user/basics.indexing.html><3E>h]<5D>h}<7D>(h]<5D><>numpy-documentation<6F>ah]<5D>h]<5D><>numpy documentation<6F>ah]<5D>h]<5D><>refuri<72>h<EFBFBD>uhh
<EFBFBD>
referenced<EFBFBD>Kh h=ubh0<68>$ for more details on
how that works.<2E><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h h=h!hh"NhNubeh}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D>uhh;h"h#hKh h&h!hubh<)<29><>}<7D>(h<05>TFor example, you can use regular integers and slices (:obj:`slice`) to index arrays:<3A>h]<5D>(h0<68>6For example, you can use regular integers and slices (<28><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h h<>h!hh"NhNubhF)<29><>}<7D>(h<05> :obj:`slice`<60>h]<5D>hL)<29><>}<7D>(hh<>h]<5D>h0<68>slice<63><65><EFBFBD><EFBFBD><EFBFBD>}<7D>(h h<>h!hh"NhNubah}<7D>(h]<5D>h]<5D>(hW<68>py<70><79>py-obj<62>eh]<5D>h]<5D>h]<5D>uhhKh h<>ubah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D><>refdoc<6F>hd<68> refdomain<69>reftype<70><65>obj<62><6A> refexplicit<69><74><EFBFBD>refwarn<72><6E>hjhkhlNhm<68>slice<63>uhhEh"h#hK h h<>ubh0<68>) to index arrays:<3A><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h h<>h!hh"NhNubeh}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D>uhh;h"h#hK h h&h!hubh <09> literal_block<63><6B><EFBFBD>)<29><>}<7D>(h<05><>>>> arr = mx.arange(10)
>>> arr[3]
array(3, dtype=int32)
>>> arr[-2] # negative indexing works
array(8, dtype=int32)
>>> arr[2:8:2] # start, stop, stride
array([2, 4, 6], dtype=int32)<29>h]<5D>h0<68><30>>>> arr = mx.arange(10)
>>> arr[3]
array(3, dtype=int32)
>>> arr[-2] # negative indexing works
array(8, dtype=int32)
>>> arr[2:8:2] # start, stop, stride
array([2, 4, 6], dtype=int32)<29><><EFBFBD><EFBFBD><EFBFBD>}<7D>h h<>sbah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D><> xml:space<63><65>preserve<76><65>force<63><65><EFBFBD>language<67><65>shell<6C><6C>highlight_args<67>}<7D>uhh<>h"h#hKh h&h!hubh<)<29><>}<7D>(h<05>VFor multi-dimensional arrays, the ``...`` or :obj:`Ellipsis` syntax works as in NumPy:<3A>h]<5D>(h0<68>"For multi-dimensional arrays, the <20><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j h!hh"NhNubhL)<29><>}<7D>(h<05>``...``<60>h]<5D>h0<68>...<2E><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h jh!hh"NhNubah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D>uhhKh j ubh0<68> or <20><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j h!hh"NhNubhF)<29><>}<7D>(h<05>:obj:`Ellipsis`<60>h]<5D>hL)<29><>}<7D>(hj(h]<5D>h0<68>Ellipsis<69><73><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j*h!hh"NhNubah}<7D>(h]<5D>h]<5D>(hW<68>py<70><79>py-obj<62>eh]<5D>h]<5D>h]<5D>uhhKh j&ubah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D><>refdoc<6F>hd<68> refdomain<69>j4<00>reftype<70><65>obj<62><6A> refexplicit<69><74><EFBFBD>refwarn<72><6E>hjhkhlNhm<68>Ellipsis<69>uhhEh"h#hKh j ubh0<68> syntax works as in NumPy:<3A><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j h!hh"NhNubeh}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D>uhh;h"h#hKh h&h!hubh<62>)<29><>}<7D>(h<05><>>>> arr = mx.arange(8).reshape(2, 2, 2)
>>> arr[:, :, 0]
array(3, dtype=int32)
array([[0, 2],
[4, 6]], dtype=int32
>>> arr[..., 0]
array([[0, 2],
[4, 6]], dtype=int32<33>h]<5D>h0<68><30>>>> arr = mx.arange(8).reshape(2, 2, 2)
>>> arr[:, :, 0]
array(3, dtype=int32)
array([[0, 2],
[4, 6]], dtype=int32
>>> arr[..., 0]
array([[0, 2],
[4, 6]], dtype=int32<33><32><EFBFBD><EFBFBD><EFBFBD>}<7D>h jPsbah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D>jjj<00>j<00>shell<6C>j
}<7D>uhh<>h"h#hKh h&h!hubh<)<29><>}<7D>(h<05>1You can index with ``None`` to create a new axis:<3A>h]<5D>(h0<68>You can index with <20><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j`h!hh"NhNubhL)<29><>}<7D>(h<05>``None``<60>h]<5D>h0<68>None<6E><65><EFBFBD><EFBFBD><EFBFBD>}<7D>(h jhh!hh"NhNubah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D>uhhKh j`ubh0<68> to create a new axis:<3A><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j`h!hh"NhNubeh}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D>uhh;h"h#hK&h h&h!hubh<62>)<29><>}<7D>(h<05>C>>> arr = mx.arange(8)
>>> arr.shape
[8]
>>> arr[None].shape
[1, 8]<5D>h]<5D>h0<68>C>>> arr = mx.arange(8)
>>> arr.shape
[8]
>>> arr[None].shape
[1, 8]<5D><><EFBFBD><EFBFBD><EFBFBD>}<7D>h j<>sbah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D>jjj<00>j<00>shell<6C>j
}<7D>uhh<>h"h#hK(h h&h!hubh<)<29><>}<7D>(h<05>?You can also use an :obj:`array` to index another :obj:`array`:<3A>h]<5D>(h0<68>You can also use an <20><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j<>h!hh"NhNubhF)<29><>}<7D>(h<05> :obj:`array`<60>h]<5D>hL)<29><>}<7D>(hj<>h]<5D>h0<68>array<61><79><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j<>h!hh"NhNubah}<7D>(h]<5D>h]<5D>(hW<68>py<70><79>py-obj<62>eh]<5D>h]<5D>h]<5D>uhhKh j<>ubah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D><>refdoc<6F>hd<68> refdomain<69>j<EFBFBD><00>reftype<70><65>obj<62><6A> refexplicit<69><74><EFBFBD>refwarn<72><6E>hjhkhlNhm<68>array<61>uhhEh"h#hK1h j<>ubh0<68> to index another <20><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j<>h!hh"NhNubhF)<29><>}<7D>(h<05> :obj:`array`<60>h]<5D>hL)<29><>}<7D>(hj<>h]<5D>h0<68>array<61><79><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j<>h!hh"NhNubah}<7D>(h]<5D>h]<5D>(hW<68>py<70><79>py-obj<62>eh]<5D>h]<5D>h]<5D>uhhKh j<>ubah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D><>refdoc<6F>hd<68> refdomain<69>j<EFBFBD><00>reftype<70><65>obj<62><6A> refexplicit<69><74><EFBFBD>refwarn<72><6E>hjhkhlNhm<68>array<61>uhhEh"h#hK1h j<>ubh0<68>:<3A><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j<>h!hh"NhNubeh}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D>uhh;h"h#hK1h h&h!hubh<62>)<29><>}<7D>(h<05>Z>>> arr = mx.arange(10)
>>> idx = mx.array([5, 7])
>>> arr[idx]
array([5, 7], dtype=int32)<29>h]<5D>h0<68>Z>>> arr = mx.arange(10)
>>> idx = mx.array([5, 7])
>>> arr[idx]
array([5, 7], dtype=int32)<29><><EFBFBD><EFBFBD><EFBFBD>}<7D>h j<>sbah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D>jjj<00>j<00>shell<6C>j
}<7D>uhh<>h"h#hK3h h&h!hubh<)<29><>}<7D>(h<05>eMixing and matching integers, :obj:`slice`, ``...``, and :obj:`array` indices
works just as in NumPy.<2E>h]<5D>(h0<68>Mixing and matching integers, <20><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j<>h!hh"NhNubhF)<29><>}<7D>(h<05> :obj:`slice`<60>h]<5D>hL)<29><>}<7D>(hjh]<5D>h0<68>slice<63><65><EFBFBD><EFBFBD><EFBFBD>}<7D>(h jh!hh"NhNubah}<7D>(h]<5D>h]<5D>(hW<68>py<70><79>py-obj<62>eh]<5D>h]<5D>h]<5D>uhhKh j<>ubah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D><>refdoc<6F>hd<68> refdomain<69>j <00>reftype<70><65>obj<62><6A> refexplicit<69><74><EFBFBD>refwarn<72><6E>hjhkhlNhm<68>slice<63>uhhEh"h#hK:h j<>ubh0<68>, <20><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j<>h!hh"NhNubhL)<29><>}<7D>(h<05>``...``<60>h]<5D>h0<68>...<2E><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j"h!hh"NhNubah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D>uhhKh j<>ubh0<68>, and <20><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j<>h!hh"NhNubhF)<29><>}<7D>(h<05> :obj:`array`<60>h]<5D>hL)<29><>}<7D>(hj6h]<5D>h0<68>array<61><79><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j8h!hh"NhNubah}<7D>(h]<5D>h]<5D>(hW<68>py<70><79>py-obj<62>eh]<5D>h]<5D>h]<5D>uhhKh j4ubah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D><>refdoc<6F>hd<68> refdomain<69>jB<00>reftype<70><65>obj<62><6A> refexplicit<69><74><EFBFBD>refwarn<72><6E>hjhkhlNhm<68>array<61>uhhEh"h#hK:h j<>ubh0<68> indices
works just as in NumPy.<2E><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j<>h!hh"NhNubeh}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D>uhh;h"h#hK:h h&h!hubh<)<29><>}<7D>(h<05>eOther functions which may be useful for indexing arrays are :func:`take` and
:func:`take_along_axis`.<2E>h]<5D>(h0<68><Other functions which may be useful for indexing arrays are <20><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j^h!hh"NhNubhF)<29><>}<7D>(h<05> :func:`take`<60>h]<5D>hL)<29><>}<7D>(hjhh]<5D>h0<68>take()<29><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h jjh!hh"NhNubah}<7D>(h]<5D>h]<5D>(hW<68>py<70><79>py-func<6E>eh]<5D>h]<5D>h]<5D>uhhKh jfubah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D><>refdoc<6F>hd<68> refdomain<69>jt<00>reftype<70><65>func<6E><63> refexplicit<69><74><EFBFBD>refwarn<72><6E>hjhkhlNhm<68>take<6B>uhhEh"h#hK=h j^ubh0<68> and
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j^h!hh"NhNubhF)<29><>}<7D>(h<05>:func:`take_along_axis`<60>h]<5D>hL)<29><>}<7D>(hj<>h]<5D>h0<68>take_along_axis()<29><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j<>h!hh"NhNubah}<7D>(h]<5D>h]<5D>(hW<68>py<70><79>py-func<6E>eh]<5D>h]<5D>h]<5D>uhhKh j<>ubah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D><>refdoc<6F>hd<68> refdomain<69>j<EFBFBD><00>reftype<70><65>func<6E><63> refexplicit<69><74><EFBFBD>refwarn<72><6E>hjhkhlNhm<68>take_along_axis<69>uhhEh"h#hK=h j^ubh0<68>.<2E><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j^h!hh"NhNubeh}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D>uhh;h"h#hK=h h&h!hubh%)<29><>}<7D>(hhh]<5D>(h*)<29><>}<7D>(h<05>Differences from NumPy<50>h]<5D>h0<68>Differences from NumPy<50><79><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j<>h!hh"NhNubah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D>uhh)h j<>h!hh"h#hKAubh <09>note<74><65><EFBFBD>)<29><>}<7D>(h<05><>MLX indexing is different from NumPy indexing in two important ways:
* Indexing does not perform bounds checking. Indexing out of bounds is
undefined behavior.
* Boolean mask based indexing is not yet supported.<2E>h]<5D>(h<)<29><>}<7D>(h<05>DMLX indexing is different from NumPy indexing in two important ways:<3A>h]<5D>h0<68>DMLX indexing is different from NumPy indexing in two important ways:<3A><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j<>h!hh"NhNubah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D>uhh;h"h#hKEh j<>ubh <09> bullet_list<73><74><EFBFBD>)<29><>}<7D>(hhh]<5D>(h <09> list_item<65><6D><EFBFBD>)<29><>}<7D>(h<05>XIndexing does not perform bounds checking. Indexing out of bounds is
undefined behavior.<2E>h]<5D>h<)<29><>}<7D>(h<05>XIndexing does not perform bounds checking. Indexing out of bounds is
undefined behavior.<2E>h]<5D>h0<68>XIndexing does not perform bounds checking. Indexing out of bounds is
undefined behavior.<2E><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j<>h!hh"NhNubah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D>uhh;h"h#hKGh j<>ubah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D>uhj<>h j<>ubj<62>)<29><>}<7D>(h<05>1Boolean mask based indexing is not yet supported.<2E>h]<5D>h<)<29><>}<7D>(hj<>h]<5D>h0<68>1Boolean mask based indexing is not yet supported.<2E><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j<>h!hh"NhNubah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D>uhh;h"h#hKIh j<>ubah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D>uhj<>h j<>ubeh}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D><>bullet<65><74>*<2A>uhj<>h"h#hKGh j<>ubeh}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D>uhj<>h j<>h!hh"NhNubh<)<29><>}<7D>(h<05><>The reason for the lack of bounds checking is that exceptions cannot propagate
from the GPU. Performing bounds checking for array indices before launching the
kernel would be extremely inefficient.<2E>h]<5D>h0<68><30>The reason for the lack of bounds checking is that exceptions cannot propagate
from the GPU. Performing bounds checking for array indices before launching the
kernel would be extremely inefficient.<2E><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h jh!hh"NhNubah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D>uhh;h"h#hKKh j<>h!hubh<)<29><>}<7D>(hXWIndexing with boolean masks is something that MLX may support in the future. In
general, MLX has limited support for operations for which outputs
*shapes* are dependent on input *data*. Other examples of these types of
operations which MLX does not yet support include :func:`numpy.nonzero` and the
single input version of :func:`numpy.where`.<2E>h]<5D>(h0<68><30>Indexing with boolean masks is something that MLX may support in the future. In
general, MLX has limited support for operations for which outputs
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j+h!hh"NhNubh <09>emphasis<69><73><EFBFBD>)<29><>}<7D>(h<05>*shapes*<2A>h]<5D>h0<68>shapes<65><73><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j5h!hh"NhNubah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D>uhj3h j+ubh0<68> are dependent on input <20><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j+h!hh"NhNubj4)<29><>}<7D>(h<05>*data*<2A>h]<5D>h0<68>data<74><61><EFBFBD><EFBFBD><EFBFBD>}<7D>(h jGh!hh"NhNubah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D>uhj3h j+ubh0<68>U. Other examples of these types of
operations which MLX does not yet support include <20><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j+h!hh"NhNubhF)<29><>}<7D>(h<05>:func:`numpy.nonzero`<60>h]<5D>hL)<29><>}<7D>(hj[h]<5D>h0<68>numpy.nonzero()<29><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j]h!hh"NhNubah}<7D>(h]<5D>h]<5D>(hW<68>py<70><79>py-func<6E>eh]<5D>h]<5D>h]<5D>uhhKh jYubah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D><>refdoc<6F>hd<68> refdomain<69>jg<00>reftype<70><65>func<6E><63> refexplicit<69><74><EFBFBD>refwarn<72><6E>hjhkhlNhm<68> numpy.nonzero<72>uhhEh"h#hKOh j+ubh0<68>! and the
single input version of <20><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j+h!hh"NhNubhF)<29><>}<7D>(h<05>:func:`numpy.where`<60>h]<5D>hL)<29><>}<7D>(hjh]<5D>h0<68> numpy.where()<29><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j<>h!hh"NhNubah}<7D>(h]<5D>h]<5D>(hW<68>py<70><79>py-func<6E>eh]<5D>h]<5D>h]<5D>uhhKh j}ubah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D><>refdoc<6F>hd<68> refdomain<69>j<EFBFBD><00>reftype<70><65>func<6E><63> refexplicit<69><74><EFBFBD>refwarn<72><6E>hjhkhlNhm<68> numpy.where<72>uhhEh"h#hKOh j+ubh0<68>.<2E><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j+h!hh"NhNubeh}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D>uhh;h"h#hKOh j<>h!hubeh}<7D>(h]<5D><>differences-from-numpy<70>ah]<5D>h]<5D><>differences from numpy<70>ah]<5D>h]<5D>uhh$h h&h!hh"h#hKAubh%)<29><>}<7D>(hhh]<5D>(h*)<29><>}<7D>(h<05>In Place Updates<65>h]<5D>h0<68>In Place Updates<65><73><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j<>h!hh"NhNubah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D>uhh)h j<>h!hh"h#hKVubh<)<29><>}<7D>(h<05>DIn place updates to indexed arrays are possible in MLX. For example:<3A>h]<5D>h0<68>DIn place updates to indexed arrays are possible in MLX. For example:<3A><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j<>h!hh"NhNubah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D>uhh;h"h#hKXh j<>h!hubh<62>)<29><>}<7D>(h<05>L>>> a = mx.array([1, 2, 3])
>>> a[2] = 0
>>> a
array([1, 2, 0], dtype=int32)<29>h]<5D>h0<68>L>>> a = mx.array([1, 2, 3])
>>> a[2] = 0
>>> a
array([1, 2, 0], dtype=int32)<29><><EFBFBD><EFBFBD><EFBFBD>}<7D>h j<>sbah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D>jjj<00>j<00>shell<6C>j
}<7D>uhh<>h"h#hKZh j<>h!hubh<)<29><>}<7D>(h<05>YJust as in NumPy, in place updates will be reflected in all references to the
same array:<3A>h]<5D>h0<68>YJust as in NumPy, in place updates will be reflected in all references to the
same array:<3A><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j<>h!hh"NhNubah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D>uhh;h"h#hKah j<>h!hubh<62>)<29><>}<7D>(h<05>z>>> a = mx.array([1, 2, 3])
>>> b = a
>>> b[2] = 0
>>> b
array([1, 2, 0], dtype=int32)
>>> a
array([1, 2, 0], dtype=int32)<29>h]<5D>h0<68>z>>> a = mx.array([1, 2, 3])
>>> b = a
>>> b[2] = 0
>>> b
array([1, 2, 0], dtype=int32)
>>> a
array([1, 2, 0], dtype=int32)<29><><EFBFBD><EFBFBD><EFBFBD>}<7D>h j<>sbah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D>jjj<00>j<00>shell<6C>j
}<7D>uhh<>h"h#hKdh j<>h!hubh<)<29><>}<7D>(h<05>fTransformations of functions which use in-place updates are allowed and work as
expected. For example:<3A>h]<5D>h0<68>fTransformations of functions which use in-place updates are allowed and work as
expected. For example:<3A><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j<>h!hh"NhNubah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D>uhh;h"h#hKnh j<>h!hubh<62>)<29><>}<7D>(h<05><>def fun(x, idx):
x[idx] = 2.0
return x.sum()
dfdx = mx.grad(fun)(mx.array([1.0, 2.0, 3.0]), mx.array([1]))
print(dfdx) # Prints: array([1, 0, 1], dtype=float32)<29>h]<5D>h0<68><30>def fun(x, idx):
x[idx] = 2.0
return x.sum()
dfdx = mx.grad(fun)(mx.array([1.0, 2.0, 3.0]), mx.array([1]))
print(dfdx) # Prints: array([1, 0, 1], dtype=float32)<29><><EFBFBD><EFBFBD><EFBFBD>}<7D>h j
sbah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D>jjj<00>j<00>python<6F>j
}<7D>uhh<>h"h#hKqh j<>h!hubh<)<29><>}<7D>(h<05>aIn the above ``dfdx`` will have the correct gradient, namely zeros at ``idx``
and ones elsewhere.<2E>h]<5D>(h0<68> In the above <20><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h jh!hh"NhNubhL)<29><>}<7D>(h<05>``dfdx``<60>h]<5D>h0<68>dfdx<64><78><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j"h!hh"NhNubah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D>uhhKh jubh0<68>1 will have the correct gradient, namely zeros at <20><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h jh!hh"NhNubhL)<29><>}<7D>(h<05>``idx``<60>h]<5D>h0<68>idx<64><78><EFBFBD><EFBFBD><EFBFBD>}<7D>(h j4h!hh"NhNubah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D>uhhKh jubh0<68>
and ones elsewhere.<2E><><EFBFBD><EFBFBD><EFBFBD>}<7D>(h jh!hh"NhNubeh}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D>uhh;h"h#hKzh j<>h!hubeh}<7D>(h]<5D><>in-place-updates<65>ah]<5D>h]<5D><>in place updates<65>ah]<5D>h]<5D>uhh$h h&h!hh"h#hKVubeh}<7D>(h]<5D>(<28>indexing-arrays<79>heh]<5D>h]<5D>(<28>indexing arrays<79><73>indexing<6E>eh]<5D>h]<5D>uhh$h hh!hh"h#hK<04>expect_referenced_by_name<6D>}<7D>jZh s<>expect_referenced_by_id<69>}<7D>hh subeh}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D><>source<63>h#uhh<01>current_source<63>N<EFBFBD> current_line<6E>N<EFBFBD>settings<67><73>docutils.frontend<6E><64>Values<65><73><EFBFBD>)<29><>}<7D>(h)N<> generator<6F>N<EFBFBD> datestamp<6D>N<EFBFBD> source_link<6E>N<EFBFBD>
source_url<EFBFBD>N<EFBFBD> toc_backlinks<6B><73>entry<72><79>footnote_backlinks<6B>K<01> sectnum_xform<72>K<01>strip_comments<74>N<EFBFBD>strip_elements_with_classes<65>N<EFBFBD> strip_classes<65>N<EFBFBD> report_level<65>K<02>
halt_level<EFBFBD>K<05>exit_status_level<65>K<05>debug<75>N<EFBFBD>warning_stream<61>N<EFBFBD> traceback<63><6B><EFBFBD>input_encoding<6E><67> utf-8-sig<69><67>input_encoding_error_handler<65><72>strict<63><74>output_encoding<6E><67>utf-8<><38>output_encoding_error_handler<65>j<EFBFBD><00>error_encoding<6E><67>utf-8<><38>error_encoding_error_handler<65><72>backslashreplace<63><65> language_code<64><65>en<65><6E>record_dependencies<65>N<EFBFBD>config<69>N<EFBFBD> id_prefix<69>h<06>auto_id_prefix<69><78>id<69><64> dump_settings<67>N<EFBFBD>dump_internals<6C>N<EFBFBD>dump_transforms<6D>N<EFBFBD>dump_pseudo_xml<6D>N<EFBFBD>expose_internals<6C>N<EFBFBD>strict_visitor<6F>N<EFBFBD>_disable_config<69>N<EFBFBD>_source<63>h#<23> _destination<6F>N<EFBFBD> _config_files<65>]<5D><>file_insertion_enabled<65><64><EFBFBD> raw_enabled<65>K<01>line_length_limit<69>M'<27>pep_references<65>N<EFBFBD> pep_base_url<72><6C>https://peps.python.org/<2F><>pep_file_url_template<74><65>pep-%04d<34><64>rfc_references<65>N<EFBFBD> rfc_base_url<72><6C>&https://datatracker.ietf.org/doc/html/<2F><> tab_width<74>K<08>trim_footnote_reference_space<63><65><EFBFBD>syntax_highlight<68><74>long<6E><67> smart_quotes<65><73><EFBFBD>smartquotes_locales<65>]<5D><>character_level_inline_markup<75><70><EFBFBD>doctitle_xform<72><6D><EFBFBD> docinfo_xform<72>K<01>sectsubtitle_xform<72><6D><EFBFBD> image_loading<6E><67>link<6E><6B>embed_stylesheet<65><74><EFBFBD>cloak_email_addresses<65><73><EFBFBD>section_self_link<6E><6B><EFBFBD>env<6E>Nub<75>reporter<65>N<EFBFBD>indirect_targets<74>]<5D><>substitution_defs<66>}<7D><>substitution_names<65>}<7D><>refnames<65>}<7D><>refids<64>}<7D>h]<5D>h as<61>nameids<64>}<7D>(jZhjYjVh<>h<EFBFBD>j<EFBFBD>j<>jQjNu<> nametypes<65>}<7D>(jZ<00>jY<00>h<EFBFBD><68>j<EFBFBD><00>jQ<00>uh}<7D>(hh&jVh&h<>h<EFBFBD>j<EFBFBD>j<>jNj<>u<> footnote_refs<66>}<7D><> citation_refs<66>}<7D><> autofootnotes<65>]<5D><>autofootnote_refs<66>]<5D><>symbol_footnotes<65>]<5D><>symbol_footnote_refs<66>]<5D><> footnotes<65>]<5D><> citations<6E>]<5D><>autofootnote_start<72>K<01>symbol_footnote_start<72>K<00>
id_counter<EFBFBD><EFBFBD> collections<6E><73>Counter<65><72><EFBFBD>}<7D><><EFBFBD>R<EFBFBD><52>parse_messages<65>]<5D><>transform_messages<65>]<5D>h <09>system_message<67><65><EFBFBD>)<29><>}<7D>(hhh]<5D>h<)<29><>}<7D>(hhh]<5D>h0<68>.Hyperlink target "indexing" is not referenced.<2E><><EFBFBD><EFBFBD><EFBFBD>}<7D>h j<>sbah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D>uhh;h j<>ubah}<7D>(h]<5D>h]<5D>h]<5D>h]<5D>h]<5D><>level<65>K<01>type<70><65>INFO<46><4F>source<63>h#<23>line<6E>Kuhj<>uba<62> transformer<65>N<EFBFBD> include_log<6F>]<5D><>
decoration<EFBFBD>Nh!hub.