001/*******************************************************************************
002 * This software is provided as a supplement to the authors' textbooks on digital
003 *  image processing published by Springer-Verlag in various languages and editions.
004 * Permission to use and distribute this software is granted under the BSD 2-Clause 
005 * "Simplified" License (see http://opensource.org/licenses/BSD-2-Clause). 
006 * Copyright (c) 2006-2016 Wilhelm Burger, Mark J. Burge. All rights reserved. 
007 * Visit http://imagingbook.com for additional details.
008 *******************************************************************************/
009
010package imagingbook.pub.noise.hashing;
011
012/**
013 * Gradient (Perlin) noise implementation. 
014 */
015public abstract class Hash32 extends HashFun {
016        
017        static final int maxInt = 0x7fffffff;
018        
019        static final int[] smallPrimes = {      // used for N-dimensional hashing
020                73, 79, 83, 89, 97, 101, 103, 107, 109, 113,
021                127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 
022            179, 181, 191, 193, 197, 199, 211, 223, 227, 229,
023            233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 
024            283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 
025            353, 359, 367, 373, 379, 383, 389, 397, 401, 409 
026        };
027
028        protected Hash32() {
029                super();
030        }
031        
032        protected Hash32(int seed) {
033                super(seed);
034        }
035        
036        /**
037         * "Hashes" an <tt>int</tt> key to a "pseudo-random" <tt>int</tt> value 
038         * in [-2147483648, 2147483647].
039         * This method is supposed to be overridden by subclasses if needed.
040         * 
041         * @param key key for random generator
042         * @return A integer value in [-2147483648, 2147483647].
043         */
044        abstract int hashInt(int key);
045        
046        public double hash(int u) {
047                int h = hashInt(73*u + seed) & maxInt;
048                return (double) h / maxInt;
049        }
050        
051//      public double[] hash(int u, int v) {
052//              int hx = hashInt(59*u + 67*v + seed) & maxInt;  
053//              int hy = hashInt(73*u + 79*v + seed) & maxInt;  
054//              return new double[] {(double) hx / maxInt, (double) hy / maxInt};
055//      }
056        
057        // call 1 hash function and extract 12-bit blocks
058        public double[] hash(int u, int v) {
059                final int M = 0x00000FFF;
060                int h = hashInt(59*u + 67*v + seed);
061                int hx =  h & M;                // extract bits  0..11
062                int hy = (h >> 12) & M; // extract bits 12..23
063                return new double[] {(double) hx / M, (double) hy / M};
064        }
065        
066        // call 3 different hash functions for 3 dimensions
067//      public double[] hash(int u, int v, int w) {
068//              int M = 0x7FFFFFFF;
069//              int hx = hashInt(59*u + 67*v + 71*w + seed) & M;
070//              int hy = hashInt(73*u + 79*v + 83*w + seed) & M;
071//              int hz = hashInt(89*u + 97*v + 101*w + seed) & M;
072//              return new double[] {(double) hx/M, (double) hy/M, (double) hz/M};
073//      }
074        
075        
076        // call 1 hash function and extract bit blocks
077        public double[] hash(int u, int v, int w) {
078                final int M = 0x000000FF;
079                int h = hashInt(59*u + 67*v + 71*w + seed);
080                int hx =  h & M;                        // extract bits 0..7
081                int hy = (h >> 8) & M;  // extract bits 8..15
082                int hz = (h >> 16) & M; // extract bits 16..23
083                return new double[] {(double) hx / M, (double) hy / M, (double) hz / M};
084        }
085        
086        /*
087         * N-dimensional permutation hash; this version does not use
088         * any bit splitting. Instead, the hashInt() function is
089         * applied repeatedly for every gradient dimension by 
090         * using the dimension number (k) as a local seed - 
091         * in addition to the global seed (seed).
092         */
093        public double[] hash(int[] p) { 
094                final int N = p.length;
095                double[] g = new double[N];
096                for (int k = 0; k < N; k++) { // dimension k
097                        int sum = seed;
098                        for (int l = 0; l < N; l++) { // dimension k
099                                sum = sum + smallPrimes[l + k] * p[l];
100                        }
101                        int h = hashInt(sum + k) & maxInt;
102                        g[k] = (double) h / maxInt;
103                }
104                return g;
105        }
106
107}