More STL algorithms. Design Decisions. Doc No: N2569= Reply to: Matt Austern Date:

Similar documents
More STL algorithms (revision 2)

Unifying Operator and Function-Object Variants of Standard Library Algorithms

Working Draft, Technical Specification for C++ Extensions for Parallelism

Bring Back the Obvious Definition of count()

A Parallel Algorithms Library N3724

SFU CMPT Topic: Function Objects

Working Draft, Technical Specification for C++ Extensions for Parallelism, Revision 1

Elements of Programming

Programming Languages Technical Specification for C++ Extensions for Parallelism

Foundations of Programming, Volume I, Linear structures

Lecture 21 Standard Template Library. A simple, but very limited, view of STL is the generality that using template functions provides.

C++0x Proposal: Function template std::minmax and / or algorithm std::minmax_element Hervé Brönnimann. Abstract

CSCI-1200 Data Structures Spring 2018 Lecture 14 Associative Containers (Maps), Part 1 (and Problem Solving Too)

Concepts for the C++0x Standard Library: Iterators

p0616r0 - de-pessimize legacy <numeric> algorithms with std::move

Iterator Concepts for the C++0x Standard Library

MODULE 37 --THE STL-- ALGORITHM PART V

Beyond Counting. Owen Kaser. September 17, 2014

Template Library for Parallel For Loops

Lecture Notes on Quicksort

Lecture 7 Quicksort : Principles of Imperative Computation (Spring 2018) Frank Pfenning

Chapter Fourteen Bonus Lessons: Algorithms and Efficiency

Lecture Notes on Quicksort

Improving the Return Value of Erase-Like Algorithms

Bits, Words, and Integers

Item 3: Predicates, Part 2: Matters of State

Chapter 21a Other Library Issues

Lambdas in unevaluated contexts

MODULE 35 --THE STL-- ALGORITHM PART III

Major Language Changes, pt. 1

Functors. Cristian Cibils

Add shift to <algorithm>

Assignment 1: grid. Due November 20, 11:59 PM Introduction

CS 161 Computer Security

CSCI-1200 Data Structures Fall 2017 Lecture 13 Problem Solving Techniques

Boost.Compute. A C++ library for GPU computing. Kyle Lutz

Add shift to <algorithm>

TDDD38 - Advanced programming in C++

Bigger Better More. The new C++ Standard Library. Thomas Witt April Copyright 2009 Thomas Witt

\n is used in a string to indicate the newline character. An expression produces data. The simplest expression

Lecture 6: Arithmetic and Threshold Circuits

Lecture 1 Contracts. 1 A Mysterious Program : Principles of Imperative Computation (Spring 2018) Frank Pfenning

3.7 Denotational Semantics

This is already grossly inconvenient in present formalisms. Why do we want to make this convenient? GENERAL GOALS

Hardware versus software

COEN244: Class & function templates

Introduction to Asymptotic Running Time Analysis CMPSC 122

CS11 Advanced C++ Fall Lecture 1

Simplifying C++0x Concepts

Problem with Scanning an Infix Expression

Algorithm Efficiency & Sorting. Algorithm efficiency Big-O notation Searching algorithms Sorting algorithms

Introduction to C++ Introduction. Structure of a C++ Program. Structure of a C++ Program. C++ widely-used general-purpose programming language

Lecture Transcript While and Do While Statements in C++

Lecture Notes on Binary Search Trees

CSE 100: C++ TEMPLATES AND ITERATORS

Introduction to C++ with content from

SOFTWARE ENGINEERING DESIGN I

Chapter 24a More Numerics and Parallelism

6.001 Notes: Section 8.1

Practice Problems for the Final

MITOCW watch?v=4dj1oguwtem

Responses to National Body Comments for ISO/IEC PDTS 19750, C++ Extensions for Parallelism Version 2

Lecture 1 Contracts : Principles of Imperative Computation (Fall 2018) Frank Pfenning

