I'm a big fan of Chop
. It's fast and useful in pre-rounding transforms and things
Unfortunately it also necessarily unpacks a real PackedArray
(it's rounding approximate 0
to true integer 0
). It does that even when it doesn't actually have to:
bigList =
BlockRandom[SeedRandom[1]; RandomReal[{}, {1000, 1000}]];
Developer`PackedArrayQ@bigList
True
Chop[bigList] === bigList
True
Chop[bigList] // Developer`PackedArrayQ
False
And, of course, it unpacks when it has to:
Chop[bigList, 10^-5] == bigList
False
Chop[bigList, 10^-5] // Developer`PackedArrayQ
False
Is there any built-in packed Chop
?
I could of course implement an array chop like:
packChop =
Compile[
{
{arr, _Real, 2},
{tol, _Real}
},
Map[
If[Abs[#] < tol, 0., #] &,
arr,
{2}
],
RuntimeOptions -> "Speed"
]
packChop[bigList, 10^-$MachinePrecision] // Developer`PackedArrayQ
True
packChop[bigList, 10^-$MachinePrecision] // RepeatedTiming // First
0.071
Or just do it in top-level code:
chop[a_, t_] :=
With[{r = N@t},
Map[
If[Abs[#] < r, 0., #] &,
bigList,
{2}
]
]
chop[bigList, 10^-$MachinePrecision] // Developer`PackedArrayQ
True
chop[bigList, 10^-$MachinePrecision] // RepeatedTiming // First
0.085
But it's always nice to use the built-ins (even if unpacking makes them slow):
uBigList = bigList;
uBigList[[1, 1]] = 1;
Chop@bigList // RepeatedTiming // First
0.089
Chop@uBigList // RepeatedTiming // First
0.033
Threshold
... $\endgroup$