3. C++ et le monde extérieur



sommaire chapitre 3

3.5. Interopérabilité avec Python

3.5.1. Introduction

Même si Python se révèle être un langage intéressant pour le calcul scientifique en raison de sa syntaxe concise il n'en demeure pas moins un langage interprété et bien souvent non optimisé.

Différentes solutions existent qui consistent à améliorer les performances de Python en faisant en sorte de compiler le code et non de l'interpréter.

La compilation est soit statique, soit dynamique (JIT = Just In Time)

Rendre Python plus efficace

Considérons un exemple celui des fractales de Mandelbrot :

mandelbrot image

Benoît Mandelbrot a donné son nom à une famille de fractales (appelée ensemble de Mandelbrot), définies par la relation de récurrence :

$$z_{n+1} = z_n^2 + c$$

$c$ étant un nombre complexe quelconque. On cherche l'ensemble des nombres tels que $z_{n}$ converge.

Comparaison sur un calcul de Mandelbrot site de Greg Baker, cependant il n'indique pas les temps d'exécution, le processeur utilisé et le parallèlisme n'est pas pris en compte :

 Solution   Accélération 
 Python - CPython 2.7.6   1.0 
 Cython 0.20   1.6 
 Cython annoté 0.20   95.8 
 Jython 2.5.3   3.4 
 PyPy 2.3.1   82.8 
 Pythran 0.5.0   92.7 
 C GCC 4.8.2 -O2   96.2 
Comparaison sur ensemble de Mandelbrot 160x400 pixels sur Intel Core i5 4570 @ 3.20GHz (JM RICHER)

Voici sur la table suivante des tests personnels réalisés sur Core i5 4570 avec une grille 256 x 256 points :

 Solution   Temps (s)   Accélération (mono-thread)   Accélération (multi-thread) 
 INTERPRETEURS Python            
 python 2.7.6   440.72   1.0    - 
 python 3.4.2   421.08   1.04    - 
 iPython 1.2.1   449.17   0.98    - 
 anaconda 2.1.0 (Python 2.7.8)   496.10    0.88    - 
 jython 2.5.3   144.53   3    - 
 COMPILATION Python / JIT          
 pypy   7.47   59    - 
 cython   5.87   75    - 
 numba   6.80   65    - 
 pythran   6.08   72    - 
 pythran + OpenMP   2.64   -   167 
 COMPILATEURS C/C++           
 clang 3.5.0   6.05   73   - 
 gcc 4.8.2-19   5.87   75   - 
 gcc 4.8.2-19 + OpenMP   2.50   -   176 
 icpc 15.0.0   4.20   105   - 
 icpc 15.0.0 + OpenMP   1.83   -   240 
 CUDA C 6.5          
 GTX 770(*) v1 256x256 x 1T   6.06   -   72 
 GTX 770(*) v2 16x16 x 16x16T   0.41   -   1074 
Comparaison de méthodes de calcul avec Python sur ensemble de Mandelbrot 256x256 pixels sur Intel Core i5 4570 @ 3.20GHz

(*) Note : La carte GTX 770 possède 1536 CUDA cores :

Voir également PyCUDA très performant.

Interpréteurs Python

3.5.2. Python de base 2.7.6 / 3.4.2

Voici le code a exécuter par Python :

  1. import sys
  2. if sys.version_info >= (3, 0):
  3.     # make it "just work" in Python3
  4.     xrange = range
  5.  
  6. def escapes(cr, ci, it):
  7.     """
  8.    Does iterating z <- z^2 + c escape after it iterations?
  9.    """
  10.     zr = 0.0
  11.     zi = 0.0
  12.     for i in xrange(it):
  13.         # z <- z^2 + c
  14.         zrtmp = zr*zr - zi*zi + cr;
  15.         zr,zi = zrtmp , 2*zr*zi + ci
  16.         if zr*zr + zi*zi > 4:
  17.             return True
  18.     return False
  19.  
  20. def toChar(p):
  21.     if p:
  22.         return " "
  23.     else:
  24.         return "X"
  25.  
  26. def mandel(xmin,xmax,xstep, ymin,ymax,ystep, iterations):
  27.   for yc in xrange(ystep):
  28.       y = yc*(ymax-ymin)/ystep + ymin
  29.       row = []
  30.       for xc in xrange(xstep):
  31.           x = xc*(xmax-xmin)/xstep + xmin
  32.           row.append( escapes(x, y, iterations) )
  33.      
  34.       print("".join([toChar(p) for p in row]))
  35.      
  36. mandel(-2.0, 1.0, 256, -1.0, 1.0, 256, 100000)      
  37.  
time python mandel_python.py >mandel_python.txt

3.5.3. iPython 2.7.6

Environnement de développement Python. On utilise le même code que pour Python :

  1. import sys
  2. if sys.version_info >= (3, 0):
  3.     # make it "just work" in Python3
  4.     xrange = range
  5.  
  6. def escapes(cr, ci, it):
  7.     """
  8.    Does iterating z <- z^2 + c escape after it iterations?
  9.    """
  10.     zr = 0.0
  11.     zi = 0.0
  12.     for i in xrange(it):
  13.         # z <- z^2 + c
  14.         zrtmp = zr*zr - zi*zi + cr;
  15.         zr,zi = zrtmp , 2*zr*zi + ci
  16.         if zr*zr + zi*zi > 4:
  17.             return True
  18.     return False
  19.  
  20. def toChar(p):
  21.     if p:
  22.         return " "
  23.     else:
  24.         return "X"
  25.  
  26. def mandel(xmin,xmax,xstep, ymin,ymax,ystep, iterations):
  27.   for yc in xrange(ystep):
  28.       y = yc*(ymax-ymin)/ystep + ymin
  29.       row = []
  30.       for xc in xrange(xstep):
  31.           x = xc*(xmax-xmin)/xstep + xmin
  32.           row.append( escapes(x, y, iterations) )
  33.      
  34.       print("".join([toChar(p) for p in row]))
  35.      
  36. mandel(-2.0, 1.0, 256, -1.0, 1.0, 256, 100000)      
  37.  
time ipython mandel_python.py >mandel_ipython.txt

Compilateurs Python

3.5.4. PyPy 2.7.3

Un compilateur alternatif souvent plus rapide que le python de base : à installer en tant que paquet Ubuntu.

Voir également le site de PyPy :

time pypy main.py >result_pypy.txt 2>time_pypy.txt

3.5.5. Cython

3.5.5.a  Installer Cython

Télécharge le fichier Cython-0.21.1.tar.gz sur le site cd Cython puis le décompresser dans /opt.

Une fois dans le répertoire /opt/Cython-0.21.1 lancer la compilation :

python setup.py install

3.5.5.b  Utiliser Cython

Avec Cython on type les variables :

  1. def escapes(double cr, double ci, int it):
  2.     """
  3.    Does iterating z <- z^2 + c escape after it iterations?
  4.    """
  5.     cdef double zr = 0.0
  6.     cdef double zi = 0.0
  7.     cdef int i
  8.     for i in xrange(it):
  9.         # z <- z^2 + c
  10.         zr,zi = zr*zr - zi*zi + cr, 2*zr*zi + ci
  11.         if zr*zr + zi*zi > 4:
  12.             return True
  13.     return False
  14.  
  15. def toChar(char p):
  16.     if p:
  17.         return " "
  18.     else:
  19.         return "X"
  20.  
  21. def mandel(double xmin, double xmax, int xstep, double ymin, double ymax, int ystep, int iterations):
  22.   for yc in xrange(ystep):
  23.       y = yc*(ymax-ymin)/ystep + ymin
  24.       row = []
  25.       for xc in xrange(xstep):
  26.           x = xc*(xmax-xmin)/xstep + xmin
  27.           row.append( escapes(x, y, iterations) )
  28.      
  29.       print("".join([toChar(p) for p in row]))
  30.  

On compile avec un makefile Python :

  1. # build with:
  2. #   python setup.py build_ext --inplace
  3.  
  4. from distutils.core import setup
  5. from distutils.extension import Extension
  6. from Cython.Distutils import build_ext
  7.  
  8. ext_modules = [Extension("static", ["static.pyx"])]
  9.  
  10. setup(
  11.   name = 'Static binding app',
  12.   cmdclass = {'build_ext': build_ext},
  13.   ext_modules = ext_modules
  14. )
  15.  
  16.  

On suppose que Cython a été installé dans le répertoire /opt :

export PATH=/opt/Cython-0.21.1/bin/:\(\text"$"\)PATH
export PYTHONPATH=/opt/Cython-0.21.1/:\(\text"$"\)PYTHONPATH
python setup.py build_ext --inplace

Eventuellement, ajouter les deux lignes export dans votre .bashrc

Puis on appelle le module généré :

  1. import static;
  2. static.mandel(-2.0, 1.0, 256, -1.0, 1.0, 256, 100000)
  3.  
  4.  
time python mandel_static.py >result_cython.txt 2>time_cython.txt

3.5.6. Numba

Suivre la procédure d'installation suivante sous Ubuntu 14.04 :

sudo apt-get install llvm-3.3-dev python-pip python-dev

# install LLVM-Py:
sudo LLVM_CONFIG_PATH=/usr/bin/llvm-config-3.3 pip install llvmpy

# test 
python -c "import llvm; llvm.test()"

# install Numba with
sudo pip install numpy
sudo pip install numba

Il est nécessaire de modifier le code car la version utilisée ne supporte pas les listes et notamment l'instruction join du code de base provoque une erreur.

  1. from numba import jit
  2. from numpy import arange
  3.  
  4. import sys
  5. if sys.version_info >= (3, 0):
  6.     # make it "just work" in Python3
  7.     range = xrange
  8.  
  9. @jit
  10. def escapes(cr, ci, it):
  11.     """
  12.    Does iterating z <- z^2 + c escape after it iterations?
  13.    """
  14.     zr = 0.0
  15.     zi = 0.0
  16.     for i in xrange(it):
  17.         # z <- z^2 + c
  18.         zr,zi = zr*zr - zi*zi + cr, 2*zr*zi + ci
  19.         if zr*zr + zi*zi > 4:
  20.             return True
  21.     return False
  22.  
  23. @jit
  24. def toChar(p):
  25.     if p:
  26.         return "_"
  27.     else:
  28.         return "X"
  29.  
  30. @jit
  31. def mandel(xmin,xmax,xstep, ymin,ymax,ystep, iterations):
  32.   for yc in xrange(ystep):
  33.       y = yc*(ymax-ymin)/ystep + ymin
  34.       row = []
  35.       for xc in xrange(xstep):
  36.           x = xc*(xmax-xmin)/xstep + xmin
  37.           row.append( toChar(escapes(x, y, iterations)) )
  38.       #print("".join([toChar(p) for p in row]))
  39.       for xc in xrange(xstep):
  40.         sys.stdout.write(row[xc])
  41.       print
  42.  
  43. mandel(-2.0, 1.0, 256, -1.0, 1.0, 256, 100000)      
  44.  

3.5.7. Pythran

3.5.7.a  Installer Pythran

sudo apt-get install libboost-python-dev libgoogle-perftools-dev 
sudo apt-get install libgmp-dev libboost-dev git cmake
sudo apt-get install python-ply python-networkx python-numpy

Obtenir la clé des nouveaux packages à installer :

wget http://ridee.enstb.org/debian/pubring.gpg -O - | sudo sh -c "apt-key add -"

Ajouter les deux lignes suivantes à la fin du fichier /etc/apt/sources.list :

deb http://ridee.enstb.org/debian unstable main
deb-src http://ridee.enstb.org/debian unstable main
sudo apt-get update
sudo apt-get install pythran

3.5.7.b  Utiliser Pythran

Il faut modifier le code en ajoutant des annotations #pythran :

  1.  
  2. def escapes(cr, ci, it):
  3.     """
  4.    Does iterating z <- z^2 + c escape after it iterations?
  5.    """
  6.     zr = 0.0
  7.     zi = 0.0
  8.     for i in xrange(it):
  9.         # z <- z^2 + c
  10.         zr,zi = zr*zr - zi*zi + cr, 2*zr*zi + ci
  11.         if zr*zr + zi*zi > 4:
  12.             return True
  13.     return False
  14.  
  15. def toChar(p):
  16.     if p:
  17.         return " "
  18.     else:
  19.         return "X"
  20.  
  21. #pythran export mandel(float64, float64, int, float64, float64,int, int)
  22. def mandel(xmin,xmax,xstep, ymin,ymax,ystep, iterations):
  23.   #omp parallel for
  24.   for yc in xrange(ystep):
  25.       y = yc*(ymax-ymin)/ystep + ymin
  26.       row = []
  27.       for xc in xrange(xstep):
  28.           x = xc*(xmax-xmin)/xstep + xmin
  29.           row.append( escapes(x, y, iterations) )
  30.      
  31.       print("".join([toChar(p) for p in row]))
  32.  
  33.  

On compile (ajouter -fopenmp pour utiliser OpenMP) :

pythran mandel_pythran_openmp.py -fopenmp -O 3 

Appel :

  1. import mandel_pythran_openmp;
  2. mandel_pythran_openmp.mandel(-2.0, 1.0, 256, -1.0, 1.0, 256, 100000)
  3.  
  4.  

Test de performance :

time python mandel_pythran_openmp_static.py >result_pythran_openmp.txt 2>time_pythran_openmp.txt 


Compilateurs C/C++

On utilise le même code pour les 3 compilateurs. J'ai modifié le code par rapport à la version Python de manière à stocker les données à afficher dans un tableau.

  1. #include <stdio.h>
  2.  
  3. double xmin = -2;
  4. double xmax = 1;
  5. int xstep = 256;
  6. double ymin = -1;
  7. double ymax = 1;
  8. int ystep = 256;
  9. int iters = 100000;
  10.  
  11. int escapes(double cr, double ci, int it) {
  12.   double zr = 0;
  13.   double zi = 0;
  14.   double zrtmp;
  15.   int i;
  16.  
  17.   for(i=0; i<it; i++) {
  18.     // z <- z^2 + c
  19.     zrtmp = zr*zr - zi*zi + cr;
  20.     zi = 2*zr*zi + ci;
  21.     zr = zrtmp;
  22.     if (zr*zr + zi*zi > 4) {
  23.       return 1;
  24.     }
  25.   }
  26.   return 0;
  27. }
  28.  
  29. // ----------------------------------------------
  30. // main function
  31. // ----------------------------------------------
  32. int main() {
  33.   int xc, yc;
  34.   double x, y;
  35.  
  36.   // array of string to store result
  37.   char m[256][257];
  38.  
  39.   for(yc=0; yc<ystep; yc++) {
  40.     y = yc*(ymax-ymin)/ystep + ymin;
  41.     for(xc=0; xc<xstep; xc++) {
  42.       x = xc*(xmax-xmin)/xstep + xmin;
  43.       escapes(x, y, iters);
  44.       if (escapes(x, y, iters)) {
  45.         m[yc][xc] = ' ';
  46.       } else {
  47.         m[yc][xc] = 'X';  
  48.       }
  49.     }
  50.     // add end of string
  51.     m[yc][xc] = '\0';  
  52.    
  53.   }
  54.  
  55.   for(yc=0; yc<ystep; yc++) {
  56.       printf("%s\n", m[yc]);
  57.   }
  58.   return 0;
  59. }
  60.  