(Refer Slide Time: 00:50)

Concepts for the C++0x Standard Library: Iterators (Revision 2)

Concepts for the C++0x Standard Library: Introduction

MITOCW watch?v=hverxup4cfg

Lecture 3: Recursion; Structural Induction

Basics of Java: Expressions & Statements. Nathaniel Osgood CMPT 858 February 15, 2011

Lecture 4 Searching Arrays

Lecture Notes on Linear Search

C++ Modern and Lucid C++ for Professional Programmers

Symbolic Execution and Proof of Properties

Guide to First-Order Logic Translations

AXIOMS FOR THE INTEGERS

Doc. No.: WG21/N0937=X3J16/ Date: 28 May 1996 Project: C++ Standard Library Reply to: Nathan Myers

C++ Basics. Data Processing Course, I. Hrivnacova, IPN Orsay

MARKING KEY The University of British Columbia MARKING KEY Computer Science 260 Midterm #2 Examination 12:30 noon, Thursday, March 15, 2012

Binary Search Trees. Contents. Steven J. Zeil. July 11, Definition: Binary Search Trees The Binary Search Tree ADT...

Efficient waiting for concurrent programs

To use various types of iterators with the STL algorithms ( ). To use Boolean functions to specify criteria for STL algorithms ( 23.8).

Proposed resolution for US104: Allocator-aware regular expressions (rev 3)

Adding std::*_semaphore to the atomics clause.

Lambdas in unevaluated contexts

Functions, Pointers, and the Basics of C++ Classes

CS2 Algorithms and Data Structures Note 1

Trees. Chapter 6. strings. 3 Both position and Enumerator are similar in concept to C++ iterators, although the details are quite different.

CS11 Advanced C++ Spring 2018 Lecture 2

Chapter 5 Errors. Bjarne Stroustrup

Outline. 1 About the course

MITOCW watch?v=kz7jjltq9r4

Overview of C++ Support in TI Compiler Tools July 2008

What will happen if we try to compile, link and run this program? Do you have any comments to the code?

Lesson 13 - Vectors Dynamic Data Storage

use static size for this buffer

Introduction to GIL, Boost and Generic Programming

14.1 Encoding for different models of computation

Data & Procedure Reasoning about correctness

Integer Algorithms and Data Structures

In our first lecture on sets and set theory, we introduced a bunch of new symbols and terminology.

Transcription:

