diff --git a/HsASA.cabal b/HsASA.cabal
new file mode 100644
--- /dev/null
+++ b/HsASA.cabal
@@ -0,0 +1,30 @@
+name:               HsASA
+version:            0.1
+homepage:           http://repetae.net/recent/out/HsASA.html
+synopsis:           A haskell interface to Lester Ingber's adaptive simulating annealing code
+description:        A haskell interface to Lester Ingber's adaptive simulating annealing code
+category:           Math
+license:            BSD3
+license-file:       LICENSE.asa
+author:             John Meacham
+extra-source-files: Main.hs Makefile README
+cabal-version:      >= 1.2
+build-type:         Simple
+
+library
+    build-depends:    base, array, haskell98
+    exposed-modules:
+                      Optimize.ASA
+                      Optimize.Parameter
+
+    ghc-options:      -O2 -funbox-strict-fields
+    cc-options:       -O2 -msse
+    extensions:       ForeignFunctionInterface,
+                      UndecidableInstances,
+                      PatternSignatures,
+                      Rank2Types
+
+    c-sources:        cbits/asa.c cbits/hs_asa.c
+    include-dirs:     include
+    includes:         asa.h asa_usr.h asa_usr_asa.h
+    install-includes: asa.h asa_usr.h asa_usr_asa.h
diff --git a/LICENSE.asa b/LICENSE.asa
new file mode 100644
--- /dev/null
+++ b/LICENSE.asa
@@ -0,0 +1,58 @@
+/***********************************************************************
+* Adaptive Simulated Annealing (ASA)
+* Lester Ingber <ingber@ingber.com>
+* Copyright (c) 1993-2004 Lester Ingber.  All Rights Reserved.
+* This LICENSE file must be included with ASA code.
+***********************************************************************/
+	
+$Id: LICENSE,v 25.15 2004/09/23 18:10:35 ingber Exp ingber $
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+			CONDITIONS
+
+1. Redistributions of ASA source code must retain the above copyright
+notice, this list of conditions, and the following disclaimer.
+
+2. Redistributions in binary form must contain the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+3. All modifications to the source code must be clearly marked as
+such.  Binary redistributions based on modified source code must be
+clearly marked as modified versions in the documentation and/or other
+materials provided with the distribution.
+
+4. Notice must be given of the location of the availability of the
+unmodified current source code, e.g.,
+	http://www.ingber.com/
+or
+	ftp://ftp.ingber.com
+in the documentation and/or other materials provided with the
+distribution.
+
+5. All advertising and published materials mentioning features or use
+of this software must display the following acknowledgment:  "This
+product includes software developed by Lester Ingber and other
+contributors."
+
+6. The name of Lester Ingber may not be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+
+			DISCLAIMER
+
+This software is provided by Lester Ingber and contributors "as is" and
+any expressed or implied warranties, including, but not limited to, the
+implied warranties of merchantability and fitness for a particular
+purpose are disclaimed.  In no event shall Lester Ingber or
+contributors be liable for any direct, indirect, incidental, special,
+exemplary, or consequential damages (including, but not limited to,
+procurement of substitute goods or services; loss of use, data, or
+profits; or business interruption) however caused and on any theory of
+liability, whether in contract, strict liability, or tort (including
+negligence or otherwise) arising in any way out of the use of this
+software, even if advised of the possibility of such damage.
+
diff --git a/Main.hs b/Main.hs
new file mode 100644
--- /dev/null
+++ b/Main.hs
@@ -0,0 +1,23 @@
+
+
+import Optimize.ASA
+import Optimize.Parameter
+import Random
+
+
+f :: (Bool,(Double,Double)) -> Double
+f (tf,(x,y)) = if  tf then x*x + y*y else x + x*x - log y 
+
+g :: Either (Int,Int) Int -> Double
+g (Left (x,y)) = realToFrac $ x * y
+g (Right r) = pi*(realToFrac r)^2
+
+main =  do
+    v1 <- minimize (empty,(limit (-10) 3, limit 4 7)) f  
+    v2 <- minimize (empty,(limit (-10) 3, limit 4 7)) (negate . f)  
+    v3 <- minimize ((limit 10 100,limit 3 1000), limit 4 1000) g  
+    v4 <- minimize ((limit 10 100,limit 3 1000), limit 4 1000) (negate . g)  
+    print v1
+    print v2
+    print v3
+    print v4
diff --git a/Makefile b/Makefile
new file mode 100644
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,27 @@
+HSC2HS = hsc2hs
+CC = ghc
+LDLIBS = -lm 
+CFLAGS = -O2 -optc-msse -optc-g
+HSC_CFLAGS = -C -O2 -C -optc-msse -C -optc-g
+
+main: Main.hs asa.o hs_asa.o  Optimize/*.hs Optimize/ASA.hs
+	ghc -O --make Main.hs asa.o hs_asa.o  -o $@
+
+www-publish: Optimize/ASA.hs
+
+asa.o: asa.h asa_usr.h asa_usr_asa.h
+hs_asa.o: asa_usr.h asa_usr_asa.h
+
+clean:
+	rm *.o main Optimize/*.o Optimize/*.hi *.hi
+
+asa_fuzzy: asa_fuzzy.o asa.o 
+
+%.hi: %.o 
+	@:
+%_hsc.c: %.hs
+	@:
+%_hsc.h: %.hs
+	@:
+%.hs: %.hsc
+	$(HSC2HS) $(HSC_CFLAGS) -C -I. -C -I@srcdir@ -o $@ $<
diff --git a/Optimize/ASA.hsc b/Optimize/ASA.hsc
new file mode 100644
--- /dev/null
+++ b/Optimize/ASA.hsc
@@ -0,0 +1,80 @@
+{-# OPTIONS -ffi -fglasgow-exts #-}
+-- | interface to the Adaptive Simulated Annealing algorithm.
+
+module Optimize.ASA where 
+
+#include "asa_usr.h"
+
+import Optimize.Parameter
+import Foreign.C.Types
+import Foreign.Storable
+import Foreign.Ptr
+import Foreign.Marshal.Array
+import Foreign.Marshal.Alloc
+import Random
+import Data.Array.Unboxed
+import Data.Int
+
+
+newtype UserOptions = UserOptions (Ptr UserOptions)
+type Doubles = UArray Int Double    
+
+data ExitCode =  NormalExit | PTempTooSmall | CTempTooSmall | CostRepeating | TooManyInvalidStates | ImmediateExit | InvalidUserInput | InvalidCostFunction | InvalidCostFunctionDeriv 
+    deriving(Eq,Ord,Enum,Show,Read)
+
+
+data Results x = Results {
+    optimalValue :: Double,
+    optimalParam :: x,
+    exitCode :: ExitCode
+    }
+
+
+type CostFunction =  Ptr Double -> Ptr Int -> IO Double
+
+foreign import ccall "wrapper" mkCostFunction :: CostFunction -> IO (FunPtr CostFunction)  
+foreign import ccall "asa_usr.h asa_main" asa_main :: FunPtr CostFunction -> CInt -> Ptr Double -> Ptr Double -> Ptr CInt -> Ptr Double -> Ptr Double -> Ptr CInt -> CInt -> IO CInt
+
+
+
+
+asa :: UserOptions     -- Options
+    -> (Doubles -> IO (Maybe Double)) -- cost function 
+    -> Int64           -- random number seed
+    -> Maybe Doubles   -- starting position
+    -> Doubles         -- upper bounds
+    -> Doubles         -- lower bounds
+    -> UArray Int Bool -- parameters are integral
+    -> IO (ExitCode,Doubles)      -- final answers
+asa = undefined
+
+toBasicCostFunction :: Parameter z x => z -> (x -> Double) -> CostFunction
+toBasicCostFunction z fn = f where
+    thePeek = peekParam z 
+    f pd pf = do
+        poke pf 1
+        x <- thePeek pd
+        let v = fn x
+        --putStrLn $ ">> Haskell Function Called: " ++ show v 
+        return $  v
+        
+
+minimize :: Parameter z x => z -> (x -> Double) -> IO x 
+minimize z (fn :: x -> Double ) = do
+    cf <- mkCostFunction (toBasicCostFunction z fn)
+    let n = numParams (undefined :: x) z 
+    let ps = paramInfo (undefined :: x) z []
+    withArray (map limitLow ps) $ \lower_bounds -> do  
+    withArray (map limitHigh ps) $ \upper_bounds -> do  
+    withArray (map (\x -> if isIntegral x then (#const INTEGER_TYPE) else (#const REAL_TYPE)) ps) $ \real_int -> do  
+    alloca $ \dummy_cost_val -> do 
+    allocaArray n $ \ret -> do
+    alloca $ \exit_code -> do 
+    r <- randomIO
+    asa_main cf (fromIntegral n) upper_bounds lower_bounds real_int dummy_cost_val ret exit_code (fromIntegral (r :: Int))
+    --code <- peek exit_code
+    --print (toEnum (fromIntegral code) :: ExitCode)
+    peekParam z ret 
+
+
+    
diff --git a/Optimize/Parameter.hs b/Optimize/Parameter.hs
new file mode 100644
--- /dev/null
+++ b/Optimize/Parameter.hs
@@ -0,0 +1,203 @@
+{-# OPTIONS -fglasgow-exts #-}
+-- | Defines the mapping between haskell types and a set of optimization
+-- parameters used to represent said type.
+
+module Optimize.Parameter where 
+
+import Foreign.Storable
+import Foreign.Ptr
+import Foreign.C.Types
+import Char
+
+
+smallDouble :: Double
+smallDouble = 1.0e-12
+bigDouble = 1.0e6
+
+data ParamInfo = ParamInfo {
+    limitLow :: {-# UNBOX #-} !Double,
+    limitHigh :: {-# UNBOX #-} !Double,
+    isIntegral :: {-# UNBOX #-} !Bool
+}
+
+paramInfoFloat = ParamInfo {
+    limitLow = -bigDouble,
+    limitHigh = bigDouble,
+    isIntegral = False
+}
+
+paramInfoInt = paramInfoFloat { limitLow = realToFrac (minBound :: Int), limitHigh = realToFrac (maxBound :: Int), isIntegral = True }
+
+data Limit a = Limit { minLimit :: Maybe a, maxLimit :: Maybe a }
+
+limit x y = Limit { minLimit = Just x, maxLimit = Just y }
+limitMin x = Limit { minLimit = Just x, maxLimit = Nothing }
+limitMax x = Limit { minLimit = Nothing, maxLimit = Just x }
+limitPositive,limitNegative,limitUnit :: Num a => Limit a
+limitPositive = limitMin 0
+limitNegative = limitMax 0
+limitUnit = limit 0 1
+
+
+
+-- z is the meta-info for the given type. such as bounds.
+
+-- This really should be a superclass of Monoid
+class Empty a where
+    empty :: a
+
+instance Empty () where
+    empty = ()
+instance (Empty x, Empty y) => Empty (x,y) where
+    empty = (empty,empty)
+instance (Empty x, Empty y, Empty z) => Empty (x,y,z) where
+    empty = (empty,empty,empty)
+instance Empty (Maybe a) where
+    empty = Nothing
+instance Empty (Limit a) where
+    empty = Limit { minLimit = Nothing, maxLimit = Nothing }
+
+class Empty z => Parameter z x | x -> z where
+    pokeParam :: z -> x -> Ptr Double -> IO ()
+    peekParam :: z -> Ptr Double -> IO x    -- needs to be as fast as possible
+    -- x is only needed on these for its type. (can we do this in a better way?)
+    paramInfo :: x -> z -> [ParamInfo] -> [ParamInfo]
+    numParams :: x -> z ->  Int
+
+instance Parameter () () where
+    pokeParam _ _ _ = return ()
+    peekParam _ _ = return ()
+    numParams _ _ = 0
+    paramInfo _ _ x = x
+
+
+instance Parameter () Bool where
+    pokeParam _ False p = poke p 0
+    pokeParam _ True p = poke p 1
+    peekParam _ p = do
+        x <- peek p
+        return (not $ abs x < smallDouble)
+    paramInfo _ _ xs = ParamInfo { limitLow = 0, limitHigh = 1, isIntegral = True }:xs
+    numParams _ _ = 1
+
+instance (Parameter za a, Parameter zb b) => Parameter (za,zb) (a,b) where
+    pokeParam (za,zb) ((a::a),b) p = do
+        pokeParam za a p 
+        pokeParam zb b (p `advancePtr` numParams (undefined::a) za) 
+    peekParam (za,zb) p = do
+        (a::a) <- peekParam za p 
+        b <- peekParam zb (p `advancePtr` numParams (undefined::a) za)
+        return (a,b)
+    paramInfo (_ :: (a,b)) (za,zb) = paramInfo a za . paramInfo b zb where
+        a = undefined :: a
+        b = undefined :: b
+
+    numParams (_ :: (a,b)) (za,zb) = numParams a za + numParams b zb  where
+        a = undefined :: a
+        b = undefined :: b
+
+instance (Parameter za a, Parameter zb b, Parameter zc c) => Parameter (za,zb,zc) (a,b,c) where
+    pokeParam (za,zb,zc) (a,b,c) p = do
+        pokeParam (za,(zb,zc)) (a,(b,c)) p
+    peekParam (za,zb,zc) p = do
+        (a,(b,c)) <- peekParam (za,(zb,zc)) p 
+        return (a,b,c)
+    paramInfo (_ :: (a,b,c)) (za,zb,zc) = paramInfo a za . paramInfo b zb . paramInfo c zc where
+        a = undefined :: a
+        b = undefined :: b
+        c = undefined :: c
+
+    numParams (_ :: (a,b,c)) (za,zb,zc) = numParams a za + numParams b zb + numParams c zc  where
+        a = undefined :: a
+        b = undefined :: b
+        c = undefined :: c
+
+instance Parameter (Limit Double) Double where
+    pokeParam _ x p = poke p  x
+    peekParam _ p = peek p 
+    paramInfo _ Limit { minLimit = Nothing, maxLimit = Nothing } xs = paramInfoFloat :xs
+    paramInfo _ Limit { minLimit = Just x, maxLimit = Nothing } xs = paramInfoFloat { limitLow =  x }:xs
+    paramInfo _ Limit { minLimit = Just x, maxLimit = Just y } xs = paramInfoFloat { limitLow =  x, limitHigh =  y }:xs
+    paramInfo _ Limit { minLimit = Nothing, maxLimit = Just y } xs = paramInfoFloat { limitHigh =  y }:xs
+    numParams _ _ = 1
+    
+instance Parameter (Limit Int) Int where
+    pokeParam _ x p = poke p (realToFrac x)
+    peekParam _ p = peek p >>= return . round
+    paramInfo _ Limit { minLimit = Nothing, maxLimit = Nothing } xs = paramInfoInt :xs
+    paramInfo _ Limit { minLimit = Just x, maxLimit = Nothing } xs = paramInfoInt { limitLow = realToFrac x }:xs
+    paramInfo _ Limit { minLimit = Just x, maxLimit = Just y } xs = paramInfoInt { limitLow = realToFrac x, limitHigh = realToFrac y }:xs
+    paramInfo _ Limit { minLimit = Nothing, maxLimit = Just y } xs = paramInfoInt { limitHigh = realToFrac y }:xs
+    numParams _ _ = 1
+
+
+-- Of questionable utility.
+instance Parameter ()  Char where 
+    pokeParam _ x p = poke p (realToFrac $ ord x)
+    peekParam _ p = peek p >>= return . chr . round
+    paramInfo _ () xs = paramInfoInt { limitLow = 0x20, limitHigh = 0x7e }:xs
+    numParams _ _ = 1
+    
+
+
+instance Parameter (Limit Float) Float where
+    pokeParam _ x p = poke p (realToFrac x)
+    peekParam _ p = peek p >>= return . realToFrac
+    paramInfo _ Limit { minLimit = Nothing, maxLimit = Nothing } xs = paramInfoFloat :xs
+    paramInfo _ Limit { minLimit = Just x, maxLimit = Nothing } xs = paramInfoFloat { limitLow = realToFrac x }:xs
+    paramInfo _ Limit { minLimit = Just x, maxLimit = Just y } xs = paramInfoFloat { limitLow = realToFrac x, limitHigh = realToFrac y }:xs
+    paramInfo _ Limit { minLimit = Nothing, maxLimit = Just y } xs = paramInfoFloat { limitHigh = realToFrac y }:xs
+    numParams _ _ = 1
+
+instance Parameter zb b => Parameter zb (Maybe b) where
+    pokeParam zb (Nothing :: Maybe b) p = do
+        pokeParam ((),zb) (Left () :: Either () b) p
+    pokeParam zb (Just b :: Maybe b) p = do
+        pokeParam ((),zb) (Right b :: Either () b) p
+    peekParam zb p = do
+        v <- peekParam ((),zb) p
+        case v of
+            Right b -> return $ Just b
+            Left () -> return $ Nothing
+    paramInfo (_ :: Maybe b) z = paramInfo (undefined :: Either () b) ((),z)
+    numParams (_ :: Maybe b) z = numParams (undefined :: Either () b) ((),z)
+
+    
+    
+    
+
+instance (Parameter za a, Parameter zb b) => Parameter (za,zb) (Either a b) where
+    pokeParam (za,zb) (Left a :: Either a b) p = do
+        pokeParam empty False p
+        p <- return $  (p `advancePtr` 1)
+        pokeParam za a p
+    pokeParam (za,zb) (Right b :: Either a b) p = do
+        pokeParam empty False p
+        p <- return $  (p `advancePtr` (1 + numParams (undefined :: a) za))
+        pokeParam zb b p
+    peekParam (za,zb) p  = do
+        b <- peekParam () p
+        p <- return $  (p `advancePtr` 1)
+        case b of
+            False -> do
+                a <- peekParam za p 
+                return $ Left a
+            True -> do
+                let f :: Either a b -> a -> Either a b
+                    f x _ = x
+                un <- return undefined
+                p <- return $ (p `advancePtr` numParams un za)
+                a <- peekParam zb p 
+                return $ f (Right a) un
+    paramInfo (_ :: Either a b) (za,zb) = paramInfo (undefined :: Bool) empty . paramInfo a za . paramInfo b zb where
+        a = undefined :: a
+        b = undefined :: b
+    numParams (_ :: Either a b) (za,zb) = 1 + numParams a za + numParams b zb  where
+        a = undefined :: a
+        b = undefined :: b
+
+advancePtr :: forall a. Storable a => Ptr a -> Int -> Ptr a
+advancePtr (p :: Ptr a) n = p `plusPtr` (n * sizeOf (undefined :: a)) 
+
+--instance (Parameter a, Parameter b) => Parameter (Either a b) where
+--      pokeParam = pokeParam (Bool,a,b)
diff --git a/README b/README
new file mode 100644
--- /dev/null
+++ b/README
@@ -0,0 +1,2 @@
+A haskell interface to Lester Ingber's adaptive simulating annealing code. 
+
diff --git a/Setup.lhs b/Setup.lhs
new file mode 100644
--- /dev/null
+++ b/Setup.lhs
@@ -0,0 +1,3 @@
+#!/usr/bin/env runhaskell
+> import Distribution.Simple
+> main = defaultMain
diff --git a/_darcs/format b/_darcs/format
new file mode 100644
--- /dev/null
+++ b/_darcs/format
@@ -0,0 +1,1 @@
+darcs-1.0
diff --git a/_darcs/inventory b/_darcs/inventory
new file mode 100644
--- /dev/null
+++ b/_darcs/inventory
@@ -0,0 +1,8 @@
+[initial import
+John Meacham <john@repetae.net>**20050119222636] 
+[Get ready for publication
+John Meacham <john@repetae.net>**20050119223112] 
+[Fix for haddock
+John Meacham <john@repetae.net>**20050119225844] 
+[Don't pass CFLAGS as a lump
+Aaron Denney <wnoise@ofb.net>**20050518054418] 
diff --git a/_darcs/patches/20050119222636-1a7c6-21b43a4c7b95ff8cf14b9172c183ce40fad6063a.gz b/_darcs/patches/20050119222636-1a7c6-21b43a4c7b95ff8cf14b9172c183ce40fad6063a.gz
new file mode 100644
Binary files /dev/null and b/_darcs/patches/20050119222636-1a7c6-21b43a4c7b95ff8cf14b9172c183ce40fad6063a.gz differ
diff --git a/_darcs/patches/20050119223112-1a7c6-9e5331c024ae010cc8dbc5ac7b9c5f0535e42bd8.gz b/_darcs/patches/20050119223112-1a7c6-9e5331c024ae010cc8dbc5ac7b9c5f0535e42bd8.gz
new file mode 100644
Binary files /dev/null and b/_darcs/patches/20050119223112-1a7c6-9e5331c024ae010cc8dbc5ac7b9c5f0535e42bd8.gz differ
diff --git a/_darcs/patches/20050119225844-1a7c6-780693a86626c686cb86fec84175b7a2e901a1a0.gz b/_darcs/patches/20050119225844-1a7c6-780693a86626c686cb86fec84175b7a2e901a1a0.gz
new file mode 100644
Binary files /dev/null and b/_darcs/patches/20050119225844-1a7c6-780693a86626c686cb86fec84175b7a2e901a1a0.gz differ
diff --git a/_darcs/patches/20050518054418-859d9-e48366547a7cac704fd95ac4b7bd3333d6a28035.gz b/_darcs/patches/20050518054418-859d9-e48366547a7cac704fd95ac4b7bd3333d6a28035.gz
new file mode 100644
Binary files /dev/null and b/_darcs/patches/20050518054418-859d9-e48366547a7cac704fd95ac4b7bd3333d6a28035.gz differ
diff --git a/_darcs/prefs/binaries b/_darcs/prefs/binaries
new file mode 100644
--- /dev/null
+++ b/_darcs/prefs/binaries
@@ -0,0 +1,59 @@
+# Binary file regexps:
+\.png$
+\.PNG$
+\.gz$
+\.GZ$
+\.pdf$
+\.PDF$
+\.jpg$
+\.JPG$
+\.jpeg$
+\.JPEG$
+\.gif$
+\.GIF$
+\.tif$
+\.TIF$
+\.tiff$
+\.TIFF$
+\.pnm$
+\.PNM$
+\.pbm$
+\.PBM$
+\.pgm$
+\.PGM$
+\.ppm$
+\.PPM$
+\.bmp$
+\.BMP$
+\.mng$
+\.MNG$
+\.tar$
+\.TAR$
+\.bz2$
+\.BZ2$
+\.z$
+\.Z$
+\.zip$
+\.ZIP$
+\.jar$
+\.JAR$
+\.so$
+\.SO$
+\.a$
+\.A$
+\.tgz$
+\.TGZ$
+\.mpg$
+\.MPG$
+\.mpeg$
+\.MPEG$
+\.iso$
+\.ISO$
+\.exe$
+\.EXE$
+\.doc$
+\.DOC$
+\.elc$
+\.ELC$
+\.pyc$
+\.PYC$
diff --git a/_darcs/prefs/boring b/_darcs/prefs/boring
new file mode 100644
--- /dev/null
+++ b/_darcs/prefs/boring
@@ -0,0 +1,68 @@
+# Boring file regexps:
+\.hi$
+\.hi-boot$
+\.o-boot$
+\.o$
+\.o\.cmd$
+\.p_hi$
+\.p_o$
+\.installed-pkg-config
+\.setup-config
+\.setup-config^dist(/|$)
+# *.ko files aren't boring by default because they might
+# be Korean translations rather than kernel modules.
+# \.ko$
+\.ko\.cmd$
+\.mod\.c$
+(^|/)\.tmp_versions($|/)
+(^|/)CVS($|/)
+\.cvsignore$
+^\.#
+(^|/)RCS($|/)
+,v$
+(^|/)\.svn($|/)
+(^|/)\.hg($|/)
+(^|/)\.git($|/)
+\.bzr$
+(^|/)SCCS($|/)
+~$
+(^|/)_darcs($|/)
+(^|/)\.darcsrepo($|/)
+\.bak$
+\.BAK$
+\.orig$
+\.rej$
+(^|/)vssver\.scc$
+\.swp$
+(^|/)MT($|/)
+(^|/)\{arch\}($|/)
+(^|/).arch-ids($|/)
+(^|/),
+\.prof$
+(^|/)\.DS_Store$
+(^|/)BitKeeper($|/)
+(^|/)ChangeSet($|/)
+\.py[co]$
+\.elc$
+\.class$
+\.zwc$
+\.revdep-rebuild.*
+\..serverauth.*
+\#
+(^|/)Thumbs\.db$
+(^|/)autom4te\.cache($|/)
+(^|/)config\.(log|status)$
+^\.depend$
+(^|/)(tags|TAGS)$
+#(^|/)\.[^/]
+(^|/|\.)core$
+\.(obj|a|exe|so|lo|la)$
+^\.darcs-temp-mail$
+-darcs-backup[[:digit:]]+$
+\.(fas|fasl|sparcf|x86f)$
+\.part$
+(^|/)\.waf-[[:digit:].]+-[[:digit:]]+($|/)
+(^|/)\.lock-wscript$
+^\.darcs-temp-mail$
+\_vti_cnf$
+\_vti_pvt$
diff --git a/_darcs/prefs/defaultrepo b/_darcs/prefs/defaultrepo
new file mode 100644
--- /dev/null
+++ b/_darcs/prefs/defaultrepo
@@ -0,0 +1,1 @@
+http://repetae.net/john/repos/HsASA
diff --git a/_darcs/prefs/motd b/_darcs/prefs/motd
new file mode 100644
--- /dev/null
+++ b/_darcs/prefs/motd
diff --git a/_darcs/prefs/repos b/_darcs/prefs/repos
new file mode 100644
--- /dev/null
+++ b/_darcs/prefs/repos
@@ -0,0 +1,1 @@
+http://repetae.net/john/repos/HsASA
diff --git a/_darcs/pristine/LICENSE.asa b/_darcs/pristine/LICENSE.asa
new file mode 100644
--- /dev/null
+++ b/_darcs/pristine/LICENSE.asa
@@ -0,0 +1,58 @@
+/***********************************************************************
+* Adaptive Simulated Annealing (ASA)
+* Lester Ingber <ingber@ingber.com>
+* Copyright (c) 1993-2004 Lester Ingber.  All Rights Reserved.
+* This LICENSE file must be included with ASA code.
+***********************************************************************/
+	
+$Id: LICENSE,v 25.15 2004/09/23 18:10:35 ingber Exp ingber $
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+			CONDITIONS
+
+1. Redistributions of ASA source code must retain the above copyright
+notice, this list of conditions, and the following disclaimer.
+
+2. Redistributions in binary form must contain the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+3. All modifications to the source code must be clearly marked as
+such.  Binary redistributions based on modified source code must be
+clearly marked as modified versions in the documentation and/or other
+materials provided with the distribution.
+
+4. Notice must be given of the location of the availability of the
+unmodified current source code, e.g.,
+	http://www.ingber.com/
+or
+	ftp://ftp.ingber.com
+in the documentation and/or other materials provided with the
+distribution.
+
+5. All advertising and published materials mentioning features or use
+of this software must display the following acknowledgment:  "This
+product includes software developed by Lester Ingber and other
+contributors."
+
+6. The name of Lester Ingber may not be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+
+			DISCLAIMER
+
+This software is provided by Lester Ingber and contributors "as is" and
+any expressed or implied warranties, including, but not limited to, the
+implied warranties of merchantability and fitness for a particular
+purpose are disclaimed.  In no event shall Lester Ingber or
+contributors be liable for any direct, indirect, incidental, special,
+exemplary, or consequential damages (including, but not limited to,
+procurement of substitute goods or services; loss of use, data, or
+profits; or business interruption) however caused and on any theory of
+liability, whether in contract, strict liability, or tort (including
+negligence or otherwise) arising in any way out of the use of this
+software, even if advised of the possibility of such damage.
+
diff --git a/_darcs/pristine/Main.hs b/_darcs/pristine/Main.hs
new file mode 100644
--- /dev/null
+++ b/_darcs/pristine/Main.hs
@@ -0,0 +1,23 @@
+
+
+import Optimize.ASA
+import Optimize.Parameter
+import Random
+
+
+f :: (Bool,(Double,Double)) -> Double
+f (tf,(x,y)) = if  tf then x*x + y*y else x + x*x - log y 
+
+g :: Either (Int,Int) Int -> Double
+g (Left (x,y)) = realToFrac $ x * y
+g (Right r) = pi*(realToFrac r)^2
+
+main =  do
+    v1 <- minimize (empty,(limit (-10) 3, limit 4 7)) f  
+    v2 <- minimize (empty,(limit (-10) 3, limit 4 7)) (negate . f)  
+    v3 <- minimize ((limit 10 100,limit 3 1000), limit 4 1000) g  
+    v4 <- minimize ((limit 10 100,limit 3 1000), limit 4 1000) (negate . g)  
+    print v1
+    print v2
+    print v3
+    print v4
diff --git a/_darcs/pristine/Makefile b/_darcs/pristine/Makefile
new file mode 100644
--- /dev/null
+++ b/_darcs/pristine/Makefile
@@ -0,0 +1,27 @@
+HSC2HS = hsc2hs
+CC = ghc
+LDLIBS = -lm 
+CFLAGS = -O2 -optc-msse -optc-g
+HSC_CFLAGS = -C -O2 -C -optc-msse -C -optc-g
+
+main: Main.hs asa.o hs_asa.o  Optimize/*.hs Optimize/ASA.hs
+	ghc -O --make Main.hs asa.o hs_asa.o  -o $@
+
+www-publish: Optimize/ASA.hs
+
+asa.o: asa.h asa_usr.h asa_usr_asa.h
+hs_asa.o: asa_usr.h asa_usr_asa.h
+
+clean:
+	rm *.o main Optimize/*.o Optimize/*.hi *.hi
+
+asa_fuzzy: asa_fuzzy.o asa.o 
+
+%.hi: %.o 
+	@:
+%_hsc.c: %.hs
+	@:
+%_hsc.h: %.hs
+	@:
+%.hs: %.hsc
+	$(HSC2HS) $(HSC_CFLAGS) -C -I. -C -I@srcdir@ -o $@ $<
diff --git a/_darcs/pristine/Optimize/ASA.hsc b/_darcs/pristine/Optimize/ASA.hsc
new file mode 100644
--- /dev/null
+++ b/_darcs/pristine/Optimize/ASA.hsc
@@ -0,0 +1,80 @@
+{-# OPTIONS -ffi -fglasgow-exts #-}
+-- | interface to the Adaptive Simulated Annealing algorithm.
+
+module Optimize.ASA where 
+
+#include "asa_usr.h"
+
+import Optimize.Parameter
+import Foreign.C.Types
+import Foreign.Storable
+import Foreign.Ptr
+import Foreign.Marshal.Array
+import Foreign.Marshal.Alloc
+import Random
+import Data.Array.Unboxed
+import Int
+
+
+newtype UserOptions = UserOptions (Ptr UserOptions)
+type Doubles = UArray Int Double    
+
+data ExitCode =  NormalExit | PTempTooSmall | CTempTooSmall | CostRepeating | TooManyInvalidStates | ImmediateExit | InvalidUserInput | InvalidCostFunction | InvalidCostFunctionDeriv 
+    deriving(Eq,Ord,Enum,Show,Read)
+
+
+data Results x = Results {
+    optimalValue :: Double,
+    optimalParam :: x,
+    exitCode :: ExitCode
+    }
+
+
+type CostFunction =  Ptr Double -> Ptr Int -> IO Double
+
+foreign import ccall "wrapper" mkCostFunction :: CostFunction -> IO (FunPtr CostFunction)  
+foreign import ccall "asa_usr.h asa_main" asa_main :: FunPtr CostFunction -> CInt -> Ptr Double -> Ptr Double -> Ptr CInt -> Ptr Double -> Ptr Double -> Ptr CInt -> CInt -> IO CInt
+
+
+
+
+asa :: UserOptions     -- Options
+    -> (Doubles -> IO (Maybe Double)) -- cost function 
+    -> Int64           -- random number seed
+    -> Maybe Doubles   -- starting position
+    -> Doubles         -- upper bounds
+    -> Doubles         -- lower bounds
+    -> UArray Int Bool -- parameters are integral
+    -> IO (ExitCode,Doubles)      -- final answers
+asa = undefined
+
+toBasicCostFunction :: Parameter z x => z -> (x -> Double) -> CostFunction
+toBasicCostFunction z fn = f where
+    thePeek = peekParam z 
+    f pd pf = do
+        poke pf 1
+        x <- thePeek pd
+        let v = fn x
+        --putStrLn $ ">> Haskell Function Called: " ++ show v 
+        return $  v
+        
+
+minimize :: Parameter z x => z -> (x -> Double) -> IO x 
+minimize z (fn :: x -> Double ) = do
+    cf <- mkCostFunction (toBasicCostFunction z fn)
+    let n = numParams (undefined :: x) z 
+    let ps = paramInfo (undefined :: x) z []
+    withArray (map limitLow ps) $ \lower_bounds -> do  
+    withArray (map limitHigh ps) $ \upper_bounds -> do  
+    withArray (map (\x -> if isIntegral x then (#const INTEGER_TYPE) else (#const REAL_TYPE)) ps) $ \real_int -> do  
+    alloca $ \dummy_cost_val -> do 
+    allocaArray n $ \ret -> do
+    alloca $ \exit_code -> do 
+    r <- randomIO
+    asa_main cf (fromIntegral n) upper_bounds lower_bounds real_int dummy_cost_val ret exit_code (fromIntegral (r :: Int))
+    --code <- peek exit_code
+    --print (toEnum (fromIntegral code) :: ExitCode)
+    peekParam z ret 
+
+
+    
diff --git a/_darcs/pristine/Optimize/Parameter.hs b/_darcs/pristine/Optimize/Parameter.hs
new file mode 100644
--- /dev/null
+++ b/_darcs/pristine/Optimize/Parameter.hs
@@ -0,0 +1,202 @@
+{-# OPTIONS -fglasgow-exts #-}
+-- | Defines the mapping between haskell types and a set of optimization
+-- parameters used to represent said type.
+
+module Optimize.Parameter where 
+
+import Foreign.Storable
+import Foreign.Ptr
+import Foreign.C.Types
+import Char
+
+
+smallDouble :: Double
+smallDouble = 1.0e-12
+bigDouble = 1.0e6
+
+data ParamInfo = ParamInfo {
+    limitLow :: {-# UNBOX #-} !Double,
+    limitHigh :: {-# UNBOX #-} !Double,
+    isIntegral :: {-# UNBOX #-} !Bool
+}
+
+paramInfoFloat = ParamInfo {
+    limitLow = -bigDouble,
+    limitHigh = bigDouble,
+    isIntegral = False
+}
+
+paramInfoInt = paramInfoFloat { limitLow = realToFrac (minBound :: Int), limitHigh = realToFrac (maxBound :: Int), isIntegral = True }
+
+data Limit a = Limit { minLimit :: Maybe a, maxLimit :: Maybe a }
+
+limit x y = Limit { minLimit = Just x, maxLimit = Just y }
+limitMin x = Limit { minLimit = Just x, maxLimit = Nothing }
+limitMax x = Limit { minLimit = Nothing, maxLimit = Just x }
+limitPositive,limitNegative,limitUnit :: Num a => Limit a
+limitPositive = limitMin 0
+limitNegative = limitMax 0
+limitUnit = limit 0 1
+
+
+
+-- z is the meta-info for the given type. such as bounds.
+
+-- This really should be a superclass of Monoid
+class Empty a where
+    empty :: a
+
+instance Empty () where
+    empty = ()
+instance (Empty x, Empty y) => Empty (x,y) where
+    empty = (empty,empty)
+instance (Empty x, Empty y, Empty z) => Empty (x,y,z) where
+    empty = (empty,empty,empty)
+instance Empty (Maybe a) where
+    empty = Nothing
+instance Empty (Limit a) where
+    empty = Limit { minLimit = Nothing, maxLimit = Nothing }
+
+class Empty z => Parameter z x | x -> z where
+    pokeParam :: z -> x -> Ptr Double -> IO ()
+    peekParam :: z -> Ptr Double -> IO x    -- needs to be as fast as possible
+    -- x is only needed on these for its type. (can we do this in a better way?)
+    paramInfo :: x -> z -> [ParamInfo] -> [ParamInfo]
+    numParams :: x -> z ->  Int
+
+instance Parameter () () where
+    pokeParam _ _ _ = return ()
+    peekParam _ _ = return ()
+    numParams _ _ = 0
+    paramInfo _ _ x = x
+
+
+instance Parameter () Bool where
+    pokeParam _ False p = poke p 0
+    pokeParam _ True p = poke p 1
+    peekParam _ p = do
+        x <- peek p
+        return (not $ abs x < smallDouble)
+    paramInfo _ _ xs = ParamInfo { limitLow = 0, limitHigh = 1, isIntegral = True }:xs
+    numParams _ _ = 1
+
+instance (Parameter za a, Parameter zb b) => Parameter (za,zb) (a,b) where
+    pokeParam (za,zb) ((a::a),b) p = do
+        pokeParam za a p 
+        pokeParam zb b (p `advancePtr` numParams (undefined::a) za) 
+    peekParam (za,zb) p = do
+        (a::a) <- peekParam za p 
+        b <- peekParam zb (p `advancePtr` numParams (undefined::a) za)
+        return (a,b)
+    paramInfo (_ :: (a,b)) (za,zb) = paramInfo a za . paramInfo b zb where
+        a = undefined :: a
+        b = undefined :: b
+
+    numParams (_ :: (a,b)) (za,zb) = numParams a za + numParams b zb  where
+        a = undefined :: a
+        b = undefined :: b
+
+instance (Parameter za a, Parameter zb b, Parameter zc c) => Parameter (za,zb,zc) (a,b,c) where
+    pokeParam (za,zb,zc) (a,b,c) p = do
+        pokeParam (za,(zb,zc)) (a,(b,c)) p
+    peekParam (za,zb,zc) p = do
+        (a,(b,c)) <- peekParam (za,(zb,zc)) p 
+        return (a,b,c)
+    paramInfo (_ :: (a,b,c)) (za,zb,zc) = paramInfo a za . paramInfo b zb . paramInfo c zc where
+        a = undefined :: a
+        b = undefined :: b
+        c = undefined :: c
+
+    numParams (_ :: (a,b,c)) (za,zb,zc) = numParams a za + numParams b zb + numParams c zc  where
+        a = undefined :: a
+        b = undefined :: b
+        c = undefined :: c
+
+instance Parameter (Limit Double) Double where
+    pokeParam _ x p = poke p  x
+    peekParam _ p = peek p 
+    paramInfo _ Limit { minLimit = Nothing, maxLimit = Nothing } xs = paramInfoFloat :xs
+    paramInfo _ Limit { minLimit = Just x, maxLimit = Nothing } xs = paramInfoFloat { limitLow =  x }:xs
+    paramInfo _ Limit { minLimit = Just x, maxLimit = Just y } xs = paramInfoFloat { limitLow =  x, limitHigh =  y }:xs
+    paramInfo _ Limit { minLimit = Nothing, maxLimit = Just y } xs = paramInfoFloat { limitHigh =  y }:xs
+    numParams _ _ = 1
+    
+instance Parameter (Limit Int) Int where
+    pokeParam _ x p = poke p (realToFrac x)
+    peekParam _ p = peek p >>= return . round
+    paramInfo _ Limit { minLimit = Nothing, maxLimit = Nothing } xs = paramInfoInt :xs
+    paramInfo _ Limit { minLimit = Just x, maxLimit = Nothing } xs = paramInfoInt { limitLow = realToFrac x }:xs
+    paramInfo _ Limit { minLimit = Just x, maxLimit = Just y } xs = paramInfoInt { limitLow = realToFrac x, limitHigh = realToFrac y }:xs
+    paramInfo _ Limit { minLimit = Nothing, maxLimit = Just y } xs = paramInfoInt { limitHigh = realToFrac y }:xs
+    numParams _ _ = 1
+
+
+-- Of questionable utility.
+instance Parameter ()  Char where 
+    pokeParam _ x p = poke p (realToFrac $ ord x)
+    peekParam _ p = peek p >>= return . chr . round
+    paramInfo _ () xs = paramInfoInt { limitLow = 0x20, limitHigh = 0x7e }:xs
+    numParams _ _ = 1
+    
+
+
+instance Parameter (Limit Float) Float where
+    pokeParam _ x p = poke p (realToFrac x)
+    peekParam _ p = peek p >>= return . realToFrac
+    paramInfo _ Limit { minLimit = Nothing, maxLimit = Nothing } xs = paramInfoFloat :xs
+    paramInfo _ Limit { minLimit = Just x, maxLimit = Nothing } xs = paramInfoFloat { limitLow = realToFrac x }:xs
+    paramInfo _ Limit { minLimit = Just x, maxLimit = Just y } xs = paramInfoFloat { limitLow = realToFrac x, limitHigh = realToFrac y }:xs
+    paramInfo _ Limit { minLimit = Nothing, maxLimit = Just y } xs = paramInfoFloat { limitHigh = realToFrac y }:xs
+    numParams _ _ = 1
+
+instance Parameter zb b => Parameter zb (Maybe b) where
+    pokeParam zb (Nothing :: Maybe b) p = do
+        pokeParam ((),zb) (Left () :: Either () b) p
+    pokeParam zb (Just b :: Maybe b) p = do
+        pokeParam ((),zb) (Right b :: Either () b) p
+    peekParam zb p = do
+        v <- peekParam ((),zb) p
+        case v of
+            Right b -> return $ Just b
+            Left () -> return $ Nothing
+    paramInfo (_ :: Maybe b) z = paramInfo (undefined :: Either () b) ((),z)
+    numParams (_ :: Maybe b) z = numParams (undefined :: Either () b) ((),z)
+
+    
+    
+    
+
+instance (Parameter za a, Parameter zb b) => Parameter (za,zb) (Either a b) where
+    pokeParam (za,zb) (Left a :: Either a b) p = do
+        pokeParam empty False p
+        p <- return $  (p `advancePtr` 1)
+        pokeParam za a p
+    pokeParam (za,zb) (Right b :: Either a b) p = do
+        pokeParam empty False p
+        p <- return $  (p `advancePtr` (1 + numParams (undefined :: a) za))
+        pokeParam zb b p
+    peekParam (za,zb) p  = do
+        b <- peekParam () p
+        p <- return $  (p `advancePtr` 1)
+        case b of
+            False -> do
+                a <- peekParam za p 
+                return $ Left a
+            True -> do
+                let f :: Either a b -> a -> Either a b
+                    f x _ = x
+                un <- return undefined
+                p <- return $ (p `advancePtr` numParams un za)
+                a <- peekParam zb p 
+                return $ f (Right a) un
+    paramInfo (_ :: Either a b) (za,zb) = paramInfo (undefined :: Bool) empty . paramInfo a za . paramInfo b zb where
+        a = undefined :: a
+        b = undefined :: b
+    numParams (_ :: Either a b) (za,zb) = 1 + numParams a za + numParams b zb  where
+        a = undefined :: a
+        b = undefined :: b
+
+advancePtr (p :: Ptr a) n = p `plusPtr` (n * sizeOf (undefined :: a)) 
+
+--instance (Parameter a, Parameter b) => Parameter (Either a b) where
+--      pokeParam = pokeParam (Bool,a,b)
diff --git a/_darcs/pristine/README b/_darcs/pristine/README
new file mode 100644
--- /dev/null
+++ b/_darcs/pristine/README
@@ -0,0 +1,2 @@
+A haskell interface to Lester Ingber's adaptive simulating annealing code. 
+
diff --git a/_darcs/pristine/asa.c b/_darcs/pristine/asa.c
new file mode 100644
--- /dev/null
+++ b/_darcs/pristine/asa.c
@@ -0,0 +1,6387 @@
+/***********************************************************************
+* Adaptive Simulated Annealing (ASA)
+* Lester Ingber <ingber@ingber.com>
+* Copyright (c) 1993-2004 Lester Ingber.  All Rights Reserved.
+* The LICENSE file must be included with ASA code.
+***********************************************************************/
+
+#define ASA_ID \
+"/* $Id: asa.c,v 25.15 2004/09/23 18:10:46 ingber Exp ingber $ */"
+
+#include "asa.h"
+static int asa_recursive_max = 0;       /* record of max recursions */
+
+/***********************************************************************
+* asa
+*       This procedure implements the full ASA function optimization.
+***********************************************************************/
+#if HAVE_ANSI
+double
+asa (double (*user_cost_function)
+
+      
+     (double *, double *, double *, double *, double *, ALLOC_INT *, int *,
+      int *, int *, USER_DEFINES *),
+     double (*user_random_generator) (LONG_INT *), LONG_INT * seed,
+     double *parameter_initial_final, double *parameter_minimum,
+     double *parameter_maximum, double *tangents, double *curvature,
+     ALLOC_INT * number_parameters, int *parameter_type,
+     int *valid_state_generated_flag, int *exit_status,
+     USER_DEFINES * OPTIONS)
+#else
+double
+asa (user_cost_function,
+     user_random_generator,
+     seed,
+     parameter_initial_final,
+     parameter_minimum,
+     parameter_maximum,
+     tangents,
+     curvature,
+     number_parameters,
+     parameter_type, valid_state_generated_flag, exit_status, OPTIONS)
+     double (*user_cost_function) ();
+     double (*user_random_generator) ();
+     LONG_INT *seed;
+     double *parameter_initial_final;
+     double *parameter_minimum;
+     double *parameter_maximum;
+     double *tangents;
+     double *curvature;
+     ALLOC_INT *number_parameters;
+     int *parameter_type;
+     int *valid_state_generated_flag;
+     int *exit_status;
+     USER_DEFINES *OPTIONS;
+#endif /* HAVE_ANSI */
+{
+#if USER_INITIAL_COST_TEMP
+#if USER_REANNEAL_COST
+#else
+  int index_cost_constraint;    /* index cost functions averaged */
+#endif /* USER_REANNEAL_COST */
+#else /* USER_INITIAL_COST_TEMP */
+  int index_cost_constraint;    /* index cost functions averaged */
+#endif /* USER_INITIAL_COST_TEMP */
+
+  int index_cost_repeat,        /* test OPTIONS->Cost_Precision when =
+                                   OPTIONS->Maximum_Cost_Repeat */
+    tmp_var_int, tmp_var_int1, tmp_var_int2;    /* temporary integers */
+
+  ALLOC_INT index_v,            /* iteration index */
+   *start_sequence;             /* initial OPTIONS->Sequential_Parameters
+                                   used if >= 0 */
+  double final_cost,            /* best cost to return to user */
+    tmp_var_db, tmp_var_db1, tmp_var_db2;       /* temporary doubles */
+  int *curvature_flag;
+  FILE *ptr_asa_out;            /* file ptr to output file */
+
+  /* The 3 states that are kept track of during the annealing process */
+  STATE *current_generated_state, *last_saved_state, *best_generated_state;
+
+#if ASA_SAVE
+  FILE *ptr_save, *ptr_comm;
+  int asa_read;
+  char asa_save_comm[100];
+#if ASA_SAVE_OPT
+  char read_option[80];
+  char read_if[4], read_FALSE[6], read_comm1[3], read_ASA_SAVE[9],
+    read_comm2[3];
+  int read_int;
+#if INT_LONG
+  LONG_INT read_long;
+#endif
+  double read_double;
+  FILE *ptr_save_opt;
+#endif
+#endif /* ASA_SAVE */
+
+#if ASA_PIPE_FILE
+  FILE *ptr_asa_pipe;
+#endif
+
+  int immediate_flag;           /* save Immediate_Exit */
+  int asa_exit_value;
+
+  double xnumber_parameters[1];
+
+  /* The array of tangents (absolute value of the numerical derivatives),
+     and the maximum |tangent| of the array */
+  double *maximum_tangent;
+
+  /* ratio of acceptances to generated points - determines when to
+     test/reanneal */
+  double *accepted_to_generated_ratio;
+
+  /* temperature parameters */
+  double temperature_scale, *temperature_scale_parameters;
+  /* relative scalings of cost and parameters to temperature_scale */
+  double *temperature_scale_cost;
+  double *current_user_parameter_temp;
+  double *initial_user_parameter_temp;
+  double *current_cost_temperature;
+  double *initial_cost_temperature;
+  double log_new_temperature_ratio;     /* current *temp = initial *temp *
+                                           exp(log_new_temperature_ratio) */
+  ALLOC_INT *index_exit_v;      /* information for asa_exit */
+
+  /* counts of generated states and acceptances */
+  LONG_INT *index_parameter_generations;
+  LONG_INT *number_generated, *best_number_generated_saved;
+  LONG_INT *recent_number_generated, *number_accepted;
+  LONG_INT *recent_number_acceptances, *index_cost_acceptances;
+  LONG_INT *number_acceptances_saved, *best_number_accepted_saved;
+
+  /* Flag indicates that the parameters generated were
+     invalid according to the cost function validity criteria. */
+  LONG_INT *number_invalid_generated_states;
+  LONG_INT repeated_invalid_states;
+
+#if ASA_QUEUE
+  int queue_new;                /* flag to add new entry */
+  int *save_queue_flag;         /* save valid_state_generated_flag */
+  LONG_INT queue;               /* index of queue */
+  LONG_INT queue_v;             /* index of parameters in queue */
+  LONG_INT save_queue_test;     /* test if all parameters are present */
+  LONG_INT save_queue;          /* last filled position in queue */
+  LONG_INT save_queue_indx;     /* current position in queue */
+  double *save_queue_cost, *save_queue_param;   /* saved states */
+  ALLOC_INT queue_size_tmp;
+#endif
+
+#if MULTI_MIN
+  int multi_index;
+  int multi_test, multi_test_cmp, multi_test_dim;
+  int *multi_sort;
+  double *multi_cost;
+  double **multi_params;
+#endif /* MULTI_MIN */
+
+#if ASA_PARALLEL
+  LONG_INT *parallel_sort;
+  LONG_INT index_parallel, sort_index;  /* count of parallel generated states */
+  LONG_INT parallel_generated;  /* saved *recent_number_generated */
+  LONG_INT parallel_block_max;  /* saved OPTIONS->Gener_Block_Max */
+  STATE *gener_block_state;
+#endif
+
+  /* used to index repeated and recursive calls to asa */
+  /* This assumes that multiple calls (>= 1) _or_ recursive
+     calls are being made to asa */
+  static int asa_open = FALSE;
+  static int number_asa_open = 0;
+  static int recursive_asa_open = 0;
+
+  /* initializations */
+
+  if ((curvature_flag = (int *) calloc (1, sizeof (int))) == NULL) {
+    strcpy (exit_msg, "asa(): curvature_flag");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((maximum_tangent = (double *) calloc (1, sizeof (double))) == NULL) {
+    strcpy (exit_msg, "asa(): maximum_tangent");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((accepted_to_generated_ratio =
+       (double *) calloc (1, sizeof (double))) == NULL) {
+    strcpy (exit_msg, "asa(): accepted_to_generated_ratio");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((temperature_scale_cost =
+       (double *) calloc (1, sizeof (double))) == NULL) {
+    strcpy (exit_msg, "asa(): temperature_scale_cost");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((current_cost_temperature =
+       (double *) calloc (1, sizeof (double))) == NULL) {
+    strcpy (exit_msg, "asa(): current_cost_temperature");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((initial_cost_temperature =
+       (double *) calloc (1, sizeof (double))) == NULL) {
+    strcpy (exit_msg, "asa(): initial_cost_temperature");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((index_exit_v = (ALLOC_INT *) calloc (1, sizeof (ALLOC_INT))) == NULL) {
+    strcpy (exit_msg, "asa(): index_exit_v");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((start_sequence = (ALLOC_INT *) calloc (1, sizeof (ALLOC_INT))) == NULL) {
+    strcpy (exit_msg, "asa(): start_sequence");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((number_generated =
+       (ALLOC_INT *) calloc (1, sizeof (ALLOC_INT))) == NULL) {
+    strcpy (exit_msg, "asa(): number_generated");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((best_number_generated_saved =
+       (ALLOC_INT *) calloc (1, sizeof (ALLOC_INT))) == NULL) {
+    strcpy (exit_msg, "asa(): best_number_generated_saved");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((recent_number_generated =
+       (ALLOC_INT *) calloc (1, sizeof (ALLOC_INT))) == NULL) {
+    strcpy (exit_msg, "asa(): recent_number_generated");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((number_accepted =
+       (ALLOC_INT *) calloc (1, sizeof (ALLOC_INT))) == NULL) {
+    strcpy (exit_msg, "asa(): number_accepted");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((recent_number_acceptances =
+       (ALLOC_INT *) calloc (1, sizeof (ALLOC_INT))) == NULL) {
+    strcpy (exit_msg, "asa(): recent_number_acceptances");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((index_cost_acceptances =
+       (ALLOC_INT *) calloc (1, sizeof (ALLOC_INT))) == NULL) {
+    strcpy (exit_msg, "asa(): index_cost_acceptances");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((number_acceptances_saved =
+       (ALLOC_INT *) calloc (1, sizeof (ALLOC_INT))) == NULL) {
+    strcpy (exit_msg, "asa(): number_acceptances_saved");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((best_number_accepted_saved =
+       (ALLOC_INT *) calloc (1, sizeof (ALLOC_INT))) == NULL) {
+    strcpy (exit_msg, "asa(): best_number_accepted_saved");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((number_invalid_generated_states =
+       (ALLOC_INT *) calloc (1, sizeof (ALLOC_INT))) == NULL) {
+    strcpy (exit_msg, "asa(): number_invalid_generated_states");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+
+  if ((current_generated_state =
+       (STATE *) calloc (1, sizeof (STATE))) == NULL) {
+    strcpy (exit_msg, "asa(): current_generated_state");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((last_saved_state = (STATE *) calloc (1, sizeof (STATE))) == NULL) {
+    strcpy (exit_msg, "asa(): last_saved_state");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((best_generated_state = (STATE *) calloc (1, sizeof (STATE))) == NULL) {
+    strcpy (exit_msg, "asa(): best_generated_state");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+#if ASA_PARALLEL
+  if ((gener_block_state =
+       (STATE *) calloc (OPTIONS->Gener_Block_Max, sizeof (STATE))) == NULL) {
+    strcpy (exit_msg, "asa(): gener_block_state");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  gener_block_state_qsort = gener_block_state;
+  if ((parallel_sort =
+       (LONG_INT *) calloc (OPTIONS->Gener_Block_Max,
+                            sizeof (LONG_INT))) == NULL) {
+    strcpy (exit_msg, "asa(): parallel_sort");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+#endif
+
+  /* set default */
+  ptr_asa_out = (FILE *) NULL;
+
+  OPTIONS->Immediate_Exit = FALSE;
+
+  if (asa_open == FALSE) {
+    asa_open = TRUE;
+    ++number_asa_open;
+#if ASA_PRINT
+    if (number_asa_open == 1) {
+      /* open the output file */
+#if USER_ASA_OUT
+      if (!strcmp (OPTIONS->Asa_Out_File, "STDOUT")) {
+#if INCL_STDOUT
+        ptr_asa_out = stdout;
+#endif /* INCL_STDOUT */
+      } else {
+#if ASA_SAVE
+        ptr_asa_out = fopen (OPTIONS->Asa_Out_File, "a");
+#else
+        ptr_asa_out = fopen (OPTIONS->Asa_Out_File, "w");
+#endif
+      }
+#else /* USER_ASA_OUT */
+      if (!strcmp (ASA_OUT, "STDOUT")) {
+#if INCL_STDOUT
+        ptr_asa_out = stdout;
+#endif /* INCL_STDOUT */
+      } else {
+#if ASA_SAVE
+        ptr_asa_out = fopen (ASA_OUT, "a");
+#else
+        ptr_asa_out = fopen (ASA_OUT, "w");
+#endif
+      }
+#endif /* USER_ASA_OUT */
+    } else {
+#if USER_ASA_OUT
+      if (!strcmp (OPTIONS->Asa_Out_File, "STDOUT")) {
+#if INCL_STDOUT
+        ptr_asa_out = stdout;
+#endif /* INCL_STDOUT */
+      } else {
+        ptr_asa_out = fopen (OPTIONS->Asa_Out_File, "a");
+      }
+#else
+      if (!strcmp (ASA_OUT, "STDOUT")) {
+#if INCL_STDOUT
+        ptr_asa_out = stdout;
+#endif /* INCL_STDOUT */
+      } else {
+        ptr_asa_out = fopen (ASA_OUT, "a");
+      }
+#endif
+      fprintf (ptr_asa_out, "\n\n\t\t number_asa_open = %d\n",
+               number_asa_open);
+    }
+#endif /* ASA_PRINT */
+  } else {
+    ++recursive_asa_open;
+#if ASA_PRINT
+    if (recursive_asa_open == 1) {
+      /* open the output file */
+#if ASA_SAVE
+#if USER_ASA_OUT
+      if (!strcmp (OPTIONS->Asa_Out_File, "STDOUT")) {
+#if INCL_STDOUT
+        ptr_asa_out = stdout;
+#endif /* INCL_STDOUT */
+      } else {
+        ptr_asa_out = fopen (OPTIONS->Asa_Out_File, "a");
+      }
+#else
+      if (!strcmp (ASA_OUT, "STDOUT")) {
+#if INCL_STDOUT
+        ptr_asa_out = stdout;
+#endif /* INCL_STDOUT */
+      } else {
+        ptr_asa_out = fopen (ASA_OUT, "a");
+      }
+#endif
+#else /* ASA_SAVE */
+#if USER_ASA_OUT
+      if (!strcmp (OPTIONS->Asa_Out_File, "STDOUT")) {
+#if INCL_STDOUT
+        ptr_asa_out = stdout;
+#endif /* INCL_STDOUT */
+      } else {
+        ptr_asa_out = fopen (OPTIONS->Asa_Out_File, "w");
+      }
+#else
+      if (!strcmp (ASA_OUT, "STDOUT")) {
+#if INCL_STDOUT
+        ptr_asa_out = stdout;
+#endif /* INCL_STDOUT */
+      } else {
+        ptr_asa_out = fopen (ASA_OUT, "w");
+      }
+#endif
+#endif /* ASA_SAVE */
+    } else {
+#if USER_ASA_OUT
+      if (!strcmp (OPTIONS->Asa_Out_File, "STDOUT")) {
+#if INCL_STDOUT
+        ptr_asa_out = stdout;
+#endif /* INCL_STDOUT */
+      } else {
+        ptr_asa_out = fopen (OPTIONS->Asa_Out_File, "a");
+      }
+#else
+      if (!strcmp (ASA_OUT, "STDOUT")) {
+#if INCL_STDOUT
+        ptr_asa_out = stdout;
+#endif /* INCL_STDOUT */
+      } else {
+        ptr_asa_out = fopen (ASA_OUT, "a");
+      }
+#endif
+      fprintf (ptr_asa_out, "\n\n\t\t recursive_asa_open = %d\n",
+               recursive_asa_open);
+    }
+#endif /* ASA_PRINT */
+  }
+
+#if ASA_PIPE_FILE
+  ptr_asa_pipe = fopen ("asa_pipe", "a");
+  fprintf (ptr_asa_pipe, "%s", "%generate");
+  fprintf (ptr_asa_pipe, "\t%s", "accept");
+  fprintf (ptr_asa_pipe, "\t%s", "best_cost");
+  VFOR (index_v)
+#if INT_ALLOC
+    fprintf (ptr_asa_pipe, "\t%s-%d", "param", index_v);
+#else
+#if INT_LONG
+    fprintf (ptr_asa_pipe, "\t%s-%ld", "param", index_v);
+#else
+    fprintf (ptr_asa_pipe, "\t%s-%d", "param", index_v);
+#endif
+#endif
+  fprintf (ptr_asa_pipe, "\t%s", "cost_temp");
+  VFOR (index_v)
+#if INT_ALLOC
+    fprintf (ptr_asa_pipe, "\t%s-%d", "param_temp", index_v);
+#else
+#if INT_LONG
+    fprintf (ptr_asa_pipe, "\t%s-%ld", "param_temp", index_v);
+#else
+    fprintf (ptr_asa_pipe, "\t%s-%d", "param_temp", index_v);
+#endif
+#endif
+  fprintf (ptr_asa_pipe, "\t%s", "last_cost");
+  fprintf (ptr_asa_pipe, "\n");
+  fflush (ptr_asa_pipe);
+#endif /* ASA_PIPE_FILE */
+
+#if ASA_PRINT
+  /* print header information as defined by user */
+  print_asa_options (ptr_asa_out, OPTIONS);
+
+  fflush (ptr_asa_out);
+#endif /* ASA_PRINT */
+
+  /* set indices and counts to 0 */
+  *best_number_generated_saved =
+    *number_generated =
+    *recent_number_generated = *recent_number_acceptances = 0;
+  *index_cost_acceptances =
+    *best_number_accepted_saved =
+    *number_accepted = *number_acceptances_saved = 0;
+  index_cost_repeat = 0;
+
+  OPTIONS->N_Accepted = *number_accepted;
+  OPTIONS->N_Generated = *number_generated;
+
+#if ASA_SAMPLE
+  OPTIONS->N_Generated = 0;
+  OPTIONS->Average_Weights = 1.0;
+#endif
+
+  /* do not calculate curvatures initially */
+  *curvature_flag = FALSE;
+
+  /* allocate storage for all parameters */
+  if ((current_generated_state->parameter =
+       (double *) calloc (*number_parameters, sizeof (double))) == NULL) {
+    strcpy (exit_msg, "asa(): current_generated_state->parameter");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((last_saved_state->parameter =
+       (double *) calloc (*number_parameters, sizeof (double))) == NULL) {
+    strcpy (exit_msg, "asa(): last_saved_state->parameter");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((best_generated_state->parameter =
+       (double *) calloc (*number_parameters, sizeof (double))) == NULL) {
+    strcpy (exit_msg, "asa(): best_generated_state->parameter");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+#if ASA_PARALLEL
+  parallel_block_max = OPTIONS->Gener_Block_Max;
+  parallel_generated = OPTIONS->Gener_Block;
+
+  for (index_parallel = 0; index_parallel < parallel_block_max;
+       ++index_parallel) {
+    if ((gener_block_state[index_parallel].parameter =
+         (double *) calloc (*number_parameters, sizeof (double))) == NULL) {
+      strcpy (exit_msg, "asa(): gener_block_state[index_parallel].parameter");
+      Exit_ASA (exit_msg);
+      *exit_status = CALLOC_FAILED;
+      return (-1);
+    }
+  }
+#endif
+
+  OPTIONS->Best_Cost = &(best_generated_state->cost);
+  OPTIONS->Best_Parameters = best_generated_state->parameter;
+  OPTIONS->Last_Cost = &(last_saved_state->cost);
+  OPTIONS->Last_Parameters = last_saved_state->parameter;
+
+  if ((initial_user_parameter_temp =
+       (double *) calloc (*number_parameters, sizeof (double))) == NULL) {
+    strcpy (exit_msg, "asa(): initial_user_parameter_temp");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((index_parameter_generations =
+       (ALLOC_INT *) calloc (*number_parameters,
+                             sizeof (ALLOC_INT))) == NULL) {
+    strcpy (exit_msg, "asa(): index_parameter_generations");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+
+  /* set all temperatures */
+  if ((current_user_parameter_temp =
+       (double *) calloc (*number_parameters, sizeof (double))) == NULL) {
+    strcpy (exit_msg, "asa(): current_user_parameter_temp");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+#if USER_INITIAL_PARAMETERS_TEMPS
+  VFOR (index_v)
+    current_user_parameter_temp[index_v] =
+    initial_user_parameter_temp[index_v] =
+    OPTIONS->User_Parameter_Temperature[index_v];
+#else
+  VFOR (index_v)
+    current_user_parameter_temp[index_v] =
+    initial_user_parameter_temp[index_v] =
+    OPTIONS->Initial_Parameter_Temperature;
+#endif
+
+  if ((temperature_scale_parameters =
+       (double *) calloc (*number_parameters, sizeof (double))) == NULL) {
+    strcpy (exit_msg, "asa(): temperature_scale_parameters");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+#if ASA_QUEUE
+  if (OPTIONS->Queue_Size > 0) {
+    queue_size_tmp = OPTIONS->Queue_Size;
+  } else {
+    queue_size_tmp = 1;
+  }
+  if ((save_queue_flag =
+       (int *) calloc (queue_size_tmp, sizeof (int))) == NULL) {
+    strcpy (exit_msg, "asa(): save_queue_flag");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((save_queue_cost =
+       (double *) calloc (queue_size_tmp, sizeof (double))) == NULL) {
+    strcpy (exit_msg, "asa(): save_queue_cost");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((save_queue_param =
+       (double *) calloc ((*number_parameters) * queue_size_tmp,
+                          sizeof (double))) == NULL) {
+    strcpy (exit_msg, "asa(): save_queue_param");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+#endif /* ASA_QUEUE */
+
+#if MULTI_MIN
+  if ((multi_cost =
+       (double *) calloc (OPTIONS->Multi_Number + 1,
+                          sizeof (double))) == NULL) {
+    strcpy (exit_msg, "asa(): *multi_cost");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  multi_cost_qsort = multi_cost;
+  if ((multi_sort =
+       (int *) calloc (OPTIONS->Multi_Number + 1, sizeof (int))) == NULL) {
+    strcpy (exit_msg, "asa(): *multi_sort");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((multi_params =
+       (double **) calloc (OPTIONS->Multi_Number + 1,
+                           sizeof (double *))) == NULL) {
+    strcpy (exit_msg, "asa(): *multi_params");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  for (multi_index = 0; multi_index <= OPTIONS->Multi_Number; ++multi_index) {
+    if ((multi_params[multi_index] =
+         (double *) calloc (*number_parameters, sizeof (double))) == NULL) {
+      strcpy (exit_msg, "asa(): multi_params[multi_index]");
+      Exit_ASA (exit_msg);
+      *exit_status = CALLOC_FAILED;
+      return (-1);
+    }
+  }
+#endif /* MULTI_MIN */
+
+#if USER_INITIAL_COST_TEMP
+#if USER_ACCEPTANCE_TEST
+  OPTIONS->Cost_Temp_Curr = OPTIONS->Cost_Temp_Init =
+#endif
+    *initial_cost_temperature = *current_cost_temperature =
+    OPTIONS->User_Cost_Temperature[0];
+#endif
+
+  /* set parameters to the initial parameter values */
+  VFOR (index_v)
+    last_saved_state->parameter[index_v] =
+    current_generated_state->parameter[index_v] =
+    parameter_initial_final[index_v];
+#if USER_ACCEPTANCE_TEST
+  OPTIONS->Random_Seed = seed;
+  OPTIONS->Random_Seed[0] = *seed;
+  OPTIONS->User_Acceptance_Flag = TRUE;
+  OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+
+#if ASA_PRINT
+#if INT_LONG
+  fprintf (ptr_asa_out, "Initial Random Seed = %ld\n\n", *seed);
+#else
+  fprintf (ptr_asa_out, "Initial Random Seed = %d\n\n", *seed);
+#endif
+#endif /* ASA_PRINT */
+
+  /* save initial user value of OPTIONS->Sequential_Parameters */
+  *start_sequence = OPTIONS->Sequential_Parameters;
+
+#if ASA_PRINT
+  fprintf (ptr_asa_out,
+#if INT_ALLOC
+           "*number_parameters = %d\n\n", *number_parameters);
+#else
+#if INT_LONG
+           "*number_parameters = %ld\n\n", *number_parameters);
+#else
+           "*number_parameters = %d\n\n", *number_parameters);
+#endif
+#endif
+
+  /* print the min, max, current values, and types of parameters */
+  fprintf (ptr_asa_out, "index_v parameter_minimum parameter_maximum\
+ parameter_value parameter_type \n");
+
+#if ASA_PRINT_INTERMED
+  VFOR (index_v) fprintf (ptr_asa_out,
+#if INT_ALLOC
+                          " %-8d %-*.*g \t\t %-*.*g \t %-*.*g %-7d\n",
+#else
+#if INT_LONG
+                          " %-8ld %-*.*g \t\t %-*.*g \t %-*.*g %-7d\n",
+#else
+                          " %-8d %-*.*g \t\t %-*.*g \t %-*.*g %-7d\n",
+#endif
+#endif
+                          index_v,
+                          G_FIELD, G_PRECISION, parameter_minimum[index_v],
+                          G_FIELD, G_PRECISION, parameter_maximum[index_v],
+                          G_FIELD, G_PRECISION,
+                          current_generated_state->parameter[index_v],
+                          parameter_type[index_v]);
+
+  fprintf (ptr_asa_out, "\n\n");
+#endif /* ASA_PRINT_INTERMED */
+  /* Print out user-defined OPTIONS */
+
+#if DELTA_PARAMETERS
+  VFOR (index_v) fprintf (ptr_asa_out,
+#if INT_ALLOC
+                          "OPTIONS->User_Delta_Parameter[%d] = %*.*g\n",
+#else
+#if INT_LONG
+                          "OPTIONS->User_Delta_Parameter[%ld] = %*.*g\n",
+#else
+                          "OPTIONS->User_Delta_Parameter[%d] = %*.*g\n",
+#endif
+#endif
+                          index_v,
+                          G_FIELD, G_PRECISION,
+                          OPTIONS->User_Delta_Parameter[index_v]);
+  fprintf (ptr_asa_out, "\n");
+#endif /* DELTA_PARAMETERS */
+
+#if QUENCH_PARAMETERS
+  VFOR (index_v) fprintf (ptr_asa_out,
+#if INT_ALLOC
+                          "OPTIONS->User_Quench_Param_Scale[%d] = %*.*g\n",
+#else
+#if INT_LONG
+                          "OPTIONS->User_Quench_Param_Scale[%ld] = %*.*g\n",
+#else
+                          "OPTIONS->User_Quench_Param_Scale[%d] = %*.*g\n",
+#endif
+#endif
+                          index_v,
+                          G_FIELD, G_PRECISION,
+                          OPTIONS->User_Quench_Param_Scale[index_v]);
+#endif /* QUENCH_PARAMETERS */
+
+#if QUENCH_COST
+  fprintf (ptr_asa_out,
+           "\nOPTIONS->User_Quench_Cost_Scale = %*.*g\n\n",
+           G_FIELD, G_PRECISION, OPTIONS->User_Quench_Cost_Scale[0]);
+#endif /* QUENCH_COST */
+
+#if USER_INITIAL_PARAMETERS_TEMPS
+  VFOR (index_v) fprintf (ptr_asa_out,
+#if INT_ALLOC
+                          "OPTIONS->User_Parameter_Temperature[%d] = %*.*g\n",
+#else
+#if INT_LONG
+                          "OPTIONS->User_Parameter_Temperature[%ld] = %*.*g\n",
+#else
+                          "OPTIONS->User_Parameter_Temperature[%d] = %*.*g\n",
+#endif
+#endif
+                          index_v,
+                          G_FIELD, G_PRECISION,
+                          initial_user_parameter_temp[index_v]);
+#endif /* USER_INITIAL_PARAMETERS_TEMPS */
+
+#if RATIO_TEMPERATURE_SCALES
+  VFOR (index_v) fprintf (ptr_asa_out,
+#if INT_ALLOC
+                          "OPTIONS->User_Temperature_Ratio[%d] = %*.*g\n",
+#else
+#if INT_LONG
+                          "OPTIONS->User_Temperature_Ratio[%ld] = %*.*g\n",
+#else
+                          "OPTIONS->User_Temperature_Ratio[%d] = %*.*g\n",
+#endif
+#endif
+                          index_v,
+                          G_FIELD, G_PRECISION,
+                          OPTIONS->User_Temperature_Ratio[index_v]);
+#endif /* RATIO_TEMPERATURE_SCALES */
+
+#if USER_INITIAL_COST_TEMP
+  fprintf (ptr_asa_out,
+           "OPTIONS->User_Cost_Temperature[0] = %*.*g\n",
+           G_FIELD, G_PRECISION, *initial_cost_temperature);
+#endif /* USER_INITIAL_COST_TEMP */
+
+  fflush (ptr_asa_out);
+#endif /* ASA_PRINT */
+
+#if MULTI_MIN
+#if ASA_PRINT
+  fprintf (ptr_asa_out, "\n");
+  fprintf (ptr_asa_out, "Multi_Number = %d\n", OPTIONS->Multi_Number);
+  fprintf (ptr_asa_out, "Multi_Specify = %d\n", OPTIONS->Multi_Specify);
+#if ASA_RESOLUTION
+#else
+  VFOR (index_v) {
+    fprintf (ptr_asa_out,
+#if INT_ALLOC
+             "Multi_Grid[%d] = %*.*g\n",
+#else
+#if INT_LONG
+             "Multi_Grid[%ld] = %*.*g\n",
+#else
+             "Multi_Grid[%d] = %*.*g\n",
+#endif
+#endif
+             index_v, G_FIELD, G_PRECISION, OPTIONS->Multi_Grid[index_v]);
+  }
+#endif /* ASA_RESOLUTION */
+  fprintf (ptr_asa_out, "\n");
+  fflush (ptr_asa_out);
+#endif /* ASA_PRINT */
+#endif /* MULTI_MIN */
+
+#if ASA_PARALLEL
+#if ASA_PRINT
+  fprintf (ptr_asa_out,
+#if INT_LONG
+           "Initial ASA_PARALLEL OPTIONS->\n\t Gener_Block = %ld\n\
+ \t Gener_Block_Max = %ld\n \t Gener_Mov_Avr= %d\n\n",
+#else
+           "ASA_PARALLEL OPTIONS->\n\t Gener_Block = %d\n\
+ \t Gener_Block_Max = %d\n \t Gener_Mov_Avr= %d\n\n",
+#endif
+           OPTIONS->Gener_Block, OPTIONS->Gener_Block_Max,
+           OPTIONS->Gener_Mov_Avr);
+#endif
+#endif /* ASA_PARALLEL */
+
+#if ASA_SAMPLE
+#if ASA_PRINT
+  fprintf (ptr_asa_out, "OPTIONS->Limit_Weights = %*.*g\n\n",
+           G_FIELD, G_PRECISION, OPTIONS->Limit_Weights);
+#endif
+#endif
+  if (OPTIONS->Asa_Recursive_Level > asa_recursive_max)
+    asa_recursive_max = OPTIONS->Asa_Recursive_Level;
+#if ASA_SAVE
+  if (OPTIONS->Asa_Recursive_Level > 0)
+    sprintf (asa_save_comm, "asa_save_%d", OPTIONS->Asa_Recursive_Level);
+  else
+    sprintf (asa_save_comm, "asa_save");
+  if ((ptr_save = fopen (asa_save_comm, "r")) == NULL) {
+    asa_read = FALSE;
+  } else {
+#if ASA_PRINT
+    fprintf (ptr_asa_out, "\n\n\trestart after ASA_SAVE\n\n");
+#endif
+    fclose (ptr_save);
+    asa_read = TRUE;
+
+    /* give some value to avoid any problems with other OPTIONS */
+#if USER_ACCEPTANCE_TEST
+    OPTIONS->Cost_Temp_Curr = OPTIONS->Cost_Temp_Init =
+#endif
+      current_generated_state->cost
+      = *initial_cost_temperature = *current_cost_temperature = 3.1416;
+  }
+#endif
+
+  tmp_var_int = cost_function_test (current_generated_state->cost,
+                                    current_generated_state->parameter,
+                                    parameter_minimum,
+                                    parameter_maximum, number_parameters,
+                                    xnumber_parameters);
+
+  /* compute temperature scales */
+  tmp_var_db1 = -F_LOG ((OPTIONS->Temperature_Ratio_Scale));
+  tmp_var_db2 = F_LOG (OPTIONS->Temperature_Anneal_Scale);
+  temperature_scale =
+    tmp_var_db1 * F_EXP (-tmp_var_db2 / *xnumber_parameters);
+
+  /* set here in case not used */
+  tmp_var_db = ZERO;
+
+#if QUENCH_PARAMETERS
+#if RATIO_TEMPERATURE_SCALES
+  VFOR (index_v) temperature_scale_parameters[index_v] = tmp_var_db1 * F_EXP
+#if QUENCH_PARAMETERS_SCALE
+    (-(tmp_var_db2 * OPTIONS->User_Quench_Param_Scale[index_v])
+#else
+    (-(tmp_var_db2)
+#endif
+     / *xnumber_parameters)
+    * OPTIONS->User_Temperature_Ratio[index_v];
+#else
+  VFOR (index_v) temperature_scale_parameters[index_v] = tmp_var_db1 * F_EXP
+#if QUENCH_PARAMETERS_SCALE
+    (-(tmp_var_db2 * OPTIONS->User_Quench_Param_Scale[index_v])
+#else
+    (-(tmp_var_db2)
+#endif
+     / *xnumber_parameters);
+#endif /* RATIO_TEMPERATURE_SCALES */
+#else /* QUENCH_PARAMETERS */
+#if RATIO_TEMPERATURE_SCALES
+  VFOR (index_v)
+    temperature_scale_parameters[index_v] =
+    tmp_var_db1 * F_EXP (-(tmp_var_db2) / *xnumber_parameters)
+    * OPTIONS->User_Temperature_Ratio[index_v];
+#else
+  VFOR (index_v)
+    temperature_scale_parameters[index_v] =
+    tmp_var_db1 * F_EXP (-(tmp_var_db2) / *xnumber_parameters);
+#endif /* RATIO_TEMPERATURE_SCALES */
+#endif /* QUENCH_PARAMETERS */
+
+#if USER_ACCEPTANCE_TEST
+  OPTIONS->Cost_Temp_Scale =
+#endif
+    *temperature_scale_cost =
+#if QUENCH_COST
+#if QUENCH_COST_SCALE
+    tmp_var_db1 * F_EXP (-(tmp_var_db2 * OPTIONS->User_Quench_Cost_Scale[0])
+#else
+    tmp_var_db1 * F_EXP (-(tmp_var_db2)
+#endif
+                         / *xnumber_parameters) *
+    OPTIONS->Cost_Parameter_Scale_Ratio;
+#else /* QUENCH_COST */
+    tmp_var_db1 * F_EXP (-(tmp_var_db2)
+                         / *xnumber_parameters) *
+    OPTIONS->Cost_Parameter_Scale_Ratio;
+#endif /* QUENCH_COST */
+
+  /* set the initial index of parameter generations to 1 */
+  VFOR (index_v) index_parameter_generations[index_v] = 1;
+
+  /* test user-defined options before calling cost function */
+  tmp_var_int = asa_test_asa_options (seed,
+                                      parameter_initial_final,
+                                      parameter_minimum,
+                                      parameter_maximum,
+                                      tangents,
+                                      curvature,
+                                      number_parameters,
+                                      parameter_type,
+                                      valid_state_generated_flag,
+                                      exit_status, ptr_asa_out, OPTIONS);
+  if (tmp_var_int > 0) {
+#if ASA_PRINT
+    fprintf (ptr_asa_out, "total number invalid OPTIONS = %d\n", tmp_var_int);
+    fflush (ptr_asa_out);
+#endif
+    *exit_status = INVALID_USER_INPUT;
+    goto EXIT_ASA;
+  }
+#if USER_INITIAL_COST_TEMP
+#else
+#if ASA_SAVE
+  if (asa_read == TRUE)
+    OPTIONS->Number_Cost_Samples = 1;
+#endif
+  /* calculate the average cost over samplings of the cost function */
+  if (OPTIONS->Number_Cost_Samples < -1) {
+    tmp_var_db1 = ZERO;
+    tmp_var_db2 = ZERO;
+    tmp_var_int = -OPTIONS->Number_Cost_Samples;
+  } else {
+    tmp_var_db1 = ZERO;
+    tmp_var_int = OPTIONS->Number_Cost_Samples;
+  }
+
+  OPTIONS->Locate_Cost = 0;     /* initial cost temp */
+
+  for (index_cost_constraint = 0;
+       index_cost_constraint < tmp_var_int; ++index_cost_constraint) {
+    *number_invalid_generated_states = 0;
+    repeated_invalid_states = 0;
+    OPTIONS->Sequential_Parameters = *start_sequence - 1;
+    do {
+      ++(*number_invalid_generated_states);
+      generate_new_state (user_random_generator,
+                          seed,
+                          parameter_minimum,
+                          parameter_maximum, current_user_parameter_temp,
+#if USER_GENERATING_FUNCTION
+                          initial_user_parameter_temp,
+                          temperature_scale_parameters,
+#endif
+                          number_parameters,
+                          parameter_type,
+                          current_generated_state, last_saved_state, OPTIONS);
+      *valid_state_generated_flag = TRUE;
+#if USER_ACCEPTANCE_TEST
+      OPTIONS->User_Acceptance_Flag = TRUE;
+      OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+      tmp_var_db =
+        user_cost_function (current_generated_state->parameter,
+                            parameter_minimum,
+                            parameter_maximum,
+                            tangents,
+                            curvature,
+                            number_parameters,
+                            parameter_type,
+                            valid_state_generated_flag, exit_status, OPTIONS);
+      if (cost_function_test
+          (tmp_var_db, current_generated_state->parameter,
+           parameter_minimum, parameter_maximum, number_parameters,
+           xnumber_parameters) == 0) {
+        *exit_status = INVALID_COST_FUNCTION;
+        goto EXIT_ASA;
+      }
+
+      ++repeated_invalid_states;
+      if (repeated_invalid_states > OPTIONS->Limit_Invalid_Generated_States) {
+        *exit_status = TOO_MANY_INVALID_STATES;
+        goto EXIT_ASA;
+      }
+    }
+    while (*valid_state_generated_flag == FALSE);
+    --(*number_invalid_generated_states);
+
+    if (OPTIONS->Number_Cost_Samples < -1) {
+      tmp_var_db1 += tmp_var_db;
+      tmp_var_db2 += (tmp_var_db * tmp_var_db);
+    } else {
+      tmp_var_db1 += fabs (tmp_var_db);
+    }
+  }
+  if (OPTIONS->Number_Cost_Samples < -1) {
+    tmp_var_db1 /= (double) tmp_var_int;
+    tmp_var_db2 /= (double) tmp_var_int;
+    tmp_var_db = sqrt (fabs ((tmp_var_db2 - tmp_var_db1 * tmp_var_db1)
+                             * ((double) tmp_var_int
+                                / ((double) tmp_var_int - ONE))))
+      + (double) EPS_DOUBLE;
+  } else {
+    tmp_var_db = tmp_var_db1 / tmp_var_int;
+  }
+
+#if USER_ACCEPTANCE_TEST
+  OPTIONS->Cost_Temp_Curr = OPTIONS->Cost_Temp_Init =
+#endif
+    *initial_cost_temperature = *current_cost_temperature = tmp_var_db;
+#endif /* USER_INITIAL_COST_TEMP */
+
+  /* set all parameters to the initial parameter values */
+  VFOR (index_v)
+    best_generated_state->parameter[index_v] =
+    last_saved_state->parameter[index_v] =
+    current_generated_state->parameter[index_v] =
+    parameter_initial_final[index_v];
+
+  OPTIONS->Locate_Cost = 1;     /* initial cost value */
+
+  /* if using user's initial parameters */
+  if (OPTIONS->User_Initial_Parameters == TRUE) {
+    *valid_state_generated_flag = TRUE;
+#if USER_ACCEPTANCE_TEST
+    OPTIONS->User_Acceptance_Flag = TRUE;
+    OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+#if ASA_SAVE
+    if (asa_read == FALSE)
+#endif
+      current_generated_state->cost =
+        user_cost_function (current_generated_state->parameter,
+                            parameter_minimum,
+                            parameter_maximum,
+                            tangents,
+                            curvature,
+                            number_parameters,
+                            parameter_type,
+                            valid_state_generated_flag, exit_status, OPTIONS);
+    if (cost_function_test
+        (current_generated_state->cost, current_generated_state->parameter,
+         parameter_minimum, parameter_maximum, number_parameters,
+         xnumber_parameters) == 0) {
+      *exit_status = INVALID_COST_FUNCTION;
+      goto EXIT_ASA;
+    }
+#if ASA_PRINT
+    if (*valid_state_generated_flag == FALSE)
+      fprintf (ptr_asa_out, "user's initial parameters generated \
+FALSE *valid_state_generated_flag\n");
+#endif
+  } else {
+    /* let asa generate valid initial parameters */
+    repeated_invalid_states = 0;
+    OPTIONS->Sequential_Parameters = *start_sequence - 1;
+    do {
+      ++(*number_invalid_generated_states);
+      generate_new_state (user_random_generator,
+                          seed,
+                          parameter_minimum,
+                          parameter_maximum, current_user_parameter_temp,
+#if USER_GENERATING_FUNCTION
+                          initial_user_parameter_temp,
+                          temperature_scale_parameters,
+#endif
+                          number_parameters,
+                          parameter_type,
+                          current_generated_state, last_saved_state, OPTIONS);
+      *valid_state_generated_flag = TRUE;
+#if USER_ACCEPTANCE_TEST
+      OPTIONS->User_Acceptance_Flag = TRUE;
+      OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+      current_generated_state->cost =
+        user_cost_function (current_generated_state->parameter,
+                            parameter_minimum,
+                            parameter_maximum,
+                            tangents,
+                            curvature,
+                            number_parameters,
+                            parameter_type,
+                            valid_state_generated_flag, exit_status, OPTIONS);
+      if (cost_function_test
+          (current_generated_state->cost,
+           current_generated_state->parameter, parameter_minimum,
+           parameter_maximum, number_parameters, xnumber_parameters) == 0) {
+        *exit_status = INVALID_COST_FUNCTION;
+        goto EXIT_ASA;
+      }
+      ++repeated_invalid_states;
+      if (repeated_invalid_states > OPTIONS->Limit_Invalid_Generated_States) {
+        *exit_status = TOO_MANY_INVALID_STATES;
+        goto EXIT_ASA;
+      }
+    }
+    while (*valid_state_generated_flag == FALSE);
+    --(*number_invalid_generated_states);
+  }                             /* OPTIONS->User_Initial_Parameters */
+
+  /* set all states to the last one generated */
+  VFOR (index_v) {
+#if DROPPED_PARAMETERS
+    /* ignore parameters that have too small a range */
+    if (PARAMETER_RANGE_TOO_SMALL (index_v))
+      continue;
+#endif
+    best_generated_state->parameter[index_v] =
+      last_saved_state->parameter[index_v] =
+      current_generated_state->parameter[index_v];
+  }
+
+  /* set all costs to the last one generated */
+  best_generated_state->cost = last_saved_state->cost =
+    current_generated_state->cost;
+
+  *accepted_to_generated_ratio = ONE;
+
+  /* do not calculate curvatures initially */
+  *curvature_flag = FALSE;
+
+#if ASA_PRINT
+  fprintf (ptr_asa_out,
+           "temperature_scale = %*.*g\n",
+           G_FIELD, G_PRECISION, temperature_scale);
+#if RATIO_TEMPERATURE_SCALES
+#if ASA_PRINT_INTERMED
+  VFOR (index_v) {
+    fprintf (ptr_asa_out,
+#if INT_ALLOC
+             "temperature_scale_parameters[%d] = %*.*g\n",
+#else
+#if INT_LONG
+             "temperature_scale_parameters[%ld] = %*.*g\n",
+#else
+             "temperature_scale_parameters[%d] = %*.*g\n",
+#endif
+#endif
+             index_v,
+             G_FIELD, G_PRECISION, temperature_scale_parameters[index_v]);
+  }
+#endif
+#else
+  fprintf (ptr_asa_out,
+           "temperature_scale_parameters[0] = %*.*g\n",
+           G_FIELD, G_PRECISION, temperature_scale_parameters[0]);
+#endif /* RATIO_TEMPERATURE_SCALES */
+  fprintf (ptr_asa_out,
+           "*temperature_scale_cost = %*.*g\n",
+           G_FIELD, G_PRECISION, *temperature_scale_cost);
+  fprintf (ptr_asa_out, "\n\n");
+
+#if ASA_PRINT_INTERMED
+  print_state (parameter_minimum,
+               parameter_maximum,
+               tangents,
+               curvature,
+               current_cost_temperature,
+               current_user_parameter_temp,
+               accepted_to_generated_ratio,
+               number_parameters,
+               curvature_flag,
+               number_accepted,
+               index_cost_acceptances,
+               number_generated,
+               number_invalid_generated_states,
+               last_saved_state, best_generated_state, ptr_asa_out, OPTIONS);
+#endif
+  fprintf (ptr_asa_out, "\n");
+
+  fflush (ptr_asa_out);
+#endif
+
+#if ASA_SAMPLE
+#if ASA_PRINT
+  fprintf (ptr_asa_out,
+           ":SAMPLE:   n_accept   cost        cost_temp    bias_accept    \
+ aver_weight\n");
+  fprintf (ptr_asa_out,
+           ":SAMPLE:   index      param[]     temp[]       bias_gener[]   \
+ range[]\n");
+#endif
+#endif
+
+  /* reset the current cost and the number of generations performed */
+  *number_invalid_generated_states = 0;
+  *best_number_generated_saved =
+    *number_generated = *recent_number_generated = 0;
+  OPTIONS->N_Generated = *number_generated;
+  VFOR (index_v) {
+    /* ignore parameters that have too small a range */
+    if (PARAMETER_RANGE_TOO_SMALL (index_v))
+      continue;
+    index_parameter_generations[index_v] = 1;
+  }
+#if USER_ACCEPTANCE_TEST
+  OPTIONS->User_Acceptance_Flag = FALSE;
+  OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+
+#if ASA_QUEUE
+#if ASA_PRINT
+#if INT_ALLOC
+  fprintf (ptr_asa_out, "OPTIONS->Queue_Size = %d\n", OPTIONS->Queue_Size);
+#else
+#if INT_LONG
+  fprintf (ptr_asa_out, "OPTIONS->Queue_Size = %ld\n", OPTIONS->Queue_Size);
+#else
+  fprintf (ptr_asa_out, "OPTIONS->Queue_Size = %d\n", OPTIONS->Queue_Size);
+#endif
+#endif
+  VFOR (index_v) {
+    fprintf (ptr_asa_out,
+#if INT_ALLOC
+             "Queue_Resolution[%d] = %*.*g\n",
+#else
+#if INT_LONG
+             "Queue_Resolution[%ld] = %*.*g\n",
+#else
+             "Queue_Resolution[%d] = %*.*g\n",
+#endif
+#endif
+             index_v,
+             G_FIELD, G_PRECISION, OPTIONS->Queue_Resolution[index_v]);
+  }
+#endif /* ASA_PRINT */
+
+  /* fill arrays to check allocated memory */
+  for (queue = 0; queue < queue_size_tmp; ++queue) {
+    VFOR (index_v) {
+      if (PARAMETER_RANGE_TOO_SMALL (index_v)) {
+        continue;
+      }
+      queue_v = index_v + queue * (LONG_INT) (*number_parameters);
+      save_queue_param[queue_v] = current_generated_state->parameter[index_v];
+    }
+    save_queue_cost[queue] = current_generated_state->cost;
+    save_queue_flag[queue] = *valid_state_generated_flag;
+  }
+  save_queue = save_queue_indx = 0;
+#endif /* ASA_QUEUE */
+
+#if ASA_RESOLUTION
+#if ASA_PRINT
+  VFOR (index_v) {
+    fprintf (ptr_asa_out,
+#if INT_ALLOC
+             "Coarse_Resolution[%d] = %*.*g\n",
+#else
+#if INT_LONG
+             "Coarse_Resolution[%ld] = %*.*g\n",
+#else
+             "Coarse_Resolution[%d] = %*.*g\n",
+#endif
+#endif
+             index_v,
+             G_FIELD, G_PRECISION, OPTIONS->Coarse_Resolution[index_v]);
+  }
+#endif /* ASA_PRINT */
+#endif /* ASA_RESOLUTION */
+
+#if MULTI_MIN
+  multi_sort[OPTIONS->Multi_Number] = OPTIONS->Multi_Number;
+  multi_cost[OPTIONS->Multi_Number] = current_generated_state->cost;
+  VFOR (index_v) {
+    multi_params[OPTIONS->Multi_Number][index_v] =
+      current_generated_state->parameter[index_v];
+  }
+  for (multi_index = 0; multi_index < OPTIONS->Multi_Number; ++multi_index) {
+    multi_sort[multi_index] = multi_index;
+    multi_cost[multi_index] = OPTIONS->Multi_Cost[multi_index] =
+      current_generated_state->cost;
+    VFOR (index_v) {
+      multi_params[multi_index][index_v] =
+        OPTIONS->Multi_Params[multi_index][index_v] =
+        current_generated_state->parameter[index_v];
+    }
+  }
+#endif /* MULTI_MIN */
+
+  OPTIONS->Sequential_Parameters = *start_sequence - 1;
+
+  /* MAIN ANNEALING LOOP */
+  while (((*number_accepted <= OPTIONS->Limit_Acceptances)
+          || (OPTIONS->Limit_Acceptances == 0))
+         && ((*number_generated <= OPTIONS->Limit_Generated)
+             || (OPTIONS->Limit_Generated == 0))) {
+
+    tmp_var_db1 = -F_LOG ((OPTIONS->Temperature_Ratio_Scale));
+
+    /* compute temperature scales */
+    tmp_var_db2 = F_LOG (OPTIONS->Temperature_Anneal_Scale);
+    temperature_scale = tmp_var_db1 *
+      F_EXP (-tmp_var_db2 / *xnumber_parameters);
+
+#if QUENCH_PARAMETERS
+#if RATIO_TEMPERATURE_SCALES
+    VFOR (index_v)
+      temperature_scale_parameters[index_v] = tmp_var_db1 * F_EXP
+#if QUENCH_PARAMETERS_SCALE
+      (-(tmp_var_db2 * OPTIONS->User_Quench_Param_Scale[index_v])
+#else
+      (-(tmp_var_db2)
+#endif
+       / *xnumber_parameters)
+      * OPTIONS->User_Temperature_Ratio[index_v];
+#else
+    VFOR (index_v)
+      temperature_scale_parameters[index_v] = tmp_var_db1 * F_EXP
+#if QUENCH_PARAMETERS_SCALE
+      (-(tmp_var_db2 * OPTIONS->User_Quench_Param_Scale[index_v])
+#else
+      (-(tmp_var_db2)
+#endif
+       / *xnumber_parameters);
+#endif /* RATIO_TEMPERATURE_SCALES */
+#else /* QUENCH_PARAMETERS */
+#if RATIO_TEMPERATURE_SCALES
+    VFOR (index_v)
+      temperature_scale_parameters[index_v] =
+      tmp_var_db1 * F_EXP (-(tmp_var_db2) / *xnumber_parameters)
+      * OPTIONS->User_Temperature_Ratio[index_v];
+#else
+    VFOR (index_v)
+      temperature_scale_parameters[index_v] =
+      tmp_var_db1 * F_EXP (-(tmp_var_db2) / *xnumber_parameters);
+#endif /* RATIO_TEMPERATURE_SCALES */
+#endif /* QUENCH_PARAMETERS */
+
+#if USER_ACCEPTANCE_TEST
+    OPTIONS->Cost_Temp_Scale =
+#endif
+      *temperature_scale_cost =
+#if QUENCH_COST
+#if QUENCH_COST_SCALE
+      tmp_var_db1 * F_EXP (-(tmp_var_db2 * OPTIONS->User_Quench_Cost_Scale[0])
+#else
+      tmp_var_db1 * F_EXP (-(tmp_var_db2)
+#endif
+                           / *xnumber_parameters) *
+      OPTIONS->Cost_Parameter_Scale_Ratio;
+#else /* QUENCH_COST */
+      tmp_var_db1 * F_EXP (-(tmp_var_db2)
+                           / *xnumber_parameters) *
+      OPTIONS->Cost_Parameter_Scale_Ratio;
+#endif /* QUENCH_COST */
+
+    /* CALCULATE NEW TEMPERATURES */
+
+    /* calculate new parameter temperatures */
+    VFOR (index_v) {
+      /* skip parameters with too small a range */
+      if (PARAMETER_RANGE_TOO_SMALL (index_v))
+        continue;
+
+      log_new_temperature_ratio =
+        -temperature_scale_parameters[index_v] *
+        F_POW ((double) index_parameter_generations[index_v],
+#if QUENCH_PARAMETERS
+               OPTIONS->User_Quench_Param_Scale[index_v]
+#else /* QUENCH_PARAMETERS */
+               ONE
+#endif /* QUENCH_PARAMETERS */
+               / *xnumber_parameters);
+      /* check (and correct) for too large an exponent */
+      log_new_temperature_ratio = EXPONENT_CHECK (log_new_temperature_ratio);
+      current_user_parameter_temp[index_v] =
+        initial_user_parameter_temp[index_v]
+        * F_EXP (log_new_temperature_ratio);
+
+#if NO_PARAM_TEMP_TEST
+      if (current_user_parameter_temp[index_v] < (double) EPS_DOUBLE)
+        current_user_parameter_temp[index_v] = (double) EPS_DOUBLE;
+#else
+      /* check for too small a parameter temperature */
+      if (current_user_parameter_temp[index_v] < (double) EPS_DOUBLE) {
+        *exit_status = P_TEMP_TOO_SMALL;
+        *index_exit_v = index_v;
+        goto EXIT_ASA;
+      }
+#endif
+    }
+
+    /* calculate new cost temperature */
+    log_new_temperature_ratio =
+      -*temperature_scale_cost * F_POW ((double) *index_cost_acceptances,
+#if QUENCH_COST
+                                        OPTIONS->User_Quench_Cost_Scale[0]
+#else
+                                        ONE
+#endif
+                                        / *xnumber_parameters);
+    log_new_temperature_ratio = EXPONENT_CHECK (log_new_temperature_ratio);
+#if USER_ACCEPTANCE_TEST
+    OPTIONS->Cost_Temp_Curr = OPTIONS->Cost_Temp_Init =
+#endif
+      *current_cost_temperature = *initial_cost_temperature
+      * F_EXP (log_new_temperature_ratio);
+
+#if NO_COST_TEMP_TEST
+    if (*current_cost_temperature < (double) EPS_DOUBLE)
+#if USER_ACCEPTANCE_TEST
+      OPTIONS->Cost_Temp_Curr =
+#endif
+        *current_cost_temperature = (double) EPS_DOUBLE;
+#else
+    /* check for too small a cost temperature */
+    if (*current_cost_temperature < (double) EPS_DOUBLE) {
+      *exit_status = C_TEMP_TOO_SMALL;
+      goto EXIT_ASA;
+    }
+#endif
+
+#if ASA_SAVE
+    if (asa_read == TRUE && OPTIONS->Asa_Recursive_Level == asa_recursive_max) {
+      if (OPTIONS->Asa_Recursive_Level > 0)
+        sprintf (asa_save_comm, "asa_save_%d", OPTIONS->Asa_Recursive_Level);
+      else
+        sprintf (asa_save_comm, "asa_save");
+      ptr_save = fopen (asa_save_comm, "r");
+
+      fread (number_parameters, sizeof (ALLOC_INT), 1, ptr_save);
+      fread (xnumber_parameters, sizeof (double), 1, ptr_save);
+      fread (parameter_minimum, sizeof (double),
+             *number_parameters, ptr_save);
+      fread (parameter_maximum, sizeof (double),
+             *number_parameters, ptr_save);
+      fread (tangents, sizeof (double), *number_parameters, ptr_save);
+      fread (current_user_parameter_temp, sizeof (double),
+             *number_parameters, ptr_save);
+      fread (initial_user_parameter_temp, sizeof (double),
+             *number_parameters, ptr_save);
+      fread (temperature_scale_parameters, sizeof (double),
+             *number_parameters, ptr_save);
+
+      fread (parameter_type, sizeof (int), *number_parameters, ptr_save);
+      fread (&index_cost_repeat, sizeof (int), 1, ptr_save);
+      fread (&asa_open, sizeof (int), 1, ptr_save);
+      fread (&number_asa_open, sizeof (int), 1, ptr_save);
+      fread (&recursive_asa_open, sizeof (int), 1, ptr_save);
+
+      fread (current_cost_temperature, sizeof (double), 1, ptr_save);
+      fread (initial_cost_temperature, sizeof (double), 1, ptr_save);
+      fread (temperature_scale_cost, sizeof (double), 1, ptr_save);
+      fread (accepted_to_generated_ratio, sizeof (double), 1, ptr_save);
+
+      fread (curvature_flag, sizeof (int), 1, ptr_save);
+
+      fread (seed, sizeof (LONG_INT), 1, ptr_save);
+      fread (number_generated, sizeof (LONG_INT), 1, ptr_save);
+      fread (number_accepted, sizeof (LONG_INT), 1, ptr_save);
+      fread (number_acceptances_saved, sizeof (LONG_INT), 1, ptr_save);
+      fread (recent_number_acceptances, sizeof (LONG_INT), 1, ptr_save);
+      fread (recent_number_generated, sizeof (LONG_INT), 1, ptr_save);
+      fread (number_invalid_generated_states, sizeof (LONG_INT), 1, ptr_save);
+      fread (index_cost_acceptances, sizeof (LONG_INT), 1, ptr_save);
+      fread (best_number_generated_saved, sizeof (LONG_INT), 1, ptr_save);
+      fread (best_number_accepted_saved, sizeof (LONG_INT), 1, ptr_save);
+
+      fread (index_parameter_generations, sizeof (LONG_INT),
+             *number_parameters, ptr_save);
+
+      fread (current_generated_state->parameter,
+             sizeof (double), *number_parameters, ptr_save);
+      fread (last_saved_state->parameter,
+             sizeof (double), *number_parameters, ptr_save);
+      fread (best_generated_state->parameter,
+             sizeof (double), *number_parameters, ptr_save);
+      fread (&(current_generated_state->cost), sizeof (double), 1, ptr_save);
+      fread (&(last_saved_state->cost), sizeof (double), 1, ptr_save);
+      fread (&(best_generated_state->cost), sizeof (double), 1, ptr_save);
+
+      fread (&(OPTIONS->Limit_Acceptances), sizeof (LONG_INT), 1, ptr_save);
+      fread (&(OPTIONS->Limit_Generated), sizeof (LONG_INT), 1, ptr_save);
+      fread (&(OPTIONS->Limit_Invalid_Generated_States), sizeof (int),
+             1, ptr_save);
+      fread (&(OPTIONS->Accepted_To_Generated_Ratio), sizeof (double),
+             1, ptr_save);
+      fread (&(OPTIONS->Cost_Precision), sizeof (double), 1, ptr_save);
+      fread (&(OPTIONS->Maximum_Cost_Repeat), sizeof (int), 1, ptr_save);
+      fread (&(OPTIONS->Number_Cost_Samples), sizeof (int), 1, ptr_save);
+      fread (&(OPTIONS->Temperature_Ratio_Scale), sizeof (double),
+             1, ptr_save);
+      fread (&(OPTIONS->Cost_Parameter_Scale_Ratio), sizeof (double),
+             1, ptr_save);
+      fread (&(OPTIONS->Temperature_Anneal_Scale), sizeof (double),
+             1, ptr_save);
+      fread (&(OPTIONS->Include_Integer_Parameters), sizeof (int),
+             1, ptr_save);
+      fread (&(OPTIONS->User_Initial_Parameters), sizeof (int), 1, ptr_save);
+      fread (&(OPTIONS->Sequential_Parameters), sizeof (ALLOC_INT), 1,
+             ptr_save);
+      fread (&(OPTIONS->Initial_Parameter_Temperature), sizeof (double), 1,
+             ptr_save);
+      fread (&(OPTIONS->Acceptance_Frequency_Modulus), sizeof (int), 1,
+             ptr_save);
+      fread (&(OPTIONS->Generated_Frequency_Modulus), sizeof (int), 1,
+             ptr_save);
+      fread (&(OPTIONS->Reanneal_Cost), sizeof (int), 1, ptr_save);
+      fread (&(OPTIONS->Reanneal_Parameters), sizeof (int), 1, ptr_save);
+      fread (&(OPTIONS->Delta_X), sizeof (double), 1, ptr_save);
+      fread (&(OPTIONS->User_Tangents), sizeof (int), 1, ptr_save);
+
+#if USER_INITIAL_COST_TEMP
+      fread (&(OPTIONS->User_Cost_Temperature), sizeof (double), 1, ptr_save);
+#endif
+#if RATIO_TEMPERATURE_SCALES
+      fread (OPTIONS->User_Temperature_Ratio, sizeof (double),
+             *number_parameters, ptr_save);
+#endif
+#if USER_INITIAL_PARAMETERS_TEMPS
+      fread (OPTIONS->User_Parameter_Temperature, sizeof (double),
+             *number_parameters, ptr_save);
+#endif
+#if DELTA_PARAMETERS
+      fread (OPTIONS->User_Delta_Parameter, sizeof (double),
+             *number_parameters, ptr_save);
+#endif
+#if QUENCH_PARAMETERS
+      fread (OPTIONS->User_Quench_Param_Scale, sizeof (double),
+             *number_parameters, ptr_save);
+#endif
+#if QUENCH_COST
+      fread (OPTIONS->User_Quench_Cost_Scale, sizeof (double), 1, ptr_save);
+#endif
+      fread (&(OPTIONS->N_Accepted), sizeof (LONG_INT), 1, ptr_save);
+      fread (&(OPTIONS->N_Generated), sizeof (LONG_INT), 1, ptr_save);
+      fread (&(OPTIONS->Locate_Cost), sizeof (int), 1, ptr_save);
+      fread (&(OPTIONS->Immediate_Exit), sizeof (int), 1, ptr_save);
+#if OPTIONAL_DATA_DBL
+      fread (&(OPTIONS->Asa_Data_Dim_Dbl), sizeof (ALLOC_INT), 1, ptr_save);
+      fread (OPTIONS->Asa_Data_Dbl, sizeof (double),
+             OPTIONS->Asa_Data_Dim_Dbl, ptr_save);
+#endif
+      fread (&(OPTIONS->Random_Array_Dim), sizeof (ALLOC_INT), 1, ptr_save);
+      fread (OPTIONS->Random_Array, sizeof (double),
+             OPTIONS->Random_Array_Dim, ptr_save);
+      fread (&(OPTIONS->Asa_Recursive_Level), sizeof (int), 1, ptr_save);
+#if OPTIONAL_DATA_INT
+      fread (&(OPTIONS->Asa_Data_Dim_Int), sizeof (ALLOC_INT), 1, ptr_save);
+      fread (OPTIONS->Asa_Data_Int, sizeof (LONG_INT),
+             OPTIONS->Asa_Data_Dim_Int, ptr_save);
+#endif
+#if OPTIONAL_DATA_PTR
+      fread (&(OPTIONS->Asa_Data_Dim_Ptr), sizeof (ALLOC_INT), 1, ptr_save);
+      if (OPTIONS->Asa_Recursive_Level == 0)
+        fread (OPTIONS->Asa_Data_Ptr, sizeof (OPTIONAL_PTR_TYPE),
+               OPTIONS->Asa_Data_Dim_Ptr, ptr_save);
+#if ASA_TEMPLATE_SELFOPT
+      if (OPTIONS->Asa_Recursive_Level == 1)
+        fread (OPTIONS->Asa_Data_Ptr, sizeof (RECUR_OPTIONAL_PTR_TYPE),
+               OPTIONS->Asa_Data_Dim_Ptr, ptr_save);
+#endif
+#endif
+#if USER_ASA_OUT
+      fread (OPTIONS->Asa_Out_File, sizeof (char), 1, ptr_save);
+#endif
+#if USER_COST_SCHEDULE
+      fread (&(OPTIONS->Cost_Schedule), sizeof (char), 1, ptr_save);
+#endif
+#if USER_ACCEPT_ASYMP_EXP
+      fread (&(OPTIONS->Asymp_Exp_Param), sizeof (double), 1, ptr_save);
+#endif
+#if USER_ACCEPTANCE_TEST
+      fread (&(OPTIONS->Acceptance_Test), sizeof (char), 1, ptr_save);
+      fread (&(OPTIONS->User_Acceptance_Flag), sizeof (int), 1, ptr_save);
+      fread (&(OPTIONS->Cost_Acceptance_Flag), sizeof (int), 1, ptr_save);
+      fread (&(OPTIONS->Cost_Temp_Curr), sizeof (double), 1, ptr_save);
+      fread (&(OPTIONS->Cost_Temp_Init), sizeof (double), 1, ptr_save);
+      fread (&(OPTIONS->Cost_Temp_Scale), sizeof (double), 1, ptr_save);
+#endif
+#if USER_GENERATING_FUNCTION
+      fread (&(OPTIONS->Generating_Distrib), sizeof (char), 1, ptr_save);
+#endif
+#if USER_REANNEAL_COST
+      fread (&(OPTIONS->Reanneal_Cost_Function), sizeof (char), 1, ptr_save);
+#endif
+#if USER_REANNEAL_PARAMETERS
+      fread (&(OPTIONS->Reanneal_Params_Function), sizeof (char),
+             1, ptr_save);
+#endif
+#if ASA_SAMPLE
+      fread (&(OPTIONS->Bias_Acceptance), sizeof (double), 1, ptr_save);
+      fread (OPTIONS->Bias_Generated, sizeof (double),
+             *number_parameters, ptr_save);
+      fread (&(OPTIONS->Average_Weights), sizeof (double), 1, ptr_save);
+      fread (&(OPTIONS->Limit_Weights), sizeof (double), 1, ptr_save);
+#endif
+#if ASA_QUEUE
+      fread (save_queue, sizeof (LONG_INT), 1, ptr_save);
+      fread (save_queue_indx, sizeof (LONG_INT), 1, ptr_save);
+      fread (&(OPTIONS->Queue_Size), sizeof (ALLOC_INT), 1, ptr_save);
+      fread (save_queue_flag, sizeof (int), save_queue, ptr_save);
+      fread (save_queue_cost, sizeof (double), save_queue, ptr_save);
+      fread (save_queue_param, sizeof (double),
+             (*number_parameters) * (OPTIONS->Queue_Size), ptr_save);
+#if ASA_RESOLUTION
+#else
+      fread (OPTIONS->Queue_Resolution, sizeof (double),
+             *number_parameters, ptr_save);
+#endif
+#endif
+#if ASA_RESOLUTION
+      fread (OPTIONS->Coarse_Resolution, sizeof (double),
+             *number_parameters, ptr_save);
+#endif
+#if FITLOC
+      fread (&(OPTIONS->Fit_Local), sizeof (int), 1, ptr_save);
+      fread (&(OPTIONS->Iter_Max), sizeof (int), 1, ptr_save);
+      fread (&(OPTIONS->Penalty), sizeof (double), 1, ptr_save);
+#endif
+#if MULTI_MIN
+      fread (OPTIONS->Multi_Number, sizeof (int), 1, ptr_save);
+      fread (OPTIONS->Multi_Grid,
+             sizeof (double), *number_parameters, ptr_save);
+      fread (&(OPTIONS->Multi_Specify), sizeof (int), 1, ptr_save);
+      for (multi_index = 0; multi_index < OPTIONS->Multi_Number;
+           ++multi_index) {
+        fread (&(OPTIONS->Multi_Cost[multi_index]), sizeof (double), 1,
+               ptr_save);
+        fread (&(OPTIONS->Multi_Params[multi_index]), sizeof (double),
+               *number_parameters, ptr_save);
+      }
+#endif
+#if ASA_PARALLEL
+      fread (&parallel_generated, sizeof (LONG_INT), 1, ptr_save);
+      fread (&parallel_block_max, sizeof (LONG_INT), 1, ptr_save);
+      for (index_parallel = 0; index_parallel < parallel_block_max;
+           ++index_parallel) {
+        fread (gener_block_state[index_parallel].parameter,
+               sizeof (double), *number_parameters, ptr_save);
+        fread (&(gener_block_state[index_parallel].cost),
+               sizeof (double), 1, ptr_save);
+#if USER_ACCEPTANCE_TEST
+        fread (&
+               (gener_block_state[index_parallel].par_user_accept_flag),
+               sizeof (int), 1, ptr_save);
+        fread (&
+               (gener_block_state[index_parallel].par_cost_accept_flag),
+               sizeof (int), 1, ptr_save);
+#endif
+      }
+      fread (&(OPTIONS->Gener_Mov_Avr), sizeof (int), 1, ptr_save);
+      fread (&(OPTIONS->Gener_Block), sizeof (LONG_INT), 1, ptr_save);
+      fread (&(OPTIONS->Gener_Block_Max), sizeof (LONG_INT), 1, ptr_save);
+#endif
+
+      fclose (ptr_save);
+
+      asa_read = FALSE;
+#if ASA_PRINT
+      print_state (parameter_minimum,
+                   parameter_maximum,
+                   tangents,
+                   curvature,
+                   current_cost_temperature,
+                   current_user_parameter_temp,
+                   accepted_to_generated_ratio,
+                   number_parameters,
+                   curvature_flag,
+                   number_accepted,
+                   index_cost_acceptances,
+                   number_generated,
+                   number_invalid_generated_states,
+                   last_saved_state,
+                   best_generated_state, ptr_asa_out, OPTIONS);
+#endif /* ASA_PRINT */
+
+#include "asa_opt"
+#if ASA_SAVE_OPT
+      if ((ptr_save_opt = fopen ("asa_save_opt", "r")) == NULL) {
+#if INCL_STDOUT
+        printf ("\n\n*** WARNING fopen asa_save_opt failed *** \n\n");
+#endif /* INCL_STDOUT */
+#if ASA_PRINT
+        fprintf (ptr_asa_out,
+                 "\n\n*** WARNING fopen asa_save_opt failed *** \n\n");
+        fflush (ptr_asa_out);
+#endif
+      } else {
+        fscanf (ptr_save_opt, "%s%s%s%s%s",
+                read_if, read_FALSE, read_comm1, read_ASA_SAVE, read_comm2);
+        if (strcmp (read_if, "#if") || strcmp (read_FALSE, "FALSE")
+            || strcmp (read_comm1, "/*")
+            || strcmp (read_ASA_SAVE, "ASA_SAVE")
+            || strcmp (read_comm2, "*/")) {
+#if INCL_STDOUT
+          printf ("\n\n*** EXIT not asa_save_opt for this version *** \n\n");
+#endif /* INCL_STDOUT */
+#if ASA_PRINT
+          fprintf (ptr_asa_out,
+                   "\n\n*** not asa_save_opt for this version *** \n\n");
+          fflush (ptr_asa_out);
+#endif
+          *exit_status = INVALID_USER_INPUT;
+          goto EXIT_ASA;
+        }
+#if INT_LONG
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%ld", &read_long);
+        OPTIONS->Limit_Acceptances = read_long;
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%ld", &read_long);
+        OPTIONS->Limit_Generated = read_long;
+#else
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%d", &read_int);
+        OPTIONS->Limit_Acceptances = read_int;
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%d", &read_int);
+        OPTIONS->Limit_Generated = read_int;
+#endif
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%d", &read_int);
+        OPTIONS->Limit_Invalid_Generated_States = read_int;
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%lf", &read_double);
+        OPTIONS->Accepted_To_Generated_Ratio = read_double;
+
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%lf", &read_double);
+        OPTIONS->Cost_Precision = read_double;
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%d", &read_int);
+        OPTIONS->Maximum_Cost_Repeat = read_int;
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%d", &read_int);
+        OPTIONS->Number_Cost_Samples = read_int;
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%lf", &read_double);
+        OPTIONS->Temperature_Ratio_Scale = read_double;
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%lf", &read_double);
+        OPTIONS->Cost_Parameter_Scale_Ratio = read_double;
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%lf", &read_double);
+        OPTIONS->Temperature_Anneal_Scale = read_double;
+
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%d", &read_int);
+        OPTIONS->Include_Integer_Parameters = read_int;
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%d", &read_int);
+        OPTIONS->User_Initial_Parameters = read_int;
+#if INT_ALLOC
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%d", &read_int);
+        OPTIONS->Sequential_Parameters = read_int;
+#else
+#if INT_LONG
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%ld", &read_long);
+        OPTIONS->Sequential_Parameters = read_long;
+#else
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%d", &read_int);
+        OPTIONS->Sequential_Parameters = read_int;
+#endif
+#endif
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%lf", &read_double);
+        OPTIONS->Initial_Parameter_Temperature = read_double;
+
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%d", &read_int);
+        OPTIONS->Acceptance_Frequency_Modulus = read_int;
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%d", &read_int);
+        OPTIONS->Generated_Frequency_Modulus = read_int;
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%d", &read_int);
+        OPTIONS->Reanneal_Cost = read_int;
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%d", &read_int);
+        OPTIONS->Reanneal_Parameters = read_int;
+
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%lf", &read_double);
+        OPTIONS->Delta_X = read_double;
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%d", &read_int);
+        OPTIONS->User_Tangents = read_int;
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%d", &read_int);
+        OPTIONS->Curvature_0 = read_int;
+
+        fclose (ptr_save_opt);
+      }
+#endif /* ASA_SAVE_OPT */
+
+      goto SAVED_ASA;
+    }
+#endif /* ASA_SAVE */
+
+    /* GENERATE NEW PARAMETERS */
+
+    /* generate a new valid set of parameters */
+#if ASA_PARALLEL
+    /* *** ENTER CODE TO SPAWN OFF PARALLEL GENERATED STATES *** */
+
+    /* check if need more memory allocated to gener_block_state */
+    if (OPTIONS->Gener_Block_Max > parallel_block_max) {
+      for (index_parallel = 0; index_parallel < parallel_block_max;
+           ++index_parallel) {
+        free (gener_block_state[index_parallel].parameter);
+      }
+      free (gener_block_state);
+
+      if ((gener_block_state =
+           (STATE *) calloc (OPTIONS->Gener_Block_Max,
+                             sizeof (STATE))) == NULL) {
+        strcpy (exit_msg, "asa(): gener_block_state");
+        Exit_ASA (exit_msg);
+        *exit_status = CALLOC_FAILED;
+        return (-1);
+      }
+
+      parallel_block_max = OPTIONS->Gener_Block_Max;
+
+      for (index_parallel = 0; index_parallel < parallel_block_max;
+           ++index_parallel) {
+        if ((gener_block_state[index_parallel].parameter =
+             (double *) calloc (*number_parameters,
+                                sizeof (double))) == NULL) {
+          strcpy (exit_msg,
+                  "asa(): gener_block_state[index_parallel].parameter");
+          Exit_ASA (exit_msg);
+          *exit_status = CALLOC_FAILED;
+          return (-1);
+        }
+      }
+    }
+#if ASA_TEMPLATE_PARALLEL
+    for (index_parallel = 0; index_parallel < OPTIONS->Gener_Block;
+         ++index_parallel) {
+#endif /* ASA_TEMPLATE_PARALLEL */
+#endif /* ASA_PARALLEL */
+
+      if (OPTIONS->Locate_Cost < 0) {
+        OPTIONS->Locate_Cost = 12;      /* generate new state from new best */
+      } else {
+        OPTIONS->Locate_Cost = 2;       /* generate new state */
+      }
+
+      repeated_invalid_states = 0;
+      do {
+        ++(*number_invalid_generated_states);
+        generate_new_state (user_random_generator,
+                            seed,
+                            parameter_minimum,
+                            parameter_maximum, current_user_parameter_temp,
+#if USER_GENERATING_FUNCTION
+                            initial_user_parameter_temp,
+                            temperature_scale_parameters,
+#endif
+                            number_parameters,
+                            parameter_type,
+                            current_generated_state,
+                            last_saved_state, OPTIONS);
+
+        *valid_state_generated_flag = TRUE;
+#if USER_ACCEPTANCE_TEST
+        OPTIONS->User_Acceptance_Flag = FALSE;
+        OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+#if ASA_QUEUE
+        /* Binary trees do not seem necessary since we are assuming
+           that the cost function calculation is the bottleneck.
+           However, see the MISC.DIR/asa_contrib file for
+           source code for doubly-linked and hashed lists. */
+        if (OPTIONS->Queue_Size == 0) {
+          queue_new = 1;
+        } else {
+          queue_new = 1;
+          for (queue = 0; queue < save_queue; ++queue) {
+            save_queue_test = 0;
+            VFOR (index_v) {
+              if (PARAMETER_RANGE_TOO_SMALL (index_v)) {
+                ++save_queue_test;
+              } else {
+                queue_v = index_v + queue * (LONG_INT) (*number_parameters);
+                if (fabs
+                    (current_generated_state->parameter[index_v] -
+                     save_queue_param[queue_v]) <=
+                    (OPTIONS->Queue_Resolution[index_v] + EPS_DOUBLE)) {
+                  ++save_queue_test;
+                }
+              }
+            }
+            if (save_queue_test == *number_parameters) {
+              tmp_var_db = save_queue_cost[queue];
+              *valid_state_generated_flag = save_queue_flag[queue];
+              queue_new = 0;
+              --(*number_generated);
+#if ASA_PRINT_MORE
+#if INT_LONG
+              fprintf (ptr_asa_out, "ASA_QUEUE: %ld \t %*.*g\n",
+                       OPTIONS->N_Generated,
+                       G_FIELD, G_PRECISION, tmp_var_db);
+#else
+              fprintf (ptr_asa_out, "ASA_QUEUE: %d \t %*.*g\n",
+                       OPTIONS->N_Generated,
+                       G_FIELD, G_PRECISION, tmp_var_db);
+#endif
+#endif
+              break;
+            }
+          }
+        }
+        if (queue_new == 1) {
+          tmp_var_db =
+            user_cost_function (current_generated_state->parameter,
+                                parameter_minimum,
+                                parameter_maximum,
+                                tangents,
+                                curvature,
+                                number_parameters,
+                                parameter_type,
+                                valid_state_generated_flag,
+                                exit_status, OPTIONS);
+          if (cost_function_test (tmp_var_db,
+                                  current_generated_state->parameter,
+                                  parameter_minimum,
+                                  parameter_maximum,
+                                  number_parameters,
+                                  xnumber_parameters) == 0) {
+            *exit_status = INVALID_COST_FUNCTION;
+            goto EXIT_ASA;
+          }
+          if (OPTIONS->Queue_Size > 0) {        /* in case recursive use */
+            VFOR (index_v) {
+              if (PARAMETER_RANGE_TOO_SMALL (index_v)) {
+                continue;
+              }
+              queue_v = index_v + save_queue_indx
+                * (LONG_INT) (*number_parameters);
+              save_queue_param[queue_v] =
+                current_generated_state->parameter[index_v];
+            }
+            save_queue_cost[save_queue_indx] = tmp_var_db;
+            save_queue_flag[save_queue_indx]
+              = *valid_state_generated_flag;
+
+            ++save_queue;
+            if (save_queue == (LONG_INT) OPTIONS->Queue_Size)
+              --save_queue;
+
+            ++save_queue_indx;
+            if (save_queue_indx == (LONG_INT) OPTIONS->Queue_Size)
+              save_queue_indx = 0;
+          }
+        }
+#else /* ASA_QUEUE */
+        tmp_var_db =
+          user_cost_function (current_generated_state->parameter,
+                              parameter_minimum,
+                              parameter_maximum,
+                              tangents,
+                              curvature,
+                              number_parameters,
+                              parameter_type,
+                              valid_state_generated_flag,
+                              exit_status, OPTIONS);
+        if (cost_function_test (tmp_var_db,
+                                current_generated_state->parameter,
+                                parameter_minimum,
+                                parameter_maximum, number_parameters,
+                                xnumber_parameters) == 0) {
+          *exit_status = INVALID_COST_FUNCTION;
+          goto EXIT_ASA;
+        }
+#endif /* ASA_QUEUE */
+        current_generated_state->cost = tmp_var_db;
+        ++repeated_invalid_states;
+        if (repeated_invalid_states > OPTIONS->Limit_Invalid_Generated_States) {
+          *exit_status = TOO_MANY_INVALID_STATES;
+          goto EXIT_ASA;
+        }
+      }
+      while (*valid_state_generated_flag == FALSE);
+      --(*number_invalid_generated_states);
+#if ASA_PARALLEL
+      gener_block_state[index_parallel].cost = current_generated_state->cost;
+#if USER_ACCEPTANCE_TEST
+      gener_block_state[index_parallel].par_user_accept_flag =
+        OPTIONS->User_Acceptance_Flag;
+      gener_block_state[index_parallel].par_cost_accept_flag =
+        OPTIONS->Cost_Acceptance_Flag;
+#endif
+      VFOR (index_v) {
+        /* ignore parameters with too small a range */
+        if (PARAMETER_RANGE_TOO_SMALL (index_v))
+          continue;
+        gener_block_state[index_parallel].parameter[index_v] =
+          current_generated_state->parameter[index_v];
+      }
+#if ASA_TEMPLATE_PARALLEL
+    }
+#endif /* ASA_TEMPLATE_PARALLEL */
+    /* *** EXIT CODE SPAWNING OFF PARALLEL GENERATED STATES *** */
+#endif /* ASA_PARALLEL */
+
+    /* ACCEPT/REJECT NEW PARAMETERS */
+
+#if ASA_PARALLEL
+    for (sort_index = 0; sort_index < OPTIONS->Gener_Block; ++sort_index)
+      parallel_sort[sort_index] = sort_index;
+    qsort (parallel_sort, OPTIONS->Gener_Block, sizeof (LONG_INT),
+           sort_parallel);
+
+    for (sort_index = 0; sort_index < OPTIONS->Gener_Block; ++sort_index) {
+      index_parallel = parallel_sort[sort_index];
+      current_generated_state->cost = gener_block_state[index_parallel].cost;
+#if USER_ACCEPTANCE_TEST
+      OPTIONS->User_Acceptance_Flag =
+        gener_block_state[index_parallel].par_user_accept_flag;
+      OPTIONS->Cost_Acceptance_Flag =
+        gener_block_state[index_parallel].par_cost_accept_flag;
+#endif
+      VFOR (index_v) {
+        /* ignore parameters with too small a range */
+        if (PARAMETER_RANGE_TOO_SMALL (index_v))
+          continue;
+        current_generated_state->parameter[index_v] =
+          gener_block_state[index_parallel].parameter[index_v];
+      }
+#endif /* ASA_PARALLEL */
+      /* decide to accept/reject the new state */
+      accept_new_state (user_random_generator,
+                        seed,
+                        parameter_minimum,
+                        parameter_maximum, current_cost_temperature,
+#if ASA_SAMPLE
+                        current_user_parameter_temp,
+#endif
+                        number_parameters,
+                        recent_number_acceptances,
+                        number_accepted,
+                        index_cost_acceptances,
+                        number_acceptances_saved,
+                        recent_number_generated,
+                        number_generated,
+                        index_parameter_generations,
+                        current_generated_state, last_saved_state,
+#if ASA_SAMPLE
+                        ptr_asa_out,
+#endif
+                        OPTIONS);
+
+#if ASA_PARALLEL
+#else
+#if ASA_PIPE_FILE
+#if INT_ALLOC
+      fprintf (ptr_asa_pipe, "%d", *number_generated);
+#else
+#if INT_LONG
+      fprintf (ptr_asa_pipe, "%ld", *number_generated);
+#else
+      fprintf (ptr_asa_pipe, "%d", *number_generated);
+#endif
+#endif
+#if INT_ALLOC
+      fprintf (ptr_asa_pipe, "\t%d", *number_accepted);
+#else
+#if INT_LONG
+      fprintf (ptr_asa_pipe, "\t%ld", *number_accepted);
+#else
+      fprintf (ptr_asa_pipe, "\t%d", *number_accepted);
+#endif
+#endif
+      fprintf (ptr_asa_pipe, "\t%g", best_generated_state->cost);
+      VFOR (index_v)
+        fprintf (ptr_asa_pipe, "\t%g",
+                 best_generated_state->parameter[index_v]);
+      fprintf (ptr_asa_pipe, "\t%g", *current_cost_temperature);
+      VFOR (index_v)
+        fprintf (ptr_asa_pipe, "\t%g", current_user_parameter_temp[index_v]);
+      fprintf (ptr_asa_pipe, "\t%g", last_saved_state->cost);
+      fprintf (ptr_asa_pipe, "\n");
+      fflush (ptr_asa_pipe);
+#endif /* ASA_PIPE_FILE */
+#if INCL_STDOUT
+#if ASA_PIPE
+#if INT_ALLOC
+      printf ("%d", *number_generated);
+#else
+#if INT_LONG
+      printf ("%ld", *number_generated);
+#else
+      printf ("%d", *number_generated);
+#endif
+#endif
+#if INT_ALLOC
+      printf ("\t%d", *number_accepted);
+#else
+#if INT_LONG
+      printf ("\t%ld", *number_accepted);
+#else
+      printf ("\t%d", *number_accepted);
+#endif
+#endif
+      printf ("\t%g", best_generated_state->cost);
+      VFOR (index_v)
+        printf ("\t%g", best_generated_state->parameter[index_v]);
+      printf ("\t%g", *current_cost_temperature);
+      VFOR (index_v)
+        printf ("\t%g", current_user_parameter_temp[index_v]);
+      printf ("\n");
+#endif /* ASA_PIPE */
+#endif /* INCL_STDOUT */
+#endif /* ASA_PARALLEL */
+
+      /* calculate the ratio of acceptances to generated states */
+      *accepted_to_generated_ratio =
+        (double) (*recent_number_acceptances + 1) /
+        (double) (*recent_number_generated + 1);
+
+#if MULTI_MIN
+      if (((OPTIONS->Multi_Specify == 0)
+           && (current_generated_state->cost <= best_generated_state->cost))
+          || ((OPTIONS->Multi_Specify == 1)
+              && (current_generated_state->cost <
+                  best_generated_state->cost))) {
+#if ASA_RESOLUTION
+        VFOR (index_v) {
+          if (OPTIONS->Multi_Grid[index_v] <
+              OPTIONS->Coarse_Resolution[index_v])
+            OPTIONS->Multi_Grid[index_v] =
+              OPTIONS->Coarse_Resolution[index_v];
+        }
+#endif /* ASA_RESOLUTION */
+        VFOR (index_v) {
+          if (OPTIONS->Multi_Grid[index_v] < EPS_DOUBLE)
+            OPTIONS->Multi_Grid[index_v] = EPS_DOUBLE;
+        }
+
+        multi_test = 0;
+        for (multi_index = 0; multi_index < OPTIONS->Multi_Number;
+             ++multi_index) {
+          multi_test_cmp = 0;
+          multi_test_dim = 0;
+          VFOR (index_v) {
+            if (PARAMETER_RANGE_TOO_SMALL (index_v))
+              continue;
+            ++multi_test_dim;
+            if (fabs (current_generated_state->parameter[index_v]
+                      - OPTIONS->Multi_Params[multi_index][index_v])
+                < OPTIONS->Multi_Grid[index_v])
+              ++multi_test_cmp;
+          }
+          if (multi_test_cmp == multi_test_dim)
+            multi_test = 1;
+          if (OPTIONS->Multi_Specify == 1)
+            break;
+        }
+
+        if (multi_test == 0) {
+          multi_cost[OPTIONS->Multi_Number] = current_generated_state->cost;
+          VFOR (index_v) {
+            multi_params[OPTIONS->Multi_Number][index_v] =
+              current_generated_state->parameter[index_v];
+          }
+          for (multi_index = 0; multi_index < OPTIONS->Multi_Number;
+               ++multi_index) {
+            multi_cost[multi_index] = OPTIONS->Multi_Cost[multi_index];
+            VFOR (index_v) {
+              multi_params[multi_index][index_v] =
+                OPTIONS->Multi_Params[multi_index][index_v];
+            }
+          }
+
+          qsort (multi_sort, OPTIONS->Multi_Number + 1, sizeof (int),
+                 multi_compare);
+          for (multi_index = 0; multi_index < OPTIONS->Multi_Number;
+               ++multi_index) {
+            OPTIONS->Multi_Cost[multi_index] =
+              multi_cost[multi_sort[multi_index]];
+            VFOR (index_v) {
+              OPTIONS->Multi_Params[multi_index][index_v] =
+                multi_params[multi_sort[multi_index]][index_v];
+            }
+          }
+        }
+      }
+#endif /* MULTI_MIN */
+
+      /* CHECK FOR NEW MINIMUM */
+
+      if (current_generated_state->cost < best_generated_state->cost) {
+        /* NEW MINIMUM FOUND */
+
+        OPTIONS->Locate_Cost = -1;
+
+        /* reset the recent acceptances and generated counts */
+#if ASA_PARALLEL
+        parallel_generated = *recent_number_generated;
+#endif
+        *recent_number_acceptances = *recent_number_generated = 0;
+        *best_number_generated_saved = *number_generated;
+        *best_number_accepted_saved = *number_accepted;
+        index_cost_repeat = 0;
+
+        /* copy the current state into the best_generated state */
+        best_generated_state->cost = current_generated_state->cost;
+        VFOR (index_v) {
+#if DROPPED_PARAMETERS
+          /* ignore parameters that have too small a range */
+          if (PARAMETER_RANGE_TOO_SMALL (index_v))
+            continue;
+#endif
+          best_generated_state->parameter[index_v] =
+            current_generated_state->parameter[index_v];
+        }
+
+        /* printout the new minimum state and value */
+#if ASA_PRINT
+        fprintf (ptr_asa_out,
+#if INT_LONG
+                 "best...->cost=%-*.*g  \
+*number_accepted=%ld  *number_generated=%ld\n", G_FIELD, G_PRECISION, best_generated_state->cost,
+#else
+                 "best...->cost=%-*.*g  \
+*number_accepted=%d  *number_generated=%d\n", G_FIELD, G_PRECISION, best_generated_state->cost,
+#endif /* INT_LONG */
+                 *number_accepted, *number_generated);
+#if ASA_PARALLEL
+        /* print OPTIONS->Gener_Block just used */
+        fprintf (ptr_asa_out,
+#if INT_LONG
+                 "OPTIONS->Gener_Block = %ld\n",
+#else
+                 "OPTIONS->Gener_Block = %d\n",
+#endif /* INT_LONG */
+                 OPTIONS->Gener_Block);
+#endif /* ASA_PARALLEL */
+#if ASA_PRINT_MORE
+#if INT_ALLOC
+        fprintf (ptr_asa_out, "Present Random Seed = %d\n\n", *seed);
+#else
+#if INT_LONG
+        fprintf (ptr_asa_out, "Present Random Seed = %ld\n\n", *seed);
+#else
+        fprintf (ptr_asa_out, "Present Random Seed = %d\n\n", *seed);
+#endif
+#endif
+        print_state (parameter_minimum,
+                     parameter_maximum,
+                     tangents,
+                     curvature,
+                     current_cost_temperature,
+                     current_user_parameter_temp,
+                     accepted_to_generated_ratio,
+                     number_parameters,
+                     curvature_flag,
+                     number_accepted,
+                     index_cost_acceptances,
+                     number_generated,
+                     number_invalid_generated_states,
+                     last_saved_state,
+                     best_generated_state, ptr_asa_out, OPTIONS);
+#endif /* ASA_PRINT_MORE */
+        fflush (ptr_asa_out);
+#endif /* ASA_PRINT */
+
+#if ASA_PARALLEL
+        /* leave index_parallel loop after new minimum */
+        break;
+#endif /* ASA_PARALLEL */
+      }
+#if ASA_PARALLEL
+    }
+#endif /* ASA_PARALLEL */
+
+#if ASA_PARALLEL
+    if (OPTIONS->Gener_Mov_Avr > 0) {
+      OPTIONS->Gener_Block = (LONG_INT)
+        ((((double) OPTIONS->Gener_Mov_Avr - ONE)
+          * (double) (OPTIONS->Gener_Block) + (double) parallel_generated)
+         / (double) (OPTIONS->Gener_Mov_Avr));
+      OPTIONS->Gener_Block = MIN (OPTIONS->Gener_Block, parallel_block_max);
+    }
+#endif /* ASA_PARALLEL */
+
+#if ASA_SAVE
+    /* These writes are put here with these tests, instead of just
+       after a new best state is found, to prevent any confusion with
+       any parallel code that might be added by users. */
+    if (*recent_number_acceptances == 0
+        && *recent_number_generated == 0
+        && *best_number_generated_saved == *number_generated
+        && *best_number_accepted_saved == *number_accepted
+        && OPTIONS->Asa_Recursive_Level == asa_recursive_max
+        && index_cost_repeat == 0) {
+      if (OPTIONS->Asa_Recursive_Level > 0)
+        sprintf (asa_save_comm, "asa_save_%d", OPTIONS->Asa_Recursive_Level);
+      else
+        sprintf (asa_save_comm, "asa_save");
+      ptr_save = fopen (asa_save_comm, "w");
+
+      fwrite (number_parameters, sizeof (ALLOC_INT), 1, ptr_save);
+      fwrite (xnumber_parameters, sizeof (double), 1, ptr_save);
+      fwrite (parameter_minimum, sizeof (double),
+              *number_parameters, ptr_save);
+      fwrite (parameter_maximum, sizeof (double),
+              *number_parameters, ptr_save);
+      fwrite (tangents, sizeof (double), *number_parameters, ptr_save);
+      fwrite (current_user_parameter_temp, sizeof (double),
+              *number_parameters, ptr_save);
+      fwrite (initial_user_parameter_temp, sizeof (double),
+              *number_parameters, ptr_save);
+      fwrite (temperature_scale_parameters, sizeof (double),
+              *number_parameters, ptr_save);
+
+      fwrite (parameter_type, sizeof (int), *number_parameters, ptr_save);
+      fwrite (&index_cost_repeat, sizeof (int), 1, ptr_save);
+      fwrite (&asa_open, sizeof (int), 1, ptr_save);
+      fwrite (&number_asa_open, sizeof (int), 1, ptr_save);
+      fwrite (&recursive_asa_open, sizeof (int), 1, ptr_save);
+
+      fwrite (current_cost_temperature, sizeof (double), 1, ptr_save);
+      fwrite (initial_cost_temperature, sizeof (double), 1, ptr_save);
+      fwrite (temperature_scale_cost, sizeof (double), 1, ptr_save);
+      fwrite (accepted_to_generated_ratio, sizeof (double), 1, ptr_save);
+
+      fwrite (curvature_flag, sizeof (int), 1, ptr_save);
+
+      fwrite (seed, sizeof (LONG_INT), 1, ptr_save);
+      fwrite (number_generated, sizeof (LONG_INT), 1, ptr_save);
+      fwrite (number_accepted, sizeof (LONG_INT), 1, ptr_save);
+      fwrite (number_acceptances_saved, sizeof (LONG_INT), 1, ptr_save);
+      fwrite (recent_number_acceptances, sizeof (LONG_INT), 1, ptr_save);
+      fwrite (recent_number_generated, sizeof (LONG_INT), 1, ptr_save);
+      fwrite (number_invalid_generated_states, sizeof (LONG_INT),
+              1, ptr_save);
+      fwrite (index_cost_acceptances, sizeof (LONG_INT), 1, ptr_save);
+      fwrite (best_number_generated_saved, sizeof (LONG_INT), 1, ptr_save);
+      fwrite (best_number_accepted_saved, sizeof (LONG_INT), 1, ptr_save);
+
+      fwrite (index_parameter_generations, sizeof (LONG_INT),
+              *number_parameters, ptr_save);
+
+      fwrite (current_generated_state->parameter,
+              sizeof (double), *number_parameters, ptr_save);
+      fwrite (last_saved_state->parameter,
+              sizeof (double), *number_parameters, ptr_save);
+      fwrite (best_generated_state->parameter,
+              sizeof (double), *number_parameters, ptr_save);
+      fwrite (&(current_generated_state->cost), sizeof (double), 1, ptr_save);
+      fwrite (&(last_saved_state->cost), sizeof (double), 1, ptr_save);
+      fwrite (&(best_generated_state->cost), sizeof (double), 1, ptr_save);
+
+      fwrite (&(OPTIONS->Limit_Acceptances), sizeof (LONG_INT), 1, ptr_save);
+      fwrite (&(OPTIONS->Limit_Generated), sizeof (LONG_INT), 1, ptr_save);
+      fwrite (&(OPTIONS->Limit_Invalid_Generated_States), sizeof (int),
+              1, ptr_save);
+      fwrite (&(OPTIONS->Accepted_To_Generated_Ratio), sizeof (double),
+              1, ptr_save);
+      fwrite (&(OPTIONS->Cost_Precision), sizeof (double), 1, ptr_save);
+      fwrite (&(OPTIONS->Maximum_Cost_Repeat), sizeof (int), 1, ptr_save);
+      fwrite (&(OPTIONS->Number_Cost_Samples), sizeof (int), 1, ptr_save);
+      fwrite (&(OPTIONS->Temperature_Ratio_Scale), sizeof (double),
+              1, ptr_save);
+      fwrite (&(OPTIONS->Cost_Parameter_Scale_Ratio), sizeof (double),
+              1, ptr_save);
+      fwrite (&(OPTIONS->Temperature_Anneal_Scale), sizeof (double),
+              1, ptr_save);
+      fwrite (&(OPTIONS->Include_Integer_Parameters), sizeof (int),
+              1, ptr_save);
+      fwrite (&(OPTIONS->User_Initial_Parameters), sizeof (int), 1, ptr_save);
+      fwrite (&(OPTIONS->Sequential_Parameters), sizeof (ALLOC_INT), 1,
+              ptr_save);
+      fwrite (&(OPTIONS->Initial_Parameter_Temperature), sizeof (double), 1,
+              ptr_save);
+      fwrite (&(OPTIONS->Acceptance_Frequency_Modulus), sizeof (int), 1,
+              ptr_save);
+      fwrite (&(OPTIONS->Generated_Frequency_Modulus), sizeof (int), 1,
+              ptr_save);
+      fwrite (&(OPTIONS->Reanneal_Cost), sizeof (int), 1, ptr_save);
+      fwrite (&(OPTIONS->Reanneal_Parameters), sizeof (int), 1, ptr_save);
+      fwrite (&(OPTIONS->Delta_X), sizeof (double), 1, ptr_save);
+      fwrite (&(OPTIONS->User_Tangents), sizeof (int), 1, ptr_save);
+
+#if USER_INITIAL_COST_TEMP
+      fwrite (&(OPTIONS->User_Cost_Temperature), sizeof (double),
+              1, ptr_save);
+#endif
+#if RATIO_TEMPERATURE_SCALES
+      fwrite (OPTIONS->User_Temperature_Ratio, sizeof (double),
+              *number_parameters, ptr_save);
+#endif
+#if USER_INITIAL_PARAMETERS_TEMPS
+      fwrite (OPTIONS->User_Parameter_Temperature, sizeof (double),
+              *number_parameters, ptr_save);
+#endif
+#if DELTA_PARAMETERS
+      fwrite (OPTIONS->User_Delta_Parameter, sizeof (double),
+              *number_parameters, ptr_save);
+#endif
+#if QUENCH_PARAMETERS
+      fwrite (OPTIONS->User_Quench_Param_Scale, sizeof (double),
+              *number_parameters, ptr_save);
+#endif
+#if QUENCH_COST
+      fwrite (OPTIONS->User_Quench_Cost_Scale, sizeof (double), 1, ptr_save);
+#endif
+      fwrite (&(OPTIONS->N_Accepted), sizeof (LONG_INT), 1, ptr_save);
+      fwrite (&(OPTIONS->N_Generated), sizeof (LONG_INT), 1, ptr_save);
+      fwrite (&(OPTIONS->Locate_Cost), sizeof (int), 1, ptr_save);
+      fwrite (&(OPTIONS->Immediate_Exit), sizeof (int), 1, ptr_save);
+#if OPTIONAL_DATA_DBL
+      fwrite (&(OPTIONS->Asa_Data_Dim_Dbl), sizeof (ALLOC_INT), 1, ptr_save);
+      fwrite (OPTIONS->Asa_Data_Dbl, sizeof (double),
+              OPTIONS->Asa_Data_Dim_Dbl, ptr_save);
+#endif
+      fwrite (&(OPTIONS->Random_Array_Dim), sizeof (ALLOC_INT), 1, ptr_save);
+      fwrite (OPTIONS->Random_Array, sizeof (double),
+              OPTIONS->Random_Array_Dim, ptr_save);
+      fwrite (&(OPTIONS->Asa_Recursive_Level), sizeof (int), 1, ptr_save);
+#if OPTIONAL_DATA_INT
+      fwrite (&(OPTIONS->Asa_Data_Dim_Int), sizeof (ALLOC_INT), 1, ptr_save);
+      fwrite (OPTIONS->Asa_Data_Int, sizeof (LONG_INT),
+              OPTIONS->Asa_Data_Dim_Int, ptr_save);
+#endif
+#if OPTIONAL_DATA_PTR
+      fwrite (&(OPTIONS->Asa_Data_Dim_Ptr), sizeof (ALLOC_INT), 1, ptr_save);
+      if (OPTIONS->Asa_Recursive_Level == 0)
+        fwrite (OPTIONS->Asa_Data_Ptr, sizeof (OPTIONAL_PTR_TYPE),
+                OPTIONS->Asa_Data_Dim_Ptr, ptr_save);
+#if ASA_TEMPLATE_SELFOPT
+      if (OPTIONS->Asa_Recursive_Level == 1)
+        fwrite (OPTIONS->Asa_Data_Ptr, sizeof (RECUR_OPTIONAL_PTR_TYPE),
+                OPTIONS->Asa_Data_Dim_Ptr, ptr_save);
+#endif
+#endif
+#if USER_ASA_OUT
+      fwrite (OPTIONS->Asa_Out_File, sizeof (char), 1, ptr_save);
+#endif
+#if USER_COST_SCHEDULE
+      fwrite (&(OPTIONS->Cost_Schedule), sizeof (char), 1, ptr_save);
+#endif
+#if USER_ACCEPT_ASYMP_EXP
+      fwrite (&(OPTIONS->Asymp_Exp_Param), sizeof (double), 1, ptr_save);
+#endif
+#if USER_ACCEPTANCE_TEST
+      fwrite (&(OPTIONS->Acceptance_Test), sizeof (char), 1, ptr_save);
+      fwrite (&(OPTIONS->User_Acceptance_Flag), sizeof (int), 1, ptr_save);
+      fwrite (&(OPTIONS->Cost_Acceptance_Flag), sizeof (int), 1, ptr_save);
+      fwrite (&(OPTIONS->Cost_Temp_Curr), sizeof (double), 1, ptr_save);
+      fwrite (&(OPTIONS->Cost_Temp_Init), sizeof (double), 1, ptr_save);
+      fwrite (&(OPTIONS->Cost_Temp_Scale), sizeof (double), 1, ptr_save);
+#endif
+#if USER_GENERATING_FUNCTION
+      fwrite (&(OPTIONS->Generating_Distrib), sizeof (char), 1, ptr_save);
+#endif
+#if USER_REANNEAL_COST
+      fwrite (&(OPTIONS->Reanneal_Cost_Function), sizeof (char), 1, ptr_save);
+#endif
+#if USER_REANNEAL_PARAMETERS
+      fwrite (&(OPTIONS->Reanneal_Params_Function), sizeof (char),
+              1, ptr_save);
+#endif
+#if ASA_SAMPLE
+      fwrite (&(OPTIONS->Bias_Acceptance), sizeof (double), 1, ptr_save);
+      fwrite (OPTIONS->Bias_Generated, sizeof (double),
+              *number_parameters, ptr_save);
+      fwrite (&(OPTIONS->Average_Weights), sizeof (double), 1, ptr_save);
+      fwrite (&(OPTIONS->Limit_Weights), sizeof (double), 1, ptr_save);
+#endif
+#if ASA_QUEUE
+      fwrite (save_queue, sizeof (LONG_INT), 1, ptr_save);
+      fwrite (save_queue_indx, sizeof (LONG_INT), 1, ptr_save);
+      fwrite (&(OPTIONS->Queue_Size), sizeof (ALLOC_INT), 1, ptr_save);
+      fwrite (save_queue_flag, sizeof (int), save_queue, ptr_save);
+      fwrite (save_queue_cost, sizeof (double), save_queue, ptr_save);
+      fwrite (save_queue_param, sizeof (double),
+              (*number_parameters) * (OPTIONS->Queue_Size), ptr_save);
+#if ASA_RESOLUTION
+#else
+      fwrite (OPTIONS->Queue_Resolution, sizeof (double),
+              *number_parameters, ptr_save);
+#endif
+#endif
+#if ASA_RESOLUTION
+      fwrite (OPTIONS->Coarse_Resolution, sizeof (double),
+              *number_parameters, ptr_save);
+#endif
+#if FITLOC
+      fwrite (&(OPTIONS->Fit_Local), sizeof (int), 1, ptr_save);
+      fwrite (&(OPTIONS->Iter_Max), sizeof (int), 1, ptr_save);
+      fwrite (&(OPTIONS->Penalty), sizeof (double), 1, ptr_save);
+#endif
+#if MULTI_MIN
+      fwrite (OPTIONS->Multi_Number, sizeof (int), 1, ptr_save);
+      fwrite (OPTIONS->Multi_Grid,
+              sizeof (double), *number_parameters, ptr_save);
+      fwrite (&(OPTIONS->Multi_Specify), sizeof (int), 1, ptr_save);
+      for (multi_index = 0; multi_index < OPTIONS->Multi_Number;
+           ++multi_index) {
+        fwrite (&(OPTIONS->Multi_Cost[multi_index]), sizeof (double), 1,
+                ptr_save);
+        fwrite (&(OPTIONS->Multi_Params[multi_index]), sizeof (double),
+                *number_parameters, ptr_save);
+      }
+#endif
+#if ASA_PARALLEL
+      fwrite (&parallel_generated, sizeof (LONG_INT), 1, ptr_save);
+      fwrite (&parallel_block_max, sizeof (LONG_INT), 1, ptr_save);
+      for (index_parallel = 0; index_parallel < parallel_block_max;
+           ++index_parallel) {
+        fwrite (gener_block_state[index_parallel].parameter,
+                sizeof (double), *number_parameters, ptr_save);
+        fwrite (&(gener_block_state[index_parallel].cost),
+                sizeof (double), 1, ptr_save);
+#if USER_ACCEPTANCE_TEST
+        fwrite (&
+                (gener_block_state[index_parallel].
+                 par_user_accept_flag), sizeof (int), 1, ptr_save);
+        fwrite (&
+                (gener_block_state[index_parallel].
+                 par_cost_accept_flag), sizeof (int), 1, ptr_save);
+#endif
+      }
+      fwrite (&(OPTIONS->Gener_Mov_Avr), sizeof (int), 1, ptr_save);
+      fwrite (&(OPTIONS->Gener_Block), sizeof (LONG_INT), 1, ptr_save);
+      fwrite (&(OPTIONS->Gener_Block_Max), sizeof (LONG_INT), 1, ptr_save);
+#endif
+
+      fclose (ptr_save);
+
+    SAVED_ASA:
+      ;
+
+#if SYSTEM_CALL
+#if ASA_SAVE_BACKUP
+#if INT_LONG
+      if (OPTIONS->Asa_Recursive_Level > 0)
+        sprintf (asa_save_comm, "/bin/cp asa_save_%d asa_save_%d.%ld",
+                 OPTIONS->Asa_Recursive_Level,
+                 OPTIONS->Asa_Recursive_Level, OPTIONS->N_Accepted);
+      else
+        sprintf (asa_save_comm, "/bin/cp asa_save asa_save.%ld",
+                 OPTIONS->N_Accepted);
+#else
+      if (OPTIONS->Asa_Recursive_Level > 0)
+        sprintf (asa_save_comm, "/bin/cp asa_save_%d asa_save_%d.%d",
+                 OPTIONS->Asa_Recursive_Level,
+                 OPTIONS->Asa_Recursive_Level, OPTIONS->N_Accepted);
+      else
+        sprintf (asa_save_comm, "/bin/cp asa_save asa_save.%d",
+                 OPTIONS->N_Accepted);
+#endif
+      ptr_comm = popen (asa_save_comm, "r");
+      pclose (ptr_comm);
+#else /* ASA_SAVE_BACKUP */
+      /* extra protection in case run aborts during write */
+      if (OPTIONS->Asa_Recursive_Level > 0)
+        sprintf (asa_save_comm, "/bin/cp asa_save_%d asa_save_%d.old",
+                 OPTIONS->Asa_Recursive_Level, OPTIONS->Asa_Recursive_Level);
+      else
+        sprintf (asa_save_comm, "/bin/cp asa_save asa_save.old");
+      ptr_comm = popen (asa_save_comm, "r");
+      pclose (ptr_comm);
+#endif /* ASA_SAVE_BACKUP */
+#endif /* SYSTEM_CALL */
+    }
+#endif /* ASA_SAVE */
+
+    if (OPTIONS->Immediate_Exit == TRUE) {
+      *exit_status = IMMEDIATE_EXIT;
+      goto EXIT_ASA;
+    }
+
+    /* PERIODIC TESTING/REANNEALING/PRINTING SECTION */
+
+    if (OPTIONS->Acceptance_Frequency_Modulus == 0)
+      tmp_var_int1 = FALSE;
+    else if ((int) (*number_accepted %
+                    ((LONG_INT) OPTIONS->Acceptance_Frequency_Modulus)) == 0
+             && *number_acceptances_saved == *number_accepted)
+      tmp_var_int1 = TRUE;
+    else
+      tmp_var_int1 = FALSE;
+
+    if (OPTIONS->Generated_Frequency_Modulus == 0)
+      tmp_var_int2 = FALSE;
+    else if ((int) (*number_generated %
+                    ((LONG_INT) OPTIONS->Generated_Frequency_Modulus)) == 0)
+      tmp_var_int2 = TRUE;
+    else
+      tmp_var_int2 = FALSE;
+
+    if (tmp_var_int1 == TRUE || tmp_var_int2 == TRUE
+        || (*accepted_to_generated_ratio
+            < OPTIONS->Accepted_To_Generated_Ratio)) {
+      if (*accepted_to_generated_ratio
+          < (OPTIONS->Accepted_To_Generated_Ratio))
+        *recent_number_acceptances = *recent_number_generated = 0;
+
+      /* if best.cost repeats OPTIONS->Maximum_Cost_Repeat then exit */
+      if (OPTIONS->Maximum_Cost_Repeat != 0) {
+        if (fabs (last_saved_state->cost - best_generated_state->cost)
+            < OPTIONS->Cost_Precision) {
+          ++index_cost_repeat;
+          if (index_cost_repeat == (OPTIONS->Maximum_Cost_Repeat)) {
+            *exit_status = COST_REPEATING;
+            goto EXIT_ASA;
+          }
+        } else {
+          index_cost_repeat = 0;
+        }
+      }
+
+      if (OPTIONS->Reanneal_Parameters == TRUE) {
+        OPTIONS->Locate_Cost = 3;       /* reanneal parameters */
+
+        /* calculate tangents, not curvatures, to reanneal */
+        *curvature_flag = FALSE;
+        cost_derivatives (user_cost_function,
+                          parameter_minimum,
+                          parameter_maximum,
+                          tangents,
+                          curvature,
+                          maximum_tangent,
+                          number_parameters,
+                          parameter_type,
+                          exit_status,
+                          curvature_flag,
+                          valid_state_generated_flag,
+                          number_invalid_generated_states,
+                          current_generated_state,
+                          best_generated_state, ptr_asa_out, OPTIONS);
+        if (*exit_status == INVALID_COST_FUNCTION_DERIV) {
+          goto EXIT_ASA;
+        }
+      }
+#if USER_REANNEAL_COST
+#else
+      if (OPTIONS->Reanneal_Cost == 0 || OPTIONS->Reanneal_Cost == 1) {
+        ;
+      } else {
+        immediate_flag = OPTIONS->Immediate_Exit;
+
+        if (OPTIONS->Reanneal_Cost < -1) {
+          tmp_var_int = -OPTIONS->Reanneal_Cost;
+        } else {
+          tmp_var_int = OPTIONS->Reanneal_Cost;
+        }
+        tmp_var_db1 = ZERO;
+        tmp_var_db2 = ZERO;
+
+        for (index_cost_constraint = 0;
+             index_cost_constraint < tmp_var_int; ++index_cost_constraint) {
+          OPTIONS->Locate_Cost = 4;     /* reanneal cost */
+
+          *number_invalid_generated_states = 0;
+          repeated_invalid_states = 0;
+          OPTIONS->Sequential_Parameters = *start_sequence - 1;
+          do {
+            ++(*number_invalid_generated_states);
+            generate_new_state (user_random_generator,
+                                seed,
+                                parameter_minimum,
+                                parameter_maximum,
+                                current_user_parameter_temp,
+#if USER_GENERATING_FUNCTION
+                                initial_user_parameter_temp,
+                                temperature_scale_parameters,
+#endif
+                                number_parameters,
+                                parameter_type,
+                                current_generated_state,
+                                last_saved_state, OPTIONS);
+            *valid_state_generated_flag = TRUE;
+#if USER_ACCEPTANCE_TEST
+            OPTIONS->User_Acceptance_Flag = TRUE;
+            OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+
+#if ASA_QUEUE
+            if (OPTIONS->Queue_Size == 0) {
+              queue_new = 1;
+            } else {
+              queue_new = 1;
+              for (queue = 0; queue < save_queue; ++queue) {
+                save_queue_test = 0;
+                VFOR (index_v) {
+                  if (PARAMETER_RANGE_TOO_SMALL (index_v)) {
+                    ++save_queue_test;
+                  } else {
+                    queue_v = index_v + queue
+                      * (LONG_INT) (*number_parameters);
+                    if (fabs
+                        (current_generated_state->
+                         parameter[index_v] -
+                         save_queue_param[queue_v]) <
+                        (OPTIONS->Queue_Resolution[index_v] + EPS_DOUBLE)) {
+                      ++save_queue_test;
+                    }
+                  }
+                }
+                if (save_queue_test == *number_parameters) {
+                  tmp_var_db = save_queue_cost[queue];
+                  *valid_state_generated_flag = save_queue_flag[queue];
+                  queue_new = 0;
+#if ASA_PRINT_MORE
+#if INT_LONG
+                  fprintf (ptr_asa_out,
+                           "ASA_QUEUE: %ld \t %*.*g\n",
+                           OPTIONS->N_Generated, G_FIELD,
+                           G_PRECISION, tmp_var_db);
+#else
+                  fprintf (ptr_asa_out,
+                           "ASA_QUEUE: %d \t %*.*g\n",
+                           OPTIONS->N_Generated, G_FIELD,
+                           G_PRECISION, tmp_var_db);
+#endif
+#endif
+                  break;
+                }
+              }
+            }
+            if (queue_new == 1) {
+              tmp_var_db =
+                user_cost_function (current_generated_state->
+                                    parameter, parameter_minimum,
+                                    parameter_maximum, tangents,
+                                    curvature, number_parameters,
+                                    parameter_type,
+                                    valid_state_generated_flag,
+                                    exit_status, OPTIONS);
+              if (cost_function_test
+                  (tmp_var_db, current_generated_state->parameter,
+                   parameter_minimum, parameter_maximum,
+                   number_parameters, xnumber_parameters) == 0) {
+                *exit_status = INVALID_COST_FUNCTION;
+                goto EXIT_ASA;
+              }
+              if (OPTIONS->Queue_Size > 0) {
+                VFOR (index_v) {
+                  if (PARAMETER_RANGE_TOO_SMALL (index_v)) {
+                    continue;
+                  }
+                  queue_v = index_v + save_queue
+                    * (LONG_INT) (*number_parameters);
+                  save_queue_param[queue_v] =
+                    current_generated_state->parameter[index_v];
+                }
+                save_queue_cost[save_queue] = tmp_var_db;
+                save_queue_flag[save_queue]
+                  = *valid_state_generated_flag;
+
+                ++save_queue;
+                if (save_queue == (LONG_INT) OPTIONS->Queue_Size)
+                  --save_queue;
+
+                ++save_queue_indx;
+                if (save_queue_indx == (LONG_INT) OPTIONS->Queue_Size)
+                  save_queue_indx = 0;
+              }
+            }
+#else /* ASA_QUEUE */
+            tmp_var_db =
+              user_cost_function (current_generated_state->
+                                  parameter, parameter_minimum,
+                                  parameter_maximum, tangents,
+                                  curvature, number_parameters,
+                                  parameter_type,
+                                  valid_state_generated_flag,
+                                  exit_status, OPTIONS);
+            if (cost_function_test
+                (tmp_var_db, current_generated_state->parameter,
+                 parameter_minimum, parameter_maximum,
+                 number_parameters, xnumber_parameters) == 0) {
+              *exit_status = INVALID_COST_FUNCTION;
+              goto EXIT_ASA;
+            }
+#endif /* ASA_QUEUE */
+            ++repeated_invalid_states;
+            if (repeated_invalid_states >
+                OPTIONS->Limit_Invalid_Generated_States) {
+              *exit_status = TOO_MANY_INVALID_STATES;
+              goto EXIT_ASA;
+            }
+          }
+          while (*valid_state_generated_flag == FALSE);
+          --(*number_invalid_generated_states);
+
+          tmp_var_db1 += tmp_var_db;
+          tmp_var_db2 += (tmp_var_db * tmp_var_db);
+        }
+        tmp_var_db1 /= (double) tmp_var_int;
+        tmp_var_db2 /= (double) tmp_var_int;
+        tmp_var_db =
+          sqrt (fabs
+                ((tmp_var_db2 -
+                  tmp_var_db1 * tmp_var_db1) * ((double) tmp_var_int /
+                                                ((double) tmp_var_int -
+                                                 ONE))));
+        if (OPTIONS->Reanneal_Cost < -1) {
+          *current_cost_temperature = *initial_cost_temperature =
+            tmp_var_db + (double) EPS_DOUBLE;
+        } else {
+          *initial_cost_temperature = tmp_var_db + (double) EPS_DOUBLE;
+        }
+        OPTIONS->Immediate_Exit = immediate_flag;
+      }
+#endif /* USER_REANNEAL_COST */
+
+      reanneal (parameter_minimum,
+                parameter_maximum,
+                tangents,
+                maximum_tangent,
+                current_cost_temperature,
+                initial_cost_temperature,
+                temperature_scale_cost,
+                current_user_parameter_temp,
+                initial_user_parameter_temp,
+                temperature_scale_parameters,
+                number_parameters,
+                parameter_type,
+                index_cost_acceptances,
+                index_parameter_generations,
+                last_saved_state, best_generated_state, OPTIONS);
+#if ASA_PRINT_INTERMED
+#if ASA_PRINT
+      print_state (parameter_minimum,
+                   parameter_maximum,
+                   tangents,
+                   curvature,
+                   current_cost_temperature,
+                   current_user_parameter_temp,
+                   accepted_to_generated_ratio,
+                   number_parameters,
+                   curvature_flag,
+                   number_accepted,
+                   index_cost_acceptances,
+                   number_generated,
+                   number_invalid_generated_states,
+                   last_saved_state,
+                   best_generated_state, ptr_asa_out, OPTIONS);
+
+      fprintf (ptr_asa_out, "\n");
+      fflush (ptr_asa_out);
+#endif
+#endif
+    }
+  }
+
+  /* FINISHED ANNEALING and MINIMIZATION */
+
+  *exit_status = NORMAL_EXIT;
+EXIT_ASA:
+
+  asa_exit_value = asa_exit (user_cost_function,
+                             &final_cost,
+                             parameter_initial_final,
+                             parameter_minimum,
+                             parameter_maximum,
+                             tangents,
+                             curvature,
+                             maximum_tangent,
+                             current_cost_temperature,
+                             initial_user_parameter_temp,
+                             current_user_parameter_temp,
+                             accepted_to_generated_ratio,
+                             number_parameters,
+                             parameter_type,
+                             valid_state_generated_flag,
+                             exit_status,
+                             index_exit_v,
+                             start_sequence,
+                             number_accepted,
+                             best_number_accepted_saved,
+                             index_cost_acceptances,
+                             number_generated,
+                             number_invalid_generated_states,
+                             index_parameter_generations,
+                             best_number_generated_saved,
+                             current_generated_state,
+                             last_saved_state,
+                             best_generated_state, ptr_asa_out, OPTIONS);
+  if (asa_exit_value == 9) {
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+
+  free (curvature_flag);
+  free (maximum_tangent);
+  free (accepted_to_generated_ratio);
+  free (temperature_scale_cost);
+  free (current_cost_temperature);
+  free (initial_cost_temperature);
+  free (number_generated);
+  free (best_number_generated_saved);
+  free (recent_number_generated);
+  free (number_accepted);
+  free (recent_number_acceptances);
+  free (index_cost_acceptances);
+  free (number_acceptances_saved);
+  free (best_number_accepted_saved);
+  free (number_invalid_generated_states);
+  free (current_generated_state->parameter);
+  free (last_saved_state->parameter);
+  free (best_generated_state->parameter);
+  free (current_generated_state);
+  free (last_saved_state);
+  free (best_generated_state);
+#if ASA_QUEUE
+  free (save_queue_flag);
+  free (save_queue_cost);
+  free (save_queue_param);
+#endif
+#if MULTI_MIN
+  for (multi_index = 0; multi_index <= OPTIONS->Multi_Number; ++multi_index)
+    free (multi_params[multi_index]);
+  free (multi_params);
+  free (multi_sort);
+  free (multi_cost);
+#endif
+#if ASA_PARALLEL
+  for (index_parallel = 0; index_parallel < parallel_block_max;
+       ++index_parallel) {
+    free (gener_block_state[index_parallel].parameter);
+  }
+  free (gener_block_state);
+  free (parallel_sort);
+#endif
+#if ASA_PIPE_FILE
+  fclose (ptr_asa_pipe);
+#endif
+  free (initial_user_parameter_temp);
+  free (index_exit_v);
+  free (start_sequence);
+  free (index_parameter_generations);
+  free (current_user_parameter_temp);
+  free (temperature_scale_parameters);
+  if (recursive_asa_open == 0)
+    asa_open = FALSE;
+  return (final_cost);
+}
+
+/***********************************************************************
+* asa_exit
+*	This procedures copies the best parameters and cost into
+*       final_cost and parameter_initial_final
+***********************************************************************/
+#if HAVE_ANSI
+int
+asa_exit (double (*user_cost_function)
+
+           
+          (double *, double *, double *, double *, double *, ALLOC_INT *,
+           int *, int *, int *, USER_DEFINES *), double *final_cost,
+          double *parameter_initial_final, double *parameter_minimum,
+          double *parameter_maximum, double *tangents, double *curvature,
+          double *maximum_tangent, double *current_cost_temperature,
+          double *initial_user_parameter_temp,
+          double *current_user_parameter_temp,
+          double *accepted_to_generated_ratio,
+          ALLOC_INT * number_parameters, int *parameter_type,
+          int *valid_state_generated_flag, int *exit_status,
+          ALLOC_INT * index_exit_v, ALLOC_INT * start_sequence,
+          LONG_INT * number_accepted,
+          LONG_INT * best_number_accepted_saved,
+          LONG_INT * index_cost_acceptances, LONG_INT * number_generated,
+          LONG_INT * number_invalid_generated_states,
+          LONG_INT * index_parameter_generations,
+          LONG_INT * best_number_generated_saved,
+          STATE * current_generated_state, STATE * last_saved_state,
+          STATE * best_generated_state, FILE * ptr_asa_out,
+          USER_DEFINES * OPTIONS)
+#else
+int
+
+asa_exit (user_cost_function,
+          final_cost,
+          parameter_initial_final,
+          parameter_minimum,
+          parameter_maximum,
+          tangents,
+          curvature,
+          maximum_tangent,
+          current_cost_temperature,
+          initial_user_parameter_temp,
+          current_user_parameter_temp,
+          accepted_to_generated_ratio,
+          number_parameters,
+          parameter_type,
+          valid_state_generated_flag,
+          exit_status,
+          index_exit_v,
+          start_sequence,
+          number_accepted,
+          best_number_accepted_saved,
+          index_cost_acceptances,
+          number_generated,
+          number_invalid_generated_states,
+          index_parameter_generations,
+          best_number_generated_saved,
+          current_generated_state,
+          last_saved_state, best_generated_state, ptr_asa_out, OPTIONS)
+     double (*user_cost_function) ();
+     double *final_cost;
+     double *parameter_initial_final;
+     double *parameter_minimum;
+     double *parameter_maximum;
+     double *tangents;
+     double *curvature;
+     double *maximum_tangent;
+     double *current_cost_temperature;
+     double *initial_user_parameter_temp;
+     double *current_user_parameter_temp;
+     double *accepted_to_generated_ratio;
+     ALLOC_INT *number_parameters;
+     int *parameter_type;
+     int *valid_state_generated_flag;
+     int *exit_status;
+     ALLOC_INT *index_exit_v;
+     ALLOC_INT *start_sequence;
+     LONG_INT *number_accepted;
+     LONG_INT *best_number_accepted_saved;
+     LONG_INT *index_cost_acceptances;
+     LONG_INT *number_generated;
+     LONG_INT *number_invalid_generated_states;
+     LONG_INT *index_parameter_generations;
+     LONG_INT *best_number_generated_saved;
+     STATE *current_generated_state;
+     STATE *last_saved_state;
+     STATE *best_generated_state;
+     FILE *ptr_asa_out;
+     USER_DEFINES *OPTIONS;
+#endif
+{
+  ALLOC_INT index_v;            /* iteration index */
+  int curvatureFlag;
+  int exit_exit_status, tmp_locate;
+#if MULTI_MIN
+  int multi_index;
+#endif
+
+  tmp_locate = OPTIONS->Locate_Cost;
+
+  /* return final function minimum and associated parameters */
+  *final_cost = best_generated_state->cost;
+  VFOR (index_v) {
+    parameter_initial_final[index_v] =
+      best_generated_state->parameter[index_v];
+  }
+
+  OPTIONS->N_Accepted = *best_number_accepted_saved;
+  OPTIONS->N_Generated = *best_number_generated_saved;
+
+#if MULTI_MIN
+  for (multi_index = 0; multi_index < OPTIONS->Multi_Number; ++multi_index) {
+    best_generated_state->cost = OPTIONS->Multi_Cost[multi_index];
+    VFOR (index_v) {
+      best_generated_state->parameter[index_v] =
+        OPTIONS->Multi_Params[multi_index][index_v];
+    }
+#if ASA_PRINT
+    fprintf (ptr_asa_out, "\n\t\t multi_index = %d\n", multi_index);
+#endif /* ASA_PRINT */
+#endif /* MULTI_MIN */
+    if (*exit_status != TOO_MANY_INVALID_STATES
+        && *exit_status != IMMEDIATE_EXIT
+        && *exit_status != INVALID_USER_INPUT
+        && *exit_status != INVALID_COST_FUNCTION
+        && *exit_status != INVALID_COST_FUNCTION_DERIV) {
+      if (OPTIONS->Curvature_0 != TRUE)
+        OPTIONS->Locate_Cost = 5;       /* calc curvatures while exiting asa */
+
+      /* calculate curvatures and tangents at best point */
+      curvatureFlag = TRUE;
+      cost_derivatives (user_cost_function,
+                        parameter_minimum,
+                        parameter_maximum,
+                        tangents,
+                        curvature,
+                        maximum_tangent,
+                        number_parameters,
+                        parameter_type,
+                        &exit_exit_status,
+                        &curvatureFlag,
+                        valid_state_generated_flag,
+                        number_invalid_generated_states,
+                        current_generated_state,
+                        best_generated_state, ptr_asa_out, OPTIONS);
+    }
+#if ASA_PRINT
+    if (exit_exit_status == INVALID_COST_FUNCTION_DERIV)
+      fprintf (ptr_asa_out, "\n\n  in asa_exit: INVALID_COST_FUNCTION_DERIV");
+
+    if (*exit_status != INVALID_USER_INPUT
+        && *exit_status != INVALID_COST_FUNCTION
+        && *exit_status != INVALID_COST_FUNCTION_DERIV)
+      print_state (parameter_minimum,
+                   parameter_maximum,
+                   tangents,
+                   curvature,
+                   current_cost_temperature,
+                   current_user_parameter_temp,
+                   accepted_to_generated_ratio,
+                   number_parameters,
+                   &curvatureFlag,
+                   number_accepted,
+                   index_cost_acceptances,
+                   number_generated,
+                   number_invalid_generated_states,
+                   last_saved_state,
+                   best_generated_state, ptr_asa_out, OPTIONS);
+#endif /* ASA_PRINT */
+
+#if MULTI_MIN
+  }
+  best_generated_state->cost = OPTIONS->Multi_Cost[0];
+  VFOR (index_v) {
+    best_generated_state->parameter[index_v] =
+      OPTIONS->Multi_Params[0][index_v];
+  }
+#endif /* MULTI_MIN */
+
+#if ASA_PRINT
+  switch (*exit_status) {
+  case NORMAL_EXIT:
+    fprintf (ptr_asa_out,
+             "\n\n NORMAL_EXIT exit_status = %d\n", *exit_status);
+    break;
+  case P_TEMP_TOO_SMALL:
+    fprintf (ptr_asa_out,
+             "\n\n P_TEMP_TOO_SMALL exit_status = %d\n", *exit_status);
+    fprintf (ptr_asa_out,
+#if INT_ALLOC
+             "current_user_parameter_temp[%d] too small = %*.*g\n",
+#else
+#if INT_LONG
+             "current_user_parameter_temp[%ld] too small = %*.*g\n",
+#else
+             "current_user_parameter_temp[%d] too small = %*.*g\n",
+#endif
+#endif
+             *index_exit_v,
+             G_FIELD, G_PRECISION,
+             current_user_parameter_temp[*index_exit_v]);
+    break;
+  case C_TEMP_TOO_SMALL:
+    fprintf (ptr_asa_out,
+             "\n\n C_TEMP_TOO_SMALL exit_status = %d\n", *exit_status);
+    fprintf (ptr_asa_out,
+             "*current_cost_temperature too small = %*.*g\n",
+             G_FIELD, G_PRECISION, *current_cost_temperature);
+    break;
+  case COST_REPEATING:
+    fprintf (ptr_asa_out,
+             "\n\n COST_REPEATING exit_status = %d\n", *exit_status);
+    break;
+  case TOO_MANY_INVALID_STATES:
+    fprintf (ptr_asa_out,
+             "\n\n  TOO_MANY_INVALID_STATES exit_status = %d\n",
+             *exit_status);
+    break;
+  case IMMEDIATE_EXIT:
+    fprintf (ptr_asa_out,
+             "\n\n  IMMEDIATE_EXIT exit_status = %d\n", *exit_status);
+    break;
+  case INVALID_USER_INPUT:
+    fprintf (ptr_asa_out,
+             "\n\n  INVALID_USER_INPUT exit_status = %d\n", *exit_status);
+    break;
+  case INVALID_COST_FUNCTION:
+    fprintf (ptr_asa_out,
+             "\n\n  INVALID_COST_FUNCTION exit_status = %d\n", *exit_status);
+    break;
+  case INVALID_COST_FUNCTION_DERIV:
+    fprintf (ptr_asa_out,
+             "\n\n  INVALID_COST_FUNCTION_DERIV exit_status = %d\n",
+             *exit_status);
+    break;
+  default:
+    fprintf (ptr_asa_out, "\n\n ERR: no exit code available = %d\n",
+             *exit_status);
+  }
+
+  switch (OPTIONS->Locate_Cost) {
+  case 0:
+    fprintf (ptr_asa_out,
+             " Locate_Cost = %d, initial cost temperature\n",
+             OPTIONS->Locate_Cost);
+    break;
+  case 1:
+    fprintf (ptr_asa_out,
+             " Locate_Cost = %d, initial cost value\n", OPTIONS->Locate_Cost);
+    break;
+  case 2:
+    fprintf (ptr_asa_out,
+             " Locate_Cost = %d, new generated state\n",
+             OPTIONS->Locate_Cost);
+    break;
+  case 12:
+    fprintf (ptr_asa_out,
+             " Locate_Cost = %d, new generated state just after a new best state\n",
+             OPTIONS->Locate_Cost);
+    break;
+  case 3:
+    fprintf (ptr_asa_out,
+             " Locate_Cost = %d, cost derivatives, reannealing parameters\n",
+             OPTIONS->Locate_Cost);
+    break;
+  case 4:
+    fprintf (ptr_asa_out,
+             " Locate_Cost = %d, reannealing cost temperature\n",
+             OPTIONS->Locate_Cost);
+    break;
+  case 5:
+    fprintf (ptr_asa_out,
+             " Locate_Cost = %d, calculating curvatures while exiting asa ()\n",
+             OPTIONS->Locate_Cost);
+    break;
+  case -1:
+    fprintf (ptr_asa_out,
+             " Locate_Cost = %d, exited main asa () loop by user-defined OPTIONS\n",
+             OPTIONS->Locate_Cost);
+    break;
+  default:
+    fprintf (ptr_asa_out,
+             " Locate_Cost = %d, no index available for Locate_Cost\n",
+             OPTIONS->Locate_Cost);
+  }
+
+  if (*exit_status != INVALID_USER_INPUT
+      && *exit_status != INVALID_COST_FUNCTION
+      && *exit_status != INVALID_COST_FUNCTION_DERIV) {
+    fprintf (ptr_asa_out,
+             "final_cost = best_generated_state->cost = %-*.*g\n",
+             G_FIELD, G_PRECISION, *final_cost);
+#if INT_LONG
+    fprintf (ptr_asa_out,
+             "*number_accepted at best_generated_state->cost = %ld\n",
+             *best_number_accepted_saved);
+    fprintf (ptr_asa_out,
+             "*number_generated at best_generated_state->cost = %ld\n",
+             *best_number_generated_saved);
+#else
+    fprintf (ptr_asa_out,
+             "*number_accepted at best_generated_state->cost = %d\n",
+             *best_number_accepted_saved);
+    fprintf (ptr_asa_out,
+             "*number_generated at best_generated_state->cost = %d\n",
+             *best_number_generated_saved);
+#endif
+  }
+#endif
+
+#if ASA_TEMPLATE_SELFOPT
+  if (OPTIONS->Asa_Data_Dbl[0] > (double) MIN_DOUBLE)
+    OPTIONS->Asa_Data_Dbl[1] = (double) (*best_number_generated_saved);
+#endif
+
+  /* reset OPTIONS->Sequential_Parameters */
+  OPTIONS->Sequential_Parameters = *start_sequence;
+
+#if ASA_PRINT
+#if TIME_CALC
+  /* print ending time */
+  print_time ("asa_end", ptr_asa_out);
+#endif
+  fprintf (ptr_asa_out, "\n\n\n");
+  fflush (ptr_asa_out);
+  ptr_asa_out != stdout && fclose (ptr_asa_out);
+#endif
+
+  return (0);
+}
+
+/***********************************************************************
+* generate_new_state
+*       Generates a valid new state from the old state
+***********************************************************************/
+#if HAVE_ANSI
+void
+
+generate_new_state (double (*user_random_generator) (LONG_INT *),
+                    LONG_INT * seed,
+                    double *parameter_minimum,
+                    double *parameter_maximum,
+                    double *current_user_parameter_temp,
+#if USER_GENERATING_FUNCTION
+                    double *initial_user_parameter_temp,
+                    double *temperature_scale_parameters,
+#endif
+                    ALLOC_INT * number_parameters,
+                    int *parameter_type,
+                    STATE * current_generated_state,
+                    STATE * last_saved_state, USER_DEFINES * OPTIONS)
+#else
+void
+
+generate_new_state (user_random_generator,
+                    seed,
+                    parameter_minimum,
+                    parameter_maximum, current_user_parameter_temp,
+#if USER_GENERATING_FUNCTION
+                    initial_user_parameter_temp, temperature_scale_parameters,
+#endif
+                    number_parameters,
+                    parameter_type,
+                    current_generated_state, last_saved_state, OPTIONS)
+     double (*user_random_generator) ();
+     LONG_INT *seed;
+     double *parameter_minimum;
+     double *parameter_maximum;
+     double *current_user_parameter_temp;
+#if USER_GENERATING_FUNCTION
+     double *initial_user_parameter_temp;
+     double *temperature_scale_parameters;
+#endif
+     ALLOC_INT *number_parameters;
+     int *parameter_type;
+     STATE *current_generated_state;
+     STATE *last_saved_state;
+     USER_DEFINES *OPTIONS;
+#endif
+{
+  ALLOC_INT index_v;
+  double x;
+  double parameter_v, min_parameter_v, max_parameter_v, temperature_v,
+    parameter_range_v;
+#if USER_GENERATING_FUNCTION
+  double init_param_temp_v;
+  double temp_scale_params_v;
+#endif
+#if ASA_RESOLUTION
+  double xres, xint, xminus, xplus, dx, dxminus, dxplus;
+#endif
+
+  /* generate a new value for each parameter */
+  VFOR (index_v) {
+    if (OPTIONS->Sequential_Parameters >= -1) {
+      ++OPTIONS->Sequential_Parameters;
+      if (OPTIONS->Sequential_Parameters == *number_parameters)
+        OPTIONS->Sequential_Parameters = 0;
+      index_v = OPTIONS->Sequential_Parameters;
+    }
+    min_parameter_v = parameter_minimum[index_v];
+    max_parameter_v = parameter_maximum[index_v];
+    parameter_range_v = max_parameter_v - min_parameter_v;
+
+    /* ignore parameters that have too small a range */
+    if (fabs (parameter_range_v) < (double) EPS_DOUBLE)
+      continue;
+
+    temperature_v = current_user_parameter_temp[index_v];
+#if USER_GENERATING_FUNCTION
+    init_param_temp_v = initial_user_parameter_temp[index_v];
+    temp_scale_params_v = temperature_scale_parameters[index_v];
+#endif
+    parameter_v = last_saved_state->parameter[index_v];
+
+    /* Handle discrete parameters. */
+#if ASA_RESOLUTION
+    xres = OPTIONS->Coarse_Resolution[index_v];
+    if (xres > EPS_DOUBLE) {
+      min_parameter_v -= (xres / TWO);
+      max_parameter_v += (xres / TWO);
+      parameter_range_v = max_parameter_v - min_parameter_v;
+    }
+#endif /* ASA_RESOLUTION */
+    if (INTEGER_PARAMETER (index_v)) {
+#if ASA_RESOLUTION
+      if (xres > EPS_DOUBLE) {
+        ;
+      } else {
+#endif /* ASA_RESOLUTION */
+        min_parameter_v -= HALF;
+        max_parameter_v += HALF;
+        parameter_range_v = max_parameter_v - min_parameter_v;
+      }
+#if ASA_RESOLUTION
+    }
+#endif
+
+    /* generate a new state x within the parameter bounds */
+    for (;;) {
+#if USER_GENERATING_FUNCTION
+      x = OPTIONS->Generating_Distrib (seed,
+                                       number_parameters,
+                                       index_v,
+                                       temperature_v,
+                                       init_param_temp_v,
+                                       temp_scale_params_v,
+                                       parameter_v,
+                                       parameter_range_v,
+                                       last_saved_state->parameter, OPTIONS);
+#else
+      x = parameter_v
+        + generate_asa_state (user_random_generator, seed, &temperature_v)
+        * parameter_range_v;
+#endif /* USER_GENERATING_FUNCTION */
+#if ASA_RESOLUTION
+      if (xres > EPS_DOUBLE) {
+        xint = xres * (double) ((LONG_INT) (x / xres));
+        xplus = xint + xres;
+        xminus = xint - xres;
+        dx = fabs (xint - x);
+        dxminus = fabs (xminus - x);
+        dxplus = fabs (xplus - x);
+
+        if (dx < dxminus && dx < dxplus)
+          x = xint;
+        else if (dxminus < dxplus)
+          x = xminus;
+        else
+          x = xplus;
+      }
+#endif /* ASA_RESOLUTION */
+
+      /* exit the loop if within its valid parameter range */
+      if (x <= max_parameter_v - (double) EPS_DOUBLE
+          && x >= min_parameter_v + (double) EPS_DOUBLE)
+        break;
+    }
+
+    /* Handle discrete parameters.
+       You might have to check rounding on your machine. */
+    if (INTEGER_PARAMETER (index_v)) {
+#if ASA_RESOLUTION
+      if (xres > EPS_DOUBLE) {
+        ;
+      } else {
+#endif /* ASA_RESOLUTION */
+        if (x < min_parameter_v + HALF)
+          x = min_parameter_v + HALF + (double) EPS_DOUBLE;
+        if (x > max_parameter_v - HALF)
+          x = max_parameter_v - HALF + (double) EPS_DOUBLE;
+
+        if (x + HALF > ZERO) {
+          x = (double) ((LONG_INT) (x + HALF));
+        } else {
+          x = (double) ((LONG_INT) (x - HALF));
+        }
+        if (x > parameter_maximum[index_v])
+          x = parameter_maximum[index_v];
+        if (x < parameter_minimum[index_v])
+          x = parameter_minimum[index_v];
+      }
+#if ASA_RESOLUTION
+    }
+    if (xres > EPS_DOUBLE) {
+      if (x < min_parameter_v + xres / TWO)
+        x = min_parameter_v + xres / TWO + (double) EPS_DOUBLE;
+      if (x > max_parameter_v - xres / TWO)
+        x = max_parameter_v - xres / TWO + (double) EPS_DOUBLE;
+
+      if (x > parameter_maximum[index_v])
+        x = parameter_maximum[index_v];
+      if (x < parameter_minimum[index_v])
+        x = parameter_minimum[index_v];
+    }
+#endif /* ASA_RESOLUTION */
+
+    /* save the newly generated value */
+    current_generated_state->parameter[index_v] = x;
+
+    if (OPTIONS->Sequential_Parameters >= 0)
+      break;
+  }
+
+}
+
+/***********************************************************************
+* generate_asa_state
+*       This function generates a single value according to the
+*       ASA generating function and the passed temperature
+***********************************************************************/
+#if HAVE_ANSI
+double
+
+generate_asa_state (double (*user_random_generator) (LONG_INT *),
+                    LONG_INT * seed, double *temp)
+#else
+double
+generate_asa_state (user_random_generator, seed, temp)
+     double (*user_random_generator) ();
+     LONG_INT *seed;
+     double *temp;
+#endif
+{
+  double x, y, z;
+
+  x = (*user_random_generator) (seed);
+  y = x < HALF ? -ONE : ONE;
+  z = y * *temp * (F_POW ((ONE + ONE / *temp), fabs (TWO * x - ONE)) - ONE);
+
+  return (z);
+
+}
+
+/***********************************************************************
+* accept_new_state
+*	This procedure accepts or rejects a newly generated state,
+*	depending on whether the difference between new and old
+*	cost functions passes a statistical test. If accepted,
+*	the current state is updated.
+***********************************************************************/
+#if HAVE_ANSI
+void
+
+accept_new_state (double (*user_random_generator) (LONG_INT *),
+                  LONG_INT * seed,
+                  double *parameter_minimum,
+                  double *parameter_maximum, double *current_cost_temperature,
+#if ASA_SAMPLE
+                  double *current_user_parameter_temp,
+#endif
+                  ALLOC_INT * number_parameters,
+                  LONG_INT * recent_number_acceptances,
+                  LONG_INT * number_accepted,
+                  LONG_INT * index_cost_acceptances,
+                  LONG_INT * number_acceptances_saved,
+                  LONG_INT * recent_number_generated,
+                  LONG_INT * number_generated,
+                  LONG_INT * index_parameter_generations,
+                  STATE * current_generated_state, STATE * last_saved_state,
+#if ASA_SAMPLE
+                  FILE * ptr_asa_out,
+#endif
+                  USER_DEFINES * OPTIONS)
+#else
+void
+
+accept_new_state (user_random_generator,
+                  seed,
+                  parameter_minimum,
+                  parameter_maximum, current_cost_temperature,
+#if ASA_SAMPLE
+                  current_user_parameter_temp,
+#endif
+                  number_parameters,
+                  recent_number_acceptances,
+                  number_accepted,
+                  index_cost_acceptances,
+                  number_acceptances_saved,
+                  recent_number_generated,
+                  number_generated,
+                  index_parameter_generations,
+                  current_generated_state, last_saved_state,
+#if ASA_SAMPLE
+                  ptr_asa_out,
+#endif
+                  OPTIONS)
+     double (*user_random_generator) ();
+     LONG_INT *seed;
+     double *parameter_minimum;
+     double *parameter_maximum;
+     double *current_cost_temperature;
+#if ASA_SAMPLE
+     double *current_user_parameter_temp;
+#endif
+     ALLOC_INT *number_parameters;
+     LONG_INT *recent_number_acceptances;
+     LONG_INT *number_accepted;
+     LONG_INT *index_cost_acceptances;
+     LONG_INT *number_acceptances_saved;
+     LONG_INT *recent_number_generated;
+     LONG_INT *number_generated;
+     LONG_INT *index_parameter_generations;
+     STATE *current_generated_state;
+     STATE *last_saved_state;
+#if ASA_SAMPLE
+     FILE *ptr_asa_out;
+#endif
+     USER_DEFINES *OPTIONS;
+
+#endif
+{
+#if USER_ACCEPTANCE_TEST
+#else
+  double delta_cost;
+#if USER_ACCEPT_ASYMP_EXP
+  double q;
+#endif
+#endif
+  double prob_test, unif_test;
+  double curr_cost_temp;
+  ALLOC_INT index_v;
+#if ASA_SAMPLE
+  LONG_INT active_params;
+  double weight_param_ind, weight_aver, range;
+#endif
+
+  /* update accepted and generated count */
+  ++*number_acceptances_saved;
+  ++*recent_number_generated;
+  ++*number_generated;
+  OPTIONS->N_Generated = *number_generated;
+
+  /* increment the parameter index generation for each parameter */
+  if (OPTIONS->Sequential_Parameters >= 0) {
+    /* ignore parameters with too small a range */
+    if (!PARAMETER_RANGE_TOO_SMALL (OPTIONS->Sequential_Parameters))
+      ++index_parameter_generations[OPTIONS->Sequential_Parameters];
+  } else {
+    VFOR (index_v) {
+      if (!PARAMETER_RANGE_TOO_SMALL (index_v))
+        ++index_parameter_generations[index_v];
+    }
+  }
+
+  /* effective cost function for testing acceptance criteria,
+     calculate the cost difference and divide by the temperature */
+  curr_cost_temp = *current_cost_temperature;
+#if USER_ACCEPTANCE_TEST
+  if (OPTIONS->Cost_Acceptance_Flag == TRUE) {
+    if (OPTIONS->User_Acceptance_Flag == TRUE) {
+      unif_test = ZERO;
+      OPTIONS->User_Acceptance_Flag = FALSE;
+      OPTIONS->Cost_Acceptance_Flag = FALSE;
+    } else {
+      unif_test = ONE;
+      OPTIONS->Cost_Acceptance_Flag = FALSE;
+    }
+  } else {
+    OPTIONS->Acceptance_Test (current_generated_state->cost,
+                              parameter_minimum,
+                              parameter_maximum, *number_parameters, OPTIONS);
+    if (OPTIONS->User_Acceptance_Flag == TRUE) {
+      unif_test = ZERO;
+      OPTIONS->User_Acceptance_Flag = FALSE;
+    } else {
+      unif_test = ONE;
+    }
+  }
+  prob_test = OPTIONS->Prob_Bias;
+#else /* USER_ACCEPTANCE_TEST */
+
+#if USER_COST_SCHEDULE
+  curr_cost_temp =
+    (OPTIONS->Cost_Schedule (*current_cost_temperature, OPTIONS)
+     + (double) EPS_DOUBLE);
+#endif
+  delta_cost = (current_generated_state->cost - last_saved_state->cost)
+    / (curr_cost_temp + (double) EPS_DOUBLE);
+
+#if USER_ACCEPT_ASYMP_EXP
+  q = OPTIONS->Asymp_Exp_Param;
+  if (fabs (ONE - q) < (double) EPS_DOUBLE)
+    prob_test = MIN (ONE, (F_EXP (EXPONENT_CHECK (-delta_cost))));
+  else if ((ONE - (ONE - q) * delta_cost) < (double) EPS_DOUBLE)
+    prob_test = MIN (ONE, (F_EXP (EXPONENT_CHECK (-delta_cost))));
+  else
+    prob_test = MIN (ONE, F_POW ((ONE - (ONE - q) * delta_cost),
+                                 (ONE / (ONE - q))));
+#else /* USER_ACCEPT_ASYMP_EXP */
+
+#if USER_ACCEPT_THRESHOLD       /* USER_ACCEPT_THRESHOLD */
+  prob_test = delta_cost <= 1.0 ? 1.0 : 0.0;
+#else /* Metropolis */
+  prob_test = MIN (ONE, (F_EXP (EXPONENT_CHECK (-delta_cost))));
+#endif /* USER_ACCEPT_THRESHOLD */
+
+#endif /* USER_ACCEPT_ASYMP_EXP */
+
+  unif_test = (*user_random_generator) (seed);
+#endif /* USER_ACCEPTANCE_TEST */
+
+#if ASA_SAMPLE
+  active_params = 0;
+  weight_aver = ZERO;
+  VFOR (index_v) {
+    /* ignore parameters with too small a range */
+    if (PARAMETER_RANGE_TOO_SMALL (index_v))
+      continue;
+    ++active_params;
+    range = parameter_maximum[index_v] - parameter_minimum[index_v];
+    weight_param_ind = TWO * (fabs ((last_saved_state->parameter[index_v]
+                                     -
+                                     current_generated_state->
+                                     parameter[index_v]) / range)
+                              + current_user_parameter_temp[index_v])
+      * F_LOG (ONE + ONE / current_user_parameter_temp[index_v]);
+    weight_aver += weight_param_ind;
+    OPTIONS->Bias_Generated[index_v] = ONE / weight_param_ind;
+  }
+  weight_aver /= (double) active_params;
+  OPTIONS->Average_Weights = weight_aver;
+  if (prob_test >= unif_test) {
+    OPTIONS->Bias_Acceptance = prob_test;
+  } else {
+    OPTIONS->Bias_Acceptance = ONE - prob_test;
+  }
+
+#if ASA_PRINT
+  if (OPTIONS->Limit_Weights < OPTIONS->Average_Weights) {
+    fprintf (ptr_asa_out, ":SAMPLE#\n");
+    if (prob_test >= unif_test) {
+      fprintf (ptr_asa_out,
+#if INT_LONG
+               ":SAMPLE+ %10ld %*.*g %*.*g %*.*g %*.*g\n",
+#else
+               ":SAMPLE+ %10d %*.*g %*.*g %*.*g\n",
+#endif
+               OPTIONS->N_Accepted,
+               G_FIELD, G_PRECISION, current_generated_state->cost,
+               G_FIELD, G_PRECISION, *current_cost_temperature,
+               G_FIELD, G_PRECISION, OPTIONS->Bias_Acceptance,
+               G_FIELD, G_PRECISION, OPTIONS->Average_Weights);
+      VFOR (index_v) {
+        /* ignore parameters with too small a range */
+        if (PARAMETER_RANGE_TOO_SMALL (index_v))
+          continue;
+        range = parameter_maximum[index_v] - parameter_minimum[index_v];
+        fprintf (ptr_asa_out,
+#if INT_ALLOC
+                 ":SAMPLE %11d %*.*g %*.*g %*.*g %*.*g\n",
+#else
+#if INT_LONG
+                 ":SAMPLE %11ld %*.*g %*.*g %*.*g %*.*g\n",
+#else
+                 ":SAMPLE %11d %*.*g %*.*g %*.*g %*.*g\n",
+#endif
+#endif
+                 index_v,
+                 G_FIELD, G_PRECISION,
+                 current_generated_state->parameter[index_v], G_FIELD,
+                 G_PRECISION, current_user_parameter_temp[index_v],
+                 G_FIELD, G_PRECISION, OPTIONS->Bias_Generated[index_v],
+                 G_FIELD, G_PRECISION, range);
+      }
+    } else {
+      fprintf (ptr_asa_out,
+#if INT_LONG
+               ":SAMPLE %11ld %*.*g %*.*g %*.*g %*.*g\n",
+#else
+               ":SAMPLE %11d %*.*g %*.*g %*.*g\n",
+#endif
+               OPTIONS->N_Accepted,
+               G_FIELD, G_PRECISION, last_saved_state->cost,
+               G_FIELD, G_PRECISION, *current_cost_temperature,
+               G_FIELD, G_PRECISION, OPTIONS->Bias_Acceptance,
+               G_FIELD, G_PRECISION, OPTIONS->Average_Weights);
+      VFOR (index_v) {
+        /* ignore parameters with too small a range */
+        if (PARAMETER_RANGE_TOO_SMALL (index_v))
+          continue;
+        range = parameter_maximum[index_v] - parameter_minimum[index_v];
+        fprintf (ptr_asa_out,
+#if INT_ALLOC
+                 ":SAMPLE %11d %*.*g %*.*g %*.*g %*.*g\n",
+#else
+#if INT_LONG
+                 ":SAMPLE %11ld %*.*g %*.*g %*.*g %*.*g\n",
+#else
+                 ":SAMPLE %11d %*.*g %*.*g %*.*g %*.*g\n",
+#endif
+#endif
+                 index_v,
+                 G_FIELD, G_PRECISION,
+                 last_saved_state->parameter[index_v], G_FIELD,
+                 G_PRECISION, current_user_parameter_temp[index_v],
+                 G_FIELD, G_PRECISION, OPTIONS->Bias_Generated[index_v],
+                 G_FIELD, G_PRECISION, range);
+      }
+    }
+  }
+#endif
+#endif /* ASA_SAMPLE */
+
+  /* accept/reject the new state */
+  if (prob_test >= unif_test) {
+    /* copy current state to the last saved state */
+
+    last_saved_state->cost = current_generated_state->cost;
+    VFOR (index_v) {
+      /* ignore parameters with too small a range */
+      if (PARAMETER_RANGE_TOO_SMALL (index_v))
+        continue;
+      last_saved_state->parameter[index_v] =
+        current_generated_state->parameter[index_v];
+    }
+
+    /* update acceptance counts */
+    ++*recent_number_acceptances;
+    ++*number_accepted;
+    ++*index_cost_acceptances;
+    *number_acceptances_saved = *number_accepted;
+    OPTIONS->N_Accepted = *number_accepted;
+  }
+}
+
+/***********************************************************************
+* reanneal
+*	Readjust temperatures of generating and acceptance functions
+***********************************************************************/
+#if HAVE_ANSI
+void
+
+reanneal (double *parameter_minimum,
+          double *parameter_maximum,
+          double *tangents,
+          double *maximum_tangent,
+          double *current_cost_temperature,
+          double *initial_cost_temperature,
+          double *temperature_scale_cost,
+          double *current_user_parameter_temp,
+          double *initial_user_parameter_temp,
+          double *temperature_scale_parameters,
+          ALLOC_INT * number_parameters,
+          int *parameter_type,
+          LONG_INT * index_cost_acceptances,
+          LONG_INT * index_parameter_generations,
+          STATE * last_saved_state,
+          STATE * best_generated_state, USER_DEFINES * OPTIONS)
+#else
+void
+
+reanneal (parameter_minimum,
+          parameter_maximum,
+          tangents,
+          maximum_tangent,
+          current_cost_temperature,
+          initial_cost_temperature,
+          temperature_scale_cost,
+          current_user_parameter_temp,
+          initial_user_parameter_temp,
+          temperature_scale_parameters,
+          number_parameters,
+          parameter_type,
+          index_cost_acceptances,
+          index_parameter_generations,
+          last_saved_state, best_generated_state, OPTIONS)
+     double *parameter_minimum;
+     double *parameter_maximum;
+     double *tangents;
+     double *maximum_tangent;
+     double *current_cost_temperature;
+     double *initial_cost_temperature;
+     double *temperature_scale_cost;
+     double *current_user_parameter_temp;
+     double *initial_user_parameter_temp;
+     double *temperature_scale_parameters;
+     ALLOC_INT *number_parameters;
+     int *parameter_type;
+     LONG_INT *index_cost_acceptances;
+     LONG_INT *index_parameter_generations;
+     STATE *last_saved_state;
+     STATE *best_generated_state;
+     USER_DEFINES *OPTIONS;
+#endif
+{
+  ALLOC_INT index_v;
+  int cost_test;
+  double tmp_var_db3;
+  double new_temperature;
+  double log_new_temperature_ratio;
+  double log_init_cur_temp_ratio;
+  double temperature_rescale_power;
+  double cost_best, cost_last;
+  double tmp_dbl, tmp_dbl1;
+
+  double xnumber_parameters[1];
+
+  cost_test = cost_function_test (last_saved_state->cost,
+                                  last_saved_state->parameter,
+                                  parameter_minimum,
+                                  parameter_maximum, number_parameters,
+                                  xnumber_parameters);
+
+  if (OPTIONS->Reanneal_Parameters == TRUE) {
+    VFOR (index_v) {
+      if (NO_REANNEAL (index_v))
+        continue;
+
+      /* use the temp double to prevent overflow */
+      tmp_dbl = (double) index_parameter_generations[index_v];
+
+      /* skip parameters with too small range or integer parameters */
+      if (OPTIONS->Include_Integer_Parameters == TRUE) {
+        if (PARAMETER_RANGE_TOO_SMALL (index_v))
+          continue;
+      } else {
+        if (PARAMETER_RANGE_TOO_SMALL (index_v) ||
+            INTEGER_PARAMETER (index_v))
+          continue;
+      }
+
+      /* ignore parameters with too small tangents */
+      if (fabs (tangents[index_v]) < (double) EPS_DOUBLE)
+        continue;
+
+      /* reset the index of parameter generations appropriately */
+#if USER_REANNEAL_PARAMETERS
+      new_temperature =
+        fabs (OPTIONS->
+              Reanneal_Params_Function (current_user_parameter_temp
+                                        [index_v], tangents[index_v],
+                                        *maximum_tangent, OPTIONS));
+#else
+      new_temperature =
+        fabs (FUNCTION_REANNEAL_PARAMS
+              (current_user_parameter_temp[index_v], tangents[index_v],
+               *maximum_tangent));
+#endif
+      if (new_temperature < initial_user_parameter_temp[index_v]) {
+        log_init_cur_temp_ratio =
+          fabs (F_LOG (((double) EPS_DOUBLE
+                        + initial_user_parameter_temp[index_v])
+                       / ((double) EPS_DOUBLE + new_temperature)));
+        tmp_dbl = (double) EPS_DOUBLE
+          + F_POW (log_init_cur_temp_ratio
+                   / temperature_scale_parameters[index_v],
+                   *xnumber_parameters
+#if QUENCH_PARAMETERS
+                   / OPTIONS->User_Quench_Param_Scale[index_v]);
+#else
+          );
+#endif
+      } else {
+        tmp_dbl = ONE;
+      }
+
+      /* Reset index_parameter_generations if index reset too large,
+         and also reset the initial_user_parameter_temp, to achieve
+         the same new temperature. */
+      while (tmp_dbl > ((double) MAXIMUM_REANNEAL_INDEX)) {
+        log_new_temperature_ratio =
+          -temperature_scale_parameters[index_v] * F_POW (tmp_dbl,
+#if QUENCH_PARAMETERS
+                                                          OPTIONS->
+                                                          User_Quench_Param_Scale
+                                                          [index_v]
+#else
+                                                          ONE
+#endif
+                                                          /
+                                                          *xnumber_parameters);
+        log_new_temperature_ratio =
+          EXPONENT_CHECK (log_new_temperature_ratio);
+        new_temperature =
+          initial_user_parameter_temp[index_v] *
+          F_EXP (log_new_temperature_ratio);
+        tmp_dbl /= (double) REANNEAL_SCALE;
+        temperature_rescale_power = ONE / F_POW ((double) REANNEAL_SCALE,
+#if QUENCH_PARAMETERS
+                                                 OPTIONS->
+                                                 User_Quench_Param_Scale
+                                                 [index_v]
+#else
+                                                 ONE
+#endif
+                                                 / *xnumber_parameters);
+        initial_user_parameter_temp[index_v] =
+          new_temperature * F_POW (initial_user_parameter_temp[index_v] /
+                                   new_temperature,
+                                   temperature_rescale_power);
+      }
+      /* restore from temporary double */
+      index_parameter_generations[index_v] = (LONG_INT) tmp_dbl;
+    }
+  }
+
+  if (OPTIONS->Reanneal_Cost == 0) {
+    ;
+  } else if (OPTIONS->Reanneal_Cost < -1) {
+    *index_cost_acceptances = 1;
+  } else {
+    /* reanneal : Reset the current cost temp and rescale the
+       index of cost acceptances. */
+
+    cost_best = best_generated_state->cost;
+    cost_last = last_saved_state->cost;
+#if USER_REANNEAL_COST
+    cost_test = OPTIONS->Reanneal_Cost_Function (&cost_best,
+                                                 &cost_last,
+                                                 initial_cost_temperature,
+                                                 current_cost_temperature,
+                                                 OPTIONS);
+    tmp_dbl1 = *current_cost_temperature;
+#else
+    cost_test = TRUE;
+    if (OPTIONS->Reanneal_Cost == 1) {
+      /* (re)set the initial cost_temperature */
+      tmp_dbl = MAX (fabs (cost_last), fabs (cost_best));
+      tmp_dbl = MAX (tmp_dbl, fabs (cost_best - cost_last));
+      tmp_dbl = MAX ((double) EPS_DOUBLE, tmp_dbl);
+      *initial_cost_temperature = MIN (*initial_cost_temperature, tmp_dbl);
+    }
+
+    tmp_dbl = (double) *index_cost_acceptances;
+
+    tmp_dbl1 = MAX (fabs (cost_last - cost_best), *current_cost_temperature);
+    tmp_dbl1 = MAX ((double) EPS_DOUBLE, tmp_dbl1);
+    tmp_dbl1 = MIN (tmp_dbl1, *initial_cost_temperature);
+#endif /* USER_REANNEAL_COST */
+    if (cost_test == TRUE && (*current_cost_temperature > tmp_dbl1)) {
+      tmp_var_db3 =
+        fabs (F_LOG (((double) EPS_DOUBLE + *initial_cost_temperature) /
+                     (tmp_dbl1)));
+      tmp_dbl = (double) EPS_DOUBLE + F_POW (tmp_var_db3
+                                             / *temperature_scale_cost,
+                                             *xnumber_parameters
+#if QUENCH_COST
+                                             /
+                                             OPTIONS->
+                                             User_Quench_Cost_Scale[0]);
+#else
+        );
+#endif
+    } else {
+      log_init_cur_temp_ratio =
+        fabs (F_LOG (((double) EPS_DOUBLE + *initial_cost_temperature) /
+                     ((double) EPS_DOUBLE + *current_cost_temperature)));
+      tmp_dbl = (double) EPS_DOUBLE
+        + F_POW (log_init_cur_temp_ratio
+                 / *temperature_scale_cost, *xnumber_parameters
+#if QUENCH_COST
+                 / OPTIONS->User_Quench_Cost_Scale[0]
+#else
+#endif
+        );
+    }
+
+    /* reset index_cost_temperature if index reset too large */
+    while (tmp_dbl > ((double) MAXIMUM_REANNEAL_INDEX)) {
+      log_new_temperature_ratio = -*temperature_scale_cost * F_POW (tmp_dbl,
+#if QUENCH_COST
+                                                                    OPTIONS->
+                                                                    User_Quench_Cost_Scale
+                                                                    [0]
+#else
+                                                                    ONE
+#endif
+                                                                    /
+                                                                    *xnumber_parameters);
+      log_new_temperature_ratio = EXPONENT_CHECK (log_new_temperature_ratio);
+      new_temperature =
+        *initial_cost_temperature * F_EXP (log_new_temperature_ratio);
+      tmp_dbl /= (double) REANNEAL_SCALE;
+      temperature_rescale_power = ONE / F_POW ((double) REANNEAL_SCALE,
+#if QUENCH_COST
+                                               OPTIONS->
+                                               User_Quench_Cost_Scale[0]
+#else
+                                               ONE
+#endif
+                                               / *xnumber_parameters);
+      *initial_cost_temperature =
+        new_temperature * F_POW (*initial_cost_temperature /
+                                 new_temperature, temperature_rescale_power);
+    }
+    *index_cost_acceptances = (LONG_INT) tmp_dbl;
+#if USER_ACCEPTANCE_TEST
+    OPTIONS->Cost_Temp_Init = *initial_cost_temperature;
+#endif
+  }
+}
+
+/***********************************************************************
+* cost_derivatives
+*	This procedure calculates the derivatives of the cost function
+*	with respect to its parameters.  The first derivatives are
+*	used as a sensitivity measure for reannealing.  The second
+*	derivatives are calculated only if *curvature_flag=TRUE;
+*	these are a measure of the covariance of the fit when a
+*	minimum is found.
+***********************************************************************/
+  /* Calculate the numerical derivatives of the best
+     generated state found so far */
+
+  /* In this implementation of ASA, no checks are made for
+   *valid_state_generated_flag=FALSE for differential neighbors
+   to the current best state. */
+
+  /* Assuming no information is given about the metric of the parameter
+     space, use simple Cartesian space to calculate curvatures. */
+
+#if HAVE_ANSI
+void
+cost_derivatives (double (*user_cost_function)
+
+                   
+                  (double *, double *, double *, double *, double *,
+                   ALLOC_INT *, int *, int *, int *, USER_DEFINES *),
+                  double *parameter_minimum, double *parameter_maximum,
+                  double *tangents, double *curvature,
+                  double *maximum_tangent, ALLOC_INT * number_parameters,
+                  int *parameter_type, int *exit_status,
+                  int *curvature_flag, int *valid_state_generated_flag,
+                  LONG_INT * number_invalid_generated_states,
+                  STATE * current_generated_state,
+                  STATE * best_generated_state, FILE * ptr_asa_out,
+                  USER_DEFINES * OPTIONS)
+#else
+void
+
+cost_derivatives (user_cost_function,
+                  parameter_minimum,
+                  parameter_maximum,
+                  tangents,
+                  curvature,
+                  maximum_tangent,
+                  number_parameters,
+                  parameter_type,
+                  exit_status,
+                  curvature_flag,
+                  valid_state_generated_flag,
+                  number_invalid_generated_states,
+                  current_generated_state,
+                  best_generated_state, ptr_asa_out, OPTIONS)
+     double (*user_cost_function) ();
+     double *parameter_minimum;
+     double *parameter_maximum;
+     double *tangents;
+     double *curvature;
+     double *maximum_tangent;
+     ALLOC_INT *number_parameters;
+     int *parameter_type;
+     int *exit_status;
+     int *curvature_flag;
+     int *valid_state_generated_flag;
+     LONG_INT *number_invalid_generated_states;
+     STATE *current_generated_state;
+     STATE *best_generated_state;
+     FILE *ptr_asa_out;
+     USER_DEFINES *OPTIONS;
+#endif
+{
+  ALLOC_INT index_v, index_vv, index_v_vv, index_vv_v;
+  LONG_INT saved_num_invalid_gen_states;
+#if ASA_PRINT
+  LONG_INT tmp_saved;
+#endif
+  double parameter_v, parameter_vv, parameter_v_offset, parameter_vv_offset;
+  double recent_best_cost;
+  double new_cost_state_1, new_cost_state_2, new_cost_state_3;
+  double delta_parameter_v, delta_parameter_vv;
+  int immediate_flag;
+  double xnumber_parameters[1];
+
+  if (OPTIONS->Curvature_0 == TRUE)
+    *curvature_flag = FALSE;
+  if (OPTIONS->Curvature_0 == -1)
+    *curvature_flag = TRUE;
+
+  /* save Immediate_Exit flag */
+  immediate_flag = OPTIONS->Immediate_Exit;
+
+  /* save the best cost */
+  recent_best_cost = best_generated_state->cost;
+
+  /* copy the best state into the current state */
+  VFOR (index_v) {
+    /* ignore parameters with too small ranges */
+    if (PARAMETER_RANGE_TOO_SMALL (index_v))
+      continue;
+    current_generated_state->parameter[index_v] =
+      best_generated_state->parameter[index_v];
+  }
+
+  saved_num_invalid_gen_states = (*number_invalid_generated_states);
+
+  /* set parameters (& possibly constraints) to best state */
+  *valid_state_generated_flag = TRUE;
+#if USER_ACCEPTANCE_TEST
+  OPTIONS->User_Acceptance_Flag = TRUE;
+  OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+  current_generated_state->cost =
+    user_cost_function (current_generated_state->parameter,
+                        parameter_minimum,
+                        parameter_maximum,
+                        tangents,
+                        curvature,
+                        number_parameters,
+                        parameter_type,
+                        valid_state_generated_flag, exit_status, OPTIONS);
+  if (cost_function_test (current_generated_state->cost,
+                          current_generated_state->parameter,
+                          parameter_minimum,
+                          parameter_maximum, number_parameters,
+                          xnumber_parameters) == 0) {
+    *exit_status = INVALID_COST_FUNCTION_DERIV;
+    return;
+  }
+  if (*valid_state_generated_flag == FALSE)
+    ++(*number_invalid_generated_states);
+
+  if (OPTIONS->User_Tangents == TRUE) {
+    *valid_state_generated_flag = FALSE;
+#if USER_ACCEPTANCE_TEST
+    OPTIONS->User_Acceptance_Flag = TRUE;
+    OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+    current_generated_state->cost =
+      user_cost_function (current_generated_state->parameter,
+                          parameter_minimum,
+                          parameter_maximum,
+                          tangents,
+                          curvature,
+                          number_parameters,
+                          parameter_type,
+                          valid_state_generated_flag, exit_status, OPTIONS);
+    if (cost_function_test (current_generated_state->cost,
+                            current_generated_state->parameter,
+                            parameter_minimum,
+                            parameter_maximum, number_parameters,
+                            xnumber_parameters) == 0) {
+      *exit_status = INVALID_COST_FUNCTION_DERIV;
+      return;
+    }
+    if (*valid_state_generated_flag == FALSE)
+      ++(*number_invalid_generated_states);
+  } else {
+    /* calculate tangents */
+    VFOR (index_v) {
+      if (NO_REANNEAL (index_v)) {
+        tangents[index_v] = ZERO;
+        continue;
+      }
+      /* skip parameters with too small range or integer parameters */
+      if (OPTIONS->Include_Integer_Parameters == TRUE) {
+        if (PARAMETER_RANGE_TOO_SMALL (index_v)) {
+          tangents[index_v] = ZERO;
+          continue;
+        }
+      } else {
+        if (PARAMETER_RANGE_TOO_SMALL (index_v) ||
+            INTEGER_PARAMETER (index_v)) {
+          tangents[index_v] = ZERO;
+          continue;
+        }
+      }
+
+      /* save the v_th parameter and delta_parameter */
+      parameter_v = best_generated_state->parameter[index_v];
+#if DELTA_PARAMETERS
+      delta_parameter_v = OPTIONS->User_Delta_Parameter[index_v];
+#else
+      delta_parameter_v = OPTIONS->Delta_X;
+#endif
+
+      parameter_v_offset = (ONE + delta_parameter_v) * parameter_v;
+      if (parameter_v_offset > parameter_maximum[index_v] ||
+          parameter_v_offset < parameter_minimum[index_v]) {
+        delta_parameter_v = -delta_parameter_v;
+        parameter_v_offset = (ONE + delta_parameter_v) * parameter_v;
+      }
+
+      /* generate the first sample point */
+      current_generated_state->parameter[index_v] = parameter_v_offset;
+      *valid_state_generated_flag = TRUE;
+#if USER_ACCEPTANCE_TEST
+      OPTIONS->User_Acceptance_Flag = TRUE;
+      OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+      current_generated_state->cost =
+        user_cost_function (current_generated_state->parameter,
+                            parameter_minimum,
+                            parameter_maximum,
+                            tangents,
+                            curvature,
+                            number_parameters,
+                            parameter_type,
+                            valid_state_generated_flag, exit_status, OPTIONS);
+      if (cost_function_test
+          (current_generated_state->cost,
+           current_generated_state->parameter, parameter_minimum,
+           parameter_maximum, number_parameters, xnumber_parameters) == 0) {
+        *exit_status = INVALID_COST_FUNCTION_DERIV;
+        return;
+      }
+      if (*valid_state_generated_flag == FALSE)
+        ++(*number_invalid_generated_states);
+      new_cost_state_1 = current_generated_state->cost;
+
+      /* restore the parameter state */
+      current_generated_state->parameter[index_v] = parameter_v;
+
+      /* calculate the numerical derivative */
+      tangents[index_v] = (new_cost_state_1 - recent_best_cost)
+        / (delta_parameter_v * parameter_v + (double) EPS_DOUBLE);
+
+    }
+  }
+
+  /* find the maximum |tangent| from all tangents */
+  *maximum_tangent = 0;
+  VFOR (index_v) {
+    if (NO_REANNEAL (index_v))
+      continue;
+
+    /* ignore too small ranges and integer parameters types */
+    if (OPTIONS->Include_Integer_Parameters == TRUE) {
+      if (PARAMETER_RANGE_TOO_SMALL (index_v))
+        continue;
+    } else {
+      if (PARAMETER_RANGE_TOO_SMALL (index_v)
+          || INTEGER_PARAMETER (index_v))
+        continue;
+    }
+
+    /* find the maximum |tangent| (from all tangents) */
+    if (fabs (tangents[index_v]) > *maximum_tangent) {
+      *maximum_tangent = fabs (tangents[index_v]);
+    }
+  }
+
+  if (*curvature_flag == TRUE || *curvature_flag == -1) {
+    /* calculate diagonal curvatures */
+    VFOR (index_v) {
+      if (NO_REANNEAL (index_v)) {
+        index_v_vv = ROW_COL_INDEX (index_v, index_v);
+        curvature[index_v_vv] = ZERO;
+        continue;
+      }
+      /* skip parameters with too small range or integer parameters */
+      if (OPTIONS->Include_Integer_Parameters == TRUE) {
+        if (PARAMETER_RANGE_TOO_SMALL (index_v)) {
+          index_v_vv = ROW_COL_INDEX (index_v, index_v);
+          curvature[index_v_vv] = ZERO;
+          continue;
+        }
+      } else {
+        if (PARAMETER_RANGE_TOO_SMALL (index_v) ||
+            INTEGER_PARAMETER (index_v)) {
+          index_v_vv = ROW_COL_INDEX (index_v, index_v);
+          curvature[index_v_vv] = ZERO;
+          continue;
+        }
+      }
+
+      /* save the v_th parameter and delta_parameter */
+      parameter_v = best_generated_state->parameter[index_v];
+#if DELTA_PARAMETERS
+      delta_parameter_v = OPTIONS->User_Delta_Parameter[index_v];
+#else
+      delta_parameter_v = OPTIONS->Delta_X;
+#endif
+
+      if (parameter_v + delta_parameter_v * fabs (parameter_v)
+          > parameter_maximum[index_v]) {
+        /* generate the first sample point */
+        current_generated_state->parameter[index_v] =
+          parameter_v - TWO * delta_parameter_v * fabs (parameter_v);
+        *valid_state_generated_flag = TRUE;
+#if USER_ACCEPTANCE_TEST
+        OPTIONS->User_Acceptance_Flag = TRUE;
+        OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+        current_generated_state->cost =
+          user_cost_function (current_generated_state->parameter,
+                              parameter_minimum,
+                              parameter_maximum,
+                              tangents,
+                              curvature,
+                              number_parameters,
+                              parameter_type,
+                              valid_state_generated_flag,
+                              exit_status, OPTIONS);
+        if (cost_function_test (current_generated_state->cost,
+                                current_generated_state->parameter,
+                                parameter_minimum,
+                                parameter_maximum, number_parameters,
+                                xnumber_parameters) == 0) {
+          *exit_status = INVALID_COST_FUNCTION_DERIV;
+          return;
+        }
+        if (*valid_state_generated_flag == FALSE)
+          ++(*number_invalid_generated_states);
+        new_cost_state_1 = current_generated_state->cost;
+
+        /* generate the second sample point */
+        current_generated_state->parameter[index_v] =
+          parameter_v - delta_parameter_v * fabs (parameter_v);
+
+        *valid_state_generated_flag = TRUE;
+#if USER_ACCEPTANCE_TEST
+        OPTIONS->User_Acceptance_Flag = TRUE;
+        OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+        current_generated_state->cost =
+          user_cost_function (current_generated_state->parameter,
+                              parameter_minimum,
+                              parameter_maximum,
+                              tangents,
+                              curvature,
+                              number_parameters,
+                              parameter_type,
+                              valid_state_generated_flag,
+                              exit_status, OPTIONS);
+        if (cost_function_test (current_generated_state->cost,
+                                current_generated_state->parameter,
+                                parameter_minimum,
+                                parameter_maximum, number_parameters,
+                                xnumber_parameters) == 0) {
+          *exit_status = INVALID_COST_FUNCTION_DERIV;
+          return;
+        }
+        if (*valid_state_generated_flag == FALSE)
+          ++(*number_invalid_generated_states);
+        new_cost_state_2 = current_generated_state->cost;
+
+        /* restore the parameter state */
+        current_generated_state->parameter[index_v] = parameter_v;
+
+        /* index_v_vv: row index_v, column index_v */
+        index_v_vv = ROW_COL_INDEX (index_v, index_v);
+
+        /* calculate and store the curvature */
+        curvature[index_v_vv] =
+          (recent_best_cost - TWO * new_cost_state_2
+           + new_cost_state_1) / (delta_parameter_v * delta_parameter_v
+                                  * parameter_v * parameter_v +
+                                  (double) EPS_DOUBLE);
+      } else if (parameter_v - delta_parameter_v * fabs (parameter_v)
+                 < parameter_minimum[index_v]) {
+        /* generate the first sample point */
+        current_generated_state->parameter[index_v] =
+          parameter_v + TWO * delta_parameter_v * fabs (parameter_v);
+        *valid_state_generated_flag = TRUE;
+#if USER_ACCEPTANCE_TEST
+        OPTIONS->User_Acceptance_Flag = TRUE;
+        OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+        current_generated_state->cost =
+          user_cost_function (current_generated_state->parameter,
+                              parameter_minimum,
+                              parameter_maximum,
+                              tangents,
+                              curvature,
+                              number_parameters,
+                              parameter_type,
+                              valid_state_generated_flag,
+                              exit_status, OPTIONS);
+        if (cost_function_test (current_generated_state->cost,
+                                current_generated_state->parameter,
+                                parameter_minimum,
+                                parameter_maximum, number_parameters,
+                                xnumber_parameters) == 0) {
+          *exit_status = INVALID_COST_FUNCTION_DERIV;
+          return;
+        }
+        if (*valid_state_generated_flag == FALSE)
+          ++(*number_invalid_generated_states);
+        new_cost_state_1 = current_generated_state->cost;
+
+        /* generate the second sample point */
+        current_generated_state->parameter[index_v] =
+          parameter_v + delta_parameter_v * fabs (parameter_v);
+
+        *valid_state_generated_flag = TRUE;
+#if USER_ACCEPTANCE_TEST
+        OPTIONS->User_Acceptance_Flag = TRUE;
+        OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+        current_generated_state->cost =
+          user_cost_function (current_generated_state->parameter,
+                              parameter_minimum,
+                              parameter_maximum,
+                              tangents,
+                              curvature,
+                              number_parameters,
+                              parameter_type,
+                              valid_state_generated_flag,
+                              exit_status, OPTIONS);
+        if (cost_function_test (current_generated_state->cost,
+                                current_generated_state->parameter,
+                                parameter_minimum,
+                                parameter_maximum, number_parameters,
+                                xnumber_parameters) == 0) {
+          *exit_status = INVALID_COST_FUNCTION_DERIV;
+          return;
+        }
+        if (*valid_state_generated_flag == FALSE)
+          ++(*number_invalid_generated_states);
+        new_cost_state_2 = current_generated_state->cost;
+
+        /* restore the parameter state */
+        current_generated_state->parameter[index_v] = parameter_v;
+
+        /* index_v_vv: row index_v, column index_v */
+        index_v_vv = ROW_COL_INDEX (index_v, index_v);
+
+        /* calculate and store the curvature */
+        curvature[index_v_vv] =
+          (recent_best_cost - TWO * new_cost_state_2
+           + new_cost_state_1) / (delta_parameter_v * delta_parameter_v
+                                  * parameter_v * parameter_v +
+                                  (double) EPS_DOUBLE);
+      } else {
+        /* generate the first sample point */
+        parameter_v_offset = (ONE + delta_parameter_v) * parameter_v;
+        current_generated_state->parameter[index_v] = parameter_v_offset;
+        *valid_state_generated_flag = TRUE;
+#if USER_ACCEPTANCE_TEST
+        OPTIONS->User_Acceptance_Flag = TRUE;
+        OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+        current_generated_state->cost =
+          user_cost_function (current_generated_state->parameter,
+                              parameter_minimum,
+                              parameter_maximum,
+                              tangents,
+                              curvature,
+                              number_parameters,
+                              parameter_type,
+                              valid_state_generated_flag,
+                              exit_status, OPTIONS);
+        if (cost_function_test (current_generated_state->cost,
+                                current_generated_state->parameter,
+                                parameter_minimum,
+                                parameter_maximum, number_parameters,
+                                xnumber_parameters) == 0) {
+          *exit_status = INVALID_COST_FUNCTION_DERIV;
+          return;
+        }
+        if (*valid_state_generated_flag == FALSE)
+          ++(*number_invalid_generated_states);
+        new_cost_state_1 = current_generated_state->cost;
+
+        /* generate the second sample point */
+        current_generated_state->parameter[index_v] =
+          (ONE - delta_parameter_v) * parameter_v;
+
+        *valid_state_generated_flag = TRUE;
+#if USER_ACCEPTANCE_TEST
+        OPTIONS->User_Acceptance_Flag = TRUE;
+        OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+        current_generated_state->cost =
+          user_cost_function (current_generated_state->parameter,
+                              parameter_minimum,
+                              parameter_maximum,
+                              tangents,
+                              curvature,
+                              number_parameters,
+                              parameter_type,
+                              valid_state_generated_flag,
+                              exit_status, OPTIONS);
+        if (cost_function_test (current_generated_state->cost,
+                                current_generated_state->parameter,
+                                parameter_minimum,
+                                parameter_maximum, number_parameters,
+                                xnumber_parameters) == 0) {
+          *exit_status = INVALID_COST_FUNCTION_DERIV;
+          return;
+        }
+        if (*valid_state_generated_flag == FALSE)
+          ++(*number_invalid_generated_states);
+        new_cost_state_2 = current_generated_state->cost;
+
+        /* restore the parameter state */
+        current_generated_state->parameter[index_v] = parameter_v;
+
+        /* index_v_vv: row index_v, column index_v */
+        index_v_vv = ROW_COL_INDEX (index_v, index_v);
+
+        /* calculate and store the curvature */
+        curvature[index_v_vv] =
+          (new_cost_state_2 - TWO * recent_best_cost
+           + new_cost_state_1) / (delta_parameter_v * delta_parameter_v
+                                  * parameter_v * parameter_v +
+                                  (double) EPS_DOUBLE);
+      }
+    }
+
+    /* calculate off-diagonal curvatures */
+    VFOR (index_v) {
+      /* save the v_th parameter and delta_x */
+      parameter_v = current_generated_state->parameter[index_v];
+#if DELTA_PARAMETERS
+      delta_parameter_v = OPTIONS->User_Delta_Parameter[index_v];
+#else
+      delta_parameter_v = OPTIONS->Delta_X;
+#endif
+
+      VFOR (index_vv) {
+        /* index_v_vv: row index_v, column index_vv */
+        index_v_vv = ROW_COL_INDEX (index_v, index_vv);
+        index_vv_v = ROW_COL_INDEX (index_vv, index_v);
+
+        if (NO_REANNEAL (index_vv) || NO_REANNEAL (index_v)) {
+          curvature[index_vv_v] = curvature[index_v_vv] = ZERO;
+          continue;
+        }
+
+        /* calculate only the upper diagonal */
+        if (index_v <= index_vv)
+          continue;
+
+        /* skip parms with too small range or integer parameters */
+        if (OPTIONS->Include_Integer_Parameters == TRUE) {
+          if (PARAMETER_RANGE_TOO_SMALL (index_v) ||
+              PARAMETER_RANGE_TOO_SMALL (index_vv)) {
+            curvature[index_vv_v] = curvature[index_v_vv] = ZERO;
+            continue;
+          }
+        } else {
+          if (INTEGER_PARAMETER (index_v) ||
+              INTEGER_PARAMETER (index_vv) ||
+              PARAMETER_RANGE_TOO_SMALL (index_v) ||
+              PARAMETER_RANGE_TOO_SMALL (index_vv)) {
+            curvature[index_vv_v] = curvature[index_v_vv] = ZERO;
+            continue;
+          }
+        }
+        /* save the vv_th parameter and delta_parameter */
+        parameter_vv = current_generated_state->parameter[index_vv];
+#if DELTA_PARAMETERS
+        delta_parameter_vv = OPTIONS->User_Delta_Parameter[index_vv];
+#else
+        delta_parameter_vv = OPTIONS->Delta_X;
+#endif
+
+        /* generate first sample point */
+        parameter_v_offset = current_generated_state->parameter[index_v] =
+          (ONE + delta_parameter_v) * parameter_v;
+        parameter_vv_offset = current_generated_state->parameter[index_vv] =
+          (ONE + delta_parameter_vv) * parameter_vv;
+        if (parameter_v_offset > parameter_maximum[index_v] ||
+            parameter_v_offset < parameter_minimum[index_v]) {
+          delta_parameter_v = -delta_parameter_v;
+          current_generated_state->parameter[index_v] =
+            (ONE + delta_parameter_v) * parameter_v;
+        }
+        if (parameter_vv_offset > parameter_maximum[index_vv] ||
+            parameter_vv_offset < parameter_minimum[index_vv]) {
+          delta_parameter_vv = -delta_parameter_vv;
+          current_generated_state->parameter[index_vv] =
+            (ONE + delta_parameter_vv) * parameter_vv;
+        }
+
+        *valid_state_generated_flag = TRUE;
+#if USER_ACCEPTANCE_TEST
+        OPTIONS->User_Acceptance_Flag = TRUE;
+        OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+        current_generated_state->cost =
+          user_cost_function (current_generated_state->parameter,
+                              parameter_minimum,
+                              parameter_maximum,
+                              tangents,
+                              curvature,
+                              number_parameters,
+                              parameter_type,
+                              valid_state_generated_flag,
+                              exit_status, OPTIONS);
+        if (cost_function_test (current_generated_state->cost,
+                                current_generated_state->parameter,
+                                parameter_minimum,
+                                parameter_maximum, number_parameters,
+                                xnumber_parameters) == 0) {
+          *exit_status = INVALID_COST_FUNCTION_DERIV;
+          return;
+        }
+        if (*valid_state_generated_flag == FALSE)
+          ++(*number_invalid_generated_states);
+        new_cost_state_1 = current_generated_state->cost;
+
+        /* restore the v_th parameter */
+        current_generated_state->parameter[index_v] = parameter_v;
+
+        /* generate second sample point */
+        *valid_state_generated_flag = TRUE;
+#if USER_ACCEPTANCE_TEST
+        OPTIONS->User_Acceptance_Flag = TRUE;
+        OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+        current_generated_state->cost =
+          user_cost_function (current_generated_state->parameter,
+                              parameter_minimum,
+                              parameter_maximum,
+                              tangents,
+                              curvature,
+                              number_parameters,
+                              parameter_type,
+                              valid_state_generated_flag,
+                              exit_status, OPTIONS);
+        if (cost_function_test (current_generated_state->cost,
+                                current_generated_state->parameter,
+                                parameter_minimum,
+                                parameter_maximum, number_parameters,
+                                xnumber_parameters) == 0) {
+          *exit_status = INVALID_COST_FUNCTION_DERIV;
+          return;
+        }
+        if (*valid_state_generated_flag == FALSE)
+          ++(*number_invalid_generated_states);
+        new_cost_state_2 = current_generated_state->cost;
+
+        /* restore the vv_th parameter */
+        current_generated_state->parameter[index_vv] = parameter_vv;
+
+        /* generate third sample point */
+        current_generated_state->parameter[index_v] =
+          (ONE + delta_parameter_v) * parameter_v;
+        *valid_state_generated_flag = TRUE;
+#if USER_ACCEPTANCE_TEST
+        OPTIONS->User_Acceptance_Flag = TRUE;
+        OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+        current_generated_state->cost =
+          user_cost_function (current_generated_state->parameter,
+                              parameter_minimum,
+                              parameter_maximum,
+                              tangents,
+                              curvature,
+                              number_parameters,
+                              parameter_type,
+                              valid_state_generated_flag,
+                              exit_status, OPTIONS);
+        if (cost_function_test (current_generated_state->cost,
+                                current_generated_state->parameter,
+                                parameter_minimum,
+                                parameter_maximum, number_parameters,
+                                xnumber_parameters) == 0) {
+          *exit_status = INVALID_COST_FUNCTION_DERIV;
+          return;
+        }
+        if (*valid_state_generated_flag == FALSE)
+          ++(*number_invalid_generated_states);
+        new_cost_state_3 = current_generated_state->cost;
+
+        /* restore the v_th parameter */
+        current_generated_state->parameter[index_v] = parameter_v;
+
+        /* calculate and store the curvature */
+        curvature[index_vv_v] = curvature[index_v_vv] =
+          (new_cost_state_1 - new_cost_state_2
+           - new_cost_state_3 + recent_best_cost)
+          / (delta_parameter_v * delta_parameter_vv
+             * parameter_v * parameter_vv + (double) EPS_DOUBLE);
+      }
+    }
+  }
+
+  /* restore Immediate_Exit flag */
+  OPTIONS->Immediate_Exit = immediate_flag;
+
+  /* restore the best cost function value */
+  current_generated_state->cost = recent_best_cost;
+#if ASA_PRINT
+  tmp_saved = *number_invalid_generated_states - saved_num_invalid_gen_states;
+  if (tmp_saved > 0)
+#if INT_LONG
+    fprintf (ptr_asa_out,
+             "Generated %ld invalid states when calculating the derivatives\n",
+             tmp_saved);
+#else
+    fprintf (ptr_asa_out,
+             "Generated %d invalid states when calculating the derivatives\n",
+             tmp_saved);
+#endif
+#endif /* ASA_PRINT */
+  *number_invalid_generated_states = saved_num_invalid_gen_states;
+#if USER_ACCEPTANCE_TEST
+  OPTIONS->User_Acceptance_Flag = TRUE;
+  OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+}
+
+/***********************************************************************
+* asa_test_asa_options
+*       Tests user's selected options
+***********************************************************************/
+#if HAVE_ANSI
+int
+
+asa_test_asa_options (LONG_INT * seed,
+                      double *parameter_initial_final,
+                      double *parameter_minimum,
+                      double *parameter_maximum,
+                      double *tangents,
+                      double *curvature,
+                      ALLOC_INT * number_parameters,
+                      int *parameter_type,
+                      int *valid_state_generated_flag,
+                      int *exit_status,
+                      FILE * ptr_asa_out, USER_DEFINES * OPTIONS)
+#else
+int
+
+asa_test_asa_options (seed,
+                      parameter_initial_final,
+                      parameter_minimum,
+                      parameter_maximum,
+                      tangents,
+                      curvature,
+                      number_parameters,
+                      parameter_type,
+                      valid_state_generated_flag,
+                      exit_status, ptr_asa_out, OPTIONS)
+     LONG_INT *seed;
+     double *parameter_initial_final;
+     double *parameter_minimum;
+     double *parameter_maximum;
+     double *tangents;
+     double *curvature;
+     ALLOC_INT *number_parameters;
+     int *parameter_type;
+     int *valid_state_generated_flag;
+     int *exit_status;
+     FILE *ptr_asa_out;
+     USER_DEFINES *OPTIONS;
+#endif /* HAVE_ANSI */
+{
+  int invalid, index_v;
+
+  invalid = 0;
+
+  if (seed == NULL) {
+    strcpy (exit_msg, "*** seed == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (parameter_initial_final == NULL) {
+    strcpy (exit_msg, "*** parameter_initial_final == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (parameter_minimum == NULL) {
+    strcpy (exit_msg, "*** parameter_minimum == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (parameter_maximum == NULL) {
+    strcpy (exit_msg, "*** parameter_maximum == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (tangents == NULL) {
+    strcpy (exit_msg, "*** tangents == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Curvature_0 == FALSE || OPTIONS->Curvature_0 == -1) {
+    if (curvature == NULL) {
+      strcpy (exit_msg, "*** curvature == NULL ***");
+      print_string (ptr_asa_out, exit_msg);
+      ++invalid;
+    }
+  }
+  if (number_parameters == NULL) {
+    strcpy (exit_msg, "*** number_parameters == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (parameter_type == NULL) {
+    strcpy (exit_msg, "*** parameter_type == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (valid_state_generated_flag == NULL) {
+    strcpy (exit_msg, "*** valid_state_generated_flag == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (exit_status == NULL) {
+    strcpy (exit_msg, "*** exit_status == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS == NULL) {
+    strcpy (exit_msg, "*** OPTIONS == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+
+  VFOR (index_v) if (parameter_minimum[index_v] > parameter_maximum[index_v]) {
+    strcpy (exit_msg, "*** parameter_minimum[] > parameter_maximum[] ***");
+    print_string_index (ptr_asa_out, exit_msg, index_v);
+    ++invalid;
+  }
+  VFOR (index_v)
+    if (parameter_initial_final[index_v] < parameter_minimum[index_v]) {
+    if (PARAMETER_RANGE_TOO_SMALL (index_v))
+      continue;
+    strcpy (exit_msg, "*** parameter_initial[] < parameter_minimum[] ***");
+    print_string_index (ptr_asa_out, exit_msg, index_v);
+    ++invalid;
+  }
+  VFOR (index_v)
+    if (parameter_initial_final[index_v] > parameter_maximum[index_v]) {
+    if (PARAMETER_RANGE_TOO_SMALL (index_v))
+      continue;
+    strcpy (exit_msg, "*** parameter_initial[] > parameter_maximum[] ***");
+    print_string_index (ptr_asa_out, exit_msg, index_v);
+    ++invalid;
+  }
+  if (*number_parameters < 1) {
+    strcpy (exit_msg, "*** *number_parameters < 1 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  VFOR (index_v)
+    if (parameter_type[index_v] != -2 && parameter_type[index_v] != 2
+        && parameter_type[index_v] != -1 && parameter_type[index_v] != 1) {
+    strcpy (exit_msg,
+            "*** parameter_type[] != -2 && parameter_type[] != 2 && parameter_type[] != -1 && parameter_type[] != 1 ***");
+    print_string_index (ptr_asa_out, exit_msg, index_v);
+    ++invalid;
+  }
+
+  if (OPTIONS_FILE != FALSE && OPTIONS_FILE != TRUE) {
+    strcpy (exit_msg,
+            "*** OPTIONS_FILE != FALSE && OPTIONS_FILE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS_FILE_DATA != FALSE && OPTIONS_FILE_DATA != TRUE) {
+    strcpy (exit_msg,
+            "*** OPTIONS_FILE_DATA != FALSE && OPTIONS_FILE_DATA != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (RECUR_OPTIONS_FILE != FALSE && RECUR_OPTIONS_FILE != TRUE) {
+    strcpy (exit_msg,
+            "*** RECUR_OPTIONS_FILE != FALSE && RECUR_OPTIONS_FILE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (RECUR_OPTIONS_FILE_DATA != FALSE && RECUR_OPTIONS_FILE_DATA != TRUE) {
+    strcpy (exit_msg,
+            "*** RECUR_OPTIONS_FILE_DATA != FALSE && RECUR_OPTIONS_FILE_DATA != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (COST_FILE != FALSE && COST_FILE != TRUE) {
+    strcpy (exit_msg, "*** COST_FILE != FALSE && COST_FILE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_LIB != FALSE && ASA_LIB != TRUE) {
+    strcpy (exit_msg, "*** ASA_LIB != FALSE && ASA_LIB != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (MY_TEMPLATE != FALSE && MY_TEMPLATE != TRUE) {
+    strcpy (exit_msg, "*** MY_TEMPLATE != FALSE && MY_TEMPLATE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_TEMPLATE_LIB != FALSE && ASA_TEMPLATE_LIB != TRUE) {
+    strcpy (exit_msg,
+            "*** ASA_TEMPLATE_LIB != FALSE && ASA_TEMPLATE_LIB != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (HAVE_ANSI != FALSE && HAVE_ANSI != TRUE) {
+    strcpy (exit_msg, "*** HAVE_ANSI != FALSE && HAVE_ANSI != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (IO_PROTOTYPES != FALSE && IO_PROTOTYPES != TRUE) {
+    strcpy (exit_msg,
+            "*** IO_PROTOTYPES != FALSE && IO_PROTOTYPES != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (TIME_CALC != FALSE && TIME_CALC != TRUE) {
+    strcpy (exit_msg, "*** TIME_CALC != FALSE && TIME_CALC != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (TIME_STD != FALSE && TIME_STD != TRUE) {
+    strcpy (exit_msg, "*** TIME_STD != FALSE && TIME_STD != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (TIME_GETRUSAGE != FALSE && TIME_GETRUSAGE != TRUE) {
+    strcpy (exit_msg,
+            "*** TIME_GETRUSAGE != FALSE && TIME_GETRUSAGE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (INT_LONG != FALSE && INT_LONG != TRUE) {
+    strcpy (exit_msg, "*** INT_LONG != FALSE && INT_LONG != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (INT_ALLOC != FALSE && INT_ALLOC != TRUE) {
+    strcpy (exit_msg, "*** INT_ALLOC != FALSE && INT_ALLOC != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (SMALL_FLOAT < ZERO) {
+    strcpy (exit_msg, "*** SMALL_FLOAT < ZERO ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (MIN_DOUBLE < ZERO) {
+    strcpy (exit_msg, "*** MIN_DOUBLE < ZERO ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (MAX_DOUBLE < ZERO) {
+    strcpy (exit_msg, "*** MAX_DOUBLE < ZERO ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (EPS_DOUBLE < ZERO) {
+    strcpy (exit_msg, "*** EPS_DOUBLE < ZERO ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (CHECK_EXPONENT != FALSE && CHECK_EXPONENT != TRUE) {
+    strcpy (exit_msg,
+            "*** CHECK_EXPONENT != FALSE && CHECK_EXPONENT != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (NO_PARAM_TEMP_TEST != FALSE && NO_PARAM_TEMP_TEST != TRUE) {
+    strcpy (exit_msg,
+            "*** NO_PARAM_TEMP_TEST != FALSE && NO_PARAM_TEMP_TEST != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (NO_COST_TEMP_TEST != FALSE && NO_COST_TEMP_TEST != TRUE) {
+    strcpy (exit_msg,
+            "*** NO_COST_TEMP_TEST != FALSE && NO_COST_TEMP_TEST != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (SELF_OPTIMIZE != FALSE && SELF_OPTIMIZE != TRUE) {
+    strcpy (exit_msg,
+            "*** SELF_OPTIMIZE != FALSE && SELF_OPTIMIZE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_TEST != FALSE && ASA_TEST != TRUE) {
+    strcpy (exit_msg, "*** ASA_TEST != FALSE && ASA_TEST != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_TEST_POINT != FALSE && ASA_TEST_POINT != TRUE) {
+    strcpy (exit_msg,
+            "*** ASA_TEST_POINT != FALSE && ASA_TEST_POINT != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_TEMPLATE != FALSE) {
+    strcpy (exit_msg, "*** ASA_TEMPLATE != FALSE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_TEMPLATE_ASA_OUT_PID != FALSE && ASA_TEMPLATE_ASA_OUT_PID != TRUE) {
+    strcpy (exit_msg,
+            "*** ASA_TEMPLATE_ASA_OUT_PID != FALSE && ASA_TEMPLATE_ASA_OUT_PID != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_TEMPLATE_MULTIPLE != FALSE && ASA_TEMPLATE_MULTIPLE != TRUE) {
+    strcpy (exit_msg,
+            "*** ASA_TEMPLATE_MULTIPLE != FALSE && ASA_TEMPLATE_MULTIPLE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_TEMPLATE_SELFOPT != FALSE && ASA_TEMPLATE_SELFOPT != TRUE) {
+    strcpy (exit_msg,
+            "*** ASA_TEMPLATE_SELFOPT != FALSE && ASA_TEMPLATE_SELFOPT != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_TEMPLATE_SAMPLE != FALSE && ASA_TEMPLATE_SAMPLE != TRUE) {
+    strcpy (exit_msg,
+            "*** ASA_TEMPLATE_SAMPLE != FALSE && ASA_TEMPLATE_SAMPLE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_TEMPLATE_QUEUE != FALSE && ASA_TEMPLATE_QUEUE != TRUE) {
+    strcpy (exit_msg,
+            "*** ASA_TEMPLATE_QUEUE != FALSE && ASA_TEMPLATE_QUEUE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_TEMPLATE_PARALLEL != FALSE && ASA_TEMPLATE_PARALLEL != TRUE) {
+    strcpy (exit_msg,
+            "*** ASA_TEMPLATE_PARALLEL != FALSE && ASA_TEMPLATE_PARALLEL != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_TEMPLATE_SAVE != FALSE && ASA_TEMPLATE_SAVE != TRUE) {
+    strcpy (exit_msg,
+            "*** ASA_TEMPLATE_SAVE != FALSE && ASA_TEMPLATE_SAVE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (USER_INITIAL_COST_TEMP != FALSE && USER_INITIAL_COST_TEMP != TRUE) {
+    strcpy (exit_msg,
+            "*** USER_INITIAL_COST_TEMP != FALSE && USER_INITIAL_COST_TEMP != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (RATIO_TEMPERATURE_SCALES != FALSE && RATIO_TEMPERATURE_SCALES != TRUE) {
+    strcpy (exit_msg,
+            "*** RATIO_TEMPERATURE_SCALES != FALSE && RATIO_TEMPERATURE_SCALES != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (USER_INITIAL_PARAMETERS_TEMPS != FALSE
+      && USER_INITIAL_PARAMETERS_TEMPS != TRUE) {
+    strcpy (exit_msg,
+            "*** USER_INITIAL_PARAMETERS_TEMPS != FALSE && USER_INITIAL_PARAMETERS_TEMPS != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (DELTA_PARAMETERS != FALSE && DELTA_PARAMETERS != TRUE) {
+    strcpy (exit_msg,
+            "*** DELTA_PARAMETERS != FALSE && DELTA_PARAMETERS != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (QUENCH_PARAMETERS != FALSE && QUENCH_PARAMETERS != TRUE) {
+    strcpy (exit_msg,
+            "*** QUENCH_PARAMETERS != FALSE && QUENCH_PARAMETERS != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (QUENCH_COST != FALSE && QUENCH_COST != TRUE) {
+    strcpy (exit_msg, "*** QUENCH_COST != FALSE && QUENCH_COST != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (QUENCH_PARAMETERS_SCALE != FALSE && QUENCH_PARAMETERS_SCALE != TRUE) {
+    strcpy (exit_msg,
+            "*** QUENCH_PARAMETERS_SCALE != FALSE && QUENCH_PARAMETERS_SCALE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (QUENCH_COST_SCALE != FALSE && QUENCH_COST_SCALE != TRUE) {
+    strcpy (exit_msg,
+            "*** QUENCH_COST_SCALE != FALSE && QUENCH_COST_SCALE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONAL_DATA_DBL != FALSE && OPTIONAL_DATA_DBL != TRUE) {
+    strcpy (exit_msg,
+            "*** OPTIONAL_DATA_DBL != FALSE && OPTIONAL_DATA_DBL != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONAL_DATA_INT != FALSE && OPTIONAL_DATA_INT != TRUE) {
+    strcpy (exit_msg,
+            "*** OPTIONAL_DATA_INT != FALSE && OPTIONAL_DATA_INT != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONAL_DATA_PTR != FALSE && OPTIONAL_DATA_PTR != TRUE) {
+    strcpy (exit_msg,
+            "*** OPTIONAL_DATA_PTR != FALSE && OPTIONAL_DATA_PTR != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (USER_COST_SCHEDULE != FALSE && USER_COST_SCHEDULE != TRUE) {
+    strcpy (exit_msg,
+            "*** USER_COST_SCHEDULE != FALSE && USER_COST_SCHEDULE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (USER_ACCEPT_ASYMP_EXP != FALSE && USER_ACCEPT_ASYMP_EXP != TRUE) {
+    strcpy (exit_msg,
+            "*** USER_ACCEPT_ASYMP_EXP != FALSE && USER_ACCEPT_ASYMP_EXP != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (USER_ACCEPT_THRESHOLD != FALSE && USER_ACCEPT_THRESHOLD != TRUE) {
+    strcpy (exit_msg,
+            "*** USER_ACCEPT_THRESHOLD != FALSE && USER_ACCEPT_THRESHOLD != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (USER_ACCEPTANCE_TEST != FALSE && USER_ACCEPTANCE_TEST != TRUE) {
+    strcpy (exit_msg,
+            "*** USER_ACCEPTANCE_TEST != FALSE && USER_ACCEPTANCE_TEST != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (USER_GENERATING_FUNCTION != FALSE && USER_GENERATING_FUNCTION != TRUE) {
+    strcpy (exit_msg,
+            "*** USER_GENERATING_FUNCTION != FALSE && USER_GENERATING_FUNCTION != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (USER_REANNEAL_COST != FALSE && USER_REANNEAL_COST != TRUE) {
+    strcpy (exit_msg,
+            "*** USER_REANNEAL_COST != FALSE && USER_REANNEAL_COST != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (USER_REANNEAL_PARAMETERS != FALSE && USER_REANNEAL_PARAMETERS != TRUE) {
+    strcpy (exit_msg,
+            "*** USER_REANNEAL_PARAMETERS != FALSE && USER_REANNEAL_PARAMETERS != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (MAXIMUM_REANNEAL_INDEX < 1) {
+    strcpy (exit_msg, "*** MAXIMUM_REANNEAL_INDEX < 1 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (REANNEAL_SCALE < ZERO) {
+    strcpy (exit_msg, "*** REANNEAL_SCALE < ZERO ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_SAMPLE != FALSE && ASA_SAMPLE != TRUE) {
+    strcpy (exit_msg, "*** ASA_SAMPLE != FALSE && ASA_SAMPLE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_QUEUE != FALSE && ASA_QUEUE != TRUE) {
+    strcpy (exit_msg, "*** ASA_QUEUE != FALSE && ASA_QUEUE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_RESOLUTION != FALSE && ASA_RESOLUTION != TRUE) {
+    strcpy (exit_msg,
+            "*** ASA_RESOLUTION != FALSE && ASA_RESOLUTION != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (FITLOC != FALSE && FITLOC != TRUE) {
+    strcpy (exit_msg, "*** FITLOC != FALSE && FITLOC != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (FITLOC_ROUND != FALSE && FITLOC_ROUND != TRUE) {
+    strcpy (exit_msg,
+            "*** FITLOC_ROUND != FALSE && FITLOC_ROUND != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (FITLOC_PRINT != FALSE && FITLOC_PRINT != TRUE) {
+    strcpy (exit_msg,
+            "*** FITLOC_PRINT != FALSE && FITLOC_PRINT != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (MULTI_MIN != FALSE && MULTI_MIN != TRUE) {
+    strcpy (exit_msg, "*** MULTI_MIN != FALSE && MULTI_MIN != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#if MULTI_MIN
+  if (OPTIONS->Multi_Number <= 0) {
+    strcpy (exit_msg, "*** OPTIONS->Multi_Number <= 0 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  VFOR (index_v) {
+    if (((OPTIONS->Multi_Grid[index_v]) != (OPTIONS->Multi_Grid[index_v]))
+        || OPTIONS->Multi_Grid[index_v] < 0) {
+      strcpy (exit_msg,
+              "*** (OPTIONS->Multi_Grid[]) != (OPTIONS->Multi_Grid[]) || OPTIONS->Multi_Grid[] < 0 ***");
+      print_string_index (ptr_asa_out, exit_msg, index_v);
+      ++invalid;
+    }
+  }
+  if (OPTIONS->Multi_Specify != 0 && OPTIONS->Multi_Specify != 1) {
+    strcpy (exit_msg,
+            "*** OPTIONS->Multi_Specify != 0 && OPTIONS->Multi_Specify != 1 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#endif
+  if (ASA_PARALLEL != FALSE && ASA_PARALLEL != TRUE) {
+    strcpy (exit_msg,
+            "*** ASA_PARALLEL != FALSE && ASA_PARALLEL != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_SAVE != FALSE && ASA_SAVE != TRUE) {
+    strcpy (exit_msg, "*** ASA_SAVE != FALSE && ASA_SAVE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_SAVE_OPT != FALSE && ASA_SAVE_OPT != TRUE) {
+    strcpy (exit_msg,
+            "*** ASA_SAVE_OPT != FALSE && ASA_SAVE_OPT != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_SAVE_BACKUP != FALSE && ASA_SAVE_BACKUP != TRUE) {
+    strcpy (exit_msg,
+            "*** ASA_SAVE_BACKUP != FALSE && ASA_SAVE_BACKUP != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_PIPE != FALSE && ASA_PIPE != TRUE) {
+    strcpy (exit_msg, "*** ASA_PIPE != FALSE && ASA_PIPE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_PIPE_FILE != FALSE && ASA_PIPE_FILE != TRUE) {
+    strcpy (exit_msg,
+            "*** ASA_PIPE_FILE != FALSE && ASA_PIPE_FILE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (SYSTEM_CALL != FALSE && SYSTEM_CALL != TRUE) {
+    strcpy (exit_msg, "*** SYSTEM_CALL != FALSE && SYSTEM_CALL != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (FDLIBM_POW != FALSE && FDLIBM_POW != TRUE) {
+    strcpy (exit_msg, "*** FDLIBM_POW != FALSE && FDLIBM_POW != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (FDLIBM_LOG != FALSE && FDLIBM_LOG != TRUE) {
+    strcpy (exit_msg, "*** FDLIBM_LOG != FALSE && FDLIBM_LOG != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (FDLIBM_EXP != FALSE && FDLIBM_EXP != TRUE) {
+    strcpy (exit_msg, "*** FDLIBM_EXP != FALSE && FDLIBM_EXP != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_PRINT != FALSE && ASA_PRINT != TRUE) {
+    strcpy (exit_msg, "*** ASA_PRINT != FALSE && ASA_PRINT != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (USER_ASA_OUT != FALSE && USER_ASA_OUT != TRUE) {
+    strcpy (exit_msg,
+            "*** USER_ASA_OUT != FALSE && USER_ASA_OUT != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_PRINT_INTERMED != FALSE && ASA_PRINT_INTERMED != TRUE) {
+    strcpy (exit_msg,
+            "*** ASA_PRINT_INTERMED != FALSE && ASA_PRINT_INTERMED != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_PRINT_MORE != FALSE && ASA_PRINT_MORE != TRUE) {
+    strcpy (exit_msg,
+            "*** ASA_PRINT_MORE != FALSE && ASA_PRINT_MORE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (G_FIELD < 0) {
+    strcpy (exit_msg, "*** G_FIELD < 0 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (G_PRECISION < 0) {
+    strcpy (exit_msg, "*** G_PRECISION < 0 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+
+  if (OPTIONS->Limit_Acceptances < 0) {
+    strcpy (exit_msg, "*** Limit_Acceptances < 0 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Limit_Generated < 0) {
+    strcpy (exit_msg, "*** Limit_Generated < 0 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Limit_Invalid_Generated_States < 0) {
+    strcpy (exit_msg, "*** Limit_Invalid_Generated_States < 0 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Accepted_To_Generated_Ratio <= ZERO) {
+    strcpy (exit_msg, "*** Accepted_To_Generated_Ratio <= ZERO ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Cost_Precision <= ZERO) {
+    strcpy (exit_msg, "*** Cost_Precision <= ZERO ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Maximum_Cost_Repeat < 0) {
+    strcpy (exit_msg, "*** Maximum_Cost_Repeat < 0 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Number_Cost_Samples == 0 || OPTIONS->Number_Cost_Samples == -1) {
+    strcpy (exit_msg,
+            "*** Number_Cost_Samples == 0 || Number_Cost_Samples == -1 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Temperature_Ratio_Scale <= ZERO) {
+    strcpy (exit_msg, "*** Temperature_Ratio_Scale <= ZERO ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Cost_Parameter_Scale_Ratio <= ZERO) {
+    strcpy (exit_msg, "*** Cost_Parameter_Scale_Ratio <= ZERO ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Temperature_Anneal_Scale <= ZERO) {
+    strcpy (exit_msg, "*** Temperature_Anneal_Scale <= ZERO ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#if USER_INITIAL_COST_TEMP
+  if (OPTIONS->User_Cost_Temperature[0] <= ZERO) {
+    strcpy (exit_msg, "*** User_Cost_Temperature[0] <= ZERO ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#endif
+  if (OPTIONS->Include_Integer_Parameters != FALSE
+      && OPTIONS->Include_Integer_Parameters != TRUE) {
+    strcpy (exit_msg, "");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->User_Initial_Parameters != FALSE
+      && OPTIONS->User_Initial_Parameters != TRUE) {
+    strcpy (exit_msg,
+            "*** User_Initial_Parameters != FALSE && User_Initial_Parameters != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Sequential_Parameters >= *number_parameters) {
+    strcpy (exit_msg, "*** Sequential_Parameters >= *number_parameters ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Initial_Parameter_Temperature <= ZERO) {
+    strcpy (exit_msg, "*** Initial_Parameter_Temperature <= ZERO ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#if RATIO_TEMPERATURE_SCALES
+  VFOR (index_v) if (OPTIONS->User_Temperature_Ratio[index_v] <= ZERO) {
+    strcpy (exit_msg, "*** User_Temperature_Ratio[] <= ZERO ***");
+    print_string_index (ptr_asa_out, exit_msg, index_v);
+    ++invalid;
+  }
+#endif
+#if USER_INITIAL_PARAMETERS_TEMPS
+  VFOR (index_v) if (OPTIONS->User_Parameter_Temperature[index_v] <= ZERO) {
+    strcpy (exit_msg, "*** User_Parameter_Temperature[] <= ZERO ***");
+    print_string_index (ptr_asa_out, exit_msg, index_v);
+    ++invalid;
+  }
+#endif
+  if (OPTIONS->Acceptance_Frequency_Modulus < 0) {
+    strcpy (exit_msg, "*** Acceptance_Frequency_Modulus < 0 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Generated_Frequency_Modulus < 0) {
+    strcpy (exit_msg, "*** Generated_Frequency_Modulus < 0 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Reanneal_Cost == -1) {
+    strcpy (exit_msg, "*** Reanneal_Cost == -1 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Reanneal_Parameters != FALSE
+      && OPTIONS->Reanneal_Parameters != TRUE) {
+    strcpy (exit_msg,
+            "*** Reanneal_Parameters != FALSE && Reanneal_Parameters != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Delta_X <= ZERO) {
+    strcpy (exit_msg, "*** Delta_X <= ZERO ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#if DELTA_PARAMETERS
+  VFOR (index_v) if (OPTIONS->User_Delta_Parameter[index_v] <= ZERO) {
+    strcpy (exit_msg, "*** User_Delta_Parameter[] <= ZERO ***");
+    print_string_index (ptr_asa_out, exit_msg, index_v);
+    ++invalid;
+  }
+#endif
+  if (OPTIONS->User_Tangents != FALSE && OPTIONS->User_Tangents != TRUE) {
+    strcpy (exit_msg,
+            "*** User_Tangents != FALSE && User_Tangents != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Curvature_0 != -1 && OPTIONS->Curvature_0 != FALSE
+      && OPTIONS->Curvature_0 != TRUE) {
+    strcpy (exit_msg,
+            "*** Curvature_0 -1 && Curvature_0 != FALSE && Curvature_0 != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#if QUENCH_PARAMETERS
+  VFOR (index_v) if (OPTIONS->User_Quench_Param_Scale[index_v] <= ZERO) {
+    strcpy (exit_msg, "*** User_Quench_Param_Scale[] <= ZERO ***");
+    print_string_index (ptr_asa_out, exit_msg, index_v);
+    ++invalid;
+  }
+#endif
+#if QUENCH_COST
+  if (OPTIONS->User_Quench_Cost_Scale[0] <= ZERO) {
+    strcpy (exit_msg, "*** User_Quench_Cost_Scale[0] <= ZERO ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#endif
+#if OPTIONAL_DATA_DBL
+  if (OPTIONS->Asa_Data_Dim_Dbl < 1) {
+    strcpy (exit_msg, "*** Asa_Data_Dim_Dbl < 1 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Asa_Data_Dbl == NULL) {
+    strcpy (exit_msg, "*** Asa_Data_Dbl == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#endif
+#if ASA_SAVE
+  if (OPTIONS->Random_Array_Dim < 1) {
+    strcpy (exit_msg, "*** Random_Array_Dim < 1 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Random_Array == NULL) {
+    strcpy (exit_msg, "*** Random_Array == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#endif
+#if OPTIONAL_DATA_INT
+  if (OPTIONS->Asa_Data_Dim_Int < 1) {
+    strcpy (exit_msg, "*** Asa_Data_Dim_Int < 1 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Asa_Data_Int == NULL) {
+    strcpy (exit_msg, "*** Asa_Data_Int == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#endif
+#if OPTIONAL_DATA_PTR
+  if (OPTIONS->Asa_Data_Dim_Ptr < 1) {
+    strcpy (exit_msg, "*** Asa_Data_Dim_Ptr < 1 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Asa_Data_Ptr == NULL) {
+    strcpy (exit_msg, "*** Asa_Data_Ptr == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#endif
+#if USER_ASA_OUT
+  if (OPTIONS->Asa_Out_File == NULL) {
+    strcpy (exit_msg, "*** Asa_Out_File == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#endif
+#if USER_COST_SCHEDULE
+  if (OPTIONS->Cost_Schedule == NULL) {
+    strcpy (exit_msg, "*** Cost_Schedule == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#endif
+#if USER_ACCEPTANCE_TEST
+  if (OPTIONS->Acceptance_Test == NULL) {
+    strcpy (exit_msg, "*** Acceptance_Test == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->User_Acceptance_Flag != FALSE
+      && OPTIONS->User_Acceptance_Flag != TRUE) {
+    strcpy (exit_msg,
+            "*** User_Acceptance_Flag != FALSE && User_Acceptance_Flag != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Cost_Acceptance_Flag != FALSE
+      && OPTIONS->Cost_Acceptance_Flag != TRUE) {
+    strcpy (exit_msg,
+            "*** Cost_Acceptance_Flag != FALSE && Cost_Acceptance_Flag != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#endif
+#if USER_GENERATING_FUNCTION
+  if (OPTIONS->Generating_Distrib == NULL) {
+    strcpy (exit_msg, "*** Generating_Distrib == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#endif
+#if USER_REANNEAL_COST
+  if (OPTIONS->Reanneal_Cost_Function == NULL) {
+    strcpy (exit_msg, "*** Reanneal_Cost_Function == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#endif
+#if USER_REANNEAL_PARAMETERS
+  if (OPTIONS->Reanneal_Params_Function == NULL) {
+    strcpy (exit_msg, "*** Reanneal_Params_Function == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#endif
+#if ASA_SAMPLE
+  if (OPTIONS->Bias_Generated == NULL) {
+    strcpy (exit_msg, "*** Bias_Generated == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Limit_Weights < ZERO) {
+    strcpy (exit_msg, "*** Limit_Weights < ZERO ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#endif
+#if ASA_QUEUE
+  if (OPTIONS->Queue_Size < 0) {
+    strcpy (exit_msg, "*** Queue_Size < 0 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Queue_Size > 0) {
+    if (OPTIONS->Queue_Resolution == NULL) {
+      strcpy (exit_msg, "*** Queue_Resolution == NULL ***");
+      print_string (ptr_asa_out, exit_msg);
+      ++invalid;
+    }
+  }
+#endif
+#if ASA_RESOLUTION
+  if (OPTIONS->Coarse_Resolution == NULL) {
+    strcpy (exit_msg, "*** Coarse_Resolution == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#endif
+#if ASA_PARALLEL
+  if (OPTIONS->Gener_Block < 1) {
+    strcpy (exit_msg, "*** Gener_Block < 1 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Gener_Block_Max < 1) {
+    strcpy (exit_msg, "*** Gener_Block_Max < 1 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Gener_Mov_Avr < 1) {
+    strcpy (exit_msg, "*** Gener_Mov_Avr < 1 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#endif
+
+  return (invalid);
+}
+
+/***********************************************************************
+* cost_function_test
+*       Tests user's returned cost function values and parameters
+***********************************************************************/
+#if HAVE_ANSI
+int
+
+cost_function_test (double cost,
+                    double *parameter,
+                    double *parameter_minimum,
+                    double *parameter_maximum,
+                    ALLOC_INT * number_parameters, double *xnumber_parameters)
+#else
+int
+
+cost_function_test (cost,
+                    parameter,
+                    parameter_minimum, parameter_maximum,
+                    number_parameters, xnumber_parameters)
+     double cost;
+     double *parameter;
+     double *parameter_minimum;
+     double *parameter_maximum;
+     ALLOC_INT *number_parameters;
+     double *xnumber_parameters;
+#endif /* HAVE_ANSI */
+{
+  ALLOC_INT index_v;
+  int test_flag;
+
+  test_flag = 1;
+
+  if (((cost) != (cost)) || (cost < -MAX_DOUBLE || cost > MAX_DOUBLE))
+    test_flag = 0;
+
+  *xnumber_parameters = (double) *number_parameters;
+  VFOR (index_v) {
+    if (PARAMETER_RANGE_TOO_SMALL (index_v)) {
+      *xnumber_parameters -= 1.0;
+      continue;
+    }
+    if (parameter[index_v] < parameter_minimum[index_v] ||
+        parameter[index_v] > parameter_maximum[index_v]) {
+      test_flag = 0;
+    }
+  }
+
+  return (test_flag);
+}
+
+/***********************************************************************
+* print_string
+*	This prints the designated string
+***********************************************************************/
+#if HAVE_ANSI
+void
+print_string (FILE * ptr_asa_out, char *string)
+#else
+void
+print_string (ptr_asa_out, string)
+     FILE *ptr_asa_out;
+     char *string;
+#endif /* HAVE_ANSI */
+{
+#if INCL_STDOUT
+  printf ("\n\n%s\n\n", string);
+#endif /* INCL_STDOUT */
+#if ASA_PRINT
+  fprintf (ptr_asa_out, "\n\n%s\n\n", string);
+#else
+#endif
+}
+
+/***********************************************************************
+* print_string_index
+*	This prints the designated string and index
+***********************************************************************/
+#if HAVE_ANSI
+void
+print_string_index (FILE * ptr_asa_out, char *string, ALLOC_INT index)
+#else
+void
+print_string_index (ptr_asa_out, string, index)
+     FILE *ptr_asa_out;
+     char *string;
+     ALLOC_INT index;
+#endif /* HAVE_ANSI */
+{
+#if INCL_STDOUT
+#if INT_ALLOC
+  printf ("\n\n%s index = %d\n\n", string, index);
+#else /* INT_ALLOC */
+#if INT_LONG
+  printf ("\n\n%s index = %ld\n\n", string, index);
+#else /* INT_LONG */
+  printf ("\n\n%s index = %ld\n\n", string, index);
+#endif /* INT_LONG */
+#endif /* INT_ALLOC */
+#endif /* INCL_STDOUT */
+
+#if ASA_PRINT
+#if INT_ALLOC
+  fprintf (ptr_asa_out, "\n\n%s index = %d\n\n", string, index);
+#else /* INT_ALLOC */
+#if INT_LONG
+  fprintf (ptr_asa_out, "\n\n%s index = %ld\n\n", string, index);
+#else /* INT_LONG */
+  fprintf (ptr_asa_out, "\n\n%s index = %d\n\n", string, index);
+#endif /* INT_LONG */
+#endif /* INT_ALLOC */
+#else /* ASA_PRINT */
+  ;
+#endif /* ASA_PRINT */
+}
+
+#if ASA_PRINT
+/***********************************************************************
+* print_state
+*	Prints a description of the current state of the system
+***********************************************************************/
+void
+print_state (double *parameter_minimum,
+             double *parameter_maximum,
+             double *tangents,
+             double *curvature,
+             double *current_cost_temperature,
+             double *current_user_parameter_temp,
+             double *accepted_to_generated_ratio,
+             ALLOC_INT * number_parameters,
+             int *curvature_flag,
+             LONG_INT * number_accepted,
+             LONG_INT * index_cost_acceptances,
+             LONG_INT * number_generated,
+             LONG_INT * number_invalid_generated_states,
+             STATE * last_saved_state,
+             STATE * best_generated_state,
+             FILE * ptr_asa_out, USER_DEFINES * OPTIONS)
+{
+  ALLOC_INT index_v;
+  ALLOC_INT index_vv, index_v_vv;
+
+  fprintf (ptr_asa_out, "\n");
+#if TIME_CALC
+  print_time ("", ptr_asa_out);
+#endif
+
+  if (OPTIONS->Curvature_0 == TRUE)
+    *curvature_flag = FALSE;
+  if (OPTIONS->Curvature_0 == -1)
+    *curvature_flag = TRUE;
+
+#if INT_LONG
+  fprintf (ptr_asa_out,
+           "*index_cost_acceptances = %ld, *current_cost_temperature = %*.*g\n",
+           *index_cost_acceptances,
+           G_FIELD, G_PRECISION, *current_cost_temperature);
+  fprintf (ptr_asa_out, "*accepted_to_generated_ratio = %*.*g,\
+ *number_invalid... = %ld\n", G_FIELD, G_PRECISION, *accepted_to_generated_ratio, (*number_invalid_generated_states));
+  fprintf (ptr_asa_out,
+           "*number_generated = %ld, *number_accepted = %ld\n",
+           *number_generated, *number_accepted);
+#else
+  fprintf (ptr_asa_out,
+           "*index_cost_acceptances = %d, *current_cost_temperature = %*.*g\n",
+           *index_cost_acceptances,
+           G_FIELD, G_PRECISION, *current_cost_temperature);
+  fprintf (ptr_asa_out, "*accepted_to_generated_ratio = %*.*g,\
+ *number_invalid... = %d\n", G_FIELD, G_PRECISION, *accepted_to_generated_ratio, *number_invalid_generated_states);
+  fprintf (ptr_asa_out,
+           "*number_generated = %d, *number_accepted = %d\n",
+           *number_generated, *number_accepted);
+#endif
+
+  fprintf (ptr_asa_out, "best...->cost = %*.*g,\
+ last...->cost = %*.*g\n", G_FIELD, G_PRECISION, best_generated_state->cost, G_FIELD, G_PRECISION, last_saved_state->cost);
+
+  /* Note that tangents will not be calculated until reanneal
+     is called, and therefore their listing in the printout only
+     is relevant then */
+
+  fprintf (ptr_asa_out,
+           "index_v  best...->parameter current_parameter_temp\ttangent\n");
+  VFOR (index_v) {
+    /* ignore too small ranges */
+#if DROPPED_PARAMETERS
+    if (PARAMETER_RANGE_TOO_SMALL (index_v))
+      continue;
+#endif
+    fprintf (ptr_asa_out,
+#if INT_ALLOC
+             "%d\t%*.*g\t\t%*.*g\t%*.*g\n",
+#else
+#if INT_LONG
+             "%ld\t%*.*g\t\t%*.*g\t%*.*g\n",
+#else
+             "%d\t%*.*g\t\t%*.*g\t%*.*g\n",
+#endif
+#endif
+             index_v,
+             G_FIELD, G_PRECISION, best_generated_state->parameter[index_v],
+             G_FIELD, G_PRECISION, current_user_parameter_temp[index_v],
+             G_FIELD, G_PRECISION, tangents[index_v]);
+  }
+
+  if (*curvature_flag == TRUE) {
+    /* print curvatures */
+    VFOR (index_v) {
+      /* ignore too small ranges */
+      if (PARAMETER_RANGE_TOO_SMALL (index_v))
+        continue;
+      fprintf (ptr_asa_out, "\n");
+      VFOR (index_vv) {
+        /* only print upper diagonal of matrix */
+        if (index_v < index_vv)
+          continue;
+        /* ignore too small ranges (index_vv) */
+        if (PARAMETER_RANGE_TOO_SMALL (index_vv))
+          continue;
+
+        /* index_v_vv: row index_v, column index_vv */
+        index_v_vv = ROW_COL_INDEX (index_v, index_vv);
+
+        if (index_v == index_vv) {
+          fprintf (ptr_asa_out,
+#if INT_ALLOC
+                   "curvature[%d][%d] = %*.*g\n",
+#else
+#if INT_LONG
+                   "curvature[%ld][%ld] = %*.*g\n",
+#else
+                   "curvature[%d][%d] = %*.*g\n",
+#endif
+#endif
+                   index_v, index_vv,
+                   G_FIELD, G_PRECISION, curvature[index_v_vv]);
+        } else {
+          fprintf (ptr_asa_out,
+#if INT_ALLOC
+                   "curvature[%d][%d] = %*.*g \t = curvature[%d][%d]\n",
+#else
+#if INT_LONG
+                   "curvature[%ld][%ld] = %*.*g \t = curvature[%ld][%ld]\n",
+#else
+                   "curvature[%d][%d] = %*.*g \t = curvature[%d][%d]\n",
+#endif
+#endif
+                   index_v, index_vv,
+                   G_FIELD, G_PRECISION, curvature[index_v_vv],
+                   index_vv, index_v);
+        }
+      }
+    }
+  }
+  fprintf (ptr_asa_out, "\n");
+  fflush (ptr_asa_out);
+
+}
+
+/***********************************************************************
+* print_asa_options
+*	Prints user's selected options
+***********************************************************************/
+void
+print_asa_options (FILE * ptr_asa_out, USER_DEFINES * OPTIONS)
+{
+  fprintf (ptr_asa_out, "\t\tADAPTIVE SIMULATED ANNEALING\n\n");
+
+  fprintf (ptr_asa_out, "%s\n\n", ASA_ID);
+
+  fprintf (ptr_asa_out, "OPTIONS_FILE = %d\n", (int) OPTIONS_FILE);
+  fprintf (ptr_asa_out, "OPTIONS_FILE_DATA = %d\n", (int) OPTIONS_FILE_DATA);
+  fprintf (ptr_asa_out, "RECUR_OPTIONS_FILE = %d\n",
+           (int) RECUR_OPTIONS_FILE);
+  fprintf (ptr_asa_out, "RECUR_OPTIONS_FILE_DATA = %d\n",
+           (int) RECUR_OPTIONS_FILE_DATA);
+  fprintf (ptr_asa_out, "COST_FILE = %d\n", (int) COST_FILE);
+  fprintf (ptr_asa_out, "ASA_LIB = %d\n", (int) ASA_LIB);
+  fprintf (ptr_asa_out, "HAVE_ANSI = %d\n", (int) HAVE_ANSI);
+  fprintf (ptr_asa_out, "IO_PROTOTYPES = %d\n", (int) IO_PROTOTYPES);
+  fprintf (ptr_asa_out, "TIME_CALC = %d\n", (int) TIME_CALC);
+  fprintf (ptr_asa_out, "TIME_STD = %d\n", (int) TIME_STD);
+  fprintf (ptr_asa_out, "TIME_GETRUSAGE = %d\n", (int) TIME_GETRUSAGE);
+  fprintf (ptr_asa_out, "INT_LONG = %d\n", (int) INT_LONG);
+  fprintf (ptr_asa_out, "INT_ALLOC = %d\n", (int) INT_ALLOC);
+  fprintf (ptr_asa_out, "SMALL_FLOAT = %*.*g\n",
+           G_FIELD, G_PRECISION, (double) SMALL_FLOAT);
+  fprintf (ptr_asa_out, "MIN_DOUBLE = %*.*g\n",
+           G_FIELD, G_PRECISION, (double) MIN_DOUBLE);
+  fprintf (ptr_asa_out, "MAX_DOUBLE = %*.*g\n",
+           G_FIELD, G_PRECISION, (double) MAX_DOUBLE);
+  fprintf (ptr_asa_out, "EPS_DOUBLE = %*.*g\n",
+           G_FIELD, G_PRECISION, (double) EPS_DOUBLE);
+  fprintf (ptr_asa_out, "CHECK_EXPONENT = %d\n", (int) CHECK_EXPONENT);
+  fprintf (ptr_asa_out, "NO_PARAM_TEMP_TEST = %d\n",
+           (int) NO_PARAM_TEMP_TEST);
+  fprintf (ptr_asa_out, "NO_COST_TEMP_TEST = %d\n", (int) NO_COST_TEMP_TEST);
+  fprintf (ptr_asa_out, "SELF_OPTIMIZE = %d\n", (int) SELF_OPTIMIZE);
+  fprintf (ptr_asa_out, "ASA_TEST = %d\n", (int) ASA_TEST);
+  fprintf (ptr_asa_out, "ASA_TEST_POINT = %d\n", (int) ASA_TEST_POINT);
+  fprintf (ptr_asa_out, "ASA_TEMPLATE = %d\n", (int) ASA_TEMPLATE);
+  fprintf (ptr_asa_out, "MY_TEMPLATE = %d\n", (int) MY_TEMPLATE);
+  fprintf (ptr_asa_out, "ASA_TEMPLATE_LIB = %d\n", (int) ASA_TEMPLATE_LIB);
+  fprintf (ptr_asa_out, "ASA_TEMPLATE_ASA_OUT_PID = %d\n",
+           (int) ASA_TEMPLATE_ASA_OUT_PID);
+  fprintf (ptr_asa_out, "ASA_TEMPLATE_MULTIPLE = %d\n",
+           (int) ASA_TEMPLATE_MULTIPLE);
+  fprintf (ptr_asa_out, "ASA_TEMPLATE_SELFOPT = %d\n",
+           (int) ASA_TEMPLATE_SELFOPT);
+  fprintf (ptr_asa_out, "ASA_TEMPLATE_SAMPLE = %d\n",
+           (int) ASA_TEMPLATE_SAMPLE);
+  fprintf (ptr_asa_out, "ASA_TEMPLATE_QUEUE = %d\n",
+           (int) ASA_TEMPLATE_QUEUE);
+  fprintf (ptr_asa_out, "ASA_TEMPLATE_PARALLEL = %d\n",
+           (int) ASA_TEMPLATE_PARALLEL);
+  fprintf (ptr_asa_out, "ASA_TEMPLATE_SAVE = %d\n", (int) ASA_TEMPLATE_SAVE);
+  fprintf (ptr_asa_out, "USER_INITIAL_COST_TEMP = %d\n",
+           (int) USER_INITIAL_COST_TEMP);
+  fprintf (ptr_asa_out, "RATIO_TEMPERATURE_SCALES = %d\n",
+           (int) RATIO_TEMPERATURE_SCALES);
+  fprintf (ptr_asa_out, "USER_INITIAL_PARAMETERS_TEMPS = %d\n",
+           (int) USER_INITIAL_PARAMETERS_TEMPS);
+  fprintf (ptr_asa_out, "DELTA_PARAMETERS = %d\n", (int) DELTA_PARAMETERS);
+  fprintf (ptr_asa_out, "QUENCH_PARAMETERS = %d\n", (int) QUENCH_PARAMETERS);
+  fprintf (ptr_asa_out, "QUENCH_COST = %d\n", (int) QUENCH_COST);
+  fprintf (ptr_asa_out, "QUENCH_PARAMETERS_SCALE = %d\n",
+           (int) QUENCH_PARAMETERS_SCALE);
+  fprintf (ptr_asa_out, "QUENCH_COST_SCALE = %d\n", (int) QUENCH_COST_SCALE);
+  fprintf (ptr_asa_out, "OPTIONAL_DATA_DBL = %d\n", (int) OPTIONAL_DATA_DBL);
+  fprintf (ptr_asa_out, "OPTIONAL_DATA_INT = %d\n", (int) OPTIONAL_DATA_INT);
+  fprintf (ptr_asa_out, "OPTIONAL_DATA_PTR = %d\n", (int) OPTIONAL_DATA_PTR);
+  fprintf (ptr_asa_out, "USER_COST_SCHEDULE = %d\n",
+           (int) USER_COST_SCHEDULE);
+  fprintf (ptr_asa_out, "USER_ACCEPT_ASYMP_EXP = %d\n",
+           (int) USER_ACCEPT_ASYMP_EXP);
+  fprintf (ptr_asa_out, "USER_ACCEPT_THRESHOLD = %d\n",
+           (int) USER_ACCEPT_THRESHOLD);
+  fprintf (ptr_asa_out, "USER_ACCEPTANCE_TEST = %d\n",
+           (int) USER_ACCEPTANCE_TEST);
+  fprintf (ptr_asa_out, "USER_GENERATING_FUNCTION = %d\n",
+           (int) USER_GENERATING_FUNCTION);
+  fprintf (ptr_asa_out, "USER_REANNEAL_COST = %d\n",
+           (int) USER_REANNEAL_COST);
+  fprintf (ptr_asa_out, "USER_REANNEAL_PARAMETERS = %d\n",
+           (int) USER_REANNEAL_PARAMETERS);
+#if INT_LONG
+  fprintf (ptr_asa_out, "MAXIMUM_REANNEAL_INDEX = %ld\n",
+           (LONG_INT) MAXIMUM_REANNEAL_INDEX);
+#else
+  fprintf (ptr_asa_out, "MAXIMUM_REANNEAL_INDEX = %d\n",
+           (LONG_INT) MAXIMUM_REANNEAL_INDEX);
+#endif
+  fprintf (ptr_asa_out, "REANNEAL_SCALE = %*.*g\n",
+           G_FIELD, G_PRECISION, (double) REANNEAL_SCALE);
+  fprintf (ptr_asa_out, "ASA_SAMPLE = %d\n", (int) ASA_SAMPLE);
+  fprintf (ptr_asa_out, "ASA_QUEUE = %d\n", (int) ASA_QUEUE);
+  fprintf (ptr_asa_out, "ASA_RESOLUTION = %d\n", (int) ASA_RESOLUTION);
+  fprintf (ptr_asa_out, "FITLOC = %d\n", (int) FITLOC);
+  fprintf (ptr_asa_out, "FITLOC_ROUND = %d\n", (int) FITLOC_ROUND);
+  fprintf (ptr_asa_out, "FITLOC_PRINT = %d\n", (int) FITLOC_PRINT);
+  fprintf (ptr_asa_out, "MULTI_MIN = %d\n", (int) MULTI_MIN);
+  fprintf (ptr_asa_out, "ASA_PARALLEL = %d\n", (int) ASA_PARALLEL);
+  fprintf (ptr_asa_out, "FDLIBM_POW = %d\n", (int) FDLIBM_POW);
+  fprintf (ptr_asa_out, "FDLIBM_LOG = %d\n", (int) FDLIBM_LOG);
+  fprintf (ptr_asa_out, "FDLIBM_EXP = %d\n\n", (int) FDLIBM_EXP);
+
+  fprintf (ptr_asa_out, "ASA_PRINT = %d\n", (int) ASA_PRINT);
+  fprintf (ptr_asa_out, "USER_OUT = %s\n", USER_OUT);
+#if USER_ASA_OUT
+  fprintf (ptr_asa_out, "ASA_OUT = %s\n", OPTIONS->Asa_Out_File);
+#else
+  fprintf (ptr_asa_out, "ASA_OUT = %s\n", ASA_OUT);
+#endif
+  fprintf (ptr_asa_out, "USER_ASA_OUT = %d\n", (int) USER_ASA_OUT);
+  fprintf (ptr_asa_out, "ASA_PRINT_INTERMED = %d\n",
+           (int) ASA_PRINT_INTERMED);
+  fprintf (ptr_asa_out, "ASA_PRINT_MORE = %d\n", (int) ASA_PRINT_MORE);
+  fprintf (ptr_asa_out, "INCL_STDOUT = %d\n", (int) INCL_STDOUT);
+  fprintf (ptr_asa_out, "G_FIELD = %d\n", (int) G_FIELD);
+  fprintf (ptr_asa_out, "G_PRECISION = %d\n", (int) G_PRECISION);
+  fprintf (ptr_asa_out, "ASA_SAVE = %d\n", (int) ASA_SAVE);
+  fprintf (ptr_asa_out, "ASA_SAVE_OPT = %d\n", (int) ASA_SAVE_OPT);
+  fprintf (ptr_asa_out, "ASA_SAVE_BACKUP = %d\n", (int) ASA_SAVE_BACKUP);
+  fprintf (ptr_asa_out, "ASA_PIPE = %d\n", (int) ASA_PIPE);
+  fprintf (ptr_asa_out, "ASA_PIPE_FILE = %d\n", (int) ASA_PIPE_FILE);
+  fprintf (ptr_asa_out, "SYSTEM_CALL = %d\n\n", (int) SYSTEM_CALL);
+
+#if INT_LONG
+  fprintf (ptr_asa_out, "OPTIONS->Limit_Acceptances = %ld\n",
+           (LONG_INT) OPTIONS->Limit_Acceptances);
+  fprintf (ptr_asa_out, "OPTIONS->Limit_Generated = %ld\n",
+           (LONG_INT) OPTIONS->Limit_Generated);
+#else
+  fprintf (ptr_asa_out, "OPTIONS->Limit_Acceptances = %d\n",
+           (LONG_INT) OPTIONS->Limit_Acceptances);
+  fprintf (ptr_asa_out, "OPTIONS->Limit_Generated = %d\n",
+           (LONG_INT) OPTIONS->Limit_Generated);
+#endif
+  fprintf (ptr_asa_out, "OPTIONS->Limit_Invalid_Generated_States = %d\n",
+           OPTIONS->Limit_Invalid_Generated_States);
+  fprintf (ptr_asa_out, "OPTIONS->Accepted_To_Generated_Ratio = %*.*g\n\n",
+           G_FIELD, G_PRECISION, OPTIONS->Accepted_To_Generated_Ratio);
+
+  fprintf (ptr_asa_out, "OPTIONS->Cost_Precision = %*.*g\n",
+           G_FIELD, G_PRECISION, OPTIONS->Cost_Precision);
+  fprintf (ptr_asa_out, "OPTIONS->Maximum_Cost_Repeat = %d\n",
+           OPTIONS->Maximum_Cost_Repeat);
+  fprintf (ptr_asa_out, "OPTIONS->Number_Cost_Samples = %d\n",
+           OPTIONS->Number_Cost_Samples);
+  fprintf (ptr_asa_out, "OPTIONS->Temperature_Ratio_Scale = %*.*g\n",
+           G_FIELD, G_PRECISION, OPTIONS->Temperature_Ratio_Scale);
+  fprintf (ptr_asa_out, "OPTIONS->Cost_Parameter_Scale_Ratio = %*.*g\n",
+           G_FIELD, G_PRECISION, OPTIONS->Cost_Parameter_Scale_Ratio);
+  fprintf (ptr_asa_out, "OPTIONS->Temperature_Anneal_Scale = %*.*g\n",
+           G_FIELD, G_PRECISION, OPTIONS->Temperature_Anneal_Scale);
+
+  fprintf (ptr_asa_out, "OPTIONS->Include_Integer_Parameters = %d\n",
+           OPTIONS->Include_Integer_Parameters);
+  fprintf (ptr_asa_out, "OPTIONS->User_Initial_Parameters = %d\n",
+           OPTIONS->User_Initial_Parameters);
+#if INT_ALLOC
+  fprintf (ptr_asa_out, "OPTIONS->Sequential_Parameters = %d\n",
+           (int) OPTIONS->Sequential_Parameters);
+#else
+#if INT_LONG
+  fprintf (ptr_asa_out, "OPTIONS->Sequential_Parameters = %ld\n",
+           (LONG_INT) OPTIONS->Sequential_Parameters);
+#else
+  fprintf (ptr_asa_out, "OPTIONS->Sequential_Parameters = %d\n",
+           (LONG_INT) OPTIONS->Sequential_Parameters);
+#endif
+#endif
+  fprintf (ptr_asa_out, "OPTIONS->Initial_Parameter_Temperature = %*.*g\n",
+           G_FIELD, G_PRECISION, OPTIONS->Initial_Parameter_Temperature);
+
+  fprintf (ptr_asa_out, "OPTIONS->Acceptance_Frequency_Modulus = %d\n",
+           OPTIONS->Acceptance_Frequency_Modulus);
+  fprintf (ptr_asa_out, "OPTIONS->Generated_Frequency_Modulus = %d\n",
+           OPTIONS->Generated_Frequency_Modulus);
+  fprintf (ptr_asa_out, "OPTIONS->Reanneal_Cost = %d\n",
+           OPTIONS->Reanneal_Cost);
+  fprintf (ptr_asa_out, "OPTIONS->Reanneal_Parameters = %d\n\n",
+           OPTIONS->Reanneal_Parameters);
+
+  fprintf (ptr_asa_out, "OPTIONS->Delta_X = %*.*g\n",
+           G_FIELD, G_PRECISION, OPTIONS->Delta_X);
+  fprintf (ptr_asa_out, "OPTIONS->User_Tangents = %d\n",
+           OPTIONS->User_Tangents);
+  fprintf (ptr_asa_out, "OPTIONS->Curvature_0 = %d\n", OPTIONS->Curvature_0);
+  fprintf (ptr_asa_out, "OPTIONS->Asa_Recursive_Level = %d\n\n",
+           OPTIONS->Asa_Recursive_Level);
+
+  fprintf (ptr_asa_out, "\n");
+}
+#endif /* ASA_PRINT */
+
+#if TIME_CALC
+#if TIME_GETRUSAGE
+/***********************************************************************
+* print_time
+*	This calculates the time and runtime and prints it.
+***********************************************************************/
+#if HAVE_ANSI
+void
+print_time (char *message, FILE * ptr_asa_out)
+#else
+void
+print_time (message, ptr_asa_out)
+     char *message;
+     FILE *ptr_asa_out;
+#endif /* HAVE_ANSI */
+{
+  int who = RUSAGE_SELF;        /* Check our own time */
+  struct rusage usage;
+
+  /* get the resource usage information */
+#if TIME_STD
+  syscall (SYS_GETRUSAGE, who, &usage);
+#else
+  getrusage (who, &usage);
+#endif
+
+  /* print the usage time in reasonable form */
+  aux_print_time (&usage.ru_utime, message, ptr_asa_out);
+}
+
+/***********************************************************************
+* aux_print_time
+*      auxiliary print the time routine
+***********************************************************************/
+#if HAVE_ANSI
+void
+aux_print_time (struct timeval *time, char *message, FILE * ptr_asa_out)
+#else
+void
+aux_print_time (time, message, ptr_asa_out)
+     struct timeval *time;
+     char *message;
+     FILE *ptr_asa_out;
+#endif /* HAVE_ANSI */
+{
+  static double sx;
+  double us, s, m, h;
+  double ds, dm, dh;
+
+  /* calculate the new microseconds, seconds, minutes, hours
+     and the differences since the last call */
+  us = (double) ((int) ((double) EPS_DOUBLE + time->tv_usec)) / 1.E6;
+  s = (double) ((int) ((double) EPS_DOUBLE + time->tv_sec)) + us;
+  ds = s - sx;
+  sx = s;
+
+  h = (int) ((double) EPS_DOUBLE + s / 3600.);
+  m = (int) ((double) EPS_DOUBLE + s / 60.) - 60. * h;
+  s -= (3600. * h + 60. * m);
+  dh = (int) ((double) EPS_DOUBLE + ds / 3600.);
+  dm = (int) ((double) EPS_DOUBLE + ds / 60.) - 60. * dh;
+  ds -= (3600. * dh + 60. * dm);
+
+  /* print the statistics */
+  fprintf (ptr_asa_out,
+           "%s:time: %gh %gm %gs; incr: %gh %gm %gs\n",
+           message, h, m, s, dh, dm, ds);
+}
+#else /* TIME_GETRUSAGE */
+  /* Note that on many machines the time resolution of this algorithm
+   * may be less than the other alternatives, e.g., rounding off the
+   * number of ticks to the nearest tens of thousands.  Also, because
+   * time here is typically indexed by a long integer, there typically
+   * is a cycle of time in periods of fractions of an hour.  For
+   * example, under Solaris 2.5.1:  The value returned by clock() is
+   * defined in microseconds, since the first call to clock(), for
+   *  compatibility with  systems that have * CPU clocks with much higher
+   * resolution.  Because of this, the value returned will wrap around
+   * after accumulating only 2147 seconds of CPU time (about 36 minutes).
+   *
+   * See asa.h for two places where some additional modifications should
+   * be made under SunOS 4.1.x. */
+
+#if HAVE_ANSI
+void
+print_time (char *message, FILE * ptr_asa_out)
+#else
+void
+print_time (message, ptr_asa_out)
+     char *message;
+     FILE *ptr_asa_out;
+#endif /* HAVE_ANSI */
+{
+  aux_print_time (clock (), message, ptr_asa_out);
+
+}                               /*print_time */
+
+/***********************************************************************
+* aux_print_time
+*      auxiliary print the time routine
+***********************************************************************/
+#if HAVE_ANSI
+void
+aux_print_time (clock_t time, char *message, FILE * ptr_asa_out)
+#else
+void
+aux_print_time (time, message, ptr_asa_out)
+     clock_t time;
+     char *message;
+     FILE *ptr_asa_out;
+#endif /* HAVE_ANSI */
+{
+  static clock_t previousTime = -1;
+  clock_t diffTime;
+  double clocksPerSecF = CLOCKS_PER_SEC;
+  double timeF, diffF;
+  double s, m, h;
+  double ds, dm, dh;
+
+  if (previousTime != -1) {
+    diffTime = time - previousTime;
+    timeF = time;
+    diffF = diffTime;
+    previousTime = time;
+
+    s = timeF / clocksPerSecF;
+    ds = diffF / clocksPerSecF;
+
+    h = (int) ((double) EPS_DOUBLE + s / 3600.);
+    m = (int) ((double) EPS_DOUBLE + s / 60.) - 60. * h;
+    s -= (3600. * h + 60. * m);
+    dh = (int) ((double) EPS_DOUBLE + ds / 3600.);
+    dm = (int) ((double) EPS_DOUBLE + ds / 60.) - 60. * dh;
+    ds -= (3600. * dh + 60. * dm);
+
+    fprintf (ptr_asa_out,
+             "%s:time: %gh %gm %gs; incr: %gh %gm %gs\n",
+             message, h, m, s, dh, dm, ds);
+  } else {
+    /* The first call will be invalid - don't output anything. */
+    fprintf (ptr_asa_out, "TIMING PARAMETERS: ticks/sec: %lu\n",
+             CLOCKS_PER_SEC);
+    previousTime = time;
+  }
+}                               /* aux_print_time */
+
+#endif /* TIME_GETRUSAGE */
+
+#endif /* TIME_CALC */
+
+#if MULTI_MIN
+#if HAVE_ANSI
+static int
+multi_compare (const void *ii, const void *jj)
+#else /* HAVE_ANSI */
+static int
+multi_compare (ii, jj)
+     char *ii;
+     char *jj;
+#endif /* HAVE_ANSI */
+{
+  int i;
+  int j;
+
+  i = *(int *) ii;
+  j = *(int *) jj;
+
+  if (multi_cost_qsort[i] > multi_cost_qsort[j] + (double) EPS_DOUBLE)
+    return (1);
+  else if (multi_cost_qsort[i] < multi_cost_qsort[j] - (double) EPS_DOUBLE)
+    return (-1);
+  else
+    return (0);
+}
+#endif /* MULTI_MIN */
+
+#if ASA_PARALLEL
+#if HAVE_ANSI
+static int
+sort_parallel (const void *ii, const void *jj)
+#else /* HAVE_ANSI */
+static int
+sort_parallel (ii, jj)
+     void *ii;
+     void *jj;
+#endif /* HAVE_ANSI */
+{
+  LONG_INT i;
+  LONG_INT j;
+
+  i = *(LONG_INT *) ii;
+  j = *(LONG_INT *) jj;
+
+  if (gener_block_state_qsort[i].cost > gener_block_state_qsort[j].cost)
+    return (1);
+  else if (gener_block_state_qsort[i].cost < gener_block_state_qsort[j].cost)
+    return (-1);
+  else
+    return (0);
+}
+#endif /* ASA_PARALLEL */
+#if HAVE_ANSI
+void
+Exit_ASA (char *statement)
+#else /* HAVE_ANSI */
+void
+Exit_ASA (statement)
+     char *statement;
+#endif /* HAVE_ANSI */
+{
+#if INCL_STDOUT
+  printf ("\n\n*** EXIT calloc failed in ASA *** %s\n\n", statement);
+#else
+  ;
+#endif /* INCL_STDOUT */
+}
diff --git a/_darcs/pristine/asa.h b/_darcs/pristine/asa.h
new file mode 100644
--- /dev/null
+++ b/_darcs/pristine/asa.h
@@ -0,0 +1,337 @@
+#ifndef _ASA_H_
+#define _ASA_H_
+
+/***********************************************************************
+* Adaptive Simulated Annealing (ASA)
+* Lester Ingber <ingber@ingber.com>
+* Copyright (c) 1993-2004 Lester Ingber.  All Rights Reserved.
+* The LICENSE file must be included with ASA code.
+***********************************************************************/
+
+ /* $Id: asa.h,v 25.15 2004/09/23 18:10:48 ingber Exp ingber $ */
+
+ /* asa.h for Adaptive Simulated Annealing */
+
+#include "asa_usr_asa.h"
+
+#define ZERO			((double) 0.0)
+#define ONE			((double) 1.0)
+#define TWO			((double) 2.0)
+#define TEN			((double) 10.0)
+#define HALF			((double) 0.5)
+
+#define NORMAL_EXIT			((int) 0)
+#define P_TEMP_TOO_SMALL		((int) 1)
+#define C_TEMP_TOO_SMALL		((int) 2)
+#define COST_REPEATING			((int) 3)
+#define TOO_MANY_INVALID_STATES		((int) 4)
+#define IMMEDIATE_EXIT			((int) 5)
+#define INVALID_USER_INPUT		((int) 7)
+#define INVALID_COST_FUNCTION		((int) 8)
+#define INVALID_COST_FUNCTION_DERIV	((int) 9)
+#define CALLOC_FAILED			((int) -1)
+
+#ifndef TIME_STD
+#define TIME_STD FALSE
+#endif
+
+#ifndef TIME_GETRUSAGE
+#define TIME_GETRUSAGE TRUE
+#endif
+
+#if TIME_CALC
+#if TIME_GETRUSAGE
+#include <sys/time.h>
+#include <sys/resource.h>
+#if TIME_STD
+#include <sys/syscall.h>
+#endif /* TIME_STD */
+#else /* TIME_GETRUSAGE */
+#if TRUE                        /* change to FALSE for SunOS 4.1.x */
+#include <time.h>
+#else
+#include </usr/5include/time.h>
+#endif
+#endif /* TIME_GETRUSAGE */
+#endif /* TIME_CALC */
+
+ /* Set this to TRUE to override the P_TEMP_TOO_SMALL test */
+#ifndef NO_PARAM_TEMP_TEST
+#define NO_PARAM_TEMP_TEST FALSE
+#endif
+
+ /* Set this to TRUE to override the C_TEMP_TOO_SMALL test */
+#ifndef NO_COST_TEMP_TEST
+#define NO_COST_TEMP_TEST FALSE
+#endif
+
+#ifndef SYSTEM_CALL
+#define SYSTEM_CALL TRUE
+#endif
+
+ /* Printing Options */
+
+#ifndef ASA_PRINT
+#define ASA_PRINT TRUE
+#endif
+
+#if ASA_PRINT
+#else
+#if ASA_SAMPLE
+#define ASA_PRINT TRUE
+#endif
+#endif
+
+#ifndef ASA_OUT
+#define ASA_OUT "asa_out"
+#endif
+
+#ifndef DROPPED_PARAMETERS
+#define DROPPED_PARAMETERS FALSE
+#endif
+
+ /* You can set ASA_PRINT_INTERMED to TRUE to print out
+    intermediate data when SELF_OPTIMIZE is set to TRUE */
+#ifndef ASA_PRINT_INTERMED
+#if SELF_OPTIMIZE
+#define ASA_PRINT_INTERMED FALSE
+#else
+#define ASA_PRINT_INTERMED TRUE
+#endif
+#endif
+
+#ifndef ASA_PRINT_MORE
+#define ASA_PRINT_MORE FALSE
+#endif
+
+char exit_msg[160];             /* temp storage for exit messages */
+
+ /* The state of the system in terms of parameters and function value */
+typedef struct {
+  double cost;
+  double *parameter;
+#if ASA_PARALLEL
+#if USER_ACCEPTANCE_TEST
+  int par_user_accept_flag;
+  int par_cost_accept_flag;
+#endif
+#endif
+} STATE;
+
+#if ASA_PARALLEL
+  /* parallel generated states */
+STATE *gener_block_state_qsort;
+#endif
+
+ /* essential MACROS */
+
+#if USER_REANNEAL_PARAMETERS
+#else
+ /* FUNCTION_REANNEAL_PARAMS(temperature, tangent, max_tangent)
+    determines the reannealed temperature. */
+#define FUNCTION_REANNEAL_PARAMS(temperature, tangent, max_tangent) \
+ (temperature * (max_tangent / tangent))
+#endif
+
+ /* IABS(i)
+    absolute value for integers, in stdlib.h on _some_ machines */
+#define IABS(i) ((i) < 0? -(i) : (i))
+
+ /*  NO_REANNEAL(x)
+    can determine whether to calculate derivatives. */
+#define NO_REANNEAL(x)	(IABS(parameter_type[x]) == 2)
+
+ /* VFOR
+    is a simple macro to iterate on each parameter index. */
+
+#define VFOR(index_v) \
+ for (index_v = 0; index_v < *number_parameters; ++index_v)
+
+#if CHECK_EXPONENT
+ /* EXPONENT_CHECK
+    checks that an exponent x is within a valid range and,
+    if not, adjusts its magnitude to fit in the range. */
+#define MIN_EXPONENT (0.9 * F_LOG ((double) MIN_DOUBLE))
+#define MAX_EXPONENT (0.9 * F_LOG ((double) MAX_DOUBLE))
+#define EXPONENT_CHECK(x) \
+ ((x) < MIN_EXPONENT ? MIN_EXPONENT : \
+ ((x) > MAX_EXPONENT ? MAX_EXPONENT : (x)))
+#else
+#define EXPONENT_CHECK(x) (x)
+#endif /* CHECK_EXPONENT */
+
+ /* PARAMETER_RANGE_TOO_SMALL(x)
+    checks if the range of parameter x is too small to work with.
+    If user_cost_function changes the parameter ranges,
+    this test could be used to adaptively bypass
+    some parameters, e.g., depending on constraints. */
+#define PARAMETER_RANGE_TOO_SMALL(x) \
+ (fabs(parameter_minimum[x] - parameter_maximum[x]) < (double) EPS_DOUBLE)
+
+ /* INTEGER_PARAMETER(x)
+    determines if the parameter is an integer type. */
+#define INTEGER_PARAMETER(x) (parameter_type[x] > 0)
+
+ /* ROW_COL_INDEX(i, j)
+    converts from row i, column j to an index. */
+#define ROW_COL_INDEX(i, j) ((i) + *number_parameters * (j))
+
+#if HAVE_ANSI
+
+ /* asa function prototypes */
+void accept_new_state (double (*user_random_generator) (LONG_INT *),
+                       LONG_INT * seed,
+                       double *parameter_minimum,
+                       double *parameter_maximum,
+                       double *current_cost_temperature,
+#if ASA_SAMPLE
+                       double *current_user_parameter_temp,
+#endif
+                       ALLOC_INT * number_parameters,
+                       LONG_INT * recent_number_acceptances,
+                       LONG_INT * number_accepted,
+                       LONG_INT * index_cost_acceptances,
+                       LONG_INT * number_acceptances_saved,
+                       LONG_INT * recent_number_generated,
+                       LONG_INT * number_generated,
+                       LONG_INT * index_parameter_generations,
+                       STATE * current_generated_state,
+                       STATE * last_saved_state,
+#if ASA_SAMPLE
+                       FILE * ptr_asa_out,
+#endif
+                       USER_DEFINES * OPTIONS);
+
+void generate_new_state (double (*user_random_generator) (LONG_INT *),
+                         LONG_INT * seed,
+                         double *parameter_minimum,
+                         double *parameter_maximum,
+                         double *current_parameter_temperature,
+#if USER_GENERATING_FUNCTION
+                         double *initial_user_parameter_temp,
+                         double *temperature_scale_parameters,
+#endif
+                         ALLOC_INT * number_parameters,
+                         int *parameter_type,
+                         STATE * current_generated_state,
+                         STATE * last_saved_state, USER_DEFINES * OPTIONS);
+
+void reanneal (double *parameter_minimum,
+               double *parameter_maximum,
+               double *tangents,
+               double *maximum_tangent,
+               double *current_cost_temperature,
+               double *initial_cost_temperature,
+               double *temperature_scale_cost,
+               double *current_user_parameter_temp,
+               double *initial_user_parameter_temp,
+               double *temperature_scale_parameters,
+               ALLOC_INT * number_parameters,
+               int *parameter_type,
+               LONG_INT * index_cost_acceptances,
+               LONG_INT * index_parameter_generations,
+               STATE * last_saved_state,
+               STATE * best_generated_state, USER_DEFINES * OPTIONS);
+
+void
+  cost_derivatives (double (*user_cost_function)
+
+                     
+                    (double *, double *, double *, double *, double *,
+                     ALLOC_INT *, int *, int *, int *, USER_DEFINES *),
+                    double *parameter_minimum, double *parameter_maximum,
+                    double *tangents, double *curvature,
+                    double *maximum_tangent, ALLOC_INT * number_parameters,
+                    int *parameter_type, int *exit_status,
+                    int *curvature_flag, int *valid_state_generated_flag,
+                    LONG_INT * number_invalid_generated_states,
+                    STATE * current_generated_state,
+                    STATE * best_generated_state, FILE * ptr_asa_out,
+                    USER_DEFINES * OPTIONS);
+
+double generate_asa_state (double (*user_random_generator) (LONG_INT *),
+                           LONG_INT * seed, double *temp);
+
+int
+  asa_exit (double (*user_cost_function)
+
+             
+            (double *, double *, double *, double *, double *, ALLOC_INT *,
+             int *, int *, int *, USER_DEFINES *), double *final_cost,
+            double *parameter_initial_final, double *parameter_minimum,
+            double *parameter_maximum, double *tangents, double *curvature,
+            double *maximum_tangent, double *current_cost_temperature,
+            double *initial_user_parameter_temp,
+            double *current_user_parameter_temp,
+            double *accepted_to_generated_ratio,
+            ALLOC_INT * number_parameters, int *parameter_type,
+            int *valid_state_generated_flag, int *exit_status,
+            ALLOC_INT * index_exit_v, ALLOC_INT * start_sequence,
+            LONG_INT * number_accepted, LONG_INT * best_number_accepted_saved,
+            LONG_INT * index_cost_acceptances, LONG_INT * number_generated,
+            LONG_INT * number_invalid_generated_states,
+            LONG_INT * index_parameter_generations,
+            LONG_INT * best_number_generated_saved,
+            STATE * current_generated_state, STATE * last_saved_state,
+            STATE * best_generated_state, FILE * ptr_asa_out,
+            USER_DEFINES * OPTIONS);
+
+void Exit_ASA (char *statement);
+
+int asa_test_asa_options (LONG_INT * seed,
+                          double *parameter_initial_final,
+                          double *parameter_minimum,
+                          double *parameter_maximum,
+                          double *tangents,
+                          double *curvature,
+                          ALLOC_INT * number_parameters,
+                          int *parameter_type,
+                          int *valid_state_generated_flag,
+                          int *exit_status,
+                          FILE * ptr_asa_out, USER_DEFINES * OPTIONS);
+
+int cost_function_test (double cost,
+                        double *parameter,
+                        double *parameter_minimum,
+                        double *parameter_maximum,
+                        ALLOC_INT * number_parameters,
+                        double *xnumber_parameters);
+
+void print_string (FILE * ptr_asa_out, char *string);
+void print_string_index (FILE * ptr_asa_out, char *string, ALLOC_INT index);
+
+#if ASA_PRINT
+void print_state (double *parameter_minimum,
+                  double *parameter_maximum,
+                  double *tangents,
+                  double *curvature,
+                  double *current_cost_temperature,
+                  double *current_user_parameter_temp,
+                  double *accepted_to_generated_ratio,
+                  ALLOC_INT * number_parameters,
+                  int *curvature_flag,
+                  LONG_INT * number_accepted,
+                  LONG_INT * index_cost_acceptances,
+                  LONG_INT * number_generated,
+                  LONG_INT * number_invalid_generated_states,
+                  STATE * last_saved_state,
+                  STATE * best_generated_state,
+                  FILE * ptr_asa_out, USER_DEFINES * OPTIONS);
+
+void print_asa_options (FILE * ptr_asa_out, USER_DEFINES * OPTIONS);
+#endif /* ASA_PRINT */
+
+
+#if MULTI_MIN
+static int multi_compare (const void *cost_ii, const void *cost_jj);
+double *multi_cost_qsort;
+#endif
+
+#if ASA_PARALLEL
+static int sort_parallel (const void *cost_ii, const void *cost_jj);
+#endif
+
+#else /* HAVE_ANSI */
+#endif /* HAVE_ANSI */
+
+#endif /* _ASA_H_ */
diff --git a/_darcs/pristine/asa_usr.h b/_darcs/pristine/asa_usr.h
new file mode 100644
--- /dev/null
+++ b/_darcs/pristine/asa_usr.h
@@ -0,0 +1,293 @@
+#ifndef _ASA_USER_H_
+#define _ASA_USER_H_
+
+/***********************************************************************
+* Adaptive Simulated Annealing (ASA)
+* Lester Ingber <ingber@ingber.com>
+* Copyright (c) 1993-2004 Lester Ingber.  All Rights Reserved.
+* The LICENSE file must be included with ASA code.
+***********************************************************************/
+
+ /* $Id: asa_usr.h,v 25.15 2004/09/23 18:10:45 ingber Exp ingber $ */
+
+ /* asa_usr.h for Adaptive Simulated Annealing */
+
+#include "asa_usr_asa.h"
+
+#define SHUFFLE 256             /* size of random array */
+
+#if ASA_TEMPLATE_ASA_OUT_PID
+#include <sys/types.h>
+#endif
+
+#if TIME_CALC
+ /* print the time every PRINT_FREQUENCY function evaluations
+    Define PRINT_FREQUENCY to 0 to not print out the time. */
+#define PRINT_FREQUENCY ((LONG_INT) 1000)
+#endif
+
+#if USER_ACCEPTANCE_TEST
+#define MIN(x,y)	((x) < (y) ? (x) : (y))
+#endif
+
+ /* system function prototypes */
+
+#if ASA_TEMPLATE_ASA_OUT_PID
+int getpid ();
+#endif
+
+#if HAVE_ANSI
+
+
+#if IO_PROTOTYPES
+#if OPTIONS_FILE
+int fscanf ();
+#endif
+#endif
+
+ /* user-defined */
+double USER_COST_FUNCTION (double *cost_parameters,
+                           double *parameter_lower_bound,
+                           double *parameter_upper_bound,
+                           double *cost_tangents,
+                           double *cost_curvature,
+                           ALLOC_INT * parameter_dimension,
+                           int *parameter_int_real,
+                           int *cost_flag,
+                           int *exit_code, USER_DEFINES * USER_OPTIONS);
+#if ASA_LIB
+int
+asa_main (
+           hs_cost_func *func, 
+           int number_parameters,
+           double *upper_bounds,
+           double *lower_bounds,
+           int *type,
+           double *main_cost_value,
+           double *main_cost_parameters, 
+           int *main_exit_code,
+           long int rand_seed
+  );
+#else
+int main (int argc, char **argv);
+#endif
+
+#if ASA_TEMPLATE_LIB
+int main ();
+#endif
+
+ /* possibly with accompanying data file */
+int initialize_parameters (double *cost_parameters,
+                           double *parameter_lower_bound,
+                           double *parameter_upper_bound,
+                           double *cost_tangents,
+                           double *cost_curvature,
+                           ALLOC_INT * parameter_dimension,
+                           int *parameter_int_real,
+#if OPTIONS_FILE_DATA
+                           FILE * ptr_options,
+#endif
+                           USER_DEFINES * USER_OPTIONS);
+
+//double myrand (LONG_INT * rand_seed);
+//double randflt (LONG_INT * rand_seed);
+//double resettable_randflt (LONG_INT * rand_seed, int reset);
+
+#if USER_COST_SCHEDULE
+double user_cost_schedule (double test_temperature,
+                           USER_DEFINES * USER_OPTIONS);
+#endif
+
+#if USER_ACCEPTANCE_TEST
+void user_acceptance_test (double current_cost,
+                           double *parameter_lower_bound,
+                           double *parameter_upper_bound,
+                           ALLOC_INT * parameter_dimension,
+                           USER_DEFINES * USER_OPTIONS);
+#endif
+
+#if USER_GENERATING_FUNCTION
+double user_generating_distrib (LONG_INT * seed,
+                                ALLOC_INT * parameter_dimension,
+                                ALLOC_INT index_v,
+                                double temperature_v,
+                                double init_param_temp_v,
+                                double temp_scale_params_v,
+                                double parameter_v,
+                                double parameter_range_v,
+                                double *last_saved_parameter,
+                                USER_DEFINES * USER_OPTIONS);
+#endif
+
+#if USER_REANNEAL_COST
+int user_reanneal_cost (double *cost_best,
+                        double *cost_last,
+                        double *initial_cost_temperature,
+                        double *current_cost_temperature,
+                        USER_DEFINES * USER_OPTIONS);
+#endif
+
+#if USER_REANNEAL_PARAMETERS
+double user_reanneal_params (double current_temp,
+                             double tangent,
+                             double max_tangent, USER_DEFINES * USER_OPTIONS);
+#endif
+
+#if ASA_TEMPLATE_SAMPLE
+void sample (FILE * ptr_out, FILE * ptr_asa);
+#endif
+
+void Exit_USER (char *statement);
+
+#else /* HAVE_ANSI */
+#endif /* HAVE_ANSI */
+
+void Exit_USER ();
+
+#if SELF_OPTIMIZE
+#if TIME_CALC
+#define RECUR_PRINT_FREQUENCY ((LONG_INT) 1)
+#endif
+
+#if HAVE_ANSI                   /* HAVE_ANSI SELF_OPTIMIZE */
+double RECUR_USER_COST_FUNCTION (double *recur_cost_parameters,
+                                 double *recur_parameter_lower_bound,
+                                 double *recur_parameter_upper_bound,
+                                 double *recur_cost_tangents,
+                                 double *recur_cost_curvature,
+                                 ALLOC_INT * recur_parameter_dimension,
+                                 int *recur_parameter_int_real,
+                                 int *recur_cost_flag,
+                                 int *recur_exit_code,
+                                 USER_DEFINES * RECUR_USER_OPTIONS);
+
+int recur_initialize_parameters (double *recur_cost_parameters,
+                                 double *recur_parameter_lower_bound,
+                                 double *recur_parameter_upper_bound,
+                                 double *recur_cost_tangents,
+                                 double *recur_cost_curvature,
+                                 ALLOC_INT * recur_parameter_dimension,
+                                 int *recur_parameter_int_real,
+#if RECUR_OPTIONS_FILE_DATA
+                                 FILE * recur_ptr_options,
+#endif
+                                 USER_DEFINES * RECUR_USER_OPTIONS);
+
+#if USER_COST_SCHEDULE
+double recur_user_cost_schedule (double test_temperature,
+                                 USER_DEFINES * RECUR_USER_OPTIONS);
+#endif
+
+#if USER_ACCEPTANCE_TEST
+void recur_user_acceptance_test (double current_cost,
+                                 double *recur_parameter_lower_bound,
+                                 double *recur_parameter_upper_bound,
+                                 ALLOC_INT * recur_parameter_dimension,
+                                 USER_DEFINES * RECUR_USER_OPTIONS);
+#endif
+
+#if USER_GENERATING_FUNCTION
+double recur_user_generating_distrib (LONG_INT * seed,
+                                      ALLOC_INT * recur_parameter_dimension,
+                                      ALLOC_INT index_v,
+                                      double temperature_v,
+                                      double init_param_temp_v,
+                                      double temp_scale_params_v,
+                                      double parameter_v,
+                                      double parameter_range_v,
+                                      double *last_saved_parameter,
+                                      USER_DEFINES * RECUR_USER_OPTIONS);
+#endif
+
+#if USER_REANNEAL_COST
+int recur_user_reanneal_cost (double *cost_best,
+                              double *cost_last,
+                              double *initial_cost_temperature,
+                              double *current_cost_temperature,
+                              USER_DEFINES * RECUR_USER_OPTIONS);
+#endif
+
+#if USER_REANNEAL_PARAMETERS
+double recur_user_reanneal_params (double current_temp,
+                                   double tangent,
+                                   double max_tangent,
+                                   USER_DEFINES * RECUR_USER_OPTIONS);
+#endif
+
+#else /* HAVE_ANSI SELF_OPTIMIZE */
+
+double RECUR_USER_COST_FUNCTION ();
+int recur_initialize_parameters ();
+
+#if USER_COST_SCHEDULE
+double recur_user_cost_schedule ();
+#endif
+
+#if USER_ACCEPTANCE_TEST
+void recur_user_acceptance_test ();
+#endif
+
+#if USER_GENERATING_FUNCTION
+double recur_user_generating_distrib ();
+#endif
+
+#if USER_REANNEAL_COST
+int recur_user_reanneal_cost ();
+#endif
+
+#if USER_REANNEAL_PARAMETERS
+double recur_user_reanneal_params ();
+#endif
+
+#endif /* HAVE_ANSI */
+#endif /* SELF_OPTIMIZE */
+
+#if FITLOC
+#if HAVE_ANSI
+double
+  calcf (double (*user_cost_function)
+
+          
+         (double *, double *, double *, double *, double *, ALLOC_INT *,
+          int *, int *, int *, USER_DEFINES *), double *cost_parameters,
+         double *parameter_lower_bound, double *parameter_upper_bound,
+         double *cost_tangents, double *cost_curvature,
+         ALLOC_INT * parameter_dimension, int *parameter_int_real,
+         int *cost_flag, int *exit_code, USER_DEFINES * USER_OPTIONS,
+         FILE * ptr_out);
+
+double
+  fitloc (double (*user_cost_function)
+
+           
+          (double *, double *, double *, double *, double *, ALLOC_INT *,
+           int *, int *, int *, USER_DEFINES *), double *cost_parameters,
+          double *parameter_lower_bound, double *parameter_upper_bound,
+          double *cost_tangents, double *cost_curvature,
+          ALLOC_INT * parameter_dimension, int *parameter_int_real,
+          int *cost_flag, int *exit_code, USER_DEFINES * USER_OPTIONS,
+          FILE * ptr_out);
+
+int
+  simplex (double (*user_cost_function)
+
+            
+           (double *, double *, double *, double *, double *, ALLOC_INT *,
+            int *, int *, int *, USER_DEFINES *), double *cost_parameters,
+           double *parameter_lower_bound, double *parameter_upper_bound,
+           double *cost_tangents, double *cost_curvature,
+           ALLOC_INT * parameter_dimension, int *parameter_int_real,
+           int *cost_flag, int *exit_code, USER_DEFINES * USER_OPTIONS,
+           FILE * ptr_out, double tol1, double tol2, int no_progress,
+           double alpha, double beta1, double beta2, double gamma,
+           double delta);
+#else /* HAVE_ANSI */
+
+double calcf ();
+double fitloc ();
+int simplex ();
+
+#endif /* HAVE_ANSI */
+#endif /* FITLOC */
+
+#endif /* _ASA_USER_H_ */
diff --git a/_darcs/pristine/asa_usr_asa.h b/_darcs/pristine/asa_usr_asa.h
new file mode 100644
--- /dev/null
+++ b/_darcs/pristine/asa_usr_asa.h
@@ -0,0 +1,682 @@
+#ifndef _ASA_USER_ASA_H_
+#define _ASA_USER_ASA_H_
+
+/***********************************************************************
+* Adaptive Simulated Annealing (ASA)
+* Lester Ingber <ingber@ingber.com>
+* Copyright (c) 1993-2004 Lester Ingber.  All Rights Reserved.
+* The LICENSE file must be included with ASA code.
+***********************************************************************/
+
+ /* $Id: asa_usr_asa.h,v 25.15 2004/09/23 18:10:49 ingber Exp ingber $ */
+
+ /* asa_usr_asa.h for Adaptive Simulated Annealing */
+
+#include <errno.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>             /* misc defs on most machines */
+#include <string.h>
+
+/* required if use machine-defined {DBL_EPSILON DBL_MIN DBL_MAX} */
+/* #include <float.h> */
+
+/* test for memory leaks */
+/* #include "/usr/local/include/leak.h" */
+
+#define	TRUE			1
+#define	FALSE			0
+
+#define MIN(x,y)	((x) < (y) ? (x) : (y))
+#define MAX(x,y)	((x) > (y) ? (x) : (y))
+
+ /* DEFAULT PARAMETERS SETTINGS */
+
+ /* Pre-Compile Options */
+
+ /* Special ASA_TEMPLATEs */
+
+#ifndef MY_TEMPLATE
+#define MY_TEMPLATE TRUE
+#endif
+#if MY_TEMPLATE                 /* MY_TEMPLATE_asa_user */
+
+// #include <HsFFI.h>
+
+typedef double hs_cost_func(double *x, int *flag);
+
+/* #define ASA_LIB TRUE */
+#define ASA_TEST FALSE
+#define ASA_LIB TRUE
+#define ASA_OUT  "STDOUT"
+#define USER_OUT "STDOUT"
+#define FITLOC TRUE
+#define COST_FILE FALSE
+// #define ASA_PRINT FALSE
+// #define USER_ASA_OUT TRUE 
+#define OPTIONS_FILE FALSE
+#define OPTIONAL_PTR_TYPE hs_cost_func
+#define OPTIONAL_DATA_PTR TRUE
+#define QUENCH_COST TRUE
+#define QUENCH_PARAMETERS TRUE
+
+
+  /* you can add your own set of #define here */
+#endif /* MY_TEMPLATE */
+
+#ifndef ASA_TEMPLATE_LIB
+#define ASA_TEMPLATE_LIB FALSE
+#endif
+#if ASA_TEMPLATE_LIB
+#define ASA_LIB TRUE
+#define ASA_TEST TRUE
+#endif
+
+#ifndef ASA_TEMPLATE_ASA_OUT_PID
+#define ASA_TEMPLATE_ASA_OUT_PID FALSE
+#endif
+#if ASA_TEMPLATE_ASA_OUT_PID
+#define USER_ASA_OUT TRUE
+#endif
+
+#ifndef ASA_TEMPLATE_MULTIPLE
+#define ASA_TEMPLATE_MULTIPLE FALSE
+#endif
+#if ASA_TEMPLATE_MULTIPLE
+#define COST_FILE FALSE
+#define USER_ASA_OUT TRUE
+#define ASA_TEST TRUE
+#define QUENCH_COST TRUE
+#define QUENCH_PARAMETERS TRUE
+#define OPTIONS_FILE FALSE
+#endif
+
+#ifndef ASA_TEMPLATE_SELFOPT
+#define ASA_TEMPLATE_SELFOPT FALSE
+#endif
+#if ASA_TEMPLATE_SELFOPT
+#define COST_FILE FALSE
+#define SELF_OPTIMIZE TRUE
+#define OPTIONAL_DATA_DBL TRUE
+#define USER_ASA_OUT TRUE
+#define ASA_TEST TRUE
+#define OPTIONS_FILE FALSE
+#endif
+
+#ifndef ASA_TEMPLATE_SAMPLE
+#define ASA_TEMPLATE_SAMPLE FALSE
+#endif
+#if ASA_TEMPLATE_SAMPLE
+#define COST_FILE FALSE
+#define ASA_SAMPLE TRUE
+#define USER_ACCEPTANCE_TEST TRUE
+#define USER_COST_SCHEDULE TRUE
+#define OPTIONS_FILE_DATA FALSE
+#define USER_ACCEPT_ASYMP_EXP TRUE
+#endif
+
+#ifndef ASA_TEMPLATE_PARALLEL
+#define ASA_TEMPLATE_PARALLEL FALSE
+#endif
+#if ASA_TEMPLATE_PARALLEL
+#define COST_FILE FALSE
+#define ASA_TEST TRUE
+#define ASA_PARALLEL TRUE
+#endif
+
+#ifndef ASA_TEMPLATE_SAVE
+#define ASA_TEMPLATE_SAVE FALSE
+#endif
+#if ASA_TEMPLATE_SAVE
+#define COST_FILE FALSE
+#define ASA_TEST TRUE
+#define ASA_SAVE TRUE
+#define QUENCH_PARAMETERS TRUE
+#define QUENCH_COST TRUE
+#endif
+
+#ifndef ASA_TEMPLATE_QUEUE
+#define ASA_TEMPLATE_QUEUE FALSE
+#endif
+#if ASA_TEMPLATE_QUEUE
+#define ASA_QUEUE TRUE
+#define ASA_RESOLUTION FALSE
+#define ASA_TEST TRUE
+#define COST_FILE FALSE
+#define ASA_PRINT_MORE TRUE
+#endif
+
+#ifndef ASA_TEST_POINT
+#define ASA_TEST_POINT FALSE
+#endif
+#if ASA_TEST_POINT
+#define ASA_TEST TRUE
+#define COST_FILE FALSE
+#define SMALL_FLOAT 1.0E-50
+#define QUENCH_COST TRUE
+#endif
+
+ /* Standard Pre-Compile Options */
+
+#ifndef USER_COST_FUNCTION
+#define USER_COST_FUNCTION cost_function
+#endif
+
+#if SELF_OPTIMIZE
+#ifndef RECUR_USER_COST_FUNCTION
+#define RECUR_USER_COST_FUNCTION recur_cost_function
+#endif
+#endif
+
+#ifndef INCL_STDOUT
+#define INCL_STDOUT TRUE
+#endif
+#if INCL_STDOUT
+#define TIME_CALC FALSE
+#endif
+
+#ifndef OPTIONS_FILE
+#define OPTIONS_FILE TRUE
+#endif
+
+#if OPTIONS_FILE
+#ifndef OPTIONS_FILE_DATA
+#define OPTIONS_FILE_DATA TRUE
+#endif
+#else
+#define OPTIONS_FILE_DATA FALSE
+#endif
+
+#ifndef RECUR_OPTIONS_FILE
+#define RECUR_OPTIONS_FILE FALSE
+#endif
+
+#if RECUR_OPTIONS_FILE
+#ifndef RECUR_OPTIONS_FILE_DATA
+#define RECUR_OPTIONS_FILE_DATA FALSE
+#endif
+#else
+#define RECUR_OPTIONS_FILE_DATA FALSE
+#endif
+
+#ifndef COST_FILE
+#define COST_FILE TRUE
+#endif
+
+#ifndef ASA_LIB
+#define ASA_LIB FALSE
+#endif
+
+#ifndef HAVE_ANSI
+#define HAVE_ANSI TRUE
+#endif
+
+#ifndef IO_PROTOTYPES
+#define IO_PROTOTYPES FALSE
+#endif
+
+#ifndef TIME_CALC
+#define TIME_CALC FALSE
+#endif
+
+#ifndef INT_LONG
+#define INT_LONG TRUE
+#endif
+
+#if INT_LONG
+#define LONG_INT long int
+#else
+#define LONG_INT int
+#endif
+
+#ifndef INT_ALLOC
+#define INT_ALLOC FALSE
+#endif
+
+#if INT_ALLOC
+#define ALLOC_INT int
+#else
+#define ALLOC_INT LONG_INT
+#endif
+
+ /* You can define SMALL_FLOAT to better correlate to your machine's
+    precision, i.e., as used in asa */
+#ifndef SMALL_FLOAT
+#define SMALL_FLOAT 1.0E-18
+#endif
+
+ /* You can define your machine's maximum and minimum doubles here */
+#ifndef MIN_DOUBLE
+#define MIN_DOUBLE ((double) SMALL_FLOAT)
+#endif
+
+#ifndef MAX_DOUBLE
+#define MAX_DOUBLE ((double) 1.0 / (double) SMALL_FLOAT)
+#endif
+
+#ifndef EPS_DOUBLE
+#define EPS_DOUBLE ((double) SMALL_FLOAT)
+#endif
+
+#ifndef CHECK_EXPONENT
+#define CHECK_EXPONENT FALSE
+#endif
+
+#ifndef ASA_TEST
+#define ASA_TEST FALSE
+#endif
+
+#ifndef ASA_TEMPLATE
+#define ASA_TEMPLATE FALSE
+#endif
+
+#ifndef USER_INITIAL_COST_TEMP
+#define USER_INITIAL_COST_TEMP FALSE
+#endif
+
+#ifndef RATIO_TEMPERATURE_SCALES
+#define RATIO_TEMPERATURE_SCALES FALSE
+#endif
+
+#ifndef USER_INITIAL_PARAMETERS_TEMPS
+#define USER_INITIAL_PARAMETERS_TEMPS FALSE
+#endif
+
+#ifndef DELTA_PARAMETERS
+#define DELTA_PARAMETERS FALSE
+#endif
+
+#ifndef QUENCH_PARAMETERS
+#define QUENCH_PARAMETERS FALSE
+#endif
+
+#ifndef QUENCH_COST
+#define QUENCH_COST FALSE
+#endif
+
+#ifndef QUENCH_PARAMETERS_SCALE
+#define QUENCH_PARAMETERS_SCALE TRUE
+#endif
+
+#ifndef QUENCH_COST_SCALE
+#define QUENCH_COST_SCALE TRUE
+#endif
+
+#ifndef OPTIONAL_DATA_DBL
+#define OPTIONAL_DATA_DBL FALSE
+#endif
+
+#ifndef OPTIONAL_DATA_INT
+#define OPTIONAL_DATA_INT FALSE
+#endif
+
+#ifndef OPTIONAL_DATA_PTR
+#define OPTIONAL_DATA_PTR FALSE
+#endif
+#if OPTIONAL_DATA_PTR
+/* user must define USER_TYPE; if a struct, it must be declared above */
+#ifndef OPTIONAL_PTR_TYPE
+#define OPTIONAL_PTR_TYPE USER_TYPE
+#endif
+#endif /* OPTIONAL_DATA_PTR */
+
+#ifndef USER_REANNEAL_COST
+#define USER_REANNEAL_COST FALSE
+#endif
+
+#ifndef USER_REANNEAL_PARAMETERS
+#define USER_REANNEAL_PARAMETERS FALSE
+#endif
+
+#ifndef MAXIMUM_REANNEAL_INDEX
+#define MAXIMUM_REANNEAL_INDEX 50000
+#endif
+
+#ifndef REANNEAL_SCALE
+#define REANNEAL_SCALE 10
+#endif
+
+#ifndef USER_COST_SCHEDULE
+#define USER_COST_SCHEDULE FALSE
+#endif
+
+#ifndef USER_ACCEPT_ASYMP_EXP
+#define USER_ACCEPT_ASYMP_EXP FALSE
+#endif
+
+#ifndef USER_ACCEPT_THRESHOLD
+#define USER_ACCEPT_THRESHOLD FALSE
+#endif
+
+#ifndef USER_ACCEPTANCE_TEST
+#define USER_ACCEPTANCE_TEST FALSE
+#endif
+
+#ifndef USER_GENERATING_FUNCTION
+#define USER_GENERATING_FUNCTION FALSE
+#endif
+
+ /* in asa.c, field-width.precision = G_FIELD.G_PRECISION */
+#ifndef G_FIELD
+#define G_FIELD 12
+#endif
+#ifndef G_PRECISION
+#define G_PRECISION 7
+#endif
+
+#define INTEGER_TYPE		((int) 1)
+#define REAL_TYPE		((int) -1)
+#define INTEGER_NO_REANNEAL	((int) 2)
+#define REAL_NO_REANNEAL	((int) -2)
+
+ /* Set this to TRUE to self-optimize the Program Options */
+#ifndef SELF_OPTIMIZE
+#define SELF_OPTIMIZE FALSE
+#endif
+
+#ifndef USER_OUT
+#define USER_OUT "asa_usr_out"
+#endif
+
+#ifndef USER_ASA_OUT
+#define USER_ASA_OUT FALSE
+#endif
+
+#ifndef ASA_SAMPLE
+#define ASA_SAMPLE FALSE
+#endif
+
+#ifndef ASA_QUEUE
+#define ASA_QUEUE FALSE
+#endif
+
+#ifndef ASA_RESOLUTION
+#define ASA_RESOLUTION FALSE
+#endif
+
+#ifndef ASA_PARALLEL
+#define ASA_PARALLEL FALSE
+#endif
+
+#ifndef ASA_SAVE_OPT
+#define ASA_SAVE_OPT FALSE
+#endif
+#if ASA_SAVE_OPT
+#define ASA_SAVE TRUE
+#endif
+
+#ifndef ASA_SAVE_BACKUP
+#define ASA_SAVE_BACKUP FALSE
+#endif
+#if ASA_SAVE_BACKUP
+#define ASA_SAVE TRUE
+#endif
+
+#ifndef ASA_SAVE
+#define ASA_SAVE FALSE
+#endif
+
+#ifndef ASA_PIPE
+#define ASA_PIPE FALSE
+#endif
+
+#ifndef ASA_PIPE_FILE
+#define ASA_PIPE_FILE FALSE
+#endif
+
+#ifndef FDLIBM_POW
+#define FDLIBM_POW FALSE
+#endif
+#if FDLIBM_POW
+#define F_POW s_pow
+#else
+#define F_POW pow
+#endif
+
+#ifndef FDLIBM_LOG
+#define FDLIBM_LOG FALSE
+#endif
+#if FDLIBM_LOG
+#define F_LOG s_log
+#else
+#define F_LOG log
+#endif
+
+#ifndef FDLIBM_EXP
+#define FDLIBM_EXP FALSE
+#endif
+#if FDLIBM_EXP
+#define F_EXP s_exp
+#else
+#define F_EXP exp
+#endif
+
+#ifndef FITLOC
+#define FITLOC FALSE
+#endif
+
+#ifndef FITLOC_ROUND
+#define FITLOC_ROUND TRUE
+#endif
+
+#ifndef FITLOC_PRINT
+#define FITLOC_PRINT TRUE
+#endif
+
+#ifndef MULTI_MIN
+#define MULTI_MIN FALSE
+#endif
+
+ /* Program Options */
+
+typedef struct {
+  LONG_INT Limit_Acceptances;
+  LONG_INT Limit_Generated;
+  int Limit_Invalid_Generated_States;
+  double Accepted_To_Generated_Ratio;
+
+  double Cost_Precision;
+  int Maximum_Cost_Repeat;
+  int Number_Cost_Samples;
+  double Temperature_Ratio_Scale;
+  double Cost_Parameter_Scale_Ratio;
+  double Temperature_Anneal_Scale;
+#if USER_INITIAL_COST_TEMP
+  double *User_Cost_Temperature;
+#endif
+
+  int Include_Integer_Parameters;
+  int User_Initial_Parameters;
+  ALLOC_INT Sequential_Parameters;
+  double Initial_Parameter_Temperature;
+#if RATIO_TEMPERATURE_SCALES
+  double *User_Temperature_Ratio;
+#endif
+#if USER_INITIAL_PARAMETERS_TEMPS
+  double *User_Parameter_Temperature;
+#endif
+
+  int Acceptance_Frequency_Modulus;
+  int Generated_Frequency_Modulus;
+  int Reanneal_Cost;
+  int Reanneal_Parameters;
+
+  double Delta_X;
+#if DELTA_PARAMETERS
+  double *User_Delta_Parameter;
+#endif
+  int User_Tangents;
+  int Curvature_0;
+
+#if QUENCH_PARAMETERS
+  double *User_Quench_Param_Scale;
+#endif
+#if QUENCH_COST
+  double *User_Quench_Cost_Scale;
+#endif
+
+  LONG_INT N_Accepted;
+  LONG_INT N_Generated;
+  int Locate_Cost;
+  int Immediate_Exit;
+
+  double *Best_Cost;
+  double *Best_Parameters;
+  double *Last_Cost;
+  double *Last_Parameters;
+
+#if OPTIONAL_DATA_DBL
+  ALLOC_INT Asa_Data_Dim_Dbl;
+  double *Asa_Data_Dbl;
+#endif
+#if OPTIONAL_DATA_INT
+  ALLOC_INT Asa_Data_Dim_Int;
+  LONG_INT *Asa_Data_Int;
+#endif
+#if OPTIONAL_DATA_PTR
+  ALLOC_INT Asa_Data_Dim_Ptr;
+  OPTIONAL_PTR_TYPE *Asa_Data_Ptr;
+#endif
+#if USER_ASA_OUT
+  char *Asa_Out_File;
+#endif
+#if USER_COST_SCHEDULE
+  double (*Cost_Schedule) ();
+#endif
+#if USER_ACCEPT_ASYMP_EXP
+  double Asymp_Exp_Param;
+#endif
+#if USER_ACCEPTANCE_TEST
+  void (*Acceptance_Test) ();
+  int User_Acceptance_Flag;
+  int Cost_Acceptance_Flag;
+  double Cost_Temp_Curr;
+  double Cost_Temp_Init;
+  double Cost_Temp_Scale;
+  double Prob_Bias;
+  LONG_INT *Random_Seed;
+#endif
+#if USER_GENERATING_FUNCTION
+  double (*Generating_Distrib) ();
+#endif
+#if USER_REANNEAL_COST
+  int (*Reanneal_Cost_Function) ();
+#endif
+#if USER_REANNEAL_PARAMETERS
+  double (*Reanneal_Params_Function) ();
+#endif
+#if ASA_SAMPLE
+  double Bias_Acceptance;
+  double *Bias_Generated;
+  double Average_Weights;
+  double Limit_Weights;
+#endif
+#if ASA_QUEUE
+  ALLOC_INT Queue_Size;
+  double *Queue_Resolution;
+#endif
+#if ASA_RESOLUTION
+  double *Coarse_Resolution;
+#endif
+#if FITLOC
+  int Fit_Local;
+  int Iter_Max;
+  double Penalty;
+#endif
+#if MULTI_MIN
+  int Multi_Number;
+  double *Multi_Cost;
+  double **Multi_Params;
+  double *Multi_Grid;
+  int Multi_Specify;
+#endif
+#if ASA_PARALLEL
+  int Gener_Mov_Avr;
+  LONG_INT Gener_Block;
+  LONG_INT Gener_Block_Max;
+#endif
+  int Asa_Recursive_Level;
+} USER_DEFINES;
+
+ /* system function prototypes */
+
+#if HAVE_ANSI
+
+/* This block gives trouble under some Ultrix */
+#if FALSE
+int fprintf (FILE * fp, const char *string, ...);
+int sprintf (char *s, const char *format, ...);
+FILE *popen (const char *command, const char *mode);
+void exit (int code);
+#endif
+
+#if IO_PROTOTYPES
+int fprintf ();
+int sprintf ();
+int fflush (FILE * fp);
+int fclose (FILE * fp);
+void exit ();
+int fread ();
+int fwrite ();
+int pclose ();
+#endif
+
+double
+  asa (double (*user_cost_function)
+
+        
+       (double *, double *, double *, double *, double *, ALLOC_INT *, int *,
+        int *, int *, USER_DEFINES *),
+       double (*user_random_generator) (LONG_INT *), LONG_INT * rand_seed,
+       double *parameter_initial_final, double *parameter_minimum,
+       double *parameter_maximum, double *tangents, double *curvature,
+       ALLOC_INT * number_parameters, int *parameter_type,
+       int *valid_state_generated_flag, int *exit_status,
+       USER_DEFINES * OPTIONS);
+
+#if TIME_CALC
+void print_time (char *message, FILE * ptr_out);
+#endif
+
+#if FDLIBM_POW
+double s_pow (double x, double y);
+#endif
+#if FDLIBM_LOG
+double s_log (double x);
+#endif
+#if FDLIBM_EXP
+double s_exp (double x);
+#endif
+
+#else /* HAVE_ANSI */
+
+#if IO_PROTOTYPES
+int fprintf ();
+int sprintf ();
+int fflush ();
+int fclose ();
+int fread ();
+int fwrite ();
+FILE *popen ();
+int pclose ();
+#endif
+
+double asa ();
+
+#if TIME_CALC
+void print_time ();
+#endif
+
+#if FDLIBM_POW
+double s_pow ();
+#endif
+#if FDLIBM_LOG
+double s_log ();
+#endif
+#if FDLIBM_EXP
+double s_exp ();
+#endif
+
+#endif /* HAVE_ANSI */
+
+#endif /* _ASA_USER_ASA_H_ */
diff --git a/_darcs/pristine/hs_asa.c b/_darcs/pristine/hs_asa.c
new file mode 100644
--- /dev/null
+++ b/_darcs/pristine/hs_asa.c
@@ -0,0 +1,4369 @@
+/***********************************************************************
+* Adaptive Simulated Annealing (ASA)
+* Lester Ingber <ingber@ingber.com>
+* Copyright (c) 1993-2004 Lester Ingber.  All Rights Reserved.
+* The LICENSE file must be included with ASA code.
+* Modified by John Meacham for Haskell interface
+***********************************************************************/
+
+#include "asa_usr.h"
+
+
+
+
+char user_exit_msg[160];        /* temp storage for exit messages */
+FILE *ptr_out;
+
+static double resettable_randflt (LONG_INT * rand_seed, int reset);
+static double randflt (LONG_INT * rand_seed);
+/***********************************************************************
+* main
+*	This is a sample calling program to optimize using ASA
+***********************************************************************/
+int
+asa_main (
+           hs_cost_func *func, 
+           int number_parameters,
+           double *upper_bounds,
+           double *lower_bounds,
+           int *type,
+           double *main_cost_value,
+           double *main_cost_parameters, 
+           int *main_exit_code,
+           long int initial_rand_seed
+  )
+{
+  int i;
+  int *exit_code;
+  ALLOC_INT n_param;
+#if ASA_TEMPLATE_SAMPLE
+  FILE *ptr_asa;
+#endif
+#if MULTI_MIN
+  int multi_index;
+#endif
+
+  /* pointer to array storage for asa arguments */
+  double *parameter_lower_bound, *parameter_upper_bound, *cost_parameters,
+    *cost_tangents, *cost_curvature;
+  double cost_value;
+
+  int initialize_parameters_value;
+
+  /* the number of parameters to optimize */
+  ALLOC_INT *parameter_dimension;
+
+  /* pointer to array storage for parameter type flags */
+  int *parameter_int_real;
+
+  /* valid flag for cost function */
+  int *cost_flag;
+
+  /* seed for random number generator */
+  LONG_INT *rand_seed;
+
+  USER_DEFINES *USER_OPTIONS;
+
+#if MY_TEMPLATE                 /* MY_TEMPLATE_main_decl */
+  /* add some declarations if required */
+#endif
+
+#if ASA_TEMPLATE_MULTIPLE
+  int n_asa, n_trajectory;
+  ALLOC_INT index;
+#if HAVE_ANSI
+  char asa_file[8] = "asa_x_y";
+#else
+  char asa_file[8];
+#endif /* HAVE_ANSI */
+#endif /* ASA_TEMPLATE_MULTIPLE */
+
+
+  if ((USER_OPTIONS =
+       (USER_DEFINES *) calloc (1, sizeof (USER_DEFINES))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): USER_DEFINES");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#if OPTIONAL_DATA_PTR
+#if ASA_TEMPLATE
+  USER_OPTIONS->Asa_Data_Dim_Ptr = 256;
+  if ((USER_OPTIONS->Asa_Data_Ptr =
+       (OPTIONAL_PTR_TYPE *) calloc (USER_OPTIONS->Asa_Data_Dim_Ptr,
+                                     sizeof (OPTIONAL_PTR_TYPE))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): USER_OPTIONS->Asa_Data_Ptr");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#endif /* ASA_TEMPLATE */
+#endif /* OPTIONAL_DATA_PTR */
+
+
+  if (!strcmp (USER_OUT, "STDOUT")) {
+#if INCL_STDOUT
+    ptr_out = stdout;
+#endif /* INCL_STDOUT */
+  } else {
+    ptr_out = fopen (USER_OUT, "w");
+  }
+
+
+  fflush (ptr_out);
+
+  if ((rand_seed = (ALLOC_INT *) calloc (1, sizeof (ALLOC_INT))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): rand_seed");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  *rand_seed = initial_rand_seed;
+
+  /* initialize random number generator with first call */
+  resettable_randflt (rand_seed, 1);
+
+  /* Initialize the users parameters, allocating space, etc.
+     Note that the default is to have asa generate the initial
+     cost_parameters that satisfy the user's constraints. */
+
+  if ((parameter_dimension =
+       (ALLOC_INT *) calloc (1, sizeof (ALLOC_INT))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): parameter_dimension");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  if ((exit_code = (int *) calloc (1, sizeof (int))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): exit_code");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  if ((cost_flag = (int *) calloc (1, sizeof (int))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): cost_flag");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+
+  //USER_OPTIONS->Limit_Acceptances = 10000; 
+  USER_OPTIONS->Limit_Acceptances = 1000;
+  USER_OPTIONS->Limit_Generated = 99999;
+  USER_OPTIONS->Limit_Invalid_Generated_States = 1000;
+  /* USER_OPTIONS->Accepted_To_Generated_Ratio = 1.0E-6; */
+  USER_OPTIONS->Accepted_To_Generated_Ratio = 1.0E-4;
+
+  USER_OPTIONS->Cost_Precision = 1.0E-18;
+  USER_OPTIONS->Maximum_Cost_Repeat = 5;
+  USER_OPTIONS->Number_Cost_Samples = 5;
+  USER_OPTIONS->Temperature_Ratio_Scale = 1.0E-5;
+  USER_OPTIONS->Cost_Parameter_Scale_Ratio = 1.0;
+  USER_OPTIONS->Temperature_Anneal_Scale = 100.0;
+
+  USER_OPTIONS->Include_Integer_Parameters = FALSE;
+  USER_OPTIONS->User_Initial_Parameters = FALSE;
+  USER_OPTIONS->Sequential_Parameters = -1;
+  USER_OPTIONS->Initial_Parameter_Temperature = 1.0;
+
+  USER_OPTIONS->Acceptance_Frequency_Modulus = 100;
+  USER_OPTIONS->Generated_Frequency_Modulus = 10000;
+  USER_OPTIONS->Reanneal_Cost = 1;
+  USER_OPTIONS->Reanneal_Parameters = TRUE;
+
+  USER_OPTIONS->Delta_X = 0.001;
+  USER_OPTIONS->User_Tangents = FALSE;
+  USER_OPTIONS->Curvature_0 = FALSE;
+
+
+  /* ALLOCATE STORAGE */
+
+
+#if USER_ASA_OUT
+  if ((USER_OPTIONS->Asa_Out_File =
+       (char *) calloc (80, sizeof (char))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): USER_OPTIONS->Asa_Out_File");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#endif
+
+  /* the number of parameters for the cost function */
+#if OPTIONS_FILE_DATA
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%s", read_option);
+
+#if INT_ALLOC
+  fscanf (ptr_options, "%d", &read_int);
+  *parameter_dimension = read_int;
+#else
+#if INT_LONG
+  fscanf (ptr_options, "%ld", &read_long);
+  *parameter_dimension = read_long;
+#else
+  fscanf (ptr_options, "%d", &read_int);
+  *parameter_dimension = read_int;
+#endif
+#endif
+
+#else /* OPTIONS_FILE_DATA */
+#endif /* OPTIONS_FILE_DATA */
+#if MY_TEMPLATE                 /* MY_TEMPLATE_dim */
+  *parameter_dimension = number_parameters;
+  /* If not using OPTIONS_FILE_DATA or data read from asa_opt,
+     insert the number of parameters for the cost_function */
+#endif /* MY_TEMPLATE dim */
+
+#if ASA_TEMPLATE_SAMPLE
+  *parameter_dimension = 2;
+  USER_OPTIONS->Limit_Acceptances = 2000;
+  USER_OPTIONS->User_Tangents = TRUE;
+  USER_OPTIONS->Limit_Weights = 1.0E-7;
+#endif
+#if ASA_TEMPLATE_PARALLEL
+  USER_OPTIONS->Gener_Block = 100;
+  USER_OPTIONS->Gener_Block_Max = 512;
+  USER_OPTIONS->Gener_Mov_Avr = 3;
+#endif
+
+  /* allocate parameter minimum space */
+  if ((parameter_lower_bound =
+       (double *) calloc (*parameter_dimension, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): parameter_lower_bound");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  /* allocate parameter maximum space */
+  if ((parameter_upper_bound =
+       (double *) calloc (*parameter_dimension, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): parameter_upper_bound");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  /* allocate parameter initial values; the parameter final values
+     will be stored here later */
+  if ((cost_parameters =
+       (double *) calloc (*parameter_dimension, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): cost_parameters");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  /* allocate the parameter types, real or integer */
+  if ((parameter_int_real =
+       (int *) calloc (*parameter_dimension, sizeof (int))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): parameter_int_real");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  /* allocate space for parameter cost_tangents -
+     used for reannealing */
+  if ((cost_tangents =
+       (double *) calloc (*parameter_dimension, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): cost_tangents");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+
+  if (USER_OPTIONS->Curvature_0 == FALSE || USER_OPTIONS->Curvature_0 == -1) {
+    /* allocate space for parameter cost_curvatures/covariance */
+    if ((cost_curvature =
+         (double *) calloc ((*parameter_dimension) *
+                            (*parameter_dimension),
+                            sizeof (double))) == NULL) {
+      strcpy (user_exit_msg, "main()/asa_main(): cost_curvature");
+      Exit_USER (user_exit_msg);
+      return (-2);
+    }
+  } else {
+    cost_curvature = (double *) NULL;
+  }
+
+#if USER_COST_SCHEDULE
+  USER_OPTIONS->Cost_Schedule = user_cost_schedule;
+#endif
+#if USER_ACCEPTANCE_TEST
+  USER_OPTIONS->Acceptance_Test = user_acceptance_test;
+#endif
+#if USER_ACCEPT_ASYMP_EXP
+  USER_OPTIONS->Asymp_Exp_Param = 1.0;
+#endif
+#if USER_GENERATING_FUNCTION
+  USER_OPTIONS->Generating_Distrib = user_generating_distrib;
+#endif
+#if USER_REANNEAL_COST
+  USER_OPTIONS->Reanneal_Cost_Function = user_reanneal_cost;
+#endif
+#if USER_REANNEAL_PARAMETERS
+  USER_OPTIONS->Reanneal_Params_Function = user_reanneal_params;
+#endif
+
+#if MY_TEMPLATE                 /* MY_TEMPLATE_pre_initialize */
+  /* last changes before entering initialize_parameters() */
+  USER_OPTIONS->Asa_Data_Ptr = func;
+  USER_OPTIONS->Asa_Data_Dim_Ptr = 1;
+  memcpy(parameter_lower_bound,lower_bounds,sizeof(double)*number_parameters);
+  memcpy(cost_parameters,lower_bounds,sizeof(double)*number_parameters);
+  memcpy(parameter_upper_bound,upper_bounds,sizeof(double)*number_parameters);
+  memcpy(parameter_int_real, type, sizeof(int)*number_parameters);
+#endif
+
+  initialize_parameters_value = initialize_parameters (cost_parameters,
+                                                       parameter_lower_bound,
+                                                       parameter_upper_bound,
+                                                       cost_tangents,
+                                                       cost_curvature,
+                                                       parameter_dimension,
+                                                       parameter_int_real,
+#if OPTIONS_FILE_DATA
+                                                       ptr_options,
+#endif
+                                                       USER_OPTIONS);
+
+  if (initialize_parameters_value == -2)
+    return (initialize_parameters_value);
+
+  for(i = 0; i < number_parameters; i++) {
+          USER_OPTIONS->User_Quench_Param_Scale[i] = 1.0;
+  }
+        USER_OPTIONS->User_Quench_Cost_Scale[0] = 1.0;
+
+  /* optimize the cost_function, returning the results in
+     cost_value and cost_parameters */
+#if ASA_TEMPLATE_MULTIPLE
+  /* multiple asa() quenched calls + multiple asa_out files
+     (To get longer quenched runs, decrease SMALL_FLOAT.) */
+  for (n_asa = 1; n_asa <= *parameter_dimension; n_asa++) {
+    asa_file[4] = 'A' + n_asa - 1;
+    USER_OPTIONS->User_Quench_Cost_Scale[0] = (double) n_asa;
+    for (index = 0; index < *parameter_dimension; ++index)
+      USER_OPTIONS->User_Quench_Param_Scale[index] = (double) n_asa;
+    for (n_trajectory = 0; n_trajectory < 3; ++n_trajectory) {
+      asa_file[6] = 'a' + n_trajectory;
+      strcpy (USER_OPTIONS->Asa_Out_File, asa_file);
+#endif
+
+#if ASA_TEMPLATE_ASA_OUT_PID
+      pid_file[0] = 'a';
+      pid_file[1] = 's';
+      pid_file[2] = 'a';
+      pid_file[3] = '_';
+      pid_file[4] = 'o';
+      pid_file[5] = 'u';
+      pid_file[6] = 't';
+      pid_file[7] = '_';
+
+      pid_int = getpid ();
+      if (pid_int < 0) {
+        pid_file[7] = '0';
+        pid_int = -pid_int;
+      }
+
+      strcpy (USER_OPTIONS->Asa_Out_File, pid_file);
+#endif
+      cost_value =
+        asa (USER_COST_FUNCTION,
+             randflt,
+             rand_seed,
+             cost_parameters,
+             parameter_lower_bound,
+             parameter_upper_bound,
+             cost_tangents,
+             cost_curvature,
+             parameter_dimension,
+             parameter_int_real, cost_flag, exit_code, USER_OPTIONS);
+      if (*exit_code == -1) {
+#if INCL_STDOUT
+        printf ("\n\n*** error in calloc in ASA ***\n\n");
+#endif /* INCL_STDOUT */
+        fprintf (ptr_out, "\n\n*** error in calloc in ASA ***\n\n");
+        fflush (ptr_out);
+        return (-1);
+      }
+#if MULTI_MIN
+      fprintf (ptr_out, "Multi_Specify = %d\n", USER_OPTIONS->Multi_Specify);
+#if INT_LONG
+      fprintf (ptr_out, "N_Accepted = %ld\n", USER_OPTIONS->N_Accepted);
+#else
+      fprintf (ptr_out, "N_Accepted = %d\n", USER_OPTIONS->N_Accepted);
+#endif
+#if ASA_RESOLUTION
+      for (n_param = 0; n_param < *parameter_dimension; ++n_param) {
+        fprintf (ptr_out,
+#if INT_ALLOC
+                 "Coarse_Resolution[%d] = %12.7g\n",
+#else
+#if INT_LONG
+                 "Coarse_Resolution[%ld] = %12.7g\n",
+#else
+                 "Coarse_Resolution[%d] = %12.7g\n",
+#endif
+#endif
+                 n_param, USER_OPTIONS->Coarse_Resolution[n_param]);
+      }
+#else /* ASA_RESOLUTION */
+      for (n_param = 0; n_param < *parameter_dimension; ++n_param) {
+        fprintf (ptr_out,
+#if INT_ALLOC
+                 "Multi_Grid[%d] = %12.7g\n",
+#else
+#if INT_LONG
+                 "Multi_Grid[%ld] = %12.7g\n",
+#else
+                 "Multi_Grid[%d] = %12.7g\n",
+#endif
+#endif
+                 n_param, USER_OPTIONS->Multi_Grid[n_param]);
+      }
+#endif /* ASA_RESOLUTION */
+      fprintf (ptr_out, "\n");
+      for (multi_index = 0; multi_index < USER_OPTIONS->Multi_Number;
+           ++multi_index) {
+        fprintf (ptr_out, "\n");
+        fprintf (ptr_out, "Multi_Cost[%d] = %12.7g\n",
+                 multi_index, USER_OPTIONS->Multi_Cost[multi_index]);
+        for (n_param = 0; n_param < *parameter_dimension; ++n_param) {
+          fprintf (ptr_out,
+#if INT_ALLOC
+                   "Multi_Params[%d][%d] = %12.7g\n",
+#else
+#if INT_LONG
+                   "Multi_Params[%d][%ld] = %12.7g\n",
+#else
+                   "Multi_Params[%d][%d] = %12.7g\n",
+#endif
+#endif
+                   multi_index, n_param,
+                   USER_OPTIONS->Multi_Params[multi_index][n_param]);
+        }
+      }
+      fprintf (ptr_out, "\n");
+      fflush (ptr_out);
+#endif /* MULTI_MIN */
+
+#if FITLOC
+      /* Fit_Local, Iter_Max and Penalty may be set adaptively */
+      USER_OPTIONS->Penalty = 1000;
+      USER_OPTIONS->Fit_Local = 0;
+      USER_OPTIONS->Iter_Max = 500;
+      if (USER_OPTIONS->Fit_Local >= 1) {
+        cost_value = fitloc (USER_COST_FUNCTION,
+                             cost_parameters,
+                             parameter_lower_bound,
+                             parameter_upper_bound,
+                             cost_tangents,
+                             cost_curvature,
+                             parameter_dimension,
+                             parameter_int_real,
+                             cost_flag, exit_code, USER_OPTIONS, ptr_out);
+      }
+#endif /* FITLOC */
+#if MY_TEMPLATE                 /* MY_TEMPLATE_post_asa */
+#endif
+      *main_cost_value = cost_value;
+      for (n_param = 0; n_param < *parameter_dimension; ++n_param) {
+        main_cost_parameters[n_param] = cost_parameters[n_param];
+      }
+      *main_exit_code = *exit_code;
+
+      fprintf (ptr_out, "exit code = %d\n", *exit_code);
+      fprintf (ptr_out, "final cost value = %-12.7g\n", cost_value);
+      fprintf (ptr_out, "%12s %12s\n","parameter","value");
+      for (n_param = 0; n_param < *parameter_dimension; ++n_param) {
+        fprintf (ptr_out,
+#if INT_ALLOC
+                 "%12d %12.7g\n",
+#else
+#if INT_LONG
+                 "%12ld %12.7g\n",
+#else
+                 "%12d %12.7g\n",
+#endif
+#endif
+                 n_param, cost_parameters[n_param]);
+      }
+
+
+#if ASA_TEMPLATE_MULTIPLE
+    }
+  }
+#endif
+
+#if ASA_TEMPLATE_SAMPLE
+  ptr_asa = fopen ("asa_out", "r");
+  sample (ptr_out, ptr_asa);
+#endif
+
+  /* close all files */
+  ptr_out != stdout && fclose (ptr_out);
+#if OPTIONAL_DATA_DBL
+  free (USER_OPTIONS->Asa_Data_Dbl);
+#endif
+#if OPTIONAL_DATA_INT
+  free (USER_OPTIONS->Asa_Data_Int);
+#endif
+#if OPTIONAL_DATA_PTR
+#if MY_TEMPLATE
+  /* Instead of freeing Asa_Data_Ptr, if memory has been allocated
+   * outside ASA, e.g., by the use of ASA_LIB, use the following: */
+  USER_OPTIONS->Asa_Data_Ptr = NULL; 
+#endif /* MY_TEMPLATE */
+  free (USER_OPTIONS->Asa_Data_Ptr);
+#endif
+#if USER_ASA_OUT
+  free (USER_OPTIONS->Asa_Out_File);
+#endif
+#if ASA_SAMPLE
+  free (USER_OPTIONS->Bias_Generated);
+#endif
+#if ASA_QUEUE
+#if ASA_RESOLUTION
+#else
+  free (USER_OPTIONS->Queue_Resolution);
+#endif
+#endif
+#if ASA_RESOLUTION
+  free (USER_OPTIONS->Coarse_Resolution);
+#endif
+  if (USER_OPTIONS->Curvature_0 == FALSE || USER_OPTIONS->Curvature_0 == -1)
+    free (cost_curvature);
+#if USER_INITIAL_PARAMETERS_TEMPS
+  free (USER_OPTIONS->User_Parameter_Temperature);
+#endif
+#if USER_INITIAL_COST_TEMP
+  free (USER_OPTIONS->User_Cost_Temperature);
+#endif
+#if DELTA_PARAMETERS
+  free (USER_OPTIONS->User_Delta_Parameter);
+#endif
+#if QUENCH_PARAMETERS
+  free (USER_OPTIONS->User_Quench_Param_Scale);
+#endif
+#if QUENCH_COST
+  free (USER_OPTIONS->User_Quench_Cost_Scale);
+#endif
+#if RATIO_TEMPERATURE_SCALES
+  free (USER_OPTIONS->User_Temperature_Ratio);
+#endif
+#if MULTI_MIN
+  free (USER_OPTIONS->Multi_Cost);
+  free (USER_OPTIONS->Multi_Grid);
+  for (multi_index = 0; multi_index < USER_OPTIONS->Multi_Number;
+       ++multi_index) {
+    free (USER_OPTIONS->Multi_Params[multi_index]);
+  }
+  free (USER_OPTIONS->Multi_Params);
+#endif /* MULTI_MIN */
+  free (USER_OPTIONS);
+  free (parameter_dimension);
+  free (exit_code);
+  free (cost_flag);
+  free (parameter_lower_bound);
+  free (parameter_upper_bound);
+  free (cost_parameters);
+  free (parameter_int_real);
+  free (cost_tangents);
+  free (rand_seed);
+  return (0);
+  /* NOTREACHED */
+}
+
+/***********************************************************************
+* initialize_parameters - sample parameter initialization function
+*	This depends on the users cost function to optimize (minimum).
+*	The routine allocates storage needed for asa. The user should
+*	define the number of parameters and their ranges,
+*	and make sure the initial parameters are within
+*	the minimum and maximum ranges. The array
+*	parameter_int_real should be REAL_TYPE (-1) for real parameters,
+*	and INTEGER_TYPE (1) for integer values
+***********************************************************************/
+#if HAVE_ANSI
+int
+initialize_parameters (double *cost_parameters,
+                       double *parameter_lower_bound,
+                       double *parameter_upper_bound,
+                       double *cost_tangents,
+                       double *cost_curvature,
+                       ALLOC_INT * parameter_dimension,
+                       int *parameter_int_real,
+#if OPTIONS_FILE_DATA
+                       FILE * ptr_options,
+#endif
+                       USER_DEFINES * USER_OPTIONS)
+#else
+int
+initialize_parameters (cost_parameters,
+                       parameter_lower_bound,
+                       parameter_upper_bound,
+                       cost_tangents,
+                       cost_curvature,
+                       parameter_dimension, parameter_int_real,
+#if OPTIONS_FILE_DATA
+                       ptr_options,
+#endif
+                       USER_OPTIONS)
+     double *cost_parameters;
+     double *parameter_lower_bound;
+     double *parameter_upper_bound;
+     double *cost_tangents;
+     double *cost_curvature;
+     ALLOC_INT *parameter_dimension;
+     int *parameter_int_real;
+#if OPTIONS_FILE_DATA
+     FILE *ptr_options;
+#endif
+     USER_DEFINES *USER_OPTIONS;
+#endif
+{
+  ALLOC_INT index;
+#if OPTIONS_FILE_DATA
+  char read_option[80];
+  ALLOC_INT read_index;
+#endif
+#if MULTI_MIN
+  int multi_index;
+#endif
+#if MY_TEMPLATE                 /* MY_TEMPLATE_init_decl */
+  /* add some declarations if required */
+#endif
+
+  index = 0;
+#if OPTIONS_FILE_DATA
+  fscanf (ptr_options, "%s", read_option);
+
+  for (index = 0; index < *parameter_dimension; ++index) {
+#if MY_TEMPLATE                 /* MY_TEMPLATE_read_opt */
+    /* put in some code as required to alter lines read from asa_opt */
+#endif
+#if INT_ALLOC
+    fscanf (ptr_options, "%d", &read_index);
+#else
+#if INT_LONG
+    fscanf (ptr_options, "%ld", &read_index);
+#else
+    fscanf (ptr_options, "%d", &read_index);
+#endif
+#endif
+    fscanf (ptr_options, "%lf%lf%lf%d",
+            &(parameter_lower_bound[read_index]),
+            &(parameter_upper_bound[read_index]),
+            &(cost_parameters[read_index]),
+            &(parameter_int_real[read_index]));
+  }
+#else /* OPTIONS_FILE_DATA */
+#if ASA_TEST
+  /* store the parameter ranges */
+  for (index = 0; index < *parameter_dimension; ++index)
+    parameter_lower_bound[index] = -10000.0;
+  for (index = 0; index < *parameter_dimension; ++index)
+    parameter_upper_bound[index] = 10000.0;
+
+  /* store the initial parameter types */
+  for (index = 0; index < *parameter_dimension; ++index)
+    parameter_int_real[index] = REAL_TYPE;
+
+  /* store the initial parameter values */
+  for (index = 0; index < *parameter_dimension / 4.0; ++index) {
+    cost_parameters[4 * (index + 1) - 4] = 999.0;
+    cost_parameters[4 * (index + 1) - 3] = -1007.0;
+    cost_parameters[4 * (index + 1) - 2] = 1001.0;
+    cost_parameters[4 * (index + 1) - 1] = -903.0;
+  }
+#endif /* ASA_TEST */
+#endif /* OPTIONS_FILE_DATA */
+#if ASA_TEMPLATE_SAMPLE
+  for (index = 0; index < *parameter_dimension; ++index)
+    parameter_lower_bound[index] = 0;
+  for (index = 0; index < *parameter_dimension; ++index)
+    parameter_upper_bound[index] = 2.0;
+  for (index = 0; index < *parameter_dimension; ++index)
+    parameter_int_real[index] = REAL_TYPE;
+  for (index = 0; index < *parameter_dimension; ++index)
+    cost_parameters[index] = 0.5;
+#endif
+
+#if USER_INITIAL_PARAMETERS_TEMPS
+  if ((USER_OPTIONS->User_Parameter_Temperature =
+       (double *) calloc (*parameter_dimension, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "initialize_parameters(): USER_OPTIONS->User_Parameter_Temperature");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#if ASA_TEMPLATE
+  for (index = 0; index < *parameter_dimension; ++index)
+    USER_OPTIONS->User_Parameter_Temperature[index] = 1.0;
+#endif
+#endif /* USER_INITIAL_PARAMETERS_TEMPS */
+#if USER_INITIAL_COST_TEMP
+  if ((USER_OPTIONS->User_Cost_Temperature =
+       (double *) calloc (1, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "initialize_parameters(): USER_OPTIONS->User_Cost_Temperature");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#if ASA_TEMPLATE
+  USER_OPTIONS->User_Cost_Temperature[0] = 5.936648E+09;
+#endif
+#endif /* USER_INITIAL_COST_TEMP */
+#if DELTA_PARAMETERS
+  if ((USER_OPTIONS->User_Delta_Parameter =
+       (double *) calloc (*parameter_dimension, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "initialize_parameters(): USER_OPTIONS->User_Delta_Parameter");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#if ASA_TEMPLATE
+  for (index = 0; index < *parameter_dimension; ++index)
+    USER_OPTIONS->User_Delta_Parameter[index] = 0.001;
+#endif
+#endif /* DELTA_PARAMETERS */
+#if QUENCH_PARAMETERS
+  if ((USER_OPTIONS->User_Quench_Param_Scale =
+       (double *) calloc (*parameter_dimension, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "initialize_parameters(): USER_OPTIONS->User_Quench_Param_Scale");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#if ASA_TEMPLATE
+  for (index = 0; index < *parameter_dimension; ++index)
+    USER_OPTIONS->User_Quench_Param_Scale[index] = 1.0;
+#endif
+#if ASA_TEMPLATE_MULTIPLE
+  for (index = 0; index < *parameter_dimension; ++index)
+    USER_OPTIONS->User_Quench_Param_Scale[index] = 1.0;
+#endif
+#if ASA_TEMPLATE_SAVE
+  for (index = 0; index < *parameter_dimension; ++index)
+    USER_OPTIONS->User_Quench_Param_Scale[index] = 1.0;
+#endif
+#endif /* QUENCH_PARAMETERS */
+#if QUENCH_COST
+  if ((USER_OPTIONS->User_Quench_Cost_Scale =
+       (double *) calloc (1, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "initialize_parameters(): USER_OPTIONS->User_Quench_Cost_Scale");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#if ASA_TEMPLATE
+  USER_OPTIONS->User_Quench_Cost_Scale[0] = 1.0;
+#endif
+#if ASA_TEMPLATE_MULTIPLE
+  USER_OPTIONS->User_Quench_Cost_Scale[0] = 1.0;
+#endif
+#if ASA_TEMPLATE_SAVE
+  USER_OPTIONS->User_Quench_Cost_Scale[0] = 1.0;
+#endif
+#endif /* QUENCH_COST */
+
+  /* use asa_opt to read in QUENCH USER_OPTIONS */
+#if OPTIONS_FILE_DATA
+#if QUENCH_COST
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%lf", &(USER_OPTIONS->User_Quench_Cost_Scale[0]));
+
+#if QUENCH_PARAMETERS
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%s", read_option);
+  for (index = 0; index < *parameter_dimension; ++index) {
+#if INT_ALLOC
+    fscanf (ptr_options, "%d", &read_index);
+#else
+#if INT_LONG
+    fscanf (ptr_options, "%ld", &read_index);
+#else
+    fscanf (ptr_options, "%d", &read_index);
+#endif
+#endif
+    fscanf (ptr_options, "%lf",
+            &(USER_OPTIONS->User_Quench_Param_Scale[read_index]));
+  }
+#endif /* QUENCH_PARAMETERS */
+#endif /* QUENCH_COST */
+#endif /* OPTIONS_FILE_DATA */
+
+#if RATIO_TEMPERATURE_SCALES
+  if ((USER_OPTIONS->User_Temperature_Ratio =
+       (double *) calloc (*parameter_dimension, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "initialize_parameters(): USER_OPTIONS->User_Temperature_Ratio");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#if ASA_TEMPLATE
+  for (index = 0; index < *parameter_dimension; ++index)
+    USER_OPTIONS->User_Temperature_Ratio[index] = 1.0;
+#endif
+#endif /* RATIO_TEMPERATURE_SCALES */
+  /* Defines the limit of collection of sampled data by asa */
+#if ASA_SAMPLE
+  /* create memory for Bias_Generated[] */
+  if ((USER_OPTIONS->Bias_Generated =
+       (double *) calloc (*parameter_dimension, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "initialize_parameters(): USER_OPTIONS->Bias_Generated");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#endif
+
+#if ASA_RESOLUTION
+  if ((USER_OPTIONS->Coarse_Resolution =
+       (double *) calloc (*parameter_dimension, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "initialize_parameters(): USER_OPTIONS->Coarse_Resolution");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#if ASA_TEMPLATE
+  for (index = 0; index < *parameter_dimension; ++index)
+    USER_OPTIONS->Coarse_Resolution[index] = 1.0;
+#endif
+#endif /* ASA_RESOLUTION */
+#if ASA_QUEUE
+#if ASA_RESOLUTION
+  USER_OPTIONS->Queue_Resolution = USER_OPTIONS->Coarse_Resolution;
+#else /* ASA_RESOLUTION */
+  if ((USER_OPTIONS->Queue_Resolution =
+       (double *) calloc (*parameter_dimension, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "initialize_parameters(): USER_OPTIONS->Queue_Resolution");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#endif /* ASA_RESOLUTION */
+#if ASA_TEMPLATE_QUEUE
+  USER_OPTIONS->Queue_Size = 100;
+  for (index = 0; index < *parameter_dimension; ++index)
+    USER_OPTIONS->Queue_Resolution[index] = 0.001;
+#endif
+#endif /* ASA_QUEUE */
+#if MULTI_MIN
+#if ASA_TEMPLATE
+  USER_OPTIONS->Multi_Number = 2;
+#endif
+  if ((USER_OPTIONS->Multi_Cost =
+       (double *) calloc (USER_OPTIONS->Multi_Number,
+                          sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "initialize_parameters(): USER_OPTIONS->Multi_Cost");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  if ((USER_OPTIONS->Multi_Grid =
+       (double *) calloc (*parameter_dimension, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "initialize_parameters(): USER_OPTIONS->Multi_Grid");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  if ((USER_OPTIONS->Multi_Params =
+       (double **) calloc (USER_OPTIONS->Multi_Number,
+                           sizeof (double *))) == NULL) {
+    strcpy (user_exit_msg,
+            "initialize_parameters(): USER_OPTIONS->Multi_Params");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  for (multi_index = 0; multi_index < USER_OPTIONS->Multi_Number;
+       ++multi_index) {
+    if ((USER_OPTIONS->Multi_Params[multi_index] =
+         (double *) calloc (*parameter_dimension, sizeof (double))) == NULL) {
+      strcpy (user_exit_msg,
+              "initialize_parameters(): USER_OPTIONS->Multi_Params[multi_index]");
+      Exit_USER (user_exit_msg);
+      return (-2);
+    }
+  }
+#if ASA_TEST
+  for (index = 0; index < *parameter_dimension; ++index) {
+    USER_OPTIONS->Multi_Grid[index] = 0.05;
+  }
+  USER_OPTIONS->Multi_Specify = 0;
+#endif
+#if ASA_TEMPLATE
+  for (index = 0; index < *parameter_dimension; ++index) {
+    USER_OPTIONS->Multi_Grid[index] =
+      (parameter_upper_bound[index] - parameter_lower_bound[index]) / 100.0;
+  }
+  USER_OPTIONS->Multi_Specify = 0;
+#endif /* ASA_TEMPLATE */
+#endif /* MULTI_MIN */
+  USER_OPTIONS->Asa_Recursive_Level = 0;
+
+#if MY_TEMPLATE                 /* MY_TEMPLATE_params */
+  /* If not using RECUR_OPTIONS_FILE_DATA or data read from asa_opt,
+     store the parameter ranges
+     store the parameter types
+     store the initial parameter values
+     other changes needed for initialization */
+#endif /* MY_TEMPLATE params */
+
+  return (0);
+}
+
+#if COST_FILE
+#else
+/***********************************************************************
+* double cost_function
+*	This is the users cost function to optimize
+*	(find the minimum).
+*	cost_flag is set to TRUE if the parameter set
+*	does not violates any constraints
+*       parameter_lower_bound and parameter_upper_bound may be
+*       adaptively changed during the search.
+***********************************************************************/
+
+#if HAVE_ANSI
+double
+cost_function (double *x,
+               double *parameter_lower_bound,
+               double *parameter_upper_bound,
+               double *cost_tangents,
+               double *cost_curvature,
+               ALLOC_INT * parameter_dimension,
+               int *parameter_int_real,
+               int *cost_flag, int *exit_code, USER_DEFINES * USER_OPTIONS)
+#else
+double
+cost_function (x,
+               parameter_lower_bound,
+               parameter_upper_bound,
+               cost_tangents,
+               cost_curvature,
+               parameter_dimension,
+               parameter_int_real, cost_flag, exit_code, USER_OPTIONS)
+     double *x;
+     double *parameter_lower_bound;
+     double *parameter_upper_bound;
+     double *cost_tangents;
+     double *cost_curvature;
+     ALLOC_INT *parameter_dimension;
+     int *parameter_int_real;
+     int *cost_flag;
+     int *exit_code;
+     USER_DEFINES *USER_OPTIONS;
+#endif
+{
+
+#if ASA_TEST                    /* ASA test problem */
+  /* Objective function from
+   * %A A. Corana
+   * %A M. Marchesi
+   * %A C. Martini
+   * %A S. Ridella
+   * %T Minimizing multimodal functions of continuous variables
+   *    with the "simulated annealing" algorithm
+   * %J ACM Trans. Mathl. Software
+   * %V 13
+   * %N 3
+   * %P 262-279
+   * %D 1987
+   *
+   * This function, when used with ASA_TEST_POINT set to TRUE, contains
+   * 1.0E20 local minima.  When *parameter_dimension is equal to 4, visiting
+   * each minimum for a millisecond would take about the present age of the
+   * universe to visit all these minima. */
+
+  /* defines for the test problem, which assume *parameter_dimension
+     is a multiple of 4.  If this is set to a large number, you
+     likely should set Curvature_0 to TRUE. */
+  double q_n, d_i, s_i, t_i, z_i, c_r;
+  int k_i;
+#if ASA_TEST_POINT
+  ALLOC_INT k_flag;
+#endif
+  ALLOC_INT i, j;
+#if SELF_OPTIMIZE
+#else
+  static LONG_INT funevals = 0;
+#endif
+#if ASA_TEMPLATE_SAVE
+  static int read_test = 0;
+  FILE *ptr_read_test;
+#endif
+
+#if MY_TEMPLATE                 /* MY_TEMPLATE_diminishing_ranges */
+  /* insert code to automate changing ranges of parameters */
+#endif
+#if ASA_TEMPLATE                /* example of diminishing ranges */
+  if (USER_OPTIONS->Locate_Cost == 12 && *(USER_OPTIONS->Best_Cost) < 1.0) {
+    fprintf (ptr_out, "best_cost = %g\n", *(USER_OPTIONS->Best_Cost));
+    for (i = 0; i < *parameter_dimension; ++i) {
+      parameter_lower_bound[i] = USER_OPTIONS->Best_Parameters[i]
+        - 0.5 * fabs (parameter_lower_bound[i]
+                      - USER_OPTIONS->Best_Parameters[i]);
+      parameter_upper_bound[i] = USER_OPTIONS->Best_Parameters[i]
+        + 0.5 * fabs (parameter_upper_bound[i]
+                      - USER_OPTIONS->Best_Parameters[i]);
+      parameter_lower_bound[i] = MIN (parameter_lower_bound[i],
+                                      USER_OPTIONS->Best_Parameters[i] -
+                                      0.01);
+      parameter_upper_bound[i] =
+        MAX (parameter_upper_bound[i],
+             USER_OPTIONS->Best_Parameters[i] + 0.01);
+    }
+  }
+#endif /* ASA_TEMPLATE */
+
+  /* a_i = parameter_upper_bound[i] */
+  s_i = 0.2;
+  t_i = 0.05;
+  c_r = 0.15;
+
+#if ASA_TEST_POINT
+  k_flag = 0;
+  for (i = 0; i < *parameter_dimension; ++i) {
+    if (fabs (parameter_upper_bound[i] - parameter_lower_bound[i]) <
+        (double) EPS_DOUBLE)
+      continue;
+
+    if (x[i] > 0.0) {
+      k_i = (int) (x[i] / s_i + 0.5);
+    } else if (x[i] < 0.0) {
+      k_i = (int) (x[i] / s_i - 0.5);
+    } else {
+      k_i = 0;
+    }
+    if (k_i == 0)
+      ++k_flag;
+  }
+#endif /* ASA_TEST_POINT */
+
+  q_n = 0.0;
+  for (i = 0; i < *parameter_dimension; ++i) {
+    if (fabs (parameter_upper_bound[i] - parameter_lower_bound[i]) <
+        (double) EPS_DOUBLE)
+      continue;
+
+    j = i % 4;
+    switch (j) {
+    case 0:
+      d_i = 1.0;
+      break;
+    case 1:
+      d_i = 1000.0;
+      break;
+    case 2:
+      d_i = 10.0;
+      break;
+    default:
+      d_i = 100.0;
+    }
+    if (x[i] > 0.0) {
+      k_i = (int) (x[i] / s_i + 0.5);
+    } else if (x[i] < 0.0) {
+      k_i = (int) (x[i] / s_i - 0.5);
+    } else {
+      k_i = 0;
+    }
+
+#if ASA_TEST_POINT
+    if (fabs (k_i * s_i - x[i]) < t_i && k_flag != *parameter_dimension)
+#else
+    if (fabs (k_i * s_i - x[i]) < t_i)
+#endif
+    {
+      if (k_i < 0) {
+        z_i = k_i * s_i + t_i;
+      } else if (k_i > 0) {
+        z_i = k_i * s_i - t_i;
+      } else {
+        z_i = 0.0;
+      }
+      q_n += c_r * d_i * z_i * z_i;
+    } else {
+      q_n += d_i * x[i] * x[i];
+    }
+  }
+  funevals = funevals + 1;
+
+#if ASA_TEMPLATE_SAVE
+  /* cause a crash */
+  if ((ptr_read_test = fopen ("asa_save", "r")) == NULL) {
+    read_test = 1;
+    fclose (ptr_read_test);
+  } else {
+    fclose (ptr_read_test);
+  }
+  /* will need a few hundred if testing ASA_PARALLEL to get an asa_save */
+  if (funevals == 50 && read_test == 1) {
+    fprintf (ptr_out, "\n\n*** intended crash to test ASA_SAVE *** \n\n");
+    fflush (ptr_out);
+#if INCL_STDOUT
+    printf ("\n\n*** intended crash to test ASA_SAVE *** \n\n");
+#endif /* INCL_STDOUT */
+    exit (2);
+  }
+#endif
+
+  *cost_flag = TRUE;
+
+#if SELF_OPTIMIZE
+#else
+#if TIME_CALC
+  /* print the time every PRINT_FREQUENCY evaluations */
+  if ((PRINT_FREQUENCY > 0) && ((funevals % PRINT_FREQUENCY) == 0)) {
+    fprintf (ptr_out, "funevals = %ld  ", funevals);
+#if INCL_STDOUT
+    print_time ("", ptr_out);
+#endif /* INCL_STDOUT */
+  }
+#endif
+#endif
+
+#if ASA_TEMPLATE_SAMPLE
+  USER_OPTIONS->Cost_Acceptance_Flag = TRUE;
+  if (USER_OPTIONS->User_Acceptance_Flag == FALSE && *cost_flag == TRUE)
+    USER_OPTIONS->Acceptance_Test (q_n,
+                                   parameter_lower_bound,
+                                   parameter_upper_bound,
+                                   *parameter_dimension, USER_OPTIONS);
+#endif /* ASA_TEMPLATE_SAMPLE */
+
+  return (q_n);
+#endif /* ASA_TEST */
+#if ASA_TEMPLATE_SAMPLE
+
+  int n;
+  double cost;
+
+  if (*cost_flag == FALSE) {
+    for (n = 0; n < *parameter_dimension; ++n)
+      if (fabs (parameter_upper_bound[n] - parameter_lower_bound[n]) <
+          (double) EPS_DOUBLE)
+        continue;
+
+    cost_tangents[n] = 2.0 * x[n];
+  }
+
+  cost = 0.0;
+  for (n = 0; n < *parameter_dimension; ++n) {
+    if (fabs (parameter_upper_bound[n] - parameter_lower_bound[n]) <
+        (double) EPS_DOUBLE)
+      continue;
+
+    cost += (x[n] * x[n]);
+  }
+
+  *cost_flag = TRUE;
+
+  USER_OPTIONS->Cost_Acceptance_Flag = TRUE;
+  if (USER_OPTIONS->User_Acceptance_Flag == FALSE && *cost_flag == TRUE)
+    USER_OPTIONS->Acceptance_Test (cost,
+                                   parameter_lower_bound,
+                                   parameter_upper_bound,
+                                   *parameter_dimension, USER_OPTIONS);
+
+  return (cost);
+#endif /* ASA_TEMPLATE_SAMPLE */
+#if MY_TEMPLATE                 /* MY_TEMPLATE_cost */
+   return USER_OPTIONS->Asa_Data_Ptr(x,cost_flag); 
+  /* Use the parameter values x[] and define your cost_function.
+     The {} brackets around this function are already in place. */
+#endif /* MY_TEMPLATE cost */
+}
+#endif /* COST_FILE */
+
+  /* Here is a good random number generator */
+
+#define MULT ((LONG_INT) 25173)
+#define MOD ((LONG_INT) 65536)
+#define INCR ((LONG_INT) 13849)
+#define FMOD ((double) 65536.0)
+
+
+/***********************************************************************
+* double myrand - returns random number between 0 and 1
+*	This routine returns the random number generator between 0 and 1
+***********************************************************************/
+
+static double
+myrand (LONG_INT * rand_seed)
+  /* returns random number in {0,1} */
+{
+#if TRUE                        /* (change to FALSE for alternative RNG) */
+  *rand_seed = (LONG_INT) ((MULT * (*rand_seed) + INCR) % MOD);
+  return ((double) (*rand_seed) / FMOD);
+#else
+  /* See "Random Number Generators: Good Ones Are Hard To Find,"
+     Park & Miller, CACM 31 (10) (October 1988) pp. 1192-1201.
+     ***********************************************************
+     THIS IMPLEMENTATION REQUIRES AT LEAST 32 BIT INTEGERS
+     *********************************************************** */
+#define _A_MULTIPLIER  16807L
+#define _M_MODULUS     2147483647L      /* (2**31)-1 */
+#define _Q_QUOTIENT    127773L  /* 2147483647 / 16807 */
+#define _R_REMAINDER   2836L    /* 2147483647 % 16807 */
+  long lo;
+  long hi;
+  long test;
+
+  hi = *rand_seed / _Q_QUOTIENT;
+  lo = *rand_seed % _Q_QUOTIENT;
+  test = _A_MULTIPLIER * lo - _R_REMAINDER * hi;
+  if (test > 0) {
+    *rand_seed = test;
+  } else {
+    *rand_seed = test + _M_MODULUS;
+  }
+  return ((double) *rand_seed / _M_MODULUS);
+#endif /* alternative RNG */
+}
+
+/***********************************************************************
+* double randflt
+***********************************************************************/
+
+static double
+randflt (LONG_INT * rand_seed)
+{
+  return (resettable_randflt (rand_seed, 0));
+}
+
+/***********************************************************************
+* double resettable_randflt
+***********************************************************************/
+
+static double
+resettable_randflt (LONG_INT * rand_seed, int reset)
+  /* shuffles random numbers in random_array[SHUFFLE] array */
+{
+
+  /* This RNG is a modified algorithm of that presented in
+   * %A K. Binder
+   * %A D. Stauffer
+   * %T A simple introduction to Monte Carlo simulations and some
+   *    specialized topics
+   * %B Applications of the Monte Carlo Method in statistical physics
+   * %E K. Binder
+   * %I Springer-Verlag
+   * %C Berlin
+   * %D 1985
+   * %P 1-36
+   * where it is stated that such algorithms have been found to be
+   * quite satisfactory in many statistical physics applications. */
+
+  double rranf;
+  unsigned kranf;
+  int n;
+  static int initial_flag = 0;
+  LONG_INT initial_seed;
+  static double random_array[SHUFFLE];  /* random variables */
+
+  if (*rand_seed < 0)
+    *rand_seed = -*rand_seed;
+
+  if ((initial_flag == 0) || reset) {
+    initial_seed = *rand_seed;
+
+    for (n = 0; n < SHUFFLE; ++n)
+      random_array[n] = myrand (&initial_seed);
+
+    initial_flag = 1;
+
+    for (n = 0; n < 1000; ++n)  /* warm up random generator */
+      rranf = randflt (&initial_seed);
+
+    rranf = randflt (rand_seed);
+
+    return (rranf);
+  }
+
+  kranf = (unsigned) (myrand (rand_seed) * SHUFFLE) % SHUFFLE;
+  rranf = *(random_array + kranf);
+  *(random_array + kranf) = myrand (rand_seed);
+
+  return (rranf);
+}
+
+#if USER_COST_SCHEDULE
+#if HAVE_ANSI
+double
+user_cost_schedule (double test_temperature, USER_DEFINES * USER_OPTIONS)
+#else
+double
+user_cost_schedule (test_temperature, USER_OPTIONS)
+     double test_temperature;
+     USER_DEFINES *USER_OPTIONS;
+#endif /* HAVE_ANSI */
+{
+  double x;
+
+#if ASA_TEMPLATE_SAMPLE
+  x = F_POW (test_temperature, 0.15);
+#endif
+#if ASA_TEMPLATE
+  x = test_temperature;
+#endif
+
+  return (x);
+}
+#endif /* USER_COST_SCHEDULE */
+
+#if USER_ACCEPTANCE_TEST
+#if HAVE_ANSI
+void
+user_acceptance_test (double current_cost,
+                      double *parameter_lower_bound,
+                      double *parameter_upper_bound,
+                      ALLOC_INT * parameter_dimension,
+                      USER_DEFINES * USER_OPTIONS)
+#else
+void
+user_acceptance_test (current_cost, parameter_lower_bound,
+                      parameter_upper_bound, parameter_dimension,
+                      USER_OPTIONS)
+     double current_cost;
+     double *parameter_lower_bound;
+     double *parameter_upper_bound;
+     ALLOC_INT *parameter_dimension;
+     USER_DEFINES *USER_OPTIONS;
+#endif /* HAVE_ANSI */
+{
+  double uniform_test, curr_cost_temp;
+#if USER_ACCEPT_ASYMP_EXP
+  double x, q, delta_cost;
+#endif
+
+#if ASA_TEMPLATE                /* ASA cost index */
+  /* Calculate the current ASA cost index.  This could be useful
+     to define a new schedule for the cost temperature, beyond
+     simple changes that can be made using USER_COST_SCHEDULE. */
+
+  int index;
+  double k_temperature, quench, y;
+  double xparameter_dimension;
+
+#if QUENCH_COST
+  quench = USER_OPTIONS->User_Quench_Cost_Scale[0];
+#else
+  quench = 1.0;
+#endif /* QUENCH_COST */
+  xparameter_dimension = (double) *parameter_dimension;
+  for (index = 0; index < *parameter_dimension; ++index)
+    if (fabs (parameter_upper_bound[index] - parameter_lower_bound[index]) <
+        (double) EPS_DOUBLE)
+      *xparameter_dimension -= 1.0;
+
+  y = -F_LOG (USER_OPTIONS->Cost_Temp_Curr
+              / USER_OPTIONS->Cost_Temp_Init) / USER_OPTIONS->Cost_Temp_Scale;
+
+  k_temperature = F_POW (y, xparameter_dimension / quench);
+#endif /* ASA cost index */
+
+  uniform_test = randflt (USER_OPTIONS->Random_Seed);
+  curr_cost_temp = USER_OPTIONS->Cost_Temp_Curr;
+
+#if ASA_TEMPLATE
+#if USER_COST_SCHEDULE
+  curr_cost_temp =
+    (USER_OPTIONS->Cost_Schedule (USER_OPTIONS->Cost_Temp_Curr,
+                                  USER_OPTIONS) + (double) EPS_DOUBLE);
+#else
+  curr_cost_temp = USER_OPTIONS->Cost_Temp_Curr;
+#endif
+#endif /* ASA_TEMPLATE */
+
+  /* You must add in your own test here.  If USER_ACCEPT_ASYMP_EXP
+     also is TRUE here, then you can use the default
+     Asymp_Exp_Param=1 to replicate the code in asa.c. */
+
+#if USER_ACCEPT_ASYMP_EXP
+#if USER_COST_SCHEDULE
+  curr_cost_temp =
+    (USER_OPTIONS->Cost_Schedule (USER_OPTIONS->Cost_Temp_Curr,
+                                  USER_OPTIONS) + (double) EPS_DOUBLE);
+#endif
+
+  delta_cost = (current_cost - *(USER_OPTIONS->Last_Cost))
+    / (curr_cost_temp + (double) EPS_DOUBLE);
+
+  /* The following asymptotic approximation to the exponential
+   * function, "Tsallis statistics," was proposed in
+   * %A T.J.P. Penna
+   * %T Traveling salesman problem and Tsallis statistics
+   * %J Phys. Rev. E
+   * %V 50
+   * %N 6
+   * %P R1-R3
+   * %D 1994
+   * While the use of the TSP for a test case is of dubious value (since
+   * there are many special algorithms for this problem), the use of this
+   * function is another example of how to control the rate of annealing
+   * of the acceptance criteria.  E.g., if you require a more moderate
+   * acceptance test, then negative q may be helpful. */
+
+  q = USER_OPTIONS->Asymp_Exp_Param;
+  if (fabs (1.0 - q) < (double) EPS_DOUBLE)
+    x = MIN (1.0, (F_EXP (-delta_cost)));       /* Boltzmann test */
+  else if ((1.0 - (1.0 - q) * delta_cost) < (double) EPS_DOUBLE)
+    x = MIN (1.0, (F_EXP (-delta_cost)));       /* Boltzmann test */
+  else
+    x = MIN (1.0, F_POW ((1.0 - (1.0 - q) * delta_cost), (1.0 / (1.0 - q))));
+
+  USER_OPTIONS->Prob_Bias = x;
+  if (x >= uniform_test)
+    USER_OPTIONS->User_Acceptance_Flag = TRUE;
+  else
+    USER_OPTIONS->User_Acceptance_Flag = FALSE;
+
+#endif /* USER_ACCEPT_ASYMP_EXP */
+}
+#endif /* USER_ACCEPTANCE_TEST */
+
+#if USER_GENERATING_FUNCTION
+#if HAVE_ANSI
+double
+user_generating_distrib (LONG_INT * seed,
+                         ALLOC_INT * parameter_dimension,
+                         ALLOC_INT index_v,
+                         double temperature_v,
+                         double init_param_temp_v,
+                         double temp_scale_params_v,
+                         double parameter_v,
+                         double parameter_range_v,
+                         double *last_saved_parameter,
+                         USER_DEFINES * USER_OPTIONS)
+#else
+double
+user_generating_distrib (seed,
+                         parameter_dimension,
+                         index_v,
+                         temperature_v,
+                         init_param_temp_v,
+                         temp_scale_params_v,
+                         parameter_v,
+                         parameter_range_v,
+                         last_saved_parameter, USER_OPTIONS)
+     LONG_INT *seed;
+     ALLOC_INT *parameter_dimension;
+     ALLOC_INT index_v;
+     double temperature_v;
+     double init_param_temp_v;
+     double temp_scale_params_v;
+     double parameter_v;
+     double parameter_range_v;
+     double *last_saved_parameter;
+     USER_DEFINES *USER_OPTIONS;
+#endif
+{
+#if ASA_TEMPLATE
+  double x, y, z;
+
+  /* This is the ASA distribution.  A slower temperature schedule can be
+     obtained here, e.g., temperature_v = pow(temperature_v, 0.5); */
+
+  x = randflt (seed);
+  y = x < 0.5 ? -1.0 : 1.0;
+  z = y * temperature_v * (F_POW ((1.0 + 1.0 / temperature_v),
+                                  fabs (2.0 * x - 1.0)) - 1.0);
+
+  x = parameter_v + z * parameter_range_v;
+
+  return (x);
+#endif /* ASA_TEMPLATE */
+}
+#endif /* USER_GENERATING_FUNCTION */
+
+#if USER_REANNEAL_COST
+#if HAVE_ANSI
+int
+user_reanneal_cost (double *cost_best,
+                    double *cost_last,
+                    double *initial_cost_temperature,
+                    double *current_cost_temperature,
+                    USER_DEFINES * USER_OPTIONS)
+#else
+int
+user_reanneal_cost (cost_best,
+                    cost_last,
+                    initial_cost_temperature,
+                    current_cost_temperature, USER_OPTIONS)
+     double *cost_best;
+     double *cost_last;
+     double *initial_cost_temperature;
+     double *current_cost_temperature;
+     USER_DEFINES *USER_OPTIONS;
+#endif /* HAVE_ANSI */
+{
+  int cost_test;
+  double tmp_dbl;
+
+#if ASA_TEMPLATE
+  static int first_time = 1;
+  static double save_last[3];
+  double average_cost_last;
+
+  if (first_time == 1) {
+    first_time = 0;
+    save_last[0] = save_last[1] = save_last[2] = *cost_last;
+  }
+
+  save_last[2] = save_last[1];
+  save_last[1] = save_last[0];
+  save_last[0] = *cost_last;
+  average_cost_last =
+    fabs ((save_last[0] + save_last[1] + save_last[2]) / 3.0);
+
+  tmp_dbl = MAX (fabs (*cost_best), average_cost_last);
+  tmp_dbl = MAX ((double) EPS_DOUBLE, tmp_dbl);
+  *initial_cost_temperature = MIN (*initial_cost_temperature, tmp_dbl);
+
+  /* This test can be useful if your cost function goes from a positive
+     to a negative value, and you do not want to get get stuck in a local
+     minima around zero due to the default in reanneal().  Pick any
+     number instead of 0.0001 */
+  tmp_dbl = MIN (fabs (*cost_last), fabs (*cost_best));
+  if (tmp_dbl < 0.0001)
+    cost_test = FALSE;
+  else
+    cost_test = TRUE;
+#endif /* ASA_TEMPLATE */
+
+  tmp_dbl = MAX (fabs (cost_last), fabs (cost_best));
+  tmp_dbl = MAX ((double) EPS_DOUBLE, tmp_dbl);
+  *initial_cost_temperature = MIN (*initial_cost_temperature, tmp_dbl);
+
+  *current_cost_temperature =
+    MAX (fabs (cost_last - cost_best), *current_cost_temperature);
+  *current_cost_temperature =
+    MAX ((double) EPS_DOUBLE, *current_cost_temperature);
+  *current_cost_temperature =
+    MIN (*current_cost_temperature, *initial_cost_temperature);
+
+  cost_test = TRUE;
+
+  return (cost_test);
+}
+#endif /* USER_REANNEAL_COST */
+
+#if USER_REANNEAL_PARAMETERS
+#if HAVE_ANSI
+double
+user_reanneal_params (double current_temp,
+                      double tangent,
+                      double max_tangent, USER_DEFINES * USER_OPTIONS)
+#else
+double
+user_reanneal_params (current_temp, tangent, max_tangent, USER_OPTIONS)
+     double current_temp;
+     double tangent;
+     double max_tangent;
+     USER_DEFINES *USER_OPTIONS;
+#endif /* HAVE_ANSI */
+{
+#if ASA_TEMPLATE
+  double x;
+
+  x = current_temp * (max_tangent / tangent);
+
+  return (x);
+#endif
+}
+#endif /* USER_REANNEAL_PARAMETERS */
+
+#if SELF_OPTIMIZE
+
+/***********************************************************************
+* main
+*	This is a sample calling program to self-optimize ASA
+***********************************************************************/
+#if HAVE_ANSI
+
+#if ASA_LIB
+int
+asa_main (
+#if ASA_TEMPLATE_LIB
+           double *main_recur_cost_value,
+           double *main_recur_cost_parameters, int *main_recur_exit_code
+#endif
+  )
+#else /* ASA_LIB */
+int
+main (int argc, char **argv)
+#endif                          /* ASA_LIB */
+#else /* HAVE_ANSI */
+
+#if ASA_LIB
+int
+asa_main (
+#if ASA_TEMPLATE_LIB
+           main_recur_cost_value,
+           main_recur_cost_parameters, main_recur_exit_code
+#endif
+  )
+#if ASA_TEMPLATE_LIB
+     double *main_recur_cost_value;
+     double *main_recur_cost_parameters;
+     int *main_recur_exit_code;
+#endif
+
+#else /* ASA_LIB */
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+#endif /* ASA_LIB */
+
+#endif /* HAVE_ANSI */
+{
+
+  /* seed for random number generator */
+  LONG_INT *recur_rand_seed;
+
+#if RECUR_OPTIONS_FILE
+  FILE *recur_ptr_options;
+  char read_option[80];
+  char read_if[4], read_FALSE[6], read_comm1[3], read_ASA_SAVE[9],
+    read_comm2[3];
+  int read_int;
+#if INT_LONG
+  LONG_INT read_long;
+#endif
+  double read_double;
+#endif
+
+  int *recur_exit_code;
+#if MULTI_MIN
+  int multi_index;
+  ALLOC_INT n_param;
+#endif
+
+  double *recur_parameter_lower_bound, *recur_parameter_upper_bound;
+  double *recur_cost_parameters, *recur_cost_tangents, *recur_cost_curvature;
+  double recur_cost_value;
+
+  ALLOC_INT *recur_parameter_dimension;
+  int *recur_parameter_int_real;
+  int *recur_cost_flag;
+  int recur_initialize_parameters_value;
+  ALLOC_INT recur_v;
+#if MY_TEMPLATE                 /* MY_TEMPLATE_recur_main_decl */
+  /* add some declarations if required */
+#endif
+
+  USER_DEFINES *RECUR_USER_OPTIONS;
+
+  if ((recur_parameter_dimension =
+       (ALLOC_INT *) calloc (1, sizeof (ALLOC_INT))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): recur_parameter_dimension");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  if ((recur_exit_code = (int *) calloc (1, sizeof (int))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): recur_exit_code");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  if ((recur_cost_flag = (int *) calloc (1, sizeof (int))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): recur_cost_flag");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+
+  if ((RECUR_USER_OPTIONS =
+       (USER_DEFINES *) calloc (1, sizeof (USER_DEFINES))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): RECUR_USER_OPTIONS");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#if RECUR_OPTIONS_FILE
+  recur_ptr_options = fopen ("asa_opt_recur", "r");
+
+  fscanf (recur_ptr_options, "%s%s%s%s%s",
+          read_if, read_FALSE, read_comm1, read_ASA_SAVE, read_comm2);
+  if (strcmp (read_if, "#if") || strcmp (read_FALSE, "FALSE") ||
+      strcmp (read_comm1, "/*") || strcmp (read_ASA_SAVE, "ASA_SAVE") ||
+      strcmp (read_comm2, "*/")) {
+    fprintf (ptr_out, "\n\n*** not asa_opt_recur for this version *** \n\n");
+    fflush (ptr_out);
+#if INCL_STDOUT
+    printf ("\n\n*** EXIT not asa_opt_recur for this version *** \n\n");
+#endif /* INCL_STDOUT */
+    return (-6);
+  }
+#if INT_LONG
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%ld", &read_long);
+  RECUR_USER_OPTIONS->Limit_Acceptances = read_long;
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%ld", &read_long);
+  RECUR_USER_OPTIONS->Limit_Generated = read_long;
+#else
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%d", &read_int);
+  RECUR_USER_OPTIONS->Limit_Acceptances = read_int;
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%d", &read_int);
+  RECUR_USER_OPTIONS->Limit_Generated = read_int;
+#endif
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%d", &read_int);
+  RECUR_USER_OPTIONS->Limit_Invalid_Generated_States = read_int;
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%lf", &read_double);
+  RECUR_USER_OPTIONS->Accepted_To_Generated_Ratio = read_double;
+
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%lf", &read_double);
+  RECUR_USER_OPTIONS->Cost_Precision = read_double;
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%d", &read_int);
+  RECUR_USER_OPTIONS->Maximum_Cost_Repeat = read_int;
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%d", &read_int);
+  RECUR_USER_OPTIONS->Number_Cost_Samples = read_int;
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%lf", &read_double);
+  RECUR_USER_OPTIONS->Temperature_Ratio_Scale = read_double;
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%lf", &read_double);
+  RECUR_USER_OPTIONS->Cost_Parameter_Scale_Ratio = read_double;
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%lf", &read_double);
+  RECUR_USER_OPTIONS->Temperature_Anneal_Scale = read_double;
+
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%d", &read_int);
+  RECUR_USER_OPTIONS->Include_Integer_Parameters = read_int;
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%d", &read_int);
+  RECUR_USER_OPTIONS->User_Initial_Parameters = read_int;
+#if INT_ALLOC
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%d", &read_int);
+  RECUR_USER_OPTIONS->Sequential_Parameters = read_int;
+#else
+#if INT_LONG
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%ld", &read_long);
+  RECUR_USER_OPTIONS->Sequential_Parameters = read_long;
+#else
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%d", &read_int);
+  RECUR_USER_OPTIONS->Sequential_Parameters = read_int;
+#endif
+#endif
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%lf", &read_double);
+  RECUR_USER_OPTIONS->Initial_Parameter_Temperature = read_double;
+
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%d", &read_int);
+  RECUR_USER_OPTIONS->Acceptance_Frequency_Modulus = read_int;
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%d", &read_int);
+  RECUR_USER_OPTIONS->Generated_Frequency_Modulus = read_int;
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%d", &read_int);
+  RECUR_USER_OPTIONS->Reanneal_Cost = read_int;
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%d", &read_int);
+  RECUR_USER_OPTIONS->Reanneal_Parameters = read_int;
+
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%lf", &read_double);
+  RECUR_USER_OPTIONS->Delta_X = read_double;
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%d", &read_int);
+  RECUR_USER_OPTIONS->User_Tangents = read_int;
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%d", &read_int);
+  RECUR_USER_OPTIONS->Curvature_0 = read_int;
+
+#else /* RECUR_OPTIONS_FILE */
+  RECUR_USER_OPTIONS->Limit_Acceptances = 100;
+  RECUR_USER_OPTIONS->Limit_Generated = 1000;
+  RECUR_USER_OPTIONS->Limit_Invalid_Generated_States = 1000;
+  RECUR_USER_OPTIONS->Accepted_To_Generated_Ratio = 1.0E-4;
+
+  RECUR_USER_OPTIONS->Cost_Precision = 1.0E-18;
+  RECUR_USER_OPTIONS->Maximum_Cost_Repeat = 2;
+  RECUR_USER_OPTIONS->Number_Cost_Samples = 2;
+  RECUR_USER_OPTIONS->Temperature_Ratio_Scale = 1.0E-5;
+  RECUR_USER_OPTIONS->Cost_Parameter_Scale_Ratio = 1.0;
+  RECUR_USER_OPTIONS->Temperature_Anneal_Scale = 100.0;
+
+  RECUR_USER_OPTIONS->Include_Integer_Parameters = FALSE;
+  RECUR_USER_OPTIONS->User_Initial_Parameters = FALSE;
+  RECUR_USER_OPTIONS->Sequential_Parameters = -1;
+  RECUR_USER_OPTIONS->Initial_Parameter_Temperature = 1.0;
+
+  RECUR_USER_OPTIONS->Acceptance_Frequency_Modulus = 15;
+  RECUR_USER_OPTIONS->Generated_Frequency_Modulus = 10000;
+  RECUR_USER_OPTIONS->Reanneal_Cost = FALSE;
+  RECUR_USER_OPTIONS->Reanneal_Parameters = FALSE;
+
+  RECUR_USER_OPTIONS->Delta_X = 1.0E-6;
+  RECUR_USER_OPTIONS->User_Tangents = FALSE;
+  RECUR_USER_OPTIONS->Curvature_0 = TRUE;
+
+#endif /* RECUR_OPTIONS_FILE */
+
+  /* the number of parameters for the recur_cost_function */
+#if RECUR_OPTIONS_FILE_DATA
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%s", read_option);
+
+#if INT_ALLOC
+  fscanf (recur_ptr_options, "%d", &read_int);
+  *recur_parameter_dimension = read_int;
+#else
+#if INT_LONG
+  fscanf (recur_ptr_options, "%ld", &read_long);
+  *recur_parameter_dimension = read_long;
+#else
+  fscanf (recur_ptr_options, "%d", &read_int);
+  *recur_parameter_dimension = read_int;
+#endif
+#endif
+
+#else /* RECUR_OPTIONS_FILE_DATA */
+#if ASA_TEMPLATE_SELFOPT
+  *recur_parameter_dimension = 2;
+#endif
+#if MY_TEMPLATE                 /* MY_TEMPLATE_recur_dim */
+  /* If not using RECUR_OPTIONS_FILE_DATA or data read from recur_asa_opt,
+     insert the number of parameters for the recur_cost_function */
+#endif /* MY_TEMPLATE recur_dim */
+#endif /* RECUR_OPTIONS_FILE_DATA */
+  if ((recur_parameter_lower_bound =
+       (double *) calloc (*recur_parameter_dimension,
+                          sizeof (double))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): recur_parameter_lower_bound");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  if ((recur_parameter_upper_bound =
+       (double *) calloc (*recur_parameter_dimension,
+                          sizeof (double))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): recur_parameter_upper_bound");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+
+  if ((recur_cost_parameters =
+       (double *) calloc (*recur_parameter_dimension,
+                          sizeof (double))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): recur_cost_parameters");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+
+  if ((recur_parameter_int_real =
+       (int *) calloc (*recur_parameter_dimension, sizeof (int))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): recur_parameter_int_real");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+
+  if ((recur_cost_tangents =
+       (double *) calloc (*recur_parameter_dimension,
+                          sizeof (double))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): recur_cost_tangents");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+
+  if (RECUR_USER_OPTIONS->Curvature_0 == FALSE
+      || RECUR_USER_OPTIONS->Curvature_0 == -1) {
+
+    if ((recur_cost_curvature =
+         (double *) calloc ((*recur_parameter_dimension)
+                            * (*recur_parameter_dimension),
+                            sizeof (double))) == NULL) {
+      strcpy (user_exit_msg, "main()/asa_main(): recur_cost_curvature");
+      Exit_USER (user_exit_msg);
+      return (-2);
+    }
+  } else {
+    recur_cost_curvature = (double *) NULL;
+  }
+
+#if ASA_TEMPLATE_SELFOPT
+  /* Set memory to that required for use. */
+  RECUR_USER_OPTIONS->Asa_Data_Dim_Dbl = 1;
+  if ((RECUR_USER_OPTIONS->Asa_Data_Dbl =
+       (double *) calloc (RECUR_USER_OPTIONS->Asa_Data_Dim_Dbl,
+                          sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "main()/asa_main(): RECUR_USER_OPTIONS->Asa_Data_Dbl");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  /* Use Asa_Data[0] as flag, e.g., if used with SELF_OPTIMIZE. */
+  RECUR_USER_OPTIONS->Asa_Data_Dbl[0] = 0;
+#endif /* ASA_TEMPLATE_SELFOPT */
+
+#if OPTIONAL_DATA_PTR
+#if ASA_TEMPLATE
+  RECUR_USER_OPTIONS->Asa_Data_Dim_Ptr = 1;
+  if ((RECUR_USER_OPTIONS->Asa_Data_Ptr =
+       (OPTIONAL_PTR_TYPE *) calloc (RECUR_USER_OPTIONS->Asa_Data_Dim_Ptr,
+                                     sizeof (OPTIONAL_PTR_TYPE))) == NULL) {
+    strcpy (user_exit_msg,
+            "main()/asa_main(): RECUR_USER_OPTIONS->Asa_Data_Ptr");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#endif /* ASA_TEMPLATE */
+#endif /* OPTIONAL_DATA_PTR */
+
+#if ASA_SAVE
+  /* Such data could be saved in a user_save file, but for
+     convenience here everything is saved in asa_save. */
+  RECUR_USER_OPTIONS->Random_Array_Dim = SHUFFLE;
+  RECUR_USER_OPTIONS->Random_Array = random_array;
+#endif /* ASA_SAVE */
+
+  /* open the output file */
+#if ASA_SAVE
+  if (!strcmp (USER_OUT, "STDOUT")) {
+#if INCL_STDOUT
+    ptr_out = stdout;
+#endif /* INCL_STDOUT */
+  } else {
+    ptr_out = fopen (USER_OUT, "a");
+  }
+#else
+  if (!strcmp (USER_OUT, "STDOUT")) {
+#if INCL_STDOUT
+    ptr_out = stdout;
+#endif /* INCL_STDOUT */
+  } else {
+    ptr_out = fopen (USER_OUT, "w");
+  }
+#endif
+//  fprintf (ptr_out, "%s\n\n", USER_ID);
+
+  fflush (ptr_out);
+
+  if ((recur_rand_seed =
+       (ALLOC_INT *) calloc (1, sizeof (ALLOC_INT))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): recur_rand_seed");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+
+  /* first value of *recur_rand_seed */
+#if ASA_LIB
+  *recur_rand_seed = (asa_rand_seed ? *asa_rand_seed : (LONG_INT) 696969);
+#else
+  *recur_rand_seed = 696969;
+#endif
+
+  randflt (recur_rand_seed);
+
+#if USER_COST_SCHEDULE
+  RECUR_USER_OPTIONS->Cost_Schedule = recur_user_cost_schedule;
+#endif
+#if USER_ACCEPTANCE_TEST
+  RECUR_USER_OPTIONS->Acceptance_Test = recur_user_acceptance_test;
+#endif
+#if USER_ACCEPT_ASYMP_EXP
+  RECUR_USER_OPTIONS->Asymp_Exp_Param = 1.0;
+#endif
+#if USER_GENERATING_FUNCTION
+  RECUR_USER_OPTIONS->Generating_Distrib = recur_user_generating_distrib;
+#endif
+#if USER_REANNEAL_COST
+  RECUR_USER_OPTIONS->Reanneal_Cost_Function = recur_user_reanneal_cost;
+#endif
+#if USER_REANNEAL_PARAMETERS
+  RECUR_USER_OPTIONS->Reanneal_Params_Function = recur_user_reanneal_params;
+#endif
+
+#if MY_TEMPLATE                 /* MY_TEMPLATE_recur_pre_initialize */
+  /* last changes before entering recur_initialize_parameters() */
+#endif
+
+  /* initialize the users parameters, allocating space, etc.
+     Note that the default is to have asa generate the initial
+     recur_cost_parameters that satisfy the user's constraints. */
+
+  recur_initialize_parameters_value =
+    recur_initialize_parameters (recur_cost_parameters,
+                                 recur_parameter_lower_bound,
+                                 recur_parameter_upper_bound,
+                                 recur_cost_tangents,
+                                 recur_cost_curvature,
+                                 recur_parameter_dimension,
+                                 recur_parameter_int_real,
+#if RECUR_OPTIONS_FILE_DATA
+                                 recur_ptr_options,
+#endif
+                                 RECUR_USER_OPTIONS);
+#if RECUR_OPTIONS_FILE
+  fclose (recur_ptr_options);
+#endif
+  if (recur_initialize_parameters_value == -2)
+    return (recur_initialize_parameters_value);
+
+#if USER_ASA_OUT
+  if ((RECUR_USER_OPTIONS->Asa_Out_File =
+       (char *) calloc (80, sizeof (char))) == NULL) {
+    strcpy (user_exit_msg,
+            "main()/asa_main(): RECUR_USER_OPTIONS->Asa_Out_File");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#if ASA_TEMPLATE_SELFOPT
+  strcpy (RECUR_USER_OPTIONS->Asa_Out_File, "asa_sfop");
+#endif
+#endif
+
+  recur_cost_value = asa (RECUR_USER_COST_FUNCTION,
+                          randflt,
+                          recur_rand_seed,
+                          recur_cost_parameters,
+                          recur_parameter_lower_bound,
+                          recur_parameter_upper_bound,
+                          recur_cost_tangents,
+                          recur_cost_curvature,
+                          recur_parameter_dimension,
+                          recur_parameter_int_real,
+                          recur_cost_flag,
+                          recur_exit_code, RECUR_USER_OPTIONS);
+  if (*recur_exit_code == -1) {
+#if INCL_STDOUT
+    printf ("\n\n*** error in calloc in ASA ***\n\n");
+#endif /* INCL_STDOUT */
+    fprintf (ptr_out, "\n\n*** error in calloc in ASA ***\n\n");
+    fflush (ptr_out);
+    return (-1);
+  }
+#if MULTI_MIN
+  fprintf (ptr_out, "Multi_Specify = %d\n",
+           RECUR_USER_OPTIONS->Multi_Specify);
+  for (n_param = 0; n_param < *recur_parameter_dimension; ++n_param) {
+    fprintf (ptr_out,
+#if INT_ALLOC
+             "Multi_Grid[%d] = %12.7g\n",
+#else
+#if INT_LONG
+             "Multi_Grid[%ld] = %12.7g\n",
+#else
+             "Multi_Grid[%d] = %12.7g\n",
+#endif
+#endif
+             n_param, RECUR_USER_OPTIONS->Multi_Grid[n_param]);
+  }
+  fprintf (ptr_out, "\n");
+  for (multi_index = 0; multi_index < RECUR_USER_OPTIONS->Multi_Number;
+       ++multi_index) {
+    fprintf (ptr_out, "\n");
+    fprintf (ptr_out, "Multi_Cost[%d] = %12.7g\n",
+             multi_index, RECUR_USER_OPTIONS->Multi_Cost[multi_index]);
+    for (n_param = 0; n_param < *recur_parameter_dimension; ++n_param) {
+      fprintf (ptr_out,
+#if INT_ALLOC
+               "Multi_Params[%d][%d] = %12.7g\n",
+#else
+#if INT_LONG
+               "Multi_Params[%d][%ld] = %12.7g\n",
+#else
+               "Multi_Params[%d][%d] = %12.7g\n",
+#endif
+#endif
+               multi_index, n_param,
+               RECUR_USER_OPTIONS->Multi_Params[multi_index][n_param]);
+    }
+  }
+  fprintf (ptr_out, "\n");
+  fflush (ptr_out);
+#endif /* MULTI_MIN */
+
+#if FITLOC
+  /* Fit_Local and Penalty may be set adaptively */
+  RECUR_USER_OPTIONS->Penalty = 1000;
+  RECUR_USER_OPTIONS->Fit_Local = 0;
+  RECUR_USER_OPTIONS->Iter_Max = 500;
+  if (RECUR_USER_OPTIONS->Fit_Local >= 1) {
+    recur_cost_value = fitloc (RECUR_USER_COST_FUNCTION,
+                               recur_cost_parameters,
+                               recur_parameter_lower_bound,
+                               recur_parameter_upper_bound,
+                               recur_cost_tangents,
+                               recur_cost_curvature,
+                               recur_parameter_dimension,
+                               recur_parameter_int_real,
+                               recur_cost_flag,
+                               recur_exit_code, RECUR_USER_OPTIONS, ptr_out);
+  }
+#endif /* FITLOC */
+
+  fprintf (ptr_out, "\n\n recur_cost_value = %12.7g\n", recur_cost_value);
+#if MY_TEMPLATE                 /* MY_TEMPLATE_recur_post_recur_asa */
+#endif
+#if ASA_TEMPLATE_LIB
+  *main_recur_cost_value = recur_cost_value;
+  for (recur_v = 0; recur_v < *recur_parameter_dimension; ++recur_v) {
+    main_recur_cost_parameters[recur_v] = recur_cost_parameters[recur_v];
+  }
+  *main_recur_exit_code = *recur_exit_code;
+#endif
+
+  for (recur_v = 0; recur_v < *recur_parameter_dimension; ++recur_v)
+#if INT_ALLOC
+    fprintf (ptr_out, "recur_cost_parameters[%d] = %12.7g\n",
+#else
+#if INT_LONG
+    fprintf (ptr_out, "recur_cost_parameters[%ld] = %12.7g\n",
+#else
+    fprintf (ptr_out, "recur_cost_parameters[%d] = %12.7g\n",
+#endif
+#endif
+             recur_v, recur_cost_parameters[recur_v]);
+
+  fprintf (ptr_out, "\n\n");
+
+
+  /* close all files */
+  ptr_out != stdout && fclose (ptr_out);
+
+#if OPTIONAL_DATA_DBL
+  free (RECUR_USER_OPTIONS->Asa_Data_Dbl);
+#endif
+#if OPTIONAL_DATA_INT
+  free (RECUR_USER_OPTIONS->Asa_Data_Int);
+#endif
+#if OPTIONAL_DATA_PTR
+  free (RECUR_USER_OPTIONS->Asa_Data_Ptr);
+#endif
+#if USER_ASA_OUT
+  free (RECUR_USER_OPTIONS->Asa_Out_File);
+#endif
+#if ASA_SAMPLE
+  free (RECUR_USER_OPTIONS->Bias_Generated);
+#endif
+#if ASA_QUEUE
+#if ASA_RESOLUTION
+#else
+  free (RECUR_USER_OPTIONS->Queue_Resolution);
+#endif
+#endif
+#if ASA_RESOLUTION
+  free (RECUR_USER_OPTIONS->Coarse_Resolution);
+#endif
+  if (RECUR_USER_OPTIONS->Curvature_0 == FALSE
+      || RECUR_USER_OPTIONS->Curvature_0 == -1)
+    free (recur_cost_curvature);
+#if USER_INITIAL_PARAMETERS_TEMPS
+  free (RECUR_USER_OPTIONS->User_Parameter_Temperature);
+#endif
+#if USER_INITIAL_COST_TEMP
+  free (RECUR_USER_OPTIONS->User_Cost_Temperature);
+#endif
+#if DELTA_PARAMETERS
+  free (RECUR_USER_OPTIONS->User_Delta_Parameter);
+#endif
+#if QUENCH_PARAMETERS
+  free (RECUR_USER_OPTIONS->User_Quench_Param_Scale);
+#endif
+#if QUENCH_COST
+  free (RECUR_USER_OPTIONS->User_Quench_Cost_Scale);
+#endif
+#if RATIO_TEMPERATURE_SCALES
+  free (RECUR_USER_OPTIONS->User_Temperature_Ratio);
+#endif
+#if MULTI_MIN
+  free (RECUR_USER_OPTIONS->Multi_Cost);
+  free (RECUR_USER_OPTIONS->Multi_Grid);
+  for (multi_index = 0; multi_index < RECUR_USER_OPTIONS->Multi_Number;
+       ++multi_index) {
+    free (RECUR_USER_OPTIONS->Multi_Params[multi_index]);
+  }
+  free (RECUR_USER_OPTIONS->Multi_Params);
+#endif /* MULTI_MIN */
+  free (RECUR_USER_OPTIONS);
+  free (recur_parameter_dimension);
+  free (recur_exit_code);
+  free (recur_cost_flag);
+  free (recur_parameter_lower_bound);
+  free (recur_parameter_upper_bound);
+  free (recur_cost_parameters);
+  free (recur_parameter_int_real);
+  free (recur_cost_tangents);
+  free (recur_rand_seed);
+
+  return (0);
+  /* NOTREACHED */
+}
+
+/***********************************************************************
+* recur_initialize_parameters
+*	This depends on the users cost function to optimize (minimum).
+*	The routine allocates storage needed for asa. The user should
+*	define the number of parameters and their ranges,
+*	and make sure the initial parameters are within
+*	the minimum and maximum ranges. The array
+*	recur_parameter_int_real should be REAL_TYPE (-1)
+*       for real parameters,
+***********************************************************************/
+#if HAVE_ANSI
+int
+recur_initialize_parameters (double *recur_cost_parameters,
+                             double *recur_parameter_lower_bound,
+                             double *recur_parameter_upper_bound,
+                             double *recur_cost_tangents,
+                             double *recur_cost_curvature,
+                             ALLOC_INT * recur_parameter_dimension,
+                             int *recur_parameter_int_real,
+#if RECUR_OPTIONS_FILE_DATA
+                             FILE * recur_ptr_options,
+#endif
+                             USER_DEFINES * RECUR_USER_OPTIONS)
+#else
+int
+recur_initialize_parameters (recur_cost_parameters,
+                             recur_parameter_lower_bound,
+                             recur_parameter_upper_bound,
+                             recur_cost_tangents,
+                             recur_cost_curvature,
+                             recur_parameter_dimension,
+                             recur_parameter_int_real,
+#if RECUR_OPTIONS_FILE_DATA
+                             recur_ptr_options,
+#endif
+                             RECUR_USER_OPTIONS)
+     double *recur_parameter_lower_bound;
+     double *recur_parameter_upper_bound;
+     double *recur_cost_parameters;
+     double *recur_cost_tangents;
+     double *recur_cost_curvature;
+     ALLOC_INT *recur_parameter_dimension;
+     int *recur_parameter_int_real;
+#if RECUR_OPTIONS_FILE_DATA
+     FILE *recur_ptr_options;
+#endif
+     USER_DEFINES *RECUR_USER_OPTIONS;
+#endif
+{
+  ALLOC_INT index;
+#if RECUR_OPTIONS_FILE_DATA
+  char read_option[80];
+  ALLOC_INT read_index;
+#endif
+#if MY_TEMPLATE                 /* MY_TEMPLATE_recur_init_decl */
+  /* add some declarations if required */
+#endif
+#if MULTI_MIN
+  int multi_index;
+#endif
+
+#if RECUR_OPTIONS_FILE_DATA
+  fscanf (recur_ptr_options, "%s", read_option);
+
+  for (index = 0; index < *recur_parameter_dimension; ++index) {
+#if MY_TEMPLATE                 /* MY_TEMPLATE_recur_read_opt */
+    /* put in some code as required to alter lines read from recur_asa_opt */
+#endif
+#if INT_ALLOC
+    fscanf (recur_ptr_options, "%d", &read_index);
+#else
+#if INT_LONG
+    fscanf (recur_ptr_options, "%ld", &read_index);
+#else
+    fscanf (recur_ptr_options, "%d", &read_index);
+#endif
+#endif
+    fscanf (recur_ptr_options, "%lf%lf%lf%d",
+            &(recur_parameter_lower_bound[read_index]),
+            &(recur_parameter_upper_bound[read_index]),
+            &(recur_cost_parameters[read_index]),
+            &(recur_parameter_int_real[read_index]));
+  }
+#else /* RECUR_OPTIONS_FILE_DATA */
+#if ASA_TEMPLATE_SELFOPT
+  /*  NOTE:
+     USER_OPTIONS->Temperature_Ratio_Scale = x[0];
+     USER_OPTIONS->Cost_Parameter_Scale_Ratio = x[1];
+   */
+
+  /* store the initial parameter values */
+  recur_cost_parameters[0] = 1.0E-5;
+  recur_cost_parameters[1] = 1.0;
+
+  recur_parameter_lower_bound[0] = 1.0E-6;
+  recur_parameter_upper_bound[0] = 1.0E-4;
+
+  recur_parameter_lower_bound[1] = 0.5;
+  recur_parameter_upper_bound[1] = 3.0;
+
+  /* store the initial parameter types */
+  for (index = 0; index < *recur_parameter_dimension; ++index)
+    recur_parameter_int_real[index] = REAL_TYPE;
+#endif
+#endif /* RECUR_OPTIONS_FILE_DATA */
+
+#if USER_INITIAL_PARAMETERS_TEMPS
+  if ((RECUR_USER_OPTIONS->User_Parameter_Temperature =
+       (double *) calloc (*recur_parameter_dimension,
+                          sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "recur_initialize_parameters(): RECUR_USER_OPTIONS->User_Parameter_Temperature");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  for (index = 0; index < *recur_parameter_dimension; ++index)
+    RECUR_USER_OPTIONS->User_Parameter_Temperature[index] = 1.0;
+#endif /* USER_INITIAL_PARAMETERS_TEMPS */
+#if USER_INITIAL_COST_TEMP
+  if ((RECUR_USER_OPTIONS->User_Cost_Temperature =
+       (double *) calloc (1, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "recur_initialize_parameters(): RECUR_USER_OPTIONS->User_Cost_Temperature");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  RECUR_USER_OPTIONS->User_Cost_Temperature[0] = 5.936648E+09;
+#endif /* USER_INITIAL_COST_TEMP */
+#if DELTA_PARAMETERS
+  if ((RECUR_USER_OPTIONS->User_Delta_Parameter =
+       (double *) calloc (*recur_parameter_dimension,
+                          sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "recur_initialize_parameters(): RECUR_USER_OPTIONS->User_Delta_Parameter");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  for (index = 0; index < *recur_parameter_dimension; ++index)
+    RECUR_USER_OPTIONS->User_Delta_Parameter[index] = 0.001;
+#endif /* DELTA_PARAMETERS */
+#if QUENCH_PARAMETERS
+  if ((RECUR_USER_OPTIONS->User_Quench_Param_Scale =
+       (double *) calloc (*recur_parameter_dimension,
+                          sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "recur_initialize_parameters(): RECUR_USER_OPTIONS->User_Quench_Param_Scale");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#if ASA_TEMPLATE
+  for (index = 0; index < *recur_parameter_dimension; ++index)
+    RECUR_USER_OPTIONS->User_Quench_Param_Scale[index] = 1.0;
+#endif
+#endif /* QUENCH_PARAMETERS */
+#if QUENCH_COST
+  if ((RECUR_USER_OPTIONS->User_Quench_Cost_Scale =
+       (double *) calloc (1, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "recur_initialize_parameters(): RECUR_USER_OPTIONS->User_Quench_Cost_Scale");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#if ASA_TEMPLATE
+  RECUR_USER_OPTIONS->User_Quench_Cost_Scale[0] = 1.0;
+#endif
+#endif /* QUENCH_COST */
+
+  /* use asa_opt_recur to read in QUENCH RECUR_USER_OPTIONS */
+#if RECUR_OPTIONS_FILE_DATA
+#if QUENCH_COST
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%lf",
+          &(RECUR_USER_OPTIONS->User_Quench_Cost_Scale[0]));
+
+#if QUENCH_PARAMETERS
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%s", read_option);
+  for (index = 0; index < *recur_parameter_dimension; ++index) {
+#if INT_ALLOC
+    fscanf (recur_ptr_options, "%d", &read_index);
+#else
+#if INT_LONG
+    fscanf (recur_ptr_options, "%ld", &read_index);
+#else
+    fscanf (recur_ptr_options, "%d", &read_index);
+#endif
+#endif
+    fscanf (recur_ptr_options, "%lf",
+            &(RECUR_USER_OPTIONS->User_Quench_Param_Scale[read_index]));
+  }
+#endif /* QUENCH_PARAMETERS */
+#endif /* QUENCH_COST */
+#endif /* RECUR_OPTIONS_FILE_DATA */
+#if RATIO_TEMPERATURE_SCALES
+  if ((RECUR_USER_OPTIONS->User_Temperature_Ratio =
+       (double *) calloc (*recur_parameter_dimension,
+                          sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "recur_initialize_parameters(): RECUR_USER_OPTIONS->User_Temperature_Ratio");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#if ASA_TEMPLATE
+  for (index = 0; index < *recur_parameter_dimension; ++index)
+    RECUR_USER_OPTIONS->User_Temperature_Ratio[index] = 1.0;
+#endif
+#endif /* RATIO_TEMPERATURE_SCALES */
+  /* Defines the limit of collection of sampled data by asa */
+#if ASA_SAMPLE
+  /* create memory for Bias_Generated[] */
+  if ((RECUR_USER_OPTIONS->Bias_Generated =
+       (double *) calloc (*recur_parameter_dimension,
+                          sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "recur_initialize_parameters(): RECUR_USER_OPTIONS->Bias_Generated");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#if ASA_TEMPLATE
+  RECUR_USER_OPTIONS->Limit_Weights = 1.0E-7;
+#if QUENCH_COST
+  RECUR_USER_OPTIONS->User_Quench_Cost_Scale[0] = 1.0;
+#endif
+#if QUENCH_PARAMETERS
+  for (index = 0; index < *recur_parameter_dimension; ++index)
+    RECUR_USER_OPTIONS->User_Quench_Param_Scale[index] = 1.0;
+#endif
+#endif /* ASA_TEMPLATE */
+#endif /* ASA_SAMPLE */
+
+#if ASA_TEMPLATE
+#if ASA_PARALLEL
+  RECUR_USER_OPTIONS->Gener_Block = 1;
+  RECUR_USER_OPTIONS->Gener_Block_Max = 1;
+  RECUR_USER_OPTIONS->Gener_Mov_Avr = 1;
+#endif
+#endif
+#if ASA_RESOLUTION
+  if ((RECUR_USER_OPTIONS->Coarse_Resolution =
+       (double *) calloc (*recur_parameter_dimension,
+                          sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "recur_initialize_parameters(): RECUR_USER_OPTIONS->Coarse_Resolution");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#endif
+#if MULTI_MIN
+#if ASA_TEMPLATE
+  RECUR_USER_OPTIONS->Multi_Number = 2;
+#endif
+  if ((RECUR_USER_OPTIONS->Multi_Cost =
+       (double *) calloc (RECUR_USER_OPTIONS->Multi_Number,
+                          sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "initialize_parameters(): RECUR_USER_OPTIONS->Multi_Cost");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  if ((RECUR_USER_OPTIONS->Multi_Grid =
+       (double *) calloc (*recur_parameter_dimension,
+                          sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "recur_initialize_parameters(): RECUR_USER_OPTIONS->Multi_Grid");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  if ((RECUR_USER_OPTIONS->Multi_Params =
+       (double **) calloc (RECUR_USER_OPTIONS->Multi_Number,
+                           sizeof (double *))) == NULL) {
+    strcpy (user_exit_msg,
+            "initialize_parameters(): RECUR_USER_OPTIONS->Multi_Params");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  for (multi_index = 0; multi_index < RECUR_USER_OPTIONS->Multi_Number;
+       ++multi_index) {
+    if ((RECUR_USER_OPTIONS->Multi_Params[multi_index] =
+         (double *) calloc (*recur_parameter_dimension,
+                            sizeof (double))) == NULL) {
+      strcpy (user_exit_msg,
+              "recur_initialize_parameters(): RECUR_USER_OPTIONS->Multi_Params[multi_index]");
+      Exit_USER (user_exit_msg);
+      return (-2);
+    }
+  }
+#if ASA_TEST
+  for (index = 0; index < *recur_parameter_dimension; ++index) {
+    RECUR_USER_OPTIONS->Multi_Grid[index] = 0.05;
+  }
+  RECUR_USER_OPTIONS->Multi_Specify = 0;
+#endif
+#if ASA_TEMPLATE
+  for (index = 0; index < *recur_parameter_dimension; ++index) {
+    RECUR_USER_OPTIONS->Multi_Grid[index] =
+      (recur_parameter_upper_bound[index] -
+       recur_parameter_lower_bound[index]) / 100.0;
+  }
+  RECUR_USER_OPTIONS->Multi_Specify = 0;
+#endif /* ASA_TEMPLATE */
+#endif /* MULTI_MIN */
+#if ASA_TEMPLATE_QUEUE
+  RECUR_USER_OPTIONS->Queue_Size = 0;
+#endif
+#if ASA_QUEUE
+#if ASA_RESOLUTION
+  RECUR_USER_OPTIONS->Queue_Resolution =
+    RECUR_USER_OPTIONS->Coarse_Resolution;
+#else /* ASA_RESOLUTION */
+  if ((RECUR_USER_OPTIONS->Queue_Resolution =
+       (double *) calloc (*recur_parameter_dimension,
+                          sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "recur_initialize_parameters(): RECUR_USER_OPTIONS->Queue_Resolution");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#endif /* ASA_RESOLUTION */
+#if ASA_TEMPLATE_QUEUE
+  RECUR_USER_OPTIONS->Queue_Size = 0;
+#endif
+#endif /* ASA_QUEUE */
+#if MY_TEMPLATE                 /* MY_TEMPLATE_recur_params */
+  /* If not using RECUR_OPTIONS_FILE_DATA or data read from recur_asa_opt,
+     store the recur_parameter ranges
+     store the recur_parameter types
+     store the initial recur_parameter values
+     other changes needed for initialization */
+#endif /* MY_TEMPLATE recur_params */
+  RECUR_USER_OPTIONS->Asa_Recursive_Level = 1;
+
+  return (0);
+}
+
+/***********************************************************************
+* double recur_cost_function
+*	This is the users cost function to optimize
+*	(find the minimum).
+*	cost_flag is set to TRUE if the parameter set
+*	does not violates any constraints
+*       recur_parameter_lower_bound and recur_parameter_upper_bound
+*       may be adaptively changed during the search.
+***********************************************************************/
+#if HAVE_ANSI
+double
+recur_cost_function (double *x,
+                     double *recur_parameter_lower_bound,
+                     double *recur_parameter_upper_bound,
+                     double *recur_cost_tangents,
+                     double *recur_cost_curvature,
+                     ALLOC_INT * recur_parameter_dimension,
+                     int *recur_parameter_int_real,
+                     int *recur_cost_flag,
+                     int *recur_exit_code, USER_DEFINES * RECUR_USER_OPTIONS)
+#else
+double
+recur_cost_function (x,
+                     recur_parameter_lower_bound,
+                     recur_parameter_upper_bound,
+                     recur_cost_tangents,
+                     recur_cost_curvature,
+                     recur_parameter_dimension,
+                     recur_parameter_int_real,
+                     recur_cost_flag, recur_exit_code, RECUR_USER_OPTIONS)
+     double *x;
+     double *recur_parameter_lower_bound;
+     double *recur_parameter_upper_bound;
+     double *recur_cost_tangents;
+     double *recur_cost_curvature;
+     ALLOC_INT *recur_parameter_dimension;
+     int *recur_parameter_int_real;
+     int *recur_cost_flag;
+     int *recur_exit_code;
+     USER_DEFINES *RECUR_USER_OPTIONS;
+#endif
+{
+  double cost_value;
+  static LONG_INT recur_funevals = 0;
+  int *exit_code;
+#if OPTIONAL_DATA_PTR
+  int data_ptr_flg;
+#endif
+#if OPTIONS_FILE
+  FILE *ptr_options;
+  char read_option[80];
+  char read_if[4], read_FALSE[6], read_comm1[3], read_ASA_SAVE[9],
+    read_comm2[3];
+  int read_int;
+#if INT_LONG
+  LONG_INT read_long;
+#endif
+  double read_double;
+#endif
+#if MY_TEMPLATE                 /* MY_TEMPLATE_recur_cost_decl */
+  /* add some declarations if required */
+#endif
+
+  double *parameter_lower_bound, *parameter_upper_bound;
+  double *cost_parameters;
+  double *cost_tangents, *cost_curvature;
+  ALLOC_INT *parameter_dimension;
+  int *parameter_int_real;
+  int *cost_flag;
+  static LONG_INT *rand_seed;
+  static int initial_flag = 0;
+#if MULTI_MIN
+  int multi_index;
+#endif
+
+  USER_DEFINES *USER_OPTIONS;
+
+  recur_funevals = recur_funevals + 1;
+
+  if ((rand_seed = (ALLOC_INT *) calloc (1, sizeof (ALLOC_INT))) == NULL) {
+    strcpy (user_exit_msg, "recur_cost_function(): rand_seed");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+
+  if ((USER_OPTIONS =
+       (USER_DEFINES *) calloc (1, sizeof (USER_DEFINES))) == NULL) {
+    strcpy (user_exit_msg, "recur_cost_function(): USER_OPTIONS");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#if OPTIONS_FILE
+  /* Test to see if asa_opt is in correct directory.
+     This is useful for some PC and Mac compilers. */
+  if ((ptr_options = fopen ("asa_opt", "r")) == NULL) {
+    fprintf (ptr_out, "\n\n*** fopen asa_opt failed *** \n\n");
+    fflush (ptr_out);
+#if INCL_STDOUT
+    printf ("\n\n*** EXIT fopen asa_opt failed *** \n\n");
+#endif /* INCL_STDOUT */
+    return (6);
+  }
+
+  fscanf (ptr_options, "%s%s%s%s%s",
+          read_if, read_FALSE, read_comm1, read_ASA_SAVE, read_comm2);
+  if (strcmp (read_if, "#if") || strcmp (read_FALSE, "FALSE") ||
+      strcmp (read_comm1, "/*") || strcmp (read_ASA_SAVE, "ASA_SAVE") ||
+      strcmp (read_comm2, "*/")) {
+    fprintf (ptr_out, "\n\n*** not asa_opt for this version *** \n\n");
+    fflush (ptr_out);
+#if INCL_STDOUT
+    printf ("\n\n*** EXIT not asa_opt for this version *** \n\n");
+#endif /* INCL_STDOUT */
+    return (-6);
+  }
+#if INT_LONG
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%ld", &read_long);
+  USER_OPTIONS->Limit_Acceptances = read_long;
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%ld", &read_long);
+  USER_OPTIONS->Limit_Generated = read_long;
+#else
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%d", &read_int);
+  USER_OPTIONS->Limit_Acceptances = read_int;
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%d", &read_int);
+  USER_OPTIONS->Limit_Generated = read_int;
+#endif
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%d", &read_int);
+  USER_OPTIONS->Limit_Invalid_Generated_States = read_int;
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%lf", &read_double);
+  USER_OPTIONS->Accepted_To_Generated_Ratio = read_double;
+
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%lf", &read_double);
+  USER_OPTIONS->Cost_Precision = read_double;
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%d", &read_int);
+  USER_OPTIONS->Maximum_Cost_Repeat = read_int;
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%d", &read_int);
+  USER_OPTIONS->Number_Cost_Samples = read_int;
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%lf", &read_double);
+  USER_OPTIONS->Temperature_Ratio_Scale = read_double;
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%lf", &read_double);
+  USER_OPTIONS->Cost_Parameter_Scale_Ratio = read_double;
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%lf", &read_double);
+  USER_OPTIONS->Temperature_Anneal_Scale = read_double;
+
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%d", &read_int);
+  USER_OPTIONS->Include_Integer_Parameters = read_int;
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%d", &read_int);
+  USER_OPTIONS->User_Initial_Parameters = read_int;
+#if INT_ALLOC
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%d", &read_int);
+  USER_OPTIONS->Sequential_Parameters = read_int;
+#else
+#if INT_LONG
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%ld", &read_long);
+  USER_OPTIONS->Sequential_Parameters = read_long;
+#else
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%d", &read_int);
+  USER_OPTIONS->Sequential_Parameters = read_int;
+#endif
+#endif
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%lf", &read_double);
+  USER_OPTIONS->Initial_Parameter_Temperature = read_double;
+
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%d", &read_int);
+  USER_OPTIONS->Acceptance_Frequency_Modulus = read_int;
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%d", &read_int);
+  USER_OPTIONS->Generated_Frequency_Modulus = read_int;
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%d", &read_int);
+  USER_OPTIONS->Reanneal_Cost = read_int;
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%d", &read_int);
+  USER_OPTIONS->Reanneal_Parameters = read_int;
+
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%lf", &read_double);
+  USER_OPTIONS->Delta_X = read_double;
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%d", &read_int);
+  USER_OPTIONS->User_Tangents = read_int;
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%d", &read_int);
+  USER_OPTIONS->Curvature_0 = read_int;
+#else /* OPTIONS_FILE */
+  /* USER_OPTIONS->Limit_Acceptances = 10000; */
+  USER_OPTIONS->Limit_Acceptances = 1000;
+  USER_OPTIONS->Limit_Generated = 99999;
+  USER_OPTIONS->Limit_Invalid_Generated_States = 1000;
+  USER_OPTIONS->Accepted_To_Generated_Ratio = 1.0E-6;
+
+  USER_OPTIONS->Cost_Precision = 1.0E-18;
+  USER_OPTIONS->Maximum_Cost_Repeat = 2;
+  USER_OPTIONS->Number_Cost_Samples = 2;
+
+  /* These variables are set below in x[.] */
+  /* USER_OPTIONS->Temperature_Ratio_Scale = 1.0E-5; */
+  /* USER_OPTIONS->Cost_Parameter_Scale_Ratio = 1.0; */
+
+  USER_OPTIONS->Temperature_Anneal_Scale = 100.;
+
+  USER_OPTIONS->Include_Integer_Parameters = FALSE;
+  USER_OPTIONS->User_Initial_Parameters = FALSE;
+  USER_OPTIONS->Sequential_Parameters = -1;
+  USER_OPTIONS->Initial_Parameter_Temperature = 1.0;
+
+  USER_OPTIONS->Acceptance_Frequency_Modulus = 100;
+  USER_OPTIONS->Generated_Frequency_Modulus = 10000;
+  USER_OPTIONS->Reanneal_Cost = 1;
+  USER_OPTIONS->Reanneal_Parameters = TRUE;
+
+  USER_OPTIONS->Delta_X = 0.001;
+  USER_OPTIONS->User_Tangents = FALSE;
+  USER_OPTIONS->Curvature_0 = TRUE;
+#endif /* OPTIONS_FILE */
+
+  USER_OPTIONS->Temperature_Ratio_Scale = x[0];
+  USER_OPTIONS->Cost_Parameter_Scale_Ratio = x[1];
+
+  if (initial_flag == 0) {
+    /* first value of *rand_seed */
+#if ASA_LIB
+    *rand_seed = (asa_rand_seed ? *asa_rand_seed : (LONG_INT) 696969);
+#else
+    *rand_seed = 696969;
+#endif
+  }
+
+  if ((parameter_dimension =
+       (ALLOC_INT *) calloc (1, sizeof (ALLOC_INT))) == NULL) {
+    strcpy (user_exit_msg, "recur_cost_function(): parameter_dimension");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  if ((exit_code = (int *) calloc (1, sizeof (int))) == NULL) {
+    strcpy (user_exit_msg, "recur_cost_function(): exit_code");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  if ((cost_flag = (int *) calloc (1, sizeof (int))) == NULL) {
+    strcpy (user_exit_msg, "recur_cost_function(): cost_flag");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+
+  /* the number of parameters for the cost function */
+#if OPTIONS_FILE_DATA
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%s", read_option);
+
+#if INT_ALLOC
+  fscanf (ptr_options, "%d", &read_int);
+  *parameter_dimension = read_int;
+#else
+#if INT_LONG
+  fscanf (ptr_options, "%ld", &read_long);
+  *parameter_dimension = read_long;
+#else
+  fscanf (ptr_options, "%d", &read_int);
+  *parameter_dimension = read_int;
+#endif
+#endif
+
+#else /* OPTIONS_FILE_DATA */
+#if ASA_TEST
+  /* set parameter dimension if SELF_OPTIMIZE=TRUE */
+  *parameter_dimension = 4;
+#endif /* ASA_TEST */
+#endif /* OPTIONS_FILE_DATA */
+#if MY_TEMPLATE                 /* MY_TEMPLATE_recur_dim */
+  /* If not using OPTIONS_FILE_DATA or data read from asa_opt,
+     set parameter dimension if SELF_OPTIMIZE=TRUE */
+#endif /* MY_TEMPLATE recur_dim */
+
+  if ((parameter_lower_bound =
+       (double *) calloc (*parameter_dimension, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg, "recur_cost_function(): parameter_lower_bound");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  if ((parameter_upper_bound =
+       (double *) calloc (*parameter_dimension, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg, "recur_cost_function(): parameter_upper_bound");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  if ((cost_parameters =
+       (double *) calloc (*parameter_dimension, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg, "recur_cost_function(): cost_parameters");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  if ((parameter_int_real =
+       (int *) calloc (*parameter_dimension, sizeof (int))) == NULL) {
+    strcpy (user_exit_msg, "recur_cost_function(): parameter_int_real");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  if ((cost_tangents =
+       (double *) calloc (*parameter_dimension, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg, "recur_cost_function(): cost_tangents");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+
+  if (USER_OPTIONS->Curvature_0 == FALSE || USER_OPTIONS->Curvature_0 == -1) {
+    if ((cost_curvature =
+         (double *) calloc ((*parameter_dimension) *
+                            (*parameter_dimension),
+                            sizeof (double))) == NULL) {
+      strcpy (user_exit_msg, "recur_cost_function(): cost_curvature");
+      Exit_USER (user_exit_msg);
+      return (-2);
+    }
+  } else {
+    cost_curvature = (double *) NULL;
+  }
+
+#if ASA_TEMPLATE_SELFOPT
+  /* Set memory to that required for use. */
+  USER_OPTIONS->Asa_Data_Dim_Dbl = 2;
+  if ((USER_OPTIONS->Asa_Data_Dbl =
+       (double *) calloc (USER_OPTIONS->Asa_Data_Dim_Dbl,
+                          sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "recur_cost_function(): USER_OPTIONS->Asa_Data_Dbl");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  /* Use Asa_Data_Dbl[0] as flag, e.g., if used with SELF_OPTIMIZE. */
+  USER_OPTIONS->Asa_Data_Dbl[0] = 1.0;
+#endif /* ASA_TEMPLATE_SELFOPT */
+
+#if USER_COST_SCHEDULE
+  USER_OPTIONS->Cost_Schedule = user_cost_schedule;
+#endif
+#if USER_ACCEPTANCE_TEST
+  USER_OPTIONS->Acceptance_Test = user_acceptance_test;
+#endif
+#if USER_ACCEPT_ASYMP_EXP
+  USER_OPTIONS->Asymp_Exp_Param = 1.0;
+#endif
+#if USER_GENERATING_FUNCTION
+  USER_OPTIONS->Generating_Distrib = user_generating_distrib;
+#endif
+#if USER_REANNEAL_COST
+  USER_OPTIONS->Reanneal_Cost_Function = user_reanneal_cost;
+#endif
+#if USER_REANNEAL_PARAMETERS
+  USER_OPTIONS->Reanneal_Params_Function = user_reanneal_params;
+#endif
+
+  initialize_parameters (cost_parameters,
+                         parameter_lower_bound,
+                         parameter_upper_bound,
+                         cost_tangents,
+                         cost_curvature,
+                         parameter_dimension, parameter_int_real,
+#if OPTIONS_FILE_DATA
+                         ptr_options,
+#endif
+                         USER_OPTIONS);
+#if OPTIONS_FILE
+  fclose (ptr_options);
+#endif
+
+#if ASA_SAVE
+  USER_OPTIONS->Random_Array_Dim = SHUFFLE;
+  USER_OPTIONS->Random_Array = random_array;
+#endif /* ASA_SAVE */
+
+  /* It might be a good idea to place a loop around this call,
+     and to average over several values of funevals returned by
+     trajectories of cost_value. */
+
+  funevals = 0;
+
+#if USER_ASA_OUT
+  if ((USER_OPTIONS->Asa_Out_File =
+       (char *) calloc (80, sizeof (char))) == NULL) {
+    strcpy (user_exit_msg,
+            "recur_cost_function(): USER_OPTIONS->Asa_Out_File");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#if ASA_TEMPLATE_SELFOPT
+  strcpy (USER_OPTIONS->Asa_Out_File, "asa_rcur");
+#endif
+#endif
+
+#if OPTIONAL_DATA_PTR
+  data_ptr_flg = 1;
+#if ASA_TEMPLATE
+  /* N.b.:  If OPTIONAL_DATA_PTR is being used for RECUR_USER_OPTIONS
+   * as well as for USER_OPTIONS, do not create (or free) additional memory
+   * in recur_cost_function() for Asa_Data_Dim_Ptr and Asa_Data_Ptr to
+   * be passed to the inner cost_function(), but rather link pointers to
+   * those in RECUR_USER_OPTIONS.  Typically, define separate structures
+   * within the structure defined by Asa_Data_Ptr to access info depending
+   * on whether the run in a particular level of cost function in this
+   * recursive operation.  In this case, set * #if TRUE to #if FALSE just
+   * below.  See the ASA-README for more discussion.
+   */
+
+#if TRUE
+  USER_OPTIONS->Asa_Data_Dim_Ptr = 1;
+  if ((USER_OPTIONS->Asa_Data_Ptr =
+       (OPTIONAL_PTR_TYPE *) calloc (USER_OPTIONS->Asa_Data_Dim_Ptr,
+                                     sizeof (OPTIONAL_PTR_TYPE))) == NULL) {
+    strcpy (user_exit_msg,
+            "recur_cost_function(): USER_OPTIONS->Asa_Data_Ptr");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#else
+  USER_OPTIONS->Asa_Data_Dim_Ptr = RECUR_USER_OPTIONS->Asa_Data_Dim_Ptr;
+  USER_OPTIONS->Asa_Data_Ptr = RECUR_USER_OPTIONS->Asa_Data_Ptr;
+  data_ptr_flg = 0;
+#endif
+#endif /* ASA_TEMPLATE */
+  USER_OPTIONS->Asa_Data_Dim_Ptr = 1;
+  if ((USER_OPTIONS->Asa_Data_Ptr =
+       (OPTIONAL_PTR_TYPE *) calloc (USER_OPTIONS->Asa_Data_Dim_Ptr,
+                                     sizeof (OPTIONAL_PTR_TYPE))) == NULL) {
+    strcpy (user_exit_msg,
+            "recur_cost_function(): USER_OPTIONS->Asa_Data_Ptr");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#endif /* OPTIONAL_DATA_PTR */
+
+  cost_value = asa (USER_COST_FUNCTION,
+                    randflt,
+                    rand_seed,
+                    cost_parameters,
+                    parameter_lower_bound,
+                    parameter_upper_bound,
+                    cost_tangents,
+                    cost_curvature,
+                    parameter_dimension,
+                    parameter_int_real, cost_flag, exit_code, USER_OPTIONS);
+  if (*exit_code == -1) {
+#if INCL_STDOUT
+    printf ("\n\n*** error in calloc in ASA ***\n\n");
+#endif /* INCL_STDOUT */
+    fprintf (ptr_out, "\n\n*** error in calloc in ASA ***\n\n");
+    fflush (ptr_out);
+    return (-1);
+  }
+#if MY_TEMPLATE                 /* MY_TEMPLATE_recur_post_asa */
+#endif
+
+  if (cost_value > .001) {
+    *recur_cost_flag = FALSE;
+  } else {
+    *recur_cost_flag = TRUE;
+  }
+
+#if FALSE                       /* set to 1 to activate FAST EXIT */
+  /* Make a quick exit */
+  if (recur_funevals >= 10) {
+    *recur_cost_flag = FALSE;
+    RECUR_USER_OPTIONS->Limit_Invalid_Generated_States = 0;
+    fprintf (ptr_out, "FAST EXIT set at recur_funevals = 10\n\n");
+  }
+#endif
+
+#if TIME_CALC
+  /* print every RECUR_PRINT_FREQUENCY evaluations */
+  if ((RECUR_PRINT_FREQUENCY > 0) &&
+      ((recur_funevals % RECUR_PRINT_FREQUENCY) == 0)) {
+    USER_OPTIONS->Temperature_Ratio_Scale = x[0];
+    fprintf (ptr_out, "USER_OPTIONS->Temperature_Ratio_Scale = %12.7g\n",
+             USER_OPTIONS->Temperature_Ratio_Scale);
+    USER_OPTIONS->Cost_Parameter_Scale_Ratio = x[1];
+    fprintf (ptr_out, "USER_OPTIONS->Cost_Parameter_Scale_Ratio = %12.7g\n",
+             USER_OPTIONS->Cost_Parameter_Scale_Ratio);
+  }
+  print_time ("", ptr_out);
+#endif
+
+  fprintf (ptr_out, "recur_funevals = %ld, *recur_cost_flag = %d\n",
+           recur_funevals, *recur_cost_flag);
+  /* cost function = number generated at best cost */
+#if ASA_TEMPLATE_SELFOPT
+  funevals = (LONG_INT) (USER_OPTIONS->Asa_Data_Dbl[1]);
+  fprintf (ptr_out, "\tbest_funevals = %ld, cost_value = %12.7g\n\n",
+           funevals, cost_value);
+  /* cost function = total number generated during run */
+#endif /* ASA_TEMPLATE_SELFOPT */
+
+#if ASA_SAMPLE
+  fprintf (ptr_out, "\tfunevals = %ld, cost_value = %12.7g\n\n",
+           funevals, cost_value);
+#endif
+  fflush (ptr_out);
+
+#if ASA_TEMPLATE_SAMPLE
+  ptr_asa = fopen ("asa_out", "r");
+  sample (ptr_out, ptr_asa);
+#endif
+
+#if OPTIONAL_DATA_DBL
+  free (USER_OPTIONS->Asa_Data_Dbl);
+#endif
+#if OPTIONAL_DATA_INT
+  free (USER_OPTIONS->Asa_Data_Int);
+#endif
+#if OPTIONAL_DATA_PTR
+  if (data_ptr_flg == 1) {
+    free (USER_OPTIONS->Asa_Data_Ptr);
+  }
+#endif
+#if USER_ASA_OUT
+  free (USER_OPTIONS->Asa_Out_File);
+#endif
+#if ASA_SAMPLE
+  free (USER_OPTIONS->Bias_Generated);
+#endif
+#if ASA_QUEUE
+#if ASA_RESOLUTION
+#else
+  free (USER_OPTIONS->Queue_Resolution);
+#endif
+#endif
+#if ASA_RESOLUTION
+  free (USER_OPTIONS->Coarse_Resolution);
+#endif
+  if (USER_OPTIONS->Curvature_0 == FALSE || USER_OPTIONS->Curvature_0 == -1)
+    free (cost_curvature);
+#if USER_INITIAL_PARAMETERS_TEMPS
+  free (USER_OPTIONS->User_Parameter_Temperature);
+#endif
+#if USER_INITIAL_COST_TEMP
+  free (USER_OPTIONS->User_Cost_Temperature);
+#endif
+#if DELTA_PARAMETERS
+  free (USER_OPTIONS->User_Delta_Parameter);
+#endif
+#if QUENCH_PARAMETERS
+  free (USER_OPTIONS->User_Quench_Param_Scale);
+#endif
+#if QUENCH_COST
+  free (USER_OPTIONS->User_Quench_Cost_Scale);
+#endif
+#if RATIO_TEMPERATURE_SCALES
+  free (USER_OPTIONS->User_Temperature_Ratio);
+#endif
+#if MULTI_MIN
+  free (USER_OPTIONS->Multi_Grid);
+  for (multi_index = 0; multi_index < USER_OPTIONS->Multi_Number;
+       ++multi_index) {
+    free (USER_OPTIONS->Multi_Params[multi_index]);
+  }
+#endif /* MULTI_MIN */
+#if OPTIONAL_DATA_PTR
+  if (data_ptr_flg == 0) {
+    USER_OPTIONS = NULL;
+  }
+#endif
+  free (USER_OPTIONS);
+  free (parameter_dimension);
+  free (exit_code);
+  free (cost_flag);
+  free (parameter_lower_bound);
+  free (parameter_upper_bound);
+  free (cost_parameters);
+  free (parameter_int_real);
+  free (cost_tangents);
+  free (rand_seed);
+
+  return ((double) funevals);
+}
+
+#if USER_COST_SCHEDULE
+#if HAVE_ANSI
+double
+recur_user_cost_schedule (double test_temperature,
+                          USER_DEFINES * RECUR_USER_OPTIONS)
+#else
+double
+recur_user_cost_schedule (test_temperature, RECUR_USER_OPTIONS)
+     double test_temperature;
+     USER_DEFINES *RECUR_USER_OPTIONS;
+#endif /* HAVE_ANSI */
+{
+#if ASA_TEMPLATE
+  double x;
+
+  x = test_temperature;
+
+  return (x);
+#endif
+}
+#endif /* USER_COST_SCHEDULE */
+
+#if USER_ACCEPTANCE_TEST
+#if HAVE_ANSI
+void
+recur_user_acceptance_test (double current_cost,
+                            double *recur_parameter_lower_bound,
+                            double *recur_parameter_upper_bound,
+                            ALLOC_INT * recur_parameter_dimension,
+                            USER_DEFINES * RECUR_USER_OPTIONS)
+#else
+void
+recur_user_acceptance_test (current_cost, recur_parameter_lower_bound,
+                            recur_parameter_upper_bound,
+                            recur_parameter_dimension, RECUR_USER_OPTIONS)
+     double current_cost;
+     double *recur_parameter_lower_bound;
+     double *recur_parameter_upper_bound;
+     ALLOC_INT *recur_parameter_dimension;
+     USER_DEFINES *RECUR_USER_OPTIONS;
+#endif /* HAVE_ANSI */
+{
+  double uniform_test, curr_cost_temp;
+#if USER_ACCEPT_ASYMP_EXP
+  double x, q, delta_cost;
+#endif
+
+#if ASA_TEMPLATE                /* ASA cost index */
+  /* Calculate the current ASA cost index.  This could be useful
+     to define a new schedule for the cost temperature, beyond
+     simple changes that can be made using USER_COST_SCHEDULE. */
+
+  int index;
+  double k_temperature, quench, y;
+  double xrecur_parameter_dimension;
+
+#if QUENCH_COST
+  quench = RECUR_USER_OPTIONS->User_Quench_Cost_Scale[0];
+#else
+  quench = 1.0;
+#endif /* QUENCH_COST */
+  xrecur_parameter_dimension = (double) *recur_parameter_dimension;
+  for (index = 0; index < *recur_parameter_dimension; ++index)
+    if (fabs
+        (recur_parameter_upper_bound[index] -
+         recur_parameter_lower_bound[index]) < (double) EPS_DOUBLE)
+      *xrecur_parameter_dimension -= 1.0;
+
+  y = -F_LOG (RECUR_USER_OPTIONS->Cost_Temp_Curr
+              / RECUR_USER_OPTIONS->Cost_Temp_Init)
+    / RECUR_USER_OPTIONS->Cost_Temp_Scale;
+
+  k_temperature = F_POW (y, xrecur_parameter_dimension / quench);
+#endif /* ASA cost index */
+
+  uniform_test = randflt (RECUR_USER_OPTIONS->Random_Seed);
+  curr_cost_temp = RECUR_USER_OPTIONS->Cost_Temp_Curr;
+
+#if ASA_TEMPLATE
+#if USER_COST_SCHEDULE
+  curr_cost_temp =
+    (RECUR_USER_OPTIONS->Cost_Schedule (RECUR_USER_OPTIONS->Cost_Temp_Curr,
+                                        RECUR_USER_OPTIONS)
+     + (double) EPS_DOUBLE);
+#else
+  curr_cost_temp = RECUR_USER_OPTIONS->Cost_Temp_Curr;
+#endif
+#endif /* ASA_TEMPLATE */
+
+#if USER_ACCEPT_ASYMP_EXP
+#if USER_COST_SCHEDULE
+  curr_cost_temp =
+    (RECUR_USER_OPTIONS->Cost_Schedule (RECUR_USER_OPTIONS->Cost_Temp_Curr,
+                                        RECUR_USER_OPTIONS)
+     + (double) EPS_DOUBLE);
+#endif
+
+  delta_cost = (current_cost - *(RECUR_USER_OPTIONS->Last_Cost))
+    / (curr_cost_temp + (double) EPS_DOUBLE);
+
+  q = RECUR_USER_OPTIONS->Asymp_Exp_Param;
+  if (fabs (1.0 - q) < (double) EPS_DOUBLE)
+    x = MIN (1.0, (F_EXP (-delta_cost)));       /* Boltzmann test */
+  else if ((1.0 - (1.0 - q) * delta_cost) < (double) EPS_DOUBLE)
+    x = MIN (1.0, (F_EXP (-delta_cost)));       /* Boltzmann test */
+  else
+    x = MIN (1.0, F_POW ((1.0 - (1.0 - q) * delta_cost), (1.0 / (1.0 - q))));
+
+  RECUR_USER_OPTIONS->Prob_Bias = x;
+  if (x >= uniform_test)
+    RECUR_USER_OPTIONS->User_Acceptance_Flag = TRUE;
+  else
+    RECUR_USER_OPTIONS->User_Acceptance_Flag = FALSE;
+
+#endif /* USER_ACCEPT_ASYMP_EXP */
+}
+#endif /* USER_ACCEPTANCE_TEST */
+
+#if USER_GENERATING_FUNCTION
+#if HAVE_ANSI
+double
+recur_user_generating_distrib (LONG_INT * seed,
+                               ALLOC_INT * recur_parameter_dimension,
+                               ALLOC_INT index_v,
+                               double temperature_v,
+                               double init_param_temp_v,
+                               double temp_scale_params_v,
+                               double parameter_v,
+                               double parameter_range_v,
+                               double *last_saved_parameter,
+                               USER_DEFINES * RECUR_USER_OPTIONS)
+#else
+double
+recur_user_generating_distrib (seed,
+                               recur_parameter_dimension,
+                               index_v,
+                               temperature_v,
+                               init_param_temp_v,
+                               temp_scale_params_v,
+                               parameter_v,
+                               parameter_range_v,
+                               last_saved_parameter, RECUR_USER_OPTIONS)
+     LONG_INT *seed;
+     ALLOC_INT *recur_parameter_dimension;
+     ALLOC_INT index_v;
+     double temperature_v;
+     double init_param_temp_v;
+     double temp_scale_params_v;
+     double parameter_v;
+     double parameter_range_v;
+     double *last_saved_parameter;
+     USER_DEFINES *RECUR_USER_OPTIONS;
+#endif
+{
+#if ASA_TEMPLATE
+  double x, y, z;
+
+  /* This is the ASA distribution.  A slower temperature schedule can be
+     obtained here, e.g., temperature_v = pow(temperature_v, 0.5); */
+
+  x = randflt (seed);
+  y = x < 0.5 ? -1.0 : 1.0;
+  z = y * temperature_v * (F_POW ((1.0 + 1.0 / temperature_v),
+                                  fabs (2.0 * x - 1.0)) - 1.0);
+
+  x = parameter_v + z * parameter_range_v;
+
+  return (x);
+#endif /* ASA_TEMPLATE */
+}
+#endif /* USER_GENERATING_FUNCTION */
+
+#if USER_REANNEAL_COST
+#if HAVE_ANSI
+int
+recur_user_reanneal_cost (double *cost_best,
+                          double *cost_last,
+                          double *initial_cost_temperature,
+                          double *current_cost_temperature,
+                          USER_DEFINES * RECUR_USER_OPTIONS)
+#else
+int
+recur_user_reanneal_cost (cost_best,
+                          cost_last,
+                          initial_cost_temperature,
+                          current_cost_temperature, RECUR_USER_OPTIONS)
+     double *cost_best;
+     double *cost_last;
+     double *initial_cost_temperature;
+     double *current_cost_temperature;
+     USER_DEFINES *RECUR_USER_OPTIONS;
+#endif /* HAVE_ANSI */
+{
+#if ASA_TEMPLATE
+  double tmp_dbl;
+
+  tmp_dbl = MAX (fabs (*cost_last), fabs (*cost_best));
+  tmp_dbl = MAX ((double) EPS_DOUBLE, tmp_dbl);
+  *initial_cost_temperature = MIN (*initial_cost_temperature, tmp_dbl);
+
+  return (TRUE);
+#endif
+}
+#endif /* USER_REANNEAL_COST */
+
+#if USER_REANNEAL_PARAMETERS
+#if HAVE_ANSI
+double
+recur_user_reanneal_params (double current_temp,
+                            double tangent,
+                            double max_tangent,
+                            USER_DEFINES * RECUR_USER_OPTIONS)
+#else
+double
+recur_user_reanneal_params (current_temp,
+                            tangent, max_tangent, RECUR_USER_OPTIONS)
+     double current_temp;
+     double tangent;
+     double max_tangent;
+     USER_DEFINES *RECUR_USER_OPTIONS;
+#endif /* HAVE_ANSI */
+{
+#if ASA_TEMPLATE
+  double x;
+
+  x = current_temp * (max_tangent / tangent);
+
+  return (x);
+#endif
+}
+#endif /* USER_REANNEAL_PARAMETERS */
+#endif /* SELF_OPTIMIZE */
+
+#if FITLOC
+#if HAVE_ANSI
+double
+calcf (double (*user_cost_function)
+
+        
+       (double *, double *, double *, double *, double *, ALLOC_INT *, int *,
+        int *, int *, USER_DEFINES *), double *xloc,
+       double *parameter_lower_bound, double *parameter_upper_bound,
+       double *cost_tangents, double *cost_curvature,
+       ALLOC_INT * parameter_dimension, int *parameter_int_real,
+       int *cost_flag, int *exit_code, USER_DEFINES * OPTIONS, FILE * ptr_out)
+#else
+double
+calcf (user_cost_function,
+       xloc,
+       parameter_lower_bound,
+       parameter_upper_bound,
+       cost_tangents,
+       cost_curvature,
+       parameter_dimension,
+       parameter_int_real, cost_flag, exit_code, OPTIONS, ptr_out)
+     double (*user_cost_function) ();
+     double *x;
+     double *parameter_lower_bound;
+     double *parameter_upper_bound;
+     double *cost_tangents;
+     double *cost_curvature;
+     ALLOC_INT *parameter_dimension;
+     int *parameter_int_real;
+     int *cost_flag;
+     int *exit_code;
+     USER_DEFINES *OPTIONS;
+     FILE *ptr_out;
+#endif
+{
+  ALLOC_INT index_v;
+#if FITLOC_ROUND
+  double x, min_parameter_v, max_parameter_v, parameter_range_v;
+#endif
+  double floc;
+#if ASA_RESOLUTION
+  double xres, xint, xplus, xminus, dx, dxminus, dxplus;
+#endif
+
+#if FITLOC_ROUND
+  /* The following section for adjustments of parameters is taken from
+     generate_new_state() in asa.c */
+  for (index_v = 0; index_v < *parameter_dimension; ++index_v) {
+    if (fabs
+        (parameter_lower_bound[index_v] - parameter_upper_bound[index_v]) <
+        EPS_DOUBLE)
+      continue;
+
+    x = xloc[index_v];
+
+    min_parameter_v = parameter_lower_bound[index_v];
+    max_parameter_v = parameter_upper_bound[index_v];
+    parameter_range_v = max_parameter_v - min_parameter_v;
+
+    /* Handle discrete parameters. */
+#if ASA_RESOLUTION
+    xres = OPTIONS->Coarse_Resolution[index_v];
+    if (xres > EPS_DOUBLE) {
+      min_parameter_v -= (xres / 2.0);
+      max_parameter_v += (xres / 2.0);
+      parameter_range_v = max_parameter_v - min_parameter_v;
+    }
+#endif /* ASA_RESOLUTION */
+    if (parameter_int_real[index_v] > 0) {
+#if ASA_RESOLUTION
+      if (xres > EPS_DOUBLE) {
+        ;
+      } else {
+#endif /* ASA_RESOLUTION */
+        min_parameter_v -= 0.5;
+        max_parameter_v += 0.5;
+        parameter_range_v = max_parameter_v - min_parameter_v;
+      }
+#if ASA_RESOLUTION
+    }
+#endif
+#if ASA_RESOLUTION
+    if (xres > EPS_DOUBLE) {
+      xint = xres * (double) ((LONG_INT) (x / xres));
+      xplus = xint + xres;
+      xminus = xint - xres;
+      dx = fabs (xint - x);
+      dxminus = fabs (xminus - x);
+      dxplus = fabs (xplus - x);
+
+      if (dx < dxminus && dx < dxplus)
+        x = xint;
+      else if (dxminus < dxplus)
+        x = xminus;
+      else
+        x = xplus;
+    }
+#endif /* ASA_RESOLUTION */
+
+    /* Handle discrete parameters.
+       You might have to check rounding on your machine. */
+    if (parameter_int_real[index_v] > 0) {
+#if ASA_RESOLUTION
+      if (xres > EPS_DOUBLE) {
+        ;
+      } else {
+#endif /* ASA_RESOLUTION */
+        if (x < min_parameter_v + 0.5)
+          x = min_parameter_v + 0.5 + (double) EPS_DOUBLE;
+        if (x > max_parameter_v - 0.5)
+          x = max_parameter_v - 0.5 + (double) EPS_DOUBLE;
+
+        if (x + 0.5 > 0.0) {
+          x = (double) ((LONG_INT) (x + 0.5));
+        } else {
+          x = (double) ((LONG_INT) (x - 0.5));
+        }
+        if (x > parameter_upper_bound[index_v])
+          x = parameter_upper_bound[index_v];
+        if (x < parameter_lower_bound[index_v])
+          x = parameter_lower_bound[index_v];
+      }
+#if ASA_RESOLUTION
+    }
+    if (xres > EPS_DOUBLE) {
+      if (x < min_parameter_v + xres / 2.0)
+        x = min_parameter_v + xres / 2.0 + (double) EPS_DOUBLE;
+      if (x > max_parameter_v - xres / 2.0)
+        x = max_parameter_v - xres / 2.0 + (double) EPS_DOUBLE;
+
+      if (x > parameter_upper_bound[index_v])
+        x = parameter_upper_bound[index_v];
+      if (x < parameter_lower_bound[index_v])
+        x = parameter_lower_bound[index_v];
+    }
+#endif /* ASA_RESOLUTION */
+    if ((x < parameter_lower_bound[index_v])
+        || (x > parameter_upper_bound[index_v])) {
+      ;
+    } else {
+      xloc[index_v] = x;
+    }
+  }
+#endif /* FITLOC_ROUND */
+
+  floc = user_cost_function (xloc,
+                             parameter_lower_bound,
+                             parameter_upper_bound,
+                             cost_tangents,
+                             cost_curvature,
+                             parameter_dimension,
+                             parameter_int_real,
+                             cost_flag, exit_code, OPTIONS);
+
+  if (*cost_flag == FALSE) {
+    floc += OPTIONS->Penalty;
+  }
+
+  for (index_v = 0; index_v < *parameter_dimension; ++index_v) {
+    if (parameter_upper_bound[index_v] - xloc[index_v] < EPS_DOUBLE)
+      floc += OPTIONS->Penalty;
+    else if (xloc[index_v] - parameter_lower_bound[index_v] < EPS_DOUBLE)
+      floc += OPTIONS->Penalty;
+  }
+
+  return (floc);
+}
+
+#if HAVE_ANSI
+double
+fitloc (double (*user_cost_function)
+
+         
+        (double *, double *, double *, double *, double *, ALLOC_INT *, int *,
+         int *, int *, USER_DEFINES *), double *xloc,
+        double *parameter_lower_bound, double *parameter_upper_bound,
+        double *cost_tangents, double *cost_curvature,
+        ALLOC_INT * parameter_dimension, int *parameter_int_real,
+        int *cost_flag, int *exit_code, USER_DEFINES * OPTIONS,
+        FILE * ptr_out)
+#else
+double
+fitloc (user_cost_function,
+        xloc,
+        parameter_lower_bound,
+        parameter_upper_bound,
+        cost_tangents,
+        cost_curvature,
+        parameter_dimension,
+        parameter_int_real, cost_flag, exit_code, OPTIONS, ptr_out)
+     double (*user_cost_function) ();
+     double *xloc;
+     double *parameter_lower_bound;
+     double *parameter_upper_bound;
+     double *cost_tangents;
+     double *cost_curvature;
+     ALLOC_INT *parameter_dimension;
+     int *parameter_int_real;
+     int *cost_flag;
+     int *exit_code;
+     USER_DEFINES *OPTIONS;
+     FILE *ptr_out;
+#endif
+{
+  double x;
+  ALLOC_INT index_v;
+#if FITLOC_ROUND
+  double min_parameter_v, max_parameter_v, parameter_range_v;
+#endif
+  double *xsave;
+  double tol1, tol2, alpha, beta1, beta2, gamma, delta, floc, fsave, ffinal;
+  int no_progress, tot_iters, locflg, bndflg;
+#if ASA_RESOLUTION
+  double xres, xint, xminus, xplus, dx, dxminus, dxplus;
+#endif
+
+#if FITLOC_PRINT
+  if (OPTIONS->Fit_Local >= 1) {
+    fprintf (ptr_out, "\n\nSTART LOCAL FIT\n");
+  } else {
+    fprintf (ptr_out, "\n\nSTART LOCAL FIT Independent of ASA\n");
+  }
+  fflush (ptr_out);
+#endif /* FITLOC_PRINT */
+
+  xsave = (double *) calloc (*parameter_dimension, sizeof (double));
+  bndflg = 0;
+
+  /* The following simplex parameters may need adjustments for your system. */
+  tol1 = EPS_DOUBLE;
+  tol2 = EPS_DOUBLE * 100.;
+  no_progress = 4;
+  alpha = 1.0;
+  beta1 = 0.75;
+  beta2 = 0.75;
+  gamma = 1.25;
+  delta = 2.50;
+
+  for (index_v = 0; index_v < *parameter_dimension; ++index_v) {
+    xsave[index_v] = xloc[index_v];
+  }
+
+  fsave = user_cost_function (xloc,
+                              parameter_lower_bound,
+                              parameter_upper_bound,
+                              cost_tangents,
+                              cost_curvature,
+                              parameter_dimension,
+                              parameter_int_real,
+                              cost_flag, exit_code, OPTIONS);
+
+  tot_iters = simplex (user_cost_function,
+                       xloc,
+                       parameter_lower_bound,
+                       parameter_upper_bound,
+                       cost_tangents,
+                       cost_curvature,
+                       parameter_dimension,
+                       parameter_int_real,
+                       cost_flag,
+                       exit_code,
+                       OPTIONS,
+                       ptr_out,
+                       tol1,
+                       tol2, no_progress, alpha, beta1, beta2, gamma, delta);
+  fflush (ptr_out);
+
+  for (index_v = 0; index_v < *parameter_dimension; ++index_v) {
+    x = xloc[index_v];
+    if ((x < parameter_lower_bound[index_v])
+        || (x > parameter_upper_bound[index_v])) {
+      bndflg = 1;
+    }
+  }
+
+  /* The following section for adjustments of parameters is taken from
+     generate_new_state() in asa.c */
+#if FITLOC_ROUND
+  for (index_v = 0; index_v < *parameter_dimension; ++index_v) {
+    if (fabs
+        (parameter_lower_bound[index_v] - parameter_upper_bound[index_v]) <
+        EPS_DOUBLE)
+      continue;
+
+    x = xloc[index_v];
+
+    min_parameter_v = parameter_lower_bound[index_v];
+    max_parameter_v = parameter_upper_bound[index_v];
+    parameter_range_v = max_parameter_v - min_parameter_v;
+
+    /* Handle discrete parameters. */
+#if ASA_RESOLUTION
+    xres = OPTIONS->Coarse_Resolution[index_v];
+    if (xres > EPS_DOUBLE) {
+      min_parameter_v -= (xres / 2.0);
+      max_parameter_v += (xres / 2.0);
+      parameter_range_v = max_parameter_v - min_parameter_v;
+    }
+#endif /* ASA_RESOLUTION */
+    if (parameter_int_real[index_v] > 0) {
+#if ASA_RESOLUTION
+      if (xres > EPS_DOUBLE) {
+        ;
+      } else {
+#endif /* ASA_RESOLUTION */
+        min_parameter_v -= 0.5;
+        max_parameter_v += 0.5;
+        parameter_range_v = max_parameter_v - min_parameter_v;
+      }
+#if ASA_RESOLUTION
+    }
+#endif
+#if ASA_RESOLUTION
+    if (xres > EPS_DOUBLE) {
+      xint = xres * (double) ((LONG_INT) (x / xres));
+      xplus = xint + xres;
+      xminus = xint - xres;
+      dx = fabs (xint - x);
+      dxminus = fabs (xminus - x);
+      dxplus = fabs (xplus - x);
+
+      if (dx < dxminus && dx < dxplus)
+        x = xint;
+      else if (dxminus < dxplus)
+        x = xminus;
+      else
+        x = xplus;
+    }
+#endif /* ASA_RESOLUTION */
+
+    /* Handle discrete parameters.
+       You might have to check rounding on your machine. */
+    if (parameter_int_real[index_v] > 0) {
+#if ASA_RESOLUTION
+      if (xres > EPS_DOUBLE) {
+        ;
+      } else {
+#endif /* ASA_RESOLUTION */
+        if (x < min_parameter_v + 0.5)
+          x = min_parameter_v + 0.5 + (double) EPS_DOUBLE;
+        if (x > max_parameter_v - 0.5)
+          x = max_parameter_v - 0.5 + (double) EPS_DOUBLE;
+
+        if (x + 0.5 > 0.0) {
+          x = (double) ((LONG_INT) (x + 0.5));
+        } else {
+          x = (double) ((LONG_INT) (x - 0.5));
+        }
+        if (x > parameter_upper_bound[index_v])
+          x = parameter_upper_bound[index_v];
+        if (x < parameter_lower_bound[index_v])
+          x = parameter_lower_bound[index_v];
+      }
+#if ASA_RESOLUTION
+    }
+    if (xres > EPS_DOUBLE) {
+      if (x < min_parameter_v + xres / 2.0)
+        x = min_parameter_v + xres / 2.0 + (double) EPS_DOUBLE;
+      if (x > max_parameter_v - xres / 2.0)
+        x = max_parameter_v - xres / 2.0 + (double) EPS_DOUBLE;
+
+      if (x > parameter_upper_bound[index_v])
+        x = parameter_upper_bound[index_v];
+      if (x < parameter_lower_bound[index_v])
+        x = parameter_lower_bound[index_v];
+    }
+#endif /* ASA_RESOLUTION */
+    if ((x < parameter_lower_bound[index_v])
+        || (x > parameter_upper_bound[index_v])) {
+      bndflg = 1;
+#if FITLOC_PRINT
+      if (OPTIONS->Fit_Local == 2)
+        fprintf (ptr_out, "IGNORE FITLOC: OUT OF BOUNDS xloc[%ld] = %g\n",
+                 index_v, xloc[index_v]);
+      else
+        fprintf (ptr_out, "OUT OF BOUNDS xloc[%ld] = %g\n",
+                 index_v, xloc[index_v]);
+#else
+      ;
+#endif /* FITLOC_PRINT */
+    } else {
+      xloc[index_v] = x;
+    }
+  }
+#endif /* FITLOC_ROUND */
+
+  floc = user_cost_function (xloc,
+                             parameter_lower_bound,
+                             parameter_upper_bound,
+                             cost_tangents,
+                             cost_curvature,
+                             parameter_dimension,
+                             parameter_int_real,
+                             cost_flag, exit_code, OPTIONS);
+
+  if (fabs (floc - fsave) < (double) EPS_DOUBLE) {
+    locflg = 1;
+    ffinal = fsave;
+#if FITLOC_PRINT
+    fprintf (ptr_out, "\nsame global cost = %g\tlocal cost = %g\n\n",
+             fsave, floc);
+#endif /* FITLOC_PRINT */
+  } else {
+    if (floc < fsave) {
+      if (OPTIONS->Fit_Local == 2 && bndflg == 1) {
+        locflg = 1;
+        ffinal = fsave;
+      } else {
+        locflg = 0;
+        ffinal = floc;
+      }
+    } else {
+      locflg = 1;
+      ffinal = fsave;
+    }
+#if FITLOC_PRINT
+    fprintf (ptr_out, "\nDIFF global cost = %g\tlocal cost = %g\n\n",
+             fsave, floc);
+#endif /* FITLOC_PRINT */
+  }
+
+  for (index_v = 0; index_v < *parameter_dimension; ++index_v) {
+    if (fabs (xloc[index_v] - xsave[index_v]) < (double) EPS_DOUBLE) {
+#if FITLOC_PRINT
+      fprintf (ptr_out, "same global param[%ld] = %g\tlocal param = %g\n",
+               index_v, xsave[index_v], xloc[index_v]);
+#else
+      ;
+#endif /* FITLOC_PRINT */
+    } else {
+#if FITLOC_PRINT
+      fprintf (ptr_out, "DIFF global param[%ld] = %g\tlocal param = %g\n",
+               index_v, xsave[index_v], xloc[index_v]);
+#else
+      ;
+#endif /* FITLOC_PRINT */
+      if (locflg == 1) {
+        xloc[index_v] = xsave[index_v];
+      }
+    }
+  }
+
+#if FITLOC_PRINT
+  fprintf (ptr_out, "\n");
+  fflush (ptr_out);
+#endif /* FITLOC_PRINT */
+
+  free (xsave);
+
+  return (ffinal);
+}
+
+/*
+   Written by Mark Johnson <mjohnson@netcom.com>, based on 
+
+   %A J.A. Nelder
+   %A R. Mead
+   %T A simplex method for function minimization
+   %J Computer J. (UK)
+   %V 7
+   %D 1964
+   %P 308-313
+
+   with improvements from
+
+   %A G.P. Barabino
+   %A G.S. Barabino
+   %A B. Bianco
+   %A M. Marchesi
+   %T A study on the performances of simplex methods for function minimization
+   %B Proc. IEEE Int. Conf. Circuits and Computers
+   %D 1980
+   %P 1150-1153
+
+   adapted for use in ASA by Lester Ingber <ingber@ingber.com>
+ */
+
+#if HAVE_ANSI
+int
+simplex (double (*user_cost_function)
+
+          
+         (double *, double *, double *, double *, double *, ALLOC_INT *,
+          int *, int *, int *, USER_DEFINES *), double *x,
+         double *parameter_lower_bound, double *parameter_upper_bound,
+         double *cost_tangents, double *cost_curvature,
+         ALLOC_INT * parameter_dimension, int *parameter_int_real,
+         int *cost_flag, int *exit_code, USER_DEFINES * OPTIONS,
+         FILE * ptr_out, double tol1, double tol2, int no_progress,
+         double alpha, double beta1, double beta2, double gamma, double delta)
+#else
+int
+simplex (user_cost_function,
+         x,
+         parameter_lower_bound,
+         parameter_upper_bound,
+         cost_tangents,
+         cost_curvature,
+         parameter_dimension,
+         parameter_int_real,
+         cost_flag,
+         exit_code,
+         OPTIONS,
+         ptr_out, tol1, tol2, no_progress, alpha, beta1, beta2, gamma, delta)
+     double (*user_cost_function) ();
+     double *x;
+     double *parameter_lower_bound;
+     double *parameter_upper_bound;
+     double *cost_tangents;
+     double *cost_curvature;
+     ALLOC_INT *parameter_dimension;
+     int *parameter_int_real;
+     int *cost_flag;
+     int *exit_code;
+     USER_DEFINES *OPTIONS;
+     FILE *ptr_out;
+     double tol1;
+     double tol2;
+     int no_progress;
+     double alpha;
+     double beta1;
+     double beta2;
+     double gamma;
+     double delta;
+#endif
+{
+  double fs, fl, fh, fr, fe, fc1, fc2, ftmp, flast;
+  double err1;
+  double *fvals;
+  double **splx;                /* the simplex of points */
+  double *x0;                   /* centroid of simplex */
+  double *xr;                   /* point for a reflection */
+  double *xe;                   /* point for an expansion */
+  double *xc1;                  /* point for a minor contraction */
+  double *xc2;                  /* point for a major contraction */
+  int s, l, h;
+  int i, j, iters, futility;
+  int lastprint;
+
+  fvals = (double *) calloc (*parameter_dimension + 1, sizeof (double));
+  splx = (double **) calloc (*parameter_dimension + 1, sizeof (double *));
+  for (i = 0; i <= *parameter_dimension; i++)
+    splx[i] = (double *) calloc (*parameter_dimension, sizeof (double));
+  x0 = (double *) calloc (*parameter_dimension, sizeof (double));
+  xr = (double *) calloc (*parameter_dimension, sizeof (double));
+  xe = (double *) calloc (*parameter_dimension, sizeof (double));
+  xc1 = (double *) calloc (*parameter_dimension, sizeof (double));
+  xc2 = (double *) calloc (*parameter_dimension, sizeof (double));
+
+  /* build the initial simplex */
+  for (i = 0; i < *parameter_dimension; i++) {
+    splx[0][i] = x[i];
+  }
+  for (i = 1; i <= *parameter_dimension; i++) {
+    for (j = 0; j < *parameter_dimension; j++) {
+      if ((j + 1) == i)
+        splx[i][j] = (x[j] * 2.25) + tol2;
+      else
+        splx[i][j] = x[j];
+      xr[j] = splx[i][j];
+    }
+    fvals[i] = calcf (user_cost_function,
+                      xr,
+                      parameter_lower_bound,
+                      parameter_upper_bound,
+                      cost_tangents,
+                      cost_curvature,
+                      parameter_dimension,
+                      parameter_int_real,
+                      cost_flag, exit_code, OPTIONS, ptr_out);
+  }
+
+  /* and of course compute function at starting point */
+  fvals[0] = calcf (user_cost_function,
+                    x,
+                    parameter_lower_bound,
+                    parameter_upper_bound,
+                    cost_tangents,
+                    cost_curvature,
+                    parameter_dimension,
+                    parameter_int_real,
+                    cost_flag, exit_code, OPTIONS, ptr_out);
+
+  /* now find the largest, 2nd largest, smallest f values */
+  if (fvals[0] > fvals[1]) {
+    h = 0;
+    s = 1;
+    l = 1;
+  } else {
+    h = 1;
+    s = 0;
+    l = 0;
+  }
+  fh = fvals[h];
+  fs = fvals[s];
+  fl = fvals[l];
+  for (i = 2; i <= *parameter_dimension; i++) {
+    if (fvals[i] <= fvals[l]) {
+      l = i;
+      fl = fvals[i];
+    } else {
+      if (fvals[i] >= fvals[h]) {
+        s = h;
+        fs = fh;
+        h = i;
+        fh = fvals[i];
+      } else if (fvals[i] >= fvals[s]) {
+        s = i;
+        fs = fvals[i];
+      }
+    }
+  }
+#if FITLOC_PRINT
+  if ((s == h) || (s == l) || (h == l))
+    fprintf (ptr_out, "\nPANIC: s,l,h not unique %d %d %d\n", s, h, l);
+
+  fprintf (ptr_out, "INITIAL SIMPLEX:\n");
+  for (i = 0; i <= *parameter_dimension; i++) {
+    for (j = 0; j < *parameter_dimension; j++) {
+      fprintf (ptr_out, "   %11.4g", splx[i][j]);
+    }
+    fprintf (ptr_out, "      f = %12.5g", fvals[i]);
+    if (i == h)
+      fprintf (ptr_out, "  HIGHEST");
+    if (i == s)
+      fprintf (ptr_out, "  SECOND HIGHEST");
+    if (i == l)
+      fprintf (ptr_out, "  LOWEST");
+    fprintf (ptr_out, "\n");
+  }
+#endif /* FITLOC_PRINT */
+
+/* MAJOR LOOP */
+
+  flast = fl;
+  futility = 0;
+  lastprint = 0;
+  iters = 0;
+  err1 = 1.1 + (1.1 * tol1);
+  while ((err1 > tol1) && (iters < OPTIONS->Iter_Max) &&
+         (futility < (*parameter_dimension * no_progress))) {
+    iters++;
+
+    /* now find the largest, 2nd largest, smallest f values */
+    if (fvals[0] > fvals[1]) {
+      h = 0;
+      s = 1;
+      l = 1;
+    } else {
+      h = 1;
+      s = 0;
+      l = 0;
+    }
+    fh = fvals[h];
+    fs = fvals[s];
+    fl = fvals[l];
+    for (i = 2; i <= *parameter_dimension; i++) {
+      if (fvals[i] <= fvals[l]) {
+        l = i;
+        fl = fvals[i];
+      } else {
+        if (fvals[i] >= fvals[h]) {
+          s = h;
+          fs = fh;
+          h = i;
+          fh = fvals[i];
+        } else if (fvals[i] >= fvals[s]) {
+          s = i;
+          fs = fvals[i];
+        }
+      }
+    }
+#if FITLOC_PRINT
+    if ((s == h) || (s == l) || (h == l))
+      fprintf (ptr_out, "\nPANIC: s,l,h not unique %d %d %d\n", s, h, l);
+#endif
+
+    /* compute the centroid */
+    for (j = 0; j < *parameter_dimension; j++) {
+      x0[j] = 0.0;
+      for (i = 0; i <= *parameter_dimension; i++) {
+        if (i != h)
+          x0[j] += splx[i][j];
+      }
+      x0[j] /= ((double) *parameter_dimension);
+    }
+
+    if (fl < flast) {
+      flast = fl;
+      futility = 0;
+    } else
+      futility += 1;
+
+#if FITLOC_PRINT
+    fprintf (ptr_out, "Iteration %3d f(best) = %12.6g halt? = %11.5g\n",
+             iters, fl, err1);
+    if ((iters - lastprint) >= 100) {
+      fprintf (ptr_out, "\n     Best point seen so far:\n");
+      for (i = 0; i < *parameter_dimension; i++) {
+        fprintf (ptr_out, "     x[%3d] = %15.7g\n", i, splx[l][i]);
+      }
+      lastprint = iters;
+      fprintf (ptr_out, "\n");
+    }
+    fflush (ptr_out);
+#endif /* FITLOC_PRINT */
+
+    /* STEP 1: compute a reflected point xr */
+    for (i = 0; i < *parameter_dimension; i++) {
+      xr[i] = ((1.0 + alpha) * x0[i]) - (alpha * splx[h][i]);
+    }
+    fr = calcf (user_cost_function,
+                xr,
+                parameter_lower_bound,
+                parameter_upper_bound,
+                cost_tangents,
+                cost_curvature,
+                parameter_dimension,
+                parameter_int_real, cost_flag, exit_code, OPTIONS, ptr_out);
+
+    /* typical outcome: <2nd-biggest , >lowest .  Go again */
+    if ((fr < fs) && (fr > fl)) {
+      for (i = 0; i < *parameter_dimension; i++) {
+        splx[h][i] = xr[i];
+      }
+      fvals[h] = fr;
+      goto more_iterations;
+    }
+
+    /* STEP 2: if reflected point is favorable, expand the simplex */
+    if (fr < fl) {
+      for (i = 0; i < *parameter_dimension; i++) {
+        xe[i] = (gamma * xr[i]) + ((1.0 - gamma) * x0[i]);
+      }
+      fe = calcf (user_cost_function,
+                  xe,
+                  parameter_lower_bound,
+                  parameter_upper_bound,
+                  cost_tangents,
+                  cost_curvature,
+                  parameter_dimension,
+                  parameter_int_real, cost_flag, exit_code, OPTIONS, ptr_out);
+      if (fe < fr) {            /* win big; expansion point tiny */
+        for (i = 0; i < *parameter_dimension; i++) {
+          splx[h][i] = xe[i];
+        }
+        fvals[h] = fh = fe;
+      } else
+        /* still ok; reflection point a winner */
+      {
+        for (i = 0; i < *parameter_dimension; i++) {
+          splx[h][i] = xr[i];
+        }
+        fvals[h] = fh = fr;
+      }
+      goto more_iterations;
+    }
+
+    /* STEP 3: if reflected point is unfavorable, contract simplex */
+    if (fr > fs) {
+      if (fr < fh) {            /* may as well replace highest pt */
+        for (i = 0; i < *parameter_dimension; i++) {
+          splx[h][i] = xr[i];
+        }
+        fvals[h] = fh = fr;
+      }
+      for (i = 0; i < *parameter_dimension; i++) {
+        xc1[i] = (beta1 * xr[i]) + ((1.0 - beta1) * x0[i]);
+      }
+      fc1 = calcf (user_cost_function,
+                   xc1,
+                   parameter_lower_bound,
+                   parameter_upper_bound,
+                   cost_tangents,
+                   cost_curvature,
+                   parameter_dimension,
+                   parameter_int_real,
+                   cost_flag, exit_code, OPTIONS, ptr_out);
+      if (fc1 < fh) {           /* slight contraction worked */
+        for (i = 0; i < *parameter_dimension; i++) {
+          splx[h][i] = xc1[i];
+        }
+        fvals[h] = fh = fc1;
+        goto more_iterations;
+      }
+      /* now have to try strong contraction */
+      for (i = 0; i < *parameter_dimension; i++) {
+        xc2[i] = (beta2 * splx[h][i]) + ((1.0 - beta2) * x0[i]);
+      }
+      fc2 = calcf (user_cost_function,
+                   xc2,
+                   parameter_lower_bound,
+                   parameter_upper_bound,
+                   cost_tangents,
+                   cost_curvature,
+                   parameter_dimension,
+                   parameter_int_real,
+                   cost_flag, exit_code, OPTIONS, ptr_out);
+      if (fc2 < fh) {           /* strong contraction worked */
+        for (i = 0; i < *parameter_dimension; i++) {
+          splx[h][i] = xc2[i];
+        }
+        fvals[h] = fh = fc2;
+        goto more_iterations;
+      }
+    }
+
+    /* STEP 4: nothing worked.  collapse the simplex around xl */
+    for (i = 0; i <= *parameter_dimension; i++) {
+      if (i != l) {
+        for (j = 0; j < *parameter_dimension; j++) {
+          splx[i][j] = (splx[i][j] + splx[l][j]) / delta;
+          xr[j] = splx[i][j];
+        }
+        fvals[i] = calcf (user_cost_function,
+                          xr,
+                          parameter_lower_bound,
+                          parameter_upper_bound,
+                          cost_tangents,
+                          cost_curvature,
+                          parameter_dimension,
+                          parameter_int_real,
+                          cost_flag, exit_code, OPTIONS, ptr_out);
+      }
+    }
+
+  more_iterations:
+
+    ftmp = 0.00;
+    for (i = 0; i <= *parameter_dimension; i++) {
+      ftmp += fvals[i];
+    }
+    ftmp /= ((double) (*parameter_dimension + 1));
+
+    err1 = 0.00;
+    for (i = 0; i <= *parameter_dimension; i++) {
+      err1 += ((fvals[i] - ftmp) * (fvals[i] - ftmp));
+    }
+    err1 /= ((double) (*parameter_dimension + 1));
+    err1 = sqrt (err1);
+  }                             /* end of major while loop */
+
+  /* find the smallest f value */
+  l = 0;
+  fl = fvals[0];
+  for (i = 1; i <= *parameter_dimension; i++) {
+    if (fvals[i] < fvals[l])
+      l = i;
+  }
+
+  /* give it back to the user */
+  for (i = 0; i < *parameter_dimension; i++) {
+    x[i] = splx[l][i];
+  }
+
+  free (fvals);
+  for (i = 0; i <= *parameter_dimension; i++)
+    free (splx[i]);
+  free (splx);
+  free (x0);
+  free (xr);
+  free (xe);
+  free (xc1);
+  free (xc2);
+
+  return (iters);
+}
+#else
+#endif /* FITLOC */
+
+#if ASA_TEMPLATE_SAMPLE
+
+#if HAVE_ANSI
+void
+sample (FILE * ptr_out, FILE * ptr_asa)
+#else
+void
+sample (ptr_out, ptr_asa)
+     FILE *ptr_out;
+     FILE *ptr_asa;
+#endif
+{
+  int ind, n_samples, n_accept, index, dim;
+  double cost, cost_temp, bias_accept;
+  double param, temp, bias_gener, aver_weight, range;
+  double sum, norm, answer, prod, binsize;
+  char ch[80], sample[8];
+
+  /*
+     This is a demonstration of using ASA_SAMPLE to perform the double integral
+     of exp(-x^2 - y^2) for x and y between 0 and 2.  The mesh is quite crude.
+
+     The temperature-dependent acceptance and generated biases factor are
+     divided out, and the actual cost function weights each point.
+   */
+
+  dim = 2;
+  norm = sum = 0.;
+  n_samples = 0;
+
+  fprintf (ptr_out,
+           ":SAMPLE:   n_accept   cost        cost_temp    bias_accept    \
+ aver_weight\n");
+  fprintf (ptr_out,
+           ":SAMPLE:   index      param[]     temp[]       bias_gener[]   \
+ range[]\n");
+  for (;;) {
+    fscanf (ptr_asa, "%s", ch);
+    if (!strcmp (ch, "exit_status")) {
+      break;
+    }
+    if (strcmp (ch, ":SAMPLE#")) {
+      continue;
+    }
+    ++n_samples;
+    fprintf (ptr_out, "%s\n", ch);
+    fflush (ptr_out);
+    fscanf (ptr_asa, "%s%d%lf%lf%lf%lf",
+            sample, &n_accept, &cost, &cost_temp, &bias_accept, &aver_weight);
+    if (strcmp (sample, ":SAMPLE+")) {
+      fprintf (ptr_out, "%s %11d %12.7g %12.7g %12.7g %12.7g\n",
+               sample, n_accept, cost, cost_temp, bias_accept, aver_weight);
+    } else {
+      fprintf (ptr_out, "%s %10d %12.7g %12.7g %12.7g %12.7g\n",
+               sample, n_accept, cost, cost_temp, bias_accept, aver_weight);
+    }
+    prod = bias_accept;
+    binsize = 1.0;
+    for (ind = 0; ind < dim; ++ind) {
+      fscanf (ptr_asa, "%s%d%lf%lf%lf%lf",
+              sample, &index, &param, &temp, &bias_gener, &range);
+      fprintf (ptr_out, "%s %11d %12.7g %12.7g %12.7g %12.7g\n",
+               sample, index, param, temp, bias_gener, range);
+      prod *= bias_gener;
+      binsize *= range;
+    }
+    /* In this example, retrieve integrand from sampling function */
+    sum += ((F_EXP (-cost) * binsize) / prod);
+    norm += (binsize / prod);
+  }
+  sum /= norm;
+
+  answer = 1.0;
+  for (ind = 0; ind < dim; ++ind) {
+    answer *= (0.5 * sqrt (3.14159265) * erf (2.0));
+  }
+
+  fprintf (ptr_out, "\n");
+  fprintf (ptr_out, "sum = %12.7g, answer = %12.7g\n", sum, answer);
+  fprintf (ptr_out, "n_samples = %d, norm = %12.7g\n", n_samples, norm);
+  fflush (ptr_out);
+
+}
+#endif /* ASA_TEMPLATE_SAMPLE */
+#if ASA_TEMPLATE_LIB
+int
+main ()
+{
+  double main_cost_value;
+  double *main_cost_parameters;
+  int main_exit_code;
+  LONG_INT number_params;
+  ALLOC_INT n_param;
+  FILE *ptr_main;
+
+#if INCL_STDOUT
+  ptr_main = stdout;
+#endif /* INCL_STDOUT */
+
+  /* Note this assumes the *parameter_dimension = 4 */
+  number_params = 4;
+
+  if ((main_cost_parameters =
+       (double *) calloc (number_params, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg, "ASA_TEMPLATE_LIB main(): main_cost_parameters");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+
+  asa_seed (696969);            /* This is the default random seed. */
+  asa_main (&main_cost_value, main_cost_parameters, &main_exit_code);
+
+  fprintf (ptr_main, "main_exit_code = %d\n", main_exit_code);
+  fprintf (ptr_main, "main_cost_value = %12.7g\n", main_cost_value);
+  fprintf (ptr_main, "parameter\tvalue\n");
+  for (n_param = 0; n_param < number_params; ++n_param) {
+    fprintf (ptr_main,
+#if INT_ALLOC
+             "%d\t\t%12.7g\n",
+#else
+#if INT_LONG
+             "%ld\t\t%12.7g\n",
+#else
+             "%d\t\t%12.7g\n",
+#endif
+#endif
+             n_param, main_cost_parameters[n_param]);
+  }
+
+  free (main_cost_parameters);
+
+  return (0);
+/* NOTREACHED */
+}
+#endif /* ASA_TEMPLATE_LIB */
+
+void
+Exit_USER (char *statement)
+{
+#if INCL_STDOUT
+  printf ("\n\n*** EXIT calloc failed *** %s\n\n", statement);
+#else
+  ;
+#endif /* INCL_STDOUT */
+}
diff --git a/cbits/asa.c b/cbits/asa.c
new file mode 100644
--- /dev/null
+++ b/cbits/asa.c
@@ -0,0 +1,6387 @@
+/***********************************************************************
+* Adaptive Simulated Annealing (ASA)
+* Lester Ingber <ingber@ingber.com>
+* Copyright (c) 1993-2004 Lester Ingber.  All Rights Reserved.
+* The LICENSE file must be included with ASA code.
+***********************************************************************/
+
+#define ASA_ID \
+"/* $Id: asa.c,v 25.15 2004/09/23 18:10:46 ingber Exp ingber $ */"
+
+#include "asa.h"
+static int asa_recursive_max = 0;       /* record of max recursions */
+
+/***********************************************************************
+* asa
+*       This procedure implements the full ASA function optimization.
+***********************************************************************/
+#if HAVE_ANSI
+double
+asa (double (*user_cost_function)
+
+      
+     (double *, double *, double *, double *, double *, ALLOC_INT *, int *,
+      int *, int *, USER_DEFINES *),
+     double (*user_random_generator) (LONG_INT *), LONG_INT * seed,
+     double *parameter_initial_final, double *parameter_minimum,
+     double *parameter_maximum, double *tangents, double *curvature,
+     ALLOC_INT * number_parameters, int *parameter_type,
+     int *valid_state_generated_flag, int *exit_status,
+     USER_DEFINES * OPTIONS)
+#else
+double
+asa (user_cost_function,
+     user_random_generator,
+     seed,
+     parameter_initial_final,
+     parameter_minimum,
+     parameter_maximum,
+     tangents,
+     curvature,
+     number_parameters,
+     parameter_type, valid_state_generated_flag, exit_status, OPTIONS)
+     double (*user_cost_function) ();
+     double (*user_random_generator) ();
+     LONG_INT *seed;
+     double *parameter_initial_final;
+     double *parameter_minimum;
+     double *parameter_maximum;
+     double *tangents;
+     double *curvature;
+     ALLOC_INT *number_parameters;
+     int *parameter_type;
+     int *valid_state_generated_flag;
+     int *exit_status;
+     USER_DEFINES *OPTIONS;
+#endif /* HAVE_ANSI */
+{
+#if USER_INITIAL_COST_TEMP
+#if USER_REANNEAL_COST
+#else
+  int index_cost_constraint;    /* index cost functions averaged */
+#endif /* USER_REANNEAL_COST */
+#else /* USER_INITIAL_COST_TEMP */
+  int index_cost_constraint;    /* index cost functions averaged */
+#endif /* USER_INITIAL_COST_TEMP */
+
+  int index_cost_repeat,        /* test OPTIONS->Cost_Precision when =
+                                   OPTIONS->Maximum_Cost_Repeat */
+    tmp_var_int, tmp_var_int1, tmp_var_int2;    /* temporary integers */
+
+  ALLOC_INT index_v,            /* iteration index */
+   *start_sequence;             /* initial OPTIONS->Sequential_Parameters
+                                   used if >= 0 */
+  double final_cost,            /* best cost to return to user */
+    tmp_var_db, tmp_var_db1, tmp_var_db2;       /* temporary doubles */
+  int *curvature_flag;
+  FILE *ptr_asa_out;            /* file ptr to output file */
+
+  /* The 3 states that are kept track of during the annealing process */
+  STATE *current_generated_state, *last_saved_state, *best_generated_state;
+
+#if ASA_SAVE
+  FILE *ptr_save, *ptr_comm;
+  int asa_read;
+  char asa_save_comm[100];
+#if ASA_SAVE_OPT
+  char read_option[80];
+  char read_if[4], read_FALSE[6], read_comm1[3], read_ASA_SAVE[9],
+    read_comm2[3];
+  int read_int;
+#if INT_LONG
+  LONG_INT read_long;
+#endif
+  double read_double;
+  FILE *ptr_save_opt;
+#endif
+#endif /* ASA_SAVE */
+
+#if ASA_PIPE_FILE
+  FILE *ptr_asa_pipe;
+#endif
+
+  int immediate_flag;           /* save Immediate_Exit */
+  int asa_exit_value;
+
+  double xnumber_parameters[1];
+
+  /* The array of tangents (absolute value of the numerical derivatives),
+     and the maximum |tangent| of the array */
+  double *maximum_tangent;
+
+  /* ratio of acceptances to generated points - determines when to
+     test/reanneal */
+  double *accepted_to_generated_ratio;
+
+  /* temperature parameters */
+  double temperature_scale, *temperature_scale_parameters;
+  /* relative scalings of cost and parameters to temperature_scale */
+  double *temperature_scale_cost;
+  double *current_user_parameter_temp;
+  double *initial_user_parameter_temp;
+  double *current_cost_temperature;
+  double *initial_cost_temperature;
+  double log_new_temperature_ratio;     /* current *temp = initial *temp *
+                                           exp(log_new_temperature_ratio) */
+  ALLOC_INT *index_exit_v;      /* information for asa_exit */
+
+  /* counts of generated states and acceptances */
+  LONG_INT *index_parameter_generations;
+  LONG_INT *number_generated, *best_number_generated_saved;
+  LONG_INT *recent_number_generated, *number_accepted;
+  LONG_INT *recent_number_acceptances, *index_cost_acceptances;
+  LONG_INT *number_acceptances_saved, *best_number_accepted_saved;
+
+  /* Flag indicates that the parameters generated were
+     invalid according to the cost function validity criteria. */
+  LONG_INT *number_invalid_generated_states;
+  LONG_INT repeated_invalid_states;
+
+#if ASA_QUEUE
+  int queue_new;                /* flag to add new entry */
+  int *save_queue_flag;         /* save valid_state_generated_flag */
+  LONG_INT queue;               /* index of queue */
+  LONG_INT queue_v;             /* index of parameters in queue */
+  LONG_INT save_queue_test;     /* test if all parameters are present */
+  LONG_INT save_queue;          /* last filled position in queue */
+  LONG_INT save_queue_indx;     /* current position in queue */
+  double *save_queue_cost, *save_queue_param;   /* saved states */
+  ALLOC_INT queue_size_tmp;
+#endif
+
+#if MULTI_MIN
+  int multi_index;
+  int multi_test, multi_test_cmp, multi_test_dim;
+  int *multi_sort;
+  double *multi_cost;
+  double **multi_params;
+#endif /* MULTI_MIN */
+
+#if ASA_PARALLEL
+  LONG_INT *parallel_sort;
+  LONG_INT index_parallel, sort_index;  /* count of parallel generated states */
+  LONG_INT parallel_generated;  /* saved *recent_number_generated */
+  LONG_INT parallel_block_max;  /* saved OPTIONS->Gener_Block_Max */
+  STATE *gener_block_state;
+#endif
+
+  /* used to index repeated and recursive calls to asa */
+  /* This assumes that multiple calls (>= 1) _or_ recursive
+     calls are being made to asa */
+  static int asa_open = FALSE;
+  static int number_asa_open = 0;
+  static int recursive_asa_open = 0;
+
+  /* initializations */
+
+  if ((curvature_flag = (int *) calloc (1, sizeof (int))) == NULL) {
+    strcpy (exit_msg, "asa(): curvature_flag");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((maximum_tangent = (double *) calloc (1, sizeof (double))) == NULL) {
+    strcpy (exit_msg, "asa(): maximum_tangent");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((accepted_to_generated_ratio =
+       (double *) calloc (1, sizeof (double))) == NULL) {
+    strcpy (exit_msg, "asa(): accepted_to_generated_ratio");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((temperature_scale_cost =
+       (double *) calloc (1, sizeof (double))) == NULL) {
+    strcpy (exit_msg, "asa(): temperature_scale_cost");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((current_cost_temperature =
+       (double *) calloc (1, sizeof (double))) == NULL) {
+    strcpy (exit_msg, "asa(): current_cost_temperature");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((initial_cost_temperature =
+       (double *) calloc (1, sizeof (double))) == NULL) {
+    strcpy (exit_msg, "asa(): initial_cost_temperature");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((index_exit_v = (ALLOC_INT *) calloc (1, sizeof (ALLOC_INT))) == NULL) {
+    strcpy (exit_msg, "asa(): index_exit_v");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((start_sequence = (ALLOC_INT *) calloc (1, sizeof (ALLOC_INT))) == NULL) {
+    strcpy (exit_msg, "asa(): start_sequence");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((number_generated =
+       (ALLOC_INT *) calloc (1, sizeof (ALLOC_INT))) == NULL) {
+    strcpy (exit_msg, "asa(): number_generated");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((best_number_generated_saved =
+       (ALLOC_INT *) calloc (1, sizeof (ALLOC_INT))) == NULL) {
+    strcpy (exit_msg, "asa(): best_number_generated_saved");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((recent_number_generated =
+       (ALLOC_INT *) calloc (1, sizeof (ALLOC_INT))) == NULL) {
+    strcpy (exit_msg, "asa(): recent_number_generated");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((number_accepted =
+       (ALLOC_INT *) calloc (1, sizeof (ALLOC_INT))) == NULL) {
+    strcpy (exit_msg, "asa(): number_accepted");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((recent_number_acceptances =
+       (ALLOC_INT *) calloc (1, sizeof (ALLOC_INT))) == NULL) {
+    strcpy (exit_msg, "asa(): recent_number_acceptances");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((index_cost_acceptances =
+       (ALLOC_INT *) calloc (1, sizeof (ALLOC_INT))) == NULL) {
+    strcpy (exit_msg, "asa(): index_cost_acceptances");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((number_acceptances_saved =
+       (ALLOC_INT *) calloc (1, sizeof (ALLOC_INT))) == NULL) {
+    strcpy (exit_msg, "asa(): number_acceptances_saved");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((best_number_accepted_saved =
+       (ALLOC_INT *) calloc (1, sizeof (ALLOC_INT))) == NULL) {
+    strcpy (exit_msg, "asa(): best_number_accepted_saved");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((number_invalid_generated_states =
+       (ALLOC_INT *) calloc (1, sizeof (ALLOC_INT))) == NULL) {
+    strcpy (exit_msg, "asa(): number_invalid_generated_states");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+
+  if ((current_generated_state =
+       (STATE *) calloc (1, sizeof (STATE))) == NULL) {
+    strcpy (exit_msg, "asa(): current_generated_state");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((last_saved_state = (STATE *) calloc (1, sizeof (STATE))) == NULL) {
+    strcpy (exit_msg, "asa(): last_saved_state");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((best_generated_state = (STATE *) calloc (1, sizeof (STATE))) == NULL) {
+    strcpy (exit_msg, "asa(): best_generated_state");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+#if ASA_PARALLEL
+  if ((gener_block_state =
+       (STATE *) calloc (OPTIONS->Gener_Block_Max, sizeof (STATE))) == NULL) {
+    strcpy (exit_msg, "asa(): gener_block_state");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  gener_block_state_qsort = gener_block_state;
+  if ((parallel_sort =
+       (LONG_INT *) calloc (OPTIONS->Gener_Block_Max,
+                            sizeof (LONG_INT))) == NULL) {
+    strcpy (exit_msg, "asa(): parallel_sort");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+#endif
+
+  /* set default */
+  ptr_asa_out = (FILE *) NULL;
+
+  OPTIONS->Immediate_Exit = FALSE;
+
+  if (asa_open == FALSE) {
+    asa_open = TRUE;
+    ++number_asa_open;
+#if ASA_PRINT
+    if (number_asa_open == 1) {
+      /* open the output file */
+#if USER_ASA_OUT
+      if (!strcmp (OPTIONS->Asa_Out_File, "STDOUT")) {
+#if INCL_STDOUT
+        ptr_asa_out = stdout;
+#endif /* INCL_STDOUT */
+      } else {
+#if ASA_SAVE
+        ptr_asa_out = fopen (OPTIONS->Asa_Out_File, "a");
+#else
+        ptr_asa_out = fopen (OPTIONS->Asa_Out_File, "w");
+#endif
+      }
+#else /* USER_ASA_OUT */
+      if (!strcmp (ASA_OUT, "STDOUT")) {
+#if INCL_STDOUT
+        ptr_asa_out = stdout;
+#endif /* INCL_STDOUT */
+      } else {
+#if ASA_SAVE
+        ptr_asa_out = fopen (ASA_OUT, "a");
+#else
+        ptr_asa_out = fopen (ASA_OUT, "w");
+#endif
+      }
+#endif /* USER_ASA_OUT */
+    } else {
+#if USER_ASA_OUT
+      if (!strcmp (OPTIONS->Asa_Out_File, "STDOUT")) {
+#if INCL_STDOUT
+        ptr_asa_out = stdout;
+#endif /* INCL_STDOUT */
+      } else {
+        ptr_asa_out = fopen (OPTIONS->Asa_Out_File, "a");
+      }
+#else
+      if (!strcmp (ASA_OUT, "STDOUT")) {
+#if INCL_STDOUT
+        ptr_asa_out = stdout;
+#endif /* INCL_STDOUT */
+      } else {
+        ptr_asa_out = fopen (ASA_OUT, "a");
+      }
+#endif
+      fprintf (ptr_asa_out, "\n\n\t\t number_asa_open = %d\n",
+               number_asa_open);
+    }
+#endif /* ASA_PRINT */
+  } else {
+    ++recursive_asa_open;
+#if ASA_PRINT
+    if (recursive_asa_open == 1) {
+      /* open the output file */
+#if ASA_SAVE
+#if USER_ASA_OUT
+      if (!strcmp (OPTIONS->Asa_Out_File, "STDOUT")) {
+#if INCL_STDOUT
+        ptr_asa_out = stdout;
+#endif /* INCL_STDOUT */
+      } else {
+        ptr_asa_out = fopen (OPTIONS->Asa_Out_File, "a");
+      }
+#else
+      if (!strcmp (ASA_OUT, "STDOUT")) {
+#if INCL_STDOUT
+        ptr_asa_out = stdout;
+#endif /* INCL_STDOUT */
+      } else {
+        ptr_asa_out = fopen (ASA_OUT, "a");
+      }
+#endif
+#else /* ASA_SAVE */
+#if USER_ASA_OUT
+      if (!strcmp (OPTIONS->Asa_Out_File, "STDOUT")) {
+#if INCL_STDOUT
+        ptr_asa_out = stdout;
+#endif /* INCL_STDOUT */
+      } else {
+        ptr_asa_out = fopen (OPTIONS->Asa_Out_File, "w");
+      }
+#else
+      if (!strcmp (ASA_OUT, "STDOUT")) {
+#if INCL_STDOUT
+        ptr_asa_out = stdout;
+#endif /* INCL_STDOUT */
+      } else {
+        ptr_asa_out = fopen (ASA_OUT, "w");
+      }
+#endif
+#endif /* ASA_SAVE */
+    } else {
+#if USER_ASA_OUT
+      if (!strcmp (OPTIONS->Asa_Out_File, "STDOUT")) {
+#if INCL_STDOUT
+        ptr_asa_out = stdout;
+#endif /* INCL_STDOUT */
+      } else {
+        ptr_asa_out = fopen (OPTIONS->Asa_Out_File, "a");
+      }
+#else
+      if (!strcmp (ASA_OUT, "STDOUT")) {
+#if INCL_STDOUT
+        ptr_asa_out = stdout;
+#endif /* INCL_STDOUT */
+      } else {
+        ptr_asa_out = fopen (ASA_OUT, "a");
+      }
+#endif
+      fprintf (ptr_asa_out, "\n\n\t\t recursive_asa_open = %d\n",
+               recursive_asa_open);
+    }
+#endif /* ASA_PRINT */
+  }
+
+#if ASA_PIPE_FILE
+  ptr_asa_pipe = fopen ("asa_pipe", "a");
+  fprintf (ptr_asa_pipe, "%s", "%generate");
+  fprintf (ptr_asa_pipe, "\t%s", "accept");
+  fprintf (ptr_asa_pipe, "\t%s", "best_cost");
+  VFOR (index_v)
+#if INT_ALLOC
+    fprintf (ptr_asa_pipe, "\t%s-%d", "param", index_v);
+#else
+#if INT_LONG
+    fprintf (ptr_asa_pipe, "\t%s-%ld", "param", index_v);
+#else
+    fprintf (ptr_asa_pipe, "\t%s-%d", "param", index_v);
+#endif
+#endif
+  fprintf (ptr_asa_pipe, "\t%s", "cost_temp");
+  VFOR (index_v)
+#if INT_ALLOC
+    fprintf (ptr_asa_pipe, "\t%s-%d", "param_temp", index_v);
+#else
+#if INT_LONG
+    fprintf (ptr_asa_pipe, "\t%s-%ld", "param_temp", index_v);
+#else
+    fprintf (ptr_asa_pipe, "\t%s-%d", "param_temp", index_v);
+#endif
+#endif
+  fprintf (ptr_asa_pipe, "\t%s", "last_cost");
+  fprintf (ptr_asa_pipe, "\n");
+  fflush (ptr_asa_pipe);
+#endif /* ASA_PIPE_FILE */
+
+#if ASA_PRINT
+  /* print header information as defined by user */
+  print_asa_options (ptr_asa_out, OPTIONS);
+
+  fflush (ptr_asa_out);
+#endif /* ASA_PRINT */
+
+  /* set indices and counts to 0 */
+  *best_number_generated_saved =
+    *number_generated =
+    *recent_number_generated = *recent_number_acceptances = 0;
+  *index_cost_acceptances =
+    *best_number_accepted_saved =
+    *number_accepted = *number_acceptances_saved = 0;
+  index_cost_repeat = 0;
+
+  OPTIONS->N_Accepted = *number_accepted;
+  OPTIONS->N_Generated = *number_generated;
+
+#if ASA_SAMPLE
+  OPTIONS->N_Generated = 0;
+  OPTIONS->Average_Weights = 1.0;
+#endif
+
+  /* do not calculate curvatures initially */
+  *curvature_flag = FALSE;
+
+  /* allocate storage for all parameters */
+  if ((current_generated_state->parameter =
+       (double *) calloc (*number_parameters, sizeof (double))) == NULL) {
+    strcpy (exit_msg, "asa(): current_generated_state->parameter");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((last_saved_state->parameter =
+       (double *) calloc (*number_parameters, sizeof (double))) == NULL) {
+    strcpy (exit_msg, "asa(): last_saved_state->parameter");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((best_generated_state->parameter =
+       (double *) calloc (*number_parameters, sizeof (double))) == NULL) {
+    strcpy (exit_msg, "asa(): best_generated_state->parameter");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+#if ASA_PARALLEL
+  parallel_block_max = OPTIONS->Gener_Block_Max;
+  parallel_generated = OPTIONS->Gener_Block;
+
+  for (index_parallel = 0; index_parallel < parallel_block_max;
+       ++index_parallel) {
+    if ((gener_block_state[index_parallel].parameter =
+         (double *) calloc (*number_parameters, sizeof (double))) == NULL) {
+      strcpy (exit_msg, "asa(): gener_block_state[index_parallel].parameter");
+      Exit_ASA (exit_msg);
+      *exit_status = CALLOC_FAILED;
+      return (-1);
+    }
+  }
+#endif
+
+  OPTIONS->Best_Cost = &(best_generated_state->cost);
+  OPTIONS->Best_Parameters = best_generated_state->parameter;
+  OPTIONS->Last_Cost = &(last_saved_state->cost);
+  OPTIONS->Last_Parameters = last_saved_state->parameter;
+
+  if ((initial_user_parameter_temp =
+       (double *) calloc (*number_parameters, sizeof (double))) == NULL) {
+    strcpy (exit_msg, "asa(): initial_user_parameter_temp");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((index_parameter_generations =
+       (ALLOC_INT *) calloc (*number_parameters,
+                             sizeof (ALLOC_INT))) == NULL) {
+    strcpy (exit_msg, "asa(): index_parameter_generations");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+
+  /* set all temperatures */
+  if ((current_user_parameter_temp =
+       (double *) calloc (*number_parameters, sizeof (double))) == NULL) {
+    strcpy (exit_msg, "asa(): current_user_parameter_temp");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+#if USER_INITIAL_PARAMETERS_TEMPS
+  VFOR (index_v)
+    current_user_parameter_temp[index_v] =
+    initial_user_parameter_temp[index_v] =
+    OPTIONS->User_Parameter_Temperature[index_v];
+#else
+  VFOR (index_v)
+    current_user_parameter_temp[index_v] =
+    initial_user_parameter_temp[index_v] =
+    OPTIONS->Initial_Parameter_Temperature;
+#endif
+
+  if ((temperature_scale_parameters =
+       (double *) calloc (*number_parameters, sizeof (double))) == NULL) {
+    strcpy (exit_msg, "asa(): temperature_scale_parameters");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+#if ASA_QUEUE
+  if (OPTIONS->Queue_Size > 0) {
+    queue_size_tmp = OPTIONS->Queue_Size;
+  } else {
+    queue_size_tmp = 1;
+  }
+  if ((save_queue_flag =
+       (int *) calloc (queue_size_tmp, sizeof (int))) == NULL) {
+    strcpy (exit_msg, "asa(): save_queue_flag");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((save_queue_cost =
+       (double *) calloc (queue_size_tmp, sizeof (double))) == NULL) {
+    strcpy (exit_msg, "asa(): save_queue_cost");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((save_queue_param =
+       (double *) calloc ((*number_parameters) * queue_size_tmp,
+                          sizeof (double))) == NULL) {
+    strcpy (exit_msg, "asa(): save_queue_param");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+#endif /* ASA_QUEUE */
+
+#if MULTI_MIN
+  if ((multi_cost =
+       (double *) calloc (OPTIONS->Multi_Number + 1,
+                          sizeof (double))) == NULL) {
+    strcpy (exit_msg, "asa(): *multi_cost");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  multi_cost_qsort = multi_cost;
+  if ((multi_sort =
+       (int *) calloc (OPTIONS->Multi_Number + 1, sizeof (int))) == NULL) {
+    strcpy (exit_msg, "asa(): *multi_sort");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  if ((multi_params =
+       (double **) calloc (OPTIONS->Multi_Number + 1,
+                           sizeof (double *))) == NULL) {
+    strcpy (exit_msg, "asa(): *multi_params");
+    Exit_ASA (exit_msg);
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+  for (multi_index = 0; multi_index <= OPTIONS->Multi_Number; ++multi_index) {
+    if ((multi_params[multi_index] =
+         (double *) calloc (*number_parameters, sizeof (double))) == NULL) {
+      strcpy (exit_msg, "asa(): multi_params[multi_index]");
+      Exit_ASA (exit_msg);
+      *exit_status = CALLOC_FAILED;
+      return (-1);
+    }
+  }
+#endif /* MULTI_MIN */
+
+#if USER_INITIAL_COST_TEMP
+#if USER_ACCEPTANCE_TEST
+  OPTIONS->Cost_Temp_Curr = OPTIONS->Cost_Temp_Init =
+#endif
+    *initial_cost_temperature = *current_cost_temperature =
+    OPTIONS->User_Cost_Temperature[0];
+#endif
+
+  /* set parameters to the initial parameter values */
+  VFOR (index_v)
+    last_saved_state->parameter[index_v] =
+    current_generated_state->parameter[index_v] =
+    parameter_initial_final[index_v];
+#if USER_ACCEPTANCE_TEST
+  OPTIONS->Random_Seed = seed;
+  OPTIONS->Random_Seed[0] = *seed;
+  OPTIONS->User_Acceptance_Flag = TRUE;
+  OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+
+#if ASA_PRINT
+#if INT_LONG
+  fprintf (ptr_asa_out, "Initial Random Seed = %ld\n\n", *seed);
+#else
+  fprintf (ptr_asa_out, "Initial Random Seed = %d\n\n", *seed);
+#endif
+#endif /* ASA_PRINT */
+
+  /* save initial user value of OPTIONS->Sequential_Parameters */
+  *start_sequence = OPTIONS->Sequential_Parameters;
+
+#if ASA_PRINT
+  fprintf (ptr_asa_out,
+#if INT_ALLOC
+           "*number_parameters = %d\n\n", *number_parameters);
+#else
+#if INT_LONG
+           "*number_parameters = %ld\n\n", *number_parameters);
+#else
+           "*number_parameters = %d\n\n", *number_parameters);
+#endif
+#endif
+
+  /* print the min, max, current values, and types of parameters */
+  fprintf (ptr_asa_out, "index_v parameter_minimum parameter_maximum\
+ parameter_value parameter_type \n");
+
+#if ASA_PRINT_INTERMED
+  VFOR (index_v) fprintf (ptr_asa_out,
+#if INT_ALLOC
+                          " %-8d %-*.*g \t\t %-*.*g \t %-*.*g %-7d\n",
+#else
+#if INT_LONG
+                          " %-8ld %-*.*g \t\t %-*.*g \t %-*.*g %-7d\n",
+#else
+                          " %-8d %-*.*g \t\t %-*.*g \t %-*.*g %-7d\n",
+#endif
+#endif
+                          index_v,
+                          G_FIELD, G_PRECISION, parameter_minimum[index_v],
+                          G_FIELD, G_PRECISION, parameter_maximum[index_v],
+                          G_FIELD, G_PRECISION,
+                          current_generated_state->parameter[index_v],
+                          parameter_type[index_v]);
+
+  fprintf (ptr_asa_out, "\n\n");
+#endif /* ASA_PRINT_INTERMED */
+  /* Print out user-defined OPTIONS */
+
+#if DELTA_PARAMETERS
+  VFOR (index_v) fprintf (ptr_asa_out,
+#if INT_ALLOC
+                          "OPTIONS->User_Delta_Parameter[%d] = %*.*g\n",
+#else
+#if INT_LONG
+                          "OPTIONS->User_Delta_Parameter[%ld] = %*.*g\n",
+#else
+                          "OPTIONS->User_Delta_Parameter[%d] = %*.*g\n",
+#endif
+#endif
+                          index_v,
+                          G_FIELD, G_PRECISION,
+                          OPTIONS->User_Delta_Parameter[index_v]);
+  fprintf (ptr_asa_out, "\n");
+#endif /* DELTA_PARAMETERS */
+
+#if QUENCH_PARAMETERS
+  VFOR (index_v) fprintf (ptr_asa_out,
+#if INT_ALLOC
+                          "OPTIONS->User_Quench_Param_Scale[%d] = %*.*g\n",
+#else
+#if INT_LONG
+                          "OPTIONS->User_Quench_Param_Scale[%ld] = %*.*g\n",
+#else
+                          "OPTIONS->User_Quench_Param_Scale[%d] = %*.*g\n",
+#endif
+#endif
+                          index_v,
+                          G_FIELD, G_PRECISION,
+                          OPTIONS->User_Quench_Param_Scale[index_v]);
+#endif /* QUENCH_PARAMETERS */
+
+#if QUENCH_COST
+  fprintf (ptr_asa_out,
+           "\nOPTIONS->User_Quench_Cost_Scale = %*.*g\n\n",
+           G_FIELD, G_PRECISION, OPTIONS->User_Quench_Cost_Scale[0]);
+#endif /* QUENCH_COST */
+
+#if USER_INITIAL_PARAMETERS_TEMPS
+  VFOR (index_v) fprintf (ptr_asa_out,
+#if INT_ALLOC
+                          "OPTIONS->User_Parameter_Temperature[%d] = %*.*g\n",
+#else
+#if INT_LONG
+                          "OPTIONS->User_Parameter_Temperature[%ld] = %*.*g\n",
+#else
+                          "OPTIONS->User_Parameter_Temperature[%d] = %*.*g\n",
+#endif
+#endif
+                          index_v,
+                          G_FIELD, G_PRECISION,
+                          initial_user_parameter_temp[index_v]);
+#endif /* USER_INITIAL_PARAMETERS_TEMPS */
+
+#if RATIO_TEMPERATURE_SCALES
+  VFOR (index_v) fprintf (ptr_asa_out,
+#if INT_ALLOC
+                          "OPTIONS->User_Temperature_Ratio[%d] = %*.*g\n",
+#else
+#if INT_LONG
+                          "OPTIONS->User_Temperature_Ratio[%ld] = %*.*g\n",
+#else
+                          "OPTIONS->User_Temperature_Ratio[%d] = %*.*g\n",
+#endif
+#endif
+                          index_v,
+                          G_FIELD, G_PRECISION,
+                          OPTIONS->User_Temperature_Ratio[index_v]);
+#endif /* RATIO_TEMPERATURE_SCALES */
+
+#if USER_INITIAL_COST_TEMP
+  fprintf (ptr_asa_out,
+           "OPTIONS->User_Cost_Temperature[0] = %*.*g\n",
+           G_FIELD, G_PRECISION, *initial_cost_temperature);
+#endif /* USER_INITIAL_COST_TEMP */
+
+  fflush (ptr_asa_out);
+#endif /* ASA_PRINT */
+
+#if MULTI_MIN
+#if ASA_PRINT
+  fprintf (ptr_asa_out, "\n");
+  fprintf (ptr_asa_out, "Multi_Number = %d\n", OPTIONS->Multi_Number);
+  fprintf (ptr_asa_out, "Multi_Specify = %d\n", OPTIONS->Multi_Specify);
+#if ASA_RESOLUTION
+#else
+  VFOR (index_v) {
+    fprintf (ptr_asa_out,
+#if INT_ALLOC
+             "Multi_Grid[%d] = %*.*g\n",
+#else
+#if INT_LONG
+             "Multi_Grid[%ld] = %*.*g\n",
+#else
+             "Multi_Grid[%d] = %*.*g\n",
+#endif
+#endif
+             index_v, G_FIELD, G_PRECISION, OPTIONS->Multi_Grid[index_v]);
+  }
+#endif /* ASA_RESOLUTION */
+  fprintf (ptr_asa_out, "\n");
+  fflush (ptr_asa_out);
+#endif /* ASA_PRINT */
+#endif /* MULTI_MIN */
+
+#if ASA_PARALLEL
+#if ASA_PRINT
+  fprintf (ptr_asa_out,
+#if INT_LONG
+           "Initial ASA_PARALLEL OPTIONS->\n\t Gener_Block = %ld\n\
+ \t Gener_Block_Max = %ld\n \t Gener_Mov_Avr= %d\n\n",
+#else
+           "ASA_PARALLEL OPTIONS->\n\t Gener_Block = %d\n\
+ \t Gener_Block_Max = %d\n \t Gener_Mov_Avr= %d\n\n",
+#endif
+           OPTIONS->Gener_Block, OPTIONS->Gener_Block_Max,
+           OPTIONS->Gener_Mov_Avr);
+#endif
+#endif /* ASA_PARALLEL */
+
+#if ASA_SAMPLE
+#if ASA_PRINT
+  fprintf (ptr_asa_out, "OPTIONS->Limit_Weights = %*.*g\n\n",
+           G_FIELD, G_PRECISION, OPTIONS->Limit_Weights);
+#endif
+#endif
+  if (OPTIONS->Asa_Recursive_Level > asa_recursive_max)
+    asa_recursive_max = OPTIONS->Asa_Recursive_Level;
+#if ASA_SAVE
+  if (OPTIONS->Asa_Recursive_Level > 0)
+    sprintf (asa_save_comm, "asa_save_%d", OPTIONS->Asa_Recursive_Level);
+  else
+    sprintf (asa_save_comm, "asa_save");
+  if ((ptr_save = fopen (asa_save_comm, "r")) == NULL) {
+    asa_read = FALSE;
+  } else {
+#if ASA_PRINT
+    fprintf (ptr_asa_out, "\n\n\trestart after ASA_SAVE\n\n");
+#endif
+    fclose (ptr_save);
+    asa_read = TRUE;
+
+    /* give some value to avoid any problems with other OPTIONS */
+#if USER_ACCEPTANCE_TEST
+    OPTIONS->Cost_Temp_Curr = OPTIONS->Cost_Temp_Init =
+#endif
+      current_generated_state->cost
+      = *initial_cost_temperature = *current_cost_temperature = 3.1416;
+  }
+#endif
+
+  tmp_var_int = cost_function_test (current_generated_state->cost,
+                                    current_generated_state->parameter,
+                                    parameter_minimum,
+                                    parameter_maximum, number_parameters,
+                                    xnumber_parameters);
+
+  /* compute temperature scales */
+  tmp_var_db1 = -F_LOG ((OPTIONS->Temperature_Ratio_Scale));
+  tmp_var_db2 = F_LOG (OPTIONS->Temperature_Anneal_Scale);
+  temperature_scale =
+    tmp_var_db1 * F_EXP (-tmp_var_db2 / *xnumber_parameters);
+
+  /* set here in case not used */
+  tmp_var_db = ZERO;
+
+#if QUENCH_PARAMETERS
+#if RATIO_TEMPERATURE_SCALES
+  VFOR (index_v) temperature_scale_parameters[index_v] = tmp_var_db1 * F_EXP
+#if QUENCH_PARAMETERS_SCALE
+    (-(tmp_var_db2 * OPTIONS->User_Quench_Param_Scale[index_v])
+#else
+    (-(tmp_var_db2)
+#endif
+     / *xnumber_parameters)
+    * OPTIONS->User_Temperature_Ratio[index_v];
+#else
+  VFOR (index_v) temperature_scale_parameters[index_v] = tmp_var_db1 * F_EXP
+#if QUENCH_PARAMETERS_SCALE
+    (-(tmp_var_db2 * OPTIONS->User_Quench_Param_Scale[index_v])
+#else
+    (-(tmp_var_db2)
+#endif
+     / *xnumber_parameters);
+#endif /* RATIO_TEMPERATURE_SCALES */
+#else /* QUENCH_PARAMETERS */
+#if RATIO_TEMPERATURE_SCALES
+  VFOR (index_v)
+    temperature_scale_parameters[index_v] =
+    tmp_var_db1 * F_EXP (-(tmp_var_db2) / *xnumber_parameters)
+    * OPTIONS->User_Temperature_Ratio[index_v];
+#else
+  VFOR (index_v)
+    temperature_scale_parameters[index_v] =
+    tmp_var_db1 * F_EXP (-(tmp_var_db2) / *xnumber_parameters);
+#endif /* RATIO_TEMPERATURE_SCALES */
+#endif /* QUENCH_PARAMETERS */
+
+#if USER_ACCEPTANCE_TEST
+  OPTIONS->Cost_Temp_Scale =
+#endif
+    *temperature_scale_cost =
+#if QUENCH_COST
+#if QUENCH_COST_SCALE
+    tmp_var_db1 * F_EXP (-(tmp_var_db2 * OPTIONS->User_Quench_Cost_Scale[0])
+#else
+    tmp_var_db1 * F_EXP (-(tmp_var_db2)
+#endif
+                         / *xnumber_parameters) *
+    OPTIONS->Cost_Parameter_Scale_Ratio;
+#else /* QUENCH_COST */
+    tmp_var_db1 * F_EXP (-(tmp_var_db2)
+                         / *xnumber_parameters) *
+    OPTIONS->Cost_Parameter_Scale_Ratio;
+#endif /* QUENCH_COST */
+
+  /* set the initial index of parameter generations to 1 */
+  VFOR (index_v) index_parameter_generations[index_v] = 1;
+
+  /* test user-defined options before calling cost function */
+  tmp_var_int = asa_test_asa_options (seed,
+                                      parameter_initial_final,
+                                      parameter_minimum,
+                                      parameter_maximum,
+                                      tangents,
+                                      curvature,
+                                      number_parameters,
+                                      parameter_type,
+                                      valid_state_generated_flag,
+                                      exit_status, ptr_asa_out, OPTIONS);
+  if (tmp_var_int > 0) {
+#if ASA_PRINT
+    fprintf (ptr_asa_out, "total number invalid OPTIONS = %d\n", tmp_var_int);
+    fflush (ptr_asa_out);
+#endif
+    *exit_status = INVALID_USER_INPUT;
+    goto EXIT_ASA;
+  }
+#if USER_INITIAL_COST_TEMP
+#else
+#if ASA_SAVE
+  if (asa_read == TRUE)
+    OPTIONS->Number_Cost_Samples = 1;
+#endif
+  /* calculate the average cost over samplings of the cost function */
+  if (OPTIONS->Number_Cost_Samples < -1) {
+    tmp_var_db1 = ZERO;
+    tmp_var_db2 = ZERO;
+    tmp_var_int = -OPTIONS->Number_Cost_Samples;
+  } else {
+    tmp_var_db1 = ZERO;
+    tmp_var_int = OPTIONS->Number_Cost_Samples;
+  }
+
+  OPTIONS->Locate_Cost = 0;     /* initial cost temp */
+
+  for (index_cost_constraint = 0;
+       index_cost_constraint < tmp_var_int; ++index_cost_constraint) {
+    *number_invalid_generated_states = 0;
+    repeated_invalid_states = 0;
+    OPTIONS->Sequential_Parameters = *start_sequence - 1;
+    do {
+      ++(*number_invalid_generated_states);
+      generate_new_state (user_random_generator,
+                          seed,
+                          parameter_minimum,
+                          parameter_maximum, current_user_parameter_temp,
+#if USER_GENERATING_FUNCTION
+                          initial_user_parameter_temp,
+                          temperature_scale_parameters,
+#endif
+                          number_parameters,
+                          parameter_type,
+                          current_generated_state, last_saved_state, OPTIONS);
+      *valid_state_generated_flag = TRUE;
+#if USER_ACCEPTANCE_TEST
+      OPTIONS->User_Acceptance_Flag = TRUE;
+      OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+      tmp_var_db =
+        user_cost_function (current_generated_state->parameter,
+                            parameter_minimum,
+                            parameter_maximum,
+                            tangents,
+                            curvature,
+                            number_parameters,
+                            parameter_type,
+                            valid_state_generated_flag, exit_status, OPTIONS);
+      if (cost_function_test
+          (tmp_var_db, current_generated_state->parameter,
+           parameter_minimum, parameter_maximum, number_parameters,
+           xnumber_parameters) == 0) {
+        *exit_status = INVALID_COST_FUNCTION;
+        goto EXIT_ASA;
+      }
+
+      ++repeated_invalid_states;
+      if (repeated_invalid_states > OPTIONS->Limit_Invalid_Generated_States) {
+        *exit_status = TOO_MANY_INVALID_STATES;
+        goto EXIT_ASA;
+      }
+    }
+    while (*valid_state_generated_flag == FALSE);
+    --(*number_invalid_generated_states);
+
+    if (OPTIONS->Number_Cost_Samples < -1) {
+      tmp_var_db1 += tmp_var_db;
+      tmp_var_db2 += (tmp_var_db * tmp_var_db);
+    } else {
+      tmp_var_db1 += fabs (tmp_var_db);
+    }
+  }
+  if (OPTIONS->Number_Cost_Samples < -1) {
+    tmp_var_db1 /= (double) tmp_var_int;
+    tmp_var_db2 /= (double) tmp_var_int;
+    tmp_var_db = sqrt (fabs ((tmp_var_db2 - tmp_var_db1 * tmp_var_db1)
+                             * ((double) tmp_var_int
+                                / ((double) tmp_var_int - ONE))))
+      + (double) EPS_DOUBLE;
+  } else {
+    tmp_var_db = tmp_var_db1 / tmp_var_int;
+  }
+
+#if USER_ACCEPTANCE_TEST
+  OPTIONS->Cost_Temp_Curr = OPTIONS->Cost_Temp_Init =
+#endif
+    *initial_cost_temperature = *current_cost_temperature = tmp_var_db;
+#endif /* USER_INITIAL_COST_TEMP */
+
+  /* set all parameters to the initial parameter values */
+  VFOR (index_v)
+    best_generated_state->parameter[index_v] =
+    last_saved_state->parameter[index_v] =
+    current_generated_state->parameter[index_v] =
+    parameter_initial_final[index_v];
+
+  OPTIONS->Locate_Cost = 1;     /* initial cost value */
+
+  /* if using user's initial parameters */
+  if (OPTIONS->User_Initial_Parameters == TRUE) {
+    *valid_state_generated_flag = TRUE;
+#if USER_ACCEPTANCE_TEST
+    OPTIONS->User_Acceptance_Flag = TRUE;
+    OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+#if ASA_SAVE
+    if (asa_read == FALSE)
+#endif
+      current_generated_state->cost =
+        user_cost_function (current_generated_state->parameter,
+                            parameter_minimum,
+                            parameter_maximum,
+                            tangents,
+                            curvature,
+                            number_parameters,
+                            parameter_type,
+                            valid_state_generated_flag, exit_status, OPTIONS);
+    if (cost_function_test
+        (current_generated_state->cost, current_generated_state->parameter,
+         parameter_minimum, parameter_maximum, number_parameters,
+         xnumber_parameters) == 0) {
+      *exit_status = INVALID_COST_FUNCTION;
+      goto EXIT_ASA;
+    }
+#if ASA_PRINT
+    if (*valid_state_generated_flag == FALSE)
+      fprintf (ptr_asa_out, "user's initial parameters generated \
+FALSE *valid_state_generated_flag\n");
+#endif
+  } else {
+    /* let asa generate valid initial parameters */
+    repeated_invalid_states = 0;
+    OPTIONS->Sequential_Parameters = *start_sequence - 1;
+    do {
+      ++(*number_invalid_generated_states);
+      generate_new_state (user_random_generator,
+                          seed,
+                          parameter_minimum,
+                          parameter_maximum, current_user_parameter_temp,
+#if USER_GENERATING_FUNCTION
+                          initial_user_parameter_temp,
+                          temperature_scale_parameters,
+#endif
+                          number_parameters,
+                          parameter_type,
+                          current_generated_state, last_saved_state, OPTIONS);
+      *valid_state_generated_flag = TRUE;
+#if USER_ACCEPTANCE_TEST
+      OPTIONS->User_Acceptance_Flag = TRUE;
+      OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+      current_generated_state->cost =
+        user_cost_function (current_generated_state->parameter,
+                            parameter_minimum,
+                            parameter_maximum,
+                            tangents,
+                            curvature,
+                            number_parameters,
+                            parameter_type,
+                            valid_state_generated_flag, exit_status, OPTIONS);
+      if (cost_function_test
+          (current_generated_state->cost,
+           current_generated_state->parameter, parameter_minimum,
+           parameter_maximum, number_parameters, xnumber_parameters) == 0) {
+        *exit_status = INVALID_COST_FUNCTION;
+        goto EXIT_ASA;
+      }
+      ++repeated_invalid_states;
+      if (repeated_invalid_states > OPTIONS->Limit_Invalid_Generated_States) {
+        *exit_status = TOO_MANY_INVALID_STATES;
+        goto EXIT_ASA;
+      }
+    }
+    while (*valid_state_generated_flag == FALSE);
+    --(*number_invalid_generated_states);
+  }                             /* OPTIONS->User_Initial_Parameters */
+
+  /* set all states to the last one generated */
+  VFOR (index_v) {
+#if DROPPED_PARAMETERS
+    /* ignore parameters that have too small a range */
+    if (PARAMETER_RANGE_TOO_SMALL (index_v))
+      continue;
+#endif
+    best_generated_state->parameter[index_v] =
+      last_saved_state->parameter[index_v] =
+      current_generated_state->parameter[index_v];
+  }
+
+  /* set all costs to the last one generated */
+  best_generated_state->cost = last_saved_state->cost =
+    current_generated_state->cost;
+
+  *accepted_to_generated_ratio = ONE;
+
+  /* do not calculate curvatures initially */
+  *curvature_flag = FALSE;
+
+#if ASA_PRINT
+  fprintf (ptr_asa_out,
+           "temperature_scale = %*.*g\n",
+           G_FIELD, G_PRECISION, temperature_scale);
+#if RATIO_TEMPERATURE_SCALES
+#if ASA_PRINT_INTERMED
+  VFOR (index_v) {
+    fprintf (ptr_asa_out,
+#if INT_ALLOC
+             "temperature_scale_parameters[%d] = %*.*g\n",
+#else
+#if INT_LONG
+             "temperature_scale_parameters[%ld] = %*.*g\n",
+#else
+             "temperature_scale_parameters[%d] = %*.*g\n",
+#endif
+#endif
+             index_v,
+             G_FIELD, G_PRECISION, temperature_scale_parameters[index_v]);
+  }
+#endif
+#else
+  fprintf (ptr_asa_out,
+           "temperature_scale_parameters[0] = %*.*g\n",
+           G_FIELD, G_PRECISION, temperature_scale_parameters[0]);
+#endif /* RATIO_TEMPERATURE_SCALES */
+  fprintf (ptr_asa_out,
+           "*temperature_scale_cost = %*.*g\n",
+           G_FIELD, G_PRECISION, *temperature_scale_cost);
+  fprintf (ptr_asa_out, "\n\n");
+
+#if ASA_PRINT_INTERMED
+  print_state (parameter_minimum,
+               parameter_maximum,
+               tangents,
+               curvature,
+               current_cost_temperature,
+               current_user_parameter_temp,
+               accepted_to_generated_ratio,
+               number_parameters,
+               curvature_flag,
+               number_accepted,
+               index_cost_acceptances,
+               number_generated,
+               number_invalid_generated_states,
+               last_saved_state, best_generated_state, ptr_asa_out, OPTIONS);
+#endif
+  fprintf (ptr_asa_out, "\n");
+
+  fflush (ptr_asa_out);
+#endif
+
+#if ASA_SAMPLE
+#if ASA_PRINT
+  fprintf (ptr_asa_out,
+           ":SAMPLE:   n_accept   cost        cost_temp    bias_accept    \
+ aver_weight\n");
+  fprintf (ptr_asa_out,
+           ":SAMPLE:   index      param[]     temp[]       bias_gener[]   \
+ range[]\n");
+#endif
+#endif
+
+  /* reset the current cost and the number of generations performed */
+  *number_invalid_generated_states = 0;
+  *best_number_generated_saved =
+    *number_generated = *recent_number_generated = 0;
+  OPTIONS->N_Generated = *number_generated;
+  VFOR (index_v) {
+    /* ignore parameters that have too small a range */
+    if (PARAMETER_RANGE_TOO_SMALL (index_v))
+      continue;
+    index_parameter_generations[index_v] = 1;
+  }
+#if USER_ACCEPTANCE_TEST
+  OPTIONS->User_Acceptance_Flag = FALSE;
+  OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+
+#if ASA_QUEUE
+#if ASA_PRINT
+#if INT_ALLOC
+  fprintf (ptr_asa_out, "OPTIONS->Queue_Size = %d\n", OPTIONS->Queue_Size);
+#else
+#if INT_LONG
+  fprintf (ptr_asa_out, "OPTIONS->Queue_Size = %ld\n", OPTIONS->Queue_Size);
+#else
+  fprintf (ptr_asa_out, "OPTIONS->Queue_Size = %d\n", OPTIONS->Queue_Size);
+#endif
+#endif
+  VFOR (index_v) {
+    fprintf (ptr_asa_out,
+#if INT_ALLOC
+             "Queue_Resolution[%d] = %*.*g\n",
+#else
+#if INT_LONG
+             "Queue_Resolution[%ld] = %*.*g\n",
+#else
+             "Queue_Resolution[%d] = %*.*g\n",
+#endif
+#endif
+             index_v,
+             G_FIELD, G_PRECISION, OPTIONS->Queue_Resolution[index_v]);
+  }
+#endif /* ASA_PRINT */
+
+  /* fill arrays to check allocated memory */
+  for (queue = 0; queue < queue_size_tmp; ++queue) {
+    VFOR (index_v) {
+      if (PARAMETER_RANGE_TOO_SMALL (index_v)) {
+        continue;
+      }
+      queue_v = index_v + queue * (LONG_INT) (*number_parameters);
+      save_queue_param[queue_v] = current_generated_state->parameter[index_v];
+    }
+    save_queue_cost[queue] = current_generated_state->cost;
+    save_queue_flag[queue] = *valid_state_generated_flag;
+  }
+  save_queue = save_queue_indx = 0;
+#endif /* ASA_QUEUE */
+
+#if ASA_RESOLUTION
+#if ASA_PRINT
+  VFOR (index_v) {
+    fprintf (ptr_asa_out,
+#if INT_ALLOC
+             "Coarse_Resolution[%d] = %*.*g\n",
+#else
+#if INT_LONG
+             "Coarse_Resolution[%ld] = %*.*g\n",
+#else
+             "Coarse_Resolution[%d] = %*.*g\n",
+#endif
+#endif
+             index_v,
+             G_FIELD, G_PRECISION, OPTIONS->Coarse_Resolution[index_v]);
+  }
+#endif /* ASA_PRINT */
+#endif /* ASA_RESOLUTION */
+
+#if MULTI_MIN
+  multi_sort[OPTIONS->Multi_Number] = OPTIONS->Multi_Number;
+  multi_cost[OPTIONS->Multi_Number] = current_generated_state->cost;
+  VFOR (index_v) {
+    multi_params[OPTIONS->Multi_Number][index_v] =
+      current_generated_state->parameter[index_v];
+  }
+  for (multi_index = 0; multi_index < OPTIONS->Multi_Number; ++multi_index) {
+    multi_sort[multi_index] = multi_index;
+    multi_cost[multi_index] = OPTIONS->Multi_Cost[multi_index] =
+      current_generated_state->cost;
+    VFOR (index_v) {
+      multi_params[multi_index][index_v] =
+        OPTIONS->Multi_Params[multi_index][index_v] =
+        current_generated_state->parameter[index_v];
+    }
+  }
+#endif /* MULTI_MIN */
+
+  OPTIONS->Sequential_Parameters = *start_sequence - 1;
+
+  /* MAIN ANNEALING LOOP */
+  while (((*number_accepted <= OPTIONS->Limit_Acceptances)
+          || (OPTIONS->Limit_Acceptances == 0))
+         && ((*number_generated <= OPTIONS->Limit_Generated)
+             || (OPTIONS->Limit_Generated == 0))) {
+
+    tmp_var_db1 = -F_LOG ((OPTIONS->Temperature_Ratio_Scale));
+
+    /* compute temperature scales */
+    tmp_var_db2 = F_LOG (OPTIONS->Temperature_Anneal_Scale);
+    temperature_scale = tmp_var_db1 *
+      F_EXP (-tmp_var_db2 / *xnumber_parameters);
+
+#if QUENCH_PARAMETERS
+#if RATIO_TEMPERATURE_SCALES
+    VFOR (index_v)
+      temperature_scale_parameters[index_v] = tmp_var_db1 * F_EXP
+#if QUENCH_PARAMETERS_SCALE
+      (-(tmp_var_db2 * OPTIONS->User_Quench_Param_Scale[index_v])
+#else
+      (-(tmp_var_db2)
+#endif
+       / *xnumber_parameters)
+      * OPTIONS->User_Temperature_Ratio[index_v];
+#else
+    VFOR (index_v)
+      temperature_scale_parameters[index_v] = tmp_var_db1 * F_EXP
+#if QUENCH_PARAMETERS_SCALE
+      (-(tmp_var_db2 * OPTIONS->User_Quench_Param_Scale[index_v])
+#else
+      (-(tmp_var_db2)
+#endif
+       / *xnumber_parameters);
+#endif /* RATIO_TEMPERATURE_SCALES */
+#else /* QUENCH_PARAMETERS */
+#if RATIO_TEMPERATURE_SCALES
+    VFOR (index_v)
+      temperature_scale_parameters[index_v] =
+      tmp_var_db1 * F_EXP (-(tmp_var_db2) / *xnumber_parameters)
+      * OPTIONS->User_Temperature_Ratio[index_v];
+#else
+    VFOR (index_v)
+      temperature_scale_parameters[index_v] =
+      tmp_var_db1 * F_EXP (-(tmp_var_db2) / *xnumber_parameters);
+#endif /* RATIO_TEMPERATURE_SCALES */
+#endif /* QUENCH_PARAMETERS */
+
+#if USER_ACCEPTANCE_TEST
+    OPTIONS->Cost_Temp_Scale =
+#endif
+      *temperature_scale_cost =
+#if QUENCH_COST
+#if QUENCH_COST_SCALE
+      tmp_var_db1 * F_EXP (-(tmp_var_db2 * OPTIONS->User_Quench_Cost_Scale[0])
+#else
+      tmp_var_db1 * F_EXP (-(tmp_var_db2)
+#endif
+                           / *xnumber_parameters) *
+      OPTIONS->Cost_Parameter_Scale_Ratio;
+#else /* QUENCH_COST */
+      tmp_var_db1 * F_EXP (-(tmp_var_db2)
+                           / *xnumber_parameters) *
+      OPTIONS->Cost_Parameter_Scale_Ratio;
+#endif /* QUENCH_COST */
+
+    /* CALCULATE NEW TEMPERATURES */
+
+    /* calculate new parameter temperatures */
+    VFOR (index_v) {
+      /* skip parameters with too small a range */
+      if (PARAMETER_RANGE_TOO_SMALL (index_v))
+        continue;
+
+      log_new_temperature_ratio =
+        -temperature_scale_parameters[index_v] *
+        F_POW ((double) index_parameter_generations[index_v],
+#if QUENCH_PARAMETERS
+               OPTIONS->User_Quench_Param_Scale[index_v]
+#else /* QUENCH_PARAMETERS */
+               ONE
+#endif /* QUENCH_PARAMETERS */
+               / *xnumber_parameters);
+      /* check (and correct) for too large an exponent */
+      log_new_temperature_ratio = EXPONENT_CHECK (log_new_temperature_ratio);
+      current_user_parameter_temp[index_v] =
+        initial_user_parameter_temp[index_v]
+        * F_EXP (log_new_temperature_ratio);
+
+#if NO_PARAM_TEMP_TEST
+      if (current_user_parameter_temp[index_v] < (double) EPS_DOUBLE)
+        current_user_parameter_temp[index_v] = (double) EPS_DOUBLE;
+#else
+      /* check for too small a parameter temperature */
+      if (current_user_parameter_temp[index_v] < (double) EPS_DOUBLE) {
+        *exit_status = P_TEMP_TOO_SMALL;
+        *index_exit_v = index_v;
+        goto EXIT_ASA;
+      }
+#endif
+    }
+
+    /* calculate new cost temperature */
+    log_new_temperature_ratio =
+      -*temperature_scale_cost * F_POW ((double) *index_cost_acceptances,
+#if QUENCH_COST
+                                        OPTIONS->User_Quench_Cost_Scale[0]
+#else
+                                        ONE
+#endif
+                                        / *xnumber_parameters);
+    log_new_temperature_ratio = EXPONENT_CHECK (log_new_temperature_ratio);
+#if USER_ACCEPTANCE_TEST
+    OPTIONS->Cost_Temp_Curr = OPTIONS->Cost_Temp_Init =
+#endif
+      *current_cost_temperature = *initial_cost_temperature
+      * F_EXP (log_new_temperature_ratio);
+
+#if NO_COST_TEMP_TEST
+    if (*current_cost_temperature < (double) EPS_DOUBLE)
+#if USER_ACCEPTANCE_TEST
+      OPTIONS->Cost_Temp_Curr =
+#endif
+        *current_cost_temperature = (double) EPS_DOUBLE;
+#else
+    /* check for too small a cost temperature */
+    if (*current_cost_temperature < (double) EPS_DOUBLE) {
+      *exit_status = C_TEMP_TOO_SMALL;
+      goto EXIT_ASA;
+    }
+#endif
+
+#if ASA_SAVE
+    if (asa_read == TRUE && OPTIONS->Asa_Recursive_Level == asa_recursive_max) {
+      if (OPTIONS->Asa_Recursive_Level > 0)
+        sprintf (asa_save_comm, "asa_save_%d", OPTIONS->Asa_Recursive_Level);
+      else
+        sprintf (asa_save_comm, "asa_save");
+      ptr_save = fopen (asa_save_comm, "r");
+
+      fread (number_parameters, sizeof (ALLOC_INT), 1, ptr_save);
+      fread (xnumber_parameters, sizeof (double), 1, ptr_save);
+      fread (parameter_minimum, sizeof (double),
+             *number_parameters, ptr_save);
+      fread (parameter_maximum, sizeof (double),
+             *number_parameters, ptr_save);
+      fread (tangents, sizeof (double), *number_parameters, ptr_save);
+      fread (current_user_parameter_temp, sizeof (double),
+             *number_parameters, ptr_save);
+      fread (initial_user_parameter_temp, sizeof (double),
+             *number_parameters, ptr_save);
+      fread (temperature_scale_parameters, sizeof (double),
+             *number_parameters, ptr_save);
+
+      fread (parameter_type, sizeof (int), *number_parameters, ptr_save);
+      fread (&index_cost_repeat, sizeof (int), 1, ptr_save);
+      fread (&asa_open, sizeof (int), 1, ptr_save);
+      fread (&number_asa_open, sizeof (int), 1, ptr_save);
+      fread (&recursive_asa_open, sizeof (int), 1, ptr_save);
+
+      fread (current_cost_temperature, sizeof (double), 1, ptr_save);
+      fread (initial_cost_temperature, sizeof (double), 1, ptr_save);
+      fread (temperature_scale_cost, sizeof (double), 1, ptr_save);
+      fread (accepted_to_generated_ratio, sizeof (double), 1, ptr_save);
+
+      fread (curvature_flag, sizeof (int), 1, ptr_save);
+
+      fread (seed, sizeof (LONG_INT), 1, ptr_save);
+      fread (number_generated, sizeof (LONG_INT), 1, ptr_save);
+      fread (number_accepted, sizeof (LONG_INT), 1, ptr_save);
+      fread (number_acceptances_saved, sizeof (LONG_INT), 1, ptr_save);
+      fread (recent_number_acceptances, sizeof (LONG_INT), 1, ptr_save);
+      fread (recent_number_generated, sizeof (LONG_INT), 1, ptr_save);
+      fread (number_invalid_generated_states, sizeof (LONG_INT), 1, ptr_save);
+      fread (index_cost_acceptances, sizeof (LONG_INT), 1, ptr_save);
+      fread (best_number_generated_saved, sizeof (LONG_INT), 1, ptr_save);
+      fread (best_number_accepted_saved, sizeof (LONG_INT), 1, ptr_save);
+
+      fread (index_parameter_generations, sizeof (LONG_INT),
+             *number_parameters, ptr_save);
+
+      fread (current_generated_state->parameter,
+             sizeof (double), *number_parameters, ptr_save);
+      fread (last_saved_state->parameter,
+             sizeof (double), *number_parameters, ptr_save);
+      fread (best_generated_state->parameter,
+             sizeof (double), *number_parameters, ptr_save);
+      fread (&(current_generated_state->cost), sizeof (double), 1, ptr_save);
+      fread (&(last_saved_state->cost), sizeof (double), 1, ptr_save);
+      fread (&(best_generated_state->cost), sizeof (double), 1, ptr_save);
+
+      fread (&(OPTIONS->Limit_Acceptances), sizeof (LONG_INT), 1, ptr_save);
+      fread (&(OPTIONS->Limit_Generated), sizeof (LONG_INT), 1, ptr_save);
+      fread (&(OPTIONS->Limit_Invalid_Generated_States), sizeof (int),
+             1, ptr_save);
+      fread (&(OPTIONS->Accepted_To_Generated_Ratio), sizeof (double),
+             1, ptr_save);
+      fread (&(OPTIONS->Cost_Precision), sizeof (double), 1, ptr_save);
+      fread (&(OPTIONS->Maximum_Cost_Repeat), sizeof (int), 1, ptr_save);
+      fread (&(OPTIONS->Number_Cost_Samples), sizeof (int), 1, ptr_save);
+      fread (&(OPTIONS->Temperature_Ratio_Scale), sizeof (double),
+             1, ptr_save);
+      fread (&(OPTIONS->Cost_Parameter_Scale_Ratio), sizeof (double),
+             1, ptr_save);
+      fread (&(OPTIONS->Temperature_Anneal_Scale), sizeof (double),
+             1, ptr_save);
+      fread (&(OPTIONS->Include_Integer_Parameters), sizeof (int),
+             1, ptr_save);
+      fread (&(OPTIONS->User_Initial_Parameters), sizeof (int), 1, ptr_save);
+      fread (&(OPTIONS->Sequential_Parameters), sizeof (ALLOC_INT), 1,
+             ptr_save);
+      fread (&(OPTIONS->Initial_Parameter_Temperature), sizeof (double), 1,
+             ptr_save);
+      fread (&(OPTIONS->Acceptance_Frequency_Modulus), sizeof (int), 1,
+             ptr_save);
+      fread (&(OPTIONS->Generated_Frequency_Modulus), sizeof (int), 1,
+             ptr_save);
+      fread (&(OPTIONS->Reanneal_Cost), sizeof (int), 1, ptr_save);
+      fread (&(OPTIONS->Reanneal_Parameters), sizeof (int), 1, ptr_save);
+      fread (&(OPTIONS->Delta_X), sizeof (double), 1, ptr_save);
+      fread (&(OPTIONS->User_Tangents), sizeof (int), 1, ptr_save);
+
+#if USER_INITIAL_COST_TEMP
+      fread (&(OPTIONS->User_Cost_Temperature), sizeof (double), 1, ptr_save);
+#endif
+#if RATIO_TEMPERATURE_SCALES
+      fread (OPTIONS->User_Temperature_Ratio, sizeof (double),
+             *number_parameters, ptr_save);
+#endif
+#if USER_INITIAL_PARAMETERS_TEMPS
+      fread (OPTIONS->User_Parameter_Temperature, sizeof (double),
+             *number_parameters, ptr_save);
+#endif
+#if DELTA_PARAMETERS
+      fread (OPTIONS->User_Delta_Parameter, sizeof (double),
+             *number_parameters, ptr_save);
+#endif
+#if QUENCH_PARAMETERS
+      fread (OPTIONS->User_Quench_Param_Scale, sizeof (double),
+             *number_parameters, ptr_save);
+#endif
+#if QUENCH_COST
+      fread (OPTIONS->User_Quench_Cost_Scale, sizeof (double), 1, ptr_save);
+#endif
+      fread (&(OPTIONS->N_Accepted), sizeof (LONG_INT), 1, ptr_save);
+      fread (&(OPTIONS->N_Generated), sizeof (LONG_INT), 1, ptr_save);
+      fread (&(OPTIONS->Locate_Cost), sizeof (int), 1, ptr_save);
+      fread (&(OPTIONS->Immediate_Exit), sizeof (int), 1, ptr_save);
+#if OPTIONAL_DATA_DBL
+      fread (&(OPTIONS->Asa_Data_Dim_Dbl), sizeof (ALLOC_INT), 1, ptr_save);
+      fread (OPTIONS->Asa_Data_Dbl, sizeof (double),
+             OPTIONS->Asa_Data_Dim_Dbl, ptr_save);
+#endif
+      fread (&(OPTIONS->Random_Array_Dim), sizeof (ALLOC_INT), 1, ptr_save);
+      fread (OPTIONS->Random_Array, sizeof (double),
+             OPTIONS->Random_Array_Dim, ptr_save);
+      fread (&(OPTIONS->Asa_Recursive_Level), sizeof (int), 1, ptr_save);
+#if OPTIONAL_DATA_INT
+      fread (&(OPTIONS->Asa_Data_Dim_Int), sizeof (ALLOC_INT), 1, ptr_save);
+      fread (OPTIONS->Asa_Data_Int, sizeof (LONG_INT),
+             OPTIONS->Asa_Data_Dim_Int, ptr_save);
+#endif
+#if OPTIONAL_DATA_PTR
+      fread (&(OPTIONS->Asa_Data_Dim_Ptr), sizeof (ALLOC_INT), 1, ptr_save);
+      if (OPTIONS->Asa_Recursive_Level == 0)
+        fread (OPTIONS->Asa_Data_Ptr, sizeof (OPTIONAL_PTR_TYPE),
+               OPTIONS->Asa_Data_Dim_Ptr, ptr_save);
+#if ASA_TEMPLATE_SELFOPT
+      if (OPTIONS->Asa_Recursive_Level == 1)
+        fread (OPTIONS->Asa_Data_Ptr, sizeof (RECUR_OPTIONAL_PTR_TYPE),
+               OPTIONS->Asa_Data_Dim_Ptr, ptr_save);
+#endif
+#endif
+#if USER_ASA_OUT
+      fread (OPTIONS->Asa_Out_File, sizeof (char), 1, ptr_save);
+#endif
+#if USER_COST_SCHEDULE
+      fread (&(OPTIONS->Cost_Schedule), sizeof (char), 1, ptr_save);
+#endif
+#if USER_ACCEPT_ASYMP_EXP
+      fread (&(OPTIONS->Asymp_Exp_Param), sizeof (double), 1, ptr_save);
+#endif
+#if USER_ACCEPTANCE_TEST
+      fread (&(OPTIONS->Acceptance_Test), sizeof (char), 1, ptr_save);
+      fread (&(OPTIONS->User_Acceptance_Flag), sizeof (int), 1, ptr_save);
+      fread (&(OPTIONS->Cost_Acceptance_Flag), sizeof (int), 1, ptr_save);
+      fread (&(OPTIONS->Cost_Temp_Curr), sizeof (double), 1, ptr_save);
+      fread (&(OPTIONS->Cost_Temp_Init), sizeof (double), 1, ptr_save);
+      fread (&(OPTIONS->Cost_Temp_Scale), sizeof (double), 1, ptr_save);
+#endif
+#if USER_GENERATING_FUNCTION
+      fread (&(OPTIONS->Generating_Distrib), sizeof (char), 1, ptr_save);
+#endif
+#if USER_REANNEAL_COST
+      fread (&(OPTIONS->Reanneal_Cost_Function), sizeof (char), 1, ptr_save);
+#endif
+#if USER_REANNEAL_PARAMETERS
+      fread (&(OPTIONS->Reanneal_Params_Function), sizeof (char),
+             1, ptr_save);
+#endif
+#if ASA_SAMPLE
+      fread (&(OPTIONS->Bias_Acceptance), sizeof (double), 1, ptr_save);
+      fread (OPTIONS->Bias_Generated, sizeof (double),
+             *number_parameters, ptr_save);
+      fread (&(OPTIONS->Average_Weights), sizeof (double), 1, ptr_save);
+      fread (&(OPTIONS->Limit_Weights), sizeof (double), 1, ptr_save);
+#endif
+#if ASA_QUEUE
+      fread (save_queue, sizeof (LONG_INT), 1, ptr_save);
+      fread (save_queue_indx, sizeof (LONG_INT), 1, ptr_save);
+      fread (&(OPTIONS->Queue_Size), sizeof (ALLOC_INT), 1, ptr_save);
+      fread (save_queue_flag, sizeof (int), save_queue, ptr_save);
+      fread (save_queue_cost, sizeof (double), save_queue, ptr_save);
+      fread (save_queue_param, sizeof (double),
+             (*number_parameters) * (OPTIONS->Queue_Size), ptr_save);
+#if ASA_RESOLUTION
+#else
+      fread (OPTIONS->Queue_Resolution, sizeof (double),
+             *number_parameters, ptr_save);
+#endif
+#endif
+#if ASA_RESOLUTION
+      fread (OPTIONS->Coarse_Resolution, sizeof (double),
+             *number_parameters, ptr_save);
+#endif
+#if FITLOC
+      fread (&(OPTIONS->Fit_Local), sizeof (int), 1, ptr_save);
+      fread (&(OPTIONS->Iter_Max), sizeof (int), 1, ptr_save);
+      fread (&(OPTIONS->Penalty), sizeof (double), 1, ptr_save);
+#endif
+#if MULTI_MIN
+      fread (OPTIONS->Multi_Number, sizeof (int), 1, ptr_save);
+      fread (OPTIONS->Multi_Grid,
+             sizeof (double), *number_parameters, ptr_save);
+      fread (&(OPTIONS->Multi_Specify), sizeof (int), 1, ptr_save);
+      for (multi_index = 0; multi_index < OPTIONS->Multi_Number;
+           ++multi_index) {
+        fread (&(OPTIONS->Multi_Cost[multi_index]), sizeof (double), 1,
+               ptr_save);
+        fread (&(OPTIONS->Multi_Params[multi_index]), sizeof (double),
+               *number_parameters, ptr_save);
+      }
+#endif
+#if ASA_PARALLEL
+      fread (&parallel_generated, sizeof (LONG_INT), 1, ptr_save);
+      fread (&parallel_block_max, sizeof (LONG_INT), 1, ptr_save);
+      for (index_parallel = 0; index_parallel < parallel_block_max;
+           ++index_parallel) {
+        fread (gener_block_state[index_parallel].parameter,
+               sizeof (double), *number_parameters, ptr_save);
+        fread (&(gener_block_state[index_parallel].cost),
+               sizeof (double), 1, ptr_save);
+#if USER_ACCEPTANCE_TEST
+        fread (&
+               (gener_block_state[index_parallel].par_user_accept_flag),
+               sizeof (int), 1, ptr_save);
+        fread (&
+               (gener_block_state[index_parallel].par_cost_accept_flag),
+               sizeof (int), 1, ptr_save);
+#endif
+      }
+      fread (&(OPTIONS->Gener_Mov_Avr), sizeof (int), 1, ptr_save);
+      fread (&(OPTIONS->Gener_Block), sizeof (LONG_INT), 1, ptr_save);
+      fread (&(OPTIONS->Gener_Block_Max), sizeof (LONG_INT), 1, ptr_save);
+#endif
+
+      fclose (ptr_save);
+
+      asa_read = FALSE;
+#if ASA_PRINT
+      print_state (parameter_minimum,
+                   parameter_maximum,
+                   tangents,
+                   curvature,
+                   current_cost_temperature,
+                   current_user_parameter_temp,
+                   accepted_to_generated_ratio,
+                   number_parameters,
+                   curvature_flag,
+                   number_accepted,
+                   index_cost_acceptances,
+                   number_generated,
+                   number_invalid_generated_states,
+                   last_saved_state,
+                   best_generated_state, ptr_asa_out, OPTIONS);
+#endif /* ASA_PRINT */
+
+#include "asa_opt"
+#if ASA_SAVE_OPT
+      if ((ptr_save_opt = fopen ("asa_save_opt", "r")) == NULL) {
+#if INCL_STDOUT
+        printf ("\n\n*** WARNING fopen asa_save_opt failed *** \n\n");
+#endif /* INCL_STDOUT */
+#if ASA_PRINT
+        fprintf (ptr_asa_out,
+                 "\n\n*** WARNING fopen asa_save_opt failed *** \n\n");
+        fflush (ptr_asa_out);
+#endif
+      } else {
+        fscanf (ptr_save_opt, "%s%s%s%s%s",
+                read_if, read_FALSE, read_comm1, read_ASA_SAVE, read_comm2);
+        if (strcmp (read_if, "#if") || strcmp (read_FALSE, "FALSE")
+            || strcmp (read_comm1, "/*")
+            || strcmp (read_ASA_SAVE, "ASA_SAVE")
+            || strcmp (read_comm2, "*/")) {
+#if INCL_STDOUT
+          printf ("\n\n*** EXIT not asa_save_opt for this version *** \n\n");
+#endif /* INCL_STDOUT */
+#if ASA_PRINT
+          fprintf (ptr_asa_out,
+                   "\n\n*** not asa_save_opt for this version *** \n\n");
+          fflush (ptr_asa_out);
+#endif
+          *exit_status = INVALID_USER_INPUT;
+          goto EXIT_ASA;
+        }
+#if INT_LONG
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%ld", &read_long);
+        OPTIONS->Limit_Acceptances = read_long;
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%ld", &read_long);
+        OPTIONS->Limit_Generated = read_long;
+#else
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%d", &read_int);
+        OPTIONS->Limit_Acceptances = read_int;
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%d", &read_int);
+        OPTIONS->Limit_Generated = read_int;
+#endif
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%d", &read_int);
+        OPTIONS->Limit_Invalid_Generated_States = read_int;
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%lf", &read_double);
+        OPTIONS->Accepted_To_Generated_Ratio = read_double;
+
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%lf", &read_double);
+        OPTIONS->Cost_Precision = read_double;
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%d", &read_int);
+        OPTIONS->Maximum_Cost_Repeat = read_int;
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%d", &read_int);
+        OPTIONS->Number_Cost_Samples = read_int;
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%lf", &read_double);
+        OPTIONS->Temperature_Ratio_Scale = read_double;
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%lf", &read_double);
+        OPTIONS->Cost_Parameter_Scale_Ratio = read_double;
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%lf", &read_double);
+        OPTIONS->Temperature_Anneal_Scale = read_double;
+
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%d", &read_int);
+        OPTIONS->Include_Integer_Parameters = read_int;
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%d", &read_int);
+        OPTIONS->User_Initial_Parameters = read_int;
+#if INT_ALLOC
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%d", &read_int);
+        OPTIONS->Sequential_Parameters = read_int;
+#else
+#if INT_LONG
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%ld", &read_long);
+        OPTIONS->Sequential_Parameters = read_long;
+#else
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%d", &read_int);
+        OPTIONS->Sequential_Parameters = read_int;
+#endif
+#endif
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%lf", &read_double);
+        OPTIONS->Initial_Parameter_Temperature = read_double;
+
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%d", &read_int);
+        OPTIONS->Acceptance_Frequency_Modulus = read_int;
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%d", &read_int);
+        OPTIONS->Generated_Frequency_Modulus = read_int;
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%d", &read_int);
+        OPTIONS->Reanneal_Cost = read_int;
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%d", &read_int);
+        OPTIONS->Reanneal_Parameters = read_int;
+
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%lf", &read_double);
+        OPTIONS->Delta_X = read_double;
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%d", &read_int);
+        OPTIONS->User_Tangents = read_int;
+        fscanf (ptr_save_opt, "%s", read_option);
+        fscanf (ptr_save_opt, "%d", &read_int);
+        OPTIONS->Curvature_0 = read_int;
+
+        fclose (ptr_save_opt);
+      }
+#endif /* ASA_SAVE_OPT */
+
+      goto SAVED_ASA;
+    }
+#endif /* ASA_SAVE */
+
+    /* GENERATE NEW PARAMETERS */
+
+    /* generate a new valid set of parameters */
+#if ASA_PARALLEL
+    /* *** ENTER CODE TO SPAWN OFF PARALLEL GENERATED STATES *** */
+
+    /* check if need more memory allocated to gener_block_state */
+    if (OPTIONS->Gener_Block_Max > parallel_block_max) {
+      for (index_parallel = 0; index_parallel < parallel_block_max;
+           ++index_parallel) {
+        free (gener_block_state[index_parallel].parameter);
+      }
+      free (gener_block_state);
+
+      if ((gener_block_state =
+           (STATE *) calloc (OPTIONS->Gener_Block_Max,
+                             sizeof (STATE))) == NULL) {
+        strcpy (exit_msg, "asa(): gener_block_state");
+        Exit_ASA (exit_msg);
+        *exit_status = CALLOC_FAILED;
+        return (-1);
+      }
+
+      parallel_block_max = OPTIONS->Gener_Block_Max;
+
+      for (index_parallel = 0; index_parallel < parallel_block_max;
+           ++index_parallel) {
+        if ((gener_block_state[index_parallel].parameter =
+             (double *) calloc (*number_parameters,
+                                sizeof (double))) == NULL) {
+          strcpy (exit_msg,
+                  "asa(): gener_block_state[index_parallel].parameter");
+          Exit_ASA (exit_msg);
+          *exit_status = CALLOC_FAILED;
+          return (-1);
+        }
+      }
+    }
+#if ASA_TEMPLATE_PARALLEL
+    for (index_parallel = 0; index_parallel < OPTIONS->Gener_Block;
+         ++index_parallel) {
+#endif /* ASA_TEMPLATE_PARALLEL */
+#endif /* ASA_PARALLEL */
+
+      if (OPTIONS->Locate_Cost < 0) {
+        OPTIONS->Locate_Cost = 12;      /* generate new state from new best */
+      } else {
+        OPTIONS->Locate_Cost = 2;       /* generate new state */
+      }
+
+      repeated_invalid_states = 0;
+      do {
+        ++(*number_invalid_generated_states);
+        generate_new_state (user_random_generator,
+                            seed,
+                            parameter_minimum,
+                            parameter_maximum, current_user_parameter_temp,
+#if USER_GENERATING_FUNCTION
+                            initial_user_parameter_temp,
+                            temperature_scale_parameters,
+#endif
+                            number_parameters,
+                            parameter_type,
+                            current_generated_state,
+                            last_saved_state, OPTIONS);
+
+        *valid_state_generated_flag = TRUE;
+#if USER_ACCEPTANCE_TEST
+        OPTIONS->User_Acceptance_Flag = FALSE;
+        OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+#if ASA_QUEUE
+        /* Binary trees do not seem necessary since we are assuming
+           that the cost function calculation is the bottleneck.
+           However, see the MISC.DIR/asa_contrib file for
+           source code for doubly-linked and hashed lists. */
+        if (OPTIONS->Queue_Size == 0) {
+          queue_new = 1;
+        } else {
+          queue_new = 1;
+          for (queue = 0; queue < save_queue; ++queue) {
+            save_queue_test = 0;
+            VFOR (index_v) {
+              if (PARAMETER_RANGE_TOO_SMALL (index_v)) {
+                ++save_queue_test;
+              } else {
+                queue_v = index_v + queue * (LONG_INT) (*number_parameters);
+                if (fabs
+                    (current_generated_state->parameter[index_v] -
+                     save_queue_param[queue_v]) <=
+                    (OPTIONS->Queue_Resolution[index_v] + EPS_DOUBLE)) {
+                  ++save_queue_test;
+                }
+              }
+            }
+            if (save_queue_test == *number_parameters) {
+              tmp_var_db = save_queue_cost[queue];
+              *valid_state_generated_flag = save_queue_flag[queue];
+              queue_new = 0;
+              --(*number_generated);
+#if ASA_PRINT_MORE
+#if INT_LONG
+              fprintf (ptr_asa_out, "ASA_QUEUE: %ld \t %*.*g\n",
+                       OPTIONS->N_Generated,
+                       G_FIELD, G_PRECISION, tmp_var_db);
+#else
+              fprintf (ptr_asa_out, "ASA_QUEUE: %d \t %*.*g\n",
+                       OPTIONS->N_Generated,
+                       G_FIELD, G_PRECISION, tmp_var_db);
+#endif
+#endif
+              break;
+            }
+          }
+        }
+        if (queue_new == 1) {
+          tmp_var_db =
+            user_cost_function (current_generated_state->parameter,
+                                parameter_minimum,
+                                parameter_maximum,
+                                tangents,
+                                curvature,
+                                number_parameters,
+                                parameter_type,
+                                valid_state_generated_flag,
+                                exit_status, OPTIONS);
+          if (cost_function_test (tmp_var_db,
+                                  current_generated_state->parameter,
+                                  parameter_minimum,
+                                  parameter_maximum,
+                                  number_parameters,
+                                  xnumber_parameters) == 0) {
+            *exit_status = INVALID_COST_FUNCTION;
+            goto EXIT_ASA;
+          }
+          if (OPTIONS->Queue_Size > 0) {        /* in case recursive use */
+            VFOR (index_v) {
+              if (PARAMETER_RANGE_TOO_SMALL (index_v)) {
+                continue;
+              }
+              queue_v = index_v + save_queue_indx
+                * (LONG_INT) (*number_parameters);
+              save_queue_param[queue_v] =
+                current_generated_state->parameter[index_v];
+            }
+            save_queue_cost[save_queue_indx] = tmp_var_db;
+            save_queue_flag[save_queue_indx]
+              = *valid_state_generated_flag;
+
+            ++save_queue;
+            if (save_queue == (LONG_INT) OPTIONS->Queue_Size)
+              --save_queue;
+
+            ++save_queue_indx;
+            if (save_queue_indx == (LONG_INT) OPTIONS->Queue_Size)
+              save_queue_indx = 0;
+          }
+        }
+#else /* ASA_QUEUE */
+        tmp_var_db =
+          user_cost_function (current_generated_state->parameter,
+                              parameter_minimum,
+                              parameter_maximum,
+                              tangents,
+                              curvature,
+                              number_parameters,
+                              parameter_type,
+                              valid_state_generated_flag,
+                              exit_status, OPTIONS);
+        if (cost_function_test (tmp_var_db,
+                                current_generated_state->parameter,
+                                parameter_minimum,
+                                parameter_maximum, number_parameters,
+                                xnumber_parameters) == 0) {
+          *exit_status = INVALID_COST_FUNCTION;
+          goto EXIT_ASA;
+        }
+#endif /* ASA_QUEUE */
+        current_generated_state->cost = tmp_var_db;
+        ++repeated_invalid_states;
+        if (repeated_invalid_states > OPTIONS->Limit_Invalid_Generated_States) {
+          *exit_status = TOO_MANY_INVALID_STATES;
+          goto EXIT_ASA;
+        }
+      }
+      while (*valid_state_generated_flag == FALSE);
+      --(*number_invalid_generated_states);
+#if ASA_PARALLEL
+      gener_block_state[index_parallel].cost = current_generated_state->cost;
+#if USER_ACCEPTANCE_TEST
+      gener_block_state[index_parallel].par_user_accept_flag =
+        OPTIONS->User_Acceptance_Flag;
+      gener_block_state[index_parallel].par_cost_accept_flag =
+        OPTIONS->Cost_Acceptance_Flag;
+#endif
+      VFOR (index_v) {
+        /* ignore parameters with too small a range */
+        if (PARAMETER_RANGE_TOO_SMALL (index_v))
+          continue;
+        gener_block_state[index_parallel].parameter[index_v] =
+          current_generated_state->parameter[index_v];
+      }
+#if ASA_TEMPLATE_PARALLEL
+    }
+#endif /* ASA_TEMPLATE_PARALLEL */
+    /* *** EXIT CODE SPAWNING OFF PARALLEL GENERATED STATES *** */
+#endif /* ASA_PARALLEL */
+
+    /* ACCEPT/REJECT NEW PARAMETERS */
+
+#if ASA_PARALLEL
+    for (sort_index = 0; sort_index < OPTIONS->Gener_Block; ++sort_index)
+      parallel_sort[sort_index] = sort_index;
+    qsort (parallel_sort, OPTIONS->Gener_Block, sizeof (LONG_INT),
+           sort_parallel);
+
+    for (sort_index = 0; sort_index < OPTIONS->Gener_Block; ++sort_index) {
+      index_parallel = parallel_sort[sort_index];
+      current_generated_state->cost = gener_block_state[index_parallel].cost;
+#if USER_ACCEPTANCE_TEST
+      OPTIONS->User_Acceptance_Flag =
+        gener_block_state[index_parallel].par_user_accept_flag;
+      OPTIONS->Cost_Acceptance_Flag =
+        gener_block_state[index_parallel].par_cost_accept_flag;
+#endif
+      VFOR (index_v) {
+        /* ignore parameters with too small a range */
+        if (PARAMETER_RANGE_TOO_SMALL (index_v))
+          continue;
+        current_generated_state->parameter[index_v] =
+          gener_block_state[index_parallel].parameter[index_v];
+      }
+#endif /* ASA_PARALLEL */
+      /* decide to accept/reject the new state */
+      accept_new_state (user_random_generator,
+                        seed,
+                        parameter_minimum,
+                        parameter_maximum, current_cost_temperature,
+#if ASA_SAMPLE
+                        current_user_parameter_temp,
+#endif
+                        number_parameters,
+                        recent_number_acceptances,
+                        number_accepted,
+                        index_cost_acceptances,
+                        number_acceptances_saved,
+                        recent_number_generated,
+                        number_generated,
+                        index_parameter_generations,
+                        current_generated_state, last_saved_state,
+#if ASA_SAMPLE
+                        ptr_asa_out,
+#endif
+                        OPTIONS);
+
+#if ASA_PARALLEL
+#else
+#if ASA_PIPE_FILE
+#if INT_ALLOC
+      fprintf (ptr_asa_pipe, "%d", *number_generated);
+#else
+#if INT_LONG
+      fprintf (ptr_asa_pipe, "%ld", *number_generated);
+#else
+      fprintf (ptr_asa_pipe, "%d", *number_generated);
+#endif
+#endif
+#if INT_ALLOC
+      fprintf (ptr_asa_pipe, "\t%d", *number_accepted);
+#else
+#if INT_LONG
+      fprintf (ptr_asa_pipe, "\t%ld", *number_accepted);
+#else
+      fprintf (ptr_asa_pipe, "\t%d", *number_accepted);
+#endif
+#endif
+      fprintf (ptr_asa_pipe, "\t%g", best_generated_state->cost);
+      VFOR (index_v)
+        fprintf (ptr_asa_pipe, "\t%g",
+                 best_generated_state->parameter[index_v]);
+      fprintf (ptr_asa_pipe, "\t%g", *current_cost_temperature);
+      VFOR (index_v)
+        fprintf (ptr_asa_pipe, "\t%g", current_user_parameter_temp[index_v]);
+      fprintf (ptr_asa_pipe, "\t%g", last_saved_state->cost);
+      fprintf (ptr_asa_pipe, "\n");
+      fflush (ptr_asa_pipe);
+#endif /* ASA_PIPE_FILE */
+#if INCL_STDOUT
+#if ASA_PIPE
+#if INT_ALLOC
+      printf ("%d", *number_generated);
+#else
+#if INT_LONG
+      printf ("%ld", *number_generated);
+#else
+      printf ("%d", *number_generated);
+#endif
+#endif
+#if INT_ALLOC
+      printf ("\t%d", *number_accepted);
+#else
+#if INT_LONG
+      printf ("\t%ld", *number_accepted);
+#else
+      printf ("\t%d", *number_accepted);
+#endif
+#endif
+      printf ("\t%g", best_generated_state->cost);
+      VFOR (index_v)
+        printf ("\t%g", best_generated_state->parameter[index_v]);
+      printf ("\t%g", *current_cost_temperature);
+      VFOR (index_v)
+        printf ("\t%g", current_user_parameter_temp[index_v]);
+      printf ("\n");
+#endif /* ASA_PIPE */
+#endif /* INCL_STDOUT */
+#endif /* ASA_PARALLEL */
+
+      /* calculate the ratio of acceptances to generated states */
+      *accepted_to_generated_ratio =
+        (double) (*recent_number_acceptances + 1) /
+        (double) (*recent_number_generated + 1);
+
+#if MULTI_MIN
+      if (((OPTIONS->Multi_Specify == 0)
+           && (current_generated_state->cost <= best_generated_state->cost))
+          || ((OPTIONS->Multi_Specify == 1)
+              && (current_generated_state->cost <
+                  best_generated_state->cost))) {
+#if ASA_RESOLUTION
+        VFOR (index_v) {
+          if (OPTIONS->Multi_Grid[index_v] <
+              OPTIONS->Coarse_Resolution[index_v])
+            OPTIONS->Multi_Grid[index_v] =
+              OPTIONS->Coarse_Resolution[index_v];
+        }
+#endif /* ASA_RESOLUTION */
+        VFOR (index_v) {
+          if (OPTIONS->Multi_Grid[index_v] < EPS_DOUBLE)
+            OPTIONS->Multi_Grid[index_v] = EPS_DOUBLE;
+        }
+
+        multi_test = 0;
+        for (multi_index = 0; multi_index < OPTIONS->Multi_Number;
+             ++multi_index) {
+          multi_test_cmp = 0;
+          multi_test_dim = 0;
+          VFOR (index_v) {
+            if (PARAMETER_RANGE_TOO_SMALL (index_v))
+              continue;
+            ++multi_test_dim;
+            if (fabs (current_generated_state->parameter[index_v]
+                      - OPTIONS->Multi_Params[multi_index][index_v])
+                < OPTIONS->Multi_Grid[index_v])
+              ++multi_test_cmp;
+          }
+          if (multi_test_cmp == multi_test_dim)
+            multi_test = 1;
+          if (OPTIONS->Multi_Specify == 1)
+            break;
+        }
+
+        if (multi_test == 0) {
+          multi_cost[OPTIONS->Multi_Number] = current_generated_state->cost;
+          VFOR (index_v) {
+            multi_params[OPTIONS->Multi_Number][index_v] =
+              current_generated_state->parameter[index_v];
+          }
+          for (multi_index = 0; multi_index < OPTIONS->Multi_Number;
+               ++multi_index) {
+            multi_cost[multi_index] = OPTIONS->Multi_Cost[multi_index];
+            VFOR (index_v) {
+              multi_params[multi_index][index_v] =
+                OPTIONS->Multi_Params[multi_index][index_v];
+            }
+          }
+
+          qsort (multi_sort, OPTIONS->Multi_Number + 1, sizeof (int),
+                 multi_compare);
+          for (multi_index = 0; multi_index < OPTIONS->Multi_Number;
+               ++multi_index) {
+            OPTIONS->Multi_Cost[multi_index] =
+              multi_cost[multi_sort[multi_index]];
+            VFOR (index_v) {
+              OPTIONS->Multi_Params[multi_index][index_v] =
+                multi_params[multi_sort[multi_index]][index_v];
+            }
+          }
+        }
+      }
+#endif /* MULTI_MIN */
+
+      /* CHECK FOR NEW MINIMUM */
+
+      if (current_generated_state->cost < best_generated_state->cost) {
+        /* NEW MINIMUM FOUND */
+
+        OPTIONS->Locate_Cost = -1;
+
+        /* reset the recent acceptances and generated counts */
+#if ASA_PARALLEL
+        parallel_generated = *recent_number_generated;
+#endif
+        *recent_number_acceptances = *recent_number_generated = 0;
+        *best_number_generated_saved = *number_generated;
+        *best_number_accepted_saved = *number_accepted;
+        index_cost_repeat = 0;
+
+        /* copy the current state into the best_generated state */
+        best_generated_state->cost = current_generated_state->cost;
+        VFOR (index_v) {
+#if DROPPED_PARAMETERS
+          /* ignore parameters that have too small a range */
+          if (PARAMETER_RANGE_TOO_SMALL (index_v))
+            continue;
+#endif
+          best_generated_state->parameter[index_v] =
+            current_generated_state->parameter[index_v];
+        }
+
+        /* printout the new minimum state and value */
+#if ASA_PRINT
+        fprintf (ptr_asa_out,
+#if INT_LONG
+                 "best...->cost=%-*.*g  \
+*number_accepted=%ld  *number_generated=%ld\n", G_FIELD, G_PRECISION, best_generated_state->cost,
+#else
+                 "best...->cost=%-*.*g  \
+*number_accepted=%d  *number_generated=%d\n", G_FIELD, G_PRECISION, best_generated_state->cost,
+#endif /* INT_LONG */
+                 *number_accepted, *number_generated);
+#if ASA_PARALLEL
+        /* print OPTIONS->Gener_Block just used */
+        fprintf (ptr_asa_out,
+#if INT_LONG
+                 "OPTIONS->Gener_Block = %ld\n",
+#else
+                 "OPTIONS->Gener_Block = %d\n",
+#endif /* INT_LONG */
+                 OPTIONS->Gener_Block);
+#endif /* ASA_PARALLEL */
+#if ASA_PRINT_MORE
+#if INT_ALLOC
+        fprintf (ptr_asa_out, "Present Random Seed = %d\n\n", *seed);
+#else
+#if INT_LONG
+        fprintf (ptr_asa_out, "Present Random Seed = %ld\n\n", *seed);
+#else
+        fprintf (ptr_asa_out, "Present Random Seed = %d\n\n", *seed);
+#endif
+#endif
+        print_state (parameter_minimum,
+                     parameter_maximum,
+                     tangents,
+                     curvature,
+                     current_cost_temperature,
+                     current_user_parameter_temp,
+                     accepted_to_generated_ratio,
+                     number_parameters,
+                     curvature_flag,
+                     number_accepted,
+                     index_cost_acceptances,
+                     number_generated,
+                     number_invalid_generated_states,
+                     last_saved_state,
+                     best_generated_state, ptr_asa_out, OPTIONS);
+#endif /* ASA_PRINT_MORE */
+        fflush (ptr_asa_out);
+#endif /* ASA_PRINT */
+
+#if ASA_PARALLEL
+        /* leave index_parallel loop after new minimum */
+        break;
+#endif /* ASA_PARALLEL */
+      }
+#if ASA_PARALLEL
+    }
+#endif /* ASA_PARALLEL */
+
+#if ASA_PARALLEL
+    if (OPTIONS->Gener_Mov_Avr > 0) {
+      OPTIONS->Gener_Block = (LONG_INT)
+        ((((double) OPTIONS->Gener_Mov_Avr - ONE)
+          * (double) (OPTIONS->Gener_Block) + (double) parallel_generated)
+         / (double) (OPTIONS->Gener_Mov_Avr));
+      OPTIONS->Gener_Block = MIN (OPTIONS->Gener_Block, parallel_block_max);
+    }
+#endif /* ASA_PARALLEL */
+
+#if ASA_SAVE
+    /* These writes are put here with these tests, instead of just
+       after a new best state is found, to prevent any confusion with
+       any parallel code that might be added by users. */
+    if (*recent_number_acceptances == 0
+        && *recent_number_generated == 0
+        && *best_number_generated_saved == *number_generated
+        && *best_number_accepted_saved == *number_accepted
+        && OPTIONS->Asa_Recursive_Level == asa_recursive_max
+        && index_cost_repeat == 0) {
+      if (OPTIONS->Asa_Recursive_Level > 0)
+        sprintf (asa_save_comm, "asa_save_%d", OPTIONS->Asa_Recursive_Level);
+      else
+        sprintf (asa_save_comm, "asa_save");
+      ptr_save = fopen (asa_save_comm, "w");
+
+      fwrite (number_parameters, sizeof (ALLOC_INT), 1, ptr_save);
+      fwrite (xnumber_parameters, sizeof (double), 1, ptr_save);
+      fwrite (parameter_minimum, sizeof (double),
+              *number_parameters, ptr_save);
+      fwrite (parameter_maximum, sizeof (double),
+              *number_parameters, ptr_save);
+      fwrite (tangents, sizeof (double), *number_parameters, ptr_save);
+      fwrite (current_user_parameter_temp, sizeof (double),
+              *number_parameters, ptr_save);
+      fwrite (initial_user_parameter_temp, sizeof (double),
+              *number_parameters, ptr_save);
+      fwrite (temperature_scale_parameters, sizeof (double),
+              *number_parameters, ptr_save);
+
+      fwrite (parameter_type, sizeof (int), *number_parameters, ptr_save);
+      fwrite (&index_cost_repeat, sizeof (int), 1, ptr_save);
+      fwrite (&asa_open, sizeof (int), 1, ptr_save);
+      fwrite (&number_asa_open, sizeof (int), 1, ptr_save);
+      fwrite (&recursive_asa_open, sizeof (int), 1, ptr_save);
+
+      fwrite (current_cost_temperature, sizeof (double), 1, ptr_save);
+      fwrite (initial_cost_temperature, sizeof (double), 1, ptr_save);
+      fwrite (temperature_scale_cost, sizeof (double), 1, ptr_save);
+      fwrite (accepted_to_generated_ratio, sizeof (double), 1, ptr_save);
+
+      fwrite (curvature_flag, sizeof (int), 1, ptr_save);
+
+      fwrite (seed, sizeof (LONG_INT), 1, ptr_save);
+      fwrite (number_generated, sizeof (LONG_INT), 1, ptr_save);
+      fwrite (number_accepted, sizeof (LONG_INT), 1, ptr_save);
+      fwrite (number_acceptances_saved, sizeof (LONG_INT), 1, ptr_save);
+      fwrite (recent_number_acceptances, sizeof (LONG_INT), 1, ptr_save);
+      fwrite (recent_number_generated, sizeof (LONG_INT), 1, ptr_save);
+      fwrite (number_invalid_generated_states, sizeof (LONG_INT),
+              1, ptr_save);
+      fwrite (index_cost_acceptances, sizeof (LONG_INT), 1, ptr_save);
+      fwrite (best_number_generated_saved, sizeof (LONG_INT), 1, ptr_save);
+      fwrite (best_number_accepted_saved, sizeof (LONG_INT), 1, ptr_save);
+
+      fwrite (index_parameter_generations, sizeof (LONG_INT),
+              *number_parameters, ptr_save);
+
+      fwrite (current_generated_state->parameter,
+              sizeof (double), *number_parameters, ptr_save);
+      fwrite (last_saved_state->parameter,
+              sizeof (double), *number_parameters, ptr_save);
+      fwrite (best_generated_state->parameter,
+              sizeof (double), *number_parameters, ptr_save);
+      fwrite (&(current_generated_state->cost), sizeof (double), 1, ptr_save);
+      fwrite (&(last_saved_state->cost), sizeof (double), 1, ptr_save);
+      fwrite (&(best_generated_state->cost), sizeof (double), 1, ptr_save);
+
+      fwrite (&(OPTIONS->Limit_Acceptances), sizeof (LONG_INT), 1, ptr_save);
+      fwrite (&(OPTIONS->Limit_Generated), sizeof (LONG_INT), 1, ptr_save);
+      fwrite (&(OPTIONS->Limit_Invalid_Generated_States), sizeof (int),
+              1, ptr_save);
+      fwrite (&(OPTIONS->Accepted_To_Generated_Ratio), sizeof (double),
+              1, ptr_save);
+      fwrite (&(OPTIONS->Cost_Precision), sizeof (double), 1, ptr_save);
+      fwrite (&(OPTIONS->Maximum_Cost_Repeat), sizeof (int), 1, ptr_save);
+      fwrite (&(OPTIONS->Number_Cost_Samples), sizeof (int), 1, ptr_save);
+      fwrite (&(OPTIONS->Temperature_Ratio_Scale), sizeof (double),
+              1, ptr_save);
+      fwrite (&(OPTIONS->Cost_Parameter_Scale_Ratio), sizeof (double),
+              1, ptr_save);
+      fwrite (&(OPTIONS->Temperature_Anneal_Scale), sizeof (double),
+              1, ptr_save);
+      fwrite (&(OPTIONS->Include_Integer_Parameters), sizeof (int),
+              1, ptr_save);
+      fwrite (&(OPTIONS->User_Initial_Parameters), sizeof (int), 1, ptr_save);
+      fwrite (&(OPTIONS->Sequential_Parameters), sizeof (ALLOC_INT), 1,
+              ptr_save);
+      fwrite (&(OPTIONS->Initial_Parameter_Temperature), sizeof (double), 1,
+              ptr_save);
+      fwrite (&(OPTIONS->Acceptance_Frequency_Modulus), sizeof (int), 1,
+              ptr_save);
+      fwrite (&(OPTIONS->Generated_Frequency_Modulus), sizeof (int), 1,
+              ptr_save);
+      fwrite (&(OPTIONS->Reanneal_Cost), sizeof (int), 1, ptr_save);
+      fwrite (&(OPTIONS->Reanneal_Parameters), sizeof (int), 1, ptr_save);
+      fwrite (&(OPTIONS->Delta_X), sizeof (double), 1, ptr_save);
+      fwrite (&(OPTIONS->User_Tangents), sizeof (int), 1, ptr_save);
+
+#if USER_INITIAL_COST_TEMP
+      fwrite (&(OPTIONS->User_Cost_Temperature), sizeof (double),
+              1, ptr_save);
+#endif
+#if RATIO_TEMPERATURE_SCALES
+      fwrite (OPTIONS->User_Temperature_Ratio, sizeof (double),
+              *number_parameters, ptr_save);
+#endif
+#if USER_INITIAL_PARAMETERS_TEMPS
+      fwrite (OPTIONS->User_Parameter_Temperature, sizeof (double),
+              *number_parameters, ptr_save);
+#endif
+#if DELTA_PARAMETERS
+      fwrite (OPTIONS->User_Delta_Parameter, sizeof (double),
+              *number_parameters, ptr_save);
+#endif
+#if QUENCH_PARAMETERS
+      fwrite (OPTIONS->User_Quench_Param_Scale, sizeof (double),
+              *number_parameters, ptr_save);
+#endif
+#if QUENCH_COST
+      fwrite (OPTIONS->User_Quench_Cost_Scale, sizeof (double), 1, ptr_save);
+#endif
+      fwrite (&(OPTIONS->N_Accepted), sizeof (LONG_INT), 1, ptr_save);
+      fwrite (&(OPTIONS->N_Generated), sizeof (LONG_INT), 1, ptr_save);
+      fwrite (&(OPTIONS->Locate_Cost), sizeof (int), 1, ptr_save);
+      fwrite (&(OPTIONS->Immediate_Exit), sizeof (int), 1, ptr_save);
+#if OPTIONAL_DATA_DBL
+      fwrite (&(OPTIONS->Asa_Data_Dim_Dbl), sizeof (ALLOC_INT), 1, ptr_save);
+      fwrite (OPTIONS->Asa_Data_Dbl, sizeof (double),
+              OPTIONS->Asa_Data_Dim_Dbl, ptr_save);
+#endif
+      fwrite (&(OPTIONS->Random_Array_Dim), sizeof (ALLOC_INT), 1, ptr_save);
+      fwrite (OPTIONS->Random_Array, sizeof (double),
+              OPTIONS->Random_Array_Dim, ptr_save);
+      fwrite (&(OPTIONS->Asa_Recursive_Level), sizeof (int), 1, ptr_save);
+#if OPTIONAL_DATA_INT
+      fwrite (&(OPTIONS->Asa_Data_Dim_Int), sizeof (ALLOC_INT), 1, ptr_save);
+      fwrite (OPTIONS->Asa_Data_Int, sizeof (LONG_INT),
+              OPTIONS->Asa_Data_Dim_Int, ptr_save);
+#endif
+#if OPTIONAL_DATA_PTR
+      fwrite (&(OPTIONS->Asa_Data_Dim_Ptr), sizeof (ALLOC_INT), 1, ptr_save);
+      if (OPTIONS->Asa_Recursive_Level == 0)
+        fwrite (OPTIONS->Asa_Data_Ptr, sizeof (OPTIONAL_PTR_TYPE),
+                OPTIONS->Asa_Data_Dim_Ptr, ptr_save);
+#if ASA_TEMPLATE_SELFOPT
+      if (OPTIONS->Asa_Recursive_Level == 1)
+        fwrite (OPTIONS->Asa_Data_Ptr, sizeof (RECUR_OPTIONAL_PTR_TYPE),
+                OPTIONS->Asa_Data_Dim_Ptr, ptr_save);
+#endif
+#endif
+#if USER_ASA_OUT
+      fwrite (OPTIONS->Asa_Out_File, sizeof (char), 1, ptr_save);
+#endif
+#if USER_COST_SCHEDULE
+      fwrite (&(OPTIONS->Cost_Schedule), sizeof (char), 1, ptr_save);
+#endif
+#if USER_ACCEPT_ASYMP_EXP
+      fwrite (&(OPTIONS->Asymp_Exp_Param), sizeof (double), 1, ptr_save);
+#endif
+#if USER_ACCEPTANCE_TEST
+      fwrite (&(OPTIONS->Acceptance_Test), sizeof (char), 1, ptr_save);
+      fwrite (&(OPTIONS->User_Acceptance_Flag), sizeof (int), 1, ptr_save);
+      fwrite (&(OPTIONS->Cost_Acceptance_Flag), sizeof (int), 1, ptr_save);
+      fwrite (&(OPTIONS->Cost_Temp_Curr), sizeof (double), 1, ptr_save);
+      fwrite (&(OPTIONS->Cost_Temp_Init), sizeof (double), 1, ptr_save);
+      fwrite (&(OPTIONS->Cost_Temp_Scale), sizeof (double), 1, ptr_save);
+#endif
+#if USER_GENERATING_FUNCTION
+      fwrite (&(OPTIONS->Generating_Distrib), sizeof (char), 1, ptr_save);
+#endif
+#if USER_REANNEAL_COST
+      fwrite (&(OPTIONS->Reanneal_Cost_Function), sizeof (char), 1, ptr_save);
+#endif
+#if USER_REANNEAL_PARAMETERS
+      fwrite (&(OPTIONS->Reanneal_Params_Function), sizeof (char),
+              1, ptr_save);
+#endif
+#if ASA_SAMPLE
+      fwrite (&(OPTIONS->Bias_Acceptance), sizeof (double), 1, ptr_save);
+      fwrite (OPTIONS->Bias_Generated, sizeof (double),
+              *number_parameters, ptr_save);
+      fwrite (&(OPTIONS->Average_Weights), sizeof (double), 1, ptr_save);
+      fwrite (&(OPTIONS->Limit_Weights), sizeof (double), 1, ptr_save);
+#endif
+#if ASA_QUEUE
+      fwrite (save_queue, sizeof (LONG_INT), 1, ptr_save);
+      fwrite (save_queue_indx, sizeof (LONG_INT), 1, ptr_save);
+      fwrite (&(OPTIONS->Queue_Size), sizeof (ALLOC_INT), 1, ptr_save);
+      fwrite (save_queue_flag, sizeof (int), save_queue, ptr_save);
+      fwrite (save_queue_cost, sizeof (double), save_queue, ptr_save);
+      fwrite (save_queue_param, sizeof (double),
+              (*number_parameters) * (OPTIONS->Queue_Size), ptr_save);
+#if ASA_RESOLUTION
+#else
+      fwrite (OPTIONS->Queue_Resolution, sizeof (double),
+              *number_parameters, ptr_save);
+#endif
+#endif
+#if ASA_RESOLUTION
+      fwrite (OPTIONS->Coarse_Resolution, sizeof (double),
+              *number_parameters, ptr_save);
+#endif
+#if FITLOC
+      fwrite (&(OPTIONS->Fit_Local), sizeof (int), 1, ptr_save);
+      fwrite (&(OPTIONS->Iter_Max), sizeof (int), 1, ptr_save);
+      fwrite (&(OPTIONS->Penalty), sizeof (double), 1, ptr_save);
+#endif
+#if MULTI_MIN
+      fwrite (OPTIONS->Multi_Number, sizeof (int), 1, ptr_save);
+      fwrite (OPTIONS->Multi_Grid,
+              sizeof (double), *number_parameters, ptr_save);
+      fwrite (&(OPTIONS->Multi_Specify), sizeof (int), 1, ptr_save);
+      for (multi_index = 0; multi_index < OPTIONS->Multi_Number;
+           ++multi_index) {
+        fwrite (&(OPTIONS->Multi_Cost[multi_index]), sizeof (double), 1,
+                ptr_save);
+        fwrite (&(OPTIONS->Multi_Params[multi_index]), sizeof (double),
+                *number_parameters, ptr_save);
+      }
+#endif
+#if ASA_PARALLEL
+      fwrite (&parallel_generated, sizeof (LONG_INT), 1, ptr_save);
+      fwrite (&parallel_block_max, sizeof (LONG_INT), 1, ptr_save);
+      for (index_parallel = 0; index_parallel < parallel_block_max;
+           ++index_parallel) {
+        fwrite (gener_block_state[index_parallel].parameter,
+                sizeof (double), *number_parameters, ptr_save);
+        fwrite (&(gener_block_state[index_parallel].cost),
+                sizeof (double), 1, ptr_save);
+#if USER_ACCEPTANCE_TEST
+        fwrite (&
+                (gener_block_state[index_parallel].
+                 par_user_accept_flag), sizeof (int), 1, ptr_save);
+        fwrite (&
+                (gener_block_state[index_parallel].
+                 par_cost_accept_flag), sizeof (int), 1, ptr_save);
+#endif
+      }
+      fwrite (&(OPTIONS->Gener_Mov_Avr), sizeof (int), 1, ptr_save);
+      fwrite (&(OPTIONS->Gener_Block), sizeof (LONG_INT), 1, ptr_save);
+      fwrite (&(OPTIONS->Gener_Block_Max), sizeof (LONG_INT), 1, ptr_save);
+#endif
+
+      fclose (ptr_save);
+
+    SAVED_ASA:
+      ;
+
+#if SYSTEM_CALL
+#if ASA_SAVE_BACKUP
+#if INT_LONG
+      if (OPTIONS->Asa_Recursive_Level > 0)
+        sprintf (asa_save_comm, "/bin/cp asa_save_%d asa_save_%d.%ld",
+                 OPTIONS->Asa_Recursive_Level,
+                 OPTIONS->Asa_Recursive_Level, OPTIONS->N_Accepted);
+      else
+        sprintf (asa_save_comm, "/bin/cp asa_save asa_save.%ld",
+                 OPTIONS->N_Accepted);
+#else
+      if (OPTIONS->Asa_Recursive_Level > 0)
+        sprintf (asa_save_comm, "/bin/cp asa_save_%d asa_save_%d.%d",
+                 OPTIONS->Asa_Recursive_Level,
+                 OPTIONS->Asa_Recursive_Level, OPTIONS->N_Accepted);
+      else
+        sprintf (asa_save_comm, "/bin/cp asa_save asa_save.%d",
+                 OPTIONS->N_Accepted);
+#endif
+      ptr_comm = popen (asa_save_comm, "r");
+      pclose (ptr_comm);
+#else /* ASA_SAVE_BACKUP */
+      /* extra protection in case run aborts during write */
+      if (OPTIONS->Asa_Recursive_Level > 0)
+        sprintf (asa_save_comm, "/bin/cp asa_save_%d asa_save_%d.old",
+                 OPTIONS->Asa_Recursive_Level, OPTIONS->Asa_Recursive_Level);
+      else
+        sprintf (asa_save_comm, "/bin/cp asa_save asa_save.old");
+      ptr_comm = popen (asa_save_comm, "r");
+      pclose (ptr_comm);
+#endif /* ASA_SAVE_BACKUP */
+#endif /* SYSTEM_CALL */
+    }
+#endif /* ASA_SAVE */
+
+    if (OPTIONS->Immediate_Exit == TRUE) {
+      *exit_status = IMMEDIATE_EXIT;
+      goto EXIT_ASA;
+    }
+
+    /* PERIODIC TESTING/REANNEALING/PRINTING SECTION */
+
+    if (OPTIONS->Acceptance_Frequency_Modulus == 0)
+      tmp_var_int1 = FALSE;
+    else if ((int) (*number_accepted %
+                    ((LONG_INT) OPTIONS->Acceptance_Frequency_Modulus)) == 0
+             && *number_acceptances_saved == *number_accepted)
+      tmp_var_int1 = TRUE;
+    else
+      tmp_var_int1 = FALSE;
+
+    if (OPTIONS->Generated_Frequency_Modulus == 0)
+      tmp_var_int2 = FALSE;
+    else if ((int) (*number_generated %
+                    ((LONG_INT) OPTIONS->Generated_Frequency_Modulus)) == 0)
+      tmp_var_int2 = TRUE;
+    else
+      tmp_var_int2 = FALSE;
+
+    if (tmp_var_int1 == TRUE || tmp_var_int2 == TRUE
+        || (*accepted_to_generated_ratio
+            < OPTIONS->Accepted_To_Generated_Ratio)) {
+      if (*accepted_to_generated_ratio
+          < (OPTIONS->Accepted_To_Generated_Ratio))
+        *recent_number_acceptances = *recent_number_generated = 0;
+
+      /* if best.cost repeats OPTIONS->Maximum_Cost_Repeat then exit */
+      if (OPTIONS->Maximum_Cost_Repeat != 0) {
+        if (fabs (last_saved_state->cost - best_generated_state->cost)
+            < OPTIONS->Cost_Precision) {
+          ++index_cost_repeat;
+          if (index_cost_repeat == (OPTIONS->Maximum_Cost_Repeat)) {
+            *exit_status = COST_REPEATING;
+            goto EXIT_ASA;
+          }
+        } else {
+          index_cost_repeat = 0;
+        }
+      }
+
+      if (OPTIONS->Reanneal_Parameters == TRUE) {
+        OPTIONS->Locate_Cost = 3;       /* reanneal parameters */
+
+        /* calculate tangents, not curvatures, to reanneal */
+        *curvature_flag = FALSE;
+        cost_derivatives (user_cost_function,
+                          parameter_minimum,
+                          parameter_maximum,
+                          tangents,
+                          curvature,
+                          maximum_tangent,
+                          number_parameters,
+                          parameter_type,
+                          exit_status,
+                          curvature_flag,
+                          valid_state_generated_flag,
+                          number_invalid_generated_states,
+                          current_generated_state,
+                          best_generated_state, ptr_asa_out, OPTIONS);
+        if (*exit_status == INVALID_COST_FUNCTION_DERIV) {
+          goto EXIT_ASA;
+        }
+      }
+#if USER_REANNEAL_COST
+#else
+      if (OPTIONS->Reanneal_Cost == 0 || OPTIONS->Reanneal_Cost == 1) {
+        ;
+      } else {
+        immediate_flag = OPTIONS->Immediate_Exit;
+
+        if (OPTIONS->Reanneal_Cost < -1) {
+          tmp_var_int = -OPTIONS->Reanneal_Cost;
+        } else {
+          tmp_var_int = OPTIONS->Reanneal_Cost;
+        }
+        tmp_var_db1 = ZERO;
+        tmp_var_db2 = ZERO;
+
+        for (index_cost_constraint = 0;
+             index_cost_constraint < tmp_var_int; ++index_cost_constraint) {
+          OPTIONS->Locate_Cost = 4;     /* reanneal cost */
+
+          *number_invalid_generated_states = 0;
+          repeated_invalid_states = 0;
+          OPTIONS->Sequential_Parameters = *start_sequence - 1;
+          do {
+            ++(*number_invalid_generated_states);
+            generate_new_state (user_random_generator,
+                                seed,
+                                parameter_minimum,
+                                parameter_maximum,
+                                current_user_parameter_temp,
+#if USER_GENERATING_FUNCTION
+                                initial_user_parameter_temp,
+                                temperature_scale_parameters,
+#endif
+                                number_parameters,
+                                parameter_type,
+                                current_generated_state,
+                                last_saved_state, OPTIONS);
+            *valid_state_generated_flag = TRUE;
+#if USER_ACCEPTANCE_TEST
+            OPTIONS->User_Acceptance_Flag = TRUE;
+            OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+
+#if ASA_QUEUE
+            if (OPTIONS->Queue_Size == 0) {
+              queue_new = 1;
+            } else {
+              queue_new = 1;
+              for (queue = 0; queue < save_queue; ++queue) {
+                save_queue_test = 0;
+                VFOR (index_v) {
+                  if (PARAMETER_RANGE_TOO_SMALL (index_v)) {
+                    ++save_queue_test;
+                  } else {
+                    queue_v = index_v + queue
+                      * (LONG_INT) (*number_parameters);
+                    if (fabs
+                        (current_generated_state->
+                         parameter[index_v] -
+                         save_queue_param[queue_v]) <
+                        (OPTIONS->Queue_Resolution[index_v] + EPS_DOUBLE)) {
+                      ++save_queue_test;
+                    }
+                  }
+                }
+                if (save_queue_test == *number_parameters) {
+                  tmp_var_db = save_queue_cost[queue];
+                  *valid_state_generated_flag = save_queue_flag[queue];
+                  queue_new = 0;
+#if ASA_PRINT_MORE
+#if INT_LONG
+                  fprintf (ptr_asa_out,
+                           "ASA_QUEUE: %ld \t %*.*g\n",
+                           OPTIONS->N_Generated, G_FIELD,
+                           G_PRECISION, tmp_var_db);
+#else
+                  fprintf (ptr_asa_out,
+                           "ASA_QUEUE: %d \t %*.*g\n",
+                           OPTIONS->N_Generated, G_FIELD,
+                           G_PRECISION, tmp_var_db);
+#endif
+#endif
+                  break;
+                }
+              }
+            }
+            if (queue_new == 1) {
+              tmp_var_db =
+                user_cost_function (current_generated_state->
+                                    parameter, parameter_minimum,
+                                    parameter_maximum, tangents,
+                                    curvature, number_parameters,
+                                    parameter_type,
+                                    valid_state_generated_flag,
+                                    exit_status, OPTIONS);
+              if (cost_function_test
+                  (tmp_var_db, current_generated_state->parameter,
+                   parameter_minimum, parameter_maximum,
+                   number_parameters, xnumber_parameters) == 0) {
+                *exit_status = INVALID_COST_FUNCTION;
+                goto EXIT_ASA;
+              }
+              if (OPTIONS->Queue_Size > 0) {
+                VFOR (index_v) {
+                  if (PARAMETER_RANGE_TOO_SMALL (index_v)) {
+                    continue;
+                  }
+                  queue_v = index_v + save_queue
+                    * (LONG_INT) (*number_parameters);
+                  save_queue_param[queue_v] =
+                    current_generated_state->parameter[index_v];
+                }
+                save_queue_cost[save_queue] = tmp_var_db;
+                save_queue_flag[save_queue]
+                  = *valid_state_generated_flag;
+
+                ++save_queue;
+                if (save_queue == (LONG_INT) OPTIONS->Queue_Size)
+                  --save_queue;
+
+                ++save_queue_indx;
+                if (save_queue_indx == (LONG_INT) OPTIONS->Queue_Size)
+                  save_queue_indx = 0;
+              }
+            }
+#else /* ASA_QUEUE */
+            tmp_var_db =
+              user_cost_function (current_generated_state->
+                                  parameter, parameter_minimum,
+                                  parameter_maximum, tangents,
+                                  curvature, number_parameters,
+                                  parameter_type,
+                                  valid_state_generated_flag,
+                                  exit_status, OPTIONS);
+            if (cost_function_test
+                (tmp_var_db, current_generated_state->parameter,
+                 parameter_minimum, parameter_maximum,
+                 number_parameters, xnumber_parameters) == 0) {
+              *exit_status = INVALID_COST_FUNCTION;
+              goto EXIT_ASA;
+            }
+#endif /* ASA_QUEUE */
+            ++repeated_invalid_states;
+            if (repeated_invalid_states >
+                OPTIONS->Limit_Invalid_Generated_States) {
+              *exit_status = TOO_MANY_INVALID_STATES;
+              goto EXIT_ASA;
+            }
+          }
+          while (*valid_state_generated_flag == FALSE);
+          --(*number_invalid_generated_states);
+
+          tmp_var_db1 += tmp_var_db;
+          tmp_var_db2 += (tmp_var_db * tmp_var_db);
+        }
+        tmp_var_db1 /= (double) tmp_var_int;
+        tmp_var_db2 /= (double) tmp_var_int;
+        tmp_var_db =
+          sqrt (fabs
+                ((tmp_var_db2 -
+                  tmp_var_db1 * tmp_var_db1) * ((double) tmp_var_int /
+                                                ((double) tmp_var_int -
+                                                 ONE))));
+        if (OPTIONS->Reanneal_Cost < -1) {
+          *current_cost_temperature = *initial_cost_temperature =
+            tmp_var_db + (double) EPS_DOUBLE;
+        } else {
+          *initial_cost_temperature = tmp_var_db + (double) EPS_DOUBLE;
+        }
+        OPTIONS->Immediate_Exit = immediate_flag;
+      }
+#endif /* USER_REANNEAL_COST */
+
+      reanneal (parameter_minimum,
+                parameter_maximum,
+                tangents,
+                maximum_tangent,
+                current_cost_temperature,
+                initial_cost_temperature,
+                temperature_scale_cost,
+                current_user_parameter_temp,
+                initial_user_parameter_temp,
+                temperature_scale_parameters,
+                number_parameters,
+                parameter_type,
+                index_cost_acceptances,
+                index_parameter_generations,
+                last_saved_state, best_generated_state, OPTIONS);
+#if ASA_PRINT_INTERMED
+#if ASA_PRINT
+      print_state (parameter_minimum,
+                   parameter_maximum,
+                   tangents,
+                   curvature,
+                   current_cost_temperature,
+                   current_user_parameter_temp,
+                   accepted_to_generated_ratio,
+                   number_parameters,
+                   curvature_flag,
+                   number_accepted,
+                   index_cost_acceptances,
+                   number_generated,
+                   number_invalid_generated_states,
+                   last_saved_state,
+                   best_generated_state, ptr_asa_out, OPTIONS);
+
+      fprintf (ptr_asa_out, "\n");
+      fflush (ptr_asa_out);
+#endif
+#endif
+    }
+  }
+
+  /* FINISHED ANNEALING and MINIMIZATION */
+
+  *exit_status = NORMAL_EXIT;
+EXIT_ASA:
+
+  asa_exit_value = asa_exit (user_cost_function,
+                             &final_cost,
+                             parameter_initial_final,
+                             parameter_minimum,
+                             parameter_maximum,
+                             tangents,
+                             curvature,
+                             maximum_tangent,
+                             current_cost_temperature,
+                             initial_user_parameter_temp,
+                             current_user_parameter_temp,
+                             accepted_to_generated_ratio,
+                             number_parameters,
+                             parameter_type,
+                             valid_state_generated_flag,
+                             exit_status,
+                             index_exit_v,
+                             start_sequence,
+                             number_accepted,
+                             best_number_accepted_saved,
+                             index_cost_acceptances,
+                             number_generated,
+                             number_invalid_generated_states,
+                             index_parameter_generations,
+                             best_number_generated_saved,
+                             current_generated_state,
+                             last_saved_state,
+                             best_generated_state, ptr_asa_out, OPTIONS);
+  if (asa_exit_value == 9) {
+    *exit_status = CALLOC_FAILED;
+    return (-1);
+  }
+
+  free (curvature_flag);
+  free (maximum_tangent);
+  free (accepted_to_generated_ratio);
+  free (temperature_scale_cost);
+  free (current_cost_temperature);
+  free (initial_cost_temperature);
+  free (number_generated);
+  free (best_number_generated_saved);
+  free (recent_number_generated);
+  free (number_accepted);
+  free (recent_number_acceptances);
+  free (index_cost_acceptances);
+  free (number_acceptances_saved);
+  free (best_number_accepted_saved);
+  free (number_invalid_generated_states);
+  free (current_generated_state->parameter);
+  free (last_saved_state->parameter);
+  free (best_generated_state->parameter);
+  free (current_generated_state);
+  free (last_saved_state);
+  free (best_generated_state);
+#if ASA_QUEUE
+  free (save_queue_flag);
+  free (save_queue_cost);
+  free (save_queue_param);
+#endif
+#if MULTI_MIN
+  for (multi_index = 0; multi_index <= OPTIONS->Multi_Number; ++multi_index)
+    free (multi_params[multi_index]);
+  free (multi_params);
+  free (multi_sort);
+  free (multi_cost);
+#endif
+#if ASA_PARALLEL
+  for (index_parallel = 0; index_parallel < parallel_block_max;
+       ++index_parallel) {
+    free (gener_block_state[index_parallel].parameter);
+  }
+  free (gener_block_state);
+  free (parallel_sort);
+#endif
+#if ASA_PIPE_FILE
+  fclose (ptr_asa_pipe);
+#endif
+  free (initial_user_parameter_temp);
+  free (index_exit_v);
+  free (start_sequence);
+  free (index_parameter_generations);
+  free (current_user_parameter_temp);
+  free (temperature_scale_parameters);
+  if (recursive_asa_open == 0)
+    asa_open = FALSE;
+  return (final_cost);
+}
+
+/***********************************************************************
+* asa_exit
+*	This procedures copies the best parameters and cost into
+*       final_cost and parameter_initial_final
+***********************************************************************/
+#if HAVE_ANSI
+int
+asa_exit (double (*user_cost_function)
+
+           
+          (double *, double *, double *, double *, double *, ALLOC_INT *,
+           int *, int *, int *, USER_DEFINES *), double *final_cost,
+          double *parameter_initial_final, double *parameter_minimum,
+          double *parameter_maximum, double *tangents, double *curvature,
+          double *maximum_tangent, double *current_cost_temperature,
+          double *initial_user_parameter_temp,
+          double *current_user_parameter_temp,
+          double *accepted_to_generated_ratio,
+          ALLOC_INT * number_parameters, int *parameter_type,
+          int *valid_state_generated_flag, int *exit_status,
+          ALLOC_INT * index_exit_v, ALLOC_INT * start_sequence,
+          LONG_INT * number_accepted,
+          LONG_INT * best_number_accepted_saved,
+          LONG_INT * index_cost_acceptances, LONG_INT * number_generated,
+          LONG_INT * number_invalid_generated_states,
+          LONG_INT * index_parameter_generations,
+          LONG_INT * best_number_generated_saved,
+          STATE * current_generated_state, STATE * last_saved_state,
+          STATE * best_generated_state, FILE * ptr_asa_out,
+          USER_DEFINES * OPTIONS)
+#else
+int
+
+asa_exit (user_cost_function,
+          final_cost,
+          parameter_initial_final,
+          parameter_minimum,
+          parameter_maximum,
+          tangents,
+          curvature,
+          maximum_tangent,
+          current_cost_temperature,
+          initial_user_parameter_temp,
+          current_user_parameter_temp,
+          accepted_to_generated_ratio,
+          number_parameters,
+          parameter_type,
+          valid_state_generated_flag,
+          exit_status,
+          index_exit_v,
+          start_sequence,
+          number_accepted,
+          best_number_accepted_saved,
+          index_cost_acceptances,
+          number_generated,
+          number_invalid_generated_states,
+          index_parameter_generations,
+          best_number_generated_saved,
+          current_generated_state,
+          last_saved_state, best_generated_state, ptr_asa_out, OPTIONS)
+     double (*user_cost_function) ();
+     double *final_cost;
+     double *parameter_initial_final;
+     double *parameter_minimum;
+     double *parameter_maximum;
+     double *tangents;
+     double *curvature;
+     double *maximum_tangent;
+     double *current_cost_temperature;
+     double *initial_user_parameter_temp;
+     double *current_user_parameter_temp;
+     double *accepted_to_generated_ratio;
+     ALLOC_INT *number_parameters;
+     int *parameter_type;
+     int *valid_state_generated_flag;
+     int *exit_status;
+     ALLOC_INT *index_exit_v;
+     ALLOC_INT *start_sequence;
+     LONG_INT *number_accepted;
+     LONG_INT *best_number_accepted_saved;
+     LONG_INT *index_cost_acceptances;
+     LONG_INT *number_generated;
+     LONG_INT *number_invalid_generated_states;
+     LONG_INT *index_parameter_generations;
+     LONG_INT *best_number_generated_saved;
+     STATE *current_generated_state;
+     STATE *last_saved_state;
+     STATE *best_generated_state;
+     FILE *ptr_asa_out;
+     USER_DEFINES *OPTIONS;
+#endif
+{
+  ALLOC_INT index_v;            /* iteration index */
+  int curvatureFlag;
+  int exit_exit_status, tmp_locate;
+#if MULTI_MIN
+  int multi_index;
+#endif
+
+  tmp_locate = OPTIONS->Locate_Cost;
+
+  /* return final function minimum and associated parameters */
+  *final_cost = best_generated_state->cost;
+  VFOR (index_v) {
+    parameter_initial_final[index_v] =
+      best_generated_state->parameter[index_v];
+  }
+
+  OPTIONS->N_Accepted = *best_number_accepted_saved;
+  OPTIONS->N_Generated = *best_number_generated_saved;
+
+#if MULTI_MIN
+  for (multi_index = 0; multi_index < OPTIONS->Multi_Number; ++multi_index) {
+    best_generated_state->cost = OPTIONS->Multi_Cost[multi_index];
+    VFOR (index_v) {
+      best_generated_state->parameter[index_v] =
+        OPTIONS->Multi_Params[multi_index][index_v];
+    }
+#if ASA_PRINT
+    fprintf (ptr_asa_out, "\n\t\t multi_index = %d\n", multi_index);
+#endif /* ASA_PRINT */
+#endif /* MULTI_MIN */
+    if (*exit_status != TOO_MANY_INVALID_STATES
+        && *exit_status != IMMEDIATE_EXIT
+        && *exit_status != INVALID_USER_INPUT
+        && *exit_status != INVALID_COST_FUNCTION
+        && *exit_status != INVALID_COST_FUNCTION_DERIV) {
+      if (OPTIONS->Curvature_0 != TRUE)
+        OPTIONS->Locate_Cost = 5;       /* calc curvatures while exiting asa */
+
+      /* calculate curvatures and tangents at best point */
+      curvatureFlag = TRUE;
+      cost_derivatives (user_cost_function,
+                        parameter_minimum,
+                        parameter_maximum,
+                        tangents,
+                        curvature,
+                        maximum_tangent,
+                        number_parameters,
+                        parameter_type,
+                        &exit_exit_status,
+                        &curvatureFlag,
+                        valid_state_generated_flag,
+                        number_invalid_generated_states,
+                        current_generated_state,
+                        best_generated_state, ptr_asa_out, OPTIONS);
+    }
+#if ASA_PRINT
+    if (exit_exit_status == INVALID_COST_FUNCTION_DERIV)
+      fprintf (ptr_asa_out, "\n\n  in asa_exit: INVALID_COST_FUNCTION_DERIV");
+
+    if (*exit_status != INVALID_USER_INPUT
+        && *exit_status != INVALID_COST_FUNCTION
+        && *exit_status != INVALID_COST_FUNCTION_DERIV)
+      print_state (parameter_minimum,
+                   parameter_maximum,
+                   tangents,
+                   curvature,
+                   current_cost_temperature,
+                   current_user_parameter_temp,
+                   accepted_to_generated_ratio,
+                   number_parameters,
+                   &curvatureFlag,
+                   number_accepted,
+                   index_cost_acceptances,
+                   number_generated,
+                   number_invalid_generated_states,
+                   last_saved_state,
+                   best_generated_state, ptr_asa_out, OPTIONS);
+#endif /* ASA_PRINT */
+
+#if MULTI_MIN
+  }
+  best_generated_state->cost = OPTIONS->Multi_Cost[0];
+  VFOR (index_v) {
+    best_generated_state->parameter[index_v] =
+      OPTIONS->Multi_Params[0][index_v];
+  }
+#endif /* MULTI_MIN */
+
+#if ASA_PRINT
+  switch (*exit_status) {
+  case NORMAL_EXIT:
+    fprintf (ptr_asa_out,
+             "\n\n NORMAL_EXIT exit_status = %d\n", *exit_status);
+    break;
+  case P_TEMP_TOO_SMALL:
+    fprintf (ptr_asa_out,
+             "\n\n P_TEMP_TOO_SMALL exit_status = %d\n", *exit_status);
+    fprintf (ptr_asa_out,
+#if INT_ALLOC
+             "current_user_parameter_temp[%d] too small = %*.*g\n",
+#else
+#if INT_LONG
+             "current_user_parameter_temp[%ld] too small = %*.*g\n",
+#else
+             "current_user_parameter_temp[%d] too small = %*.*g\n",
+#endif
+#endif
+             *index_exit_v,
+             G_FIELD, G_PRECISION,
+             current_user_parameter_temp[*index_exit_v]);
+    break;
+  case C_TEMP_TOO_SMALL:
+    fprintf (ptr_asa_out,
+             "\n\n C_TEMP_TOO_SMALL exit_status = %d\n", *exit_status);
+    fprintf (ptr_asa_out,
+             "*current_cost_temperature too small = %*.*g\n",
+             G_FIELD, G_PRECISION, *current_cost_temperature);
+    break;
+  case COST_REPEATING:
+    fprintf (ptr_asa_out,
+             "\n\n COST_REPEATING exit_status = %d\n", *exit_status);
+    break;
+  case TOO_MANY_INVALID_STATES:
+    fprintf (ptr_asa_out,
+             "\n\n  TOO_MANY_INVALID_STATES exit_status = %d\n",
+             *exit_status);
+    break;
+  case IMMEDIATE_EXIT:
+    fprintf (ptr_asa_out,
+             "\n\n  IMMEDIATE_EXIT exit_status = %d\n", *exit_status);
+    break;
+  case INVALID_USER_INPUT:
+    fprintf (ptr_asa_out,
+             "\n\n  INVALID_USER_INPUT exit_status = %d\n", *exit_status);
+    break;
+  case INVALID_COST_FUNCTION:
+    fprintf (ptr_asa_out,
+             "\n\n  INVALID_COST_FUNCTION exit_status = %d\n", *exit_status);
+    break;
+  case INVALID_COST_FUNCTION_DERIV:
+    fprintf (ptr_asa_out,
+             "\n\n  INVALID_COST_FUNCTION_DERIV exit_status = %d\n",
+             *exit_status);
+    break;
+  default:
+    fprintf (ptr_asa_out, "\n\n ERR: no exit code available = %d\n",
+             *exit_status);
+  }
+
+  switch (OPTIONS->Locate_Cost) {
+  case 0:
+    fprintf (ptr_asa_out,
+             " Locate_Cost = %d, initial cost temperature\n",
+             OPTIONS->Locate_Cost);
+    break;
+  case 1:
+    fprintf (ptr_asa_out,
+             " Locate_Cost = %d, initial cost value\n", OPTIONS->Locate_Cost);
+    break;
+  case 2:
+    fprintf (ptr_asa_out,
+             " Locate_Cost = %d, new generated state\n",
+             OPTIONS->Locate_Cost);
+    break;
+  case 12:
+    fprintf (ptr_asa_out,
+             " Locate_Cost = %d, new generated state just after a new best state\n",
+             OPTIONS->Locate_Cost);
+    break;
+  case 3:
+    fprintf (ptr_asa_out,
+             " Locate_Cost = %d, cost derivatives, reannealing parameters\n",
+             OPTIONS->Locate_Cost);
+    break;
+  case 4:
+    fprintf (ptr_asa_out,
+             " Locate_Cost = %d, reannealing cost temperature\n",
+             OPTIONS->Locate_Cost);
+    break;
+  case 5:
+    fprintf (ptr_asa_out,
+             " Locate_Cost = %d, calculating curvatures while exiting asa ()\n",
+             OPTIONS->Locate_Cost);
+    break;
+  case -1:
+    fprintf (ptr_asa_out,
+             " Locate_Cost = %d, exited main asa () loop by user-defined OPTIONS\n",
+             OPTIONS->Locate_Cost);
+    break;
+  default:
+    fprintf (ptr_asa_out,
+             " Locate_Cost = %d, no index available for Locate_Cost\n",
+             OPTIONS->Locate_Cost);
+  }
+
+  if (*exit_status != INVALID_USER_INPUT
+      && *exit_status != INVALID_COST_FUNCTION
+      && *exit_status != INVALID_COST_FUNCTION_DERIV) {
+    fprintf (ptr_asa_out,
+             "final_cost = best_generated_state->cost = %-*.*g\n",
+             G_FIELD, G_PRECISION, *final_cost);
+#if INT_LONG
+    fprintf (ptr_asa_out,
+             "*number_accepted at best_generated_state->cost = %ld\n",
+             *best_number_accepted_saved);
+    fprintf (ptr_asa_out,
+             "*number_generated at best_generated_state->cost = %ld\n",
+             *best_number_generated_saved);
+#else
+    fprintf (ptr_asa_out,
+             "*number_accepted at best_generated_state->cost = %d\n",
+             *best_number_accepted_saved);
+    fprintf (ptr_asa_out,
+             "*number_generated at best_generated_state->cost = %d\n",
+             *best_number_generated_saved);
+#endif
+  }
+#endif
+
+#if ASA_TEMPLATE_SELFOPT
+  if (OPTIONS->Asa_Data_Dbl[0] > (double) MIN_DOUBLE)
+    OPTIONS->Asa_Data_Dbl[1] = (double) (*best_number_generated_saved);
+#endif
+
+  /* reset OPTIONS->Sequential_Parameters */
+  OPTIONS->Sequential_Parameters = *start_sequence;
+
+#if ASA_PRINT
+#if TIME_CALC
+  /* print ending time */
+  print_time ("asa_end", ptr_asa_out);
+#endif
+  fprintf (ptr_asa_out, "\n\n\n");
+  fflush (ptr_asa_out);
+  ptr_asa_out != stdout && fclose (ptr_asa_out);
+#endif
+
+  return (0);
+}
+
+/***********************************************************************
+* generate_new_state
+*       Generates a valid new state from the old state
+***********************************************************************/
+#if HAVE_ANSI
+void
+
+generate_new_state (double (*user_random_generator) (LONG_INT *),
+                    LONG_INT * seed,
+                    double *parameter_minimum,
+                    double *parameter_maximum,
+                    double *current_user_parameter_temp,
+#if USER_GENERATING_FUNCTION
+                    double *initial_user_parameter_temp,
+                    double *temperature_scale_parameters,
+#endif
+                    ALLOC_INT * number_parameters,
+                    int *parameter_type,
+                    STATE * current_generated_state,
+                    STATE * last_saved_state, USER_DEFINES * OPTIONS)
+#else
+void
+
+generate_new_state (user_random_generator,
+                    seed,
+                    parameter_minimum,
+                    parameter_maximum, current_user_parameter_temp,
+#if USER_GENERATING_FUNCTION
+                    initial_user_parameter_temp, temperature_scale_parameters,
+#endif
+                    number_parameters,
+                    parameter_type,
+                    current_generated_state, last_saved_state, OPTIONS)
+     double (*user_random_generator) ();
+     LONG_INT *seed;
+     double *parameter_minimum;
+     double *parameter_maximum;
+     double *current_user_parameter_temp;
+#if USER_GENERATING_FUNCTION
+     double *initial_user_parameter_temp;
+     double *temperature_scale_parameters;
+#endif
+     ALLOC_INT *number_parameters;
+     int *parameter_type;
+     STATE *current_generated_state;
+     STATE *last_saved_state;
+     USER_DEFINES *OPTIONS;
+#endif
+{
+  ALLOC_INT index_v;
+  double x;
+  double parameter_v, min_parameter_v, max_parameter_v, temperature_v,
+    parameter_range_v;
+#if USER_GENERATING_FUNCTION
+  double init_param_temp_v;
+  double temp_scale_params_v;
+#endif
+#if ASA_RESOLUTION
+  double xres, xint, xminus, xplus, dx, dxminus, dxplus;
+#endif
+
+  /* generate a new value for each parameter */
+  VFOR (index_v) {
+    if (OPTIONS->Sequential_Parameters >= -1) {
+      ++OPTIONS->Sequential_Parameters;
+      if (OPTIONS->Sequential_Parameters == *number_parameters)
+        OPTIONS->Sequential_Parameters = 0;
+      index_v = OPTIONS->Sequential_Parameters;
+    }
+    min_parameter_v = parameter_minimum[index_v];
+    max_parameter_v = parameter_maximum[index_v];
+    parameter_range_v = max_parameter_v - min_parameter_v;
+
+    /* ignore parameters that have too small a range */
+    if (fabs (parameter_range_v) < (double) EPS_DOUBLE)
+      continue;
+
+    temperature_v = current_user_parameter_temp[index_v];
+#if USER_GENERATING_FUNCTION
+    init_param_temp_v = initial_user_parameter_temp[index_v];
+    temp_scale_params_v = temperature_scale_parameters[index_v];
+#endif
+    parameter_v = last_saved_state->parameter[index_v];
+
+    /* Handle discrete parameters. */
+#if ASA_RESOLUTION
+    xres = OPTIONS->Coarse_Resolution[index_v];
+    if (xres > EPS_DOUBLE) {
+      min_parameter_v -= (xres / TWO);
+      max_parameter_v += (xres / TWO);
+      parameter_range_v = max_parameter_v - min_parameter_v;
+    }
+#endif /* ASA_RESOLUTION */
+    if (INTEGER_PARAMETER (index_v)) {
+#if ASA_RESOLUTION
+      if (xres > EPS_DOUBLE) {
+        ;
+      } else {
+#endif /* ASA_RESOLUTION */
+        min_parameter_v -= HALF;
+        max_parameter_v += HALF;
+        parameter_range_v = max_parameter_v - min_parameter_v;
+      }
+#if ASA_RESOLUTION
+    }
+#endif
+
+    /* generate a new state x within the parameter bounds */
+    for (;;) {
+#if USER_GENERATING_FUNCTION
+      x = OPTIONS->Generating_Distrib (seed,
+                                       number_parameters,
+                                       index_v,
+                                       temperature_v,
+                                       init_param_temp_v,
+                                       temp_scale_params_v,
+                                       parameter_v,
+                                       parameter_range_v,
+                                       last_saved_state->parameter, OPTIONS);
+#else
+      x = parameter_v
+        + generate_asa_state (user_random_generator, seed, &temperature_v)
+        * parameter_range_v;
+#endif /* USER_GENERATING_FUNCTION */
+#if ASA_RESOLUTION
+      if (xres > EPS_DOUBLE) {
+        xint = xres * (double) ((LONG_INT) (x / xres));
+        xplus = xint + xres;
+        xminus = xint - xres;
+        dx = fabs (xint - x);
+        dxminus = fabs (xminus - x);
+        dxplus = fabs (xplus - x);
+
+        if (dx < dxminus && dx < dxplus)
+          x = xint;
+        else if (dxminus < dxplus)
+          x = xminus;
+        else
+          x = xplus;
+      }
+#endif /* ASA_RESOLUTION */
+
+      /* exit the loop if within its valid parameter range */
+      if (x <= max_parameter_v - (double) EPS_DOUBLE
+          && x >= min_parameter_v + (double) EPS_DOUBLE)
+        break;
+    }
+
+    /* Handle discrete parameters.
+       You might have to check rounding on your machine. */
+    if (INTEGER_PARAMETER (index_v)) {
+#if ASA_RESOLUTION
+      if (xres > EPS_DOUBLE) {
+        ;
+      } else {
+#endif /* ASA_RESOLUTION */
+        if (x < min_parameter_v + HALF)
+          x = min_parameter_v + HALF + (double) EPS_DOUBLE;
+        if (x > max_parameter_v - HALF)
+          x = max_parameter_v - HALF + (double) EPS_DOUBLE;
+
+        if (x + HALF > ZERO) {
+          x = (double) ((LONG_INT) (x + HALF));
+        } else {
+          x = (double) ((LONG_INT) (x - HALF));
+        }
+        if (x > parameter_maximum[index_v])
+          x = parameter_maximum[index_v];
+        if (x < parameter_minimum[index_v])
+          x = parameter_minimum[index_v];
+      }
+#if ASA_RESOLUTION
+    }
+    if (xres > EPS_DOUBLE) {
+      if (x < min_parameter_v + xres / TWO)
+        x = min_parameter_v + xres / TWO + (double) EPS_DOUBLE;
+      if (x > max_parameter_v - xres / TWO)
+        x = max_parameter_v - xres / TWO + (double) EPS_DOUBLE;
+
+      if (x > parameter_maximum[index_v])
+        x = parameter_maximum[index_v];
+      if (x < parameter_minimum[index_v])
+        x = parameter_minimum[index_v];
+    }
+#endif /* ASA_RESOLUTION */
+
+    /* save the newly generated value */
+    current_generated_state->parameter[index_v] = x;
+
+    if (OPTIONS->Sequential_Parameters >= 0)
+      break;
+  }
+
+}
+
+/***********************************************************************
+* generate_asa_state
+*       This function generates a single value according to the
+*       ASA generating function and the passed temperature
+***********************************************************************/
+#if HAVE_ANSI
+double
+
+generate_asa_state (double (*user_random_generator) (LONG_INT *),
+                    LONG_INT * seed, double *temp)
+#else
+double
+generate_asa_state (user_random_generator, seed, temp)
+     double (*user_random_generator) ();
+     LONG_INT *seed;
+     double *temp;
+#endif
+{
+  double x, y, z;
+
+  x = (*user_random_generator) (seed);
+  y = x < HALF ? -ONE : ONE;
+  z = y * *temp * (F_POW ((ONE + ONE / *temp), fabs (TWO * x - ONE)) - ONE);
+
+  return (z);
+
+}
+
+/***********************************************************************
+* accept_new_state
+*	This procedure accepts or rejects a newly generated state,
+*	depending on whether the difference between new and old
+*	cost functions passes a statistical test. If accepted,
+*	the current state is updated.
+***********************************************************************/
+#if HAVE_ANSI
+void
+
+accept_new_state (double (*user_random_generator) (LONG_INT *),
+                  LONG_INT * seed,
+                  double *parameter_minimum,
+                  double *parameter_maximum, double *current_cost_temperature,
+#if ASA_SAMPLE
+                  double *current_user_parameter_temp,
+#endif
+                  ALLOC_INT * number_parameters,
+                  LONG_INT * recent_number_acceptances,
+                  LONG_INT * number_accepted,
+                  LONG_INT * index_cost_acceptances,
+                  LONG_INT * number_acceptances_saved,
+                  LONG_INT * recent_number_generated,
+                  LONG_INT * number_generated,
+                  LONG_INT * index_parameter_generations,
+                  STATE * current_generated_state, STATE * last_saved_state,
+#if ASA_SAMPLE
+                  FILE * ptr_asa_out,
+#endif
+                  USER_DEFINES * OPTIONS)
+#else
+void
+
+accept_new_state (user_random_generator,
+                  seed,
+                  parameter_minimum,
+                  parameter_maximum, current_cost_temperature,
+#if ASA_SAMPLE
+                  current_user_parameter_temp,
+#endif
+                  number_parameters,
+                  recent_number_acceptances,
+                  number_accepted,
+                  index_cost_acceptances,
+                  number_acceptances_saved,
+                  recent_number_generated,
+                  number_generated,
+                  index_parameter_generations,
+                  current_generated_state, last_saved_state,
+#if ASA_SAMPLE
+                  ptr_asa_out,
+#endif
+                  OPTIONS)
+     double (*user_random_generator) ();
+     LONG_INT *seed;
+     double *parameter_minimum;
+     double *parameter_maximum;
+     double *current_cost_temperature;
+#if ASA_SAMPLE
+     double *current_user_parameter_temp;
+#endif
+     ALLOC_INT *number_parameters;
+     LONG_INT *recent_number_acceptances;
+     LONG_INT *number_accepted;
+     LONG_INT *index_cost_acceptances;
+     LONG_INT *number_acceptances_saved;
+     LONG_INT *recent_number_generated;
+     LONG_INT *number_generated;
+     LONG_INT *index_parameter_generations;
+     STATE *current_generated_state;
+     STATE *last_saved_state;
+#if ASA_SAMPLE
+     FILE *ptr_asa_out;
+#endif
+     USER_DEFINES *OPTIONS;
+
+#endif
+{
+#if USER_ACCEPTANCE_TEST
+#else
+  double delta_cost;
+#if USER_ACCEPT_ASYMP_EXP
+  double q;
+#endif
+#endif
+  double prob_test, unif_test;
+  double curr_cost_temp;
+  ALLOC_INT index_v;
+#if ASA_SAMPLE
+  LONG_INT active_params;
+  double weight_param_ind, weight_aver, range;
+#endif
+
+  /* update accepted and generated count */
+  ++*number_acceptances_saved;
+  ++*recent_number_generated;
+  ++*number_generated;
+  OPTIONS->N_Generated = *number_generated;
+
+  /* increment the parameter index generation for each parameter */
+  if (OPTIONS->Sequential_Parameters >= 0) {
+    /* ignore parameters with too small a range */
+    if (!PARAMETER_RANGE_TOO_SMALL (OPTIONS->Sequential_Parameters))
+      ++index_parameter_generations[OPTIONS->Sequential_Parameters];
+  } else {
+    VFOR (index_v) {
+      if (!PARAMETER_RANGE_TOO_SMALL (index_v))
+        ++index_parameter_generations[index_v];
+    }
+  }
+
+  /* effective cost function for testing acceptance criteria,
+     calculate the cost difference and divide by the temperature */
+  curr_cost_temp = *current_cost_temperature;
+#if USER_ACCEPTANCE_TEST
+  if (OPTIONS->Cost_Acceptance_Flag == TRUE) {
+    if (OPTIONS->User_Acceptance_Flag == TRUE) {
+      unif_test = ZERO;
+      OPTIONS->User_Acceptance_Flag = FALSE;
+      OPTIONS->Cost_Acceptance_Flag = FALSE;
+    } else {
+      unif_test = ONE;
+      OPTIONS->Cost_Acceptance_Flag = FALSE;
+    }
+  } else {
+    OPTIONS->Acceptance_Test (current_generated_state->cost,
+                              parameter_minimum,
+                              parameter_maximum, *number_parameters, OPTIONS);
+    if (OPTIONS->User_Acceptance_Flag == TRUE) {
+      unif_test = ZERO;
+      OPTIONS->User_Acceptance_Flag = FALSE;
+    } else {
+      unif_test = ONE;
+    }
+  }
+  prob_test = OPTIONS->Prob_Bias;
+#else /* USER_ACCEPTANCE_TEST */
+
+#if USER_COST_SCHEDULE
+  curr_cost_temp =
+    (OPTIONS->Cost_Schedule (*current_cost_temperature, OPTIONS)
+     + (double) EPS_DOUBLE);
+#endif
+  delta_cost = (current_generated_state->cost - last_saved_state->cost)
+    / (curr_cost_temp + (double) EPS_DOUBLE);
+
+#if USER_ACCEPT_ASYMP_EXP
+  q = OPTIONS->Asymp_Exp_Param;
+  if (fabs (ONE - q) < (double) EPS_DOUBLE)
+    prob_test = MIN (ONE, (F_EXP (EXPONENT_CHECK (-delta_cost))));
+  else if ((ONE - (ONE - q) * delta_cost) < (double) EPS_DOUBLE)
+    prob_test = MIN (ONE, (F_EXP (EXPONENT_CHECK (-delta_cost))));
+  else
+    prob_test = MIN (ONE, F_POW ((ONE - (ONE - q) * delta_cost),
+                                 (ONE / (ONE - q))));
+#else /* USER_ACCEPT_ASYMP_EXP */
+
+#if USER_ACCEPT_THRESHOLD       /* USER_ACCEPT_THRESHOLD */
+  prob_test = delta_cost <= 1.0 ? 1.0 : 0.0;
+#else /* Metropolis */
+  prob_test = MIN (ONE, (F_EXP (EXPONENT_CHECK (-delta_cost))));
+#endif /* USER_ACCEPT_THRESHOLD */
+
+#endif /* USER_ACCEPT_ASYMP_EXP */
+
+  unif_test = (*user_random_generator) (seed);
+#endif /* USER_ACCEPTANCE_TEST */
+
+#if ASA_SAMPLE
+  active_params = 0;
+  weight_aver = ZERO;
+  VFOR (index_v) {
+    /* ignore parameters with too small a range */
+    if (PARAMETER_RANGE_TOO_SMALL (index_v))
+      continue;
+    ++active_params;
+    range = parameter_maximum[index_v] - parameter_minimum[index_v];
+    weight_param_ind = TWO * (fabs ((last_saved_state->parameter[index_v]
+                                     -
+                                     current_generated_state->
+                                     parameter[index_v]) / range)
+                              + current_user_parameter_temp[index_v])
+      * F_LOG (ONE + ONE / current_user_parameter_temp[index_v]);
+    weight_aver += weight_param_ind;
+    OPTIONS->Bias_Generated[index_v] = ONE / weight_param_ind;
+  }
+  weight_aver /= (double) active_params;
+  OPTIONS->Average_Weights = weight_aver;
+  if (prob_test >= unif_test) {
+    OPTIONS->Bias_Acceptance = prob_test;
+  } else {
+    OPTIONS->Bias_Acceptance = ONE - prob_test;
+  }
+
+#if ASA_PRINT
+  if (OPTIONS->Limit_Weights < OPTIONS->Average_Weights) {
+    fprintf (ptr_asa_out, ":SAMPLE#\n");
+    if (prob_test >= unif_test) {
+      fprintf (ptr_asa_out,
+#if INT_LONG
+               ":SAMPLE+ %10ld %*.*g %*.*g %*.*g %*.*g\n",
+#else
+               ":SAMPLE+ %10d %*.*g %*.*g %*.*g\n",
+#endif
+               OPTIONS->N_Accepted,
+               G_FIELD, G_PRECISION, current_generated_state->cost,
+               G_FIELD, G_PRECISION, *current_cost_temperature,
+               G_FIELD, G_PRECISION, OPTIONS->Bias_Acceptance,
+               G_FIELD, G_PRECISION, OPTIONS->Average_Weights);
+      VFOR (index_v) {
+        /* ignore parameters with too small a range */
+        if (PARAMETER_RANGE_TOO_SMALL (index_v))
+          continue;
+        range = parameter_maximum[index_v] - parameter_minimum[index_v];
+        fprintf (ptr_asa_out,
+#if INT_ALLOC
+                 ":SAMPLE %11d %*.*g %*.*g %*.*g %*.*g\n",
+#else
+#if INT_LONG
+                 ":SAMPLE %11ld %*.*g %*.*g %*.*g %*.*g\n",
+#else
+                 ":SAMPLE %11d %*.*g %*.*g %*.*g %*.*g\n",
+#endif
+#endif
+                 index_v,
+                 G_FIELD, G_PRECISION,
+                 current_generated_state->parameter[index_v], G_FIELD,
+                 G_PRECISION, current_user_parameter_temp[index_v],
+                 G_FIELD, G_PRECISION, OPTIONS->Bias_Generated[index_v],
+                 G_FIELD, G_PRECISION, range);
+      }
+    } else {
+      fprintf (ptr_asa_out,
+#if INT_LONG
+               ":SAMPLE %11ld %*.*g %*.*g %*.*g %*.*g\n",
+#else
+               ":SAMPLE %11d %*.*g %*.*g %*.*g\n",
+#endif
+               OPTIONS->N_Accepted,
+               G_FIELD, G_PRECISION, last_saved_state->cost,
+               G_FIELD, G_PRECISION, *current_cost_temperature,
+               G_FIELD, G_PRECISION, OPTIONS->Bias_Acceptance,
+               G_FIELD, G_PRECISION, OPTIONS->Average_Weights);
+      VFOR (index_v) {
+        /* ignore parameters with too small a range */
+        if (PARAMETER_RANGE_TOO_SMALL (index_v))
+          continue;
+        range = parameter_maximum[index_v] - parameter_minimum[index_v];
+        fprintf (ptr_asa_out,
+#if INT_ALLOC
+                 ":SAMPLE %11d %*.*g %*.*g %*.*g %*.*g\n",
+#else
+#if INT_LONG
+                 ":SAMPLE %11ld %*.*g %*.*g %*.*g %*.*g\n",
+#else
+                 ":SAMPLE %11d %*.*g %*.*g %*.*g %*.*g\n",
+#endif
+#endif
+                 index_v,
+                 G_FIELD, G_PRECISION,
+                 last_saved_state->parameter[index_v], G_FIELD,
+                 G_PRECISION, current_user_parameter_temp[index_v],
+                 G_FIELD, G_PRECISION, OPTIONS->Bias_Generated[index_v],
+                 G_FIELD, G_PRECISION, range);
+      }
+    }
+  }
+#endif
+#endif /* ASA_SAMPLE */
+
+  /* accept/reject the new state */
+  if (prob_test >= unif_test) {
+    /* copy current state to the last saved state */
+
+    last_saved_state->cost = current_generated_state->cost;
+    VFOR (index_v) {
+      /* ignore parameters with too small a range */
+      if (PARAMETER_RANGE_TOO_SMALL (index_v))
+        continue;
+      last_saved_state->parameter[index_v] =
+        current_generated_state->parameter[index_v];
+    }
+
+    /* update acceptance counts */
+    ++*recent_number_acceptances;
+    ++*number_accepted;
+    ++*index_cost_acceptances;
+    *number_acceptances_saved = *number_accepted;
+    OPTIONS->N_Accepted = *number_accepted;
+  }
+}
+
+/***********************************************************************
+* reanneal
+*	Readjust temperatures of generating and acceptance functions
+***********************************************************************/
+#if HAVE_ANSI
+void
+
+reanneal (double *parameter_minimum,
+          double *parameter_maximum,
+          double *tangents,
+          double *maximum_tangent,
+          double *current_cost_temperature,
+          double *initial_cost_temperature,
+          double *temperature_scale_cost,
+          double *current_user_parameter_temp,
+          double *initial_user_parameter_temp,
+          double *temperature_scale_parameters,
+          ALLOC_INT * number_parameters,
+          int *parameter_type,
+          LONG_INT * index_cost_acceptances,
+          LONG_INT * index_parameter_generations,
+          STATE * last_saved_state,
+          STATE * best_generated_state, USER_DEFINES * OPTIONS)
+#else
+void
+
+reanneal (parameter_minimum,
+          parameter_maximum,
+          tangents,
+          maximum_tangent,
+          current_cost_temperature,
+          initial_cost_temperature,
+          temperature_scale_cost,
+          current_user_parameter_temp,
+          initial_user_parameter_temp,
+          temperature_scale_parameters,
+          number_parameters,
+          parameter_type,
+          index_cost_acceptances,
+          index_parameter_generations,
+          last_saved_state, best_generated_state, OPTIONS)
+     double *parameter_minimum;
+     double *parameter_maximum;
+     double *tangents;
+     double *maximum_tangent;
+     double *current_cost_temperature;
+     double *initial_cost_temperature;
+     double *temperature_scale_cost;
+     double *current_user_parameter_temp;
+     double *initial_user_parameter_temp;
+     double *temperature_scale_parameters;
+     ALLOC_INT *number_parameters;
+     int *parameter_type;
+     LONG_INT *index_cost_acceptances;
+     LONG_INT *index_parameter_generations;
+     STATE *last_saved_state;
+     STATE *best_generated_state;
+     USER_DEFINES *OPTIONS;
+#endif
+{
+  ALLOC_INT index_v;
+  int cost_test;
+  double tmp_var_db3;
+  double new_temperature;
+  double log_new_temperature_ratio;
+  double log_init_cur_temp_ratio;
+  double temperature_rescale_power;
+  double cost_best, cost_last;
+  double tmp_dbl, tmp_dbl1;
+
+  double xnumber_parameters[1];
+
+  cost_test = cost_function_test (last_saved_state->cost,
+                                  last_saved_state->parameter,
+                                  parameter_minimum,
+                                  parameter_maximum, number_parameters,
+                                  xnumber_parameters);
+
+  if (OPTIONS->Reanneal_Parameters == TRUE) {
+    VFOR (index_v) {
+      if (NO_REANNEAL (index_v))
+        continue;
+
+      /* use the temp double to prevent overflow */
+      tmp_dbl = (double) index_parameter_generations[index_v];
+
+      /* skip parameters with too small range or integer parameters */
+      if (OPTIONS->Include_Integer_Parameters == TRUE) {
+        if (PARAMETER_RANGE_TOO_SMALL (index_v))
+          continue;
+      } else {
+        if (PARAMETER_RANGE_TOO_SMALL (index_v) ||
+            INTEGER_PARAMETER (index_v))
+          continue;
+      }
+
+      /* ignore parameters with too small tangents */
+      if (fabs (tangents[index_v]) < (double) EPS_DOUBLE)
+        continue;
+
+      /* reset the index of parameter generations appropriately */
+#if USER_REANNEAL_PARAMETERS
+      new_temperature =
+        fabs (OPTIONS->
+              Reanneal_Params_Function (current_user_parameter_temp
+                                        [index_v], tangents[index_v],
+                                        *maximum_tangent, OPTIONS));
+#else
+      new_temperature =
+        fabs (FUNCTION_REANNEAL_PARAMS
+              (current_user_parameter_temp[index_v], tangents[index_v],
+               *maximum_tangent));
+#endif
+      if (new_temperature < initial_user_parameter_temp[index_v]) {
+        log_init_cur_temp_ratio =
+          fabs (F_LOG (((double) EPS_DOUBLE
+                        + initial_user_parameter_temp[index_v])
+                       / ((double) EPS_DOUBLE + new_temperature)));
+        tmp_dbl = (double) EPS_DOUBLE
+          + F_POW (log_init_cur_temp_ratio
+                   / temperature_scale_parameters[index_v],
+                   *xnumber_parameters
+#if QUENCH_PARAMETERS
+                   / OPTIONS->User_Quench_Param_Scale[index_v]);
+#else
+          );
+#endif
+      } else {
+        tmp_dbl = ONE;
+      }
+
+      /* Reset index_parameter_generations if index reset too large,
+         and also reset the initial_user_parameter_temp, to achieve
+         the same new temperature. */
+      while (tmp_dbl > ((double) MAXIMUM_REANNEAL_INDEX)) {
+        log_new_temperature_ratio =
+          -temperature_scale_parameters[index_v] * F_POW (tmp_dbl,
+#if QUENCH_PARAMETERS
+                                                          OPTIONS->
+                                                          User_Quench_Param_Scale
+                                                          [index_v]
+#else
+                                                          ONE
+#endif
+                                                          /
+                                                          *xnumber_parameters);
+        log_new_temperature_ratio =
+          EXPONENT_CHECK (log_new_temperature_ratio);
+        new_temperature =
+          initial_user_parameter_temp[index_v] *
+          F_EXP (log_new_temperature_ratio);
+        tmp_dbl /= (double) REANNEAL_SCALE;
+        temperature_rescale_power = ONE / F_POW ((double) REANNEAL_SCALE,
+#if QUENCH_PARAMETERS
+                                                 OPTIONS->
+                                                 User_Quench_Param_Scale
+                                                 [index_v]
+#else
+                                                 ONE
+#endif
+                                                 / *xnumber_parameters);
+        initial_user_parameter_temp[index_v] =
+          new_temperature * F_POW (initial_user_parameter_temp[index_v] /
+                                   new_temperature,
+                                   temperature_rescale_power);
+      }
+      /* restore from temporary double */
+      index_parameter_generations[index_v] = (LONG_INT) tmp_dbl;
+    }
+  }
+
+  if (OPTIONS->Reanneal_Cost == 0) {
+    ;
+  } else if (OPTIONS->Reanneal_Cost < -1) {
+    *index_cost_acceptances = 1;
+  } else {
+    /* reanneal : Reset the current cost temp and rescale the
+       index of cost acceptances. */
+
+    cost_best = best_generated_state->cost;
+    cost_last = last_saved_state->cost;
+#if USER_REANNEAL_COST
+    cost_test = OPTIONS->Reanneal_Cost_Function (&cost_best,
+                                                 &cost_last,
+                                                 initial_cost_temperature,
+                                                 current_cost_temperature,
+                                                 OPTIONS);
+    tmp_dbl1 = *current_cost_temperature;
+#else
+    cost_test = TRUE;
+    if (OPTIONS->Reanneal_Cost == 1) {
+      /* (re)set the initial cost_temperature */
+      tmp_dbl = MAX (fabs (cost_last), fabs (cost_best));
+      tmp_dbl = MAX (tmp_dbl, fabs (cost_best - cost_last));
+      tmp_dbl = MAX ((double) EPS_DOUBLE, tmp_dbl);
+      *initial_cost_temperature = MIN (*initial_cost_temperature, tmp_dbl);
+    }
+
+    tmp_dbl = (double) *index_cost_acceptances;
+
+    tmp_dbl1 = MAX (fabs (cost_last - cost_best), *current_cost_temperature);
+    tmp_dbl1 = MAX ((double) EPS_DOUBLE, tmp_dbl1);
+    tmp_dbl1 = MIN (tmp_dbl1, *initial_cost_temperature);
+#endif /* USER_REANNEAL_COST */
+    if (cost_test == TRUE && (*current_cost_temperature > tmp_dbl1)) {
+      tmp_var_db3 =
+        fabs (F_LOG (((double) EPS_DOUBLE + *initial_cost_temperature) /
+                     (tmp_dbl1)));
+      tmp_dbl = (double) EPS_DOUBLE + F_POW (tmp_var_db3
+                                             / *temperature_scale_cost,
+                                             *xnumber_parameters
+#if QUENCH_COST
+                                             /
+                                             OPTIONS->
+                                             User_Quench_Cost_Scale[0]);
+#else
+        );
+#endif
+    } else {
+      log_init_cur_temp_ratio =
+        fabs (F_LOG (((double) EPS_DOUBLE + *initial_cost_temperature) /
+                     ((double) EPS_DOUBLE + *current_cost_temperature)));
+      tmp_dbl = (double) EPS_DOUBLE
+        + F_POW (log_init_cur_temp_ratio
+                 / *temperature_scale_cost, *xnumber_parameters
+#if QUENCH_COST
+                 / OPTIONS->User_Quench_Cost_Scale[0]
+#else
+#endif
+        );
+    }
+
+    /* reset index_cost_temperature if index reset too large */
+    while (tmp_dbl > ((double) MAXIMUM_REANNEAL_INDEX)) {
+      log_new_temperature_ratio = -*temperature_scale_cost * F_POW (tmp_dbl,
+#if QUENCH_COST
+                                                                    OPTIONS->
+                                                                    User_Quench_Cost_Scale
+                                                                    [0]
+#else
+                                                                    ONE
+#endif
+                                                                    /
+                                                                    *xnumber_parameters);
+      log_new_temperature_ratio = EXPONENT_CHECK (log_new_temperature_ratio);
+      new_temperature =
+        *initial_cost_temperature * F_EXP (log_new_temperature_ratio);
+      tmp_dbl /= (double) REANNEAL_SCALE;
+      temperature_rescale_power = ONE / F_POW ((double) REANNEAL_SCALE,
+#if QUENCH_COST
+                                               OPTIONS->
+                                               User_Quench_Cost_Scale[0]
+#else
+                                               ONE
+#endif
+                                               / *xnumber_parameters);
+      *initial_cost_temperature =
+        new_temperature * F_POW (*initial_cost_temperature /
+                                 new_temperature, temperature_rescale_power);
+    }
+    *index_cost_acceptances = (LONG_INT) tmp_dbl;
+#if USER_ACCEPTANCE_TEST
+    OPTIONS->Cost_Temp_Init = *initial_cost_temperature;
+#endif
+  }
+}
+
+/***********************************************************************
+* cost_derivatives
+*	This procedure calculates the derivatives of the cost function
+*	with respect to its parameters.  The first derivatives are
+*	used as a sensitivity measure for reannealing.  The second
+*	derivatives are calculated only if *curvature_flag=TRUE;
+*	these are a measure of the covariance of the fit when a
+*	minimum is found.
+***********************************************************************/
+  /* Calculate the numerical derivatives of the best
+     generated state found so far */
+
+  /* In this implementation of ASA, no checks are made for
+   *valid_state_generated_flag=FALSE for differential neighbors
+   to the current best state. */
+
+  /* Assuming no information is given about the metric of the parameter
+     space, use simple Cartesian space to calculate curvatures. */
+
+#if HAVE_ANSI
+void
+cost_derivatives (double (*user_cost_function)
+
+                   
+                  (double *, double *, double *, double *, double *,
+                   ALLOC_INT *, int *, int *, int *, USER_DEFINES *),
+                  double *parameter_minimum, double *parameter_maximum,
+                  double *tangents, double *curvature,
+                  double *maximum_tangent, ALLOC_INT * number_parameters,
+                  int *parameter_type, int *exit_status,
+                  int *curvature_flag, int *valid_state_generated_flag,
+                  LONG_INT * number_invalid_generated_states,
+                  STATE * current_generated_state,
+                  STATE * best_generated_state, FILE * ptr_asa_out,
+                  USER_DEFINES * OPTIONS)
+#else
+void
+
+cost_derivatives (user_cost_function,
+                  parameter_minimum,
+                  parameter_maximum,
+                  tangents,
+                  curvature,
+                  maximum_tangent,
+                  number_parameters,
+                  parameter_type,
+                  exit_status,
+                  curvature_flag,
+                  valid_state_generated_flag,
+                  number_invalid_generated_states,
+                  current_generated_state,
+                  best_generated_state, ptr_asa_out, OPTIONS)
+     double (*user_cost_function) ();
+     double *parameter_minimum;
+     double *parameter_maximum;
+     double *tangents;
+     double *curvature;
+     double *maximum_tangent;
+     ALLOC_INT *number_parameters;
+     int *parameter_type;
+     int *exit_status;
+     int *curvature_flag;
+     int *valid_state_generated_flag;
+     LONG_INT *number_invalid_generated_states;
+     STATE *current_generated_state;
+     STATE *best_generated_state;
+     FILE *ptr_asa_out;
+     USER_DEFINES *OPTIONS;
+#endif
+{
+  ALLOC_INT index_v, index_vv, index_v_vv, index_vv_v;
+  LONG_INT saved_num_invalid_gen_states;
+#if ASA_PRINT
+  LONG_INT tmp_saved;
+#endif
+  double parameter_v, parameter_vv, parameter_v_offset, parameter_vv_offset;
+  double recent_best_cost;
+  double new_cost_state_1, new_cost_state_2, new_cost_state_3;
+  double delta_parameter_v, delta_parameter_vv;
+  int immediate_flag;
+  double xnumber_parameters[1];
+
+  if (OPTIONS->Curvature_0 == TRUE)
+    *curvature_flag = FALSE;
+  if (OPTIONS->Curvature_0 == -1)
+    *curvature_flag = TRUE;
+
+  /* save Immediate_Exit flag */
+  immediate_flag = OPTIONS->Immediate_Exit;
+
+  /* save the best cost */
+  recent_best_cost = best_generated_state->cost;
+
+  /* copy the best state into the current state */
+  VFOR (index_v) {
+    /* ignore parameters with too small ranges */
+    if (PARAMETER_RANGE_TOO_SMALL (index_v))
+      continue;
+    current_generated_state->parameter[index_v] =
+      best_generated_state->parameter[index_v];
+  }
+
+  saved_num_invalid_gen_states = (*number_invalid_generated_states);
+
+  /* set parameters (& possibly constraints) to best state */
+  *valid_state_generated_flag = TRUE;
+#if USER_ACCEPTANCE_TEST
+  OPTIONS->User_Acceptance_Flag = TRUE;
+  OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+  current_generated_state->cost =
+    user_cost_function (current_generated_state->parameter,
+                        parameter_minimum,
+                        parameter_maximum,
+                        tangents,
+                        curvature,
+                        number_parameters,
+                        parameter_type,
+                        valid_state_generated_flag, exit_status, OPTIONS);
+  if (cost_function_test (current_generated_state->cost,
+                          current_generated_state->parameter,
+                          parameter_minimum,
+                          parameter_maximum, number_parameters,
+                          xnumber_parameters) == 0) {
+    *exit_status = INVALID_COST_FUNCTION_DERIV;
+    return;
+  }
+  if (*valid_state_generated_flag == FALSE)
+    ++(*number_invalid_generated_states);
+
+  if (OPTIONS->User_Tangents == TRUE) {
+    *valid_state_generated_flag = FALSE;
+#if USER_ACCEPTANCE_TEST
+    OPTIONS->User_Acceptance_Flag = TRUE;
+    OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+    current_generated_state->cost =
+      user_cost_function (current_generated_state->parameter,
+                          parameter_minimum,
+                          parameter_maximum,
+                          tangents,
+                          curvature,
+                          number_parameters,
+                          parameter_type,
+                          valid_state_generated_flag, exit_status, OPTIONS);
+    if (cost_function_test (current_generated_state->cost,
+                            current_generated_state->parameter,
+                            parameter_minimum,
+                            parameter_maximum, number_parameters,
+                            xnumber_parameters) == 0) {
+      *exit_status = INVALID_COST_FUNCTION_DERIV;
+      return;
+    }
+    if (*valid_state_generated_flag == FALSE)
+      ++(*number_invalid_generated_states);
+  } else {
+    /* calculate tangents */
+    VFOR (index_v) {
+      if (NO_REANNEAL (index_v)) {
+        tangents[index_v] = ZERO;
+        continue;
+      }
+      /* skip parameters with too small range or integer parameters */
+      if (OPTIONS->Include_Integer_Parameters == TRUE) {
+        if (PARAMETER_RANGE_TOO_SMALL (index_v)) {
+          tangents[index_v] = ZERO;
+          continue;
+        }
+      } else {
+        if (PARAMETER_RANGE_TOO_SMALL (index_v) ||
+            INTEGER_PARAMETER (index_v)) {
+          tangents[index_v] = ZERO;
+          continue;
+        }
+      }
+
+      /* save the v_th parameter and delta_parameter */
+      parameter_v = best_generated_state->parameter[index_v];
+#if DELTA_PARAMETERS
+      delta_parameter_v = OPTIONS->User_Delta_Parameter[index_v];
+#else
+      delta_parameter_v = OPTIONS->Delta_X;
+#endif
+
+      parameter_v_offset = (ONE + delta_parameter_v) * parameter_v;
+      if (parameter_v_offset > parameter_maximum[index_v] ||
+          parameter_v_offset < parameter_minimum[index_v]) {
+        delta_parameter_v = -delta_parameter_v;
+        parameter_v_offset = (ONE + delta_parameter_v) * parameter_v;
+      }
+
+      /* generate the first sample point */
+      current_generated_state->parameter[index_v] = parameter_v_offset;
+      *valid_state_generated_flag = TRUE;
+#if USER_ACCEPTANCE_TEST
+      OPTIONS->User_Acceptance_Flag = TRUE;
+      OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+      current_generated_state->cost =
+        user_cost_function (current_generated_state->parameter,
+                            parameter_minimum,
+                            parameter_maximum,
+                            tangents,
+                            curvature,
+                            number_parameters,
+                            parameter_type,
+                            valid_state_generated_flag, exit_status, OPTIONS);
+      if (cost_function_test
+          (current_generated_state->cost,
+           current_generated_state->parameter, parameter_minimum,
+           parameter_maximum, number_parameters, xnumber_parameters) == 0) {
+        *exit_status = INVALID_COST_FUNCTION_DERIV;
+        return;
+      }
+      if (*valid_state_generated_flag == FALSE)
+        ++(*number_invalid_generated_states);
+      new_cost_state_1 = current_generated_state->cost;
+
+      /* restore the parameter state */
+      current_generated_state->parameter[index_v] = parameter_v;
+
+      /* calculate the numerical derivative */
+      tangents[index_v] = (new_cost_state_1 - recent_best_cost)
+        / (delta_parameter_v * parameter_v + (double) EPS_DOUBLE);
+
+    }
+  }
+
+  /* find the maximum |tangent| from all tangents */
+  *maximum_tangent = 0;
+  VFOR (index_v) {
+    if (NO_REANNEAL (index_v))
+      continue;
+
+    /* ignore too small ranges and integer parameters types */
+    if (OPTIONS->Include_Integer_Parameters == TRUE) {
+      if (PARAMETER_RANGE_TOO_SMALL (index_v))
+        continue;
+    } else {
+      if (PARAMETER_RANGE_TOO_SMALL (index_v)
+          || INTEGER_PARAMETER (index_v))
+        continue;
+    }
+
+    /* find the maximum |tangent| (from all tangents) */
+    if (fabs (tangents[index_v]) > *maximum_tangent) {
+      *maximum_tangent = fabs (tangents[index_v]);
+    }
+  }
+
+  if (*curvature_flag == TRUE || *curvature_flag == -1) {
+    /* calculate diagonal curvatures */
+    VFOR (index_v) {
+      if (NO_REANNEAL (index_v)) {
+        index_v_vv = ROW_COL_INDEX (index_v, index_v);
+        curvature[index_v_vv] = ZERO;
+        continue;
+      }
+      /* skip parameters with too small range or integer parameters */
+      if (OPTIONS->Include_Integer_Parameters == TRUE) {
+        if (PARAMETER_RANGE_TOO_SMALL (index_v)) {
+          index_v_vv = ROW_COL_INDEX (index_v, index_v);
+          curvature[index_v_vv] = ZERO;
+          continue;
+        }
+      } else {
+        if (PARAMETER_RANGE_TOO_SMALL (index_v) ||
+            INTEGER_PARAMETER (index_v)) {
+          index_v_vv = ROW_COL_INDEX (index_v, index_v);
+          curvature[index_v_vv] = ZERO;
+          continue;
+        }
+      }
+
+      /* save the v_th parameter and delta_parameter */
+      parameter_v = best_generated_state->parameter[index_v];
+#if DELTA_PARAMETERS
+      delta_parameter_v = OPTIONS->User_Delta_Parameter[index_v];
+#else
+      delta_parameter_v = OPTIONS->Delta_X;
+#endif
+
+      if (parameter_v + delta_parameter_v * fabs (parameter_v)
+          > parameter_maximum[index_v]) {
+        /* generate the first sample point */
+        current_generated_state->parameter[index_v] =
+          parameter_v - TWO * delta_parameter_v * fabs (parameter_v);
+        *valid_state_generated_flag = TRUE;
+#if USER_ACCEPTANCE_TEST
+        OPTIONS->User_Acceptance_Flag = TRUE;
+        OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+        current_generated_state->cost =
+          user_cost_function (current_generated_state->parameter,
+                              parameter_minimum,
+                              parameter_maximum,
+                              tangents,
+                              curvature,
+                              number_parameters,
+                              parameter_type,
+                              valid_state_generated_flag,
+                              exit_status, OPTIONS);
+        if (cost_function_test (current_generated_state->cost,
+                                current_generated_state->parameter,
+                                parameter_minimum,
+                                parameter_maximum, number_parameters,
+                                xnumber_parameters) == 0) {
+          *exit_status = INVALID_COST_FUNCTION_DERIV;
+          return;
+        }
+        if (*valid_state_generated_flag == FALSE)
+          ++(*number_invalid_generated_states);
+        new_cost_state_1 = current_generated_state->cost;
+
+        /* generate the second sample point */
+        current_generated_state->parameter[index_v] =
+          parameter_v - delta_parameter_v * fabs (parameter_v);
+
+        *valid_state_generated_flag = TRUE;
+#if USER_ACCEPTANCE_TEST
+        OPTIONS->User_Acceptance_Flag = TRUE;
+        OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+        current_generated_state->cost =
+          user_cost_function (current_generated_state->parameter,
+                              parameter_minimum,
+                              parameter_maximum,
+                              tangents,
+                              curvature,
+                              number_parameters,
+                              parameter_type,
+                              valid_state_generated_flag,
+                              exit_status, OPTIONS);
+        if (cost_function_test (current_generated_state->cost,
+                                current_generated_state->parameter,
+                                parameter_minimum,
+                                parameter_maximum, number_parameters,
+                                xnumber_parameters) == 0) {
+          *exit_status = INVALID_COST_FUNCTION_DERIV;
+          return;
+        }
+        if (*valid_state_generated_flag == FALSE)
+          ++(*number_invalid_generated_states);
+        new_cost_state_2 = current_generated_state->cost;
+
+        /* restore the parameter state */
+        current_generated_state->parameter[index_v] = parameter_v;
+
+        /* index_v_vv: row index_v, column index_v */
+        index_v_vv = ROW_COL_INDEX (index_v, index_v);
+
+        /* calculate and store the curvature */
+        curvature[index_v_vv] =
+          (recent_best_cost - TWO * new_cost_state_2
+           + new_cost_state_1) / (delta_parameter_v * delta_parameter_v
+                                  * parameter_v * parameter_v +
+                                  (double) EPS_DOUBLE);
+      } else if (parameter_v - delta_parameter_v * fabs (parameter_v)
+                 < parameter_minimum[index_v]) {
+        /* generate the first sample point */
+        current_generated_state->parameter[index_v] =
+          parameter_v + TWO * delta_parameter_v * fabs (parameter_v);
+        *valid_state_generated_flag = TRUE;
+#if USER_ACCEPTANCE_TEST
+        OPTIONS->User_Acceptance_Flag = TRUE;
+        OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+        current_generated_state->cost =
+          user_cost_function (current_generated_state->parameter,
+                              parameter_minimum,
+                              parameter_maximum,
+                              tangents,
+                              curvature,
+                              number_parameters,
+                              parameter_type,
+                              valid_state_generated_flag,
+                              exit_status, OPTIONS);
+        if (cost_function_test (current_generated_state->cost,
+                                current_generated_state->parameter,
+                                parameter_minimum,
+                                parameter_maximum, number_parameters,
+                                xnumber_parameters) == 0) {
+          *exit_status = INVALID_COST_FUNCTION_DERIV;
+          return;
+        }
+        if (*valid_state_generated_flag == FALSE)
+          ++(*number_invalid_generated_states);
+        new_cost_state_1 = current_generated_state->cost;
+
+        /* generate the second sample point */
+        current_generated_state->parameter[index_v] =
+          parameter_v + delta_parameter_v * fabs (parameter_v);
+
+        *valid_state_generated_flag = TRUE;
+#if USER_ACCEPTANCE_TEST
+        OPTIONS->User_Acceptance_Flag = TRUE;
+        OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+        current_generated_state->cost =
+          user_cost_function (current_generated_state->parameter,
+                              parameter_minimum,
+                              parameter_maximum,
+                              tangents,
+                              curvature,
+                              number_parameters,
+                              parameter_type,
+                              valid_state_generated_flag,
+                              exit_status, OPTIONS);
+        if (cost_function_test (current_generated_state->cost,
+                                current_generated_state->parameter,
+                                parameter_minimum,
+                                parameter_maximum, number_parameters,
+                                xnumber_parameters) == 0) {
+          *exit_status = INVALID_COST_FUNCTION_DERIV;
+          return;
+        }
+        if (*valid_state_generated_flag == FALSE)
+          ++(*number_invalid_generated_states);
+        new_cost_state_2 = current_generated_state->cost;
+
+        /* restore the parameter state */
+        current_generated_state->parameter[index_v] = parameter_v;
+
+        /* index_v_vv: row index_v, column index_v */
+        index_v_vv = ROW_COL_INDEX (index_v, index_v);
+
+        /* calculate and store the curvature */
+        curvature[index_v_vv] =
+          (recent_best_cost - TWO * new_cost_state_2
+           + new_cost_state_1) / (delta_parameter_v * delta_parameter_v
+                                  * parameter_v * parameter_v +
+                                  (double) EPS_DOUBLE);
+      } else {
+        /* generate the first sample point */
+        parameter_v_offset = (ONE + delta_parameter_v) * parameter_v;
+        current_generated_state->parameter[index_v] = parameter_v_offset;
+        *valid_state_generated_flag = TRUE;
+#if USER_ACCEPTANCE_TEST
+        OPTIONS->User_Acceptance_Flag = TRUE;
+        OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+        current_generated_state->cost =
+          user_cost_function (current_generated_state->parameter,
+                              parameter_minimum,
+                              parameter_maximum,
+                              tangents,
+                              curvature,
+                              number_parameters,
+                              parameter_type,
+                              valid_state_generated_flag,
+                              exit_status, OPTIONS);
+        if (cost_function_test (current_generated_state->cost,
+                                current_generated_state->parameter,
+                                parameter_minimum,
+                                parameter_maximum, number_parameters,
+                                xnumber_parameters) == 0) {
+          *exit_status = INVALID_COST_FUNCTION_DERIV;
+          return;
+        }
+        if (*valid_state_generated_flag == FALSE)
+          ++(*number_invalid_generated_states);
+        new_cost_state_1 = current_generated_state->cost;
+
+        /* generate the second sample point */
+        current_generated_state->parameter[index_v] =
+          (ONE - delta_parameter_v) * parameter_v;
+
+        *valid_state_generated_flag = TRUE;
+#if USER_ACCEPTANCE_TEST
+        OPTIONS->User_Acceptance_Flag = TRUE;
+        OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+        current_generated_state->cost =
+          user_cost_function (current_generated_state->parameter,
+                              parameter_minimum,
+                              parameter_maximum,
+                              tangents,
+                              curvature,
+                              number_parameters,
+                              parameter_type,
+                              valid_state_generated_flag,
+                              exit_status, OPTIONS);
+        if (cost_function_test (current_generated_state->cost,
+                                current_generated_state->parameter,
+                                parameter_minimum,
+                                parameter_maximum, number_parameters,
+                                xnumber_parameters) == 0) {
+          *exit_status = INVALID_COST_FUNCTION_DERIV;
+          return;
+        }
+        if (*valid_state_generated_flag == FALSE)
+          ++(*number_invalid_generated_states);
+        new_cost_state_2 = current_generated_state->cost;
+
+        /* restore the parameter state */
+        current_generated_state->parameter[index_v] = parameter_v;
+
+        /* index_v_vv: row index_v, column index_v */
+        index_v_vv = ROW_COL_INDEX (index_v, index_v);
+
+        /* calculate and store the curvature */
+        curvature[index_v_vv] =
+          (new_cost_state_2 - TWO * recent_best_cost
+           + new_cost_state_1) / (delta_parameter_v * delta_parameter_v
+                                  * parameter_v * parameter_v +
+                                  (double) EPS_DOUBLE);
+      }
+    }
+
+    /* calculate off-diagonal curvatures */
+    VFOR (index_v) {
+      /* save the v_th parameter and delta_x */
+      parameter_v = current_generated_state->parameter[index_v];
+#if DELTA_PARAMETERS
+      delta_parameter_v = OPTIONS->User_Delta_Parameter[index_v];
+#else
+      delta_parameter_v = OPTIONS->Delta_X;
+#endif
+
+      VFOR (index_vv) {
+        /* index_v_vv: row index_v, column index_vv */
+        index_v_vv = ROW_COL_INDEX (index_v, index_vv);
+        index_vv_v = ROW_COL_INDEX (index_vv, index_v);
+
+        if (NO_REANNEAL (index_vv) || NO_REANNEAL (index_v)) {
+          curvature[index_vv_v] = curvature[index_v_vv] = ZERO;
+          continue;
+        }
+
+        /* calculate only the upper diagonal */
+        if (index_v <= index_vv)
+          continue;
+
+        /* skip parms with too small range or integer parameters */
+        if (OPTIONS->Include_Integer_Parameters == TRUE) {
+          if (PARAMETER_RANGE_TOO_SMALL (index_v) ||
+              PARAMETER_RANGE_TOO_SMALL (index_vv)) {
+            curvature[index_vv_v] = curvature[index_v_vv] = ZERO;
+            continue;
+          }
+        } else {
+          if (INTEGER_PARAMETER (index_v) ||
+              INTEGER_PARAMETER (index_vv) ||
+              PARAMETER_RANGE_TOO_SMALL (index_v) ||
+              PARAMETER_RANGE_TOO_SMALL (index_vv)) {
+            curvature[index_vv_v] = curvature[index_v_vv] = ZERO;
+            continue;
+          }
+        }
+        /* save the vv_th parameter and delta_parameter */
+        parameter_vv = current_generated_state->parameter[index_vv];
+#if DELTA_PARAMETERS
+        delta_parameter_vv = OPTIONS->User_Delta_Parameter[index_vv];
+#else
+        delta_parameter_vv = OPTIONS->Delta_X;
+#endif
+
+        /* generate first sample point */
+        parameter_v_offset = current_generated_state->parameter[index_v] =
+          (ONE + delta_parameter_v) * parameter_v;
+        parameter_vv_offset = current_generated_state->parameter[index_vv] =
+          (ONE + delta_parameter_vv) * parameter_vv;
+        if (parameter_v_offset > parameter_maximum[index_v] ||
+            parameter_v_offset < parameter_minimum[index_v]) {
+          delta_parameter_v = -delta_parameter_v;
+          current_generated_state->parameter[index_v] =
+            (ONE + delta_parameter_v) * parameter_v;
+        }
+        if (parameter_vv_offset > parameter_maximum[index_vv] ||
+            parameter_vv_offset < parameter_minimum[index_vv]) {
+          delta_parameter_vv = -delta_parameter_vv;
+          current_generated_state->parameter[index_vv] =
+            (ONE + delta_parameter_vv) * parameter_vv;
+        }
+
+        *valid_state_generated_flag = TRUE;
+#if USER_ACCEPTANCE_TEST
+        OPTIONS->User_Acceptance_Flag = TRUE;
+        OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+        current_generated_state->cost =
+          user_cost_function (current_generated_state->parameter,
+                              parameter_minimum,
+                              parameter_maximum,
+                              tangents,
+                              curvature,
+                              number_parameters,
+                              parameter_type,
+                              valid_state_generated_flag,
+                              exit_status, OPTIONS);
+        if (cost_function_test (current_generated_state->cost,
+                                current_generated_state->parameter,
+                                parameter_minimum,
+                                parameter_maximum, number_parameters,
+                                xnumber_parameters) == 0) {
+          *exit_status = INVALID_COST_FUNCTION_DERIV;
+          return;
+        }
+        if (*valid_state_generated_flag == FALSE)
+          ++(*number_invalid_generated_states);
+        new_cost_state_1 = current_generated_state->cost;
+
+        /* restore the v_th parameter */
+        current_generated_state->parameter[index_v] = parameter_v;
+
+        /* generate second sample point */
+        *valid_state_generated_flag = TRUE;
+#if USER_ACCEPTANCE_TEST
+        OPTIONS->User_Acceptance_Flag = TRUE;
+        OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+        current_generated_state->cost =
+          user_cost_function (current_generated_state->parameter,
+                              parameter_minimum,
+                              parameter_maximum,
+                              tangents,
+                              curvature,
+                              number_parameters,
+                              parameter_type,
+                              valid_state_generated_flag,
+                              exit_status, OPTIONS);
+        if (cost_function_test (current_generated_state->cost,
+                                current_generated_state->parameter,
+                                parameter_minimum,
+                                parameter_maximum, number_parameters,
+                                xnumber_parameters) == 0) {
+          *exit_status = INVALID_COST_FUNCTION_DERIV;
+          return;
+        }
+        if (*valid_state_generated_flag == FALSE)
+          ++(*number_invalid_generated_states);
+        new_cost_state_2 = current_generated_state->cost;
+
+        /* restore the vv_th parameter */
+        current_generated_state->parameter[index_vv] = parameter_vv;
+
+        /* generate third sample point */
+        current_generated_state->parameter[index_v] =
+          (ONE + delta_parameter_v) * parameter_v;
+        *valid_state_generated_flag = TRUE;
+#if USER_ACCEPTANCE_TEST
+        OPTIONS->User_Acceptance_Flag = TRUE;
+        OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+        current_generated_state->cost =
+          user_cost_function (current_generated_state->parameter,
+                              parameter_minimum,
+                              parameter_maximum,
+                              tangents,
+                              curvature,
+                              number_parameters,
+                              parameter_type,
+                              valid_state_generated_flag,
+                              exit_status, OPTIONS);
+        if (cost_function_test (current_generated_state->cost,
+                                current_generated_state->parameter,
+                                parameter_minimum,
+                                parameter_maximum, number_parameters,
+                                xnumber_parameters) == 0) {
+          *exit_status = INVALID_COST_FUNCTION_DERIV;
+          return;
+        }
+        if (*valid_state_generated_flag == FALSE)
+          ++(*number_invalid_generated_states);
+        new_cost_state_3 = current_generated_state->cost;
+
+        /* restore the v_th parameter */
+        current_generated_state->parameter[index_v] = parameter_v;
+
+        /* calculate and store the curvature */
+        curvature[index_vv_v] = curvature[index_v_vv] =
+          (new_cost_state_1 - new_cost_state_2
+           - new_cost_state_3 + recent_best_cost)
+          / (delta_parameter_v * delta_parameter_vv
+             * parameter_v * parameter_vv + (double) EPS_DOUBLE);
+      }
+    }
+  }
+
+  /* restore Immediate_Exit flag */
+  OPTIONS->Immediate_Exit = immediate_flag;
+
+  /* restore the best cost function value */
+  current_generated_state->cost = recent_best_cost;
+#if ASA_PRINT
+  tmp_saved = *number_invalid_generated_states - saved_num_invalid_gen_states;
+  if (tmp_saved > 0)
+#if INT_LONG
+    fprintf (ptr_asa_out,
+             "Generated %ld invalid states when calculating the derivatives\n",
+             tmp_saved);
+#else
+    fprintf (ptr_asa_out,
+             "Generated %d invalid states when calculating the derivatives\n",
+             tmp_saved);
+#endif
+#endif /* ASA_PRINT */
+  *number_invalid_generated_states = saved_num_invalid_gen_states;
+#if USER_ACCEPTANCE_TEST
+  OPTIONS->User_Acceptance_Flag = TRUE;
+  OPTIONS->Cost_Acceptance_Flag = FALSE;
+#endif
+}
+
+/***********************************************************************
+* asa_test_asa_options
+*       Tests user's selected options
+***********************************************************************/
+#if HAVE_ANSI
+int
+
+asa_test_asa_options (LONG_INT * seed,
+                      double *parameter_initial_final,
+                      double *parameter_minimum,
+                      double *parameter_maximum,
+                      double *tangents,
+                      double *curvature,
+                      ALLOC_INT * number_parameters,
+                      int *parameter_type,
+                      int *valid_state_generated_flag,
+                      int *exit_status,
+                      FILE * ptr_asa_out, USER_DEFINES * OPTIONS)
+#else
+int
+
+asa_test_asa_options (seed,
+                      parameter_initial_final,
+                      parameter_minimum,
+                      parameter_maximum,
+                      tangents,
+                      curvature,
+                      number_parameters,
+                      parameter_type,
+                      valid_state_generated_flag,
+                      exit_status, ptr_asa_out, OPTIONS)
+     LONG_INT *seed;
+     double *parameter_initial_final;
+     double *parameter_minimum;
+     double *parameter_maximum;
+     double *tangents;
+     double *curvature;
+     ALLOC_INT *number_parameters;
+     int *parameter_type;
+     int *valid_state_generated_flag;
+     int *exit_status;
+     FILE *ptr_asa_out;
+     USER_DEFINES *OPTIONS;
+#endif /* HAVE_ANSI */
+{
+  int invalid, index_v;
+
+  invalid = 0;
+
+  if (seed == NULL) {
+    strcpy (exit_msg, "*** seed == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (parameter_initial_final == NULL) {
+    strcpy (exit_msg, "*** parameter_initial_final == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (parameter_minimum == NULL) {
+    strcpy (exit_msg, "*** parameter_minimum == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (parameter_maximum == NULL) {
+    strcpy (exit_msg, "*** parameter_maximum == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (tangents == NULL) {
+    strcpy (exit_msg, "*** tangents == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Curvature_0 == FALSE || OPTIONS->Curvature_0 == -1) {
+    if (curvature == NULL) {
+      strcpy (exit_msg, "*** curvature == NULL ***");
+      print_string (ptr_asa_out, exit_msg);
+      ++invalid;
+    }
+  }
+  if (number_parameters == NULL) {
+    strcpy (exit_msg, "*** number_parameters == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (parameter_type == NULL) {
+    strcpy (exit_msg, "*** parameter_type == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (valid_state_generated_flag == NULL) {
+    strcpy (exit_msg, "*** valid_state_generated_flag == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (exit_status == NULL) {
+    strcpy (exit_msg, "*** exit_status == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS == NULL) {
+    strcpy (exit_msg, "*** OPTIONS == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+
+  VFOR (index_v) if (parameter_minimum[index_v] > parameter_maximum[index_v]) {
+    strcpy (exit_msg, "*** parameter_minimum[] > parameter_maximum[] ***");
+    print_string_index (ptr_asa_out, exit_msg, index_v);
+    ++invalid;
+  }
+  VFOR (index_v)
+    if (parameter_initial_final[index_v] < parameter_minimum[index_v]) {
+    if (PARAMETER_RANGE_TOO_SMALL (index_v))
+      continue;
+    strcpy (exit_msg, "*** parameter_initial[] < parameter_minimum[] ***");
+    print_string_index (ptr_asa_out, exit_msg, index_v);
+    ++invalid;
+  }
+  VFOR (index_v)
+    if (parameter_initial_final[index_v] > parameter_maximum[index_v]) {
+    if (PARAMETER_RANGE_TOO_SMALL (index_v))
+      continue;
+    strcpy (exit_msg, "*** parameter_initial[] > parameter_maximum[] ***");
+    print_string_index (ptr_asa_out, exit_msg, index_v);
+    ++invalid;
+  }
+  if (*number_parameters < 1) {
+    strcpy (exit_msg, "*** *number_parameters < 1 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  VFOR (index_v)
+    if (parameter_type[index_v] != -2 && parameter_type[index_v] != 2
+        && parameter_type[index_v] != -1 && parameter_type[index_v] != 1) {
+    strcpy (exit_msg,
+            "*** parameter_type[] != -2 && parameter_type[] != 2 && parameter_type[] != -1 && parameter_type[] != 1 ***");
+    print_string_index (ptr_asa_out, exit_msg, index_v);
+    ++invalid;
+  }
+
+  if (OPTIONS_FILE != FALSE && OPTIONS_FILE != TRUE) {
+    strcpy (exit_msg,
+            "*** OPTIONS_FILE != FALSE && OPTIONS_FILE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS_FILE_DATA != FALSE && OPTIONS_FILE_DATA != TRUE) {
+    strcpy (exit_msg,
+            "*** OPTIONS_FILE_DATA != FALSE && OPTIONS_FILE_DATA != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (RECUR_OPTIONS_FILE != FALSE && RECUR_OPTIONS_FILE != TRUE) {
+    strcpy (exit_msg,
+            "*** RECUR_OPTIONS_FILE != FALSE && RECUR_OPTIONS_FILE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (RECUR_OPTIONS_FILE_DATA != FALSE && RECUR_OPTIONS_FILE_DATA != TRUE) {
+    strcpy (exit_msg,
+            "*** RECUR_OPTIONS_FILE_DATA != FALSE && RECUR_OPTIONS_FILE_DATA != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (COST_FILE != FALSE && COST_FILE != TRUE) {
+    strcpy (exit_msg, "*** COST_FILE != FALSE && COST_FILE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_LIB != FALSE && ASA_LIB != TRUE) {
+    strcpy (exit_msg, "*** ASA_LIB != FALSE && ASA_LIB != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (MY_TEMPLATE != FALSE && MY_TEMPLATE != TRUE) {
+    strcpy (exit_msg, "*** MY_TEMPLATE != FALSE && MY_TEMPLATE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_TEMPLATE_LIB != FALSE && ASA_TEMPLATE_LIB != TRUE) {
+    strcpy (exit_msg,
+            "*** ASA_TEMPLATE_LIB != FALSE && ASA_TEMPLATE_LIB != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (HAVE_ANSI != FALSE && HAVE_ANSI != TRUE) {
+    strcpy (exit_msg, "*** HAVE_ANSI != FALSE && HAVE_ANSI != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (IO_PROTOTYPES != FALSE && IO_PROTOTYPES != TRUE) {
+    strcpy (exit_msg,
+            "*** IO_PROTOTYPES != FALSE && IO_PROTOTYPES != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (TIME_CALC != FALSE && TIME_CALC != TRUE) {
+    strcpy (exit_msg, "*** TIME_CALC != FALSE && TIME_CALC != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (TIME_STD != FALSE && TIME_STD != TRUE) {
+    strcpy (exit_msg, "*** TIME_STD != FALSE && TIME_STD != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (TIME_GETRUSAGE != FALSE && TIME_GETRUSAGE != TRUE) {
+    strcpy (exit_msg,
+            "*** TIME_GETRUSAGE != FALSE && TIME_GETRUSAGE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (INT_LONG != FALSE && INT_LONG != TRUE) {
+    strcpy (exit_msg, "*** INT_LONG != FALSE && INT_LONG != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (INT_ALLOC != FALSE && INT_ALLOC != TRUE) {
+    strcpy (exit_msg, "*** INT_ALLOC != FALSE && INT_ALLOC != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (SMALL_FLOAT < ZERO) {
+    strcpy (exit_msg, "*** SMALL_FLOAT < ZERO ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (MIN_DOUBLE < ZERO) {
+    strcpy (exit_msg, "*** MIN_DOUBLE < ZERO ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (MAX_DOUBLE < ZERO) {
+    strcpy (exit_msg, "*** MAX_DOUBLE < ZERO ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (EPS_DOUBLE < ZERO) {
+    strcpy (exit_msg, "*** EPS_DOUBLE < ZERO ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (CHECK_EXPONENT != FALSE && CHECK_EXPONENT != TRUE) {
+    strcpy (exit_msg,
+            "*** CHECK_EXPONENT != FALSE && CHECK_EXPONENT != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (NO_PARAM_TEMP_TEST != FALSE && NO_PARAM_TEMP_TEST != TRUE) {
+    strcpy (exit_msg,
+            "*** NO_PARAM_TEMP_TEST != FALSE && NO_PARAM_TEMP_TEST != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (NO_COST_TEMP_TEST != FALSE && NO_COST_TEMP_TEST != TRUE) {
+    strcpy (exit_msg,
+            "*** NO_COST_TEMP_TEST != FALSE && NO_COST_TEMP_TEST != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (SELF_OPTIMIZE != FALSE && SELF_OPTIMIZE != TRUE) {
+    strcpy (exit_msg,
+            "*** SELF_OPTIMIZE != FALSE && SELF_OPTIMIZE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_TEST != FALSE && ASA_TEST != TRUE) {
+    strcpy (exit_msg, "*** ASA_TEST != FALSE && ASA_TEST != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_TEST_POINT != FALSE && ASA_TEST_POINT != TRUE) {
+    strcpy (exit_msg,
+            "*** ASA_TEST_POINT != FALSE && ASA_TEST_POINT != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_TEMPLATE != FALSE) {
+    strcpy (exit_msg, "*** ASA_TEMPLATE != FALSE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_TEMPLATE_ASA_OUT_PID != FALSE && ASA_TEMPLATE_ASA_OUT_PID != TRUE) {
+    strcpy (exit_msg,
+            "*** ASA_TEMPLATE_ASA_OUT_PID != FALSE && ASA_TEMPLATE_ASA_OUT_PID != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_TEMPLATE_MULTIPLE != FALSE && ASA_TEMPLATE_MULTIPLE != TRUE) {
+    strcpy (exit_msg,
+            "*** ASA_TEMPLATE_MULTIPLE != FALSE && ASA_TEMPLATE_MULTIPLE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_TEMPLATE_SELFOPT != FALSE && ASA_TEMPLATE_SELFOPT != TRUE) {
+    strcpy (exit_msg,
+            "*** ASA_TEMPLATE_SELFOPT != FALSE && ASA_TEMPLATE_SELFOPT != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_TEMPLATE_SAMPLE != FALSE && ASA_TEMPLATE_SAMPLE != TRUE) {
+    strcpy (exit_msg,
+            "*** ASA_TEMPLATE_SAMPLE != FALSE && ASA_TEMPLATE_SAMPLE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_TEMPLATE_QUEUE != FALSE && ASA_TEMPLATE_QUEUE != TRUE) {
+    strcpy (exit_msg,
+            "*** ASA_TEMPLATE_QUEUE != FALSE && ASA_TEMPLATE_QUEUE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_TEMPLATE_PARALLEL != FALSE && ASA_TEMPLATE_PARALLEL != TRUE) {
+    strcpy (exit_msg,
+            "*** ASA_TEMPLATE_PARALLEL != FALSE && ASA_TEMPLATE_PARALLEL != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_TEMPLATE_SAVE != FALSE && ASA_TEMPLATE_SAVE != TRUE) {
+    strcpy (exit_msg,
+            "*** ASA_TEMPLATE_SAVE != FALSE && ASA_TEMPLATE_SAVE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (USER_INITIAL_COST_TEMP != FALSE && USER_INITIAL_COST_TEMP != TRUE) {
+    strcpy (exit_msg,
+            "*** USER_INITIAL_COST_TEMP != FALSE && USER_INITIAL_COST_TEMP != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (RATIO_TEMPERATURE_SCALES != FALSE && RATIO_TEMPERATURE_SCALES != TRUE) {
+    strcpy (exit_msg,
+            "*** RATIO_TEMPERATURE_SCALES != FALSE && RATIO_TEMPERATURE_SCALES != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (USER_INITIAL_PARAMETERS_TEMPS != FALSE
+      && USER_INITIAL_PARAMETERS_TEMPS != TRUE) {
+    strcpy (exit_msg,
+            "*** USER_INITIAL_PARAMETERS_TEMPS != FALSE && USER_INITIAL_PARAMETERS_TEMPS != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (DELTA_PARAMETERS != FALSE && DELTA_PARAMETERS != TRUE) {
+    strcpy (exit_msg,
+            "*** DELTA_PARAMETERS != FALSE && DELTA_PARAMETERS != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (QUENCH_PARAMETERS != FALSE && QUENCH_PARAMETERS != TRUE) {
+    strcpy (exit_msg,
+            "*** QUENCH_PARAMETERS != FALSE && QUENCH_PARAMETERS != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (QUENCH_COST != FALSE && QUENCH_COST != TRUE) {
+    strcpy (exit_msg, "*** QUENCH_COST != FALSE && QUENCH_COST != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (QUENCH_PARAMETERS_SCALE != FALSE && QUENCH_PARAMETERS_SCALE != TRUE) {
+    strcpy (exit_msg,
+            "*** QUENCH_PARAMETERS_SCALE != FALSE && QUENCH_PARAMETERS_SCALE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (QUENCH_COST_SCALE != FALSE && QUENCH_COST_SCALE != TRUE) {
+    strcpy (exit_msg,
+            "*** QUENCH_COST_SCALE != FALSE && QUENCH_COST_SCALE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONAL_DATA_DBL != FALSE && OPTIONAL_DATA_DBL != TRUE) {
+    strcpy (exit_msg,
+            "*** OPTIONAL_DATA_DBL != FALSE && OPTIONAL_DATA_DBL != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONAL_DATA_INT != FALSE && OPTIONAL_DATA_INT != TRUE) {
+    strcpy (exit_msg,
+            "*** OPTIONAL_DATA_INT != FALSE && OPTIONAL_DATA_INT != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONAL_DATA_PTR != FALSE && OPTIONAL_DATA_PTR != TRUE) {
+    strcpy (exit_msg,
+            "*** OPTIONAL_DATA_PTR != FALSE && OPTIONAL_DATA_PTR != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (USER_COST_SCHEDULE != FALSE && USER_COST_SCHEDULE != TRUE) {
+    strcpy (exit_msg,
+            "*** USER_COST_SCHEDULE != FALSE && USER_COST_SCHEDULE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (USER_ACCEPT_ASYMP_EXP != FALSE && USER_ACCEPT_ASYMP_EXP != TRUE) {
+    strcpy (exit_msg,
+            "*** USER_ACCEPT_ASYMP_EXP != FALSE && USER_ACCEPT_ASYMP_EXP != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (USER_ACCEPT_THRESHOLD != FALSE && USER_ACCEPT_THRESHOLD != TRUE) {
+    strcpy (exit_msg,
+            "*** USER_ACCEPT_THRESHOLD != FALSE && USER_ACCEPT_THRESHOLD != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (USER_ACCEPTANCE_TEST != FALSE && USER_ACCEPTANCE_TEST != TRUE) {
+    strcpy (exit_msg,
+            "*** USER_ACCEPTANCE_TEST != FALSE && USER_ACCEPTANCE_TEST != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (USER_GENERATING_FUNCTION != FALSE && USER_GENERATING_FUNCTION != TRUE) {
+    strcpy (exit_msg,
+            "*** USER_GENERATING_FUNCTION != FALSE && USER_GENERATING_FUNCTION != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (USER_REANNEAL_COST != FALSE && USER_REANNEAL_COST != TRUE) {
+    strcpy (exit_msg,
+            "*** USER_REANNEAL_COST != FALSE && USER_REANNEAL_COST != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (USER_REANNEAL_PARAMETERS != FALSE && USER_REANNEAL_PARAMETERS != TRUE) {
+    strcpy (exit_msg,
+            "*** USER_REANNEAL_PARAMETERS != FALSE && USER_REANNEAL_PARAMETERS != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (MAXIMUM_REANNEAL_INDEX < 1) {
+    strcpy (exit_msg, "*** MAXIMUM_REANNEAL_INDEX < 1 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (REANNEAL_SCALE < ZERO) {
+    strcpy (exit_msg, "*** REANNEAL_SCALE < ZERO ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_SAMPLE != FALSE && ASA_SAMPLE != TRUE) {
+    strcpy (exit_msg, "*** ASA_SAMPLE != FALSE && ASA_SAMPLE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_QUEUE != FALSE && ASA_QUEUE != TRUE) {
+    strcpy (exit_msg, "*** ASA_QUEUE != FALSE && ASA_QUEUE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_RESOLUTION != FALSE && ASA_RESOLUTION != TRUE) {
+    strcpy (exit_msg,
+            "*** ASA_RESOLUTION != FALSE && ASA_RESOLUTION != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (FITLOC != FALSE && FITLOC != TRUE) {
+    strcpy (exit_msg, "*** FITLOC != FALSE && FITLOC != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (FITLOC_ROUND != FALSE && FITLOC_ROUND != TRUE) {
+    strcpy (exit_msg,
+            "*** FITLOC_ROUND != FALSE && FITLOC_ROUND != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (FITLOC_PRINT != FALSE && FITLOC_PRINT != TRUE) {
+    strcpy (exit_msg,
+            "*** FITLOC_PRINT != FALSE && FITLOC_PRINT != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (MULTI_MIN != FALSE && MULTI_MIN != TRUE) {
+    strcpy (exit_msg, "*** MULTI_MIN != FALSE && MULTI_MIN != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#if MULTI_MIN
+  if (OPTIONS->Multi_Number <= 0) {
+    strcpy (exit_msg, "*** OPTIONS->Multi_Number <= 0 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  VFOR (index_v) {
+    if (((OPTIONS->Multi_Grid[index_v]) != (OPTIONS->Multi_Grid[index_v]))
+        || OPTIONS->Multi_Grid[index_v] < 0) {
+      strcpy (exit_msg,
+              "*** (OPTIONS->Multi_Grid[]) != (OPTIONS->Multi_Grid[]) || OPTIONS->Multi_Grid[] < 0 ***");
+      print_string_index (ptr_asa_out, exit_msg, index_v);
+      ++invalid;
+    }
+  }
+  if (OPTIONS->Multi_Specify != 0 && OPTIONS->Multi_Specify != 1) {
+    strcpy (exit_msg,
+            "*** OPTIONS->Multi_Specify != 0 && OPTIONS->Multi_Specify != 1 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#endif
+  if (ASA_PARALLEL != FALSE && ASA_PARALLEL != TRUE) {
+    strcpy (exit_msg,
+            "*** ASA_PARALLEL != FALSE && ASA_PARALLEL != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_SAVE != FALSE && ASA_SAVE != TRUE) {
+    strcpy (exit_msg, "*** ASA_SAVE != FALSE && ASA_SAVE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_SAVE_OPT != FALSE && ASA_SAVE_OPT != TRUE) {
+    strcpy (exit_msg,
+            "*** ASA_SAVE_OPT != FALSE && ASA_SAVE_OPT != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_SAVE_BACKUP != FALSE && ASA_SAVE_BACKUP != TRUE) {
+    strcpy (exit_msg,
+            "*** ASA_SAVE_BACKUP != FALSE && ASA_SAVE_BACKUP != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_PIPE != FALSE && ASA_PIPE != TRUE) {
+    strcpy (exit_msg, "*** ASA_PIPE != FALSE && ASA_PIPE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_PIPE_FILE != FALSE && ASA_PIPE_FILE != TRUE) {
+    strcpy (exit_msg,
+            "*** ASA_PIPE_FILE != FALSE && ASA_PIPE_FILE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (SYSTEM_CALL != FALSE && SYSTEM_CALL != TRUE) {
+    strcpy (exit_msg, "*** SYSTEM_CALL != FALSE && SYSTEM_CALL != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (FDLIBM_POW != FALSE && FDLIBM_POW != TRUE) {
+    strcpy (exit_msg, "*** FDLIBM_POW != FALSE && FDLIBM_POW != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (FDLIBM_LOG != FALSE && FDLIBM_LOG != TRUE) {
+    strcpy (exit_msg, "*** FDLIBM_LOG != FALSE && FDLIBM_LOG != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (FDLIBM_EXP != FALSE && FDLIBM_EXP != TRUE) {
+    strcpy (exit_msg, "*** FDLIBM_EXP != FALSE && FDLIBM_EXP != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_PRINT != FALSE && ASA_PRINT != TRUE) {
+    strcpy (exit_msg, "*** ASA_PRINT != FALSE && ASA_PRINT != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (USER_ASA_OUT != FALSE && USER_ASA_OUT != TRUE) {
+    strcpy (exit_msg,
+            "*** USER_ASA_OUT != FALSE && USER_ASA_OUT != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_PRINT_INTERMED != FALSE && ASA_PRINT_INTERMED != TRUE) {
+    strcpy (exit_msg,
+            "*** ASA_PRINT_INTERMED != FALSE && ASA_PRINT_INTERMED != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (ASA_PRINT_MORE != FALSE && ASA_PRINT_MORE != TRUE) {
+    strcpy (exit_msg,
+            "*** ASA_PRINT_MORE != FALSE && ASA_PRINT_MORE != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (G_FIELD < 0) {
+    strcpy (exit_msg, "*** G_FIELD < 0 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (G_PRECISION < 0) {
+    strcpy (exit_msg, "*** G_PRECISION < 0 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+
+  if (OPTIONS->Limit_Acceptances < 0) {
+    strcpy (exit_msg, "*** Limit_Acceptances < 0 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Limit_Generated < 0) {
+    strcpy (exit_msg, "*** Limit_Generated < 0 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Limit_Invalid_Generated_States < 0) {
+    strcpy (exit_msg, "*** Limit_Invalid_Generated_States < 0 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Accepted_To_Generated_Ratio <= ZERO) {
+    strcpy (exit_msg, "*** Accepted_To_Generated_Ratio <= ZERO ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Cost_Precision <= ZERO) {
+    strcpy (exit_msg, "*** Cost_Precision <= ZERO ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Maximum_Cost_Repeat < 0) {
+    strcpy (exit_msg, "*** Maximum_Cost_Repeat < 0 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Number_Cost_Samples == 0 || OPTIONS->Number_Cost_Samples == -1) {
+    strcpy (exit_msg,
+            "*** Number_Cost_Samples == 0 || Number_Cost_Samples == -1 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Temperature_Ratio_Scale <= ZERO) {
+    strcpy (exit_msg, "*** Temperature_Ratio_Scale <= ZERO ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Cost_Parameter_Scale_Ratio <= ZERO) {
+    strcpy (exit_msg, "*** Cost_Parameter_Scale_Ratio <= ZERO ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Temperature_Anneal_Scale <= ZERO) {
+    strcpy (exit_msg, "*** Temperature_Anneal_Scale <= ZERO ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#if USER_INITIAL_COST_TEMP
+  if (OPTIONS->User_Cost_Temperature[0] <= ZERO) {
+    strcpy (exit_msg, "*** User_Cost_Temperature[0] <= ZERO ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#endif
+  if (OPTIONS->Include_Integer_Parameters != FALSE
+      && OPTIONS->Include_Integer_Parameters != TRUE) {
+    strcpy (exit_msg, "");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->User_Initial_Parameters != FALSE
+      && OPTIONS->User_Initial_Parameters != TRUE) {
+    strcpy (exit_msg,
+            "*** User_Initial_Parameters != FALSE && User_Initial_Parameters != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Sequential_Parameters >= *number_parameters) {
+    strcpy (exit_msg, "*** Sequential_Parameters >= *number_parameters ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Initial_Parameter_Temperature <= ZERO) {
+    strcpy (exit_msg, "*** Initial_Parameter_Temperature <= ZERO ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#if RATIO_TEMPERATURE_SCALES
+  VFOR (index_v) if (OPTIONS->User_Temperature_Ratio[index_v] <= ZERO) {
+    strcpy (exit_msg, "*** User_Temperature_Ratio[] <= ZERO ***");
+    print_string_index (ptr_asa_out, exit_msg, index_v);
+    ++invalid;
+  }
+#endif
+#if USER_INITIAL_PARAMETERS_TEMPS
+  VFOR (index_v) if (OPTIONS->User_Parameter_Temperature[index_v] <= ZERO) {
+    strcpy (exit_msg, "*** User_Parameter_Temperature[] <= ZERO ***");
+    print_string_index (ptr_asa_out, exit_msg, index_v);
+    ++invalid;
+  }
+#endif
+  if (OPTIONS->Acceptance_Frequency_Modulus < 0) {
+    strcpy (exit_msg, "*** Acceptance_Frequency_Modulus < 0 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Generated_Frequency_Modulus < 0) {
+    strcpy (exit_msg, "*** Generated_Frequency_Modulus < 0 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Reanneal_Cost == -1) {
+    strcpy (exit_msg, "*** Reanneal_Cost == -1 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Reanneal_Parameters != FALSE
+      && OPTIONS->Reanneal_Parameters != TRUE) {
+    strcpy (exit_msg,
+            "*** Reanneal_Parameters != FALSE && Reanneal_Parameters != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Delta_X <= ZERO) {
+    strcpy (exit_msg, "*** Delta_X <= ZERO ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#if DELTA_PARAMETERS
+  VFOR (index_v) if (OPTIONS->User_Delta_Parameter[index_v] <= ZERO) {
+    strcpy (exit_msg, "*** User_Delta_Parameter[] <= ZERO ***");
+    print_string_index (ptr_asa_out, exit_msg, index_v);
+    ++invalid;
+  }
+#endif
+  if (OPTIONS->User_Tangents != FALSE && OPTIONS->User_Tangents != TRUE) {
+    strcpy (exit_msg,
+            "*** User_Tangents != FALSE && User_Tangents != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Curvature_0 != -1 && OPTIONS->Curvature_0 != FALSE
+      && OPTIONS->Curvature_0 != TRUE) {
+    strcpy (exit_msg,
+            "*** Curvature_0 -1 && Curvature_0 != FALSE && Curvature_0 != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#if QUENCH_PARAMETERS
+  VFOR (index_v) if (OPTIONS->User_Quench_Param_Scale[index_v] <= ZERO) {
+    strcpy (exit_msg, "*** User_Quench_Param_Scale[] <= ZERO ***");
+    print_string_index (ptr_asa_out, exit_msg, index_v);
+    ++invalid;
+  }
+#endif
+#if QUENCH_COST
+  if (OPTIONS->User_Quench_Cost_Scale[0] <= ZERO) {
+    strcpy (exit_msg, "*** User_Quench_Cost_Scale[0] <= ZERO ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#endif
+#if OPTIONAL_DATA_DBL
+  if (OPTIONS->Asa_Data_Dim_Dbl < 1) {
+    strcpy (exit_msg, "*** Asa_Data_Dim_Dbl < 1 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Asa_Data_Dbl == NULL) {
+    strcpy (exit_msg, "*** Asa_Data_Dbl == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#endif
+#if ASA_SAVE
+  if (OPTIONS->Random_Array_Dim < 1) {
+    strcpy (exit_msg, "*** Random_Array_Dim < 1 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Random_Array == NULL) {
+    strcpy (exit_msg, "*** Random_Array == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#endif
+#if OPTIONAL_DATA_INT
+  if (OPTIONS->Asa_Data_Dim_Int < 1) {
+    strcpy (exit_msg, "*** Asa_Data_Dim_Int < 1 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Asa_Data_Int == NULL) {
+    strcpy (exit_msg, "*** Asa_Data_Int == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#endif
+#if OPTIONAL_DATA_PTR
+  if (OPTIONS->Asa_Data_Dim_Ptr < 1) {
+    strcpy (exit_msg, "*** Asa_Data_Dim_Ptr < 1 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Asa_Data_Ptr == NULL) {
+    strcpy (exit_msg, "*** Asa_Data_Ptr == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#endif
+#if USER_ASA_OUT
+  if (OPTIONS->Asa_Out_File == NULL) {
+    strcpy (exit_msg, "*** Asa_Out_File == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#endif
+#if USER_COST_SCHEDULE
+  if (OPTIONS->Cost_Schedule == NULL) {
+    strcpy (exit_msg, "*** Cost_Schedule == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#endif
+#if USER_ACCEPTANCE_TEST
+  if (OPTIONS->Acceptance_Test == NULL) {
+    strcpy (exit_msg, "*** Acceptance_Test == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->User_Acceptance_Flag != FALSE
+      && OPTIONS->User_Acceptance_Flag != TRUE) {
+    strcpy (exit_msg,
+            "*** User_Acceptance_Flag != FALSE && User_Acceptance_Flag != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Cost_Acceptance_Flag != FALSE
+      && OPTIONS->Cost_Acceptance_Flag != TRUE) {
+    strcpy (exit_msg,
+            "*** Cost_Acceptance_Flag != FALSE && Cost_Acceptance_Flag != TRUE ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#endif
+#if USER_GENERATING_FUNCTION
+  if (OPTIONS->Generating_Distrib == NULL) {
+    strcpy (exit_msg, "*** Generating_Distrib == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#endif
+#if USER_REANNEAL_COST
+  if (OPTIONS->Reanneal_Cost_Function == NULL) {
+    strcpy (exit_msg, "*** Reanneal_Cost_Function == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#endif
+#if USER_REANNEAL_PARAMETERS
+  if (OPTIONS->Reanneal_Params_Function == NULL) {
+    strcpy (exit_msg, "*** Reanneal_Params_Function == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#endif
+#if ASA_SAMPLE
+  if (OPTIONS->Bias_Generated == NULL) {
+    strcpy (exit_msg, "*** Bias_Generated == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Limit_Weights < ZERO) {
+    strcpy (exit_msg, "*** Limit_Weights < ZERO ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#endif
+#if ASA_QUEUE
+  if (OPTIONS->Queue_Size < 0) {
+    strcpy (exit_msg, "*** Queue_Size < 0 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Queue_Size > 0) {
+    if (OPTIONS->Queue_Resolution == NULL) {
+      strcpy (exit_msg, "*** Queue_Resolution == NULL ***");
+      print_string (ptr_asa_out, exit_msg);
+      ++invalid;
+    }
+  }
+#endif
+#if ASA_RESOLUTION
+  if (OPTIONS->Coarse_Resolution == NULL) {
+    strcpy (exit_msg, "*** Coarse_Resolution == NULL ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#endif
+#if ASA_PARALLEL
+  if (OPTIONS->Gener_Block < 1) {
+    strcpy (exit_msg, "*** Gener_Block < 1 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Gener_Block_Max < 1) {
+    strcpy (exit_msg, "*** Gener_Block_Max < 1 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+  if (OPTIONS->Gener_Mov_Avr < 1) {
+    strcpy (exit_msg, "*** Gener_Mov_Avr < 1 ***");
+    print_string (ptr_asa_out, exit_msg);
+    ++invalid;
+  }
+#endif
+
+  return (invalid);
+}
+
+/***********************************************************************
+* cost_function_test
+*       Tests user's returned cost function values and parameters
+***********************************************************************/
+#if HAVE_ANSI
+int
+
+cost_function_test (double cost,
+                    double *parameter,
+                    double *parameter_minimum,
+                    double *parameter_maximum,
+                    ALLOC_INT * number_parameters, double *xnumber_parameters)
+#else
+int
+
+cost_function_test (cost,
+                    parameter,
+                    parameter_minimum, parameter_maximum,
+                    number_parameters, xnumber_parameters)
+     double cost;
+     double *parameter;
+     double *parameter_minimum;
+     double *parameter_maximum;
+     ALLOC_INT *number_parameters;
+     double *xnumber_parameters;
+#endif /* HAVE_ANSI */
+{
+  ALLOC_INT index_v;
+  int test_flag;
+
+  test_flag = 1;
+
+  if (((cost) != (cost)) || (cost < -MAX_DOUBLE || cost > MAX_DOUBLE))
+    test_flag = 0;
+
+  *xnumber_parameters = (double) *number_parameters;
+  VFOR (index_v) {
+    if (PARAMETER_RANGE_TOO_SMALL (index_v)) {
+      *xnumber_parameters -= 1.0;
+      continue;
+    }
+    if (parameter[index_v] < parameter_minimum[index_v] ||
+        parameter[index_v] > parameter_maximum[index_v]) {
+      test_flag = 0;
+    }
+  }
+
+  return (test_flag);
+}
+
+/***********************************************************************
+* print_string
+*	This prints the designated string
+***********************************************************************/
+#if HAVE_ANSI
+void
+print_string (FILE * ptr_asa_out, char *string)
+#else
+void
+print_string (ptr_asa_out, string)
+     FILE *ptr_asa_out;
+     char *string;
+#endif /* HAVE_ANSI */
+{
+#if INCL_STDOUT
+  printf ("\n\n%s\n\n", string);
+#endif /* INCL_STDOUT */
+#if ASA_PRINT
+  fprintf (ptr_asa_out, "\n\n%s\n\n", string);
+#else
+#endif
+}
+
+/***********************************************************************
+* print_string_index
+*	This prints the designated string and index
+***********************************************************************/
+#if HAVE_ANSI
+void
+print_string_index (FILE * ptr_asa_out, char *string, ALLOC_INT index)
+#else
+void
+print_string_index (ptr_asa_out, string, index)
+     FILE *ptr_asa_out;
+     char *string;
+     ALLOC_INT index;
+#endif /* HAVE_ANSI */
+{
+#if INCL_STDOUT
+#if INT_ALLOC
+  printf ("\n\n%s index = %d\n\n", string, index);
+#else /* INT_ALLOC */
+#if INT_LONG
+  printf ("\n\n%s index = %ld\n\n", string, index);
+#else /* INT_LONG */
+  printf ("\n\n%s index = %ld\n\n", string, index);
+#endif /* INT_LONG */
+#endif /* INT_ALLOC */
+#endif /* INCL_STDOUT */
+
+#if ASA_PRINT
+#if INT_ALLOC
+  fprintf (ptr_asa_out, "\n\n%s index = %d\n\n", string, index);
+#else /* INT_ALLOC */
+#if INT_LONG
+  fprintf (ptr_asa_out, "\n\n%s index = %ld\n\n", string, index);
+#else /* INT_LONG */
+  fprintf (ptr_asa_out, "\n\n%s index = %d\n\n", string, index);
+#endif /* INT_LONG */
+#endif /* INT_ALLOC */
+#else /* ASA_PRINT */
+  ;
+#endif /* ASA_PRINT */
+}
+
+#if ASA_PRINT
+/***********************************************************************
+* print_state
+*	Prints a description of the current state of the system
+***********************************************************************/
+void
+print_state (double *parameter_minimum,
+             double *parameter_maximum,
+             double *tangents,
+             double *curvature,
+             double *current_cost_temperature,
+             double *current_user_parameter_temp,
+             double *accepted_to_generated_ratio,
+             ALLOC_INT * number_parameters,
+             int *curvature_flag,
+             LONG_INT * number_accepted,
+             LONG_INT * index_cost_acceptances,
+             LONG_INT * number_generated,
+             LONG_INT * number_invalid_generated_states,
+             STATE * last_saved_state,
+             STATE * best_generated_state,
+             FILE * ptr_asa_out, USER_DEFINES * OPTIONS)
+{
+  ALLOC_INT index_v;
+  ALLOC_INT index_vv, index_v_vv;
+
+  fprintf (ptr_asa_out, "\n");
+#if TIME_CALC
+  print_time ("", ptr_asa_out);
+#endif
+
+  if (OPTIONS->Curvature_0 == TRUE)
+    *curvature_flag = FALSE;
+  if (OPTIONS->Curvature_0 == -1)
+    *curvature_flag = TRUE;
+
+#if INT_LONG
+  fprintf (ptr_asa_out,
+           "*index_cost_acceptances = %ld, *current_cost_temperature = %*.*g\n",
+           *index_cost_acceptances,
+           G_FIELD, G_PRECISION, *current_cost_temperature);
+  fprintf (ptr_asa_out, "*accepted_to_generated_ratio = %*.*g,\
+ *number_invalid... = %ld\n", G_FIELD, G_PRECISION, *accepted_to_generated_ratio, (*number_invalid_generated_states));
+  fprintf (ptr_asa_out,
+           "*number_generated = %ld, *number_accepted = %ld\n",
+           *number_generated, *number_accepted);
+#else
+  fprintf (ptr_asa_out,
+           "*index_cost_acceptances = %d, *current_cost_temperature = %*.*g\n",
+           *index_cost_acceptances,
+           G_FIELD, G_PRECISION, *current_cost_temperature);
+  fprintf (ptr_asa_out, "*accepted_to_generated_ratio = %*.*g,\
+ *number_invalid... = %d\n", G_FIELD, G_PRECISION, *accepted_to_generated_ratio, *number_invalid_generated_states);
+  fprintf (ptr_asa_out,
+           "*number_generated = %d, *number_accepted = %d\n",
+           *number_generated, *number_accepted);
+#endif
+
+  fprintf (ptr_asa_out, "best...->cost = %*.*g,\
+ last...->cost = %*.*g\n", G_FIELD, G_PRECISION, best_generated_state->cost, G_FIELD, G_PRECISION, last_saved_state->cost);
+
+  /* Note that tangents will not be calculated until reanneal
+     is called, and therefore their listing in the printout only
+     is relevant then */
+
+  fprintf (ptr_asa_out,
+           "index_v  best...->parameter current_parameter_temp\ttangent\n");
+  VFOR (index_v) {
+    /* ignore too small ranges */
+#if DROPPED_PARAMETERS
+    if (PARAMETER_RANGE_TOO_SMALL (index_v))
+      continue;
+#endif
+    fprintf (ptr_asa_out,
+#if INT_ALLOC
+             "%d\t%*.*g\t\t%*.*g\t%*.*g\n",
+#else
+#if INT_LONG
+             "%ld\t%*.*g\t\t%*.*g\t%*.*g\n",
+#else
+             "%d\t%*.*g\t\t%*.*g\t%*.*g\n",
+#endif
+#endif
+             index_v,
+             G_FIELD, G_PRECISION, best_generated_state->parameter[index_v],
+             G_FIELD, G_PRECISION, current_user_parameter_temp[index_v],
+             G_FIELD, G_PRECISION, tangents[index_v]);
+  }
+
+  if (*curvature_flag == TRUE) {
+    /* print curvatures */
+    VFOR (index_v) {
+      /* ignore too small ranges */
+      if (PARAMETER_RANGE_TOO_SMALL (index_v))
+        continue;
+      fprintf (ptr_asa_out, "\n");
+      VFOR (index_vv) {
+        /* only print upper diagonal of matrix */
+        if (index_v < index_vv)
+          continue;
+        /* ignore too small ranges (index_vv) */
+        if (PARAMETER_RANGE_TOO_SMALL (index_vv))
+          continue;
+
+        /* index_v_vv: row index_v, column index_vv */
+        index_v_vv = ROW_COL_INDEX (index_v, index_vv);
+
+        if (index_v == index_vv) {
+          fprintf (ptr_asa_out,
+#if INT_ALLOC
+                   "curvature[%d][%d] = %*.*g\n",
+#else
+#if INT_LONG
+                   "curvature[%ld][%ld] = %*.*g\n",
+#else
+                   "curvature[%d][%d] = %*.*g\n",
+#endif
+#endif
+                   index_v, index_vv,
+                   G_FIELD, G_PRECISION, curvature[index_v_vv]);
+        } else {
+          fprintf (ptr_asa_out,
+#if INT_ALLOC
+                   "curvature[%d][%d] = %*.*g \t = curvature[%d][%d]\n",
+#else
+#if INT_LONG
+                   "curvature[%ld][%ld] = %*.*g \t = curvature[%ld][%ld]\n",
+#else
+                   "curvature[%d][%d] = %*.*g \t = curvature[%d][%d]\n",
+#endif
+#endif
+                   index_v, index_vv,
+                   G_FIELD, G_PRECISION, curvature[index_v_vv],
+                   index_vv, index_v);
+        }
+      }
+    }
+  }
+  fprintf (ptr_asa_out, "\n");
+  fflush (ptr_asa_out);
+
+}
+
+/***********************************************************************
+* print_asa_options
+*	Prints user's selected options
+***********************************************************************/
+void
+print_asa_options (FILE * ptr_asa_out, USER_DEFINES * OPTIONS)
+{
+  fprintf (ptr_asa_out, "\t\tADAPTIVE SIMULATED ANNEALING\n\n");
+
+  fprintf (ptr_asa_out, "%s\n\n", ASA_ID);
+
+  fprintf (ptr_asa_out, "OPTIONS_FILE = %d\n", (int) OPTIONS_FILE);
+  fprintf (ptr_asa_out, "OPTIONS_FILE_DATA = %d\n", (int) OPTIONS_FILE_DATA);
+  fprintf (ptr_asa_out, "RECUR_OPTIONS_FILE = %d\n",
+           (int) RECUR_OPTIONS_FILE);
+  fprintf (ptr_asa_out, "RECUR_OPTIONS_FILE_DATA = %d\n",
+           (int) RECUR_OPTIONS_FILE_DATA);
+  fprintf (ptr_asa_out, "COST_FILE = %d\n", (int) COST_FILE);
+  fprintf (ptr_asa_out, "ASA_LIB = %d\n", (int) ASA_LIB);
+  fprintf (ptr_asa_out, "HAVE_ANSI = %d\n", (int) HAVE_ANSI);
+  fprintf (ptr_asa_out, "IO_PROTOTYPES = %d\n", (int) IO_PROTOTYPES);
+  fprintf (ptr_asa_out, "TIME_CALC = %d\n", (int) TIME_CALC);
+  fprintf (ptr_asa_out, "TIME_STD = %d\n", (int) TIME_STD);
+  fprintf (ptr_asa_out, "TIME_GETRUSAGE = %d\n", (int) TIME_GETRUSAGE);
+  fprintf (ptr_asa_out, "INT_LONG = %d\n", (int) INT_LONG);
+  fprintf (ptr_asa_out, "INT_ALLOC = %d\n", (int) INT_ALLOC);
+  fprintf (ptr_asa_out, "SMALL_FLOAT = %*.*g\n",
+           G_FIELD, G_PRECISION, (double) SMALL_FLOAT);
+  fprintf (ptr_asa_out, "MIN_DOUBLE = %*.*g\n",
+           G_FIELD, G_PRECISION, (double) MIN_DOUBLE);
+  fprintf (ptr_asa_out, "MAX_DOUBLE = %*.*g\n",
+           G_FIELD, G_PRECISION, (double) MAX_DOUBLE);
+  fprintf (ptr_asa_out, "EPS_DOUBLE = %*.*g\n",
+           G_FIELD, G_PRECISION, (double) EPS_DOUBLE);
+  fprintf (ptr_asa_out, "CHECK_EXPONENT = %d\n", (int) CHECK_EXPONENT);
+  fprintf (ptr_asa_out, "NO_PARAM_TEMP_TEST = %d\n",
+           (int) NO_PARAM_TEMP_TEST);
+  fprintf (ptr_asa_out, "NO_COST_TEMP_TEST = %d\n", (int) NO_COST_TEMP_TEST);
+  fprintf (ptr_asa_out, "SELF_OPTIMIZE = %d\n", (int) SELF_OPTIMIZE);
+  fprintf (ptr_asa_out, "ASA_TEST = %d\n", (int) ASA_TEST);
+  fprintf (ptr_asa_out, "ASA_TEST_POINT = %d\n", (int) ASA_TEST_POINT);
+  fprintf (ptr_asa_out, "ASA_TEMPLATE = %d\n", (int) ASA_TEMPLATE);
+  fprintf (ptr_asa_out, "MY_TEMPLATE = %d\n", (int) MY_TEMPLATE);
+  fprintf (ptr_asa_out, "ASA_TEMPLATE_LIB = %d\n", (int) ASA_TEMPLATE_LIB);
+  fprintf (ptr_asa_out, "ASA_TEMPLATE_ASA_OUT_PID = %d\n",
+           (int) ASA_TEMPLATE_ASA_OUT_PID);
+  fprintf (ptr_asa_out, "ASA_TEMPLATE_MULTIPLE = %d\n",
+           (int) ASA_TEMPLATE_MULTIPLE);
+  fprintf (ptr_asa_out, "ASA_TEMPLATE_SELFOPT = %d\n",
+           (int) ASA_TEMPLATE_SELFOPT);
+  fprintf (ptr_asa_out, "ASA_TEMPLATE_SAMPLE = %d\n",
+           (int) ASA_TEMPLATE_SAMPLE);
+  fprintf (ptr_asa_out, "ASA_TEMPLATE_QUEUE = %d\n",
+           (int) ASA_TEMPLATE_QUEUE);
+  fprintf (ptr_asa_out, "ASA_TEMPLATE_PARALLEL = %d\n",
+           (int) ASA_TEMPLATE_PARALLEL);
+  fprintf (ptr_asa_out, "ASA_TEMPLATE_SAVE = %d\n", (int) ASA_TEMPLATE_SAVE);
+  fprintf (ptr_asa_out, "USER_INITIAL_COST_TEMP = %d\n",
+           (int) USER_INITIAL_COST_TEMP);
+  fprintf (ptr_asa_out, "RATIO_TEMPERATURE_SCALES = %d\n",
+           (int) RATIO_TEMPERATURE_SCALES);
+  fprintf (ptr_asa_out, "USER_INITIAL_PARAMETERS_TEMPS = %d\n",
+           (int) USER_INITIAL_PARAMETERS_TEMPS);
+  fprintf (ptr_asa_out, "DELTA_PARAMETERS = %d\n", (int) DELTA_PARAMETERS);
+  fprintf (ptr_asa_out, "QUENCH_PARAMETERS = %d\n", (int) QUENCH_PARAMETERS);
+  fprintf (ptr_asa_out, "QUENCH_COST = %d\n", (int) QUENCH_COST);
+  fprintf (ptr_asa_out, "QUENCH_PARAMETERS_SCALE = %d\n",
+           (int) QUENCH_PARAMETERS_SCALE);
+  fprintf (ptr_asa_out, "QUENCH_COST_SCALE = %d\n", (int) QUENCH_COST_SCALE);
+  fprintf (ptr_asa_out, "OPTIONAL_DATA_DBL = %d\n", (int) OPTIONAL_DATA_DBL);
+  fprintf (ptr_asa_out, "OPTIONAL_DATA_INT = %d\n", (int) OPTIONAL_DATA_INT);
+  fprintf (ptr_asa_out, "OPTIONAL_DATA_PTR = %d\n", (int) OPTIONAL_DATA_PTR);
+  fprintf (ptr_asa_out, "USER_COST_SCHEDULE = %d\n",
+           (int) USER_COST_SCHEDULE);
+  fprintf (ptr_asa_out, "USER_ACCEPT_ASYMP_EXP = %d\n",
+           (int) USER_ACCEPT_ASYMP_EXP);
+  fprintf (ptr_asa_out, "USER_ACCEPT_THRESHOLD = %d\n",
+           (int) USER_ACCEPT_THRESHOLD);
+  fprintf (ptr_asa_out, "USER_ACCEPTANCE_TEST = %d\n",
+           (int) USER_ACCEPTANCE_TEST);
+  fprintf (ptr_asa_out, "USER_GENERATING_FUNCTION = %d\n",
+           (int) USER_GENERATING_FUNCTION);
+  fprintf (ptr_asa_out, "USER_REANNEAL_COST = %d\n",
+           (int) USER_REANNEAL_COST);
+  fprintf (ptr_asa_out, "USER_REANNEAL_PARAMETERS = %d\n",
+           (int) USER_REANNEAL_PARAMETERS);
+#if INT_LONG
+  fprintf (ptr_asa_out, "MAXIMUM_REANNEAL_INDEX = %ld\n",
+           (LONG_INT) MAXIMUM_REANNEAL_INDEX);
+#else
+  fprintf (ptr_asa_out, "MAXIMUM_REANNEAL_INDEX = %d\n",
+           (LONG_INT) MAXIMUM_REANNEAL_INDEX);
+#endif
+  fprintf (ptr_asa_out, "REANNEAL_SCALE = %*.*g\n",
+           G_FIELD, G_PRECISION, (double) REANNEAL_SCALE);
+  fprintf (ptr_asa_out, "ASA_SAMPLE = %d\n", (int) ASA_SAMPLE);
+  fprintf (ptr_asa_out, "ASA_QUEUE = %d\n", (int) ASA_QUEUE);
+  fprintf (ptr_asa_out, "ASA_RESOLUTION = %d\n", (int) ASA_RESOLUTION);
+  fprintf (ptr_asa_out, "FITLOC = %d\n", (int) FITLOC);
+  fprintf (ptr_asa_out, "FITLOC_ROUND = %d\n", (int) FITLOC_ROUND);
+  fprintf (ptr_asa_out, "FITLOC_PRINT = %d\n", (int) FITLOC_PRINT);
+  fprintf (ptr_asa_out, "MULTI_MIN = %d\n", (int) MULTI_MIN);
+  fprintf (ptr_asa_out, "ASA_PARALLEL = %d\n", (int) ASA_PARALLEL);
+  fprintf (ptr_asa_out, "FDLIBM_POW = %d\n", (int) FDLIBM_POW);
+  fprintf (ptr_asa_out, "FDLIBM_LOG = %d\n", (int) FDLIBM_LOG);
+  fprintf (ptr_asa_out, "FDLIBM_EXP = %d\n\n", (int) FDLIBM_EXP);
+
+  fprintf (ptr_asa_out, "ASA_PRINT = %d\n", (int) ASA_PRINT);
+  fprintf (ptr_asa_out, "USER_OUT = %s\n", USER_OUT);
+#if USER_ASA_OUT
+  fprintf (ptr_asa_out, "ASA_OUT = %s\n", OPTIONS->Asa_Out_File);
+#else
+  fprintf (ptr_asa_out, "ASA_OUT = %s\n", ASA_OUT);
+#endif
+  fprintf (ptr_asa_out, "USER_ASA_OUT = %d\n", (int) USER_ASA_OUT);
+  fprintf (ptr_asa_out, "ASA_PRINT_INTERMED = %d\n",
+           (int) ASA_PRINT_INTERMED);
+  fprintf (ptr_asa_out, "ASA_PRINT_MORE = %d\n", (int) ASA_PRINT_MORE);
+  fprintf (ptr_asa_out, "INCL_STDOUT = %d\n", (int) INCL_STDOUT);
+  fprintf (ptr_asa_out, "G_FIELD = %d\n", (int) G_FIELD);
+  fprintf (ptr_asa_out, "G_PRECISION = %d\n", (int) G_PRECISION);
+  fprintf (ptr_asa_out, "ASA_SAVE = %d\n", (int) ASA_SAVE);
+  fprintf (ptr_asa_out, "ASA_SAVE_OPT = %d\n", (int) ASA_SAVE_OPT);
+  fprintf (ptr_asa_out, "ASA_SAVE_BACKUP = %d\n", (int) ASA_SAVE_BACKUP);
+  fprintf (ptr_asa_out, "ASA_PIPE = %d\n", (int) ASA_PIPE);
+  fprintf (ptr_asa_out, "ASA_PIPE_FILE = %d\n", (int) ASA_PIPE_FILE);
+  fprintf (ptr_asa_out, "SYSTEM_CALL = %d\n\n", (int) SYSTEM_CALL);
+
+#if INT_LONG
+  fprintf (ptr_asa_out, "OPTIONS->Limit_Acceptances = %ld\n",
+           (LONG_INT) OPTIONS->Limit_Acceptances);
+  fprintf (ptr_asa_out, "OPTIONS->Limit_Generated = %ld\n",
+           (LONG_INT) OPTIONS->Limit_Generated);
+#else
+  fprintf (ptr_asa_out, "OPTIONS->Limit_Acceptances = %d\n",
+           (LONG_INT) OPTIONS->Limit_Acceptances);
+  fprintf (ptr_asa_out, "OPTIONS->Limit_Generated = %d\n",
+           (LONG_INT) OPTIONS->Limit_Generated);
+#endif
+  fprintf (ptr_asa_out, "OPTIONS->Limit_Invalid_Generated_States = %d\n",
+           OPTIONS->Limit_Invalid_Generated_States);
+  fprintf (ptr_asa_out, "OPTIONS->Accepted_To_Generated_Ratio = %*.*g\n\n",
+           G_FIELD, G_PRECISION, OPTIONS->Accepted_To_Generated_Ratio);
+
+  fprintf (ptr_asa_out, "OPTIONS->Cost_Precision = %*.*g\n",
+           G_FIELD, G_PRECISION, OPTIONS->Cost_Precision);
+  fprintf (ptr_asa_out, "OPTIONS->Maximum_Cost_Repeat = %d\n",
+           OPTIONS->Maximum_Cost_Repeat);
+  fprintf (ptr_asa_out, "OPTIONS->Number_Cost_Samples = %d\n",
+           OPTIONS->Number_Cost_Samples);
+  fprintf (ptr_asa_out, "OPTIONS->Temperature_Ratio_Scale = %*.*g\n",
+           G_FIELD, G_PRECISION, OPTIONS->Temperature_Ratio_Scale);
+  fprintf (ptr_asa_out, "OPTIONS->Cost_Parameter_Scale_Ratio = %*.*g\n",
+           G_FIELD, G_PRECISION, OPTIONS->Cost_Parameter_Scale_Ratio);
+  fprintf (ptr_asa_out, "OPTIONS->Temperature_Anneal_Scale = %*.*g\n",
+           G_FIELD, G_PRECISION, OPTIONS->Temperature_Anneal_Scale);
+
+  fprintf (ptr_asa_out, "OPTIONS->Include_Integer_Parameters = %d\n",
+           OPTIONS->Include_Integer_Parameters);
+  fprintf (ptr_asa_out, "OPTIONS->User_Initial_Parameters = %d\n",
+           OPTIONS->User_Initial_Parameters);
+#if INT_ALLOC
+  fprintf (ptr_asa_out, "OPTIONS->Sequential_Parameters = %d\n",
+           (int) OPTIONS->Sequential_Parameters);
+#else
+#if INT_LONG
+  fprintf (ptr_asa_out, "OPTIONS->Sequential_Parameters = %ld\n",
+           (LONG_INT) OPTIONS->Sequential_Parameters);
+#else
+  fprintf (ptr_asa_out, "OPTIONS->Sequential_Parameters = %d\n",
+           (LONG_INT) OPTIONS->Sequential_Parameters);
+#endif
+#endif
+  fprintf (ptr_asa_out, "OPTIONS->Initial_Parameter_Temperature = %*.*g\n",
+           G_FIELD, G_PRECISION, OPTIONS->Initial_Parameter_Temperature);
+
+  fprintf (ptr_asa_out, "OPTIONS->Acceptance_Frequency_Modulus = %d\n",
+           OPTIONS->Acceptance_Frequency_Modulus);
+  fprintf (ptr_asa_out, "OPTIONS->Generated_Frequency_Modulus = %d\n",
+           OPTIONS->Generated_Frequency_Modulus);
+  fprintf (ptr_asa_out, "OPTIONS->Reanneal_Cost = %d\n",
+           OPTIONS->Reanneal_Cost);
+  fprintf (ptr_asa_out, "OPTIONS->Reanneal_Parameters = %d\n\n",
+           OPTIONS->Reanneal_Parameters);
+
+  fprintf (ptr_asa_out, "OPTIONS->Delta_X = %*.*g\n",
+           G_FIELD, G_PRECISION, OPTIONS->Delta_X);
+  fprintf (ptr_asa_out, "OPTIONS->User_Tangents = %d\n",
+           OPTIONS->User_Tangents);
+  fprintf (ptr_asa_out, "OPTIONS->Curvature_0 = %d\n", OPTIONS->Curvature_0);
+  fprintf (ptr_asa_out, "OPTIONS->Asa_Recursive_Level = %d\n\n",
+           OPTIONS->Asa_Recursive_Level);
+
+  fprintf (ptr_asa_out, "\n");
+}
+#endif /* ASA_PRINT */
+
+#if TIME_CALC
+#if TIME_GETRUSAGE
+/***********************************************************************
+* print_time
+*	This calculates the time and runtime and prints it.
+***********************************************************************/
+#if HAVE_ANSI
+void
+print_time (char *message, FILE * ptr_asa_out)
+#else
+void
+print_time (message, ptr_asa_out)
+     char *message;
+     FILE *ptr_asa_out;
+#endif /* HAVE_ANSI */
+{
+  int who = RUSAGE_SELF;        /* Check our own time */
+  struct rusage usage;
+
+  /* get the resource usage information */
+#if TIME_STD
+  syscall (SYS_GETRUSAGE, who, &usage);
+#else
+  getrusage (who, &usage);
+#endif
+
+  /* print the usage time in reasonable form */
+  aux_print_time (&usage.ru_utime, message, ptr_asa_out);
+}
+
+/***********************************************************************
+* aux_print_time
+*      auxiliary print the time routine
+***********************************************************************/
+#if HAVE_ANSI
+void
+aux_print_time (struct timeval *time, char *message, FILE * ptr_asa_out)
+#else
+void
+aux_print_time (time, message, ptr_asa_out)
+     struct timeval *time;
+     char *message;
+     FILE *ptr_asa_out;
+#endif /* HAVE_ANSI */
+{
+  static double sx;
+  double us, s, m, h;
+  double ds, dm, dh;
+
+  /* calculate the new microseconds, seconds, minutes, hours
+     and the differences since the last call */
+  us = (double) ((int) ((double) EPS_DOUBLE + time->tv_usec)) / 1.E6;
+  s = (double) ((int) ((double) EPS_DOUBLE + time->tv_sec)) + us;
+  ds = s - sx;
+  sx = s;
+
+  h = (int) ((double) EPS_DOUBLE + s / 3600.);
+  m = (int) ((double) EPS_DOUBLE + s / 60.) - 60. * h;
+  s -= (3600. * h + 60. * m);
+  dh = (int) ((double) EPS_DOUBLE + ds / 3600.);
+  dm = (int) ((double) EPS_DOUBLE + ds / 60.) - 60. * dh;
+  ds -= (3600. * dh + 60. * dm);
+
+  /* print the statistics */
+  fprintf (ptr_asa_out,
+           "%s:time: %gh %gm %gs; incr: %gh %gm %gs\n",
+           message, h, m, s, dh, dm, ds);
+}
+#else /* TIME_GETRUSAGE */
+  /* Note that on many machines the time resolution of this algorithm
+   * may be less than the other alternatives, e.g., rounding off the
+   * number of ticks to the nearest tens of thousands.  Also, because
+   * time here is typically indexed by a long integer, there typically
+   * is a cycle of time in periods of fractions of an hour.  For
+   * example, under Solaris 2.5.1:  The value returned by clock() is
+   * defined in microseconds, since the first call to clock(), for
+   *  compatibility with  systems that have * CPU clocks with much higher
+   * resolution.  Because of this, the value returned will wrap around
+   * after accumulating only 2147 seconds of CPU time (about 36 minutes).
+   *
+   * See asa.h for two places where some additional modifications should
+   * be made under SunOS 4.1.x. */
+
+#if HAVE_ANSI
+void
+print_time (char *message, FILE * ptr_asa_out)
+#else
+void
+print_time (message, ptr_asa_out)
+     char *message;
+     FILE *ptr_asa_out;
+#endif /* HAVE_ANSI */
+{
+  aux_print_time (clock (), message, ptr_asa_out);
+
+}                               /*print_time */
+
+/***********************************************************************
+* aux_print_time
+*      auxiliary print the time routine
+***********************************************************************/
+#if HAVE_ANSI
+void
+aux_print_time (clock_t time, char *message, FILE * ptr_asa_out)
+#else
+void
+aux_print_time (time, message, ptr_asa_out)
+     clock_t time;
+     char *message;
+     FILE *ptr_asa_out;
+#endif /* HAVE_ANSI */
+{
+  static clock_t previousTime = -1;
+  clock_t diffTime;
+  double clocksPerSecF = CLOCKS_PER_SEC;
+  double timeF, diffF;
+  double s, m, h;
+  double ds, dm, dh;
+
+  if (previousTime != -1) {
+    diffTime = time - previousTime;
+    timeF = time;
+    diffF = diffTime;
+    previousTime = time;
+
+    s = timeF / clocksPerSecF;
+    ds = diffF / clocksPerSecF;
+
+    h = (int) ((double) EPS_DOUBLE + s / 3600.);
+    m = (int) ((double) EPS_DOUBLE + s / 60.) - 60. * h;
+    s -= (3600. * h + 60. * m);
+    dh = (int) ((double) EPS_DOUBLE + ds / 3600.);
+    dm = (int) ((double) EPS_DOUBLE + ds / 60.) - 60. * dh;
+    ds -= (3600. * dh + 60. * dm);
+
+    fprintf (ptr_asa_out,
+             "%s:time: %gh %gm %gs; incr: %gh %gm %gs\n",
+             message, h, m, s, dh, dm, ds);
+  } else {
+    /* The first call will be invalid - don't output anything. */
+    fprintf (ptr_asa_out, "TIMING PARAMETERS: ticks/sec: %lu\n",
+             CLOCKS_PER_SEC);
+    previousTime = time;
+  }
+}                               /* aux_print_time */
+
+#endif /* TIME_GETRUSAGE */
+
+#endif /* TIME_CALC */
+
+#if MULTI_MIN
+#if HAVE_ANSI
+static int
+multi_compare (const void *ii, const void *jj)
+#else /* HAVE_ANSI */
+static int
+multi_compare (ii, jj)
+     char *ii;
+     char *jj;
+#endif /* HAVE_ANSI */
+{
+  int i;
+  int j;
+
+  i = *(int *) ii;
+  j = *(int *) jj;
+
+  if (multi_cost_qsort[i] > multi_cost_qsort[j] + (double) EPS_DOUBLE)
+    return (1);
+  else if (multi_cost_qsort[i] < multi_cost_qsort[j] - (double) EPS_DOUBLE)
+    return (-1);
+  else
+    return (0);
+}
+#endif /* MULTI_MIN */
+
+#if ASA_PARALLEL
+#if HAVE_ANSI
+static int
+sort_parallel (const void *ii, const void *jj)
+#else /* HAVE_ANSI */
+static int
+sort_parallel (ii, jj)
+     void *ii;
+     void *jj;
+#endif /* HAVE_ANSI */
+{
+  LONG_INT i;
+  LONG_INT j;
+
+  i = *(LONG_INT *) ii;
+  j = *(LONG_INT *) jj;
+
+  if (gener_block_state_qsort[i].cost > gener_block_state_qsort[j].cost)
+    return (1);
+  else if (gener_block_state_qsort[i].cost < gener_block_state_qsort[j].cost)
+    return (-1);
+  else
+    return (0);
+}
+#endif /* ASA_PARALLEL */
+#if HAVE_ANSI
+void
+Exit_ASA (char *statement)
+#else /* HAVE_ANSI */
+void
+Exit_ASA (statement)
+     char *statement;
+#endif /* HAVE_ANSI */
+{
+#if INCL_STDOUT
+  printf ("\n\n*** EXIT calloc failed in ASA *** %s\n\n", statement);
+#else
+  ;
+#endif /* INCL_STDOUT */
+}
diff --git a/cbits/hs_asa.c b/cbits/hs_asa.c
new file mode 100644
--- /dev/null
+++ b/cbits/hs_asa.c
@@ -0,0 +1,4369 @@
+/***********************************************************************
+* Adaptive Simulated Annealing (ASA)
+* Lester Ingber <ingber@ingber.com>
+* Copyright (c) 1993-2004 Lester Ingber.  All Rights Reserved.
+* The LICENSE file must be included with ASA code.
+* Modified by John Meacham for Haskell interface
+***********************************************************************/
+
+#include "asa_usr.h"
+
+
+
+
+char user_exit_msg[160];        /* temp storage for exit messages */
+FILE *ptr_out;
+
+static double resettable_randflt (LONG_INT * rand_seed, int reset);
+static double randflt (LONG_INT * rand_seed);
+/***********************************************************************
+* main
+*	This is a sample calling program to optimize using ASA
+***********************************************************************/
+int
+asa_main (
+           hs_cost_func *func, 
+           int number_parameters,
+           double *upper_bounds,
+           double *lower_bounds,
+           int *type,
+           double *main_cost_value,
+           double *main_cost_parameters, 
+           int *main_exit_code,
+           long int initial_rand_seed
+  )
+{
+  int i;
+  int *exit_code;
+  ALLOC_INT n_param;
+#if ASA_TEMPLATE_SAMPLE
+  FILE *ptr_asa;
+#endif
+#if MULTI_MIN
+  int multi_index;
+#endif
+
+  /* pointer to array storage for asa arguments */
+  double *parameter_lower_bound, *parameter_upper_bound, *cost_parameters,
+    *cost_tangents, *cost_curvature;
+  double cost_value;
+
+  int initialize_parameters_value;
+
+  /* the number of parameters to optimize */
+  ALLOC_INT *parameter_dimension;
+
+  /* pointer to array storage for parameter type flags */
+  int *parameter_int_real;
+
+  /* valid flag for cost function */
+  int *cost_flag;
+
+  /* seed for random number generator */
+  LONG_INT *rand_seed;
+
+  USER_DEFINES *USER_OPTIONS;
+
+#if MY_TEMPLATE                 /* MY_TEMPLATE_main_decl */
+  /* add some declarations if required */
+#endif
+
+#if ASA_TEMPLATE_MULTIPLE
+  int n_asa, n_trajectory;
+  ALLOC_INT index;
+#if HAVE_ANSI
+  char asa_file[8] = "asa_x_y";
+#else
+  char asa_file[8];
+#endif /* HAVE_ANSI */
+#endif /* ASA_TEMPLATE_MULTIPLE */
+
+
+  if ((USER_OPTIONS =
+       (USER_DEFINES *) calloc (1, sizeof (USER_DEFINES))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): USER_DEFINES");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#if OPTIONAL_DATA_PTR
+#if ASA_TEMPLATE
+  USER_OPTIONS->Asa_Data_Dim_Ptr = 256;
+  if ((USER_OPTIONS->Asa_Data_Ptr =
+       (OPTIONAL_PTR_TYPE *) calloc (USER_OPTIONS->Asa_Data_Dim_Ptr,
+                                     sizeof (OPTIONAL_PTR_TYPE))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): USER_OPTIONS->Asa_Data_Ptr");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#endif /* ASA_TEMPLATE */
+#endif /* OPTIONAL_DATA_PTR */
+
+
+  if (!strcmp (USER_OUT, "STDOUT")) {
+#if INCL_STDOUT
+    ptr_out = stdout;
+#endif /* INCL_STDOUT */
+  } else {
+    ptr_out = fopen (USER_OUT, "w");
+  }
+
+
+  fflush (ptr_out);
+
+  if ((rand_seed = (ALLOC_INT *) calloc (1, sizeof (ALLOC_INT))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): rand_seed");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  *rand_seed = initial_rand_seed;
+
+  /* initialize random number generator with first call */
+  resettable_randflt (rand_seed, 1);
+
+  /* Initialize the users parameters, allocating space, etc.
+     Note that the default is to have asa generate the initial
+     cost_parameters that satisfy the user's constraints. */
+
+  if ((parameter_dimension =
+       (ALLOC_INT *) calloc (1, sizeof (ALLOC_INT))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): parameter_dimension");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  if ((exit_code = (int *) calloc (1, sizeof (int))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): exit_code");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  if ((cost_flag = (int *) calloc (1, sizeof (int))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): cost_flag");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+
+  //USER_OPTIONS->Limit_Acceptances = 10000; 
+  USER_OPTIONS->Limit_Acceptances = 1000;
+  USER_OPTIONS->Limit_Generated = 99999;
+  USER_OPTIONS->Limit_Invalid_Generated_States = 1000;
+  /* USER_OPTIONS->Accepted_To_Generated_Ratio = 1.0E-6; */
+  USER_OPTIONS->Accepted_To_Generated_Ratio = 1.0E-4;
+
+  USER_OPTIONS->Cost_Precision = 1.0E-18;
+  USER_OPTIONS->Maximum_Cost_Repeat = 5;
+  USER_OPTIONS->Number_Cost_Samples = 5;
+  USER_OPTIONS->Temperature_Ratio_Scale = 1.0E-5;
+  USER_OPTIONS->Cost_Parameter_Scale_Ratio = 1.0;
+  USER_OPTIONS->Temperature_Anneal_Scale = 100.0;
+
+  USER_OPTIONS->Include_Integer_Parameters = FALSE;
+  USER_OPTIONS->User_Initial_Parameters = FALSE;
+  USER_OPTIONS->Sequential_Parameters = -1;
+  USER_OPTIONS->Initial_Parameter_Temperature = 1.0;
+
+  USER_OPTIONS->Acceptance_Frequency_Modulus = 100;
+  USER_OPTIONS->Generated_Frequency_Modulus = 10000;
+  USER_OPTIONS->Reanneal_Cost = 1;
+  USER_OPTIONS->Reanneal_Parameters = TRUE;
+
+  USER_OPTIONS->Delta_X = 0.001;
+  USER_OPTIONS->User_Tangents = FALSE;
+  USER_OPTIONS->Curvature_0 = FALSE;
+
+
+  /* ALLOCATE STORAGE */
+
+
+#if USER_ASA_OUT
+  if ((USER_OPTIONS->Asa_Out_File =
+       (char *) calloc (80, sizeof (char))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): USER_OPTIONS->Asa_Out_File");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#endif
+
+  /* the number of parameters for the cost function */
+#if OPTIONS_FILE_DATA
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%s", read_option);
+
+#if INT_ALLOC
+  fscanf (ptr_options, "%d", &read_int);
+  *parameter_dimension = read_int;
+#else
+#if INT_LONG
+  fscanf (ptr_options, "%ld", &read_long);
+  *parameter_dimension = read_long;
+#else
+  fscanf (ptr_options, "%d", &read_int);
+  *parameter_dimension = read_int;
+#endif
+#endif
+
+#else /* OPTIONS_FILE_DATA */
+#endif /* OPTIONS_FILE_DATA */
+#if MY_TEMPLATE                 /* MY_TEMPLATE_dim */
+  *parameter_dimension = number_parameters;
+  /* If not using OPTIONS_FILE_DATA or data read from asa_opt,
+     insert the number of parameters for the cost_function */
+#endif /* MY_TEMPLATE dim */
+
+#if ASA_TEMPLATE_SAMPLE
+  *parameter_dimension = 2;
+  USER_OPTIONS->Limit_Acceptances = 2000;
+  USER_OPTIONS->User_Tangents = TRUE;
+  USER_OPTIONS->Limit_Weights = 1.0E-7;
+#endif
+#if ASA_TEMPLATE_PARALLEL
+  USER_OPTIONS->Gener_Block = 100;
+  USER_OPTIONS->Gener_Block_Max = 512;
+  USER_OPTIONS->Gener_Mov_Avr = 3;
+#endif
+
+  /* allocate parameter minimum space */
+  if ((parameter_lower_bound =
+       (double *) calloc (*parameter_dimension, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): parameter_lower_bound");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  /* allocate parameter maximum space */
+  if ((parameter_upper_bound =
+       (double *) calloc (*parameter_dimension, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): parameter_upper_bound");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  /* allocate parameter initial values; the parameter final values
+     will be stored here later */
+  if ((cost_parameters =
+       (double *) calloc (*parameter_dimension, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): cost_parameters");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  /* allocate the parameter types, real or integer */
+  if ((parameter_int_real =
+       (int *) calloc (*parameter_dimension, sizeof (int))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): parameter_int_real");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  /* allocate space for parameter cost_tangents -
+     used for reannealing */
+  if ((cost_tangents =
+       (double *) calloc (*parameter_dimension, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): cost_tangents");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+
+  if (USER_OPTIONS->Curvature_0 == FALSE || USER_OPTIONS->Curvature_0 == -1) {
+    /* allocate space for parameter cost_curvatures/covariance */
+    if ((cost_curvature =
+         (double *) calloc ((*parameter_dimension) *
+                            (*parameter_dimension),
+                            sizeof (double))) == NULL) {
+      strcpy (user_exit_msg, "main()/asa_main(): cost_curvature");
+      Exit_USER (user_exit_msg);
+      return (-2);
+    }
+  } else {
+    cost_curvature = (double *) NULL;
+  }
+
+#if USER_COST_SCHEDULE
+  USER_OPTIONS->Cost_Schedule = user_cost_schedule;
+#endif
+#if USER_ACCEPTANCE_TEST
+  USER_OPTIONS->Acceptance_Test = user_acceptance_test;
+#endif
+#if USER_ACCEPT_ASYMP_EXP
+  USER_OPTIONS->Asymp_Exp_Param = 1.0;
+#endif
+#if USER_GENERATING_FUNCTION
+  USER_OPTIONS->Generating_Distrib = user_generating_distrib;
+#endif
+#if USER_REANNEAL_COST
+  USER_OPTIONS->Reanneal_Cost_Function = user_reanneal_cost;
+#endif
+#if USER_REANNEAL_PARAMETERS
+  USER_OPTIONS->Reanneal_Params_Function = user_reanneal_params;
+#endif
+
+#if MY_TEMPLATE                 /* MY_TEMPLATE_pre_initialize */
+  /* last changes before entering initialize_parameters() */
+  USER_OPTIONS->Asa_Data_Ptr = func;
+  USER_OPTIONS->Asa_Data_Dim_Ptr = 1;
+  memcpy(parameter_lower_bound,lower_bounds,sizeof(double)*number_parameters);
+  memcpy(cost_parameters,lower_bounds,sizeof(double)*number_parameters);
+  memcpy(parameter_upper_bound,upper_bounds,sizeof(double)*number_parameters);
+  memcpy(parameter_int_real, type, sizeof(int)*number_parameters);
+#endif
+
+  initialize_parameters_value = initialize_parameters (cost_parameters,
+                                                       parameter_lower_bound,
+                                                       parameter_upper_bound,
+                                                       cost_tangents,
+                                                       cost_curvature,
+                                                       parameter_dimension,
+                                                       parameter_int_real,
+#if OPTIONS_FILE_DATA
+                                                       ptr_options,
+#endif
+                                                       USER_OPTIONS);
+
+  if (initialize_parameters_value == -2)
+    return (initialize_parameters_value);
+
+  for(i = 0; i < number_parameters; i++) {
+          USER_OPTIONS->User_Quench_Param_Scale[i] = 1.0;
+  }
+        USER_OPTIONS->User_Quench_Cost_Scale[0] = 1.0;
+
+  /* optimize the cost_function, returning the results in
+     cost_value and cost_parameters */
+#if ASA_TEMPLATE_MULTIPLE
+  /* multiple asa() quenched calls + multiple asa_out files
+     (To get longer quenched runs, decrease SMALL_FLOAT.) */
+  for (n_asa = 1; n_asa <= *parameter_dimension; n_asa++) {
+    asa_file[4] = 'A' + n_asa - 1;
+    USER_OPTIONS->User_Quench_Cost_Scale[0] = (double) n_asa;
+    for (index = 0; index < *parameter_dimension; ++index)
+      USER_OPTIONS->User_Quench_Param_Scale[index] = (double) n_asa;
+    for (n_trajectory = 0; n_trajectory < 3; ++n_trajectory) {
+      asa_file[6] = 'a' + n_trajectory;
+      strcpy (USER_OPTIONS->Asa_Out_File, asa_file);
+#endif
+
+#if ASA_TEMPLATE_ASA_OUT_PID
+      pid_file[0] = 'a';
+      pid_file[1] = 's';
+      pid_file[2] = 'a';
+      pid_file[3] = '_';
+      pid_file[4] = 'o';
+      pid_file[5] = 'u';
+      pid_file[6] = 't';
+      pid_file[7] = '_';
+
+      pid_int = getpid ();
+      if (pid_int < 0) {
+        pid_file[7] = '0';
+        pid_int = -pid_int;
+      }
+
+      strcpy (USER_OPTIONS->Asa_Out_File, pid_file);
+#endif
+      cost_value =
+        asa (USER_COST_FUNCTION,
+             randflt,
+             rand_seed,
+             cost_parameters,
+             parameter_lower_bound,
+             parameter_upper_bound,
+             cost_tangents,
+             cost_curvature,
+             parameter_dimension,
+             parameter_int_real, cost_flag, exit_code, USER_OPTIONS);
+      if (*exit_code == -1) {
+#if INCL_STDOUT
+        printf ("\n\n*** error in calloc in ASA ***\n\n");
+#endif /* INCL_STDOUT */
+        fprintf (ptr_out, "\n\n*** error in calloc in ASA ***\n\n");
+        fflush (ptr_out);
+        return (-1);
+      }
+#if MULTI_MIN
+      fprintf (ptr_out, "Multi_Specify = %d\n", USER_OPTIONS->Multi_Specify);
+#if INT_LONG
+      fprintf (ptr_out, "N_Accepted = %ld\n", USER_OPTIONS->N_Accepted);
+#else
+      fprintf (ptr_out, "N_Accepted = %d\n", USER_OPTIONS->N_Accepted);
+#endif
+#if ASA_RESOLUTION
+      for (n_param = 0; n_param < *parameter_dimension; ++n_param) {
+        fprintf (ptr_out,
+#if INT_ALLOC
+                 "Coarse_Resolution[%d] = %12.7g\n",
+#else
+#if INT_LONG
+                 "Coarse_Resolution[%ld] = %12.7g\n",
+#else
+                 "Coarse_Resolution[%d] = %12.7g\n",
+#endif
+#endif
+                 n_param, USER_OPTIONS->Coarse_Resolution[n_param]);
+      }
+#else /* ASA_RESOLUTION */
+      for (n_param = 0; n_param < *parameter_dimension; ++n_param) {
+        fprintf (ptr_out,
+#if INT_ALLOC
+                 "Multi_Grid[%d] = %12.7g\n",
+#else
+#if INT_LONG
+                 "Multi_Grid[%ld] = %12.7g\n",
+#else
+                 "Multi_Grid[%d] = %12.7g\n",
+#endif
+#endif
+                 n_param, USER_OPTIONS->Multi_Grid[n_param]);
+      }
+#endif /* ASA_RESOLUTION */
+      fprintf (ptr_out, "\n");
+      for (multi_index = 0; multi_index < USER_OPTIONS->Multi_Number;
+           ++multi_index) {
+        fprintf (ptr_out, "\n");
+        fprintf (ptr_out, "Multi_Cost[%d] = %12.7g\n",
+                 multi_index, USER_OPTIONS->Multi_Cost[multi_index]);
+        for (n_param = 0; n_param < *parameter_dimension; ++n_param) {
+          fprintf (ptr_out,
+#if INT_ALLOC
+                   "Multi_Params[%d][%d] = %12.7g\n",
+#else
+#if INT_LONG
+                   "Multi_Params[%d][%ld] = %12.7g\n",
+#else
+                   "Multi_Params[%d][%d] = %12.7g\n",
+#endif
+#endif
+                   multi_index, n_param,
+                   USER_OPTIONS->Multi_Params[multi_index][n_param]);
+        }
+      }
+      fprintf (ptr_out, "\n");
+      fflush (ptr_out);
+#endif /* MULTI_MIN */
+
+#if FITLOC
+      /* Fit_Local, Iter_Max and Penalty may be set adaptively */
+      USER_OPTIONS->Penalty = 1000;
+      USER_OPTIONS->Fit_Local = 0;
+      USER_OPTIONS->Iter_Max = 500;
+      if (USER_OPTIONS->Fit_Local >= 1) {
+        cost_value = fitloc (USER_COST_FUNCTION,
+                             cost_parameters,
+                             parameter_lower_bound,
+                             parameter_upper_bound,
+                             cost_tangents,
+                             cost_curvature,
+                             parameter_dimension,
+                             parameter_int_real,
+                             cost_flag, exit_code, USER_OPTIONS, ptr_out);
+      }
+#endif /* FITLOC */
+#if MY_TEMPLATE                 /* MY_TEMPLATE_post_asa */
+#endif
+      *main_cost_value = cost_value;
+      for (n_param = 0; n_param < *parameter_dimension; ++n_param) {
+        main_cost_parameters[n_param] = cost_parameters[n_param];
+      }
+      *main_exit_code = *exit_code;
+
+      fprintf (ptr_out, "exit code = %d\n", *exit_code);
+      fprintf (ptr_out, "final cost value = %-12.7g\n", cost_value);
+      fprintf (ptr_out, "%12s %12s\n","parameter","value");
+      for (n_param = 0; n_param < *parameter_dimension; ++n_param) {
+        fprintf (ptr_out,
+#if INT_ALLOC
+                 "%12d %12.7g\n",
+#else
+#if INT_LONG
+                 "%12ld %12.7g\n",
+#else
+                 "%12d %12.7g\n",
+#endif
+#endif
+                 n_param, cost_parameters[n_param]);
+      }
+
+
+#if ASA_TEMPLATE_MULTIPLE
+    }
+  }
+#endif
+
+#if ASA_TEMPLATE_SAMPLE
+  ptr_asa = fopen ("asa_out", "r");
+  sample (ptr_out, ptr_asa);
+#endif
+
+  /* close all files */
+  ptr_out != stdout && fclose (ptr_out);
+#if OPTIONAL_DATA_DBL
+  free (USER_OPTIONS->Asa_Data_Dbl);
+#endif
+#if OPTIONAL_DATA_INT
+  free (USER_OPTIONS->Asa_Data_Int);
+#endif
+#if OPTIONAL_DATA_PTR
+#if MY_TEMPLATE
+  /* Instead of freeing Asa_Data_Ptr, if memory has been allocated
+   * outside ASA, e.g., by the use of ASA_LIB, use the following: */
+  USER_OPTIONS->Asa_Data_Ptr = NULL; 
+#endif /* MY_TEMPLATE */
+  free (USER_OPTIONS->Asa_Data_Ptr);
+#endif
+#if USER_ASA_OUT
+  free (USER_OPTIONS->Asa_Out_File);
+#endif
+#if ASA_SAMPLE
+  free (USER_OPTIONS->Bias_Generated);
+#endif
+#if ASA_QUEUE
+#if ASA_RESOLUTION
+#else
+  free (USER_OPTIONS->Queue_Resolution);
+#endif
+#endif
+#if ASA_RESOLUTION
+  free (USER_OPTIONS->Coarse_Resolution);
+#endif
+  if (USER_OPTIONS->Curvature_0 == FALSE || USER_OPTIONS->Curvature_0 == -1)
+    free (cost_curvature);
+#if USER_INITIAL_PARAMETERS_TEMPS
+  free (USER_OPTIONS->User_Parameter_Temperature);
+#endif
+#if USER_INITIAL_COST_TEMP
+  free (USER_OPTIONS->User_Cost_Temperature);
+#endif
+#if DELTA_PARAMETERS
+  free (USER_OPTIONS->User_Delta_Parameter);
+#endif
+#if QUENCH_PARAMETERS
+  free (USER_OPTIONS->User_Quench_Param_Scale);
+#endif
+#if QUENCH_COST
+  free (USER_OPTIONS->User_Quench_Cost_Scale);
+#endif
+#if RATIO_TEMPERATURE_SCALES
+  free (USER_OPTIONS->User_Temperature_Ratio);
+#endif
+#if MULTI_MIN
+  free (USER_OPTIONS->Multi_Cost);
+  free (USER_OPTIONS->Multi_Grid);
+  for (multi_index = 0; multi_index < USER_OPTIONS->Multi_Number;
+       ++multi_index) {
+    free (USER_OPTIONS->Multi_Params[multi_index]);
+  }
+  free (USER_OPTIONS->Multi_Params);
+#endif /* MULTI_MIN */
+  free (USER_OPTIONS);
+  free (parameter_dimension);
+  free (exit_code);
+  free (cost_flag);
+  free (parameter_lower_bound);
+  free (parameter_upper_bound);
+  free (cost_parameters);
+  free (parameter_int_real);
+  free (cost_tangents);
+  free (rand_seed);
+  return (0);
+  /* NOTREACHED */
+}
+
+/***********************************************************************
+* initialize_parameters - sample parameter initialization function
+*	This depends on the users cost function to optimize (minimum).
+*	The routine allocates storage needed for asa. The user should
+*	define the number of parameters and their ranges,
+*	and make sure the initial parameters are within
+*	the minimum and maximum ranges. The array
+*	parameter_int_real should be REAL_TYPE (-1) for real parameters,
+*	and INTEGER_TYPE (1) for integer values
+***********************************************************************/
+#if HAVE_ANSI
+int
+initialize_parameters (double *cost_parameters,
+                       double *parameter_lower_bound,
+                       double *parameter_upper_bound,
+                       double *cost_tangents,
+                       double *cost_curvature,
+                       ALLOC_INT * parameter_dimension,
+                       int *parameter_int_real,
+#if OPTIONS_FILE_DATA
+                       FILE * ptr_options,
+#endif
+                       USER_DEFINES * USER_OPTIONS)
+#else
+int
+initialize_parameters (cost_parameters,
+                       parameter_lower_bound,
+                       parameter_upper_bound,
+                       cost_tangents,
+                       cost_curvature,
+                       parameter_dimension, parameter_int_real,
+#if OPTIONS_FILE_DATA
+                       ptr_options,
+#endif
+                       USER_OPTIONS)
+     double *cost_parameters;
+     double *parameter_lower_bound;
+     double *parameter_upper_bound;
+     double *cost_tangents;
+     double *cost_curvature;
+     ALLOC_INT *parameter_dimension;
+     int *parameter_int_real;
+#if OPTIONS_FILE_DATA
+     FILE *ptr_options;
+#endif
+     USER_DEFINES *USER_OPTIONS;
+#endif
+{
+  ALLOC_INT index;
+#if OPTIONS_FILE_DATA
+  char read_option[80];
+  ALLOC_INT read_index;
+#endif
+#if MULTI_MIN
+  int multi_index;
+#endif
+#if MY_TEMPLATE                 /* MY_TEMPLATE_init_decl */
+  /* add some declarations if required */
+#endif
+
+  index = 0;
+#if OPTIONS_FILE_DATA
+  fscanf (ptr_options, "%s", read_option);
+
+  for (index = 0; index < *parameter_dimension; ++index) {
+#if MY_TEMPLATE                 /* MY_TEMPLATE_read_opt */
+    /* put in some code as required to alter lines read from asa_opt */
+#endif
+#if INT_ALLOC
+    fscanf (ptr_options, "%d", &read_index);
+#else
+#if INT_LONG
+    fscanf (ptr_options, "%ld", &read_index);
+#else
+    fscanf (ptr_options, "%d", &read_index);
+#endif
+#endif
+    fscanf (ptr_options, "%lf%lf%lf%d",
+            &(parameter_lower_bound[read_index]),
+            &(parameter_upper_bound[read_index]),
+            &(cost_parameters[read_index]),
+            &(parameter_int_real[read_index]));
+  }
+#else /* OPTIONS_FILE_DATA */
+#if ASA_TEST
+  /* store the parameter ranges */
+  for (index = 0; index < *parameter_dimension; ++index)
+    parameter_lower_bound[index] = -10000.0;
+  for (index = 0; index < *parameter_dimension; ++index)
+    parameter_upper_bound[index] = 10000.0;
+
+  /* store the initial parameter types */
+  for (index = 0; index < *parameter_dimension; ++index)
+    parameter_int_real[index] = REAL_TYPE;
+
+  /* store the initial parameter values */
+  for (index = 0; index < *parameter_dimension / 4.0; ++index) {
+    cost_parameters[4 * (index + 1) - 4] = 999.0;
+    cost_parameters[4 * (index + 1) - 3] = -1007.0;
+    cost_parameters[4 * (index + 1) - 2] = 1001.0;
+    cost_parameters[4 * (index + 1) - 1] = -903.0;
+  }
+#endif /* ASA_TEST */
+#endif /* OPTIONS_FILE_DATA */
+#if ASA_TEMPLATE_SAMPLE
+  for (index = 0; index < *parameter_dimension; ++index)
+    parameter_lower_bound[index] = 0;
+  for (index = 0; index < *parameter_dimension; ++index)
+    parameter_upper_bound[index] = 2.0;
+  for (index = 0; index < *parameter_dimension; ++index)
+    parameter_int_real[index] = REAL_TYPE;
+  for (index = 0; index < *parameter_dimension; ++index)
+    cost_parameters[index] = 0.5;
+#endif
+
+#if USER_INITIAL_PARAMETERS_TEMPS
+  if ((USER_OPTIONS->User_Parameter_Temperature =
+       (double *) calloc (*parameter_dimension, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "initialize_parameters(): USER_OPTIONS->User_Parameter_Temperature");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#if ASA_TEMPLATE
+  for (index = 0; index < *parameter_dimension; ++index)
+    USER_OPTIONS->User_Parameter_Temperature[index] = 1.0;
+#endif
+#endif /* USER_INITIAL_PARAMETERS_TEMPS */
+#if USER_INITIAL_COST_TEMP
+  if ((USER_OPTIONS->User_Cost_Temperature =
+       (double *) calloc (1, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "initialize_parameters(): USER_OPTIONS->User_Cost_Temperature");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#if ASA_TEMPLATE
+  USER_OPTIONS->User_Cost_Temperature[0] = 5.936648E+09;
+#endif
+#endif /* USER_INITIAL_COST_TEMP */
+#if DELTA_PARAMETERS
+  if ((USER_OPTIONS->User_Delta_Parameter =
+       (double *) calloc (*parameter_dimension, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "initialize_parameters(): USER_OPTIONS->User_Delta_Parameter");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#if ASA_TEMPLATE
+  for (index = 0; index < *parameter_dimension; ++index)
+    USER_OPTIONS->User_Delta_Parameter[index] = 0.001;
+#endif
+#endif /* DELTA_PARAMETERS */
+#if QUENCH_PARAMETERS
+  if ((USER_OPTIONS->User_Quench_Param_Scale =
+       (double *) calloc (*parameter_dimension, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "initialize_parameters(): USER_OPTIONS->User_Quench_Param_Scale");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#if ASA_TEMPLATE
+  for (index = 0; index < *parameter_dimension; ++index)
+    USER_OPTIONS->User_Quench_Param_Scale[index] = 1.0;
+#endif
+#if ASA_TEMPLATE_MULTIPLE
+  for (index = 0; index < *parameter_dimension; ++index)
+    USER_OPTIONS->User_Quench_Param_Scale[index] = 1.0;
+#endif
+#if ASA_TEMPLATE_SAVE
+  for (index = 0; index < *parameter_dimension; ++index)
+    USER_OPTIONS->User_Quench_Param_Scale[index] = 1.0;
+#endif
+#endif /* QUENCH_PARAMETERS */
+#if QUENCH_COST
+  if ((USER_OPTIONS->User_Quench_Cost_Scale =
+       (double *) calloc (1, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "initialize_parameters(): USER_OPTIONS->User_Quench_Cost_Scale");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#if ASA_TEMPLATE
+  USER_OPTIONS->User_Quench_Cost_Scale[0] = 1.0;
+#endif
+#if ASA_TEMPLATE_MULTIPLE
+  USER_OPTIONS->User_Quench_Cost_Scale[0] = 1.0;
+#endif
+#if ASA_TEMPLATE_SAVE
+  USER_OPTIONS->User_Quench_Cost_Scale[0] = 1.0;
+#endif
+#endif /* QUENCH_COST */
+
+  /* use asa_opt to read in QUENCH USER_OPTIONS */
+#if OPTIONS_FILE_DATA
+#if QUENCH_COST
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%lf", &(USER_OPTIONS->User_Quench_Cost_Scale[0]));
+
+#if QUENCH_PARAMETERS
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%s", read_option);
+  for (index = 0; index < *parameter_dimension; ++index) {
+#if INT_ALLOC
+    fscanf (ptr_options, "%d", &read_index);
+#else
+#if INT_LONG
+    fscanf (ptr_options, "%ld", &read_index);
+#else
+    fscanf (ptr_options, "%d", &read_index);
+#endif
+#endif
+    fscanf (ptr_options, "%lf",
+            &(USER_OPTIONS->User_Quench_Param_Scale[read_index]));
+  }
+#endif /* QUENCH_PARAMETERS */
+#endif /* QUENCH_COST */
+#endif /* OPTIONS_FILE_DATA */
+
+#if RATIO_TEMPERATURE_SCALES
+  if ((USER_OPTIONS->User_Temperature_Ratio =
+       (double *) calloc (*parameter_dimension, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "initialize_parameters(): USER_OPTIONS->User_Temperature_Ratio");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#if ASA_TEMPLATE
+  for (index = 0; index < *parameter_dimension; ++index)
+    USER_OPTIONS->User_Temperature_Ratio[index] = 1.0;
+#endif
+#endif /* RATIO_TEMPERATURE_SCALES */
+  /* Defines the limit of collection of sampled data by asa */
+#if ASA_SAMPLE
+  /* create memory for Bias_Generated[] */
+  if ((USER_OPTIONS->Bias_Generated =
+       (double *) calloc (*parameter_dimension, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "initialize_parameters(): USER_OPTIONS->Bias_Generated");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#endif
+
+#if ASA_RESOLUTION
+  if ((USER_OPTIONS->Coarse_Resolution =
+       (double *) calloc (*parameter_dimension, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "initialize_parameters(): USER_OPTIONS->Coarse_Resolution");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#if ASA_TEMPLATE
+  for (index = 0; index < *parameter_dimension; ++index)
+    USER_OPTIONS->Coarse_Resolution[index] = 1.0;
+#endif
+#endif /* ASA_RESOLUTION */
+#if ASA_QUEUE
+#if ASA_RESOLUTION
+  USER_OPTIONS->Queue_Resolution = USER_OPTIONS->Coarse_Resolution;
+#else /* ASA_RESOLUTION */
+  if ((USER_OPTIONS->Queue_Resolution =
+       (double *) calloc (*parameter_dimension, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "initialize_parameters(): USER_OPTIONS->Queue_Resolution");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#endif /* ASA_RESOLUTION */
+#if ASA_TEMPLATE_QUEUE
+  USER_OPTIONS->Queue_Size = 100;
+  for (index = 0; index < *parameter_dimension; ++index)
+    USER_OPTIONS->Queue_Resolution[index] = 0.001;
+#endif
+#endif /* ASA_QUEUE */
+#if MULTI_MIN
+#if ASA_TEMPLATE
+  USER_OPTIONS->Multi_Number = 2;
+#endif
+  if ((USER_OPTIONS->Multi_Cost =
+       (double *) calloc (USER_OPTIONS->Multi_Number,
+                          sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "initialize_parameters(): USER_OPTIONS->Multi_Cost");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  if ((USER_OPTIONS->Multi_Grid =
+       (double *) calloc (*parameter_dimension, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "initialize_parameters(): USER_OPTIONS->Multi_Grid");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  if ((USER_OPTIONS->Multi_Params =
+       (double **) calloc (USER_OPTIONS->Multi_Number,
+                           sizeof (double *))) == NULL) {
+    strcpy (user_exit_msg,
+            "initialize_parameters(): USER_OPTIONS->Multi_Params");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  for (multi_index = 0; multi_index < USER_OPTIONS->Multi_Number;
+       ++multi_index) {
+    if ((USER_OPTIONS->Multi_Params[multi_index] =
+         (double *) calloc (*parameter_dimension, sizeof (double))) == NULL) {
+      strcpy (user_exit_msg,
+              "initialize_parameters(): USER_OPTIONS->Multi_Params[multi_index]");
+      Exit_USER (user_exit_msg);
+      return (-2);
+    }
+  }
+#if ASA_TEST
+  for (index = 0; index < *parameter_dimension; ++index) {
+    USER_OPTIONS->Multi_Grid[index] = 0.05;
+  }
+  USER_OPTIONS->Multi_Specify = 0;
+#endif
+#if ASA_TEMPLATE
+  for (index = 0; index < *parameter_dimension; ++index) {
+    USER_OPTIONS->Multi_Grid[index] =
+      (parameter_upper_bound[index] - parameter_lower_bound[index]) / 100.0;
+  }
+  USER_OPTIONS->Multi_Specify = 0;
+#endif /* ASA_TEMPLATE */
+#endif /* MULTI_MIN */
+  USER_OPTIONS->Asa_Recursive_Level = 0;
+
+#if MY_TEMPLATE                 /* MY_TEMPLATE_params */
+  /* If not using RECUR_OPTIONS_FILE_DATA or data read from asa_opt,
+     store the parameter ranges
+     store the parameter types
+     store the initial parameter values
+     other changes needed for initialization */
+#endif /* MY_TEMPLATE params */
+
+  return (0);
+}
+
+#if COST_FILE
+#else
+/***********************************************************************
+* double cost_function
+*	This is the users cost function to optimize
+*	(find the minimum).
+*	cost_flag is set to TRUE if the parameter set
+*	does not violates any constraints
+*       parameter_lower_bound and parameter_upper_bound may be
+*       adaptively changed during the search.
+***********************************************************************/
+
+#if HAVE_ANSI
+double
+cost_function (double *x,
+               double *parameter_lower_bound,
+               double *parameter_upper_bound,
+               double *cost_tangents,
+               double *cost_curvature,
+               ALLOC_INT * parameter_dimension,
+               int *parameter_int_real,
+               int *cost_flag, int *exit_code, USER_DEFINES * USER_OPTIONS)
+#else
+double
+cost_function (x,
+               parameter_lower_bound,
+               parameter_upper_bound,
+               cost_tangents,
+               cost_curvature,
+               parameter_dimension,
+               parameter_int_real, cost_flag, exit_code, USER_OPTIONS)
+     double *x;
+     double *parameter_lower_bound;
+     double *parameter_upper_bound;
+     double *cost_tangents;
+     double *cost_curvature;
+     ALLOC_INT *parameter_dimension;
+     int *parameter_int_real;
+     int *cost_flag;
+     int *exit_code;
+     USER_DEFINES *USER_OPTIONS;
+#endif
+{
+
+#if ASA_TEST                    /* ASA test problem */
+  /* Objective function from
+   * %A A. Corana
+   * %A M. Marchesi
+   * %A C. Martini
+   * %A S. Ridella
+   * %T Minimizing multimodal functions of continuous variables
+   *    with the "simulated annealing" algorithm
+   * %J ACM Trans. Mathl. Software
+   * %V 13
+   * %N 3
+   * %P 262-279
+   * %D 1987
+   *
+   * This function, when used with ASA_TEST_POINT set to TRUE, contains
+   * 1.0E20 local minima.  When *parameter_dimension is equal to 4, visiting
+   * each minimum for a millisecond would take about the present age of the
+   * universe to visit all these minima. */
+
+  /* defines for the test problem, which assume *parameter_dimension
+     is a multiple of 4.  If this is set to a large number, you
+     likely should set Curvature_0 to TRUE. */
+  double q_n, d_i, s_i, t_i, z_i, c_r;
+  int k_i;
+#if ASA_TEST_POINT
+  ALLOC_INT k_flag;
+#endif
+  ALLOC_INT i, j;
+#if SELF_OPTIMIZE
+#else
+  static LONG_INT funevals = 0;
+#endif
+#if ASA_TEMPLATE_SAVE
+  static int read_test = 0;
+  FILE *ptr_read_test;
+#endif
+
+#if MY_TEMPLATE                 /* MY_TEMPLATE_diminishing_ranges */
+  /* insert code to automate changing ranges of parameters */
+#endif
+#if ASA_TEMPLATE                /* example of diminishing ranges */
+  if (USER_OPTIONS->Locate_Cost == 12 && *(USER_OPTIONS->Best_Cost) < 1.0) {
+    fprintf (ptr_out, "best_cost = %g\n", *(USER_OPTIONS->Best_Cost));
+    for (i = 0; i < *parameter_dimension; ++i) {
+      parameter_lower_bound[i] = USER_OPTIONS->Best_Parameters[i]
+        - 0.5 * fabs (parameter_lower_bound[i]
+                      - USER_OPTIONS->Best_Parameters[i]);
+      parameter_upper_bound[i] = USER_OPTIONS->Best_Parameters[i]
+        + 0.5 * fabs (parameter_upper_bound[i]
+                      - USER_OPTIONS->Best_Parameters[i]);
+      parameter_lower_bound[i] = MIN (parameter_lower_bound[i],
+                                      USER_OPTIONS->Best_Parameters[i] -
+                                      0.01);
+      parameter_upper_bound[i] =
+        MAX (parameter_upper_bound[i],
+             USER_OPTIONS->Best_Parameters[i] + 0.01);
+    }
+  }
+#endif /* ASA_TEMPLATE */
+
+  /* a_i = parameter_upper_bound[i] */
+  s_i = 0.2;
+  t_i = 0.05;
+  c_r = 0.15;
+
+#if ASA_TEST_POINT
+  k_flag = 0;
+  for (i = 0; i < *parameter_dimension; ++i) {
+    if (fabs (parameter_upper_bound[i] - parameter_lower_bound[i]) <
+        (double) EPS_DOUBLE)
+      continue;
+
+    if (x[i] > 0.0) {
+      k_i = (int) (x[i] / s_i + 0.5);
+    } else if (x[i] < 0.0) {
+      k_i = (int) (x[i] / s_i - 0.5);
+    } else {
+      k_i = 0;
+    }
+    if (k_i == 0)
+      ++k_flag;
+  }
+#endif /* ASA_TEST_POINT */
+
+  q_n = 0.0;
+  for (i = 0; i < *parameter_dimension; ++i) {
+    if (fabs (parameter_upper_bound[i] - parameter_lower_bound[i]) <
+        (double) EPS_DOUBLE)
+      continue;
+
+    j = i % 4;
+    switch (j) {
+    case 0:
+      d_i = 1.0;
+      break;
+    case 1:
+      d_i = 1000.0;
+      break;
+    case 2:
+      d_i = 10.0;
+      break;
+    default:
+      d_i = 100.0;
+    }
+    if (x[i] > 0.0) {
+      k_i = (int) (x[i] / s_i + 0.5);
+    } else if (x[i] < 0.0) {
+      k_i = (int) (x[i] / s_i - 0.5);
+    } else {
+      k_i = 0;
+    }
+
+#if ASA_TEST_POINT
+    if (fabs (k_i * s_i - x[i]) < t_i && k_flag != *parameter_dimension)
+#else
+    if (fabs (k_i * s_i - x[i]) < t_i)
+#endif
+    {
+      if (k_i < 0) {
+        z_i = k_i * s_i + t_i;
+      } else if (k_i > 0) {
+        z_i = k_i * s_i - t_i;
+      } else {
+        z_i = 0.0;
+      }
+      q_n += c_r * d_i * z_i * z_i;
+    } else {
+      q_n += d_i * x[i] * x[i];
+    }
+  }
+  funevals = funevals + 1;
+
+#if ASA_TEMPLATE_SAVE
+  /* cause a crash */
+  if ((ptr_read_test = fopen ("asa_save", "r")) == NULL) {
+    read_test = 1;
+    fclose (ptr_read_test);
+  } else {
+    fclose (ptr_read_test);
+  }
+  /* will need a few hundred if testing ASA_PARALLEL to get an asa_save */
+  if (funevals == 50 && read_test == 1) {
+    fprintf (ptr_out, "\n\n*** intended crash to test ASA_SAVE *** \n\n");
+    fflush (ptr_out);
+#if INCL_STDOUT
+    printf ("\n\n*** intended crash to test ASA_SAVE *** \n\n");
+#endif /* INCL_STDOUT */
+    exit (2);
+  }
+#endif
+
+  *cost_flag = TRUE;
+
+#if SELF_OPTIMIZE
+#else
+#if TIME_CALC
+  /* print the time every PRINT_FREQUENCY evaluations */
+  if ((PRINT_FREQUENCY > 0) && ((funevals % PRINT_FREQUENCY) == 0)) {
+    fprintf (ptr_out, "funevals = %ld  ", funevals);
+#if INCL_STDOUT
+    print_time ("", ptr_out);
+#endif /* INCL_STDOUT */
+  }
+#endif
+#endif
+
+#if ASA_TEMPLATE_SAMPLE
+  USER_OPTIONS->Cost_Acceptance_Flag = TRUE;
+  if (USER_OPTIONS->User_Acceptance_Flag == FALSE && *cost_flag == TRUE)
+    USER_OPTIONS->Acceptance_Test (q_n,
+                                   parameter_lower_bound,
+                                   parameter_upper_bound,
+                                   *parameter_dimension, USER_OPTIONS);
+#endif /* ASA_TEMPLATE_SAMPLE */
+
+  return (q_n);
+#endif /* ASA_TEST */
+#if ASA_TEMPLATE_SAMPLE
+
+  int n;
+  double cost;
+
+  if (*cost_flag == FALSE) {
+    for (n = 0; n < *parameter_dimension; ++n)
+      if (fabs (parameter_upper_bound[n] - parameter_lower_bound[n]) <
+          (double) EPS_DOUBLE)
+        continue;
+
+    cost_tangents[n] = 2.0 * x[n];
+  }
+
+  cost = 0.0;
+  for (n = 0; n < *parameter_dimension; ++n) {
+    if (fabs (parameter_upper_bound[n] - parameter_lower_bound[n]) <
+        (double) EPS_DOUBLE)
+      continue;
+
+    cost += (x[n] * x[n]);
+  }
+
+  *cost_flag = TRUE;
+
+  USER_OPTIONS->Cost_Acceptance_Flag = TRUE;
+  if (USER_OPTIONS->User_Acceptance_Flag == FALSE && *cost_flag == TRUE)
+    USER_OPTIONS->Acceptance_Test (cost,
+                                   parameter_lower_bound,
+                                   parameter_upper_bound,
+                                   *parameter_dimension, USER_OPTIONS);
+
+  return (cost);
+#endif /* ASA_TEMPLATE_SAMPLE */
+#if MY_TEMPLATE                 /* MY_TEMPLATE_cost */
+   return USER_OPTIONS->Asa_Data_Ptr(x,cost_flag); 
+  /* Use the parameter values x[] and define your cost_function.
+     The {} brackets around this function are already in place. */
+#endif /* MY_TEMPLATE cost */
+}
+#endif /* COST_FILE */
+
+  /* Here is a good random number generator */
+
+#define MULT ((LONG_INT) 25173)
+#define MOD ((LONG_INT) 65536)
+#define INCR ((LONG_INT) 13849)
+#define FMOD ((double) 65536.0)
+
+
+/***********************************************************************
+* double myrand - returns random number between 0 and 1
+*	This routine returns the random number generator between 0 and 1
+***********************************************************************/
+
+static double
+myrand (LONG_INT * rand_seed)
+  /* returns random number in {0,1} */
+{
+#if TRUE                        /* (change to FALSE for alternative RNG) */
+  *rand_seed = (LONG_INT) ((MULT * (*rand_seed) + INCR) % MOD);
+  return ((double) (*rand_seed) / FMOD);
+#else
+  /* See "Random Number Generators: Good Ones Are Hard To Find,"
+     Park & Miller, CACM 31 (10) (October 1988) pp. 1192-1201.
+     ***********************************************************
+     THIS IMPLEMENTATION REQUIRES AT LEAST 32 BIT INTEGERS
+     *********************************************************** */
+#define _A_MULTIPLIER  16807L
+#define _M_MODULUS     2147483647L      /* (2**31)-1 */
+#define _Q_QUOTIENT    127773L  /* 2147483647 / 16807 */
+#define _R_REMAINDER   2836L    /* 2147483647 % 16807 */
+  long lo;
+  long hi;
+  long test;
+
+  hi = *rand_seed / _Q_QUOTIENT;
+  lo = *rand_seed % _Q_QUOTIENT;
+  test = _A_MULTIPLIER * lo - _R_REMAINDER * hi;
+  if (test > 0) {
+    *rand_seed = test;
+  } else {
+    *rand_seed = test + _M_MODULUS;
+  }
+  return ((double) *rand_seed / _M_MODULUS);
+#endif /* alternative RNG */
+}
+
+/***********************************************************************
+* double randflt
+***********************************************************************/
+
+static double
+randflt (LONG_INT * rand_seed)
+{
+  return (resettable_randflt (rand_seed, 0));
+}
+
+/***********************************************************************
+* double resettable_randflt
+***********************************************************************/
+
+static double
+resettable_randflt (LONG_INT * rand_seed, int reset)
+  /* shuffles random numbers in random_array[SHUFFLE] array */
+{
+
+  /* This RNG is a modified algorithm of that presented in
+   * %A K. Binder
+   * %A D. Stauffer
+   * %T A simple introduction to Monte Carlo simulations and some
+   *    specialized topics
+   * %B Applications of the Monte Carlo Method in statistical physics
+   * %E K. Binder
+   * %I Springer-Verlag
+   * %C Berlin
+   * %D 1985
+   * %P 1-36
+   * where it is stated that such algorithms have been found to be
+   * quite satisfactory in many statistical physics applications. */
+
+  double rranf;
+  unsigned kranf;
+  int n;
+  static int initial_flag = 0;
+  LONG_INT initial_seed;
+  static double random_array[SHUFFLE];  /* random variables */
+
+  if (*rand_seed < 0)
+    *rand_seed = -*rand_seed;
+
+  if ((initial_flag == 0) || reset) {
+    initial_seed = *rand_seed;
+
+    for (n = 0; n < SHUFFLE; ++n)
+      random_array[n] = myrand (&initial_seed);
+
+    initial_flag = 1;
+
+    for (n = 0; n < 1000; ++n)  /* warm up random generator */
+      rranf = randflt (&initial_seed);
+
+    rranf = randflt (rand_seed);
+
+    return (rranf);
+  }
+
+  kranf = (unsigned) (myrand (rand_seed) * SHUFFLE) % SHUFFLE;
+  rranf = *(random_array + kranf);
+  *(random_array + kranf) = myrand (rand_seed);
+
+  return (rranf);
+}
+
+#if USER_COST_SCHEDULE
+#if HAVE_ANSI
+double
+user_cost_schedule (double test_temperature, USER_DEFINES * USER_OPTIONS)
+#else
+double
+user_cost_schedule (test_temperature, USER_OPTIONS)
+     double test_temperature;
+     USER_DEFINES *USER_OPTIONS;
+#endif /* HAVE_ANSI */
+{
+  double x;
+
+#if ASA_TEMPLATE_SAMPLE
+  x = F_POW (test_temperature, 0.15);
+#endif
+#if ASA_TEMPLATE
+  x = test_temperature;
+#endif
+
+  return (x);
+}
+#endif /* USER_COST_SCHEDULE */
+
+#if USER_ACCEPTANCE_TEST
+#if HAVE_ANSI
+void
+user_acceptance_test (double current_cost,
+                      double *parameter_lower_bound,
+                      double *parameter_upper_bound,
+                      ALLOC_INT * parameter_dimension,
+                      USER_DEFINES * USER_OPTIONS)
+#else
+void
+user_acceptance_test (current_cost, parameter_lower_bound,
+                      parameter_upper_bound, parameter_dimension,
+                      USER_OPTIONS)
+     double current_cost;
+     double *parameter_lower_bound;
+     double *parameter_upper_bound;
+     ALLOC_INT *parameter_dimension;
+     USER_DEFINES *USER_OPTIONS;
+#endif /* HAVE_ANSI */
+{
+  double uniform_test, curr_cost_temp;
+#if USER_ACCEPT_ASYMP_EXP
+  double x, q, delta_cost;
+#endif
+
+#if ASA_TEMPLATE                /* ASA cost index */
+  /* Calculate the current ASA cost index.  This could be useful
+     to define a new schedule for the cost temperature, beyond
+     simple changes that can be made using USER_COST_SCHEDULE. */
+
+  int index;
+  double k_temperature, quench, y;
+  double xparameter_dimension;
+
+#if QUENCH_COST
+  quench = USER_OPTIONS->User_Quench_Cost_Scale[0];
+#else
+  quench = 1.0;
+#endif /* QUENCH_COST */
+  xparameter_dimension = (double) *parameter_dimension;
+  for (index = 0; index < *parameter_dimension; ++index)
+    if (fabs (parameter_upper_bound[index] - parameter_lower_bound[index]) <
+        (double) EPS_DOUBLE)
+      *xparameter_dimension -= 1.0;
+
+  y = -F_LOG (USER_OPTIONS->Cost_Temp_Curr
+              / USER_OPTIONS->Cost_Temp_Init) / USER_OPTIONS->Cost_Temp_Scale;
+
+  k_temperature = F_POW (y, xparameter_dimension / quench);
+#endif /* ASA cost index */
+
+  uniform_test = randflt (USER_OPTIONS->Random_Seed);
+  curr_cost_temp = USER_OPTIONS->Cost_Temp_Curr;
+
+#if ASA_TEMPLATE
+#if USER_COST_SCHEDULE
+  curr_cost_temp =
+    (USER_OPTIONS->Cost_Schedule (USER_OPTIONS->Cost_Temp_Curr,
+                                  USER_OPTIONS) + (double) EPS_DOUBLE);
+#else
+  curr_cost_temp = USER_OPTIONS->Cost_Temp_Curr;
+#endif
+#endif /* ASA_TEMPLATE */
+
+  /* You must add in your own test here.  If USER_ACCEPT_ASYMP_EXP
+     also is TRUE here, then you can use the default
+     Asymp_Exp_Param=1 to replicate the code in asa.c. */
+
+#if USER_ACCEPT_ASYMP_EXP
+#if USER_COST_SCHEDULE
+  curr_cost_temp =
+    (USER_OPTIONS->Cost_Schedule (USER_OPTIONS->Cost_Temp_Curr,
+                                  USER_OPTIONS) + (double) EPS_DOUBLE);
+#endif
+
+  delta_cost = (current_cost - *(USER_OPTIONS->Last_Cost))
+    / (curr_cost_temp + (double) EPS_DOUBLE);
+
+  /* The following asymptotic approximation to the exponential
+   * function, "Tsallis statistics," was proposed in
+   * %A T.J.P. Penna
+   * %T Traveling salesman problem and Tsallis statistics
+   * %J Phys. Rev. E
+   * %V 50
+   * %N 6
+   * %P R1-R3
+   * %D 1994
+   * While the use of the TSP for a test case is of dubious value (since
+   * there are many special algorithms for this problem), the use of this
+   * function is another example of how to control the rate of annealing
+   * of the acceptance criteria.  E.g., if you require a more moderate
+   * acceptance test, then negative q may be helpful. */
+
+  q = USER_OPTIONS->Asymp_Exp_Param;
+  if (fabs (1.0 - q) < (double) EPS_DOUBLE)
+    x = MIN (1.0, (F_EXP (-delta_cost)));       /* Boltzmann test */
+  else if ((1.0 - (1.0 - q) * delta_cost) < (double) EPS_DOUBLE)
+    x = MIN (1.0, (F_EXP (-delta_cost)));       /* Boltzmann test */
+  else
+    x = MIN (1.0, F_POW ((1.0 - (1.0 - q) * delta_cost), (1.0 / (1.0 - q))));
+
+  USER_OPTIONS->Prob_Bias = x;
+  if (x >= uniform_test)
+    USER_OPTIONS->User_Acceptance_Flag = TRUE;
+  else
+    USER_OPTIONS->User_Acceptance_Flag = FALSE;
+
+#endif /* USER_ACCEPT_ASYMP_EXP */
+}
+#endif /* USER_ACCEPTANCE_TEST */
+
+#if USER_GENERATING_FUNCTION
+#if HAVE_ANSI
+double
+user_generating_distrib (LONG_INT * seed,
+                         ALLOC_INT * parameter_dimension,
+                         ALLOC_INT index_v,
+                         double temperature_v,
+                         double init_param_temp_v,
+                         double temp_scale_params_v,
+                         double parameter_v,
+                         double parameter_range_v,
+                         double *last_saved_parameter,
+                         USER_DEFINES * USER_OPTIONS)
+#else
+double
+user_generating_distrib (seed,
+                         parameter_dimension,
+                         index_v,
+                         temperature_v,
+                         init_param_temp_v,
+                         temp_scale_params_v,
+                         parameter_v,
+                         parameter_range_v,
+                         last_saved_parameter, USER_OPTIONS)
+     LONG_INT *seed;
+     ALLOC_INT *parameter_dimension;
+     ALLOC_INT index_v;
+     double temperature_v;
+     double init_param_temp_v;
+     double temp_scale_params_v;
+     double parameter_v;
+     double parameter_range_v;
+     double *last_saved_parameter;
+     USER_DEFINES *USER_OPTIONS;
+#endif
+{
+#if ASA_TEMPLATE
+  double x, y, z;
+
+  /* This is the ASA distribution.  A slower temperature schedule can be
+     obtained here, e.g., temperature_v = pow(temperature_v, 0.5); */
+
+  x = randflt (seed);
+  y = x < 0.5 ? -1.0 : 1.0;
+  z = y * temperature_v * (F_POW ((1.0 + 1.0 / temperature_v),
+                                  fabs (2.0 * x - 1.0)) - 1.0);
+
+  x = parameter_v + z * parameter_range_v;
+
+  return (x);
+#endif /* ASA_TEMPLATE */
+}
+#endif /* USER_GENERATING_FUNCTION */
+
+#if USER_REANNEAL_COST
+#if HAVE_ANSI
+int
+user_reanneal_cost (double *cost_best,
+                    double *cost_last,
+                    double *initial_cost_temperature,
+                    double *current_cost_temperature,
+                    USER_DEFINES * USER_OPTIONS)
+#else
+int
+user_reanneal_cost (cost_best,
+                    cost_last,
+                    initial_cost_temperature,
+                    current_cost_temperature, USER_OPTIONS)
+     double *cost_best;
+     double *cost_last;
+     double *initial_cost_temperature;
+     double *current_cost_temperature;
+     USER_DEFINES *USER_OPTIONS;
+#endif /* HAVE_ANSI */
+{
+  int cost_test;
+  double tmp_dbl;
+
+#if ASA_TEMPLATE
+  static int first_time = 1;
+  static double save_last[3];
+  double average_cost_last;
+
+  if (first_time == 1) {
+    first_time = 0;
+    save_last[0] = save_last[1] = save_last[2] = *cost_last;
+  }
+
+  save_last[2] = save_last[1];
+  save_last[1] = save_last[0];
+  save_last[0] = *cost_last;
+  average_cost_last =
+    fabs ((save_last[0] + save_last[1] + save_last[2]) / 3.0);
+
+  tmp_dbl = MAX (fabs (*cost_best), average_cost_last);
+  tmp_dbl = MAX ((double) EPS_DOUBLE, tmp_dbl);
+  *initial_cost_temperature = MIN (*initial_cost_temperature, tmp_dbl);
+
+  /* This test can be useful if your cost function goes from a positive
+     to a negative value, and you do not want to get get stuck in a local
+     minima around zero due to the default in reanneal().  Pick any
+     number instead of 0.0001 */
+  tmp_dbl = MIN (fabs (*cost_last), fabs (*cost_best));
+  if (tmp_dbl < 0.0001)
+    cost_test = FALSE;
+  else
+    cost_test = TRUE;
+#endif /* ASA_TEMPLATE */
+
+  tmp_dbl = MAX (fabs (cost_last), fabs (cost_best));
+  tmp_dbl = MAX ((double) EPS_DOUBLE, tmp_dbl);
+  *initial_cost_temperature = MIN (*initial_cost_temperature, tmp_dbl);
+
+  *current_cost_temperature =
+    MAX (fabs (cost_last - cost_best), *current_cost_temperature);
+  *current_cost_temperature =
+    MAX ((double) EPS_DOUBLE, *current_cost_temperature);
+  *current_cost_temperature =
+    MIN (*current_cost_temperature, *initial_cost_temperature);
+
+  cost_test = TRUE;
+
+  return (cost_test);
+}
+#endif /* USER_REANNEAL_COST */
+
+#if USER_REANNEAL_PARAMETERS
+#if HAVE_ANSI
+double
+user_reanneal_params (double current_temp,
+                      double tangent,
+                      double max_tangent, USER_DEFINES * USER_OPTIONS)
+#else
+double
+user_reanneal_params (current_temp, tangent, max_tangent, USER_OPTIONS)
+     double current_temp;
+     double tangent;
+     double max_tangent;
+     USER_DEFINES *USER_OPTIONS;
+#endif /* HAVE_ANSI */
+{
+#if ASA_TEMPLATE
+  double x;
+
+  x = current_temp * (max_tangent / tangent);
+
+  return (x);
+#endif
+}
+#endif /* USER_REANNEAL_PARAMETERS */
+
+#if SELF_OPTIMIZE
+
+/***********************************************************************
+* main
+*	This is a sample calling program to self-optimize ASA
+***********************************************************************/
+#if HAVE_ANSI
+
+#if ASA_LIB
+int
+asa_main (
+#if ASA_TEMPLATE_LIB
+           double *main_recur_cost_value,
+           double *main_recur_cost_parameters, int *main_recur_exit_code
+#endif
+  )
+#else /* ASA_LIB */
+int
+main (int argc, char **argv)
+#endif                          /* ASA_LIB */
+#else /* HAVE_ANSI */
+
+#if ASA_LIB
+int
+asa_main (
+#if ASA_TEMPLATE_LIB
+           main_recur_cost_value,
+           main_recur_cost_parameters, main_recur_exit_code
+#endif
+  )
+#if ASA_TEMPLATE_LIB
+     double *main_recur_cost_value;
+     double *main_recur_cost_parameters;
+     int *main_recur_exit_code;
+#endif
+
+#else /* ASA_LIB */
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+#endif /* ASA_LIB */
+
+#endif /* HAVE_ANSI */
+{
+
+  /* seed for random number generator */
+  LONG_INT *recur_rand_seed;
+
+#if RECUR_OPTIONS_FILE
+  FILE *recur_ptr_options;
+  char read_option[80];
+  char read_if[4], read_FALSE[6], read_comm1[3], read_ASA_SAVE[9],
+    read_comm2[3];
+  int read_int;
+#if INT_LONG
+  LONG_INT read_long;
+#endif
+  double read_double;
+#endif
+
+  int *recur_exit_code;
+#if MULTI_MIN
+  int multi_index;
+  ALLOC_INT n_param;
+#endif
+
+  double *recur_parameter_lower_bound, *recur_parameter_upper_bound;
+  double *recur_cost_parameters, *recur_cost_tangents, *recur_cost_curvature;
+  double recur_cost_value;
+
+  ALLOC_INT *recur_parameter_dimension;
+  int *recur_parameter_int_real;
+  int *recur_cost_flag;
+  int recur_initialize_parameters_value;
+  ALLOC_INT recur_v;
+#if MY_TEMPLATE                 /* MY_TEMPLATE_recur_main_decl */
+  /* add some declarations if required */
+#endif
+
+  USER_DEFINES *RECUR_USER_OPTIONS;
+
+  if ((recur_parameter_dimension =
+       (ALLOC_INT *) calloc (1, sizeof (ALLOC_INT))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): recur_parameter_dimension");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  if ((recur_exit_code = (int *) calloc (1, sizeof (int))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): recur_exit_code");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  if ((recur_cost_flag = (int *) calloc (1, sizeof (int))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): recur_cost_flag");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+
+  if ((RECUR_USER_OPTIONS =
+       (USER_DEFINES *) calloc (1, sizeof (USER_DEFINES))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): RECUR_USER_OPTIONS");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#if RECUR_OPTIONS_FILE
+  recur_ptr_options = fopen ("asa_opt_recur", "r");
+
+  fscanf (recur_ptr_options, "%s%s%s%s%s",
+          read_if, read_FALSE, read_comm1, read_ASA_SAVE, read_comm2);
+  if (strcmp (read_if, "#if") || strcmp (read_FALSE, "FALSE") ||
+      strcmp (read_comm1, "/*") || strcmp (read_ASA_SAVE, "ASA_SAVE") ||
+      strcmp (read_comm2, "*/")) {
+    fprintf (ptr_out, "\n\n*** not asa_opt_recur for this version *** \n\n");
+    fflush (ptr_out);
+#if INCL_STDOUT
+    printf ("\n\n*** EXIT not asa_opt_recur for this version *** \n\n");
+#endif /* INCL_STDOUT */
+    return (-6);
+  }
+#if INT_LONG
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%ld", &read_long);
+  RECUR_USER_OPTIONS->Limit_Acceptances = read_long;
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%ld", &read_long);
+  RECUR_USER_OPTIONS->Limit_Generated = read_long;
+#else
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%d", &read_int);
+  RECUR_USER_OPTIONS->Limit_Acceptances = read_int;
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%d", &read_int);
+  RECUR_USER_OPTIONS->Limit_Generated = read_int;
+#endif
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%d", &read_int);
+  RECUR_USER_OPTIONS->Limit_Invalid_Generated_States = read_int;
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%lf", &read_double);
+  RECUR_USER_OPTIONS->Accepted_To_Generated_Ratio = read_double;
+
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%lf", &read_double);
+  RECUR_USER_OPTIONS->Cost_Precision = read_double;
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%d", &read_int);
+  RECUR_USER_OPTIONS->Maximum_Cost_Repeat = read_int;
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%d", &read_int);
+  RECUR_USER_OPTIONS->Number_Cost_Samples = read_int;
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%lf", &read_double);
+  RECUR_USER_OPTIONS->Temperature_Ratio_Scale = read_double;
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%lf", &read_double);
+  RECUR_USER_OPTIONS->Cost_Parameter_Scale_Ratio = read_double;
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%lf", &read_double);
+  RECUR_USER_OPTIONS->Temperature_Anneal_Scale = read_double;
+
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%d", &read_int);
+  RECUR_USER_OPTIONS->Include_Integer_Parameters = read_int;
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%d", &read_int);
+  RECUR_USER_OPTIONS->User_Initial_Parameters = read_int;
+#if INT_ALLOC
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%d", &read_int);
+  RECUR_USER_OPTIONS->Sequential_Parameters = read_int;
+#else
+#if INT_LONG
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%ld", &read_long);
+  RECUR_USER_OPTIONS->Sequential_Parameters = read_long;
+#else
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%d", &read_int);
+  RECUR_USER_OPTIONS->Sequential_Parameters = read_int;
+#endif
+#endif
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%lf", &read_double);
+  RECUR_USER_OPTIONS->Initial_Parameter_Temperature = read_double;
+
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%d", &read_int);
+  RECUR_USER_OPTIONS->Acceptance_Frequency_Modulus = read_int;
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%d", &read_int);
+  RECUR_USER_OPTIONS->Generated_Frequency_Modulus = read_int;
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%d", &read_int);
+  RECUR_USER_OPTIONS->Reanneal_Cost = read_int;
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%d", &read_int);
+  RECUR_USER_OPTIONS->Reanneal_Parameters = read_int;
+
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%lf", &read_double);
+  RECUR_USER_OPTIONS->Delta_X = read_double;
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%d", &read_int);
+  RECUR_USER_OPTIONS->User_Tangents = read_int;
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%d", &read_int);
+  RECUR_USER_OPTIONS->Curvature_0 = read_int;
+
+#else /* RECUR_OPTIONS_FILE */
+  RECUR_USER_OPTIONS->Limit_Acceptances = 100;
+  RECUR_USER_OPTIONS->Limit_Generated = 1000;
+  RECUR_USER_OPTIONS->Limit_Invalid_Generated_States = 1000;
+  RECUR_USER_OPTIONS->Accepted_To_Generated_Ratio = 1.0E-4;
+
+  RECUR_USER_OPTIONS->Cost_Precision = 1.0E-18;
+  RECUR_USER_OPTIONS->Maximum_Cost_Repeat = 2;
+  RECUR_USER_OPTIONS->Number_Cost_Samples = 2;
+  RECUR_USER_OPTIONS->Temperature_Ratio_Scale = 1.0E-5;
+  RECUR_USER_OPTIONS->Cost_Parameter_Scale_Ratio = 1.0;
+  RECUR_USER_OPTIONS->Temperature_Anneal_Scale = 100.0;
+
+  RECUR_USER_OPTIONS->Include_Integer_Parameters = FALSE;
+  RECUR_USER_OPTIONS->User_Initial_Parameters = FALSE;
+  RECUR_USER_OPTIONS->Sequential_Parameters = -1;
+  RECUR_USER_OPTIONS->Initial_Parameter_Temperature = 1.0;
+
+  RECUR_USER_OPTIONS->Acceptance_Frequency_Modulus = 15;
+  RECUR_USER_OPTIONS->Generated_Frequency_Modulus = 10000;
+  RECUR_USER_OPTIONS->Reanneal_Cost = FALSE;
+  RECUR_USER_OPTIONS->Reanneal_Parameters = FALSE;
+
+  RECUR_USER_OPTIONS->Delta_X = 1.0E-6;
+  RECUR_USER_OPTIONS->User_Tangents = FALSE;
+  RECUR_USER_OPTIONS->Curvature_0 = TRUE;
+
+#endif /* RECUR_OPTIONS_FILE */
+
+  /* the number of parameters for the recur_cost_function */
+#if RECUR_OPTIONS_FILE_DATA
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%s", read_option);
+
+#if INT_ALLOC
+  fscanf (recur_ptr_options, "%d", &read_int);
+  *recur_parameter_dimension = read_int;
+#else
+#if INT_LONG
+  fscanf (recur_ptr_options, "%ld", &read_long);
+  *recur_parameter_dimension = read_long;
+#else
+  fscanf (recur_ptr_options, "%d", &read_int);
+  *recur_parameter_dimension = read_int;
+#endif
+#endif
+
+#else /* RECUR_OPTIONS_FILE_DATA */
+#if ASA_TEMPLATE_SELFOPT
+  *recur_parameter_dimension = 2;
+#endif
+#if MY_TEMPLATE                 /* MY_TEMPLATE_recur_dim */
+  /* If not using RECUR_OPTIONS_FILE_DATA or data read from recur_asa_opt,
+     insert the number of parameters for the recur_cost_function */
+#endif /* MY_TEMPLATE recur_dim */
+#endif /* RECUR_OPTIONS_FILE_DATA */
+  if ((recur_parameter_lower_bound =
+       (double *) calloc (*recur_parameter_dimension,
+                          sizeof (double))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): recur_parameter_lower_bound");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  if ((recur_parameter_upper_bound =
+       (double *) calloc (*recur_parameter_dimension,
+                          sizeof (double))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): recur_parameter_upper_bound");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+
+  if ((recur_cost_parameters =
+       (double *) calloc (*recur_parameter_dimension,
+                          sizeof (double))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): recur_cost_parameters");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+
+  if ((recur_parameter_int_real =
+       (int *) calloc (*recur_parameter_dimension, sizeof (int))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): recur_parameter_int_real");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+
+  if ((recur_cost_tangents =
+       (double *) calloc (*recur_parameter_dimension,
+                          sizeof (double))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): recur_cost_tangents");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+
+  if (RECUR_USER_OPTIONS->Curvature_0 == FALSE
+      || RECUR_USER_OPTIONS->Curvature_0 == -1) {
+
+    if ((recur_cost_curvature =
+         (double *) calloc ((*recur_parameter_dimension)
+                            * (*recur_parameter_dimension),
+                            sizeof (double))) == NULL) {
+      strcpy (user_exit_msg, "main()/asa_main(): recur_cost_curvature");
+      Exit_USER (user_exit_msg);
+      return (-2);
+    }
+  } else {
+    recur_cost_curvature = (double *) NULL;
+  }
+
+#if ASA_TEMPLATE_SELFOPT
+  /* Set memory to that required for use. */
+  RECUR_USER_OPTIONS->Asa_Data_Dim_Dbl = 1;
+  if ((RECUR_USER_OPTIONS->Asa_Data_Dbl =
+       (double *) calloc (RECUR_USER_OPTIONS->Asa_Data_Dim_Dbl,
+                          sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "main()/asa_main(): RECUR_USER_OPTIONS->Asa_Data_Dbl");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  /* Use Asa_Data[0] as flag, e.g., if used with SELF_OPTIMIZE. */
+  RECUR_USER_OPTIONS->Asa_Data_Dbl[0] = 0;
+#endif /* ASA_TEMPLATE_SELFOPT */
+
+#if OPTIONAL_DATA_PTR
+#if ASA_TEMPLATE
+  RECUR_USER_OPTIONS->Asa_Data_Dim_Ptr = 1;
+  if ((RECUR_USER_OPTIONS->Asa_Data_Ptr =
+       (OPTIONAL_PTR_TYPE *) calloc (RECUR_USER_OPTIONS->Asa_Data_Dim_Ptr,
+                                     sizeof (OPTIONAL_PTR_TYPE))) == NULL) {
+    strcpy (user_exit_msg,
+            "main()/asa_main(): RECUR_USER_OPTIONS->Asa_Data_Ptr");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#endif /* ASA_TEMPLATE */
+#endif /* OPTIONAL_DATA_PTR */
+
+#if ASA_SAVE
+  /* Such data could be saved in a user_save file, but for
+     convenience here everything is saved in asa_save. */
+  RECUR_USER_OPTIONS->Random_Array_Dim = SHUFFLE;
+  RECUR_USER_OPTIONS->Random_Array = random_array;
+#endif /* ASA_SAVE */
+
+  /* open the output file */
+#if ASA_SAVE
+  if (!strcmp (USER_OUT, "STDOUT")) {
+#if INCL_STDOUT
+    ptr_out = stdout;
+#endif /* INCL_STDOUT */
+  } else {
+    ptr_out = fopen (USER_OUT, "a");
+  }
+#else
+  if (!strcmp (USER_OUT, "STDOUT")) {
+#if INCL_STDOUT
+    ptr_out = stdout;
+#endif /* INCL_STDOUT */
+  } else {
+    ptr_out = fopen (USER_OUT, "w");
+  }
+#endif
+//  fprintf (ptr_out, "%s\n\n", USER_ID);
+
+  fflush (ptr_out);
+
+  if ((recur_rand_seed =
+       (ALLOC_INT *) calloc (1, sizeof (ALLOC_INT))) == NULL) {
+    strcpy (user_exit_msg, "main()/asa_main(): recur_rand_seed");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+
+  /* first value of *recur_rand_seed */
+#if ASA_LIB
+  *recur_rand_seed = (asa_rand_seed ? *asa_rand_seed : (LONG_INT) 696969);
+#else
+  *recur_rand_seed = 696969;
+#endif
+
+  randflt (recur_rand_seed);
+
+#if USER_COST_SCHEDULE
+  RECUR_USER_OPTIONS->Cost_Schedule = recur_user_cost_schedule;
+#endif
+#if USER_ACCEPTANCE_TEST
+  RECUR_USER_OPTIONS->Acceptance_Test = recur_user_acceptance_test;
+#endif
+#if USER_ACCEPT_ASYMP_EXP
+  RECUR_USER_OPTIONS->Asymp_Exp_Param = 1.0;
+#endif
+#if USER_GENERATING_FUNCTION
+  RECUR_USER_OPTIONS->Generating_Distrib = recur_user_generating_distrib;
+#endif
+#if USER_REANNEAL_COST
+  RECUR_USER_OPTIONS->Reanneal_Cost_Function = recur_user_reanneal_cost;
+#endif
+#if USER_REANNEAL_PARAMETERS
+  RECUR_USER_OPTIONS->Reanneal_Params_Function = recur_user_reanneal_params;
+#endif
+
+#if MY_TEMPLATE                 /* MY_TEMPLATE_recur_pre_initialize */
+  /* last changes before entering recur_initialize_parameters() */
+#endif
+
+  /* initialize the users parameters, allocating space, etc.
+     Note that the default is to have asa generate the initial
+     recur_cost_parameters that satisfy the user's constraints. */
+
+  recur_initialize_parameters_value =
+    recur_initialize_parameters (recur_cost_parameters,
+                                 recur_parameter_lower_bound,
+                                 recur_parameter_upper_bound,
+                                 recur_cost_tangents,
+                                 recur_cost_curvature,
+                                 recur_parameter_dimension,
+                                 recur_parameter_int_real,
+#if RECUR_OPTIONS_FILE_DATA
+                                 recur_ptr_options,
+#endif
+                                 RECUR_USER_OPTIONS);
+#if RECUR_OPTIONS_FILE
+  fclose (recur_ptr_options);
+#endif
+  if (recur_initialize_parameters_value == -2)
+    return (recur_initialize_parameters_value);
+
+#if USER_ASA_OUT
+  if ((RECUR_USER_OPTIONS->Asa_Out_File =
+       (char *) calloc (80, sizeof (char))) == NULL) {
+    strcpy (user_exit_msg,
+            "main()/asa_main(): RECUR_USER_OPTIONS->Asa_Out_File");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#if ASA_TEMPLATE_SELFOPT
+  strcpy (RECUR_USER_OPTIONS->Asa_Out_File, "asa_sfop");
+#endif
+#endif
+
+  recur_cost_value = asa (RECUR_USER_COST_FUNCTION,
+                          randflt,
+                          recur_rand_seed,
+                          recur_cost_parameters,
+                          recur_parameter_lower_bound,
+                          recur_parameter_upper_bound,
+                          recur_cost_tangents,
+                          recur_cost_curvature,
+                          recur_parameter_dimension,
+                          recur_parameter_int_real,
+                          recur_cost_flag,
+                          recur_exit_code, RECUR_USER_OPTIONS);
+  if (*recur_exit_code == -1) {
+#if INCL_STDOUT
+    printf ("\n\n*** error in calloc in ASA ***\n\n");
+#endif /* INCL_STDOUT */
+    fprintf (ptr_out, "\n\n*** error in calloc in ASA ***\n\n");
+    fflush (ptr_out);
+    return (-1);
+  }
+#if MULTI_MIN
+  fprintf (ptr_out, "Multi_Specify = %d\n",
+           RECUR_USER_OPTIONS->Multi_Specify);
+  for (n_param = 0; n_param < *recur_parameter_dimension; ++n_param) {
+    fprintf (ptr_out,
+#if INT_ALLOC
+             "Multi_Grid[%d] = %12.7g\n",
+#else
+#if INT_LONG
+             "Multi_Grid[%ld] = %12.7g\n",
+#else
+             "Multi_Grid[%d] = %12.7g\n",
+#endif
+#endif
+             n_param, RECUR_USER_OPTIONS->Multi_Grid[n_param]);
+  }
+  fprintf (ptr_out, "\n");
+  for (multi_index = 0; multi_index < RECUR_USER_OPTIONS->Multi_Number;
+       ++multi_index) {
+    fprintf (ptr_out, "\n");
+    fprintf (ptr_out, "Multi_Cost[%d] = %12.7g\n",
+             multi_index, RECUR_USER_OPTIONS->Multi_Cost[multi_index]);
+    for (n_param = 0; n_param < *recur_parameter_dimension; ++n_param) {
+      fprintf (ptr_out,
+#if INT_ALLOC
+               "Multi_Params[%d][%d] = %12.7g\n",
+#else
+#if INT_LONG
+               "Multi_Params[%d][%ld] = %12.7g\n",
+#else
+               "Multi_Params[%d][%d] = %12.7g\n",
+#endif
+#endif
+               multi_index, n_param,
+               RECUR_USER_OPTIONS->Multi_Params[multi_index][n_param]);
+    }
+  }
+  fprintf (ptr_out, "\n");
+  fflush (ptr_out);
+#endif /* MULTI_MIN */
+
+#if FITLOC
+  /* Fit_Local and Penalty may be set adaptively */
+  RECUR_USER_OPTIONS->Penalty = 1000;
+  RECUR_USER_OPTIONS->Fit_Local = 0;
+  RECUR_USER_OPTIONS->Iter_Max = 500;
+  if (RECUR_USER_OPTIONS->Fit_Local >= 1) {
+    recur_cost_value = fitloc (RECUR_USER_COST_FUNCTION,
+                               recur_cost_parameters,
+                               recur_parameter_lower_bound,
+                               recur_parameter_upper_bound,
+                               recur_cost_tangents,
+                               recur_cost_curvature,
+                               recur_parameter_dimension,
+                               recur_parameter_int_real,
+                               recur_cost_flag,
+                               recur_exit_code, RECUR_USER_OPTIONS, ptr_out);
+  }
+#endif /* FITLOC */
+
+  fprintf (ptr_out, "\n\n recur_cost_value = %12.7g\n", recur_cost_value);
+#if MY_TEMPLATE                 /* MY_TEMPLATE_recur_post_recur_asa */
+#endif
+#if ASA_TEMPLATE_LIB
+  *main_recur_cost_value = recur_cost_value;
+  for (recur_v = 0; recur_v < *recur_parameter_dimension; ++recur_v) {
+    main_recur_cost_parameters[recur_v] = recur_cost_parameters[recur_v];
+  }
+  *main_recur_exit_code = *recur_exit_code;
+#endif
+
+  for (recur_v = 0; recur_v < *recur_parameter_dimension; ++recur_v)
+#if INT_ALLOC
+    fprintf (ptr_out, "recur_cost_parameters[%d] = %12.7g\n",
+#else
+#if INT_LONG
+    fprintf (ptr_out, "recur_cost_parameters[%ld] = %12.7g\n",
+#else
+    fprintf (ptr_out, "recur_cost_parameters[%d] = %12.7g\n",
+#endif
+#endif
+             recur_v, recur_cost_parameters[recur_v]);
+
+  fprintf (ptr_out, "\n\n");
+
+
+  /* close all files */
+  ptr_out != stdout && fclose (ptr_out);
+
+#if OPTIONAL_DATA_DBL
+  free (RECUR_USER_OPTIONS->Asa_Data_Dbl);
+#endif
+#if OPTIONAL_DATA_INT
+  free (RECUR_USER_OPTIONS->Asa_Data_Int);
+#endif
+#if OPTIONAL_DATA_PTR
+  free (RECUR_USER_OPTIONS->Asa_Data_Ptr);
+#endif
+#if USER_ASA_OUT
+  free (RECUR_USER_OPTIONS->Asa_Out_File);
+#endif
+#if ASA_SAMPLE
+  free (RECUR_USER_OPTIONS->Bias_Generated);
+#endif
+#if ASA_QUEUE
+#if ASA_RESOLUTION
+#else
+  free (RECUR_USER_OPTIONS->Queue_Resolution);
+#endif
+#endif
+#if ASA_RESOLUTION
+  free (RECUR_USER_OPTIONS->Coarse_Resolution);
+#endif
+  if (RECUR_USER_OPTIONS->Curvature_0 == FALSE
+      || RECUR_USER_OPTIONS->Curvature_0 == -1)
+    free (recur_cost_curvature);
+#if USER_INITIAL_PARAMETERS_TEMPS
+  free (RECUR_USER_OPTIONS->User_Parameter_Temperature);
+#endif
+#if USER_INITIAL_COST_TEMP
+  free (RECUR_USER_OPTIONS->User_Cost_Temperature);
+#endif
+#if DELTA_PARAMETERS
+  free (RECUR_USER_OPTIONS->User_Delta_Parameter);
+#endif
+#if QUENCH_PARAMETERS
+  free (RECUR_USER_OPTIONS->User_Quench_Param_Scale);
+#endif
+#if QUENCH_COST
+  free (RECUR_USER_OPTIONS->User_Quench_Cost_Scale);
+#endif
+#if RATIO_TEMPERATURE_SCALES
+  free (RECUR_USER_OPTIONS->User_Temperature_Ratio);
+#endif
+#if MULTI_MIN
+  free (RECUR_USER_OPTIONS->Multi_Cost);
+  free (RECUR_USER_OPTIONS->Multi_Grid);
+  for (multi_index = 0; multi_index < RECUR_USER_OPTIONS->Multi_Number;
+       ++multi_index) {
+    free (RECUR_USER_OPTIONS->Multi_Params[multi_index]);
+  }
+  free (RECUR_USER_OPTIONS->Multi_Params);
+#endif /* MULTI_MIN */
+  free (RECUR_USER_OPTIONS);
+  free (recur_parameter_dimension);
+  free (recur_exit_code);
+  free (recur_cost_flag);
+  free (recur_parameter_lower_bound);
+  free (recur_parameter_upper_bound);
+  free (recur_cost_parameters);
+  free (recur_parameter_int_real);
+  free (recur_cost_tangents);
+  free (recur_rand_seed);
+
+  return (0);
+  /* NOTREACHED */
+}
+
+/***********************************************************************
+* recur_initialize_parameters
+*	This depends on the users cost function to optimize (minimum).
+*	The routine allocates storage needed for asa. The user should
+*	define the number of parameters and their ranges,
+*	and make sure the initial parameters are within
+*	the minimum and maximum ranges. The array
+*	recur_parameter_int_real should be REAL_TYPE (-1)
+*       for real parameters,
+***********************************************************************/
+#if HAVE_ANSI
+int
+recur_initialize_parameters (double *recur_cost_parameters,
+                             double *recur_parameter_lower_bound,
+                             double *recur_parameter_upper_bound,
+                             double *recur_cost_tangents,
+                             double *recur_cost_curvature,
+                             ALLOC_INT * recur_parameter_dimension,
+                             int *recur_parameter_int_real,
+#if RECUR_OPTIONS_FILE_DATA
+                             FILE * recur_ptr_options,
+#endif
+                             USER_DEFINES * RECUR_USER_OPTIONS)
+#else
+int
+recur_initialize_parameters (recur_cost_parameters,
+                             recur_parameter_lower_bound,
+                             recur_parameter_upper_bound,
+                             recur_cost_tangents,
+                             recur_cost_curvature,
+                             recur_parameter_dimension,
+                             recur_parameter_int_real,
+#if RECUR_OPTIONS_FILE_DATA
+                             recur_ptr_options,
+#endif
+                             RECUR_USER_OPTIONS)
+     double *recur_parameter_lower_bound;
+     double *recur_parameter_upper_bound;
+     double *recur_cost_parameters;
+     double *recur_cost_tangents;
+     double *recur_cost_curvature;
+     ALLOC_INT *recur_parameter_dimension;
+     int *recur_parameter_int_real;
+#if RECUR_OPTIONS_FILE_DATA
+     FILE *recur_ptr_options;
+#endif
+     USER_DEFINES *RECUR_USER_OPTIONS;
+#endif
+{
+  ALLOC_INT index;
+#if RECUR_OPTIONS_FILE_DATA
+  char read_option[80];
+  ALLOC_INT read_index;
+#endif
+#if MY_TEMPLATE                 /* MY_TEMPLATE_recur_init_decl */
+  /* add some declarations if required */
+#endif
+#if MULTI_MIN
+  int multi_index;
+#endif
+
+#if RECUR_OPTIONS_FILE_DATA
+  fscanf (recur_ptr_options, "%s", read_option);
+
+  for (index = 0; index < *recur_parameter_dimension; ++index) {
+#if MY_TEMPLATE                 /* MY_TEMPLATE_recur_read_opt */
+    /* put in some code as required to alter lines read from recur_asa_opt */
+#endif
+#if INT_ALLOC
+    fscanf (recur_ptr_options, "%d", &read_index);
+#else
+#if INT_LONG
+    fscanf (recur_ptr_options, "%ld", &read_index);
+#else
+    fscanf (recur_ptr_options, "%d", &read_index);
+#endif
+#endif
+    fscanf (recur_ptr_options, "%lf%lf%lf%d",
+            &(recur_parameter_lower_bound[read_index]),
+            &(recur_parameter_upper_bound[read_index]),
+            &(recur_cost_parameters[read_index]),
+            &(recur_parameter_int_real[read_index]));
+  }
+#else /* RECUR_OPTIONS_FILE_DATA */
+#if ASA_TEMPLATE_SELFOPT
+  /*  NOTE:
+     USER_OPTIONS->Temperature_Ratio_Scale = x[0];
+     USER_OPTIONS->Cost_Parameter_Scale_Ratio = x[1];
+   */
+
+  /* store the initial parameter values */
+  recur_cost_parameters[0] = 1.0E-5;
+  recur_cost_parameters[1] = 1.0;
+
+  recur_parameter_lower_bound[0] = 1.0E-6;
+  recur_parameter_upper_bound[0] = 1.0E-4;
+
+  recur_parameter_lower_bound[1] = 0.5;
+  recur_parameter_upper_bound[1] = 3.0;
+
+  /* store the initial parameter types */
+  for (index = 0; index < *recur_parameter_dimension; ++index)
+    recur_parameter_int_real[index] = REAL_TYPE;
+#endif
+#endif /* RECUR_OPTIONS_FILE_DATA */
+
+#if USER_INITIAL_PARAMETERS_TEMPS
+  if ((RECUR_USER_OPTIONS->User_Parameter_Temperature =
+       (double *) calloc (*recur_parameter_dimension,
+                          sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "recur_initialize_parameters(): RECUR_USER_OPTIONS->User_Parameter_Temperature");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  for (index = 0; index < *recur_parameter_dimension; ++index)
+    RECUR_USER_OPTIONS->User_Parameter_Temperature[index] = 1.0;
+#endif /* USER_INITIAL_PARAMETERS_TEMPS */
+#if USER_INITIAL_COST_TEMP
+  if ((RECUR_USER_OPTIONS->User_Cost_Temperature =
+       (double *) calloc (1, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "recur_initialize_parameters(): RECUR_USER_OPTIONS->User_Cost_Temperature");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  RECUR_USER_OPTIONS->User_Cost_Temperature[0] = 5.936648E+09;
+#endif /* USER_INITIAL_COST_TEMP */
+#if DELTA_PARAMETERS
+  if ((RECUR_USER_OPTIONS->User_Delta_Parameter =
+       (double *) calloc (*recur_parameter_dimension,
+                          sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "recur_initialize_parameters(): RECUR_USER_OPTIONS->User_Delta_Parameter");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  for (index = 0; index < *recur_parameter_dimension; ++index)
+    RECUR_USER_OPTIONS->User_Delta_Parameter[index] = 0.001;
+#endif /* DELTA_PARAMETERS */
+#if QUENCH_PARAMETERS
+  if ((RECUR_USER_OPTIONS->User_Quench_Param_Scale =
+       (double *) calloc (*recur_parameter_dimension,
+                          sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "recur_initialize_parameters(): RECUR_USER_OPTIONS->User_Quench_Param_Scale");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#if ASA_TEMPLATE
+  for (index = 0; index < *recur_parameter_dimension; ++index)
+    RECUR_USER_OPTIONS->User_Quench_Param_Scale[index] = 1.0;
+#endif
+#endif /* QUENCH_PARAMETERS */
+#if QUENCH_COST
+  if ((RECUR_USER_OPTIONS->User_Quench_Cost_Scale =
+       (double *) calloc (1, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "recur_initialize_parameters(): RECUR_USER_OPTIONS->User_Quench_Cost_Scale");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#if ASA_TEMPLATE
+  RECUR_USER_OPTIONS->User_Quench_Cost_Scale[0] = 1.0;
+#endif
+#endif /* QUENCH_COST */
+
+  /* use asa_opt_recur to read in QUENCH RECUR_USER_OPTIONS */
+#if RECUR_OPTIONS_FILE_DATA
+#if QUENCH_COST
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%lf",
+          &(RECUR_USER_OPTIONS->User_Quench_Cost_Scale[0]));
+
+#if QUENCH_PARAMETERS
+  fscanf (recur_ptr_options, "%s", read_option);
+  fscanf (recur_ptr_options, "%s", read_option);
+  for (index = 0; index < *recur_parameter_dimension; ++index) {
+#if INT_ALLOC
+    fscanf (recur_ptr_options, "%d", &read_index);
+#else
+#if INT_LONG
+    fscanf (recur_ptr_options, "%ld", &read_index);
+#else
+    fscanf (recur_ptr_options, "%d", &read_index);
+#endif
+#endif
+    fscanf (recur_ptr_options, "%lf",
+            &(RECUR_USER_OPTIONS->User_Quench_Param_Scale[read_index]));
+  }
+#endif /* QUENCH_PARAMETERS */
+#endif /* QUENCH_COST */
+#endif /* RECUR_OPTIONS_FILE_DATA */
+#if RATIO_TEMPERATURE_SCALES
+  if ((RECUR_USER_OPTIONS->User_Temperature_Ratio =
+       (double *) calloc (*recur_parameter_dimension,
+                          sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "recur_initialize_parameters(): RECUR_USER_OPTIONS->User_Temperature_Ratio");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#if ASA_TEMPLATE
+  for (index = 0; index < *recur_parameter_dimension; ++index)
+    RECUR_USER_OPTIONS->User_Temperature_Ratio[index] = 1.0;
+#endif
+#endif /* RATIO_TEMPERATURE_SCALES */
+  /* Defines the limit of collection of sampled data by asa */
+#if ASA_SAMPLE
+  /* create memory for Bias_Generated[] */
+  if ((RECUR_USER_OPTIONS->Bias_Generated =
+       (double *) calloc (*recur_parameter_dimension,
+                          sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "recur_initialize_parameters(): RECUR_USER_OPTIONS->Bias_Generated");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#if ASA_TEMPLATE
+  RECUR_USER_OPTIONS->Limit_Weights = 1.0E-7;
+#if QUENCH_COST
+  RECUR_USER_OPTIONS->User_Quench_Cost_Scale[0] = 1.0;
+#endif
+#if QUENCH_PARAMETERS
+  for (index = 0; index < *recur_parameter_dimension; ++index)
+    RECUR_USER_OPTIONS->User_Quench_Param_Scale[index] = 1.0;
+#endif
+#endif /* ASA_TEMPLATE */
+#endif /* ASA_SAMPLE */
+
+#if ASA_TEMPLATE
+#if ASA_PARALLEL
+  RECUR_USER_OPTIONS->Gener_Block = 1;
+  RECUR_USER_OPTIONS->Gener_Block_Max = 1;
+  RECUR_USER_OPTIONS->Gener_Mov_Avr = 1;
+#endif
+#endif
+#if ASA_RESOLUTION
+  if ((RECUR_USER_OPTIONS->Coarse_Resolution =
+       (double *) calloc (*recur_parameter_dimension,
+                          sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "recur_initialize_parameters(): RECUR_USER_OPTIONS->Coarse_Resolution");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#endif
+#if MULTI_MIN
+#if ASA_TEMPLATE
+  RECUR_USER_OPTIONS->Multi_Number = 2;
+#endif
+  if ((RECUR_USER_OPTIONS->Multi_Cost =
+       (double *) calloc (RECUR_USER_OPTIONS->Multi_Number,
+                          sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "initialize_parameters(): RECUR_USER_OPTIONS->Multi_Cost");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  if ((RECUR_USER_OPTIONS->Multi_Grid =
+       (double *) calloc (*recur_parameter_dimension,
+                          sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "recur_initialize_parameters(): RECUR_USER_OPTIONS->Multi_Grid");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  if ((RECUR_USER_OPTIONS->Multi_Params =
+       (double **) calloc (RECUR_USER_OPTIONS->Multi_Number,
+                           sizeof (double *))) == NULL) {
+    strcpy (user_exit_msg,
+            "initialize_parameters(): RECUR_USER_OPTIONS->Multi_Params");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  for (multi_index = 0; multi_index < RECUR_USER_OPTIONS->Multi_Number;
+       ++multi_index) {
+    if ((RECUR_USER_OPTIONS->Multi_Params[multi_index] =
+         (double *) calloc (*recur_parameter_dimension,
+                            sizeof (double))) == NULL) {
+      strcpy (user_exit_msg,
+              "recur_initialize_parameters(): RECUR_USER_OPTIONS->Multi_Params[multi_index]");
+      Exit_USER (user_exit_msg);
+      return (-2);
+    }
+  }
+#if ASA_TEST
+  for (index = 0; index < *recur_parameter_dimension; ++index) {
+    RECUR_USER_OPTIONS->Multi_Grid[index] = 0.05;
+  }
+  RECUR_USER_OPTIONS->Multi_Specify = 0;
+#endif
+#if ASA_TEMPLATE
+  for (index = 0; index < *recur_parameter_dimension; ++index) {
+    RECUR_USER_OPTIONS->Multi_Grid[index] =
+      (recur_parameter_upper_bound[index] -
+       recur_parameter_lower_bound[index]) / 100.0;
+  }
+  RECUR_USER_OPTIONS->Multi_Specify = 0;
+#endif /* ASA_TEMPLATE */
+#endif /* MULTI_MIN */
+#if ASA_TEMPLATE_QUEUE
+  RECUR_USER_OPTIONS->Queue_Size = 0;
+#endif
+#if ASA_QUEUE
+#if ASA_RESOLUTION
+  RECUR_USER_OPTIONS->Queue_Resolution =
+    RECUR_USER_OPTIONS->Coarse_Resolution;
+#else /* ASA_RESOLUTION */
+  if ((RECUR_USER_OPTIONS->Queue_Resolution =
+       (double *) calloc (*recur_parameter_dimension,
+                          sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "recur_initialize_parameters(): RECUR_USER_OPTIONS->Queue_Resolution");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#endif /* ASA_RESOLUTION */
+#if ASA_TEMPLATE_QUEUE
+  RECUR_USER_OPTIONS->Queue_Size = 0;
+#endif
+#endif /* ASA_QUEUE */
+#if MY_TEMPLATE                 /* MY_TEMPLATE_recur_params */
+  /* If not using RECUR_OPTIONS_FILE_DATA or data read from recur_asa_opt,
+     store the recur_parameter ranges
+     store the recur_parameter types
+     store the initial recur_parameter values
+     other changes needed for initialization */
+#endif /* MY_TEMPLATE recur_params */
+  RECUR_USER_OPTIONS->Asa_Recursive_Level = 1;
+
+  return (0);
+}
+
+/***********************************************************************
+* double recur_cost_function
+*	This is the users cost function to optimize
+*	(find the minimum).
+*	cost_flag is set to TRUE if the parameter set
+*	does not violates any constraints
+*       recur_parameter_lower_bound and recur_parameter_upper_bound
+*       may be adaptively changed during the search.
+***********************************************************************/
+#if HAVE_ANSI
+double
+recur_cost_function (double *x,
+                     double *recur_parameter_lower_bound,
+                     double *recur_parameter_upper_bound,
+                     double *recur_cost_tangents,
+                     double *recur_cost_curvature,
+                     ALLOC_INT * recur_parameter_dimension,
+                     int *recur_parameter_int_real,
+                     int *recur_cost_flag,
+                     int *recur_exit_code, USER_DEFINES * RECUR_USER_OPTIONS)
+#else
+double
+recur_cost_function (x,
+                     recur_parameter_lower_bound,
+                     recur_parameter_upper_bound,
+                     recur_cost_tangents,
+                     recur_cost_curvature,
+                     recur_parameter_dimension,
+                     recur_parameter_int_real,
+                     recur_cost_flag, recur_exit_code, RECUR_USER_OPTIONS)
+     double *x;
+     double *recur_parameter_lower_bound;
+     double *recur_parameter_upper_bound;
+     double *recur_cost_tangents;
+     double *recur_cost_curvature;
+     ALLOC_INT *recur_parameter_dimension;
+     int *recur_parameter_int_real;
+     int *recur_cost_flag;
+     int *recur_exit_code;
+     USER_DEFINES *RECUR_USER_OPTIONS;
+#endif
+{
+  double cost_value;
+  static LONG_INT recur_funevals = 0;
+  int *exit_code;
+#if OPTIONAL_DATA_PTR
+  int data_ptr_flg;
+#endif
+#if OPTIONS_FILE
+  FILE *ptr_options;
+  char read_option[80];
+  char read_if[4], read_FALSE[6], read_comm1[3], read_ASA_SAVE[9],
+    read_comm2[3];
+  int read_int;
+#if INT_LONG
+  LONG_INT read_long;
+#endif
+  double read_double;
+#endif
+#if MY_TEMPLATE                 /* MY_TEMPLATE_recur_cost_decl */
+  /* add some declarations if required */
+#endif
+
+  double *parameter_lower_bound, *parameter_upper_bound;
+  double *cost_parameters;
+  double *cost_tangents, *cost_curvature;
+  ALLOC_INT *parameter_dimension;
+  int *parameter_int_real;
+  int *cost_flag;
+  static LONG_INT *rand_seed;
+  static int initial_flag = 0;
+#if MULTI_MIN
+  int multi_index;
+#endif
+
+  USER_DEFINES *USER_OPTIONS;
+
+  recur_funevals = recur_funevals + 1;
+
+  if ((rand_seed = (ALLOC_INT *) calloc (1, sizeof (ALLOC_INT))) == NULL) {
+    strcpy (user_exit_msg, "recur_cost_function(): rand_seed");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+
+  if ((USER_OPTIONS =
+       (USER_DEFINES *) calloc (1, sizeof (USER_DEFINES))) == NULL) {
+    strcpy (user_exit_msg, "recur_cost_function(): USER_OPTIONS");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#if OPTIONS_FILE
+  /* Test to see if asa_opt is in correct directory.
+     This is useful for some PC and Mac compilers. */
+  if ((ptr_options = fopen ("asa_opt", "r")) == NULL) {
+    fprintf (ptr_out, "\n\n*** fopen asa_opt failed *** \n\n");
+    fflush (ptr_out);
+#if INCL_STDOUT
+    printf ("\n\n*** EXIT fopen asa_opt failed *** \n\n");
+#endif /* INCL_STDOUT */
+    return (6);
+  }
+
+  fscanf (ptr_options, "%s%s%s%s%s",
+          read_if, read_FALSE, read_comm1, read_ASA_SAVE, read_comm2);
+  if (strcmp (read_if, "#if") || strcmp (read_FALSE, "FALSE") ||
+      strcmp (read_comm1, "/*") || strcmp (read_ASA_SAVE, "ASA_SAVE") ||
+      strcmp (read_comm2, "*/")) {
+    fprintf (ptr_out, "\n\n*** not asa_opt for this version *** \n\n");
+    fflush (ptr_out);
+#if INCL_STDOUT
+    printf ("\n\n*** EXIT not asa_opt for this version *** \n\n");
+#endif /* INCL_STDOUT */
+    return (-6);
+  }
+#if INT_LONG
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%ld", &read_long);
+  USER_OPTIONS->Limit_Acceptances = read_long;
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%ld", &read_long);
+  USER_OPTIONS->Limit_Generated = read_long;
+#else
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%d", &read_int);
+  USER_OPTIONS->Limit_Acceptances = read_int;
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%d", &read_int);
+  USER_OPTIONS->Limit_Generated = read_int;
+#endif
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%d", &read_int);
+  USER_OPTIONS->Limit_Invalid_Generated_States = read_int;
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%lf", &read_double);
+  USER_OPTIONS->Accepted_To_Generated_Ratio = read_double;
+
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%lf", &read_double);
+  USER_OPTIONS->Cost_Precision = read_double;
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%d", &read_int);
+  USER_OPTIONS->Maximum_Cost_Repeat = read_int;
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%d", &read_int);
+  USER_OPTIONS->Number_Cost_Samples = read_int;
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%lf", &read_double);
+  USER_OPTIONS->Temperature_Ratio_Scale = read_double;
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%lf", &read_double);
+  USER_OPTIONS->Cost_Parameter_Scale_Ratio = read_double;
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%lf", &read_double);
+  USER_OPTIONS->Temperature_Anneal_Scale = read_double;
+
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%d", &read_int);
+  USER_OPTIONS->Include_Integer_Parameters = read_int;
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%d", &read_int);
+  USER_OPTIONS->User_Initial_Parameters = read_int;
+#if INT_ALLOC
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%d", &read_int);
+  USER_OPTIONS->Sequential_Parameters = read_int;
+#else
+#if INT_LONG
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%ld", &read_long);
+  USER_OPTIONS->Sequential_Parameters = read_long;
+#else
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%d", &read_int);
+  USER_OPTIONS->Sequential_Parameters = read_int;
+#endif
+#endif
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%lf", &read_double);
+  USER_OPTIONS->Initial_Parameter_Temperature = read_double;
+
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%d", &read_int);
+  USER_OPTIONS->Acceptance_Frequency_Modulus = read_int;
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%d", &read_int);
+  USER_OPTIONS->Generated_Frequency_Modulus = read_int;
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%d", &read_int);
+  USER_OPTIONS->Reanneal_Cost = read_int;
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%d", &read_int);
+  USER_OPTIONS->Reanneal_Parameters = read_int;
+
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%lf", &read_double);
+  USER_OPTIONS->Delta_X = read_double;
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%d", &read_int);
+  USER_OPTIONS->User_Tangents = read_int;
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%d", &read_int);
+  USER_OPTIONS->Curvature_0 = read_int;
+#else /* OPTIONS_FILE */
+  /* USER_OPTIONS->Limit_Acceptances = 10000; */
+  USER_OPTIONS->Limit_Acceptances = 1000;
+  USER_OPTIONS->Limit_Generated = 99999;
+  USER_OPTIONS->Limit_Invalid_Generated_States = 1000;
+  USER_OPTIONS->Accepted_To_Generated_Ratio = 1.0E-6;
+
+  USER_OPTIONS->Cost_Precision = 1.0E-18;
+  USER_OPTIONS->Maximum_Cost_Repeat = 2;
+  USER_OPTIONS->Number_Cost_Samples = 2;
+
+  /* These variables are set below in x[.] */
+  /* USER_OPTIONS->Temperature_Ratio_Scale = 1.0E-5; */
+  /* USER_OPTIONS->Cost_Parameter_Scale_Ratio = 1.0; */
+
+  USER_OPTIONS->Temperature_Anneal_Scale = 100.;
+
+  USER_OPTIONS->Include_Integer_Parameters = FALSE;
+  USER_OPTIONS->User_Initial_Parameters = FALSE;
+  USER_OPTIONS->Sequential_Parameters = -1;
+  USER_OPTIONS->Initial_Parameter_Temperature = 1.0;
+
+  USER_OPTIONS->Acceptance_Frequency_Modulus = 100;
+  USER_OPTIONS->Generated_Frequency_Modulus = 10000;
+  USER_OPTIONS->Reanneal_Cost = 1;
+  USER_OPTIONS->Reanneal_Parameters = TRUE;
+
+  USER_OPTIONS->Delta_X = 0.001;
+  USER_OPTIONS->User_Tangents = FALSE;
+  USER_OPTIONS->Curvature_0 = TRUE;
+#endif /* OPTIONS_FILE */
+
+  USER_OPTIONS->Temperature_Ratio_Scale = x[0];
+  USER_OPTIONS->Cost_Parameter_Scale_Ratio = x[1];
+
+  if (initial_flag == 0) {
+    /* first value of *rand_seed */
+#if ASA_LIB
+    *rand_seed = (asa_rand_seed ? *asa_rand_seed : (LONG_INT) 696969);
+#else
+    *rand_seed = 696969;
+#endif
+  }
+
+  if ((parameter_dimension =
+       (ALLOC_INT *) calloc (1, sizeof (ALLOC_INT))) == NULL) {
+    strcpy (user_exit_msg, "recur_cost_function(): parameter_dimension");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  if ((exit_code = (int *) calloc (1, sizeof (int))) == NULL) {
+    strcpy (user_exit_msg, "recur_cost_function(): exit_code");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  if ((cost_flag = (int *) calloc (1, sizeof (int))) == NULL) {
+    strcpy (user_exit_msg, "recur_cost_function(): cost_flag");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+
+  /* the number of parameters for the cost function */
+#if OPTIONS_FILE_DATA
+  fscanf (ptr_options, "%s", read_option);
+  fscanf (ptr_options, "%s", read_option);
+
+#if INT_ALLOC
+  fscanf (ptr_options, "%d", &read_int);
+  *parameter_dimension = read_int;
+#else
+#if INT_LONG
+  fscanf (ptr_options, "%ld", &read_long);
+  *parameter_dimension = read_long;
+#else
+  fscanf (ptr_options, "%d", &read_int);
+  *parameter_dimension = read_int;
+#endif
+#endif
+
+#else /* OPTIONS_FILE_DATA */
+#if ASA_TEST
+  /* set parameter dimension if SELF_OPTIMIZE=TRUE */
+  *parameter_dimension = 4;
+#endif /* ASA_TEST */
+#endif /* OPTIONS_FILE_DATA */
+#if MY_TEMPLATE                 /* MY_TEMPLATE_recur_dim */
+  /* If not using OPTIONS_FILE_DATA or data read from asa_opt,
+     set parameter dimension if SELF_OPTIMIZE=TRUE */
+#endif /* MY_TEMPLATE recur_dim */
+
+  if ((parameter_lower_bound =
+       (double *) calloc (*parameter_dimension, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg, "recur_cost_function(): parameter_lower_bound");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  if ((parameter_upper_bound =
+       (double *) calloc (*parameter_dimension, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg, "recur_cost_function(): parameter_upper_bound");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  if ((cost_parameters =
+       (double *) calloc (*parameter_dimension, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg, "recur_cost_function(): cost_parameters");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  if ((parameter_int_real =
+       (int *) calloc (*parameter_dimension, sizeof (int))) == NULL) {
+    strcpy (user_exit_msg, "recur_cost_function(): parameter_int_real");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  if ((cost_tangents =
+       (double *) calloc (*parameter_dimension, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg, "recur_cost_function(): cost_tangents");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+
+  if (USER_OPTIONS->Curvature_0 == FALSE || USER_OPTIONS->Curvature_0 == -1) {
+    if ((cost_curvature =
+         (double *) calloc ((*parameter_dimension) *
+                            (*parameter_dimension),
+                            sizeof (double))) == NULL) {
+      strcpy (user_exit_msg, "recur_cost_function(): cost_curvature");
+      Exit_USER (user_exit_msg);
+      return (-2);
+    }
+  } else {
+    cost_curvature = (double *) NULL;
+  }
+
+#if ASA_TEMPLATE_SELFOPT
+  /* Set memory to that required for use. */
+  USER_OPTIONS->Asa_Data_Dim_Dbl = 2;
+  if ((USER_OPTIONS->Asa_Data_Dbl =
+       (double *) calloc (USER_OPTIONS->Asa_Data_Dim_Dbl,
+                          sizeof (double))) == NULL) {
+    strcpy (user_exit_msg,
+            "recur_cost_function(): USER_OPTIONS->Asa_Data_Dbl");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+  /* Use Asa_Data_Dbl[0] as flag, e.g., if used with SELF_OPTIMIZE. */
+  USER_OPTIONS->Asa_Data_Dbl[0] = 1.0;
+#endif /* ASA_TEMPLATE_SELFOPT */
+
+#if USER_COST_SCHEDULE
+  USER_OPTIONS->Cost_Schedule = user_cost_schedule;
+#endif
+#if USER_ACCEPTANCE_TEST
+  USER_OPTIONS->Acceptance_Test = user_acceptance_test;
+#endif
+#if USER_ACCEPT_ASYMP_EXP
+  USER_OPTIONS->Asymp_Exp_Param = 1.0;
+#endif
+#if USER_GENERATING_FUNCTION
+  USER_OPTIONS->Generating_Distrib = user_generating_distrib;
+#endif
+#if USER_REANNEAL_COST
+  USER_OPTIONS->Reanneal_Cost_Function = user_reanneal_cost;
+#endif
+#if USER_REANNEAL_PARAMETERS
+  USER_OPTIONS->Reanneal_Params_Function = user_reanneal_params;
+#endif
+
+  initialize_parameters (cost_parameters,
+                         parameter_lower_bound,
+                         parameter_upper_bound,
+                         cost_tangents,
+                         cost_curvature,
+                         parameter_dimension, parameter_int_real,
+#if OPTIONS_FILE_DATA
+                         ptr_options,
+#endif
+                         USER_OPTIONS);
+#if OPTIONS_FILE
+  fclose (ptr_options);
+#endif
+
+#if ASA_SAVE
+  USER_OPTIONS->Random_Array_Dim = SHUFFLE;
+  USER_OPTIONS->Random_Array = random_array;
+#endif /* ASA_SAVE */
+
+  /* It might be a good idea to place a loop around this call,
+     and to average over several values of funevals returned by
+     trajectories of cost_value. */
+
+  funevals = 0;
+
+#if USER_ASA_OUT
+  if ((USER_OPTIONS->Asa_Out_File =
+       (char *) calloc (80, sizeof (char))) == NULL) {
+    strcpy (user_exit_msg,
+            "recur_cost_function(): USER_OPTIONS->Asa_Out_File");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#if ASA_TEMPLATE_SELFOPT
+  strcpy (USER_OPTIONS->Asa_Out_File, "asa_rcur");
+#endif
+#endif
+
+#if OPTIONAL_DATA_PTR
+  data_ptr_flg = 1;
+#if ASA_TEMPLATE
+  /* N.b.:  If OPTIONAL_DATA_PTR is being used for RECUR_USER_OPTIONS
+   * as well as for USER_OPTIONS, do not create (or free) additional memory
+   * in recur_cost_function() for Asa_Data_Dim_Ptr and Asa_Data_Ptr to
+   * be passed to the inner cost_function(), but rather link pointers to
+   * those in RECUR_USER_OPTIONS.  Typically, define separate structures
+   * within the structure defined by Asa_Data_Ptr to access info depending
+   * on whether the run in a particular level of cost function in this
+   * recursive operation.  In this case, set * #if TRUE to #if FALSE just
+   * below.  See the ASA-README for more discussion.
+   */
+
+#if TRUE
+  USER_OPTIONS->Asa_Data_Dim_Ptr = 1;
+  if ((USER_OPTIONS->Asa_Data_Ptr =
+       (OPTIONAL_PTR_TYPE *) calloc (USER_OPTIONS->Asa_Data_Dim_Ptr,
+                                     sizeof (OPTIONAL_PTR_TYPE))) == NULL) {
+    strcpy (user_exit_msg,
+            "recur_cost_function(): USER_OPTIONS->Asa_Data_Ptr");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#else
+  USER_OPTIONS->Asa_Data_Dim_Ptr = RECUR_USER_OPTIONS->Asa_Data_Dim_Ptr;
+  USER_OPTIONS->Asa_Data_Ptr = RECUR_USER_OPTIONS->Asa_Data_Ptr;
+  data_ptr_flg = 0;
+#endif
+#endif /* ASA_TEMPLATE */
+  USER_OPTIONS->Asa_Data_Dim_Ptr = 1;
+  if ((USER_OPTIONS->Asa_Data_Ptr =
+       (OPTIONAL_PTR_TYPE *) calloc (USER_OPTIONS->Asa_Data_Dim_Ptr,
+                                     sizeof (OPTIONAL_PTR_TYPE))) == NULL) {
+    strcpy (user_exit_msg,
+            "recur_cost_function(): USER_OPTIONS->Asa_Data_Ptr");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+#endif /* OPTIONAL_DATA_PTR */
+
+  cost_value = asa (USER_COST_FUNCTION,
+                    randflt,
+                    rand_seed,
+                    cost_parameters,
+                    parameter_lower_bound,
+                    parameter_upper_bound,
+                    cost_tangents,
+                    cost_curvature,
+                    parameter_dimension,
+                    parameter_int_real, cost_flag, exit_code, USER_OPTIONS);
+  if (*exit_code == -1) {
+#if INCL_STDOUT
+    printf ("\n\n*** error in calloc in ASA ***\n\n");
+#endif /* INCL_STDOUT */
+    fprintf (ptr_out, "\n\n*** error in calloc in ASA ***\n\n");
+    fflush (ptr_out);
+    return (-1);
+  }
+#if MY_TEMPLATE                 /* MY_TEMPLATE_recur_post_asa */
+#endif
+
+  if (cost_value > .001) {
+    *recur_cost_flag = FALSE;
+  } else {
+    *recur_cost_flag = TRUE;
+  }
+
+#if FALSE                       /* set to 1 to activate FAST EXIT */
+  /* Make a quick exit */
+  if (recur_funevals >= 10) {
+    *recur_cost_flag = FALSE;
+    RECUR_USER_OPTIONS->Limit_Invalid_Generated_States = 0;
+    fprintf (ptr_out, "FAST EXIT set at recur_funevals = 10\n\n");
+  }
+#endif
+
+#if TIME_CALC
+  /* print every RECUR_PRINT_FREQUENCY evaluations */
+  if ((RECUR_PRINT_FREQUENCY > 0) &&
+      ((recur_funevals % RECUR_PRINT_FREQUENCY) == 0)) {
+    USER_OPTIONS->Temperature_Ratio_Scale = x[0];
+    fprintf (ptr_out, "USER_OPTIONS->Temperature_Ratio_Scale = %12.7g\n",
+             USER_OPTIONS->Temperature_Ratio_Scale);
+    USER_OPTIONS->Cost_Parameter_Scale_Ratio = x[1];
+    fprintf (ptr_out, "USER_OPTIONS->Cost_Parameter_Scale_Ratio = %12.7g\n",
+             USER_OPTIONS->Cost_Parameter_Scale_Ratio);
+  }
+  print_time ("", ptr_out);
+#endif
+
+  fprintf (ptr_out, "recur_funevals = %ld, *recur_cost_flag = %d\n",
+           recur_funevals, *recur_cost_flag);
+  /* cost function = number generated at best cost */
+#if ASA_TEMPLATE_SELFOPT
+  funevals = (LONG_INT) (USER_OPTIONS->Asa_Data_Dbl[1]);
+  fprintf (ptr_out, "\tbest_funevals = %ld, cost_value = %12.7g\n\n",
+           funevals, cost_value);
+  /* cost function = total number generated during run */
+#endif /* ASA_TEMPLATE_SELFOPT */
+
+#if ASA_SAMPLE
+  fprintf (ptr_out, "\tfunevals = %ld, cost_value = %12.7g\n\n",
+           funevals, cost_value);
+#endif
+  fflush (ptr_out);
+
+#if ASA_TEMPLATE_SAMPLE
+  ptr_asa = fopen ("asa_out", "r");
+  sample (ptr_out, ptr_asa);
+#endif
+
+#if OPTIONAL_DATA_DBL
+  free (USER_OPTIONS->Asa_Data_Dbl);
+#endif
+#if OPTIONAL_DATA_INT
+  free (USER_OPTIONS->Asa_Data_Int);
+#endif
+#if OPTIONAL_DATA_PTR
+  if (data_ptr_flg == 1) {
+    free (USER_OPTIONS->Asa_Data_Ptr);
+  }
+#endif
+#if USER_ASA_OUT
+  free (USER_OPTIONS->Asa_Out_File);
+#endif
+#if ASA_SAMPLE
+  free (USER_OPTIONS->Bias_Generated);
+#endif
+#if ASA_QUEUE
+#if ASA_RESOLUTION
+#else
+  free (USER_OPTIONS->Queue_Resolution);
+#endif
+#endif
+#if ASA_RESOLUTION
+  free (USER_OPTIONS->Coarse_Resolution);
+#endif
+  if (USER_OPTIONS->Curvature_0 == FALSE || USER_OPTIONS->Curvature_0 == -1)
+    free (cost_curvature);
+#if USER_INITIAL_PARAMETERS_TEMPS
+  free (USER_OPTIONS->User_Parameter_Temperature);
+#endif
+#if USER_INITIAL_COST_TEMP
+  free (USER_OPTIONS->User_Cost_Temperature);
+#endif
+#if DELTA_PARAMETERS
+  free (USER_OPTIONS->User_Delta_Parameter);
+#endif
+#if QUENCH_PARAMETERS
+  free (USER_OPTIONS->User_Quench_Param_Scale);
+#endif
+#if QUENCH_COST
+  free (USER_OPTIONS->User_Quench_Cost_Scale);
+#endif
+#if RATIO_TEMPERATURE_SCALES
+  free (USER_OPTIONS->User_Temperature_Ratio);
+#endif
+#if MULTI_MIN
+  free (USER_OPTIONS->Multi_Grid);
+  for (multi_index = 0; multi_index < USER_OPTIONS->Multi_Number;
+       ++multi_index) {
+    free (USER_OPTIONS->Multi_Params[multi_index]);
+  }
+#endif /* MULTI_MIN */
+#if OPTIONAL_DATA_PTR
+  if (data_ptr_flg == 0) {
+    USER_OPTIONS = NULL;
+  }
+#endif
+  free (USER_OPTIONS);
+  free (parameter_dimension);
+  free (exit_code);
+  free (cost_flag);
+  free (parameter_lower_bound);
+  free (parameter_upper_bound);
+  free (cost_parameters);
+  free (parameter_int_real);
+  free (cost_tangents);
+  free (rand_seed);
+
+  return ((double) funevals);
+}
+
+#if USER_COST_SCHEDULE
+#if HAVE_ANSI
+double
+recur_user_cost_schedule (double test_temperature,
+                          USER_DEFINES * RECUR_USER_OPTIONS)
+#else
+double
+recur_user_cost_schedule (test_temperature, RECUR_USER_OPTIONS)
+     double test_temperature;
+     USER_DEFINES *RECUR_USER_OPTIONS;
+#endif /* HAVE_ANSI */
+{
+#if ASA_TEMPLATE
+  double x;
+
+  x = test_temperature;
+
+  return (x);
+#endif
+}
+#endif /* USER_COST_SCHEDULE */
+
+#if USER_ACCEPTANCE_TEST
+#if HAVE_ANSI
+void
+recur_user_acceptance_test (double current_cost,
+                            double *recur_parameter_lower_bound,
+                            double *recur_parameter_upper_bound,
+                            ALLOC_INT * recur_parameter_dimension,
+                            USER_DEFINES * RECUR_USER_OPTIONS)
+#else
+void
+recur_user_acceptance_test (current_cost, recur_parameter_lower_bound,
+                            recur_parameter_upper_bound,
+                            recur_parameter_dimension, RECUR_USER_OPTIONS)
+     double current_cost;
+     double *recur_parameter_lower_bound;
+     double *recur_parameter_upper_bound;
+     ALLOC_INT *recur_parameter_dimension;
+     USER_DEFINES *RECUR_USER_OPTIONS;
+#endif /* HAVE_ANSI */
+{
+  double uniform_test, curr_cost_temp;
+#if USER_ACCEPT_ASYMP_EXP
+  double x, q, delta_cost;
+#endif
+
+#if ASA_TEMPLATE                /* ASA cost index */
+  /* Calculate the current ASA cost index.  This could be useful
+     to define a new schedule for the cost temperature, beyond
+     simple changes that can be made using USER_COST_SCHEDULE. */
+
+  int index;
+  double k_temperature, quench, y;
+  double xrecur_parameter_dimension;
+
+#if QUENCH_COST
+  quench = RECUR_USER_OPTIONS->User_Quench_Cost_Scale[0];
+#else
+  quench = 1.0;
+#endif /* QUENCH_COST */
+  xrecur_parameter_dimension = (double) *recur_parameter_dimension;
+  for (index = 0; index < *recur_parameter_dimension; ++index)
+    if (fabs
+        (recur_parameter_upper_bound[index] -
+         recur_parameter_lower_bound[index]) < (double) EPS_DOUBLE)
+      *xrecur_parameter_dimension -= 1.0;
+
+  y = -F_LOG (RECUR_USER_OPTIONS->Cost_Temp_Curr
+              / RECUR_USER_OPTIONS->Cost_Temp_Init)
+    / RECUR_USER_OPTIONS->Cost_Temp_Scale;
+
+  k_temperature = F_POW (y, xrecur_parameter_dimension / quench);
+#endif /* ASA cost index */
+
+  uniform_test = randflt (RECUR_USER_OPTIONS->Random_Seed);
+  curr_cost_temp = RECUR_USER_OPTIONS->Cost_Temp_Curr;
+
+#if ASA_TEMPLATE
+#if USER_COST_SCHEDULE
+  curr_cost_temp =
+    (RECUR_USER_OPTIONS->Cost_Schedule (RECUR_USER_OPTIONS->Cost_Temp_Curr,
+                                        RECUR_USER_OPTIONS)
+     + (double) EPS_DOUBLE);
+#else
+  curr_cost_temp = RECUR_USER_OPTIONS->Cost_Temp_Curr;
+#endif
+#endif /* ASA_TEMPLATE */
+
+#if USER_ACCEPT_ASYMP_EXP
+#if USER_COST_SCHEDULE
+  curr_cost_temp =
+    (RECUR_USER_OPTIONS->Cost_Schedule (RECUR_USER_OPTIONS->Cost_Temp_Curr,
+                                        RECUR_USER_OPTIONS)
+     + (double) EPS_DOUBLE);
+#endif
+
+  delta_cost = (current_cost - *(RECUR_USER_OPTIONS->Last_Cost))
+    / (curr_cost_temp + (double) EPS_DOUBLE);
+
+  q = RECUR_USER_OPTIONS->Asymp_Exp_Param;
+  if (fabs (1.0 - q) < (double) EPS_DOUBLE)
+    x = MIN (1.0, (F_EXP (-delta_cost)));       /* Boltzmann test */
+  else if ((1.0 - (1.0 - q) * delta_cost) < (double) EPS_DOUBLE)
+    x = MIN (1.0, (F_EXP (-delta_cost)));       /* Boltzmann test */
+  else
+    x = MIN (1.0, F_POW ((1.0 - (1.0 - q) * delta_cost), (1.0 / (1.0 - q))));
+
+  RECUR_USER_OPTIONS->Prob_Bias = x;
+  if (x >= uniform_test)
+    RECUR_USER_OPTIONS->User_Acceptance_Flag = TRUE;
+  else
+    RECUR_USER_OPTIONS->User_Acceptance_Flag = FALSE;
+
+#endif /* USER_ACCEPT_ASYMP_EXP */
+}
+#endif /* USER_ACCEPTANCE_TEST */
+
+#if USER_GENERATING_FUNCTION
+#if HAVE_ANSI
+double
+recur_user_generating_distrib (LONG_INT * seed,
+                               ALLOC_INT * recur_parameter_dimension,
+                               ALLOC_INT index_v,
+                               double temperature_v,
+                               double init_param_temp_v,
+                               double temp_scale_params_v,
+                               double parameter_v,
+                               double parameter_range_v,
+                               double *last_saved_parameter,
+                               USER_DEFINES * RECUR_USER_OPTIONS)
+#else
+double
+recur_user_generating_distrib (seed,
+                               recur_parameter_dimension,
+                               index_v,
+                               temperature_v,
+                               init_param_temp_v,
+                               temp_scale_params_v,
+                               parameter_v,
+                               parameter_range_v,
+                               last_saved_parameter, RECUR_USER_OPTIONS)
+     LONG_INT *seed;
+     ALLOC_INT *recur_parameter_dimension;
+     ALLOC_INT index_v;
+     double temperature_v;
+     double init_param_temp_v;
+     double temp_scale_params_v;
+     double parameter_v;
+     double parameter_range_v;
+     double *last_saved_parameter;
+     USER_DEFINES *RECUR_USER_OPTIONS;
+#endif
+{
+#if ASA_TEMPLATE
+  double x, y, z;
+
+  /* This is the ASA distribution.  A slower temperature schedule can be
+     obtained here, e.g., temperature_v = pow(temperature_v, 0.5); */
+
+  x = randflt (seed);
+  y = x < 0.5 ? -1.0 : 1.0;
+  z = y * temperature_v * (F_POW ((1.0 + 1.0 / temperature_v),
+                                  fabs (2.0 * x - 1.0)) - 1.0);
+
+  x = parameter_v + z * parameter_range_v;
+
+  return (x);
+#endif /* ASA_TEMPLATE */
+}
+#endif /* USER_GENERATING_FUNCTION */
+
+#if USER_REANNEAL_COST
+#if HAVE_ANSI
+int
+recur_user_reanneal_cost (double *cost_best,
+                          double *cost_last,
+                          double *initial_cost_temperature,
+                          double *current_cost_temperature,
+                          USER_DEFINES * RECUR_USER_OPTIONS)
+#else
+int
+recur_user_reanneal_cost (cost_best,
+                          cost_last,
+                          initial_cost_temperature,
+                          current_cost_temperature, RECUR_USER_OPTIONS)
+     double *cost_best;
+     double *cost_last;
+     double *initial_cost_temperature;
+     double *current_cost_temperature;
+     USER_DEFINES *RECUR_USER_OPTIONS;
+#endif /* HAVE_ANSI */
+{
+#if ASA_TEMPLATE
+  double tmp_dbl;
+
+  tmp_dbl = MAX (fabs (*cost_last), fabs (*cost_best));
+  tmp_dbl = MAX ((double) EPS_DOUBLE, tmp_dbl);
+  *initial_cost_temperature = MIN (*initial_cost_temperature, tmp_dbl);
+
+  return (TRUE);
+#endif
+}
+#endif /* USER_REANNEAL_COST */
+
+#if USER_REANNEAL_PARAMETERS
+#if HAVE_ANSI
+double
+recur_user_reanneal_params (double current_temp,
+                            double tangent,
+                            double max_tangent,
+                            USER_DEFINES * RECUR_USER_OPTIONS)
+#else
+double
+recur_user_reanneal_params (current_temp,
+                            tangent, max_tangent, RECUR_USER_OPTIONS)
+     double current_temp;
+     double tangent;
+     double max_tangent;
+     USER_DEFINES *RECUR_USER_OPTIONS;
+#endif /* HAVE_ANSI */
+{
+#if ASA_TEMPLATE
+  double x;
+
+  x = current_temp * (max_tangent / tangent);
+
+  return (x);
+#endif
+}
+#endif /* USER_REANNEAL_PARAMETERS */
+#endif /* SELF_OPTIMIZE */
+
+#if FITLOC
+#if HAVE_ANSI
+double
+calcf (double (*user_cost_function)
+
+        
+       (double *, double *, double *, double *, double *, ALLOC_INT *, int *,
+        int *, int *, USER_DEFINES *), double *xloc,
+       double *parameter_lower_bound, double *parameter_upper_bound,
+       double *cost_tangents, double *cost_curvature,
+       ALLOC_INT * parameter_dimension, int *parameter_int_real,
+       int *cost_flag, int *exit_code, USER_DEFINES * OPTIONS, FILE * ptr_out)
+#else
+double
+calcf (user_cost_function,
+       xloc,
+       parameter_lower_bound,
+       parameter_upper_bound,
+       cost_tangents,
+       cost_curvature,
+       parameter_dimension,
+       parameter_int_real, cost_flag, exit_code, OPTIONS, ptr_out)
+     double (*user_cost_function) ();
+     double *x;
+     double *parameter_lower_bound;
+     double *parameter_upper_bound;
+     double *cost_tangents;
+     double *cost_curvature;
+     ALLOC_INT *parameter_dimension;
+     int *parameter_int_real;
+     int *cost_flag;
+     int *exit_code;
+     USER_DEFINES *OPTIONS;
+     FILE *ptr_out;
+#endif
+{
+  ALLOC_INT index_v;
+#if FITLOC_ROUND
+  double x, min_parameter_v, max_parameter_v, parameter_range_v;
+#endif
+  double floc;
+#if ASA_RESOLUTION
+  double xres, xint, xplus, xminus, dx, dxminus, dxplus;
+#endif
+
+#if FITLOC_ROUND
+  /* The following section for adjustments of parameters is taken from
+     generate_new_state() in asa.c */
+  for (index_v = 0; index_v < *parameter_dimension; ++index_v) {
+    if (fabs
+        (parameter_lower_bound[index_v] - parameter_upper_bound[index_v]) <
+        EPS_DOUBLE)
+      continue;
+
+    x = xloc[index_v];
+
+    min_parameter_v = parameter_lower_bound[index_v];
+    max_parameter_v = parameter_upper_bound[index_v];
+    parameter_range_v = max_parameter_v - min_parameter_v;
+
+    /* Handle discrete parameters. */
+#if ASA_RESOLUTION
+    xres = OPTIONS->Coarse_Resolution[index_v];
+    if (xres > EPS_DOUBLE) {
+      min_parameter_v -= (xres / 2.0);
+      max_parameter_v += (xres / 2.0);
+      parameter_range_v = max_parameter_v - min_parameter_v;
+    }
+#endif /* ASA_RESOLUTION */
+    if (parameter_int_real[index_v] > 0) {
+#if ASA_RESOLUTION
+      if (xres > EPS_DOUBLE) {
+        ;
+      } else {
+#endif /* ASA_RESOLUTION */
+        min_parameter_v -= 0.5;
+        max_parameter_v += 0.5;
+        parameter_range_v = max_parameter_v - min_parameter_v;
+      }
+#if ASA_RESOLUTION
+    }
+#endif
+#if ASA_RESOLUTION
+    if (xres > EPS_DOUBLE) {
+      xint = xres * (double) ((LONG_INT) (x / xres));
+      xplus = xint + xres;
+      xminus = xint - xres;
+      dx = fabs (xint - x);
+      dxminus = fabs (xminus - x);
+      dxplus = fabs (xplus - x);
+
+      if (dx < dxminus && dx < dxplus)
+        x = xint;
+      else if (dxminus < dxplus)
+        x = xminus;
+      else
+        x = xplus;
+    }
+#endif /* ASA_RESOLUTION */
+
+    /* Handle discrete parameters.
+       You might have to check rounding on your machine. */
+    if (parameter_int_real[index_v] > 0) {
+#if ASA_RESOLUTION
+      if (xres > EPS_DOUBLE) {
+        ;
+      } else {
+#endif /* ASA_RESOLUTION */
+        if (x < min_parameter_v + 0.5)
+          x = min_parameter_v + 0.5 + (double) EPS_DOUBLE;
+        if (x > max_parameter_v - 0.5)
+          x = max_parameter_v - 0.5 + (double) EPS_DOUBLE;
+
+        if (x + 0.5 > 0.0) {
+          x = (double) ((LONG_INT) (x + 0.5));
+        } else {
+          x = (double) ((LONG_INT) (x - 0.5));
+        }
+        if (x > parameter_upper_bound[index_v])
+          x = parameter_upper_bound[index_v];
+        if (x < parameter_lower_bound[index_v])
+          x = parameter_lower_bound[index_v];
+      }
+#if ASA_RESOLUTION
+    }
+    if (xres > EPS_DOUBLE) {
+      if (x < min_parameter_v + xres / 2.0)
+        x = min_parameter_v + xres / 2.0 + (double) EPS_DOUBLE;
+      if (x > max_parameter_v - xres / 2.0)
+        x = max_parameter_v - xres / 2.0 + (double) EPS_DOUBLE;
+
+      if (x > parameter_upper_bound[index_v])
+        x = parameter_upper_bound[index_v];
+      if (x < parameter_lower_bound[index_v])
+        x = parameter_lower_bound[index_v];
+    }
+#endif /* ASA_RESOLUTION */
+    if ((x < parameter_lower_bound[index_v])
+        || (x > parameter_upper_bound[index_v])) {
+      ;
+    } else {
+      xloc[index_v] = x;
+    }
+  }
+#endif /* FITLOC_ROUND */
+
+  floc = user_cost_function (xloc,
+                             parameter_lower_bound,
+                             parameter_upper_bound,
+                             cost_tangents,
+                             cost_curvature,
+                             parameter_dimension,
+                             parameter_int_real,
+                             cost_flag, exit_code, OPTIONS);
+
+  if (*cost_flag == FALSE) {
+    floc += OPTIONS->Penalty;
+  }
+
+  for (index_v = 0; index_v < *parameter_dimension; ++index_v) {
+    if (parameter_upper_bound[index_v] - xloc[index_v] < EPS_DOUBLE)
+      floc += OPTIONS->Penalty;
+    else if (xloc[index_v] - parameter_lower_bound[index_v] < EPS_DOUBLE)
+      floc += OPTIONS->Penalty;
+  }
+
+  return (floc);
+}
+
+#if HAVE_ANSI
+double
+fitloc (double (*user_cost_function)
+
+         
+        (double *, double *, double *, double *, double *, ALLOC_INT *, int *,
+         int *, int *, USER_DEFINES *), double *xloc,
+        double *parameter_lower_bound, double *parameter_upper_bound,
+        double *cost_tangents, double *cost_curvature,
+        ALLOC_INT * parameter_dimension, int *parameter_int_real,
+        int *cost_flag, int *exit_code, USER_DEFINES * OPTIONS,
+        FILE * ptr_out)
+#else
+double
+fitloc (user_cost_function,
+        xloc,
+        parameter_lower_bound,
+        parameter_upper_bound,
+        cost_tangents,
+        cost_curvature,
+        parameter_dimension,
+        parameter_int_real, cost_flag, exit_code, OPTIONS, ptr_out)
+     double (*user_cost_function) ();
+     double *xloc;
+     double *parameter_lower_bound;
+     double *parameter_upper_bound;
+     double *cost_tangents;
+     double *cost_curvature;
+     ALLOC_INT *parameter_dimension;
+     int *parameter_int_real;
+     int *cost_flag;
+     int *exit_code;
+     USER_DEFINES *OPTIONS;
+     FILE *ptr_out;
+#endif
+{
+  double x;
+  ALLOC_INT index_v;
+#if FITLOC_ROUND
+  double min_parameter_v, max_parameter_v, parameter_range_v;
+#endif
+  double *xsave;
+  double tol1, tol2, alpha, beta1, beta2, gamma, delta, floc, fsave, ffinal;
+  int no_progress, tot_iters, locflg, bndflg;
+#if ASA_RESOLUTION
+  double xres, xint, xminus, xplus, dx, dxminus, dxplus;
+#endif
+
+#if FITLOC_PRINT
+  if (OPTIONS->Fit_Local >= 1) {
+    fprintf (ptr_out, "\n\nSTART LOCAL FIT\n");
+  } else {
+    fprintf (ptr_out, "\n\nSTART LOCAL FIT Independent of ASA\n");
+  }
+  fflush (ptr_out);
+#endif /* FITLOC_PRINT */
+
+  xsave = (double *) calloc (*parameter_dimension, sizeof (double));
+  bndflg = 0;
+
+  /* The following simplex parameters may need adjustments for your system. */
+  tol1 = EPS_DOUBLE;
+  tol2 = EPS_DOUBLE * 100.;
+  no_progress = 4;
+  alpha = 1.0;
+  beta1 = 0.75;
+  beta2 = 0.75;
+  gamma = 1.25;
+  delta = 2.50;
+
+  for (index_v = 0; index_v < *parameter_dimension; ++index_v) {
+    xsave[index_v] = xloc[index_v];
+  }
+
+  fsave = user_cost_function (xloc,
+                              parameter_lower_bound,
+                              parameter_upper_bound,
+                              cost_tangents,
+                              cost_curvature,
+                              parameter_dimension,
+                              parameter_int_real,
+                              cost_flag, exit_code, OPTIONS);
+
+  tot_iters = simplex (user_cost_function,
+                       xloc,
+                       parameter_lower_bound,
+                       parameter_upper_bound,
+                       cost_tangents,
+                       cost_curvature,
+                       parameter_dimension,
+                       parameter_int_real,
+                       cost_flag,
+                       exit_code,
+                       OPTIONS,
+                       ptr_out,
+                       tol1,
+                       tol2, no_progress, alpha, beta1, beta2, gamma, delta);
+  fflush (ptr_out);
+
+  for (index_v = 0; index_v < *parameter_dimension; ++index_v) {
+    x = xloc[index_v];
+    if ((x < parameter_lower_bound[index_v])
+        || (x > parameter_upper_bound[index_v])) {
+      bndflg = 1;
+    }
+  }
+
+  /* The following section for adjustments of parameters is taken from
+     generate_new_state() in asa.c */
+#if FITLOC_ROUND
+  for (index_v = 0; index_v < *parameter_dimension; ++index_v) {
+    if (fabs
+        (parameter_lower_bound[index_v] - parameter_upper_bound[index_v]) <
+        EPS_DOUBLE)
+      continue;
+
+    x = xloc[index_v];
+
+    min_parameter_v = parameter_lower_bound[index_v];
+    max_parameter_v = parameter_upper_bound[index_v];
+    parameter_range_v = max_parameter_v - min_parameter_v;
+
+    /* Handle discrete parameters. */
+#if ASA_RESOLUTION
+    xres = OPTIONS->Coarse_Resolution[index_v];
+    if (xres > EPS_DOUBLE) {
+      min_parameter_v -= (xres / 2.0);
+      max_parameter_v += (xres / 2.0);
+      parameter_range_v = max_parameter_v - min_parameter_v;
+    }
+#endif /* ASA_RESOLUTION */
+    if (parameter_int_real[index_v] > 0) {
+#if ASA_RESOLUTION
+      if (xres > EPS_DOUBLE) {
+        ;
+      } else {
+#endif /* ASA_RESOLUTION */
+        min_parameter_v -= 0.5;
+        max_parameter_v += 0.5;
+        parameter_range_v = max_parameter_v - min_parameter_v;
+      }
+#if ASA_RESOLUTION
+    }
+#endif
+#if ASA_RESOLUTION
+    if (xres > EPS_DOUBLE) {
+      xint = xres * (double) ((LONG_INT) (x / xres));
+      xplus = xint + xres;
+      xminus = xint - xres;
+      dx = fabs (xint - x);
+      dxminus = fabs (xminus - x);
+      dxplus = fabs (xplus - x);
+
+      if (dx < dxminus && dx < dxplus)
+        x = xint;
+      else if (dxminus < dxplus)
+        x = xminus;
+      else
+        x = xplus;
+    }
+#endif /* ASA_RESOLUTION */
+
+    /* Handle discrete parameters.
+       You might have to check rounding on your machine. */
+    if (parameter_int_real[index_v] > 0) {
+#if ASA_RESOLUTION
+      if (xres > EPS_DOUBLE) {
+        ;
+      } else {
+#endif /* ASA_RESOLUTION */
+        if (x < min_parameter_v + 0.5)
+          x = min_parameter_v + 0.5 + (double) EPS_DOUBLE;
+        if (x > max_parameter_v - 0.5)
+          x = max_parameter_v - 0.5 + (double) EPS_DOUBLE;
+
+        if (x + 0.5 > 0.0) {
+          x = (double) ((LONG_INT) (x + 0.5));
+        } else {
+          x = (double) ((LONG_INT) (x - 0.5));
+        }
+        if (x > parameter_upper_bound[index_v])
+          x = parameter_upper_bound[index_v];
+        if (x < parameter_lower_bound[index_v])
+          x = parameter_lower_bound[index_v];
+      }
+#if ASA_RESOLUTION
+    }
+    if (xres > EPS_DOUBLE) {
+      if (x < min_parameter_v + xres / 2.0)
+        x = min_parameter_v + xres / 2.0 + (double) EPS_DOUBLE;
+      if (x > max_parameter_v - xres / 2.0)
+        x = max_parameter_v - xres / 2.0 + (double) EPS_DOUBLE;
+
+      if (x > parameter_upper_bound[index_v])
+        x = parameter_upper_bound[index_v];
+      if (x < parameter_lower_bound[index_v])
+        x = parameter_lower_bound[index_v];
+    }
+#endif /* ASA_RESOLUTION */
+    if ((x < parameter_lower_bound[index_v])
+        || (x > parameter_upper_bound[index_v])) {
+      bndflg = 1;
+#if FITLOC_PRINT
+      if (OPTIONS->Fit_Local == 2)
+        fprintf (ptr_out, "IGNORE FITLOC: OUT OF BOUNDS xloc[%ld] = %g\n",
+                 index_v, xloc[index_v]);
+      else
+        fprintf (ptr_out, "OUT OF BOUNDS xloc[%ld] = %g\n",
+                 index_v, xloc[index_v]);
+#else
+      ;
+#endif /* FITLOC_PRINT */
+    } else {
+      xloc[index_v] = x;
+    }
+  }
+#endif /* FITLOC_ROUND */
+
+  floc = user_cost_function (xloc,
+                             parameter_lower_bound,
+                             parameter_upper_bound,
+                             cost_tangents,
+                             cost_curvature,
+                             parameter_dimension,
+                             parameter_int_real,
+                             cost_flag, exit_code, OPTIONS);
+
+  if (fabs (floc - fsave) < (double) EPS_DOUBLE) {
+    locflg = 1;
+    ffinal = fsave;
+#if FITLOC_PRINT
+    fprintf (ptr_out, "\nsame global cost = %g\tlocal cost = %g\n\n",
+             fsave, floc);
+#endif /* FITLOC_PRINT */
+  } else {
+    if (floc < fsave) {
+      if (OPTIONS->Fit_Local == 2 && bndflg == 1) {
+        locflg = 1;
+        ffinal = fsave;
+      } else {
+        locflg = 0;
+        ffinal = floc;
+      }
+    } else {
+      locflg = 1;
+      ffinal = fsave;
+    }
+#if FITLOC_PRINT
+    fprintf (ptr_out, "\nDIFF global cost = %g\tlocal cost = %g\n\n",
+             fsave, floc);
+#endif /* FITLOC_PRINT */
+  }
+
+  for (index_v = 0; index_v < *parameter_dimension; ++index_v) {
+    if (fabs (xloc[index_v] - xsave[index_v]) < (double) EPS_DOUBLE) {
+#if FITLOC_PRINT
+      fprintf (ptr_out, "same global param[%ld] = %g\tlocal param = %g\n",
+               index_v, xsave[index_v], xloc[index_v]);
+#else
+      ;
+#endif /* FITLOC_PRINT */
+    } else {
+#if FITLOC_PRINT
+      fprintf (ptr_out, "DIFF global param[%ld] = %g\tlocal param = %g\n",
+               index_v, xsave[index_v], xloc[index_v]);
+#else
+      ;
+#endif /* FITLOC_PRINT */
+      if (locflg == 1) {
+        xloc[index_v] = xsave[index_v];
+      }
+    }
+  }
+
+#if FITLOC_PRINT
+  fprintf (ptr_out, "\n");
+  fflush (ptr_out);
+#endif /* FITLOC_PRINT */
+
+  free (xsave);
+
+  return (ffinal);
+}
+
+/*
+   Written by Mark Johnson <mjohnson@netcom.com>, based on 
+
+   %A J.A. Nelder
+   %A R. Mead
+   %T A simplex method for function minimization
+   %J Computer J. (UK)
+   %V 7
+   %D 1964
+   %P 308-313
+
+   with improvements from
+
+   %A G.P. Barabino
+   %A G.S. Barabino
+   %A B. Bianco
+   %A M. Marchesi
+   %T A study on the performances of simplex methods for function minimization
+   %B Proc. IEEE Int. Conf. Circuits and Computers
+   %D 1980
+   %P 1150-1153
+
+   adapted for use in ASA by Lester Ingber <ingber@ingber.com>
+ */
+
+#if HAVE_ANSI
+int
+simplex (double (*user_cost_function)
+
+          
+         (double *, double *, double *, double *, double *, ALLOC_INT *,
+          int *, int *, int *, USER_DEFINES *), double *x,
+         double *parameter_lower_bound, double *parameter_upper_bound,
+         double *cost_tangents, double *cost_curvature,
+         ALLOC_INT * parameter_dimension, int *parameter_int_real,
+         int *cost_flag, int *exit_code, USER_DEFINES * OPTIONS,
+         FILE * ptr_out, double tol1, double tol2, int no_progress,
+         double alpha, double beta1, double beta2, double gamma, double delta)
+#else
+int
+simplex (user_cost_function,
+         x,
+         parameter_lower_bound,
+         parameter_upper_bound,
+         cost_tangents,
+         cost_curvature,
+         parameter_dimension,
+         parameter_int_real,
+         cost_flag,
+         exit_code,
+         OPTIONS,
+         ptr_out, tol1, tol2, no_progress, alpha, beta1, beta2, gamma, delta)
+     double (*user_cost_function) ();
+     double *x;
+     double *parameter_lower_bound;
+     double *parameter_upper_bound;
+     double *cost_tangents;
+     double *cost_curvature;
+     ALLOC_INT *parameter_dimension;
+     int *parameter_int_real;
+     int *cost_flag;
+     int *exit_code;
+     USER_DEFINES *OPTIONS;
+     FILE *ptr_out;
+     double tol1;
+     double tol2;
+     int no_progress;
+     double alpha;
+     double beta1;
+     double beta2;
+     double gamma;
+     double delta;
+#endif
+{
+  double fs, fl, fh, fr, fe, fc1, fc2, ftmp, flast;
+  double err1;
+  double *fvals;
+  double **splx;                /* the simplex of points */
+  double *x0;                   /* centroid of simplex */
+  double *xr;                   /* point for a reflection */
+  double *xe;                   /* point for an expansion */
+  double *xc1;                  /* point for a minor contraction */
+  double *xc2;                  /* point for a major contraction */
+  int s, l, h;
+  int i, j, iters, futility;
+  int lastprint;
+
+  fvals = (double *) calloc (*parameter_dimension + 1, sizeof (double));
+  splx = (double **) calloc (*parameter_dimension + 1, sizeof (double *));
+  for (i = 0; i <= *parameter_dimension; i++)
+    splx[i] = (double *) calloc (*parameter_dimension, sizeof (double));
+  x0 = (double *) calloc (*parameter_dimension, sizeof (double));
+  xr = (double *) calloc (*parameter_dimension, sizeof (double));
+  xe = (double *) calloc (*parameter_dimension, sizeof (double));
+  xc1 = (double *) calloc (*parameter_dimension, sizeof (double));
+  xc2 = (double *) calloc (*parameter_dimension, sizeof (double));
+
+  /* build the initial simplex */
+  for (i = 0; i < *parameter_dimension; i++) {
+    splx[0][i] = x[i];
+  }
+  for (i = 1; i <= *parameter_dimension; i++) {
+    for (j = 0; j < *parameter_dimension; j++) {
+      if ((j + 1) == i)
+        splx[i][j] = (x[j] * 2.25) + tol2;
+      else
+        splx[i][j] = x[j];
+      xr[j] = splx[i][j];
+    }
+    fvals[i] = calcf (user_cost_function,
+                      xr,
+                      parameter_lower_bound,
+                      parameter_upper_bound,
+                      cost_tangents,
+                      cost_curvature,
+                      parameter_dimension,
+                      parameter_int_real,
+                      cost_flag, exit_code, OPTIONS, ptr_out);
+  }
+
+  /* and of course compute function at starting point */
+  fvals[0] = calcf (user_cost_function,
+                    x,
+                    parameter_lower_bound,
+                    parameter_upper_bound,
+                    cost_tangents,
+                    cost_curvature,
+                    parameter_dimension,
+                    parameter_int_real,
+                    cost_flag, exit_code, OPTIONS, ptr_out);
+
+  /* now find the largest, 2nd largest, smallest f values */
+  if (fvals[0] > fvals[1]) {
+    h = 0;
+    s = 1;
+    l = 1;
+  } else {
+    h = 1;
+    s = 0;
+    l = 0;
+  }
+  fh = fvals[h];
+  fs = fvals[s];
+  fl = fvals[l];
+  for (i = 2; i <= *parameter_dimension; i++) {
+    if (fvals[i] <= fvals[l]) {
+      l = i;
+      fl = fvals[i];
+    } else {
+      if (fvals[i] >= fvals[h]) {
+        s = h;
+        fs = fh;
+        h = i;
+        fh = fvals[i];
+      } else if (fvals[i] >= fvals[s]) {
+        s = i;
+        fs = fvals[i];
+      }
+    }
+  }
+#if FITLOC_PRINT
+  if ((s == h) || (s == l) || (h == l))
+    fprintf (ptr_out, "\nPANIC: s,l,h not unique %d %d %d\n", s, h, l);
+
+  fprintf (ptr_out, "INITIAL SIMPLEX:\n");
+  for (i = 0; i <= *parameter_dimension; i++) {
+    for (j = 0; j < *parameter_dimension; j++) {
+      fprintf (ptr_out, "   %11.4g", splx[i][j]);
+    }
+    fprintf (ptr_out, "      f = %12.5g", fvals[i]);
+    if (i == h)
+      fprintf (ptr_out, "  HIGHEST");
+    if (i == s)
+      fprintf (ptr_out, "  SECOND HIGHEST");
+    if (i == l)
+      fprintf (ptr_out, "  LOWEST");
+    fprintf (ptr_out, "\n");
+  }
+#endif /* FITLOC_PRINT */
+
+/* MAJOR LOOP */
+
+  flast = fl;
+  futility = 0;
+  lastprint = 0;
+  iters = 0;
+  err1 = 1.1 + (1.1 * tol1);
+  while ((err1 > tol1) && (iters < OPTIONS->Iter_Max) &&
+         (futility < (*parameter_dimension * no_progress))) {
+    iters++;
+
+    /* now find the largest, 2nd largest, smallest f values */
+    if (fvals[0] > fvals[1]) {
+      h = 0;
+      s = 1;
+      l = 1;
+    } else {
+      h = 1;
+      s = 0;
+      l = 0;
+    }
+    fh = fvals[h];
+    fs = fvals[s];
+    fl = fvals[l];
+    for (i = 2; i <= *parameter_dimension; i++) {
+      if (fvals[i] <= fvals[l]) {
+        l = i;
+        fl = fvals[i];
+      } else {
+        if (fvals[i] >= fvals[h]) {
+          s = h;
+          fs = fh;
+          h = i;
+          fh = fvals[i];
+        } else if (fvals[i] >= fvals[s]) {
+          s = i;
+          fs = fvals[i];
+        }
+      }
+    }
+#if FITLOC_PRINT
+    if ((s == h) || (s == l) || (h == l))
+      fprintf (ptr_out, "\nPANIC: s,l,h not unique %d %d %d\n", s, h, l);
+#endif
+
+    /* compute the centroid */
+    for (j = 0; j < *parameter_dimension; j++) {
+      x0[j] = 0.0;
+      for (i = 0; i <= *parameter_dimension; i++) {
+        if (i != h)
+          x0[j] += splx[i][j];
+      }
+      x0[j] /= ((double) *parameter_dimension);
+    }
+
+    if (fl < flast) {
+      flast = fl;
+      futility = 0;
+    } else
+      futility += 1;
+
+#if FITLOC_PRINT
+    fprintf (ptr_out, "Iteration %3d f(best) = %12.6g halt? = %11.5g\n",
+             iters, fl, err1);
+    if ((iters - lastprint) >= 100) {
+      fprintf (ptr_out, "\n     Best point seen so far:\n");
+      for (i = 0; i < *parameter_dimension; i++) {
+        fprintf (ptr_out, "     x[%3d] = %15.7g\n", i, splx[l][i]);
+      }
+      lastprint = iters;
+      fprintf (ptr_out, "\n");
+    }
+    fflush (ptr_out);
+#endif /* FITLOC_PRINT */
+
+    /* STEP 1: compute a reflected point xr */
+    for (i = 0; i < *parameter_dimension; i++) {
+      xr[i] = ((1.0 + alpha) * x0[i]) - (alpha * splx[h][i]);
+    }
+    fr = calcf (user_cost_function,
+                xr,
+                parameter_lower_bound,
+                parameter_upper_bound,
+                cost_tangents,
+                cost_curvature,
+                parameter_dimension,
+                parameter_int_real, cost_flag, exit_code, OPTIONS, ptr_out);
+
+    /* typical outcome: <2nd-biggest , >lowest .  Go again */
+    if ((fr < fs) && (fr > fl)) {
+      for (i = 0; i < *parameter_dimension; i++) {
+        splx[h][i] = xr[i];
+      }
+      fvals[h] = fr;
+      goto more_iterations;
+    }
+
+    /* STEP 2: if reflected point is favorable, expand the simplex */
+    if (fr < fl) {
+      for (i = 0; i < *parameter_dimension; i++) {
+        xe[i] = (gamma * xr[i]) + ((1.0 - gamma) * x0[i]);
+      }
+      fe = calcf (user_cost_function,
+                  xe,
+                  parameter_lower_bound,
+                  parameter_upper_bound,
+                  cost_tangents,
+                  cost_curvature,
+                  parameter_dimension,
+                  parameter_int_real, cost_flag, exit_code, OPTIONS, ptr_out);
+      if (fe < fr) {            /* win big; expansion point tiny */
+        for (i = 0; i < *parameter_dimension; i++) {
+          splx[h][i] = xe[i];
+        }
+        fvals[h] = fh = fe;
+      } else
+        /* still ok; reflection point a winner */
+      {
+        for (i = 0; i < *parameter_dimension; i++) {
+          splx[h][i] = xr[i];
+        }
+        fvals[h] = fh = fr;
+      }
+      goto more_iterations;
+    }
+
+    /* STEP 3: if reflected point is unfavorable, contract simplex */
+    if (fr > fs) {
+      if (fr < fh) {            /* may as well replace highest pt */
+        for (i = 0; i < *parameter_dimension; i++) {
+          splx[h][i] = xr[i];
+        }
+        fvals[h] = fh = fr;
+      }
+      for (i = 0; i < *parameter_dimension; i++) {
+        xc1[i] = (beta1 * xr[i]) + ((1.0 - beta1) * x0[i]);
+      }
+      fc1 = calcf (user_cost_function,
+                   xc1,
+                   parameter_lower_bound,
+                   parameter_upper_bound,
+                   cost_tangents,
+                   cost_curvature,
+                   parameter_dimension,
+                   parameter_int_real,
+                   cost_flag, exit_code, OPTIONS, ptr_out);
+      if (fc1 < fh) {           /* slight contraction worked */
+        for (i = 0; i < *parameter_dimension; i++) {
+          splx[h][i] = xc1[i];
+        }
+        fvals[h] = fh = fc1;
+        goto more_iterations;
+      }
+      /* now have to try strong contraction */
+      for (i = 0; i < *parameter_dimension; i++) {
+        xc2[i] = (beta2 * splx[h][i]) + ((1.0 - beta2) * x0[i]);
+      }
+      fc2 = calcf (user_cost_function,
+                   xc2,
+                   parameter_lower_bound,
+                   parameter_upper_bound,
+                   cost_tangents,
+                   cost_curvature,
+                   parameter_dimension,
+                   parameter_int_real,
+                   cost_flag, exit_code, OPTIONS, ptr_out);
+      if (fc2 < fh) {           /* strong contraction worked */
+        for (i = 0; i < *parameter_dimension; i++) {
+          splx[h][i] = xc2[i];
+        }
+        fvals[h] = fh = fc2;
+        goto more_iterations;
+      }
+    }
+
+    /* STEP 4: nothing worked.  collapse the simplex around xl */
+    for (i = 0; i <= *parameter_dimension; i++) {
+      if (i != l) {
+        for (j = 0; j < *parameter_dimension; j++) {
+          splx[i][j] = (splx[i][j] + splx[l][j]) / delta;
+          xr[j] = splx[i][j];
+        }
+        fvals[i] = calcf (user_cost_function,
+                          xr,
+                          parameter_lower_bound,
+                          parameter_upper_bound,
+                          cost_tangents,
+                          cost_curvature,
+                          parameter_dimension,
+                          parameter_int_real,
+                          cost_flag, exit_code, OPTIONS, ptr_out);
+      }
+    }
+
+  more_iterations:
+
+    ftmp = 0.00;
+    for (i = 0; i <= *parameter_dimension; i++) {
+      ftmp += fvals[i];
+    }
+    ftmp /= ((double) (*parameter_dimension + 1));
+
+    err1 = 0.00;
+    for (i = 0; i <= *parameter_dimension; i++) {
+      err1 += ((fvals[i] - ftmp) * (fvals[i] - ftmp));
+    }
+    err1 /= ((double) (*parameter_dimension + 1));
+    err1 = sqrt (err1);
+  }                             /* end of major while loop */
+
+  /* find the smallest f value */
+  l = 0;
+  fl = fvals[0];
+  for (i = 1; i <= *parameter_dimension; i++) {
+    if (fvals[i] < fvals[l])
+      l = i;
+  }
+
+  /* give it back to the user */
+  for (i = 0; i < *parameter_dimension; i++) {
+    x[i] = splx[l][i];
+  }
+
+  free (fvals);
+  for (i = 0; i <= *parameter_dimension; i++)
+    free (splx[i]);
+  free (splx);
+  free (x0);
+  free (xr);
+  free (xe);
+  free (xc1);
+  free (xc2);
+
+  return (iters);
+}
+#else
+#endif /* FITLOC */
+
+#if ASA_TEMPLATE_SAMPLE
+
+#if HAVE_ANSI
+void
+sample (FILE * ptr_out, FILE * ptr_asa)
+#else
+void
+sample (ptr_out, ptr_asa)
+     FILE *ptr_out;
+     FILE *ptr_asa;
+#endif
+{
+  int ind, n_samples, n_accept, index, dim;
+  double cost, cost_temp, bias_accept;
+  double param, temp, bias_gener, aver_weight, range;
+  double sum, norm, answer, prod, binsize;
+  char ch[80], sample[8];
+
+  /*
+     This is a demonstration of using ASA_SAMPLE to perform the double integral
+     of exp(-x^2 - y^2) for x and y between 0 and 2.  The mesh is quite crude.
+
+     The temperature-dependent acceptance and generated biases factor are
+     divided out, and the actual cost function weights each point.
+   */
+
+  dim = 2;
+  norm = sum = 0.;
+  n_samples = 0;
+
+  fprintf (ptr_out,
+           ":SAMPLE:   n_accept   cost        cost_temp    bias_accept    \
+ aver_weight\n");
+  fprintf (ptr_out,
+           ":SAMPLE:   index      param[]     temp[]       bias_gener[]   \
+ range[]\n");
+  for (;;) {
+    fscanf (ptr_asa, "%s", ch);
+    if (!strcmp (ch, "exit_status")) {
+      break;
+    }
+    if (strcmp (ch, ":SAMPLE#")) {
+      continue;
+    }
+    ++n_samples;
+    fprintf (ptr_out, "%s\n", ch);
+    fflush (ptr_out);
+    fscanf (ptr_asa, "%s%d%lf%lf%lf%lf",
+            sample, &n_accept, &cost, &cost_temp, &bias_accept, &aver_weight);
+    if (strcmp (sample, ":SAMPLE+")) {
+      fprintf (ptr_out, "%s %11d %12.7g %12.7g %12.7g %12.7g\n",
+               sample, n_accept, cost, cost_temp, bias_accept, aver_weight);
+    } else {
+      fprintf (ptr_out, "%s %10d %12.7g %12.7g %12.7g %12.7g\n",
+               sample, n_accept, cost, cost_temp, bias_accept, aver_weight);
+    }
+    prod = bias_accept;
+    binsize = 1.0;
+    for (ind = 0; ind < dim; ++ind) {
+      fscanf (ptr_asa, "%s%d%lf%lf%lf%lf",
+              sample, &index, &param, &temp, &bias_gener, &range);
+      fprintf (ptr_out, "%s %11d %12.7g %12.7g %12.7g %12.7g\n",
+               sample, index, param, temp, bias_gener, range);
+      prod *= bias_gener;
+      binsize *= range;
+    }
+    /* In this example, retrieve integrand from sampling function */
+    sum += ((F_EXP (-cost) * binsize) / prod);
+    norm += (binsize / prod);
+  }
+  sum /= norm;
+
+  answer = 1.0;
+  for (ind = 0; ind < dim; ++ind) {
+    answer *= (0.5 * sqrt (3.14159265) * erf (2.0));
+  }
+
+  fprintf (ptr_out, "\n");
+  fprintf (ptr_out, "sum = %12.7g, answer = %12.7g\n", sum, answer);
+  fprintf (ptr_out, "n_samples = %d, norm = %12.7g\n", n_samples, norm);
+  fflush (ptr_out);
+
+}
+#endif /* ASA_TEMPLATE_SAMPLE */
+#if ASA_TEMPLATE_LIB
+int
+main ()
+{
+  double main_cost_value;
+  double *main_cost_parameters;
+  int main_exit_code;
+  LONG_INT number_params;
+  ALLOC_INT n_param;
+  FILE *ptr_main;
+
+#if INCL_STDOUT
+  ptr_main = stdout;
+#endif /* INCL_STDOUT */
+
+  /* Note this assumes the *parameter_dimension = 4 */
+  number_params = 4;
+
+  if ((main_cost_parameters =
+       (double *) calloc (number_params, sizeof (double))) == NULL) {
+    strcpy (user_exit_msg, "ASA_TEMPLATE_LIB main(): main_cost_parameters");
+    Exit_USER (user_exit_msg);
+    return (-2);
+  }
+
+  asa_seed (696969);            /* This is the default random seed. */
+  asa_main (&main_cost_value, main_cost_parameters, &main_exit_code);
+
+  fprintf (ptr_main, "main_exit_code = %d\n", main_exit_code);
+  fprintf (ptr_main, "main_cost_value = %12.7g\n", main_cost_value);
+  fprintf (ptr_main, "parameter\tvalue\n");
+  for (n_param = 0; n_param < number_params; ++n_param) {
+    fprintf (ptr_main,
+#if INT_ALLOC
+             "%d\t\t%12.7g\n",
+#else
+#if INT_LONG
+             "%ld\t\t%12.7g\n",
+#else
+             "%d\t\t%12.7g\n",
+#endif
+#endif
+             n_param, main_cost_parameters[n_param]);
+  }
+
+  free (main_cost_parameters);
+
+  return (0);
+/* NOTREACHED */
+}
+#endif /* ASA_TEMPLATE_LIB */
+
+void
+Exit_USER (char *statement)
+{
+#if INCL_STDOUT
+  printf ("\n\n*** EXIT calloc failed *** %s\n\n", statement);
+#else
+  ;
+#endif /* INCL_STDOUT */
+}
diff --git a/include/asa.h b/include/asa.h
new file mode 100644
--- /dev/null
+++ b/include/asa.h
@@ -0,0 +1,337 @@
+#ifndef _ASA_H_
+#define _ASA_H_
+
+/***********************************************************************
+* Adaptive Simulated Annealing (ASA)
+* Lester Ingber <ingber@ingber.com>
+* Copyright (c) 1993-2004 Lester Ingber.  All Rights Reserved.
+* The LICENSE file must be included with ASA code.
+***********************************************************************/
+
+ /* $Id: asa.h,v 25.15 2004/09/23 18:10:48 ingber Exp ingber $ */
+
+ /* asa.h for Adaptive Simulated Annealing */
+
+#include "asa_usr_asa.h"
+
+#define ZERO			((double) 0.0)
+#define ONE			((double) 1.0)
+#define TWO			((double) 2.0)
+#define TEN			((double) 10.0)
+#define HALF			((double) 0.5)
+
+#define NORMAL_EXIT			((int) 0)
+#define P_TEMP_TOO_SMALL		((int) 1)
+#define C_TEMP_TOO_SMALL		((int) 2)
+#define COST_REPEATING			((int) 3)
+#define TOO_MANY_INVALID_STATES		((int) 4)
+#define IMMEDIATE_EXIT			((int) 5)
+#define INVALID_USER_INPUT		((int) 7)
+#define INVALID_COST_FUNCTION		((int) 8)
+#define INVALID_COST_FUNCTION_DERIV	((int) 9)
+#define CALLOC_FAILED			((int) -1)
+
+#ifndef TIME_STD
+#define TIME_STD FALSE
+#endif
+
+#ifndef TIME_GETRUSAGE
+#define TIME_GETRUSAGE TRUE
+#endif
+
+#if TIME_CALC
+#if TIME_GETRUSAGE
+#include <sys/time.h>
+#include <sys/resource.h>
+#if TIME_STD
+#include <sys/syscall.h>
+#endif /* TIME_STD */
+#else /* TIME_GETRUSAGE */
+#if TRUE                        /* change to FALSE for SunOS 4.1.x */
+#include <time.h>
+#else
+#include </usr/5include/time.h>
+#endif
+#endif /* TIME_GETRUSAGE */
+#endif /* TIME_CALC */
+
+ /* Set this to TRUE to override the P_TEMP_TOO_SMALL test */
+#ifndef NO_PARAM_TEMP_TEST
+#define NO_PARAM_TEMP_TEST FALSE
+#endif
+
+ /* Set this to TRUE to override the C_TEMP_TOO_SMALL test */
+#ifndef NO_COST_TEMP_TEST
+#define NO_COST_TEMP_TEST FALSE
+#endif
+
+#ifndef SYSTEM_CALL
+#define SYSTEM_CALL TRUE
+#endif
+
+ /* Printing Options */
+
+#ifndef ASA_PRINT
+#define ASA_PRINT TRUE
+#endif
+
+#if ASA_PRINT
+#else
+#if ASA_SAMPLE
+#define ASA_PRINT TRUE
+#endif
+#endif
+
+#ifndef ASA_OUT
+#define ASA_OUT "asa_out"
+#endif
+
+#ifndef DROPPED_PARAMETERS
+#define DROPPED_PARAMETERS FALSE
+#endif
+
+ /* You can set ASA_PRINT_INTERMED to TRUE to print out
+    intermediate data when SELF_OPTIMIZE is set to TRUE */
+#ifndef ASA_PRINT_INTERMED
+#if SELF_OPTIMIZE
+#define ASA_PRINT_INTERMED FALSE
+#else
+#define ASA_PRINT_INTERMED TRUE
+#endif
+#endif
+
+#ifndef ASA_PRINT_MORE
+#define ASA_PRINT_MORE FALSE
+#endif
+
+char exit_msg[160];             /* temp storage for exit messages */
+
+ /* The state of the system in terms of parameters and function value */
+typedef struct {
+  double cost;
+  double *parameter;
+#if ASA_PARALLEL
+#if USER_ACCEPTANCE_TEST
+  int par_user_accept_flag;
+  int par_cost_accept_flag;
+#endif
+#endif
+} STATE;
+
+#if ASA_PARALLEL
+  /* parallel generated states */
+STATE *gener_block_state_qsort;
+#endif
+
+ /* essential MACROS */
+
+#if USER_REANNEAL_PARAMETERS
+#else
+ /* FUNCTION_REANNEAL_PARAMS(temperature, tangent, max_tangent)
+    determines the reannealed temperature. */
+#define FUNCTION_REANNEAL_PARAMS(temperature, tangent, max_tangent) \
+ (temperature * (max_tangent / tangent))
+#endif
+
+ /* IABS(i)
+    absolute value for integers, in stdlib.h on _some_ machines */
+#define IABS(i) ((i) < 0? -(i) : (i))
+
+ /*  NO_REANNEAL(x)
+    can determine whether to calculate derivatives. */
+#define NO_REANNEAL(x)	(IABS(parameter_type[x]) == 2)
+
+ /* VFOR
+    is a simple macro to iterate on each parameter index. */
+
+#define VFOR(index_v) \
+ for (index_v = 0; index_v < *number_parameters; ++index_v)
+
+#if CHECK_EXPONENT
+ /* EXPONENT_CHECK
+    checks that an exponent x is within a valid range and,
+    if not, adjusts its magnitude to fit in the range. */
+#define MIN_EXPONENT (0.9 * F_LOG ((double) MIN_DOUBLE))
+#define MAX_EXPONENT (0.9 * F_LOG ((double) MAX_DOUBLE))
+#define EXPONENT_CHECK(x) \
+ ((x) < MIN_EXPONENT ? MIN_EXPONENT : \
+ ((x) > MAX_EXPONENT ? MAX_EXPONENT : (x)))
+#else
+#define EXPONENT_CHECK(x) (x)
+#endif /* CHECK_EXPONENT */
+
+ /* PARAMETER_RANGE_TOO_SMALL(x)
+    checks if the range of parameter x is too small to work with.
+    If user_cost_function changes the parameter ranges,
+    this test could be used to adaptively bypass
+    some parameters, e.g., depending on constraints. */
+#define PARAMETER_RANGE_TOO_SMALL(x) \
+ (fabs(parameter_minimum[x] - parameter_maximum[x]) < (double) EPS_DOUBLE)
+
+ /* INTEGER_PARAMETER(x)
+    determines if the parameter is an integer type. */
+#define INTEGER_PARAMETER(x) (parameter_type[x] > 0)
+
+ /* ROW_COL_INDEX(i, j)
+    converts from row i, column j to an index. */
+#define ROW_COL_INDEX(i, j) ((i) + *number_parameters * (j))
+
+#if HAVE_ANSI
+
+ /* asa function prototypes */
+void accept_new_state (double (*user_random_generator) (LONG_INT *),
+                       LONG_INT * seed,
+                       double *parameter_minimum,
+                       double *parameter_maximum,
+                       double *current_cost_temperature,
+#if ASA_SAMPLE
+                       double *current_user_parameter_temp,
+#endif
+                       ALLOC_INT * number_parameters,
+                       LONG_INT * recent_number_acceptances,
+                       LONG_INT * number_accepted,
+                       LONG_INT * index_cost_acceptances,
+                       LONG_INT * number_acceptances_saved,
+                       LONG_INT * recent_number_generated,
+                       LONG_INT * number_generated,
+                       LONG_INT * index_parameter_generations,
+                       STATE * current_generated_state,
+                       STATE * last_saved_state,
+#if ASA_SAMPLE
+                       FILE * ptr_asa_out,
+#endif
+                       USER_DEFINES * OPTIONS);
+
+void generate_new_state (double (*user_random_generator) (LONG_INT *),
+                         LONG_INT * seed,
+                         double *parameter_minimum,
+                         double *parameter_maximum,
+                         double *current_parameter_temperature,
+#if USER_GENERATING_FUNCTION
+                         double *initial_user_parameter_temp,
+                         double *temperature_scale_parameters,
+#endif
+                         ALLOC_INT * number_parameters,
+                         int *parameter_type,
+                         STATE * current_generated_state,
+                         STATE * last_saved_state, USER_DEFINES * OPTIONS);
+
+void reanneal (double *parameter_minimum,
+               double *parameter_maximum,
+               double *tangents,
+               double *maximum_tangent,
+               double *current_cost_temperature,
+               double *initial_cost_temperature,
+               double *temperature_scale_cost,
+               double *current_user_parameter_temp,
+               double *initial_user_parameter_temp,
+               double *temperature_scale_parameters,
+               ALLOC_INT * number_parameters,
+               int *parameter_type,
+               LONG_INT * index_cost_acceptances,
+               LONG_INT * index_parameter_generations,
+               STATE * last_saved_state,
+               STATE * best_generated_state, USER_DEFINES * OPTIONS);
+
+void
+  cost_derivatives (double (*user_cost_function)
+
+                     
+                    (double *, double *, double *, double *, double *,
+                     ALLOC_INT *, int *, int *, int *, USER_DEFINES *),
+                    double *parameter_minimum, double *parameter_maximum,
+                    double *tangents, double *curvature,
+                    double *maximum_tangent, ALLOC_INT * number_parameters,
+                    int *parameter_type, int *exit_status,
+                    int *curvature_flag, int *valid_state_generated_flag,
+                    LONG_INT * number_invalid_generated_states,
+                    STATE * current_generated_state,
+                    STATE * best_generated_state, FILE * ptr_asa_out,
+                    USER_DEFINES * OPTIONS);
+
+double generate_asa_state (double (*user_random_generator) (LONG_INT *),
+                           LONG_INT * seed, double *temp);
+
+int
+  asa_exit (double (*user_cost_function)
+
+             
+            (double *, double *, double *, double *, double *, ALLOC_INT *,
+             int *, int *, int *, USER_DEFINES *), double *final_cost,
+            double *parameter_initial_final, double *parameter_minimum,
+            double *parameter_maximum, double *tangents, double *curvature,
+            double *maximum_tangent, double *current_cost_temperature,
+            double *initial_user_parameter_temp,
+            double *current_user_parameter_temp,
+            double *accepted_to_generated_ratio,
+            ALLOC_INT * number_parameters, int *parameter_type,
+            int *valid_state_generated_flag, int *exit_status,
+            ALLOC_INT * index_exit_v, ALLOC_INT * start_sequence,
+            LONG_INT * number_accepted, LONG_INT * best_number_accepted_saved,
+            LONG_INT * index_cost_acceptances, LONG_INT * number_generated,
+            LONG_INT * number_invalid_generated_states,
+            LONG_INT * index_parameter_generations,
+            LONG_INT * best_number_generated_saved,
+            STATE * current_generated_state, STATE * last_saved_state,
+            STATE * best_generated_state, FILE * ptr_asa_out,
+            USER_DEFINES * OPTIONS);
+
+void Exit_ASA (char *statement);
+
+int asa_test_asa_options (LONG_INT * seed,
+                          double *parameter_initial_final,
+                          double *parameter_minimum,
+                          double *parameter_maximum,
+                          double *tangents,
+                          double *curvature,
+                          ALLOC_INT * number_parameters,
+                          int *parameter_type,
+                          int *valid_state_generated_flag,
+                          int *exit_status,
+                          FILE * ptr_asa_out, USER_DEFINES * OPTIONS);
+
+int cost_function_test (double cost,
+                        double *parameter,
+                        double *parameter_minimum,
+                        double *parameter_maximum,
+                        ALLOC_INT * number_parameters,
+                        double *xnumber_parameters);
+
+void print_string (FILE * ptr_asa_out, char *string);
+void print_string_index (FILE * ptr_asa_out, char *string, ALLOC_INT index);
+
+#if ASA_PRINT
+void print_state (double *parameter_minimum,
+                  double *parameter_maximum,
+                  double *tangents,
+                  double *curvature,
+                  double *current_cost_temperature,
+                  double *current_user_parameter_temp,
+                  double *accepted_to_generated_ratio,
+                  ALLOC_INT * number_parameters,
+                  int *curvature_flag,
+                  LONG_INT * number_accepted,
+                  LONG_INT * index_cost_acceptances,
+                  LONG_INT * number_generated,
+                  LONG_INT * number_invalid_generated_states,
+                  STATE * last_saved_state,
+                  STATE * best_generated_state,
+                  FILE * ptr_asa_out, USER_DEFINES * OPTIONS);
+
+void print_asa_options (FILE * ptr_asa_out, USER_DEFINES * OPTIONS);
+#endif /* ASA_PRINT */
+
+
+#if MULTI_MIN
+static int multi_compare (const void *cost_ii, const void *cost_jj);
+double *multi_cost_qsort;
+#endif
+
+#if ASA_PARALLEL
+static int sort_parallel (const void *cost_ii, const void *cost_jj);
+#endif
+
+#else /* HAVE_ANSI */
+#endif /* HAVE_ANSI */
+
+#endif /* _ASA_H_ */
diff --git a/include/asa_usr.h b/include/asa_usr.h
new file mode 100644
--- /dev/null
+++ b/include/asa_usr.h
@@ -0,0 +1,293 @@
+#ifndef _ASA_USER_H_
+#define _ASA_USER_H_
+
+/***********************************************************************
+* Adaptive Simulated Annealing (ASA)
+* Lester Ingber <ingber@ingber.com>
+* Copyright (c) 1993-2004 Lester Ingber.  All Rights Reserved.
+* The LICENSE file must be included with ASA code.
+***********************************************************************/
+
+ /* $Id: asa_usr.h,v 25.15 2004/09/23 18:10:45 ingber Exp ingber $ */
+
+ /* asa_usr.h for Adaptive Simulated Annealing */
+
+#include "asa_usr_asa.h"
+
+#define SHUFFLE 256             /* size of random array */
+
+#if ASA_TEMPLATE_ASA_OUT_PID
+#include <sys/types.h>
+#endif
+
+#if TIME_CALC
+ /* print the time every PRINT_FREQUENCY function evaluations
+    Define PRINT_FREQUENCY to 0 to not print out the time. */
+#define PRINT_FREQUENCY ((LONG_INT) 1000)
+#endif
+
+#if USER_ACCEPTANCE_TEST
+#define MIN(x,y)	((x) < (y) ? (x) : (y))
+#endif
+
+ /* system function prototypes */
+
+#if ASA_TEMPLATE_ASA_OUT_PID
+int getpid ();
+#endif
+
+#if HAVE_ANSI
+
+
+#if IO_PROTOTYPES
+#if OPTIONS_FILE
+int fscanf ();
+#endif
+#endif
+
+ /* user-defined */
+double USER_COST_FUNCTION (double *cost_parameters,
+                           double *parameter_lower_bound,
+                           double *parameter_upper_bound,
+                           double *cost_tangents,
+                           double *cost_curvature,
+                           ALLOC_INT * parameter_dimension,
+                           int *parameter_int_real,
+                           int *cost_flag,
+                           int *exit_code, USER_DEFINES * USER_OPTIONS);
+#if ASA_LIB
+int
+asa_main (
+           hs_cost_func *func, 
+           int number_parameters,
+           double *upper_bounds,
+           double *lower_bounds,
+           int *type,
+           double *main_cost_value,
+           double *main_cost_parameters, 
+           int *main_exit_code,
+           long int rand_seed
+  );
+#else
+int main (int argc, char **argv);
+#endif
+
+#if ASA_TEMPLATE_LIB
+int main ();
+#endif
+
+ /* possibly with accompanying data file */
+int initialize_parameters (double *cost_parameters,
+                           double *parameter_lower_bound,
+                           double *parameter_upper_bound,
+                           double *cost_tangents,
+                           double *cost_curvature,
+                           ALLOC_INT * parameter_dimension,
+                           int *parameter_int_real,
+#if OPTIONS_FILE_DATA
+                           FILE * ptr_options,
+#endif
+                           USER_DEFINES * USER_OPTIONS);
+
+//double myrand (LONG_INT * rand_seed);
+//double randflt (LONG_INT * rand_seed);
+//double resettable_randflt (LONG_INT * rand_seed, int reset);
+
+#if USER_COST_SCHEDULE
+double user_cost_schedule (double test_temperature,
+                           USER_DEFINES * USER_OPTIONS);
+#endif
+
+#if USER_ACCEPTANCE_TEST
+void user_acceptance_test (double current_cost,
+                           double *parameter_lower_bound,
+                           double *parameter_upper_bound,
+                           ALLOC_INT * parameter_dimension,
+                           USER_DEFINES * USER_OPTIONS);
+#endif
+
+#if USER_GENERATING_FUNCTION
+double user_generating_distrib (LONG_INT * seed,
+                                ALLOC_INT * parameter_dimension,
+                                ALLOC_INT index_v,
+                                double temperature_v,
+                                double init_param_temp_v,
+                                double temp_scale_params_v,
+                                double parameter_v,
+                                double parameter_range_v,
+                                double *last_saved_parameter,
+                                USER_DEFINES * USER_OPTIONS);
+#endif
+
+#if USER_REANNEAL_COST
+int user_reanneal_cost (double *cost_best,
+                        double *cost_last,
+                        double *initial_cost_temperature,
+                        double *current_cost_temperature,
+                        USER_DEFINES * USER_OPTIONS);
+#endif
+
+#if USER_REANNEAL_PARAMETERS
+double user_reanneal_params (double current_temp,
+                             double tangent,
+                             double max_tangent, USER_DEFINES * USER_OPTIONS);
+#endif
+
+#if ASA_TEMPLATE_SAMPLE
+void sample (FILE * ptr_out, FILE * ptr_asa);
+#endif
+
+void Exit_USER (char *statement);
+
+#else /* HAVE_ANSI */
+#endif /* HAVE_ANSI */
+
+void Exit_USER ();
+
+#if SELF_OPTIMIZE
+#if TIME_CALC
+#define RECUR_PRINT_FREQUENCY ((LONG_INT) 1)
+#endif
+
+#if HAVE_ANSI                   /* HAVE_ANSI SELF_OPTIMIZE */
+double RECUR_USER_COST_FUNCTION (double *recur_cost_parameters,
+                                 double *recur_parameter_lower_bound,
+                                 double *recur_parameter_upper_bound,
+                                 double *recur_cost_tangents,
+                                 double *recur_cost_curvature,
+                                 ALLOC_INT * recur_parameter_dimension,
+                                 int *recur_parameter_int_real,
+                                 int *recur_cost_flag,
+                                 int *recur_exit_code,
+                                 USER_DEFINES * RECUR_USER_OPTIONS);
+
+int recur_initialize_parameters (double *recur_cost_parameters,
+                                 double *recur_parameter_lower_bound,
+                                 double *recur_parameter_upper_bound,
+                                 double *recur_cost_tangents,
+                                 double *recur_cost_curvature,
+                                 ALLOC_INT * recur_parameter_dimension,
+                                 int *recur_parameter_int_real,
+#if RECUR_OPTIONS_FILE_DATA
+                                 FILE * recur_ptr_options,
+#endif
+                                 USER_DEFINES * RECUR_USER_OPTIONS);
+
+#if USER_COST_SCHEDULE
+double recur_user_cost_schedule (double test_temperature,
+                                 USER_DEFINES * RECUR_USER_OPTIONS);
+#endif
+
+#if USER_ACCEPTANCE_TEST
+void recur_user_acceptance_test (double current_cost,
+                                 double *recur_parameter_lower_bound,
+                                 double *recur_parameter_upper_bound,
+                                 ALLOC_INT * recur_parameter_dimension,
+                                 USER_DEFINES * RECUR_USER_OPTIONS);
+#endif
+
+#if USER_GENERATING_FUNCTION
+double recur_user_generating_distrib (LONG_INT * seed,
+                                      ALLOC_INT * recur_parameter_dimension,
+                                      ALLOC_INT index_v,
+                                      double temperature_v,
+                                      double init_param_temp_v,
+                                      double temp_scale_params_v,
+                                      double parameter_v,
+                                      double parameter_range_v,
+                                      double *last_saved_parameter,
+                                      USER_DEFINES * RECUR_USER_OPTIONS);
+#endif
+
+#if USER_REANNEAL_COST
+int recur_user_reanneal_cost (double *cost_best,
+                              double *cost_last,
+                              double *initial_cost_temperature,
+                              double *current_cost_temperature,
+                              USER_DEFINES * RECUR_USER_OPTIONS);
+#endif
+
+#if USER_REANNEAL_PARAMETERS
+double recur_user_reanneal_params (double current_temp,
+                                   double tangent,
+                                   double max_tangent,
+                                   USER_DEFINES * RECUR_USER_OPTIONS);
+#endif
+
+#else /* HAVE_ANSI SELF_OPTIMIZE */
+
+double RECUR_USER_COST_FUNCTION ();
+int recur_initialize_parameters ();
+
+#if USER_COST_SCHEDULE
+double recur_user_cost_schedule ();
+#endif
+
+#if USER_ACCEPTANCE_TEST
+void recur_user_acceptance_test ();
+#endif
+
+#if USER_GENERATING_FUNCTION
+double recur_user_generating_distrib ();
+#endif
+
+#if USER_REANNEAL_COST
+int recur_user_reanneal_cost ();
+#endif
+
+#if USER_REANNEAL_PARAMETERS
+double recur_user_reanneal_params ();
+#endif
+
+#endif /* HAVE_ANSI */
+#endif /* SELF_OPTIMIZE */
+
+#if FITLOC
+#if HAVE_ANSI
+double
+  calcf (double (*user_cost_function)
+
+          
+         (double *, double *, double *, double *, double *, ALLOC_INT *,
+          int *, int *, int *, USER_DEFINES *), double *cost_parameters,
+         double *parameter_lower_bound, double *parameter_upper_bound,
+         double *cost_tangents, double *cost_curvature,
+         ALLOC_INT * parameter_dimension, int *parameter_int_real,
+         int *cost_flag, int *exit_code, USER_DEFINES * USER_OPTIONS,
+         FILE * ptr_out);
+
+double
+  fitloc (double (*user_cost_function)
+
+           
+          (double *, double *, double *, double *, double *, ALLOC_INT *,
+           int *, int *, int *, USER_DEFINES *), double *cost_parameters,
+          double *parameter_lower_bound, double *parameter_upper_bound,
+          double *cost_tangents, double *cost_curvature,
+          ALLOC_INT * parameter_dimension, int *parameter_int_real,
+          int *cost_flag, int *exit_code, USER_DEFINES * USER_OPTIONS,
+          FILE * ptr_out);
+
+int
+  simplex (double (*user_cost_function)
+
+            
+           (double *, double *, double *, double *, double *, ALLOC_INT *,
+            int *, int *, int *, USER_DEFINES *), double *cost_parameters,
+           double *parameter_lower_bound, double *parameter_upper_bound,
+           double *cost_tangents, double *cost_curvature,
+           ALLOC_INT * parameter_dimension, int *parameter_int_real,
+           int *cost_flag, int *exit_code, USER_DEFINES * USER_OPTIONS,
+           FILE * ptr_out, double tol1, double tol2, int no_progress,
+           double alpha, double beta1, double beta2, double gamma,
+           double delta);
+#else /* HAVE_ANSI */
+
+double calcf ();
+double fitloc ();
+int simplex ();
+
+#endif /* HAVE_ANSI */
+#endif /* FITLOC */
+
+#endif /* _ASA_USER_H_ */
diff --git a/include/asa_usr_asa.h b/include/asa_usr_asa.h
new file mode 100644
--- /dev/null
+++ b/include/asa_usr_asa.h
@@ -0,0 +1,682 @@
+#ifndef _ASA_USER_ASA_H_
+#define _ASA_USER_ASA_H_
+
+/***********************************************************************
+* Adaptive Simulated Annealing (ASA)
+* Lester Ingber <ingber@ingber.com>
+* Copyright (c) 1993-2004 Lester Ingber.  All Rights Reserved.
+* The LICENSE file must be included with ASA code.
+***********************************************************************/
+
+ /* $Id: asa_usr_asa.h,v 25.15 2004/09/23 18:10:49 ingber Exp ingber $ */
+
+ /* asa_usr_asa.h for Adaptive Simulated Annealing */
+
+#include <errno.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>             /* misc defs on most machines */
+#include <string.h>
+
+/* required if use machine-defined {DBL_EPSILON DBL_MIN DBL_MAX} */
+/* #include <float.h> */
+
+/* test for memory leaks */
+/* #include "/usr/local/include/leak.h" */
+
+#define	TRUE			1
+#define	FALSE			0
+
+#define MIN(x,y)	((x) < (y) ? (x) : (y))
+#define MAX(x,y)	((x) > (y) ? (x) : (y))
+
+ /* DEFAULT PARAMETERS SETTINGS */
+
+ /* Pre-Compile Options */
+
+ /* Special ASA_TEMPLATEs */
+
+#ifndef MY_TEMPLATE
+#define MY_TEMPLATE TRUE
+#endif
+#if MY_TEMPLATE                 /* MY_TEMPLATE_asa_user */
+
+// #include <HsFFI.h>
+
+typedef double hs_cost_func(double *x, int *flag);
+
+/* #define ASA_LIB TRUE */
+#define ASA_TEST FALSE
+#define ASA_LIB TRUE
+#define ASA_OUT  "STDOUT"
+#define USER_OUT "STDOUT"
+#define FITLOC TRUE
+#define COST_FILE FALSE
+// #define ASA_PRINT FALSE
+// #define USER_ASA_OUT TRUE 
+#define OPTIONS_FILE FALSE
+#define OPTIONAL_PTR_TYPE hs_cost_func
+#define OPTIONAL_DATA_PTR TRUE
+#define QUENCH_COST TRUE
+#define QUENCH_PARAMETERS TRUE
+
+
+  /* you can add your own set of #define here */
+#endif /* MY_TEMPLATE */
+
+#ifndef ASA_TEMPLATE_LIB
+#define ASA_TEMPLATE_LIB FALSE
+#endif
+#if ASA_TEMPLATE_LIB
+#define ASA_LIB TRUE
+#define ASA_TEST TRUE
+#endif
+
+#ifndef ASA_TEMPLATE_ASA_OUT_PID
+#define ASA_TEMPLATE_ASA_OUT_PID FALSE
+#endif
+#if ASA_TEMPLATE_ASA_OUT_PID
+#define USER_ASA_OUT TRUE
+#endif
+
+#ifndef ASA_TEMPLATE_MULTIPLE
+#define ASA_TEMPLATE_MULTIPLE FALSE
+#endif
+#if ASA_TEMPLATE_MULTIPLE
+#define COST_FILE FALSE
+#define USER_ASA_OUT TRUE
+#define ASA_TEST TRUE
+#define QUENCH_COST TRUE
+#define QUENCH_PARAMETERS TRUE
+#define OPTIONS_FILE FALSE
+#endif
+
+#ifndef ASA_TEMPLATE_SELFOPT
+#define ASA_TEMPLATE_SELFOPT FALSE
+#endif
+#if ASA_TEMPLATE_SELFOPT
+#define COST_FILE FALSE
+#define SELF_OPTIMIZE TRUE
+#define OPTIONAL_DATA_DBL TRUE
+#define USER_ASA_OUT TRUE
+#define ASA_TEST TRUE
+#define OPTIONS_FILE FALSE
+#endif
+
+#ifndef ASA_TEMPLATE_SAMPLE
+#define ASA_TEMPLATE_SAMPLE FALSE
+#endif
+#if ASA_TEMPLATE_SAMPLE
+#define COST_FILE FALSE
+#define ASA_SAMPLE TRUE
+#define USER_ACCEPTANCE_TEST TRUE
+#define USER_COST_SCHEDULE TRUE
+#define OPTIONS_FILE_DATA FALSE
+#define USER_ACCEPT_ASYMP_EXP TRUE
+#endif
+
+#ifndef ASA_TEMPLATE_PARALLEL
+#define ASA_TEMPLATE_PARALLEL FALSE
+#endif
+#if ASA_TEMPLATE_PARALLEL
+#define COST_FILE FALSE
+#define ASA_TEST TRUE
+#define ASA_PARALLEL TRUE
+#endif
+
+#ifndef ASA_TEMPLATE_SAVE
+#define ASA_TEMPLATE_SAVE FALSE
+#endif
+#if ASA_TEMPLATE_SAVE
+#define COST_FILE FALSE
+#define ASA_TEST TRUE
+#define ASA_SAVE TRUE
+#define QUENCH_PARAMETERS TRUE
+#define QUENCH_COST TRUE
+#endif
+
+#ifndef ASA_TEMPLATE_QUEUE
+#define ASA_TEMPLATE_QUEUE FALSE
+#endif
+#if ASA_TEMPLATE_QUEUE
+#define ASA_QUEUE TRUE
+#define ASA_RESOLUTION FALSE
+#define ASA_TEST TRUE
+#define COST_FILE FALSE
+#define ASA_PRINT_MORE TRUE
+#endif
+
+#ifndef ASA_TEST_POINT
+#define ASA_TEST_POINT FALSE
+#endif
+#if ASA_TEST_POINT
+#define ASA_TEST TRUE
+#define COST_FILE FALSE
+#define SMALL_FLOAT 1.0E-50
+#define QUENCH_COST TRUE
+#endif
+
+ /* Standard Pre-Compile Options */
+
+#ifndef USER_COST_FUNCTION
+#define USER_COST_FUNCTION cost_function
+#endif
+
+#if SELF_OPTIMIZE
+#ifndef RECUR_USER_COST_FUNCTION
+#define RECUR_USER_COST_FUNCTION recur_cost_function
+#endif
+#endif
+
+#ifndef INCL_STDOUT
+#define INCL_STDOUT TRUE
+#endif
+#if INCL_STDOUT
+#define TIME_CALC FALSE
+#endif
+
+#ifndef OPTIONS_FILE
+#define OPTIONS_FILE TRUE
+#endif
+
+#if OPTIONS_FILE
+#ifndef OPTIONS_FILE_DATA
+#define OPTIONS_FILE_DATA TRUE
+#endif
+#else
+#define OPTIONS_FILE_DATA FALSE
+#endif
+
+#ifndef RECUR_OPTIONS_FILE
+#define RECUR_OPTIONS_FILE FALSE
+#endif
+
+#if RECUR_OPTIONS_FILE
+#ifndef RECUR_OPTIONS_FILE_DATA
+#define RECUR_OPTIONS_FILE_DATA FALSE
+#endif
+#else
+#define RECUR_OPTIONS_FILE_DATA FALSE
+#endif
+
+#ifndef COST_FILE
+#define COST_FILE TRUE
+#endif
+
+#ifndef ASA_LIB
+#define ASA_LIB FALSE
+#endif
+
+#ifndef HAVE_ANSI
+#define HAVE_ANSI TRUE
+#endif
+
+#ifndef IO_PROTOTYPES
+#define IO_PROTOTYPES FALSE
+#endif
+
+#ifndef TIME_CALC
+#define TIME_CALC FALSE
+#endif
+
+#ifndef INT_LONG
+#define INT_LONG TRUE
+#endif
+
+#if INT_LONG
+#define LONG_INT long int
+#else
+#define LONG_INT int
+#endif
+
+#ifndef INT_ALLOC
+#define INT_ALLOC FALSE
+#endif
+
+#if INT_ALLOC
+#define ALLOC_INT int
+#else
+#define ALLOC_INT LONG_INT
+#endif
+
+ /* You can define SMALL_FLOAT to better correlate to your machine's
+    precision, i.e., as used in asa */
+#ifndef SMALL_FLOAT
+#define SMALL_FLOAT 1.0E-18
+#endif
+
+ /* You can define your machine's maximum and minimum doubles here */
+#ifndef MIN_DOUBLE
+#define MIN_DOUBLE ((double) SMALL_FLOAT)
+#endif
+
+#ifndef MAX_DOUBLE
+#define MAX_DOUBLE ((double) 1.0 / (double) SMALL_FLOAT)
+#endif
+
+#ifndef EPS_DOUBLE
+#define EPS_DOUBLE ((double) SMALL_FLOAT)
+#endif
+
+#ifndef CHECK_EXPONENT
+#define CHECK_EXPONENT FALSE
+#endif
+
+#ifndef ASA_TEST
+#define ASA_TEST FALSE
+#endif
+
+#ifndef ASA_TEMPLATE
+#define ASA_TEMPLATE FALSE
+#endif
+
+#ifndef USER_INITIAL_COST_TEMP
+#define USER_INITIAL_COST_TEMP FALSE
+#endif
+
+#ifndef RATIO_TEMPERATURE_SCALES
+#define RATIO_TEMPERATURE_SCALES FALSE
+#endif
+
+#ifndef USER_INITIAL_PARAMETERS_TEMPS
+#define USER_INITIAL_PARAMETERS_TEMPS FALSE
+#endif
+
+#ifndef DELTA_PARAMETERS
+#define DELTA_PARAMETERS FALSE
+#endif
+
+#ifndef QUENCH_PARAMETERS
+#define QUENCH_PARAMETERS FALSE
+#endif
+
+#ifndef QUENCH_COST
+#define QUENCH_COST FALSE
+#endif
+
+#ifndef QUENCH_PARAMETERS_SCALE
+#define QUENCH_PARAMETERS_SCALE TRUE
+#endif
+
+#ifndef QUENCH_COST_SCALE
+#define QUENCH_COST_SCALE TRUE
+#endif
+
+#ifndef OPTIONAL_DATA_DBL
+#define OPTIONAL_DATA_DBL FALSE
+#endif
+
+#ifndef OPTIONAL_DATA_INT
+#define OPTIONAL_DATA_INT FALSE
+#endif
+
+#ifndef OPTIONAL_DATA_PTR
+#define OPTIONAL_DATA_PTR FALSE
+#endif
+#if OPTIONAL_DATA_PTR
+/* user must define USER_TYPE; if a struct, it must be declared above */
+#ifndef OPTIONAL_PTR_TYPE
+#define OPTIONAL_PTR_TYPE USER_TYPE
+#endif
+#endif /* OPTIONAL_DATA_PTR */
+
+#ifndef USER_REANNEAL_COST
+#define USER_REANNEAL_COST FALSE
+#endif
+
+#ifndef USER_REANNEAL_PARAMETERS
+#define USER_REANNEAL_PARAMETERS FALSE
+#endif
+
+#ifndef MAXIMUM_REANNEAL_INDEX
+#define MAXIMUM_REANNEAL_INDEX 50000
+#endif
+
+#ifndef REANNEAL_SCALE
+#define REANNEAL_SCALE 10
+#endif
+
+#ifndef USER_COST_SCHEDULE
+#define USER_COST_SCHEDULE FALSE
+#endif
+
+#ifndef USER_ACCEPT_ASYMP_EXP
+#define USER_ACCEPT_ASYMP_EXP FALSE
+#endif
+
+#ifndef USER_ACCEPT_THRESHOLD
+#define USER_ACCEPT_THRESHOLD FALSE
+#endif
+
+#ifndef USER_ACCEPTANCE_TEST
+#define USER_ACCEPTANCE_TEST FALSE
+#endif
+
+#ifndef USER_GENERATING_FUNCTION
+#define USER_GENERATING_FUNCTION FALSE
+#endif
+
+ /* in asa.c, field-width.precision = G_FIELD.G_PRECISION */
+#ifndef G_FIELD
+#define G_FIELD 12
+#endif
+#ifndef G_PRECISION
+#define G_PRECISION 7
+#endif
+
+#define INTEGER_TYPE		((int) 1)
+#define REAL_TYPE		((int) -1)
+#define INTEGER_NO_REANNEAL	((int) 2)
+#define REAL_NO_REANNEAL	((int) -2)
+
+ /* Set this to TRUE to self-optimize the Program Options */
+#ifndef SELF_OPTIMIZE
+#define SELF_OPTIMIZE FALSE
+#endif
+
+#ifndef USER_OUT
+#define USER_OUT "asa_usr_out"
+#endif
+
+#ifndef USER_ASA_OUT
+#define USER_ASA_OUT FALSE
+#endif
+
+#ifndef ASA_SAMPLE
+#define ASA_SAMPLE FALSE
+#endif
+
+#ifndef ASA_QUEUE
+#define ASA_QUEUE FALSE
+#endif
+
+#ifndef ASA_RESOLUTION
+#define ASA_RESOLUTION FALSE
+#endif
+
+#ifndef ASA_PARALLEL
+#define ASA_PARALLEL FALSE
+#endif
+
+#ifndef ASA_SAVE_OPT
+#define ASA_SAVE_OPT FALSE
+#endif
+#if ASA_SAVE_OPT
+#define ASA_SAVE TRUE
+#endif
+
+#ifndef ASA_SAVE_BACKUP
+#define ASA_SAVE_BACKUP FALSE
+#endif
+#if ASA_SAVE_BACKUP
+#define ASA_SAVE TRUE
+#endif
+
+#ifndef ASA_SAVE
+#define ASA_SAVE FALSE
+#endif
+
+#ifndef ASA_PIPE
+#define ASA_PIPE FALSE
+#endif
+
+#ifndef ASA_PIPE_FILE
+#define ASA_PIPE_FILE FALSE
+#endif
+
+#ifndef FDLIBM_POW
+#define FDLIBM_POW FALSE
+#endif
+#if FDLIBM_POW
+#define F_POW s_pow
+#else
+#define F_POW pow
+#endif
+
+#ifndef FDLIBM_LOG
+#define FDLIBM_LOG FALSE
+#endif
+#if FDLIBM_LOG
+#define F_LOG s_log
+#else
+#define F_LOG log
+#endif
+
+#ifndef FDLIBM_EXP
+#define FDLIBM_EXP FALSE
+#endif
+#if FDLIBM_EXP
+#define F_EXP s_exp
+#else
+#define F_EXP exp
+#endif
+
+#ifndef FITLOC
+#define FITLOC FALSE
+#endif
+
+#ifndef FITLOC_ROUND
+#define FITLOC_ROUND TRUE
+#endif
+
+#ifndef FITLOC_PRINT
+#define FITLOC_PRINT TRUE
+#endif
+
+#ifndef MULTI_MIN
+#define MULTI_MIN FALSE
+#endif
+
+ /* Program Options */
+
+typedef struct {
+  LONG_INT Limit_Acceptances;
+  LONG_INT Limit_Generated;
+  int Limit_Invalid_Generated_States;
+  double Accepted_To_Generated_Ratio;
+
+  double Cost_Precision;
+  int Maximum_Cost_Repeat;
+  int Number_Cost_Samples;
+  double Temperature_Ratio_Scale;
+  double Cost_Parameter_Scale_Ratio;
+  double Temperature_Anneal_Scale;
+#if USER_INITIAL_COST_TEMP
+  double *User_Cost_Temperature;
+#endif
+
+  int Include_Integer_Parameters;
+  int User_Initial_Parameters;
+  ALLOC_INT Sequential_Parameters;
+  double Initial_Parameter_Temperature;
+#if RATIO_TEMPERATURE_SCALES
+  double *User_Temperature_Ratio;
+#endif
+#if USER_INITIAL_PARAMETERS_TEMPS
+  double *User_Parameter_Temperature;
+#endif
+
+  int Acceptance_Frequency_Modulus;
+  int Generated_Frequency_Modulus;
+  int Reanneal_Cost;
+  int Reanneal_Parameters;
+
+  double Delta_X;
+#if DELTA_PARAMETERS
+  double *User_Delta_Parameter;
+#endif
+  int User_Tangents;
+  int Curvature_0;
+
+#if QUENCH_PARAMETERS
+  double *User_Quench_Param_Scale;
+#endif
+#if QUENCH_COST
+  double *User_Quench_Cost_Scale;
+#endif
+
+  LONG_INT N_Accepted;
+  LONG_INT N_Generated;
+  int Locate_Cost;
+  int Immediate_Exit;
+
+  double *Best_Cost;
+  double *Best_Parameters;
+  double *Last_Cost;
+  double *Last_Parameters;
+
+#if OPTIONAL_DATA_DBL
+  ALLOC_INT Asa_Data_Dim_Dbl;
+  double *Asa_Data_Dbl;
+#endif
+#if OPTIONAL_DATA_INT
+  ALLOC_INT Asa_Data_Dim_Int;
+  LONG_INT *Asa_Data_Int;
+#endif
+#if OPTIONAL_DATA_PTR
+  ALLOC_INT Asa_Data_Dim_Ptr;
+  OPTIONAL_PTR_TYPE *Asa_Data_Ptr;
+#endif
+#if USER_ASA_OUT
+  char *Asa_Out_File;
+#endif
+#if USER_COST_SCHEDULE
+  double (*Cost_Schedule) ();
+#endif
+#if USER_ACCEPT_ASYMP_EXP
+  double Asymp_Exp_Param;
+#endif
+#if USER_ACCEPTANCE_TEST
+  void (*Acceptance_Test) ();
+  int User_Acceptance_Flag;
+  int Cost_Acceptance_Flag;
+  double Cost_Temp_Curr;
+  double Cost_Temp_Init;
+  double Cost_Temp_Scale;
+  double Prob_Bias;
+  LONG_INT *Random_Seed;
+#endif
+#if USER_GENERATING_FUNCTION
+  double (*Generating_Distrib) ();
+#endif
+#if USER_REANNEAL_COST
+  int (*Reanneal_Cost_Function) ();
+#endif
+#if USER_REANNEAL_PARAMETERS
+  double (*Reanneal_Params_Function) ();
+#endif
+#if ASA_SAMPLE
+  double Bias_Acceptance;
+  double *Bias_Generated;
+  double Average_Weights;
+  double Limit_Weights;
+#endif
+#if ASA_QUEUE
+  ALLOC_INT Queue_Size;
+  double *Queue_Resolution;
+#endif
+#if ASA_RESOLUTION
+  double *Coarse_Resolution;
+#endif
+#if FITLOC
+  int Fit_Local;
+  int Iter_Max;
+  double Penalty;
+#endif
+#if MULTI_MIN
+  int Multi_Number;
+  double *Multi_Cost;
+  double **Multi_Params;
+  double *Multi_Grid;
+  int Multi_Specify;
+#endif
+#if ASA_PARALLEL
+  int Gener_Mov_Avr;
+  LONG_INT Gener_Block;
+  LONG_INT Gener_Block_Max;
+#endif
+  int Asa_Recursive_Level;
+} USER_DEFINES;
+
+ /* system function prototypes */
+
+#if HAVE_ANSI
+
+/* This block gives trouble under some Ultrix */
+#if FALSE
+int fprintf (FILE * fp, const char *string, ...);
+int sprintf (char *s, const char *format, ...);
+FILE *popen (const char *command, const char *mode);
+void exit (int code);
+#endif
+
+#if IO_PROTOTYPES
+int fprintf ();
+int sprintf ();
+int fflush (FILE * fp);
+int fclose (FILE * fp);
+void exit ();
+int fread ();
+int fwrite ();
+int pclose ();
+#endif
+
+double
+  asa (double (*user_cost_function)
+
+        
+       (double *, double *, double *, double *, double *, ALLOC_INT *, int *,
+        int *, int *, USER_DEFINES *),
+       double (*user_random_generator) (LONG_INT *), LONG_INT * rand_seed,
+       double *parameter_initial_final, double *parameter_minimum,
+       double *parameter_maximum, double *tangents, double *curvature,
+       ALLOC_INT * number_parameters, int *parameter_type,
+       int *valid_state_generated_flag, int *exit_status,
+       USER_DEFINES * OPTIONS);
+
+#if TIME_CALC
+void print_time (char *message, FILE * ptr_out);
+#endif
+
+#if FDLIBM_POW
+double s_pow (double x, double y);
+#endif
+#if FDLIBM_LOG
+double s_log (double x);
+#endif
+#if FDLIBM_EXP
+double s_exp (double x);
+#endif
+
+#else /* HAVE_ANSI */
+
+#if IO_PROTOTYPES
+int fprintf ();
+int sprintf ();
+int fflush ();
+int fclose ();
+int fread ();
+int fwrite ();
+FILE *popen ();
+int pclose ();
+#endif
+
+double asa ();
+
+#if TIME_CALC
+void print_time ();
+#endif
+
+#if FDLIBM_POW
+double s_pow ();
+#endif
+#if FDLIBM_LOG
+double s_log ();
+#endif
+#if FDLIBM_EXP
+double s_exp ();
+#endif
+
+#endif /* HAVE_ANSI */
+
+#endif /* _ASA_USER_ASA_H_ */
