big refactoring for function gradient