by Franco Saliola and Sébastien Labbé

 

Two important (but minor) differences between Sage language and Python

Integer division in Python :

{{{id=117| %python 2/3 + 4/5 + 1/7 /// 0 }}}

in Sage:

{{{id=125| 2/3 + 4/5 + 1/7 /// 169/105 }}}

Exponent (^) in Python :

{{{id=130| %python 10^14 #exclusive OR /// 4 }}}

in Sage :

{{{id=149| 10^14 /// 100000000000000 }}}

The preparser

{{{id=154| preparse('2/3 + 2^3 + 3.0') /// "Integer(2)/Integer(3) + Integer(2)**Integer(3) + RealNumber('3.0')" }}} {{{id=35| preparse('2^3') /// 'Integer(2)**Integer(3)' }}}

2D  Plots

{{{id=3| f = sin(1/x) P = plot(f, -10, 10, color='red') P /// }}} {{{id=43| Q = line([(3,0.9), (7,0.9), (7,1.1), (3,1.1), (3,0.9)], color='green') Q /// }}} {{{id=6| R = text('$f(x) = \\sin(\\frac{1}{x})$', (5,1)) R /// }}} {{{id=44| Q + R + P /// }}} {{{id=157| /// }}} {{{id=116| /// }}}

L'outil interact (exemples tirés du wiki de Sage : http://wiki.sagemath.org/)

Curves of Pursuit

by Marshall Hampton.

{{{id=46| %hide npi = RDF(pi) from math import cos,sin def rot(t): return matrix([[cos(t),sin(t)],[-sin(t),cos(t)]]) def pursuit(n,x0,y0,lamb,steps = 100, threshold = .01): paths = [[[x0,y0]]] for i in range(1,n): rx,ry = list(rot(2*npi*i/n)*vector([x0,y0])) paths.append([[rx,ry]]) oldpath = [x[-1] for x in paths] for q in range(steps): diffs = [[oldpath[(j+1)%n][0]-oldpath[j][0],oldpath[(j+1)%n][1]-oldpath[j][1]] for j in range(n)] npath = [[oldpath[j][0]+lamb*diffs[j][0],oldpath[j][1]+lamb*diffs[j][1]] for j in range(n)] for j in range(n): paths[j].append(npath[j]) oldpath = npath return paths html('

Curves of Pursuit

') @interact def curves_of_pursuit(n = slider([2..20],default = 5, label="# of points"),steps = slider([floor(1.4^i) for i in range(2,18)],default = 10, label="# of steps"), stepsize = slider(srange(.01,1,.01),default = .2, label="stepsize"), colorize = selector(['BW','Line color', 'Filled'],default = 'BW')): outpaths = pursuit(n,0,1,stepsize, steps = steps) mcolor = (0,0,0) outer = line([q[0] for q in outpaths]+[outpaths[0][0]], rgbcolor = mcolor) polys = Graphics() if colorize=='Line color': colors = [hue(j/steps,1,1) for j in range(len(outpaths[0]))] elif colorize == 'BW': colors = [(0,0,0) for j in range(len(outpaths[0]))] else: colors = [hue(j/steps,1,1) for j in range(len(outpaths[0]))] polys = sum([polygon([outpaths[(i+1)%n][j+1],outpaths[(i+1)%n][j], outpaths[i][j+1]], rgbcolor = colors[j]) for i in range(n) for j in range(len(outpaths[0])-1)]) #polys = polys[0] colors = [(0,0,0) for j in range(len(outpaths[0]))] nested = sum([line([q[j] for q in outpaths]+[outpaths[0][j]], rgbcolor = colors[j]) for j in range(len(outpaths[0]))]) lpaths = [line(x, rgbcolor = mcolor) for x in outpaths] show(sum(lpaths)+nested+polys, axes = False, figsize = [5,5], xmin = -1, xmax = 1, ymin = -1, ymax =1) ///

Curves of Pursuit

# of points 
# of steps 
stepsize 
colorize 
}}}

Factor Trees

by William Stein

{{{id=11| %hide import random def ftree(rows, v, i, F): if len(v) > 0: # add a row to g at the ith level. rows.append(v) w = [] for i in range(len(v)): k, _, _ = v[i] if k is None or is_prime(k): w.append((None,None,None)) else: d = random.choice(divisors(k)[1:-1]) w.append((d,k,i)) e = k//d if e == 1: w.append((None,None)) else: w.append((e,k,i)) if len(w) > len(v): ftree(rows, w, i+1, F) def draw_ftree(rows,font): g = Graphics() for i in range(len(rows)): cur = rows[i] for j in range(len(cur)): e, f, k = cur[j] if not e is None: if is_prime(e): c = (1,0,0) else: c = (0,0,.4) g += text(str(e), (j*2-len(cur),-i), fontsize=font, rgbcolor=c) if not k is None and not f is None: g += line([(j*2-len(cur),-i), ((k*2)-len(rows[i-1]),-i+1)], alpha=0.5) return g @interact def factor_tree(n=100, font=(10, (8..20)), redraw=['Redraw']): n = Integer(n) rows = [] v = [(n,None,0)] ftree(rows, v, 0, factor(n)) show(draw_ftree(rows, font), axes=False) ///
font 
redraw 
}}} {{{id=114| /// }}}

Illustrating the prime number theorem

by William Stein

{{{id=156| @interact def _(N=(100,(2..2000))): html("$\pi(x)$ and $x/(\log(x)-1)$ for $x < %s$"%N) show(plot(prime_pi, 0, N, rgbcolor='red') + plot(x/(log(x)-1), 5, N, rgbcolor='blue')) ///
}}}

Stock Market data, fetched from Yahoo and Google

by William Stein

{{{id=115| %hide import urllib class Day: def __init__(self, date, open, high, low, close, volume): self.date = date self.open=float(open); self.high=float(high); self.low=float(low); self.close=float(close) self.volume=int(volume) def __repr__(self): return '%10s %4.2f %4.2f %4.2f %4.2f %10d'%(self.date, self.open, self.high, self.low, self.close, self.volume) class Stock: def __init__(self, symbol): self.symbol = symbol.upper() def __repr__(self): return "%s (%s)"%(self.symbol, self.yahoo()['price']) def yahoo(self): url = 'http://finance.yahoo.com/d/quotes.csv?s=%s&f=%s' % (self.symbol, 'l1c1va2xj1b4j4dyekjm3m4rr5p5p6s7') values = urllib.urlopen(url).read().strip().strip('"').split(',') data = {} data['price'] = values[0] data['change'] = values[1] data['volume'] = values[2] data['avg_daily_volume'] = values[3] data['stock_exchange'] = values[4] data['market_cap'] = values[5] data['book_value'] = values[6] data['ebitda'] = values[7] data['dividend_per_share'] = values[8] data['dividend_yield'] = values[9] data['earnings_per_share'] = values[10] data['52_week_high'] = values[11] data['52_week_low'] = values[12] data['50day_moving_avg'] = values[13] data['200day_moving_avg'] = values[14] data['price_earnings_ratio'] = values[15] data['price_earnings_growth_ratio'] = values[16] data['price_sales_ratio'] = values[17] data['price_book_ratio'] = values[18] data['short_ratio'] = values[19] return data def historical(self): try: return self.__historical except AttributeError: pass symbol = self.symbol def get_data(exchange): name = get_remote_file('http://finance.google.com/finance/historical?q=%s:%s&output=csv'%(exchange, symbol.upper()), verbose=False) return open(name).read() R = get_data('NASDAQ') if "Bad Request" in R: R = get_data("NYSE") R = R.splitlines() headings = R[0].split(',') self.__historical = [] try: for x in reversed(R[1:]): date, opn, high, low, close, volume = x.split(',') self.__historical.append(Day(date, opn,high,low,close,volume)) except ValueError: pass self.__historical = Sequence(self.__historical,cr=True,universe=lambda x:x) return self.__historical def plot_average(self, spline_samples=10): d = self.historical() if len(d) == 0: return text('no historical data at Google Finance about %s'%self.symbol, (0,3)) avg = list(enumerate([(z.high+z.low)/2 for z in d])) P = line(avg) + points(avg, rgbcolor='black', pointsize=4) + \ text(self.symbol, (len(d)*1.05, d[-1].low), horizontal_alignment='right', rgbcolor='black') if spline_samples > 0: k = 250//spline_samples spl = spline([avg[i*k] for i in range(len(d)//k)] + [avg[-1]]) P += plot(spl, (0,len(d)+30), color=(0.7,0.7,0.7)) P.xmax(260) return P def plot_diff(self): d = self.historical() if len(d) == 0: return text('no historical data at Google Finance about %s'%self.symbol, (0,3)) diff = [] for i in range(1, len(d)): z1 = d[i]; z0 = d[i-1] diff.append((i, (z1.high+z1.low)/2 - (z0.high + z0.low)/2)) P = line(diff,thickness=0.5) + points(diff, rgbcolor='black', pointsize=4) + \ text(self.symbol, (len(d)*1.05, 0), horizontal_alignment='right', rgbcolor='black') P.xmax(260) return P symbols = ['bsc', 'vmw', 'sbux', 'aapl', 'amzn', 'goog', 'wfmi', 'msft', 'yhoo', 'ebay', 'java', 'rht', ]; symbols.sort() stocks = dict([(s,Stock(s)) for s in symbols]) @interact def data(symbol = symbols, other_symbol='', spline_samples=(8,[0..15])): if other_symbol != '': symbol = other_symbol S = Stock(symbol) html('

%s

'%S) S.plot_average(spline_samples).save('avg.png', figsize=[10,2]) S.plot_diff().save('diff.png', figsize=[10,2]) Y = S.yahoo() k = Y.keys(); k.sort() html('Price during last 52 weeks:
Grey line is a spline through %s points (do not take seriously!):
'%spline_samples) html('Difference from previous day:
') html('' + '\n'.join(''%(k[i], Y[k[i]]) for i in range(len(k))) + '
%s%s
') ///
symbol 
other_symbol 
spline_samples 
}}}

Cryptography

The Diffie-Hellman Key Exchange Protocol

by Timothy Clemans and William Stein

{{{id=167| @interact def diffie_hellman(bits=slider(8, 513, 4, 8, 'Number of bits', False), button=selector(["Show new example"],label='',buttons=True)): maxp = 2 ^ bits p = random_prime(maxp) k = GF(p) if bits > 100: g = k(2) else: g = k.multiplicative_generator() a = ZZ.random_element(10, maxp) b = ZZ.random_element(10, maxp) print """

%s-Bit Diffie-Hellman Key Exchange

  1. Alice and Bob agree to use the prime number p = %s and base g = %s.
  2. Alice chooses the secret integer a = %s, then sends Bob (ga mod p):
    %s%s mod %s = %s.
  3. Bob chooses the secret integer b=%s, then sends Alice (gb mod p):
    %s%s mod %s = %s.
  4. Alice computes (gb mod p)a mod p:
    %s%s mod %s = %s.
  5. Bob computes (ga mod p)b mod p:
    %s%s mod %s = %s.
""" % (bits, p, g, a, g, a, p, (g^a), b, g, b, p, (g^b), (g^b), a, p, (g^ b)^a, g^a, b, p, (g^a)^b) ///
Number of bits 
}}}

Dessiner une fonction $\mathbb{R}^2\mapsto \mathbb{R}$ : la commande plot3d

{{{id=58| def f(x, y): return x^2 + y^2 plot3d(f, (-10,10), (-10,10), viewer='tachyon') /// }}} {{{id=59| /// }}}

Animations

{{{id=20| a = animate([sin(x + float(k)) for k in srange(0,2*pi,0.3)], xmin=0, xmax=2*pi, figsize=[2,1]) /// }}} {{{id=19| a.show() /// }}} {{{id=34| /// }}}

 La commande complex_plot pour les fonctions $\mathbb{C}\mapsto \mathbb{C}$

{{{id=76| f(x) = x^4 - 1 /// }}} {{{id=37| complex_plot(f, (-2,2), (-2,2)) /// }}} {{{id=65| def newton(f, z, precision=0.001) : while abs(f(x=z)) >= precision: z = z - f(x=z) / diff(f)(x=z) return z /// }}} {{{id=66| complex_plot(lambda z : newton(f, z), (-1,1), (-1,1)) /// }}} {{{id=67| /// }}} {{{id=68| /// }}} {{{id=147| /// }}}

 Utilisation du Notebook : Écriture, édition et évaluation d'une saisie

Pour évaluer une saisie dans le Notebook de Sage, tapez la saisie dans une cellule et faites shift-entrée ou cliquer le lien evaluate.  Essayez-le maintenant avec une expression simple (e.g., 2 + 2).   La première évaluation d'une cellule prend plus de temps que les fois suivantes, car un processus commence.

{{{id=159| 2+3 /// 5 }}} {{{id=2| 4+5 /// 9 }}}

Créez de nouvelles cellules de saisie en cliquant sur la ligne bleue qui apparaît entre les cellules lorsque vous déplacez la souris. Essayez-le maintenant.

Vous pouvez rééditer n'importe quelle cellule en cliquant dessus (ou en utilisant les flèches du clavier). Retournez plus haut et changez votre 2 + 2 en un 3 + 3 et réévaluez la cellule.

{{{id=9| /// }}}

Vous pouvez aussi éditer ce texte-ci en double cliquant dessus ce qui fera apparaître un éditeur de texte TinyMCE Javascript. Vous pouvez même ajouter des expressions mathématiques telles que $\sin(x) - y^3$ comme avec LaTeX.

{{{id=54| /// }}}

$$\int e^x dx = e^x + c$$

{{{id=75| /// }}}

Comment consulter l'aide contextuelle et obtenir de la documentation

Vous trouvez la liste des fonctions que vous pouvez appelez sur un objet X en tappant X.<touche de tabulation>.

{{{id=33| X = 2009 /// }}}

Écrivez X. et appuyez sur la touche de tabulation.

{{{id=28| X.factor() /// 7^2 * 41 }}}

Une fois que vous avez sélectionné une fonction, disons factor, tappez X.factor(<touche de tabulation> ou X.factor?<touche de tabulation> pour obtenir de l'aide et des exemples d'utilisation de cette fonction. Essayez-le maintenant avec X.factor.

{{{id=161| 4+5 /// 9 }}} {{{id=39| /// }}}

Pour obtenir l'aide complète et un tutoriel plus exhaustif, cliquez sur le lien Help en haut à droite de cette page, et cliquer ensuite sur Fast Static Versions of the Documentation.

Résolution d'équations polynomiales

{{{id=108| a,b,c,d,X = var('a,b,c,d,X') /// }}} {{{id=25| s = solve(a*X^2 + b*X + c == 0, X) show(s) ///
\newcommand{\Bold}[1]{\mathbf{#1}}\left[X = -\frac{b + \sqrt{-4 \, a c + b^{2}}}{2 \, a}, X = -\frac{b - \sqrt{-4 \, a c + b^{2}}}{2 \, a}\right]
}}} {{{id=40| s = solve(a*X^3 + b*X^2 + c*X + d == 0, X) show(s[0]) ///
\newcommand{\Bold}[1]{\mathbf{#1}}X = -\frac{1}{2} \, {\left(i \, \sqrt{3} + 1\right)} {\left(\frac{\sqrt{27 \, a^{2} d^{2} + 4 \, a c^{3} - b^{2} c^{2} - 2 \, {\left(9 \, a b c - 2 \, b^{3}\right)} d} \sqrt{3}}{18 \, a^{2}} - \frac{27 \, a^{2} d - 9 \, a b c + 2 \, b^{3}}{54 \, a^{3}}\right)}^{\left(\frac{1}{3}\right)} - \frac{b}{3 \, a} + \frac{{\left(-i \, \sqrt{3} + 1\right)} {\left(3 \, a c - b^{2}\right)}}{18 \, {\left(\frac{\sqrt{27 \, a^{2} d^{2} + 4 \, a c^{3} - b^{2} c^{2} - 2 \, {\left(9 \, a b c - 2 \, b^{3}\right)} d} \sqrt{3}}{18 \, a^{2}} - \frac{27 \, a^{2} d - 9 \, a b c + 2 \, b^{3}}{54 \, a^{3}}\right)}^{\left(\frac{1}{3}\right)} a^{2}}
}}} {{{id=71| /// }}} {{{id=41| /// }}} {{{id=18| /// }}}

Algèbre linéaire

{{{id=38| A = matrix(3, [9,4,2,4,6,1,6,4,3,2,3,4,2,7,8,6,5,3]); A /// [9 4 2 4 6 1] [6 4 3 2 3 4] [2 7 8 6 5 3] }}} {{{id=110| show(A) ///
\newcommand{\Bold}[1]{\mathbf{#1}}\left(\begin{array}{rrrrrr} 9 & 4 & 2 & 4 & 6 & 1 \\ 6 & 4 & 3 & 2 & 3 & 4 \\ 2 & 7 & 8 & 6 & 5 & 3 \end{array}\right)
}}} {{{id=111| latex(A) /// \left(\begin{array}{rrrrrr} 9 & 4 & 2 & 4 & 6 & 1 \\ 6 & 4 & 3 & 2 & 3 & 4 \\ 2 & 7 & 8 & 6 & 5 & 3 \end{array}\right) }}} {{{id=112| r = random_matrix(ZZ, 200) r[0] /// (6, 1, -4, 1, 3, 2, 0, 4, 1, 2, 1, -2, 0, 3, 1, 5, 0, 0, 3, -4, 68, 4, -1, -29, 2, 0, 1, 2, 4, -1, 1, 0, 1, 0, -22, 0, -2, 0, -1, -1, -3, -1, 0, 1, 1, 1, -32, 1, -1, -1, 0, 5, -1, -13, 0, 2, -1, -50, -1, 0, 16, 1, 1, -5, 0, -5, -3, -1, 1, 0, 1, -6, 0, -1, 1, 1, 0, 3, 0, -2, 1, 3, 0, 2, 5, -5, 3, 0, -9, 3, -1, 5, 0, -1, -1, 3, 0, 2, 0, 1, 0, 3, -1, 0, 0, 1, 0, -1, 0, 0, -7, 1, 0, 0, -3, -1, 12, 1, 0, -74, 1, 1, 0, 1, 1164, 21, -109, -5, -2, 1, 1, 3, -30, 17, -28, 1, 1, 161, -4, 1, 10, 2, -1, -1, 4, -6, 0, 17, 0, 25, -1, -1, -1, 0, -2, -1, -1, -1, 1, -6, -1, -2, 1, 2, -1, 0, -6, 1, -3, -1, 6, 0, -3, 0, -4, -1, 1, 1, 12, -7, -1, 1, -1, -1, 1, 2, 2, -25, -2, -1, 0, -1, 2, 3, 1, -3, 12, -10, 1, 0) }}} {{{id=24| time r.determinant() /// -1529834725553757938763159502025548590567911254662803196770598603331067849864395053736435397051765374245101197807489393057663130380141963203671083430967372792929619229867512126727684265591250414807452250453734959591879530432065001775694429765051483913590921267567927871370268065203061006918276079882798699436138525602103991441803398564880661084453659955387439288542429758896771118012008221672140101768416901702596791928059352838737552772934612946211933401613477671553715592 Time: CPU 0.45 s, Wall: 0.73 s }}} {{{id=105| r.determinant? ///

File: /Users/slabbe/Applications/sage-4.6/devel/sage/sage/matrix/matrix_integer_dense.pyx

Type: <type ‘builtin_function_or_method’>

Definition: r.determinant(algorithm=’default’, proof=None, stabilize=2)

Docstring:

Return the determinant of this matrix.

INPUT:

ALGORITHM: The p-adic algorithm works by first finding a random vector v, then solving A*x = v and taking the denominator d. This gives a divisor of the determinant. Then we compute \det(A)/d using a multimodular algorithm and the Hadamard bound, skipping primes that divide d.

TIMINGS: This is perhaps the fastest implementation of determinants in the world. E.g., for a 500x500 random matrix with 32-bit entries on a core2 duo 2.6Ghz running OS X, Sage takes 4.12 seconds, whereas Magma takes 62.87 seconds (both with proof False). With proof=True on the same problem Sage takes 5.73 seconds. For another example, a 200x200 random matrix with 1-digit entries takes 4.18 seconds in pari, 0.18 in Sage with proof True, 0.11 in Sage with proof False, and 0.21 seconds in Magma with proof True and 0.18 in Magma with proof False.

EXAMPLES:

sage: A = matrix(ZZ,8,8,[3..66])
sage: A.determinant()
0
sage: A = random_matrix(ZZ,20,20)
sage: D1 = A.determinant()
sage: A._clear_cache()
sage: D2 = A.determinant(algorithm='ntl')
sage: D1 == D2
True

Next we try the Linbox det. Note that we must have proof=False.

sage: A = matrix(ZZ,5,[1,2,3,4,5,4,6,3,2,1,7,9,7,5,2,1,4,6,7,8,3,2,4,6,7])
sage: A.determinant(algorithm='linbox')
...
RuntimeError: you must pass the proof=False option to the determinant command to use LinBox's det algorithm
sage: A.determinant(algorithm='linbox',proof=False)
-21
sage: A._clear_cache()
sage: A.determinant()
-21

A bigger example:

sage: A = random_matrix(ZZ,30)
sage: d = A.determinant()
sage: A._clear_cache()
sage: A.determinant(algorithm='linbox',proof=False) == d
True
}}}

Théorie des graphes

{{{id=49| D = graphs.DodecahedralGraph() D.show() /// }}} {{{id=48| D.show3d(viewer='tachyon') /// }}} {{{id=77| D.chromatic_polynomial() /// x^20 - 30*x^19 + 435*x^18 - 4060*x^17 + 27393*x^16 - 142194*x^15 + 589875*x^14 - 2004600*x^13 + 5673571*x^12 - 13518806*x^11 + 27292965*x^10 - 46805540*x^9 + 68090965*x^8 - 83530946*x^7 + 85371335*x^6 - 71159652*x^5 + 46655060*x^4 - 22594964*x^3 + 7171160*x^2 - 1111968*x }}} {{{id=148| /// }}} {{{id=78| graph_editor(D); ///
}}} {{{id=52| D.show() /// }}}

Recherche dans l'encyclopédie de séquences en ligne de Sloane

{{{id=80| sloane_find([1,5,29,169],1) /// Searching Sloane's online database... [] }}} {{{id=81| sloane_find([1,2,3,4,5,6],1) /// Searching Sloane's online database... [] }}} {{{id=162| /// }}} {{{id=96| /// }}} {{{id=97| /// }}} {{{id=82| /// }}}

Cython

The Sage notebook allows transparently editing and compiling Cython code simply by typing %cython at the top of a cell and evaluate it. Variables and functions defined in a Cython cell are imported into the running session.

Example 1, pure Python

Here is some simple Python code to numerically integrate the function $f(x) = x^2$.

{{{id=47| /// }}} {{{id=1| from math import sin def f(x): return sin(x**2) def integrate_f_py(a, b, N): s = 0 dx = (b-a)/N for i in range(N): s += f(a+i*dx) return s * dx /// }}} {{{id=62| timeit('integrate_f_py(0, 1, 1000)', number=50) /// 50 loops, best of 3: 18.5 ms per loop }}} {{{id=7| /// }}} {{{id=63| /// }}}

Example 1, compiled with Cython (no other changes)

Simply compiling this in Cython gives a speedup.

{{{id=5| %cython from math import sin def f(x): return sin(x**2) def integrate_f_cy0(a, b, N): s = 0 dx = (b-a)/N for i in range(N): s += f(a+i*dx) return s * dx /// }}} {{{id=4| timeit('integrate_f_cy0(0, 1, 1000)', number=50) /// 50 loops, best of 3: 16.7 ms per loop }}} {{{id=8| /// }}} {{{id=69| /// }}}

Example 1, typed and compiled with Cython

Adding some static type declarations makes a much greater difference.

{{{id=10| %cython from math import sin def f(double x): return sin(x**2) def integrate_f_cy(double a, double b, int N): cdef int i cdef double s, dx s = 0 dx = (b-a)/N for i in range(N): s += f(a+i*dx) return s * dx /// }}} {{{id=72| timeit('integrate_f_cy(0, 1, 1000)') /// 625 loops, best of 3: 489 µs per loop }}} {{{id=12| 18500 /489.0 /// 37.8323108384458 }}} {{{id=17| /// }}}

Example 2, pure Python

Here is a Python function that computes the sum of the first $n$ positive integers.

{{{id=29| def mysum_py(n): s = 0 for k in range(n): s += k return s /// }}} {{{id=31| time mysum_py(10^6) /// 499999500000 Time: CPU 2.09 s, Wall: 2.16 s }}} {{{id=32| /// }}} {{{id=74| /// }}}

Example 2, just compiled with Cython

Simply compiling this function with Cython provides a speedup.

{{{id=83| %cython def mysum_cy0(n): s = 0 for k in range(n): s += k return s /// }}} {{{id=84| time mysum_cy0(10^6) /// 499999500000L Time: CPU 0.25 s, Wall: 0.27 s }}} {{{id=85| 2.09 / 0.25 /// 8.36000000000000 }}} {{{id=86| /// }}}

Example 2, typed and compiled with Cython

Adding some static type declarations makes a much greater difference.

{{{id=88| %cython def mysum_cy1(n): cdef int k cdef long long s s = 0 for k in range(n): s += k return s /// }}} {{{id=42| time mysum_cy1(10^6) /// 499999500000L Time: CPU 0.00 s, Wall: 0.00 s }}} {{{id=89| 2.09 / 0.00 /// +infinity }}} {{{id=90| timeit('mysum_cy1(10^6)') /// 125 loops, best of 3: 1.57 ms per loop }}} {{{id=91| 2.09/0.00157 /// 1331.21019108280 }}} {{{id=163| /// }}}