Plan 9 from Bell Labs’s /usr/web/sources/contrib/fernan/nhc98/tests/nofib/real/fluid/Chl_method.hs
{- The third part of the Choleski decomposition. Contains forward, backward substitution and their driver. XZ, 24/10/91 -} {- Modified to employ S_array. (Forward and backward substitution functions have been recoded.) XZ, 7/2/92 -} module Chl_method ( chl_method ) where import Defs import S_Array -- not needed w/ proper module handling import Norm -- ditto import Asb_routs import Ix--1.3 infix 1 =: (=:) a b = (a,b) ----------------------------------------------------------- -- Forward substitution for the Choleski method. Called -- -- in "chl_method". -- ----------------------------------------------------------- lower_part u off_diag = dropWhile (\(i,_)->i<=u) (sparse_assocs off_diag) -- forward substitution fwd_sbs chl_fac b_old = s_listArray (s_bounds b_old) (gen_x (1::Int) b_old []) where b_up = snd (s_bounds chl_fac) -- generate solution gen_x blck b x = if blck > b_up then x else gen_x (blck+1) new_b (x++new_x) where diag = fst this_block off_diag = snd this_block this_block = chl_fac!^blck block_bounds = s_bounds diag (l,u) = block_bounds new_x = gen_block_x (l+1) [(b!^l)/(diag!^l)] -- update RHS new_b = s_accum (-) b [ k =: list_inner_prod (drop (j-l) new_x) vs | (k,(j,vs)) <- lower_part u off_diag ] -- generate solution for one block gen_block_x i x_res = if i>u then x_res else gen_block_x (i+1) ( x_res ++ [ ((b!^i)-list_inner_prod (drop (j-l) x_res) vs)/(diag!^i) ] ) where (j,vs) = off_diag!^i ----------------------------------------------------------- -- Backward substitution for the Choleski method. -- -- It works in a column by column manner. -- -- Called in "chl_methold". -- ----------------------------------------------------------- -- backward substitution bwd_sbs chl_fac y = gen_x b_up ((s_array (s_bounds y) [])::(My_Array Int Frac_type)) where b_up = snd (s_bounds chl_fac) -- generate solution gen_x blck x_res = if blck < (1::Int) then x_res else gen_x (blck-1) new_x where diag = fst this_block off_diag = snd this_block this_block = chl_fac!^blck block_bounds = s_bounds diag (l,u) = block_bounds new_x = gen_block_x u new_b x_res -- update RHS new_b = s_accum (-) (s_listArray block_bounds [y!^i|i<-range block_bounds]) ( concat [ zipWith (\l v->l=:v) (range (j,u)) (map ((*) (x_res!^k)) vs) | (k,(j,vs)) <- lower_part u off_diag ] ) -- generate solution for one block gen_block_x i b x_res1 = if i<l then x_res1 else gen_block_x (i-1) new_b1 (x_res1//^[i=:new_x]) where new_x = (b!^i) / (diag!^i) (j,vs) = off_diag!^i new_b1 = s_accum (-) b (zipWith (\l v->l=:v) (range (j,i-1)) (map ((*) new_x) vs)) ----------------------------------------------------------- -- The driving function for the Choleski method. -- -- Because the used generalized envelope mathod reorders -- -- the system matrix, the right-hand-side and result are -- -- also reordered to match the internal and external -- -- forms. -- -- Called in the TG iteration. -- -- Calls "fwd_sbs" and "bwd_sbs" -- ----------------------------------------------------------- chl_method (chl_fac,o_to_n) b scalor = -- parameters: (Choleski_factor,ordering) right_hand_side -- constant_in_front_of_the_system s_amap ((*) scalor) (s_ixmap bnds ((!^) o_to_n) x) where x = bwd_sbs chl_fac (fwd_sbs chl_fac new_b) new_b = s_array bnds (map (\(i,v)->(o_to_n!^i)=:v) (s_assocs b)) bnds = s_bounds b