Friday, July 16, 2021

C++ versus Python solving one interesting problem from the field of number theory

UPDATE as of 18/07/201 for C++ versus Python solving one problem from the field of number theory 

The version of C++ code here differs from the first one been posted at Lxer.com . Vector "v1" been pushed back by 2D vector "vec" is supposed to be re-declared before every next push  back by "vec" versus option of been cleaned up in previous version of compilation. I just believe that attempt to follow previous schema doesn't work properly as it did before due to pushing back the same variable "j" by vector "v1" in the loop preparing "v1" to be pushed by "vec".  

Original problem itself

Write a program that searches among the integers that belong to the numerical segment [174457;174505], numbers that have exactly two different natural divisors, not counting the unit and the number itself. For each of the found number, write these two divisors into the table on the screen with a new lines in ascending order of the product of these two divisors. Divisors in the table row must also follow in ascending order.

We intend to assembly  Python External C++ procedure using 2D vector to solve the the task mentioned  above for segment [174457;184505] without significant performance penalty, which would affect pure Python module runtime


(.env) [boris@fedora33server NEWFORWARD]$ cat procVector.h

#pragma once

#include <iostream>

#include <vector>

#include <cstddef>

namespace abc {

std::vector<std::vector<int> >  resultList(int m, int n);

}

(.env) [boris@fedora33server NEWFORWARD]$ cat procVector.cpp

#include <iostream>

#include <vector>

#include <cstddef>

#include <cmath>

#pragma GCC diagnostic ignored "-Wsign-compare"

namespace abc {

std::vector<std::vector<int> >  resultList(int m, int n)

{

   std::vector<std::vector<int> > vec;

   int j,cntDiv;

    for (int i = m; i <= n  ; i++) {

        std::vector<int> v1;    

        cntDiv = 0;

      for (j = 2; j < i; j++)

      {

          if (i%j == 0)

          {

              cntDiv +=1;

              v1.push_back(j);

          }

      }           

      if (cntDiv == 2)

      {        

         vec.push_back(v1);

      }

     } 

 return vec;

};

} //namespace















(.env) [boris@fedora33server NEWFORWARD]$ cat mainVector.cpp

#include <Python.h>

#include <iostream>

#include <vector>

#include <cstddef>

#include <fstream>

#include <cstdlib>

#include "procVector.h"

#pragma GCC diagnostic ignored "-Wsign-compare"

using std::endl;

using std::ofstream;

#pragma GCC diagnostic ignored "-Wsign-compare"

extern "C"{}

namespace {

static PyObject *resList(PyObject* self, PyObject* args)

{

    ofstream outdata;

    int m1,n1;

    if(!PyArg_ParseTuple(args,"ii",&m1,&n1))

        return NULL;

    outdata.open("./outvector.dat"); 

    std::vector<std::vector<int> > rez = abc::resultList(m1,n1);

    // Writing to file content of the 2D vector

    for (int i = 0; i < rez.size(); i++) {

       for (int j = 0; j < rez[i].size(); j++)

           outdata << rez[i][j] << " ";

       outdata << endl;

  }

    return Py_None ;

};

// Our Module's Function Definition structure

// We require this `NULL` to signal the end of our method

// definition

static PyMethodDef myMethodsTable[] = {

    { "resList", resList, METH_VARARGS, "Tracking factorial" },

    { NULL, NULL, 0, NULL }

};

// Our Module Definition struct

static struct PyModuleDef myModule = {

    PyModuleDef_HEAD_INIT,

    "myModule",

    "Test Module",

    -1,

    myMethodsTable

};

// Initializes our module using our above struct

PyMODINIT_FUNC PyInit_myModule(void)

{

    return PyModule_Create(&myModule);

};

} //namespace


(.env) [boris@fedora33server NEWFORWARD]$ cat setup.py

from distutils.core import setup, Extension

import sysconfig

language = 'c++'

std = 'c++20'

default_compile_args = sysconfig.get_config_var('CFLAGS').split()

extra_compile_args = [f"-std={std}", "-Wall", "-Wextra", "-Werror", "-DNDEBUG", "-O3"]

setup(name = 'myModule', version = '1.0',  \

   ext_modules = [Extension('myModule', ['mainVector.cpp','procVector.cpp'])])

*******************************************************

Now build and install Shared Library containing required C++

procedure

*******************************************************

$ python setup.py install

(.env) [boris@fedora33server build]$ ls -CRl

.:

total 0

drwxrwxr-x. 2 boris boris 53 Jul 15 16:46 lib.linux-x86_64-3.9

drwxrwxr-x. 2 boris boris 46 Jul 15 16:46 temp.linux-x86_64-3.9

./lib.linux-x86_64-3.9:

total 224

-rwxrwxr-x. 1 boris boris 225856 Jul 15 16:46 myModule.cpython-39-x86_64-linux-gnu.so

./temp.linux-x86_64-3.9:

total 408

-rw-rw-r--. 1 boris boris 221464 Jul 15 16:46 mainVector.o

-rw-rw-r--. 1 boris boris 189056 Jul 15 16:46 procVector.o


(.env) [boris@fedora33server NEWFORWARD]$ cat MyProg.py

import myModule

# a = int(input("Input start   number : "))

# b = int(input("Input finish  number : "))

# Initial segment [174457;174505] intentionally increased 

# to make Python performance hardly acceptable

a = 174457

b = 184505

myModule.resList(a,b)

lines = []

with open('./outvector.dat') as f:

    lines = f.readlines()

for line in lines:

    print(line)

(.env) [boris@fedora33server NEWFORWARD]$ cat speed.sh

date

python MyProg.py

date

(.env) [boris@fedora33server NEWFORWARD]$ ./speed.sh

Thu Jul 15 04:46:20 PM MSK 2021

3 58153 

7 24923 

59 2957 

13 13421 

149 1171 

5 34897 

211 827 

. . . . . 

3 61487 

2 92233 

29 6361 

2 92237 

3 61493 

2 92243 

5 36899 

7 26357 

17 10853 

2 92251 

5 36901 

Thu Jul 15 04:46:24 PM MSK 2021



1 comment:

  1. You should resize the vector to fit the size of the data, and stop using push_back just assign values at vector elements in the properly sized vector.

    ReplyDelete