{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Sage Days 74\n",
    "============\n",
    "\n",
    "Introduction\n",
    "------------\n",
    "\n",
    "Sage comes with a lot of *rings and fields* that are at the basis of mathematical structures:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(Integer Ring,\n",
       " Rational Field,\n",
       " Real Double Field,\n",
       " Real Field with 53 bits of precision,\n",
       " Complex Double Field,\n",
       " Complex Field with 53 bits of precision,\n",
       " Algebraic Real Field,\n",
       " Finite Field in z2 of size 5^2,\n",
       " 5-adic Ring with capped relative precision 20,\n",
       " 5-adic Field with capped relative precision 20,\n",
       " Universal Cyclotomic Field,\n",
       " Univariate Polynomial Ring in x over Rational Field,\n",
       " Power Series Ring in x over Rational Field,\n",
       " Symbolic Ring)"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "(ZZ, QQ, RDF, RR, CDF , CC, AA, GF(5^2), Zp(5), Qp(5), \n",
    " CyclotomicField(),\n",
    " PolynomialRing(QQ, 'x'), PowerSeriesRing(QQ, 'x'), \n",
    " SR)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We say that the ring is the *parent* of the ring elements. In interactive use you use the parent to construct elements:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1, 0)"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ZZ(1), ZZ.zero()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1, Integer Ring)"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "1, 1.parent()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "How do these work together?\n",
    "---------------------------\n",
    "\n",
    "First, explicit conversion:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1.0"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "CDF(1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "CDF._element_constructor_??"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The preparser uses explicit conversion for Python -> Sage types:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"Integer(1), Integer(2), RealNumber('3.0')\""
      ]
     },
     "execution_count": 73,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "preparse('1, 2, 3.0')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ok for computer programming, but interactively we want to be able to write"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3/2"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "1 + 1/2    # and not QQ(1) + 1/2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Rational Field"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = ZZ(1)\n",
    "b = QQ(1/2)\n",
    "(a+b).parent()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Coercion\n",
    "--------\n",
    "\n",
    "This is called coercion in Sage. It only depends on the operation and the parents of the operands:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Coercion on left operand via\n",
      "    Natural morphism:\n",
      "      From: Integer Ring\n",
      "      To:   Rational Field\n",
      "Arithmetic performed after coercions.\n",
      "Result lives in Rational Field\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "Rational Field"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cm = get_coercion_model()\n",
    "cm.explain(ZZ, QQ, operator.add)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Natural morphism:\n",
       "  From: Integer Ring\n",
       "  To:   Rational Field"
      ]
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "QQ.coerce_map_from(ZZ)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Even though coercion doesn't depend on the element, they can be used as arguments instead of their parent:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Coercion on left operand via\n",
      "    Conversion map:\n",
      "      From: Integer Ring\n",
      "      To:   The Infinity Ring\n",
      "Arithmetic performed after coercions.\n",
      "Result lives in The Infinity Ring\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "The Infinity Ring"
      ]
     },
     "execution_count": 65,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cm.explain(1, oo, operator.add)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(A positive finite number, +Infinity)"
      ]
     },
     "execution_count": 66,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "InfinityRing(1), InfinityRing(oo)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Further topics\n",
    "--------------\n",
    "* Attach\n",
    "* Git log\n",
    "* Development workflow"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "SageMath 7.3.beta2",
   "language": "",
   "name": "sagemath"
  },
  "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.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
