{
  "nbformat": 4,
  "nbformat_minor": 5,
  "metadata": {
    "kernelspec": {
      "name": "aner",
      "display_name": "Aner",
      "language": "aner"
    },
    "language_info": {
      "name": "aner",
      "file_extension": ".aner"
    },
    "aner": {
      "execution_mode": "persistent-session",
      "runtime_mode": "development"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "id": "ndarrays-0",
      "metadata": {},
      "source": "# Aner multidimensional arrays\n\nChoose **Run All** with compatible Aner and extension 0.1.27. **Dev** and **Inspector** show shape, element strides, and shared storage identifiers. NDArray requires no import. Read docs/NDARRAYS.md for methods and Big O costs.\n"
    },
    {
      "cell_type": "code",
      "id": "ndarrays-1",
      "metadata": {},
      "source": [
        "let matrix = NDArray<Int64>(shape: List(2, 3), fill: 0)\n",
        "matrix.set(List(0, 0), 1)\n",
        "matrix.set(List(0, 1), 2)\n",
        "matrix.set(List(0, 2), 3)\n",
        "matrix.set(List(1, 0), 4)\n",
        "matrix.set(List(1, 1), 5)\n",
        "matrix.set(List(1, 2), 6)\n",
        "print(matrix.shape())\n",
        "print(matrix.strides())\n",
        "print(matrix.to_list())\n"
      ],
      "outputs": [],
      "execution_count": null
    },
    {
      "cell_type": "markdown",
      "id": "ndarrays-2",
      "metadata": {},
      "source": "## Shared reshape and detached transpose\n\nReshaping fixed storage creates a descriptor sharing the same storage ID. Element mutations are visible through both descriptors. Transpose and flatten make independent copies.\n"
    },
    {
      "cell_type": "code",
      "id": "ndarrays-3",
      "metadata": {},
      "source": [
        "let reshaped = matrix.reshape(List(3, 2))\n",
        "reshaped.set(List(0, 0), 99)\n",
        "print(matrix.get(List(0, 0)))\n",
        "let transposed = matrix.transpose()\n",
        "transposed.set(List(0, 0), -1)\n",
        "print(matrix.get(List(0, 0)))\n",
        "print(transposed.shape())\n",
        "print(matrix.flatten().to_list())\n"
      ],
      "outputs": [],
      "execution_count": null
    },
    {
      "cell_type": "markdown",
      "id": "ndarrays-4",
      "metadata": {},
      "source": "## Trailing axis broadcasting\n\nDimensions must match or one must be 1. Shapes [2, 3] and [3] produce [2, 3]. Inputs are not expanded into repeated temporary arrays.\n"
    },
    {
      "cell_type": "code",
      "id": "ndarrays-5",
      "metadata": {},
      "source": [
        "let numbers = matrix.to_float()\n",
        "let bias = NDArray<Float64>(shape: List(3), fill: 10.0)\n",
        "let shifted = numbers.add(bias)\n",
        "print(shifted.shape())\n",
        "print(shifted.to_list())\n",
        "let columns = NDArray<Float64>(List(2, 1), 2.0)\n",
        "print(columns.mul(bias).to_list())\n"
      ],
      "outputs": [],
      "execution_count": null
    },
    {
      "cell_type": "markdown",
      "id": "ndarrays-6",
      "metadata": {},
      "source": "## Matrix multiplication and a third dimension\n\nMatrix products use matmul, while mul is elementwise. Axis permutations produce contiguous copies.\n"
    },
    {
      "cell_type": "code",
      "id": "ndarrays-7",
      "metadata": {},
      "source": [
        "let right = NDArray<Float64>(List(3, 2), 1.0)\n",
        "let product = numbers.matmul(right)\n",
        "print(product.shape())\n",
        "print(product.to_list())\n",
        "print(product.mean())\n",
        "let cube = NDArray<Bool>(List(2, 2, 2), false)\n",
        "cube.set(List(1, 0, 1), true)\n",
        "print(cube.permute(List(2, 0, 1)).shape())\n"
      ],
      "outputs": [],
      "execution_count": null
    }
  ]
}
