From 04cb2cd39abbadab46e07d6e13f464d6c411b292 Mon Sep 17 00:00:00 2001 From: Raoul Gough Date: Tue, 7 Oct 2003 17:28:24 +0000 Subject: [PATCH] Initial revision [SVN r1644] --- .../suite/indexing/detail/test_performance.py | 85 +++++++++ .../indexing/detail2/python_iterator.cpp | 168 ++++++++++++++++++ .../python/suite/indexing/detail2/slice.cpp | 65 +++++++ 3 files changed, 318 insertions(+) create mode 100755 include/boost/python/suite/indexing/detail/test_performance.py create mode 100755 include/boost/python/suite/indexing/detail2/python_iterator.cpp create mode 100755 include/boost/python/suite/indexing/detail2/slice.cpp diff --git a/include/boost/python/suite/indexing/detail/test_performance.py b/include/boost/python/suite/indexing/detail/test_performance.py new file mode 100755 index 00000000..9c6f43c8 --- /dev/null +++ b/include/boost/python/suite/indexing/detail/test_performance.py @@ -0,0 +1,85 @@ +#!/usr/bin/python +# -*- mode:python -*- +# +# Python module test_performance.py +# +# Copyright (c) 2003 Raoul M. Gough +# +# Use, modification and distribution is subject to the Boost Software +# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy +# at http://www.boost.org/LICENSE_1_0.txt) +# +# History +# ======= +# 2003/10/ 5 rmg File creation +# +# $Id$ +# + +from time import clock +from testlinear import Vector + +def fillByAppend (container, size): + append = container.append + for count in range (size): + append (count) + +def fillByExtend (container, size): + extend = container.extend + for count in range (size / 100): + extend (range (count * 100, count * 100 + 100)) + +def search (container, item, iterations): + index = container.index + for count in range (iterations): + index (item) + +def reverse_part (container, start, end): + end -= 1 + while start < end: + temp = container[start] + container[start] = container[end] + container[end] = temp + start += 1 + end -= 1 + +def reorder (container, block = 10): + for count in range (len(container) / block): + reverse_part (container, count * block, count * block + block) + +def testPerformance (container): + size = 1000000 + start = clock() + fillByExtend (container, size) + print "Fill:", clock() - start + + start = clock() + search (container, container[size - 1], 10) + print "Search:", clock() - start + + start = clock() + reorder (container, 8) + reorder (container, 16) + reorder (container, 32) + print "Reorder:", clock() - start + +# print container[:20] +# print container[-20:] + + start = clock() + container.sort() + print "Sort:", clock() - start + + +print "list =====" +testPerformance ([]) +v1 = Vector() +v1.reserve (1000000) +print "vector (with reserve) =====" +testPerformance (v1) + +print "list =====" +testPerformance ([]) +print "vector (no reserve) =====" +testPerformance (Vector()) + diff --git a/include/boost/python/suite/indexing/detail2/python_iterator.cpp b/include/boost/python/suite/indexing/detail2/python_iterator.cpp new file mode 100755 index 00000000..015171a4 --- /dev/null +++ b/include/boost/python/suite/indexing/detail2/python_iterator.cpp @@ -0,0 +1,168 @@ +// -*- mode:c++ -*- +// +// Module python_iterator.cpp +// +// Copyright (c) 2003 Raoul M. Gough +// +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy +// at http://www.boost.org/LICENSE_1_0.txt) +// +// History +// ======= +// 2003/ 9/10 rmg File creation +// +// $Id$ +// + +#include + +//////////////////////////////////////////////////////////////////////////// +// python_iterator factory +/////////////////////////////////////////////////////////////////////////// + +std::auto_ptr +boost::python::indexing::make_iterator (boost::python::object temp) +{ + std::auto_ptr result; + + try + { + result.reset (new python_iter_iterator (temp)); + } + + catch (boost::python::error_already_set const &) + { + PyErr_Clear (); + + try + { + result.reset (new python_getitem_iterator (temp)); + } + + catch (boost::python::error_already_set const &) + { + PyErr_Clear (); + } + } + + return result; +} + +//////////////////////////////////////////////////////////////////////////// +// Base class (virtual) destructor +/////////////////////////////////////////////////////////////////////////// + +boost::python::indexing::python_iterator::~python_iterator () +{ +} + +//////////////////////////////////////////////////////////////////////////// +// python_getitem_iterator constructor +/////////////////////////////////////////////////////////////////////////// + +boost::python::indexing::python_getitem_iterator +::python_getitem_iterator (boost::python::object obj) + : mGetitemMethod (obj.attr ("__getitem__")) + , mIndex (0) + , mCurrent() +{ +} + +//////////////////////////////////////////////////////////////////////////// +// Get our next item (if any) +/////////////////////////////////////////////////////////////////////////// + +bool boost::python::indexing::python_getitem_iterator::next () +{ + bool result = true; // Assume success + + try + { + mCurrent = mGetitemMethod (mIndex); + ++mIndex; + } + + catch (boost::python::error_already_set const &) + { + if (PyErr_ExceptionMatches (PyExc_IndexError)) + { + // Eat this exception + PyErr_Clear (); + mCurrent = boost::python::object (); + result = false; + } + + else + { + // Pass it up the line + throw; + } + } + + return result; +} + +//////////////////////////////////////////////////////////////////////////// +// Return our current item +/////////////////////////////////////////////////////////////////////////// + +boost::python::object +boost::python::indexing::python_getitem_iterator::current () const +{ + return mCurrent; +} + +//////////////////////////////////////////////////////////////////////////// +// python_iter_iterator constructor +/////////////////////////////////////////////////////////////////////////// + +boost::python::indexing::python_iter_iterator +::python_iter_iterator (boost::python::object obj) + : mNextMethod (obj.attr ("__iter__")().attr ("next")) + , mCurrent() +{ +} + +//////////////////////////////////////////////////////////////////////////// +// Get our next item (if any) +/////////////////////////////////////////////////////////////////////////// + +bool boost::python::indexing::python_iter_iterator::next () +{ + bool result = true; // Assume success + + try + { + mCurrent = mNextMethod (); + } + + catch (boost::python::error_already_set const &) + { + if (PyErr_ExceptionMatches (PyExc_StopIteration)) + { + // Eat this exception + PyErr_Clear (); + mCurrent = boost::python::object (); + result = false; + } + + else + { + // Pass it up the line + throw; + } + } + + return result; +} + +//////////////////////////////////////////////////////////////////////////// +// Return our current item +/////////////////////////////////////////////////////////////////////////// + +boost::python::object +boost::python::indexing::python_iter_iterator::current () const +{ + return mCurrent; +} diff --git a/include/boost/python/suite/indexing/detail2/slice.cpp b/include/boost/python/suite/indexing/detail2/slice.cpp new file mode 100755 index 00000000..cfd740bb --- /dev/null +++ b/include/boost/python/suite/indexing/detail2/slice.cpp @@ -0,0 +1,65 @@ +// -*- mode:c++ -*- +// +// Module slice.cpp +// +// Copyright (c) 2003 Raoul M. Gough +// +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy +// at http://www.boost.org/LICENSE_1_0.txt) +// +// History +// ======= +// 2003/ 9/10 rmg File creation +// +// $Id$ +// + +#include + +///////////////////////////////////////////////////////////////////////////// +// Check that setLength has been called, and throw otherwise +///////////////////////////////////////////////////////////////////////////// + +void boost::python::indexing::slice::validate () const +{ + if (mDirection == 0) + { + PyErr_SetString (PyExc_RuntimeError + , "slice access attempted before setLength called"); + boost::python::throw_error_already_set(); + } +} + +///////////////////////////////////////////////////////////////////////////// +// Set up our member variables for a sequence of a given length +///////////////////////////////////////////////////////////////////////////// + +void boost::python::indexing::slice::setLength (int sequenceLength) +{ + PySlice_GetIndices ((PySliceObject *) this->ptr() + , sequenceLength + , &mStart + , &mStop + , &mStep); + + if (mStep == 0) + { + // Can happen with Python prior to 2.3 + PyErr_SetString (PyExc_ValueError, "slice step cannot be zero"); + boost::python::throw_error_already_set (); + } + + mStart = std::max (0, std::min (sequenceLength, mStart)); + mStop = std::max (0, std::min (sequenceLength, mStop)); + mDirection = (mStep > 0) ? 1 : -1; +} + +///////////////////////////////////////////////////////////////////////////// +// Check if an index is within the range of this slice +///////////////////////////////////////////////////////////////////////////// + +bool boost::python::indexing::slice::inRange (int index) +{ + return ((mStop - index) * mDirection) > 0; +}