open Lacaml.D open Util type t = { p : Vec.t list; e : Vec.t list; m : int; mmax : int; } let make ?mmax:(mmax=15) () = assert (mmax > 1); { p = []; e = []; m = 0 ; mmax; } let append ~p ~e diis = let update v l = if diis.m < diis.mmax then v :: l else match List.rev l with | [] -> assert false | _ :: rest -> v :: List.rev rest in { diis with p = update p diis.p; e = update e diis.e; m = min diis.mmax (diis.m+1); } let next diis = let e = Mat.of_col_vecs_list diis.e and p = Mat.of_col_vecs_list diis.p in let a = let rec aux m = let a = Mat.make (m+1) (m+1) 1. in a.{m+1,m+1} <- 0.; ignore @@ lacpy ~b:a (gemm ~transa:`T ~m ~n:m e e); if m > 1 && sycon (lacpy a) > 1.e-14 then (aux [@tailcall]) (m-1) else a in aux diis.m in let m = Mat.dim1 a - 1 in let c = Mat.make0 (m+1) 1 in c.{m+1,1} <- 1.; sysv a c; gemm p c ~k:m |> Mat.as_vec