Version OpenMP :

  1. #include <stdio.h>
  2.  
  3. double xmin = -2;
  4. double xmax = 1;
  5. int xstep = 256;
  6. double ymin = -1;
  7. double ymax = 1;
  8. int ystep = 256;
  9. int iters = 100000;
  10.  
  11. int escapes(double cr, double ci, int it) {
  12.   double zr = 0;
  13.   double zi = 0;
  14.   double zrtmp;
  15.   int i;
  16.  
  17.   for(i=0; i<it; i++) {
  18.     // z <- z^2 + c
  19.     zrtmp = zr*zr - zi*zi + cr;
  20.     zi = 2*zr*zi + ci;
  21.     zr = zrtmp;
  22.     if (zr*zr + zi*zi > 4) {
  23.       return 1;
  24.     }
  25.   }
  26.   return 0;
  27. }
  28.  
  29. // ----------------------------------------------
  30. // main function
  31. // ----------------------------------------------
  32. int main() {
  33.   int xc, yc;
  34.   double x, y;
  35.  
  36.   // array of string to store result
  37.   char m[256][257];
  38.  
  39.   #pragma omp parallel for private (xc, x, y)
  40.   for(yc=0; yc<ystep; yc++) {
  41.     y = yc*(ymax-ymin)/ystep + ymin;
  42.     for(xc=0; xc<xstep; xc++) {
  43.       x = xc*(xmax-xmin)/xstep + xmin;
  44.       escapes(x, y, iters);
  45.       if (escapes(x, y, iters)) {
  46.         m[yc][xc] = ' ';
  47.       } else {
  48.         m[yc][xc] = 'X';  
  49.       }
  50.     }
  51.     // add end of string
  52.     m[yc][xc] = '\0';  
  53.    
  54.   }
  55.  
  56.   #pragma omp barrier
  57.   for(yc=0; yc<ystep; yc++) {
  58.       printf("%s\n", m[yc]);
  59.   }
  60.   return 0;
  61. }
  62.  

3.5.8. CLang / LLVM

J'ai rencontré des difficultés à compiler avec CLANG et OpenMP, de plus l'exécutable OpenMP crashe.

clang -o mandel_clang.exe mandel_c.c -O3

3.5.9. GNU GCC

Utilisation de la vectorisation et notamment des instructions AVX2.

gcc -o mandel_gcc.exe mandel_c.c -O3 -mavx2 -fopenmp

3.5.10. Intel ICPC

icpc -o mandel_icpc.exe mandel_c.c -O3 -xCORE-AVX2 -unroll8 -funroll-loops -openmp

On peut utiliser l'optimisation dirigée par le profil (Profile-guided optimization - PGO) grâce aux options -prof-gen, puis -prof-use ce qui permet d'améliorer l'efficacité.



Solution CUDA : GPU Computing

3.5.11. codage C

Voici le code CUDA correspondant à l'implantation de mandel_c.c :

  1. #include <iostream>
  2. #include <cuda.h>
  3. #include <stdio.h>
  4. using namespace std;
  5.  
  6. #define CUDA_CHECK(value) {     \
  7.     cudaError_t cu_err = value; \
  8.     if (cu_err != cudaSuccess) { \
  9.         cerr <<  "Error " << cudaGetErrorString(cu_err) << " at line "; \
  10.         cerr << __LINE__ << " in file " << __FILE__<< endl; \
  11.         exit(1); \
  12.         } \
  13.     }
  14.        
  15. double xmin = -2;
  16. double xmax = 1;
  17. int xstep = 256;
  18. double ymin = -1;
  19. double ymax = 1;
  20. int ystep = 256;
  21. const int iters = 100000;
  22.  
  23. // -----------------------------------------------------
  24. // function executed on device
  25. // -----------------------------------------------------
  26. __device__ int escapes(double cr, double ci, int it) {
  27.   double zr = 0;
  28.   double zi = 0;
  29.   double zrtmp;
  30.   int i;
  31.  
  32.   for(i=0; i<it; i++) {
  33.     // z <- z^2 + c
  34.     zrtmp = zr*zr - zi*zi + cr;
  35.     zi = 2*zr*zi + ci;
  36.     zr = zrtmp;
  37.     if (zr*zr + zi*zi > 4) {
  38.       return 1;
  39.     }
  40.   }
  41.   return 0;
  42. }
  43.  
  44. // -----------------------------------------------------
  45. // non optimized kernel for grid / block
  46. // -----------------------------------------------------
  47. __global__ void kernel_1(char *m, const double ymin, const double ymax,
  48.     const double xmin, const double xmax, const int ystep, const int xstep) {
  49.     int xc = blockIdx.x;
  50.     int yc = blockIdx.y;
  51.    
  52.     double y = yc*(ymax-ymin) / ystep + ymin;
  53.     double x = xc*(xmax-xmin) / xstep + xmin;
  54.     if (escapes(x, y, iters)) {
  55.         m[yc*xstep+xc] = ' ';
  56.     } else {
  57.         m[yc*xstep+xc] = 'X';
  58.     }  
  59. }
  60.  
  61. // -----------------------------------------------------
  62. // optimized kernel for grid / block
  63. // -----------------------------------------------------
  64. __global__ void kernel_2(char *m, const double ymin, const double ymax,
  65.     const double xmin, const double xmax, const int ystep, const int xstep) {
  66.     int xc = blockIdx.x * blockDim.x + threadIdx.x;
  67.     int yc = blockIdx.y * blockDim.y + threadIdx.y;
  68.     int offset = xc + yc * gridDim.x * blockDim.x;
  69.    
  70.     double y = yc*(ymax-ymin) / ystep + ymin;
  71.     double x = xc*(xmax-xmin) / xstep + xmin;
  72.     if (escapes(x, y, iters)) {
  73.         m[offset] = ' ';
  74.     } else {
  75.         m[offset] = 'X';
  76.     }  
  77. }
  78.  
  79. int kernel = 1;
  80.  
  81. // -----------------------------------------------------
  82. // main function
  83. // -----------------------------------------------------
  84. int main(int argc, char *argv[]) {
  85.     size_t size = 256 * 256;
  86.     size_t size_in_bytes = size * sizeof(char);
  87.    
  88.     // allocate matrix on CPU as AD-array
  89.     char *h_m = new char [size];
  90.  
  91.     if (argc > 1) {
  92.         kernel  = atoi(argv[1]);
  93.     }
  94.    
  95.     // allocate matrix on GPU as 1D-array
  96.     char *d_m;
  97.     CUDA_CHECK(cudaMalloc(&d_m, size_in_bytes));
  98.    
  99.     if (kernel == 1) {
  100.         dim3 grid(xstep, ystep);
  101.         dim3 block(1);
  102.         kernel_1<<<grid,block>>>(d_m, ymin, ymax, xmin, xmax, ystep, xstep);
  103.     } else {
  104.         dim3 grid(xstep/16, ystep/16);
  105.         dim3 block(16,16);
  106.         kernel_2<<<grid,block>>>(d_m, ymin, ymax, xmin, xmax, ystep, xstep);
  107.     }  
  108.     cudaError_t _m_cudaStat = cudaGetLastError();                                      
  109.     if (_m_cudaStat != cudaSuccess) {
  110.         cerr << "error " << cudaGetLastError() << endl;
  111.     }
  112.      
  113.     // copy result from GPU to CPU
  114.     CUDA_CHECK(cudaMemcpy(h_m, d_m, size_in_bytes, cudaMemcpyDeviceToHost));  
  115.     for (int i=0; i<ystep; ++i) {
  116.         for (int j=0; j<xstep; ++j) {
  117.             printf("%c", h_m[i*xstep+j]);
  118.         }
  119.         printf("\n");
  120.     }
  121.    
  122.     delete [] h_m;
  123.     cudaFree(d_m);
  124.    
  125.     return 0;
  126. }
  127.  

A compiler avec :

nvcc -o mandel_cu.exe mandel_c.cu -O2 -arch sm_30

3.5.12. Codage Python + PyCUDA

mandelbrot image

Voici un example tiré de PyCUDA qui propose de réaliser les calculs de quatre manières différentes :

  1. # Mandelbrot calculate using GPU, Serial numpy and faster numpy
  2. # Use to show the speed difference between CPU and GPU calculations
  3. # ian@ianozsvald.com July 2010
  4.  
  5. # Based on vegaseat's TKinter/numpy example code from 2006
  6. # http://www.daniweb.com/code/snippet216851.html#
  7. # with minor changes to move to numpy from the obsolete Numeric
  8.  
  9. import sys
  10. import numpy as nm
  11.  
  12. import Tkinter as tk
  13. import Image          # PIL
  14. import ImageTk        # PIL
  15.  
  16. import pycuda.driver as drv
  17. import pycuda.tools
  18. import pycuda.autoinit
  19. from pycuda.compiler import SourceModule
  20. import pycuda.gpuarray as gpuarray
  21.  
  22. # set width and height of window, more pixels take longer to calculate
  23. w = 1000
  24. h = 1000
  25.  
  26. from pycuda.elementwise import ElementwiseKernel
  27. complex_gpu = ElementwiseKernel(
  28.         "pycuda::complex<float> *z, pycuda::complex<float> *q, int *iteration, int maxiter",
  29.             "for (int n=0; n < maxiter; n++) {z[i] = (z[i]*z[i])+q[i]; if (abs(z[i]) > 2.0f) {iteration[i]=n; z[i] = pycuda::complex<float>(); q[i] = pycuda::complex<float>();};}",
  30.         "complex5",
  31.         preamble="#include <pycuda-complex.hpp>",)
  32.  
  33. def calculate_z_gpu(q, maxiter, z):
  34.     output = nm.resize(nm.array(0,), q.shape)
  35.     q_gpu = gpuarray.to_gpu(q.astype(nm.complex64))
  36.     z_gpu = gpuarray.to_gpu(z.astype(nm.complex64))
  37.     iterations_gpu = gpuarray.to_gpu(output)
  38.     # the for loop and complex calculations are all done on the GPU
  39.     # we bring the iterations_gpu array back to determine pixel colours later
  40.     complex_gpu(z_gpu, q_gpu, iterations_gpu, maxiter)
  41.  
  42.     iterations = iterations_gpu.get()
  43.     return iterations
  44.  
  45.  
  46. def calculate_z_numpy_gpu(q, maxiter, z):
  47.     """Calculate z using numpy on the GPU via gpuarray"""
  48.     outputg = gpuarray.to_gpu(nm.resize(nm.array(0,), q.shape).astype(nm.int32))
  49.     zg = gpuarray.to_gpu(z.astype(nm.complex64))
  50.     qg = gpuarray.to_gpu(q.astype(nm.complex64))
  51.     # 2.0 as an array
  52.     twosg = gpuarray.to_gpu(nm.array([2.0]*zg.size).astype(nm.float32))
  53.     # 0+0j as an array
  54.     cmplx0sg = gpuarray.to_gpu(nm.array([0+0j]*zg.size).astype(nm.complex64))
  55.     # for abs_zg > twosg result
  56.     comparison_result = gpuarray.to_gpu(nm.array([False]*zg.size).astype(nm.bool))
  57.     # we'll add 1 to iterg after each iteration
  58.     iterg = gpuarray.to_gpu(nm.array([0]*zg.size).astype(nm.int32))
  59.  
  60.     for iter in range(maxiter):
  61.         zg = zg*zg + qg
  62.  
  63.         # abs returns a complex (rather than a float) from the complex
  64.         # input where the real component is the absolute value (which
  65.         # looks like a bug) so I take the .real after abs()
  66.         abs_zg = abs(zg).real
  67.  
  68.         comparison_result = abs_zg > twosg
  69.         qg = gpuarray.if_positive(comparison_result, cmplx0sg, qg)
  70.         zg = gpuarray.if_positive(comparison_result, cmplx0sg, zg)
  71.         outputg = gpuarray.if_positive(comparison_result, iterg, outputg)
  72.         iterg = iterg + 1
  73.     output = outputg.get()
  74.     return output
  75.  
  76.  
  77. def calculate_z_numpy(q, maxiter, z):
  78.     # calculate z using numpy, this is the original
  79.     # routine from vegaseat's URL
  80.     # NOTE this routine was faster using a default of double-precision complex nbrs
  81.     # rather than the current single precision
  82.     output = nm.resize(nm.array(0,), q.shape).astype(nm.int32)
  83.     for iter in range(maxiter):
  84.         z = z*z + q
  85.         done = nm.greater(abs(z), 2.0)
  86.         q = nm.where(done,0+0j, q)
  87.         z = nm.where(done,0+0j, z)
  88.         output = nm.where(done, iter, output)
  89.     return output
  90.  
  91. def calculate_z_serial(q, maxiter, z):
  92.     # calculate z using pure python with numpy arrays
  93.     # this routine unrolls calculate_z_numpy as an intermediate
  94.     # step to the creation of calculate_z_gpu
  95.     # it runs slower than calculate_z_numpy
  96.     output = nm.resize(nm.array(0,), q.shape).astype(nm.int32)
  97.     for i in range(len(q)):
  98.         if i % 100 == 0:
  99.             # print out some progress info since it is so slow...
  100.             print "%0.2f%% complete" % (1.0/len(q) * i * 100)
  101.         for iter in range(maxiter):
  102.             z[i] = z[i]*z[i] + q[i]
  103.             if abs(z[i]) > 2.0:
  104.                 q[i] = 0+0j
  105.                 z[i] = 0+0j
  106.                 output[i] = iter
  107.     return output
  108.  
  109.  
  110. show_instructions = False
  111. if len(sys.argv) == 1:
  112.     show_instructions = True
  113.  
  114. if len(sys.argv) > 1:
  115.     if sys.argv[1] not in ['gpu', 'gpuarray', 'numpy', 'python']:
  116.         show_instructions = True
  117.  
  118. if show_instructions:
  119.     print "Usage: python mandelbrot.py [gpu|gpuarray|numpy|python]"
  120.     print "Where:"
  121.     print " gpu is a pure CUDA solution on the GPU"
  122.     print " gpuarray uses a numpy-like CUDA wrapper in Python on the GPU"
  123.     print " numpy is a pure Numpy (C-based) solution on the CPU"
  124.     print " python is a pure Python solution on the CPU with numpy arrays"
  125.     sys.exit(0)
  126.  
  127. routine = {'gpuarray':calculate_z_numpy_gpu,
  128.             'gpu':calculate_z_gpu,
  129.             'numpy':calculate_z_numpy,
  130.             'python':calculate_z_serial}
  131.  
  132. calculate_z = routine[sys.argv[1]]
  133. ##if sys.argv[1] == 'python':
  134. #    import psyco
  135. #    psyco.full()
  136.  
  137. # Using a WinXP Intel Core2 Duo 2.66GHz CPU (1 CPU used)
  138. # with a 9800GT GPU I get the following timings (smaller is better).
  139. # With 200x200 problem with max iterations set at 300:
  140. # calculate_z_gpu: 0.03s
  141. # calculate_z_serial: 8.7s
  142. # calculate_z_numpy: 0.3s
  143. #
  144. # Using WinXP Intel 2.9GHz CPU (1 CPU used)
  145. # with a GTX 480 GPU I get the following using 1000x1000 plot with 1000 max iterations:
  146. # gpu: 0.07s
  147. # gpuarray: 3.4s
  148. # numpy: 43.4s
  149. # python (serial): 1605.6s
  150.  
  151. class Mandelbrot(object):
  152.     def __init__(self):
  153.         # create window
  154.         self.root = tk.Tk()
  155.         self.root.title("Mandelbrot Set")
  156.         self.create_image()
  157.         self.create_label()
  158.         # start event loop
  159.         self.root.mainloop()
  160.  
  161.  
  162.     def draw(self, x1, x2, y1, y2, maxiter=300):
  163.         # draw the Mandelbrot set, from numpy example
  164.         xx = nm.arange(x1, x2, (x2-x1)/w*2)
  165.         yy = nm.arange(y2, y1, (y1-y2)/h*2) * 1j
  166.         # force yy, q and z to use 32 bit floats rather than
  167.         # the default 64 doubles for nm.complex for consistency with CUDA
  168.         yy = yy.astype(nm.complex64)
  169.         q = nm.ravel(xx+yy[:, nm.newaxis]).astype(nm.complex64)
  170.         z = nm.zeros(q.shape, nm.complex64)
  171.  
  172.         start_main = drv.Event()
  173.         end_main  = drv.Event()
  174.         start_main.record()
  175.         output = calculate_z(q, maxiter, z)
  176.  
  177.         end_main.record()
  178.         end_main.synchronize()
  179.         secs = start_main.time_till(end_main)*1e-3
  180.         print "Main took", secs
  181.  
  182.         output = (output + (256*output) + (256**2)*output) * 8
  183.         # convert output to a string
  184.         self.mandel = output.tostring()
  185.  
  186.     def create_image(self):
  187.         """"
  188.         create the image from the draw() string
  189.         """
  190.        self.im = Image.new("RGB", (w/2, h/2))
  191.        # you can experiment with these x and y ranges
  192.        self.draw(-2.13, 0.77, -1.3, 1.3, 1000)
  193.        self.im.fromstring(self.mandel, "raw", "RGBX", 0, -1)
  194.  
  195.    def create_label(self):
  196.        # put the image on a label widget
  197.        self.image = ImageTk.PhotoImage(self.im)
  198.        self.label = tk.Label(self.root, image=self.image)
  199.        self.label.pack()
  200.  
  201. # test the class
  202. if __name__ == '__main__':
  203.    test = Mandelbrot()
  204.  
 Solution   Temps (s) 
 gpu   0.20 
 gpuarray   13.40 
 numpy   3.04 
 python   347.22 
