packages feed

pure-noise 0.1.0.1 → 0.2.0.0

raw patch · 18 files changed

+490/−131 lines, 18 filesdep +primitivedep ~basePVP ok

version bump matches the API change (PVP)

Dependencies added: primitive

Dependency ranges changed: base

API changes (from Hackage documentation)

- Numeric.Noise.Cellular: instance GHC.Enum.Bounded Numeric.Noise.Cellular.CellularDistanceFn
- Numeric.Noise.Cellular: instance GHC.Enum.Bounded Numeric.Noise.Cellular.CellularResult
- Numeric.Noise.Cellular: instance GHC.Enum.Enum Numeric.Noise.Cellular.CellularDistanceFn
- Numeric.Noise.Cellular: instance GHC.Enum.Enum Numeric.Noise.Cellular.CellularResult
- Numeric.Noise.Cellular: instance GHC.Generics.Generic (Numeric.Noise.Cellular.CellularConfig a)
- Numeric.Noise.Cellular: instance GHC.Generics.Generic Numeric.Noise.Cellular.CellularDistanceFn
- Numeric.Noise.Cellular: instance GHC.Generics.Generic Numeric.Noise.Cellular.CellularResult
- Numeric.Noise.Cellular: instance GHC.Read.Read Numeric.Noise.Cellular.CellularDistanceFn
- Numeric.Noise.Cellular: instance GHC.Read.Read Numeric.Noise.Cellular.CellularResult
- Numeric.Noise.Cellular: instance GHC.Show.Show Numeric.Noise.Cellular.CellularDistanceFn
- Numeric.Noise.Cellular: instance GHC.Show.Show Numeric.Noise.Cellular.CellularResult
- Numeric.Noise.Cellular: instance GHC.Show.Show a => GHC.Show.Show (Numeric.Noise.Cellular.CellularConfig a)
- Numeric.Noise.Cellular: noise2BaseWith :: RealFrac a => a -> (a -> a -> a) -> Seed -> a -> a -> (Hash, a, a)
- Numeric.Noise.Fractal: instance GHC.Generics.Generic (Numeric.Noise.Fractal.FractalConfig a)
- Numeric.Noise.Fractal: instance GHC.Generics.Generic (Numeric.Noise.Fractal.PingPongStrength a)
- Numeric.Noise.Fractal: instance GHC.Read.Read a => GHC.Read.Read (Numeric.Noise.Fractal.FractalConfig a)
- Numeric.Noise.Fractal: instance GHC.Show.Show a => GHC.Show.Show (Numeric.Noise.Fractal.FractalConfig a)
- Numeric.Noise.Internal: Noise2 :: (Seed -> a -> a -> a) -> Noise2 a
- Numeric.Noise.Internal: Noise3 :: (Seed -> a -> a -> a -> a) -> Noise3 a
- Numeric.Noise.Internal: [unNoise2] :: Noise2 a -> Seed -> a -> a -> a
- Numeric.Noise.Internal: [unNoise3] :: Noise3 a -> Seed -> a -> a -> a -> a
- Numeric.Noise.Internal: clamp :: Ord a => a -> a -> a -> a
- Numeric.Noise.Internal: clamp2 :: Ord a => a -> a -> Noise2 a -> Noise2 a
- Numeric.Noise.Internal: clamp3 :: Ord a => a -> a -> Noise3 a -> Noise3 a
- Numeric.Noise.Internal: const2 :: a -> Noise2 a
- Numeric.Noise.Internal: const3 :: a -> Noise3 a
- Numeric.Noise.Internal: cubicInterp :: Num a => a -> a -> a -> a -> a -> a
- Numeric.Noise.Internal: hermiteInterp :: Num a => a -> a
- Numeric.Noise.Internal: instance GHC.Float.Floating a => GHC.Float.Floating (Numeric.Noise.Internal.Noise2 a)
- Numeric.Noise.Internal: instance GHC.Float.Floating a => GHC.Float.Floating (Numeric.Noise.Internal.Noise3 a)
- Numeric.Noise.Internal: instance GHC.Num.Num a => GHC.Num.Num (Numeric.Noise.Internal.Noise2 a)
- Numeric.Noise.Internal: instance GHC.Num.Num a => GHC.Num.Num (Numeric.Noise.Internal.Noise3 a)
- Numeric.Noise.Internal: instance GHC.Real.Fractional a => GHC.Real.Fractional (Numeric.Noise.Internal.Noise2 a)
- Numeric.Noise.Internal: instance GHC.Real.Fractional a => GHC.Real.Fractional (Numeric.Noise.Internal.Noise3 a)
- Numeric.Noise.Internal: lerp :: Num a => a -> a -> a -> a
- Numeric.Noise.Internal: map2 :: (a -> a) -> Noise2 a -> Noise2 a
- Numeric.Noise.Internal: map3 :: (a -> a) -> Noise3 a -> Noise3 a
- Numeric.Noise.Internal: newtype Noise2 a
- Numeric.Noise.Internal: newtype Noise3 a
- Numeric.Noise.Internal: next2 :: Noise2 a -> Noise2 a
- Numeric.Noise.Internal: next3 :: Noise3 a -> Noise3 a
- Numeric.Noise.Internal: quinticInterp :: Num a => a -> a
- Numeric.Noise.Internal: type Hash = Int32
- Numeric.Noise.Internal: type Seed = Word64
- Numeric.Noise.Internal.Math: clamp :: Ord a => a -> a -> a -> a
- Numeric.Noise.Internal.Math: cubicInterp :: Num a => a -> a -> a -> a -> a -> a
- Numeric.Noise.Internal.Math: g2 :: Fractional a => a
- Numeric.Noise.Internal.Math: gradCoord2 :: RealFrac a => Seed -> Hash -> Hash -> a -> a -> a
- Numeric.Noise.Internal.Math: gradCoord3 :: RealFrac a => Seed -> Hash -> Hash -> Hash -> a -> a -> a -> a
- Numeric.Noise.Internal.Math: hash2 :: Seed -> Hash -> Hash -> Hash
- Numeric.Noise.Internal.Math: hash3 :: Seed -> Hash -> Hash -> Hash -> Hash
- Numeric.Noise.Internal.Math: hermiteInterp :: Num a => a -> a
- Numeric.Noise.Internal.Math: infinity :: Fractional a => a
- Numeric.Noise.Internal.Math: lerp :: Num a => a -> a -> a -> a
- Numeric.Noise.Internal.Math: maxHash :: RealFrac a => a
- Numeric.Noise.Internal.Math: primeX :: Hash
- Numeric.Noise.Internal.Math: primeY :: Hash
- Numeric.Noise.Internal.Math: primeZ :: Hash
- Numeric.Noise.Internal.Math: quinticInterp :: Num a => a -> a
- Numeric.Noise.Internal.Math: sqrt3 :: Fractional a => a
- Numeric.Noise.Internal.Math: type Hash = Int32
- Numeric.Noise.Internal.Math: type Seed = Word64
- Numeric.Noise.Internal.Math: valCoord2 :: RealFrac a => Word64 -> Hash -> Hash -> a
- Numeric.Noise.Internal.Math: valCoord3 :: RealFrac a => Word64 -> Hash -> Hash -> Hash -> a
+ Numeric.Noise: FractalConfig :: Int -> a -> a -> a -> FractalConfig a
+ Numeric.Noise: PingPongStrength :: a -> PingPongStrength a
+ Numeric.Noise: [gain] :: FractalConfig a -> a
+ Numeric.Noise: [lacunarity] :: FractalConfig a -> a
+ Numeric.Noise: [octaves] :: FractalConfig a -> Int
+ Numeric.Noise: [weightedStrength] :: FractalConfig a -> a
+ Numeric.Noise: billow2 :: RealFrac a => FractalConfig a -> Noise2 a -> Noise2 a
+ Numeric.Noise: billow3 :: RealFrac a => FractalConfig a -> Noise3 a -> Noise3 a
+ Numeric.Noise: const2 :: a -> Noise2 a
+ Numeric.Noise: const3 :: a -> Noise3 a
+ Numeric.Noise: data FractalConfig a
+ Numeric.Noise: defaultFractalConfig :: RealFrac a => FractalConfig a
+ Numeric.Noise: defaultPingPongStrength :: RealFrac a => PingPongStrength a
+ Numeric.Noise: fractal2 :: RealFrac a => FractalConfig a -> Noise2 a -> Noise2 a
+ Numeric.Noise: fractal3 :: RealFrac a => FractalConfig a -> Noise3 a -> Noise3 a
+ Numeric.Noise: newtype PingPongStrength a
+ Numeric.Noise: pingPong2 :: RealFrac a => FractalConfig a -> PingPongStrength a -> Noise2 a -> Noise2 a
+ Numeric.Noise: pingPong3 :: RealFrac a => FractalConfig a -> PingPongStrength a -> Noise3 a -> Noise3 a
+ Numeric.Noise: ridged2 :: RealFrac a => FractalConfig a -> Noise2 a -> Noise2 a
+ Numeric.Noise: ridged3 :: RealFrac a => FractalConfig a -> Noise3 a -> Noise3 a
+ Numeric.Noise.Cellular: instance GHC.Internal.Enum.Bounded Numeric.Noise.Cellular.CellularDistanceFn
+ Numeric.Noise.Cellular: instance GHC.Internal.Enum.Bounded Numeric.Noise.Cellular.CellularResult
+ Numeric.Noise.Cellular: instance GHC.Internal.Enum.Enum Numeric.Noise.Cellular.CellularDistanceFn
+ Numeric.Noise.Cellular: instance GHC.Internal.Enum.Enum Numeric.Noise.Cellular.CellularResult
+ Numeric.Noise.Cellular: instance GHC.Internal.Generics.Generic (Numeric.Noise.Cellular.CellularConfig a)
+ Numeric.Noise.Cellular: instance GHC.Internal.Generics.Generic Numeric.Noise.Cellular.CellularDistanceFn
+ Numeric.Noise.Cellular: instance GHC.Internal.Generics.Generic Numeric.Noise.Cellular.CellularResult
+ Numeric.Noise.Cellular: instance GHC.Internal.Read.Read Numeric.Noise.Cellular.CellularDistanceFn
+ Numeric.Noise.Cellular: instance GHC.Internal.Read.Read Numeric.Noise.Cellular.CellularResult
+ Numeric.Noise.Cellular: instance GHC.Internal.Show.Show Numeric.Noise.Cellular.CellularDistanceFn
+ Numeric.Noise.Cellular: instance GHC.Internal.Show.Show Numeric.Noise.Cellular.CellularResult
+ Numeric.Noise.Cellular: instance GHC.Internal.Show.Show a => GHC.Internal.Show.Show (Numeric.Noise.Cellular.CellularConfig a)
+ Numeric.Noise.Fractal: instance GHC.Internal.Generics.Generic (Numeric.Noise.Fractal.FractalConfig a)
+ Numeric.Noise.Fractal: instance GHC.Internal.Generics.Generic (Numeric.Noise.Fractal.PingPongStrength a)
+ Numeric.Noise.Fractal: instance GHC.Internal.Read.Read a => GHC.Internal.Read.Read (Numeric.Noise.Fractal.FractalConfig a)
+ Numeric.Noise.Fractal: instance GHC.Internal.Show.Show a => GHC.Internal.Show.Show (Numeric.Noise.Fractal.FractalConfig a)
- Numeric.Noise.Perlin: noise2Base :: forall a. RealFrac a => Seed -> a -> a -> a
+ Numeric.Noise.Perlin: noise2Base :: RealFrac a => Seed -> a -> a -> a

