uses memoization to allow products overloading