惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

aimingoo的专栏
aimingoo的专栏
宝玉的分享
宝玉的分享
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
WordPress大学
WordPress大学
V
V2EX
Apple Machine Learning Research
Apple Machine Learning Research
J
Java Code Geeks
腾讯CDC
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Engineering at Meta
Engineering at Meta
L
LangChain Blog
Jina AI
Jina AI
博客园 - 叶小钗
B
Blog RSS Feed
Recent Announcements
Recent Announcements
H
Help Net Security
小众软件
小众软件
大猫的无限游戏
大猫的无限游戏
B
Blog
云风的 BLOG
云风的 BLOG
Blog — PlanetScale
Blog — PlanetScale
D
DataBreaches.Net
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
罗磊的独立博客

The Old New Thing

Why do Microsoft job levels start in the high 50's instead of starting at a sane number like 1? - The Old New Thing Why didn't Read­Directory­ChangesW provide a way to correlate the two sides of a rename operation? - The Old New Thing How can I remove the Close button from my window caption? - The Old New Thing Why is the x86 undefined instruction called ud2? Why 2? - The Old New Thing What algorithm did Windows XP use to choose your initial user picture? - The Old New Thing A sample use of the winstart.bat file in Windows 95 - The Old New Thing Why don't we allow stacks to be sparse, instead of forcing them to be contiguous? - The Old New Thing What happens if you change a window class's GCL_CB­WND­EXTRA? - The Old New Thing The case of the progress callback that never got called when progress happened - The Old New Thing The perils of binding to value types in XAML - The Old New Thing Microspeak: Funded / unfunded - The Old New Thing AWE does not require PAE, though PAE makes it much more useful - The Old New Thing On forcing all derived classes to implement a specific non-virtual method, part 2 - The Old New Thing On forcing all derived classes to implement a specific non-virtual method, part 1 - The Old New Thing In the product end game, every change carries significant risk, episode 2 - The Old New Thing Why didn't the Windows Entertainment Pack just run the MS-DOS version inside an emulator? - The Old New Thing Comparing the two holograms on the Windows 95 box - The Old New Thing Reducing C++ template bloat by factoring out the type-dependent portions of the function, practical exam - The Old New Thing Reducing C++ template bloat by factoring out the type-dependent portions of the function - The Old New Thing On wrapping a callable in a lambda that just calls it with the same parameters - The Old New Thing Why did the Microsoft Entertainment Pack for Windows have a special sticker announcing that it also had Tetris? - The Old New Thing How do functions like alloca allocate memory from the stack? - The Old New Thing How do functions like alloca allocate memory from the stack? - The Old New Thing Forcing an ARM64X executable to run as a specific architecture - The Old New Thing A little helper class for managing LPPROC_THREAD_ATTRIBUTE_LISTs - The Old New Thing The comments that go into code versus those that go into the pull request description - The Old New Thing The little-known winstart.bat batch file - The Old New Thing How can I perform a Copy­File&shy in unbuffered mode? - The Old New Thing Creating a fake agile wrapper that is technically agile but is not useful outside its home apartment, part 5 - The Old New Thing Creating a fake agile wrapper that is technically agile but is not useful outside its home apartment, part 4 - The Old New Thing
Rotation revisited: Another unidirectional algorithm
Raymond Chen · 2026-06-02 · via The Old New Thing

Some time ago, we looked at the problem of swapping two blocks of memory that reside inside a larger block, in constant memory, and along the way, we learned about std::rotate which swaps two adjacent blocks of memory (not necessarily the same size).

I noted in a postscript that clang’s libcxx and gcc’s libstdc++ contain specializations of std::rotate for random-access iterators that view the operation as a permutation and decomposes the permutation into cycles.

I was mistaken.

The implementation in gcc’s libstdc++ has special cases for single-element rotations, but in the general case, it uses a different algorithm.

Let’s call the blocks of memory to be exchanged A and B, where A is made up of elements A1, A2, A3, and so on; and block B has elements B1, B2, B3, and so on. Without loss of generality, suppose the A block is smaller. (If not, we can just mirror the algorithm.) And for concreteness let’s say that the elements are A1, A2, A3, B1, B2, B3, B4, B5.

A1 A2 A3 B1 B2 B3 B4 B5
           
first     mid         last

Exchange elements at first and mid, then move both iterators forward. After the first step, we have this:

B1 A2 A3 A1 B2 B3 B4 B5
           
  first     mid       last

After three steps, we have moved all of the A’s out and replaced them with an equal number of B’s.

B1 B2 B3 A1 A2 A3 B4 B5
           
      first     mid   last

But don’t stop. Keep on going until mid reaches last.

B1 B2 B3 B4 B5 A3 A1 A2
             
          first         mid
last

All of the B’s have been swapped to their final positions, but the A’s are jumbled.

But you can predict the exact nature of the jumbling. The A block is in two chunks. If we let n be the total number of elements |A| + |B| and a be the number of elements in A, then the first chunk has the final n % a elements, and the second chunk has the initial a − (n % a) elements.

Therefore, we can recursively rotate the two pieces of the A block to finish the job. Move mid to first + (n % a) and restart the algorithm.

This algorithm performs n − 1 swaps. You can calculate this inductively by observing that we perform |B| swaps, and then recursively rotate |A|. Or you can calculate this directly by observing that each swap moves one element to its final position, except that the final swap moves two elements to their final position.

The locality of this algorithm fairly good. The first iterator moves steadily forward, and the mid iterator moves forward most of the time, with at most O(log (min(|A|, |B|)) backward resets.

Next time, we’ll make a shocking discovery about this algorithm.

Category

Topics

Author

Raymond Chen

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.