├── .gitignore ├── .travis.yml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── NOTICE ├── README.md ├── build.gradle ├── dist ├── README └── logback.xml ├── doc ├── docinfo.html ├── getting_started.adoc ├── img │ └── design.png ├── index.adoc ├── introduction.adoc ├── release_notes.adoc └── user_guide.adoc ├── findbugsExclude.xml ├── ghpages ├── CNAME ├── index.html └── releases │ └── latest │ └── index.html ├── gradle-local.template.properties ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── license-header.txt ├── settings.gradle ├── streamplify-examples └── src │ └── main │ ├── java │ └── org │ │ └── beryx │ │ └── streamplify │ │ ├── benchmark │ │ ├── DelayedBenchmark.java │ │ ├── FibonacciBenchmark.java │ │ ├── IterSpliterPermutations.java │ │ ├── JacobsthalBenchmark.java │ │ ├── NQueensBenchmark.java │ │ └── ShufflerView.java │ │ └── example │ │ ├── Arrangements.java │ │ ├── CardDeck.java │ │ ├── Diet.java │ │ ├── Fibonacci.java │ │ ├── Friends.java │ │ ├── Hats.java │ │ ├── Jacobsthal.java │ │ ├── NQueens.java │ │ ├── RandomPoetry.java │ │ ├── TSP.java │ │ └── Vacation.java │ └── resources │ └── logback.xml ├── streamplify └── src │ ├── main │ └── java │ │ └── org │ │ └── beryx │ │ └── streamplify │ │ ├── BigIntegerIndexedSpliterator.java │ │ ├── IntArraySupplier.java │ │ ├── LongIndexedSpliterator.java │ │ ├── Splittable.java │ │ ├── Streamable.java │ │ ├── StreamableProxy.java │ │ ├── combination │ │ ├── BigIntegerCombinations.java │ │ ├── CombinationSupplier.java │ │ ├── Combinations.java │ │ └── LongCombinations.java │ │ ├── derangement │ │ ├── BigIntegerDerangements.java │ │ ├── DerangementSupplier.java │ │ ├── Derangements.java │ │ └── LongDerangements.java │ │ ├── partperm │ │ ├── BigIntegerPartialPermutations.java │ │ ├── LongPartialPermutations.java │ │ ├── PartialPermutationSupplier.java │ │ └── PartialPermutations.java │ │ ├── permutation │ │ ├── BigIntegerPermutations.java │ │ ├── LongPermutations.java │ │ ├── PermutationSupplier.java │ │ └── Permutations.java │ │ ├── powerset │ │ ├── BigIntegerPowerSet.java │ │ ├── LongPowerSet.java │ │ ├── PowerSet.java │ │ └── PowerSetSupplier.java │ │ ├── product │ │ ├── BigIntegerCartesianProduct.java │ │ ├── CartesianProduct.java │ │ ├── CartesianProductSupplier.java │ │ └── LongCartesianProduct.java │ │ ├── shared │ │ └── Unranking.java │ │ └── shuffler │ │ ├── BigIntegerShuffler.java │ │ ├── DefaultBigIntegerShuffler.java │ │ ├── DefaultLongShuffler.java │ │ ├── LongShuffler.java │ │ └── ShufflerImpl.java │ └── test │ ├── groovy │ └── org │ │ └── beryx │ │ └── streamplify │ │ ├── BigIntegerIndexedSpliteratorSpec.groovy │ │ ├── CartesianProductSpec.groovy │ │ ├── CombinationsSpec.groovy │ │ ├── DerangementsSpec.groovy │ │ ├── LongIndexedSpliteratorSpec.groovy │ │ ├── PartialPermutationsSpec.groovy │ │ ├── PermutationsSpec.groovy │ │ ├── PowerSetSpec.groovy │ │ └── ShufflerSpec.groovy │ └── resources │ └── logback.groovy └── travis-build.sh /.gitignore: -------------------------------------------------------------------------------- 1 | # directory names ending with / will be excluded from all IDEA modules (see ide.gradle) 2 | 3 | gradle-local.properties 4 | gpg/ 5 | .gradle/ 6 | build/ 7 | *.class 8 | *.log 9 | *.settings.xml 10 | 11 | # Eclipse 12 | .classpath 13 | .project 14 | .settings/ 15 | bin/ 16 | 17 | # IDEA 18 | *.iml 19 | *.ipr 20 | *.iws 21 | .idea/ 22 | out/ 23 | 24 | hs_err_pid* 25 | _ignore* 26 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | 3 | sudo: false 4 | 5 | addons: 6 | apt: 7 | packages: 8 | - oracle-java8-installer 9 | 10 | jdk: 11 | - oraclejdk8 12 | 13 | cache: 14 | directories: 15 | - $HOME/.gradle 16 | 17 | script: 18 | - ./travis-build.sh 19 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [streamplify@beryx.org](mailto:streamplify@beryx.org). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing 2 | 3 | We accept all types of contributions and we are very welcoming to first time contributors. 4 | 5 | ### Code of Conduct 6 | 7 | This project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDUCT.md). 8 | By participating, you are expected to uphold this code. 9 | Please report unacceptable behavior to [streamplify@beryx.org](mailto:streamplify@beryx.org). 10 | 11 | ### How Can I Contribute? 12 | - report bugs 13 | - suggest enhancements 14 | - improve / write documentation 15 | - answer questions 16 | - promote the project 17 | - submit new unit tests 18 | - submit new examples 19 | - fix bugs 20 | - implement new features 21 | 22 | #### up-for-grabs issues 23 | 24 | Issues labeled ![up-for-grabs](https://img.shields.io/badge/-up----for----grabs-blue.svg?logoWidth=-10) indicate tasks specifically chosen to be implemented by contributors. In most cases, these are new features and enhancements with clearly defined requirements, which makes them newcomer-friendly. 25 | 26 | Please leave a message before starting to work on a task. 27 | This way, we can mark the issue as grabbed in order to prevent that two people work on the same thing. 28 | 29 | If you claimed an issue and are no longer able to work on it, please tell us to make it available again. 30 | 31 | Advice for newcomers: Don't be afraid to grab an issue, even if you're not sure you can implement it. 32 | Try your hand at it and don't hesitate to ask for clarification and guidance. 33 | 34 | #### Code contributions 35 | If you implement a new feature, your pull request should also contain: 36 | - unit tests - we use [Spock](http://spockframework.org/) 37 | - examples - should be placed in [streamplify-examples](../master/streamplify-examples/src/main/java/org/beryx/streamplify/example) 38 | - documentation - we use [Asciidoctor](http://asciidoctor.org/) 39 | 40 | #### Working on your first Pull Request? 41 | 42 | You can learn how from this free series: [How to Contribute to an Open Source Project on GitHub](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github). 43 | 44 | 45 | ### Development Tools 46 | 47 | #### Command Line Build 48 | Streamplify is built with [Gradle](http://www.gradle.org/) and requires JDK 8 or higher. 49 | Clone the GitHub repository, `cd` into the top directory and start the build: 50 | 51 |
git clone https://github.com/beryx/streamplify.git 52 |
cd streamplify 53 |
./gradlew clean build            54 | (On Windows: gradlew clean build) 55 |
56 | 57 | #### IntelliJ Idea 58 | 59 | - make sure that the Groovy plugin is enabled 60 | - open build.gradle 61 | 62 | #### Eclipse 63 | 64 | - install the [Groovy plugin](https://github.com/groovy/groovy-eclipse/wiki); 65 | update site: http://dist.springsource.org/snapshot/GRECLIPSE/e4.6/ 66 | - install Buildship 1.0.21 or newer; 67 | update site: http://download.eclipse.org/buildship/updates/e46/releases/1.0/1.0.21.v20161010-1640/ 68 | - import the project using the _Gradle Project_ wizard 69 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | 2 | Copyright 2016 Streamplify development team 3 | 4 | This product includes software developed at The Apache Software Foundation (http://www.apache.org/). 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com) 2 | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/beryx/streamplify/blob/master/LICENSE) 3 | [![Build Status](https://img.shields.io/travis/beryx/handlebars-java-helpers/master.svg?label=Build)](https://travis-ci.org/beryx/streamplify) 4 | ## Streamplify ## 5 | 6 | 7 | The goal of this library is to provide useful Java 8 streams and to assist you in building new streams that allow efficient parallel processing. 8 | 9 | The utilities offered by Streamplify include: 10 | 11 | - combinatorics streams: permutations, combinations, Cartesian products, power sets, derangements, partial permutations. 12 | - classes that help you implement your own efficient parallel streams. 13 | 14 | **Example** 15 | 16 | The following code snippet uses a parallel permutation stream to find all solutions of the [N-Queens problem](https://en.wikipedia.org/wiki/Eight_queens_puzzle) for n = 10. 17 | ``` 18 | System.out.println(new Permutations(10) 19 | .parallelStream() 20 | .filter(perm -> { 21 | for(int i = 0; i < perm.length - 1; i++) { 22 | for(int j = i + 1; j < perm.length; j++) { 23 | if(Math.abs(perm[j] - perm[i]) == j - i) return false; 24 | } 25 | } 26 | return true; 27 | }) 28 | .map(perm -> IntStream.range(0, perm.length) 29 | .mapToObj(i -> "(" + (i + 1) + "," + (perm[i] + 1) + ")") 30 | .collect(Collectors.joining(", "))) 31 | .collect(Collectors.joining("\n"))); 32 | ``` 33 | 34 | 35 | Before starting to use the library, take a look at the **[examples](streamplify-examples/src/main/java/org/beryx/streamplify/example)**, read the **[documentation](http://streamplify.beryx.org)** and consult the **[javadoc](http://streamplify.beryx.org/releases/latest/javadoc)**. 36 | 37 | Streamplify is available in [Maven Central](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.beryx%22%20AND%20a%3A%22streamplify%22) and [JCenter](https://bintray.com/beryx/maven/streamplify). 38 | 39 | **Contribute to this project!** 40 | 41 | We accept all types of contributions and we are very welcoming to first time contributors. 42 | 43 | Read **[how to contribute](CONTRIBUTING.md)** and jump in! 44 | -------------------------------------------------------------------------------- /dist/README: -------------------------------------------------------------------------------- 1 | ======================================================================= 2 | Streamplify @streamplifyVersion@ 3 | ======================================================================= 4 | 5 | Visit the Streamplify site for the latest news and downloads: https://github.com/beryx/ 6 | -------------------------------------------------------------------------------- /dist/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /doc/docinfo.html: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /doc/getting_started.adoc: -------------------------------------------------------------------------------- 1 | [[getting_started]] 2 | = Getting Started 3 | 4 | CAUTION: You need Java 8 or newer in order to use {project-name}. 5 | 6 | {project-name} is available in Maven Central and JCenter. 7 | 8 | [subs="attributes",options="nowrap",title="Maven"] 9 | ---- 10 | <dependency> 11 | <groupId>{project-group}</groupId> 12 | <artifactId>{project-name}</artifactId> 13 | <version>{project-version}</version> 14 | </dependency> 15 | ---- 16 | 17 | [subs="attributes",options="nowrap",title="Gradle"] 18 | ---- 19 | compile '{project-group}:{project-name}:{project-version}' 20 | ---- 21 | -------------------------------------------------------------------------------- /doc/img/design.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beryx/streamplify/e4c20b713f5e45a06ccd83557e1db6b248ca6b93/doc/img/design.png -------------------------------------------------------------------------------- /doc/index.adoc: -------------------------------------------------------------------------------- 1 | = Streamplify 2 | :author: Serban Iordache 3 | :revnumber: {project-version} 4 | :toc: left 5 | :toclevels: 3 6 | :data-uri: 7 | :caption: 8 | :last-update-label!: 9 | :docinfo1: 10 | 11 | :leveloffset: +1 12 | 13 | include::introduction.adoc[] 14 | include::getting_started.adoc[] 15 | include::user_guide.adoc[] 16 | include::release_notes.adoc[] 17 | 18 | :leveloffset: -1 19 | -------------------------------------------------------------------------------- /doc/introduction.adoc: -------------------------------------------------------------------------------- 1 | [[introduction]] 2 | = Introduction 3 | 4 | The goal of this library is to provide useful Java 8 streams and to assist you in building new streams that allow efficient parallel processing. 5 | 6 | The utilities offered by Streamplify include: 7 | 8 | - combinatorics streams: permutations, combinations, Cartesian products, powers sets, derangements, partial permutations. 9 | - classes that help you implement your own efficient parallel streams. 10 | 11 | NOTE: The source code is available on https://github.com/beryx/streamplify[GitHub]. 12 | -------------------------------------------------------------------------------- /doc/release_notes.adoc: -------------------------------------------------------------------------------- 1 | [[release_notes]] 2 | = Release Notes 3 | 4 | == 1.1.0 5 | 6 | - support for https://en.wikipedia.org/wiki/Power_set[power sets]. 7 | - support for https://en.wikipedia.org/wiki/Derangement[derangements]. 8 | - support for https://en.wikipedia.org/wiki/Partial_permutation[partial permutations]. 9 | 10 | Thanks to all the contributors to this release: 11 | https://github.com/brightcoder[brightcoder], 12 | https://github.com/polmauri[polmauri] and 13 | https://github.com/johnhadfield[John Hadfield]. 14 | 15 | 16 | == 1.0.0 17 | - support for https://en.wikipedia.org/wiki/Permutation[permutations]. 18 | - support for https://en.wikipedia.org/wiki/Combination[combinations]. 19 | - support for https://en.wikipedia.org/wiki/Cartesian_product[Cartesian products]. 20 | -------------------------------------------------------------------------------- /findbugsExclude.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /ghpages/CNAME: -------------------------------------------------------------------------------- 1 | streamplify.beryx.org 2 | -------------------------------------------------------------------------------- /ghpages/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ghpages/releases/latest/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

No release yet

