summaryrefslogtreecommitdiff
path: root/testsuite/tests/llvm/should_compile/T5054_2.hs
blob: 29a7ed829fdb2c20e618caa31835d8fbba3f6783 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# OPTIONS_GHC -W #-}

import Data.Int
import Data.Packed
import Data.Packed.ST
import Control.Applicative
import Control.Monad
import Control.Monad.ST
import Foreign.Storable
import Foreign.Ptr
import Foreign.Marshal.Utils

import Control.Parallel.Strategies

import Graphics.Plot


main :: IO ()
main = let whee = jacobiST zeroRho (0, 1) (constLeftBorder 100 128)
       in writeFile "Something.pgm" $ matrixToPGM (computeElementMatrixToDouble whee)

inParallel = parMap rwhnf id

zeroMatrix m n = buildMatrix m n (const 0)

twoMatrix m n = buildMatrix m n (const (Value 2))

data ComputeElement = Constant !Double
                    | Value !Double
                    deriving (Eq)

-- We don't care about showing if it's constant or not
instance Show ComputeElement where
  show (Constant v) = show v
  show (Value v) = show v

instance Element ComputeElement

isConstant (Constant _) = True
isConstant _            = False

fromComputeElement (Constant v) = v
fromComputeElement (Value    v) = v

sizeofDouble = sizeOf (undefined :: Double)
sizeofInt64  = sizeOf (undefined :: Int64)

instance Storable ComputeElement where
  sizeOf _ = sizeofDouble + sizeofInt64
  alignment _ = 16

  peek p = do v <- peek (castPtr p)
              c <- peek (castPtr (p `plusPtr` sizeofDouble))
              return $ if toBool (c :: Int64)
                         then Constant v
                         else Value v

  poke p v = do let c :: Int64
                    c = fromBool (isConstant v)
                poke (castPtr p) (fromComputeElement v)
                poke (castPtr p `plusPtr` sizeofDouble) c

jacobi :: Element a => Int -> Matrix a -> Matrix a
jacobi n mat = undefined
  where
    core = subMatrix (1, 1) (rows mat - 1, cols mat - 1) mat

applyComputeElement _ v@(Constant _) = v
applyComputeElement f   (Value    v) = Value (f v)


writeMatrix' = uncurry . writeMatrix
readMatrix'  = uncurry . readMatrix

zeroRho _ _ = 0

type STComputeMatrix s = STMatrix s ComputeElement

type RelaxationFunction s =  STComputeMatrix s    -- initial matrix
                          -> STComputeMatrix s -- new matrix
                          -> Int               -- i
                          -> Int               -- j
                          -> ST s Double       -- new element

applyMethod :: RelaxationFunction s -> STComputeMatrix s -> STComputeMatrix s -> Int -> Int -> ST s ()
applyMethod f mat mat' i j = do
  c <- readMatrix mat i j
  u <- f mat mat' i j
  writeMatrix mat' i j $ if isConstant c
                           then c
                           else Value u

{-# INLINE readElement #-}
readElement mat x y = fromComputeElement <$> readMatrix mat x y

jacobiST :: (Double -> Double -> Double) -> (Double, Double) -> Matrix ComputeElement -> Matrix ComputeElement
jacobiST rho (rangeX, rangeY) origMat = runST $ do
  let m = rows origMat
      n = cols origMat

      dx = rangeX / fromIntegral (m - 1)
      dy = rangeY / fromIntegral (n - 1)
      dd = dx * dy

      rs = [1 .. (m - 2)] -- without borders
      cs = [1 .. (n - 2)]

      evalRho i j = rho (fromIntegral i * dx) (fromIntegral j * dy)

      gaussSeidel f mat mat' i j = do
        -- Read from old matrix
        a1 <- readElement mat (i + 1) j
        a2 <- readElement mat i       (j + 1)

        -- Read from new matrix
        b1 <- readElement mat' (i - 1) j
        b2 <- readElement mat' i       (j - 1)
        let f = evalRho i j
            u = 0.25 * (a1 + a2 + b1 + b2) + (pi * f * dd)
        return u


      jacobi mat mat' i j = do
        a <- readElement mat (i + 1) j
        b <- readElement mat (i - 1) j
        c <- readElement mat i       (j + 1)
        d <- readElement mat i       (j - 1)

        let f = evalRho i j
            u = 0.25 * (a + b + c + d) + (pi * f * dd)
        return u

      jacobiThings = applyMethod jacobi

      --iterateJacobi mat mat' = sequence_ [jacobiThings mat mat' r c | r <- rs, c <- cs]

      -- faster
      iterateJacobi mat mat' = sequence_ $ map (uncurry (jacobiThings mat mat')) [(r, c) | r <- rs, c <- cs]

      -- Swap the matrices. Iterations will be an event number, 2 * n
      iterateNJacobi n mat mat' = replicateM n (iterateJacobi mat mat' >> iterateJacobi mat' mat)

  mat  <- thawMatrix origMat
  mat' <- thawMatrix origMat

  iterateNJacobi 4000 mat mat'

  freezeMatrix mat'

constLeftBorder v n = fromColumns (border:replicate (n - 1) rest)
  where border = buildVector n (const (Constant v))
        rest = buildVector n (const (Value 0))

computeElementMatrixToDouble :: Matrix ComputeElement -> Matrix Double
computeElementMatrixToDouble = liftMatrix (mapVector fromComputeElement)