{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# [Quadratic formula](https://en.wikipedia.org/wiki/Quadratic_formula)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from notebook_preamble import J, V, define"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Cf. [jp-quadratic.html](http://www.kevinalbrecht.com/code/joy-mirror/jp-quadratic.html)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "             -b  +/- sqrt(b^2 - 4 * a * c)\n",
    "             -----------------------------\n",
    "                        2 * a"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$\\frac{-b  \\pm \\sqrt{b^2 - 4ac}}{2a}$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Write a straightforward program with variable names.\n",
    "    b neg b sqr 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2\n",
    "\n",
    "### Check it.\n",
    "\n",
    "     b neg b sqr 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2\n",
    "    -b     b sqr 4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2\n",
    "    -b     b^2   4 a c * * - sqrt [+] [-] cleave a 2 * [truediv] cons app2\n",
    "    -b     b^2 4ac         - sqrt [+] [-] cleave a 2 * [truediv] cons app2\n",
    "    -b     b^2-4ac           sqrt [+] [-] cleave a 2 * [truediv] cons app2\n",
    "    -b sqrt(b^2-4ac)              [+] [-] cleave a 2 * [truediv] cons app2\n",
    "\n",
    "    -b -b+sqrt(b^2-4ac)    -b-sqrt(b^2-4ac)    a 2 * [truediv] cons app2\n",
    "    -b -b+sqrt(b^2-4ac)    -b-sqrt(b^2-4ac)    2a    [truediv] cons app2\n",
    "    -b -b+sqrt(b^2-4ac)    -b-sqrt(b^2-4ac)    [2a truediv]         app2\n",
    "    -b -b+sqrt(b^2-4ac)/2a -b-sqrt(b^2-4ac)/2a\n",
    "### Codicil\n",
    "    -b -b+sqrt(b^2-4ac)/2a -b-sqrt(b^2-4ac)/2a                          roll< pop\n",
    "       -b+sqrt(b^2-4ac)/2a -b-sqrt(b^2-4ac)/2a -b                             pop\n",
    "       -b+sqrt(b^2-4ac)/2a -b-sqrt(b^2-4ac)/2a"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Derive a definition.\n",
    "\n",
    "    b neg b           sqr 4 a c        * * - sqrt [+] [-] cleave a       2 * [truediv] cons app2 roll< pop\n",
    "    b    [neg] dupdip sqr 4 a c        * * - sqrt [+] [-] cleave a       2 * [truediv] cons app2 roll< pop\n",
    "    b a c    [[neg] dupdip sqr 4] dipd * * - sqrt [+] [-] cleave a       2 * [truediv] cons app2 roll< pop\n",
    "    b a c a    [[[neg] dupdip sqr 4] dipd * * - sqrt [+] [-] cleave] dip 2 * [truediv] cons app2 roll< pop\n",
    "    b a c over [[[neg] dupdip sqr 4] dipd * * - sqrt [+] [-] cleave] dip 2 * [truediv] cons app2 roll< pop"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "define('quadratic == over [[[neg] dupdip sqr 4] dipd * * - sqrt [+] [-] cleave] dip 2 * [truediv] cons app2 roll< pop')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-0.3819660112501051 -2.618033988749895\n"
     ]
    }
   ],
   "source": [
    "J('3 1 1 quadratic')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Simplify\n",
    "We can define a `pm` plus-or-minus function:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "define('pm == [+] [-] cleave popdd')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Then `quadratic` becomes:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "define('quadratic == over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [truediv] cons app2')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-0.3819660112501051 -2.618033988749895\n"
     ]
    }
   ],
   "source": [
    "J('3 1 1 quadratic')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Define a \"native\" `pm` function.\n",
    "The definition of `pm` above is pretty elegant, but the implementation takes a lot of steps relative to what it's accomplishing.  Since we are likely to use `pm` more than once in the future, let's write a primitive in Python and add it to the dictionary."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "from joy.library import SimpleFunctionWrapper\n",
    "from notebook_preamble import D\n",
    "\n",
    "\n",
    "@SimpleFunctionWrapper\n",
    "def pm(stack):\n",
    "    a, (b, stack) = stack\n",
    "    p, m, = b + a, b - a\n",
    "    return m, (p, stack)\n",
    "\n",
    "\n",
    "D['pm'] = pm"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The resulting trace is short enough to fit on a page."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "                                                    . 3 1 1 quadratic\n",
      "                                                  3 . 1 1 quadratic\n",
      "                                                3 1 . 1 quadratic\n",
      "                                              3 1 1 . quadratic\n",
      "                                              3 1 1 . over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [truediv] cons app2\n",
      "                                            3 1 1 1 . [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [truediv] cons app2\n",
      "  3 1 1 1 [[[neg] dupdip sqr 4] dipd * * - sqrt pm] . dip 2 * [truediv] cons app2\n",
      "                                              3 1 1 . [[neg] dupdip sqr 4] dipd * * - sqrt pm 1 2 * [truediv] cons app2\n",
      "                         3 1 1 [[neg] dupdip sqr 4] . dipd * * - sqrt pm 1 2 * [truediv] cons app2\n",
      "                                                  3 . [neg] dupdip sqr 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2\n",
      "                                            3 [neg] . dupdip sqr 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2\n",
      "                                                  3 . neg 3 sqr 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2\n",
      "                                                 -3 . 3 sqr 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2\n",
      "                                               -3 3 . sqr 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2\n",
      "                                               -3 3 . dup mul 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2\n",
      "                                             -3 3 3 . mul 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2\n",
      "                                               -3 9 . 4 1 1 * * - sqrt pm 1 2 * [truediv] cons app2\n",
      "                                             -3 9 4 . 1 1 * * - sqrt pm 1 2 * [truediv] cons app2\n",
      "                                           -3 9 4 1 . 1 * * - sqrt pm 1 2 * [truediv] cons app2\n",
      "                                         -3 9 4 1 1 . * * - sqrt pm 1 2 * [truediv] cons app2\n",
      "                                           -3 9 4 1 . * - sqrt pm 1 2 * [truediv] cons app2\n",
      "                                             -3 9 4 . - sqrt pm 1 2 * [truediv] cons app2\n",
      "                                               -3 5 . sqrt pm 1 2 * [truediv] cons app2\n",
      "                                -3 2.23606797749979 . pm 1 2 * [truediv] cons app2\n",
      "              -0.7639320225002102 -5.23606797749979 . 1 2 * [truediv] cons app2\n",
      "            -0.7639320225002102 -5.23606797749979 1 . 2 * [truediv] cons app2\n",
      "          -0.7639320225002102 -5.23606797749979 1 2 . * [truediv] cons app2\n",
      "            -0.7639320225002102 -5.23606797749979 2 . [truediv] cons app2\n",
      "  -0.7639320225002102 -5.23606797749979 2 [truediv] . cons app2\n",
      "  -0.7639320225002102 -5.23606797749979 [2 truediv] . app2\n",
      "                  [-0.7639320225002102] [2 truediv] . infra first [-5.23606797749979] [2 truediv] infra first\n",
      "                                -0.7639320225002102 . 2 truediv [] swaack first [-5.23606797749979] [2 truediv] infra first\n",
      "                              -0.7639320225002102 2 . truediv [] swaack first [-5.23606797749979] [2 truediv] infra first\n",
      "                                -0.3819660112501051 . [] swaack first [-5.23606797749979] [2 truediv] infra first\n",
      "                             -0.3819660112501051 [] . swaack first [-5.23606797749979] [2 truediv] infra first\n",
      "                              [-0.3819660112501051] . first [-5.23606797749979] [2 truediv] infra first\n",
      "                                -0.3819660112501051 . [-5.23606797749979] [2 truediv] infra first\n",
      "            -0.3819660112501051 [-5.23606797749979] . [2 truediv] infra first\n",
      "-0.3819660112501051 [-5.23606797749979] [2 truediv] . infra first\n",
      "                                  -5.23606797749979 . 2 truediv [-0.3819660112501051] swaack first\n",
      "                                -5.23606797749979 2 . truediv [-0.3819660112501051] swaack first\n",
      "                                 -2.618033988749895 . [-0.3819660112501051] swaack first\n",
      "           -2.618033988749895 [-0.3819660112501051] . swaack first\n",
      "           -0.3819660112501051 [-2.618033988749895] . first\n",
      "             -0.3819660112501051 -2.618033988749895 . \n"
     ]
    }
   ],
   "source": [
    "V('3 1 1 quadratic')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
