full impl of HMM