<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.sarg.dev/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=2605%3A8D80%3A5825%3A1532%3AD58%3A188C%3A5434%3AD54</id>
	<title>Vero - Wikipedia - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.sarg.dev/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=2605%3A8D80%3A5825%3A1532%3AD58%3A188C%3A5434%3AD54"/>
	<link rel="alternate" type="text/html" href="https://wiki.sarg.dev/index.php/Special:Contributions/2605:8D80:5825:1532:D58:188C:5434:D54"/>
	<updated>2026-08-14T18:48:45Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.44.2</generator>
	<entry>
		<id>https://wiki.sarg.dev/index.php?title=Shellsort&amp;diff=50922</id>
		<title>Shellsort</title>
		<link rel="alternate" type="text/html" href="https://wiki.sarg.dev/index.php?title=Shellsort&amp;diff=50922"/>
		<updated>2025-11-04T01:26:41Z</updated>

		<summary type="html">&lt;p&gt;2605:8D80:5825:1532:D58:188C:5434:D54: /* Example */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Short description|Sorting algorithm which uses multiple comparison intervals}}&lt;br /&gt;
{{Infobox Algorithm&lt;br /&gt;
 |class=[[Sorting algorithm]]&lt;br /&gt;
 |image=[[File:Sorting shellsort anim.gif|Step-by-step visualisation of Shellsort]]&lt;br /&gt;
 |caption=Shellsort with gaps 23, 10, 4, 1 in action&lt;br /&gt;
 |data=[[Array data structure|Array]]&lt;br /&gt;
 |time=O(&#039;&#039;n&#039;&#039;&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;) (worst known worst case gap sequence)&amp;lt;br /&amp;gt;O(&#039;&#039;n&#039;&#039; log&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;&#039;&#039;n&#039;&#039;) (best known worst case gap sequence)&amp;lt;ref name=&amp;quot;Pratt&amp;quot;&amp;gt;{{Cite book&lt;br /&gt;
  |last=Pratt&lt;br /&gt;
  |first=Vaughan Ronald |author-link=Vaughan Ronald Pratt&lt;br /&gt;
  |year=1979&lt;br /&gt;
  |publisher=Garland&lt;br /&gt;
  |title=Shellsort and Sorting Networks (Outstanding Dissertations in the Computer Sciences)&lt;br /&gt;
  |url=https://apps.dtic.mil/sti/pdfs/AD0740110.pdf&lt;br /&gt;
  |archive-url=https://web.archive.org/web/20210907132436/https://apps.dtic.mil/sti/pdfs/AD0740110.pdf&lt;br /&gt;
  |url-status=live&lt;br /&gt;
  |archive-date=7 September 2021&lt;br /&gt;
  |isbn=978-0-8240-4406-0}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
 |best-time=O(&#039;&#039;n&#039;&#039; log &#039;&#039;n&#039;&#039;) (most gap sequences)&amp;lt;br&amp;gt;O(&#039;&#039;n&#039;&#039; log&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;&#039;&#039;n&#039;&#039;) (best known worst-case gap sequence)&amp;lt;ref&amp;gt;{{cite web |title=Shellsort &amp;amp; Comparisons |url=http://www.cs.wcupa.edu/rkline/ds/shell-comparison.html |access-date=14 November 2015 |archive-date=20 December 2019 |archive-url=https://web.archive.org/web/20191220040546/https://www.cs.wcupa.edu/rkline/ds/shell-comparison.html |url-status=dead }}&amp;lt;/ref&amp;gt;&lt;br /&gt;
 |average-time=depends on gap sequence&lt;br /&gt;
 |space=О(&#039;&#039;n&#039;&#039;) total, O(1) auxiliary&lt;br /&gt;
 |optimal=No&lt;br /&gt;
}}&lt;br /&gt;
[[File:Shell sorting algorithm color bars.svg|thumb|alt=The steps of Shellsort.|Swapping pairs of items in successive steps of Shellsort with gaps 5, 3, 1]]&lt;br /&gt;
&#039;&#039;&#039;Shellsort&#039;&#039;&#039;, also known as &#039;&#039;&#039;Shell sort&#039;&#039;&#039; or &#039;&#039;&#039;Shell&#039;s method&#039;&#039;&#039;, is an [[in-place algorithm|in-place]] [[comparison sort]]. It can be understood as either a generalization of sorting by exchange ([[bubble sort]]) or sorting by insertion ([[insertion sort]]).&amp;lt;ref name=&amp;quot;Knuth&amp;quot; /&amp;gt; The method starts by sorting pairs of elements far apart from each other, then progressively reducing the gap between elements to be compared. By starting with far-apart elements, it can move some out-of-place elements into the position faster than a simple nearest-neighbor exchange. &lt;br /&gt;
The running time of Shellsort is heavily dependent on the gap sequence it uses. For many practical variants, determining their [[time complexity]] remains an [[open problem]].&lt;br /&gt;
&lt;br /&gt;
The algorithm was first published by [[Donald Shell]] in 1959, and has nothing to do with shells.&amp;lt;ref name=&amp;quot;Shell&amp;quot;&amp;gt;{{Cite journal&lt;br /&gt;
  |url=http://penguin.ewu.edu/cscd300/Topic/AdvSorting/p30-shell.pdf&lt;br /&gt;
  |last=Shell&lt;br /&gt;
  |first=D. L.&lt;br /&gt;
  |title=A High-Speed Sorting Procedure&lt;br /&gt;
  |journal=Communications of the ACM&lt;br /&gt;
  |volume=2&lt;br /&gt;
  |issue=7&lt;br /&gt;
  |year=1959&lt;br /&gt;
  |pages=30–32&lt;br /&gt;
  |doi=10.1145/368370.368387&lt;br /&gt;
  |s2cid=28572656&lt;br /&gt;
  |access-date=18 October 2011&lt;br /&gt;
  |archive-date=30 August 2017&lt;br /&gt;
  |archive-url=https://web.archive.org/web/20170830020037/http://penguin.ewu.edu/cscd300/Topic/AdvSorting/p30-shell.pdf&lt;br /&gt;
  |url-status=dead&lt;br /&gt;
  }}&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Some older textbooks and references call this the &amp;quot;Shell–Metzner&amp;quot; sort after [[Marlene Metzner Norton]], but according to Metzner, &amp;quot;I had nothing to do with the sort, and my name should never have been attached to it.&amp;quot; See {{Cite web |title=Shell sort |url=https://xlinux.nist.gov/dads/HTML/shellsort.html |access-date=2007-07-17 |publisher=National Institute of Standards and Technology}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
Shellsort is an optimization of [[insertion sort]] that allows the exchange of items that are far apart. The idea is to arrange the list of elements so that, starting anywhere, taking every &#039;&#039;h&#039;&#039;th element produces a sorted list. Such a list is said to be &#039;&#039;h&#039;&#039;-sorted. It can also be thought of as &#039;&#039;h&#039;&#039; interleaved lists, each individually sorted.&amp;lt;ref name=&amp;quot;Sedgewick&amp;quot;&amp;gt;&lt;br /&gt;
 {{Cite book&lt;br /&gt;
  |last=Sedgewick&lt;br /&gt;
  |first=Robert&lt;br /&gt;
  |author-link=Robert Sedgewick (computer scientist)&lt;br /&gt;
  |title=Algorithms in C&lt;br /&gt;
  |edition=3rd&lt;br /&gt;
  |volume=1&lt;br /&gt;
  |publisher=Addison-Wesley&lt;br /&gt;
  |year=1998&lt;br /&gt;
  |pages=[https://archive.org/details/algorithmsinc00sedg/page/273 273–281]&lt;br /&gt;
  |isbn=978-0-201-31452-6&lt;br /&gt;
  |url-access=registration&lt;br /&gt;
  |url=https://archive.org/details/algorithmsinc00sedg/page/273&lt;br /&gt;
  }}&amp;lt;/ref&amp;gt; Beginning with large values of &#039;&#039;h&#039;&#039; allows elements to move long distances in the original list, reducing large amounts of disorder quickly, and leaving less work for smaller &#039;&#039;h&#039;&#039;-sort steps to do.&amp;lt;ref name=&amp;quot;KR&amp;quot;&amp;gt;&lt;br /&gt;
 {{Cite book&lt;br /&gt;
  |last1=Kernighan&lt;br /&gt;
  |first1=Brian W.&lt;br /&gt;
  |author-link1=Brian Kernighan&lt;br /&gt;
  |last2=Ritchie&lt;br /&gt;
  |first2=Dennis M.&lt;br /&gt;
  |author-link2=Dennis Ritchie&lt;br /&gt;
  |title=The C Programming Language&lt;br /&gt;
  |edition=2nd&lt;br /&gt;
  |publisher=Prentice Hall&lt;br /&gt;
  |year=1996&lt;br /&gt;
  |pages=62&lt;br /&gt;
  |isbn=978-7-302-02412-5&lt;br /&gt;
 }}&amp;lt;/ref&amp;gt; If the list is then &#039;&#039;k-sorted&#039;&#039; for some smaller integer &#039;&#039;k&#039;&#039;, then the list remains &#039;&#039;h&#039;&#039;-sorted. A final sort with &#039;&#039;h&#039;&#039;&amp;amp;nbsp;=&amp;amp;nbsp;1 ensures the list is fully sorted at the end,&amp;lt;ref name=&amp;quot;Sedgewick&amp;quot;/&amp;gt; but a judiciously chosen decreasing sequence of &#039;&#039;h&#039;&#039; values leaves very little work for this final pass to do.&lt;br /&gt;
&lt;br /&gt;
In simplistic terms, this means if we have an array of 1024 numbers, our first gap (&#039;&#039;h&#039;&#039;) could be 512. We then run through the list comparing each element in the first half to the element in the second half. Our second gap (&#039;&#039;k&#039;&#039;) is 256, which breaks the array into four sections (starting at 0, 256, 512, 768), and we make sure the first items in each section are sorted relative to each other, then the second item in each section, and so on. In practice the gap sequence could be anything, but the last gap is always 1 to finish the sort (effectively finishing with an ordinary insertion sort).&lt;br /&gt;
&lt;br /&gt;
An example run of Shellsort with gaps 5, 3 and 1 is shown below.&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align:center&amp;quot;&lt;br /&gt;
!&lt;br /&gt;
! {{mvar|a}}&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt; || {{mvar|a}}&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; || {{mvar|a}}&amp;lt;sub&amp;gt;3&amp;lt;/sub&amp;gt; || {{mvar|a}}&amp;lt;sub&amp;gt;4&amp;lt;/sub&amp;gt;&lt;br /&gt;
! {{mvar|a}}&amp;lt;sub&amp;gt;5&amp;lt;/sub&amp;gt; || {{mvar|a}}&amp;lt;sub&amp;gt;6&amp;lt;/sub&amp;gt; || {{mvar|a}}&amp;lt;sub&amp;gt;7&amp;lt;/sub&amp;gt; || {{mvar|a}}&amp;lt;sub&amp;gt;8&amp;lt;/sub&amp;gt;&lt;br /&gt;
! {{mvar|a}}&amp;lt;sub&amp;gt;9&amp;lt;/sub&amp;gt; || {{mvar|a}}&amp;lt;sub&amp;gt;10&amp;lt;/sub&amp;gt; || {{mvar|a}}&amp;lt;sub&amp;gt;11&amp;lt;/sub&amp;gt; || {{mvar|a}}&amp;lt;sub&amp;gt;12&amp;lt;/sub&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
! Input data&lt;br /&gt;
| 62 || 83 || 18 || 53 || 07 || 17 || 95 || 86 || 47 || 69 || 25 || 28&lt;br /&gt;
|-&lt;br /&gt;
! After 5-sorting&lt;br /&gt;
|                   17 ||                   28 ||                   18 ||                   47 ||                   07&lt;br /&gt;
|bgcolor=lightcyan| 25 ||bgcolor=lightcyan| 83 ||bgcolor=lightcyan| 86 ||bgcolor=lightcyan| 53 ||bgcolor=lightcyan| 69&lt;br /&gt;
|                   62 ||                   95&lt;br /&gt;
|-&lt;br /&gt;
! After 3-sorting&lt;br /&gt;
|                   17 ||                   07 ||                   18&lt;br /&gt;
|bgcolor=lightcyan| 47 ||bgcolor=lightcyan| 28 ||bgcolor=lightcyan| 25&lt;br /&gt;
|                   69 ||                   62 ||                   53&lt;br /&gt;
|bgcolor=lightcyan| 83 ||bgcolor=lightcyan| 86 ||bgcolor=lightcyan| 95&lt;br /&gt;
|-&lt;br /&gt;
! After 1-sorting&lt;br /&gt;
| 07 ||bgcolor=lightcyan| 17 || 18 ||bgcolor=lightcyan| 25 || 28 ||bgcolor=lightcyan| 47 || 53 ||bgcolor=lightcyan| 62 || 69 ||bgcolor=lightcyan| 83 || 86 ||bgcolor=lightcyan| 95&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The first pass, 5-sorting, performs insertion sort on five  separate subarrays (&#039;&#039;a&#039;&#039;&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;, &#039;&#039;a&#039;&#039;&amp;lt;sub&amp;gt;6&amp;lt;/sub&amp;gt;, &#039;&#039;a&#039;&#039;&amp;lt;sub&amp;gt;11&amp;lt;/sub&amp;gt;), (&#039;&#039;a&#039;&#039;&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;, &#039;&#039;a&#039;&#039;&amp;lt;sub&amp;gt;7&amp;lt;/sub&amp;gt;, &#039;&#039;a&#039;&#039;&amp;lt;sub&amp;gt;12&amp;lt;/sub&amp;gt;), (&#039;&#039;a&#039;&#039;&amp;lt;sub&amp;gt;3&amp;lt;/sub&amp;gt;, &#039;&#039;a&#039;&#039;&amp;lt;sub&amp;gt;8&amp;lt;/sub&amp;gt;), (&#039;&#039;a&#039;&#039;&amp;lt;sub&amp;gt;4&amp;lt;/sub&amp;gt;, &#039;&#039;a&#039;&#039;&amp;lt;sub&amp;gt;9&amp;lt;/sub&amp;gt;), (&#039;&#039;a&#039;&#039;&amp;lt;sub&amp;gt;5&amp;lt;/sub&amp;gt;, &#039;&#039;a&#039;&#039;&amp;lt;sub&amp;gt;10&amp;lt;/sub&amp;gt;). For instance, it changes the subarray (&#039;&#039;a&#039;&#039;&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;, &#039;&#039;a&#039;&#039;&amp;lt;sub&amp;gt;6&amp;lt;/sub&amp;gt;, &#039;&#039;a&#039;&#039;&amp;lt;sub&amp;gt;11&amp;lt;/sub&amp;gt;) from (62, 17, 25) to (17, 25, 62). The next pass, 3-sorting, performs insertion sort on the three subarrays (&#039;&#039;a&#039;&#039;&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;, &#039;&#039;a&#039;&#039;&amp;lt;sub&amp;gt;4&amp;lt;/sub&amp;gt;, &#039;&#039;a&#039;&#039;&amp;lt;sub&amp;gt;7&amp;lt;/sub&amp;gt;, &#039;&#039;a&#039;&#039;&amp;lt;sub&amp;gt;10&amp;lt;/sub&amp;gt;), (&#039;&#039;a&#039;&#039;&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;, &#039;&#039;a&#039;&#039;&amp;lt;sub&amp;gt;5&amp;lt;/sub&amp;gt;, &#039;&#039;a&#039;&#039;&amp;lt;sub&amp;gt;8&amp;lt;/sub&amp;gt;, &#039;&#039;a&#039;&#039;&amp;lt;sub&amp;gt;11&amp;lt;/sub&amp;gt;), (&#039;&#039;a&#039;&#039;&amp;lt;sub&amp;gt;3&amp;lt;/sub&amp;gt;, &#039;&#039;a&#039;&#039;&amp;lt;sub&amp;gt;6&amp;lt;/sub&amp;gt;, &#039;&#039;a&#039;&#039;&amp;lt;sub&amp;gt;9&amp;lt;/sub&amp;gt;, &#039;&#039;a&#039;&#039;&amp;lt;sub&amp;gt;12&amp;lt;/sub&amp;gt;). The last pass, 1-sorting, is an ordinary insertion sort of the entire array (&#039;&#039;a&#039;&#039;&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;,..., &#039;&#039;a&#039;&#039;&amp;lt;sub&amp;gt;12&amp;lt;/sub&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
As the example illustrates, the subarrays that Shellsort operates on are initially short; later they are longer but almost ordered. In both cases insertion sort works efficiently.&lt;br /&gt;
&lt;br /&gt;
Unlike [[insertion sort]], Shellsort is not a [[sorting algorithm#Stability|stable sort]] since gapped insertions transport equal elements past one another and thus lose their original order. It is an [[Adaptive sort|adaptive sorting algorithm]] in that it executes faster when the input is partially sorted.&lt;br /&gt;
&lt;br /&gt;
== Example ==&lt;br /&gt;
This is a [[C Sharp (programming language)|C#]] example using Marcin Ciura&#039;s gap sequence, with an inner insertion sort.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot;&amp;gt;&lt;br /&gt;
using System.Collections.Generic;&lt;br /&gt;
&lt;br /&gt;
// Sort an array a[0...n-1].&lt;br /&gt;
List&amp;lt;int&amp;gt; gaps = [701, 301, 132, 57, 23, 10, 4, 1]; // Ciura gap sequence&lt;br /&gt;
&lt;br /&gt;
// Start with the largest gap and work down to a gap of 1&lt;br /&gt;
// similar to insertion sort but instead of 1, gap is being used in each step&lt;br /&gt;
foreach (int gap in gaps)&lt;br /&gt;
{&lt;br /&gt;
    // Do a gapped insertion sort for every element in gaps&lt;br /&gt;
    // Each loop leaves a[0..gap-1] in gapped order&lt;br /&gt;
    for (int i = gap; i &amp;lt; n; ++i)&lt;br /&gt;
    {&lt;br /&gt;
        // save a[i] in temp and make a hole at position i&lt;br /&gt;
        int temp = a[i];&lt;br /&gt;
        // shift earlier gap-sorted elements up until the correct location for a[i] is found&lt;br /&gt;
        for (int j = i; (j &amp;gt;= gap) &amp;amp;&amp;amp; (a[j - gap] &amp;gt; temp); j -= gap)&lt;br /&gt;
        {&lt;br /&gt;
            a[j] = a[j - gap];&lt;br /&gt;
        }&lt;br /&gt;
        // put temp (the original a[i]) in its correct location&lt;br /&gt;
        a[j] = temp;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Gap sequences ==&lt;br /&gt;
The question of deciding which gap sequence to use is difficult. Every gap sequence that contains 1 yields a correct sort (as this makes the final pass an ordinary insertion sort); however, the properties of thus obtained versions of Shellsort may be very different. Too few gaps slows down the passes, and too many gaps produces an overhead.&lt;br /&gt;
&lt;br /&gt;
The table below compares most proposed gap sequences published so far. Some of them have decreasing elements that depend on the size of the sorted array (&#039;&#039;N&#039;&#039;). Others are increasing infinite sequences, whose elements less than &#039;&#039;N&#039;&#039; should be used in reverse order.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|- style=&amp;quot;background-color: #efefef;&amp;quot;&lt;br /&gt;
! [[OEIS]]&lt;br /&gt;
! General term (&#039;&#039;k&#039;&#039; ≥ 1)&lt;br /&gt;
! Concrete gaps&lt;br /&gt;
! Worst-case&amp;lt;br&amp;gt;time complexity&lt;br /&gt;
! Author and year of publication&lt;br /&gt;
|----&lt;br /&gt;
|&lt;br /&gt;
| &amp;lt;math&amp;gt;\left\lfloor\frac{N}{2^k}\right\rfloor&amp;lt;/math&amp;gt;&lt;br /&gt;
| &amp;lt;math&amp;gt;1, 2, \ldots, \left\lfloor\frac{N}{4}\right\rfloor,&lt;br /&gt;
        \left\lfloor\frac{N}{2}\right\rfloor&lt;br /&gt;
  &amp;lt;/math&amp;gt;&lt;br /&gt;
| &amp;lt;math&amp;gt;\Theta\left(N^2\right)&amp;lt;/math&amp;gt; [e.g. when &#039;&#039;N&#039;&#039; = 2&amp;lt;sup&amp;gt;&#039;&#039;p&#039;&#039;&amp;lt;/sup&amp;gt;]&lt;br /&gt;
| [[Donald Shell|Shell]], 1959&amp;lt;ref name=&amp;quot;Shell&amp;quot;/&amp;gt;&lt;br /&gt;
|----&lt;br /&gt;
|&lt;br /&gt;
| &amp;lt;math&amp;gt;2 \left\lfloor\frac{N}{2^{k+1}}\right\rfloor + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| &amp;lt;math&amp;gt;1, 3, \ldots, \; 2 \left\lfloor\frac{N}{8}\right\rfloor + 1,&lt;br /&gt;
        \; \; 2 \left\lfloor\frac{N}{4}\right\rfloor + 1&lt;br /&gt;
  &amp;lt;/math&amp;gt;&lt;br /&gt;
| &amp;lt;math&amp;gt;\Theta\left(N^\frac{3}{2}\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
| Frank &amp;amp; Lazarus, 1960&amp;lt;ref&amp;gt;{{Cite journal&lt;br /&gt;
  |last1=Frank&lt;br /&gt;
  |first1=R. M.&lt;br /&gt;
  |last2=Lazarus&lt;br /&gt;
  |first2=R. B.&lt;br /&gt;
  |title=A High-Speed Sorting Procedure&lt;br /&gt;
  |journal=Communications of the ACM&lt;br /&gt;
  |volume=3&lt;br /&gt;
  |issue=1&lt;br /&gt;
  |year=1960&lt;br /&gt;
  |pages=20–22&lt;br /&gt;
  |doi=10.1145/366947.366957|s2cid=34066017&lt;br /&gt;
 |doi-access=free&lt;br /&gt;
  }}&amp;lt;/ref&amp;gt;&lt;br /&gt;
|----&lt;br /&gt;
| {{OEIS link|A000225}}&lt;br /&gt;
| &amp;lt;math&amp;gt;2^k - 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| &amp;lt;math&amp;gt;1, 3, 7, 15, 31, 63, \ldots&amp;lt;/math&amp;gt;&lt;br /&gt;
| &amp;lt;math&amp;gt;\Theta\left(N^\frac{3}{2}\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
| [[Thomas N. Hibbard|Hibbard]], 1963&amp;lt;ref&amp;gt;{{Cite journal&lt;br /&gt;
  |last=Hibbard&lt;br /&gt;
  |first=Thomas N.&lt;br /&gt;
  |title=An Empirical Study of Minimal Storage Sorting&lt;br /&gt;
  |journal=Communications of the ACM&lt;br /&gt;
  |volume=6&lt;br /&gt;
  |issue=5&lt;br /&gt;
  |year=1963&lt;br /&gt;
  |pages=206–213&lt;br /&gt;
  |doi=10.1145/366552.366557|s2cid=12146844&lt;br /&gt;
 |doi-access=free&lt;br /&gt;
  }}&amp;lt;/ref&amp;gt;&lt;br /&gt;
|----&lt;br /&gt;
| {{OEIS link|A083318}}&lt;br /&gt;
| &amp;lt;math&amp;gt;2^k + 1&amp;lt;/math&amp;gt;, prefixed with 1&lt;br /&gt;
| &amp;lt;math&amp;gt;1, 3, 5, 9, 17, 33, 65, \ldots&amp;lt;/math&amp;gt;&lt;br /&gt;
| &amp;lt;math&amp;gt;\Theta\left(N^\frac{3}{2}\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
| Papernov &amp;amp; Stasevich, 1965&amp;lt;ref&amp;gt;{{Cite journal&lt;br /&gt;
  |url=http://www.mathnet.ru/links/83f0a81df1ec06f76d3683c6cab7d143/ppi751.pdf&lt;br /&gt;
  |last1=Papernov&lt;br /&gt;
  |first1=A. A.&lt;br /&gt;
  |last2=Stasevich&lt;br /&gt;
  |first2=G. V.&lt;br /&gt;
  |title=A Method of Information Sorting in Computer Memories&lt;br /&gt;
  |journal=Problems of Information Transmission&lt;br /&gt;
  |volume=1&lt;br /&gt;
  |issue=3&lt;br /&gt;
  |year=1965&lt;br /&gt;
  |pages=63–75}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
|----&lt;br /&gt;
| {{OEIS link|A003586}}&lt;br /&gt;
| Successive numbers of the form &amp;lt;math&amp;gt;2^p 3^q&amp;lt;/math&amp;gt; ([[3-smooth]] numbers)&lt;br /&gt;
| &amp;lt;math&amp;gt;1, 2, 3, 4, 6, 8, 9, 12, \ldots&amp;lt;/math&amp;gt;&lt;br /&gt;
| &amp;lt;math&amp;gt;\Theta\left(N \log^2 N\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
| [[Vaughan Ronald Pratt|Pratt]], 1971&amp;lt;ref name=&amp;quot;Pratt&amp;quot;/&amp;gt;&lt;br /&gt;
|----&lt;br /&gt;
| {{OEIS link|A003462}}&lt;br /&gt;
| &amp;lt;math&amp;gt;\frac{3^k - 1}{2}&amp;lt;/math&amp;gt;, not greater than &amp;lt;math&amp;gt;\left\lceil\frac{N}{3}\right\rceil&amp;lt;/math&amp;gt;&lt;br /&gt;
| &amp;lt;math&amp;gt;1, 4, 13, 40, 121, \ldots &amp;lt;/math&amp;gt;&lt;br /&gt;
| &amp;lt;math&amp;gt;\Theta\left(N^\frac{3}{2}\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
| [[Donald Knuth|Knuth]], 1973,&amp;lt;ref name=&amp;quot;Knuth&amp;quot;&amp;gt;{{Cite book&lt;br /&gt;
  |last=Knuth&lt;br /&gt;
  |first=Donald E. |author-link=Donald Knuth&lt;br /&gt;
  |title=The Art of Computer Programming. Volume 3: Sorting and Searching&lt;br /&gt;
  |edition=2nd&lt;br /&gt;
  |publisher=Addison-Wesley&lt;br /&gt;
  |location=Reading, Massachusetts&lt;br /&gt;
  |year=1997&lt;br /&gt;
  |pages=83–95&lt;br /&gt;
  |chapter=Shell&#039;s method&lt;br /&gt;
  |isbn=978-0-201-89685-5}}&amp;lt;/ref&amp;gt; based on [[Vaughan Ronald Pratt|Pratt]], 1971&amp;lt;ref name=&amp;quot;Pratt&amp;quot;/&amp;gt;&lt;br /&gt;
|----&lt;br /&gt;
| {{OEIS link|A036569}}&lt;br /&gt;
| &amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
           &amp;amp;\prod\limits_I a_q, \hbox{where} \\&lt;br /&gt;
  a_0 = {} &amp;amp;3 \\&lt;br /&gt;
  a_q = {} &amp;amp;\min\left\{n \in \mathbb{N}\colon n \ge \left(\frac{5}{2}\right)^{q+1}, \forall p\colon 0 \le p &amp;lt; q \Rightarrow \gcd(a_p, n) = 1\right\} \\&lt;br /&gt;
    I = {} &amp;amp;\left\{0 \le q &amp;lt; r \mid q \neq \frac{1}{2}\left(r^2 + r\right) - k \right\} \\&lt;br /&gt;
    r = {} &amp;amp;\left\lfloor \sqrt{2k + \sqrt{2k}} \right\rfloor&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;&lt;br /&gt;
| &amp;lt;math&amp;gt;1, 3, 7, 21, 48, 112, \ldots&amp;lt;/math&amp;gt;&lt;br /&gt;
| &amp;lt;math&amp;gt;O\left(N^{1 + \sqrt{\frac{8\ln\left(5/2\right)}{\ln(N)}}}\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
| Incerpi &amp;amp; [[Robert Sedgewick (computer scientist)|Sedgewick]], 1985,&amp;lt;ref&amp;gt;{{Cite journal&lt;br /&gt;
  |last1=Incerpi&lt;br /&gt;
  |first1=Janet&lt;br /&gt;
  |last2=Sedgewick&lt;br /&gt;
  |first2=Robert |author2-link=Robert Sedgewick (computer scientist)&lt;br /&gt;
  |title=Improved Upper Bounds on Shellsort&lt;br /&gt;
  |journal=Journal of Computer and System Sciences&lt;br /&gt;
  |volume=31&lt;br /&gt;
  |issue=2&lt;br /&gt;
  |year=1985&lt;br /&gt;
  |pages=210–224&lt;br /&gt;
  |doi=10.1016/0022-0000(85)90042-x|url=https://hal.inria.fr/inria-00076291/file/RR-0267.pdf&lt;br /&gt;
  }}&amp;lt;/ref&amp;gt; [[Donald Knuth|Knuth]]&amp;lt;ref name=&amp;quot;Knuth&amp;quot;/&amp;gt;&lt;br /&gt;
|----&lt;br /&gt;
| {{OEIS link|A036562}}&lt;br /&gt;
| &amp;lt;math&amp;gt;4^k + 3 \cdot 2^{k-1} + 1&amp;lt;/math&amp;gt;, prefixed with 1&lt;br /&gt;
| &amp;lt;math&amp;gt;1, 8, 23, 77, 281, \ldots&amp;lt;/math&amp;gt;&lt;br /&gt;
| &amp;lt;math&amp;gt;O\left(N^\frac{4}{3}\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
| Sedgewick, 1982&amp;lt;ref name=&amp;quot;Sedgewick&amp;quot;/&amp;gt;&lt;br /&gt;
|----&lt;br /&gt;
| {{OEIS link|A033622}}&lt;br /&gt;
| &amp;lt;math&amp;gt;\begin{cases}&lt;br /&gt;
  9\left(2^{k} - 2^\frac{k}{2}\right) + 1 &amp;amp; k\text{ even}, \\&lt;br /&gt;
  8 \cdot 2^{k} - 6 \cdot 2^{(k+1)/2} + 1         &amp;amp; k\text{ odd}&lt;br /&gt;
\end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
| &amp;lt;math&amp;gt;1, 5, 19, 41, 109, \ldots&amp;lt;/math&amp;gt;&lt;br /&gt;
| &amp;lt;math&amp;gt;O\left(N^\frac{4}{3}\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
| Sedgewick, 1986&amp;lt;ref name=&amp;quot;Sedgewick2&amp;quot;&amp;gt;&lt;br /&gt;
  {{Cite journal&lt;br /&gt;
   |last=Sedgewick&lt;br /&gt;
   |first=Robert |author-link=Robert Sedgewick (computer scientist)&lt;br /&gt;
   |title=A New Upper Bound for Shellsort&lt;br /&gt;
   |journal=Journal of Algorithms&lt;br /&gt;
   |volume=7&lt;br /&gt;
   |issue=2&lt;br /&gt;
   |year=1986&lt;br /&gt;
   |pages=159–173&lt;br /&gt;
   |doi=10.1016/0196-6774(86)90001-5&lt;br /&gt;
  }}&amp;lt;/ref&amp;gt;&lt;br /&gt;
|----&lt;br /&gt;
| &lt;br /&gt;
| &amp;lt;math&amp;gt;h_k = \max\left\{\left\lfloor \frac{5h_{k-1}-1}{11} \right\rfloor, 1\right\}, h_0 = N&amp;lt;/math&amp;gt;&lt;br /&gt;
| &amp;lt;math&amp;gt;1, \ldots, \left\lfloor \frac{5}{11}\left\lfloor \frac{5N-1}{11} \right\rfloor-\frac{1}{11}\right\rfloor,&lt;br /&gt;
        \left\lfloor \frac{5N-1}{11} \right\rfloor&lt;br /&gt;
  &amp;lt;/math&amp;gt;&lt;br /&gt;
| {{unk}}&lt;br /&gt;
| [[Gaston Gonnet|Gonnet]] &amp;amp; [[Ricardo Baeza-Yates|{{nowrap|Baeza-Yates}}]], 1991&amp;lt;ref name=&amp;quot;Gonnet&amp;quot;&amp;gt;{{Cite book&lt;br /&gt;
  |last1=Gonnet&lt;br /&gt;
  |first1=Gaston H.&lt;br /&gt;
  |last2=Baeza-Yates&lt;br /&gt;
  |first2=Ricardo&lt;br /&gt;
  |title=Handbook of Algorithms and Data Structures: In Pascal and C&lt;br /&gt;
  |publisher=Addison-Wesley&lt;br /&gt;
  |location=Reading, Massachusetts&lt;br /&gt;
  |edition=2nd&lt;br /&gt;
  |year=1991&lt;br /&gt;
  |pages=161–163&lt;br /&gt;
  |chapter=Shellsort&lt;br /&gt;
  |isbn=978-0-201-41607-7&lt;br /&gt;
  |quote=Extensive experiments indicate that the sequence defined by {{math|1=&#039;&#039;&amp;amp;alpha;&#039;&#039; = 0.45454 &amp;lt; 5/11}} performs significantly better than other sequences. The easiest way to compute {{math|{{floor|0.45454&#039;&#039;n&#039;&#039;}}}} is by &amp;lt;code&amp;gt;(5 * &#039;&#039;n&#039;&#039; — 1)/11&amp;lt;/code&amp;gt; using integer arithmetic.&lt;br /&gt;
}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
|----&lt;br /&gt;
| {{OEIS link|A108870}}&lt;br /&gt;
| &amp;lt;math&amp;gt;\left\lceil \frac{1}{5} \left(9\cdot \left(\frac{9}{4}\right)^{k-1} - 4 \right) \right\rceil&amp;lt;/math&amp;gt; (or equivalently, &amp;lt;math&amp;gt;\left\lceil \frac{\left(9/4\right)^k-1}{\left(9/4\right)-1} \right\rceil&amp;lt;/math&amp;gt;) &lt;br /&gt;
| &amp;lt;math&amp;gt;1, 4, 9, 20, 46, 103, \ldots&amp;lt;/math&amp;gt;&lt;br /&gt;
| {{unk}}&lt;br /&gt;
| Tokuda, 1992&amp;lt;ref&amp;gt;{{Cite book&lt;br /&gt;
  |editor-last=van Leeuven&lt;br /&gt;
  |editor-first=Jan&lt;br /&gt;
  |chapter=An Improved Shellsort&lt;br /&gt;
  |last=Tokuda&lt;br /&gt;
  |first=Naoyuki&lt;br /&gt;
  |title=Proceedings of the IFIP 12th World Computer Congress on Algorithms, Software, Architecture&lt;br /&gt;
  |publisher=North-Holland Publishing Co.&lt;br /&gt;
  |location=Amsterdam&lt;br /&gt;
  |year=1992&lt;br /&gt;
  |pages=449–457&lt;br /&gt;
  |isbn=978-0-444-89747-3}}&amp;lt;/ref&amp;gt; (misquote per OEIS)&lt;br /&gt;
|----&lt;br /&gt;
| {{OEIS link|A102549}}&lt;br /&gt;
| Unknown (experimentally derived)&lt;br /&gt;
| &amp;lt;math&amp;gt;1, 4, 10, 23, 57, 132, 301, 701&amp;lt;/math&amp;gt;&amp;lt;!--Please don&#039;t add 1750. It doesn&#039;t belong here.--&amp;gt;&lt;br /&gt;
| {{unk}}&lt;br /&gt;
| Ciura, 2001&amp;lt;ref name=&amp;quot;:0&amp;quot;&amp;gt;{{Cite book&lt;br /&gt;
  |chapter-url=http://sun.aei.polsl.pl/~mciura/publikacje/shellsort.pdf&lt;br /&gt;
  |archive-url=https://web.archive.org/web/20180923235211/http://sun.aei.polsl.pl/~mciura/publikacje/shellsort.pdf&lt;br /&gt;
  |archive-date=23 September 2018&lt;br /&gt;
  |title=Proceedings of the 13th International Symposium on Fundamentals of Computation Theory&lt;br /&gt;
  |editor-last=Freiwalds&lt;br /&gt;
  |editor-first=Rusins&lt;br /&gt;
  |last=Ciura&lt;br /&gt;
  |first=Marcin&lt;br /&gt;
  |chapter=Best Increments for the Average Case of Shellsort&lt;br /&gt;
  |publisher=Springer-Verlag&lt;br /&gt;
  |location=London&lt;br /&gt;
  |year=2001&lt;br /&gt;
  |pages=106–117&lt;br /&gt;
  |isbn=978-3-540-42487-1}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
|----&lt;br /&gt;
| {{OEIS link|A366726}}&lt;br /&gt;
| &amp;lt;math&amp;gt;\left\lceil \frac{\gamma^k-1}{\gamma-1} \right\rceil, \gamma = 2.243609061420001\ldots&amp;lt;/math&amp;gt;&lt;br /&gt;
| &amp;lt;math&amp;gt;1, 4, 9, 20, 45, 102, 230, 516, \ldots&amp;lt;/math&amp;gt;&lt;br /&gt;
| {{unk}}&lt;br /&gt;
| Lee, 2021&amp;lt;ref&amp;gt;{{cite arXiv&lt;br /&gt;
 | last       = Lee&lt;br /&gt;
 | first      = Ying Wai&lt;br /&gt;
 | eprint     = 2112.11112&lt;br /&gt;
 | title      = Empirically Improved Tokuda Gap Sequence in Shellsort&lt;br /&gt;
 | class      = cs.DS&lt;br /&gt;
 | date       = 21 December 2021&lt;br /&gt;
 }}&amp;lt;/ref&amp;gt;&lt;br /&gt;
|----&lt;br /&gt;
| &lt;br /&gt;
| &amp;lt;math&amp;gt;\left\lfloor 4.0816\cdot 8.5714^{\frac{k}{2.2449}} \right\rfloor&amp;lt;/math&amp;gt;&lt;br /&gt;
| &amp;lt;math&amp;gt;1, 4, 10, 27, 72, 187, 488, \ldots&amp;lt;/math&amp;gt;&lt;br /&gt;
| {{unk}}&lt;br /&gt;
| Skean, Ehrenborg, Jaromczyk, 2023&amp;lt;ref&amp;gt;{{cite arXiv&lt;br /&gt;
 | first1     = Oscar&lt;br /&gt;
 | last1      = Skean&lt;br /&gt;
 | first2     = Richard&lt;br /&gt;
 | last2      = Ehrenborg&lt;br /&gt;
 | first3     = Jerzy W.&lt;br /&gt;
 | last3      = Jaromczyk&lt;br /&gt;
 | eprint     = 2301.00316&lt;br /&gt;
 | title      = Optimization Perspectives on Shellsort&lt;br /&gt;
 | class      = cs.DS&lt;br /&gt;
 | date       = 1 Jan 2023&lt;br /&gt;
 }}&amp;lt;/ref&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|Start at 1.  Successive increments are smallest prime &amp;lt;math&amp;gt;  \geq 3  &amp;lt;/math&amp;gt; times previous&lt;br /&gt;
|&amp;lt;math&amp;gt;1, 3, 11, 37, 113, 347, 1049, \ldots&amp;lt;/math&amp;gt;&lt;br /&gt;
|{{unk}}&lt;br /&gt;
|Glenn C. Rhoads&amp;lt;ref&amp;gt;{{Cite web |last=Rhoads |first=Glenn |date=March 1, 2010 |title=Shellsort Increment Sequences |url=https://gcrhoads.byethost4.com/shellSort.html |access-date=May 13, 2025 |website=The Glenn}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
When the binary representation of &#039;&#039;N&#039;&#039; contains many consecutive zeroes, Shellsort using Shell&#039;s original gap sequence makes Θ(&#039;&#039;N&#039;&#039;&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;) comparisons in the worst case. For instance, this case occurs for &#039;&#039;N&#039;&#039; equal to a power of two when elements greater and smaller than the median occupy odd and even positions respectively, since they are compared only in the last pass.&lt;br /&gt;
&lt;br /&gt;
Although it has higher complexity than the &#039;&#039;O&#039;&#039;(&#039;&#039;N&#039;&#039;&amp;amp;nbsp;log&amp;amp;nbsp;&#039;&#039;N&#039;&#039;) that is optimal for comparison sorts, Pratt&#039;s version lends itself to [[sorting network]]s and has the same asymptotic gate complexity as Batcher&#039;s [[bitonic sorter]].&lt;br /&gt;
&lt;br /&gt;
Gonnet and Baeza-Yates observed that Shellsort makes the fewest comparisons on average when the ratios of successive gaps are roughly equal to 2.2.&amp;lt;ref name=&amp;quot;Gonnet&amp;quot;/&amp;gt; This is why their sequence with ratio 2.2 and Tokuda&#039;s sequence with ratio 2.25 prove efficient. However, it is not known why this is so. Sedgewick recommends using gaps which have low [[greatest common divisor]]s or are pairwise [[coprime]].&amp;lt;ref&amp;gt;{{Cite book&lt;br /&gt;
  |title=Algorithms in C++, Parts 1–4: Fundamentals, Data Structure, Sorting, Searching&lt;br /&gt;
  |last=Sedgewick&lt;br /&gt;
  |first=Robert |author-link=Robert Sedgewick (computer scientist)&lt;br /&gt;
  |chapter=Shellsort&lt;br /&gt;
  |publisher=Addison-Wesley&lt;br /&gt;
  |location=Reading, Massachusetts&lt;br /&gt;
  |year=1998&lt;br /&gt;
  |pages=285–292&lt;br /&gt;
  |isbn=978-0-201-35088-3}}&amp;lt;/ref&amp;gt;{{Fv|date=February 2021|reason=There&#039;s a lot of discussion of divisibility, but I couldn&#039;t find this explicitly stated.  E.g. p.&amp;amp;nbsp;289 says &amp;amp;quot;The increment sequences that we have discussed to this point are effective because successive elements are relatively prime. Another family of increment sequences is effective precisely because successive elements are not relatively prime.&amp;amp;quot;}} Gaps which are odd numbers seem to work well in practice: 25% reductions have been observed by avoiding even-numbered gaps. Gaps which avoid multiples of 3 and 5 seem to produce small benefits of &amp;lt; 10%.{{OR|date=May 2023}}&lt;br /&gt;
&lt;br /&gt;
With respect to the average number of comparisons, Ciura&#039;s sequence&amp;lt;ref name=&amp;quot;:0&amp;quot; /&amp;gt; has the best known performance; gaps greater than 701 were not determined but the sequence can be further extended according to the recursive formula &amp;lt;math&amp;gt;h_k = \lfloor 2.25 h_{k-1} \rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Tokuda&#039;s sequence, defined by the simple formula &amp;lt;math&amp;gt;h_k = \lceil h&#039;_k \rceil&amp;lt;/math&amp;gt;, where &amp;lt;math&amp;gt;h&#039;_k = 2.25 h&#039;_{k-1} + 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;h&#039;_1 = 1&amp;lt;/math&amp;gt;, can be recommended for practical applications.&lt;br /&gt;
&lt;br /&gt;
If the maximum input size is small, as may occur if Shellsort is used on small subarrays by another recursive sorting algorithm such as [[quicksort]] or [[merge sort]], then it is possible to tabulate an optimal sequence for each input size.&amp;lt;ref&amp;gt;{{cite web&lt;br /&gt;
 |title=How to choose the lengths of my sub sequences for a shell sort?&lt;br /&gt;
 |first=Olof |last=Forshell&lt;br /&gt;
 |date=22 May 2018&lt;br /&gt;
 |url=https://stackoverflow.com/a/50470237&lt;br /&gt;
 |website=[[Stack Overflow]]&lt;br /&gt;
}}  Additional commentary at [https://stackoverflow.com/a/50490873#50490873 Fastest gap sequence for shell sort?] (23 May 2018).&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;{{cite arXiv&lt;br /&gt;
 |title=Optimal Gap Sequences in Shellsort for {{math|&#039;&#039;n&#039;&#039; ≤ 16}} Elements &lt;br /&gt;
 |first=Ying Wai |last=Lee&lt;br /&gt;
 |date=21 December 2021&lt;br /&gt;
 |eprint=2112.11127&lt;br /&gt;
 |class=math.CO&lt;br /&gt;
}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Computational complexity ==&lt;br /&gt;
The following property holds: after &#039;&#039;h&#039;&#039;&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;-sorting of any &#039;&#039;h&#039;&#039;&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;-sorted array, the array remains &#039;&#039;h&#039;&#039;&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;-sorted.&amp;lt;ref&amp;gt;{{Cite journal&lt;br /&gt;
  |last1=Gale&lt;br /&gt;
  |first1=David&lt;br /&gt;
  |author-link=David Gale&lt;br /&gt;
  |last2=Karp&lt;br /&gt;
  |first2=Richard M.&lt;br /&gt;
  |author2-link=Richard M. Karp&lt;br /&gt;
  |title=A Phenomenon in the Theory of Sorting&lt;br /&gt;
  |journal=Journal of Computer and System Sciences&lt;br /&gt;
  |volume=6&lt;br /&gt;
  |issue=2&lt;br /&gt;
  |date=April 1972&lt;br /&gt;
  |pages=103–115&lt;br /&gt;
  |doi=10.1016/S0022-0000(72)80016-3&lt;br /&gt;
  |url=https://core.ac.uk/download/pdf/82277625.pdf&lt;br /&gt;
|doi-access=free&lt;br /&gt;
  }}&amp;lt;/ref&amp;gt; Every &#039;&#039;h&#039;&#039;&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;-sorted and &#039;&#039;h&#039;&#039;&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;-sorted array is also (&#039;&#039;a&#039;&#039;&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;h&#039;&#039;&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;+&#039;&#039;a&#039;&#039;&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;&#039;&#039;h&#039;&#039;&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;)-sorted, for any nonnegative integers &#039;&#039;a&#039;&#039;&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt; and &#039;&#039;a&#039;&#039;&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;. The worst-case complexity of Shellsort is therefore connected with the [[coin problem|Frobenius problem]]: for given integers &#039;&#039;h&#039;&#039;&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;,..., &#039;&#039;h&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;&#039;&#039; with gcd = 1, the Frobenius number &#039;&#039;g&#039;&#039;(&#039;&#039;h&#039;&#039;&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;,..., &#039;&#039;h&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;&#039;&#039;) is the greatest integer that cannot be represented as &#039;&#039;a&#039;&#039;&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;h&#039;&#039;&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;+ ... +&#039;&#039;a&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;h&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;&#039;&#039; with nonnegative integer &#039;&#039;a&#039;&#039;&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;,..., &#039;&#039;a&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;&#039;&#039;. Using known formulae for Frobenius numbers, we can determine the worst-case complexity of Shellsort for several classes of gap sequences.&amp;lt;ref&amp;gt;{{Cite journal&lt;br /&gt;
  |last=Selmer&lt;br /&gt;
  |first=Ernst S.&lt;br /&gt;
  |author-link=Ernst Sejersted Selmer&lt;br /&gt;
  |title=On Shellsort and the Frobenius Problem&lt;br /&gt;
  |journal=BIT Numerical Mathematics&lt;br /&gt;
  |volume=29&lt;br /&gt;
  |issue=1&lt;br /&gt;
  |date=March 1989&lt;br /&gt;
  |pages=37–40&lt;br /&gt;
  |doi=10.1007/BF01932703&lt;br /&gt;
  |hdl=1956/19572&lt;br /&gt;
  |s2cid=32467267&lt;br /&gt;
 |hdl-access=free&lt;br /&gt;
  |url=https://bora.uib.no/bora-xmlui/bitstream/handle/1956/19572/On%20Shellsort%20and%20the%20Frobenius%20problem.pdf&lt;br /&gt;
}}&amp;lt;/ref&amp;gt; Proven results are shown in the above table.&lt;br /&gt;
&lt;br /&gt;
Mark Allen Weiss proved that Shellsort runs in &#039;&#039;O&#039;&#039;(&#039;&#039;N&#039;&#039; log &#039;&#039;N&#039;&#039;) time when the input array is in reverse order.&amp;lt;ref&amp;gt;{{Cite journal&lt;br /&gt;
  |last=Weiss&lt;br /&gt;
  |first=Mark Allen&lt;br /&gt;
  |title=A good case for Shellsort&lt;br /&gt;
  |journal=Congressus Numerantium&lt;br /&gt;
  |volume=73&lt;br /&gt;
  |date=1989&lt;br /&gt;
  |pages=59–62&lt;br /&gt;
}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With respect to the average number of operations, none of the proven results concerns a practical gap sequence. For gaps that are powers of two, Espelid computed this average as &amp;lt;math&amp;gt;0.5349N\sqrt{N}-0.4387N-0.097\sqrt{N}+O(1)&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;{{Cite journal&lt;br /&gt;
  |last=Espelid&lt;br /&gt;
  |first=Terje O.&lt;br /&gt;
  |title=Analysis of a Shellsort Algorithm&lt;br /&gt;
  |journal=BIT Numerical Mathematics&lt;br /&gt;
  |volume=13&lt;br /&gt;
  |issue=4&lt;br /&gt;
  |date=December 1973&lt;br /&gt;
  |pages=394–400&lt;br /&gt;
  |doi=10.1007/BF01933401&lt;br /&gt;
|s2cid=119443598&lt;br /&gt;
 }}  The quoted result is equation (8) on p. 399.&amp;lt;/ref&amp;gt; [[Donald Knuth|Knuth]] determined the average complexity of sorting an &#039;&#039;N&#039;&#039;-element array with two gaps (&#039;&#039;h&#039;&#039;, 1) to be &amp;lt;math&amp;gt;\frac{2N^2}{h} + \sqrt{\pi N^3 h}&amp;lt;/math&amp;gt;.&amp;lt;ref name=&amp;quot;Knuth&amp;quot; /&amp;gt; It follows that a two-pass Shellsort with &#039;&#039;h&#039;&#039; = Θ(&#039;&#039;N&#039;&#039;&amp;lt;sup&amp;gt;1/3&amp;lt;/sup&amp;gt;) makes on average &#039;&#039;O&#039;&#039;(&#039;&#039;N&#039;&#039;&amp;lt;sup&amp;gt;5/3&amp;lt;/sup&amp;gt;) comparisons/inversions/running time. [[Andrew Yao|Yao]] found the average complexity of a three-pass Shellsort.&amp;lt;ref&amp;gt;{{Cite journal&lt;br /&gt;
  |last=Yao&lt;br /&gt;
  |first=Andrew Chi-Chih&lt;br /&gt;
  |author-link=Andrew Yao&lt;br /&gt;
  |title=An Analysis of (&#039;&#039;h&#039;&#039;, &#039;&#039;k&#039;&#039;, 1)-Shellsort&lt;br /&gt;
  |journal=Journal of Algorithms&lt;br /&gt;
  |volume=1&lt;br /&gt;
  |issue=1&lt;br /&gt;
  |year=1980&lt;br /&gt;
  |pages=14–50&lt;br /&gt;
  |doi=10.1016/0196-6774(80)90003-6&lt;br /&gt;
  |s2cid=3054966&lt;br /&gt;
  |url=http://pdfs.semanticscholar.org/d569/b8a70a808c6b808ca2e25371c736ce98b14f.pdf&lt;br /&gt;
  |archive-url=https://web.archive.org/web/20190304043832/http://pdfs.semanticscholar.org/d569/b8a70a808c6b808ca2e25371c736ce98b14f.pdf&lt;br /&gt;
  |url-status=dead&lt;br /&gt;
  |archive-date=2019-03-04&lt;br /&gt;
  |id=STAN-CS-79-726&lt;br /&gt;
}}&amp;lt;/ref&amp;gt; His result was refined by [[Svante Janson|Janson]] and Knuth:&amp;lt;ref&amp;gt;{{Cite journal&lt;br /&gt;
  |last1=Janson&lt;br /&gt;
  |first1=Svante |author1-link=Svante Janson&lt;br /&gt;
  |last2=Knuth&lt;br /&gt;
  |first2=Donald E. |author2-link=Donald Knuth&lt;br /&gt;
  |title=Shellsort with Three Increments&lt;br /&gt;
  |journal=Random Structures and Algorithms&lt;br /&gt;
  |volume=10&lt;br /&gt;
  |issue=1–2&lt;br /&gt;
  |year=1997&lt;br /&gt;
  |pages=125–142&lt;br /&gt;
  |doi=10.1002/(SICI)1098-2418(199701/03)10:1/2&amp;lt;125::AID-RSA6&amp;gt;3.0.CO;2-X&lt;br /&gt;
  |arxiv=cs/9608105&lt;br /&gt;
  |citeseerx=10.1.1.54.9911&lt;br /&gt;
  |url=http://www2.math.uu.se/~svante/papers/sj113.pdf&lt;br /&gt;
}}&amp;lt;/ref&amp;gt; the average number of comparisons/inversions/running time made during a Shellsort with three gaps (&#039;&#039;ch&#039;&#039;, &#039;&#039;cg&#039;&#039;, 1), where &#039;&#039;h&#039;&#039; and &#039;&#039;g&#039;&#039; are coprime, is &amp;lt;math&amp;gt;\frac{N^2}{4ch} + O(N)&amp;lt;/math&amp;gt; in the first pass, &amp;lt;math&amp;gt;\frac{1}{8g}\sqrt{\frac{\pi}{ch}}(h - 1)N^{3/2} + O(hN)&amp;lt;/math&amp;gt; in the second pass and &amp;lt;math&amp;gt;\psi(h, g)N + \frac{1}{8}\sqrt{\frac{\pi}{c}}(c - 1)N^{3/2} + O\left((c - 1)gh^{1/2}N\right) + O\left(c^2g^3h^2\right)&amp;lt;/math&amp;gt; in the third pass. &#039;&#039;ψ&#039;&#039;(&#039;&#039;h&#039;&#039;, &#039;&#039;g&#039;&#039;) in the last formula is a complicated function asymptotically equal to &amp;lt;math&amp;gt;\sqrt{\frac{\pi h}{128}}g + O\left(g^{-1/2}h^{1/2}\right) + O\left(gh^{-1/2}\right)&amp;lt;/math&amp;gt;. In particular, when &#039;&#039;h&#039;&#039; = Θ(&#039;&#039;N&#039;&#039;&amp;lt;sup&amp;gt;7/15&amp;lt;/sup&amp;gt;) and &#039;&#039;g&#039;&#039; = Θ(&#039;&#039;N&#039;&#039;&amp;lt;sup&amp;gt;1/5&amp;lt;/sup&amp;gt;), the average time of sorting is &#039;&#039;O&#039;&#039;(&#039;&#039;N&#039;&#039;&amp;lt;sup&amp;gt;23/15&amp;lt;/sup&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Based on experiments, it is conjectured that Shellsort with [[Thomas N. Hibbard|Hibbard]]&#039;s gap sequence runs in &#039;&#039;O&#039;&#039;(&#039;&#039;N&#039;&#039;&amp;lt;sup&amp;gt;5/4&amp;lt;/sup&amp;gt;) average time,&amp;lt;ref name=&amp;quot;Knuth&amp;quot; /&amp;gt; and that Gonnet and Baeza-Yates&#039;s sequence requires on average 0.41&#039;&#039;N&#039;&#039;&amp;amp;nbsp;ln&amp;amp;nbsp;&#039;&#039;N&#039;&#039;&amp;amp;nbsp;(ln&amp;amp;nbsp;ln&amp;amp;nbsp;&#039;&#039;N&#039;&#039;&amp;amp;nbsp;+&amp;amp;nbsp;1/6) element moves.&amp;lt;ref name=&amp;quot;Gonnet&amp;quot; /&amp;gt; Approximations of the average number of operations formerly put forward for other sequences fail when sorted arrays contain millions of elements.&lt;br /&gt;
&lt;br /&gt;
The graph below shows the average number of element comparisons use by various gap sequences, divided by the [[Comparison sort#Number of comparisons required to sort a list|theoretical lower bound]], i.e. log&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;&#039;&#039;N&#039;&#039;!.  Ciuria&#039;s sequence 1, 4, 10, 23, 57, 132, 301, 701 (labelled Ci01) has been extended according to the formula &amp;lt;math&amp;gt;h_k = \lfloor2.25 h_{k-1}\rfloor&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[File:Shell sort average number of comparisons (English).svg|center]]&lt;br /&gt;
&lt;br /&gt;
Applying the theory of [[Kolmogorov complexity]], Jiang, [[Ming Li|Li]], and [[Paul Vitányi|Vitányi]] &lt;br /&gt;
&amp;lt;ref&amp;gt;{{Cite journal&lt;br /&gt;
  |last1=Jiang&lt;br /&gt;
  |first1=Tao&lt;br /&gt;
  |last2=Li&lt;br /&gt;
  |first2=Ming&lt;br /&gt;
  |author2-link=Ming Li&lt;br /&gt;
  |last3=Vitányi&lt;br /&gt;
  |first3=Paul&lt;br /&gt;
  |author3-link=Paul Vitányi&lt;br /&gt;
  |title=A Lower Bound on the Average-Case Complexity of Shellsort&lt;br /&gt;
  |journal=[[Journal of the ACM]]&lt;br /&gt;
  |volume=47&lt;br /&gt;
  |issue=5&lt;br /&gt;
  |date=September 2000&lt;br /&gt;
  |pages=905–911&lt;br /&gt;
  |doi=10.1145/355483.355488&lt;br /&gt;
  |citeseerx=10.1.1.6.6508&lt;br /&gt;
  |url=https://homepages.cwi.nl/~paulv/papers/shellsort.pdf&lt;br /&gt;
  |arxiv=cs/9906008&lt;br /&gt;
|s2cid=3265123&lt;br /&gt;
 }}&amp;lt;/ref&amp;gt; proved the following lower bound for the order of the average number of operations/running time in a &#039;&#039;p&#039;&#039;-pass Shellsort: Ω(&#039;&#039;pN&#039;&#039;&amp;lt;sup&amp;gt;1+1/&#039;&#039;p&#039;&#039;&amp;lt;/sup&amp;gt;) when &#039;&#039;p&#039;&#039;&amp;amp;nbsp;≤&amp;amp;nbsp;log&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;&#039;&#039;N&#039;&#039; and Ω(&#039;&#039;pN&#039;&#039;) when &#039;&#039;p&#039;&#039;&amp;amp;nbsp;&amp;gt;&amp;amp;nbsp;log&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;&#039;&#039;N&#039;&#039;.&lt;br /&gt;
Therefore, Shellsort has prospects of running in an average time that asymptotically grows like &#039;&#039;N&#039;&#039; log&#039;&#039;N&#039;&#039; only when using gap sequences whose number of gaps grows in proportion to the logarithm of the array size. It is, however, unknown whether Shellsort can reach this asymptotic order of average-case complexity, which is optimal for comparison sorts. The lower bound was improved by [[Paul Vitányi|Vitányi]]&amp;lt;ref&amp;gt;{{cite journal&lt;br /&gt;
  |doi=10.1002/rsa.20737&lt;br /&gt;
  |last=Vitányi&lt;br /&gt;
  |first=Paul&lt;br /&gt;
  |author-link=Paul Vitányi&lt;br /&gt;
  |date=March 2018&lt;br /&gt;
  |title=On the average-case complexity of Shellsort&lt;br /&gt;
  |journal=Random Structures and Algorithms&lt;br /&gt;
  |volume=52&lt;br /&gt;
  |issue=2&lt;br /&gt;
  |pages=354–363&lt;br /&gt;
  |arxiv=1501.06461&lt;br /&gt;
  |s2cid=6833808&lt;br /&gt;
 |url=https://homepages.cwi.nl/~paulv/papers/shell2015.pdf&lt;br /&gt;
}}&amp;lt;/ref&amp;gt; for every number of passes &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; to  &lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\Omega ( N\sum_{k=1}^p h_{k-1}/h_k )&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
where &amp;lt;math&amp;gt;h_0=N&amp;lt;/math&amp;gt;. This result implies for example the Jiang-Li-Vitányi lower bound for all &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;-pass increment sequences and improves that lower bound for particular increment sequences. In fact all bounds (lower and upper) currently known for the average case are precisely matched by this lower bound. For example, this gives the new result that the Janson-Knuth upper bound is matched by the resulting lower bound for the used increment sequence, showing that three pass Shellsort for this increment sequence uses &amp;lt;math&amp;gt;\Theta(N^{23/15})&amp;lt;/math&amp;gt; comparisons/inversions/running time.&lt;br /&gt;
The formula allows us to search for increment sequences that yield lower bounds which are unknown; for example an increment sequence for four passes which has a lower bound greater than&lt;br /&gt;
&amp;lt;math&amp;gt;\Omega(pn^{1+1/p}) = \Omega(n^{5/4})&amp;lt;/math&amp;gt; for the increment sequence&lt;br /&gt;
&amp;lt;math&amp;gt;h_1 = n^{11/16},&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;h_2 = n^{7/16},&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;h_3 = n^{3/16},&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;h_4 = 1&amp;lt;/math&amp;gt;. The lower bound becomes&lt;br /&gt;
&amp;lt;math&amp;gt;T = \Omega(n\cdot (n^{1-11/16}+n^{11/16-7/16}+n^{7/16-3/16}+n^{3/16}) = \Omega(n^{1+5/16}) = \Omega(n^{21/16}).&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The worst-case complexity of any version of Shellsort is of higher order: Plaxton, [[Bjorn Poonen|Poonen]], and [[Torsten Suel|Suel]] showed that it grows at least as rapidly as &amp;lt;math&amp;gt;\Omega\left(N \left( {\log N \over \log \log N} \right)^2\right)&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;{{Cite book&lt;br /&gt;
  |last1=Plaxton&lt;br /&gt;
  |first1=C. Greg&lt;br /&gt;
  |last2=Poonen&lt;br /&gt;
  |first2=Bjorn&lt;br /&gt;
  |author2-link=Bjorn Poonen&lt;br /&gt;
  |last3=Suel&lt;br /&gt;
  |first3=Torsten&lt;br /&gt;
  |title=Proceedings., 33rd Annual Symposium on Foundations of Computer Science&lt;br /&gt;
 |chapter=Improved lower bounds for Shellsort&lt;br /&gt;
 |author3-link=Torsten Suel&lt;br /&gt;
  |volume=33&lt;br /&gt;
  |date=24–27 October 1992&lt;br /&gt;
  |location=Pittsburgh, United States&lt;br /&gt;
  |pages=226–235&lt;br /&gt;
  |doi=10.1109/SFCS.1992.267769&lt;br /&gt;
  |isbn=978-0-8186-2900-6&lt;br /&gt;
  |citeseerx=10.1.1.43.1393&lt;br /&gt;
  |s2cid=15095863&lt;br /&gt;
 |chapter-url=http://engineering.nyu.edu/~suel/papers/shell.pdf&lt;br /&gt;
}}&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;{{Cite journal&lt;br /&gt;
  |last1=Plaxton&lt;br /&gt;
  |first1=C. Greg&lt;br /&gt;
  |last2=Suel&lt;br /&gt;
  |first2=Torsten&lt;br /&gt;
  |author2-link=Torsten Suel&lt;br /&gt;
  |title=Lower Bounds for Shellsort&lt;br /&gt;
  |journal=Journal of Algorithms&lt;br /&gt;
  |volume=23 |issue=2&lt;br /&gt;
  |date=May 1997&lt;br /&gt;
  |pages=221–240&lt;br /&gt;
  |doi=10.1006/jagm.1996.0825&lt;br /&gt;
  |citeseerx=10.1.1.460.2429&lt;br /&gt;
  |url=http://engineering.nyu.edu/~suel/papers/shell2.pdf&lt;br /&gt;
}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
Robert Cypher proved a stronger lower bound: &amp;lt;math&amp;gt;\Omega\left(N {{(\log N)^2} \over {\log\log N}}\right)&amp;lt;/math&amp;gt; when &amp;lt;math&amp;gt;h_{s+1} &amp;gt; h_s&amp;lt;/math&amp;gt; for all &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;{{Cite journal&lt;br /&gt;
  |last=Cypher&lt;br /&gt;
  |first=Robert&lt;br /&gt;
  |title=A Lower Bound on the Size of Shellsort Sorting Networks&lt;br /&gt;
  |journal=SIAM Journal on Computing&lt;br /&gt;
  |volume=22&lt;br /&gt;
  |date=1993&lt;br /&gt;
  |pages=62–71&lt;br /&gt;
|doi=10.1137/0222006&lt;br /&gt;
 }}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Applications ==&lt;br /&gt;
Shellsort performs more operations and has higher [[CPU cache#Cache miss|cache miss ratio]] than [[quicksort]]. However, since it can be implemented using little code and does not use the [[call stack]], some implementations of the [[qsort]] function in the [[C standard library]] targeted at [[embedded systems]] use it instead of quicksort. Shellsort is, for example, used in the [[uClibc]] library.&amp;lt;ref&amp;gt;{{Cite web&lt;br /&gt;
  | url=http://git.uclibc.org/uClibc/tree/libc/stdlib/stdlib.c#n700&lt;br /&gt;
  | title=libc/stdlib/stdlib.c&lt;br /&gt;
  | first=Manuel III |last=Novoa&lt;br /&gt;
  | access-date=2014-10-29}}&amp;lt;/ref&amp;gt; For similar reasons, in the past, Shellsort was used in the [[Linux kernel]].&amp;lt;ref&amp;gt;{{Cite web&lt;br /&gt;
  | url=https://github.com/torvalds/linux/blob/72932611b4b05bbd89fafa369d564ac8e449809b/kernel/groups.c#L105&lt;br /&gt;
  | title=kernel/groups.c&lt;br /&gt;
  | website=[[GitHub]]&lt;br /&gt;
 | access-date=2012-05-05}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Shellsort can also serve as a sub-algorithm of [[introsort|introspective sort]], to sort short subarrays and to prevent a slowdown when the recursion depth exceeds a given limit. This principle is employed, for instance, in the [[bzip2]] compressor.&amp;lt;ref&amp;gt;{{Cite web&lt;br /&gt;
  |url=https://www.ncbi.nlm.nih.gov/IEB/ToolBox/CPP_DOC/lxr/source/src/util/compress/bzip2/blocksort.c#L519&lt;br /&gt;
  |title=bzip2/blocksort.c&lt;br /&gt;
  |author=Julian Seward&lt;br /&gt;
  |access-date=2011-03-30}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [[Comb sort]]&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
{{reflist|30em}}&lt;br /&gt;
&lt;br /&gt;
== Bibliography ==&lt;br /&gt;
* {{Cite book&lt;br /&gt;
  |last=Knuth&lt;br /&gt;
  |first=Donald E. |author-link=Donald Knuth&lt;br /&gt;
  |title=The Art of Computer Programming. Volume 3: Sorting and Searching&lt;br /&gt;
  |edition=2nd&lt;br /&gt;
  |publisher=Addison-Wesley&lt;br /&gt;
  |location=Reading, Massachusetts&lt;br /&gt;
  |year=1997&lt;br /&gt;
  |pages=83–95&lt;br /&gt;
  |chapter=Shell&#039;s method&lt;br /&gt;
  |isbn=978-0-201-89685-5&lt;br /&gt;
  |title-link=The Art of Computer Programming }}&lt;br /&gt;
* [http://www.cs.princeton.edu/~rs/shell/ Analysis of Shellsort and Related Algorithms], Robert Sedgewick, Fourth European Symposium on Algorithms, Barcelona, September 1996.&lt;br /&gt;
&lt;br /&gt;
== External links ==&lt;br /&gt;
{{wikibooks|Algorithm implementation|Sorting/Shell_sort|Shell sort}}&lt;br /&gt;
* {{webarchive |url=https://web.archive.org/web/20150310043846/http://www.sorting-algorithms.com/shell-sort |date=10 March 2015 |title=Animated Sorting Algorithms: Shell Sort}} – graphical demonstration&lt;br /&gt;
* [https://www.youtube.com/watch?v=CmPA7zE8mx0 Shellsort with gaps 5, 3, 1 as a Hungarian folk dance]&lt;br /&gt;
&lt;br /&gt;
{{sorting}}&lt;br /&gt;
{{Use dmy dates|date=April 2020}}&lt;br /&gt;
&lt;br /&gt;
{{Authority control}}&lt;br /&gt;
&lt;br /&gt;
{{DEFAULTSORT:Shellsort}}&lt;br /&gt;
[[Category:Comparison sorts]]&lt;/div&gt;</summary>
		<author><name>2605:8D80:5825:1532:D58:188C:5434:D54</name></author>
	</entry>
	<entry>
		<id>https://wiki.sarg.dev/index.php?title=Node_(computer_science)&amp;diff=589079</id>
		<title>Node (computer science)</title>
		<link rel="alternate" type="text/html" href="https://wiki.sarg.dev/index.php?title=Node_(computer_science)&amp;diff=589079"/>
		<updated>2025-11-03T18:11:42Z</updated>

		<summary type="html">&lt;p&gt;2605:8D80:5825:1532:D58:188C:5434:D54: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Short description|Basic unit of a data structure}}&lt;br /&gt;
A &#039;&#039;&#039;node&#039;&#039;&#039; is a basic unit of a [[data structure]], such as a [[linked list]] or [[Tree (data structure)|tree]] data structure. Nodes contain [[data]] and also may link to other nodes. Links between nodes are often implemented by [[Pointer (computer programming)|pointers]].&lt;br /&gt;
&lt;br /&gt;
[[File:6n-graf.svg|thumb|250px|In [[graph theory]], the image provides a simplified view of a network, where each of the numbers represents a different node.]]&lt;br /&gt;
&lt;br /&gt;
==Nodes and trees ==&lt;br /&gt;
[[File:binary tree.svg|right|192px|thumb|A simple [[binary tree]] of size 9 and height 3, with a root node whose value is 2. The above tree is unbalanced and not sorted.]]&lt;br /&gt;
Nodes are often arranged into tree structures. A node represents the information contained in a single data structure. These nodes may contain a value or condition, or possibly serve as another independent data structure. Nodes are represented by a single parent node. The highest point on a tree structure is called a root node, which does not have a parent node, but serves as the parent or &#039;grandparent&#039; of all of the nodes below it in the tree. The height of a node is determined by the total number of edges on the path from that node to the furthest leaf node, and the height of the tree is equal to the height of the root node.&amp;lt;ref&amp;gt;{{cite web|url=http://xlinux.nist.gov/dads//HTML/tree.html|title=tree (data structure)|publisher=[[National Institute of Standards and Technology]]|url-status=live|archive-url=https://web.archive.org/web/20141124223717/http://xlinux.nist.gov/dads/HTML/tree.html|archive-date=2014-11-24}}&amp;lt;/ref&amp;gt; Node depth is determined by the distance between that particular node and the root node. The root node is said to have a depth of zero.&amp;lt;ref&amp;gt;{{cite book | last=Teukolsky | first=Roselyn | title=Barron&#039;s AP Computer Science A| url=https://archive.org/details/apcomputerscienc0006teuk | url-access=registration |publisher=[[Barron&#039;s Educational Series|Barron&#039;s]]|isbn = 978-1-4380-0152-4|year=2013 }}&amp;lt;/ref&amp;gt; Data can be discovered along these network paths.&amp;lt;ref&amp;gt;{{cite web|url=http://www.eecs.berkeley.edu/~bh/ssch18/trees.html|title=Simply Scheme: Introducing Computer Science ch 18: Trees|publisher=College Of Engineering, [[University of California, Berkeley]]|url-status=live|archive-url=https://web.archive.org/web/20131222183836/http://www.eecs.berkeley.edu/~bh/ssch18/trees.html|archive-date=2013-12-22}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
An [[IP address]] uses this kind of system of nodes to define its location in a network.&lt;br /&gt;
&lt;br /&gt;
===Definitions===&lt;br /&gt;
*&#039;&#039;&#039;Child&#039;&#039;&#039;: A child node is a node extending from another node. For example, a computer with internet access could be considered a child node of a node representing the internet. The inverse relationship is that of a &#039;&#039;&#039;parent node&#039;&#039;&#039;. If node &#039;&#039;C&#039;&#039; is a child of node &#039;&#039;A&#039;&#039;, then &#039;&#039;A&#039;&#039; is the parent node of &#039;&#039;C&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;Degree&#039;&#039;&#039;: the degree of a node is the number of children of the node.&lt;br /&gt;
*&#039;&#039;&#039;Depth&#039;&#039;&#039;: the depth of node &#039;&#039;A&#039;&#039; is the length of the path from &#039;&#039;A&#039;&#039; to the root node. The root node is said to have depth 0.&lt;br /&gt;
*&#039;&#039;&#039;Edge&#039;&#039;&#039;: the connection between nodes.&lt;br /&gt;
*&#039;&#039;&#039;Forest&#039;&#039;&#039;: a set of trees.&lt;br /&gt;
*&#039;&#039;&#039;Height&#039;&#039;&#039;: the height of node &#039;&#039;A&#039;&#039; is the length of the longest path through children to a leaf node.&lt;br /&gt;
*&#039;&#039;&#039;Internal node&#039;&#039;&#039;: a node with at least one child.&lt;br /&gt;
*&#039;&#039;&#039;Leaf node&#039;&#039;&#039;: a node with no children.&lt;br /&gt;
*&#039;&#039;&#039;Root node&#039;&#039;&#039;: a node distinguished from the rest of the tree nodes. Usually, it is depicted as the highest node of the tree.&lt;br /&gt;
*&#039;&#039;&#039;Sibling nodes&#039;&#039;&#039;: these are nodes connected to the same parent node.&lt;br /&gt;
&lt;br /&gt;
==Markup languages==&lt;br /&gt;
Another common use of node trees is in [[web development]]. In programming, [[XML]] is used to communicate information between computer programmers and computers alike. For this reason XML is used to create common [[communication protocol]]s used in [[office productivity software]], and serves as the base for the development of modern web [[markup language]]s like [[XHTML]]. Though similar in how it is approached by a programmer, [[HTML]] and [[CSS]] is typically the language used to develop website text and design. While XML, HTML and XHTML provide the language and expression, the [[Document Object Model|DOM]] serves as a translator.&amp;lt;ref&amp;gt;{{cite web|url=https://www.w3schools.com/dom/dom_intro.asp|title=XML DOM Introduction|publisher=[[W3Schools]]|url-status=dead|archive-url=https://web.archive.org/web/20140611052725/https://www.w3schools.com/dom/dom_intro.asp|archive-date=2014-06-11|access-date=2018-04-07}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Node type ===&lt;br /&gt;
Different types of nodes in a tree are represented by specific interfaces. In other words, the node type is defined by how it communicates with other nodes. Each node has a node type property, which specifies the type of node, such as sibling or leaf.&lt;br /&gt;
For example, if the node type property is the constant properties for a node, this property specifies the type of the node. So if a node type property is the constant node &amp;lt;code&amp;gt;ELEMENT_NODE&amp;lt;/code&amp;gt;, one can know that this node object is an object &amp;lt;code&amp;gt;Element&amp;lt;/code&amp;gt;. This object uses the &amp;lt;code&amp;gt;Element&amp;lt;/code&amp;gt; interface to define all the methods and properties of that particular node.&lt;br /&gt;
&lt;br /&gt;
Different W3C [[World Wide Web Consortium]] node types and descriptions:&lt;br /&gt;
* &amp;lt;code&amp;gt;Document&amp;lt;/code&amp;gt; represents the entire document (the root-node of the DOM tree) 	&lt;br /&gt;
* &amp;lt;code&amp;gt;DocumentFragment&amp;lt;/code&amp;gt; represents a &amp;quot;lightweight&amp;quot; &amp;lt;code&amp;gt;Document&amp;lt;/code&amp;gt; object, which can hold a portion of a document&lt;br /&gt;
* &amp;lt;code&amp;gt;DocumentType&amp;lt;/code&amp;gt; provides an interface to the entities defined for the document&lt;br /&gt;
* &amp;lt;code&amp;gt;ProcessingInstruction&amp;lt;/code&amp;gt; represents a processing instruction&lt;br /&gt;
* &amp;lt;code&amp;gt;EntityReference&amp;lt;/code&amp;gt; represents an entity reference&lt;br /&gt;
* &amp;lt;code&amp;gt;Element&amp;lt;/code&amp;gt; represents an element&lt;br /&gt;
* &amp;lt;code&amp;gt;Attr&amp;lt;/code&amp;gt; represents an attribute&lt;br /&gt;
* &amp;lt;code&amp;gt;Text&amp;lt;/code&amp;gt; represents textual content in an element or attribute&lt;br /&gt;
* &amp;lt;code&amp;gt;CDATASection&amp;lt;/code&amp;gt; represents a [[CDATA]] section in a document (text that will NOT be parsed by a parser)&lt;br /&gt;
* &amp;lt;code&amp;gt;Comment&amp;lt;/code&amp;gt; represents a comment&lt;br /&gt;
* &amp;lt;code&amp;gt;Entity&amp;lt;/code&amp;gt; represents an entity&lt;br /&gt;
* &amp;lt;code&amp;gt;Notation&amp;lt;/code&amp;gt; represents a notation declared in the DTD&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! &amp;lt;code&amp;gt;NodeType&amp;lt;/code&amp;gt; !! Named constant&lt;br /&gt;
|-&lt;br /&gt;
| 1|| &amp;lt;code&amp;gt;ELEMENT_NODE&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 2|| &amp;lt;code&amp;gt;ATTRIBUTE_NODE&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 3|| &amp;lt;code&amp;gt;TEXT_NODE&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 4|| &amp;lt;code&amp;gt;CDATA_SECTION_NODE&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 5|| &amp;lt;code&amp;gt;ENTITY_REFERENCE_NODE&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 6|| &amp;lt;code&amp;gt;ENTITY_NODE&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 7|| &amp;lt;code&amp;gt;PROCESSING_INSTRUCTION_NODE&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 8|| &amp;lt;code&amp;gt;COMMENT_NODE&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 9|| &amp;lt;code&amp;gt;DOCUMENT_NODE&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 10|| &amp;lt;code&amp;gt;DOCUMENT_TYPE_NODE&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 11|| &amp;lt;code&amp;gt;DOCUMENT_FRAGMENT_NODE&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 12|| &amp;lt;code&amp;gt;NOTATION_NODE&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Node object ===&lt;br /&gt;
A node object is represented by a single node in a tree. It can be an element node, attribute node, text node, or any type that is described in section &amp;quot;node type&amp;quot;. All objects can inherit properties and methods for dealing with parent and child nodes, but not all of the objects have parent or child nodes. For example, with text nodes that cannot have child nodes, trying to add child nodes results in a [[Document Object Model|DOM]] error.&lt;br /&gt;
&lt;br /&gt;
Objects in the DOM tree may be addressed and manipulated by using methods on the objects. The public interface of a DOM is specified in its [[application programming interface]] (API). The history of the Document Object Model is intertwined with the history of the &amp;quot;[[browser wars]]&amp;quot; of the late 1990s between [[Netscape Navigator]] and [[Microsoft Internet Explorer]], as well as with that of [[JavaScript]] and [[JScript]],  the first [[scripting language]]s to be widely implemented in the [[Browser engine|layout engine]]s of [[web browser]]s.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [[Vertex (graph theory)]]&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
{{Reflist}}&lt;br /&gt;
&lt;br /&gt;
==External links==&lt;br /&gt;
* [http://www.community-of-knowledge.de/beitrag/data-trees-as-a-means-of-presenting-complex-data-analysis/ Data Trees as a Means of Presenting Complex Data Analysis] by Sally Knipe&lt;br /&gt;
* [http://tree.phi-sci.com STL-like C++ tree class] {{Webarchive|url=https://web.archive.org/web/20201126210313/http://tree.phi-sci.com/ |date=2020-11-26 }}&lt;br /&gt;
* [https://web.archive.org/web/20180306223544/http://ideainfo.8m.com/ Description of tree data structures from ideainfo.8m.com]&lt;br /&gt;
* [http://wormweb.org/celllineage WormWeb.org: Interactive Visualization of the &#039;&#039;C. elegans&#039;&#039; Cell Tree] - Visualize the entire cell lineage tree of the nematode &#039;&#039;C. elegans&#039;&#039; (javascript)&lt;br /&gt;
&lt;br /&gt;
[[Category:Linked lists]]&lt;br /&gt;
[[Category:Graph data structures]]&lt;/div&gt;</summary>
		<author><name>2605:8D80:5825:1532:D58:188C:5434:D54</name></author>
	</entry>
	<entry>
		<id>https://wiki.sarg.dev/index.php?title=Automatic_differentiation&amp;diff=433343</id>
		<title>Automatic differentiation</title>
		<link rel="alternate" type="text/html" href="https://wiki.sarg.dev/index.php?title=Automatic_differentiation&amp;diff=433343"/>
		<updated>2025-11-03T16:21:49Z</updated>

		<summary type="html">&lt;p&gt;2605:8D80:5825:1532:D58:188C:5434:D54: /* C++ */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Short description|Numerical calculations carrying along derivatives}}&lt;br /&gt;
In [[mathematics]] and [[computer algebra]], &#039;&#039;&#039;automatic differentiation&#039;&#039;&#039; (&#039;&#039;&#039;auto-differentiation&#039;&#039;&#039;, &#039;&#039;&#039;autodiff&#039;&#039;&#039;, or &#039;&#039;&#039;AD&#039;&#039;&#039;), also called &#039;&#039;&#039;algorithmic differentiation&#039;&#039;&#039;, &#039;&#039;&#039;computational differentiation&#039;&#039;&#039;, and &#039;&#039;&#039;differentiation arithmetic&#039;&#039;&#039;&amp;lt;ref&amp;gt;{{cite journal|last=Neidinger|first=Richard D.|title=Introduction to Automatic Differentiation and MATLAB Object-Oriented Programming|journal=SIAM Review| year=2010| volume=52| issue=3| pages=545–563| url=http://academics.davidson.edu/math/neidinger/SIAMRev74362.pdf|doi=10.1137/080743627| citeseerx=10.1.1.362.6580|s2cid=17134969 }}&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;baydin2018automatic&amp;quot;&amp;gt;{{cite journal|last1=Baydin|first1=Atilim Gunes|last2=Pearlmutter| first2=Barak|last3=Radul|first3=Alexey Andreyevich|last4=Siskind|first4=Jeffrey|title=Automatic differentiation in machine learning: a survey| journal=Journal of Machine Learning Research|year=2018|volume=18|pages=1–43|url=http://jmlr.org/papers/v18/17-468.html}}&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;Dawood.Megahed.2023&amp;quot;&amp;gt;[[Hend Dawood]] and [[Nefertiti Megahed]] (2023). Automatic differentiation of uncertainties: an interval computational differentiation for first and higher derivatives with implementation. PeerJ Computer Science 9:e1301 https://doi.org/10.7717/peerj-cs.1301.&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;Dawood.Megahed.2019&amp;quot;&amp;gt;[[Hend Dawood]] and [[Nefertiti Megahed]] (2019). A Consistent and Categorical Axiomatization of Differentiation Arithmetic Applicable to First and Higher Order Derivatives. Punjab University Journal of Mathematics. 51(11). pp. 77-100. doi: 10.5281/zenodo.3479546. http://doi.org/10.5281/zenodo.3479546.&amp;lt;/ref&amp;gt; is a set of techniques to evaluate the [[partial derivative]] of a function specified by a computer program. Automatic differentiation is a subtle and central tool to automate the simultaneous computation of the numerical values of arbitrarily complex functions and their derivatives with no need for the symbolic representation of the derivative, only the function rule or an algorithm thereof is required.&amp;lt;ref name=&amp;quot;Dawood.Megahed.2023&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;Dawood.Megahed.2019&amp;quot;/&amp;gt; Auto-differentiation is thus neither numeric nor symbolic, nor is it a combination of both. It is also preferable to ordinary numerical methods: In contrast to the more traditional numerical methods based on finite differences, auto-differentiation is &#039;in theory&#039; exact, and in comparison to symbolic algorithms, it is computationally inexpensive.&amp;lt;ref name=&amp;quot;Dawood-attribution&amp;quot;&amp;gt;{{Creative Commons text attribution notice|cc=bysa4|url=https://pmc.ncbi.nlm.nih.gov/articles/PMC10280627/|author(s)=Dawood and Megahed}}&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;Dawood.Megahed.2023&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;Dawood.Dawood.2022&amp;quot;&amp;gt;[[Hend Dawood]] and [[Yasser Dawood]] (2022). Interval Root Finding and Interval Polynomials: Methods and Applications in Science and Engineering. In S. Chakraverty, editor, Polynomial Paradigms: Trends and Applications in Science and Engineering, chapter 15. IOP Publishing. ISBN 978-0-7503-5065-5. doi: 10.1088/978-0-7503-5067-9ch15. URL https://doi.org/10.1088/978-0-7503-5067-9ch15.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Automatic differentiation exploits the fact that every computer calculation, no matter how complicated, executes a sequence of elementary arithmetic operations (addition, subtraction, multiplication, division, etc.) and elementary functions ([[exponential function|exp]], [[natural logarithm|log]], [[sine|sin]], [[cosine|cos]], etc.). By applying the [[chain rule]] repeatedly to these operations, partial derivatives of arbitrary order can be computed automatically, accurately to working precision, and using at most a small constant factor of more arithmetic operations than the original program.&lt;br /&gt;
&lt;br /&gt;
== Difference from other differentiation methods ==&lt;br /&gt;
[[Image:AutomaticDifferentiationNutshell.png|right|thumb|300px|Figure 1: How automatic differentiation relates to symbolic differentiation]]&lt;br /&gt;
Automatic differentiation is distinct from [[symbolic differentiation]] and [[numerical differentiation]]. &lt;br /&gt;
Symbolic differentiation faces the difficulty of converting a computer program into a single [[mathematical expression]] and can lead to inefficient code. Numerical differentiation (the method of finite differences) can introduce [[round-off error]]s in the [[discretization]] process and cancellation. Both of these classical methods have problems with calculating higher derivatives, where complexity and errors increase. Finally, both of these classical methods are slow at computing partial derivatives of a function with respect to &#039;&#039;many&#039;&#039; inputs, as is needed for [[gradient descent|gradient]]-based [[Optimization (mathematics)|optimization]] algorithms. Automatic differentiation solves all of these problems.&lt;br /&gt;
&lt;br /&gt;
== Applications ==&lt;br /&gt;
Currently, for its efficiency and accuracy in computing first and higher order [[derivative]]s, auto-differentiation is a celebrated technique with diverse applications in [[scientific computing]] and [[mathematics]]. It should therefore come as no surprise that there are numerous computational implementations of auto-differentiation. Among these, one mentions [[INTLAB]], Sollya, and InCLosure.&amp;lt;ref name=&amp;quot;Rump.1999&amp;quot;&amp;gt;[[Siegfried M. Rump]] (1999). INTLAB–INTerval LABoratory. In T. Csendes, editor, Developments in Reliable Computing, pages 77–104. Kluwer Academic Publishers, Dordrecht.&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;Chevillard.Joldes.Lauter.2010&amp;quot;&amp;gt;S. Chevillard, M. Joldes, and C. Lauter. Sollya (2010). An Environment for the Development of Numerical Codes. In K. Fukuda, J. van der Hoeven, M. Joswig, and N. Takayama, editors, Mathematical Software - ICMS 2010, volume 6327 of Lecture Notes in Computer Science, pages 28–31, Heidelberg, Germany. Springer.&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;Dawood.Inc4.2022&amp;quot;&amp;gt;[[Hend Dawood]] (2022). [[InCLosure]] (Interval enCLosure)–A Language and Environment for Reliable Scientific Computing. Computer Software, Version 4.0. Department of Mathematics. Faculty of Science, Cairo University, Giza, Egypt, September 2022. url: https://doi.org/10.5281/zenodo.2702404.&amp;lt;/ref&amp;gt; In practice, there are two types (modes) of algorithmic differentiation: a forward-type and a reversed-type.&amp;lt;ref name=&amp;quot;Dawood.Megahed.2023&amp;quot; /&amp;gt;&amp;lt;ref name=&amp;quot;Dawood.Megahed.2019&amp;quot; /&amp;gt; Presently, the two types are highly correlated and complementary and both have a wide variety of applications in, e.g., non-linear [[optimization]], [[sensitivity analysis]], [[robotics]], [[machine learning]], [[computer graphics]], and [[computer vision]].&amp;lt;ref name=&amp;quot;Dawood-attribution&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;Fries.2019&amp;quot;&amp;gt;Christian P. Fries (2019). Stochastic Automatic Differentiation: Automatic Differentiation for Monte-Carlo Simulations. Quantitative Finance, 19(6):1043–1059. doi: 10.1080/14697688.2018.1556398. url: https://doi.org/10.1080/14697688.2018.1556398.&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;Dawood.Megahed.2023&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;Dawood.Megahed.2019&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;Dawood.Dawood.2020&amp;quot;&amp;gt;[[Hend Dawood]] and [[Yasser Dawood]] (2020). Universal Intervals: Towards a Dependency-Aware Interval Algebra. In S. Chakraverty, editor, Mathematical Methods in Interdisciplinary Sciences. chapter 10, pages 167–214. John Wiley &amp;amp; Sons, Hoboken, New Jersey. ISBN 978-1-119-58550-3. doi: 10.1002/9781119585640.ch10. url: https://doi.org/10.1002/9781119585640.ch10.&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;Dawood.2014&amp;quot;&amp;gt;[[Hend Dawood]] (2014). Interval Mathematics as a Potential Weapon against Uncertainty. In S. Chakraverty, editor, Mathematics of Uncertainty Modeling in the Analysis of Engineering and Science Problems. chapter 1, pages 1–38. IGI Global, Hershey, PA. ISBN 978-1-4666-4991-0.&amp;lt;/ref&amp;gt; Automatic differentiation is particularly important in the field of [[machine learning]]. For example, it allows one to implement [[backpropagation]] in a [[neural network (machine learning)|neural network]] without a manually-computed derivative.&lt;br /&gt;
&lt;br /&gt;
== Forward and reverse accumulation ==&lt;br /&gt;
=== Chain rule of partial derivatives of composite functions ===&lt;br /&gt;
Fundamental to automatic differentiation is the decomposition of differentials provided by the [[chain rule]] of [[partial derivative]]s of [[function composition|composite functions]]. For the simple composition&lt;br /&gt;
&amp;lt;math display=&amp;quot;block&amp;quot;&amp;gt;\begin{align}&lt;br /&gt;
y &amp;amp;= f(g(h(x))) = f(g(h(w_0))) = f(g(w_1)) = f(w_2) = w_3 \\&lt;br /&gt;
w_0 &amp;amp;= x \\ &lt;br /&gt;
w_1 &amp;amp;= h(w_0) \\&lt;br /&gt;
w_2 &amp;amp;= g(w_1) \\&lt;br /&gt;
w_3 &amp;amp;= f(w_2) = y&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;&lt;br /&gt;
the chain rule gives&lt;br /&gt;
&amp;lt;math display=&amp;quot;block&amp;quot;&amp;gt;\frac{\partial y}{\partial x} = \frac{\partial y}{\partial w_2} \frac{\partial w_2}{\partial w_1} \frac{\partial w_1}{\partial x} = \frac{\partial f(w_2)}{\partial w_2} \frac{\partial g(w_1)}{\partial w_1} \frac{\partial h(w_0)}{\partial x}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Two types of automatic differentiation ===&lt;br /&gt;
Usually, two distinct modes of automatic differentiation are presented.&lt;br /&gt;
* &#039;&#039;&#039;forward accumulation&#039;&#039;&#039; (also called &#039;&#039;&#039;bottom-up&#039;&#039;&#039;, &#039;&#039;&#039;forward mode&#039;&#039;&#039;, or &#039;&#039;&#039;tangent mode&#039;&#039;&#039;)&lt;br /&gt;
* &#039;&#039;&#039;reverse accumulation&#039;&#039;&#039; (also called &#039;&#039;&#039;top-down&#039;&#039;&#039;, &#039;&#039;&#039;reverse mode&#039;&#039;&#039;, or &#039;&#039;&#039;adjoint mode&#039;&#039;&#039;)&lt;br /&gt;
Forward accumulation specifies that one traverses the chain rule from inside to outside (that is, first compute &amp;lt;math&amp;gt;\partial w_1/ \partial x&amp;lt;/math&amp;gt; and then &amp;lt;math&amp;gt;\partial w_2/\partial w_1&amp;lt;/math&amp;gt; and lastly &amp;lt;math&amp;gt;\partial y/\partial w_2&amp;lt;/math&amp;gt;), while reverse accumulation traverses from outside to inside (first compute &amp;lt;math&amp;gt;\partial y/\partial w_2&amp;lt;/math&amp;gt; and then &amp;lt;math&amp;gt;\partial w_2/\partial w_1&amp;lt;/math&amp;gt; and lastly &amp;lt;math&amp;gt;\partial w_1/\partial x&amp;lt;/math&amp;gt;). More succinctly,&lt;br /&gt;
* Forward accumulation computes the recursive relation: &amp;lt;math&amp;gt;\frac{\partial w_i}{\partial x} = \frac{\partial w_i}{\partial w_{i-1}} \frac{\partial w_{i-1}}{\partial x}&amp;lt;/math&amp;gt; with &amp;lt;math&amp;gt;w_3 = y&amp;lt;/math&amp;gt;, and,&lt;br /&gt;
* Reverse accumulation computes the recursive relation: &amp;lt;math&amp;gt;\frac{\partial y}{\partial w_i} = \frac{\partial y}{\partial w_{i+1}} \frac{\partial w_{i+1}}{\partial w_{i}}&amp;lt;/math&amp;gt; with &amp;lt;math&amp;gt;w_0 = x&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The value of the partial derivative, called the &#039;&#039;seed&#039;&#039;, is propagated forward or backward and is initially &amp;lt;math&amp;gt;\frac{\partial x}{\partial x}=1&amp;lt;/math&amp;gt; or &amp;lt;math&amp;gt;\frac{\partial y}{\partial y}=1&amp;lt;/math&amp;gt;. Forward accumulation evaluates the function and calculates the derivative with respect to one independent variable in one pass. For each independent variable &amp;lt;math&amp;gt;x_1,x_2,\dots,x_n&amp;lt;/math&amp;gt; a separate pass is therefore necessary in which the derivative with respect to that independent variable is set to one (&amp;lt;math&amp;gt;\frac{\partial x_1}{\partial x_1}=1&amp;lt;/math&amp;gt;) and of all others to zero (&amp;lt;math&amp;gt;\frac{\partial x_2}{\partial x_1}= \dots = \frac{\partial x_n}{\partial x_1} = 0&amp;lt;/math&amp;gt;). In contrast, reverse accumulation requires the evaluated partial functions for the partial derivatives. Reverse accumulation therefore evaluates the function first and calculates the derivatives with respect to all independent variables in an additional pass.&lt;br /&gt;
&lt;br /&gt;
Which of these two types should be used depends on the sweep count. The [[Computational complexity theory|computational complexity]] of one sweep is proportional to the complexity of the original code.&lt;br /&gt;
* Forward accumulation is more efficient than reverse accumulation for functions {{math|&#039;&#039;f&#039;&#039; : &#039;&#039;&#039;R&#039;&#039;&#039;&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt; → &#039;&#039;&#039;R&#039;&#039;&#039;&amp;lt;sup&amp;gt;&#039;&#039;m&#039;&#039;&amp;lt;/sup&amp;gt;}} with {{math|&#039;&#039;n&#039;&#039; ≪ &#039;&#039;m&#039;&#039;}} as only {{math|&#039;&#039;n&#039;&#039;}} sweeps are necessary, compared to {{math|&#039;&#039;m&#039;&#039;}} sweeps for reverse accumulation.&lt;br /&gt;
* Reverse accumulation is more efficient than forward accumulation for functions {{math|&#039;&#039;f&#039;&#039; : &#039;&#039;&#039;R&#039;&#039;&#039;&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt; → &#039;&#039;&#039;R&#039;&#039;&#039;&amp;lt;sup&amp;gt;&#039;&#039;m&#039;&#039;&amp;lt;/sup&amp;gt;}} with {{math|&#039;&#039;n&#039;&#039; ≫ &#039;&#039;m&#039;&#039;}} as only {{math|&#039;&#039;m&#039;&#039;}} sweeps are necessary, compared to {{math|&#039;&#039;n&#039;&#039;}} sweeps for forward accumulation.&lt;br /&gt;
[[Backpropagation]] of errors in multilayer perceptrons, a technique used in [[machine learning]], is a special case of reverse accumulation.&amp;lt;ref name=&amp;quot;baydin2018automatic&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Forward accumulation was introduced by R.E. Wengert in 1964.&amp;lt;ref name=&amp;quot;Wengert1964&amp;quot;/&amp;gt; According to Andreas Griewank, reverse accumulation has been suggested since the late 1960s, but the inventor is unknown.&amp;lt;ref name=&amp;quot;grie2012&amp;quot;&amp;gt;{{cite book |last=Griewank |first=Andreas |title=Optimization Stories |chapter=Who invented the reverse mode of differentiation? |year=2012  |series=Documenta Mathematica Series |volume=  6|pages=389–400 |doi=10.4171/dms/6/38 |doi-access=free |isbn=978-3-936609-58-5 |chapter-url=https://ftp.gwdg.de/pub/misc/EMIS/journals/DMJDMV/vol-ismp/52_griewank-andreas-b.pdf }}&amp;lt;/ref&amp;gt; [[Seppo Linnainmaa]] published reverse accumulation in 1976.&amp;lt;ref name=&amp;quot;lin1976&amp;quot;&amp;gt;{{cite journal |last=Linnainmaa |first=Seppo |year=1976 |title=Taylor Expansion of the Accumulated Rounding Error |journal=BIT Numerical Mathematics |volume=16 |issue=2 |pages=146–160 |doi=10.1007/BF01931367 |s2cid=122357351 }}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Forward accumulation ===&lt;br /&gt;
[[File:ForwardAD.png|thumb|Forward accumulation]]&lt;br /&gt;
In forward accumulation AD, one first fixes the &#039;&#039;independent variable&#039;&#039; with respect to which differentiation is performed and computes the derivative of each sub-[[expression (mathematics)|expression]] recursively. In a pen-and-paper calculation, this involves repeatedly substituting the derivative of the &#039;&#039;inner&#039;&#039; functions in the chain rule:&lt;br /&gt;
&amp;lt;math display=&amp;quot;block&amp;quot;&amp;gt;\begin{align}&lt;br /&gt;
\frac{\partial y}{\partial x}&lt;br /&gt;
&amp;amp;= \frac{\partial y}{\partial w_{n-1}} \frac{\partial w_{n-1}}{\partial x} \\[6pt]&lt;br /&gt;
&amp;amp;= \frac{\partial y}{\partial w_{n-1}} \left(\frac{\partial w_{n-1}}{\partial w_{n-2}} \frac{\partial w_{n-2}}{\partial x}\right) \\[6pt]&lt;br /&gt;
&amp;amp;= \frac{\partial y}{\partial w_{n-1}} \left(\frac{\partial w_{n-1}}{\partial w_{n-2}} \left(\frac{\partial w_{n-2}}{\partial w_{n-3}} \frac{\partial w_{n-3}}{\partial x}\right)\right) \\[6pt]&lt;br /&gt;
&amp;amp;= \cdots&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;&lt;br /&gt;
This can be generalized to multiple variables as a matrix product of [[Jacobian matrix and determinant|Jacobian]]s.&lt;br /&gt;
&lt;br /&gt;
Compared to reverse accumulation, forward accumulation is natural and easy to implement as the flow of derivative information coincides with the order of evaluation. Each variable &amp;lt;math&amp;gt;w_i&amp;lt;/math&amp;gt; is augmented with its derivative &amp;lt;math&amp;gt;\dot w_i&amp;lt;/math&amp;gt; (stored as a numerical value, not a symbolic expression),&lt;br /&gt;
&amp;lt;math display=&amp;quot;block&amp;quot;&amp;gt;\dot w_i = \frac{\partial w_i}{\partial x}&amp;lt;/math&amp;gt;&lt;br /&gt;
as denoted by the dot. The derivatives are then computed in sync with the evaluation steps and combined with other derivatives via the chain rule.&lt;br /&gt;
&lt;br /&gt;
Using the chain rule, if &amp;lt;math&amp;gt;w_i&amp;lt;/math&amp;gt; has predecessors in the computational graph:&lt;br /&gt;
:&amp;lt;math&amp;gt;\dot w_i = \sum_{j \in \{\text{predecessors of i}\}} \frac{\partial w_i}{\partial w_j} \dot w_j&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:ForwardAccumulationAutomaticDifferentiation.png|right|thumb|300px|Figure 2: Example of forward accumulation with computational graph]]&lt;br /&gt;
&lt;br /&gt;
As an example, consider the function:&lt;br /&gt;
&amp;lt;math display=&amp;quot;block&amp;quot;&amp;gt;\begin{align}&lt;br /&gt;
y&lt;br /&gt;
&amp;amp;= f(x_1, x_2) \\&lt;br /&gt;
&amp;amp;= x_1 x_2 + \sin x_1 \\&lt;br /&gt;
&amp;amp;= w_1 w_2 + \sin w_1 \\&lt;br /&gt;
&amp;amp;= w_3 + w_4 \\&lt;br /&gt;
&amp;amp;= w_5&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;&lt;br /&gt;
For clarity, the individual sub-expressions have been labeled with the variables &amp;lt;math&amp;gt;w_i&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The choice of the independent variable to which differentiation is performed affects the &#039;&#039;seed&#039;&#039; values {{math|&#039;&#039;ẇ&#039;&#039;&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;}} and {{math|&#039;&#039;ẇ&#039;&#039;&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;}}. Given interest in the derivative of this function with respect to {{math|&#039;&#039;x&#039;&#039;&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;}}, the seed values should be set to:&lt;br /&gt;
&amp;lt;math display=&amp;quot;block&amp;quot;&amp;gt;\begin{align}&lt;br /&gt;
\dot w_1 = \frac{\partial w_1}{\partial x_1} = \frac{\partial x_1}{\partial x_1} = 1 \\&lt;br /&gt;
\dot w_2 = \frac{\partial w_2}{\partial x_1} = \frac{\partial x_2}{\partial x_1} = 0&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With the seed values set, the values propagate using the chain rule as shown. Figure 2 shows a pictorial depiction of this process as a computational graph.&lt;br /&gt;
:{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Operations to compute value !!Operations to compute derivative&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;math&amp;gt;w_1 = x_1&amp;lt;/math&amp;gt; || &amp;lt;math&amp;gt;\dot w_1 = 1&amp;lt;/math&amp;gt; (seed)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;math&amp;gt;w_2 = x_2&amp;lt;/math&amp;gt; || &amp;lt;math&amp;gt;\dot w_2 = 0&amp;lt;/math&amp;gt; (seed)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;math&amp;gt;w_3 = w_1 \cdot w_2&amp;lt;/math&amp;gt; || &amp;lt;math&amp;gt;\dot w_3 = w_2 \cdot \dot w_1 + w_1 \cdot \dot w_2&amp;lt;/math&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;math&amp;gt;w_4 = \sin w_1&amp;lt;/math&amp;gt; || &amp;lt;math&amp;gt;\dot w_4 = \cos w_1 \cdot \dot w_1&amp;lt;/math&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;math&amp;gt;w_5 = w_3 + w_4&amp;lt;/math&amp;gt; || &amp;lt;math&amp;gt;\dot w_5 = \dot w_3 + \dot w_4&amp;lt;/math&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
To compute the [[gradient]] of this example function, which requires not only &amp;lt;math&amp;gt;\tfrac{\partial y}{\partial x_1}&amp;lt;/math&amp;gt; but also &amp;lt;math&amp;gt;\tfrac{\partial y}{\partial x_2}&amp;lt;/math&amp;gt;, an &#039;&#039;additional&#039;&#039; sweep is performed over the computational graph using the seed values &amp;lt;math&amp;gt;\dot w_1 = 0; \dot w_2 = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Implementation ====&lt;br /&gt;
===== Pseudocode =====&lt;br /&gt;
Forward accumulation calculates the function and the derivative (but only for one independent variable each) in one pass. The associated method call expects the expression &#039;&#039;Z&#039;&#039; to be derived with regard to a variable &#039;&#039;V&#039;&#039;. The method returns a pair of the evaluated function and its derivative. The method traverses the expression tree recursively until a variable is reached. If the derivative with respect to this variable is requested, its derivative is 1, 0 otherwise. Then the partial function as well as the partial derivative are evaluated.&amp;lt;ref name=demm22&amp;gt;{{cite book|author = Maximilian E. Schüle, Maximilian Springer, [[Alfons Kemper]], [[Thomas Neumann]] |title=Proceedings of the Sixth Workshop on Data Management for End-To-End Machine Learning |chapter=LLVM code optimisation for automatic differentiation |date=2022|pages=1–4 |doi = 10.1145/3533028.3533302|isbn=9781450393751 |s2cid=248853034 |language=English}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
Tuple&amp;lt;float, float&amp;gt; evaluateAndDerive(Expression Z, Variable V) {&lt;br /&gt;
    if isVariable(Z) {&lt;br /&gt;
        if (Z = V) {&lt;br /&gt;
            return {valueOf(Z), 1};&lt;br /&gt;
        } else {&lt;br /&gt;
            return {valueOf(Z), 0};&lt;br /&gt;
        }&lt;br /&gt;
    } else if (Z = A + B) {&lt;br /&gt;
        {a, a&#039;} = evaluateAndDerive(A, V);&lt;br /&gt;
        {b, b&#039;} = evaluateAndDerive(B, V);&lt;br /&gt;
        return {a + b, a&#039; + b&#039;};&lt;br /&gt;
    } else if (Z = A - B) {&lt;br /&gt;
        {a, a&#039;} = evaluateAndDerive(A, V);&lt;br /&gt;
        {b, b&#039;} = evaluateAndDerive(B, V);&lt;br /&gt;
        return {a - b, a&#039; - b&#039;};&lt;br /&gt;
    } else if (Z = A * B) {&lt;br /&gt;
        {a, a&#039;} = evaluateAndDerive(A, V);&lt;br /&gt;
        {b, b&#039;} = evaluateAndDerive(B, V);&lt;br /&gt;
        return {a * b, b * a&#039; + a * b&#039;};&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== C++ =====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
import std;&lt;br /&gt;
&lt;br /&gt;
using std::unique_ptr;&lt;br /&gt;
&lt;br /&gt;
struct ValueAndPartial {&lt;br /&gt;
    float value;&lt;br /&gt;
    float partial;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Expression {&lt;br /&gt;
public:&lt;br /&gt;
    virtual ValueAndPartial evaluateAndDerive(class Variable* variable) const noexcept = 0;&lt;br /&gt;
    virtual ~Expression() = default;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Variable : public Expression {&lt;br /&gt;
private:&lt;br /&gt;
    float value;&lt;br /&gt;
public:&lt;br /&gt;
    explicit Variable(float value):&lt;br /&gt;
        value{value} {}&lt;br /&gt;
&lt;br /&gt;
    [[nodiscard]]&lt;br /&gt;
    ValueAndPartial evaluateAndDerive(Variable* variable) const noexcept override {&lt;br /&gt;
        float partial = (this == variable) ? 1.0f : 0.0f;&lt;br /&gt;
        return {value, partial};&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    [[nodiscard]]&lt;br /&gt;
    float getValue() const noexcept {&lt;br /&gt;
        return value;&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Plus : public Expression {&lt;br /&gt;
private:&lt;br /&gt;
    unique_ptr&amp;lt;Expression&amp;gt; a;&lt;br /&gt;
    unique_ptr&amp;lt;Expression&amp;gt; b;&lt;br /&gt;
public:&lt;br /&gt;
    Plus(unique_ptr&amp;lt;Expression&amp;gt; a, unique_ptr&amp;lt;Expression&amp;gt; b):&lt;br /&gt;
        a{std::move(a)}, b{std::move(b)} {}&lt;br /&gt;
&lt;br /&gt;
    [[nodiscard]]&lt;br /&gt;
    ValueAndPartial evaluateAndDerive(Variable* variable) const noexcept override {&lt;br /&gt;
        auto [valueA, partialA] = a-&amp;gt;evaluateAndDerive(variable);&lt;br /&gt;
        auto [valueB, partialB] = b-&amp;gt;evaluateAndDerive(variable);&lt;br /&gt;
        return {valueA + valueB, partialA + partialB};&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Multiply : public Expression {&lt;br /&gt;
private:&lt;br /&gt;
    unique_ptr&amp;lt;Expression&amp;gt; a;&lt;br /&gt;
    unique_ptr&amp;lt;Expression&amp;gt; b;&lt;br /&gt;
public:&lt;br /&gt;
    Multiply(unique_ptr&amp;lt;Expression&amp;gt; a, unique_ptr&amp;lt;Expression&amp;gt; b): &lt;br /&gt;
        a{std::move(a)}, b{std::move(b)} {}&lt;br /&gt;
&lt;br /&gt;
    [[nodiscard]]&lt;br /&gt;
    ValueAndPartial evaluateAndDerive(Variable* variable) const noexcept override {&lt;br /&gt;
        auto [valueA, partialA] = a-&amp;gt;evaluateAndDerive(variable);&lt;br /&gt;
        auto [valueB, partialB] = b-&amp;gt;evaluateAndDerive(variable);&lt;br /&gt;
        return {valueA * valueB, valueB * partialA + valueA * partialB};&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    // Example: Finding the partials of z = x * (x + y) + y * y at (x, y) = (2, 3)&lt;br /&gt;
    Variable x(2.0f);&lt;br /&gt;
    Variable y(3.0f);&lt;br /&gt;
&lt;br /&gt;
    // Create expressions using smart pointers&lt;br /&gt;
    unique_ptr&amp;lt;Plus&amp;gt; p1 = std::make_unique&amp;lt;Plus&amp;gt;(std::make_unique&amp;lt;Variable&amp;gt;(x), std::make_unique&amp;lt;Variable&amp;gt;(y));&lt;br /&gt;
    unique_ptr&amp;lt;Multiply&amp;gt; m1 = std::make_unique&amp;lt;Multiply&amp;gt;(std::make_unique&amp;lt;Variable&amp;gt;(x), std::move(p1));&lt;br /&gt;
    unique_ptr&amp;lt;Multiply&amp;gt; m2 = std::make_unique&amp;lt;Multiply&amp;gt;(std::make_unique&amp;lt;Variable&amp;gt;(y), std::make_unique&amp;lt;Variable&amp;gt;(y));&lt;br /&gt;
    unique_ptr&amp;lt;Plus&amp;gt; z = std::make_unique&amp;lt;Plus&amp;gt;(std::move(m1), std::move(m2));&lt;br /&gt;
&lt;br /&gt;
    // Evaluate the partials&lt;br /&gt;
    float xPartial = z-&amp;gt;evaluateAndDerive(&amp;amp;x).partial;&lt;br /&gt;
    float yPartial = z-&amp;gt;evaluateAndDerive(&amp;amp;y).partial;&lt;br /&gt;
    &lt;br /&gt;
    std::println(&amp;quot;∂z/∂x = {}, ∂z/∂y = {}&amp;quot;, xPartial, yPartial);&lt;br /&gt;
    // Output: ∂z/∂x = 7, ∂z/∂y = 8&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Reverse accumulation ===&lt;br /&gt;
[[File:AutoDiff.webp|thumb|Reverse accumulation]]&lt;br /&gt;
In reverse accumulation AD, the &#039;&#039;dependent variable&#039;&#039; to be differentiated is fixed and the derivative is computed &#039;&#039;with respect to&#039;&#039; each sub-[[expression (mathematics)|expression]] recursively. In a pen-and-paper calculation, the derivative of the &#039;&#039;outer&#039;&#039; functions is repeatedly substituted in the chain rule:&lt;br /&gt;
&amp;lt;math display=&amp;quot;block&amp;quot;&amp;gt;\begin{align}&lt;br /&gt;
\frac{\partial y}{\partial x}&lt;br /&gt;
&amp;amp;= \frac{\partial y}{\partial w_1} \frac{\partial w_1}{\partial x}\\&lt;br /&gt;
&amp;amp;= \left(\frac{\partial y}{\partial w_2} \frac{\partial w_2}{\partial w_1}\right) \frac{\partial w_1}{\partial x}\\&lt;br /&gt;
&amp;amp;= \left(\left(\frac{\partial y}{\partial w_3} \frac{\partial w_3}{\partial w_2}\right) \frac{\partial w_2}{\partial w_1}\right) \frac{\partial w_1}{\partial x}\\&lt;br /&gt;
&amp;amp;= \cdots&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In reverse accumulation, the quantity of interest is the &#039;&#039;adjoint&#039;&#039;, denoted with a bar &amp;lt;math&amp;gt;\bar w_i&amp;lt;/math&amp;gt;; it is a derivative of a chosen dependent variable with respect to a subexpression &amp;lt;math&amp;gt;w_i&amp;lt;/math&amp;gt;:&lt;br /&gt;
&amp;lt;math display=&amp;quot;block&amp;quot;&amp;gt;\bar w_i = \frac{\partial y}{\partial w_i}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using the chain rule, if &amp;lt;math&amp;gt;w_i&amp;lt;/math&amp;gt; has successors in the computational graph:&lt;br /&gt;
:&amp;lt;math&amp;gt;\bar w_i = \sum_{j \in \{\text{successors of i}\}} \bar w_j \frac{\partial w_j}{\partial w_i}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reverse accumulation traverses the chain rule from outside to inside, or in the case of the computational graph in Figure 3, from top to bottom. The example function is scalar-valued, and thus there is only one seed for the derivative computation, and only one sweep of the computational graph is needed to calculate the (two-component) gradient. This is only [[space–time tradeoff|half the work]] when compared to forward accumulation, but reverse accumulation requires the storage of the intermediate variables {{math|&#039;&#039;w&#039;&#039;&amp;lt;sub&amp;gt;&#039;&#039;i&#039;&#039;&amp;lt;/sub&amp;gt;}} as well as the instructions that produced them in a data structure known as a &amp;quot;tape&amp;quot; or a Wengert list&amp;lt;ref&amp;gt;{{cite journal|last1=Bartholomew-Biggs|first1=Michael| last2=Brown|first2=Steven|last3=Christianson|first3=Bruce|last4=Dixon|first4=Laurence|date=2000|title=Automatic differentiation of algorithms|journal=Journal of Computational and Applied Mathematics| volume=124|issue=1–2|pages=171–190| doi=10.1016/S0377-0427(00)00422-2|bibcode=2000JCoAM.124..171B|hdl=2299/3010|hdl-access=free}}&amp;lt;/ref&amp;gt; (however, Wengert published forward accumulation, not reverse accumulation&amp;lt;ref name=&amp;quot;Wengert1964&amp;quot;&amp;gt;{{cite journal|author=R.E. Wengert|title=A simple automatic derivative evaluation program|journal=Comm. ACM|volume=7&lt;br /&gt;
|issue=8|year=1964|pages=463–464|doi=10.1145/355586.364791|s2cid=24039274|doi-access=free}}&amp;lt;/ref&amp;gt;), which may consume significant memory if the computational graph is large. This can be mitigated to some extent by storing only a subset of the intermediate variables and then reconstructing the necessary work variables by repeating the evaluations, a technique known as [[rematerialization]]. [[checkpointing scheme|Checkpointing]] is also used to save intermediary states.&lt;br /&gt;
&lt;br /&gt;
[[Image:ReverseaccumulationAD.png|right|thumb|300px|Figure 3: Example of reverse accumulation with computational graph]]&lt;br /&gt;
&lt;br /&gt;
The operations to compute the derivative using reverse accumulation are shown in the table below (note the reversed order):&lt;br /&gt;
{{block indent|&lt;br /&gt;
; Operations to compute derivative&lt;br /&gt;
:&amp;lt;math&amp;gt;\bar w_5 = 1 \text{ (seed)}&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;\bar w_4 = \bar w_5 \cdot 1&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;\bar w_3 = \bar w_5 \cdot 1&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;\bar w_2 = \bar w_3 \cdot w_1&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;\bar w_1 = \bar w_3 \cdot w_2 + \bar w_4 \cdot \cos w_1&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
The data flow graph of a computation can be manipulated to calculate the gradient of its original calculation. This is done by adding an adjoint node for each primal node, connected by adjoint edges which parallel the primal edges but flow in the opposite direction. The nodes in the adjoint graph represent multiplication by the derivatives of the functions calculated by the nodes in the primal. For instance, addition in the primal causes fanout in the adjoint; fanout in the primal causes addition in the adjoint;{{efn|In terms of weight matrices, the adjoint is the [[transpose]]. Addition is the [[covector]] &amp;lt;math&amp;gt;[1 \cdots 1]&amp;lt;/math&amp;gt;, since &amp;lt;math&amp;gt;[1 \cdots 1]\left[\begin{smallmatrix}x_1 \\ \vdots \\ x_n \end{smallmatrix}\right] = x_1 + \cdots + x_n,&amp;lt;/math&amp;gt; and fanout is the vector &amp;lt;math&amp;gt;\left[\begin{smallmatrix}1 \\ \vdots \\ 1 \end{smallmatrix}\right],&amp;lt;/math&amp;gt; since &amp;lt;math&amp;gt;\left[\begin{smallmatrix}1 \\ \vdots \\ 1 \end{smallmatrix}\right][x] = \left[\begin{smallmatrix}x \\ \vdots \\ x \end{smallmatrix}\right].&amp;lt;/math&amp;gt;}} a [[unary operation|unary]] function {{math|1=&#039;&#039;y&#039;&#039; = &#039;&#039;f&#039;&#039;(&#039;&#039;x&#039;&#039;)}} in the primal causes {{math|1=&#039;&#039;x̄&#039;&#039; = &#039;&#039;ȳ&#039;&#039; &#039;&#039;f&#039;&#039;′(&#039;&#039;x&#039;&#039;)}} in the adjoint; etc.&lt;br /&gt;
&lt;br /&gt;
==== Implementation ====&lt;br /&gt;
===== Pseudo code =====&lt;br /&gt;
Reverse accumulation requires two passes: In the forward pass, the function is evaluated first and the partial results are cached. In the reverse pass, the partial derivatives are calculated and the previously derived value is backpropagated. The corresponding method call expects the expression &#039;&#039;Z&#039;&#039; to be derived and &#039;&#039;seeded&#039;&#039; with the derived value of the parent expression. For the top expression, Z differentiated with respect to Z, this is 1. The method traverses the expression tree recursively until a variable is reached and adds the current &#039;&#039;seed&#039;&#039; value to the derivative expression.&amp;lt;ref name=ssdbm21&amp;gt;{{cite book|author= Maximilian E. Schüle, Harald Lang, Maximilian Springer, [[Alfons Kemper]], [[Thomas Neumann]], Stephan Günnemann|title=33rd International Conference on Scientific and Statistical Database Management |chapter=In-Database Machine Learning with SQL on GPUs |date=2021|pages=25–36 |doi = 10.1145/3468791.3468840|isbn=9781450384131 |s2cid=235386969 |language=English}}&amp;lt;/ref&amp;gt;&amp;lt;ref name=dpd&amp;gt;{{cite journal|author= Maximilian E. Schüle, Harald Lang, Maximilian Springer, [[Alfons Kemper]], [[Thomas Neumann]], Stephan Günnemann|title=Recursive SQL and GPU-support for in-database machine learning|journal=Distributed and Parallel Databases|date=2022|volume=40 |issue=2–3 |pages=205–259 |doi = 10.1007/s10619-022-07417-7|s2cid=250412395 |language=English|doi-access=free}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
void derive(Expression Z, float seed) {&lt;br /&gt;
    if isVariable(Z) {&lt;br /&gt;
        partialDerivativeOf(Z) += seed;&lt;br /&gt;
    } else if (Z = A + B) {&lt;br /&gt;
        derive(A, seed);&lt;br /&gt;
        derive(B, seed);&lt;br /&gt;
    } else if (Z = A - B) {&lt;br /&gt;
        derive(A, seed);&lt;br /&gt;
        derive(B, -seed);&lt;br /&gt;
    } else if (Z = A * B) {&lt;br /&gt;
        derive(A, valueOf(B) * seed);&lt;br /&gt;
        derive(B, valueOf(A) * seed);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== C++ =====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
import std;&lt;br /&gt;
&lt;br /&gt;
using std::unique_ptr;&lt;br /&gt;
&lt;br /&gt;
class Expression {&lt;br /&gt;
private:&lt;br /&gt;
    float value;&lt;br /&gt;
public:&lt;br /&gt;
    virtual void evaluate() noexcept = 0;&lt;br /&gt;
    virtual void derive(float seed) noexcept = 0;&lt;br /&gt;
    virtual ~Expression() = default;&lt;br /&gt;
&lt;br /&gt;
    [[nodiscard]]&lt;br /&gt;
    float getValue() const noexcept {&lt;br /&gt;
        return value;&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Variable : public Expression {&lt;br /&gt;
private:&lt;br /&gt;
    float partial;&lt;br /&gt;
public:&lt;br /&gt;
    explicit Variable(float value): &lt;br /&gt;
        value{value}, partial{0.0f} {}&lt;br /&gt;
&lt;br /&gt;
    void evaluate() noexcept override {&lt;br /&gt;
        // no-op&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void derive(float seed) noexcept override {&lt;br /&gt;
        partial += seed;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    [[nodiscard]]&lt;br /&gt;
    float getPartial() const noexcept {&lt;br /&gt;
        return partial;&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Plus : public Expression {&lt;br /&gt;
private:&lt;br /&gt;
    unique_ptr&amp;lt;Expression&amp;gt; a;&lt;br /&gt;
    unique_ptr&amp;lt;Expression&amp;gt; b;&lt;br /&gt;
public:&lt;br /&gt;
    Plus(unique_ptr&amp;lt;Expression&amp;gt; a, unique_ptr&amp;lt;Expression&amp;gt; b): &lt;br /&gt;
        a{std::move(a)}, b{std::move(b)} {}&lt;br /&gt;
&lt;br /&gt;
    void evaluate() noexcept override {&lt;br /&gt;
        a-&amp;gt;evaluate();&lt;br /&gt;
        b-&amp;gt;evaluate();&lt;br /&gt;
        value = a-&amp;gt;value + b-&amp;gt;value;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void derive(float seed) noexcept override {&lt;br /&gt;
        a-&amp;gt;derive(seed);&lt;br /&gt;
        b-&amp;gt;derive(seed);&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Multiply : public Expression {&lt;br /&gt;
private:&lt;br /&gt;
    unique_ptr&amp;lt;Expression&amp;gt; a;&lt;br /&gt;
    unique_ptr&amp;lt;Expression&amp;gt; b;&lt;br /&gt;
public:&lt;br /&gt;
    Multiply(unique_ptr&amp;lt;Expression&amp;gt; a, unique_ptr&amp;lt;Expression&amp;gt; b):&lt;br /&gt;
        a{std::move(a)}, b{std::move(b)} {}&lt;br /&gt;
&lt;br /&gt;
    void evaluate() noexcept override {&lt;br /&gt;
        a-&amp;gt;evaluate();&lt;br /&gt;
        b-&amp;gt;evaluate();&lt;br /&gt;
        value = a-&amp;gt;value * b-&amp;gt;value;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void derive(float seed) noexcept override {&lt;br /&gt;
        a-&amp;gt;derive(b-&amp;gt;value * seed);&lt;br /&gt;
        b-&amp;gt;derive(a-&amp;gt;value * seed);&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    // Example: Finding the partials of z = x * (x + y) + y * y at (x, y) = (2, 3)&lt;br /&gt;
    Variable x(2.0f);&lt;br /&gt;
    Variable y(3.0f);&lt;br /&gt;
&lt;br /&gt;
    // Create expressions using smart pointers&lt;br /&gt;
    unique_ptr&amp;lt;Plus&amp;gt; p1 = std::make_unique&amp;lt;Plus&amp;gt;(std::make_unique&amp;lt;Variable&amp;gt;(x), std::make_unique&amp;lt;Variable&amp;gt;(y));&lt;br /&gt;
    unique_ptr&amp;lt;Multiply&amp;gt; m1 = std::make_unique&amp;lt;Multiply&amp;gt;(std::make_unique&amp;lt;Variable&amp;gt;(x), std::move(p1));&lt;br /&gt;
    unique_ptr&amp;lt;Multiply&amp;gt; m2 = std::make_unique&amp;lt;Multiply&amp;gt;(std::make_unique&amp;lt;Variable&amp;gt;(y), std::make_unique&amp;lt;Variable&amp;gt;(y));&lt;br /&gt;
    unique_ptr&amp;lt;Plus&amp;gt; z = std::make_unique&amp;lt;Plus&amp;gt;(std::move(m1), std::move(m2));&lt;br /&gt;
&lt;br /&gt;
    // Evaluate the expression&lt;br /&gt;
    z-&amp;gt;evaluate();&lt;br /&gt;
    std::println(&amp;quot;z = {}&amp;quot;, z-&amp;gt;getValue());&lt;br /&gt;
    // Output: z = 19&lt;br /&gt;
&lt;br /&gt;
    // Derivative calculation (partials)&lt;br /&gt;
    z-&amp;gt;derive(1); // Derivative with respect to x and y&lt;br /&gt;
&lt;br /&gt;
    std::println(&amp;quot;∂z/∂x = {}, ∂z/∂y = {}&amp;quot;, x.getPartial(), y.getPartial());&lt;br /&gt;
    // Output: ∂z/∂x = 7, ∂z/∂y = 8&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Beyond forward and reverse accumulation ===&lt;br /&gt;
&lt;br /&gt;
Forward and reverse accumulation are just two (extreme) ways of traversing the chain rule. The problem of computing a full Jacobian of {{math|&#039;&#039;f&#039;&#039; : &#039;&#039;&#039;R&#039;&#039;&#039;&amp;lt;sup&amp;gt;&#039;&#039;n&#039;&#039;&amp;lt;/sup&amp;gt; → &#039;&#039;&#039;R&#039;&#039;&#039;&amp;lt;sup&amp;gt;&#039;&#039;m&#039;&#039;&amp;lt;/sup&amp;gt;}} with a minimum number of arithmetic operations is known as the &#039;&#039;optimal Jacobian accumulation&#039;&#039; (OJA) problem, which is [[NP-complete]].&amp;lt;ref&amp;gt;{{Cite journal|first=Uwe|last=Naumann|journal=Mathematical Programming|volume=112|issue=2|pages=427–441|date=April 2008|doi=10.1007/s10107-006-0042-z|title=Optimal Jacobian accumulation is NP-complete|citeseerx=10.1.1.320.5665|s2cid=30219572}}&amp;lt;/ref&amp;gt; Central to this proof is the idea that algebraic dependencies may exist between the local partials that label the edges of the graph. In particular, two or more edge labels may be recognized as equal. The complexity of the problem is still open if it is assumed that all edge labels are unique and algebraically independent.&lt;br /&gt;
&lt;br /&gt;
== Automatic differentiation using dual numbers ==&lt;br /&gt;
&lt;br /&gt;
Forward mode automatic differentiation is accomplished by augmenting the [[Algebra over a field|algebra]] of [[real numbers]] and obtaining a new [[arithmetic]]. An additional component is added to every number to represent the derivative of a function at the number, and all arithmetic operators are extended for the augmented algebra. The augmented algebra is the algebra of [[dual numbers]].&lt;br /&gt;
&lt;br /&gt;
Replace every number &amp;lt;math&amp;gt;\,x&amp;lt;/math&amp;gt; with the number &amp;lt;math&amp;gt;x + x&#039;\varepsilon&amp;lt;/math&amp;gt;, where &amp;lt;math&amp;gt;x&#039;&amp;lt;/math&amp;gt; is a real number, but &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; is an [[abstract number]] with the property &amp;lt;math&amp;gt;\varepsilon^2=0&amp;lt;/math&amp;gt; (an [[infinitesimal]]; see &#039;&#039;[[Smooth infinitesimal analysis]]&#039;&#039;). Using only this, regular arithmetic gives&lt;br /&gt;
&amp;lt;math display=&amp;quot;block&amp;quot;&amp;gt;\begin{align}&lt;br /&gt;
      (x + x&#039;\varepsilon) + (y + y&#039;\varepsilon) &amp;amp;= x + y + (x&#039; + y&#039;)\varepsilon \\&lt;br /&gt;
      (x + x&#039;\varepsilon) - (y + y&#039;\varepsilon) &amp;amp;= x - y + (x&#039; - y&#039;)\varepsilon \\&lt;br /&gt;
  (x + x&#039;\varepsilon) \cdot (y + y&#039;\varepsilon) &amp;amp;= xy + xy&#039;\varepsilon + yx&#039;\varepsilon + x&#039;y&#039;\varepsilon^2 = xy + (x y&#039; + yx&#039;)\varepsilon \\&lt;br /&gt;
  (x + x&#039;\varepsilon) / (y + y&#039;\varepsilon) &amp;amp;= (x/y + x&#039;\varepsilon/y) / (1 + y&#039;\varepsilon/y) = (x/y + x&#039;\varepsilon/y) \cdot (1 - y&#039;\varepsilon/y) = x/y + (x&#039;/y - xy&#039;/y^2)\varepsilon&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;&lt;br /&gt;
using &amp;lt;math&amp;gt;(1 + y&#039;\varepsilon/y) \cdot (1 - y&#039;\varepsilon/y) = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Now, [[polynomials]] can be calculated in this augmented arithmetic. If &amp;lt;math&amp;gt;P(x) = p_0 + p_1 x + p_2x^2 + \cdots + p_n x^n&amp;lt;/math&amp;gt;, then&lt;br /&gt;
&amp;lt;math display=&amp;quot;block&amp;quot;&amp;gt;\begin{align}&lt;br /&gt;
  P(x + x&#039;\varepsilon) &amp;amp;= p_0 + p_1(x + x&#039;\varepsilon) + \cdots + p_n (x + x&#039;\varepsilon)^n \\&lt;br /&gt;
                       &amp;amp;= p_0 + p_1 x + \cdots + p_n x^n + p_1x&#039;\varepsilon + 2p_2xx&#039;\varepsilon + \cdots + np_n x^{n-1} x&#039;\varepsilon \\&lt;br /&gt;
                       &amp;amp;= P(x) + P^{(1)}(x)x&#039;\varepsilon&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;&lt;br /&gt;
where &amp;lt;math&amp;gt;P^{(1)}&amp;lt;/math&amp;gt; denotes the derivative of &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; with respect to its first argument, and &amp;lt;math&amp;gt;x&#039;&amp;lt;/math&amp;gt;, called a &#039;&#039;seed&#039;&#039;, can be chosen arbitrarily.&lt;br /&gt;
&lt;br /&gt;
The new arithmetic consists of [[ordered pair]]s, elements written &amp;lt;math&amp;gt;\langle x, x&#039; \rangle&amp;lt;/math&amp;gt;, with ordinary arithmetics on the first component, and first order differentiation arithmetic on the second component, as described above. Extending the above results on polynomials to [[analytic functions]] gives a list of the basic arithmetic and some standard functions for the new arithmetic:&lt;br /&gt;
&amp;lt;math display=&amp;quot;block&amp;quot;&amp;gt;\begin{align}&lt;br /&gt;
  \left\langle u,u&#039;\right\rangle + \left\langle v,v&#039;\right\rangle &amp;amp;= \left\langle u + v, u&#039; + v&#039; \right\rangle \\&lt;br /&gt;
  \left\langle u,u&#039;\right\rangle - \left\langle v,v&#039;\right\rangle &amp;amp;= \left\langle u - v, u&#039; - v&#039; \right\rangle \\&lt;br /&gt;
  \left\langle u,u&#039;\right\rangle * \left\langle v,v&#039;\right\rangle &amp;amp;= \left\langle u v, u&#039;v + uv&#039; \right\rangle \\&lt;br /&gt;
  \left\langle u,u&#039;\right\rangle / \left\langle v,v&#039;\right\rangle &amp;amp;= \left\langle \frac{u}{v}, \frac{u&#039;v - uv&#039;}{v^2} \right\rangle \quad ( v\ne 0) \\&lt;br /&gt;
                               \sin\left\langle u,u&#039;\right\rangle &amp;amp;= \left\langle \sin(u) , u&#039; \cos(u) \right\rangle \\&lt;br /&gt;
                               \cos\left\langle u,u&#039;\right\rangle &amp;amp;= \left\langle \cos(u) , -u&#039; \sin(u) \right\rangle \\&lt;br /&gt;
                               \exp\left\langle u,u&#039;\right\rangle &amp;amp;= \left\langle \exp u , u&#039; \exp u \right\rangle \\&lt;br /&gt;
                               \log\left\langle u,u&#039;\right\rangle &amp;amp;= \left\langle \log(u) , u&#039;/u \right\rangle \quad (u&amp;gt;0) \\&lt;br /&gt;
                                 \left\langle u,u&#039;\right\rangle^k &amp;amp;= \left\langle u^k , u&#039; k u^{k - 1} \right\rangle \quad (u \ne 0) \\&lt;br /&gt;
                    \left| \left\langle u,u&#039;\right\rangle \right| &amp;amp;= \left\langle \left| u \right| , u&#039; \operatorname{sign} u \right\rangle \quad (u \ne 0)&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;&lt;br /&gt;
and in general for the primitive function &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;math display=&amp;quot;block&amp;quot;&amp;gt;g(\langle u,u&#039; \rangle , \langle v,v&#039; \rangle ) = \langle g(u,v) , g_u(u,v) u&#039; + g_v(u,v) v&#039; \rangle&amp;lt;/math&amp;gt;&lt;br /&gt;
where &amp;lt;math&amp;gt;g_u&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;g_v&amp;lt;/math&amp;gt; are the derivatives of &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; with respect to its first and second arguments, respectively.&lt;br /&gt;
&lt;br /&gt;
When a binary basic arithmetic operation is applied to mixed arguments—the pair &amp;lt;math&amp;gt;\langle u, u&#039; \rangle&amp;lt;/math&amp;gt; and the real number &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;—the real number is first lifted to &amp;lt;math&amp;gt;\langle c, 0 \rangle&amp;lt;/math&amp;gt;. The derivative of a function &amp;lt;math&amp;gt;f : \R\to\R&amp;lt;/math&amp;gt; at the point &amp;lt;math&amp;gt;x_0&amp;lt;/math&amp;gt; is now found by calculating &amp;lt;math&amp;gt;f(\langle x_0, 1 \rangle)&amp;lt;/math&amp;gt; using the above arithmetic, which gives &amp;lt;math&amp;gt;\langle f ( x_0 ) , f&#039; ( x_0 ) \rangle &amp;lt;/math&amp;gt; as the result.&lt;br /&gt;
&lt;br /&gt;
=== Implementation ===&lt;br /&gt;
An example implementation based on the dual number approach follows.&lt;br /&gt;
&lt;br /&gt;
==== Pseudo code ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
Dual plus(Dual A, Dual B) {&lt;br /&gt;
    return {&lt;br /&gt;
        realPartOf(A) + realPartOf(B),&lt;br /&gt;
        infinitesimalPartOf(A) + infinitesimalPartOf(B)&lt;br /&gt;
    };&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Dual minus(Dual A, Dual B) {&lt;br /&gt;
    return {&lt;br /&gt;
        realPartOf(A) - realPartOf(B),&lt;br /&gt;
        infinitesimalPartOf(A) - infinitesimalPartOf(B)&lt;br /&gt;
    };&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Dual multiply(Dual A, Dual B) {&lt;br /&gt;
    return {&lt;br /&gt;
        realPartOf(A) * realPartOf(B),&lt;br /&gt;
        realPartOf(B) * infinitesimalPartOf(A) + realPartOf(A) * infinitesimalPartOf(B)&lt;br /&gt;
    };&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
X = {x, 0};&lt;br /&gt;
Y = {y, 0};&lt;br /&gt;
Epsilon = {0, 1};&lt;br /&gt;
xPartial = infinitesimalPartOf(f(X + Epsilon, Y));&lt;br /&gt;
yPartial = infinitesimalPartOf(f(X, Y + Epsilon));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== C++ ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
import std;&lt;br /&gt;
&lt;br /&gt;
class Dual {&lt;br /&gt;
private:&lt;br /&gt;
    float realPart;&lt;br /&gt;
    float infinitesimalPart;&lt;br /&gt;
public:&lt;br /&gt;
    explicit Dual(float realPart, float infinitesimalPart = 0.0f):&lt;br /&gt;
        realPart{realPart}, infinitesimalPart{infinitesimalPart} {}&lt;br /&gt;
&lt;br /&gt;
    Dual operator+(const Dual&amp;amp; other) noexcept {&lt;br /&gt;
        return Dual(&lt;br /&gt;
            realPart + other.realPart,&lt;br /&gt;
            infinitesimalPart + other.infinitesimalPart&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    Dual operator*(const Dual&amp;amp; other) noexcept {&lt;br /&gt;
        return Dual(&lt;br /&gt;
            realPart * other.realPart,&lt;br /&gt;
            other.realPart * infinitesimalPart + realPart * other.infinitesimalPart&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    [[nodiscard]]&lt;br /&gt;
    float getRealPart() const noexcept {&lt;br /&gt;
        return realPart;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    [[nodiscard]]&lt;br /&gt;
    float getInfinitesimalPart() const noexcept {&lt;br /&gt;
        return infinitesimalPart;&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
// Example: Finding the partials of z = x * (x + y) + y * y at (x, y) = (2, 3)&lt;br /&gt;
[[nodiscard]]&lt;br /&gt;
Dual f(const Dual&amp;amp; x, const Dual&amp;amp; y) noexcept {&lt;br /&gt;
    return x * (x + y) + y * y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Dual x(2.0f);&lt;br /&gt;
    Dual y(3.0f);&lt;br /&gt;
    Dual epsilon(0.0f, 1.0f);&lt;br /&gt;
    Dual a = f(x + epsilon, y);&lt;br /&gt;
    Dual b = f(x, y + epsilon);&lt;br /&gt;
    std::println(&amp;quot;∂z/∂x = {}, ∂z/∂y = {}&amp;quot;, a.getInfinitesimalPart(), b.getInfinitesimalPart());&lt;br /&gt;
    // Output: ∂z/∂x = 7, ∂z/∂y = 8&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Vector arguments and functions===&lt;br /&gt;
&lt;br /&gt;
Multivariate functions can be handled with the same efficiency and mechanisms as univariate functions by adopting a directional derivative operator. That is, if it is sufficient to compute &amp;lt;math&amp;gt;y&#039; = \nabla f(x)\cdot x&#039;&amp;lt;/math&amp;gt;, the directional derivative &amp;lt;math&amp;gt;y&#039; \in \R^m&amp;lt;/math&amp;gt; of &amp;lt;math&amp;gt;f:\R^n\to\R^m&amp;lt;/math&amp;gt; at &amp;lt;math&amp;gt;x \in \R^n&amp;lt;/math&amp;gt; in the direction &amp;lt;math&amp;gt;x&#039; \in \R^n&amp;lt;/math&amp;gt; may be calculated as &amp;lt;math&amp;gt;(\langle y_1,y&#039;_1\rangle, \ldots, \langle y_m,y&#039;_m\rangle) = f(\langle x_1,x&#039;_1\rangle, \ldots, \langle x_n,x&#039;_n\rangle)&amp;lt;/math&amp;gt; using the same arithmetic as above. If all the elements of &amp;lt;math&amp;gt;\nabla f&amp;lt;/math&amp;gt; are desired, then &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; function evaluations are required. Note that in many optimization applications, the directional derivative is indeed sufficient.&lt;br /&gt;
&lt;br /&gt;
===High order and many variables===&lt;br /&gt;
&lt;br /&gt;
The above arithmetic can be generalized to calculate second order and higher derivatives of multivariate functions. However, the arithmetic rules quickly grow complicated: complexity is quadratic in the highest derivative degree. Instead, truncated [[Taylor series|Taylor polynomial]] algebra can be used. The resulting arithmetic, defined on generalized dual numbers, allows efficient computation using functions as if they were a data type. Once the Taylor polynomial of a function is known, the derivatives are easily extracted.&lt;br /&gt;
&lt;br /&gt;
== Implementation ==&lt;br /&gt;
&lt;br /&gt;
Forward-mode AD is implemented by a [[nonstandard interpretation]] of the program in which real numbers are replaced by dual numbers, constants are lifted to dual numbers with a zero epsilon coefficient, and the numeric primitives are lifted to operate on dual numbers. This nonstandard interpretation is generally implemented using one of two strategies: &#039;&#039;source code transformation&#039;&#039; or &#039;&#039;operator overloading&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Source code transformation (SCT) ===&lt;br /&gt;
[[Image:SourceTransformationAutomaticDifferentiation.png|thumb|right|300px|Figure 4: Example of how source code transformation could work]]&lt;br /&gt;
&lt;br /&gt;
The source code for a function is replaced by an automatically generated source code that includes statements for calculating the derivatives interleaved with the original instructions.&lt;br /&gt;
&lt;br /&gt;
[[Source code transformation]] can be implemented for all programming languages, and it is also easier for the compiler to do compile time optimizations. However, the implementation of the AD tool itself is more difficult and the build system is more complex.&lt;br /&gt;
&lt;br /&gt;
=== Operator overloading (OO) ===&lt;br /&gt;
&lt;br /&gt;
[[Image:OperatorOverloadingAutomaticDifferentiation.png|thumb|right|300px|Figure 5: Example of how operator overloading could work]]&lt;br /&gt;
[[Operator overloading]] is a possibility for source code written in a language supporting it. Objects for real numbers and elementary mathematical operations must be overloaded to cater for the augmented arithmetic depicted above. This requires no change in the form or sequence of operations in the original source code for the function to be differentiated, but often requires changes in basic data types for numbers and vectors to support overloading and often also involves the insertion of special flagging operations. Due to the inherent operator overloading overhead on each loop, this approach usually demonstrates weaker speed performance.&lt;br /&gt;
&lt;br /&gt;
=== Operator overloading and source code transformation ===&lt;br /&gt;
Overloaded Operators can be used to extract the valuation graph, followed by automatic generation of the AD-version of the primal function at run-time. Unlike the classic OO AAD{{Clarify|date=July 2025}}, such AD-function does not change from one iteration to the next one. Hence there is any OO or tape interpretation run-time overhead per Xi sample.&lt;br /&gt;
&lt;br /&gt;
With the AD-function being generated at runtime, it can be optimised to take into account the current state of the program and precompute certain values. In addition, it can be generated in a way to consistently utilize native CPU vectorization to process 4(8)-double chunks of user data (AVX2\AVX512 speed up x4-x8). With multithreading added into account, such approach can lead to a final acceleration of order 8 × #Cores compared to the traditional AAD tools. A reference implementation is available on GitHub.&amp;lt;ref&amp;gt;{{Cite web|url=https://github.com/matlogica/aadc-prototype|title=AADC Prototype Library|date=June 22, 2022|via=GitHub}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
* [[Differentiable programming]]&lt;br /&gt;
&lt;br /&gt;
==Notes==&lt;br /&gt;
{{Notelist}}&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
{{Reflist|30em}}&lt;br /&gt;
&lt;br /&gt;
== Further reading ==&lt;br /&gt;
* {{cite book&lt;br /&gt;
  | last = Rall&lt;br /&gt;
  | first = Louis B.&lt;br /&gt;
  | title = Automatic Differentiation: Techniques and Applications&lt;br /&gt;
  | publisher = [[Springer Science+Business Media|Springer]]&lt;br /&gt;
  | series = Lecture Notes in Computer Science&lt;br /&gt;
  | volume = 120&lt;br /&gt;
  | year = 1981&lt;br /&gt;
  | isbn = 978-3-540-10861-0&lt;br /&gt;
}}&lt;br /&gt;
* {{cite book&lt;br /&gt;
 |last1        = Griewank&lt;br /&gt;
 |first1       = Andreas&lt;br /&gt;
 |last2        = Walther&lt;br /&gt;
 |first2       = Andrea | author2-link = Andrea Walther&lt;br /&gt;
 |title        = Evaluating Derivatives: Principles and Techniques of Algorithmic Differentiation&lt;br /&gt;
 |edition      = 2nd&lt;br /&gt;
 |publisher    = [[Society for Industrial and Applied Mathematics|SIAM]]&lt;br /&gt;
 |series       = Other Titles in Applied Mathematics&lt;br /&gt;
 |volume       = 105&lt;br /&gt;
 |year         = 2008&lt;br /&gt;
 |doi = 10.1137/1.9780898717761&lt;br /&gt;
 |isbn         = 978-0-89871-659-7&lt;br /&gt;
 |url          = https://epubs.siam.org/doi/book/10.1137/1.9780898717761 &amp;lt;!--&lt;br /&gt;
 |access-date  = 2009-10-21&lt;br /&gt;
 |archive-url  = https://web.archive.org/web/20100323035649/http://www.ec-securehost.com/SIAM/OT105.html&lt;br /&gt;
 |archive-date = 2010-03-23&lt;br /&gt;
 |url-status     = dead&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
*  {{cite journal&lt;br /&gt;
   |last=Neidinger&lt;br /&gt;
   |first=Richard&lt;br /&gt;
   |title=Introduction to Automatic Differentiation and MATLAB Object-Oriented Programming&lt;br /&gt;
   |journal=SIAM Review&lt;br /&gt;
   |year=2010|volume=52 &lt;br /&gt;
   |issue=3&lt;br /&gt;
   |pages=545–563&lt;br /&gt;
   |doi=10.1137/080743627&lt;br /&gt;
   |url=http://academics.davidson.edu/math/neidinger/SIAMRev74362.pdf&lt;br /&gt;
   |access-date=2013-03-15&lt;br /&gt;
|citeseerx=10.1.1.362.6580&lt;br /&gt;
   |s2cid=17134969&lt;br /&gt;
 }}&lt;br /&gt;
* {{cite book&lt;br /&gt;
  | last = Naumann&lt;br /&gt;
  | first = Uwe&lt;br /&gt;
  | title = The Art of Differentiating Computer Programs&lt;br /&gt;
  | publisher = [[Society for Industrial and Applied Mathematics|SIAM]]&lt;br /&gt;
  | series = Software-Environments-tools&lt;br /&gt;
  | year = 2012&lt;br /&gt;
  | isbn = 978-1-611972-06-1&lt;br /&gt;
}}&lt;br /&gt;
* {{cite book&lt;br /&gt;
  | last = Henrard&lt;br /&gt;
  | first = Marc&lt;br /&gt;
  | title = Algorithmic Differentiation in Finance Explained&lt;br /&gt;
  | publisher = [[Palgrave Macmillan]]&lt;br /&gt;
  | series = Financial Engineering Explained&lt;br /&gt;
  | year = 2017&lt;br /&gt;
  | isbn = 978-3-319-53978-2&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==External links==&lt;br /&gt;
* [http://www.autodiff.org/ www.autodiff.org], An &amp;quot;entry site to everything you want to know about automatic differentiation&amp;quot;&lt;br /&gt;
* [http://www.autodiff.org/?module=Applications&amp;amp;application=HC1 Automatic Differentiation of Parallel OpenMP Programs]&lt;br /&gt;
* [https://www.researchgate.net/publication/241730000_Automatic_Differentiation_C_Templates_and_Photogrammetry Automatic Differentiation, C++ Templates and Photogrammetry]&lt;br /&gt;
* [https://web.archive.org/web/20070927120356/http://www.vivlabs.com/subpage_ad.php Automatic Differentiation, Operator Overloading Approach]&lt;br /&gt;
* [http://tapenade.inria.fr:8080/tapenade/index.jsp Compute analytic derivatives of any Fortran77, Fortran95, or C program through a web-based interface] Automatic Differentiation of Fortran programs&lt;br /&gt;
* [http://www.win-vector.com/dfiles/AutomaticDifferentiationWithScala.pdf Description and example code for forward Automatic Differentiation in Scala] {{Webarchive|url=https://web.archive.org/web/20160803214549/http://www.win-vector.com/dfiles/AutomaticDifferentiationWithScala.pdf |date=2016-08-03 }}&lt;br /&gt;
* [https://www.finmath.net/finmath-lib/concepts/stochasticautomaticdifferentiation/ finmath-lib stochastic automatic differentiation], Automatic differentiation for random variables (Java implementation of the stochastic automatic differentiation).&lt;br /&gt;
* [https://web.archive.org/web/20140423121504/http://developers.opengamma.com/quantitative-research/Adjoint-Algorithmic-Differentiation-OpenGamma.pdf Adjoint Algorithmic Differentiation: Calibration and Implicit Function Theorem]&lt;br /&gt;
* [http://www.quantandfinancial.com/2017/02/automatic-differentiation-templated.html C++ Template-based automatic differentiation article] and [https://github.com/omartinsky/QuantAndFinancial/tree/master/autodiff_templated implementation]&lt;br /&gt;
* [https://github.com/google/tangent Tangent] [https://research.googleblog.com/2017/11/tangent-source-to-source-debuggable.html Source-to-Source Debuggable Derivatives]&lt;br /&gt;
* [http://www.nag.co.uk/doc/techrep/pdf/tr5_10.pdf Exact First- and Second-Order Greeks by Algorithmic Differentiation]&lt;br /&gt;
* [http://www.nag.co.uk/Market/articles/adjoint-algorithmic-differentiation-of-gpu-accelerated-app.pdf Adjoint Algorithmic Differentiation of a GPU Accelerated Application]&lt;br /&gt;
* [http://www.nag.co.uk/Market/seminars/Uwe_AD_Slides_July13.pdf Adjoint Methods in Computational Finance Software Tool Support for Algorithmic Differentiationop]&lt;br /&gt;
* [https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/xva-pricing-application-financial-services-white-papers.pdf More than a Thousand Fold Speed Up for xVA Pricing Calculations with Intel Xeon Scalable Processors]&lt;br /&gt;
* [https://github.com/ExcessPhase/ctaylor Sparse truncated Taylor series implementation with VBIC95 example for higher order derivatives]&lt;br /&gt;
&lt;br /&gt;
{{Differentiable computing}}&lt;br /&gt;
{{Authority control}}&lt;br /&gt;
&lt;br /&gt;
{{DEFAULTSORT:Automatic Differentiation}}&lt;br /&gt;
[[Category:Differential calculus]]&lt;br /&gt;
[[Category:Computer algebra]]&lt;br /&gt;
[[Category:Articles with example pseudocode]]&lt;br /&gt;
[[Category:Articles with example Python (programming language) code]]&lt;br /&gt;
[[Category:Articles with example C++ code]]&lt;/div&gt;</summary>
		<author><name>2605:8D80:5825:1532:D58:188C:5434:D54</name></author>
	</entry>
	<entry>
		<id>https://wiki.sarg.dev/index.php?title=Pointer_swizzling&amp;diff=822947</id>
		<title>Pointer swizzling</title>
		<link rel="alternate" type="text/html" href="https://wiki.sarg.dev/index.php?title=Pointer_swizzling&amp;diff=822947"/>
		<updated>2025-11-03T07:08:34Z</updated>

		<summary type="html">&lt;p&gt;2605:8D80:5825:1532:D58:188C:5434:D54: /* Example */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Short description|Computer science term}}&lt;br /&gt;
{{No footnotes|date=May 2011}}&lt;br /&gt;
{{Use dmy dates|date=December 2021|cs1-dates=y}}&lt;br /&gt;
In [[computer science]], &#039;&#039;&#039;pointer swizzling&#039;&#039;&#039; is the conversion of references based on name or [[offset (computer science)|position]] into direct [[pointer (computer programming)|pointer]] references ([[memory address]]es). It is typically performed during [[deserialization]] or [[loader (computing)|loading]] of a relocatable object from a disk file, such as an [[executable file]] or pointer-based [[data structure]].&lt;br /&gt;
&lt;br /&gt;
The reverse operation, replacing memory pointers with position-independent symbols or positions, is sometimes referred to as &#039;&#039;&#039;unswizzling&#039;&#039;&#039;, and is performed during [[serialization]] (saving). Alternatively, both operations can also be referred to as swizzling.&lt;br /&gt;
&lt;br /&gt;
==Example==&lt;br /&gt;
It is easy to create a [[linked list]] data structure using elements like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=c&amp;gt;&lt;br /&gt;
struct LinkedList {&lt;br /&gt;
    int data;&lt;br /&gt;
    struct LinkedList* next;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But saving the list to a file and then reloading it will (on most operating systems) break every link and render the list useless because the nodes will almost never be loaded into the same memory locations. One way to usefully save and retrieve the list is to assign a unique id number to each node and then &#039;&#039;&#039;unswizzle&#039;&#039;&#039; the pointers by turning them into a field indicating the id number of the next node:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=c&amp;gt;&lt;br /&gt;
struct UnswizzledLinkedList {&lt;br /&gt;
    int data;&lt;br /&gt;
    unsigned int id;&lt;br /&gt;
    unsigned int id_of_next_node;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Records like these can be saved to a file in any order and reloaded without breaking the list. Other options include saving the file offset of the next node or a number indicating its position in the sequence of saved records, or simply saving the nodes in-order to the file.&lt;br /&gt;
&lt;br /&gt;
After loading such a list, finding a node based on its number is cumbersome and inefficient (serial search). Traversing the list was very fast with the original &amp;quot;next&amp;quot; pointers. To convert the list back to its original form, or &#039;&#039;&#039;swizzle&#039;&#039;&#039; the pointers, requires finding the address of each node and turning the &amp;lt;code&amp;gt;id_of_next_node&amp;lt;/code&amp;gt; fields back into direct pointers to the right node.&lt;br /&gt;
&lt;br /&gt;
==Methods of unswizzling==&lt;br /&gt;
There are a potentially unlimited number of forms into which a pointer can be unswizzled, but some of the most popular include:&lt;br /&gt;
* The offset of the pointed-to object in the file&lt;br /&gt;
* The index of the pointed-to object in some sequence of records&lt;br /&gt;
* A unique identifier possessed by the pointed-to object, such as a person&#039;s [[Social Security number]]; in databases, all pointers are unswizzled in this manner (see [[Foreign key]]).&lt;br /&gt;
&lt;br /&gt;
==Methods of swizzling==&lt;br /&gt;
Swizzling in the general case can be complicated. The reference [[graph (abstract data type)|graph]] of pointers might contain an arbitrary number of [[cycle (graph theory)|cycle]]s; this complicates maintaining a mapping from the old unswizzled values to the new addresses. [[Associative array]]s are useful for maintaining the mapping, while algorithms such as [[breadth-first search]] help to traverse the graph, although both of these require extra storage. Various [[serialization]] [[library (computing)|libraries]] provide general swizzling systems. In many cases, however, swizzling can be performed with simplifying assumptions, such as a [[tree (data structure)|tree]] or [[list (abstract data type)|list]] structure of references.&lt;br /&gt;
&lt;br /&gt;
The different types of swizzling are:&lt;br /&gt;
* Automatic swizzling &amp;lt;!--[EXPAND]--&amp;gt;&lt;br /&gt;
* On-demand swizzling &amp;lt;!--[EXPAND]--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Potential security weaknesses==&lt;br /&gt;
For security, unswizzling and swizzling must be implemented with great caution. In particular, an attacker&#039;s presentation of a specially crafted file may allow access to addresses outside of the expected and proper bounds. In systems with weak memory protection this can lead to exposure of confidential data or modification of code likely to be executed. If the system does not implement guards against execution of data the system may be severely compromised by the installation of various kinds of [[malware]].&lt;br /&gt;
&lt;br /&gt;
Methods of protection include verifications prior to releasing the data to an application:&lt;br /&gt;
* That every offset lies within the bounds of the data read.&lt;br /&gt;
* That a table of indexes and the records pointed to is similarly constrained.&lt;br /&gt;
* That identifiers are unique and, if sensitive, encrypted.&lt;br /&gt;
* That all variable-length data is restrained to lengths not exceeding the actual allocation.&lt;br /&gt;
* That allocations are of reasonable size.&lt;br /&gt;
* That allocations made that are not loaded with data read are cleared, or loaded with some specific pattern.&lt;br /&gt;
{{Expand list|date=August 2011}}&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
* [[Relocation (computing)|Relocation]], an eager form of pointer modification&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
{{Reflist|refs=}}&lt;br /&gt;
&lt;br /&gt;
==Further reading==&lt;br /&gt;
* {{cite news |title=Pointer swizzling at page fault time: efficiently supporting huge address spaces on standard hardware |author-first=Paul R. |author-last=Wilson |newspaper=ACM SIGARCH Computer Architecture News |volume=19 |issue=4 |pages=6–13 |date=1991-07-01 |orig-date=June 1991 |doi=10.1145/122576.122577 |url=}}&lt;br /&gt;
* {{cite journal |title=Adaptable Pointer Swizzling Strategies in Object Bases: Design, Realization, and Quantitative Analysis |author-first1=Alfons |author-last1=Kemper |author-first2=Donald |author-last2=Kossmann |journal=The International Journal on Very Large Data Bases |volume=4 |issue=3 |pages=519–567 |date=July 1995 |doi=10.1007/BF01231646 |s2cid=4556203 |url=http://www.vldb.org/journal/VLDBJ4/P519.pdf |access-date=2021-12-08 |url-status=live |archive-url=https://web.archive.org/web/20080725153221/http://www.vldb.org/journal/VLDBJ4/P519.pdf |archive-date=2008-07-25}} (49 pages)&lt;br /&gt;
* {{cite book |author-first=Derek |author-last=Crawford |title=Derek&#039;s ABC of C |volume=2 |pages=340–343 |date=June 1992}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Memory management]]&lt;br /&gt;
[[Category:Pointers (computer programming)]]&lt;/div&gt;</summary>
		<author><name>2605:8D80:5825:1532:D58:188C:5434:D54</name></author>
	</entry>
</feed>