Temps de calcul Mandelbrot 1000x1000 100000 itérations

Installation

Il existe un module PyCUDA que j'ai compilé et installé sous Ubuntu 14.04 / CUDA 6.5 / Python 2.7.6 mais qui dans un premier temps ne fonctionnait pas avec la configuration de ma machine.

J'ai donc du installé dans l'ordre suivant les modules :

  • tk-dev (package Ubuntu à installer en premier pour le support Tkinter)
  • Python 2.7.9 (serveur Python.org)
  • les modules : appdirs-1.4.0, decorator-3.4.0, py-1.4.6, pytest-2.6.4, six-1.8.0, scimath-4.1.2, traits-4.5.0, numpy, pycuda
  • PIL 1.1.7

Le tout m'a pris 4h afin de trouver la solution adéquat et faire les tests.

Concernant PIL 1.1.7 avant de compiler, il faut installer les packages Ubuntu:

libjpeg62-dev zlib1g-dev libfreetype6-dev liblcms1-dev emscripten

modifuer le fichier setup.py comme suit :

TCL_ROOT = ("/usr/lib/x86_64-linux-gnu", "/usr/include/tcl8.6/")
JPEG_ROOT = None
ZLIB_ROOT = None
TIFF_ROOT = None
FREETYPE_ROOT = ("/usr/lib/x86_64-linux-gnu","/usr/share/emscripten/tests/freetype/include/")
LCMS_ROOT = None

puis compiler et installer avec les commandes :

python setup.py build_ext -i
python selftest.py 
python setup.py install


Inclure du code Python dans un programme C/C++ avec Cython

>On veut utiliser du code Python à l'intérieur d'un programme C/C++, pour celà on va convertir le code Python en C :

Programme principal en C/C++ :

  1. #include <Python.h>
  2. // inclure ce fichier une fois la compilation cython effectuée
  3. #include "my_prog_cython.h"
  4.  
  5. int main (int argc, char ** argv) {
  6.     Py_SetProgramName (argv [0]);
  7.     Py_Initialize ();
  8.    
  9.     // partie du code à insérer
  10.     initmy_prog_cython();
  11.     cythonFunction(30);
  12.  
  13.     Py_Finalize ();
  14.     return 0;
  15. }
  16.  

Code Python à incorporer, on utilise les annotations Cython :

  1. cdef public void cythonFunction (int n):
  2.     print "=" * n
  3.     print "inside cython function!!!"
  4.     print "=" * n
  5.  
  6.  

On compile le code Python en C :

cython my_prog_cython.pyx

