9

I was going to post an answer for fast way to replace all zeros in the matrix. I was even quite happy because timings were the same order of magnitude as others.

The idea was to overwrite Identity:

Internal`InheritedBlock[{Identity}, Unprotect[Identity]; Identity[0] = 1; 

   Map[Identity, {{2, 0}, {Pi, 9}}, {2}]]
{{2, 1}, {Pi, 9}}

But I've checked that for bigger matrices the result is not even close to the expected one:

Internal`InheritedBlock[{Identity}, Unprotect[Identity]; Identity[0] = 1; 

   m = RandomInteger[1, {100, 2}]; 
   Map[Identity, m, {2}] ~ Shallow ~ {5, 2}]
{{0, 1}, {1, 0}, <<98>>}

It seem it breaks at size of the array of about $90$ positions:

 test = Internal`InheritedBlock[{Identity}, Unprotect[Identity]; Identity[0] = 1;

         Apply[
          Boole[Map[Identity, RandomInteger[1, {##}], {2}] == ConstantArray[1, {##}]
               ]&,                     
          Array[List, {35, 35}],
          {2}]];

Show[MatrixPlot[test, DataReversed -> True, Mesh -> All],
     ContourPlot[x y == 90, {x, 1, 35}, {y, 1, 35}]
     , BaseStyle -> {Thickness@.01, 18}]

enter image description here


I hope I haven't missed anything obvious. Any ideas?

Kuba
  • 136,707
  • 13
  • 279
  • 740
  • 8
    Perhaps that's when Map starts compiling – ssch Oct 24 '13 at 21:25
  • 1
    I fiddled with SystemOptions["CompileOptions" -> "MapCompileLength"] and the plot changed, but now even after restarting the kernel I can't reproduce the original plot. Strange indeed :) – ssch Oct 24 '13 at 21:33
  • @ssch I must admit I have not done much compiling in MMA, so could you explain, even if it is so, why Map does not care about overwritten definition? – Kuba Oct 24 '13 at 21:35
  • 2
    I can only speculate, I guess that the compiler sees Identity and assumes it knows how that behaves, not looking for changed definition. – ssch Oct 24 '13 at 21:37
  • @ssch I see, I think I saw here similar question about Sin behaviour is some circumstances, but I can recall it. – Kuba Oct 24 '13 at 21:39
  • 3
    Map auto-compiles, basically applying Compile to your mapped function. Of course, Compile uses its own versions for compilable functions, so whatever top-level definitions you have made won't fire. – Leonid Shifrin Oct 24 '13 at 21:56
  • @LeonidShifrin so.. is anybody going to answer? :) or is it duplicate/simple mistake? – Kuba Oct 25 '13 at 10:18

1 Answers1

4

I think this is related to my own question Block attributes of Equal though the circumstance is different. As already stated in the comments:

I can only speculate, I guess that the compiler sees Identity and assumes it knows how that behaves, not looking for changed definition. – ssch Oct 24 '13 at 21:37

Map auto-compiles, basically applying Compile to your mapped function. Of course, Compile uses its own versions for compilable functions, so whatever top-level definitions you have made won't fire. – Leonid Shifrin Oct 24 '13 at 21:56

Whether it be by auto-compilation or by special optimization for Packed Arrays, one must accept that top-level definitions and attributes may not be used in some cases.

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371