Submit Search
Upload
ACCU Keynote by Andrei Alexandrescu
•
4 likes
•
2,632 views
A
Andrei Alexandrescu
Follow
Andrei discusses C++ concepts, sentinels, and a new fast partitioning algorithm.
Read less
Read more
Software
Report
Share
Report
Share
1 of 47
Download now
Download to read offline
Recommended
DConf 2016 Opening Keynote
DConf 2016 Opening Keynote
Andrei Alexandrescu
Generic Programming Galore Using D
Generic Programming Galore Using D
Andrei Alexandrescu
Three, no, Four Cool Things About D
Three, no, Four Cool Things About D
Andrei Alexandrescu
Value Objects, Full Throttle (to be updated for spring TC39 meetings)
Value Objects, Full Throttle (to be updated for spring TC39 meetings)
Brendan Eich
Value objects in JS - an ES7 work in progress
Value objects in JS - an ES7 work in progress
Brendan Eich
Andrei Alexandrescu keynote at CSDN 2007 in Beijing, China
Andrei Alexandrescu keynote at CSDN 2007 in Beijing, China
Andrei Alexandrescu
C++17 - the upcoming revolution (Code::Dive 2015)/
C++17 - the upcoming revolution (Code::Dive 2015)/
Sławomir Zborowski
DConf 2016: What Parnas72 Means for D by Luis Marques
DConf 2016: What Parnas72 Means for D by Luis Marques
Andrei Alexandrescu
Recommended
DConf 2016 Opening Keynote
DConf 2016 Opening Keynote
Andrei Alexandrescu
Generic Programming Galore Using D
Generic Programming Galore Using D
Andrei Alexandrescu
Three, no, Four Cool Things About D
Three, no, Four Cool Things About D
Andrei Alexandrescu
Value Objects, Full Throttle (to be updated for spring TC39 meetings)
Value Objects, Full Throttle (to be updated for spring TC39 meetings)
Brendan Eich
Value objects in JS - an ES7 work in progress
Value objects in JS - an ES7 work in progress
Brendan Eich
Andrei Alexandrescu keynote at CSDN 2007 in Beijing, China
Andrei Alexandrescu keynote at CSDN 2007 in Beijing, China
Andrei Alexandrescu
C++17 - the upcoming revolution (Code::Dive 2015)/
C++17 - the upcoming revolution (Code::Dive 2015)/
Sławomir Zborowski
DConf 2016: What Parnas72 Means for D by Luis Marques
DConf 2016: What Parnas72 Means for D by Luis Marques
Andrei Alexandrescu
Return of c++
Return of c++
Yongwei Wu
How to make a large C++-code base manageable
How to make a large C++-code base manageable
corehard_by
GALE: Geometric active learning for Search-Based Software Engineering
GALE: Geometric active learning for Search-Based Software Engineering
CS, NcState
He stopped using for/while loops, you won't believe what happened next!
He stopped using for/while loops, you won't believe what happened next!
François-Guillaume Ribreau
Designing a machine learning algorithm for Apache Spark
Designing a machine learning algorithm for Apache Spark
Marco Gaido
10 declarative-control-flow.handouts
10 declarative-control-flow.handouts
Andrei Alexandrescu
Lecture1
Lecture1
tarikh007
Arduino experimenters guide hq
Arduino experimenters guide hq
Andreis Santos
How to Lose Functional Programming at Work
How to Lose Functional Programming at Work
Robert Pearce
Arduino experimenters guide ARDX
Arduino experimenters guide ARDX
Johnny Parrales
The Present and Future of the Web Platform
The Present and Future of the Web Platform
C4Media
ESL Anyone?
ESL Anyone?
DVClub
2 Years of Real World FP at REA
2 Years of Real World FP at REA
kenbot
The Need for Async @ ScalaWorld
The Need for Async @ ScalaWorld
Konrad Malawski
SAST, fight against potential vulnerabilities
SAST, fight against potential vulnerabilities
Andrey Karpov
DAA Notes.pdf
DAA Notes.pdf
SauravPawar14
Atmosphere Conference 2015: Need for Async: In pursuit of scalable internet-s...
Atmosphere Conference 2015: Need for Async: In pursuit of scalable internet-s...
PROIDEA
C sharp 8.0 new features
C sharp 8.0 new features
MSDEVMTL
C sharp 8.0 new features
C sharp 8.0 new features
Miguel Bernard
Scilab: Computing Tool For Engineers
Scilab: Computing Tool For Engineers
Naren P.R.
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
StefanoLambiase
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEE
VICTOR MAESTRE RAMIREZ
More Related Content
Similar to ACCU Keynote by Andrei Alexandrescu
Return of c++
Return of c++
Yongwei Wu
How to make a large C++-code base manageable
How to make a large C++-code base manageable
corehard_by
GALE: Geometric active learning for Search-Based Software Engineering
GALE: Geometric active learning for Search-Based Software Engineering
CS, NcState
He stopped using for/while loops, you won't believe what happened next!
He stopped using for/while loops, you won't believe what happened next!
François-Guillaume Ribreau
Designing a machine learning algorithm for Apache Spark
Designing a machine learning algorithm for Apache Spark
Marco Gaido
10 declarative-control-flow.handouts
10 declarative-control-flow.handouts
Andrei Alexandrescu
Lecture1
Lecture1
tarikh007
Arduino experimenters guide hq
Arduino experimenters guide hq
Andreis Santos
How to Lose Functional Programming at Work
How to Lose Functional Programming at Work
Robert Pearce
Arduino experimenters guide ARDX
Arduino experimenters guide ARDX
Johnny Parrales
The Present and Future of the Web Platform
The Present and Future of the Web Platform
C4Media
ESL Anyone?
ESL Anyone?
DVClub
2 Years of Real World FP at REA
2 Years of Real World FP at REA
kenbot
The Need for Async @ ScalaWorld
The Need for Async @ ScalaWorld
Konrad Malawski
SAST, fight against potential vulnerabilities
SAST, fight against potential vulnerabilities
Andrey Karpov
DAA Notes.pdf
DAA Notes.pdf
SauravPawar14
Atmosphere Conference 2015: Need for Async: In pursuit of scalable internet-s...
Atmosphere Conference 2015: Need for Async: In pursuit of scalable internet-s...
PROIDEA
C sharp 8.0 new features
C sharp 8.0 new features
MSDEVMTL
C sharp 8.0 new features
C sharp 8.0 new features
Miguel Bernard
Scilab: Computing Tool For Engineers
Scilab: Computing Tool For Engineers
Naren P.R.
Similar to ACCU Keynote by Andrei Alexandrescu
(20)
Return of c++
Return of c++
How to make a large C++-code base manageable
How to make a large C++-code base manageable
GALE: Geometric active learning for Search-Based Software Engineering
GALE: Geometric active learning for Search-Based Software Engineering
He stopped using for/while loops, you won't believe what happened next!
He stopped using for/while loops, you won't believe what happened next!
Designing a machine learning algorithm for Apache Spark
Designing a machine learning algorithm for Apache Spark
10 declarative-control-flow.handouts
10 declarative-control-flow.handouts
Lecture1
Lecture1
Arduino experimenters guide hq
Arduino experimenters guide hq
How to Lose Functional Programming at Work
How to Lose Functional Programming at Work
Arduino experimenters guide ARDX
Arduino experimenters guide ARDX
The Present and Future of the Web Platform
The Present and Future of the Web Platform
ESL Anyone?
ESL Anyone?
2 Years of Real World FP at REA
2 Years of Real World FP at REA
The Need for Async @ ScalaWorld
The Need for Async @ ScalaWorld
SAST, fight against potential vulnerabilities
SAST, fight against potential vulnerabilities
DAA Notes.pdf
DAA Notes.pdf
Atmosphere Conference 2015: Need for Async: In pursuit of scalable internet-s...
Atmosphere Conference 2015: Need for Async: In pursuit of scalable internet-s...
C sharp 8.0 new features
C sharp 8.0 new features
C sharp 8.0 new features
C sharp 8.0 new features
Scilab: Computing Tool For Engineers
Scilab: Computing Tool For Engineers
Recently uploaded
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
StefanoLambiase
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEE
VICTOR MAESTRE RAMIREZ
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.ppt
kotipi9215
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
Tier1 app
The Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdf
Power Karaoke
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
Christina Lin
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio, Inc.
MYjobs Presentation Django-based project
MYjobs Presentation Django-based project
AnoyGreter
Asset Management Software - Infographic
Asset Management Software - Infographic
Hr365.us smith
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
stazi3110
EY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
Neo4j
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Ahmed Mohamed
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
9953056974 Low Rate Call Girls In Saket, Delhi NCR
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
Ortus Solutions, Corp
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with Azure
Dinusha Kumarasiri
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New Features
Łukasz Chruściel
Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)
Hr365.us smith
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
Alina Yurenko
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...
OnePlan Solutions
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
umasea
Recently uploaded
(20)
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEE
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.ppt
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
The Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdf
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
MYjobs Presentation Django-based project
MYjobs Presentation Django-based project
Asset Management Software - Infographic
Asset Management Software - Infographic
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
EY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with Azure
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New Features
Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
ACCU Keynote by Andrei Alexandrescu
1.
© 2015- Andrei
Alexandrescu. Do not redistribute. 1 / 39 There’s Treasure Everywhere Prepared for ACCU 2016 Andrei Alexandrescu, Ph.D. 2016-04-21
2.
Working Title © 2015-
Andrei Alexandrescu. Do not redistribute. 2 / 39 How to Write and Deliver a Keynote
3.
What’s (in) a
Keynote? © 2015- Andrei Alexandrescu. Do not redistribute. 3 / 39 • Friend 1: “Just talk about things you like.” • Friend 2: “Should have no code and no math.”
4.
Things I Like ©
2015- Andrei Alexandrescu. Do not redistribute. 4 / 39
5.
Things I Like ©
2015- Andrei Alexandrescu. Do not redistribute. 4 / 39 • Confusing aphorisms
6.
Confusing Aphorisms © 2015-
Andrei Alexandrescu. Do not redistribute. 5 / 39 When you hear hoofbeats, think horses, not zebras.
7.
Confusing Aphorisms © 2015-
Andrei Alexandrescu. Do not redistribute. 6 / 39 When you hear hoofbeats, think horses, not zebras. —Not an African Proverb
8.
Things I Like ©
2015- Andrei Alexandrescu. Do not redistribute. 7 / 39 • Confusing aphorisms
9.
Things I Like ©
2015- Andrei Alexandrescu. Do not redistribute. 7 / 39 • Confusing aphorisms • Fast code
10.
Things I Like ©
2015- Andrei Alexandrescu. Do not redistribute. 7 / 39 • Confusing aphorisms • Fast code • C++ Concepts
11.
Toto Washlet © 2015-
Andrei Alexandrescu. Do not redistribute. 8 / 39
12.
The Toto Company ©
2015- Andrei Alexandrescu. Do not redistribute. 9 / 39 • Offers 8 washlet models
13.
The Toto Company ©
2015- Andrei Alexandrescu. Do not redistribute. 9 / 39 • Offers 8 washlet models • Of these, 7 have a remote control
14.
The Toto Company ©
2015- Andrei Alexandrescu. Do not redistribute. 9 / 39 • Offers 8 washlet models • Of these, 7 have a remote control • A remote control
15.
Washlets with Remotes ©
2015- Andrei Alexandrescu. Do not redistribute. 10 / 39 • Combine two nice things • Complex and interesting • Modern and cool • Unlikely to be super useful in practice
16.
“Why Concepts didn’t
make C++17” © 2015- Andrei Alexandrescu. Do not redistribute. 11 / 39 • Not enough time
17.
“Why Concepts didn’t
make C++17” © 2015- Andrei Alexandrescu. Do not redistribute. 11 / 39 • Not enough time • “The Concepts TS does not specify any concept definitions”
18.
“Why Concepts didn’t
make C++17” © 2015- Andrei Alexandrescu. Do not redistribute. 11 / 39 • Not enough time • “The Concepts TS does not specify any concept definitions” • “Use of concepts sometimes results in worse error messages”
19.
Upcoming © 2015- Andrei
Alexandrescu. Do not redistribute. 12 / 39 “Why Concepts did make C++20”
20.
Sentinels © 2015- Andrei
Alexandrescu. Do not redistribute. 13 / 39
21.
Let’s talk about
linear find © 2015- Andrei Alexandrescu. Do not redistribute. 14 / 39 • Nothing out of the ordinary: Range find(Range, E)(Range r, E e) { for (; !r.empty; r.popFront) { if (r.front == e) break; } return r; } • Implemented many times in many languages
22.
To index or
not to index © 2015- Andrei Alexandrescu. Do not redistribute. 15 / 39 • Indexed access and pointer arithmetic changed relative speed over years • Today: indexed access has a slight edge ◦ Less aliasing ◦ CPU has sophisticated indexed addressing
23.
Linear find using
random access © 2015- Andrei Alexandrescu. Do not redistribute. 16 / 39 Range find(Range, E)(Range r, E e) { size_t i = 0; for (; i != r.length; ++i) { if (r[i] == e) break; } return r[i .. $]; } • Task: make it faster
24.
Linear find with
sentinel © 2015- Andrei Alexandrescu. Do not redistribute. 17 / 39 Range find(Range, E)(Range r, E e) { auto c = r[$ - 1]; r[$ - 1] = e; size_t i = 0; { scope(exit) r[$ - 1] = c; for (;; ++i) if (r[i] == e) break; } if (i + 1 == r.length && c != e) ++i; return r[i .. $]; }
25.
But. . .
but. . . © 2015- Andrei Alexandrescu. Do not redistribute. 18 / 39 • That doesn’t work for all types! • r[$ - 1] = c may throw • Also, find itself doesn’t work for all types ◦ Need to define only when we should • Need to choose “right” implementation automatically ◦ With sentinel for certain types ◦ Conservative for the others
26.
Linear find with
sentinel, take 2 © 2015- Andrei Alexandrescu. Do not redistribute. 19 / 39 Range find(Range, E)(Range r, E e) if (isInputRange!Range && is(typeof(r.front == e) == bool) ) { ... } • is(typeof(e) == T) Does expression e “work” and has type T? • e must look like an expression syntactically • Boolean returned, compilation not stopped ◦ SFINAE on steroids • Still, how to choose with/without sentinel?
27.
static if to
the rescue © 2015- Andrei Alexandrescu. Do not redistribute. 20 / 39 Range find(R, E)(R r, E e) if (isInputRange!R && is(typeof(r.front == e) : bool)) { static if (isRandomAccessRange!R && hasSlicing!R) { static if (is(typeof( () nothrow { r[0] = r[0]; } ))) { ... sentinel implementation ... } else { ... indexed implementation ... } } else { ... conservative implementation ... } }
28.
Please note © 2015-
Andrei Alexandrescu. Do not redistribute. 21 / 39 • Sentinel technique old as dust • Yet not applicable directly to generic code • Must use proper introspection techniques • is and static if widely applicable ◦ Mold structure depending on capabilities ◦ stdlib: static if every 88 lines as wc counts • Does the optimization help?
29.
Find with Sentinel ©
2015- Andrei Alexandrescu. Do not redistribute. 22 / 39 5 6 7 8 9 10 0 2 4 6 Input size [millions of elements] Time[ms]
30.
Relative Speedup © 2015-
Andrei Alexandrescu. Do not redistribute. 23 / 39 5 6 7 8 9 10 20 25 30 35 40 Input size [millions of elements] Speedup[%]
31.
Sentinels © 2015- Andrei
Alexandrescu. Do not redistribute. 24 / 39 • Widely applicable technique • Let’s use them for something more complex • How about Tony Hoare’s partition? ◦ Workhorse of sorting and the selection problem
32.
Baseline (1/2) © 2015-
Andrei Alexandrescu. Do not redistribute. 25 / 39 size_t pivotPartition(Range)(Range r, size_t pivot) { r.swapAt(pivot, 0); size_t lo = 1, hi = r.length - 1; loop: for (;; lo++, hi--) { for (;; ++lo) { if (lo > hi) break loop; if (r[lo] >= r[0]) break; } // found the left bound: r[lo] >= r[0]
33.
Baseline (2/2) © 2015-
Andrei Alexandrescu. Do not redistribute. 26 / 39 // found the left bound: r[lo] >= r[0] for (;; --hi) { if (lo >= hi) break loop; if (r[0] >= r[hi]) break; } // found the right bound: r[hi] <= r[0] // swap them & make progress r.swapAt(lo, hi); } --lo; r.swapAt(lo, 0); return lo; }
34.
© 2015- Andrei
Alexandrescu. Do not redistribute. 27 / 39 Make It Faster
35.
Accelerating pivotPartition © 2015-
Andrei Alexandrescu. Do not redistribute. 28 / 39 • Currently: find from left, find from right, swap, make progress • Done when indexes meet • Many index checks interspersed with actual work • Can’t plant a sentinel in the “middle”—final pivot position unknown
36.
Key Idea © 2015-
Andrei Alexandrescu. Do not redistribute. 29 / 39 • Plant sentinels at both ends • Create a “vacancy” in the range • Break swapAt into two assignments • An assignment fills a vacancy and leaves another one Half swap! • Work becomes matter of moving the vacancy around • At the end fill back the vacancy
37.
Implementation (1/3): Setup ©
2015- Andrei Alexandrescu. Do not redistribute. 30 / 39 size_t pivotPartition(Range)(Range r, size_t pivot) { if (r.length <= 1) return 0; // Put pivot at the front r.swapAt(pivot, 0); auto p = r[0]; // Plant the pivot in the end as well as a sentinel auto save = r[$ - 1]; r[$ - 1] = p; // r[$ - 1] is now vacant
38.
Implementation (2/3): Core ©
2015- Andrei Alexandrescu. Do not redistribute. 31 / 39 size_t lo = 0, hi = r.length - 1; for (;;) { do ++lo; while (r[lo] < p); r[hi] = r[lo]; do --hi; while (p < r[hi]); if (lo >= hi) break; r[lo] = r[hi]; }
39.
Implementation (3/3): Fixup ©
2015- Andrei Alexandrescu. Do not redistribute. 32 / 39 assert(lo - hi <= 2); assert(p >= r[hi]); if (lo == hi + 2) { assert(r[hi + 1] >= p); r[lo] = r[hi + 1]; --lo; } r[lo] = save; if (p < save) --lo; assert(p >= r[lo]); r.swapAt(0, lo); return lo; }
40.
Partition © 2015- Andrei
Alexandrescu. Do not redistribute. 33 / 39 5 6 7 8 9 10 0 10 20 30 Input size [millions of elements] Time[ms]
41.
Partition Speedup © 2015-
Andrei Alexandrescu. Do not redistribute. 34 / 39 5 6 7 8 9 10 17 18 19 20 21 22 Input size [millions of elements] Speedup[%]
42.
Credit © 2015- Andrei
Alexandrescu. Do not redistribute. 35 / 39 • Thought I invented this! • Nope: “Engineering of a Quicksort Partitioning Algorithm”, Abhyankar & Ingle, Journal of Global Research in Computer Science, Feb 2011 ◦ “Vacancy” idea, cannot choose any pivot
43.
More Sentinels © 2015-
Andrei Alexandrescu. Do not redistribute. 36 / 39 • These sentinel-based optimizations are not cherry picked! • Dot product • Set intersection • Merge sorted lists • Lexing and parsing
44.
There’s Treasure Everywhere ©
2015- Andrei Alexandrescu. Do not redistribute. 37 / 39 • You just have to find it
45.
There’s Treasure Everywhere ©
2015- Andrei Alexandrescu. Do not redistribute. 37 / 39 • You just have to find it • (by using introspection)
46.
Fastware © 2015- Andrei
Alexandrescu. Do not redistribute. 38 / 39 • A cornucopia of optimization techniques • Benchmarking Techniques • Strength Reduction • Cache Friendliness • Indirect Write Elision • Memoization and Obliviation • Hoisting and Lowering • . . . and many more!
47.
© 2015- Andrei
Alexandrescu. Do not redistribute. 39 / 39 Destroy!
Download now