{"id":16910035,"url":"https://github.com/pauldreik/tiptap","last_synced_at":"2025-09-24T17:18:14.773Z","repository":{"id":214223721,"uuid":"735975270","full_name":"pauldreik/tiptap","owner":"pauldreik","description":"A C++ library for implementing linear feedback shift registers (LFSR)","archived":false,"fork":false,"pushed_at":"2023-12-31T17:47:23.000Z","size":141,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-01-25T21:12:22.400Z","etag":null,"topics":["lfsr"],"latest_commit_sha":null,"homepage":"https://www.pauldreik.se","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsl-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pauldreik.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-12-26T16:12:27.000Z","updated_at":"2023-12-26T21:32:16.000Z","dependencies_parsed_at":"2023-12-31T18:29:36.095Z","dependency_job_id":"d340742e-84e2-47f8-b0cd-9e8baad80e91","html_url":"https://github.com/pauldreik/tiptap","commit_stats":{"total_commits":21,"total_committers":1,"mean_commits":21.0,"dds":0.0,"last_synced_commit":"65502ac438b891b1b18c506457f82c557136456d"},"previous_names":["pauldreik/tiptap"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pauldreik%2Ftiptap","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pauldreik%2Ftiptap/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pauldreik%2Ftiptap/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pauldreik%2Ftiptap/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pauldreik","download_url":"https://codeload.github.com/pauldreik/tiptap/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244717365,"owners_count":20498284,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["lfsr"],"created_at":"2024-10-13T18:58:51.157Z","updated_at":"2025-09-24T17:18:09.716Z","avatar_url":"https://github.com/pauldreik.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# tiptap - Linear Feedback Shift Register (LFSR) in C++ 20\n\nThis is a constexpr C++ 20 header only library for implementing [LFSR](https://en.wikipedia.org/wiki/Linear-feedback_shift_register) of varying size.\n\nThe performance is on par with hand coded C.\n\nSizes between N=3 and N=168 are supported, plus some additional values N=512, 768, 1024, 2048,4096.\n\nLicense: Boost software license 1.0\n\n## Quick example\n```cpp\n#include \u003ciostream\u003e\n#include \u003ctiptap/lfsr.h\u003e\n\nint\nmain()\n{\n  constexpr std::size_t N = 4;\n  BigLFSR\u003cN\u003e lfsr;\n\n  const auto initial_state = lfsr.state();\n  do {\n    std::cout \u003c\u003c +lfsr.state().m_data[0] \u003c\u003c ' ';\n    lfsr.next();\n  } while (lfsr.state() != initial_state);\n  std::cout \u003c\u003c '\\n';\n}\n```\nThe above example will output:\n\u003e 1 8 4 2 9 12 6 11 5 10 13 14 15 7 3 \n\nThis is 15 elements, which is the longest possible cycle using N=4 taps.\n\nThere are no external dependencies.\n\n## Longer example with N=4096\n\nThis example shows a very big shift register. It deliberately uses a second optional template argument to specify the state to be built from std::uint8_t.\n\n```cpp\n#include \u003ciostream\u003e\n#include \u003ctiptap/lfsr.h\u003e\n\nint\nmain()\n{\n  constexpr std::size_t N = 4096;\n  BigLFSR\u003cN, std::uint8_t\u003e lfsr;\n\n  const auto initial_state = lfsr.state();\n  do {\n    std::cout \u003c\u003c +lfsr.state().m_data[0] \u003c\u003c '\\n';\n    lfsr.next();\n  } while (lfsr.state() != initial_state);\n}\n\n```\nThis program takes very long to finish, the first 100 M lines took 47 seconds on my machine. It is expected to wrap around at `2**N`, which is about 1e1219 years.\n\n## Why? What is the purpose?\n\nI made this for fun. I had in mind to make a counter+block cipher based pseudo random number generator (see it in action at [examples/encryptedcounter.cpp](examples/encryptedcounter.cpp)), to see how many rounds of AES would be needed to pass statistical randomness tests. \n\nIt may be useful to prototype stuff - I have FPGA implementations in mind, where an LFSR should be very cheap compared to a counter. Being able to prototype in C++ is nice.\n\n## How it is implemented\n\nBigLFSR uses a custom bignum class, with minimal functionality needed for this purpose. Despite it's name, it also handles smaller sizes, down to a single std::uint8_t.\n\nThere is no limit on size, if the taps are known for larger N (the best I could find is [this pdf linked from wikipedia](https://web.archive.org/web/20161007061934/http://courses.cse.tamu.edu/csce680/walker/lfsr_table.pdf)), there is no problem augmenting the code by adding to the coefficients in [include/tiptap/lfsr_coefficients.h](include/tiptap/lfsr_coefficients.h).\n\nTrying to use a size which is unsupported results in a compile time error, there is no risk of misusing the class.\n\n## The SmallLFSR class, alternative implementation for (3\u003c=N\u003c=64)\n\n\u003e Note: there is no performance or size benefit of SmallLFSR over BigLFSR - will maybe deprecate it in favor of BigLFSR.\n\nThe class SmallLFSR implements smaller LFSRs using the builtin std::uint8_t, std::uint16_t etc. up to std::uint64_t. There is no bignum functionality. The resulting machine code is slightly different. It may be easier to understand due to having less abstractions than the BigLFSR class.\n\nThe class is templated on the size, all steps between N=3 and N=64 are supported. By default, the smallest underlying type that is large enough is used.\n\nTrying to use an excessive size or below 3 results in a compile time error.\n\n## Performance ##\n\nThe abstraction provided mostly melts away in the optimizer, and the performance is on par with hand coded C. There are however knobs to tweak, since the best performance depends on N (and obviously the compiler settings, cpu etc). The classes have template parameters for the underlying storage and how the topmost bit is set during the LFSR update step.\n\nBenchmarks are included in the benchmark folder. Looking at the case of N=16:\n - The [code snippet on wikipedia](https://en.wikipedia.org/wiki/Linear-feedback_shift_register), written in C: 1642 µs/1M iterations \n - The BigLFSR class: 1393-2024 µs/1M iterations depending on the template parameters \n - The SmallLFSR class: 1668-2022 µs/1M iterations depending on the template parameters\n\nIt is recommended to run the benchmark on the target system to find the optimal settings, if performance is important. See [benchmark results](benchmark/benchmark_results_N_up_to_64.ods) for performance measured with gcc 12 on a i7-10710U CPU.\n   \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpauldreik%2Ftiptap","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpauldreik%2Ftiptap","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpauldreik%2Ftiptap/lists"}