Deux fichiers sont générés :

  1. #ifndef __PYX_HAVE__my_prog_cython
  2. #define __PYX_HAVE__my_prog_cython
  3.  
  4.  
  5. #ifndef __PYX_HAVE_API__my_prog_cython
  6.  
  7. #ifndef __PYX_EXTERN_C
  8.   #ifdef __cplusplus
  9.     #define __PYX_EXTERN_C extern "C"
  10.   #else
  11.     #define __PYX_EXTERN_C extern
  12.   #endif
  13. #endif
  14.  
  15. __PYX_EXTERN_C DL_IMPORT(void) cythonFunction(int);
  16.  
  17. #endif /* !__PYX_HAVE_API__my_prog_cython */
  18.  
  19. #if PY_MAJOR_VERSION < 3
  20. PyMODINIT_FUNC initmy_prog_cython(void);
  21. #else
  22. PyMODINIT_FUNC PyInit_my_prog_cython(void);
  23. #endif
  24.  
  25. #endif /* !__PYX_HAVE__my_prog_cython */
  26.  
  1. /* Generated by Cython 0.21.1 */
  2.  
  3. #define PY_SSIZE_T_CLEAN
  4. #ifndef CYTHON_USE_PYLONG_INTERNALS
  5. #ifdef PYLONG_BITS_IN_DIGIT
  6. #define CYTHON_USE_PYLONG_INTERNALS 0
  7. #else
  8. #include "pyconfig.h"
  9. #ifdef PYLONG_BITS_IN_DIGIT
  10. #define CYTHON_USE_PYLONG_INTERNALS 1
  11. #else
  12. #define CYTHON_USE_PYLONG_INTERNALS 0
  13. #endif
  14. #endif
  15. #endif
  16. #include "Python.h"
  17. #ifndef Py_PYTHON_H
  18.     #error Python headers needed to compile C extensions, please install development version of Python.
  19. #elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03020000)
  20.     #error Cython requires Python 2.6+ or Python 3.2+.
  21. #else
  22. #define CYTHON_ABI "0_21_1"
  23. #include <stddef.h>
  24. #ifndef offsetof
  25. #define offsetof(type, member) ( (size_t) & ((type*)0) -> member )
  26. #endif
  27. #if !defined(WIN32) && !defined(MS_WINDOWS)
  28.   #ifndef __stdcall
  29.     #define __stdcall
  30.   #endif
  31.   #ifndef __cdecl
  32.     #define __cdecl
  33.   #endif
  34.   #ifndef __fastcall
  35.     #define __fastcall
  36.   #endif
  37. #endif
  38. #ifndef DL_IMPORT
  39.   #define DL_IMPORT(t) t
  40. #endif
  41. #ifndef DL_EXPORT
  42.   #define DL_EXPORT(t) t
  43. #endif
  44. #ifndef PY_LONG_LONG
  45.   #define PY_LONG_LONG LONG_LONG
  46. #endif
  47. #ifndef Py_HUGE_VAL
  48.   #define Py_HUGE_VAL HUGE_VAL
  49. #endif
  50. #ifdef PYPY_VERSION
  51. #define CYTHON_COMPILING_IN_PYPY 1
  52. #define CYTHON_COMPILING_IN_CPYTHON 0
  53. #else
  54. #define CYTHON_COMPILING_IN_PYPY 0
  55. #define CYTHON_COMPILING_IN_CPYTHON 1
  56. #endif
  57. #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x02070600
  58. #define Py_OptimizeFlag 0
  59. #endif
  60. #define __PYX_BUILD_PY_SSIZE_T "n"
  61. #define CYTHON_FORMAT_SSIZE_T "z"
  62. #if PY_MAJOR_VERSION < 3
  63.   #define __Pyx_BUILTIN_MODULE_NAME "__builtin__"
  64.   #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) \
  65.           PyCode_New(a+k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
  66.   #define __Pyx_DefaultClassType PyClass_Type
  67. #else
  68.   #define __Pyx_BUILTIN_MODULE_NAME "builtins"
  69.   #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) \
  70.           PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
  71.   #define __Pyx_DefaultClassType PyType_Type
  72. #endif
  73. #if PY_MAJOR_VERSION >= 3
  74.   #define Py_TPFLAGS_CHECKTYPES 0
  75.   #define Py_TPFLAGS_HAVE_INDEX 0
  76.   #define Py_TPFLAGS_HAVE_NEWBUFFER 0
  77. #endif
  78. #if PY_VERSION_HEX < 0x030400a1 && !defined(Py_TPFLAGS_HAVE_FINALIZE)
  79.   #define Py_TPFLAGS_HAVE_FINALIZE 0
  80. #endif
  81. #if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_KIND)
  82.   #define CYTHON_PEP393_ENABLED 1
  83.   #define __Pyx_PyUnicode_READY(op)       (likely(PyUnicode_IS_READY(op)) ? \
  84.                                               0 : _PyUnicode_Ready((PyObject *)(op)))
  85.   #define __Pyx_PyUnicode_GET_LENGTH(u)   PyUnicode_GET_LENGTH(u)
  86.   #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i)
  87.   #define __Pyx_PyUnicode_KIND(u)         PyUnicode_KIND(u)
  88.   #define __Pyx_PyUnicode_DATA(u)         PyUnicode_DATA(u)
  89.   #define __Pyx_PyUnicode_READ(k, d, i)   PyUnicode_READ(k, d, i)
  90. #else
  91.   #define CYTHON_PEP393_ENABLED 0
  92.   #define __Pyx_PyUnicode_READY(op)       (0)
  93.   #define __Pyx_PyUnicode_GET_LENGTH(u)   PyUnicode_GET_SIZE(u)
  94.   #define __Pyx_PyUnicode_READ_CHAR(u, i) ((Py_UCS4)(PyUnicode_AS_UNICODE(u)[i]))
  95.   #define __Pyx_PyUnicode_KIND(u)         (sizeof(Py_UNICODE))
  96.   #define __Pyx_PyUnicode_DATA(u)         ((void*)PyUnicode_AS_UNICODE(u))
  97.   #define __Pyx_PyUnicode_READ(k, d, i)   ((void)(k), (Py_UCS4)(((Py_UNICODE*)d)[i]))
  98. #endif
  99. #if CYTHON_COMPILING_IN_PYPY
  100.   #define __Pyx_PyUnicode_Concat(a, b)      PyNumber_Add(a, b)
  101.   #define __Pyx_PyUnicode_ConcatSafe(a, b)  PyNumber_Add(a, b)
  102.   #define __Pyx_PyFrozenSet_Size(s)         PyObject_Size(s)
  103. #else
  104.   #define __Pyx_PyUnicode_Concat(a, b)      PyUnicode_Concat(a, b)
  105.   #define __Pyx_PyUnicode_ConcatSafe(a, b)  ((unlikely((a) == Py_None) || unlikely((b) == Py_None)) ? \
  106.       PyNumber_Add(a, b) : __Pyx_PyUnicode_Concat(a, b))
  107.   #define __Pyx_PyFrozenSet_Size(s)         PySet_Size(s)
  108. #endif
  109. #define __Pyx_PyString_FormatSafe(a, b)   ((unlikely((a) == Py_None)) ? PyNumber_Remainder(a, b) : __Pyx_PyString_Format(a, b))
  110. #define __Pyx_PyUnicode_FormatSafe(a, b)  ((unlikely((a) == Py_None)) ? PyNumber_Remainder(a, b) : PyUnicode_Format(a, b))
  111. #if PY_MAJOR_VERSION >= 3
  112.   #define __Pyx_PyString_Format(a, b)  PyUnicode_Format(a, b)
  113. #else
  114.   #define __Pyx_PyString_Format(a, b)  PyString_Format(a, b)
  115. #endif
  116. #if PY_MAJOR_VERSION >= 3
  117.   #define PyBaseString_Type            PyUnicode_Type
  118.   #define PyStringObject               PyUnicodeObject
  119.   #define PyString_Type                PyUnicode_Type
  120.   #define PyString_Check               PyUnicode_Check
  121.   #define PyString_CheckExact          PyUnicode_CheckExact
  122. #endif
  123. #if PY_MAJOR_VERSION >= 3
  124.   #define __Pyx_PyBaseString_Check(obj) PyUnicode_Check(obj)
  125.   #define __Pyx_PyBaseString_CheckExact(obj) PyUnicode_CheckExact(obj)
  126. #else
  127.   #define __Pyx_PyBaseString_Check(obj) (PyString_Check(obj) || PyUnicode_Check(obj))
  128.   #define __Pyx_PyBaseString_CheckExact(obj) (PyString_CheckExact(obj) || PyUnicode_CheckExact(obj))
  129. #endif
  130. #ifndef PySet_CheckExact
  131.   #define PySet_CheckExact(obj)        (Py_TYPE(obj) == &PySet_Type)
  132. #endif
  133. #define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type)
  134. #if PY_MAJOR_VERSION >= 3
  135.   #define PyIntObject                  PyLongObject
  136.   #define PyInt_Type                   PyLong_Type
  137.   #define PyInt_Check(op)              PyLong_Check(op)
  138.   #define PyInt_CheckExact(op)         PyLong_CheckExact(op)
  139.   #define PyInt_FromString             PyLong_FromString
  140.   #define PyInt_FromUnicode            PyLong_FromUnicode
  141.   #define PyInt_FromLong               PyLong_FromLong
  142.   #define PyInt_FromSize_t             PyLong_FromSize_t
  143.   #define PyInt_FromSsize_t            PyLong_FromSsize_t
  144.   #define PyInt_AsLong                 PyLong_AsLong
  145.   #define PyInt_AS_LONG                PyLong_AS_LONG
  146.   #define PyInt_AsSsize_t              PyLong_AsSsize_t
  147.   #define PyInt_AsUnsignedLongMask     PyLong_AsUnsignedLongMask
  148.   #define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask
  149.   #define PyNumber_Int                 PyNumber_Long
  150. #endif
  151. #if PY_MAJOR_VERSION >= 3
  152.   #define PyBoolObject                 PyLongObject
  153. #endif
  154. #if PY_MAJOR_VERSION >= 3 && CYTHON_COMPILING_IN_PYPY
  155.   #ifndef PyUnicode_InternFromString
  156.     #define PyUnicode_InternFromString(s) PyUnicode_FromString(s)
  157.   #endif
  158. #endif
  159. #if PY_VERSION_HEX < 0x030200A4
  160.   typedef long Py_hash_t;
  161.   #define __Pyx_PyInt_FromHash_t PyInt_FromLong
  162.   #define __Pyx_PyInt_AsHash_t   PyInt_AsLong
  163. #else
  164.   #define __Pyx_PyInt_FromHash_t PyInt_FromSsize_t
  165.   #define __Pyx_PyInt_AsHash_t   PyInt_AsSsize_t
  166. #endif
  167. #if PY_MAJOR_VERSION >= 3
  168.   #define __Pyx_PyMethod_New(func, self, klass) ((self) ? PyMethod_New(func, self) : PyInstanceMethod_New(func))
  169. #else
  170.   #define __Pyx_PyMethod_New(func, self, klass) PyMethod_New(func, self, klass)
  171. #endif
  172. #ifndef CYTHON_INLINE
  173.   #if defined(__GNUC__)
  174.     #define CYTHON_INLINE __inline__
  175.   #elif defined(_MSC_VER)
  176.     #define CYTHON_INLINE __inline
  177.   #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
  178.     #define CYTHON_INLINE inline
  179.   #else
  180.     #define CYTHON_INLINE
  181.   #endif
  182. #endif
  183. #ifndef CYTHON_RESTRICT
  184.   #if defined(__GNUC__)
  185.     #define CYTHON_RESTRICT __restrict__
  186.   #elif defined(_MSC_VER) && _MSC_VER >= 1400
  187.     #define CYTHON_RESTRICT __restrict
  188.   #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
  189.     #define CYTHON_RESTRICT restrict
  190.   #else
  191.     #define CYTHON_RESTRICT
  192.   #endif
  193. #endif
  194. #ifdef NAN
  195. #define __PYX_NAN() ((float) NAN)
  196. #else
  197. static CYTHON_INLINE float __PYX_NAN() {
  198.   /* Initialize NaN. The sign is irrelevant, an exponent with all bits 1 and
  199.    a nonzero mantissa means NaN. If the first bit in the mantissa is 1, it is
  200.    a quiet NaN. */
  201.   float value;
  202.   memset(&value, 0xFF, sizeof(value));
  203.   return value;
  204. }
  205. #endif
  206. #ifdef __cplusplus
  207. template<typename T>
  208. void __Pyx_call_destructor(T* x) {
  209.     x->~T();
  210. }
  211. #endif
  212.  
  213.  
  214. #if PY_MAJOR_VERSION >= 3
  215.   #define __Pyx_PyNumber_Divide(x,y)         PyNumber_TrueDivide(x,y)
  216.   #define __Pyx_PyNumber_InPlaceDivide(x,y)  PyNumber_InPlaceTrueDivide(x,y)
  217. #else
  218.   #define __Pyx_PyNumber_Divide(x,y)         PyNumber_Divide(x,y)
  219.   #define __Pyx_PyNumber_InPlaceDivide(x,y)  PyNumber_InPlaceDivide(x,y)
  220. #endif
  221.  
  222. #ifndef __PYX_EXTERN_C
  223.   #ifdef __cplusplus
  224.     #define __PYX_EXTERN_C extern "C"
  225.   #else
  226.     #define __PYX_EXTERN_C extern
  227.   #endif
  228. #endif
  229.  
  230. #if defined(WIN32) || defined(MS_WINDOWS)
  231. #define _USE_MATH_DEFINES
  232. #endif
  233. #include <math.h>
  234. #define __PYX_HAVE__my_prog_cython
  235. #define __PYX_HAVE_API__my_prog_cython
  236. #ifdef _OPENMP
  237. #include <omp.h>
  238. #endif /* _OPENMP */
  239.  
  240. #ifdef PYREX_WITHOUT_ASSERTIONS
  241. #define CYTHON_WITHOUT_ASSERTIONS
  242. #endif
  243.  
  244. #ifndef CYTHON_UNUSED
  245. # if defined(__GNUC__)
  246. #   if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
  247. #     define CYTHON_UNUSED __attribute__ ((__unused__))
  248. #   else
  249. #     define CYTHON_UNUSED
  250. #   endif
  251. # elif defined(__ICC) || (defined(__INTEL_COMPILER) && !defined(_MSC_VER))
  252. #   define CYTHON_UNUSED __attribute__ ((__unused__))
  253. # else
  254. #   define CYTHON_UNUSED
  255. # endif
  256. #endif
  257. typedef struct {PyObject **p; char *s; const Py_ssize_t n; const char* encoding;
  258.                 const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry;
  259.  
  260. #define __PYX_DEFAULT_STRING_ENCODING_IS_ASCII 0
  261. #define __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT 0
  262. #define __PYX_DEFAULT_STRING_ENCODING ""
  263. #define __Pyx_PyObject_FromString __Pyx_PyBytes_FromString
  264. #define __Pyx_PyObject_FromStringAndSize __Pyx_PyBytes_FromStringAndSize
  265. #define __Pyx_fits_Py_ssize_t(v, type, is_signed)  (    \
  266.     (sizeof(type) < sizeof(Py_ssize_t))  ||             \
  267.     (sizeof(type) > sizeof(Py_ssize_t) &&               \
  268.           likely(v < (type)PY_SSIZE_T_MAX ||            \
  269.                  v == (type)PY_SSIZE_T_MAX)  &&         \
  270.           (!is_signed || likely(v > (type)PY_SSIZE_T_MIN ||       \
  271.                                 v == (type)PY_SSIZE_T_MIN)))  ||  \
  272.     (sizeof(type) == sizeof(Py_ssize_t) &&              \
  273.           (is_signed || likely(v < (type)PY_SSIZE_T_MAX ||        \
  274.                                v == (type)PY_SSIZE_T_MAX)))  )
  275. static CYTHON_INLINE char* __Pyx_PyObject_AsString(PyObject*);
  276. static CYTHON_INLINE char* __Pyx_PyObject_AsStringAndSize(PyObject*, Py_ssize_t* length);
  277. #define __Pyx_PyByteArray_FromString(s) PyByteArray_FromStringAndSize((const char*)s, strlen((const char*)s))
  278. #define __Pyx_PyByteArray_FromStringAndSize(s, l) PyByteArray_FromStringAndSize((const char*)s, l)
  279. #define __Pyx_PyBytes_FromString        PyBytes_FromString
  280. #define __Pyx_PyBytes_FromStringAndSize PyBytes_FromStringAndSize
  281. static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char*);
  282. #if PY_MAJOR_VERSION < 3
  283.     #define __Pyx_PyStr_FromString        __Pyx_PyBytes_FromString
  284.     #define __Pyx_PyStr_FromStringAndSize __Pyx_PyBytes_FromStringAndSize
  285. #else
  286.     #define __Pyx_PyStr_FromString        __Pyx_PyUnicode_FromString
  287.     #define __Pyx_PyStr_FromStringAndSize __Pyx_PyUnicode_FromStringAndSize
  288. #endif
  289. #define __Pyx_PyObject_AsSString(s)    ((signed char*) __Pyx_PyObject_AsString(s))
  290. #define __Pyx_PyObject_AsUString(s)    ((unsigned char*) __Pyx_PyObject_AsString(s))
  291. #define __Pyx_PyObject_FromUString(s)  __Pyx_PyObject_FromString((const char*)s)
  292. #define __Pyx_PyBytes_FromUString(s)   __Pyx_PyBytes_FromString((const char*)s)
  293. #define __Pyx_PyByteArray_FromUString(s)   __Pyx_PyByteArray_FromString((const char*)s)
  294. #define __Pyx_PyStr_FromUString(s)     __Pyx_PyStr_FromString((const char*)s)
  295. #define __Pyx_PyUnicode_FromUString(s) __Pyx_PyUnicode_FromString((const char*)s)
  296. #if PY_MAJOR_VERSION < 3
  297. static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u)
  298. {
  299.     const Py_UNICODE *u_end = u;
  300.     while (*u_end++) ;
  301.     return (size_t)(u_end - u - 1);
  302. }
  303. #else
  304. #define __Pyx_Py_UNICODE_strlen Py_UNICODE_strlen
  305. #endif
  306. #define __Pyx_PyUnicode_FromUnicode(u)       PyUnicode_FromUnicode(u, __Pyx_Py_UNICODE_strlen(u))
  307. #define __Pyx_PyUnicode_FromUnicodeAndLength PyUnicode_FromUnicode
  308. #define __Pyx_PyUnicode_AsUnicode            PyUnicode_AsUnicode
  309. #define __Pyx_Owned_Py_None(b) (Py_INCREF(Py_None), Py_None)
  310. #define __Pyx_PyBool_FromLong(b) ((b) ? (Py_INCREF(Py_True), Py_True) : (Py_INCREF(Py_False), Py_False))
  311. static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*);
  312. static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x);
  313. static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*);
  314. static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t);
  315. #if CYTHON_COMPILING_IN_CPYTHON
  316. #define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x))
  317. #else
  318. #define __pyx_PyFloat_AsDouble(x) PyFloat_AsDouble(x)
  319. #endif
  320. #define __pyx_PyFloat_AsFloat(x) ((float) __pyx_PyFloat_AsDouble(x))
  321. #if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII
  322. static int __Pyx_sys_getdefaultencoding_not_ascii;
  323. static int __Pyx_init_sys_getdefaultencoding_params(void) {
  324.     PyObject* sys;
  325.     PyObject* default_encoding = NULL;
  326.     PyObject* ascii_chars_u = NULL;
  327.     PyObject* ascii_chars_b = NULL;
  328.     const char* default_encoding_c;
  329.     sys = PyImport_ImportModule("sys");
  330.     if (!sys) goto bad;
  331.     default_encoding = PyObject_CallMethod(sys, (char*) (const char*) "getdefaultencoding", NULL);
  332.     Py_DECREF(sys);
  333.     if (!default_encoding) goto bad;
  334.     default_encoding_c = PyBytes_AsString(default_encoding);
  335.     if (!default_encoding_c) goto bad;
  336.     if (strcmp(default_encoding_c, "ascii") == 0) {
  337.         __Pyx_sys_getdefaultencoding_not_ascii = 0;
  338.     } else {
  339.         char ascii_chars[128];
  340.         int c;
  341.         for (c = 0; c < 128; c++) {
  342.             ascii_chars[c] = c;
  343.         }
  344.         __Pyx_sys_getdefaultencoding_not_ascii = 1;
  345.         ascii_chars_u = PyUnicode_DecodeASCII(ascii_chars, 128, NULL);
  346.         if (!ascii_chars_u) goto bad;
  347.         ascii_chars_b = PyUnicode_AsEncodedString(ascii_chars_u, default_encoding_c, NULL);
  348.         if (!ascii_chars_b || !PyBytes_Check(ascii_chars_b) || memcmp(ascii_chars, PyBytes_AS_STRING(ascii_chars_b), 128) != 0) {
  349.             PyErr_Format(
  350.                 PyExc_ValueError,
  351.                 "This module compiled with c_string_encoding=ascii, but default encoding '%.200s' is not a superset of ascii.",
  352.                 default_encoding_c);
  353.             goto bad;
  354.         }
  355.         Py_DECREF(ascii_chars_u);
  356.         Py_DECREF(ascii_chars_b);
  357.     }
  358.     Py_DECREF(default_encoding);
  359.     return 0;
  360. bad:
  361.     Py_XDECREF(default_encoding);
  362.     Py_XDECREF(ascii_chars_u);
  363.     Py_XDECREF(ascii_chars_b);
  364.     return -1;
  365. }
  366. #endif
  367. #if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT && PY_MAJOR_VERSION >= 3
  368. #define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_DecodeUTF8(c_str, size, NULL)
  369. #else
  370. #define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_Decode(c_str, size, __PYX_DEFAULT_STRING_ENCODING, NULL)
  371. #if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT
  372. static char* __PYX_DEFAULT_STRING_ENCODING;
  373. static int __Pyx_init_sys_getdefaultencoding_params(void) {
  374.     PyObject* sys;
  375.     PyObject* default_encoding = NULL;
  376.     char* default_encoding_c;
  377.     sys = PyImport_ImportModule("sys");
  378.     if (!sys) goto bad;
  379.     default_encoding = PyObject_CallMethod(sys, (char*) (const char*) "getdefaultencoding", NULL);
  380.     Py_DECREF(sys);
  381.     if (!default_encoding) goto bad;
  382.     default_encoding_c = PyBytes_AsString(default_encoding);
  383.     if (!default_encoding_c) goto bad;
  384.     __PYX_DEFAULT_STRING_ENCODING = (char*) malloc(strlen(default_encoding_c));
  385.     if (!__PYX_DEFAULT_STRING_ENCODING) goto bad;
  386.     strcpy(__PYX_DEFAULT_STRING_ENCODING, default_encoding_c);
  387.     Py_DECREF(default_encoding);
  388.     return 0;
  389. bad:
  390.     Py_XDECREF(default_encoding);
  391.     return -1;
  392. }
  393. #endif
  394. #endif
  395.  
  396.  
  397. /* Test for GCC > 2.95 */
  398. #if defined(__GNUC__)     && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95)))
  399.   #define likely(x)   __builtin_expect(!!(x), 1)
  400.   #define unlikely(x) __builtin_expect(!!(x), 0)
  401. #else /* !__GNUC__ or GCC < 2.95 */
  402.   #define likely(x)   (x)
  403.   #define unlikely(x) (x)
  404. #endif /* __GNUC__ */
  405.  
  406. static PyObject *__pyx_m;
  407. static PyObject *__pyx_d;
  408. static PyObject *__pyx_b;
  409. static PyObject *__pyx_empty_tuple;
  410. static PyObject *__pyx_empty_bytes;
  411. static int __pyx_lineno;
  412. static int __pyx_clineno = 0;
  413. static const char * __pyx_cfilenm= __FILE__;
  414. static const char *__pyx_filename;
  415.  
  416.  
  417. static const char *__pyx_f[] = {
  418.   "my_prog_cython.pyx",
  419. };
  420.  
  421. /*--- Type declarations ---*/
  422. #ifndef CYTHON_REFNANNY
  423.   #define CYTHON_REFNANNY 0
  424. #endif
  425. #if CYTHON_REFNANNY
  426.   typedef struct {
  427.     void (*INCREF)(void*, PyObject*, int);
  428.     void (*DECREF)(void*, PyObject*, int);
  429.     void (*GOTREF)(void*, PyObject*, int);
  430.     void (*GIVEREF)(void*, PyObject*, int);
  431.     void* (*SetupContext)(const char*, int, const char*);
  432.     void (*FinishContext)(void**);
  433.   } __Pyx_RefNannyAPIStruct;
  434.   static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL;
  435.   static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname);
  436.   #define __Pyx_RefNannyDeclarations void *__pyx_refnanny = NULL;
  437. #ifdef WITH_THREAD
  438.   #define __Pyx_RefNannySetupContext(name, acquire_gil) \
  439.           if (acquire_gil) { \
  440.               PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure(); \
  441.               __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__); \
  442.               PyGILState_Release(__pyx_gilstate_save); \
  443.           } else { \
  444.               __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__); \
  445.           }
  446. #else
  447.   #define __Pyx_RefNannySetupContext(name, acquire_gil) \
  448.           __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__)
  449. #endif
  450.   #define __Pyx_RefNannyFinishContext() \
  451.           __Pyx_RefNanny->FinishContext(&__pyx_refnanny)
  452.   #define __Pyx_INCREF(r)  __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
  453.   #define __Pyx_DECREF(r)  __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
  454.   #define __Pyx_GOTREF(r)  __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
  455.   #define __Pyx_GIVEREF(r) __Pyx_RefNanny->GIVEREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
  456.   #define __Pyx_XINCREF(r)  do { if((r) != NULL) {__Pyx_INCREF(r); }} while(0)
  457.   #define __Pyx_XDECREF(r)  do { if((r) != NULL) {__Pyx_DECREF(r); }} while(0)
  458.   #define __Pyx_XGOTREF(r)  do { if((r) != NULL) {__Pyx_GOTREF(r); }} while(0)
  459.   #define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);}} while(0)
  460. #else
  461.   #define __Pyx_RefNannyDeclarations
  462.   #define __Pyx_RefNannySetupContext(name, acquire_gil)
  463.   #define __Pyx_RefNannyFinishContext()
  464.   #define __Pyx_INCREF(r) Py_INCREF(r)
  465.   #define __Pyx_DECREF(r) Py_DECREF(r)
  466.   #define __Pyx_GOTREF(r)
  467.   #define __Pyx_GIVEREF(r)
  468.   #define __Pyx_XINCREF(r) Py_XINCREF(r)
  469.   #define __Pyx_XDECREF(r) Py_XDECREF(r)
  470.   #define __Pyx_XGOTREF(r)
  471.   #define __Pyx_XGIVEREF(r)
  472. #endif
  473. #define __Pyx_XDECREF_SET(r, v) do {                            \
  474.         PyObject *tmp = (PyObject *) r;                         \
  475.         r = v; __Pyx_XDECREF(tmp);                              \
  476.     } while (0)
  477. #define __Pyx_DECREF_SET(r, v) do {                             \
  478.         PyObject *tmp = (PyObject *) r;                         \
  479.         r = v; __Pyx_DECREF(tmp);                               \
  480.     } while (0)
  481. #define __Pyx_CLEAR(r)    do { PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);} while(0)
  482. #define __Pyx_XCLEAR(r)   do { if((r) != NULL) {PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);}} while(0)
  483.  
  484. static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb);
  485. static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb);
  486.  
  487. static void __Pyx_WriteUnraisable(const char *name, int clineno,
  488.                                   int lineno, const char *filename,
  489.                                   int full_traceback);
  490.  
  491. typedef struct {
  492.     int code_line;
  493.     PyCodeObject* code_object;
  494. } __Pyx_CodeObjectCacheEntry;
  495. struct __Pyx_CodeObjectCache {
  496.     int count;
  497.     int max_count;
  498.     __Pyx_CodeObjectCacheEntry* entries;
  499. };
  500. static struct __Pyx_CodeObjectCache __pyx_code_cache = {0,0,NULL};
  501. static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line);
  502. static PyCodeObject *__pyx_find_code_object(int code_line);
  503. static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object);
  504.  
  505. static void __Pyx_AddTraceback(const char *funcname, int c_line,
  506.                                int py_line, const char *filename);
  507.  
  508. static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value);
  509.  
  510. static int __Pyx_Print(PyObject*, PyObject *, int);
  511. #if CYTHON_COMPILING_IN_PYPY || PY_MAJOR_VERSION >= 3
  512. static PyObject* __pyx_print = 0;
  513. static PyObject* __pyx_print_kwargs = 0;
  514. #endif
  515.  
  516. static int __Pyx_PrintOne(PyObject* stream, PyObject *o);
  517.  
  518. static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value);
  519.  
  520. static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *);
  521.  
  522. static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *);
  523.  
  524. static int __Pyx_check_binary_version(void);
  525.  
  526. static int __Pyx_InitStrings(__Pyx_StringTabEntry *t);
  527.  
  528.  
  529. /* Module declarations from 'my_prog_cython' */
  530. __PYX_EXTERN_C DL_EXPORT(void) cythonFunction(int); /*proto*/
  531. #define __Pyx_MODULE_NAME "my_prog_cython"
  532. int __pyx_module_is_main_my_prog_cython = 0;
  533.  
  534. /* Implementation of 'my_prog_cython' */
  535. static char __pyx_k_[] = "=";
  536. static char __pyx_k_end[] = "end";
  537. static char __pyx_k_file[] = "file";
  538. static char __pyx_k_main[] = "__main__";
  539. static char __pyx_k_test[] = "__test__";
  540. static char __pyx_k_print[] = "print";
  541. static char __pyx_k_inside_cython_function[] = "inside cython function!!!";
  542. static PyObject *__pyx_kp_s_;
  543. static PyObject *__pyx_n_s_end;
  544. static PyObject *__pyx_n_s_file;
  545. static PyObject *__pyx_kp_s_inside_cython_function;
  546. static PyObject *__pyx_n_s_main;
  547. static PyObject *__pyx_n_s_print;
  548. static PyObject *__pyx_n_s_test;
  549.  
  550. /* "my_prog_cython.pyx":1
  551.  * cdef public void cythonFunction (int n):             # <<<<<<<<<<<<<<
  552.  *  print "=" * n
  553.  *  print "inside cython function!!!"
  554.  */
  555.  
  556. void cythonFunction(int __pyx_v_n) {
  557.   __Pyx_RefNannyDeclarations
  558.   PyObject *__pyx_t_1 = NULL;
  559.   PyObject *__pyx_t_2 = NULL;
  560.   int __pyx_lineno = 0;
  561.   const char *__pyx_filename = NULL;
  562.   int __pyx_clineno = 0;
  563.   __Pyx_RefNannySetupContext("cythonFunction", 0);
  564.  
  565.   /* "my_prog_cython.pyx":2
  566.  * cdef public void cythonFunction (int n):
  567.  *  print "=" * n             # <<<<<<<<<<<<<<
  568.  *  print "inside cython function!!!"
  569.  *  print "=" * n
  570.  */
  571.   __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_n); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 2; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  572.   __Pyx_GOTREF(__pyx_t_1);
  573.   __pyx_t_2 = PyNumber_Multiply(__pyx_kp_s_, __pyx_t_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 2; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  574.   __Pyx_GOTREF(__pyx_t_2);
  575.   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  576.   if (__Pyx_PrintOne(0, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 2; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  577.   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  578.  
  579.   /* "my_prog_cython.pyx":3
  580.  * cdef public void cythonFunction (int n):
  581.  *  print "=" * n
  582.  *  print "inside cython function!!!"             # <<<<<<<<<<<<<<
  583.  *  print "=" * n
  584.  *
  585.  */
  586.   if (__Pyx_PrintOne(0, __pyx_kp_s_inside_cython_function) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  587.  
  588.   /* "my_prog_cython.pyx":4
  589.  *  print "=" * n
  590.  *  print "inside cython function!!!"
  591.  *  print "=" * n             # <<<<<<<<<<<<<<
  592.  *
  593.  */
  594.   __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_v_n); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  595.   __Pyx_GOTREF(__pyx_t_2);
  596.   __pyx_t_1 = PyNumber_Multiply(__pyx_kp_s_, __pyx_t_2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  597.   __Pyx_GOTREF(__pyx_t_1);
  598.   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  599.   if (__Pyx_PrintOne(0, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  600.   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  601.  
  602.   /* "my_prog_cython.pyx":1
  603.  * cdef public void cythonFunction (int n):             # <<<<<<<<<<<<<<
  604.  *  print "=" * n
  605.  *  print "inside cython function!!!"
  606.  */
  607.  
  608.   /* function exit code */
  609.   goto __pyx_L0;
  610.   __pyx_L1_error:;
  611.   __Pyx_XDECREF(__pyx_t_1);
  612.   __Pyx_XDECREF(__pyx_t_2);
  613.   __Pyx_WriteUnraisable("my_prog_cython.cythonFunction", __pyx_clineno, __pyx_lineno, __pyx_filename, 0);
  614.   __pyx_L0:;
  615.   __Pyx_RefNannyFinishContext();
  616. }
  617.  
  618. static PyMethodDef __pyx_methods[] = {
  619.   {0, 0, 0, 0}
  620. };
  621.  
  622. #if PY_MAJOR_VERSION >= 3
  623. static struct PyModuleDef __pyx_moduledef = {
  624.   #if PY_VERSION_HEX < 0x03020000
  625.     { PyObject_HEAD_INIT(NULL) NULL, 0, NULL },
  626.   #else
  627.     PyModuleDef_HEAD_INIT,
  628.   #endif
  629.     "my_prog_cython",
  630.     0, /* m_doc */
  631.     -1, /* m_size */
  632.     __pyx_methods /* m_methods */,
  633.     NULL, /* m_reload */
  634.     NULL, /* m_traverse */
  635.     NULL, /* m_clear */
  636.     NULL /* m_free */
  637. };
  638. #endif
  639.  
  640. static __Pyx_StringTabEntry __pyx_string_tab[] = {
  641.   {&__pyx_kp_s_, __pyx_k_, sizeof(__pyx_k_), 0, 0, 1, 0},
  642.   {&__pyx_n_s_end, __pyx_k_end, sizeof(__pyx_k_end), 0, 0, 1, 1},
  643.   {&__pyx_n_s_file, __pyx_k_file, sizeof(__pyx_k_file), 0, 0, 1, 1},
  644.   {&__pyx_kp_s_inside_cython_function, __pyx_k_inside_cython_function, sizeof(__pyx_k_inside_cython_function), 0, 0, 1, 0},
  645.   {&__pyx_n_s_main, __pyx_k_main, sizeof(__pyx_k_main), 0, 0, 1, 1},
  646.   {&__pyx_n_s_print, __pyx_k_print, sizeof(__pyx_k_print), 0, 0, 1, 1},
  647.   {&__pyx_n_s_test, __pyx_k_test, sizeof(__pyx_k_test), 0, 0, 1, 1},
  648.   {0, 0, 0, 0, 0, 0, 0}
  649. };
  650. static int __Pyx_InitCachedBuiltins(void) {
  651.   return 0;
  652. }
  653.  
  654. static int __Pyx_InitCachedConstants(void) {
  655.   __Pyx_RefNannyDeclarations
  656.   __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0);
  657.   __Pyx_RefNannyFinishContext();
  658.   return 0;
  659. }
  660.  
  661. static int __Pyx_InitGlobals(void) {
  662.   if (__Pyx_InitStrings(__pyx_string_tab) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
  663.   return 0;
  664.   __pyx_L1_error:;
  665.   return -1;
  666. }
  667.  
  668. #if PY_MAJOR_VERSION < 3
  669. PyMODINIT_FUNC initmy_prog_cython(void); /*proto*/
  670. PyMODINIT_FUNC initmy_prog_cython(void)
  671. #else
  672. PyMODINIT_FUNC PyInit_my_prog_cython(void); /*proto*/
  673. PyMODINIT_FUNC PyInit_my_prog_cython(void)
  674. #endif
  675. {
  676.   PyObject *__pyx_t_1 = NULL;
  677.   int __pyx_lineno = 0;
  678.   const char *__pyx_filename = NULL;
  679.   int __pyx_clineno = 0;
  680.   __Pyx_RefNannyDeclarations
  681.   #if CYTHON_REFNANNY
  682.   __Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny");
  683.   if (!__Pyx_RefNanny) {
  684.       PyErr_Clear();
  685.       __Pyx_RefNanny = __Pyx_RefNannyImportAPI("Cython.Runtime.refnanny");
  686.       if (!__Pyx_RefNanny)
  687.           Py_FatalError("failed to import 'refnanny' module");
  688.   }
  689.   #endif
  690.   __Pyx_RefNannySetupContext("PyMODINIT_FUNC PyInit_my_prog_cython(void)", 0);
  691.   if ( __Pyx_check_binary_version() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  692.   __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  693.   __pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  694.   #ifdef __Pyx_CyFunction_USED
  695.   if (__Pyx_CyFunction_init() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  696.   #endif
  697.   #ifdef __Pyx_FusedFunction_USED
  698.   if (__pyx_FusedFunction_init() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  699.   #endif
  700.   #ifdef __Pyx_Generator_USED
  701.   if (__pyx_Generator_init() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  702.   #endif
  703.   /*--- Library function declarations ---*/
  704.   /*--- Threads initialization code ---*/
  705.   #if defined(__PYX_FORCE_INIT_THREADS) && __PYX_FORCE_INIT_THREADS
  706.   #ifdef WITH_THREAD /* Python build with threading support? */
  707.   PyEval_InitThreads();
  708.   #endif
  709.   #endif
  710.   /*--- Module creation code ---*/
  711.   #if PY_MAJOR_VERSION < 3
  712.   __pyx_m = Py_InitModule4("my_prog_cython", __pyx_methods, 0, 0, PYTHON_API_VERSION); Py_XINCREF(__pyx_m);
  713.   #else
  714.   __pyx_m = PyModule_Create(&__pyx_moduledef);
  715.   #endif
  716.   if (unlikely(!__pyx_m)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  717.   __pyx_d = PyModule_GetDict(__pyx_m); if (unlikely(!__pyx_d)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  718.   Py_INCREF(__pyx_d);
  719.   __pyx_b = PyImport_AddModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_b)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  720.   #if CYTHON_COMPILING_IN_PYPY
  721.   Py_INCREF(__pyx_b);
  722.   #endif
  723.   if (PyObject_SetAttrString(__pyx_m, "__builtins__", __pyx_b) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
  724.   /*--- Initialize various global constants etc. ---*/
  725.   if (unlikely(__Pyx_InitGlobals() < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  726.   #if PY_MAJOR_VERSION < 3 && (__PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT)
  727.   if (__Pyx_init_sys_getdefaultencoding_params() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  728.   #endif
  729.   if (__pyx_module_is_main_my_prog_cython) {
  730.     if (PyObject_SetAttrString(__pyx_m, "__name__", __pyx_n_s_main) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
  731.   }
  732.   #if PY_MAJOR_VERSION >= 3
  733.   {
  734.     PyObject *modules = PyImport_GetModuleDict(); if (unlikely(!modules)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  735.     if (!PyDict_GetItemString(modules, "my_prog_cython")) {
  736.       if (unlikely(PyDict_SetItemString(modules, "my_prog_cython", __pyx_m) < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  737.     }
  738.   }
  739.   #endif
  740.   /*--- Builtin init code ---*/
  741.   if (unlikely(__Pyx_InitCachedBuiltins() < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  742.   /*--- Constants init code ---*/
  743.   if (unlikely(__Pyx_InitCachedConstants() < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  744.   /*--- Global init code ---*/
  745.   /*--- Variable export code ---*/
  746.   /*--- Function export code ---*/
  747.   /*--- Type init code ---*/
  748.   /*--- Type import code ---*/
  749.   /*--- Variable import code ---*/
  750.   /*--- Function import code ---*/
  751.   /*--- Execution code ---*/
  752.  
  753.   /* "my_prog_cython.pyx":1
  754.  * cdef public void cythonFunction (int n):             # <<<<<<<<<<<<<<
  755.  *  print "=" * n
  756.  *  print "inside cython function!!!"
  757.  */
  758.   __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  759.   __Pyx_GOTREF(__pyx_t_1);
  760.   if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  761.   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  762.  
  763.   /*--- Wrapped vars code ---*/
  764.  
  765.   goto __pyx_L0;
  766.   __pyx_L1_error:;
  767.   __Pyx_XDECREF(__pyx_t_1);
  768.   if (__pyx_m) {
  769.     if (__pyx_d) {
  770.       __Pyx_AddTraceback("init my_prog_cython", __pyx_clineno, __pyx_lineno, __pyx_filename);
  771.     }
  772.     Py_DECREF(__pyx_m); __pyx_m = 0;
  773.   } else if (!PyErr_Occurred()) {
  774.     PyErr_SetString(PyExc_ImportError, "init my_prog_cython");
  775.   }
  776.   __pyx_L0:;
  777.   __Pyx_RefNannyFinishContext();
  778.   #if PY_MAJOR_VERSION < 3
  779.   return;
  780.   #else
  781.   return __pyx_m;
  782.   #endif
  783. }
  784.  
  785. /* Runtime support code */
  786. #if CYTHON_REFNANNY
  787. static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) {
  788.     PyObject *m = NULL, *p = NULL;
  789.     void *r = NULL;
  790.     m = PyImport_ImportModule((char *)modname);
  791.     if (!m) goto end;
  792.     p = PyObject_GetAttrString(m, (char *)"RefNannyAPI");
  793.     if (!p) goto end;
  794.     r = PyLong_AsVoidPtr(p);
  795. end:
  796.     Py_XDECREF(p);
  797.     Py_XDECREF(m);
  798.     return (__Pyx_RefNannyAPIStruct *)r;
  799. }
  800. #endif
  801.  
  802. static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
  803. #if CYTHON_COMPILING_IN_CPYTHON
  804.     PyObject *tmp_type, *tmp_value, *tmp_tb;
  805.     PyThreadState *tstate = PyThreadState_GET();
  806.     tmp_type = tstate->curexc_type;
  807.     tmp_value = tstate->curexc_value;
  808.     tmp_tb = tstate->curexc_traceback;
  809.     tstate->curexc_type = type;
  810.     tstate->curexc_value = value;
  811.     tstate->curexc_traceback = tb;
  812.     Py_XDECREF(tmp_type);
  813.     Py_XDECREF(tmp_value);
  814.     Py_XDECREF(tmp_tb);
  815. #else
  816.     PyErr_Restore(type, value, tb);
  817. #endif
  818. }
  819. static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
  820. #if CYTHON_COMPILING_IN_CPYTHON
  821.     PyThreadState *tstate = PyThreadState_GET();
  822.     *type = tstate->curexc_type;
  823.     *value = tstate->curexc_value;
  824.     *tb = tstate->curexc_traceback;
  825.     tstate->curexc_type = 0;
  826.     tstate->curexc_value = 0;
  827.     tstate->curexc_traceback = 0;
  828. #else
  829.     PyErr_Fetch(type, value, tb);
  830. #endif
  831. }
  832.  
  833. static void __Pyx_WriteUnraisable(const char *name, CYTHON_UNUSED int clineno,
  834.                                   CYTHON_UNUSED int lineno, CYTHON_UNUSED const char *filename,
  835.                                   int full_traceback) {
  836.     PyObject *old_exc, *old_val, *old_tb;
  837.     PyObject *ctx;
  838.     __Pyx_ErrFetch(&old_exc, &old_val, &old_tb);
  839.     if (full_traceback) {
  840.         Py_XINCREF(old_exc);
  841.         Py_XINCREF(old_val);
  842.         Py_XINCREF(old_tb);
  843.         __Pyx_ErrRestore(old_exc, old_val, old_tb);
  844.         PyErr_PrintEx(1);
  845.     }
  846.     #if PY_MAJOR_VERSION < 3
  847.     ctx = PyString_FromString(name);
  848.     #else
  849.     ctx = PyUnicode_FromString(name);
  850.     #endif
  851.     __Pyx_ErrRestore(old_exc, old_val, old_tb);
  852.     if (!ctx) {
  853.         PyErr_WriteUnraisable(Py_None);
  854.     } else {
  855.         PyErr_WriteUnraisable(ctx);
  856.         Py_DECREF(ctx);
  857.     }
  858. }
  859.  
  860. static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line) {
  861.     int start = 0, mid = 0, end = count - 1;
  862.     if (end >= 0 && code_line > entries[end].code_line) {
  863.         return count;
  864.     }
  865.     while (start < end) {
  866.         mid = (start + end) / 2;
  867.         if (code_line < entries[mid].code_line) {
  868.             end = mid;
  869.         } else if (code_line > entries[mid].code_line) {
  870.              start = mid + 1;
  871.         } else {
  872.             return mid;
  873.         }
  874.     }
  875.     if (code_line <= entries[mid].code_line) {
  876.         return mid;
  877.     } else {
  878.         return mid + 1;
  879.     }
  880. }
  881. static PyCodeObject *__pyx_find_code_object(int code_line) {
  882.     PyCodeObject* code_object;
  883.     int pos;
  884.     if (unlikely(!code_line) || unlikely(!__pyx_code_cache.entries)) {
  885.         return NULL;
  886.     }
  887.     pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line);
  888.     if (unlikely(pos >= __pyx_code_cache.count) || unlikely(__pyx_code_cache.entries[pos].code_line != code_line)) {
  889.         return NULL;
  890.     }
  891.     code_object = __pyx_code_cache.entries[pos].code_object;
  892.     Py_INCREF(code_object);
  893.     return code_object;
  894. }
  895. static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object) {
  896.     int pos, i;
  897.     __Pyx_CodeObjectCacheEntry* entries = __pyx_code_cache.entries;
  898.     if (unlikely(!code_line)) {
  899.         return;
  900.     }
  901.     if (unlikely(!entries)) {
  902.         entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Malloc(64*sizeof(__Pyx_CodeObjectCacheEntry));
  903.         if (likely(entries)) {
  904.             __pyx_code_cache.entries = entries;
  905.             __pyx_code_cache.max_count = 64;
  906.             __pyx_code_cache.count = 1;
  907.             entries[0].code_line = code_line;
  908.             entries[0].code_object = code_object;
  909.             Py_INCREF(code_object);
  910.         }
  911.         return;
  912.     }
  913.     pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line);
  914.     if ((pos < __pyx_code_cache.count) && unlikely(__pyx_code_cache.entries[pos].code_line == code_line)) {
  915.         PyCodeObject* tmp = entries[pos].code_object;
  916.         entries[pos].code_object = code_object;
  917.         Py_DECREF(tmp);
  918.         return;
  919.     }
  920.     if (__pyx_code_cache.count == __pyx_code_cache.max_count) {
  921.         int new_max = __pyx_code_cache.max_count + 64;
  922.         entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Realloc(
  923.             __pyx_code_cache.entries, (size_t)new_max*sizeof(__Pyx_CodeObjectCacheEntry));
  924.         if (unlikely(!entries)) {
  925.             return;
  926.         }
  927.         __pyx_code_cache.entries = entries;
  928.         __pyx_code_cache.max_count = new_max;
  929.     }
  930.     for (i=__pyx_code_cache.count; i>pos; i--) {
  931.         entries[i] = entries[i-1];
  932.     }
  933.     entries[pos].code_line = code_line;
  934.     entries[pos].code_object = code_object;
  935.     __pyx_code_cache.count++;
  936.     Py_INCREF(code_object);
  937. }
  938.  
  939. #include "compile.h"
  940. #include "frameobject.h"
  941. #include "traceback.h"
  942. static PyCodeObject* __Pyx_CreateCodeObjectForTraceback(
  943.             const char *funcname, int c_line,
  944.             int py_line, const char *filename) {
  945.     PyCodeObject *py_code = 0;
  946.     PyObject *py_srcfile = 0;
  947.     PyObject *py_funcname = 0;
  948.     #if PY_MAJOR_VERSION < 3
  949.     py_srcfile = PyString_FromString(filename);
  950.     #else
  951.     py_srcfile = PyUnicode_FromString(filename);
  952.     #endif
  953.     if (!py_srcfile) goto bad;
  954.     if (c_line) {
  955.         #if PY_MAJOR_VERSION < 3
  956.         py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line);
  957.         #else
  958.         py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line);
  959.         #endif
  960.     }
  961.     else {
  962.         #if PY_MAJOR_VERSION < 3
  963.         py_funcname = PyString_FromString(funcname);
  964.         #else
  965.         py_funcname = PyUnicode_FromString(funcname);
  966.         #endif
  967.     }
  968.     if (!py_funcname) goto bad;
  969.     py_code = __Pyx_PyCode_New(
  970.         0,
  971.         0,
  972.         0,
  973.         0,
  974.         0,
  975.         __pyx_empty_bytes, /*PyObject *code,*/
  976.         __pyx_empty_tuple, /*PyObject *consts,*/
  977.         __pyx_empty_tuple, /*PyObject *names,*/
  978.         __pyx_empty_tuple, /*PyObject *varnames,*/
  979.         __pyx_empty_tuple, /*PyObject *freevars,*/
  980.         __pyx_empty_tuple, /*PyObject *cellvars,*/
  981.         py_srcfile,   /*PyObject *filename,*/
  982.         py_funcname,  /*PyObject *name,*/
  983.         py_line,
  984.         __pyx_empty_bytes  /*PyObject *lnotab*/
  985.     );
  986.     Py_DECREF(py_srcfile);
  987.     Py_DECREF(py_funcname);
  988.     return py_code;
  989. bad:
  990.     Py_XDECREF(py_srcfile);
  991.     Py_XDECREF(py_funcname);
  992.     return NULL;
  993. }
  994. static void __Pyx_AddTraceback(const char *funcname, int c_line,
  995.                                int py_line, const char *filename) {
  996.     PyCodeObject *py_code = 0;
  997.     PyFrameObject *py_frame = 0;
  998.     py_code = __pyx_find_code_object(c_line ? c_line : py_line);
  999.     if (!py_code) {
  1000.         py_code = __Pyx_CreateCodeObjectForTraceback(
  1001.             funcname, c_line, py_line, filename);
  1002.         if (!py_code) goto bad;
  1003.         __pyx_insert_code_object(c_line ? c_line : py_line, py_code);
  1004.     }
  1005.     py_frame = PyFrame_New(
  1006.         PyThreadState_GET(), /*PyThreadState *tstate,*/
  1007.         py_code,             /*PyCodeObject *code,*/
  1008.         __pyx_d,      /*PyObject *globals,*/
  1009.         0                    /*PyObject *locals*/
  1010.     );
  1011.     if (!py_frame) goto bad;
  1012.     py_frame->f_lineno = py_line;
  1013.     PyTraceBack_Here(py_frame);
  1014. bad:
  1015.     Py_XDECREF(py_code);
  1016.     Py_XDECREF(py_frame);
  1017. }
  1018.  
  1019. static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value) {
  1020.     const int neg_one = (int) -1, const_zero = 0;
  1021.     const int is_unsigned = neg_one > const_zero;
  1022.     if (is_unsigned) {
  1023.         if (sizeof(int) < sizeof(long)) {
  1024.             return PyInt_FromLong((long) value);
  1025.         } else if (sizeof(int) <= sizeof(unsigned long)) {
  1026.             return PyLong_FromUnsignedLong((unsigned long) value);
  1027.         } else if (sizeof(int) <= sizeof(unsigned long long)) {
  1028.             return PyLong_FromUnsignedLongLong((unsigned long long) value);
  1029.         }
  1030.     } else {
  1031.         if (sizeof(int) <= sizeof(long)) {
  1032.             return PyInt_FromLong((long) value);
  1033.         } else if (sizeof(int) <= sizeof(long long)) {
  1034.             return PyLong_FromLongLong((long long) value);
  1035.         }
  1036.     }
  1037.     {
  1038.         int one = 1; int little = (int)*(unsigned char *)&one;
  1039.         unsigned char *bytes = (unsigned char *)&value;
  1040.         return _PyLong_FromByteArray(bytes, sizeof(int),
  1041.                                      little, !is_unsigned);
  1042.     }
  1043. }
  1044.  
  1045. #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION < 3
  1046. static PyObject *__Pyx_GetStdout(void) {
  1047.     PyObject *f = PySys_GetObject((char *)"stdout");
  1048.     if (!f) {
  1049.         PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
  1050.     }
  1051.     return f;
  1052. }
  1053. static int __Pyx_Print(PyObject* f, PyObject *arg_tuple, int newline) {
  1054.     int i;
  1055.     if (!f) {
  1056.         if (!(f = __Pyx_GetStdout()))
  1057.             return -1;
  1058.     }
  1059.     Py_INCREF(f);
  1060.     for (i=0; i < PyTuple_GET_SIZE(arg_tuple); i++) {
  1061.         PyObject* v;
  1062.         if (PyFile_SoftSpace(f, 1)) {
  1063.             if (PyFile_WriteString(" ", f) < 0)
  1064.                 goto error;
  1065.         }
  1066.         v = PyTuple_GET_ITEM(arg_tuple, i);
  1067.         if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0)
  1068.             goto error;
  1069.         if (PyString_Check(v)) {
  1070.             char *s = PyString_AsString(v);
  1071.             Py_ssize_t len = PyString_Size(v);
  1072.             if (len > 0) {
  1073.                 switch (s[len-1]) {
  1074.                     case ' ': break;
  1075.                     case '\f': case '\r': case '\n': case '\t': case '\v':
  1076.                         PyFile_SoftSpace(f, 0);
  1077.                         break;
  1078.                     default:  break;
  1079.                 }
  1080.             }
  1081.         }
  1082.     }
  1083.     if (newline) {
  1084.         if (PyFile_WriteString("\n", f) < 0)
  1085.             goto error;
  1086.         PyFile_SoftSpace(f, 0);
  1087.     }
  1088.     Py_DECREF(f);
  1089.     return 0;
  1090. error:
  1091.     Py_DECREF(f);
  1092.     return -1;
  1093. }
  1094. #else
  1095. static int __Pyx_Print(PyObject* stream, PyObject *arg_tuple, int newline) {
  1096.     PyObject* kwargs = 0;
  1097.     PyObject* result = 0;
  1098.     PyObject* end_string;
  1099.     if (unlikely(!__pyx_print)) {
  1100.         __pyx_print = PyObject_GetAttr(__pyx_b, __pyx_n_s_print);
  1101.         if (!__pyx_print)
  1102.             return -1;
  1103.     }
  1104.     if (stream) {
  1105.         kwargs = PyDict_New();
  1106.         if (unlikely(!kwargs))
  1107.             return -1;
  1108.         if (unlikely(PyDict_SetItem(kwargs, __pyx_n_s_file, stream) < 0))
  1109.             goto bad;
  1110.         if (!newline) {
  1111.             end_string = PyUnicode_FromStringAndSize(" ", 1);
  1112.             if (unlikely(!end_string))
  1113.                 goto bad;
  1114.             if (PyDict_SetItem(kwargs, __pyx_n_s_end, end_string) < 0) {
  1115.                 Py_DECREF(end_string);
  1116.                 goto bad;
  1117.             }
  1118.             Py_DECREF(end_string);
  1119.         }
  1120.     } else if (!newline) {
  1121.         if (unlikely(!__pyx_print_kwargs)) {
  1122.             __pyx_print_kwargs = PyDict_New();
  1123.             if (unlikely(!__pyx_print_kwargs))
  1124.                 return -1;
  1125.             end_string = PyUnicode_FromStringAndSize(" ", 1);
  1126.             if (unlikely(!end_string))
  1127.                 return -1;
  1128.             if (PyDict_SetItem(__pyx_print_kwargs, __pyx_n_s_end, end_string) < 0) {
  1129.                 Py_DECREF(end_string);
  1130.                 return -1;
  1131.             }
  1132.             Py_DECREF(end_string);
  1133.         }
  1134.         kwargs = __pyx_print_kwargs;
  1135.     }
  1136.     result = PyObject_Call(__pyx_print, arg_tuple, kwargs);
  1137.     if (unlikely(kwargs) && (kwargs != __pyx_print_kwargs))
  1138.         Py_DECREF(kwargs);
  1139.     if (!result)
  1140.         return -1;
  1141.     Py_DECREF(result);
  1142.     return 0;
  1143. bad:
  1144.     if (kwargs != __pyx_print_kwargs)
  1145.         Py_XDECREF(kwargs);
  1146.     return -1;
  1147. }
  1148. #endif
  1149.  
  1150. #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION < 3
  1151. static int __Pyx_PrintOne(PyObject* f, PyObject *o) {
  1152.     if (!f) {
  1153.         if (!(f = __Pyx_GetStdout()))
  1154.             return -1;
  1155.     }
  1156.     Py_INCREF(f);
  1157.     if (PyFile_SoftSpace(f, 0)) {
  1158.         if (PyFile_WriteString(" ", f) < 0)
  1159.             goto error;
  1160.     }
  1161.     if (PyFile_WriteObject(o, f, Py_PRINT_RAW) < 0)
  1162.         goto error;
  1163.     if (PyFile_WriteString("\n", f) < 0)
  1164.         goto error;
  1165.     Py_DECREF(f);
  1166.     return 0;
  1167. error:
  1168.     Py_DECREF(f);
  1169.     return -1;
  1170.     /* the line below is just to avoid C compiler
  1171.      * warnings about unused functions */
  1172.     return __Pyx_Print(f, NULL, 0);
  1173. }
  1174. #else
  1175. static int __Pyx_PrintOne(PyObject* stream, PyObject *o) {
  1176.     int res;
  1177.     PyObject* arg_tuple = PyTuple_Pack(1, o);
  1178.     if (unlikely(!arg_tuple))
  1179.         return -1;
  1180.     res = __Pyx_Print(stream, arg_tuple, 1);
  1181.     Py_DECREF(arg_tuple);
  1182.     return res;
  1183. }
  1184. #endif
  1185.  
  1186. static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) {
  1187.     const long neg_one = (long) -1, const_zero = 0;
  1188.     const int is_unsigned = neg_one > const_zero;
  1189.     if (is_unsigned) {
  1190.         if (sizeof(long) < sizeof(long)) {
  1191.             return PyInt_FromLong((long) value);
  1192.         } else if (sizeof(long) <= sizeof(unsigned long)) {
  1193.             return PyLong_FromUnsignedLong((unsigned long) value);
  1194.         } else if (sizeof(long) <= sizeof(unsigned long long)) {
  1195.             return PyLong_FromUnsignedLongLong((unsigned long long) value);
  1196.         }
  1197.     } else {
  1198.         if (sizeof(long) <= sizeof(long)) {
  1199.             return PyInt_FromLong((long) value);
  1200.         } else if (sizeof(long) <= sizeof(long long)) {
  1201.             return PyLong_FromLongLong((long long) value);
  1202.         }
  1203.     }
  1204.     {
  1205.         int one = 1; int little = (int)*(unsigned char *)&one;
  1206.         unsigned char *bytes = (unsigned char *)&value;
  1207.         return _PyLong_FromByteArray(bytes, sizeof(long),
  1208.                                      little, !is_unsigned);
  1209.     }
  1210. }
  1211.  
  1212. #define __PYX_VERIFY_RETURN_INT(target_type, func_type, func_value)       \
  1213.     {                                                                     \
  1214.         func_type value = func_value;                                     \
  1215.         if (sizeof(target_type) < sizeof(func_type)) {                    \
  1216.             if (unlikely(value != (func_type) (target_type) value)) {     \
  1217.                 func_type zero = 0;                                       \
  1218.                 if (is_unsigned && unlikely(value < zero))                \
  1219.                     goto raise_neg_overflow;                              \
  1220.                 else                                                      \
  1221.                     goto raise_overflow;                                  \
  1222.             }                                                             \
  1223.         }                                                                 \
  1224.         return (target_type) value;                                       \
  1225.     }
  1226.  
  1227. #if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
  1228.  #if CYTHON_USE_PYLONG_INTERNALS
  1229.   #include "longintrepr.h"
  1230.  #endif
  1231. #endif
  1232.  
  1233. static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *x) {
  1234.     const long neg_one = (long) -1, const_zero = 0;
  1235.     const int is_unsigned = neg_one > const_zero;
  1236. #if PY_MAJOR_VERSION < 3
  1237.     if (likely(PyInt_Check(x))) {
  1238.         if (sizeof(long) < sizeof(long)) {
  1239.             __PYX_VERIFY_RETURN_INT(long, long, PyInt_AS_LONG(x))
  1240.         } else {
  1241.             long val = PyInt_AS_LONG(x);
  1242.             if (is_unsigned && unlikely(val < 0)) {
  1243.                 goto raise_neg_overflow;
  1244.             }
  1245.             return (long) val;
  1246.         }
  1247.     } else
  1248. #endif
  1249.     if (likely(PyLong_Check(x))) {
  1250.         if (is_unsigned) {
  1251. #if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
  1252.  #if CYTHON_USE_PYLONG_INTERNALS
  1253.             switch (Py_SIZE(x)) {
  1254.                 case  0: return 0;
  1255.                 case  1: __PYX_VERIFY_RETURN_INT(long, digit, ((PyLongObject*)x)->ob_digit[0]);
  1256.             }
  1257.  #endif
  1258. #endif
  1259.             if (unlikely(Py_SIZE(x) < 0)) {
  1260.                 goto raise_neg_overflow;
  1261.             }
  1262.             if (sizeof(long) <= sizeof(unsigned long)) {
  1263.                 __PYX_VERIFY_RETURN_INT(long, unsigned long, PyLong_AsUnsignedLong(x))
  1264.             } else if (sizeof(long) <= sizeof(unsigned long long)) {
  1265.                 __PYX_VERIFY_RETURN_INT(long, unsigned long long, PyLong_AsUnsignedLongLong(x))
  1266.             }
  1267.         } else {
  1268. #if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
  1269.  #if CYTHON_USE_PYLONG_INTERNALS
  1270.             switch (Py_SIZE(x)) {
  1271.                 case  0: return 0;
  1272.                 case  1: __PYX_VERIFY_RETURN_INT(long,  digit, +(((PyLongObject*)x)->ob_digit[0]));
  1273.                 case -1: __PYX_VERIFY_RETURN_INT(long, sdigit, -(sdigit) ((PyLongObject*)x)->ob_digit[0]);
  1274.             }
  1275.  #endif
  1276. #endif
  1277.             if (sizeof(long) <= sizeof(long)) {
  1278.                 __PYX_VERIFY_RETURN_INT(long, long, PyLong_AsLong(x))
  1279.             } else if (sizeof(long) <= sizeof(long long)) {
  1280.                 __PYX_VERIFY_RETURN_INT(long, long long, PyLong_AsLongLong(x))
  1281.             }
  1282.         }
  1283.         {
  1284. #if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray)
  1285.             PyErr_SetString(PyExc_RuntimeError,
  1286.                             "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers");
  1287. #else
  1288.             long val;
  1289.             PyObject *v = __Pyx_PyNumber_Int(x);
  1290.  #if PY_MAJOR_VERSION < 3
  1291.             if (likely(v) && !PyLong_Check(v)) {
  1292.                 PyObject *tmp = v;
  1293.                 v = PyNumber_Long(tmp);
  1294.                 Py_DECREF(tmp);
  1295.             }
  1296.  #endif
  1297.             if (likely(v)) {
  1298.                 int one = 1; int is_little = (int)*(unsigned char *)&one;
  1299.                 unsigned char *bytes = (unsigned char *)&val;
  1300.                 int ret = _PyLong_AsByteArray((PyLongObject *)v,
  1301.                                               bytes, sizeof(val),
  1302.                                               is_little, !is_unsigned);
  1303.                 Py_DECREF(v);
  1304.                 if (likely(!ret))
  1305.                     return val;
  1306.             }
  1307. #endif
  1308.             return (long) -1;
  1309.         }
  1310.     } else {
  1311.         long val;
  1312.         PyObject *tmp = __Pyx_PyNumber_Int(x);
  1313.         if (!tmp) return (long) -1;
  1314.         val = __Pyx_PyInt_As_long(tmp);
  1315.         Py_DECREF(tmp);
  1316.         return val;
  1317.     }
  1318. raise_overflow:
  1319.     PyErr_SetString(PyExc_OverflowError,
  1320.         "value too large to convert to long");
  1321.     return (long) -1;
  1322. raise_neg_overflow:
  1323.     PyErr_SetString(PyExc_OverflowError,
  1324.         "can't convert negative value to long");
  1325.     return (long) -1;
  1326. }
  1327.  
  1328. static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *x) {
  1329.     const int neg_one = (int) -1, const_zero = 0;
  1330.     const int is_unsigned = neg_one > const_zero;
  1331. #if PY_MAJOR_VERSION < 3
  1332.     if (likely(PyInt_Check(x))) {
  1333.         if (sizeof(int) < sizeof(long)) {
  1334.             __PYX_VERIFY_RETURN_INT(int, long, PyInt_AS_LONG(x))
  1335.         } else {
  1336.             long val = PyInt_AS_LONG(x);
  1337.             if (is_unsigned && unlikely(val < 0)) {
  1338.                 goto raise_neg_overflow;
  1339.             }
  1340.             return (int) val;
  1341.         }
  1342.     } else
  1343. #endif
  1344.     if (likely(PyLong_Check(x))) {
  1345.         if (is_unsigned) {
  1346. #if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
  1347.  #if CYTHON_USE_PYLONG_INTERNALS
  1348.             switch (Py_SIZE(x)) {
  1349.                 case  0: return 0;
  1350.                 case  1: __PYX_VERIFY_RETURN_INT(int, digit, ((PyLongObject*)x)->ob_digit[0]);
  1351.             }
  1352.  #endif
  1353. #endif
  1354.             if (unlikely(Py_SIZE(x) < 0)) {
  1355.                 goto raise_neg_overflow;
  1356.             }
  1357.             if (sizeof(int) <= sizeof(unsigned long)) {
  1358.                 __PYX_VERIFY_RETURN_INT(int, unsigned long, PyLong_AsUnsignedLong(x))
  1359.             } else if (sizeof(int) <= sizeof(unsigned long long)) {
  1360.                 __PYX_VERIFY_RETURN_INT(int, unsigned long long, PyLong_AsUnsignedLongLong(x))
  1361.             }
  1362.         } else {
  1363. #if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
  1364.  #if CYTHON_USE_PYLONG_INTERNALS
  1365.             switch (Py_SIZE(x)) {
  1366.                 case  0: return 0;
  1367.                 case  1: __PYX_VERIFY_RETURN_INT(int,  digit, +(((PyLongObject*)x)->ob_digit[0]));
  1368.                 case -1: __PYX_VERIFY_RETURN_INT(int, sdigit, -(sdigit) ((PyLongObject*)x)->ob_digit[0]);
  1369.             }
  1370.  #endif
  1371. #endif
  1372.             if (sizeof(int) <= sizeof(long)) {
  1373.                 __PYX_VERIFY_RETURN_INT(int, long, PyLong_AsLong(x))
  1374.             } else if (sizeof(int) <= sizeof(long long)) {
  1375.                 __PYX_VERIFY_RETURN_INT(int, long long, PyLong_AsLongLong(x))
  1376.             }
  1377.         }
  1378.         {
  1379. #if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray)
  1380.             PyErr_SetString(PyExc_RuntimeError,
  1381.                             "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers");
  1382. #else
  1383.             int val;
  1384.             PyObject *v = __Pyx_PyNumber_Int(x);
  1385.  #if PY_MAJOR_VERSION < 3
  1386.             if (likely(v) && !PyLong_Check(v)) {
  1387.                 PyObject *tmp = v;
  1388.                 v = PyNumber_Long(tmp);
  1389.                 Py_DECREF(tmp);
  1390.             }
  1391.  #endif
  1392.             if (likely(v)) {
  1393.                 int one = 1; int is_little = (int)*(unsigned char *)&one;
  1394.                 unsigned char *bytes = (unsigned char *)&val;
  1395.                 int ret = _PyLong_AsByteArray((PyLongObject *)v,
  1396.                                               bytes, sizeof(val),
  1397.                                               is_little, !is_unsigned);
  1398.                 Py_DECREF(v);
  1399.                 if (likely(!ret))
  1400.                     return val;
  1401.             }
  1402. #endif
  1403.             return (int) -1;
  1404.         }
  1405.     } else {
  1406.         int val;
  1407.         PyObject *tmp = __Pyx_PyNumber_Int(x);
  1408.         if (!tmp) return (int) -1;
  1409.         val = __Pyx_PyInt_As_int(tmp);
  1410.         Py_DECREF(tmp);
  1411.         return val;
  1412.     }
  1413. raise_overflow:
  1414.     PyErr_SetString(PyExc_OverflowError,
  1415.         "value too large to convert to int");
  1416.     return (int) -1;
  1417. raise_neg_overflow:
  1418.     PyErr_SetString(PyExc_OverflowError,
  1419.         "can't convert negative value to int");
  1420.     return (int) -1;
  1421. }
  1422.  
  1423. static int __Pyx_check_binary_version(void) {
  1424.     char ctversion[4], rtversion[4];
  1425.     PyOS_snprintf(ctversion, 4, "%d.%d", PY_MAJOR_VERSION, PY_MINOR_VERSION);
  1426.     PyOS_snprintf(rtversion, 4, "%s", Py_GetVersion());
  1427.     if (ctversion[0] != rtversion[0] || ctversion[2] != rtversion[2]) {
  1428.         char message[200];
  1429.         PyOS_snprintf(message, sizeof(message),
  1430.                       "compiletime version %s of module '%.100s' "
  1431.                       "does not match runtime version %s",
  1432.                       ctversion, __Pyx_MODULE_NAME, rtversion);
  1433.         return PyErr_WarnEx(NULL, message, 1);
  1434.     }
  1435.     return 0;
  1436. }
  1437.  
  1438. static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
  1439.     while (t->p) {
  1440.         #if PY_MAJOR_VERSION < 3
  1441.         if (t->is_unicode) {
  1442.             *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL);
  1443.         } else if (t->intern) {
  1444.             *t->p = PyString_InternFromString(t->s);
  1445.         } else {
  1446.             *t->p = PyString_FromStringAndSize(t->s, t->n - 1);
  1447.         }
  1448.         #else
  1449.         if (t->is_unicode | t->is_str) {
  1450.             if (t->intern) {
  1451.                 *t->p = PyUnicode_InternFromString(t->s);
  1452.             } else if (t->encoding) {
  1453.                 *t->p = PyUnicode_Decode(t->s, t->n - 1, t->encoding, NULL);
  1454.             } else {
  1455.                 *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1);
  1456.             }
  1457.         } else {
  1458.             *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1);
  1459.         }
  1460.         #endif
  1461.         if (!*t->p)
  1462.             return -1;
  1463.         ++t;
  1464.     }
  1465.     return 0;
  1466. }
  1467.  
  1468. static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char* c_str) {
  1469.     return __Pyx_PyUnicode_FromStringAndSize(c_str, (Py_ssize_t)strlen(c_str));
  1470. }
  1471. static CYTHON_INLINE char* __Pyx_PyObject_AsString(PyObject* o) {
  1472.     Py_ssize_t ignore;
  1473.     return __Pyx_PyObject_AsStringAndSize(o, &ignore);
  1474. }
  1475. static CYTHON_INLINE char* __Pyx_PyObject_AsStringAndSize(PyObject* o, Py_ssize_t *length) {
  1476. #if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT
  1477.     if (
  1478. #if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII
  1479.             __Pyx_sys_getdefaultencoding_not_ascii &&
  1480. #endif
  1481.             PyUnicode_Check(o)) {
  1482. #if PY_VERSION_HEX < 0x03030000
  1483.         char* defenc_c;
  1484.         PyObject* defenc = _PyUnicode_AsDefaultEncodedString(o, NULL);
  1485.         if (!defenc) return NULL;
  1486.         defenc_c = PyBytes_AS_STRING(defenc);
  1487. #if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII
  1488.         {
  1489.             char* end = defenc_c + PyBytes_GET_SIZE(defenc);
  1490.             char* c;
  1491.             for (c = defenc_c; c < end; c++) {
  1492.                 if ((unsigned char) (*c) >= 128) {
  1493.                     PyUnicode_AsASCIIString(o);
  1494.                     return NULL;
  1495.                 }
  1496.             }
  1497.         }
  1498. #endif
  1499.         *length = PyBytes_GET_SIZE(defenc);
  1500.         return defenc_c;
  1501. #else
  1502.         if (__Pyx_PyUnicode_READY(o) == -1) return NULL;
  1503. #if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII
  1504.         if (PyUnicode_IS_ASCII(o)) {
  1505.             *length = PyUnicode_GET_LENGTH(o);
  1506.             return PyUnicode_AsUTF8(o);
  1507.         } else {
  1508.             PyUnicode_AsASCIIString(o);
  1509.             return NULL;
  1510.         }
  1511. #else
  1512.         return PyUnicode_AsUTF8AndSize(o, length);
  1513. #endif
  1514. #endif
  1515.     } else
  1516. #endif
  1517. #if !CYTHON_COMPILING_IN_PYPY
  1518.     if (PyByteArray_Check(o)) {
  1519.         *length = PyByteArray_GET_SIZE(o);
  1520.         return PyByteArray_AS_STRING(o);
  1521.     } else
  1522. #endif
  1523.     {
  1524.         char* result;
  1525.         int r = PyBytes_AsStringAndSize(o, &result, length);
  1526.         if (unlikely(r < 0)) {
  1527.             return NULL;
  1528.         } else {
  1529.             return result;
  1530.         }
  1531.     }
  1532. }
  1533. static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) {
  1534.    int is_true = x == Py_True;
  1535.    if (is_true | (x == Py_False) | (x == Py_None)) return is_true;
  1536.    else return PyObject_IsTrue(x);
  1537. }
  1538. static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x) {
  1539.   PyNumberMethods *m;
  1540.   const char *name = NULL;
  1541.   PyObject *res = NULL;
  1542. #if PY_MAJOR_VERSION < 3
  1543.   if (PyInt_Check(x) || PyLong_Check(x))
  1544. #else
  1545.   if (PyLong_Check(x))
  1546. #endif
  1547.     return Py_INCREF(x), x;
  1548.   m = Py_TYPE(x)->tp_as_number;
  1549. #if PY_MAJOR_VERSION < 3
  1550.   if (m && m->nb_int) {
  1551.     name = "int";
  1552.     res = PyNumber_Int(x);
  1553.   }
  1554.   else if (m && m->nb_long) {
  1555.     name = "long";
  1556.     res = PyNumber_Long(x);
  1557.   }
  1558. #else
  1559.   if (m && m->nb_int) {
  1560.     name = "int";
  1561.     res = PyNumber_Long(x);
  1562.   }
  1563. #endif
  1564.   if (res) {
  1565. #if PY_MAJOR_VERSION < 3
  1566.     if (!PyInt_Check(res) && !PyLong_Check(res)) {
  1567. #else
  1568.     if (!PyLong_Check(res)) {
  1569. #endif
  1570.       PyErr_Format(PyExc_TypeError,
  1571.                    "__%.4s__ returned non-%.4s (type %.200s)",
  1572.                    name, name, Py_TYPE(res)->tp_name);
  1573.       Py_DECREF(res);
  1574.       return NULL;
  1575.     }
  1576.   }
  1577.   else if (!PyErr_Occurred()) {
  1578.     PyErr_SetString(PyExc_TypeError,
  1579.                     "an integer is required");
  1580.   }
  1581.   return res;
  1582. }
  1583. static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) {
  1584.   Py_ssize_t ival;
  1585.   PyObject *x;
  1586. #if PY_MAJOR_VERSION < 3
  1587.   if (likely(PyInt_CheckExact(b)))
  1588.       return PyInt_AS_LONG(b);
  1589. #endif
  1590.   if (likely(PyLong_CheckExact(b))) {
  1591.     #if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
  1592.      #if CYTHON_USE_PYLONG_INTERNALS
  1593.        switch (Py_SIZE(b)) {
  1594.        case -1: return -(sdigit)((PyLongObject*)b)->ob_digit[0];
  1595.        case  0: return 0;
  1596.        case  1: return ((PyLongObject*)b)->ob_digit[0];
  1597.        }
  1598.      #endif
  1599.     #endif
  1600.     return PyLong_AsSsize_t(b);
  1601.   }
  1602.   x = PyNumber_Index(b);
  1603.   if (!x) return -1;
  1604.   ival = PyInt_AsSsize_t(x);
  1605.   Py_DECREF(x);
  1606.   return ival;
  1607. }
  1608. static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) {
  1609.     return PyInt_FromSize_t(ival);
  1610. }
  1611.  
  1612.  
  1613. #endif /* Py_PYTHON_H */
  1614.  

