{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# Conditioning of evaluating tan()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "metadata": {
        "collapsed": true
      },
      "outputs": [],
      "source": [
        "import numpy as np\n",
        "import matplotlib.pyplot as pt"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Let us estimate the sensitivity of evaluating the $\\tan$ function:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "metadata": {
        "collapsed": false
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "[<matplotlib.lines.Line2D at 0x7f448ae83ba8>]"
            ]
          },
          "execution_count": 3,
          "metadata": {},
          "output_type": "execute_result"
        },
        {
          "data": {
            "image/png": "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\nrkJggg==\n",
            "text/plain": [
              "<matplotlib.figure.Figure at 0x7f448ae83be0>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "x = np.linspace(-5, 5, 1000)\n",
        "pt.ylim([-10, 10])\n",
        "pt.plot(x, np.tan(x))"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 18,
      "metadata": {
        "collapsed": false
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "1.5706963267948966"
            ]
          },
          "execution_count": 18,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "x = np.pi/2 - 0.0001\n",
        "#x = 0.1\n",
        "x"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 19,
      "metadata": {
        "collapsed": false
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "9999.9999666616441"
            ]
          },
          "execution_count": 19,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "np.tan(x)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 20,
      "metadata": {
        "collapsed": false
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "19999.99998335545"
            ]
          },
          "execution_count": 20,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "dx = 0.00005\n",
        "np.tan(x+dx)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Condition number estimates"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### From evaluation data\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 21,
      "metadata": {
        "collapsed": false
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "31413.926693068603"
            ]
          },
          "execution_count": 21,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "\n",
        "np.abs(np.tan(x+dx) - np.tan(x))/np.abs(np.tan(x)) / (np.abs(dx) / np.abs(x))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Using the derivative estimate"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 22,
      "metadata": {
        "collapsed": false
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "tan(x)**2 + 1"
            ]
          },
          "execution_count": 22,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "import sympy as sp\n",
        "\n",
        "xsym = sp.Symbol(\"x\")\n",
        "\n",
        "f = sp.tan(xsym)\n",
        "df = f.diff(xsym)\n",
        "df"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Evaluate the derivative estimate. Use `.subs(xsym, x)` to substitute in the value of `x`."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 23,
      "metadata": {
        "collapsed": false
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "15706.9633726542"
            ]
          },
          "execution_count": 23,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "(xsym*df/f).subs(xsym, x)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": true
      },
      "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.5.0+"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}