Ah! Well, thank you for pointing it out. That is why I asked for feedback on the benchmarks.
I ran more accurate ones and, sure enough, they show a thousand-fold increase... Plus contrary to my comments about convergent series, you now see a polynomial rate of growth same as space over the length of the series (although keep in mind these are ratios peppered with BigInts when they reduce, so purposefully not the fastest choice):
power-series.core=> (bench (into [] (take 10 (cosine-series))))
Evaluation count : 1574520 in 60 samples of 26242 calls.
Execution time mean : 38.838738 µs
Execution time std-deviation : 445.092552 ns
Execution time lower quantile : 38.240002 µs ( 2.5%)
Execution time upper quantile : 39.891957 µs (97.5%)
Overhead used : 12.286567 ns
Found 2 outliers in 60 samples (3.3333 %)
low-severe 2 (3.3333 %)
Variance from outliers : 1.6389 % Variance is slightly inflated by outliers
power-series.core=> (bench (into [] (take 1000 (cosine-series))))
Evaluation count : 60 in 60 samples of 1 calls.
Execution time mean : 1.869831 sec
Execution time std-deviation : 19.002563 ms
Execution time lower quantile : 1.843601 sec ( 2.5%)
Execution time upper quantile : 1.918796 sec (97.5%)
Overhead used : 12.286567 ns
Found 4 outliers in 60 samples (6.6667 %)
low-severe 4 (6.6667 %)
Variance from outliers : 1.6389 % Variance is slightly inflated by outlier
Now, exuberance aside... Storing one million values in a vector isn't a suitable application for lazy evaluation. It's what Clojure vectors were made for. What you suggested, trying to retrieve a single value located very deep into the dataset is a much better test:
power-series.core=> (bench (conj [] (take-nth 1000 (cosine-series))))
Evaluation count : 683765640 in 60 samples of 11396094 calls.
Execution time mean : 75.009083 ns
Execution time std-deviation : 0.959064 ns
Execution time lower quantile : 73.493562 ns ( 2.5%)
Execution time upper quantile : 76.835144 ns (97.5%)
Overhead used : 12.286567 ns
Found 2 outliers in 60 samples (3.3333 %)
low-severe 1 (1.6667 %)
low-mild 1 (1.6667 %)
Variance from outliers : 1.6389 % Variance is slightly inflated by outliers
power-series.core=> (bench (conj [] (take-nth 1000000 (cosine-series))))
Evaluation count : 693054420 in 60 samples of 11550907 calls.
Execution time mean : 74.754414 ns
Execution time std-deviation : 1.375869 ns
Execution time lower quantile : 73.148560 ns ( 2.5%)
Execution time upper quantile : 78.131448 ns (97.5%)
Overhead used : 12.286567 ns
Found 4 outliers in 60 samples (6.6667 %)
low-severe 3 (5.0000 %)
low-mild 1 (1.6667 %)
Variance from outliers : 7.7995 % Variance is slightly inflated by outliers
power-series.core=> (bench (conj [] (take-nth 1000000000 (cosine-series))))
Evaluation count : 685621980 in 60 samples of 11427033 calls.
Execution time mean : 75.855787 ns
Execution time std-deviation : 0.994341 ns
Execution time lower quantile : 74.524899 ns ( 2.5%)
Execution time upper quantile : 77.558569 ns (97.5%)
Overhead used : 12.286567 ns
Found 1 outliers in 60 samples (1.6667 %)
low-severe 1 (1.6667 %)
Variance from outliers : 1.6389 % Variance is slightly inflated by outliers
There you go. ~75ns constant-time retrieval for one element up to one billion deep (didn't both trying to go further). Those results seem pretty damn good so please do let me know if my methodology could still be flawed.
And in addition to running all new benchmarks I'm going to have to rethink how to discuss this disparity on the repo, so please give me about a day for that.
Sophia