5 | 6 | 7 | -------------------------------------------------------------------------------- /gradle-local.template.properties: -------------------------------------------------------------------------------- 1 | signingKeyId = A0B1C2D3 2 | signingSecretKeyRingFile = C:/Beryx/gpg/beryx.gpg 3 | 4 | bintrayUser = siordache 5 | bintrayKey = a0b1c2d3e4f5a0b1c2d3e4f5a0b1c2d3e4f5a0b1 6 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | streamplifyVersionMajor = 1 2 | streamplifyVersionMinor = 2 3 | streamplifyVersionPatch = 0 4 | # streamplifyVersionLabel = rc-1 5 | streamplifyReleaseBuild = false 6 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beryx/streamplify/e4c20b713f5e45a06ccd83557e1db6b248ca6b93/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Oct 25 22:49:48 CEST 2016 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.8.1-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn ( ) { 37 | echo "$*" 38 | } 39 | 40 | die ( ) { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 165 | if [[ "$(uname)" == "Darwin" ]] && [[ "$HOME" == "$PWD" ]]; then 166 | cd "$(dirname "$0")" 167 | fi 168 | 169 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 170 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /license-header.txt: -------------------------------------------------------------------------------- 1 | Copyright 2016 the original author or authors. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'streamplify-root' 2 | 3 | String[] modules = [ 4 | 'streamplify', 5 | 'streamplify-examples', 6 | ] 7 | 8 | include modules 9 | -------------------------------------------------------------------------------- /streamplify-examples/src/main/java/org/beryx/streamplify/benchmark/DelayedBenchmark.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.benchmark; 17 | 18 | import org.beryx.streamplify.LongIndexedSpliterator; 19 | import org.beryx.streamplify.Splittable; 20 | 21 | import java.util.Iterator; 22 | import java.util.Spliterator; 23 | import java.util.Spliterators; 24 | import java.util.stream.Stream; 25 | import java.util.stream.StreamSupport; 26 | 27 | /** 28 | * This benchmark shows that in situations where the iterator's next() method is time consuming, 29 | * the {@code IteratorSpliterator} created by {@link Spliterators#spliterator(Iterator, long, int)} is not adequate for parallel processing, 30 | * and the {@link LongIndexedSpliterator} should be used instead. 31 | */ 32 | public class DelayedBenchmark { 33 | private final long count; 34 | private final long delay; 35 | 36 | public DelayedBenchmark(long count, long delay) { 37 | this.count = count; 38 | this.delay = delay; 39 | } 40 | 41 | @SuppressWarnings("unchecked") 42 | public class DelayedIdentitySpliterator extends LongIndexedSpliterator { 43 | DelayedIdentitySpliterator() { 44 | super(0, count); 45 | this.withValueSupplier(new Splittable.LongIndexed() { 46 | @Override 47 | public Long apply(long value) { 48 | busy(delay); 49 | return value; 50 | } 51 | 52 | @Override 53 | public LongIndexed split() { 54 | return this; 55 | } 56 | }); 57 | this.withAdditionalCharacteristics(DISTINCT); 58 | } 59 | } 60 | 61 | public class DelayedIdentityIterator implements Iterator { 62 | private long index = 0; 63 | 64 | @Override 65 | public boolean hasNext() { 66 | return index < count; 67 | } 68 | 69 | @Override 70 | public Long next() { 71 | busy(delay); 72 | return index++; 73 | } 74 | } 75 | 76 | private static void busy(long millis) { 77 | try { 78 | Thread.sleep(millis); 79 | } catch (InterruptedException e) { 80 | System.err.println("Interrupted"); 81 | } 82 | } 83 | 84 | public Stream getStreamplifyStream() { 85 | return new DelayedIdentitySpliterator().parallelStream(); 86 | } 87 | 88 | public Stream getIterSpliterStream() { 89 | Spliterator spliterator = Spliterators.spliterator(new DelayedIdentityIterator(), count, 90 | Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.IMMUTABLE | Spliterator.DISTINCT); 91 | return StreamSupport.stream(spliterator, true); 92 | } 93 | 94 | 95 | public void run() { 96 | System.out.println("########################################################"); 97 | System.out.println("Running DelayedBenchmark for count " + count + " with delay " + delay + " ms."); 98 | 99 | long start1 = System.currentTimeMillis(); 100 | Stream stream1 = getStreamplifyStream(); 101 | long count1 = stream1.count(); 102 | long duration1 = System.currentTimeMillis() - start1; 103 | 104 | System.out.println("duration(streamplify) = " + duration1 + " ms."); 105 | 106 | long start2 = System.currentTimeMillis(); 107 | Stream stream2 = getIterSpliterStream(); 108 | long count2 = stream2.count(); 109 | long duration2 = System.currentTimeMillis() - start2; 110 | 111 | if(count1 != count2) throw new AssertionError("count1 = " + count1 + ", count2 = " + count2); 112 | 113 | System.out.println("duration(IterSpliter) = " + duration2 + " ms."); 114 | System.out.println("--------------------------------------------------------"); 115 | } 116 | 117 | /** 118 | * Compares the performance of the implementation using {@link LongIndexedSpliterator} with 119 | * that of the {@code IteratorSpliterator} created by {@link Spliterators#spliterator(Iterator, long, int)}. 120 | *
On multicore and multiprocessor systems, the implementation based on {@link LongIndexedSpliterator} is typically faster. 121 | */ 122 | public static void main(String[] args) { 123 | new DelayedBenchmark(1000, 10).run(); 124 | new DelayedBenchmark(1000, 100).run(); 125 | new DelayedBenchmark(10000, 10).run(); 126 | new DelayedBenchmark(100, 1000).run(); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /streamplify-examples/src/main/java/org/beryx/streamplify/benchmark/FibonacciBenchmark.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.benchmark; 17 | 18 | import org.beryx.streamplify.example.Fibonacci; 19 | 20 | import java.math.BigInteger; 21 | import java.util.stream.Stream; 22 | 23 | /** 24 | * Performs parallel and sequential benchmarks on the {@link org.beryx.streamplify.example.Fibonacci} class. 25 | *
On multicore and multiprocessor systems, the parallel version is typically faster than the sequential one. 26 | *
(However, if you replace {@link org.beryx.streamplify.example.Fibonacci.Supplier#forIndex(int)} 27 | * with {@link org.beryx.streamplify.example.Fibonacci.Supplier#forIndexBinet(int)}}, the parallel version is typically slower.) 28 | */ 29 | public class FibonacciBenchmark { 30 | private static void runBenchmark(int startIndex, int count) { 31 | System.out.println("\nThe total number of bits needed to store " + count + " Fibonacci numbers, starting with the " + startIndex + "th:"); 32 | runBenchmark(startIndex, count, true); 33 | runBenchmark(startIndex, count, false); 34 | } 35 | 36 | /** 37 | * Measures the time taken to generate a stream of {@code count} Fibonacci numbers starting with {@code startIndex} and to perform a reduce operation on it. 38 | * The operation performed consists in computing the sum of the number of bits in the representation of each BigInteger element in the stream. 39 | */ 40 | private static void runBenchmark(int startIndex, int count, boolean parallel) { 41 | long start = System.currentTimeMillis(); 42 | Fibonacci fib = new Fibonacci(startIndex, count); 43 | Stream stream = parallel ? fib.parallelStream() : fib.stream(); 44 | long bitSum = stream.mapToLong(BigInteger::bitLength).reduce(0, (a, b) -> a + b); 45 | long duration = System.currentTimeMillis() - start; 46 | System.out.println(bitSum + " bits. Computed " + (parallel ? "in parallel" : "sequentially") + " in " + duration + " ms."); 47 | } 48 | 49 | public static void main(String[] args) { 50 | runBenchmark(1000, 1_000_000); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /streamplify-examples/src/main/java/org/beryx/streamplify/benchmark/IterSpliterPermutations.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.benchmark; 17 | 18 | import org.beryx.streamplify.permutation.LongPermutations; 19 | import org.beryx.streamplify.permutation.PermutationSupplier; 20 | 21 | import java.util.Iterator; 22 | import java.util.Spliterator; 23 | import java.util.Spliterators; 24 | import java.util.stream.Stream; 25 | import java.util.stream.StreamSupport; 26 | 27 | /** 28 | * This class is functionally equivalent to {@link LongPermutations}, but it doesn't use the {@link org.beryx.streamplify.LongIndexedSpliterator}. 29 | *
Instead, it uses the {@code IteratorSpliterator} created by {@link Spliterators#spliterator(Iterator, long, int)}. 30 | *
{@link NQueensBenchmark} compares the performance of this class with that of {@link LongPermutations}. 31 | */ 32 | public class IterSpliterPermutations { 33 | private final int length; 34 | private final long count; 35 | 36 | public IterSpliterPermutations(int length) { 37 | this.length = length; 38 | this.count = LongPermutations.factorial(length); 39 | } 40 | 41 | private class PermutationIterator implements Iterator { 42 | private long index = 0; 43 | private final PermutationSupplier.Long supplier = new PermutationSupplier.Long(length); 44 | 45 | @Override 46 | public boolean hasNext() { 47 | return index < count; 48 | } 49 | 50 | @Override 51 | public int[] next() { 52 | return supplier.apply(index++); 53 | } 54 | } 55 | 56 | public Stream stream() { 57 | return StreamSupport.stream(spliterator(), false); 58 | } 59 | 60 | public Stream parallelStream() { 61 | return StreamSupport.stream(spliterator(), true); 62 | } 63 | 64 | private Spliterator spliterator() { 65 | PermutationIterator permIterator = new PermutationIterator(); 66 | return Spliterators.spliterator(permIterator, count, 67 | Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.IMMUTABLE | Spliterator.DISTINCT); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /streamplify-examples/src/main/java/org/beryx/streamplify/benchmark/JacobsthalBenchmark.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.benchmark; 17 | 18 | import org.beryx.streamplify.example.Jacobsthal; 19 | 20 | import java.math.BigInteger; 21 | import java.util.stream.Stream; 22 | 23 | /** 24 | * Performs parallel and sequential benchmarks on the {@link org.beryx.streamplify.example.Jacobsthal} class. 25 | *
On multicore and multiprocessor systems, the parallel version is typically faster than the sequential one. 26 | */ 27 | public class JacobsthalBenchmark { 28 | private static void runBenchmark(int startIndex, int count) { 29 | System.out.println("\nThe total number of bits needed to store " + count + " Jacobsthal numbers, starting with the " + startIndex + "th:"); 30 | run(startIndex, count, true); 31 | run(startIndex, count, false); 32 | } 33 | 34 | /** 35 | * Measures the time taken to generate a stream of {@code count} Jacobsthal numbers starting with {@code startIndex} and to perform a reduce operation on it. 36 | * The operation performed consists in computing the sum of the number of bits in the representation of each BigInteger element in the stream. 37 | */ 38 | private static void run(int startIndex, int count, boolean parallel) { 39 | long start = System.currentTimeMillis(); 40 | Jacobsthal jacobsthal = new Jacobsthal(startIndex, count); 41 | Stream stream = parallel ? jacobsthal.parallelStream() : jacobsthal.stream(); 42 | long bitSum = stream.mapToLong(BigInteger::bitLength).reduce(0, (a, b) -> a + b); 43 | long duration = System.currentTimeMillis() - start; 44 | System.out.println(bitSum + " bits. Computed " + (parallel ? "in parallel" : "sequentially") + " in " + duration + " ms."); 45 | } 46 | 47 | public static void main(String[] args) { 48 | runBenchmark(100_000, 1_000_000); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /streamplify-examples/src/main/java/org/beryx/streamplify/benchmark/NQueensBenchmark.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.benchmark; 17 | 18 | import org.beryx.streamplify.permutation.LongPermutations; 19 | 20 | import java.util.Iterator; 21 | import java.util.Spliterators; 22 | import java.util.stream.Stream; 23 | 24 | /** 25 | * Compares the performance of {@link LongPermutations} with that of {@link IterSpliterPermutations}, 26 | * which is a functionally equivalent class, but uses the {@code IteratorSpliterator} created by {@link Spliterators#spliterator(Iterator, long, int)}. 27 | *
The benchmark applies a filter for selecting those permutations that represent solutions of the N-Queens problem. 28 | *
On multicore and multiprocessor systems, the parallel version using {@link LongPermutations} is typically faster than the one using {@link IterSpliterPermutations}. 29 | *
When using sequential streams, the performance of {@link LongPermutations} is typically comparable to that of {@link IterSpliterPermutations}. 30 | */ 31 | public class NQueensBenchmark { 32 | private final int length; 33 | private final boolean parallel; 34 | 35 | public NQueensBenchmark(int length, boolean parallel) { 36 | this.length = length; 37 | this.parallel = parallel; 38 | } 39 | 40 | public Stream getStreamplifyStream() { 41 | LongPermutations longPermutations = new LongPermutations(length); 42 | Stream stream = parallel ? longPermutations.parallelStream() : longPermutations.stream(); 43 | return stream.filter(perm -> isNQueensSolution(perm)); 44 | } 45 | 46 | public Stream getIterSpliterStream() { 47 | IterSpliterPermutations iterSpliterPermutations = new IterSpliterPermutations(length); 48 | Stream stream = parallel ? iterSpliterPermutations.parallelStream() : iterSpliterPermutations.stream(); 49 | stream = stream.filter(perm -> isNQueensSolution(perm)); 50 | if(parallel) stream.parallel(); 51 | return stream; 52 | } 53 | 54 | public void run() { 55 | System.out.println("########################################################"); 56 | System.out.println("Solving NQueens for size " + length + " using " + (parallel ? "parallel" : "sequential") + " streams."); 57 | 58 | long start1 = System.currentTimeMillis(); 59 | Stream stream1 = getStreamplifyStream(); 60 | long count1 = stream1.count(); 61 | long duration1 = System.currentTimeMillis() - start1; 62 | 63 | System.out.println("count: " + count1); 64 | System.out.println("duration(streamplify) = " + duration1); 65 | 66 | long start2 = System.currentTimeMillis(); 67 | Stream stream2 = getIterSpliterStream(); 68 | long count2 = stream2.count(); 69 | long duration2 = System.currentTimeMillis() - start2; 70 | 71 | if(count1 != count2) throw new AssertionError("count1 = " + count1 + ", count2 = " + count2); 72 | 73 | System.out.println("duration(IterSpliter) = " + duration2); 74 | System.out.println("--------------------------------------------------------"); 75 | } 76 | 77 | private static boolean isNQueensSolution(int[] perm) { 78 | int size = perm.length; 79 | for(int i = 0; i < size - 1; i++) { 80 | for(int j = i + 1; j < size; j++) { 81 | if(Math.abs(perm[j] - perm[i]) == j - i) return false; 82 | } 83 | } 84 | return true; 85 | } 86 | 87 | public static void main(String[] args) { 88 | new NQueensBenchmark(11, true).run(); 89 | new NQueensBenchmark(11, false).run(); 90 | new NQueensBenchmark(12, true).run(); 91 | new NQueensBenchmark(12, false).run(); 92 | new NQueensBenchmark(13, true).run(); 93 | new NQueensBenchmark(13, false).run(); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /streamplify-examples/src/main/java/org/beryx/streamplify/example/Arrangements.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.example; 17 | 18 | import org.beryx.streamplify.combination.Combinations; 19 | import org.beryx.streamplify.permutation.Permutations; 20 | 21 | import java.util.Arrays; 22 | import java.util.stream.Collectors; 23 | import java.util.stream.Stream; 24 | 25 | /** 26 | * Generates k-permutations of n. 27 | *
This implementation makes use of the {@link Combinations} and {@link Permutations} classes. 28 | * It generates all k-combinations of n, and for each combination generates all permutations of its k elements. 29 | *
This is a simple and easy to understand solution. 30 | * However, for improved performance, you may provide implementations based on the 31 | * {@link org.beryx.streamplify.LongIndexedSpliterator} and {@link org.beryx.streamplify.BigIntegerIndexedSpliterator}. 32 | */ 33 | public class Arrangements { 34 | private final int n; 35 | private final int k; 36 | 37 | public Arrangements(int n, int k) { 38 | this.n = n; 39 | this.k = k; 40 | } 41 | 42 | public Stream stream() { 43 | return new Combinations(n, k) 44 | .stream() 45 | .flatMap(comb -> new Permutations(k) 46 | .stream() 47 | .map(perm -> Arrays.stream(perm).map(p -> comb[p]).toArray())); 48 | } 49 | 50 | public Stream parallelStream() { 51 | return new Combinations(n, k) 52 | .parallelStream() 53 | .flatMap(comb -> new Permutations(k) 54 | .parallelStream() 55 | .map(perm -> Arrays.stream(perm).map(p -> comb[p]).toArray())); 56 | } 57 | 58 | /** 59 | * Solves the following problem:
60 |      * Alice, Bob, Chloe, David, and Emma take part in a competition.
61 |      * List all possible outcomes for the top 3 ranking.
62 | */ 63 | public static void main(String[] args) { 64 | String[] names = {"Alice", "Bob", "Chloe", "David", "Emma"}; 65 | System.out.println(new Arrangements(5, 3) 66 | .stream() 67 | .map(arr -> Arrays.stream(arr).mapToObj(i -> names[i]).collect(Collectors.toList()).toString()) 68 | .collect(Collectors.joining("\n"))); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /streamplify-examples/src/main/java/org/beryx/streamplify/example/CardDeck.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.example; 17 | 18 | import org.beryx.streamplify.permutation.Permutations; 19 | 20 | import java.util.Arrays; 21 | import java.util.stream.Collectors; 22 | import java.util.stream.Stream; 23 | 24 | /** 25 | * Generates random arrangements of playing cards in a standard 52-card deck. 26 | *
Illustrates the use of {@link Permutations}. 27 | */ 28 | public class CardDeck { 29 | private static final String[] RANKS = {"Ace", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King"}; 30 | private static final int RANKS_COUNT = RANKS.length; 31 | private static final String[] SUITS = {"Clubs", "Diamonds", "Hearts", "Spades"}; 32 | private static final int LENGTH = RANKS_COUNT * SUITS.length; 33 | 34 | public Stream stream() { 35 | return new Permutations(LENGTH).shuffle().stream(); 36 | } 37 | 38 | public int[] getShuffledCards() { 39 | return stream().findFirst().get(); 40 | } 41 | 42 | public static String toString(int val) { 43 | String rank = RANKS[val % RANKS_COUNT]; 44 | String suit = SUITS[val / RANKS_COUNT]; 45 | return rank + " of " + suit; 46 | } 47 | 48 | public static String toString(int[] arrangement) { 49 | return Arrays.stream(arrangement).mapToObj(CardDeck::toString).collect(Collectors.joining("\n")); 50 | } 51 | 52 | public static void main(String[] args) { 53 | System.out.println(toString(new CardDeck().getShuffledCards())); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /streamplify-examples/src/main/java/org/beryx/streamplify/example/Diet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.example; 17 | 18 | import org.beryx.streamplify.combination.Combinations; 19 | 20 | import java.util.Arrays; 21 | import java.util.stream.Collectors; 22 | import java.util.stream.Stream; 23 | 24 | /** 25 | * Illustrates the use of {@link Combinations} by solving the following problem: 26 | *
Each morning, you must eat 3 different fruits. 27 | * You can choose from: apple, banana, mango, orange, peach. 28 | * Print all your options. 29 | */ 30 | public class Diet { 31 | private static final String[] FRUITS = {"apple", "banana", "mango", "orange", "peach"}; 32 | 33 | private final int fruitCount; 34 | 35 | public Diet(int fruitCount) { 36 | this.fruitCount = fruitCount; 37 | } 38 | 39 | public Stream stream() { 40 | return new Combinations(FRUITS.length, fruitCount).stream(); 41 | } 42 | 43 | public static String toString(int[] combination) { 44 | return Arrays.stream(combination).mapToObj(i -> FRUITS[i]).collect(Collectors.joining(", ")); 45 | } 46 | 47 | public static void main(String[] args) { 48 | System.out.println(new Diet(3).stream().map(Diet::toString).collect(Collectors.joining("\n"))); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /streamplify-examples/src/main/java/org/beryx/streamplify/example/Fibonacci.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.example; 17 | 18 | import org.beryx.streamplify.LongIndexedSpliterator; 19 | import org.beryx.streamplify.Splittable; 20 | 21 | import java.math.BigDecimal; 22 | import java.math.BigInteger; 23 | import java.util.Spliterator; 24 | import java.util.stream.Collectors; 25 | 26 | /** 27 | * Provides Fibonacci numbers in a given interval of indices as a stream of BigInteger. 28 | *
The implementation illustrates the use of a {@link LongIndexedSpliterator} and the construction of its value supplier. 29 | *
The {@link Supplier#apply(long)} method computes the Fibonacci number with the index given by its argument as follows:
    30 | *
  • if the requested index is the successor of the previously computed index, it uses the recurrence formula: F(n) = F(n-1) + F(n-2)
  • 31 | *
  • otherwise, it uses the formula: 32 | *
    F(2*k) = F(k) * (2 * F(k+1) - F(k)) 33 | *
    F(2*k+1) = F(k+1)^2 + F(k)^2 34 | *
  • 35 | *
36 | * It is also possible to compute the Fibonacci number with a given index by using the closed-form solution given by Binet's formula (see {@link Supplier#forIndexBinet(int)}). 37 | * However, this involves time consuming BigDecimal computations, leading to situations where using a parallel stream takes longer than using a sequential one. 38 | * (See {@link Jacobsthal} for an example of a series with computationally cheap closed-form solutions.) 39 | */ 40 | @SuppressWarnings("unchecked") 41 | public class Fibonacci extends LongIndexedSpliterator { 42 | public Fibonacci(int fromValue, int count) { 43 | super(fromValue, fromValue + count); 44 | if(fromValue < 0 || count < 0 || fromValue > Integer.MAX_VALUE - count) { 45 | throw new IllegalArgumentException("fromValue: " + fromValue + ", count: " + count); 46 | } 47 | this.withValueSupplier(new Supplier()); 48 | this.withAdditionalCharacteristics(Spliterator.DISTINCT); 49 | } 50 | 51 | public static class Supplier implements Splittable.LongIndexed { 52 | long currentIndex = -2; 53 | BigInteger lastVal; 54 | BigInteger beforeLastVal; 55 | 56 | @Override 57 | public BigInteger apply(long index) { 58 | if(index < 0 || index > Integer.MAX_VALUE) throw new AssertionError("index: " + index); 59 | if(index == 0) return BigInteger.ZERO; 60 | boolean useNext = (index == currentIndex + 1); 61 | currentIndex = index; 62 | if(useNext) { 63 | BigInteger newVal = lastVal.add(beforeLastVal); 64 | beforeLastVal = lastVal; 65 | lastVal = newVal; 66 | } else { 67 | beforeLastVal = forIndex((int)index - 1); 68 | lastVal = forIndex((int)index); 69 | } 70 | return lastVal; 71 | } 72 | 73 | /** 74 | * Computes the Fibonacci number with the given index using the formula: 75 | *
F(2*k) = F(k) * (2 * F(k+1) − F(k)) 76 | *
F(2*k+1) = F(k+1)^2 + F(k)^2 77 | */ 78 | public static BigInteger forIndex(int index) { 79 | if(index == 0) return BigInteger.ZERO; 80 | if(index == 1 || index == 2) return BigInteger.ONE; 81 | if(index % 2 == 0) { 82 | int k = index / 2; 83 | BigInteger fk = forIndex(k); 84 | BigInteger fk1 = forIndex(k + 1); 85 | return fk.multiply(fk1.shiftLeft(1).subtract(fk)); 86 | } else { 87 | int k = (index - 1) / 2; 88 | BigInteger fk = forIndex(k); 89 | BigInteger fk1 = forIndex(k + 1); 90 | return fk.multiply(fk).add(fk1.multiply(fk1)); 91 | } 92 | } 93 | 94 | private static final BigDecimal SQRT_5 = new BigDecimal(Math.sqrt(5)); 95 | private static final BigDecimal PHI = new BigDecimal((1 + Math.sqrt(5)) / 2); 96 | private static final BigDecimal PSI = new BigDecimal((1 - Math.sqrt(5)) / 2); 97 | /** 98 | * Another possible implementation of the {@link #forIndex(int)} method, using Binet's formula. 99 | * The code is shorter, but involves time consuming BigDecimal computations. 100 | * Using this method instead of the original forIndex will lead to situations where running in parallel takes longer than running sequentially. 101 | */ 102 | public static BigInteger forIndexBinet(int index) { 103 | return PHI.pow(index).subtract(PSI.pow(index)).divide(SQRT_5).toBigInteger(); 104 | } 105 | 106 | @Override 107 | public LongIndexed split() { 108 | return new Supplier(); 109 | } 110 | } 111 | 112 | /** 113 | * Prints some Fibonacci numbers. 114 | */ 115 | public static void main(String[] args) { 116 | System.out.println("20 Fibonacci numbers (starting with index 10):\n" + new Fibonacci(10, 20).stream().collect(Collectors.toList())); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /streamplify-examples/src/main/java/org/beryx/streamplify/example/Friends.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.example; 17 | 18 | import org.beryx.streamplify.powerset.PowerSet; 19 | 20 | /** 21 | * Example to demonstrate the use of {@link PowerSet} stream. 22 | */ 23 | public class Friends { 24 | 25 | /** 26 | * Print number of ways 4 friends (Alice, Bob, Chloe, David ) can go on for a weekend trip. 27 | */ 28 | public static void main(String[] args) { 29 | String[] friends = new String[]{"Alice", "Bob", "Chloe", "David"}; 30 | new PowerSet(4).stream().forEach(set -> { 31 | for (int setElementIndex : set) { 32 | System.out.print(friends[setElementIndex] + " "); 33 | } 34 | System.out.println(); 35 | }); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /streamplify-examples/src/main/java/org/beryx/streamplify/example/Hats.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.example; 17 | 18 | import java.util.Arrays; 19 | import java.util.stream.Collectors; 20 | 21 | import org.beryx.streamplify.derangement.Derangements; 22 | 23 | /** 24 | * Generates derangements. 25 | *
This implementation makes use of the {@link Derangements} class. 26 | */ 27 | public class Hats { 28 | /** 29 | * Solves the following problem:
30 |      * Alice, Bob, Chloe, David, and Emma have one hat each with their name on it.
31 |      * List all possible ways of assigning one hat to each person so that no one
32 |      * gets the hat that has their own name.
33 | */ 34 | public static void main(String[] args) { 35 | String[] names = {"Alice", "Bob", "Chloe", "David", "Emma"}; 36 | System.out.println("Original sequence:"); 37 | System.out.println(Arrays.toString(names)); 38 | System.out.println("All possible derangements:"); 39 | System.out.println(new Derangements(5) 40 | .stream() 41 | .map(arr -> Arrays.stream(arr).mapToObj(i -> names[i]) 42 | .collect(Collectors.toList()).toString()) 43 | .collect(Collectors.joining("\n"))); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /streamplify-examples/src/main/java/org/beryx/streamplify/example/Jacobsthal.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.example; 17 | 18 | import org.beryx.streamplify.LongIndexedSpliterator; 19 | import org.beryx.streamplify.Splittable; 20 | 21 | import java.math.BigInteger; 22 | import java.util.Spliterator; 23 | import java.util.stream.Collectors; 24 | 25 | /** 26 | * Provides Jacobsthal numbers in a given interval of indices as a stream of BigInteger. 27 | *
The implementation illustrates the use of a {@link LongIndexedSpliterator} and the construction of its value supplier. 28 | *
The {@link Supplier#apply(long)} method computes the Jacobsthal number with the index given by its argument as follows:
    29 | *
  • if the requested index is the successor of the previously computed index, it uses the recurrence formula: J(n) = J(n-1) + 2 * J(n-2)
  • 30 | *
  • otherwise, it uses the closed-form solution: J(n) = (2^n - (-1)^n) / 3
  • 31 | *
32 | * (Note that the closed-form solution is computationally cheap. 33 | * See {@link Fibonacci} for an example of a series where the closed-form solution involves time consuming computations, thus prohibiting its use.) 34 | */ 35 | @SuppressWarnings("unchecked") 36 | public class Jacobsthal extends LongIndexedSpliterator { 37 | public Jacobsthal(int fromValue, int count) { 38 | super(fromValue, fromValue + count); 39 | if(fromValue < 0 || count < 0 || fromValue > Integer.MAX_VALUE - count) { 40 | throw new IllegalArgumentException("fromValue: " + fromValue + ", count: " + count); 41 | } 42 | this.withValueSupplier(new Supplier()); 43 | this.withAdditionalCharacteristics(Spliterator.DISTINCT); 44 | } 45 | 46 | private static class Supplier implements Splittable.LongIndexed { 47 | 48 | long currentIndex = -2; 49 | BigInteger lastVal; 50 | BigInteger beforeLastVal; 51 | 52 | @Override 53 | public BigInteger apply(long index) { 54 | if(index < 0 || index > Integer.MAX_VALUE) throw new AssertionError("index: " + index); 55 | if(index == 0) return BigInteger.ZERO; 56 | boolean useNext = (index == currentIndex + 1); 57 | currentIndex = index; 58 | if(useNext) { 59 | BigInteger newVal = lastVal.add(beforeLastVal.shiftLeft(1)); 60 | beforeLastVal = lastVal; 61 | lastVal = newVal; 62 | } else { 63 | beforeLastVal = forIndex((int)index - 1); 64 | lastVal = forIndex((int)index); 65 | } 66 | return lastVal; 67 | } 68 | 69 | /** Computes the Jacobsthal number with the given index using the closed-form equation: J(n) = (2^n - (-1)^n) / 3 */ 70 | private static BigInteger forIndex(int n) { 71 | if(n == 0) return BigInteger.ZERO; 72 | BigInteger val = BigInteger.ONE.shiftLeft(n); 73 | if(n % 2 == 0) { 74 | val = val.subtract(BigInteger.ONE); 75 | } else { 76 | val = val.add(BigInteger.ONE); 77 | } 78 | return val.divide(BigInteger.valueOf(3)); 79 | } 80 | 81 | @Override 82 | public LongIndexed split() { 83 | return new Supplier(); 84 | } 85 | } 86 | 87 | /** 88 | * Prints some Jacobsthal numbers. 89 | */ 90 | public static void main(String[] args) { 91 | System.out.println("20 Jacobsthal numbers (starting with index 10):\n" + new Jacobsthal(10, 20).stream().collect(Collectors.toList())); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /streamplify-examples/src/main/java/org/beryx/streamplify/example/NQueens.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.example; 17 | 18 | import org.beryx.streamplify.permutation.Permutations; 19 | 20 | import java.util.stream.Collectors; 21 | import java.util.stream.Stream; 22 | 23 | /** 24 | * A brute force solver for the N-Queens problem. 25 | *
Illustrates the use of {@link Permutations}. 26 | */ 27 | public class NQueens { 28 | private final int length; 29 | 30 | public NQueens(int length) { 31 | this.length = length; 32 | } 33 | 34 | public Stream stream() { 35 | return new Permutations(length).stream().filter(NQueens::isNQueensSolution); 36 | } 37 | 38 | public Stream parallelStream() { 39 | return new Permutations(length).parallelStream().filter(NQueens::isNQueensSolution); 40 | } 41 | 42 | public static boolean isNQueensSolution(int[] perm) { 43 | int size = perm.length; 44 | for(int i = 0; i < size - 1; i++) { 45 | for(int j = i + 1; j < size; j++) { 46 | if(Math.abs(perm[j] - perm[i]) == j - i) return false; 47 | } 48 | } 49 | return true; 50 | } 51 | 52 | /** 53 | * @return a representation of the solution in table format. Example: 54 | *
 55 |      * 
|---|---|---|---|---|---| 56 | *
| | * | | | | | 57 | *
|---|---|---|---|---|---| 58 | *
| | | | * | | | 59 | *
|---|---|---|---|---|---| 60 | *
| | | | | | * | 61 | *
|---|---|---|---|---|---| 62 | *
| * | | | | | | 63 | *
|---|---|---|---|---|---| 64 | *
| | | * | | | | 65 | *
|---|---|---|---|---|---| 66 | *
| | | | | * | | 67 | *
|---|---|---|---|---|---| 68 | *
69 | */ 70 | public static String toString(int[] solution) { 71 | StringBuilder sb = new StringBuilder(); 72 | int len = solution.length; 73 | for(int i = 0; i < len; i++) { 74 | appendLine(sb, len, -1); 75 | appendLine(sb, len, solution[i]); 76 | } 77 | appendLine(sb, len, -1); 78 | sb.append('\n'); 79 | return sb.toString(); 80 | } 81 | 82 | private static void appendLine(StringBuilder sb, int len, int queenPos) { 83 | char fill = (queenPos < 0) ? '-' : ' '; 84 | sb.append('|'); 85 | for(int k = 0; k < len; k++) { 86 | char ch = (queenPos < 0) ? '-' : (queenPos == k ? '*' : ' '); 87 | sb.append(fill).append(ch).append(fill).append('|'); 88 | } 89 | sb.append('\n'); 90 | } 91 | 92 | /** 93 | * Prints at most 10 solutions of the N-Queens problem with size 12. 94 | */ 95 | public static void main(String[] args) { 96 | System.out.println("Solutions:\n" 97 | + new NQueens(12) 98 | .parallelStream() 99 | .limit(10) 100 | .map(NQueens::toString) 101 | .collect(Collectors.joining("\n\n"))); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /streamplify-examples/src/main/java/org/beryx/streamplify/example/RandomPoetry.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.example; 17 | 18 | import org.beryx.streamplify.product.CartesianProduct; 19 | 20 | import java.util.ArrayList; 21 | import java.util.List; 22 | import java.util.stream.Collectors; 23 | 24 | /** 25 | * Generates poems by randomly selecting words from some lists of words. 26 | *
Illustrates the use of {@link CartesianProduct}. 27 | */ 28 | public class RandomPoetry { 29 | private final List wordList = new ArrayList<>(); 30 | 31 | public RandomPoetry withOneOf(String... words) { 32 | wordList.add(words); 33 | return this; 34 | } 35 | 36 | public String generate(int lineCount) { 37 | int[] dimensions = wordList.stream().mapToInt(lst -> lst.length).toArray(); 38 | return new CartesianProduct(dimensions) 39 | .shuffle() 40 | .stream() 41 | .limit(lineCount) 42 | .map(seq -> { 43 | StringBuilder sb = new StringBuilder(); 44 | for (int i = 0; i < seq.length; i++) { 45 | sb.append(wordList.get(i)[seq[i]]).append(' '); 46 | } 47 | return sb.toString(); 48 | }) 49 | .collect(Collectors.joining("\n")); 50 | } 51 | 52 | /** 53 | * Generates a random poem. Example output: 54 | *
55 |      * One eagle cannot kill the light
56 |      * One girl wants to leave this fight
57 |      * The woman cannot break this site
58 |      * The eagle wants to leave the night
59 |      * 
60 | * @param args 61 | */ 62 | public static void main(String[] args) { 63 | System.out.println(new RandomPoetry() 64 | .withOneOf("The", "One", "A") 65 | .withOneOf("cat", "dog", "eagle", "man", "woman", "child", "girl", "boy") 66 | .withOneOf("can", "cannot", "hopes to", "fears to", "wants to") 67 | .withOneOf("break", "leave", "kill", "get") 68 | .withOneOf("the", "this", "that") 69 | .withOneOf("night", "light", "fight", "knight", "byte", "height", "kite", "site") 70 | .generate(4)); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /streamplify-examples/src/main/java/org/beryx/streamplify/example/TSP.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.example; 17 | 18 | import javafx.geometry.Point2D; 19 | import org.beryx.streamplify.permutation.Permutations; 20 | 21 | import java.util.Arrays; 22 | import java.util.Random; 23 | import java.util.stream.Collectors; 24 | 25 | /** 26 | * A brute force solver for the Travelling salesman problem. 27 | *
Illustrates the use of {@link Permutations}. 28 | */ 29 | public class TSP { 30 | private final Point2D[] locations; 31 | private final double[][] distances; 32 | 33 | private class Solution { 34 | final int[] route; 35 | final double routeLength; 36 | 37 | Solution(int[] route) { 38 | this.route = route; 39 | int len = route.length; 40 | double d = distances[len-1][0]; 41 | for(int i = 0; i < len-1; i++) { 42 | d += distances[i][i+1]; 43 | } 44 | this.routeLength = d; 45 | } 46 | 47 | @Override 48 | public String toString() { 49 | return "Route of length " + routeLength + ": " + 50 | Arrays.stream(route) 51 | .mapToObj(i -> "(" + locations[i].getX() + "," + locations[i].getY() + ")") 52 | .collect(Collectors.joining(" -> ")); 53 | 54 | } 55 | } 56 | 57 | public TSP(Point2D... locations) { 58 | this.locations = locations; 59 | int len = locations.length; 60 | this.distances = new double[len][len]; 61 | for(int i = 0; i < len - 1; i++) { 62 | for(int j = i + 1; j < len; j++) { 63 | distances[i][j] = distances[j][i] = locations[i].distance(locations[j]); 64 | } 65 | } 66 | } 67 | 68 | public static TSP ofRandomLocations(int length) { 69 | Random rnd = new Random(); 70 | Point2D[] locations = new Point2D[length]; 71 | for(int i = 0; i < length; i++) { 72 | locations[i] = new Point2D(rnd.nextInt(100), rnd.nextInt(100)); 73 | } 74 | return new TSP(locations); 75 | } 76 | 77 | public Solution solve() { 78 | return new Permutations(locations.length) 79 | .parallelStream() 80 | .map(route -> new Solution(route)) 81 | .min((sol1, sol2) -> Double.compare(sol1.routeLength, sol2.routeLength)) 82 | .get(); 83 | } 84 | 85 | public static void main(String[] args) { 86 | System.out.println(TSP.ofRandomLocations(10).solve()); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /streamplify-examples/src/main/java/org/beryx/streamplify/example/Vacation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.example; 17 | 18 | import org.beryx.streamplify.partperm.PartialPermutationSupplier; 19 | import org.beryx.streamplify.partperm.PartialPermutations; 20 | 21 | import java.util.Arrays; 22 | import java.util.stream.Collectors; 23 | import java.util.stream.IntStream; 24 | 25 | /** 26 | * Illustrates the use of {@link PartialPermutations} by solving the following problem:
27 |  * You have an activity you want to do for each day of your vacation
28 |  * but on any day you may instead choose to explore.
29 |  * Print all possible itineraries for your vacation.
30 | */ 31 | public class Vacation { 32 | 33 | public static void main(String[] args) { 34 | String[] thingsToDoOnVacation = {"Hiking", "Museum"}; 35 | String thingToDoInstead = "Explore"; 36 | 37 | System.out.print("Things I want to do on vacation: "); 38 | printFormattedString(Arrays.toString(thingsToDoOnVacation), ", "); 39 | System.out.println("But instead I might " + thingToDoInstead + "\n"); 40 | System.out.println("All possible itineraries:\n"); 41 | 42 | System.out.println(IntStream.range(1, thingsToDoOnVacation.length + 1) 43 | .mapToObj(i -> "-Day " + i + "-") 44 | .collect(Collectors.joining("\t"))); 45 | 46 | printFormattedString(new PartialPermutations(thingsToDoOnVacation.length) 47 | .stream() 48 | .map(arr -> Arrays.stream(arr).mapToObj(i -> i == PartialPermutationSupplier.HOLE ? thingToDoInstead : thingsToDoOnVacation[i]) 49 | .collect(Collectors.toList()).toString()) 50 | .collect(Collectors.joining("\n")), "\t"); 51 | } 52 | 53 | private static void printFormattedString(String output, String delimiter) { 54 | System.out.println(output.replaceAll(",? ", delimiter).replaceAll("]|\\[", "")); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /streamplify-examples/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 19 | 20 | 21 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /streamplify/src/main/java/org/beryx/streamplify/BigIntegerIndexedSpliterator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify; 17 | 18 | import org.beryx.streamplify.permutation.LongPermutations; 19 | import org.beryx.streamplify.shuffler.BigIntegerShuffler; 20 | import org.beryx.streamplify.shuffler.DefaultBigIntegerShuffler; 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | 24 | import java.math.BigInteger; 25 | import java.util.Random; 26 | import java.util.Spliterator; 27 | import java.util.function.Consumer; 28 | import java.util.stream.Stream; 29 | import java.util.stream.StreamSupport; 30 | 31 | /** 32 | * An indexed-spliterator that uses a BigInteger index. 33 | */ 34 | public class BigIntegerIndexedSpliterator> implements Spliterator, Streamable { 35 | private static final Logger logger = LoggerFactory.getLogger(LongPermutations.class); 36 | 37 | private Splittable.BigIntegerIndexed valueSupplier; 38 | private BigInteger index; 39 | private final BigInteger fence; 40 | int characteristics = Spliterator.IMMUTABLE; 41 | private BigIntegerShuffler shuffler = BigIntegerShuffler.IDENTITY; 42 | 43 | protected BigIntegerIndexedSpliterator(BigInteger origin, BigInteger fence) { 44 | logger.trace("BigIntegerIndexedSpliterator({}, {})", origin, fence); 45 | if(origin.compareTo(BigInteger.ZERO) < 0 || fence.compareTo(origin) < 0) throw new IllegalArgumentException("origin: " + origin + ", fence: " + fence); 46 | this.index = origin; 47 | this.fence = fence; 48 | } 49 | 50 | @SuppressWarnings("unchecked") 51 | public final S withAdditionalCharacteristics(int additionalCharacteristics) { 52 | this.characteristics |= additionalCharacteristics; 53 | return (S)this; 54 | } 55 | 56 | /** 57 | * Configures the shuffler of this source. 58 | * Unless you provide your own {@link BigIntegerShuffler} implementation, you should use {@link #shuffle()} or {@link #shuffle(Random)} instead of this method. 59 | * @return this instance 60 | */ 61 | @SuppressWarnings("unchecked") 62 | public final S withShuffler(BigIntegerShuffler shuffler) { 63 | this.shuffler = shuffler; 64 | return (S)this; 65 | } 66 | 67 | /** 68 | * Configures the value supplier of this source. 69 | * @return this instance 70 | */ 71 | @SuppressWarnings("unchecked") 72 | public final S withValueSupplier(Splittable.BigIntegerIndexed valueSupplier) { 73 | this.valueSupplier = valueSupplier; 74 | return (S)this; 75 | } 76 | 77 | protected BigInteger getIndex() { 78 | return index; 79 | } 80 | 81 | protected BigInteger getFence() { 82 | return fence; 83 | } 84 | 85 | @Override 86 | public Stream stream() { 87 | return StreamSupport.stream(this, false); 88 | } 89 | 90 | @Override 91 | public Stream parallelStream() { 92 | return StreamSupport.stream(this, true); 93 | } 94 | 95 | @Override 96 | public long count() { 97 | BigInteger size = bigCount(); 98 | if(size.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) <= 0) { 99 | return size.longValueExact(); 100 | } 101 | return -1; 102 | } 103 | 104 | @Override 105 | public BigInteger bigCount() { 106 | return fence.subtract(index); 107 | } 108 | 109 | @SuppressWarnings("unchecked") 110 | @Override 111 | public S skip(long n) { 112 | return skip(BigInteger.valueOf(n)); 113 | } 114 | 115 | @SuppressWarnings("unchecked") 116 | @Override 117 | public S skip(BigInteger n) { 118 | if(n.compareTo(BigInteger.ZERO) < 0) throw new IllegalArgumentException("skip(" + n + ")"); 119 | BigInteger targetIndex = index.add(n); 120 | index = (targetIndex.compareTo(fence) >= 0) ? fence : targetIndex; 121 | return (S)this; 122 | } 123 | 124 | @Override 125 | public long estimateSize() { 126 | long size = count(); 127 | return size < 0 ? Long.MAX_VALUE : size; 128 | } 129 | 130 | @Override 131 | public int characteristics() { 132 | return characteristics; 133 | } 134 | 135 | @Override 136 | public boolean tryAdvance(Consumer action) { 137 | if (action == null) throw new NullPointerException(); 138 | if (index.compareTo(BigInteger.ZERO) >= 0 && index.compareTo(fence) < 0) { 139 | BigInteger shuffledIndex = shuffler.getShuffledIndex(index); 140 | T val = valueSupplier.apply(shuffledIndex); 141 | index = index.add(BigInteger.ONE); 142 | action.accept(val); 143 | return true; 144 | } 145 | return false; 146 | } 147 | 148 | @Override 149 | public Spliterator trySplit() { 150 | BigInteger mid = index.add(fence).divide(BigInteger.valueOf(2)); 151 | if(index.compareTo(mid) >= 0) return null; 152 | S spliterator = (S)new BigIntegerIndexedSpliterator(index, mid) 153 | .withAdditionalCharacteristics(characteristics) 154 | .withValueSupplier(valueSupplier.split()) 155 | .withShuffler(shuffler); 156 | index = mid; 157 | return spliterator; 158 | } 159 | 160 | @Override 161 | public void forEachRemaining(Consumer action) { 162 | if (action == null) throw new NullPointerException(); 163 | if(index.compareTo(BigInteger.ZERO) >= 0 && index.compareTo(fence) < 0) { 164 | for(BigInteger i = index; i.compareTo(fence) < 0; i = i.add(BigInteger.ONE)) { 165 | BigInteger shuffledIndex = shuffler.getShuffledIndex(i); 166 | T val = valueSupplier.apply(shuffledIndex); 167 | action.accept(val); 168 | } 169 | index = fence; 170 | } 171 | } 172 | 173 | @SuppressWarnings("unchecked") 174 | @Override 175 | public S shuffle(Random rnd) { 176 | shuffler = new DefaultBigIntegerShuffler(fence, rnd); 177 | return (S)this; 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /streamplify/src/main/java/org/beryx/streamplify/IntArraySupplier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify; 17 | 18 | /** 19 | * This interface acts as a trait that helps implementing the valueSupplier requested by indexed-spliterators 20 | * (such as {@link LongIndexedSpliterator} or {@link BigIntegerIndexedSpliterator}) with the type parameter {@code int[]}. 21 | *
There is an implicit assumption that the implementing class uses an index (or some similar information) in order to decide 22 | * whether the value to be supplied can be computed based on the previous value or based on the index. 23 | */ 24 | public interface IntArraySupplier { 25 | /** @return the current sequence provided by this value supplier */ 26 | int[] getCurrentSequence(); 27 | 28 | /** 29 | * Computes the value to be supplied next, using the currently supplied value. 30 | * The next call of {@link #getCurrentSequence()} should return this newly computed value. 31 | */ 32 | void computeNext(); 33 | 34 | /** 35 | * @return the next value to be supplied. 36 | * It is assumed that the next value cannot be obtained using the current one, 37 | * but it has to be computed based on an index (or some similar information) handled by the implementing class. 38 | */ 39 | int[] unrank(); 40 | 41 | /** 42 | * Retrieves the next value to be supplied. 43 | * Postcondition: a call to {@link #getCurrentSequence()} will return an equal (but not identical) value. 44 | * @param useNext true, if the next value can be computed based on the current one; 45 | * @return the next value to be supplied. This should not be a reference to the array that backs {@link #getCurrentSequence()}. 46 | * @implSpec 47 | * This default implementation assumes that the value returned by {@link #getCurrentSequence()} is 48 | * a reference to the array containing the current sequence (and not a copy of it). 49 | *
Therefore, modifying this value is a way to configure the value to be returned by the next call of {@link #getCurrentSequence()}. 50 | *
if {@code useNext} is true, this implementation calls {@link #computeNext()}; otherwise, it calls {@link #unrank()}. 51 | */ 52 | default int[] getNextSequence(boolean useNext) { 53 | int[] currSeq = getCurrentSequence(); 54 | int len = currSeq.length; 55 | if(useNext) { 56 | computeNext(); 57 | int[] seq = new int[len]; 58 | System.arraycopy(currSeq, 0, seq, 0, len); 59 | return seq; 60 | } else { 61 | int[] prod = unrank(); 62 | System.arraycopy(prod, 0, currSeq, 0, len); 63 | return prod; 64 | } 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /streamplify/src/main/java/org/beryx/streamplify/LongIndexedSpliterator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify; 17 | 18 | import java.math.BigInteger; 19 | import java.util.*; 20 | import java.util.function.Consumer; 21 | import java.util.stream.Stream; 22 | import java.util.stream.StreamSupport; 23 | 24 | import org.beryx.streamplify.permutation.LongPermutations; 25 | import org.beryx.streamplify.shuffler.DefaultLongShuffler; 26 | import org.beryx.streamplify.shuffler.LongShuffler; 27 | import org.slf4j.Logger; 28 | import org.slf4j.LoggerFactory; 29 | 30 | /** 31 | * An indexed-spliterator that uses a long index. 32 | */ 33 | public class LongIndexedSpliterator> implements Spliterator, Streamable { 34 | private static final Logger logger = LoggerFactory.getLogger(LongPermutations.class); 35 | 36 | private Splittable.LongIndexed valueSupplier; 37 | private long index; 38 | private final long fence; 39 | private int characteristics = Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.IMMUTABLE; 40 | private LongShuffler shuffler = LongShuffler.IDENTITY; 41 | 42 | protected LongIndexedSpliterator(long origin, long fence) { 43 | logger.trace("LongIndexedSpliterator({}, {})", origin, fence); 44 | if(origin < 0 || fence < origin) throw new IllegalArgumentException("origin: " + origin + ", fence: " + fence); 45 | this.index = origin; 46 | this.fence = fence; 47 | } 48 | 49 | @SuppressWarnings("unchecked") 50 | public final S withAdditionalCharacteristics(int additionalCharacteristics) { 51 | this.characteristics |= additionalCharacteristics; 52 | return (S)this; 53 | } 54 | 55 | /** 56 | * Configures the shuffler of this source. 57 | * Unless you provide your own {@link LongShuffler} implementation, you should use {@link #shuffle()} or {@link #shuffle(Random)} instead of this method. 58 | * @return this instance 59 | */ 60 | @SuppressWarnings("unchecked") 61 | public final S withShuffler(LongShuffler shuffler) { 62 | this.shuffler = shuffler; 63 | return (S)this; 64 | } 65 | 66 | /** 67 | * Configures the value supplier of this source. 68 | * @return this instance 69 | */ 70 | @SuppressWarnings("unchecked") 71 | public final S withValueSupplier(Splittable.LongIndexed valueSupplier) { 72 | this.valueSupplier = valueSupplier; 73 | return (S)this; 74 | } 75 | 76 | protected final long getIndex() { 77 | return index; 78 | } 79 | 80 | protected final long getFence() { 81 | return fence; 82 | } 83 | 84 | @Override 85 | public Stream stream() { 86 | return StreamSupport.stream(this, false); 87 | } 88 | 89 | @Override 90 | public Stream parallelStream() { 91 | return StreamSupport.stream(this, true); 92 | } 93 | 94 | @Override 95 | public long count() { 96 | return fence - index; 97 | } 98 | 99 | @Override 100 | public BigInteger bigCount() { 101 | return BigInteger.valueOf(count()); 102 | } 103 | 104 | @SuppressWarnings("unchecked") 105 | @Override 106 | public S skip(long n) { 107 | if(n < 0) throw new IllegalArgumentException("skip(" + n + ")"); 108 | index = (fence - index <= n) ? fence : (index + n); 109 | return (S)this; 110 | } 111 | 112 | @SuppressWarnings("unchecked") 113 | @Override 114 | public S skip(BigInteger bigN) { 115 | if(bigN.compareTo(BigInteger.ZERO) < 0) throw new IllegalArgumentException("skip(" + bigN + ")"); 116 | if(bigN.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0) { 117 | index = fence; 118 | } else { 119 | long n = bigN.longValueExact(); 120 | index = (fence - index <= n) ? fence : (index + n); 121 | } 122 | return (S)this; 123 | } 124 | 125 | @Override 126 | public long estimateSize() { 127 | return fence - index; 128 | } 129 | 130 | @Override 131 | public int characteristics() { 132 | return characteristics; 133 | } 134 | 135 | @Override 136 | public boolean tryAdvance(Consumer action) { 137 | if (action == null) throw new NullPointerException(); 138 | if (index >= 0 && index < fence) { 139 | long shuffledIndex = shuffler.getShuffledIndex(index); 140 | T val = valueSupplier.apply(shuffledIndex); 141 | index++; 142 | action.accept(val); 143 | return true; 144 | } 145 | return false; 146 | } 147 | 148 | @Override 149 | public Spliterator trySplit() { 150 | long mid = (index + fence) >>> 1; 151 | if(index >= mid) return null; 152 | S spliterator = (S)new LongIndexedSpliterator(index, mid) 153 | .withAdditionalCharacteristics(characteristics) 154 | .withValueSupplier(valueSupplier.split()) 155 | .withShuffler(shuffler); 156 | index = mid; 157 | return spliterator; 158 | } 159 | 160 | @Override 161 | public void forEachRemaining(Consumer action) { 162 | if (action == null) throw new NullPointerException(); 163 | if(index >= 0 && index < fence) { 164 | for(long i = index; i < fence; i++) { 165 | long shuffledIndex = shuffler.getShuffledIndex(i); 166 | T val = valueSupplier.apply(shuffledIndex); 167 | action.accept(val); 168 | } 169 | index = fence; 170 | } 171 | } 172 | 173 | @SuppressWarnings("unchecked") 174 | @Override 175 | public S shuffle(Random rnd) { 176 | shuffler = new DefaultLongShuffler(fence, rnd); 177 | return (S)this; 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /streamplify/src/main/java/org/beryx/streamplify/Splittable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify; 17 | 18 | import java.math.BigInteger; 19 | import java.util.Spliterator; 20 | import java.util.function.Function; 21 | import java.util.function.LongFunction; 22 | 23 | /** 24 | * A functional interface providing a method for splitting this instance. 25 | *
Used primarily by implementations of the valueSupplier requested by indexed-spliterators 26 | * (such as {@link LongIndexedSpliterator} or {@link BigIntegerIndexedSpliterator}). 27 | * The valueSupplier's {@link #split()} is typically called whenever the indexed spliterator performs a {@link Spliterator#trySplit()}. 28 | */ 29 | @FunctionalInterface 30 | public interface Splittable> { 31 | interface LongIndexed extends LongFunction, Splittable> { 32 | LongIndexed IDENTITY = new LongIndexed() { 33 | @Override 34 | public LongIndexed split() { 35 | return this; 36 | } 37 | 38 | @Override 39 | public Long apply(long value) { 40 | return value; 41 | } 42 | }; 43 | } 44 | 45 | interface BigIntegerIndexed extends Function, Splittable> { 46 | BigIntegerIndexed IDENTITY = new BigIntegerIndexed() { 47 | @Override 48 | public BigIntegerIndexed split() { 49 | return this; 50 | } 51 | 52 | @Override 53 | public BigInteger apply(BigInteger value) { 54 | return value; 55 | } 56 | }; 57 | 58 | } 59 | 60 | /** 61 | * Splits this instance. 62 | * @return a Splittable. 63 | * This is usually a newly created instance, but may also be this instance, if the implementing class has no state. 64 | */ 65 | S split(); 66 | } 67 | -------------------------------------------------------------------------------- /streamplify/src/main/java/org/beryx/streamplify/Streamable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify; 17 | 18 | import java.math.BigInteger; 19 | import java.util.Random; 20 | import java.util.Spliterator; 21 | import java.util.stream.Stream; 22 | 23 | /** 24 | * Objects implementing this interface provide data in form of sequential or parallel {@link Stream}s. 25 | */ 26 | public interface Streamable> { 27 | /** @return a sequential {@code Stream} */ 28 | Stream stream(); 29 | 30 | /** @return a possibly parallel {@code Stream} */ 31 | Stream parallelStream(); 32 | 33 | /** @return the number of elements in the data source, or -1 if the number is too big to fit in a long. **/ 34 | long count(); 35 | 36 | /** @return the number of elements in the data source as BigInteger. **/ 37 | BigInteger bigCount(); 38 | 39 | /** 40 | * Adds {@code additionalCharacteristics} to the provided streams. 41 | * @return this instance 42 | */ 43 | S withAdditionalCharacteristics(int additionalCharacteristics); 44 | 45 | /** 46 | * Convenience method for adding the {@link Spliterator#ORDERED} characteristic to the provided streams. 47 | * @return this instance 48 | */ 49 | default S ordered() { 50 | return withAdditionalCharacteristics(Spliterator.ORDERED); 51 | } 52 | 53 | /** 54 | * Configure this instance to provide streams that skip the first {}@code n} elements in the data source. 55 | * It is usually more efficient to call this method instead of {@link Stream#skip(long)}. 56 | * @param n the number of elements to be skipped (as a long). 57 | * @return depending on the implementation, it may return this instance or another Streamable. 58 | */ 59 | > Z skip(long n); 60 | 61 | /** 62 | * Configure this instance to provide streams that skip the first {}@code n} elements in the data source. 63 | * @param n the number of elements to be skipped (as a BigInteger). 64 | * @return depending on the implementation, it may return this instance or another Streamable. 65 | */ 66 | > Z skip(BigInteger n); 67 | 68 | /** 69 | * Configure this instance to provide streams that shuffle elements in the data source. 70 | * @param random the random number generator to be used to perform the shuffling. 71 | * @return depending on the implementation, it may return this instance or another Streamable. 72 | */ 73 | > Z shuffle(Random random); 74 | 75 | /** 76 | * Configure this instance to provide streams that shuffle elements in the data source. 77 | *
This default implementation calls {@link #shuffle(Random)} with a random number generator created using the parameterless constructor of {@link Random}. 78 | * @return depending on the implementation, it may return this instance or another Streamable. 79 | */ 80 | default > Z shuffle() { 81 | return shuffle(new Random()); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /streamplify/src/main/java/org/beryx/streamplify/StreamableProxy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify; 17 | 18 | import java.math.BigInteger; 19 | import java.util.Random; 20 | import java.util.stream.Stream; 21 | 22 | /** 23 | * A {@link Streamable} that forwards its calls to a delegate 24 | */ 25 | public abstract class StreamableProxy> implements Streamable { 26 | /** 27 | * @return the delegate to which method calls are forwarded. 28 | */ 29 | protected abstract Streamable getDelegate(); 30 | 31 | @SuppressWarnings("unchecked") 32 | public S withAdditionalCharacteristics(int additionalCharacteristics) { 33 | getDelegate().withAdditionalCharacteristics(additionalCharacteristics); 34 | return (S)this; 35 | } 36 | 37 | @Override 38 | public Stream stream() { 39 | return getDelegate().stream(); 40 | } 41 | 42 | @Override 43 | public Stream parallelStream() { 44 | return getDelegate().parallelStream(); 45 | } 46 | 47 | @Override 48 | public long count() { 49 | return getDelegate().count(); 50 | } 51 | 52 | @Override 53 | public BigInteger bigCount() { 54 | return getDelegate().bigCount(); 55 | } 56 | 57 | @SuppressWarnings("unchecked") 58 | @Override 59 | public > Z skip(long n) { 60 | return (Z)getDelegate().skip(n); 61 | } 62 | 63 | @SuppressWarnings("unchecked") 64 | @Override 65 | public > Z skip(BigInteger n) { 66 | return (Z)getDelegate().skip(n); 67 | } 68 | 69 | @SuppressWarnings("unchecked") 70 | @Override 71 | public > Z shuffle(Random rnd) { 72 | return (Z)getDelegate().shuffle(rnd); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /streamplify/src/main/java/org/beryx/streamplify/combination/BigIntegerCombinations.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.combination; 17 | 18 | import org.beryx.streamplify.BigIntegerIndexedSpliterator; 19 | 20 | import java.math.BigInteger; 21 | 22 | /** 23 | * Provides streams of combinations. 24 | *
When the binomial coefficient (n choose k) can fit in a long, you may consider using the more efficient {@link LongCombinations}. 25 | */ 26 | @SuppressWarnings("unchecked") 27 | public class BigIntegerCombinations extends BigIntegerIndexedSpliterator { 28 | /** 29 | * {@code k}-combinations from a set of {@code n} elements 30 | */ 31 | public BigIntegerCombinations(int n, int k) { 32 | this(count(n, k), n, k); 33 | } 34 | 35 | BigIntegerCombinations(BigInteger count, int n, int k) { 36 | super(BigInteger.ZERO, count); 37 | if(n < 0 || k < 0 || n < k) throw new IllegalArgumentException("Invalid (n,k): (" + n + "," + k + ")"); 38 | this.withValueSupplier(new CombinationSupplier.BigInt(count, n, k)); 39 | this.withAdditionalCharacteristics(DISTINCT); 40 | } 41 | 42 | protected static BigInteger count(int n, int k) { 43 | if(n > Combinations.MAX_N) throw new IllegalArgumentException("Value too big: " + n); 44 | BigInteger cnt = BigInteger.ONE; 45 | for(int i = 0; i < k; i++) { 46 | cnt = cnt.multiply(BigInteger.valueOf(n - i)); 47 | cnt = cnt.divide(BigInteger.valueOf(i + 1)); 48 | } 49 | return cnt; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /streamplify/src/main/java/org/beryx/streamplify/combination/CombinationSupplier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.combination; 17 | 18 | import org.beryx.streamplify.IntArraySupplier; 19 | import org.beryx.streamplify.Splittable; 20 | import org.beryx.streamplify.shared.Unranking; 21 | 22 | import java.math.BigInteger; 23 | 24 | /** 25 | * A value supplier for combinations. 26 | *
It may compute the next combination based on the current one, or by unranking an index. 27 | */ 28 | public abstract class CombinationSupplier implements IntArraySupplier { 29 | protected final int n; 30 | protected final int k; 31 | protected final int[] currentCombination; 32 | 33 | CombinationSupplier(int n, int k) { 34 | this.n = n; 35 | this.k = k; 36 | this.currentCombination = new int[k]; 37 | } 38 | 39 | @Override 40 | public int[] getCurrentSequence() { 41 | return currentCombination; 42 | } 43 | 44 | public void computeNext() { 45 | int pos = k - 1; 46 | while(pos >= 0 && currentCombination[pos] >= n - k + pos) pos--; 47 | if(pos < 0) return; 48 | int val = currentCombination[pos]; 49 | for(int i = pos; i < k; i++) { 50 | currentCombination[i] = ++val; 51 | } 52 | } 53 | 54 | public static class Long extends CombinationSupplier implements Splittable.LongIndexed { 55 | private final long count; 56 | private long currentIndex = -2; 57 | 58 | public Long(long count, int n, int k) { 59 | super(n, k); 60 | this.count = count; 61 | } 62 | 63 | @Override 64 | public Long split() { 65 | return new Long(count, n, k); 66 | } 67 | 68 | @Override 69 | public int[] apply(long index) { 70 | boolean useNext = (index == currentIndex + 1); 71 | currentIndex = index; 72 | return getNextSequence(useNext); 73 | } 74 | 75 | @Override 76 | public int[] unrank() { 77 | return Unranking.unrankCombination(n, k, count, currentIndex); 78 | } 79 | } 80 | 81 | public static class BigInt extends CombinationSupplier implements Splittable.BigIntegerIndexed { 82 | private final BigInteger count; 83 | private BigInteger currentIndex = BigInteger.valueOf(-2); 84 | 85 | public BigInt(BigInteger count, int n, int k) { 86 | super(n, k); 87 | this.count = count; 88 | } 89 | 90 | @Override 91 | public BigInt split() { 92 | return new BigInt(count, n, k); 93 | } 94 | 95 | @Override 96 | public int[] apply(BigInteger index) { 97 | boolean useNext = index.equals(currentIndex.add(BigInteger.ONE)); 98 | currentIndex = index; 99 | return getNextSequence(useNext); 100 | } 101 | 102 | @Override 103 | public int[] unrank() { 104 | return Unranking.unrankCombination(n, k, count, currentIndex); 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /streamplify/src/main/java/org/beryx/streamplify/combination/Combinations.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.combination; 17 | 18 | import org.beryx.streamplify.Streamable; 19 | import org.beryx.streamplify.StreamableProxy; 20 | 21 | import java.math.BigInteger; 22 | 23 | /** 24 | * A {@link Streamable} providing streams of combinations. 25 | *
This class is a proxy that delegates to either {@link LongCombinations} or {@link BigIntegerCombinations}, depending on the values of {@code n} and {@code k}. 26 | */ 27 | public class Combinations extends StreamableProxy { 28 | public static final int MAX_N = 50_000; 29 | 30 | private final Streamable delegate; 31 | 32 | /** 33 | * {@code k}-combinations from a set of {@code n} elements 34 | */ 35 | public Combinations(int n, int k) { 36 | BigInteger count = BigIntegerCombinations.count(n, k); 37 | BigInteger maxVal = count.multiply(BigInteger.valueOf(n - 1)); 38 | if(maxVal.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) < 0) { 39 | delegate = new LongCombinations(count.longValueExact(), n, k); 40 | } else { 41 | delegate = new BigIntegerCombinations(count, n, k); 42 | } 43 | } 44 | 45 | @Override 46 | protected Streamable getDelegate() { 47 | return delegate; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /streamplify/src/main/java/org/beryx/streamplify/combination/LongCombinations.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.combination; 17 | 18 | import org.beryx.streamplify.LongIndexedSpliterator; 19 | 20 | import java.math.BigInteger; 21 | 22 | /** 23 | * Provides streams of combinations. 24 | *
Can be used when the binomial coefficient (n choose k) is a number that can fit in a long. 25 | * For bigger values, a {@link BigIntegerCombinations} is needed. 26 | */ 27 | @SuppressWarnings("unchecked") 28 | public class LongCombinations extends LongIndexedSpliterator { 29 | /** 30 | * {@code k}-combinations from a set of {@code n} elements 31 | */ 32 | public LongCombinations(int n, int k) { 33 | this(count(n, k), n, k); 34 | } 35 | 36 | LongCombinations(long count, int n, int k) { 37 | super(0, count); 38 | if(n < 0 || k < 0 || n < k) throw new IllegalArgumentException("Invalid (n,k): (" + n + "," + k + ")"); 39 | this.withValueSupplier(new CombinationSupplier.Long(count, n, k)); 40 | this.withAdditionalCharacteristics(DISTINCT); 41 | } 42 | 43 | protected static long count(int n, int k) { 44 | BigInteger bigCount = BigIntegerCombinations.count(n, k); 45 | BigInteger maxVal = bigCount.multiply(BigInteger.valueOf(n - 1)); 46 | if(maxVal.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) >= 0) throw new IllegalArgumentException("Combination arguments too big: " + n + ", " + k); 47 | return bigCount.longValueExact(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /streamplify/src/main/java/org/beryx/streamplify/derangement/BigIntegerDerangements.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.derangement; 17 | 18 | import org.beryx.streamplify.BigIntegerIndexedSpliterator; 19 | 20 | import java.math.BigInteger; 21 | 22 | /** 23 | * Provides streams of derangements. 24 | *
For derangements with a length <= 21, you may consider using the more efficient {@link LongDerangements}. 25 | */ 26 | @SuppressWarnings("unchecked") 27 | public class BigIntegerDerangements extends BigIntegerIndexedSpliterator { 28 | public static final int MAX_LENGTH = 20_000; 29 | 30 | /** 31 | * Constructs derangements of {@code length} elements 32 | */ 33 | public BigIntegerDerangements(int length) { 34 | super(BigInteger.ZERO, subfactorial(length)); 35 | this.withValueSupplier(new DerangementSupplier.BigInt(length)); 36 | this.withAdditionalCharacteristics(DISTINCT); 37 | } 38 | 39 | /** 40 | * @throws IllegalArgumentException if {@code n} is negative or too big (> {@value #MAX_LENGTH}) 41 | */ 42 | public static BigInteger subfactorial(int n) { 43 | if (n < 0) throw new IllegalArgumentException("Invalid derangement length: " + n); 44 | if (n > MAX_LENGTH) throw new IllegalArgumentException("Value too big: " + n); 45 | if (n == 0) return BigInteger.ONE; 46 | BigInteger prev = BigInteger.ONE; 47 | BigInteger curr = BigInteger.ZERO; 48 | for (int i = 2; i <= n; ++i) { 49 | BigInteger next = BigInteger.valueOf(i - 1).multiply(curr.add(prev)); 50 | prev = curr; 51 | curr = next; 52 | } 53 | return curr; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /streamplify/src/main/java/org/beryx/streamplify/derangement/Derangements.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.derangement; 17 | 18 | import org.beryx.streamplify.Streamable; 19 | import org.beryx.streamplify.StreamableProxy; 20 | 21 | /** 22 | * A {@link Streamable} providing streams of derangements. 23 | *
This class is a proxy that delegates to either {@link LongDerangements} or {@link BigIntegerDerangements}, depending on the derangement length. 24 | */ 25 | public class Derangements extends StreamableProxy { 26 | 27 | private final Streamable delegate; 28 | 29 | /** 30 | * @param length the derangement length 31 | */ 32 | public Derangements(int length) { 33 | if (length <= LongDerangements.MAX_LENGTH) { 34 | delegate = new LongDerangements(length); 35 | } else { 36 | delegate = new BigIntegerDerangements(length); 37 | } 38 | } 39 | 40 | @Override 41 | public Streamable getDelegate() { 42 | return delegate; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /streamplify/src/main/java/org/beryx/streamplify/derangement/LongDerangements.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.derangement; 17 | 18 | import org.beryx.streamplify.LongIndexedSpliterator; 19 | 20 | /** 21 | * Provides streams of derangements. 22 | *
Can be used for derangements with a maximum length of {@value #MAX_LENGTH}. 23 | * For bigger values, a {@link BigIntegerDerangements} is needed. 24 | */ 25 | @SuppressWarnings("unchecked") 26 | public class LongDerangements extends LongIndexedSpliterator { 27 | public static final int MAX_LENGTH = 21; 28 | 29 | /** 30 | * Constructs derangements of {@code length} elements 31 | */ 32 | public LongDerangements(int length) { 33 | super(0, subfactorial(length)); 34 | this.withValueSupplier(new DerangementSupplier.Long(length)); 35 | this.withAdditionalCharacteristics(DISTINCT); 36 | } 37 | 38 | /** 39 | * @throws IllegalArgumentException if {@code n} is negative or the result does not fit in a long (that is, {@code n} > {@value #MAX_LENGTH}) 40 | */ 41 | public static long subfactorial(int n) { 42 | if (n < 0) throw new IllegalArgumentException("Invalid derangement length: " + n); 43 | if (n > MAX_LENGTH) throw new IllegalArgumentException("Derangement length too big: " + n); 44 | if (n == 0) return 1; 45 | long prev = 1; 46 | long curr = 0; 47 | for (int i = 2; i <= n; ++i) { 48 | long next = (i - 1)*(curr + prev); 49 | prev = curr; 50 | curr = next; 51 | } 52 | return curr; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /streamplify/src/main/java/org/beryx/streamplify/partperm/BigIntegerPartialPermutations.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.partperm; 17 | 18 | import org.beryx.streamplify.BigIntegerIndexedSpliterator; 19 | 20 | import java.math.BigInteger; 21 | 22 | /** 23 | * Provides streams of partial permutations. 24 | *
For permutations with a length <= 18, you may consider using the more efficient {@link LongPartialPermutations}. 25 | */ 26 | public class BigIntegerPartialPermutations extends BigIntegerIndexedSpliterator { 27 | public static final int MAX_LENGTH = 10_000; 28 | 29 | /** 30 | * Constructs partial permutations of {@code length} elements 31 | */ 32 | public BigIntegerPartialPermutations(int length) { 33 | super(BigInteger.ZERO, numberOfPermutations(length)); 34 | this.withValueSupplier(new PartialPermutationSupplier.BigInt(length)); 35 | this.withAdditionalCharacteristics(DISTINCT); 36 | } 37 | 38 | /** 39 | * @throws IllegalArgumentException if {@code n} is negative or too big (> {@value #MAX_LENGTH}) 40 | */ 41 | public static BigInteger numberOfPermutations(int n) { 42 | if (n < 0) throw new IllegalArgumentException("Invalid partial permutation length: " + n); 43 | if (n > MAX_LENGTH) throw new IllegalArgumentException("Partial permutation length too big: " + n); 44 | 45 | BigInteger[] factorials = computeFactorials(n); 46 | BigInteger numberOfPermutations = BigInteger.ZERO; 47 | for (int i = 0; i <= n; i++) { 48 | numberOfPermutations = numberOfPermutations.add(computeNextNcK(n, factorials, i)); 49 | } 50 | return numberOfPermutations; 51 | } 52 | 53 | public static BigInteger[] computeFactorials(int length) { 54 | BigInteger[] factorials = new BigInteger[length + 1]; 55 | factorials[0] = BigInteger.ONE; 56 | for (int i = 1; i <= length; i++) { 57 | factorials[i] = factorials[i - 1].multiply(BigInteger.valueOf(i)); 58 | } 59 | return factorials; 60 | } 61 | 62 | private static BigInteger computeNextNcK(int n, BigInteger[] factorials, int i) { 63 | BigInteger nCk = factorials[n].divide(factorials[i].multiply(factorials[n - i])); 64 | return factorials[i].multiply(nCk.pow(2)); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /streamplify/src/main/java/org/beryx/streamplify/partperm/LongPartialPermutations.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.partperm; 17 | 18 | import org.beryx.streamplify.LongIndexedSpliterator; 19 | 20 | /** 21 | * Provides streams of partial permutations. 22 | *
Can be used for partial permutations with a maximum length of {@value #MAX_LENGTH}. 23 | * For bigger values, a {@link BigIntegerPartialPermutations} is needed. 24 | */ 25 | public class LongPartialPermutations extends LongIndexedSpliterator { 26 | public static final int MAX_LENGTH = 18; 27 | 28 | /** 29 | * Constructs partial permutations of {@code length} elements 30 | */ 31 | public LongPartialPermutations(int length) { 32 | super(0, numberOfPermutations(length)); 33 | this.withValueSupplier(new PartialPermutationSupplier.Long(length)); 34 | this.withAdditionalCharacteristics(DISTINCT); 35 | } 36 | 37 | /** 38 | * @throws IllegalArgumentException if {@code n} is negative or the result does not fit in a long (that is, {@code n} > {@value #MAX_LENGTH}) 39 | */ 40 | public static long numberOfPermutations(int n) { 41 | if (n < 0) throw new IllegalArgumentException("Invalid partial permutation length: " + n); 42 | if (n > MAX_LENGTH) throw new IllegalArgumentException("Partial permutation length too big: " + n); 43 | if (n == 0) return 1; 44 | if (n == 1) return 2; 45 | return 2 * n * numberOfPermutations(n - 1) - (long) Math.pow(n - 1, 2) * numberOfPermutations(n - 2); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /streamplify/src/main/java/org/beryx/streamplify/partperm/PartialPermutations.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.partperm; 17 | 18 | import org.beryx.streamplify.Streamable; 19 | import org.beryx.streamplify.StreamableProxy; 20 | 21 | /** 22 | * A {@link Streamable} providing streams of permutations. 23 | *
This class is a proxy that delegates to either {@link LongPartialPermutations} or {@link BigIntegerPartialPermutations}, depending on the permutation length. 24 | */ 25 | public class PartialPermutations extends StreamableProxy { 26 | private final Streamable delegate; 27 | 28 | /** 29 | * @param length the partial permutation length 30 | */ 31 | public PartialPermutations(int length) { 32 | if (length <= LongPartialPermutations.MAX_LENGTH) { 33 | delegate = new LongPartialPermutations(length); 34 | } else { 35 | delegate = new BigIntegerPartialPermutations(length); 36 | } 37 | } 38 | 39 | @Override 40 | public Streamable getDelegate() { 41 | return delegate; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /streamplify/src/main/java/org/beryx/streamplify/permutation/BigIntegerPermutations.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.permutation; 17 | 18 | import org.beryx.streamplify.BigIntegerIndexedSpliterator; 19 | 20 | import java.math.BigInteger; 21 | 22 | /** 23 | * Provides streams of permutations. 24 | *
For permutations with a length <= 20, you may consider using the more efficient {@link LongPermutations}. 25 | */ 26 | @SuppressWarnings("unchecked") 27 | public class BigIntegerPermutations extends BigIntegerIndexedSpliterator { 28 | public static final int MAX_LENGTH = 20_000; 29 | 30 | /** 31 | * Constructs permutations of {@code length} elements 32 | */ 33 | public BigIntegerPermutations(int length) { 34 | super(BigInteger.ZERO, factorial(length)); 35 | this.withValueSupplier(new PermutationSupplier.BigInt(length)); 36 | this.withAdditionalCharacteristics(DISTINCT); 37 | } 38 | 39 | /** 40 | * @throws IllegalArgumentException if {@code n} is negative or too big (> {@value #MAX_LENGTH}) 41 | */ 42 | public static BigInteger factorial(int n) { 43 | if(n < 0) throw new IllegalArgumentException("Invalid permutation length: " + n); 44 | if(n > MAX_LENGTH) throw new IllegalArgumentException("Value too big: " + n); 45 | BigInteger fact = BigInteger.ONE; 46 | for(int i = 2; i <= n; i++) { 47 | fact = fact.multiply(BigInteger.valueOf(i)); 48 | } 49 | return fact; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /streamplify/src/main/java/org/beryx/streamplify/permutation/LongPermutations.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.permutation; 17 | 18 | import org.beryx.streamplify.LongIndexedSpliterator; 19 | 20 | /** 21 | * Provides streams of permutations. 22 | *
Can be used for permutations with a maximum length of {@value #MAX_LENGTH}. 23 | * For bigger values, a {@link BigIntegerPermutations} is needed. 24 | */ 25 | @SuppressWarnings("unchecked") 26 | public class LongPermutations extends LongIndexedSpliterator { 27 | public static final int MAX_LENGTH = 20; 28 | 29 | /** 30 | * Constructs permutations of {@code length} elements 31 | */ 32 | public LongPermutations(int length) { 33 | super(0, factorial(length)); 34 | this.withValueSupplier(new PermutationSupplier.Long(length)); 35 | this.withAdditionalCharacteristics(DISTINCT); 36 | } 37 | 38 | /** 39 | * @throws IllegalArgumentException if {@code n} is negative or the result does not fit in a long (that is, {@code n} > {@value #MAX_LENGTH}) 40 | */ 41 | public static long factorial(int n) { 42 | if(n < 0) throw new IllegalArgumentException("Invalid permutation length: " + n); 43 | if(n > MAX_LENGTH) throw new IllegalArgumentException("Permutation length too big: " + n); 44 | long fact = 1; 45 | for(int i = 2; i <= n; i ++) fact *= i; 46 | return fact; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /streamplify/src/main/java/org/beryx/streamplify/permutation/PermutationSupplier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.permutation; 17 | 18 | import org.beryx.streamplify.IntArraySupplier; 19 | import org.beryx.streamplify.Splittable; 20 | 21 | import java.math.BigInteger; 22 | 23 | /** 24 | * A value supplier for permutations. 25 | *
It may compute the next permutation based on the current one, or by unranking an index. 26 | */ 27 | public abstract class PermutationSupplier implements IntArraySupplier { 28 | protected final int length; 29 | protected final int[] currentPermutation; 30 | 31 | PermutationSupplier(int length) { 32 | this.length = length; 33 | this.currentPermutation = new int[length]; 34 | } 35 | 36 | @Override 37 | public int[] getCurrentSequence() { 38 | return currentPermutation; 39 | } 40 | 41 | public void computeNext() { 42 | int pos = length - 1; 43 | while(pos > 0 && currentPermutation[pos] <= currentPermutation[pos - 1]) pos--; 44 | if(pos == 0) return; 45 | int pivotPos = pos - 1; 46 | int pivotVal = currentPermutation[pivotPos]; 47 | int swapIdx = length - 1; 48 | while(swapIdx > pivotPos && currentPermutation[swapIdx] < pivotVal) swapIdx--; 49 | currentPermutation[pivotPos] = currentPermutation[swapIdx]; 50 | currentPermutation[swapIdx] = pivotVal; 51 | for(int i = 0; i < (length - pivotPos - 1) / 2; i++) { 52 | int tmp = currentPermutation[pivotPos + i + 1]; 53 | currentPermutation[pivotPos + i + 1] = currentPermutation[length - i - 1]; 54 | currentPermutation[length - i - 1] = tmp; 55 | } 56 | } 57 | 58 | public static class Long extends PermutationSupplier implements Splittable.LongIndexed { 59 | private final long[] divisors; 60 | 61 | private long currentIndex = -2; 62 | 63 | public Long(int length) { 64 | this(length, computeDivisors(length)); 65 | } 66 | 67 | private Long(int length, long[] divisors) { 68 | super(length); 69 | this.divisors = divisors; 70 | } 71 | 72 | @Override 73 | public Long split() { 74 | return new Long(length, divisors); 75 | } 76 | 77 | @Override 78 | public int[] apply(long index) { 79 | boolean useNext = (index == currentIndex + 1); 80 | currentIndex = index; 81 | return getNextSequence(useNext); 82 | } 83 | 84 | @Override 85 | public int[] unrank() { 86 | int[] perm = new int[length]; 87 | for(int i = 0; i < length; i++) 88 | perm[i] = i; 89 | 90 | long dividend = currentIndex; 91 | for(int step = 0; step < length - 1; step++) { 92 | int idx = (int) (dividend / divisors[step]); 93 | if(idx > 0) { 94 | int val = perm[step + idx]; 95 | System.arraycopy(perm, step, perm, step + 1, idx); 96 | perm[step] = val; 97 | } 98 | dividend = dividend % divisors[step]; 99 | } 100 | return perm; 101 | } 102 | 103 | private static long[] computeDivisors(int len) { 104 | if(len < 1) return null; 105 | long[] divs = new long[len - 1]; 106 | long fac = 1; 107 | for(int i = 1; i < len; i++) { 108 | fac *= i; 109 | divs[len - i - 1] = fac; 110 | } 111 | return divs; 112 | } 113 | } 114 | 115 | public static class BigInt extends PermutationSupplier implements Splittable.BigIntegerIndexed { 116 | private final BigInteger[] divisors; 117 | private BigInteger currentIndex = BigInteger.valueOf(-2); 118 | 119 | public BigInt(int length) { 120 | this(length, computeDivisors(length)); 121 | } 122 | 123 | private BigInt(int length, BigInteger[] divisors) { 124 | super(length); 125 | this.divisors = divisors; 126 | } 127 | 128 | @Override 129 | public BigInt split() { 130 | return new BigInt(length, divisors); 131 | } 132 | 133 | @Override 134 | public int[] apply(BigInteger index) { 135 | boolean useNext = index.equals(currentIndex.add(BigInteger.ONE)); 136 | currentIndex = index; 137 | return getNextSequence(useNext); 138 | } 139 | 140 | @Override 141 | public int[] unrank() { 142 | int[] perm = new int[length]; 143 | for(int i = 0; i < length; i++) 144 | perm[i] = i; 145 | 146 | BigInteger dividend = currentIndex; 147 | for(int step = 0; step < length - 1; step++) { 148 | BigInteger[] quotientAndRemainder = dividend.divideAndRemainder(divisors[step]); 149 | int idx = quotientAndRemainder[0].intValueExact(); 150 | if(idx > 0) { 151 | int val = perm[step + idx]; 152 | System.arraycopy(perm, step, perm, step + 1, idx); 153 | perm[step] = val; 154 | } 155 | dividend = quotientAndRemainder[1]; 156 | } 157 | return perm; 158 | } 159 | 160 | private static BigInteger[] computeDivisors(int len) { 161 | if(len < 1) return null; 162 | BigInteger[] divs = new BigInteger[len - 1]; 163 | BigInteger fac = BigInteger.ONE; 164 | for(int i = 1; i < len; i++) { 165 | fac = fac.multiply(BigInteger.valueOf(i)); 166 | divs[len - i - 1] = fac; 167 | } 168 | return divs; 169 | } 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /streamplify/src/main/java/org/beryx/streamplify/permutation/Permutations.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.permutation; 17 | 18 | import org.beryx.streamplify.Streamable; 19 | import org.beryx.streamplify.StreamableProxy; 20 | 21 | /** 22 | * A {@link Streamable} providing streams of permutations. 23 | *
This class is a proxy that delegates to either {@link LongPermutations} or {@link BigIntegerPermutations}, depending on the permutation length. 24 | */ 25 | public class Permutations extends StreamableProxy { 26 | 27 | private final Streamable delegate; 28 | 29 | /** 30 | * @param length the permutation length 31 | */ 32 | public Permutations(int length) { 33 | if(length <= LongPermutations.MAX_LENGTH) { 34 | delegate = new LongPermutations(length); 35 | } else { 36 | delegate = new BigIntegerPermutations(length); 37 | } 38 | } 39 | 40 | @Override 41 | public Streamable getDelegate() { 42 | return delegate; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /streamplify/src/main/java/org/beryx/streamplify/powerset/BigIntegerPowerSet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.powerset; 17 | 18 | import java.math.BigInteger; 19 | 20 | import org.beryx.streamplify.BigIntegerIndexedSpliterator; 21 | 22 | /** 23 | * Provides stream of power set for the given length. 24 | *
For length < 63, you may consider using the more efficient {@link LongPowerSet}. 25 | */ 26 | @SuppressWarnings("unchecked") 27 | public class BigIntegerPowerSet extends BigIntegerIndexedSpliterator { 28 | 29 | private static final int MAX_LENGTH = 512; 30 | 31 | /** 32 | * Constructs power set for {@code length} number of elements. 33 | */ 34 | public BigIntegerPowerSet(int length) { 35 | super(BigInteger.ZERO, powerOfTwo(length)); 36 | this.withValueSupplier(new PowerSetSupplier.BigInt(length)); 37 | this.withAdditionalCharacteristics(DISTINCT); 38 | } 39 | 40 | /** 41 | * Calculates 2 ^ length. 42 | * 43 | * @throws {@link IllegalArgumentException} if length < 0 or length >= 512 44 | */ 45 | private static BigInteger powerOfTwo(int length) { 46 | if (length < 0) { 47 | throw new IllegalArgumentException("Invalid length of power set"); 48 | } 49 | if (length >= MAX_LENGTH) { 50 | throw new IllegalArgumentException("Power set size will be too big for length " + length); 51 | } 52 | return BigInteger.ONE.shiftLeft(length); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /streamplify/src/main/java/org/beryx/streamplify/powerset/LongPowerSet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.powerset; 17 | 18 | import org.beryx.streamplify.LongIndexedSpliterator; 19 | 20 | /** 21 | * Provides stream of power set. 22 | *
Can be used for permutations with a maximum length of {@value #MAX_LENGTH}. 23 | * For bigger values, a {@link BigIntegerPowerSet} is needed. 24 | */ 25 | @SuppressWarnings("unchecked") 26 | public class LongPowerSet extends LongIndexedSpliterator { 27 | 28 | public static final int MAX_LENGTH = 63; 29 | 30 | /** 31 | * Constructs power set for {@code length} number of elements. 32 | */ 33 | public LongPowerSet(int length) { 34 | super(0, powerOfTwo(length)); 35 | this.withValueSupplier(new PowerSetSupplier.Long(length)); 36 | this.withAdditionalCharacteristics(DISTINCT); 37 | } 38 | 39 | /** 40 | * Calculates 2 ^ length. 41 | * 42 | * @throws {@link IllegalArgumentException} if length < 0 or length >= 63. 43 | */ 44 | private static long powerOfTwo(int length) { 45 | if (length < 0) { 46 | throw new IllegalArgumentException("Invalid length of power set"); 47 | } 48 | if (length >= MAX_LENGTH) { 49 | throw new IllegalArgumentException("Size of power set too long for length " + length); 50 | } 51 | return (long) 1 << length; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /streamplify/src/main/java/org/beryx/streamplify/powerset/PowerSet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.powerset; 17 | 18 | import org.beryx.streamplify.Streamable; 19 | import org.beryx.streamplify.StreamableProxy; 20 | 21 | /** 22 | * A {@link Streamable} providing streams of power set. 23 | *
This class is a proxy that delegates to either {@link LongPowerSet} or {@link BigIntegerPowerSet}, depending on the length. 24 | */ 25 | public class PowerSet extends StreamableProxy { 26 | 27 | private final Streamable delegate; 28 | 29 | public PowerSet(int length) { 30 | if (length < LongPowerSet.MAX_LENGTH) { 31 | delegate = new LongPowerSet(length); 32 | } else { 33 | delegate = new BigIntegerPowerSet(length); 34 | } 35 | } 36 | 37 | @Override 38 | protected Streamable getDelegate() { 39 | return delegate; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /streamplify/src/main/java/org/beryx/streamplify/powerset/PowerSetSupplier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.powerset; 17 | 18 | import java.math.BigInteger; 19 | import java.util.ArrayList; 20 | import java.util.Arrays; 21 | import java.util.List; 22 | 23 | import org.beryx.streamplify.IntArraySupplier; 24 | import org.beryx.streamplify.Splittable; 25 | 26 | /** 27 | * A value supplier for power sets. 28 | *
It may compute the next set based on the current one, or by unranking an index. 29 | */ 30 | public abstract class PowerSetSupplier implements IntArraySupplier { 31 | 32 | protected final int length; 33 | protected int[] currentPowerSet; 34 | protected final int[] binaryCounter; 35 | 36 | public PowerSetSupplier(int length) { 37 | this.length = length; 38 | // initial power set would be empty array 39 | this.currentPowerSet = new int[0]; 40 | this.binaryCounter = new int[length]; 41 | } 42 | 43 | @Override 44 | public int[] getCurrentSequence() { 45 | return currentPowerSet; 46 | } 47 | 48 | @Override 49 | public void computeNext() { 50 | int index = length - 1; 51 | for (; index >= 0 && binaryCounter[index] == 1; index--); 52 | if (index == -1) { 53 | // current power set is the last set 54 | return; 55 | } 56 | binaryCounter[index] = 1; 57 | while (++index < length) { 58 | binaryCounter[index] = 0; 59 | } 60 | List powerSetList = new ArrayList<>(); 61 | for (int i = length - 1; i >= 0; i--) { 62 | if (binaryCounter[i] == 1) { 63 | powerSetList.add(length - i - 1); 64 | } 65 | } 66 | currentPowerSet = powerSetList.stream().mapToInt(element -> element.intValue()).toArray(); 67 | } 68 | 69 | @Override 70 | public int[] getNextSequence(boolean useNext) { 71 | if (useNext) { 72 | computeNext(); 73 | return getCurrentSequence(); 74 | } else { 75 | int[] nextSeq = unrank(); 76 | currentPowerSet = nextSeq; 77 | updateBinaryCounter(); 78 | return nextSeq; 79 | } 80 | } 81 | 82 | private void updateBinaryCounter() { 83 | Arrays.fill(binaryCounter, 0); 84 | for (int element : currentPowerSet) { 85 | binaryCounter[element] = 1; 86 | } 87 | } 88 | 89 | public static class Long extends PowerSetSupplier implements Splittable.LongIndexed { 90 | 91 | private long currentIndex = -2; 92 | 93 | public Long(int length) { 94 | super(length); 95 | } 96 | 97 | @Override 98 | public int[] apply(long index) { 99 | boolean useNext = (index == currentIndex + 1); 100 | currentIndex = index; 101 | return getNextSequence(useNext); 102 | } 103 | 104 | @Override 105 | public LongIndexed split() { 106 | return new Long(length); 107 | } 108 | 109 | @Override 110 | public int[] unrank() { 111 | List powerSetList = new ArrayList<>(); 112 | long dividend = currentIndex; 113 | int setElement = 0; 114 | while(dividend != 0) { 115 | long reminder = dividend & 1; 116 | if (reminder == 1) { 117 | powerSetList.add(setElement); 118 | } 119 | dividend = dividend >> 1; 120 | setElement++; 121 | } 122 | return powerSetList.stream().mapToInt(element -> element.intValue()).toArray(); 123 | } 124 | 125 | } 126 | 127 | public static class BigInt extends PowerSetSupplier implements Splittable.BigIntegerIndexed { 128 | 129 | private BigInteger currentIndex = BigInteger.valueOf(-2); 130 | 131 | public BigInt(int length) { 132 | super(length); 133 | } 134 | 135 | @Override 136 | public int[] apply(BigInteger index) { 137 | boolean useNext = index.equals(currentIndex.add(BigInteger.ONE)); 138 | currentIndex = index; 139 | return getNextSequence(useNext); 140 | } 141 | 142 | @Override 143 | public Splittable.BigIntegerIndexed split() { 144 | return new BigInt(length); 145 | } 146 | 147 | @Override 148 | public int[] unrank() { 149 | List powerSetList = new ArrayList<>(); 150 | BigInteger dividend = currentIndex; 151 | int setElement = 0; 152 | while(!dividend.equals(BigInteger.ZERO)) { 153 | BigInteger reminder = dividend.remainder(BigInteger.valueOf(2)); 154 | if (reminder.equals(BigInteger.ONE)) { 155 | powerSetList.add(setElement); 156 | } 157 | dividend = dividend.divide(BigInteger.valueOf(2)); 158 | setElement++; 159 | } 160 | return powerSetList.stream().mapToInt(element -> element.intValue()).toArray(); 161 | } 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /streamplify/src/main/java/org/beryx/streamplify/product/BigIntegerCartesianProduct.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.product; 17 | 18 | import org.beryx.streamplify.BigIntegerIndexedSpliterator; 19 | 20 | import java.math.BigInteger; 21 | import java.util.Arrays; 22 | 23 | /** 24 | * Provides streams of cartesian product tuples. 25 | *
When the cardinality of the cartesian product can fit in a long, you may consider using the more efficient {@link LongCartesianProduct}. 26 | */ 27 | @SuppressWarnings("unchecked") 28 | public class BigIntegerCartesianProduct extends BigIntegerIndexedSpliterator { 29 | /** 30 | * @param dimensions the cardinalities of the input sets. 31 | */ 32 | public BigIntegerCartesianProduct(int... dimensions) { 33 | this(count(dimensions), dimensions); 34 | } 35 | 36 | BigIntegerCartesianProduct(BigInteger count, int... dimensions) { 37 | super(BigInteger.ZERO, count); 38 | if(Arrays.stream(dimensions).anyMatch(dim -> dim < 0)) throw new IllegalArgumentException("Invalid dimensions: " + Arrays.toString(dimensions)); 39 | this.withValueSupplier(new CartesianProductSupplier.BigInt(dimensions, count)); 40 | this.withAdditionalCharacteristics(DISTINCT); 41 | } 42 | 43 | protected static BigInteger count(int[] dimensions) { 44 | BigInteger cnt = BigInteger.ONE; 45 | for(long dim : dimensions) { 46 | cnt = cnt.multiply(BigInteger.valueOf(dim)); 47 | } 48 | return cnt; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /streamplify/src/main/java/org/beryx/streamplify/product/CartesianProduct.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.product; 17 | 18 | import org.beryx.streamplify.Streamable; 19 | import org.beryx.streamplify.StreamableProxy; 20 | 21 | import java.math.BigInteger; 22 | 23 | /** 24 | * A {@link Streamable} providing streams of cartesian product tuples. 25 | *
This class is a proxy that delegates to either {@link LongCartesianProduct} or {@link BigIntegerCartesianProduct}, depending on the cardinalities of the input sets. 26 | */ 27 | public class CartesianProduct extends StreamableProxy { 28 | private final Streamable delegate; 29 | 30 | /** 31 | * @param dimensions the cardinalities of the input sets. 32 | */ 33 | public CartesianProduct(int... dimensions) { 34 | BigInteger count = BigIntegerCartesianProduct.count(dimensions); 35 | if(count.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) < 0) { 36 | delegate = new LongCartesianProduct(count.longValueExact(), dimensions); 37 | } else { 38 | delegate = new BigIntegerCartesianProduct(count, dimensions); 39 | } 40 | } 41 | 42 | @Override 43 | protected Streamable getDelegate() { 44 | return delegate; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /streamplify/src/main/java/org/beryx/streamplify/product/CartesianProductSupplier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.product; 17 | 18 | import org.beryx.streamplify.IntArraySupplier; 19 | import org.beryx.streamplify.Splittable; 20 | 21 | import java.math.BigInteger; 22 | 23 | /** 24 | * A value supplier for cartesian product. 25 | *
It may compute the next tuple based on the current one, or by unranking an index. 26 | */ 27 | public abstract class CartesianProductSupplier implements IntArraySupplier { 28 | protected final int[] dimensions; 29 | protected final int[] currentProduct; 30 | 31 | CartesianProductSupplier(int[] dimensions) { 32 | this.dimensions = dimensions; 33 | this.currentProduct = new int[dimensions.length]; 34 | } 35 | 36 | @Override 37 | public int[] getCurrentSequence() { 38 | return currentProduct; 39 | } 40 | 41 | @Override 42 | public void computeNext() { 43 | int pos = dimensions.length - 1; 44 | while(pos >= 0 && currentProduct[pos] >= dimensions[pos] - 1) pos--; 45 | if(pos < 0) return; 46 | currentProduct[pos]++; 47 | for(int i = pos + 1; i < dimensions.length; i++) { 48 | currentProduct[i] = 0; 49 | } 50 | } 51 | 52 | public static class Long extends CartesianProductSupplier implements Splittable.LongIndexed { 53 | private final long count; 54 | private long currentIndex = -2; 55 | 56 | public Long(long count, int[] dimensions) { 57 | super(dimensions); 58 | this.count = count; 59 | } 60 | 61 | @Override 62 | public Long split() { 63 | return new Long(count, dimensions); 64 | } 65 | 66 | @Override 67 | public int[] apply(long index) { 68 | boolean useNext = (index == currentIndex + 1); 69 | currentIndex = index; 70 | return getNextSequence(useNext); 71 | } 72 | 73 | @Override 74 | public int[] unrank() { 75 | int[] product = new int[dimensions.length]; 76 | long dividend = currentIndex; 77 | for(int k = dimensions.length - 1; k >= 0; k--) { 78 | product[k] = (int)(dividend % dimensions[k]); 79 | dividend /= dimensions[k]; 80 | } 81 | return product; 82 | } 83 | } 84 | 85 | public static class BigInt extends CartesianProductSupplier implements Splittable.BigIntegerIndexed { 86 | private final BigInteger count; 87 | private BigInteger currentIndex = BigInteger.valueOf(-2); 88 | 89 | public BigInt(int[] dimensions, BigInteger count) { 90 | super(dimensions); 91 | this.count = count; 92 | } 93 | 94 | @Override 95 | public BigInt split() { 96 | return new BigInt(dimensions, count); 97 | } 98 | 99 | @Override 100 | public int[] apply(BigInteger index) { 101 | boolean useNext = index.equals(currentIndex.add(BigInteger.ONE)); 102 | currentIndex = index; 103 | return getNextSequence(useNext); 104 | } 105 | 106 | @Override 107 | public int[] unrank() { 108 | int[] product = new int[dimensions.length]; 109 | BigInteger dividend = currentIndex; 110 | for(int k = dimensions.length - 1; k >= 0; k--) { 111 | BigInteger[] quotientAndRemainder = dividend.divideAndRemainder(BigInteger.valueOf(dimensions[k])); 112 | product[k] = quotientAndRemainder[1].intValueExact(); 113 | dividend = quotientAndRemainder[0]; 114 | } 115 | return product; 116 | } 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /streamplify/src/main/java/org/beryx/streamplify/product/LongCartesianProduct.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.product; 17 | 18 | import org.beryx.streamplify.LongIndexedSpliterator; 19 | 20 | import java.math.BigInteger; 21 | import java.util.Arrays; 22 | 23 | /** 24 | * Provides streams of cartesian product tuples. 25 | *
Can be used when the cardinality of the cartesian product can fit in a long. 26 | * For bigger cardinalities, a {@link BigIntegerCartesianProduct} is needed. 27 | */ 28 | @SuppressWarnings("unchecked") 29 | public class LongCartesianProduct extends LongIndexedSpliterator { 30 | /** 31 | * @param dimensions the cardinalities of the input sets. 32 | */ 33 | public LongCartesianProduct(int... dimensions) { 34 | this(count(dimensions), dimensions); 35 | } 36 | 37 | public LongCartesianProduct(long count, int... dimensions) { 38 | super(0, count); 39 | if(Arrays.stream(dimensions).anyMatch(dim -> dim < 0)) throw new IllegalArgumentException("Invalid dimensions: " + Arrays.toString(dimensions)); 40 | this.withValueSupplier(new CartesianProductSupplier.Long(count, dimensions)); 41 | this.withAdditionalCharacteristics(DISTINCT); 42 | } 43 | 44 | protected static long count(int[] dimensions) { 45 | BigInteger bigCount = BigIntegerCartesianProduct.count(dimensions); 46 | if(bigCount.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) >= 0) throw new IllegalArgumentException("Dimensions too big: " + Arrays.toString(dimensions)); 47 | return bigCount.longValueExact(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /streamplify/src/main/java/org/beryx/streamplify/shared/Unranking.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.shared; 17 | 18 | import java.math.BigInteger; 19 | 20 | public class Unranking { 21 | /** 22 | * Unranks the combination with the given long index. 23 | *
This implementation uses the UNRANKCOMB-D algorithm introduced in: 24 | * Kokosinski, Zbigniew, and Ikki-Machi Tsuruga. "Algorithms for unranking combinations and other related choice functions." (1995). 25 | * 26 | * @param n the total number of elements in the set 27 | * @param k the number of elements taken 28 | * @param count the number of {@code k}-combinations 29 | * @param index the index of the combination to be unranked 30 | * @return the combination corresponding to the given index 31 | */ 32 | public static int[] unrankCombination(int n, int k, long count, long index) { 33 | if (k == 0) return new int[0]; 34 | int[] combi = new int[k]; 35 | long rank = count - 1 - index; 36 | long e = (n - k) * count / n; 37 | int t = n - k + 1; 38 | int m = k; 39 | int p = n - 1; 40 | do { 41 | if (e <= rank) { 42 | combi[k - m] = n - t - m + 1; 43 | if (e > 0) { 44 | rank = rank - e; 45 | e = m * e / p; 46 | } 47 | m--; 48 | p--; 49 | } else { 50 | e = (p - m) * e / p; 51 | t--; 52 | p--; 53 | } 54 | } while (m > 0); 55 | return combi; 56 | } 57 | 58 | /** 59 | /** 60 | * Unranks the combination with the given BigInteger index. 61 | * This implementation uses the UNRANKCOMB-D algorithm introduced in: 62 | * Kokosinski, Zbigniew, and Ikki-Machi Tsuruga. "Algorithms for unranking combinations and other related choice functions." (1995). 63 | * 64 | * @param n the total number of elements in the set 65 | * @param k the number of elements taken 66 | * @param count number of {@code k}-combinations 67 | * @param index the index of the combination to be unranked 68 | * @return the combination corresponding to the given index 69 | */ 70 | public static int[] unrankCombination(int n, int k, BigInteger count, BigInteger index) { 71 | if (k == 0) return new int[0]; 72 | int[] combi = new int[k]; 73 | BigInteger rank = count.subtract(BigInteger.ONE).subtract(index); 74 | BigInteger e = count.multiply(BigInteger.valueOf(n - k)).divide(BigInteger.valueOf(n)); 75 | int t = n - k + 1; 76 | int m = k; 77 | int p = n - 1; 78 | do { 79 | if (e.compareTo(rank) <= 0) { 80 | combi[k - m] = n - t - m + 1; 81 | if (e.compareTo(BigInteger.ZERO) > 0) { 82 | rank = rank.subtract(e); 83 | e = e.multiply(BigInteger.valueOf(m)).divide(BigInteger.valueOf(p)); 84 | } 85 | m--; 86 | p--; 87 | } else { 88 | e = e.multiply(BigInteger.valueOf(p - m)).divide(BigInteger.valueOf(p)); 89 | t--; 90 | p--; 91 | } 92 | } while (m > 0); 93 | return combi; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /streamplify/src/main/java/org/beryx/streamplify/shuffler/BigIntegerShuffler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.shuffler; 17 | 18 | import java.math.BigInteger; 19 | 20 | /** 21 | * Provides a way of shuffling BigInteger indices. 22 | * The shuffling function should be a permutation of the set of indices. 23 | */ 24 | @FunctionalInterface 25 | public interface BigIntegerShuffler { 26 | BigIntegerShuffler IDENTITY = index -> index; 27 | 28 | /** 29 | * Retrieves the value corresponding to {@code index} in the permutation associated with this shuffler. 30 | */ 31 | BigInteger getShuffledIndex(BigInteger index); 32 | } 33 | -------------------------------------------------------------------------------- /streamplify/src/main/java/org/beryx/streamplify/shuffler/DefaultBigIntegerShuffler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.shuffler; 17 | 18 | import java.math.BigInteger; 19 | import java.util.Random; 20 | 21 | /** 22 | * An implementation of {@link BigIntegerShuffler} based on {@link ShufflerImpl}. 23 | */ 24 | public class DefaultBigIntegerShuffler implements BigIntegerShuffler { 25 | private final BigInteger count; 26 | private final ShufflerImpl shufflerImpl; 27 | 28 | /** 29 | * Constructs a shuffler for indices in the range [0 .. {@code count} - 1]. 30 | * @param count the number of indices in the range 31 | */ 32 | public DefaultBigIntegerShuffler(BigInteger count) { 33 | this(count, new Random()); 34 | } 35 | 36 | /** 37 | * Constructs a shuffler for indices in the range [0 .. {@code count} - 1], specifying the random number generator to be used. 38 | * @param count the number of indices in the range 39 | * @param rnd the random number generator to be used 40 | */ 41 | public DefaultBigIntegerShuffler(BigInteger count, Random rnd) { 42 | this.count = count; 43 | this.shufflerImpl = new ShufflerImpl(rnd); 44 | } 45 | 46 | /** 47 | * @param seed the seed of the random generator used by this instance 48 | * @return this instance 49 | */ 50 | public DefaultBigIntegerShuffler withSeed(long seed) { 51 | shufflerImpl.withSeed(seed); 52 | return this; 53 | } 54 | 55 | @Override 56 | public BigInteger getShuffledIndex(BigInteger index) { 57 | return shufflerImpl.getShuffledIndex(index, count); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /streamplify/src/main/java/org/beryx/streamplify/shuffler/DefaultLongShuffler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.shuffler; 17 | 18 | import java.util.Random; 19 | 20 | /** 21 | * An implementation of {@link LongShuffler} based on {@link ShufflerImpl}. 22 | */ 23 | public class DefaultLongShuffler implements LongShuffler { 24 | private final long count; 25 | private final ShufflerImpl shufflerImpl; 26 | 27 | /** 28 | * Constructs a shuffler for indices in the range [0 .. {@code count} - 1]. 29 | * @param count the number of indices in the range 30 | */ 31 | public DefaultLongShuffler(long count) { 32 | this(count, new Random()); 33 | } 34 | 35 | /** 36 | * Constructs a shuffler for indices in the range [0 .. {@code count} - 1], specifying the random number generator to be used. 37 | * @param count the number of indices in the range 38 | * @param rnd the random number generator to be used 39 | */ 40 | public DefaultLongShuffler(long count, Random rnd) { 41 | this.count = count; 42 | this.shufflerImpl = new ShufflerImpl(rnd); 43 | } 44 | 45 | /** 46 | * @param seed the seed of the random generator used by this instance 47 | * @return this instance 48 | */ 49 | public DefaultLongShuffler withSeed(long seed) { 50 | shufflerImpl.withSeed(seed); 51 | return this; 52 | } 53 | 54 | @Override 55 | public long getShuffledIndex(long index) { 56 | return shufflerImpl.getShuffledIndex(index, count); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /streamplify/src/main/java/org/beryx/streamplify/shuffler/LongShuffler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.shuffler; 17 | 18 | /** 19 | * Provides a way of shuffling long indices. 20 | * The shuffling function should be a permutation of the set of indices. 21 | */ 22 | @FunctionalInterface 23 | public interface LongShuffler { 24 | LongShuffler IDENTITY = index -> index; 25 | 26 | /** 27 | * Retrieves the value corresponding to {@code index} in the permutation associated with this shuffler. 28 | */ 29 | long getShuffledIndex(long index); 30 | } 31 | -------------------------------------------------------------------------------- /streamplify/src/main/java/org/beryx/streamplify/shuffler/ShufflerImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify.shuffler; 17 | 18 | import java.math.BigInteger; 19 | import java.util.Arrays; 20 | import java.util.Random; 21 | 22 | /** 23 | * A helper class that implements the shuffling logic used by the default shufflers ({@link DefaultLongShuffler} and {@link DefaultBigIntegerShuffler}). 24 | *
This implementation is able to shuffle indices from very large sets. 25 | *
The algorithm used by this class requires a constant amount of memory and runs in O(B) time, 26 | * where B is the number of bytes used by the BigInteger internal representation of the cardinality of the set of indices. 27 | *
Although it decently scatters the indices, this class will not produce uniformly distributed values 28 | * (unless the set of indexes has a cardinality <= 256 and the random number generator produces uniformly distributed values). 29 | */ 30 | public class ShufflerImpl { 31 | private static final int BYTE_PERMUTATIONS_COUNT = 4; 32 | 33 | private final Random rnd; 34 | private final int[][] bytePermutations = new int[BYTE_PERMUTATIONS_COUNT][]; 35 | private final int[][] bitPermutations = new int[8][]; 36 | 37 | /** 38 | * @param rnd the random number generator used by this instance. 39 | */ 40 | public ShufflerImpl(Random rnd) { 41 | this.rnd = rnd; 42 | for(int i = 0; i < BYTE_PERMUTATIONS_COUNT; i++) { 43 | bytePermutations[i] = getRandomPermutation(256); 44 | } 45 | for(int i = 1; i < 8; i++) { 46 | bitPermutations[i] = getRandomPermutation(1 << i); 47 | } 48 | } 49 | 50 | /** 51 | * @param seed the seed of the random generator used by this instance 52 | * @return this instance 53 | */ 54 | public ShufflerImpl withSeed(long seed) { 55 | rnd.setSeed(seed); 56 | return this; 57 | } 58 | 59 | /** 60 | * Retrieves the long value corresponding to {@code index} in a permutation with {@code count} elements. 61 | */ 62 | public long getShuffledIndex(long index, long count) { 63 | BigInteger bigIndex = BigInteger.valueOf(index); 64 | BigInteger bigCount = BigInteger.valueOf(count); 65 | BigInteger bigShuffled = getShuffledIndex(bigIndex, bigCount); 66 | return bigShuffled.longValueExact(); 67 | } 68 | 69 | /** 70 | * Retrieves the BigInteger value corresponding to {@code index} in a permutation with {@code count} elements. 71 | */ 72 | public BigInteger getShuffledIndex(BigInteger index, BigInteger count) { 73 | int bitCount = count.subtract(BigInteger.ONE).bitLength(); 74 | int wholeBytes = bitCount / 8; 75 | int restBits = bitCount % 8; 76 | int bytesLen = (bitCount + 7) / 8; 77 | 78 | byte[] bytes = index.toByteArray(); 79 | if(bytes.length > bytesLen) { 80 | if(bytes[0] != 0) { 81 | throw new AssertionError("bytes: " + Arrays.toString(bytes)); 82 | } 83 | bytes = Arrays.copyOfRange(bytes, 1, bytes.length); 84 | } 85 | if(bytes.length < bytesLen) { 86 | byte[] tmp = bytes; 87 | bytes = new byte[bytesLen]; 88 | System.arraycopy(tmp, 0, bytes, bytesLen - tmp.length, tmp.length); 89 | } 90 | int bytesOff = bytes.length - bytesLen; 91 | byte[] shuffled = new byte[bytes.length]; 92 | 93 | 94 | int idx = 0; 95 | for(int i = 0; i < wholeBytes; i++) { 96 | idx = (int)((bytes[bytesLen + bytesOff - 1 - i] ^ idx ) & 0xFF); 97 | shuffled[i + bytesOff] = (byte)bytePermutations[i % BYTE_PERMUTATIONS_COUNT][idx]; 98 | } 99 | if(restBits > 0) { 100 | idx = (bytes[bytesOff] ^ idx) & ((1 << restBits) - 1); 101 | int shuffledByte = bitPermutations[restBits][idx]; 102 | shuffled[bytesLen + bytesOff - 1] = (byte) (shuffledByte << (8 - restBits)); 103 | } 104 | 105 | for(int i = 0; i < bytes.length - 1; i++) { 106 | shuffled[bytes.length - 2 - i] ^= shuffled[bytes.length - 1 - i]; 107 | } 108 | 109 | BigInteger bigShuffled = new BigInteger(1, shuffled); 110 | if(restBits > 0) { 111 | bigShuffled = bigShuffled.shiftRight(8 - restBits); 112 | } 113 | if(bigShuffled.compareTo(count) < 0) return bigShuffled; 114 | else return getShuffledIndex(bigShuffled, count); 115 | } 116 | 117 | /** 118 | * @return a random permutation with the given {@code length}. 119 | */ 120 | public int[] getRandomPermutation(int length) { 121 | int[] perm = new int[length]; 122 | for(int i = 0; i < length; i++) { 123 | int j = rnd.nextInt(i + 1); 124 | if(j != i) perm[i] = perm[j]; 125 | perm[j] = i; 126 | } 127 | return perm; 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /streamplify/src/test/groovy/org/beryx/streamplify/CartesianProductSpec.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify 17 | 18 | import org.beryx.streamplify.product.BigIntegerCartesianProduct 19 | import org.beryx.streamplify.product.CartesianProduct 20 | import org.beryx.streamplify.product.LongCartesianProduct 21 | import spock.lang.Specification 22 | import spock.lang.Unroll 23 | 24 | import java.util.stream.Collectors 25 | 26 | @Unroll 27 | class CartesianProductSpec extends Specification { 28 | 29 | def "LongCartesianProduct should throw IllegalArgumentException for dimensions #dimensions"() { 30 | when: 31 | def cartesianProduct = new LongCartesianProduct(dimensions as int[]) 32 | 33 | then: 34 | thrown(IllegalArgumentException) 35 | 36 | where: 37 | dimensions | _ 38 | [-1] | _ 39 | [-1, 1] | _ 40 | [-1, 2, 3] | _ 41 | [-1, 0] | _ 42 | [-1, 0, 1] | _ 43 | [0, -1] | _ 44 | [0, 2, -1] | _ 45 | [2, -1] | _ 46 | [2, -1, 0] | _ 47 | [2, -1, 1] | _ 48 | [2, 0, -1] | _ 49 | [-1, -2] | _ 50 | [-1, -2, -3] | _ 51 | [-1, -2, 0] | _ 52 | [0, -1, -2] | _ 53 | [Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE] | _ 54 | [1_000_000, 1_000_000, 1_000_000, 1_000_000] | _ 55 | } 56 | 57 | def "BigIntegerCartesianProduct should throw IllegalArgumentException for dimensions #dimensions"() { 58 | when: 59 | def cartesianProduct = new BigIntegerCartesianProduct(dimensions as int[]) 60 | 61 | then: 62 | thrown(IllegalArgumentException) 63 | 64 | where: 65 | dimensions | _ 66 | [-1] | _ 67 | [-1, 1] | _ 68 | [-1, 2, 3] | _ 69 | [-1, 0] | _ 70 | [-1, 0, 1] | _ 71 | [0, -1] | _ 72 | [0, 2, -1] | _ 73 | [2, -1] | _ 74 | [2, -1, 0] | _ 75 | [2, -1, 1] | _ 76 | [2, 0, -1] | _ 77 | [-1, -2] | _ 78 | [-1, -2, -3] | _ 79 | [-1, -2, 0] | _ 80 | [0, -1, -2] | _ 81 | } 82 | 83 | 84 | def "should use a #delegateClass.simpleName for dimensions #dimensions"() { 85 | given: 86 | def cartesianProduct = new CartesianProduct(dimensions as int[]) 87 | 88 | expect: 89 | cartesianProduct.delegate.getClass().name == delegateClass.name 90 | 91 | where: 92 | dimensions | delegateClass 93 | [] | LongCartesianProduct 94 | [0] | LongCartesianProduct 95 | [Integer.MAX_VALUE] | LongCartesianProduct 96 | [1_000_000, 1_000_000, 1_000_000] | LongCartesianProduct 97 | [Integer.MAX_VALUE, Integer.MAX_VALUE] | LongCartesianProduct 98 | [Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE] | BigIntegerCartesianProduct 99 | [1_000_000, 1_000_000, 1_000_000, 1_000_000] | BigIntegerCartesianProduct 100 | } 101 | 102 | def "LongCartesianProduct should correctly produce a cartesian product stream for dimensions #dimensions"() { 103 | given: 104 | def stream = new LongCartesianProduct(dimensions as int[]).stream() 105 | 106 | when: 107 | def prod = stream.map { int[] arr -> (arr as List).toString() }.collect(Collectors.toList()) 108 | 109 | then: 110 | prod == product 111 | 112 | where: 113 | dimensions | product 114 | [] | ['[]'] 115 | [0] | [] 116 | [3, 0, 4] | [] 117 | [1, 1] | ['[0, 0]'] 118 | [3, 4] | ['[0, 0]', '[0, 1]', '[0, 2]', '[0, 3]', '[1, 0]', '[1, 1]', '[1, 2]', '[1, 3]', '[2, 0]', '[2, 1]', '[2, 2]', '[2, 3]'] 119 | [2, 3, 2] | ['[0, 0, 0]', '[0, 0, 1]', '[0, 1, 0]', '[0, 1, 1]', '[0, 2, 0]', '[0, 2, 1]', '[1, 0, 0]', '[1, 0, 1]', '[1, 1, 0]', '[1, 1, 1]', '[1, 2, 0]', '[1, 2, 1]'] 120 | } 121 | 122 | def "BigIntegerCartesianProduct should correctly produce a cartesian product stream for dimensions #dimensions"() { 123 | given: 124 | def stream = new BigIntegerCartesianProduct(dimensions as int[]).stream() 125 | 126 | when: 127 | def prod = stream.map { int[] arr -> (arr as List).toString() }.collect(Collectors.toList()) 128 | 129 | then: 130 | prod == product 131 | 132 | where: 133 | dimensions | product 134 | [] | ['[]'] 135 | [0] | [] 136 | [3, 0, 4] | [] 137 | [1, 1] | ['[0, 0]'] 138 | [3, 4] | ['[0, 0]', '[0, 1]', '[0, 2]', '[0, 3]', '[1, 0]', '[1, 1]', '[1, 2]', '[1, 3]', '[2, 0]', '[2, 1]', '[2, 2]', '[2, 3]'] 139 | [2, 3, 2] | ['[0, 0, 0]', '[0, 0, 1]', '[0, 1, 0]', '[0, 1, 1]', '[0, 2, 0]', '[0, 2, 1]', '[1, 0, 0]', '[1, 0, 1]', '[1, 1, 0]', '[1, 1, 1]', '[1, 2, 0]', '[1, 2, 1]'] 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /streamplify/src/test/groovy/org/beryx/streamplify/CombinationsSpec.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify 17 | 18 | import org.beryx.streamplify.combination.BigIntegerCombinations 19 | import org.beryx.streamplify.combination.Combinations 20 | import org.beryx.streamplify.combination.LongCombinations 21 | import spock.lang.Specification 22 | import spock.lang.Unroll 23 | 24 | import java.util.stream.Collectors 25 | 26 | @Unroll 27 | class CombinationsSpec extends Specification { 28 | 29 | def "LongCombinations should throw IllegalArgumentException for n=#n and k=#k"() { 30 | when: 31 | def combinations = new LongCombinations(n, k) 32 | 33 | then: 34 | thrown(IllegalArgumentException) 35 | 36 | where: 37 | n | k 38 | -1 | 1 39 | 1 | -1 40 | -1 | -1 41 | 0 | -1 42 | -1 | 0 43 | 0 | 1 44 | 0 | 2 45 | 1 | 2 46 | 3 | 4 47 | 61 | 30 48 | Combinations.MAX_N + 1 | 1 49 | Combinations.MAX_N + 1 | Combinations.MAX_N 50 | 51 | } 52 | 53 | def "BigIntegerCombinations should throw IllegalArgumentException for n=#n and k=#k"() { 54 | when: 55 | def combinations = new BigIntegerCombinations(n, k) 56 | 57 | then: 58 | thrown(IllegalArgumentException) 59 | 60 | where: 61 | n | k 62 | -1 | 1 63 | 1 | -1 64 | -1 | -1 65 | 0 | -1 66 | -1 | 0 67 | 0 | 1 68 | 0 | 2 69 | 1 | 2 70 | 3 | 4 71 | Combinations.MAX_N + 1 | 1 72 | Combinations.MAX_N + 1 | Combinations.MAX_N 73 | 74 | } 75 | 76 | 77 | def "should use a #delegateClass.simpleName for n=#n, k=#k"() { 78 | given: 79 | def combinations = new Combinations(n, k) 80 | 81 | expect: 82 | combinations.delegate.getClass().name == delegateClass.name 83 | 84 | where: 85 | n | k | delegateClass 86 | 0 | 0 | LongCombinations 87 | 1 | 0 | LongCombinations 88 | 1 | 1 | LongCombinations 89 | 2 | 0 | LongCombinations 90 | 2 | 1 | LongCombinations 91 | 2 | 2 | LongCombinations 92 | 10 | 5 | LongCombinations 93 | 20 | 19 | LongCombinations 94 | 61 | 20 | LongCombinations 95 | 61 | 30 | BigIntegerCombinations 96 | Combinations.MAX_N | 1 | LongCombinations 97 | Combinations.MAX_N | Combinations.MAX_N | LongCombinations 98 | Combinations.MAX_N | ((int) (Combinations.MAX_N / 2)) | BigIntegerCombinations 99 | } 100 | 101 | def "LongCombinations should correctly produce a combination stream for n=#n, k=#k"() { 102 | given: 103 | def stream = new LongCombinations(n, k).stream() 104 | 105 | when: 106 | def comb = stream.map { int[] arr -> (arr as List).toString() }.collect(Collectors.toList()) 107 | 108 | then: 109 | comb == combinations 110 | 111 | where: 112 | n | k | combinations 113 | 0 | 0 | ['[]'] 114 | 1 | 0 | ['[]'] 115 | 1 | 1 | ['[0]'] 116 | 2 | 0 | ['[]'] 117 | 2 | 1 | ['[0]', '[1]'] 118 | 2 | 2 | ['[0, 1]'] 119 | 5 | 3 | ['[0, 1, 2]', '[0, 1, 3]', '[0, 1, 4]', '[0, 2, 3]', '[0, 2, 4]', '[0, 3, 4]', '[1, 2, 3]', '[1, 2, 4]', '[1, 3, 4]', '[2, 3, 4]'] 120 | } 121 | 122 | 123 | def "BigIntegerCombinations should correctly produce a combination stream for n=#n, k=#k"() { 124 | given: 125 | def stream = new BigIntegerCombinations(n, k).stream() 126 | 127 | when: 128 | def comb = stream.map { int[] arr -> (arr as List).toString() }.collect(Collectors.toList()) 129 | 130 | then: 131 | comb == combinations 132 | 133 | where: 134 | n | k | combinations 135 | 0 | 0 | ['[]'] 136 | 1 | 0 | ['[]'] 137 | 1 | 1 | ['[0]'] 138 | 2 | 0 | ['[]'] 139 | 2 | 1 | ['[0]', '[1]'] 140 | 2 | 2 | ['[0, 1]'] 141 | 5 | 3 | ['[0, 1, 2]', '[0, 1, 3]', '[0, 1, 4]', '[0, 2, 3]', '[0, 2, 4]', '[0, 3, 4]', '[1, 2, 3]', '[1, 2, 4]', '[1, 3, 4]', '[2, 3, 4]'] 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /streamplify/src/test/groovy/org/beryx/streamplify/LongIndexedSpliteratorSpec.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify 17 | 18 | import spock.lang.Specification 19 | import spock.lang.Unroll 20 | 21 | @Unroll 22 | class LongIndexedSpliteratorSpec extends Specification { 23 | def "should throw IllegalArgumentException for origin=#origin and fence=#fence"() { 24 | when: 25 | new LongIndexedSpliterator(origin, fence) 26 | 27 | then: 28 | thrown(IllegalArgumentException) 29 | 30 | where: 31 | origin | fence 32 | -1 | -1 33 | -1 | 0 34 | -1 | 1 35 | 0 | -1 36 | 1 | -1 37 | 7 | 6 38 | } 39 | 40 | def "count() should return #count for origin=#origin and fence=#fence"() { 41 | given: 42 | def streamable = new LongIndexedSpliterator(origin, fence) 43 | 44 | expect: 45 | streamable.count() == count 46 | 47 | where: 48 | origin | fence | count 49 | 0 | 0 | 0 50 | 0 | 1 | 1 51 | 1 | 1 | 0 52 | 0 | 2 | 2 53 | 111 | 111 | 0 54 | 111 | 222 | 111 55 | 0 | Long.MAX_VALUE | Long.MAX_VALUE 56 | 111 | Long.MAX_VALUE | (Long.MAX_VALUE - 111) 57 | } 58 | 59 | def "bigCount() should return #count for origin=#origin and fence=#fence"() { 60 | given: 61 | def streamable = new LongIndexedSpliterator(origin, fence) 62 | 63 | expect: 64 | streamable.bigCount() == new BigInteger("$count") 65 | 66 | where: 67 | origin | fence | count 68 | 0 | 0 | 0 69 | 0 | 1 | 1 70 | 1 | 1 | 0 71 | 0 | 2 | 2 72 | 111 | 111 | 0 73 | 111 | 222 | 111 74 | 0 | Long.MAX_VALUE | Long.MAX_VALUE 75 | 111 | Long.MAX_VALUE | (Long.MAX_VALUE - 111) 76 | } 77 | 78 | def "skip(#n) should set index to #newIndex for origin=#origin and fence=#fence"() { 79 | given: 80 | def streamable = new LongIndexedSpliterator(origin, fence) 81 | 82 | when: 83 | streamable.skip(n) 84 | 85 | then: 86 | streamable.getIndex() == newIndex 87 | 88 | where: 89 | origin | fence | n | newIndex 90 | 0 | 0 | 0 | 0 91 | 0 | 1 | 1 | 1 92 | 0 | 1 | 2 | 1 93 | 0 | 0 | Long.MAX_VALUE | 0 94 | 0 | 1 | Long.MAX_VALUE | 1 95 | 0 | Long.MAX_VALUE | 0 | 0 96 | 0 | Long.MAX_VALUE | Long.MAX_VALUE | Long.MAX_VALUE 97 | 111 | 333 | 111 | 222 98 | 111 | 222 | 111 | 222 99 | 111 | 222 | 333 | 222 100 | 111 | 222 | Long.MAX_VALUE | 222 101 | 111 | 222 | (Long.MAX_VALUE - 111) | 222 102 | 111 | Long.MAX_VALUE | 222 | 333 103 | 111 | (Long.MAX_VALUE - 111) | 222 | 333 104 | 111 | Long.MAX_VALUE | Long.MAX_VALUE | Long.MAX_VALUE 105 | 111 | Long.MAX_VALUE | (Long.MAX_VALUE - 111) | Long.MAX_VALUE 106 | 111 | Long.MAX_VALUE | (Long.MAX_VALUE - 222) | (Long.MAX_VALUE - 111) 107 | 111 | (Long.MAX_VALUE - 111) | Long.MAX_VALUE | (Long.MAX_VALUE - 111) 108 | 111 | (Long.MAX_VALUE - 111) | (Long.MAX_VALUE - 111) | (Long.MAX_VALUE - 111) 109 | 111 | (Long.MAX_VALUE - 111) | (Long.MAX_VALUE - 222) | (Long.MAX_VALUE - 111) 110 | 111 | (Long.MAX_VALUE - 333) | (Long.MAX_VALUE - 222) | (Long.MAX_VALUE - 333) 111 | 111 | (Long.MAX_VALUE - 111) | (Long.MAX_VALUE - 333) | (Long.MAX_VALUE - 222) 112 | } 113 | 114 | 115 | def "big skip(#n) should set index to #newIndex for origin=#origin and fence=#fence"() { 116 | given: 117 | def streamable = new LongIndexedSpliterator(origin, fence) 118 | 119 | when: 120 | streamable.skip(new BigInteger("$n")) 121 | 122 | then: 123 | streamable.getIndex() == newIndex 124 | 125 | where: 126 | origin | fence | n | newIndex 127 | 0 | 0 | 0 | 0 128 | 0 | 1 | 1 | 1 129 | 0 | 1 | 2 | 1 130 | 0 | 0 | Long.MAX_VALUE | 0 131 | 0 | 1 | Long.MAX_VALUE | 1 132 | 0 | Long.MAX_VALUE | 0 | 0 133 | 0 | Long.MAX_VALUE | Long.MAX_VALUE | Long.MAX_VALUE 134 | 111 | 333 | 111 | 222 135 | 111 | 222 | 111 | 222 136 | 111 | 222 | 333 | 222 137 | 111 | 222 | Long.MAX_VALUE | 222 138 | 111 | 222 | (Long.MAX_VALUE - 111) | 222 139 | 111 | Long.MAX_VALUE | 222 | 333 140 | 111 | (Long.MAX_VALUE - 111) | 222 | 333 141 | 111 | Long.MAX_VALUE | Long.MAX_VALUE | Long.MAX_VALUE 142 | 111 | Long.MAX_VALUE | (Long.MAX_VALUE - 111) | Long.MAX_VALUE 143 | 111 | Long.MAX_VALUE | (Long.MAX_VALUE - 222) | (Long.MAX_VALUE - 111) 144 | 111 | (Long.MAX_VALUE - 111) | Long.MAX_VALUE | (Long.MAX_VALUE - 111) 145 | 111 | (Long.MAX_VALUE - 111) | (Long.MAX_VALUE - 111) | (Long.MAX_VALUE - 111) 146 | 111 | (Long.MAX_VALUE - 111) | (Long.MAX_VALUE - 222) | (Long.MAX_VALUE - 111) 147 | 111 | (Long.MAX_VALUE - 333) | (Long.MAX_VALUE - 222) | (Long.MAX_VALUE - 333) 148 | 111 | (Long.MAX_VALUE - 111) | (Long.MAX_VALUE - 333) | (Long.MAX_VALUE - 222) 149 | 0 | 0 | "12345678901234567890" | 0 150 | 0 | 1 | "12345678901234567890" | 1 151 | 0 | (Long.MAX_VALUE - 1) | "12345678901234567890" | (Long.MAX_VALUE - 1) 152 | 0 | Long.MAX_VALUE | "12345678901234567890" | Long.MAX_VALUE 153 | 111 | (Long.MAX_VALUE - 222) | "12345678901234567890" | (Long.MAX_VALUE - 222) 154 | 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /streamplify/src/test/groovy/org/beryx/streamplify/PartialPermutationsSpec.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify 17 | 18 | import org.beryx.streamplify.partperm.BigIntegerPartialPermutations 19 | import org.beryx.streamplify.partperm.LongPartialPermutations 20 | import org.beryx.streamplify.partperm.PartialPermutations 21 | import spock.lang.Specification 22 | 23 | import java.util.stream.Collectors 24 | 25 | class PartialPermutationsSpec extends Specification { 26 | 27 | def "LongPartialPermutations should throw IllegalArgumentException for length #length"() { 28 | when: 29 | def partialPermutations = new LongPartialPermutations(length) 30 | 31 | then: 32 | thrown(IllegalArgumentException) 33 | 34 | where: 35 | length | _ 36 | -1 | _ 37 | -2 | _ 38 | LongPartialPermutations.MAX_LENGTH + 1 | _ 39 | Integer.MAX_VALUE | _ 40 | -Integer.MAX_VALUE | _ 41 | } 42 | 43 | def "BigIntegerPartialPermutations should throw IllegalArgumentException for length #length"() { 44 | when: 45 | def partialPermutations = new BigIntegerPartialPermutations(length) 46 | 47 | then: 48 | thrown(IllegalArgumentException) 49 | 50 | where: 51 | length | _ 52 | -1 | _ 53 | -2 | _ 54 | BigIntegerPartialPermutations.MAX_LENGTH + 1 | _ 55 | Integer.MAX_VALUE | _ 56 | -Integer.MAX_VALUE | _ 57 | } 58 | 59 | def "should use a #delegateClass.simpleName for length #length"() { 60 | given: 61 | def partialPermutations = new PartialPermutations(length) 62 | 63 | expect: 64 | partialPermutations.delegate.getClass().name == delegateClass.name 65 | 66 | where: 67 | length | delegateClass 68 | 0 | LongPartialPermutations 69 | 1 | LongPartialPermutations 70 | 2 | LongPartialPermutations 71 | LongPartialPermutations.MAX_LENGTH | LongPartialPermutations 72 | (LongPartialPermutations.MAX_LENGTH + 1) | BigIntegerPartialPermutations 73 | } 74 | 75 | def "LongPartialPermutations should correctly produce a partial permutation stream for length #length"() { 76 | given: 77 | def stream = new LongPartialPermutations(length).stream() 78 | 79 | when: 80 | def partialPerm = stream.map { int[] arr -> (arr as List).toString() }.collect(Collectors.toList()) 81 | 82 | then: 83 | partialPerm == partialPermutations 84 | 85 | where: 86 | length | partialPermutations 87 | 0 | ['[]'] 88 | 1 | ['[-1]', '[0]'] 89 | 2 | ['[-1, -1]', '[-1, 0]', '[0, -1]', '[-1, 1]', '[1, -1]', '[0, 1]', '[1, 0]'] 90 | } 91 | 92 | def "BigIntegerPartialPermutations should correctly produce a partial permutation stream for length #length"() { 93 | given: 94 | def stream = new BigIntegerPartialPermutations(length).stream() 95 | 96 | when: 97 | def partialPerm = stream.map { int[] arr -> (arr as List).toString() }.collect(Collectors.toList()) 98 | 99 | then: 100 | partialPerm == partialPermutations 101 | 102 | where: 103 | length | partialPermutations 104 | 0 | ['[]'] 105 | 1 | ['[-1]', '[0]'] 106 | 2 | ['[-1, -1]', '[-1, 0]', '[0, -1]', '[-1, 1]', '[1, -1]', '[0, 1]', '[1, 0]'] 107 | } 108 | 109 | def "PartialPermutations should skip correctly #skip partials permutations with length #length"() { 110 | given: 111 | def stream = new PartialPermutations(length).skip(skip).stream() 112 | 113 | when: 114 | def partialPerm = stream.map { int[] arr -> (arr as List).toString() }.findFirst().orElse('') 115 | 116 | then: 117 | partialPerm == permutation 118 | 119 | where: 120 | length | skip | permutation 121 | 2 | 0 | '[-1, -1]' 122 | 2 | 1 | '[-1, 0]' 123 | 6 | 7329 | '[1, -1, -1, 4, 2, 5]' 124 | 25 | 10 | '[-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1]' 125 | 21 | (new BigInteger('44552237162692939114280')) | '[20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 0, 1]' 126 | } 127 | 128 | def "LongPartialPermutations should calculate the correct number of partial permutations given length #length"() { 129 | expect: 130 | LongPartialPermutations.numberOfPermutations(length) == numberOfPartialPermutations 131 | 132 | where: 133 | length | numberOfPartialPermutations 134 | 0 | 1 135 | 1 | 2 136 | 7 | 130922 137 | 8 | 1441729 138 | 18 | 2968971263911288999 139 | } 140 | 141 | def "BigIntegerPartialPermutations should calculate the correct number of partial permutations given length #length"() { 142 | expect: 143 | BigIntegerPartialPermutations.numberOfPermutations(length) == numberOfPartialPermutations 144 | 145 | where: 146 | length | numberOfPartialPermutations 147 | 0 | 1 148 | 1 | 2 149 | 7 | 130922 150 | 30 | new BigInteger('1240758969214239528262796909096631871') 151 | } 152 | 153 | } 154 | -------------------------------------------------------------------------------- /streamplify/src/test/groovy/org/beryx/streamplify/PermutationsSpec.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify 17 | 18 | import org.beryx.streamplify.permutation.BigIntegerPermutations 19 | import org.beryx.streamplify.permutation.LongPermutations 20 | import org.beryx.streamplify.permutation.Permutations 21 | import spock.lang.Specification 22 | import spock.lang.Unroll 23 | 24 | import java.util.stream.Collectors 25 | 26 | @Unroll 27 | class PermutationsSpec extends Specification { 28 | 29 | def "LongPermutations should throw IllegalArgumentException for length #length"() { 30 | when: 31 | def permutations = new LongPermutations(length) 32 | 33 | then: 34 | thrown(IllegalArgumentException) 35 | 36 | where: 37 | length | _ 38 | -1 | _ 39 | -2 | _ 40 | 21 | _ 41 | Integer.MAX_VALUE | _ 42 | -Integer.MAX_VALUE | _ 43 | } 44 | 45 | def "BigIntegerPermutations should throw IllegalArgumentException for length #length"() { 46 | when: 47 | def permutations = new BigIntegerPermutations(length) 48 | 49 | then: 50 | thrown(IllegalArgumentException) 51 | 52 | where: 53 | length | _ 54 | -1 | _ 55 | -2 | _ 56 | BigIntegerPermutations.MAX_LENGTH + 1 | _ 57 | Integer.MAX_VALUE | _ 58 | -Integer.MAX_VALUE | _ 59 | } 60 | 61 | def "should use a #delegateClass.simpleName for length #length"() { 62 | given: 63 | def permutations = new Permutations(length) 64 | 65 | expect: 66 | permutations.delegate.getClass().name == delegateClass.name 67 | 68 | where: 69 | length | delegateClass 70 | 0 | LongPermutations 71 | 1 | LongPermutations 72 | 2 | LongPermutations 73 | LongPermutations.MAX_LENGTH | LongPermutations 74 | (LongPermutations.MAX_LENGTH + 1) | BigIntegerPermutations 75 | BigIntegerPermutations.MAX_LENGTH | BigIntegerPermutations 76 | } 77 | 78 | def "LongPermutations should correctly produce a permutation stream for length #length"() { 79 | given: 80 | def stream = new LongPermutations(length).stream() 81 | 82 | when: 83 | def perm = stream.map { int[] arr -> (arr as List).toString() }.collect(Collectors.toList()) 84 | 85 | then: 86 | perm == permutations 87 | 88 | where: 89 | length | permutations 90 | 0 | ['[]'] 91 | 1 | ['[0]'] 92 | 2 | ['[0, 1]', '[1, 0]'] 93 | 3 | ['[0, 1, 2]', '[0, 2, 1]', '[1, 0, 2]', '[1, 2, 0]', '[2, 0, 1]', '[2, 1, 0]'] 94 | } 95 | 96 | def "BigIntegerPermutations should correctly produce a permutation stream for length #length"() { 97 | given: 98 | def stream = new BigIntegerPermutations(length).stream() 99 | 100 | when: 101 | def perm = stream.map { int[] arr -> (arr as List).toString() }.collect(Collectors.toList()) 102 | 103 | then: 104 | perm == permutations 105 | 106 | where: 107 | length | permutations 108 | 0 | ['[]'] 109 | 1 | ['[0]'] 110 | 2 | ['[0, 1]', '[1, 0]'] 111 | 3 | ['[0, 1, 2]', '[0, 2, 1]', '[1, 0, 2]', '[1, 2, 0]', '[2, 0, 1]', '[2, 1, 0]'] 112 | } 113 | 114 | def "should skip correctly #skip permutations with length #length"() { 115 | given: 116 | def stream = new Permutations(length).skip(skip).stream() 117 | 118 | when: 119 | def perm = stream.map { int[] arr -> (arr as List).toString() }.findFirst().orElse('') 120 | 121 | then: 122 | perm == permutation 123 | 124 | where: 125 | length | skip | permutation 126 | 2 | 0 | '[0, 1]' 127 | 2 | 1 | '[1, 0]' 128 | 2 | 2 | '' 129 | 2 | 3 | '' 130 | 3 | 4 | '[2, 0, 1]' 131 | 25 | 5 | '[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 24, 23, 22]' 132 | 25 | (new BigInteger('12345678901234567890123456')) | '[19, 22, 12, 16, 5, 3, 2, 7, 17, 21, 10, 4, 8, 24, 6, 18, 20, 23, 9, 11, 15, 0, 1, 13, 14]' 133 | 25 | (new BigInteger('123456789012345678901234567')) | '' 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /streamplify/src/test/groovy/org/beryx/streamplify/PowerSetSpec.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify 17 | 18 | import org.beryx.streamplify.powerset.BigIntegerPowerSet; 19 | import org.beryx.streamplify.powerset.LongPowerSet 20 | import org.beryx.streamplify.powerset.PowerSet 21 | import spock.lang.Specification 22 | import spock.lang.Unroll; 23 | 24 | import java.util.stream.Collectors; 25 | 26 | @Unroll 27 | class PowerSetSpec extends Specification { 28 | 29 | def "LongPowerSet should throw IllegalArgumentException for length #length"() { 30 | when: 31 | def powerSet = new LongPowerSet(length); 32 | 33 | then: 34 | thrown(IllegalArgumentException); 35 | 36 | where: 37 | length | _ 38 | -1 | _ 39 | -2 | _ 40 | 63 | _ 41 | Integer.MAX_VALUE | _ 42 | -Integer.MAX_VALUE | _ 43 | } 44 | 45 | def "BigIntegerPowerSet should throw IllegalArgumentException for length #length"() { 46 | when: 47 | def powerSet = new BigIntegerPowerSet(length); 48 | 49 | then: 50 | thrown(IllegalArgumentException); 51 | 52 | where: 53 | length | _ 54 | -1 | _ 55 | -2 | _ 56 | 512 | _ 57 | Integer.MAX_VALUE | _ 58 | -Integer.MAX_VALUE | _ 59 | } 60 | 61 | def "should use a #delegateClass.simpleName for length #length"() { 62 | given: 63 | def powerSet = new PowerSet(length) 64 | 65 | expect: 66 | powerSet.delegate.getClass().name == delegateClass.name 67 | 68 | where: 69 | length | delegateClass 70 | 0 | LongPowerSet 71 | 1 | LongPowerSet 72 | 62 | LongPowerSet 73 | 63 | BigIntegerPowerSet 74 | } 75 | 76 | def "LongPowerSet should correctly produce a powerset stream for length #length"() { 77 | given: 78 | def stream = new LongPowerSet(length).stream() 79 | 80 | when: 81 | def powerSet = stream.map { int[] arr -> (arr as List).toString() }.collect(Collectors.toList()) 82 | 83 | then: 84 | powerSet == expectedPowerSet 85 | 86 | where: 87 | length | expectedPowerSet 88 | 0 | ['[]'] 89 | 1 | ['[]', '[0]'] 90 | 2 | ['[]', '[0]', '[1]', '[0, 1]'] 91 | 3 | ['[]', '[0]', '[1]', '[0, 1]', '[2]', '[0, 2]', '[1, 2]', '[0, 1, 2]'] 92 | } 93 | 94 | def "BigIntegerPowerSet should correctly produce a powerset stream for length #length"() { 95 | given: 96 | def stream = new BigIntegerPowerSet(length).stream() 97 | 98 | when: 99 | def powerSet = stream.map { int[] arr -> (arr as List).toString() }.collect(Collectors.toList()) 100 | 101 | then: 102 | powerSet == expectedPowerSet 103 | 104 | where: 105 | length | expectedPowerSet 106 | 0 | ['[]'] 107 | 1 | ['[]', '[0]'] 108 | 2 | ['[]', '[0]', '[1]', '[0, 1]'] 109 | 3 | ['[]', '[0]', '[1]', '[0, 1]', '[2]', '[0, 2]', '[1, 2]', '[0, 1, 2]'] 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /streamplify/src/test/groovy/org/beryx/streamplify/ShufflerSpec.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.beryx.streamplify 17 | 18 | import org.beryx.streamplify.shuffler.ShufflerImpl 19 | import spock.lang.Specification 20 | import spock.lang.Unroll 21 | 22 | @Unroll 23 | public class ShufflerSpec extends Specification { 24 | def shuffler = new ShufflerImpl(new Random()) 25 | 26 | def "should shuffle all #count elements using long index"() { 27 | when: 28 | def shuffledIndexes = [] as Set 29 | for(long i = 0; i < count; i++) { 30 | long shuffled = shuffler.getShuffledIndex(i, count); 31 | shuffledIndexes << shuffled 32 | } 33 | 34 | then: 35 | shuffledIndexes.size() == count 36 | shuffledIndexes.min() == 0 37 | shuffledIndexes.max() == count - 1 38 | 39 | where: 40 | count << (1..258) + (1022..1026) + (32766..32770) + (65534..65538) 41 | } 42 | 43 | def "should shuffle all #count elements using BigInteger index"() { 44 | when: 45 | def shuffledIndexes = [] as Set 46 | for(long i = 0; i < count; i++) { 47 | BigInteger shuffled = shuffler.getShuffledIndex(i, BigInteger.valueOf(count)); 48 | shuffledIndexes << shuffled 49 | } 50 | 51 | then: 52 | shuffledIndexes.size() == count 53 | shuffledIndexes.min() == BigInteger.ZERO 54 | shuffledIndexes.max() == BigInteger.valueOf(count) - 1 55 | 56 | where: 57 | count << (1..258) + (1022..1026) + (32766..32770) + (65534..65538) 58 | } 59 | 60 | def "should shuffle #sampleCount elements from a total of #count, starting with index #startIndex"() { 61 | when: 62 | Set shuffledIndexes = [] 63 | def bigCount = new BigInteger("$count") 64 | def bigStartIndex = new BigInteger("$startIndex") 65 | for(long i = 0; i < sampleCount; i++) { 66 | def bigIndex = bigStartIndex.add(BigInteger.valueOf(i)) 67 | BigInteger shuffled = shuffler.getShuffledIndex(bigIndex, bigCount); 68 | shuffledIndexes << shuffled 69 | } 70 | 71 | then: 72 | shuffledIndexes.size() == sampleCount 73 | (shuffledIndexes.min() <=> BigInteger.ZERO) >= 0 74 | (shuffledIndexes.max() <=> bigCount) < 0 75 | 76 | where: 77 | startIndex | count | sampleCount 78 | 0 | (Long.MAX_VALUE - 2) | 10000 79 | (Long.MAX_VALUE >> 1) | (Long.MAX_VALUE - 1) | 10000 80 | (Long.MAX_VALUE >> 2) | Long.MAX_VALUE | 10000 81 | 0 | "10000000000000000000000" | 10000 82 | "10000000000000000000000" | "20000000000000000000000" | 10000 83 | "20000000000000000000000" | "20000000000000000011111" | 11111 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /streamplify/src/test/resources/logback.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import ch.qos.logback.classic.encoder.PatternLayoutEncoder 17 | import ch.qos.logback.core.ConsoleAppender 18 | 19 | import static ch.qos.logback.classic.Level.OFF 20 | 21 | appender("STDOUT", ConsoleAppender) { 22 | encoder(PatternLayoutEncoder) { 23 | pattern = "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" 24 | } 25 | } 26 | //logger("org.beryx.streamplify", TRACE) 27 | root(OFF, ["STDOUT"]) 28 | -------------------------------------------------------------------------------- /travis-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -ev 3 | ./gradlew --no-daemon build javadoc asciidoc 4 | 5 | if [ "${TRAVIS_PULL_REQUEST}" == "false" -a "${TRAVIS_BRANCH}" == "master" ]; then 6 | if [ "`git ls-remote origin gh-pages`" == "" ]; then 7 | ./gradlew --no-daemon publishGhPages --rerun-tasks --info --stacktrace -PghPageType=init 8 | fi 9 | ./gradlew --no-daemon publishGhPages --rerun-tasks --info --stacktrace -PghPageType=latest 10 | ./gradlew --no-daemon publishGhPages --rerun-tasks --info --stacktrace -PghPageType=version 11 | fi 12 | --------------------------------------------------------------------------------