-
Notifications
You must be signed in to change notification settings - Fork 264
Description
A little while ago I was experimenting with a faster definition for Data.Nat.Base._^_. When I came to actually time my code, however, I couldn't see any difference between the execution time. I profiled, and execution was absolutely dominated by show (as I was printing the results to ensure they were forced).
Data.Nat.Show.show is defined using Data.Digit.toNatDigits, which in turn uses repeated division by the base. This is quadratic in the number of digits, and slow for huge numbers in practice.
I compared how GHC implements show for Integer, which seemed to be much faster, and was surprised by how complex the implementation is. Disregarding details concerning sign and precedence, which isn't relevant to us here, it uses a divide-and-conquer method to split the number into 10^k sized blocks, with k chosen as large as possible such that 10^k is less than machine word size (with, presumably, faster division). These blocks are then converted to strings using repeated division and concatenated.
Would such an approach work for us, and would it be faster?