001package squidpony.squidmath;
002
003/**
004 * An interface for "point hashes", that is, functions that produce usually-unique integer results given multiple
005 * integer inputs. The hash functions this guarantees an implementor will provide all take int inputs and return an int.
006 * There are lots of cases where an implementor would have other functions that take long inputs or return longs, and in
007 * those cases the interface methods would probably be implemented by delegating to the long inputs and/or casting the
008 * result to a long. Implementors must have a {@link #setState(int)} function, but it doesn't have to do anything if the
009 * algorithm doesn't support a state; similarly, {@link #hashWithState(int, int, int)} can return the same thing as
010 * {@link #hash(int, int)} if states aren't supported. If states are supported, then calling {@link #hash(int, int)}
011 * while the state is, for example, 42 should be the same as calling {@link #hashWithState(int, int, int)} with a state
012 * parameter of 42 (regardless of what the state actually is in the implementor).
013 * <br>
014 * Created by Tommy Ettinger on 4/13/2020.
015 */
016public interface IPointHash {
017    void setState(int state);
018    int hash(int x, int y);
019    int hash(int x, int y, int z);
020    int hash(int x, int y, int z, int w);
021    int hash(int x, int y, int z, int w, int u, int v);
022    int hashWithState(int x, int y, int state);
023    int hashWithState(int x, int y, int z, int state);
024    int hashWithState(int x, int y, int z, int w, int state);
025    int hashWithState(int x, int y, int z, int w, int u, int v, int state);
026
027    /**
028     * A convenience abstract class to implement IPointHash when you have an int for state. Subclasses will need to
029     * implement {@link #hashWithState(int, int, int)},  {@link #hashWithState(int, int, int, int)},
030     * {@link #hashWithState(int, int, int, int, int)}, and  {@link #hashWithState(int, int, int, int, int, int, int)}.
031     * They can optionally override {@link #setState(int)}, and can at their discretion provide an accessor for the
032     * protected int {@link #state}.
033     */
034    abstract class IntImpl implements IPointHash {
035        protected int state = 42;
036        public IntImpl(){
037            setState(42);
038        }
039        public IntImpl(int state){
040            setState(state);
041        }
042
043        @Override
044        public void setState(int state) {
045            this.state = state;
046        }
047
048        @Override
049        public int hash(int x, int y) {
050            return hashWithState(x, y, state);
051        }
052
053        @Override
054        public int hash(int x, int y, int z) {
055            return hashWithState(x, y, z, state);
056        }
057
058        @Override
059        public int hash(int x, int y, int z, int w) {
060            return hashWithState(x, y, z, w, state);
061        }
062
063        @Override
064        public int hash(int x, int y, int z, int w, int u, int v) {
065            return hashWithState(x, y, z, w, u, v, state);
066        }
067    }
068    /**
069     * A convenience abstract class to implement IPointHash when you have a long for state. Subclasses will need to
070     * implement {@link #hashWithState(int, int, int)},  {@link #hashWithState(int, int, int, int)},
071     * {@link #hashWithState(int, int, int, int, int)}, and  {@link #hashWithState(int, int, int, int, int, int, int)}.
072     * They can optionally override {@link #setState(int)} or {@link #setState(long)}, and can at their discretion
073     * provide an accessor for the protected long {@link #state}.
074     */
075    abstract class LongImpl implements IPointHash {
076        protected long state = 42;
077        public LongImpl(){
078            setState(42);
079        }
080        public LongImpl(int state){
081            setState(state);
082        }
083        public LongImpl(long state){
084            setState(state);
085        }
086
087        @Override
088        public void setState(int state) {
089            this.state = state;
090        }
091        
092        public void setState(long state){
093            this.state = state;
094        }
095
096        @Override
097        public int hash(int x, int y) {
098            return hashWithState(x, y, (int) (state ^ state >>> 32));
099        }
100
101        @Override
102        public int hash(int x, int y, int z) {
103            return hashWithState(x, y, z, (int) (state ^ state >>> 32));
104        }
105
106        @Override
107        public int hash(int x, int y, int z, int w) {
108            return hashWithState(x, y, z, w, (int) (state ^ state >>> 32));
109        }
110
111        @Override
112        public int hash(int x, int y, int z, int w, int u, int v) {
113            return hashWithState(x, y, z, w, u, v, (int) (state ^ state >>> 32));
114        }
115    }
116}