{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Intrepydd functions reference\n",
    "\n",
    "This notebook serves as a \"executable\" reference guide to the functions available in reference, as summarized [here in the Intrepydd Guide](https://hpcgarage.github.io/intrepyddguide/library/functions.html).\n",
    "\n",
    "**Run these first.** If you are executing this reference, please run the following two code cells first. You can then run any subsection, as there are no additional dependencies among them."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from os import makedirs\n",
    "makedirs('ref', exist_ok=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "from numpy import array, float32, int32"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Table of contents\n",
    "\n",
    "The following [Python builtins](https://docs.python.org/3/library/functions.html) have counterparts in Intrepydd.\n",
    "\n",
    "- [`abs`](#abs): Absolute value of an iterable collection\n",
    "- [`all`](#all): Check whether all elements of an iterable collection are `True`\n",
    "- [`any`](#any): Check whether any element of an iterable collection is `True`\n",
    "- [`len`](#len): Returns the length of an iterable collection\n",
    "- [`max`](#max): Returns the largest value in an iterable collection\n",
    "- [`pow`](#pow): Raises a given value or every element of an iterable object to some power\n",
    "- [`range`](#range): Generates an integer range (sequence).\n",
    "- [`sum`](#sum): Returns the sum of the elements in an iterable object.\n",
    "- [Type conversion](#type_conv):`int32`, `int64`, `float32`, `float64`: Constructors and converters for basic primitive types.\n",
    "\n",
    "Intrepydd also provides counterparts to a subset of the functions available in [Numpy/Scipy](https://www.numpy.org/).\n",
    "\n",
    "- [Basic arithmetic, unary operators](#unary) `elemwise_not`, `minus`: Elementwise arithmetic on a single input array.\n",
    "- [Basic arithmetic, binary operators](#binary) `add`, `sub`, `mul`, `div`: Elementwise arithmetic between pairs of arrays.\n",
    "- [Comparisons](#comparisons) `eq`, `ge`, `gt`, `le`, `lt`: Elementwise signed comparison (e.g., equality, less than, greater than).\n",
    "- [Trignometric functions](#trig), `acos`, `asin`, `atan`, `cos`, `sin`, `sqrt`, `tan`: Elementwise trigonometric functions.\n",
    "- [`allclose`](#allclose): Returns `True` if all elements of a given array are close to a given value.\n",
    "- [`argmin`](#argmin): Returns the location of the minimum value in an array.\n",
    "- [`argmax`](#argmax): Returns the location of the maximum value in an array.\n",
    "- [`empty`](#empty): Returns an \"empty\" (uninitialized) multidimensional array.\n",
    "- [`innerprod`](#innerprod): Returns the inner product (dot-product) between two arrays of the same size.\n",
    "- [`isinf`, `isnan`](#isfpXXX): Tests for IEEE-754 floating-point infinity (`inf`) and not-a-number (`NaN`) values.\n",
    "- [`prod`](#prod): Returns the product of all elements of a collection.\n",
    "- [`transpose`](#transpose): Returns the transpose of a matrix.\n",
    "- [`zeros`](#zeros): Returns an array of all zero elements."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Python builtin-equivalents"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='abs'></a>\n",
    "\n",
    "## Function: `abs`\n",
    "\n",
    "Returns the absolute value of a given object or iterable; equivalent to its [Python builtin](https://docs.python.org/3/library/functions.html#abs)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Example.**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting ref/abs.pydd\n"
     ]
    }
   ],
   "source": [
    "%%writefile ref/abs.pydd\n",
    "\n",
    "def demo_float32(x: float32) -> float32:\n",
    "    return abs(x)\n",
    "\n",
    "def demo_Array(x: Array(float64, 2)) -> Array(float64, 2):\n",
    "    return abs(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pyddc ref/abs.pydd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3.140000104904175\n",
      "[[1. 2. 3.]\n",
      " [4. 5. 6.]]\n"
     ]
    }
   ],
   "source": [
    "import ref.abs\n",
    "print(ref.abs.demo_float32(-3.14))\n",
    "\n",
    "A = array([[-1., 2., -3.],\n",
    "           [4., -5., 6.]])\n",
    "print(ref.abs.demo_Array(A))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='all'></a>\n",
    "\n",
    "## Function: `all`\n",
    "\n",
    "Returns `True` if all elements of a given iterable object are `True`; equivalent to its [Python builtin](https://docs.python.org/3/library/functions.html#all)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Example.**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting ref/all.pydd\n"
     ]
    }
   ],
   "source": [
    "%%writefile ref/all.pydd\n",
    "\n",
    "def demo_bool(A: Array(bool, 2)) -> bool:\n",
    "    return all(A)\n",
    "\n",
    "def demo_int(A: Array(int64)) -> bool:\n",
    "    return all(A)\n",
    "\n",
    "def demo_double(A: Array(float64, 2)) -> bool:\n",
    "    return all(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pyddc ref/all.pydd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "False\n",
      "[0 1 2 3 4 5 6 7 8 9]\n",
      "False\n",
      "True\n",
      "[[ 1. -2.  3.]\n",
      " [-4.  5.  6.]]\n",
      "True\n",
      "[[ 1. -2.  3.]\n",
      " [-4.  5.  0.]]\n",
      "False\n"
     ]
    }
   ],
   "source": [
    "import ref.all\n",
    "\n",
    "A = array(2 * [3 * [True]])\n",
    "print(ref.all.demo_bool(A))\n",
    "\n",
    "A[0, 1] = False\n",
    "print(ref.all.demo_bool(A))\n",
    "\n",
    "L = array(range(10)) # Doesn't work with `list(range(10))`\n",
    "print(L)\n",
    "print(ref.all.demo_int(L)) # False\n",
    "\n",
    "L[0] = -1\n",
    "print(ref.all.demo_int(L)) # True\n",
    "\n",
    "A = array([[1., -2., 3.],\n",
    "           [-4., 5., 6.]])\n",
    "print(A)\n",
    "print(ref.all.demo_double(A))\n",
    "\n",
    "A[-1, -1] = 0.0\n",
    "print(A)\n",
    "print(ref.all.demo_double(A))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='any'></a>\n",
    "\n",
    "## Function: `any`\n",
    "\n",
    "Returns `True` if any element of a given iterable object is `True`; equivalent to its [Python builtin](https://docs.python.org/3/library/functions.html#any)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Example.**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting ref/any.pydd\n"
     ]
    }
   ],
   "source": [
    "%%writefile ref/any.pydd\n",
    "\n",
    "def demo_bool(A: Array(bool, 2)) -> bool:\n",
    "    return any(A)\n",
    "\n",
    "def demo_int(A: Array(int64)) -> bool:\n",
    "    return any(A)\n",
    "\n",
    "def demo_double(A: Array(float64, 2)) -> bool:\n",
    "    return any(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pyddc ref/any.pydd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "False\n",
      "True\n",
      "[0 0 0 0 0]\n",
      "False\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "import ref.any\n",
    "\n",
    "A = array(2 * [3 * [False]])\n",
    "print(ref.any.demo_bool(A))\n",
    "\n",
    "A[0, 1] = True\n",
    "print(ref.any.demo_bool(A))\n",
    "\n",
    "L = array([0] * 5) # Doesn't work with `list(range(10))`\n",
    "print(L)\n",
    "print(ref.any.demo_int(L)) # False\n",
    "\n",
    "L[0] = -1\n",
    "print(ref.any.demo_int(L)) # True"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='len'></a>\n",
    "\n",
    "## Function: `len`\n",
    "\n",
    "Returns the length of the object; equivalent to its [Python builtin](https://docs.python.org/3/library/functions.html#len)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Example.**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting ref/len.pydd\n"
     ]
    }
   ],
   "source": [
    "%%writefile ref/len.pydd\n",
    "\n",
    "def demo_list(L: List(int)) -> int64:\n",
    "    return len(L)\n",
    "\n",
    "def demo_dict(D: Dict(int64, float64)) -> int64:\n",
    "    return len(D)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pyddc ref/len.pydd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3\n",
      "4\n"
     ]
    }
   ],
   "source": [
    "import ref.len\n",
    "print(ref.len.demo_list([-1, -2, -3]))\n",
    "print(ref.len.demo_dict({1: 3.14, 2: 2.718, 3: 6.9824, 4: -1.2}))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='max'></a>\n",
    "\n",
    "## Function: `max`\n",
    "\n",
    "Returns the maximum value of an iterable; equivalent to its [Python builtin](https://docs.python.org/3/library/functions.html#max)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Example.**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting ref/max.pydd\n"
     ]
    }
   ],
   "source": [
    "%%writefile ref/max.pydd\n",
    "\n",
    "def demo_int(A: Array(int64, 1)) -> int64:\n",
    "    return max(A)\n",
    "\n",
    "def demo_float32_2d(A: Array(float32, 2)) -> float32:\n",
    "    return max(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pyddc ref/max.pydd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "100\n",
      "100.0\n"
     ]
    }
   ],
   "source": [
    "import ref.max\n",
    "print(ref.max.demo_int(array([3, 2, 100, 7])))\n",
    "print(ref.max.demo_float32_2d(array([[3, 2, 100, 33], [-500, 1, 0, -40]], dtype=float32)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='min'></a>\n",
    "\n",
    "## Function: `min`\n",
    "\n",
    "Returns the maximum value of an iterable object; equivalent to its [Python builtin](https://docs.python.org/3/library/functions.html#max)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Example.**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting ref/min.pydd\n"
     ]
    }
   ],
   "source": [
    "%%writefile ref/min.pydd\n",
    "\n",
    "def demo_int(A: Array(int64, 1)) -> int64:\n",
    "    return min(A)\n",
    "\n",
    "def demo_float32_2d(A: Array(float32, 2)) -> float32:\n",
    "    return min(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pyddc ref/min.pydd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2\n",
      "-500.0\n"
     ]
    }
   ],
   "source": [
    "import ref.min\n",
    "print(ref.min.demo_int(array([3, 2, 100, 7])))\n",
    "print(ref.min.demo_float32_2d(array([[3, 2, 100, 33], [-500, 1, 0, -40]], dtype=float32)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='pow'></a>\n",
    "\n",
    "## Function: `pow`\n",
    "\n",
    "Raises a given value or every element of an iterable object to some power; equivalent to its [Python builtin](https://docs.python.org/3/library/functions.html#pow)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting ref/pow.pydd\n"
     ]
    }
   ],
   "source": [
    "%%writefile ref/pow.pydd\n",
    "\n",
    "def demo_float32(x: float32, p: float32) -> float32:\n",
    "    return pow(x, p)\n",
    "\n",
    "def demo_float32_1d(A: Array(float32, 1), p: float32) -> Array(float32, 1):\n",
    "    return pow(A, p)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pyddc ref/pow.pydd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "9.859601020812988\n",
      "[ 30.959146 -30.959146]\n"
     ]
    }
   ],
   "source": [
    "import ref.pow\n",
    "\n",
    "print(ref.pow.demo_float32(3.14, 2.0))\n",
    "print(ref.pow.demo_float32_1d(array([3.14, -3.14], dtype=float32), 3.0))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='print'></a>\n",
    "\n",
    "## Function: `print`\n",
    "\n",
    "Prints a value to standard output.\n",
    "\n",
    "This function is equivalent to its [Python builtin](https://docs.python.org/3/library/functions.html#print). However, in the current version of Intrepydd, it is limited to accepting just one argument, i.e., `print(x)`, where `x` must be a primitive type."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting ref/print.pydd\n"
     ]
    }
   ],
   "source": [
    "%%writefile ref/print.pydd\n",
    "\n",
    "def demo_float32(x: float32):\n",
    "    print(x)\n",
    "\n",
    "def demo_float32_1d(A: Array(float32, 1)):\n",
    "    for i in range(shape(A, 0)):\n",
    "        print(A[i])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pyddc ref/print.pydd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3.140000104904175\n",
      "1.0\n",
      "2.0\n",
      "3.0\n"
     ]
    }
   ],
   "source": [
    "import ref.print\n",
    "ref.print.demo_float32(3.14)\n",
    "ref.print.demo_float32_1d(array([1, 2, 3], dtype=float32))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='range'></a>\n",
    "\n",
    "## Function: `range`\n",
    "\n",
    "Generates an integer range (sequence); equivalent to its [Python builtin](https://docs.python.org/3/library/functions.html#func-range)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting ref/range.pydd\n"
     ]
    }
   ],
   "source": [
    "%%writefile ref/range.pydd\n",
    "\n",
    "def demo_std(n: int64) -> int64:\n",
    "    s = 0\n",
    "    for i in range(n):\n",
    "        s += i\n",
    "        print(i)\n",
    "    return s\n",
    "        \n",
    "def demo_start_end(a: int64, b: int64) -> int64:\n",
    "    s = 0\n",
    "    for i in range(a, b):\n",
    "        print(i)\n",
    "        s += i\n",
    "    return s\n",
    "\n",
    "def demo_start_end_step(a: int64, b: int64, c: int64) -> int64:\n",
    "    s = 0\n",
    "    for i in range(a, b, c):\n",
    "        print(i)\n",
    "        s += i\n",
    "    return s"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pyddc ref/range.pydd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n",
      "1\n",
      "2\n",
      "3\n",
      "4\n",
      "-3\n",
      "-2\n",
      "-1\n",
      "0\n",
      "1\n",
      "2\n",
      "3\n",
      "4\n",
      "5\n",
      "6\n",
      "-3\n",
      "-1\n",
      "1\n",
      "3\n",
      "5\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "5"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import ref.range\n",
    "ref.range.demo_std(5)\n",
    "ref.range.demo_start_end(-3, 7)\n",
    "ref.range.demo_start_end_step(-3, 7, 2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='sum'></a>\n",
    "\n",
    "## Function: `sum`\n",
    "\n",
    "Returns the sum of the elements in an iterable object.\n",
    "\n",
    "This function is equivalent to its [Python builtin](https://docs.python.org/3/library/functions.html#sum), except it does **not** support the optional start argument, i.e., it does not support the calling signature, `sum(x, start)`, where in standard Python `start` is the position of the first index at which to begin the sum."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting ref/sum.pydd\n"
     ]
    }
   ],
   "source": [
    "%%writefile ref/sum.pydd\n",
    "\n",
    "def demo(x: Array(int64, 2)) -> int64:\n",
    "    return sum(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pyddc ref/sum.pydd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "55"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import ref.sum\n",
    "ref.sum.demo(array([[1, 2, 3, 4, 5],\n",
    "                    [6, 7, 8, 9, 10]]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='type_conv'></a>\n",
    "\n",
    "## Type conversion\n",
    "\n",
    "Construct or convert scalar variables among primitive types: `int32`, `int64`, `float32`, `float64`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Example:** `float32`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting ref/types.pydd\n"
     ]
    }
   ],
   "source": [
    "%%writefile ref/types.pydd\n",
    "\n",
    "def do_float32() -> float32:\n",
    "    return float32()\n",
    "\n",
    "def do_float32_2(val: int32) -> float32:\n",
    "    return float32(val)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pyddc ref/types.pydd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.0\n",
      "124.0\n",
      "1.0\n"
     ]
    }
   ],
   "source": [
    "import ref.types\n",
    "\n",
    "print(ref.types.do_float32()) # 0, as a float\n",
    "print(ref.types.do_float32_2(124))\n",
    "print(ref.types.do_float32_2(True))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Numpy equivalents"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='unary'></a>\n",
    "\n",
    "## Basic arithmetic: unary operators, `elemwise_not`, `minus`\n",
    "\n",
    "Applies basic arithmetic options elementwise to an input. These are equivalent to their Numpy counterparts; e.g., see [Numpy's `logical_not`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.logical_not.html)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Example:** `minus`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting ref/minus.pydd\n"
     ]
    }
   ],
   "source": [
    "%%writefile ref/minus.pydd\n",
    "\n",
    "def demo_float32(x: Array(float32, 2)) -> Array(float32, 2):\n",
    "    return minus(x)\n",
    "\n",
    "def demo_int64(x: Array(int64, 2)) -> Array(int64, 2):\n",
    "    return minus(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pyddc ref/minus.pydd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-1., -2., -3.],\n",
       "       [-4., -5., -6.]], dtype=float32)"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import ref.minus\n",
    "x = array([[1, 2, 3], [4, 5, 6]], dtype=float32)\n",
    "ref.minus.demo_float32(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-1,  2, -3],\n",
       "       [ 4, -5,  6]])"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y = array([[1, -2, 3], [-4, 5, -6]], dtype=int)\n",
    "ref.minus.demo_int64(y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='binary'></a>\n",
    "\n",
    "## Basic arithmetic: binary operators, `add`, `sub`, `mul`, `div`\n",
    "\n",
    "Applies basic arithmetic options elementwise to a pair of inputs. These are equivalent to their Numpy counterparts; e.g., see [Numpy's `add`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.add.html?highlight=add#numpy.add)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Example:** `add`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting ref/add.pydd\n"
     ]
    }
   ],
   "source": [
    "%%writefile ref/add.pydd\n",
    "\n",
    "def demo_float32(x: Array(float32, 2), y: Array(float32, 2)) -> Array(float32, 2):\n",
    "    return add(x, y)\n",
    "\n",
    "def demo_int64(x: Array(int64, 2), y: Array(int64, 2)) -> Array(int64, 2):\n",
    "    return add(x, y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pyddc ref/add.pydd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 2.,  0.,  6.],\n",
       "       [ 0., 10.,  0.]], dtype=float32)"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import ref.add\n",
    "x = array([[1, 2, 3], [4, 5, 6]], dtype=float32)\n",
    "y = array([[1, -2, 3], [-4, 5, -6]], dtype=float32)\n",
    "ref.add.demo_float32(x, y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 2,  0,  6],\n",
       "       [ 0, 10,  0]], dtype=int64)"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = array([[1, 2, 3], [4, 5, 6]], dtype=int)\n",
    "y = array([[1, -2, 3], [-4, 5, -6]], dtype=int)\n",
    "ref.add.demo_int64(x, y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='comparisons'></a>\n",
    "\n",
    "## Comparisons: binary logical operators, `eq`, `ge`, `gt`, `le`, `lt`\n",
    "\n",
    "Given a pair of inputs, performs elementwise binary comparisons: equality (`eq`), greater than (`gt`), greater than or equal to (`ge`), less than (`lt`), and less than or equal to (`le`). These are equivalent to their Numpy counterparts; e.g., see [Numpy's `eq`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.eq.html?highlight=eq#numpy.eq) for an example of equality comparison.\n",
    "\n",
    "> When the inputs are floating-point, it is usually better to apply `allclose` rather than `eq` to test for approximate equality due to round-off errors with floating-point arithmetic."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Example:** greater than (`gt`)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting ref/gt.pydd\n"
     ]
    }
   ],
   "source": [
    "%%writefile ref/gt.pydd\n",
    "\n",
    "def demo_float32(x: Array(float32, 2), y: Array(float32, 2)) -> Array(bool, 2):\n",
    "    return gt(x, y)\n",
    "\n",
    "def demo_int64(x: Array(int64, 2), y: Array(int64, 2)) -> Array(bool, 2):\n",
    "    return gt(x, y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pyddc ref/gt.pydd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[False,  True, False],\n",
       "       [ True, False,  True]])"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import ref.gt\n",
    "eps = 1e-6 # greater than float32 machine epsilon\n",
    "x = array([[1, 2, 3], [4, 5, 6]], dtype=float32)\n",
    "y = x + eps*array([[1, -1, 1], [-1, 0, -1]], dtype=float32)\n",
    "ref.gt.demo_float32(x, y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[False,  True, False],\n",
       "       [ True, False,  True]])"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = array([[1, 2, 3], [4, 5, 6]], dtype=int)\n",
    "y = x + array([[1, -1, 1], [-1, 0, -1]], dtype=int)\n",
    "ref.gt.demo_int64(x, y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='elemfun'></a>\n",
    "\n",
    "## Elementary functions: `acos`, `asin`, `atan`, `cos`, `exp`, `log`, `sin`, `sqrt`, `tan`\n",
    "\n",
    "Applies trigonometric function elementwise and returns the result. These are equivalent to their Numpy equivalents, e.g., see [Numpy's `arccos`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.arccos.html).\n",
    "\n",
    "**Example:** `acos`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting ref/acos.pydd\n"
     ]
    }
   ],
   "source": [
    "%%writefile ref/acos.pydd\n",
    "\n",
    "def demo(x: Array(float32, 2)) -> Array(float32, 2):\n",
    "    return acos(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pyddc ref/acos.pydd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0.99999994 0.6666667  0.5       ]\n",
      " [0.5        0.33333328 0.        ]] * pi\n"
     ]
    }
   ],
   "source": [
    "import math\n",
    "import ref.acos\n",
    "theta_over_pi = ref.acos.demo(array([[-1, -0.5, 0],\n",
    "                                     [0, 0.5, 1]], dtype=float32))/math.pi\n",
    "print('{} * pi'.format(theta_over_pi))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='allclose'></a>\n",
    "\n",
    "## Function: `allclose`\n",
    "\n",
    "Returns `True` if all elements of a given array are close to a given value.\n",
    "\n",
    "This function implements `allclose(x, atol)`, where `x` is an input array and `atol` is an absolute threshold. Therefore, Intrepydd's `allclose` is similar to, but **not** equivalent to, its [Numpy counterpart](https://docs.scipy.org/doc/numpy/reference/generated/numpy.allclose.html)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Numpy's `allclose`.** In particular, Numpy's `allclose` evaluates the logical operation $\\bigwedge_i \\left( |a_i - b_i| \\leq \\alpha + \\rho |b_i| \\right)$, where $\\bigwedge$ denotes logical-and, $a_i$ and $b_i$ are the elements of two arrays, and $\\alpha$ and $\\rho$ are absolute and relative threshold parameters, respectively. (The values of $\\alpha$ and $\\rho$ are the `atol` and `rtol` arguments to `allclose()`.) For instance, suppose we have two Numpy arrays, `a` and `b`, and suppose the absolute difference between any pair of corresponding elements is $10^{-10}$.\n",
    "\n",
    "```python\n",
    "# Numpy allclose\n",
    "from numpy import allclose, array\n",
    "tiny_diff = 1e-10\n",
    "a = array([1., 2., 3.])\n",
    "b = a + array([tiny_diff, -tiny_diff, tiny_diff])\n",
    "```\n",
    "\n",
    "Consider two calls to `allclose`: one that checks whether the absolute difference is less than $10^{-11}$, which will be false, and the other that checks against $10^{-9}$, which will be true.\n",
    "\n",
    "```python\n",
    "print(allclose(a, b, atol=1e-11, rtol=0)) # False!\n",
    "print(allclose(a, b, atol=1e-9, rtol=0)) # True!\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Intrepydd's `allclose`.** By contrast, Intrepydd's interface, `allclose(x, atol)`, is \"lighter.\" It accepts just a single array (`x`) and an absolute tolerance (`atol`). There is no direct relative tolerance support (but see below!). The previous two checks would be rewritten as follows:\n",
    "\n",
    "```python\n",
    "    # Intrepydd:\n",
    "    allclose(abs(a-b), 1e-11)  # False!\n",
    "    allclose(abs(a-b), 1e-9)   # True!\n",
    "```\n",
    "\n",
    "To implement something like Numpy's `allclose()`, which accepts both `atol` and `rtol` parameters, see the `demo` function in the code cells below."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[-1.00000008e-10  1.00000008e-10 -1.00000008e-10]\n",
      "False\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "from numpy import allclose, array\n",
    "a = array([1., 2., 3.])\n",
    "b = a + array([1e-10, -1e-10, 1e-10])\n",
    "print(a-b)\n",
    "print(allclose(a, b, atol=1e-11, rtol=0)) # False!\n",
    "print(allclose(a, b, atol=1e-9, rtol=0)) # True!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting ref/allclose.pydd\n"
     ]
    }
   ],
   "source": [
    "%%writefile ref/allclose.pydd\n",
    "\n",
    "def scale_array(x: Array(float64, 2), s: float64) -> Array(float64, 2):\n",
    "    y = empty([shape(x, 0), shape(x, 1)])\n",
    "    for i in range(shape(y, 0)):\n",
    "        for j in range(shape(y, 1)):\n",
    "            y[i, j] = x[i, j] * s\n",
    "    return y\n",
    "\n",
    "def demo(a: Array(float64, 2), b: Array(float64, 2), atol: float64, rtol: float64) -> bool:\n",
    "    diff = abs(sub(a, b))\n",
    "    relterm = abs(scale_array(b, rtol))\n",
    "    x = sub(diff, relterm)\n",
    "    return allclose(x, atol)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pyddc ref/allclose.pydd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "False\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "import ref.allclose\n",
    "\n",
    "a = array([[1., 2., 3.],\n",
    "           [4., 5., 6.]])\n",
    "b = a + 1e-10\n",
    "print(ref.allclose.demo(a, b, 1e-11, 0.)) # False?\n",
    "print(ref.allclose.demo(a, b, 1e-9, 0.))  # True?"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='argmin'></a>\n",
    "\n",
    "## Function: `argmin`\n",
    "\n",
    "Returns the location of the minimum value of an array; equivalent to its [Numpy counterpart](https://docs.scipy.org/doc/numpy/reference/generated/numpy.argmin.html?highlight=add#numpy.argmin).\n",
    "\n",
    "The return value is a list, since the input array may be multidimensional. A best-practice in the current version of Intrepydd is to recast this return as an array before returning, as the following example shows.\n",
    "\n",
    "> If there are duplicates, one of them will be returned. The precise one is not specified."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting ref/argmin.pydd\n"
     ]
    }
   ],
   "source": [
    "%%writefile ref/argmin.pydd\n",
    "\n",
    "def demo(A: Array(float64, 3)) -> Array(int32) :\n",
    "    r = argmin(A)\n",
    "    r_np = empty((3,), int32())\n",
    "    r_np[0] = r[0]\n",
    "    r_np[1] = r[1]\n",
    "    r_np[2] = r[2]\n",
    "    return r_np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pyddc ref/argmin.pydd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1 1 2] : <class 'numpy.ndarray'>\n",
      "Min value is -6.0, which resides at location x[1 1 2]\n"
     ]
    }
   ],
   "source": [
    "import ref.argmin\n",
    "plane = array([[1., 2., 3.],\n",
    "               [4., 5., 6.]])\n",
    "x = array([plane, -plane, plane])\n",
    "loc = ref.argmin.demo(x)\n",
    "print(loc, ':', type(loc))\n",
    "print(\"Min value is {}, which resides at location x{}\".format(x[loc[0], loc[1], loc[2]], loc))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='argmax'></a>\n",
    "\n",
    "## Function: `argmax`\n",
    "\n",
    "Returns the location of the maximum value of an array; equivalent to its [Numpy counterpart](https://docs.scipy.org/doc/numpy/reference/generated/numpy.argmax.html?highlight=add#numpy.argmax).\n",
    "\n",
    "The return value is a list, since the input array may be multidimensional. A best-practice in the current version of Intrepydd is to recast this return as an array before returning, as the following example shows.\n",
    "\n",
    "> If there are duplicates, one of them will be returned. The precise one is not specified."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting ref/argmax.pydd\n"
     ]
    }
   ],
   "source": [
    "%%writefile ref/argmax.pydd\n",
    "\n",
    "def demo(A: Array(float64, 3)) -> Array(int32) :\n",
    "    r = argmax(A)\n",
    "    r_np = empty((3,), int32())\n",
    "    r_np[0] = r[0]\n",
    "    r_np[1] = r[1]\n",
    "    r_np[2] = r[2]\n",
    "    return r_np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pyddc ref/argmax.pydd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1 1 2] : <class 'numpy.ndarray'>\n",
      "Max value is 6.0, which resides at location x[1 1 2]\n"
     ]
    }
   ],
   "source": [
    "import ref.argmax\n",
    "plane = array([[1., 2., 3.],\n",
    "               [4., 5., 6.]])\n",
    "x = array([-plane, plane, -plane])\n",
    "loc = ref.argmax.demo(x)\n",
    "print(loc, ':', type(loc))\n",
    "print(\"Max value is {}, which resides at location x{}\".format(x[loc[0], loc[1], loc[2]], loc))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='empty'></a>\n",
    "\n",
    "## Function: `empty`\n",
    "\n",
    "Returns an \"empty\" (uninitialized) multidimensional array; equivalent to its [Numpy counterpart](https://docs.scipy.org/doc/numpy/reference/generated/numpy.empty.html?highlight=add#numpy.empty).\n",
    "\n",
    "> Intrepydd does not currently implement the `order` parameter, which would be used to specify row- vs. column-major layouts. Intrepydd's default is row-major."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting ref/empty.pydd\n"
     ]
    }
   ],
   "source": [
    "%%writefile ref/empty.pydd\n",
    "\n",
    "def demo_int32(shape: List(int32)) -> Array(int32):\n",
    "    return empty(shape, int32())\n",
    "\n",
    "def demo_float64(shape: List(int32)) -> Array(float64):\n",
    "    return empty(shape, float64())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pyddc ref/empty.pydd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'numpy.ndarray'> int32\n",
      "[[[          0 -1074790400]\n",
      "  [          0 -1073741824]\n",
      "  [          0 -1073217536]]\n",
      "\n",
      " [[          0 -1072693248]\n",
      "  [          0 -1072431104]\n",
      "  [          0 -1072168960]]]\n",
      "<class 'numpy.ndarray'> float64\n",
      "[[[-8.39911598e-323 -0.00000000e+000]\n",
      "  [ 1.49458072e-154 -0.00000000e+000]\n",
      "  [ 7.41098469e-323  0.00000000e+000]]\n",
      "\n",
      " [[ 0.00000000e+000  0.00000000e+000]\n",
      "  [ 0.00000000e+000  0.00000000e+000]\n",
      "  [ 0.00000000e+000  0.00000000e+000]]]\n"
     ]
    }
   ],
   "source": [
    "import ref.empty\n",
    "A = ref.empty.demo_int32([2, 3, 2])\n",
    "print(type(A), A.dtype)\n",
    "print(A)\n",
    "\n",
    "B = ref.empty.demo_float64([2, 3, 2])\n",
    "print(type(B), B.dtype)\n",
    "print(B)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='innerprod'></a>\n",
    "\n",
    "## Function: `innerprod`\n",
    "\n",
    "Returns the inner product (dot-product) between two arrays of the same size. Its closest counterpart in Numpy is [`numpy.ma.innerproduct`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.ma.innerproduct.html)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting ref/innerprod.pydd\n"
     ]
    }
   ],
   "source": [
    "%%writefile ref/innerprod.pydd\n",
    "\n",
    "def func(A: Array(int32, 1), B: Array(float64, 1)) -> float64:\n",
    "    return innerprod(A, B)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pyddc ref/innerprod.pydd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "14.0"
      ]
     },
     "execution_count": 66,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import ref.innerprod\n",
    "\n",
    "x = array([1, 2, 3], dtype=int32)\n",
    "y = array([1., 2., 3.])\n",
    "\n",
    "ref.innerprod.func(x, y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='isfpXXX'></a>\n",
    "\n",
    "## Functions: `isinf`, `isnan`\n",
    "\n",
    "Tests whether values of an array are IEEE floating-point infinity (`inf`) or not-a-number (`NaN`) values; equivalent to the Numpy functions [`numpy.isinf`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.isinf.html) and [`numpy.isnan`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.isnan.html)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting ref/isfpXXX.pydd\n"
     ]
    }
   ],
   "source": [
    "%%writefile ref/isfpXXX.pydd\n",
    "\n",
    "def demo_isinf(x: Array(float64, 2)) -> Array(bool, 2):\n",
    "    return isinf(x)\n",
    "\n",
    "def demo_isnan(x: Array(float32, 2)) -> Array(bool, 2):\n",
    "    return isnan(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pyddc ref/isfpXXX.pydd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[False  True False]\n",
      " [False False  True]]\n",
      "[[False False False]\n",
      " [ True False False]]\n"
     ]
    }
   ],
   "source": [
    "import ref.isfpXXX\n",
    "\n",
    "z = array([[1.0, float('inf'), 0.0],\n",
    "           [float('nan'), -2.0, float('inf')]])\n",
    "\n",
    "print(ref.isfpXXX.demo_isinf(z))\n",
    "print(ref.isfpXXX.demo_isnan(z.astype(float32)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='prod'></a>\n",
    "\n",
    "## Function: `prod`\n",
    "\n",
    "Returns the product of all elements of a collection; equivalent to its [`Numpy counterpart`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.prod.html)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting ref/prod.pydd\n"
     ]
    }
   ],
   "source": [
    "%%writefile ref/prod.pydd\n",
    "\n",
    "def demo(arr: Array(int64)) -> int64:\n",
    "    return prod(arr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pyddc ref/prod.pydd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "-30"
      ]
     },
     "execution_count": 72,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import ref.prod\n",
    "ref.prod.demo(array([1, -2, 3, 5], dtype=int))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='transpose'></a>\n",
    "\n",
    "## Function: `transpose`\n",
    "\n",
    "Returns the transpose of a matrix.\n",
    "\n",
    "This function is roughly equivalent to its [`Numpy counterpart`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.transpose.html), except that it works only for matrix (2-D) inputs."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting ref/transpose.pydd\n"
     ]
    }
   ],
   "source": [
    "%%writefile ref/transpose.pydd\n",
    "\n",
    "def demo(arr: Array(int32, 2)) -> Array(int32, 2):\n",
    "    return transpose(arr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pyddc ref/transpose.pydd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 4],\n",
       "       [2, 5],\n",
       "       [3, 6]], dtype=int32)"
      ]
     },
     "execution_count": 75,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import ref.transpose\n",
    "ref.transpose.demo(array([[1, 2, 3], [4, 5, 6]], dtype=int32))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='zeros'></a>\n",
    "\n",
    "## Function: `zeros`\n",
    "\n",
    "Returns an array of all zeros; equivalent to its [`Numpy counterpart`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.zeros.html)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting ref/zeros.pydd\n"
     ]
    }
   ],
   "source": [
    "%%writefile ref/zeros.pydd\n",
    "\n",
    "def zeros_1d(n: int) -> Array(float64, 1):\n",
    "    return zeros(n, float64())\n",
    "\n",
    "def ones_2d(m:int, n: int) -> Array(float64, 2):\n",
    "    C = zeros([m, n], float64())\n",
    "    return cos(C)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pyddc ref/zeros.pydd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0. 0. 0. 0.]\n",
      "[[1. 1. 1.]\n",
      " [1. 1. 1.]]\n"
     ]
    }
   ],
   "source": [
    "import ref.zeros\n",
    "print(ref.zeros.zeros_1d(4))\n",
    "print(ref.zeros.ones_2d(2, 3))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}