On compile et on effecture l'édition de liens (sous Ubuntu 14.04) :

g++ -o my_prog.exe my_prog.cpp my_prog_cython.c 
	-I/usr/include/python2.7/ -L/usr/lib/x86_64-linux-gnu -lpython2.7

Le résultat à l'exécution est :

==============================
inside cython function!!!
==============================


Compiler NumPy avec le multi-threading

Pour prendre en compte le multi-threading avec NumPy il peut être nécessaire de recompiler avec OpenBlas comme suit :

Compiler OpenBlas

git clone git://github.com/xianyi/OpenBLAS
cd OpenBLAS && make FC=gfortran
sudo make PREFIX=/opt/OpenBLAS install
sudo ldconfig

Compiler NumPy avec OpenBlas

git clone https://github.com/numpy/numpy
cd numpy
cp site.cfg.example site.cfg
gedit site.cfg &

décommenter les lignes suivantes (on peut linker avec d'autres librairies comme Atlas ou MKL) :

[openblas]
libraries = openblas
library_dirs = /opt/OpenBLAS/lib
include_dirs = /opt/OpenBLAS/include

vérifier que la configuration est prise en compte :

python setup.py config
openblas_info:
  FOUND:
    libraries = ['openblas', 'openblas']
    library_dirs = ['/opt/OpenBLAS/lib']
    language = c

  FOUND:
    libraries = ['openblas', 'openblas']
    library_dirs = ['/opt/OpenBLAS/lib']
    language = c
    ....

compiler et installer :

python setup.py build && python setup.py install

finalement pour tester :

OMP_NUM_THREADS=4 python mon_script.py