Doc No: N2569=08-0079 Reply to: Matt Austern <austern@google.com> Date: 2008-02-29 More STL algorithms This paper proposes a number of nonstandard STL-style algorithms for inclusion in the standard. Nothing in this paper is novel or complicated. All of these algorithms have been around for years, and have been described in books and provided by library vendors as nonstandard extensions. All of them are easily implementable, and have been implemented. Most of them are taken from the SGI STL (http://www.sgi.com/tech/stl). This proposal is a pure extension. Design Decisions In most cases there aren't any very important decisions to be made once we've decided to provide the algorithm in the first place. Counting versions of copy The standard copy algorithm takes three arguments: a first/last input iterator pair to determine the input range, and a single output iterator to determine the start of the output range. Sometimes, however, it's more convenient to describe the operation as a starting point and a count than as a starting point and an ending point. This is usually just a matter of convenience, since we can usually convert between those forms by writing n = distance(first, last) or last = first, advance(last, n), but it can occasionally be more important if the iterators are of a type where converting between a range and a count would be expensive or impractical. (Input iterators that aren't forward iterators, for example.) The SGI STL provides copy_n and the corresponding version for initializing raw memory, uninitialized_copy_n. All, any, and none These three algorithms provide the ordinary mathematical operations,, and : given a range and a predicate, determine whether that predicate is true for all elements; whether there exists an element for which the predicate is true; or whether there exist no elements for which the predicate is true. Strictly speaking there is no need to provide all three of these algorithms (!none and any are equivalent), but all three of these operations feel equally fundamental. These three algorithms have accumulated various names over the years. I have taken the names any/none/all from the latest draft of Alex Stepanov and Paul McJones's Elements of Programming. copy_if This is a frequently requested addition, mentioned in (for example) the latest edition of The C++ Programming Language. It is formally redundant, since it's just the inverse of remove_copy_if: copying all elements that satisfy a predicate p is just the same as not copying all elements that satisfy!p. It's worth adding anyway. First, C++ isn't really a

functional language and transforming a predicate into its negation is sometimes awkward. Second, the workaround of using double negatives is not unconfusing. find_if_not Just as copy_if is the inverse of remove_copy_if, find_if_not is the inverse of find_if: it returns an iterator pointing to the first element that fails to satisfy a predicate p. It's worth adding for the same reason. Random sampling The standard contains random_shuffle, which randomly permutes a range with uniform distribution. A closely related operation is randomly selecting elements from a range. (Indeed, Knuth discusses those operations in a single subsection, "Random Sampling and Shuffling".) There are two important versions of random sampling, one of which randomly chooses n elements from a range of N elements and the other of which randomly chooses n elements from an input range whose size is initially unknown except that it is at least n. These two algorithms are not redundant, even theoretically. Knuth calls them "Algorithm S" and "Algorithm R". The SGI STL, which has provided them for many years, calls them random_sample and random_sample_n. Three-way lexicographical comparison The standard lexicographical comparison algorithm throws away information: if we know that lexicographical_compare(f1, l1, f2, l2) returns false, it could mean either that the second range is lexicographically less than the other or that the two are lexicographically equal. Given the existing interface, the only way for the user to get that extra information is with a second linear-time range traversal. Changing the interface, however, allows the lexicographical comparison to compute that extra information with just a single extra comparison. There are several possible way to of providing the extended version of lexicographical comparison. The SGI STL provides it as lexicographical_compare_3way, which uses the ordinary strcmp convention: the return value is negative if the first range is less than the second, zero if they are equal, positive if the first range is greater. Partition algorithms The original HP STL included partition, but not partition_copy, mainly because it wasn't clear what the partition_copy interface should be: how can you have a single output range when you're partitioning elements into two sets? T. K. Lakshman, then at SGI, pointed out what now seems obvious: partition_copy should copy to two output ranges. Partitioning a range imposes a structure on it. The standard now provides is_sorted and is_heap to test whether ranges have specific structures, and is_partitioned is useful for just the same reasons. One final partition algorithm is partition_point, which takes a partitioned range as input and finds the boundary between the elements that do and don't satisfy the partitioning predicate. This is just a variation of binary search. It generalizes the more common version of binary search, since searching for a value in a sorted range simply means finding the partition point between elements greater and less than that value. In fact, as Dave Abrahams pointed out, this is the most natural way to think about the standard binary search algorithms in the presence of heterogeneous comparisons. (And the wording in the C++0x draft already reflects that insight.)

Iota This algorithm is inspired by the APL ι operator. Like ι, the iota algorithm creates a range of sequentially increasing values. It's especially useful for testing, since permutations of {1, 2,... N} often make good test input, and it has been in the SGI STL for years. Exponentiation The SGI STL provides one more nonstandard algorithm, power. I am not proposing power for standardization at this time because it is too closely tied into concepts that don't yet exist in the standard, Monoid and Semigroup. The interface for power would look different depending on which of those concepts we want it to operate on, and, if we chose Monoid, we would have to standardize a mechanism for computing a monoid's identity element. The SGI STL addresses those questions, but not in a completely satisfactory way. More complete mechanisms are described in the draft of Elements of Programming. Proposed Wording Add the following text to an appropriate subsection of 20.6.4 [specialized.algorithms], and add the signatures to the header <memory> synopsis at the beginning of clause 20.6 [memory]. template <class InputIterator, class Size, class ForwardIterator> ForwardIterator uninitialized_copy_n(inputiterator first, Size n, ForwardIterator result); Effects: for ( ; n > 0; ++result, ++first, --n) { new (static_cast<void*>(&*result)) typename iterator_traits<forwarditerator>::value_type(*first); } Returns: result Add the following text to appropriate subsections of 25.1 [alg.nonmodifying], and add the signatures to the header <algorithm> synopsis at the beginning of clause 25 [algorithms]. bool all(inputiterator first, InputIterator last, Predicate pred); Returns: true if pred(*i) is true for every iterator in the range [first, last), and false otherwise. bool any(inputiterator first, InputIterator last, Predicate pred);

Returns: true if there exists any iterator in the range [first, last) such that pred(*i) is true, and false otherwise. bool none(inputiterator first, InputIterator last, Predicate pred); Returns: true if pred(*i) is false for every iterator in the range [first, last), and false otherwise. bool find_if_not(inputiterator first, InputIterator last, Predicate pred); Returns: the first iterator i in the range [first, last) such that pred(*i) is false, or last if there is no such iterator. Add the following text to appropriate subsections of 25.2 [alg.modifying.operators], and add the signatures to the header <algorithm> synopsis at the beginning of clause 25 [algorithms]. template <class InputIterator, class Size, class OutputIterator> OutputIterator copy_n(inputiterator first, Size n, OutputIterator result); Effects: Copies elements in the range [first, first+n) into the range [result, result+n) starting from first and proceeding to first+n. For each non-negative integer i<n, performs *(result+i) = *(first+i). Returns: result+n. Complexity: Exactly n assignments. template <class InputIterator, class OutputIterator, class Predicate> OutputIterator copy_if(inputiterator first, InputIterator last, OutputIterator result, Predicate pred); Requires: The ranges [first, last) and [result, result + (last - first)) shall not overlap. Effects: Copies all of the elements referred to by the iterator i in the range [first, last) for which pred(*i) is true. Returns: The end of the resulting range. Complexity: Exactly last - first applications of the corresponding predicate. Remarks: Stable. template <class InputIterator, class RandomAccessIterator> RandomAccessIterator random_sample(inputiterator first, InputIterator last, RandomAccessIterator ofirst, RandomAccessIterator olast); template <class InputIterator, class RandomAccessIterator, class

RandomNumberGenerator> RandomAccessIterator random_sample(inputiterator first, InputIterator last, RandomAccessIterator ofirst, RandomAccessIterator olast, RandomNumberGenerator& rand); template <class InputIterator, class RandomAccessIterator, class UniformRandomNumberGenerator> RandomAccessIterator random_sample(inputiterator first, InputIterator last, RandomAccessIterator ofirst, RandomAccessIterator olast, UniformRandomNumberGenerator& g); Requires: InputIterator's value type shall be Assignable, and shall be convertible to RandomAccessIterator's value type. RandomNumberGenerator shall have a return type that is convertible to InputIterator's difference type, and the call rand(n) shall return a randomly chosen value in the interval [0, n). The function object g shall meet the requirements of a uniform random number generator. [first, last) and [ofirst, olast) shall be valid and non-overlapping ranges. Effects: copies min(last-first, olast-ofirst) elements from [first, last) to [ofirst, olast), such that each possible sampling has equal probability of appearance. Returns: The end of the resulting range. Complexity: Linear in last-first. Remarks: Relative order within the input range is not preserved. The underlying sources of randomness is as described for random_shuffle. template <class ForwardIterator, class OutputIterator, class Distance> OutputIterator random_sample_n(forwarditerator first, ForwardIterator last, OutputIterator out, Distance n); template <class ForwardIterator, class OutputIterator, class Distance, class RandomNumberGenerator> OutputIterator random_sample_n(forwarditerator first, ForwardIterator last, OutputIterator out, Distance n, RandomNumberGenerator& rand); template <class ForwardIterator, class OutputIterator, class Distance, class UniformRandomNumberGenerator> OutputIterator random_sample_n(forwarditerator first, ForwardIterator last, OutputIterator out, Distance n, UniformRandomNumberGenerator& rand); Requires: ForwardIterator's value type shall be Assignable, and shall be writable to the out OutputIterator. The input and output ranges shall not overlap. RandomNumberGenerator shall have a return type that is convertible to ForwardIterator's difference type, and the call rand(n) shall return a randomly chosen value in the interval [0, n). The function object g shall meet the requirements of a uniform random number generator.

Effects: copies min(last-first, n) elements from [first, last) to out, such that each possible sampling has equal probability of appearance. Returns: The end of the resulting range. Complexity: Linear in last-first. Remarks: Stable. The underlying sources of randomness is as described for random_shuffle. template <class InputIterator, class OutputIterator1, class OutputIterator2, class Predicate> pair<outputiterator1, OutputIterator2> partition_copy(inputiterator first, InputIterator last, OutputIterator1 out_true, OutputIterator2 out_false, Predicate pred); Requires: InputIterator's value type shall be Assignable, and shall be writable to the out_true and out_false OutputIterators, and shall be convertible to Predicate's argument type. The input range shall not overlap with either of the output ranges. Effects: For each iterator i in [first, last), copies *i to the output range beginning with out_true if pred(*i) is true, or to the output range beginning with out_false otherwise. Returns: A pair p such that p.first is the end of the output range beginning with out_true and p.second is the end of the output range beginning with out_false. Complexity: Exactly last-first applications of pred. bool is_partitioned(inputiterator first, InputIterator last, Predicate pred); Requires: InputIterator's value type shall be convertible to Predicate's argument type. Returns: true if [first, last) is partitioned by pred, i.e. if all elements that satisfy pred appear before those that do not. Complexity: Linear. At most last-first applications of pred. template <class ForwardIterator, class Predicate> ForwardIterator partition_point(forwarditerator first, ForwardIterator last, Predicate pred); Requires: ForwardIterator's value type shall be convertible to Predicate's argument type. [first, last) shall be partitioned by pred, i.e. all elements that satisfy pred shall appear before those that do not. Returns: An iterator mid such that all(first, mid, pred) and none(mid, last, pred) are both true. Complexity: O(log(last-first)) applications of pred. Add the following text to an appropriate subsection of 25.3 [alg.sorting], and add the signature to the header <algorithm> synopsis at the beginning of clause 25 [algorithms].

template <class InputIterator1, class InputIterator2> int lexicographical_compare_3way(inputiterator1 first1, InputIterator1 last2, InputIterator2 first2, InputIterator2 last2); Returns: A negative number if the sequence of elements defined by the range [first1, last1) is lexicographically less than the sequence of elements defined by the range [first2, last2), a positive number if [first2, last2) is lexicographically less than [first1, last1), and zero if neither sequence is less than the other. Complexity: At most 2 min(last1-first1, last2-first2) comparisons. Remarks: The definition of lexicographical ordering is the same as for lexicographical_compare. Add the following text as a new subsection of 26.6 [numeric.ops], and add the signature to the header <numeric> synopsis at the beginning of clause 26.6 [numeric.ops]. template <class ForwardIterator, class T> void iota(forwarditerator first, ForwardIterator last, T value); Requires: T shall meet the requirements of CopyConstructible and Assignable types, and shall be convertible to Forwarditerator's value type. T shall provide an increment operator. Effects: For each element referred to by the iterator i in the range [first, last), assigns *i = value and increments value as if by ++value. Complexity: Exactly last-first increments and assignments. References Donald Knuth, The Art of Computer Programming (Third Edition). Volume 2: Seminumerical Algorithms. SGI, Standard Template Library Programmer's Guide, http://www.sgi.com/tech/stl Alex Stepanov and Paul McJones, Elements of Programming (draft), http://www.stepanovpapers.com/eop/lecture_all.pdf Bjarne Stroustrup, The C++ Programming Language (Special Edition).