Files

CHANGELOG.md view
@@ -8,6 +8,25 @@  ## Unreleased +## 0.2.0.0 - 2025-10-21++### Added++- Comprehensive haddock documentation for main `Numeric.Noise` module with usage examples++### Changed++- Migrated internal implementation from `vector` to `primitive` (PrimArray)+- Removed `vector` dependency from library (still used in benchmarks)+- Require GHC 9.2+ (base >= 4.16)+- Hide internal modules from public API (`Numeric.Noise.Internal`, `Numeric.Noise.Internal.Math`)+- Improved cellular noise performance by 20-30% through specialized computation paths for different result types++### Fixed++- Fixed intermediate list allocation in fractal functions on GHC 9.6++- Improved division performance for `Noise3` instances+ ## 0.1.0.1 - 2024-10-15  - Add bounds for vector
README.md view
@@ -42,35 +42,35 @@  | name          | values / second | | ------------- | --------------- |-| value2        | 157_347_680     |-| perlin2       | 129_541_747     |-| openSimplex2  | 64_758_006      |-| superSimplex2 | 64_072_639      |-| valueCubic2   | 52_110_819      |-| cellular2     | 15_743_434      |+| value2        | 156_797_694     |+| perlin2       | 138_048_921     |+| superSimplex2 | 65_204_214      |+| openSimplex2  | 64_483_692      |+| valueCubic2   | 50_666_467      |+| cellular2     | 20_819_883      |  #### 3D  | name        | values / second | | ----------- | --------------- |-| value3      | 85_438_023      |-| perlin3     | 56_830_482      |-| valueCubic3 | 15_559_523      |+| value3      | 83_034_432      |+| perlin3     | 60_233_650      |+| valueCubic3 | 15_220_433      |  ## Examples -There's an interactive [demo app](demo/README.md) in the `demo` directory.+There's an interactive [demo app](https://github.com/jtnuttall/pure-noise/tree/main/demo) in the `demo` directory.  _OpenSimplex2_ -![OpenSimplex2](demo/images/opensimplex.png)-![OpenSimplex2 ridged](demo/images/opensimplex-ridged.png)+![OpenSimplex2](https://raw.githubusercontent.com/jtnuttall/pure-noise/main/demo/images/opensimplex.png)+![OpenSimplex2 ridged](https://raw.githubusercontent.com/jtnuttall/pure-noise/main/demo/images/opensimplex-ridged.png)  _Perlin_ -![Perlin fBm](demo/images/perlin-fbm.png)+![Perlin fBm](https://raw.githubusercontent.com/jtnuttall/pure-noise/main/demo/images/perlin-fbm.png)  _Cellular_ -![value](demo/images/cell-value.png)-![distance2add](demo/images/cell-d2.png)+![value](https://raw.githubusercontent.com/jtnuttall/pure-noise/main/demo/images/cell-value.png)+![distance2add](https://raw.githubusercontent.com/jtnuttall/pure-noise/main/demo/images/cell-d2.png)
bench/Bench.hs view
@@ -2,7 +2,6 @@ import Data.Typeable import Data.Vector.Unboxed qualified as U import Numeric.Noise-import Numeric.Noise.Internal (const2, const3) import System.Random.MWC qualified as MWC  main :: IO ()
bench/BenchLib.hs view
pure-noise.cabal view
@@ -1,13 +1,17 @@ cabal-version: 2.2 --- This file has been generated from package.yaml by hpack version 0.37.0.+-- This file has been generated from package.yaml by hpack version 0.38.1. -- -- see: https://github.com/sol/hpack  name:           pure-noise-version:        0.1.0.1-synopsis:       Performant, modern noise generation for Haskell with minimal dependencies. Based on FastNoiseLite.-description:    Please see the README on GitHub at <https://github.com/jtnuttall/pure-noise#readme>+version:        0.2.0.0+synopsis:       High-performance composable noise generation (Perlin, Simplex, Cellular)+description:    A high-performance noise generation library ported from FastNoiseLite.+                Provides N-dimensional noise functions (Perlin, OpenSimplex, SuperSimplex,+                Value, Cellular) that can be composed using Num or Fractional methods with+                minimal performance overhead. Noise values are generally clamped to [-1, 1].+                Benefits significantly from LLVM backend compilation (~50-80% performance improvement). category:       Math, Numeric, Noise homepage:       https://github.com/jtnuttall/pure-noise#readme bug-reports:    https://github.com/jtnuttall/pure-noise/issues@@ -19,6 +23,7 @@ build-type:     Simple extra-source-files:     README.md+extra-doc-files:     CHANGELOG.md  source-repository head@@ -30,14 +35,14 @@       Numeric.Noise       Numeric.Noise.Cellular       Numeric.Noise.Fractal-      Numeric.Noise.Internal-      Numeric.Noise.Internal.Math       Numeric.Noise.OpenSimplex       Numeric.Noise.Perlin       Numeric.Noise.SuperSimplex       Numeric.Noise.Value       Numeric.Noise.ValueCubic   other-modules:+      Numeric.Noise.Internal+      Numeric.Noise.Internal.Math       Paths_pure_noise   autogen-modules:       Paths_pure_noise@@ -45,8 +50,8 @@       src   ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints   build-depends:-      base >=4.7 && <5-    , vector <=0.14+      base >=4.16 && <5+    , primitive >=0.8 && <0.10   default-language: GHC2021  test-suite pure-noise-test@@ -63,13 +68,13 @@       test   ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -Wno-missing-export-lists -threaded -rtsopts -with-rtsopts=-N   build-depends:-      base >=4.7 && <5+      base >=4.16 && <5+    , primitive >=0.8 && <0.10     , pure-noise     , tasty     , tasty-discover     , tasty-hunit     , tasty-quickcheck-    , vector <=0.14   default-language: GHC2021  benchmark pure-noise-bench@@ -82,11 +87,12 @@       Paths_pure_noise   hs-source-dirs:       bench-  ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N +RTS -A32m --nonmoving-gc -T -RTS -O2 -optc-O3 -fproc-alignment=64 -fsimpl-tick-factor=1000+  ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N +RTS -A32m --nonmoving-gc -T -RTS -O2 -optc-O3 -fsimpl-tick-factor=1000   build-depends:-      base >=4.7 && <5+      base >=4.16 && <5     , deepseq     , mwc-random+    , primitive >=0.8 && <0.10     , pure-noise     , tasty     , tasty-bench
src/Numeric/Noise.hs view
@@ -3,15 +3,60 @@ -- | -- Maintainer: Jeremy Nuttall <jeremy@jeremy-nuttall.com> -- Stability : experimental+--+-- Performant noise generation with composable noise functions.+--+-- Noise functions are wrapped in 'Noise2' and 'Noise3' newtypes that abstract over+-- the seed and coordinate parameters. These can be composed using 'Num' or 'Fractional'+-- methods with minimal performance overhead.+--+-- Noise values are generally clamped to @[-1, 1]@, though some functions may+-- occasionally produce values slightly outside this range.+--+-- == Basic Usage+--+-- Generate 2D Perlin noise:+--+-- @+-- import Numeric.Noise qualified as Noise+--+-- myNoise :: Noise.Seed -> Float -> Float -> Float+-- myNoise = Noise.noise2At Noise.perlin2+-- @+--+-- Compose multiple noise functions:+--+-- @+-- combined :: (RealFrac a) => Noise.Noise2 a+-- combined = (Noise.perlin2 + Noise.superSimplex2) / 2+--+-- myNoise2 :: Noise.Seed -> Float -> Float -> Float+-- myNoise2 = Noise.noise2At combined+-- @+--+-- Apply fractal Brownian motion:+--+-- @+-- fbm :: (RealFrac a) => Noise.Noise2 a+-- fbm = Noise.fractal2 Noise.defaultFractalConfig Noise.perlin2+-- @ module Numeric.Noise (-  -- * Noise functions+  -- * Core Types -  -- ** Noise functions+  --++  -- | 'Noise2' and 'Noise3' are newtypes wrapping noise functions. They can be+  -- unwrapped with 'noise2At' and 'noise3At' respectively.+  --+  -- 'Seed' is a 'Word64' value used for deterministic noise generation.   module NoiseTypes,++  -- * Noise evaluation   noise2At,   noise3At,    -- ** 2D Noise+  const2,   cellular2,   openSimplex2,   superSimplex2,@@ -20,6 +65,7 @@   valueCubic2,    -- ** 3D Noise+  const3,   perlin3,   value3,   valueCubic3,@@ -29,21 +75,51 @@   -- ** Math utility functions   module NoiseUtility, -  -- ** Fractal Brownian Motion-  module Fractal,+  -- ** Fractal noise composition +  --++  -- | Fractal noise combines multiple octaves at different frequencies and+  -- amplitudes to create natural-looking, multi-scale patterns.+  --+  -- For custom fractal implementations using modifier functions, see+  -- "Numeric.Noise.Fractal".++  -- *** Configuration+  FractalConfig (..),+  defaultFractalConfig,+  PingPongStrength (..),+  defaultPingPongStrength,++  -- *** Fractal Brownian Motion (FBM)+  fractal2,+  fractal3,++  -- *** Fractal variants+  billow2,+  billow3,+  ridged2,+  ridged3,+  pingPong2,+  pingPong3,+   -- ** Cellular noise configuration-  module Cellular,-) where -import Numeric.Noise.Cellular as Cellular (+  --++  -- | Cellular (Worley) noise creates patterns based on distances to+  -- randomly distributed cell points.++  -- *** Configuration   CellularConfig (..),+  defaultCellularConfig,   CellularDistanceFn (..),   CellularResult (..),-  defaultCellularConfig,- )+) where++import Numeric.Noise.Cellular (CellularConfig, CellularDistanceFn (..), CellularResult (..), defaultCellularConfig) import Numeric.Noise.Cellular qualified as Cellular-import Numeric.Noise.Fractal as Fractal+import Numeric.Noise.Fractal import Numeric.Noise.Internal import Numeric.Noise.Internal as NoiseTypes (   Noise2,@@ -67,46 +143,78 @@ import Numeric.Noise.Value qualified as Value import Numeric.Noise.ValueCubic qualified as ValueCubic -noise2At :: Noise2 a -> Seed -> a -> a -> a+-- | Evaluate a 2D noise function at the given coordinates with the given seed.+noise2At+  :: Noise2 a+  -> Seed+  -- ^ deterministic seed+  -> a+  -- ^ x coordinate+  -> a+  -- ^ y coordinate+  -> a noise2At = unNoise2 {-# INLINE noise2At #-} +-- | 2D Cellular (Worley) noise. Configure with 'CellularConfig' to control+-- distance functions and return values. cellular2 :: (RealFrac a, Floating a) => CellularConfig a -> Noise2 a cellular2 = Cellular.noise2 {-# INLINE cellular2 #-} +-- | 2D OpenSimplex noise. Smooth gradient noise similar to Perlin but without+-- directional artifacts. openSimplex2 :: (RealFrac a) => Noise2 a openSimplex2 = OpenSimplex.noise2 {-# INLINE openSimplex2 #-} +-- | 2D SuperSimplex noise. Improved OpenSimplex variant with better visual+-- characteristics. superSimplex2 :: (RealFrac a) => Noise2 a superSimplex2 = SuperSimplex.noise2 {-# INLINE superSimplex2 #-} +-- | 2D Perlin noise. Classic gradient noise algorithm. perlin2 :: (RealFrac a) => Noise2 a perlin2 = Perlin.noise2 {-# INLINE perlin2 #-} -noise3At :: Noise3 a -> Seed -> a -> a -> a -> a+-- | Evaluate a 3D noise function at the given coordinates with the given seed.+noise3At+  :: Noise3 a+  -> Seed+  -- ^ deterministic seed+  -> a+  -- ^ x coordinate+  -> a+  -- ^ y coordinate+  -> a+  -- ^ z coordinate+  -> a noise3At = unNoise3 {-# INLINE noise3At #-} +-- | 3D Perlin noise. Classic gradient noise algorithm. perlin3 :: (RealFrac a) => Noise3 a perlin3 = Perlin.noise3 {-# INLINE perlin3 #-} +-- | 2D Value noise. Simple noise based on interpolated random values at grid points. value2 :: (RealFrac a) => Noise2 a value2 = Value.noise2 {-# INLINE value2 #-} +-- | 3D Value noise. Simple noise based on interpolated random values at grid points. value3 :: (RealFrac a) => Noise3 a value3 = Value.noise3 {-# INLINE value3 #-} +-- | 2D Value noise with cubic interpolation for smoother results. valueCubic2 :: (RealFrac a) => Noise2 a valueCubic2 = ValueCubic.noise2 {-# INLINE valueCubic2 #-} +-- | 3D Value noise with cubic interpolation for smoother results. valueCubic3 :: (RealFrac a) => Noise3 a valueCubic3 = ValueCubic.noise3 {-# INLINE valueCubic3 #-}
src/Numeric/Noise/Cellular.hs view
@@ -14,23 +14,32 @@    -- * 2D Noise   noise2,-  noise2BaseWith, ) where  import Data.Bits-import Data.Foldable-import Data.Vector.Unboxed qualified as U+import Data.Foldable -- redundant since GHC 9.10.1, here for compat+import Data.Primitive.PrimArray import GHC.Generics (Generic) import Numeric.Noise.Internal import Numeric.Noise.Internal.Math +-- | Configuration for cellular (Worley) noise generation.+--+-- Cellular noise is based on distances to randomly distributed cell points,+-- creating a distinctive cellular or organic pattern. data CellularConfig a = CellularConfig   { cellularDistanceFn :: !CellularDistanceFn+  -- ^ Distance metric to use when computing distance to cell points.   , cellularJitter :: !a+  -- ^ Amount of randomness in cell point positions.+  -- 0 creates a regular grid, 1 creates fully random positions.+  -- Values outside [0, 1] are valid but may produce unusual results.   , cellularResult :: !CellularResult+  -- ^ What value to return from the noise function.   }   deriving (Generic, Show) +-- | Default configuration for cellular noise generation. defaultCellularConfig :: (RealFrac a) => CellularConfig a defaultCellularConfig =   CellularConfig@@ -39,21 +48,51 @@     , cellularResult = CellValue     } +-- | Distance function for cellular noise calculations.+--+-- Different distance metrics produce different visual characteristics+-- in the cellular pattern. data CellularDistanceFn-  = DistEuclidean-  | DistEuclideanSq-  | DistManhattan-  | DistHybrid+  = -- | Standard Euclidean distance (sqrt(dx² + dy²)).+    -- Creates circular cells with smooth edges.+    DistEuclidean+  | -- | Squared Euclidean distance (dx² + dy²), no square root.+    -- Faster than 'DistEuclidean' with similar appearance.+    DistEuclideanSq+  | -- | Manhattan/taxicab distance (|dx| + |dy|).+    -- Creates diamond-shaped cells with sharp edges.+    DistManhattan+  | -- | Hybrid of Euclidean and Manhattan distances.+    -- Combines characteristics of both metrics.+    DistHybrid   deriving (Generic, Read, Show, Eq, Ord, Enum, Bounded) +-- | What value to return from cellular noise evaluation.+--+-- These options allow for different visual effects by returning different+-- properties of the cell structure. data CellularResult-  = CellValue-  | Distance-  | Distance2-  | Distance2Add-  | Distance2Sub-  | Distance2Mul-  | Distance2Div+  = -- | Return the hash value of the nearest cell point.+    -- Creates discrete regions with constant values.+    CellValue+  | -- | Return the distance to the nearest cell point.+    -- Creates a classic Worley noise pattern with cell boundaries.+    Distance+  | -- | Return the distance to the second-nearest cell point.+    -- Creates larger, more organic-looking cells.+    Distance2+  | -- | Return the sum of distances to the two nearest cell points.+    -- Creates smooth, rounded cells.+    Distance2Add+  | -- | Return the difference between distances to the two nearest cell points.+    -- Emphasizes cell boundaries and creates sharp edges.+    Distance2Sub+  | -- | Return the product of distances to the two nearest cell points.+    -- Creates cells with varying contrast.+    Distance2Mul+  | -- | Return the ratio of nearest to second-nearest distance.+    -- Creates normalized cell patterns.+    Distance2Div   deriving (Generic, Read, Show, Eq, Ord, Enum, Bounded)  distance :: (RealFrac a) => CellularDistanceFn -> a -> a -> a@@ -71,68 +110,80 @@ {-# INLINE normDist #-}  noise2 :: (RealFrac a, Floating a) => CellularConfig a -> Noise2 a-noise2 CellularConfig{..} =+noise2 CellularConfig{..} = Noise2 $ \ !seed !x !y ->   let !jitter = cellularJitter * 0.43701595-      !dist = distance cellularDistanceFn-      !norm = normDist cellularDistanceFn+      !rx = round x+      !ry = round y++      dist = distance cellularDistanceFn+      norm = normDist cellularDistanceFn       coeff = 1 / (fromIntegral (maxBound @Hash) + 1)-   in Noise2 $ \seed x y ->-        let (!hash, !d0u, !d1u) = noise2BaseWith jitter dist seed x y-            !d0 = norm d0u-            !d1 = norm d1u-         in case cellularResult of-              CellValue -> fromIntegral hash * coeff-              Distance -> d0 - 1-              Distance2 -> d1 - 1-              Distance2Add -> (d1 + d0) * 0.5 - 1-              Distance2Sub -> d1 - d0 - 1-              Distance2Mul -> d1 * d0 * 0.5 - 1-              Distance2Div -> d0 / d1 - 1-{-# INLINE noise2 #-} --- | Calculate 2D cellular noise values at a given point using the given distance function-noise2BaseWith-  :: (RealFrac a)-  => a-  -- ^ cellular jitter-  -> (a -> a -> a)-  -- ^ distance function-  -> Seed-  -> a-  -- ^ x-  -> a-  -- ^ y-  -> (Hash, a, a)-noise2BaseWith !jitter !dist !seed !x !y =-  foldl' @[]-    minmax-    (0, infinity, infinity)-    [pointDist (rx + xi) (ry + yi) | !xi <- [-1 .. 1], !yi <- [-1 .. 1]]- where-  !rx = round x-  !ry = round y+      {-# INLINE pointDist #-}+      pointDist !xi !yi =+        let !px = fromIntegral xi - x+            !py = fromIntegral yi - y+            !h = hash2 seed (primeX * xi) (primeY * yi)+            !i = h .&. 0x1FE+            !rvx = randVecs2d `indexPrimArray` fromIntegral i+            !rvy = randVecs2d `indexPrimArray` (fromIntegral i .|. 1)+            !d = dist (px + realToFrac rvx * jitter) (py + realToFrac rvy * jitter)+         in (h, d) -  minmax (!c, !d0, !d1) (!h, !d)-    | d < d0 = (h, d, d1')-    | otherwise = (c, d0, d1')-   where-    !d1' = max (min d1 d) d0+      {-# INLINE points #-}+      points = [pointDist (rx + xi) (ry + yi) | !xi <- [-1 .. 1], !yi <- [-1 .. 1]] -  pointDist !xi !yi =-    let !px = fromIntegral xi - x-        !py = fromIntegral yi - y-        !h = hash2 seed (primeX * xi) (primeY * yi)-        !i = h .&. 510-        !rvx = randVecs2d `U.unsafeIndex` fromIntegral i-        !rvy = randVecs2d `U.unsafeIndex` (fromIntegral i .|. 1)-        !d = dist (px + realToFrac rvx * jitter) (py + realToFrac rvy * jitter)-     in (h, d)-{-# INLINE noise2BaseWith #-}+      {-# INLINE selectMinHash #-}+      selectMinHash =+        let minHash (!hMin, !dMin) (!h, !d)+              | d < dMin = (h, d)+              | otherwise = (hMin, dMin)+         in foldl' minHash (0, infinity) points --- >>> U.length randVecs2d == 512+      {-# INLINE selectMinDist #-}+      selectMinDist =+        let minDist !dMin (_, !d)+              | d < dMin = d+              | otherwise = dMin+         in foldl' minDist infinity points++      {-# INLINE selectSmallestTwo #-}+      selectSmallestTwo =+        let smallestTwo (!c, !d0, !d1) (!h, !d)+              | d < d0 = (h, d, d0)+              | d < d1 = (c, d0, d)+              | otherwise = (c, d0, d1)+         in foldl' smallestTwo (0, infinity, infinity) points+   in case cellularResult of+        CellValue ->+          let (!hash, !_) = selectMinHash+           in fromIntegral hash * coeff+        Distance ->+          let !d0 = selectMinDist+           in norm d0 - 1+        Distance2 ->+          let (!_, !_, !d1) = selectSmallestTwo+           in norm d1 - 1+        Distance2Add ->+          let (!_, !d0, !d1) = selectSmallestTwo+           in (norm d1 + norm d0) * 0.5 - 1+        Distance2Sub ->+          let (!_, !d0, !d1) = selectSmallestTwo+           in norm d1 - norm d0 - 1+        Distance2Mul ->+          let (!_, !d0, !d1) = selectSmallestTwo+           in norm d1 * norm d0 * 0.5 - 1+        Distance2Div ->+          let (!_, !d0, !d1) = selectSmallestTwo+           in norm d0 / norm d1 - 1+ where++{-# INLINE noise2 #-}++-- >>> sizeofPrimArray randVecs2d == 512 -- True {- ORMOLU_DISABLE -}-randVecs2d :: U.Vector Float+randVecs2d :: PrimArray Float randVecs2d =   [-0.2700222198,-0.9628540911,0.3863092627,-0.9223693152,0.04444859006,-0.999011673,-0.5992523158,-0.8005602176   ,-0.7819280288,0.6233687174,0.9464672271,0.3227999196,-0.6514146797,-0.7587218957,0.9378472289,0.347048376
src/Numeric/Noise/Fractal.hs view
@@ -37,14 +37,30 @@ import GHC.Generics import Numeric.Noise.Internal +-- | Configuration for fractal noise generation.+--+-- Fractal noise combines multiple octaves (layers) of noise at different+-- frequencies and amplitudes to create more complex, natural-looking patterns. data FractalConfig a = FractalConfig   { octaves :: Int+  -- ^ Number of noise layers to combine. More octaves create more detail+  -- but are more expensive to compute. Must be >= 1.   , lacunarity :: a+  -- ^ Frequency multiplier between octaves. Each octave's frequency is+  -- the previous octave's frequency multiplied by lacunarity.   , gain :: a+  -- ^ Amplitude multiplier between octaves. Each octave's amplitude is+  -- the previous octave's amplitude multiplied by gain.+  -- Values < 1 create smoother noise, values > 1 create rougher noise.   , weightedStrength :: a+  -- ^ Controls how much each octave's amplitude is influenced by the+  -- previous octave's value. At 0, octaves have independent amplitudes.+  -- At 1, lower-valued areas in previous octaves reduce the amplitude+  -- of subsequent octaves. Range: [0, 1].   }   deriving (Generic, Read, Show, Eq) +-- | Default configuration for fractal noise generation. defaultFractalConfig :: (RealFrac a) => FractalConfig a defaultFractalConfig =   FractalConfig@@ -54,18 +70,58 @@     , weightedStrength = 0     } +-- | Apply Fractal Brownian Motion (FBM) to a 2D noise function.+--+-- FBM combines multiple octaves of noise at increasing frequencies and+-- decreasing amplitudes to create natural-looking, multi-scale patterns.+-- This is the standard fractal noise implementation.+--+-- @+-- fbm :: Noise2 Float+-- fbm = fractal2 defaultFractalConfig perlin2+-- @ fractal2 :: (RealFrac a) => FractalConfig a -> Noise2 a -> Noise2 a fractal2 config = Noise2 . fractal2With fractalNoiseMod (fractalAmpMod config) config . unNoise2 {-# INLINE fractal2 #-} +-- | Apply billow fractal to a 2D noise function.+--+-- Billow creates a cloud-like or billowy appearance by taking the absolute+-- value of each octave. This produces sharp ridges in the negative regions+-- of the noise, creating a distinct puffy or cloudy look.+--+-- @+-- clouds :: Noise2 Float+-- clouds = billow2 defaultFractalConfig perlin2+-- @ billow2 :: (RealFrac a) => FractalConfig a -> Noise2 a -> Noise2 a billow2 config = Noise2 . fractal2With billowNoiseMod (billowAmpMod config) config . unNoise2 {-# INLINE billow2 #-} +-- | Apply ridged fractal to a 2D noise function.+--+-- Ridged creates sharp ridges by inverting and taking the absolute value+-- of each octave. This is particularly useful for terrain generation,+-- creating mountain ridges and valleys.+--+-- @+-- mountains :: Noise2 Float+-- mountains = ridged2 defaultFractalConfig perlin2+-- @ ridged2 :: (RealFrac a) => FractalConfig a -> Noise2 a -> Noise2 a ridged2 config = Noise2 . fractal2With ridgedNoiseMod (ridgedAmpMod config) config . unNoise2 {-# INLINE ridged2 #-} +-- | Apply ping-pong fractal to a 2D noise function.+--+-- Ping-pong creates a wave-like pattern by folding the noise values back+-- and forth within a range, creating a distinctive undulating appearance.+-- The strength parameter controls the intensity of the ping-pong effect.+--+-- @+-- waves :: Noise2 Float+-- waves = pingPong2 defaultFractalConfig defaultPingPongStrength perlin2+-- @ pingPong2 :: (RealFrac a) => FractalConfig a -> PingPongStrength a -> Noise2 a -> Noise2 a pingPong2 config strength =   Noise2 . fractal2With (pingPongNoiseMod strength) (pingPongAmpMod config) config . unNoise2@@ -96,18 +152,30 @@      in go (o - 1) (acc + noise) (s + 1) (freq * lacunarity) amp' {-# INLINE fractal2With #-} +-- | Apply Fractal Brownian Motion (FBM) to a 3D noise function.+--+-- 3D version of 'fractal2'. See 'fractal2' for details. fractal3 :: (RealFrac a) => FractalConfig a -> Noise3 a -> Noise3 a fractal3 config = Noise3 . fractal3With fractalNoiseMod (fractalAmpMod config) config . unNoise3 {-# INLINE fractal3 #-} +-- | Apply billow fractal to a 3D noise function.+--+-- 3D version of 'billow2'. See 'billow2' for details. billow3 :: (RealFrac a) => FractalConfig a -> Noise3 a -> Noise3 a billow3 config = Noise3 . fractal3With billowNoiseMod (billowAmpMod config) config . unNoise3 {-# INLINE billow3 #-} +-- | Apply ridged fractal to a 3D noise function.+--+-- 3D version of 'ridged2'. See 'ridged2' for details. ridged3 :: (RealFrac a) => FractalConfig a -> Noise3 a -> Noise3 a ridged3 config = Noise3 . fractal3With ridgedNoiseMod (ridgedAmpMod config) config . unNoise3 {-# INLINE ridged3 #-} +-- | Apply ping-pong fractal to a 3D noise function.+--+-- 3D version of 'pingPong2'. See 'pingPong2' for details. pingPong3 :: (RealFrac a) => FractalConfig a -> PingPongStrength a -> Noise3 a -> Noise3 a pingPong3 config strength =   Noise3 . fractal3With (pingPongNoiseMod strength) (pingPongAmpMod config) config . unNoise3@@ -128,10 +196,10 @@   -> a fractal3With modNoise modAmps FractalConfig{..} noise3 seed x y z   | octaves < 1 = error "octaves must be a positive integer"-  | otherwise =-      let bounding = fractalBounding FractalConfig{..}-       in go octaves 0 seed 1 bounding+  | otherwise = go octaves 0 seed 1 bounding  where+  bounding = fractalBounding FractalConfig{..}+   go 0 acc _ _ _ = acc   go o acc s freq amp =     let noise = amp * modNoise (noise3 s (freq * x) (freq * y) (freq * z))@@ -140,41 +208,75 @@ {-# INLINE fractal3With #-}  fractalBounding :: (RealFrac a) => FractalConfig a -> a-fractalBounding FractalConfig{..} =-  let amps = take octaves $ iterate (* gain) gain-   in 1 / (sum amps + 1)+fractalBounding FractalConfig{..} = recip (sum amps + 1)+ where+  ~amps = take octaves $ iterate (* gain) gain {-# INLINE fractalBounding #-} +-- | Identity noise modifier for standard FBM.+--+-- This is used internally by 'fractal2' and 'fractal3'.+-- Exposed for users creating custom fractal implementations. fractalNoiseMod :: a -> a fractalNoiseMod = id {-# INLINE fractalNoiseMod #-}++-- | Amplitude modifier for standard FBM.+--+-- Uses the 'weightedStrength' parameter to influence amplitude based on+-- the previous octave's value. Exposed for custom fractal implementations. fractalAmpMod :: (Num a) => FractalConfig a -> a -> a fractalAmpMod FractalConfig{..} n = lerp 1 n weightedStrength {-# INLINE fractalAmpMod #-} +-- | Noise modifier for billow fractal.+--+-- Transforms noise value to @abs(n) * 2 - 1@, creating the billow effect.+-- Exposed for custom fractal implementations. billowNoiseMod :: (Num a) => a -> a billowNoiseMod n = abs n * 2 - 1 {-# INLINE billowNoiseMod #-} +-- | Amplitude modifier for billow fractal.+--+-- Uses the 'weightedStrength' parameter. Exposed for custom fractal implementations. billowAmpMod :: (Num a) => FractalConfig a -> a -> a billowAmpMod FractalConfig{..} n = lerp 1 n weightedStrength {-# INLINE billowAmpMod #-} +-- | Noise modifier for ridged fractal.+--+-- Transforms noise value to @abs(n) * (-2) + 1@, creating the ridge effect.+-- Exposed for custom fractal implementations. ridgedNoiseMod :: (Num a) => a -> a ridgedNoiseMod n = abs n * (-2) + 1 {-# INLINE ridgedNoiseMod #-} +-- | Amplitude modifier for ridged fractal.+--+-- Uses the 'weightedStrength' parameter with inverted noise value.+-- Exposed for custom fractal implementations. ridgedAmpMod :: (Num a) => FractalConfig a -> a -> a ridgedAmpMod FractalConfig{..} n = lerp 1 (1 - n) weightedStrength {-# INLINE ridgedAmpMod #-} +-- | Strength parameter for ping-pong fractal noise.+--+-- Controls the intensity of the ping-pong folding effect.+-- Higher values create more frequent oscillations. newtype PingPongStrength a = PingPongStrength a   deriving (Generic) +-- | Default ping-pong strength value. defaultPingPongStrength :: (RealFrac a) => PingPongStrength a defaultPingPongStrength = PingPongStrength 2 {-# INLINE defaultPingPongStrength #-} +-- | Noise modifier for ping-pong fractal.+--+-- Folds noise values back and forth within a range, creating a wave-like+-- pattern. The strength parameter controls the folding intensity.+-- Exposed for custom fractal implementations. pingPongNoiseMod :: (RealFrac a) => PingPongStrength a -> a -> a pingPongNoiseMod (PingPongStrength s) n =   let n' = (n + 1) * s@@ -182,6 +284,9 @@    in if t < 1 then t else 2 - t {-# INLINE pingPongNoiseMod #-} +-- | Amplitude modifier for ping-pong fractal.+--+-- Uses the 'weightedStrength' parameter. Exposed for custom fractal implementations. pingPongAmpMod :: (Num a) => FractalConfig a -> a -> a pingPongAmpMod FractalConfig{..} n = lerp 1 n weightedStrength {-# INLINE pingPongAmpMod #-}
src/Numeric/Noise/Internal.hs view
@@ -25,9 +25,32 @@   quinticInterp,  ) +-- | A 2D noise function parameterized by a seed and two coordinates.+--+-- 'Noise2' wraps a function @Seed -> a -> a -> a@ that takes a seed value+-- and x, y coordinates to produce a noise value.+--+-- This type supports 'Num', 'Fractional', and 'Floating' instances, allowing+-- noise functions to be combined algebraically:+--+-- @+-- combined :: Noise2 Float+-- combined = (perlin2 + superSimplex2) / 2+-- @+--+-- To evaluate a 'Noise2', use 'noise2At' from "Numeric.Noise". newtype Noise2 a = Noise2   {unNoise2 :: Seed -> a -> a -> a} +-- | Increment the seed for a 2D noise function.+--+-- This is useful for generating independent noise layers:+--+-- @+-- layer1 = perlin2+-- layer2 = next2 perlin2+-- layer3 = next2 (next2 perlin2)+-- @ next2 :: Noise2 a -> Noise2 a next2 (Noise2 f) = Noise2 (\s x y -> f (s + 1) x y) {-# INLINE next2 #-}@@ -36,6 +59,12 @@ map2 f (Noise2 g) = Noise2 (\s x y -> f (g s x y)) {-# INLINE map2 #-} +-- | Clamp the output of a 2D noise function to the range @[lower, upper]@.+--+-- @+-- clamped :: Noise2 Float+-- clamped = clamp2 0 1 perlin2  -- clamp to [0, 1]+-- @ clamp2 :: (Ord a) => a -> a -> Noise2 a -> Noise2 a clamp2 l u (Noise2 f) = Noise2 $ \s x y -> clamp l u (f s x y) {-# INLINE clamp2 #-}@@ -44,6 +73,10 @@ const2 a = Noise2 (\_ _ _ -> a) {-# INLINE const2 #-} +-- | Arithmetic operations on 'Noise2' are performed point-wise.+--+-- For example, @n1 + n2@ creates a new noise function that adds the+-- results of @n1@ and @n2@ at each coordinate. instance (Num a) => Num (Noise2 a) where   Noise2 f + Noise2 g = Noise2 $ \s x y -> f s x y + g s x y   {-# INLINE (+) #-}@@ -94,9 +127,21 @@   atanh (Noise2 f) = Noise2 $ \s x y -> atanh (f s x y)   {-# INLINE atanh #-} +-- | A 3D noise function parameterized by a seed and three coordinates.+--+-- 'Noise3' wraps a function @Seed -> a -> a -> a -> a@ that takes a seed value+-- and x, y, z coordinates to produce a noise value.+--+-- Like 'Noise2', this type supports 'Num', 'Fractional', and 'Floating' instances+-- for algebraic composition.+--+-- To evaluate a 'Noise3', use 'noise3At' from "Numeric.Noise". newtype Noise3 a = Noise3   {unNoise3 :: Seed -> a -> a -> a -> a} +-- | Increment the seed for a 3D noise function.+--+-- Analogous to 'next2', this is useful for generating independent 3D noise layers. next3 :: Noise3 a -> Noise3 a next3 (Noise3 f) = Noise3 (\s x y z -> f (s + 1) x y z) {-# INLINE next3 #-}@@ -109,10 +154,20 @@ const3 a = Noise3 (\_ _ _ _ -> a) {-# INLINE const3 #-} +-- | Clamp the output of a 3D noise function to the range @[lower, upper]@.+--+-- @+-- clamped :: Noise3 Float+-- clamped = clamp3 (-0.5) 0.5 perlin3  -- clamp to [-0.5, 0.5]+-- @ clamp3 :: (Ord a) => a -> a -> Noise3 a -> Noise3 a clamp3 l u (Noise3 f) = Noise3 $ \s x y z -> clamp l u (f s x y z) {-# INLINE clamp3 #-} +-- | Arithmetic operations on 'Noise3' are performed point-wise.+--+-- For example, @n1 * n2@ creates a new noise function that multiplies the+-- results of @n1@ and @n2@ at each coordinate. instance (Num a) => Num (Noise3 a) where   Noise3 f + Noise3 g = Noise3 $ \s x y z -> f s x y z + g s x y z   {-# INLINE (+) #-}@@ -132,6 +187,8 @@   {-# INLINE fromRational #-}   recip (Noise3 f) = Noise3 $ \s x y z -> recip (f s x y z)   {-# INLINE recip #-}+  Noise3 f / Noise3 g = Noise3 $ \s x y z -> f s x y z / g s x y z+  {-# INLINE (/) #-}  instance (Floating a) => Floating (Noise3 a) where   pi = const3 pi
src/Numeric/Noise/Internal/Math.hs view
@@ -29,13 +29,22 @@  import Data.Bits import Data.Int-import Data.Vector.Unboxed qualified as U+import Data.Primitive.PrimArray import Data.Word +-- | Seed value for deterministic noise generation.+--+-- Using the same 'Seed' value will produce the same noise pattern,+-- allowing for reproducible results. Different seed values produce+-- different, independent noise patterns. type Seed = Word64++-- | Internal hash value type used in noise calculations. type Hash = Int32 --- | monotonic lerp+-- | Linear interpolation between two values.+--+-- Monotonic lerp lerp   :: (Num a)   => a@@ -65,6 +74,10 @@ quinticInterp t = t * t * t * (t * (t * 6 - 15) + 10) {-# INLINE quinticInterp #-} +-- | Clamp a value to a specified range.+--+-- Returns the value if it's within bounds, otherwise returns+-- the nearest boundary. clamp   :: (Ord a)   => a@@ -130,8 +143,8 @@ gradCoord2 seed xPrimed yPrimed xd yd =   let !hash = hash2 seed xPrimed yPrimed       !ix = (hash `xor` (hash `shiftR` 15)) .&. 0xFE-      !xg = grad2d `U.unsafeIndex` fromIntegral ix-      !yg = grad2d `U.unsafeIndex` fromIntegral (ix .|. 1)+      !xg = grad2d `indexPrimArray` fromIntegral ix+      !yg = grad2d `indexPrimArray` fromIntegral (ix .|. 1)    in xd * realToFrac xg + yd * realToFrac yg {-# INLINE gradCoord2 #-} @@ -139,9 +152,9 @@ gradCoord3 seed xPrimed yPrimed zPrimed xd yd zd =   let !hash = hash3 seed xPrimed yPrimed zPrimed       !ix = (hash `xor` (hash `shiftR` 15)) .&. 0xFC-      !xg = grad3d `U.unsafeIndex` fromIntegral ix-      !yg = grad3d `U.unsafeIndex` fromIntegral (ix .|. 1)-      !zg = grad3d `U.unsafeIndex` fromIntegral (ix .|. 2)+      !xg = grad3d `indexPrimArray` fromIntegral ix+      !yg = grad3d `indexPrimArray` fromIntegral (ix .|. 1)+      !zg = grad3d `indexPrimArray` fromIntegral (ix .|. 2)    in xd * fromIntegral xg + yd * fromIntegral yg + zd * fromIntegral zg {-# INLINE gradCoord3 #-} @@ -150,9 +163,9 @@ {-# INLINE maxHash #-}  {- ORMOLU_DISABLE -}--- >>> U.length grad2d == 256+-- >>> sizeofPrimArray grad2d == 256 -- True-grad2d :: U.Vector Float+grad2d :: PrimArray Float grad2d =   [ 0.130526192220052,  0.99144486137381 ,  0.38268343236509 ,  0.923879532511287,  0.608761429008721,  0.793353340291235,  0.793353340291235,  0.608761429008721,     0.923879532511287,  0.38268343236509 ,  0.99144486137381 ,  0.130526192220051,  0.99144486137381 , -0.130526192220051,  0.923879532511287, -0.38268343236509,@@ -187,10 +200,11 @@     0.38268343236509 ,  0.923879532511287,  0.923879532511287,  0.38268343236509 ,  0.923879532511287, -0.38268343236509 ,  0.38268343236509 , -0.923879532511287,    -0.38268343236509 , -0.923879532511287, -0.923879532511287, -0.38268343236509 , -0.923879532511287,  0.38268343236509 , -0.38268343236509 ,  0.923879532511287   ]+{-# INLINABLE grad2d #-} --- >>> U.length grad3d == 256+-- >>> sizeofPrimArray grad3d == 256 -- True-grad3d :: U.Vector Int+grad3d :: PrimArray Int grad3d =   [ 0, 1, 1, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, -1, -1, 0   , 1, 0, 1, 0, -1, 0, 1, 0, 1, 0, -1, 0, -1, 0, -1, 0@@ -209,3 +223,4 @@   , 1, 1, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, -1, -1, 0, 0   , 1, 1, 0, 0, 0, -1, 1, 0, -1, 1, 0, 0, 0, -1, -1, 0   ]+{-# INLINABLE grad3d #-}
src/Numeric/Noise/OpenSimplex.hs view
src/Numeric/Noise/Perlin.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE Strict #-}- -- | -- Maintainer: Jeremy Nuttall <jeremy@jeremy-nuttall.com> -- Stability : experimental
src/Numeric/Noise/SuperSimplex.hs view
src/Numeric/Noise/Value.hs view
src/Numeric/Noise/ValueCubic.hs view
test/Noise2Spec.hs view
@@ -1,7 +1,6 @@ module Noise2Spec where  import Numeric.Noise-import Numeric.Noise.Internal  seed :: Seed seed = 55
test/Noise3Spec.hs view
@@ -1,7 +1,6 @@ module Noise3Spec where  import Numeric.Noise-import Numeric.Noise.Internal  seed :: Seed seed = 2381
test/PerlinSpec.hs view
@@ -1,5 +1,6 @@ module PerlinSpec where +import GHC.Exts (noinline) import Numeric.Noise  seed :: Seed@@ -12,8 +13,10 @@  prop_noise2_addition_associative :: Rational -> Rational -> Bool prop_noise2_addition_associative x y =-  noise2At ((perlin2 + perlin2) + perlin2) seed x y == noise2At (perlin2 + (perlin2 + perlin2)) seed x y+  noise2At ((noinline perlin2 + noinline superSimplex2) + noinline openSimplex2) seed x y+    == noise2At (perlin2 + (noinline superSimplex2 + noinline openSimplex2)) seed x y  prop_noise2_addition_commutative :: Rational -> Rational -> Bool prop_noise2_addition_commutative x y =-  noise2At (perlin2 + perlin2) seed x y == noise2At (perlin2 + perlin2) seed x y+  noise2At (noinline perlin2 + noinline superSimplex2) seed x y+    == noise2At (noinline superSimplex2 + noinline perlin2) seed x y