王昱承
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Versions and GitHub Sync Note Insights Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       owned this note    owned this note      
    Published Linked with GitHub
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    # RISC-V Cache implementation and software optimization case study ###### tags:`Course`, `Final Project` ## Overview ![](https://i.imgur.com/Pl0qRHY.png) ### Features * 32-bit RISC-V ISA CPU core. * Support RISC-V integer (I), multiplication and division (M), and CSR instructions (Z) extensions (RV32IMZicsr). * Supports user, supervisor and machine mode privilege levels. * Basic MMU support - capable of booting Linux with atomics (RV-A) SW emulation. * Implements base ISA spec v2.1 and privileged ISA spec v1.11. * Verified using Google's RISCV-DV random instruction sequences using cosimulation against C++ ISA model. * Support for instruction / data cache, AXI bus interfaces or tightly coupled memories. * Configurable number of pipeline stages and result forwarding options. * Synthesizable Verilog 2001, Verilator and FPGA friendly. * Coremark: 2.94 CoreMark/MHz * Dhrystone: 1.25 DMIPS/MHz ('legal compile options' / 337 instructions per iteration) ## Analyze RISC-V Core with cache by [Reference](https://hackmd.io/@_UHs74UQS7uNne9_7SwQFQ/HyFHdpw3t#Overview) ### Environment Setup * :::danger Please use **ubuntu20.04**, or else it will report ERROR when building ::: * **Git clone the project** ```bash= $ git clone https://github.com/ultraembedded/riscv.git ``` * **Install the required package** ```bash= $ sudo apt-get install libelf-dev binutils-dev build-essential ``` * **Install GTKwave** ```bash= $ sudo apt install gtkwave ``` * **Install Verilator** ```bash= git clone https://github.com/verilator/verilator # first time install # Every time you need to build: unsetenv VERILATOR_ROOT # For csh; ignore error if on bash unset VERILATOR_ROOT # For bash cd verilator git pull # Make sure git repository is up-to-date git tag # See what versions exist git checkout v{version} # Switch to specified release version sudo apt-get install git perl python3 make autoconf g++ flex bison ccache autoconf # Create ./configure script ./configure # Configure and create Makefile make # Build Verilator itself (if error, try just 'make') sudo make install ``` :::warning Success with Verilator **v4.110** Report **ERROR** with v4.012 by the versiom of the reference ![](https://i.imgur.com/47H72dt.png) ::: * **Install systemc from** [systemc-2.3.3](https://www.accellera.org/images/downloads/standards/systemc/systemc-2.3.3.tar.gz) **and follow the following instruction** ```bash= tar -xzf systemc-2.3.3.tar.gz cd systemc-2.3.3 mkdir objdir && cd objdir sudo mkdir /usr/local/systemc-2.3.3 sudo ../configure --prefix=/usr/local/systemc-2.3.3/ #You can configure with no prefix, but cautious about the folder path sudo make sudo make install ``` :::warning success with systemc-2.3.3 systemc-2.3.4 may face problems ::: ### Modify Makefile * Modify makefile in `/riscv/top_tcm_axi/tb/` and `/riscv/top_cache_axi/tb/` Change the `VERILATOR_SRC` and `SYSTEMC_HOME` to the path where you install systemc and verilator **Add on 'SYSTEMC_INCLUDE', 'SYSTEMC_LIBDIR', 'LD_LIBRARY_PATH'.** You will need to set the SYSTEMC_INCLUDE environment variable to point to the include directory with systemc.h in it, and set the SYSTEMC_LIBDIR, LD_LIBRARY_PATH environment variable to point to the directory with libsystemc.a in it. ```makefile= ############################################################################### ## Tool paths ############################################################################### VERILATOR_SRC ?= /home/dhiptmc/Desktop/verilator/include SYSTEMC_HOME ?= /home/dhiptmc/Desktop/systemc-2.3.3 SYSTEMC_INCLUDE = /home/dhiptmc/Desktop/systemc-2.3.3/include SYSTEMC_LIBDIR = /home/dhiptmc/Desktop/systemc-2.3.3/lib-linux64 LD_LIBRARY_PATH = /home/dhiptmc/Desktop/systemc-2.3.3/lib-linux64 TEST_IMAGE ?= ../../isa_sim/images/basic.elf CORE ?= riscv export VERILATOR_SRC export SYSTEMC_HOME export SYSTEMC_INCLUDE export SYSTEMC_LIBDIR export LD_LIBRARY_PATH ``` ### Run the program & Observe * **Run top_tcm_axi/tb** ```bash= cd riscv/top_tcm_axi/tb/ make make run ``` Results: ```bash= ./build/test.x -f ../../isa_sim/images/basic.elf SystemC 2.3.3-Accellera --- Jan 6 2023 19:52:37 Copyright (c) 1996-2018 by all Contributors, ALL RIGHTS RESERVED Info: (I702) default timescale unit used for tracing: 1 ns (sysc_wave.vcd) Memory: 0x2000 - 0x3cd3 (Size=7KB) [.text] Memory: 0x3cd4 - 0x3ce7 (Size=0KB) [.data] Memory: 0x3ce8 - 0x4d07 (Size=4KB) [.bss] Starting from 0x00002000 Test: 1. Initialised data 2. Multiply 3. Divide 4. Shift left 5. Shift right 6. Shift right arithmetic 7. Signed comparision 8. Word access 9. Byte access 10. Comparision TB: Aborted at 109020 ns ``` * **Run top_cache_axi/tb** ```bash= cd riscv/top_cache_axi/tb/ make make run ``` Results: ```bash= ./build/test.x -f ../../isa_sim/images/basic.elf SystemC 2.3.3-Accellera --- Jan 6 2023 19:52:37 Copyright (c) 1996-2018 by all Contributors, ALL RIGHTS RESERVED Info: (I702) default timescale unit used for tracing: 1 ns (sysc_wave.vcd) Memory: 0x2000 - 0x3cd3 (Size=7KB) [.text] Memory: 0x3cd4 - 0x3ce7 (Size=0KB) [.data] Memory: 0x3ce8 - 0x4d07 (Size=4KB) [.bss] Starting from 0x00002000 Test: 1. Initialised data 2. Multiply 3. Divide 4. Shift left 5. Shift right 6. Shift right arithmetic 7. Signed comparision 8. Word access 9. Byte access 10. Comparision TB: Aborted at 157910 ns ``` :::warning Do not immediately retry the execution after failing to do so. You should restore the data status in the folder to the previous status before retrying. ::: * **Observe of the cache & AXI** * Cache :::danger The Cache part of VCD file is unable to open . We're still figuring out the problem where it located. ![](https://i.imgur.com/HPai1XZ.png) ::: * AXI [**AXI(Advanced Xtensible Interface)**](http://www.gstitt.ece.ufl.edu/courses/fall15/eel4720_5721/labs/refs/AXI4_specification.pdf) is is an interface protocol defined by ARM as par of the AMBA (Advanced Microcontroller Bus Architecture) standard. ![](https://i.imgur.com/r6I8v18.png) As the computing demands rise, **AHB(Advanced High performance Bus)** started to fall short in meeting the demands of the system which were ever hungry for more bandwidths. AXI was then invented with "**outstanding transaction**". It can be observed in the diagram shown below, as the number of OTs (outstanding transaction) increase in AXI, the efficiency increases. ![](https://i.imgur.com/1km0qD7.png) The AXI protocol is burst-based and defines the following independent transaction channels: • read address • read data • write address • write data • write response * **Read transaction** ![](https://i.imgur.com/m33chvX.png) A read data channel to transfer data from the slave to the master. * **Write transaction** ![](https://i.imgur.com/7xh3jE8.png) A write data channel to transfer data from the master to the slave. In a write transaction, the slave uses the write response channel to signal the completion of the transfer to the master. * **Handshake** All five transaction channels use the same VALID/READY handshake process to transfer address, data, and control information. This two-way flow control mechanism means both the master and slave can control the rate at which the information moves between master and slave. ![](https://i.imgur.com/gIk4LAB.png) ![](https://i.imgur.com/KEpX71u.png) ![](https://i.imgur.com/bsSvWnA.png) * **Burst Type** The AXI protocol defines three burst types: * **FIXED :** In a fixed burst, the address is the same for every transfer in the burst. This burst type is used for repeated accesses to the same location such as when loading or emptying a FIFO. * **INCR :** Incrementing. In an incrementing burst, the address for each transfer in the burst is an increment of the address for the previous transfer. The increment value depends on the size of the transfer. For example, the address for each transfer in a burst with a size of four bytes is the previous address plus four. This burst type is used for accesses to normal sequential memory. * **WRAP :** A wrapping burst is similar to an incrementing burst, except that the address wraps around to a lower address if an upper address limit is reached. The following restrictions apply to wrapping bursts: • the start address must be aligned to the size of each transfer • the length of the burst must be 2, 4, 8, or 16 transfers. The behavior of a wrapping burst is: • The lowest address used by the burst is aligned to the total size of the data to be transferred, that is, to ((size of each transfer in the burst) × (number of transfers in the burst)). This address is defined as the wrap boundary. • After each transfer, the address increments in the same way as for an INCR burst. However, if this incremented address is ((wrap boundary) + (total size of data to be transferred)) then the address wraps round to the wrap boundary. • The first transfer in the burst can use an address that is higher than the wrap boundary, subject to the restrictions that apply to wrapping bursts. This means that the address wraps for any WRAP burst for which the first address is higher than the wrap boundary. This burst type is used for cache line accesses. * **Waveform of Read Instruction** ![](https://i.imgur.com/j3sMw8F.png) * Read Addresss Channel ![](https://i.imgur.com/wG03sOS.png) 1. araddress = 0x2000. 2. arburst = 0x01 ,According to the Burst type define in "axi4_defines.h",it's INCREMENTAL type. ```=c enum eAXI4_BURST { AXI4_BURST_FIXED, AXI4_BURST_INCR, AXI4_BURST_WRAP }; ``` 3. arid = 0(from master 0). 4. arlen = 0x07, Request len+1,total 8 data from memory ,due to the burst type is INCR,it's mean master request data from address 0x2000 , 0x2004 ... 0x2018 , 0x201C. ```=c //from "tb_axi4_mem.cpp" // Unroll burst for (int i=0;i<((int)(axi_first.ARLEN) + 1);i++) { axi4_master item = axi_first; item.ARVALID = true; item.ARADDR = next_addr; item.WLAST = (i == axi_first.ARLEN); axi_rd_q.push(item); // Generate next address next_addr = calc_next_addr(next_addr, axi_first.ARBURST, axi_first.ARLEN); } ``` 5. arvalid = 1 && arready = 1 ,means Handshake done , read address transaction ended. * Read data Channel ![](https://i.imgur.com/hQpsLjt.png) 1. rid = 0.(to master 0) 2. rdata : means the data from slave(Instruction memory). 3. rvalid = 1 & rready = 1.means read data Handshake done,In the mean time the rdata(memory output) is avaliable. observe the above image can found there were total 8 clks of handshake occurred. It means memory send 8(burst_len+1,from address 0x2000 , 0x2004 ... 0x2018 , 0x201C) avaliable data back. Instruction in basic.elf: ``` Disassembly of section .text: 00002000 <boot_vector>: 2000: 2580006f j 2258 <start> 2004: 0000 unimp ... 00002008 <ipc_vector>: ... 2010: 1140006f j 2124 <isr_vector> ... 00002020 <arg_argc>: 2020: 0000 unimp ... ``` Data send back from Instruction memory(Signal in first line is rdata): ![](https://i.imgur.com/9zuIpRu.png) 4. rlast pull up only when it's the last data from this read data transaction(handshake&&(data_cnt==ar_len)) ```=c item.WLAST = (i == axi_first.ARLEN); axi_o.RLAST = item.WLAST; ``` 5. resp = 0 ,according to "axi4_defines.h",the read data response is okay (avaliable with handshake,means the data is error or not). ```=c enum eAXI4_RESP { AXI4_RESP_OKAY, AXI4_RESP_EXOKAY, AXI4_RESP_SLVERR, AXI4_RESP_DECERR }; ``` * **Waveform of Write Data** ![](https://i.imgur.com/QrpnwyD.png) * Write address channel ![](https://i.imgur.com/sltEpn7.png) 1. awaddr=0x4020 , write data from address 0x4020. 2. awburst = 0x01 , INCREMENT type. 3. awid = 0x0 ,request send from master 0. 4. awlen = 0x07 , send total of 8 datas (len +1) to data memory . 5. awvalid = 1 & awready = 1 , Handshake occurred,Write address transaction ended. * Write data channel ![](https://i.imgur.com/da1QD8o.png) 1. wdata ,Data send from master which is going to write in data memory(only avaliable when handshake occurred). It will keep procedure until total 8 of data complete transmission,that is, write data to memory address 0x4020,0x4024 .... 0x4030,0x403C. 2. wstrb , determine which Byte in Word is willing to write. In waveform the signal wstrb is 0xF,so write in the whole Word to memory. ```=c //from tb_axi4_mem.cpp //----------------------------------------------------------------- // write32: Write a 32-bit word to memory //----------------------------------------------------------------- void tb_axi4_mem::write32(uint32_t addr, uint32_t data, uint8_t strb) { for (int i=0;i<4;i++) if (strb & (1 << i)) tb_memory::write(addr + i,data >> (i*8)); } ``` 3. wvalid = 1 & wready = 1 , Handshake occurred. wdata,wstrb and wlast only avaliable when this situation happened. It can be observed that there are 8 handshakes in waveform,means master send 8 data to slave(memory). 4. wlast, when master is going to send the last data , the signal wlast pull up , and the write data transaction ended. * Write Respond Channel ![](https://i.imgur.com/SklDAes.png) 1. bid=0 , slave send data to master 0. 2. bresp=0x00 , the same as rresp,check write data succeded or not. ```=c enum eAXI4_RESP { AXI4_RESP_OKAY, AXI4_RESP_EXOKAY, AXI4_RESP_SLVERR, AXI4_RESP_DECERR }; ``` 3. bvalid = 1 & bready = 1 , Handshake occurred , bid and bresp only avaliable when this situation happened.Write Response transaction ended. * **Arbiter** Generally speaking, some channel in AXI have arbiter and decoder according to their design. * SAMD(Share Address Multiple Data) High performance , allow outstanding. ![](https://i.imgur.com/rN5EyRq.png) * SASD(Share Address Share Data) Low cost. ![](https://i.imgur.com/Hu6eM8p.png) * Arbiter in waveform ![](https://i.imgur.com/hcPpdWO.png) It seems there are no arbiter in this case. After I check tb_axi4_mem.c file , the original aurthor build 2 AXI bus directly (one for Instruction,one for data) , so the need of arbiter is unnecessary. ## The [problem](https://leetcode.com/problems/flipping-an-image/) pick at before works ### row-major vs. column-major * **The meaning of row-major & column-major** * Row-major : the consecutive elements of a row reside next to each other ![](https://i.imgur.com/RsttRxX.png) * Column-major : the consecutive elements of a column reside next to each other ![](https://i.imgur.com/6eYCyQ4.png) * For example, the array could be stored in two possible ways: $$\begin{bmatrix} a_{11} & a_{12} & a_{13} \\ a_{21} & a_{22} & a_{23} \\ \end{bmatrix}$$ | Address | r_Access | r_Value | c_Access | c_Value | |:---:|:---:|:---:|:---:|:---:| | 0 |A[0][0]|$a_{11}$|A[0][0]|$a_{11}$| | 1 |A[0][1]|$a_{12}$|A[1][0]|$a_{21}$| | 2 |A[0][2]|$a_{13}$|A[0][1]|$a_{12}$| | 3 |A[1][0]|$a_{21}$|A[1][1]|$a_{22}$| | 4 |A[1][1]|$a_{22}$|A[0][2]|$a_{13}$| | 5 |A[1][2]|$a_{23}$|A[1][2]|$a_{23}$| * **C code for dealing problem with Row/Col-major** ```c= #include <stdio.h> #include <stdlib.h> #define ROWS 3 #define COLS 4 #define IMGSIZE 12 int main() { int image[ROWS][COLS] = { {1,1,0,0}, {1,0,1,1}, {0,1,1,0}}; int row_image[IMGSIZE]; int col_image[IMGSIZE]; for(int r=0; r<ROWS; r++){ //row-major for(int c=0; c<COLS; c++) row_image[COLS*r+c] = image[r][c]; } for(int c=0; c<COLS; c++){ //col-majar for(int r=0; r<COLS; r++) col_image[ROWS*c+r] = image[r][c]; } printf("The row major result is \n"); flipimage(row_image, IMGSIZE, 'r'); printf("\nThe col major result is \n"); flipimage(col_image, IMGSIZE, 'c'); return 0; } void flipimage(int image[IMGSIZE], int imageSize, char type){ int left_pointer; int right_pointer; int pivot; int temp; for(int i=0; i<imageSize; i++){ if(image[i]==0) image[i]=1; else image[i]=0; } if(type == 'r'){ //Row-major solution pivot=0; right_pointer=pivot+COLS-1; while(pivot<COLS*ROWS){ //if left smaller than last row's first element left_pointer = pivot; while(left_pointer<right_pointer){ temp = image[left_pointer]; image[left_pointer] = image[right_pointer]; image[right_pointer] = temp; left_pointer++; right_pointer--; } pivot += COLS; right_pointer = pivot+COLS-1; } for(int i=0; i<imageSize; i++){ if((i+1)%COLS == 0) printf("%d\n", image[i]); else printf("%d, ", image[i]); } } if(type == 'c'){ pivot=0; right_pointer=pivot+ROWS*(COLS-1); while(pivot<ROWS){ left_pointer = pivot; while((right_pointer-left_pointer)>=ROWS){ temp = image[left_pointer]; image[left_pointer] = image[right_pointer]; image[right_pointer] = temp; left_pointer+=ROWS; right_pointer-=ROWS; } pivot++; right_pointer=pivot+ROWS*(COLS-1); } for(int i=0; i<imageSize/4; i++){ printf(" %d, %d, %d, %d\n", image[i], image[i+ROWS], image[i+2*ROWS], image[i+3*ROWS]); } } } ``` * **Result** ![](https://i.imgur.com/spHgDOr.png) * **The performance compare** :::success Because we can't run .elf on his RISCV-Core. So we try to imitate the Cache behavior by the spec giving in his file as below. * Total 16KB * 2-way set * 1-word width per block * 2048 liines ::: * Row-Major ![](https://i.imgur.com/H3sJRYw.png) * Col-Major ![](https://i.imgur.com/qA0F2wf.png) * By the hit rate result generated by $Ripes$, we can found that the **Row-major** performance is $better$ than **Col-major** due to the input of array is retangle shape, with row's length larger than column's length. ## The [specific problem](https://github.com/scandum/rotate) analyzation * **Introduction to rotating** A rotation is to swap the left side of an array with the right side. ![](https://i.imgur.com/rmZbJBC.png) After the rotation the data is as following. ![](https://i.imgur.com/JDRhFns.png) * **C code for various rotations and benchmark** rotate.h: ``` C= #ifndef ROTATE_H #define ROTATE_H void outsidein_reversal(int *array, size_t block_size) { int *pta, *ptb, swap; pta = array; ptb = array + block_size; block_size /= 2; while (block_size--) { swap = *pta; *pta++ = *--ptb; *ptb = swap; } } void insideout_reversal(int *array, size_t block_size) { int *pta, *ptb, swap; ptb = array + block_size; block_size /= 2; pta = array + block_size; ptb -= block_size; while (block_size--) { swap = *--pta; *pta = *ptb; *ptb++ = swap; } } void forward_block_swap(int *array, const size_t start1, const size_t start2, size_t block_size) { int *pta, *ptb, swap; pta = array + start1; ptb = array + start2; while (block_size--) { swap = *pta; *pta++ = *ptb; *ptb++ = swap; } } void backward_block_swap(int *array, const size_t start1, const size_t start2, size_t block_size) { int *pta, *ptb, swap; pta = array + start1 + block_size; ptb = array + start2 + block_size; while (block_size--) { swap = *--pta; *pta = *--ptb; *ptb = swap; } } void auxiliary_rotation(int *array, size_t left, size_t right) { int *pta, *ptb, *ptc, *swap; pta = array; ptb = array + left; ptc = array + right; if (left < right) { swap = malloc(left * sizeof(int)); memcpy(swap, pta, left * sizeof(int)); memmove(pta, ptb, right * sizeof(int)); memcpy(ptc, swap, left * sizeof(int)); } else { swap = malloc(right * sizeof(int)); memcpy(swap, ptb, right * sizeof(int)); memmove(ptc, pta, left * sizeof(int)); memcpy(pta, swap, right * sizeof(int)); } free(swap); } void stack_rotation(int *array, size_t left, size_t right) { int *pta, *ptb, *ptc, swap[8]; pta = array; ptb = array + left; ptc = array + right; if (left < right) { memcpy(swap, pta, left * sizeof(int)); memmove(pta, ptb, right * sizeof(int)); memcpy(ptc, swap, left * sizeof(int)); } else { memcpy(swap, ptb, right * sizeof(int)); memmove(ptc, pta, left * sizeof(int)); memcpy(pta, swap, right * sizeof(int)); } } // 3 reversal - Origin unknown, but prior to 1981 void reversal_rotation(int *array, size_t left, size_t right) { outsidein_reversal(array, left); outsidein_reversal(array + left, right); outsidein_reversal(array, left + right); } // 2021 - Bridge rotation by Igor van den Hoven void bridge_rotation(int *array, size_t left, size_t right) { int *pta, *ptb, *ptc, *ptd, *swap; pta = array; ptb = pta + left; ptc = pta + right; ptd = ptc + left; if (left < right) { size_t bridge = right - left; if (bridge < left) { swap = malloc(bridge * sizeof(int)); memcpy(swap, ptb, bridge * sizeof(int)); while (left--) { *--ptc = *--ptd; *ptd = *--ptb; } memcpy(pta, swap, bridge * sizeof(int)); } else { swap = malloc(left * sizeof(int)); memcpy(swap, pta, left * sizeof(int)); memmove(pta, ptb, right * sizeof(int)); memcpy(ptc, swap, left * sizeof(int)); } } else if (right < left) { size_t bridge = left - right; if (bridge < right) { swap = malloc(bridge * sizeof(int)); memcpy(swap, ptc, bridge * sizeof(int)); while (right--) { *ptc++ = *pta; *pta++ = *ptb++; } memcpy(ptd - bridge, swap, bridge * sizeof(int)); } else { swap = malloc(right * sizeof(int)); memcpy(swap, ptb, right * sizeof(int)); memmove(ptc, pta, left * sizeof(int)); memcpy(pta, swap, right * sizeof(int)); } } else { swap = malloc(1 * sizeof(int)); while (left--) { *swap = *pta; *pta++ = *ptb; *ptb++ = *swap; } } free(swap); } // 2021 - Conjoined Triple Reversal rotation by Igor van den Hoven void contrev_rotation(int *array, size_t left, size_t right) { int *pta, *ptb, *ptc, *ptd, swap; size_t loop; pta = array; ptb = array + left; ptc = array + left; ptd = array + left + right; if (left > right) { loop = right / 2; while (loop--) { swap = *--ptb; *ptb = *pta; *pta++ = *ptc; *ptc++ = *--ptd; *ptd = swap; } loop = (ptb - pta) / 2; while (loop--) { swap = *--ptb; *ptb = *pta; *pta++ = *--ptd; *ptd = swap; } loop = (ptd - pta) / 2; while (loop--) { swap = *pta; *pta++ = *--ptd; *ptd = swap; } } else if (left < right) { loop = left / 2; while (loop--) { swap = *--ptb; *ptb = *pta; *pta++ = *ptc; *ptc++ = *--ptd; *ptd = swap; } loop = (ptd - ptc) / 2; while (loop--) { swap = *ptc; *ptc++ = *--ptd; *ptd = *pta; *pta++ = swap; } loop = (ptd - pta) / 2; while (loop--) { swap = *pta; *pta++ = *--ptd; *ptd = swap; } } else { loop = left; while (loop--) { swap = *pta; *pta++ = *ptb; *ptb++ = swap; } } } // 2021 - Trinity rotation by Igor van den Hoven (Conjoined Triple Reversal + Bridge rotation) #define MAX_AUX 8 void trinity_rotation(int *array, size_t left, size_t right) { int *pta, *ptb, *ptc, *ptd, swap[MAX_AUX]; size_t loop; if (left < right) { if (left <= MAX_AUX) { memcpy(swap, array, left * sizeof(int)); memmove(array, array + left, right * sizeof(int)); memcpy(array + right, swap, left * sizeof(int)); } else { pta = array; ptb = pta + left; loop = right - left; if (loop <= MAX_AUX && loop > 3) { ptc = pta + right; ptd = ptc + left; memcpy(swap, ptb, loop * sizeof(int)); while (left--) { *--ptc = *--ptd; *ptd = *--ptb; } memcpy(pta, swap, loop * sizeof(int)); } else { ptc = ptb; ptd = ptc + right; loop = left / 2; while (loop--) { *swap = *--ptb; *ptb = *pta; *pta++ = *ptc; *ptc++ = *--ptd; *ptd = *swap; } loop = (ptd - ptc) / 2; while (loop--) { *swap = *ptc; *ptc++ = *--ptd; *ptd = *pta; *pta++ = *swap; } loop = (ptd - pta) / 2; while (loop--) { *swap = *pta; *pta++ = *--ptd; *ptd = *swap; } } } } else if (right < left) { if (right <= MAX_AUX) { memcpy(swap, array + left, right * sizeof(int)); memmove(array + right, array, left * sizeof(int)); memcpy(array, swap, right * sizeof(int)); } else { pta = array; ptb = pta + left; loop = left - right; if (loop <= MAX_AUX && loop > 3) { ptc = pta + right; ptd = ptc + left; memcpy(swap, ptc, loop * sizeof(int)); while (right--) { *ptc++ = *pta; *pta++ = *ptb++; } memcpy(ptd - loop, swap, loop * sizeof(int)); } else { ptc = ptb; ptd = ptc + right; loop = right / 2; while (loop--) { *swap = *--ptb; *ptb = *pta; *pta++ = *ptc; *ptc++ = *--ptd; *ptd = *swap; } loop = (ptb - pta) / 2; while (loop--) { *swap = *--ptb; *ptb = *pta; *pta++ = *--ptd; *ptd = *swap; } loop = (ptd - pta) / 2; while (loop--) { *swap = *pta; *pta++ = *--ptd; *ptd = *swap; } } } } else { pta = array; ptb = pta + left; while (left--) { *swap = *pta; *pta++ = *ptb; *ptb++ = *swap; } } } #undef MAX_AUX // 1981 - Gries-Mills rotation by David Gries and Harlan Mills void griesmills_rotation(int *array, size_t left, size_t right) { size_t start = 0; while (left && right) { if (left <= right) { do { forward_block_swap(array, start, start + left, left); start += left; right -= left; } while (left <= right); } else { do { forward_block_swap(array, start + left - right, start + left, right); left -= right; } while (right <= left); } } } // 2020 - Grail rotation by the Holy Grail Sort project (Gries-Mills derived) void grail_rotation(int *array, size_t left, size_t right) { size_t min = left <= right ? left : right; size_t start = 0; while (min > 1) { if (left <= right) { do { forward_block_swap(array, start, start + left, left); start += left; right -= left; } while (left <= right); min = right; } else { do { backward_block_swap(array, start + left - right, start + left, right); left -= right; } while (right <= left); min = left; } } if (min) { stack_rotation(array + start, left, right); } } // 2021 - Piston rotation by Igor van den Hoven. Based on the successive swap described by Gries and Mills in 1981. void piston_rotation(int *array, size_t left, size_t right) { size_t start = 0; while (left > 0) { while (left <= right) { forward_block_swap(array, start, start + right, left); right -= left; } if (right <= 0) { break; } do { forward_block_swap(array, start, start + left, right); left -= right; start += right; } while (right <= left); } /* if (left && right) { stack_rotation(array + start, left, right); }*/ } // 2021 - Helix rotation by Control (grail derived) void helix_rotation(int *array, size_t left, size_t right) { int swap; size_t start = 0; size_t end = left + right; size_t mid = left; while (1) { if (left > right) { if (right <= 1) { break; } while (mid > start) { swap = array[--mid]; array[mid] = array[--end]; array[end] = swap; } mid += (left %= right); right = end - mid; } else { if (left <= 1) { break; } while (mid < end) { swap = array[mid]; array[mid++] = array[start]; array[start++] = swap; } mid -= (right %= left); left = mid - start; } } if (left && right) { stack_rotation(array + start, left, right); } } // 2021 - Drill rotation by Igor van den Hoven (grail derived with piston and helix loops) void drill_rotation(int *array, size_t left, size_t right) { int swap; size_t start = 0; size_t end = left + right; size_t mid = left; size_t loop; while (left > 1) { if (left <= right) { loop = end - mid - (right %= left); do { swap = array[mid]; array[mid++] = array[start]; array[start++] = swap; } while (--loop); } if (right <= 1) { break; } loop = mid - start - (left %= right); do { swap = array[--mid]; array[mid] = array[--end]; array[end] = swap; } while (--loop); } if (left && right) { stack_rotation(array + start, left, right); } } // 1965 - Juggling aka Dolphin rotation int gcd(int a, int b) { int r; while (b) { r = a % b; a = b; b = r; } return a; } void juggling_rotation(int *array, size_t left, size_t right) { int *pta, *ptb, *ptc, *ptd, swap; const size_t nmemb = left + right; if (left == 0) { return; } ptd = array + gcd(left, nmemb); for (ptc = array ; ptc < ptd ; ptc++) { swap = *ptc; pta = ptc; while (1) { ptb = pta + left; if (ptb >= array + nmemb) { ptb -= nmemb; if (ptb == ptc) { break; } } *pta = *ptb; pta = ptb; } *pta = swap; } } #endif ``` bench.c: ```c= #include <stdlib.h> #include <stdio.h> #include <string.h> #include <sys/time.h> #include <time.h> #include <errno.h> #include <math.h> #include "rotate.h" long long utime() { struct timeval now_time; gettimeofday(&now_time, NULL); return now_time.tv_sec * 1000000LL + now_time.tv_usec; } typedef void ROTATEFUNC(int *array, size_t left, size_t right); void test_sort(void *array, void *unsorted, void *valid, int max, int samples, int repetitions, int left, int right, const char *name, char *desc, size_t size) { ROTATEFUNC *rotate; long long start, end, total, best, average; size_t rep, sam; int *pta = (int *) array, *ptv = (int *) valid, cnt; static int legend; if (*name == '*') { if (legend == 0) { legend = 1; printf("%s\n", "| Name | Items | Type | Best | Average | Loops | Samples | Distribution |"); printf("%s\n", "| --------- | -------- | ---- | -------- | -------- | --------- | ------- | ---------------- |"); } else { printf("%s\n", "| | | | | | | | |"); } return; } switch (name[0] + name[1] * 128 + name[2] * 16384) { case 'a' + 'u' * 128 + 'x' * 16384: rotate = auxiliary_rotation; break; case 'b' + 'r' * 128 + 'i' * 16384: rotate = bridge_rotation; break; case 'c' + 'o' * 128 + 'n' * 16384: rotate = contrev_rotation; break; case 'd' + 'r' * 128 + 'i' * 16384: rotate = drill_rotation; break; case 'g' + 'r' * 128 + 'a' * 16384: rotate = grail_rotation; break; case 'g' + 'r' * 128 + 'i' * 16384: rotate = griesmills_rotation; break; case 'h' + 'e' * 128 + 'l' * 16384: rotate = helix_rotation; break; case 'j' + 'u' * 128 + 'g' * 16384: rotate = juggling_rotation; break; case 'p' + 'i' * 128 + 's' * 16384: rotate = piston_rotation; break; case 'r' + 'e' * 128 + 'v' * 16384: rotate = reversal_rotation; break; case 't' + 'r' * 128 + 'i' * 16384: rotate = trinity_rotation; break; default: printf("Unknown rotation: (%s). Valid rotations are: auxiliary, bridge, contrev, drill, grail, griesmills, helix, juggling, piston, reversal, trinity\n", name); return; } best = average = 0; for (sam = 0 ; sam < samples ; sam++) { total = 0; start = utime(); for (rep = 0 ; rep < repetitions ; rep++) { memcpy(array, unsorted, max * size); rotate(array, left, right); } end = utime(); total = end - start; if (!best || total < best) { best = total; } average += total; } average /= samples; printf("|%10s | %8d | %4d | %f | %f | %9d | %7d | %16s |\n", name, max, (int) size * 8, best / 1000000.0, average / 1000000.0, repetitions, samples, desc); for (cnt = 0 ; cnt < max ; cnt++) { if (pta[cnt] != ptv[cnt]) { printf(" validate: array[%d] != valid[%d]. (%d vs %d\n", cnt, cnt, pta[cnt], ptv[cnt]); break; } } } int main(int argc, char **argv) { int max = 1000000; int samples = 200; int repetitions = 1; int seed = 0; int cnt, left, right, index; int *a_array, *r_array, *v_array; char dist[40], *sorts[] = { "*", "bridge", "helix", "trinity", "reversal" }; // char dist[40], *sorts[] = { "*", "contrev", "piston", "griesmills", "juggler" }; // char dist[40], *sorts[] = { "*", "auxiliary", "bridge", "contrev", "drill", "grail", "griesmills", "helix", "juggling", "piston", "reversal", "trinity" }; if (argc >= 1 && argv[1] && *argv[1]) { max = atoi(argv[1]); } if (argc >= 2 && argv[2] && *argv[2]) { samples = atoi(argv[2]); } if (argc >= 3 && argv[3] && *argv[3]) { repetitions = atoi(argv[3]); } if (argc >= 4 && argv[4] && *argv[4]) { seed = atoi(argv[4]); } printf("Benchmark: array size: %d, samples: %d, repetitions: %d, seed: %d\n\n", max, samples, repetitions, seed); // 32 bit a_array = (int *) malloc(max * sizeof(int)); r_array = (int *) malloc(max * sizeof(int)); v_array = (int *) malloc(max * sizeof(int)); for (cnt = 0 ; cnt < max ; cnt++) { r_array[cnt] = cnt; } int values[] = { 1, 1000, 99999, 199998, 299997, 399996, 499995, 0}; for (index = 0 ; values[index] != 0 ; index++) { left = values[index]; right = max - left; memcpy(v_array, r_array, max * sizeof(int)); auxiliary_rotation(v_array, left, right); sprintf(dist, "%d/%d", left, right); for (cnt = 0 ; cnt < sizeof(sorts) / sizeof(char *) ; cnt++) { test_sort(a_array, r_array, v_array, max, samples, repetitions, left, right, sorts[cnt], dist, sizeof(int)); } } for (left = 1 ; left <= 9 ; left ++) { right = max - left; memcpy(v_array, r_array, max * sizeof(int)); auxiliary_rotation(v_array, left, right); sprintf(dist, "%d/%d", left, right); for (cnt = 0 ; cnt < sizeof(sorts) / sizeof(char *) ; cnt++) { test_sort(a_array, r_array, v_array, max, samples, repetitions, left, right, sorts[cnt], dist, sizeof(int)); } } for (left = max / 3 ; left < max / 3 + 5 ; left++) { right = max - left; memcpy(v_array, r_array, max * sizeof(int)); auxiliary_rotation(v_array, left, right); sprintf(dist, "%d/%d", left, right); for (cnt = 0 ; cnt < sizeof(sorts) / sizeof(char *) ; cnt++) { test_sort(a_array, r_array, v_array, max, samples, repetitions, left, right, sorts[cnt], dist, sizeof(int)); } } for (left = max / 2 ; left < max / 2 + 9 ; left++) { right = max - left; memcpy(v_array, r_array, max * sizeof(int)); auxiliary_rotation(v_array, left, right); sprintf(dist, "%d/%d", left, right); for (cnt = 0 ; cnt < sizeof(sorts) / sizeof(char *) ; cnt++) { test_sort(a_array, r_array, v_array, max, samples, repetitions, left, right, sorts[cnt], dist, sizeof(int)); } } for (left = max * 10 / 100 - 1 ; left < max ; left += max * 10 / 100 - 1) { right = max - left; memcpy(v_array, r_array, max * sizeof(int)); auxiliary_rotation(v_array, left, right); sprintf(dist, "%d/%d", left, right); for (cnt = 0 ; cnt < sizeof(sorts) / sizeof(char *) ; cnt++) { test_sort(a_array, r_array, v_array, max, samples, repetitions, left, right, sorts[cnt], dist, sizeof(int)); } } free(a_array); free(r_array); free(v_array); return 0; } ``` * **Result:** Benchmark: array size: 1000000, samples: 200, repetitions: 1, seed: 0 | Name | Items | Type | Best | Average | Loops | Samples | Distribution | | --------- | -------- | ---- | -------- | -------- | --------- | ------- | ---------------- | | bridge | 1000000 | 32 | 0.000999 | 0.000562 | 1 | 200 | 1/999999 | | helix | 1000000 | 32 | 0.000000 | 0.000457 | 1 | 200 | 1/999999 | | trinity | 1000000 | 32 | 0.000000 | 0.000452 | 1 | 200 | 1/999999 | | reversal | 1000000 | 32 | 0.000985 | 0.001492 | 1 | 200 | 1/999999 | | | | | | | | | | | bridge | 1000000 | 32 | 0.000000 | 0.000404 | 1 | 200 | 1000/999000 | | helix | 1000000 | 32 | 0.000999 | 0.002212 | 1 | 200 | 1000/999000 | | trinity | 1000000 | 32 | 0.000995 | 0.001047 | 1 | 200 | 1000/999000 | | reversal | 1000000 | 32 | 0.000994 | 0.001502 | 1 | 200 | 1000/999000 | | | | | | | | | | | bridge | 1000000 | 32 | 0.001000 | 0.000397 | 1 | 200 | 99999/900001 | | helix | 1000000 | 32 | 0.001506 | 0.002200 | 1 | 200 | 99999/900001 | | trinity | 1000000 | 32 | 0.000997 | 0.001100 | 1 | 200 | 99999/900001 | | reversal | 1000000 | 32 | 0.000989 | 0.001512 | 1 | 200 | 99999/900001 | | | | | | | | | | | bridge | 1000000 | 32 | 0.000000 | 0.000432 | 1 | 200 | 199998/800002 | | helix | 1000000 | 32 | 0.001986 | 0.002239 | 1 | 200 | 199998/800002 | | trinity | 1000000 | 32 | 0.000993 | 0.001010 | 1 | 200 | 199998/800002 | | reversal | 1000000 | 32 | 0.000997 | 0.001387 | 1 | 200 | 199998/800002 | | | | | | | | | | | bridge | 1000000 | 32 | 0.000000 | 0.000532 | 1 | 200 | 299997/700003 | | helix | 1000000 | 32 | 0.001995 | 0.002205 | 1 | 200 | 299997/700003 | | trinity | 1000000 | 32 | 0.000994 | 0.001015 | 1 | 200 | 299997/700003 | | reversal | 1000000 | 32 | 0.000993 | 0.001407 | 1 | 200 | 299997/700003 | | | | | | | | | | | bridge | 1000000 | 32 | 0.000999 | 0.000830 | 1 | 200 | 399996/600004 | | helix | 1000000 | 32 | 0.001509 | 0.002155 | 1 | 200 | 399996/600004 | | trinity | 1000000 | 32 | 0.000987 | 0.001025 | 1 | 200 | 399996/600004 | | reversal | 1000000 | 32 | 0.000994 | 0.001427 | 1 | 200 | 399996/600004 | | | | | | | | | | | bridge | 1000000 | 32 | 0.001000 | 0.000870 | 1 | 200 | 499995/500005 | | helix | 1000000 | 32 | 0.001001 | 0.002215 | 1 | 200 | 499995/500005 | | trinity | 1000000 | 32 | 0.000997 | 0.001015 | 1 | 200 | 499995/500005 | | reversal | 1000000 | 32 | 0.000992 | 0.001402 | 1 | 200 | 499995/500005 | | | | | | | | | | | bridge | 1000000 | 32 | 0.001000 | 0.000422 | 1 | 200 | 1/999999 | | helix | 1000000 | 32 | 0.000000 | 0.000396 | 1 | 200 | 1/999999 | | trinity | 1000000 | 32 | 0.000000 | 0.000405 | 1 | 200 | 1/999999 | | reversal | 1000000 | 32 | 0.000996 | 0.001377 | 1 | 200 | 1/999999 | | | | | | | | | | | bridge | 1000000 | 32 | 0.000000 | 0.000407 | 1 | 200 | 2/999998 | | helix | 1000000 | 32 | 0.001504 | 0.002232 | 1 | 200 | 2/999998 | | trinity | 1000000 | 32 | 0.000000 | 0.000410 | 1 | 200 | 2/999998 | | reversal | 1000000 | 32 | 0.000995 | 0.001397 | 1 | 200 | 2/999998 | | | | | | | | | | | bridge | 1000000 | 32 | 0.001001 | 0.000407 | 1 | 200 | 3/999997 | | helix | 1000000 | 32 | 0.000996 | 0.002230 | 1 | 200 | 3/999997 | | trinity | 1000000 | 32 | 0.000000 | 0.000397 | 1 | 200 | 3/999997 | | reversal | 1000000 | 32 | 0.000991 | 0.001375 | 1 | 200 | 3/999997 | | | | | | | | | | | bridge | 1000000 | 32 | 0.000000 | 0.000401 | 1 | 200 | 4/999996 | | helix | 1000000 | 32 | 0.001505 | 0.002189 | 1 | 200 | 4/999996 | | trinity | 1000000 | 32 | 0.000000 | 0.000402 | 1 | 200 | 4/999996 | | reversal | 1000000 | 32 | 0.000995 | 0.001387 | 1 | 200 | 4/999996 | | | | | | | | | | | bridge | 1000000 | 32 | 0.000000 | 0.000417 | 1 | 200 | 5/999995 | | helix | 1000000 | 32 | 0.001001 | 0.002200 | 1 | 200 | 5/999995 | | trinity | 1000000 | 32 | 0.000000 | 0.000402 | 1 | 200 | 5/999995 | | reversal | 1000000 | 32 | 0.000991 | 0.001396 | 1 | 200 | 5/999995 | | | | | | | | | | | bridge | 1000000 | 32 | 0.000000 | 0.000417 | 1 | 200 | 6/999994 | | helix | 1000000 | 32 | 0.001505 | 0.002205 | 1 | 200 | 6/999994 | | trinity | 1000000 | 32 | 0.000999 | 0.000402 | 1 | 200 | 6/999994 | | reversal | 1000000 | 32 | 0.000996 | 0.001477 | 1 | 200 | 6/999994 | | | | | | | | | | | bridge | 1000000 | 32 | 0.000000 | 0.000407 | 1 | 200 | 7/999993 | | helix | 1000000 | 32 | 0.001503 | 0.002148 | 1 | 200 | 7/999993 | | trinity | 1000000 | 32 | 0.000000 | 0.000417 | 1 | 200 | 7/999993 | | reversal | 1000000 | 32 | 0.000980 | 0.001407 | 1 | 200 | 7/999993 | | | | | | | | | | | bridge | 1000000 | 32 | 0.000000 | 0.000410 | 1 | 200 | 8/999992 | | helix | 1000000 | 32 | 0.001514 | 0.002167 | 1 | 200 | 8/999992 | | trinity | 1000000 | 32 | 0.000000 | 0.000412 | 1 | 200 | 8/999992 | | reversal | 1000000 | 32 | 0.000992 | 0.001405 | 1 | 200 | 8/999992 | | | | | | | | | | | bridge | 1000000 | 32 | 0.001003 | 0.000405 | 1 | 200 | 9/999991 | | helix | 1000000 | 32 | 0.001504 | 0.002146 | 1 | 200 | 9/999991 | | trinity | 1000000 | 32 | 0.000506 | 0.000970 | 1 | 200 | 9/999991 | | reversal | 1000000 | 32 | 0.000989 | 0.001507 | 1 | 200 | 9/999991 | | | | | | | | | | | bridge | 1000000 | 32 | 0.001000 | 0.000597 | 1 | 200 | 333333/666667 | | helix | 1000000 | 32 | 0.000992 | 0.001587 | 1 | 200 | 333333/666667 | | trinity | 1000000 | 32 | 0.000998 | 0.001060 | 1 | 200 | 333333/666667 | | reversal | 1000000 | 32 | 0.000994 | 0.001480 | 1 | 200 | 333333/666667 | | | | | | | | | | | bridge | 1000000 | 32 | 0.000998 | 0.000958 | 1 | 200 | 333334/666666 | | helix | 1000000 | 32 | 0.001991 | 0.002205 | 1 | 200 | 333334/666666 | | trinity | 1000000 | 32 | 0.001000 | 0.001042 | 1 | 200 | 333334/666666 | | reversal | 1000000 | 32 | 0.000997 | 0.001390 | 1 | 200 | 333334/666666 | | | | | | | | | | | bridge | 1000000 | 32 | 0.000993 | 0.001040 | 1 | 200 | 333335/666665 | | helix | 1000000 | 32 | 0.001505 | 0.002162 | 1 | 200 | 333335/666665 | | trinity | 1000000 | 32 | 0.000503 | 0.001045 | 1 | 200 | 333335/666665 | | reversal | 1000000 | 32 | 0.000988 | 0.001422 | 1 | 200 | 333335/666665 | | | | | | | | | | | bridge | 1000000 | 32 | 0.000995 | 0.000980 | 1 | 200 | 333336/666664 | | helix | 1000000 | 32 | 0.001507 | 0.002210 | 1 | 200 | 333336/666664 | | trinity | 1000000 | 32 | 0.000999 | 0.001015 | 1 | 200 | 333336/666664 | | reversal | 1000000 | 32 | 0.000993 | 0.001397 | 1 | 200 | 333336/666664 | | | | | | | | | | | bridge | 1000000 | 32 | 0.000998 | 0.000955 | 1 | 200 | 333337/666663 | | helix | 1000000 | 32 | 0.001000 | 0.002214 | 1 | 200 | 333337/666663 | | trinity | 1000000 | 32 | 0.000996 | 0.000980 | 1 | 200 | 333337/666663 | | reversal | 1000000 | 32 | 0.000997 | 0.001422 | 1 | 200 | 333337/666663 | | | | | | | | | | | bridge | 1000000 | 32 | 0.000997 | 0.000850 | 1 | 200 | 500000/500000 | | helix | 1000000 | 32 | 0.000993 | 0.001160 | 1 | 200 | 500000/500000 | | trinity | 1000000 | 32 | 0.000999 | 0.000875 | 1 | 200 | 500000/500000 | | reversal | 1000000 | 32 | 0.000996 | 0.001401 | 1 | 200 | 500000/500000 | | | | | | | | | | | bridge | 1000000 | 32 | 0.001002 | 0.000840 | 1 | 200 | 500001/499999 | | helix | 1000000 | 32 | 0.001505 | 0.002304 | 1 | 200 | 500001/499999 | | trinity | 1000000 | 32 | 0.000993 | 0.001025 | 1 | 200 | 500001/499999 | | reversal | 1000000 | 32 | 0.000996 | 0.001371 | 1 | 200 | 500001/499999 | | | | | | | | | | | bridge | 1000000 | 32 | 0.000998 | 0.000845 | 1 | 200 | 500002/499998 | | helix | 1000000 | 32 | 0.001000 | 0.002200 | 1 | 200 | 500002/499998 | | trinity | 1000000 | 32 | 0.001002 | 0.000845 | 1 | 200 | 500002/499998 | | reversal | 1000000 | 32 | 0.000987 | 0.001417 | 1 | 200 | 500002/499998 | | | | | | | | | | | bridge | 1000000 | 32 | 0.000994 | 0.000832 | 1 | 200 | 500003/499997 | | helix | 1000000 | 32 | 0.001983 | 0.002277 | 1 | 200 | 500003/499997 | | trinity | 1000000 | 32 | 0.000999 | 0.000910 | 1 | 200 | 500003/499997 | | reversal | 1000000 | 32 | 0.000992 | 0.001460 | 1 | 200 | 500003/499997 | | | | | | | | | | | bridge | 1000000 | 32 | 0.000999 | 0.000940 | 1 | 200 | 500004/499996 | | helix | 1000000 | 32 | 0.001506 | 0.002340 | 1 | 200 | 500004/499996 | | trinity | 1000000 | 32 | 0.000998 | 0.000885 | 1 | 200 | 500004/499996 | | reversal | 1000000 | 32 | 0.000993 | 0.001370 | 1 | 200 | 500004/499996 | | | | | | | | | | | bridge | 1000000 | 32 | 0.000000 | 0.000909 | 1 | 200 | 500005/499995 | | helix | 1000000 | 32 | 0.001000 | 0.002285 | 1 | 200 | 500005/499995 | | trinity | 1000000 | 32 | 0.000992 | 0.001167 | 1 | 200 | 500005/499995 | | reversal | 1000000 | 32 | 0.000995 | 0.001462 | 1 | 200 | 500005/499995 | | | | | | | | | | | bridge | 1000000 | 32 | 0.000997 | 0.000857 | 1 | 200 | 500006/499994 | | helix | 1000000 | 32 | 0.001976 | 0.002411 | 1 | 200 | 500006/499994 | | trinity | 1000000 | 32 | 0.000907 | 0.001154 | 1 | 200 | 500006/499994 | | reversal | 1000000 | 32 | 0.000994 | 0.001517 | 1 | 200 | 500006/499994 | | | | | | | | | | | bridge | 1000000 | 32 | 0.001000 | 0.000895 | 1 | 200 | 500007/499993 | | helix | 1000000 | 32 | 0.001507 | 0.002325 | 1 | 200 | 500007/499993 | | trinity | 1000000 | 32 | 0.000998 | 0.001022 | 1 | 200 | 500007/499993 | | reversal | 1000000 | 32 | 0.000990 | 0.001415 | 1 | 200 | 500007/499993 | | | | | | | | | | | bridge | 1000000 | 32 | 0.000999 | 0.000870 | 1 | 200 | 500008/499992 | | helix | 1000000 | 32 | 0.001989 | 0.002260 | 1 | 200 | 500008/499992 | | trinity | 1000000 | 32 | 0.000998 | 0.001040 | 1 | 200 | 500008/499992 | | reversal | 1000000 | 32 | 0.000996 | 0.001397 | 1 | 200 | 500008/499992 | | | | | | | | | | | bridge | 1000000 | 32 | 0.000999 | 0.000397 | 1 | 200 | 99999/900001 | | helix | 1000000 | 32 | 0.001496 | 0.002165 | 1 | 200 | 99999/900001 | | trinity | 1000000 | 32 | 0.000999 | 0.000985 | 1 | 200 | 99999/900001 | | reversal | 1000000 | 32 | 0.000990 | 0.001382 | 1 | 200 | 99999/900001 | | | | | | | | | | | bridge | 1000000 | 32 | 0.000999 | 0.000417 | 1 | 200 | 199998/800002 | | helix | 1000000 | 32 | 0.001988 | 0.002210 | 1 | 200 | 199998/800002 | | trinity | 1000000 | 32 | 0.000997 | 0.000967 | 1 | 200 | 199998/800002 | | reversal | 1000000 | 32 | 0.000988 | 0.001415 | 1 | 200 | 199998/800002 | | | | | | | | | | | bridge | 1000000 | 32 | 0.000000 | 0.000557 | 1 | 200 | 299997/700003 | | helix | 1000000 | 32 | 0.001514 | 0.002208 | 1 | 200 | 299997/700003 | | trinity | 1000000 | 32 | 0.000999 | 0.001000 | 1 | 200 | 299997/700003 | | reversal | 1000000 | 32 | 0.000989 | 0.001462 | 1 | 200 | 299997/700003 | | | | | | | | | | | bridge | 1000000 | 32 | 0.000997 | 0.000817 | 1 | 200 | 399996/600004 | | helix | 1000000 | 32 | 0.000999 | 0.002237 | 1 | 200 | 399996/600004 | | trinity | 1000000 | 32 | 0.000983 | 0.001053 | 1 | 200 | 399996/600004 | | reversal | 1000000 | 32 | 0.000989 | 0.001447 | 1 | 200 | 399996/600004 | | | | | | | | | | | bridge | 1000000 | 32 | 0.000000 | 0.000852 | 1 | 200 | 499995/500005 | | helix | 1000000 | 32 | 0.001503 | 0.002237 | 1 | 200 | 499995/500005 | | trinity | 1000000 | 32 | 0.000988 | 0.001035 | 1 | 200 | 499995/500005 | | reversal | 1000000 | 32 | 0.000995 | 0.001467 | 1 | 200 | 499995/500005 | | | | | | | | | | | bridge | 1000000 | 32 | 0.000000 | 0.000820 | 1 | 200 | 599994/400006 | | helix | 1000000 | 32 | 0.001990 | 0.002330 | 1 | 200 | 599994/400006 | | trinity | 1000000 | 32 | 0.000995 | 0.001030 | 1 | 200 | 599994/400006 | | reversal | 1000000 | 32 | 0.000506 | 0.001387 | 1 | 200 | 599994/400006 | | | | | | | | | | | bridge | 1000000 | 32 | 0.000000 | 0.000522 | 1 | 200 | 699993/300007 | | helix | 1000000 | 32 | 0.001984 | 0.002322 | 1 | 200 | 699993/300007 | | trinity | 1000000 | 32 | 0.000985 | 0.001100 | 1 | 200 | 699993/300007 | | reversal | 1000000 | 32 | 0.000996 | 0.001397 | 1 | 200 | 699993/300007 | | | | | | | | | | | bridge | 1000000 | 32 | 0.000000 | 0.000372 | 1 | 200 | 799992/200008 | | helix | 1000000 | 32 | 0.001512 | 0.002330 | 1 | 200 | 799992/200008 | | trinity | 1000000 | 32 | 0.000993 | 0.001045 | 1 | 200 | 799992/200008 | | reversal | 1000000 | 32 | 0.000997 | 0.001530 | 1 | 200 | 799992/200008 | | | | | | | | | | | bridge | 1000000 | 32 | 0.001001 | 0.000325 | 1 | 200 | 899991/100009 | | helix | 1000000 | 32 | 0.001996 | 0.002327 | 1 | 200 | 899991/100009 | | trinity | 1000000 | 32 | 0.000986 | 0.001054 | 1 | 200 | 899991/100009 | | reversal | 1000000 | 32 | 0.000997 | 0.001382 | 1 | 200 | 899991/100009 | | | | | | | | | | | bridge | 1000000 | 32 | 0.000000 | 0.000290 | 1 | 200 | 999990/10 | | helix | 1000000 | 32 | 0.001503 | 0.002337 | 1 | 200 | 999990/10 | | trinity | 1000000 | 32 | 0.000994 | 0.001030 | 1 | 200 | 999990/10 | | reversal | 1000000 | 32 | 0.000982 | 0.001387 | 1 | 200 | 999990/10 | Overall performance: trinity > helix > reversal > bridge | Name | Items | Type | Best | Average | Loops | Samples | Distribution | | --------- | -------- | ---- | -------- | -------- | --------- | ------- | ---------------- | | contrev | 1000000 | 32 | 0.000996 | 0.001154 | 1 | 200 | 1/999999 | | piston | 1000000 | 32 | 0.003001 | 0.004461 | 1 | 200 | 1/999999 | |griesmills | 1000000 | 32 | 0.003503 | 0.004223 | 1 | 200 | 1/999999 | | juggler | 1000000 | 32 | 0.000996 | 0.001255 | 1 | 200 | 1/999999 | | | | | | | | | | | contrev | 1000000 | 32 | 0.000998 | 0.001050 | 1 | 200 | 1000/999000 | | piston | 1000000 | 32 | 0.000984 | 0.001725 | 1 | 200 | 1000/999000 | |griesmills | 1000000 | 32 | 0.000996 | 0.001647 | 1 | 200 | 1000/999000 | | juggler | 1000000 | 32 | 0.000999 | 0.001969 | 1 | 200 | 1000/999000 | | | | | | | | | | | contrev | 1000000 | 32 | 0.000996 | 0.001035 | 1 | 200 | 99999/900001 | | piston | 1000000 | 32 | 0.000992 | 0.001677 | 1 | 200 | 99999/900001 | |griesmills | 1000000 | 32 | 0.000988 | 0.001715 | 1 | 200 | 99999/900001 | | juggler | 1000000 | 32 | 0.000997 | 0.001815 | 1 | 200 | 99999/900001 | | | | | | | | | | | contrev | 1000000 | 32 | 0.001000 | 0.000995 | 1 | 200 | 199998/800002 | | piston | 1000000 | 32 | 0.000997 | 0.001722 | 1 | 200 | 199998/800002 | |griesmills | 1000000 | 32 | 0.000998 | 0.002005 | 1 | 200 | 199998/800002 | | juggler | 1000000 | 32 | 0.001002 | 0.002095 | 1 | 200 | 199998/800002 | | | | | | | | | | | contrev | 1000000 | 32 | 0.001002 | 0.000955 | 1 | 200 | 299997/700003 | | piston | 1000000 | 32 | 0.000995 | 0.001627 | 1 | 200 | 299997/700003 | |griesmills | 1000000 | 32 | 0.000997 | 0.001679 | 1 | 200 | 299997/700003 | | juggler | 1000000 | 32 | 0.001506 | 0.002250 | 1 | 200 | 299997/700003 | | | | | | | | | | | contrev | 1000000 | 32 | 0.000998 | 0.000960 | 1 | 200 | 399996/600004 | | piston | 1000000 | 32 | 0.000911 | 0.001709 | 1 | 200 | 399996/600004 | |griesmills | 1000000 | 32 | 0.000992 | 0.001742 | 1 | 200 | 399996/600004 | | juggler | 1000000 | 32 | 0.001722 | 0.002256 | 1 | 200 | 399996/600004 | | | | | | | | | | | contrev | 1000000 | 32 | 0.000997 | 0.001037 | 1 | 200 | 499995/500005 | | piston | 1000000 | 32 | 0.000995 | 0.001812 | 1 | 200 | 499995/500005 | |griesmills | 1000000 | 32 | 0.001995 | 0.002710 | 1 | 200 | 499995/500005 | | juggler | 1000000 | 32 | 0.001978 | 0.002263 | 1 | 200 | 499995/500005 | | | | | | | | | | | contrev | 1000000 | 32 | 0.000998 | 0.001072 | 1 | 200 | 1/999999 | | piston | 1000000 | 32 | 0.003469 | 0.004402 | 1 | 200 | 1/999999 | |griesmills | 1000000 | 32 | 0.003000 | 0.004301 | 1 | 200 | 1/999999 | | juggler | 1000000 | 32 | 0.000508 | 0.001268 | 1 | 200 | 1/999999 | | | | | | | | | | | contrev | 1000000 | 32 | 0.000999 | 0.001040 | 1 | 200 | 2/999998 | | piston | 1000000 | 32 | 0.001998 | 0.004253 | 1 | 200 | 2/999998 | |griesmills | 1000000 | 32 | 0.002511 | 0.003727 | 1 | 200 | 2/999998 | | juggler | 1000000 | 32 | 0.000996 | 0.001437 | 1 | 200 | 2/999998 | | | | | | | | | | | contrev | 1000000 | 32 | 0.000988 | 0.001053 | 1 | 200 | 3/999997 | | piston | 1000000 | 32 | 0.003000 | 0.005062 | 1 | 200 | 3/999997 | |griesmills | 1000000 | 32 | 0.001995 | 0.002855 | 1 | 200 | 3/999997 | | juggler | 1000000 | 32 | 0.000995 | 0.001510 | 1 | 200 | 3/999997 | | | | | | | | | | | contrev | 1000000 | 32 | 0.000996 | 0.001066 | 1 | 200 | 4/999996 | | piston | 1000000 | 32 | 0.002999 | 0.004779 | 1 | 200 | 4/999996 | |griesmills | 1000000 | 32 | 0.001992 | 0.002430 | 1 | 200 | 4/999996 | | juggler | 1000000 | 32 | 0.000990 | 0.001382 | 1 | 200 | 4/999996 | | | | | | | | | | | contrev | 1000000 | 32 | 0.000992 | 0.001068 | 1 | 200 | 5/999995 | | piston | 1000000 | 32 | 0.002997 | 0.004117 | 1 | 200 | 5/999995 | |griesmills | 1000000 | 32 | 0.001000 | 0.002137 | 1 | 200 | 5/999995 | | juggler | 1000000 | 32 | 0.000982 | 0.001355 | 1 | 200 | 5/999995 | | | | | | | | | | | contrev | 1000000 | 32 | 0.000997 | 0.000965 | 1 | 200 | 6/999994 | | piston | 1000000 | 32 | 0.002000 | 0.003928 | 1 | 200 | 6/999994 | |griesmills | 1000000 | 32 | 0.001002 | 0.002139 | 1 | 200 | 6/999994 | | juggler | 1000000 | 32 | 0.000822 | 0.001412 | 1 | 200 | 6/999994 | | | | | | | | | | | contrev | 1000000 | 32 | 0.000998 | 0.000990 | 1 | 200 | 7/999993 | | piston | 1000000 | 32 | 0.002994 | 0.004123 | 1 | 200 | 7/999993 | |griesmills | 1000000 | 32 | 0.000999 | 0.002022 | 1 | 200 | 7/999993 | | juggler | 1000000 | 32 | 0.000991 | 0.001444 | 1 | 200 | 7/999993 | | | | | | | | | | | contrev | 1000000 | 32 | 0.000000 | 0.001018 | 1 | 200 | 8/999992 | | piston | 1000000 | 32 | 0.002995 | 0.003666 | 1 | 200 | 8/999992 | |griesmills | 1000000 | 32 | 0.000998 | 0.002175 | 1 | 200 | 8/999992 | | juggler | 1000000 | 32 | 0.000994 | 0.001440 | 1 | 200 | 8/999992 | | | | | | | | | | | contrev | 1000000 | 32 | 0.000996 | 0.001016 | 1 | 200 | 9/999991 | | piston | 1000000 | 32 | 0.001999 | 0.003753 | 1 | 200 | 9/999991 | |griesmills | 1000000 | 32 | 0.000997 | 0.001902 | 1 | 200 | 9/999991 | | juggler | 1000000 | 32 | 0.000910 | 0.001450 | 1 | 200 | 9/999991 | | | | | | | | | | | contrev | 1000000 | 32 | 0.000983 | 0.000993 | 1 | 200 | 333333/666667 | | piston | 1000000 | 32 | 0.001505 | 0.002467 | 1 | 200 | 333333/666667 | |griesmills | 1000000 | 32 | 0.001993 | 0.002990 | 1 | 200 | 333333/666667 | | juggler | 1000000 | 32 | 0.001000 | 0.002030 | 1 | 200 | 333333/666667 | | | | | | | | | | | contrev | 1000000 | 32 | 0.000997 | 0.000970 | 1 | 200 | 333334/666666 | | piston | 1000000 | 32 | 0.001001 | 0.002537 | 1 | 200 | 333334/666666 | |griesmills | 1000000 | 32 | 0.001000 | 0.002120 | 1 | 200 | 333334/666666 | | juggler | 1000000 | 32 | 0.000998 | 0.002044 | 1 | 200 | 333334/666666 | | | | | | | | | | | contrev | 1000000 | 32 | 0.000999 | 0.000990 | 1 | 200 | 333335/666665 | | piston | 1000000 | 32 | 0.001513 | 0.002423 | 1 | 200 | 333335/666665 | |griesmills | 1000000 | 32 | 0.000997 | 0.001777 | 1 | 200 | 333335/666665 | | juggler | 1000000 | 32 | 0.001000 | 0.002084 | 1 | 200 | 333335/666665 | | | | | | | | | | | contrev | 1000000 | 32 | 0.000993 | 0.000999 | 1 | 200 | 333336/666664 | | piston | 1000000 | 32 | 0.001992 | 0.002352 | 1 | 200 | 333336/666664 | |griesmills | 1000000 | 32 | 0.000990 | 0.001723 | 1 | 200 | 333336/666664 | | juggler | 1000000 | 32 | 0.001000 | 0.002103 | 1 | 200 | 333336/666664 | | | | | | | | | | | contrev | 1000000 | 32 | 0.000995 | 0.001033 | 1 | 200 | 333337/666663 | | piston | 1000000 | 32 | 0.001507 | 0.002306 | 1 | 200 | 333337/666663 | |griesmills | 1000000 | 32 | 0.000997 | 0.001667 | 1 | 200 | 333337/666663 | | juggler | 1000000 | 32 | 0.000999 | 0.002070 | 1 | 200 | 333337/666663 | | | | | | | | | | | contrev | 1000000 | 32 | 0.001000 | 0.000845 | 1 | 200 | 500000/500000 | | piston | 1000000 | 32 | 0.000000 | 0.000847 | 1 | 200 | 500000/500000 | |griesmills | 1000000 | 32 | 0.001000 | 0.000842 | 1 | 200 | 500000/500000 | | juggler | 1000000 | 32 | 0.000998 | 0.001795 | 1 | 200 | 500000/500000 | | | | | | | | | | | contrev | 1000000 | 32 | 0.000983 | 0.000999 | 1 | 200 | 500001/499999 | | piston | 1000000 | 32 | 0.001987 | 0.003023 | 1 | 200 | 500001/499999 | |griesmills | 1000000 | 32 | 0.001998 | 0.002638 | 1 | 200 | 500001/499999 | | juggler | 1000000 | 32 | 0.000999 | 0.001965 | 1 | 200 | 500001/499999 | | | | | | | | | | | contrev | 1000000 | 32 | 0.001003 | 0.000959 | 1 | 200 | 500002/499998 | | piston | 1000000 | 32 | 0.001000 | 0.002874 | 1 | 200 | 500002/499998 | |griesmills | 1000000 | 32 | 0.000999 | 0.002040 | 1 | 200 | 500002/499998 | | juggler | 1000000 | 32 | 0.001000 | 0.002060 | 1 | 200 | 500002/499998 | | | | | | | | | | | contrev | 1000000 | 32 | 0.000999 | 0.000999 | 1 | 200 | 500003/499997 | | piston | 1000000 | 32 | 0.001993 | 0.002638 | 1 | 200 | 500003/499997 | |griesmills | 1000000 | 32 | 0.000997 | 0.001842 | 1 | 200 | 500003/499997 | | juggler | 1000000 | 32 | 0.001000 | 0.002005 | 1 | 200 | 500003/499997 | | | | | | | | | | | contrev | 1000000 | 32 | 0.000508 | 0.000985 | 1 | 200 | 500004/499996 | | piston | 1000000 | 32 | 0.001988 | 0.002618 | 1 | 200 | 500004/499996 | |griesmills | 1000000 | 32 | 0.000993 | 0.002035 | 1 | 200 | 500004/499996 | | juggler | 1000000 | 32 | 0.001000 | 0.002037 | 1 | 200 | 500004/499996 | | | | | | | | | | | contrev | 1000000 | 32 | 0.000994 | 0.000990 | 1 | 200 | 500005/499995 | | piston | 1000000 | 32 | 0.001994 | 0.002528 | 1 | 200 | 500005/499995 | |griesmills | 1000000 | 32 | 0.000997 | 0.001797 | 1 | 200 | 500005/499995 | | juggler | 1000000 | 32 | 0.001000 | 0.002083 | 1 | 200 | 500005/499995 | | | | | | | | | | | contrev | 1000000 | 32 | 0.000999 | 0.000985 | 1 | 200 | 500006/499994 | | piston | 1000000 | 32 | 0.001997 | 0.002565 | 1 | 200 | 500006/499994 | |griesmills | 1000000 | 32 | 0.000997 | 0.001845 | 1 | 200 | 500006/499994 | | juggler | 1000000 | 32 | 0.001984 | 0.002188 | 1 | 200 | 500006/499994 | | | | | | | | | | | contrev | 1000000 | 32 | 0.000508 | 0.001120 | 1 | 200 | 500007/499993 | | piston | 1000000 | 32 | 0.001997 | 0.002655 | 1 | 200 | 500007/499993 | |griesmills | 1000000 | 32 | 0.000998 | 0.001878 | 1 | 200 | 500007/499993 | | juggler | 1000000 | 32 | 0.001994 | 0.002308 | 1 | 200 | 500007/499993 | | | | | | | | | | | contrev | 1000000 | 32 | 0.000997 | 0.001024 | 1 | 200 | 500008/499992 | | piston | 1000000 | 32 | 0.001506 | 0.002658 | 1 | 200 | 500008/499992 | |griesmills | 1000000 | 32 | 0.000998 | 0.001864 | 1 | 200 | 500008/499992 | | juggler | 1000000 | 32 | 0.001503 | 0.002200 | 1 | 200 | 500008/499992 | | | | | | | | | | | contrev | 1000000 | 32 | 0.000897 | 0.001015 | 1 | 200 | 99999/900001 | | piston | 1000000 | 32 | 0.000988 | 0.001670 | 1 | 200 | 99999/900001 | |griesmills | 1000000 | 32 | 0.000988 | 0.001727 | 1 | 200 | 99999/900001 | | juggler | 1000000 | 32 | 0.000997 | 0.001820 | 1 | 200 | 99999/900001 | | | | | | | | | | | contrev | 1000000 | 32 | 0.000997 | 0.001003 | 1 | 200 | 199998/800002 | | piston | 1000000 | 32 | 0.000992 | 0.001737 | 1 | 200 | 199998/800002 | |griesmills | 1000000 | 32 | 0.001507 | 0.002105 | 1 | 200 | 199998/800002 | | juggler | 1000000 | 32 | 0.001000 | 0.002062 | 1 | 200 | 199998/800002 | | | | | | | | | | | contrev | 1000000 | 32 | 0.000991 | 0.001004 | 1 | 200 | 299997/700003 | | piston | 1000000 | 32 | 0.000998 | 0.001617 | 1 | 200 | 299997/700003 | |griesmills | 1000000 | 32 | 0.000988 | 0.001655 | 1 | 200 | 299997/700003 | | juggler | 1000000 | 32 | 0.001507 | 0.002208 | 1 | 200 | 299997/700003 | | | | | | | | | | | contrev | 1000000 | 32 | 0.000995 | 0.000990 | 1 | 200 | 399996/600004 | | piston | 1000000 | 32 | 0.000997 | 0.001692 | 1 | 200 | 399996/600004 | |griesmills | 1000000 | 32 | 0.000991 | 0.001747 | 1 | 200 | 399996/600004 | | juggler | 1000000 | 32 | 0.001508 | 0.002141 | 1 | 200 | 399996/600004 | | | | | | | | | | | contrev | 1000000 | 32 | 0.000993 | 0.000988 | 1 | 200 | 499995/500005 | | piston | 1000000 | 32 | 0.000991 | 0.001737 | 1 | 200 | 499995/500005 | |griesmills | 1000000 | 32 | 0.001993 | 0.002650 | 1 | 200 | 499995/500005 | | juggler | 1000000 | 32 | 0.001503 | 0.002060 | 1 | 200 | 499995/500005 | | | | | | | | | | | contrev | 1000000 | 32 | 0.000988 | 0.001030 | 1 | 200 | 599994/400006 | | piston | 1000000 | 32 | 0.000991 | 0.001672 | 1 | 200 | 599994/400006 | |griesmills | 1000000 | 32 | 0.000995 | 0.001727 | 1 | 200 | 599994/400006 | | juggler | 1000000 | 32 | 0.001995 | 0.002303 | 1 | 200 | 599994/400006 | | | | | | | | | | | contrev | 1000000 | 32 | 0.000991 | 0.001035 | 1 | 200 | 699993/300007 | | piston | 1000000 | 32 | 0.000996 | 0.001602 | 1 | 200 | 699993/300007 | |griesmills | 1000000 | 32 | 0.000997 | 0.001647 | 1 | 200 | 699993/300007 | | juggler | 1000000 | 32 | 0.002999 | 0.004158 | 1 | 200 | 699993/300007 | | | | | | | | | | | contrev | 1000000 | 32 | 0.000993 | 0.001025 | 1 | 200 | 799992/200008 | | piston | 1000000 | 32 | 0.000994 | 0.001655 | 1 | 200 | 799992/200008 | |griesmills | 1000000 | 32 | 0.000997 | 0.001657 | 1 | 200 | 799992/200008 | | juggler | 1000000 | 32 | 0.002506 | 0.003488 | 1 | 200 | 799992/200008 | | | | | | | | | | | contrev | 1000000 | 32 | 0.000508 | 0.001055 | 1 | 200 | 899991/100009 | | piston | 1000000 | 32 | 0.000996 | 0.001612 | 1 | 200 | 899991/100009 | |griesmills | 1000000 | 32 | 0.000996 | 0.001645 | 1 | 200 | 899991/100009 | | juggler | 1000000 | 32 | 0.002996 | 0.004048 | 1 | 200 | 899991/100009 | | | | | | | | | | | contrev | 1000000 | 32 | 0.000508 | 0.001065 | 1 | 200 | 999990/10 | | piston | 1000000 | 32 | 0.000997 | 0.001915 | 1 | 200 | 999990/10 | |griesmills | 1000000 | 32 | 0.002980 | 0.003693 | 1 | 200 | 999990/10 | | juggler | 1000000 | 32 | 0.000999 | 0.001995 | 1 | 200 | 999990/10 | Overall performance: contrev > piston > griesmills > juggler **Noted that performance may vary depending on the specific implemention and array size, from worst to best the order is:** Juggling Rotation (juggler) Gries-Mills Rotation (griesmills) Successive Rotation (piston) Bridge Rotation (bridge) Triple Reversal Rotation (reversal) Helix Rotation (helix) Conjoined Triple Reversal Rotation (contrev) Trinity Rotation (trinity)

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully