From b45239f3dfaac39856e2aafc082d6704565392e5 Mon Sep 17 00:00:00 2001 From: fkaelberer Date: Thu, 28 Aug 2014 13:21:19 +0200 Subject: [PATCH] Differential cmap compression code --- external/bcmaps_temp/savings.json | 1 + external/cmapscompress/README.md | 51 +- external/cmapscompress/compress.js | 384 ++++---- external/cmapscompress/differentialStorage.js | 844 ++++++++++++++++++ make.js | 19 +- src/core/cmap.js | 58 +- 6 files changed, 1171 insertions(+), 186 deletions(-) create mode 100644 external/bcmaps_temp/savings.json create mode 100644 external/cmapscompress/differentialStorage.js diff --git a/external/bcmaps_temp/savings.json b/external/bcmaps_temp/savings.json new file mode 100644 index 00000000000000..deb06b96ccc78e --- /dev/null +++ b/external/bcmaps_temp/savings.json @@ -0,0 +1 @@ +[[0,70,2065,1251,70,70,1240,70,88,87,70,85,70,85,69,818,566,69,69,73,72,73,72,72,72,72,63,73,73,73,72,73,73,56,73,73,73,73,73,73,73,62,73,73,73,66,78,70,77,70,81,77,73,70,73,69,78,70,78,70,74,70,163,70,1913,1194,70,70,86,69,76,69,70,69,79,70,71,69,81,69,71,69,78,69,83,69,128,77,70,78,70,77,70,76,70,76,70,78,70,78,77,81,69,70,73,69,69,78,78,69,69,75,69,77,1909,69,95,70,81,60,70,57,70,68,70,75,70,73,69,65,70,63,69,72,70,71,73,68,68,76,68,75,67,62,69,76,68,75,67,67,69,68,68,69,74,67,74,67,66,70,61,70,60,70,69,71,70,77],[69,0,69,69,125,138,69,120,68,69,120,69,120,115,124,69,69,101,101,69,69,69,69,69,69,69,67,69,69,69,69,69,69,65,69,69,69,69,69,69,69,66,69,69,69,68,68,75,68,75,69,73,69,75,69,74,75,75,68,75,70,75,69,156,68,69,108,117,69,80,69,75,66,79,75,75,66,79,68,79,68,75,68,79,69,79,69,68,75,68,75,70,75,68,75,67,75,75,75,70,69,69,79,69,67,75,76,69,69,75,76,69,79,69,68,117,69,125,69,70,75,73,75,78,75,73,75,71,75,74,75,74,75,74,75,72,70,105,105,73,103,73,103,73,95,74,103,73,103,73,95,105,105,95,72,103,72,103,69,75,79,76,79,76,77,76,137,70],[2069,74,0,1239,74,74,1234,73,85,81,73,81,73,82,72,916,554,72,72,79,78,79,78,78,78,78,67,79,79,79,78,79,79,61,79,79,79,79,79,79,79,67,79,79,79,70,74,74,74,74,75,71,85,74,85,73,74,74,74,74,77,74,132,74,2155,1182,73,73,80,73,88,73,67,73,74,72,67,73,75,73,83,73,75,73,80,73,142,73,74,74,74,73,74,72,74,72,74,74,74,78,77,74,73,82,67,73,73,74,74,73,73,74,73,77,2154,72,83,74,77,67,74,65,74,75,74,65,74,78,73,67,74,65,73,66,74,78,77,72,72,82,73,79,72,61,71,82,73,79,72,66,71,72,72,72,79,72,79,72,72,74,68,74,65,74,66,74,74,77],[1250,69,1234,0,69,69,2360,69,148,153,69,151,69,149,68,534,874,68,68,71,71,71,71,70,70,70,63,71,71,70,70,71,71,59,71,71,71,71,71,71,71,60,71,71,71,63,79,69,78,69,76,72,70,69,72,68,77,69,79,69,73,69,97,69,1188,2088,69,69,79,68,71,68,70,68,71,69,71,68,78,68,69,68,78,68,79,68,81,77,69,79,69,79,69,76,69,78,69,77,69,76,75,79,68,70,72,68,68,80,80,68,68,75,68,75,1188,67,161,69,80,60,69,54,69,67,69,74,69,68,68,66,68,70,68,72,68,66,71,66,67,72,67,62,63,64,68,72,67,64,63,65,68,66,67,68,57,63,60,63,63,69,61,69,61,69,72,70,69,77],[68,124,68,68,0,124,68,139,67,68,139,68,139,129,155,68,68,123,110,68,68,68,68,68,68,68,67,68,68,68,68,68,68,63,68,68,68,68,68,68,68,66,68,68,68,66,68,74,68,74,68,72,68,74,68,73,74,75,68,75,70,74,68,124,68,68,124,95,68,74,68,74,66,75,74,75,66,74,67,75,67,74,67,74,68,74,68,67,74,68,74,69,74,68,74,67,74,74,74,69,68,68,75,68,62,74,74,68,68,74,74,68,74,68,68,95,68,155,68,70,74,72,74,77,74,72,74,70,74,73,74,73,74,73,74,70,69,99,99,71,98,71,98,71,85,72,98,71,98,71,85,99,99,84,70,98,70,98,66,74,78,75,78,75,76,75,123,69],[73,142,73,73,129,0,73,124,72,73,124,73,124,119,128,73,73,105,109,73,73,73,73,73,73,73,71,73,73,73,73,73,73,69,73,73,73,73,73,73,73,70,73,73,73,72,72,80,72,79,73,77,73,79,73,78,79,79,72,79,74,79,73,142,72,73,112,125,73,79,73,80,70,79,79,79,70,79,72,79,72,79,72,79,73,79,73,72,79,72,79,74,79,72,79,71,79,79,79,74,73,73,79,73,71,79,79,73,73,79,79,73,79,73,72,125,73,129,73,74,79,77,79,82,79,77,79,75,79,78,79,78,79,78,79,76,74,108,108,77,107,77,107,77,99,78,107,77,107,77,99,108,108,100,76,107,76,107,73,79,83,80,83,80,81,80,156,74],[1237,67,1227,2358,67,67,0,69,212,412,69,397,69,211,66,581,928,66,66,69,69,69,68,68,68,68,61,69,69,68,68,69,69,55,69,69,69,69,69,69,69,61,69,69,69,92,77,66,77,66,72,68,68,67,70,66,73,67,77,67,70,67,138,67,1195,2119,67,67,78,66,70,66,65,66,71,67,65,66,75,66,67,66,75,66,77,66,128,75,66,77,66,77,66,76,66,76,66,73,67,76,73,76,66,68,67,66,66,77,77,66,66,73,66,73,1201,66,218,67,74,55,67,52,67,61,67,60,67,66,66,64,66,68,66,72,66,61,71,66,65,70,64,60,63,57,65,70,64,61,63,56,65,66,65,65,54,63,56,63,62,67,58,67,58,67,62,68,67,74],[66,118,66,66,138,118,68,0,68,68,271,68,268,121,147,66,68,121,108,66,66,66,66,66,66,66,65,66,66,66,66,65,65,61,66,66,66,66,66,66,66,63,66,66,66,64,65,72,65,72,66,70,66,72,66,71,72,72,65,72,67,73,66,118,66,64,126,108,66,72,66,72,65,72,72,72,65,72,64,72,64,72,64,73,66,72,66,65,72,65,72,67,73,65,73,65,73,72,72,67,66,65,72,65,65,73,72,64,64,72,73,65,73,66,65,107,68,137,66,68,72,69,72,72,72,70,72,68,72,71,72,71,72,71,72,65,67,99,99,74,96,74,96,72,83,74,96,74,96,72,83,99,99,84,74,96,74,96,64,72,75,73,75,73,72,73,118,67],[84,67,77,149,67,67,212,69,0,466,69,468,69,507,66,127,200,66,66,69,69,69,69,69,69,69,65,70,69,69,69,69,69,61,69,69,69,69,69,69,69,61,69,69,69,91,76,67,88,67,74,70,68,67,70,66,77,67,76,67,71,67,133,67,115,209,71,67,78,66,70,66,74,66,73,67,76,66,77,66,69,66,89,66,90,66,126,78,67,77,67,76,67,76,67,75,67,77,67,76,73,76,66,68,76,66,66,79,77,66,66,79,66,75,120,68,485,67,74,63,67,61,67,64,67,70,66,65,67,66,67,65,67,71,67,68,70,64,64,71,63,69,63,72,64,71,63,69,63,72,64,64,64,65,69,63,69,63,68,67,66,67,65,67,70,68,67,75],[84,67,74,151,67,67,412,69,466,0,69,692,69,469,66,133,210,66,66,70,70,70,69,70,70,70,65,70,70,70,70,70,70,60,70,70,70,70,70,70,70,61,70,70,70,92,77,67,77,67,76,72,70,67,70,66,78,67,77,67,70,67,137,67,88,187,67,67,78,67,70,67,76,67,73,67,76,67,75,67,67,67,75,67,78,67,127,76,67,77,67,77,67,77,67,77,67,78,67,76,74,76,67,68,72,67,67,77,77,67,67,73,67,73,94,67,491,67,73,64,67,65,67,65,67,67,67,66,67,68,67,68,67,72,67,65,71,65,63,70,64,69,64,71,65,70,64,69,64,71,65,65,63,65,67,64,67,64,63,67,64,67,64,67,68,68,67,74],[66,118,66,66,138,118,68,271,68,68,0,68,269,121,149,66,68,121,108,66,66,66,66,66,66,66,65,66,66,66,66,65,65,61,66,66,66,66,66,66,66,63,66,66,66,64,65,72,65,72,66,70,66,72,66,71,72,72,65,72,67,73,66,118,66,64,126,108,66,72,66,72,65,72,72,72,65,72,64,72,64,72,64,73,66,72,66,65,72,65,72,67,73,65,73,65,73,72,72,67,66,65,72,65,65,73,72,64,64,72,73,65,73,66,65,107,68,137,66,68,72,69,72,72,72,70,72,68,72,71,72,71,72,71,72,65,67,99,99,74,96,74,96,72,83,74,96,74,96,72,83,99,99,84,74,96,74,96,64,72,75,73,75,73,72,73,118,67],[81,66,73,148,66,66,396,68,467,691,68,0,68,470,65,132,207,65,65,69,69,69,68,69,69,69,64,69,69,69,69,69,69,59,69,69,69,69,69,69,69,60,69,69,69,91,78,66,79,66,76,72,69,66,69,65,80,66,78,66,72,66,134,66,87,184,66,66,77,66,69,66,76,66,74,66,84,66,74,66,66,66,76,66,79,66,126,83,66,83,66,82,66,84,66,84,66,80,66,74,73,76,66,67,79,66,66,83,77,66,66,74,66,72,93,66,488,66,74,63,66,64,66,65,66,72,66,65,66,67,66,67,66,75,66,64,69,62,62,69,63,68,63,70,64,69,63,68,63,70,64,62,62,64,67,63,66,63,62,66,65,66,63,66,73,67,66,73],[65,117,65,65,137,117,67,267,67,67,268,67,0,120,145,65,67,120,107,65,65,65,65,65,65,65,64,65,65,65,65,64,64,60,65,65,65,65,65,65,65,62,65,65,65,63,64,71,64,71,65,69,65,71,65,70,71,71,64,71,66,71,65,117,65,63,125,107,65,71,65,71,64,71,71,71,64,71,63,71,63,71,63,71,65,71,65,64,71,64,71,66,71,64,71,64,71,71,71,66,65,64,71,64,64,71,71,63,63,71,71,64,71,65,64,106,67,136,65,67,71,68,71,71,71,69,71,67,72,70,71,70,71,70,72,64,66,98,98,73,95,73,95,71,82,73,95,73,95,71,82,98,98,83,73,95,73,95,63,72,74,72,74,72,71,73,117,66],[80,113,73,147,128,113,212,121,507,469,121,471,121,0,127,125,206,107,100,69,69,69,69,69,69,69,63,70,69,69,68,69,69,60,70,70,69,69,69,69,69,61,69,69,69,93,75,67,88,67,76,72,70,67,70,66,82,66,75,66,71,67,132,113,73,142,108,85,78,66,70,66,80,66,80,67,82,66,74,66,67,66,86,66,90,66,125,77,67,77,67,80,67,78,67,76,67,82,66,74,74,75,68,67,76,68,68,78,76,68,68,78,68,73,90,85,470,128,74,71,67,73,67,69,66,78,67,71,65,73,66,73,66,78,66,66,70,90,90,69,90,69,90,73,77,70,90,69,90,73,77,90,90,76,67,90,67,90,64,66,77,67,76,67,79,68,113,75],[65,122,64,65,154,122,65,147,65,66,149,66,146,127,0,66,66,128,115,66,66,66,66,66,66,66,66,66,66,66,66,66,66,61,65,65,66,66,66,66,66,64,66,66,66,64,66,72,66,72,66,70,66,72,66,71,72,72,66,72,67,73,66,122,64,65,122,93,66,72,66,72,67,72,72,73,67,72,65,72,65,72,65,73,66,72,66,65,72,66,72,67,73,66,73,65,73,72,72,67,66,65,71,64,60,72,71,65,65,71,72,65,72,66,64,93,66,153,66,68,72,70,72,74,72,70,72,69,72,71,72,70,72,71,72,68,67,101,101,68,96,69,96,69,83,69,96,68,96,69,83,101,101,86,68,96,67,96,63,72,76,73,75,73,74,73,121,67],[822,72,916,540,72,72,589,71,134,139,71,139,71,131,72,0,1182,74,74,77,76,77,77,77,77,77,66,78,78,77,76,77,77,61,78,78,78,78,77,77,77,71,78,77,77,95,75,73,75,73,74,70,83,73,83,72,72,73,75,73,76,73,183,72,883,534,73,73,78,73,86,73,64,73,75,71,64,73,74,73,82,73,74,73,78,73,198,74,73,75,73,74,73,74,73,74,73,72,73,76,75,73,71,81,53,71,71,73,73,71,71,73,71,76,906,73,130,72,76,66,72,62,73,67,73,64,73,64,72,71,73,69,72,69,73,75,75,69,70,81,71,79,71,67,71,81,71,79,71,62,71,71,71,71,79,71,79,71,50,72,63,73,61,73,61,73,72,76],[566,68,550,874,68,68,930,70,208,212,70,210,70,208,66,1178,0,69,69,71,71,71,70,71,71,71,64,71,71,70,70,71,70,57,70,70,71,71,71,71,71,64,71,71,71,87,78,68,77,68,75,71,68,68,71,67,77,68,78,68,72,68,141,68,532,872,68,68,78,67,71,67,71,67,69,68,72,67,73,67,65,67,73,67,79,67,125,77,68,78,68,77,68,78,68,75,68,77,68,75,75,76,67,67,50,67,67,77,77,67,67,72,67,74,547,68,221,68,79,62,68,58,68,59,68,73,68,65,67,64,68,63,68,73,68,65,70,64,64,71,65,69,65,66,66,71,65,59,65,66,66,64,64,65,61,65,56,65,49,67,60,68,60,68,70,69,68,75],[66,100,66,66,123,100,66,122,67,67,122,67,122,108,128,70,70,0,215,67,67,67,67,67,67,67,65,67,67,67,67,67,67,63,66,66,67,66,67,67,67,64,66,67,67,65,67,73,67,73,67,71,67,73,67,72,72,73,67,73,68,73,67,100,66,66,131,106,67,73,67,73,66,73,73,73,66,74,65,73,65,73,65,73,67,74,67,66,74,67,74,68,73,67,73,66,73,72,74,68,67,66,73,65,61,73,73,66,66,73,73,66,73,67,66,106,67,122,67,68,73,68,73,73,73,68,73,67,73,71,73,68,73,71,73,68,68,88,88,69,97,69,97,69,83,70,97,68,97,69,83,88,88,84,68,97,67,97,64,73,76,74,75,74,74,74,100,68],[71,105,71,71,115,109,71,114,71,72,114,72,114,107,120,75,75,220,0,72,72,72,72,72,72,72,70,72,72,72,72,72,72,67,72,72,72,71,72,72,72,69,71,72,72,70,72,78,72,78,72,76,72,78,72,77,77,78,72,78,73,78,72,106,71,71,122,116,72,78,72,78,71,78,77,78,71,78,70,78,70,79,70,78,72,78,72,71,78,72,78,73,78,72,78,71,78,77,78,73,72,71,78,71,65,78,79,71,71,78,78,71,78,72,71,116,72,115,72,72,78,73,78,78,78,73,78,73,78,76,78,74,78,76,78,74,73,93,93,74,106,74,106,75,98,75,106,74,106,75,98,93,93,99,73,106,73,106,68,78,82,79,81,79,80,79,109,73],[69,66,71,68,66,66,68,65,68,69,65,69,65,69,65,70,69,65,65,0,291,291,291,291,291,291,62,192,224,290,290,290,290,71,199,200,207,216,291,291,290,65,215,291,291,69,68,66,69,66,69,65,71,66,71,65,69,66,68,66,69,66,69,66,71,67,65,65,69,66,71,66,66,66,65,65,66,66,69,66,71,66,69,66,69,66,71,68,66,68,66,68,66,68,66,67,66,69,66,70,69,69,66,71,67,66,66,69,69,66,66,69,66,69,71,65,69,66,69,68,66,71,66,67,66,66,66,68,67,71,67,67,67,66,67,69,69,65,65,71,65,67,64,66,65,71,65,67,64,67,65,65,65,65,67,64,67,64,70,66,73,66,68,66,63,66,66,70],[68,66,70,68,66,66,68,65,69,69,65,69,65,69,65,69,69,65,65,291,0,348,348,348,348,348,62,192,224,348,348,347,347,71,199,200,207,216,311,348,348,65,215,348,348,69,68,66,69,66,69,65,71,66,71,65,69,66,68,66,69,66,69,66,70,68,65,65,69,66,71,66,65,66,64,65,65,66,69,66,71,66,69,66,69,66,71,67,66,68,66,68,66,69,66,69,66,69,66,70,69,69,66,71,68,66,66,68,68,66,66,69,66,69,70,65,69,66,69,67,66,71,66,67,66,67,66,64,66,71,66,68,66,66,66,69,69,65,65,69,65,65,64,66,65,69,65,66,64,67,65,65,65,65,65,64,66,64,70,66,73,66,69,66,62,66,66,70],[69,66,71,68,66,66,68,65,69,69,65,69,65,69,65,70,69,65,65,291,349,0,349,349,349,349,62,192,224,349,349,348,348,71,199,200,207,216,311,349,349,65,215,349,349,69,68,66,69,66,69,65,71,66,71,65,69,66,68,66,69,66,69,66,71,68,65,65,69,66,71,66,64,66,64,65,64,66,69,66,71,66,69,66,69,66,71,67,66,68,66,68,66,68,66,67,66,69,66,70,69,69,66,71,69,66,66,69,69,66,66,69,66,69,71,65,69,66,69,70,66,69,66,65,66,67,66,68,66,71,66,67,66,65,66,70,69,65,65,69,65,65,64,66,65,69,65,65,64,66,65,65,65,65,65,64,65,64,70,66,73,66,69,66,61,66,66,70],[68,66,70,68,66,66,68,65,69,69,65,69,65,69,65,71,69,65,65,291,349,350,0,374,374,374,62,192,224,374,374,373,373,71,199,200,207,216,311,374,374,65,215,360,365,69,68,66,69,66,69,65,71,66,71,65,67,66,68,66,69,66,69,66,70,68,65,65,69,66,71,66,64,66,65,65,64,66,69,66,71,66,69,66,69,66,71,67,66,68,66,68,66,68,66,67,66,67,66,70,69,68,66,70,68,66,66,68,68,66,66,68,66,69,70,65,69,66,69,66,66,71,66,67,66,67,66,68,66,71,66,67,66,65,66,69,69,65,65,69,65,65,64,66,65,69,65,66,64,67,65,65,65,65,65,64,66,64,70,66,73,66,69,66,62,66,66,70],[68,66,70,67,66,66,67,65,69,69,65,69,65,68,65,70,69,65,65,291,349,350,375,0,386,386,63,192,224,378,378,377,377,71,199,200,207,216,311,378,378,65,215,360,365,69,68,66,69,66,69,65,71,66,71,65,69,66,68,66,69,66,69,66,70,67,65,65,69,66,71,66,65,66,64,65,65,66,69,66,71,66,69,66,69,66,71,67,66,68,66,68,66,68,66,67,66,69,66,70,69,69,66,71,68,66,66,69,69,66,66,69,66,69,70,65,69,66,69,66,66,71,66,67,66,67,66,68,66,71,66,68,66,64,66,69,69,65,65,69,65,66,64,66,65,69,65,65,64,67,65,65,65,65,66,64,65,64,70,66,73,66,69,66,62,66,66,70],[68,66,70,67,66,66,67,65,69,69,65,69,65,68,65,70,69,65,65,291,349,350,375,386,0,387,63,192,224,379,379,378,378,71,199,200,207,216,311,379,379,65,215,360,365,69,68,66,69,66,69,65,71,66,71,65,69,66,68,66,69,66,69,66,70,67,65,65,69,66,71,66,65,66,64,65,65,66,69,66,71,66,69,66,69,66,71,67,66,68,66,68,66,68,66,67,66,69,66,70,69,69,66,71,68,66,66,69,69,66,66,69,66,69,70,65,69,66,69,66,66,71,66,65,66,67,66,68,66,71,66,68,66,64,66,67,69,65,65,69,65,66,64,66,65,69,65,65,64,67,65,65,65,65,66,64,65,64,68,66,71,66,67,66,62,66,66,70],[68,66,70,67,66,66,67,65,69,69,65,69,65,68,65,70,69,65,65,291,349,350,375,386,387,0,63,192,224,379,379,378,378,71,199,200,207,216,311,379,379,65,215,360,365,69,68,66,69,66,69,65,71,66,71,65,69,66,68,66,69,66,69,66,70,67,65,65,69,66,71,66,65,66,64,65,65,66,69,66,71,66,69,66,69,66,71,67,66,68,66,68,66,68,66,67,66,69,66,70,69,69,66,71,68,66,66,69,69,66,66,69,66,69,70,65,69,66,69,66,66,71,66,67,66,67,66,68,66,71,66,68,66,64,66,67,69,65,65,69,65,66,64,66,65,69,65,65,64,67,65,65,65,65,66,64,65,64,70,66,73,66,69,66,62,66,66,70],[51,63,52,50,62,63,50,62,56,57,62,57,62,60,62,52,50,61,62,59,62,62,61,61,61,61,0,64,63,60,60,57,58,115,62,64,62,64,61,61,60,60,64,62,62,81,54,59,54,59,53,53,61,59,59,61,54,62,54,62,61,62,58,63,52,50,62,61,59,60,59,60,44,60,30,59,44,60,56,60,58,60,56,60,59,60,59,49,59,54,59,57,59,53,59,51,59,54,62,59,59,52,61,54,36,59,61,55,55,61,61,52,61,60,53,61,58,62,60,21,59,27,59,47,59,31,59,38,61,44,59,34,60,30,59,49,60,62,62,37,59,29,59,39,60,37,59,29,59,39,60,62,62,62,31,58,31,58,46,60,55,61,50,61,46,63,63,61],[69,67,71,69,67,67,69,66,70,70,66,70,66,70,66,71,70,66,66,193,192,192,192,192,192,192,64,0,193,192,192,192,192,72,193,193,193,193,193,192,192,68,193,192,192,70,69,67,70,67,70,66,72,67,72,66,70,67,69,67,70,67,70,67,71,69,66,66,70,67,72,67,67,67,70,66,67,67,70,67,72,67,70,67,70,67,72,69,67,69,67,69,67,69,67,68,67,70,67,71,70,70,67,72,68,67,67,70,70,67,67,70,67,70,71,66,70,67,70,71,67,72,67,68,67,67,67,69,67,72,67,68,67,67,67,70,70,66,66,72,66,69,65,69,66,72,66,69,65,70,66,66,66,66,69,65,69,65,71,67,74,67,70,67,67,67,67,71],[70,67,72,69,67,67,69,66,70,70,66,70,66,70,66,71,70,66,66,225,225,224,224,224,224,224,64,193,0,224,224,224,224,72,200,201,208,217,225,224,224,66,216,224,224,70,69,67,70,67,70,66,72,67,72,66,70,67,69,67,70,67,70,67,72,69,66,66,70,67,72,67,68,67,68,66,68,67,70,67,72,67,70,67,70,67,72,69,67,69,67,69,67,69,67,68,67,70,67,71,70,70,67,72,68,67,67,70,70,67,67,70,67,70,72,66,70,67,70,71,67,71,67,68,67,67,67,69,67,72,67,68,67,67,67,68,70,66,66,71,66,66,65,67,66,71,66,66,65,68,66,66,66,66,66,65,66,65,69,67,72,67,69,67,67,67,67,71],[70,67,72,68,67,67,68,65,70,70,65,70,65,70,66,71,69,66,66,292,350,351,376,380,381,381,64,193,225,0,439,438,438,72,200,201,208,217,312,405,439,66,216,361,366,70,69,67,70,67,70,66,72,67,72,66,70,67,69,67,70,67,70,67,72,68,67,67,70,67,72,67,67,67,64,66,67,67,70,67,72,67,70,67,70,67,72,68,67,69,67,69,67,69,67,68,67,70,67,71,70,70,67,72,69,67,67,70,70,67,67,70,67,70,72,67,70,67,70,67,67,72,67,68,67,68,67,66,67,84,67,80,67,62,67,70,70,66,66,70,66,66,65,67,66,70,66,66,65,68,66,66,66,66,66,65,66,65,71,67,74,67,70,67,63,67,67,71],[69,67,71,68,67,67,68,65,70,70,65,70,65,68,66,70,69,66,66,292,350,351,376,380,381,381,63,193,225,440,0,443,443,72,200,201,208,217,312,405,444,66,216,361,366,70,69,67,70,67,70,66,72,67,72,66,70,67,69,67,70,67,70,67,71,68,66,66,70,67,72,67,62,67,64,66,62,67,70,67,72,67,70,67,70,67,72,68,67,69,67,69,67,69,67,68,67,70,67,71,70,70,67,72,69,67,67,70,70,67,67,70,67,70,71,66,70,67,70,69,67,72,67,68,67,68,67,61,67,84,67,80,67,62,67,70,70,66,66,69,66,66,65,67,66,69,66,66,65,68,66,66,66,66,65,65,65,65,71,67,74,67,70,67,63,67,67,71],[70,67,72,69,67,67,69,65,70,70,65,70,65,70,66,71,70,66,66,292,350,351,376,380,381,381,61,193,225,440,445,0,575,72,200,201,208,217,312,405,460,66,216,361,366,70,69,67,70,67,70,66,72,67,72,66,70,67,69,67,70,67,70,67,72,69,66,66,70,67,72,67,64,67,68,66,64,67,70,67,72,67,70,67,70,67,72,68,67,69,67,69,67,69,67,68,67,70,67,71,70,70,67,72,69,67,67,70,70,67,67,70,67,70,72,66,70,67,70,67,67,70,67,67,67,68,67,61,67,84,67,80,67,62,67,70,70,66,66,70,66,66,65,66,66,69,66,66,65,67,66,66,66,66,66,65,66,65,71,67,74,67,70,67,63,67,67,71],[70,67,72,69,67,67,69,65,70,70,65,70,65,70,66,71,69,66,66,292,350,351,376,380,381,381,61,193,225,440,445,576,0,71,200,201,208,217,312,405,460,66,216,361,366,70,69,67,70,67,70,66,72,67,72,66,70,67,69,67,70,67,70,67,72,69,66,66,70,67,72,67,68,67,68,66,68,67,70,67,72,67,70,67,70,67,72,68,67,69,67,69,67,69,67,68,67,70,67,71,70,70,67,72,69,67,67,70,70,67,67,70,67,70,72,66,70,67,70,69,67,71,67,68,67,68,67,60,67,84,67,80,67,62,67,70,70,66,66,70,66,66,65,66,66,69,66,65,65,67,66,66,66,66,66,65,65,65,71,67,74,67,70,67,63,67,67,71],[55,61,54,54,61,61,54,60,58,58,60,58,60,58,61,56,54,58,59,66,66,66,66,66,66,66,117,67,67,60,60,60,60,0,67,67,67,67,66,66,62,116,67,66,62,152,59,61,59,61,58,58,62,62,63,62,55,61,59,61,62,61,56,61,57,54,60,61,59,60,61,60,48,60,45,59,48,60,55,60,57,60,55,60,59,60,58,58,61,59,61,55,61,59,61,58,61,55,61,61,61,59,62,61,41,62,62,58,58,62,62,59,62,60,57,60,58,61,60,51,59,45,58,43,58,28,58,41,63,36,61,40,61,24,61,54,62,60,60,52,62,41,63,46,62,54,62,47,63,51,62,59,59,60,46,63,52,63,36,63,54,61,49,61,50,61,61,61],[67,64,69,66,64,64,66,63,67,67,63,67,63,67,63,68,66,63,64,197,196,196,196,196,196,196,61,190,197,196,196,196,196,69,0,204,197,197,197,196,196,64,197,196,196,67,66,64,67,64,67,63,69,64,69,63,67,64,66,64,67,64,67,64,69,66,63,63,67,64,69,64,66,64,67,63,66,64,66,64,68,64,66,64,67,64,69,66,64,66,64,66,64,66,64,65,64,67,64,68,67,67,64,69,65,64,64,67,67,64,64,67,64,67,69,63,67,64,67,65,64,69,64,65,64,64,64,66,64,69,64,65,64,64,64,67,67,63,63,69,63,67,62,64,63,69,63,66,62,65,63,63,63,63,67,62,66,62,68,64,71,64,66,64,64,64,64,68],[67,64,69,66,64,64,66,63,67,67,63,67,63,67,63,68,66,63,64,198,197,197,197,197,197,197,61,190,198,197,197,197,197,69,204,0,198,198,198,197,197,64,198,197,197,67,66,64,67,64,67,63,69,64,69,63,67,64,66,64,67,64,67,64,69,66,63,63,67,64,69,64,66,64,66,63,66,64,66,64,68,64,66,64,67,64,69,66,64,66,64,66,64,66,64,65,64,67,64,68,67,67,64,69,65,64,64,67,67,64,64,67,64,67,69,63,67,64,67,65,64,69,64,65,64,64,64,65,64,69,64,65,64,64,64,67,67,63,63,69,63,67,62,64,63,69,63,66,62,65,63,63,63,63,67,62,66,62,67,64,70,64,65,64,64,64,64,68],[67,64,69,66,64,64,66,63,67,67,63,67,63,67,63,68,67,63,63,205,204,204,204,204,204,204,61,190,205,204,204,204,204,69,197,198,0,205,205,204,204,64,205,204,204,67,67,64,67,64,67,63,69,64,69,63,67,64,67,64,67,64,67,64,69,66,63,63,67,64,69,64,64,64,66,63,64,64,66,64,68,64,66,64,67,64,69,67,64,67,64,67,64,67,64,66,64,67,64,68,67,66,64,68,67,64,64,66,66,64,64,66,64,67,69,63,67,64,67,66,64,69,64,64,64,64,64,66,64,69,64,66,64,64,64,67,67,63,63,69,63,65,62,64,63,69,63,65,62,65,63,63,63,63,65,62,65,62,68,64,71,64,66,64,64,64,64,68],[67,64,69,66,64,64,66,63,67,67,63,67,63,67,63,68,67,63,63,214,213,213,213,213,213,213,61,190,214,213,213,213,213,69,197,198,205,0,214,213,213,66,220,213,213,67,66,64,67,64,67,63,69,64,69,63,67,64,66,64,67,64,67,64,69,66,63,63,67,64,69,64,64,64,66,63,64,64,66,64,68,64,67,64,67,64,69,66,64,66,64,66,64,66,64,65,64,67,64,68,67,67,64,69,65,64,64,67,67,64,64,67,64,67,69,63,67,64,67,68,64,68,64,64,64,64,64,66,64,69,64,65,64,64,64,67,67,63,63,68,63,64,62,64,63,68,63,64,62,65,63,63,63,63,64,62,64,62,67,64,71,64,66,64,64,64,64,68],[67,64,69,66,64,64,66,63,67,67,63,67,63,67,63,68,67,63,63,289,309,309,309,309,309,309,60,190,222,308,308,308,308,69,197,198,205,214,0,309,308,63,213,309,309,67,66,64,67,64,67,63,69,64,69,63,67,64,66,64,67,64,67,64,69,66,63,63,67,64,69,64,64,64,63,63,64,64,67,64,69,64,67,64,67,64,69,65,64,66,64,65,64,66,64,65,64,67,64,68,67,67,64,69,66,64,64,67,67,64,64,67,64,67,69,63,67,64,67,64,64,69,64,65,64,64,64,64,64,69,64,67,64,64,64,67,67,63,63,67,63,64,62,64,63,67,63,65,62,65,63,63,63,63,64,62,65,62,68,64,71,64,67,64,60,64,64,68],[67,64,69,66,64,64,66,63,67,67,63,67,63,67,63,68,67,63,63,289,347,348,373,377,378,378,61,190,222,401,401,400,400,69,197,198,205,214,309,0,401,63,213,358,363,67,66,64,67,64,67,63,69,64,69,63,67,64,66,64,67,64,67,64,69,66,64,64,67,64,69,64,61,64,62,63,61,64,67,64,69,64,67,64,67,64,69,65,64,66,64,66,64,66,64,65,64,67,64,68,67,66,64,68,66,64,64,66,66,64,64,66,64,67,69,63,67,64,67,65,64,69,64,65,64,65,64,59,64,69,64,66,64,62,64,67,67,63,63,67,63,64,62,64,63,67,63,63,62,65,63,63,63,63,64,62,63,62,68,64,71,64,67,64,60,64,64,68],[67,64,69,66,64,64,66,62,67,67,62,67,62,67,63,68,67,63,63,289,347,348,373,377,378,378,60,190,222,437,442,456,455,69,197,198,205,214,309,402,0,63,213,358,363,67,66,64,67,64,67,63,69,64,69,63,67,64,66,64,67,64,67,64,69,66,63,63,67,64,69,64,59,64,60,63,59,64,67,64,69,64,67,64,67,64,69,65,64,66,64,66,64,66,64,65,64,67,64,68,67,66,64,68,66,64,64,66,66,64,64,66,64,67,69,63,67,64,67,66,64,69,64,65,64,65,64,59,64,81,64,77,64,59,64,67,67,63,63,67,63,63,62,64,63,67,63,63,62,65,63,63,63,63,63,62,63,62,68,64,71,64,67,64,60,64,64,68],[50,59,52,50,58,59,49,57,57,56,57,56,57,56,58,50,50,58,58,58,61,60,62,59,61,63,66,59,60,59,59,57,56,109,59,59,59,59,58,60,59,0,59,60,61,121,53,56,52,56,49,53,57,56,56,59,54,59,52,59,59,57,58,59,51,46,58,59,56,57,57,57,47,57,36,55,47,57,58,57,60,57,58,57,56,57,60,56,56,46,56,50,56,48,56,51,56,54,59,59,58,52,57,53,46,56,57,50,50,57,57,52,57,58,62,59,55,58,59,48,60,44,59,44,59,37,56,47,59,54,57,46,57,43,58,51,59,54,54,57,57,46,57,53,56,63,57,52,57,50,56,53,53,53,45,54,51,54,49,58,60,59,55,59,60,60,59,57],[67,64,69,66,64,64,66,63,67,67,63,67,63,67,63,68,67,63,63,213,212,212,212,212,212,212,61,190,213,212,212,212,212,69,197,198,205,220,213,212,212,66,0,212,212,67,66,64,67,64,67,63,69,64,69,63,67,64,66,64,67,64,67,64,69,66,63,63,67,64,69,64,64,64,66,63,64,64,66,64,68,64,67,64,67,64,69,66,64,66,64,66,64,66,64,65,64,67,64,68,67,67,64,69,65,64,64,67,67,64,64,67,64,67,69,63,67,64,67,68,64,69,64,65,64,64,64,66,64,69,64,65,64,64,64,67,67,63,63,69,63,66,62,64,63,69,63,66,62,65,63,63,63,63,66,62,66,62,67,64,71,64,66,64,64,64,64,68],[67,64,69,66,64,64,66,63,67,67,63,67,63,67,63,68,67,63,63,289,347,348,357,357,357,357,60,190,222,357,357,356,356,69,197,198,205,214,309,357,357,63,213,0,357,67,66,64,67,64,67,63,69,64,69,63,65,64,66,64,67,64,67,64,69,66,63,63,67,64,69,64,62,64,63,63,62,64,67,64,69,64,67,64,67,64,69,65,64,66,64,66,64,66,64,65,64,65,64,68,67,66,64,68,66,64,64,66,66,64,64,66,64,67,69,63,67,64,67,68,64,69,64,65,64,65,64,67,64,69,64,66,64,63,64,67,67,63,63,67,63,63,62,64,63,67,63,63,62,65,63,63,63,63,63,62,63,62,68,64,71,64,67,64,60,64,64,68],[67,64,69,66,64,64,66,63,67,67,63,67,63,67,63,68,67,63,63,289,347,348,362,362,362,362,63,190,222,362,362,361,361,69,197,198,205,214,309,362,362,62,213,358,0,67,66,64,66,64,67,63,69,64,69,63,67,64,66,64,67,64,67,64,69,66,63,63,67,64,69,64,62,64,63,63,62,64,67,64,69,64,67,64,67,64,69,65,64,66,64,65,64,66,64,65,64,67,64,68,67,67,64,69,66,64,64,67,67,64,64,67,64,67,69,63,67,64,67,64,64,69,64,66,64,65,64,61,64,69,64,66,64,63,64,67,67,63,63,67,63,63,62,64,63,67,63,63,62,65,63,63,63,63,63,62,63,62,67,64,71,64,67,64,60,64,64,68],[53,59,55,55,59,59,83,58,84,85,58,85,58,85,57,86,84,57,57,61,61,60,60,62,60,62,80,62,61,60,60,59,59,148,62,62,62,61,61,60,60,119,61,61,61,0,55,59,56,59,56,55,60,59,57,59,45,59,55,59,59,59,84,59,54,54,59,59,53,58,56,58,46,58,41,58,46,58,37,58,39,58,37,58,54,58,86,50,59,55,59,52,59,52,59,55,59,46,59,58,58,52,59,54,54,58,59,51,51,59,59,52,59,57,56,58,88,59,57,42,57,38,59,28,59,31,59,36,59,59,57,56,57,49,57,57,59,58,58,55,58,54,58,54,58,51,58,50,58,49,58,58,58,58,54,58,50,58,38,59,63,58,60,58,58,58,59,57],[82,73,74,84,73,73,82,73,85,84,73,86,73,84,73,73,83,72,72,77,77,77,77,77,77,77,70,78,77,77,77,77,77,72,77,77,77,77,77,77,77,71,77,77,77,69,0,74,1054,74,93,89,79,74,78,73,842,74,1068,74,78,74,85,73,74,84,73,73,87,73,78,73,81,73,82,74,82,73,82,73,73,73,82,73,87,73,77,1067,74,1061,74,1048,74,1059,74,1067,74,842,74,81,80,86,73,76,74,73,73,85,85,73,73,81,73,81,74,73,86,73,82,70,74,67,74,65,73,80,74,68,72,77,73,75,72,80,73,65,76,71,71,77,71,72,70,75,72,77,71,71,70,75,72,70,70,71,70,70,70,70,71,73,75,74,75,74,80,75,73,81],[73,79,73,73,79,80,73,78,73,73,78,73,78,73,78,73,73,78,78,73,73,73,73,73,73,73,71,73,73,73,73,73,73,70,73,73,73,73,73,73,73,70,73,73,73,73,73,0,73,130,73,77,73,113,73,78,72,109,73,109,75,108,73,79,73,73,80,80,73,79,73,80,70,79,73,81,70,79,73,79,73,79,73,79,73,79,73,73,132,73,132,73,132,73,132,72,132,72,109,74,73,73,79,73,70,79,79,73,73,79,79,73,79,73,73,79,73,79,73,73,82,72,82,72,82,69,82,68,79,70,79,69,79,70,79,72,74,77,77,67,77,67,77,67,77,67,77,67,77,67,77,77,77,77,67,77,67,77,71,79,70,79,70,79,70,79,79,74],[79,71,72,80,71,71,80,71,95,82,71,85,71,94,71,71,80,70,70,75,75,75,75,75,75,75,68,76,75,75,75,75,75,70,75,75,75,75,75,75,75,68,75,75,75,67,1053,72,0,72,82,78,76,72,76,71,834,72,1046,72,76,72,82,71,72,80,71,71,85,71,76,71,78,71,80,72,80,71,80,71,71,71,92,71,97,71,75,1053,72,1051,72,1041,72,1048,72,1053,72,834,72,79,78,83,71,74,73,71,71,84,82,71,71,85,71,79,72,71,83,71,79,68,72,65,72,63,71,79,72,66,70,75,71,73,70,78,71,63,74,69,69,75,69,70,68,74,70,75,69,69,68,74,70,68,68,69,67,68,67,68,68,71,72,72,72,72,78,73,71,79],[71,77,71,71,77,77,71,76,71,71,76,71,76,71,76,71,71,76,76,71,71,71,71,71,71,71,69,71,71,71,71,71,71,68,71,71,71,71,71,71,71,68,71,71,71,71,71,128,71,0,71,75,71,112,71,77,70,105,71,105,72,105,71,77,71,71,78,78,71,77,71,77,68,77,71,79,68,77,71,77,71,77,71,77,71,77,71,71,128,71,128,71,128,71,128,70,128,70,105,72,71,71,77,71,68,77,77,71,71,77,77,71,77,71,71,77,71,78,71,71,80,70,80,70,80,67,80,66,77,68,77,67,77,68,77,70,72,75,75,65,75,65,75,65,75,65,75,65,75,65,75,75,75,75,65,75,65,75,69,77,68,77,68,77,68,77,77,72],[78,69,68,77,69,69,76,69,76,78,69,79,69,78,68,69,76,68,68,72,72,72,72,72,72,72,65,72,72,72,72,72,72,66,72,72,72,72,72,72,72,66,72,72,72,65,88,69,79,69,0,1733,651,69,477,68,79,69,88,69,73,69,134,69,68,78,69,69,89,69,76,69,69,69,74,69,70,69,81,69,68,69,76,69,84,69,124,80,69,80,69,78,69,81,69,80,69,79,69,77,76,87,69,73,77,69,69,80,80,69,69,78,69,76,66,69,79,69,77,61,69,62,69,67,69,75,68,66,69,66,69,64,69,71,69,68,72,67,67,72,66,72,66,68,67,71,66,72,66,72,67,67,67,68,71,66,72,66,73,69,68,69,68,69,73,70,69,77],[72,73,62,73,73,73,72,73,72,74,73,75,73,74,72,65,72,72,72,68,68,68,68,68,68,68,64,68,68,68,68,68,68,66,68,68,68,68,68,68,68,65,68,68,68,61,84,75,75,75,1733,0,640,75,473,72,72,74,84,74,69,74,130,73,64,74,73,73,132,72,119,72,64,72,115,73,65,72,77,72,64,72,72,72,127,72,120,76,75,76,75,75,75,77,75,76,75,72,74,72,71,98,73,84,73,73,73,91,91,73,73,89,73,72,62,73,75,73,73,76,73,53,74,56,74,68,74,58,73,57,73,54,73,61,73,63,68,71,71,64,70,64,70,62,71,64,70,64,70,67,71,71,71,72,64,70,64,70,67,73,63,73,63,73,66,74,73,73],[71,72,79,73,72,72,73,71,73,75,71,75,71,75,71,81,72,71,71,77,77,77,77,77,77,77,70,77,77,77,77,77,77,69,77,77,77,77,77,77,77,70,77,77,77,71,76,72,75,72,652,641,0,72,83,71,74,72,76,72,75,72,114,72,80,73,71,71,75,72,83,72,71,72,73,71,71,72,71,72,79,72,71,72,75,72,123,76,72,75,72,75,72,76,72,76,72,74,72,76,75,76,72,84,73,72,72,76,76,72,72,76,72,75,80,71,75,72,75,69,72,72,72,70,72,71,71,73,72,71,72,69,72,67,72,75,75,71,71,76,71,74,71,69,71,76,71,75,71,73,71,71,71,71,74,71,75,71,77,72,76,72,74,72,74,72,72,76],[71,77,71,71,77,77,71,76,71,71,76,71,76,71,76,71,71,76,76,71,71,71,71,71,71,71,68,71,71,71,71,71,71,68,71,71,71,71,71,71,71,68,71,71,71,71,71,111,71,112,71,75,71,0,71,80,71,105,71,105,72,105,71,77,71,71,78,79,71,77,71,77,68,77,71,78,68,77,71,77,71,77,71,77,71,77,71,71,111,71,111,71,111,71,111,70,111,71,105,72,71,71,77,71,68,77,77,71,71,77,77,71,77,71,71,78,71,78,71,68,80,70,80,70,80,67,80,66,77,68,77,68,77,68,77,70,72,76,76,64,75,64,75,65,75,64,75,64,75,65,75,76,76,76,64,75,64,75,69,77,68,77,68,77,68,77,77,72],[73,72,81,74,72,72,75,71,75,75,71,75,71,75,71,81,75,71,71,77,77,77,77,77,77,77,71,77,77,77,77,77,77,70,77,77,77,77,77,77,77,70,77,77,77,69,76,72,76,72,478,474,83,72,0,71,75,72,76,72,75,72,87,72,82,75,71,71,91,72,99,72,72,72,88,71,72,72,74,72,82,72,74,72,91,72,95,75,72,76,72,75,72,76,72,75,72,75,72,76,75,78,72,86,75,72,72,78,78,72,72,78,72,75,82,71,75,72,75,72,72,74,72,74,72,74,72,73,72,74,72,72,72,74,72,76,75,71,71,74,71,72,71,70,71,73,71,71,71,70,71,71,71,71,72,71,71,71,76,72,77,72,75,72,75,72,72,76],[72,78,72,72,78,78,72,77,72,72,77,72,77,72,77,72,72,77,77,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,78,72,79,72,76,72,82,72,0,72,78,72,78,73,78,72,78,72,72,77,77,72,78,72,78,72,78,72,77,72,78,72,78,72,78,72,78,72,78,72,72,78,72,78,72,78,72,78,72,78,72,78,73,72,72,78,72,72,78,78,72,72,78,78,72,78,72,72,77,72,79,72,72,79,72,78,72,78,72,78,72,79,72,78,72,78,72,78,72,74,78,78,72,77,72,77,72,77,72,77,72,77,72,77,78,78,77,72,77,72,77,72,79,72,78,72,78,72,78,78,73],[76,74,70,77,74,74,78,74,79,80,74,83,74,84,74,70,75,73,73,72,72,72,71,72,72,72,52,72,72,72,72,72,72,59,72,72,72,72,72,72,72,63,72,71,72,64,839,66,831,66,80,74,72,67,73,68,0,67,846,67,74,67,79,74,70,77,73,73,78,67,70,67,70,67,86,66,72,67,77,67,69,67,78,67,79,67,71,839,66,840,66,1063,66,841,66,839,66,4355,67,76,75,79,68,69,79,68,68,82,79,68,68,75,68,76,70,73,80,74,76,160,67,1202,67,1422,67,715,67,57,68,109,68,109,68,109,67,70,72,70,70,86,69,84,69,91,69,87,69,84,69,90,69,70,70,71,84,70,85,70,70,69,102,71,99,71,106,70,74,77],[68,74,68,68,75,74,68,73,68,68,73,68,73,67,73,68,68,73,73,68,68,68,68,68,68,68,63,68,68,68,68,68,68,66,68,68,68,68,68,68,68,65,68,68,68,68,68,105,68,103,68,72,68,103,68,73,67,0,68,142,74,107,68,74,67,67,74,74,68,74,68,74,65,75,68,74,65,74,68,75,68,74,68,74,68,74,68,68,106,68,106,68,106,68,106,68,106,67,139,69,68,68,75,68,67,74,74,68,68,74,74,68,74,68,68,73,68,74,68,68,78,66,77,66,77,64,77,63,74,66,74,66,74,65,74,66,69,72,72,62,72,62,72,62,72,62,72,62,72,62,72,72,72,72,62,72,62,72,67,74,65,74,65,74,65,74,74,69],[77,68,69,79,68,68,77,68,80,79,68,81,68,79,68,68,78,67,67,72,72,72,72,72,72,72,65,73,72,72,72,72,72,67,72,72,72,72,72,72,72,66,72,72,72,64,1064,69,1043,69,88,84,74,69,73,68,844,69,0,69,73,69,80,68,69,79,68,68,82,68,73,68,76,68,77,69,77,68,77,68,68,68,77,68,82,68,72,1053,69,1047,69,1037,69,1054,69,1053,69,841,69,76,75,81,68,71,69,68,68,80,80,68,68,76,68,76,69,68,81,68,77,65,69,65,69,66,68,75,69,63,67,72,68,70,67,75,68,60,71,66,66,72,66,67,65,70,67,72,66,66,65,70,67,65,65,66,65,65,65,65,66,68,70,69,70,69,75,70,68,76],[68,74,68,68,75,74,68,73,68,68,73,68,73,67,73,68,68,73,73,68,68,68,68,68,68,68,63,68,68,68,68,68,68,66,68,68,68,68,68,68,68,65,68,68,68,68,68,105,68,103,68,72,68,103,68,73,67,142,68,0,79,108,68,74,67,67,74,74,68,74,68,74,65,75,68,74,65,74,68,75,68,74,68,74,68,74,68,68,106,68,106,68,106,68,106,68,106,67,139,69,68,68,75,68,67,74,74,68,68,74,74,68,74,68,68,73,68,74,68,68,78,66,77,66,77,64,77,63,74,66,74,66,74,65,74,66,69,72,72,62,72,62,72,62,72,62,72,62,72,62,72,72,72,72,62,72,62,72,67,74,65,74,65,74,65,74,74,69],[72,69,71,72,70,69,71,68,71,71,68,73,68,71,68,71,72,68,68,71,71,71,71,71,71,71,67,71,71,71,71,71,71,67,71,71,71,71,71,71,71,67,71,71,71,67,72,70,71,69,72,68,71,69,71,68,72,74,72,79,0,72,72,69,71,72,68,68,71,69,71,69,71,70,73,68,73,69,71,70,71,69,71,69,71,69,71,73,71,73,71,73,71,73,71,73,71,72,71,72,71,72,70,71,73,69,69,73,72,69,69,71,69,71,71,68,72,69,72,71,69,70,69,70,69,72,69,71,69,69,69,69,69,72,69,71,72,68,68,71,68,71,68,71,68,71,68,71,68,71,68,68,68,68,71,68,71,68,71,69,70,69,70,69,72,69,69,72],[66,72,66,66,72,72,66,72,66,66,72,66,71,66,72,66,66,71,71,66,66,66,66,66,66,66,64,66,66,66,66,66,66,63,66,66,66,66,66,66,66,63,66,66,66,64,66,101,66,100,66,71,66,100,66,71,66,105,66,106,70,0,66,72,66,66,71,71,66,72,66,72,65,72,64,72,65,72,66,72,66,72,66,73,66,72,66,66,102,66,102,66,104,66,103,65,103,66,106,67,66,66,72,66,64,73,72,66,66,72,73,66,73,66,66,71,66,72,66,64,75,64,77,64,76,64,76,60,72,63,72,62,72,62,72,64,67,71,71,57,70,57,70,58,70,57,70,57,70,58,70,71,71,71,57,70,57,70,65,72,62,72,62,72,66,72,72,67],[166,72,131,101,73,72,143,73,137,142,73,140,73,137,72,181,145,72,72,76,76,76,76,76,76,76,69,76,76,76,76,76,76,71,76,76,76,76,76,76,76,72,76,76,76,97,83,73,82,73,149,145,122,73,111,72,82,73,83,73,77,73,0,72,122,101,73,72,132,73,122,73,81,73,125,73,82,73,85,73,75,73,82,73,129,73,521,83,73,82,73,82,73,82,73,82,73,82,73,81,80,101,73,90,84,73,73,98,98,73,73,95,73,80,147,72,148,73,84,71,73,68,73,68,73,78,73,72,73,75,73,75,73,78,73,75,76,71,71,79,70,79,70,76,71,79,70,79,70,76,71,71,71,72,78,70,77,70,75,73,73,73,73,73,78,74,72,81],[72,159,72,72,128,141,72,123,71,72,123,72,123,118,127,72,72,104,105,72,72,72,72,72,72,72,70,72,72,72,72,72,72,68,72,72,72,72,72,72,72,69,72,72,72,71,71,78,71,78,72,76,72,78,72,77,78,78,71,78,73,78,72,0,71,72,111,122,72,81,72,78,69,81,78,78,69,81,71,81,71,79,71,81,72,81,72,71,78,71,78,73,78,71,78,70,78,78,78,73,72,72,81,72,70,78,80,72,72,78,79,72,81,72,71,121,72,128,72,73,78,76,78,81,78,76,78,74,78,77,78,77,78,77,78,75,73,108,108,76,106,76,106,76,98,77,106,76,106,76,98,108,108,98,75,106,75,106,72,78,82,79,82,79,80,79,140,73],[1917,72,2155,1194,73,72,1201,72,122,95,72,95,72,81,72,889,534,72,72,78,77,78,77,77,77,77,65,78,78,78,77,78,78,60,78,78,78,78,78,78,78,65,78,78,78,70,73,73,73,73,74,70,83,73,84,72,72,72,73,72,76,73,122,72,0,1337,72,72,75,72,83,72,70,72,71,71,70,72,74,72,82,72,74,72,75,72,130,72,73,73,73,72,73,71,73,71,73,72,72,79,76,71,73,80,67,73,73,71,71,73,73,71,73,78,2418,72,82,73,76,67,73,75,73,73,73,74,73,75,72,70,73,66,72,72,73,78,76,71,71,81,72,78,71,58,70,81,72,78,71,60,70,71,71,71,78,71,78,71,70,73,70,73,67,73,68,73,72,76],[1192,68,1176,2088,68,68,2119,67,209,187,67,185,67,143,67,525,870,66,66,69,70,70,70,69,69,69,62,70,70,69,69,70,70,58,70,70,70,70,70,70,70,58,70,70,70,63,79,68,77,68,74,70,68,68,71,67,76,67,79,67,72,68,96,68,1331,0,68,68,78,67,70,67,69,67,70,68,70,67,77,67,68,67,77,67,78,67,80,77,68,78,68,78,68,76,68,78,68,76,67,78,74,78,67,69,72,67,67,79,79,67,67,74,67,77,1305,66,155,68,79,64,68,62,67,65,68,73,68,65,67,65,67,69,67,71,67,64,70,65,66,72,66,60,62,59,67,72,66,60,62,60,67,65,66,67,54,62,59,62,64,68,63,68,62,68,72,69,68,75],[67,107,67,65,124,107,65,127,70,67,127,67,127,109,123,68,68,131,117,67,67,67,67,67,67,67,66,67,67,67,67,67,67,61,67,67,67,67,67,67,67,65,67,67,67,65,66,74,66,74,67,71,67,74,67,72,72,73,66,73,68,73,67,107,67,65,0,156,67,73,67,73,69,73,73,74,69,74,66,73,66,73,66,73,67,74,67,66,75,66,75,68,74,66,74,66,74,72,74,68,67,66,73,66,62,73,73,66,66,73,73,66,73,67,67,154,67,123,67,69,73,71,73,74,73,71,73,69,73,72,73,72,73,71,73,67,68,98,98,75,98,73,97,74,84,77,98,76,97,75,84,98,98,83,73,97,76,97,64,73,76,74,76,74,74,74,107,68],[72,121,72,70,100,125,70,114,71,72,114,72,114,92,99,73,73,111,116,72,72,72,72,72,72,72,69,72,72,72,72,72,72,68,72,72,72,72,72,72,72,69,72,72,72,69,71,79,71,79,72,76,72,80,72,77,77,78,71,78,73,78,72,123,72,70,161,0,72,78,72,78,73,78,78,79,73,78,71,78,71,79,71,78,72,78,72,71,79,71,79,73,79,71,79,70,79,77,78,73,72,71,78,71,68,78,79,71,71,78,78,71,78,72,72,197,72,100,72,73,78,76,78,77,78,76,78,74,78,77,78,77,78,77,78,73,73,107,107,80,107,78,106,79,98,82,107,80,106,81,98,107,107,98,78,106,80,106,69,78,82,79,82,79,80,79,125,73],[81,70,71,80,70,70,81,70,81,81,70,81,70,81,69,73,80,69,69,73,73,73,73,73,73,73,68,73,73,73,73,73,73,68,73,73,73,73,73,73,73,68,73,73,73,67,82,70,82,70,148,144,112,70,111,69,80,70,82,70,73,70,124,70,71,80,70,70,0,70,503,70,140,70,509,70,127,70,171,70,140,70,153,70,517,70,114,82,70,79,70,80,70,81,70,82,70,80,70,78,77,109,70,93,80,70,70,101,101,70,70,98,70,77,70,70,81,70,77,70,70,70,70,70,70,73,70,69,70,72,70,72,70,75,70,71,73,68,68,70,68,70,68,74,69,70,68,70,68,74,69,68,68,69,68,68,68,68,72,70,71,70,71,70,75,71,70,78],[66,80,66,65,75,75,65,74,69,69,74,69,74,69,74,69,67,74,74,69,69,69,69,69,69,69,66,69,69,69,69,69,69,67,69,69,69,69,69,69,69,66,69,69,69,68,68,75,68,75,67,71,68,75,69,74,67,75,68,75,70,75,69,78,66,65,75,75,69,0,69,154,65,163,68,122,65,163,68,163,68,154,68,163,69,163,69,68,75,68,75,67,75,68,75,68,75,67,75,70,69,70,79,70,67,75,76,70,70,75,76,70,79,69,66,74,69,75,69,68,75,67,75,67,75,67,75,67,95,65,76,65,76,65,76,67,70,74,74,66,73,67,73,67,73,67,73,67,73,67,73,74,74,74,67,73,67,73,67,75,67,75,67,75,67,75,75,70],[76,74,84,76,74,74,77,73,77,77,73,77,73,77,73,86,77,73,73,79,79,79,79,79,79,79,72,79,79,79,79,79,79,73,79,79,79,79,79,79,79,71,79,79,79,72,77,74,77,74,139,135,124,74,123,73,76,74,77,74,77,74,118,74,84,76,73,73,507,74,0,74,121,74,505,73,121,74,144,74,154,74,144,74,506,74,126,77,74,75,74,76,74,76,74,77,74,76,74,78,77,97,74,105,77,74,74,97,97,74,74,97,74,77,83,73,77,74,77,75,74,78,74,76,74,73,74,74,74,78,74,76,74,76,74,78,77,73,73,75,73,73,73,72,73,75,73,73,73,72,73,73,73,73,73,73,73,73,78,74,78,74,76,74,75,74,74,78],[70,79,70,69,79,80,69,78,73,73,78,73,78,73,78,73,71,78,78,73,73,73,73,73,73,73,70,73,73,73,73,73,73,71,73,73,73,73,73,73,73,70,73,73,73,72,72,80,72,79,71,75,72,79,73,78,71,79,72,79,74,79,73,79,70,69,79,79,73,158,73,0,69,158,72,124,69,158,72,158,72,163,72,158,73,158,73,72,79,72,79,70,79,72,79,72,79,71,79,74,73,74,79,74,71,79,79,74,74,79,79,74,79,73,70,78,73,79,73,72,79,71,79,71,79,71,79,71,99,69,80,69,80,69,80,71,74,78,78,70,77,71,77,71,77,71,77,71,77,71,77,78,78,78,71,77,71,77,71,79,70,79,70,79,70,79,79,74],[71,66,64,77,67,66,77,68,81,79,68,80,68,82,69,63,73,68,68,69,71,72,69,70,70,70,42,70,69,66,67,65,69,48,72,72,69,69,69,67,65,46,69,70,69,62,79,66,78,66,70,69,69,68,69,68,76,66,79,66,72,68,77,66,65,76,70,69,141,67,118,67,0,67,1022,69,14665,67,148,67,125,67,135,67,127,67,70,76,66,79,66,75,66,77,66,79,66,76,66,76,75,70,68,62,87,68,68,70,70,68,68,66,68,76,65,69,81,67,76,56,66,55,66,43,64,59,67,6888,67,571,67,566,67,527,67,52,72,65,66,69,65,70,64,59,66,69,65,69,64,57,66,65,66,67,61,64,60,64,83,69,52,69,52,68,58,70,66,76],[65,78,65,64,75,74,64,73,68,68,73,68,73,68,73,68,66,73,73,68,68,68,68,68,68,68,65,68,68,68,68,68,68,66,68,68,68,68,68,68,68,65,68,68,68,67,67,74,67,74,66,70,67,74,68,73,66,75,67,75,70,74,68,77,65,64,74,74,68,162,68,153,64,0,67,121,64,162,67,165,67,153,67,162,68,162,68,67,74,67,74,66,74,67,74,67,74,66,74,69,68,69,79,69,66,74,75,69,69,74,75,69,78,68,65,73,68,74,68,67,74,66,74,66,74,66,74,66,94,64,75,64,75,64,75,66,69,73,73,65,72,66,72,66,72,66,72,66,72,66,72,73,73,73,66,72,66,72,66,74,66,74,66,74,66,74,74,69],[72,75,68,74,75,75,73,75,77,75,75,79,75,83,75,65,74,75,74,69,71,73,71,70,71,71,52,73,71,69,68,70,70,45,73,72,72,72,69,70,70,53,72,72,73,48,76,69,76,69,136,105,109,69,108,69,86,69,76,69,75,68,117,75,70,73,75,75,510,69,502,69,1040,69,0,67,1041,69,145,69,139,69,145,69,509,69,112,75,69,73,69,84,69,78,69,76,69,86,69,76,74,96,68,89,82,68,68,98,96,68,68,94,68,76,68,74,76,75,76,60,69,58,69,60,69,66,68,846,69,4341,69,4287,69,3973,69,58,73,73,73,51,70,49,70,65,68,52,70,56,70,66,68,72,72,71,49,70,56,70,67,69,66,68,66,68,77,69,75,76],[68,76,68,68,77,76,68,76,70,70,76,70,76,71,77,69,69,76,76,70,70,70,70,70,70,70,67,70,70,70,70,70,70,66,70,70,70,70,70,70,70,66,70,70,70,68,69,78,69,78,69,73,69,77,70,75,68,76,69,76,71,76,70,76,68,68,77,77,70,123,70,121,67,123,67,0,67,123,69,123,69,121,70,123,70,123,70,68,78,69,78,68,78,69,78,68,78,68,76,71,70,70,76,70,67,76,76,70,70,76,76,70,76,70,68,77,70,77,70,68,76,70,76,70,76,69,76,67,98,64,77,63,77,66,77,67,71,74,74,67,74,68,74,66,74,66,74,67,74,66,74,74,74,74,68,74,67,74,68,76,67,76,67,76,67,76,76,71],[71,65,63,78,66,65,76,67,82,78,67,86,67,83,68,62,74,67,67,68,70,71,68,69,69,69,41,69,68,65,66,64,68,47,71,71,68,68,68,66,64,45,68,69,68,61,79,65,79,65,70,69,68,67,68,67,72,65,79,65,74,67,77,65,64,77,69,68,127,66,117,66,14664,66,1022,68,0,66,134,66,124,66,136,66,128,66,69,82,65,84,65,81,65,83,65,85,65,72,65,75,74,70,67,61,93,67,67,76,70,67,67,67,67,75,64,68,81,66,76,55,65,54,65,42,63,68,66,6887,66,570,66,565,66,527,66,52,71,64,65,68,64,69,63,60,65,68,64,68,63,58,65,64,65,66,60,63,59,63,82,68,51,68,51,67,65,69,65,75],[64,77,64,63,73,73,63,72,67,67,72,67,72,67,72,67,65,73,72,67,67,67,67,67,67,67,64,67,67,67,67,67,67,65,67,67,67,67,67,67,67,64,67,67,67,66,66,73,66,73,65,69,66,73,67,72,65,73,66,73,68,73,67,76,64,63,74,73,67,161,67,152,63,161,66,120,63,0,66,161,66,152,66,161,67,164,67,66,74,66,74,65,73,66,73,66,73,65,74,68,67,68,77,68,65,73,74,68,68,73,74,68,77,67,64,72,67,73,67,66,73,65,73,65,73,65,73,65,93,63,74,63,74,63,74,65,68,72,72,64,71,65,71,65,71,65,71,65,71,65,71,72,72,72,65,71,65,71,65,73,65,73,65,73,65,73,73,68],[83,69,73,80,69,69,80,69,79,78,69,78,69,79,68,70,78,68,68,72,72,72,72,72,72,72,61,72,71,72,72,72,72,50,70,70,71,70,72,72,72,63,70,72,72,46,77,69,77,69,79,75,67,69,71,68,77,69,77,69,72,69,82,69,73,82,69,69,171,67,140,67,142,67,128,69,129,67,0,67,6859,67,7257,67,153,67,72,79,69,75,69,76,69,74,69,77,69,77,69,77,76,87,67,71,73,67,67,78,78,67,67,76,67,76,73,69,80,69,76,54,69,60,69,56,68,63,69,49,68,70,69,68,69,74,69,63,72,67,67,61,65,58,65,62,67,59,65,56,65,65,67,67,67,67,56,65,54,65,53,67,63,69,63,68,68,70,69,76],[65,78,65,64,75,74,64,73,68,68,73,68,73,68,73,68,66,73,73,68,68,68,68,68,68,68,65,68,68,68,68,68,68,66,68,68,68,68,68,68,68,65,68,68,68,67,67,74,67,74,66,70,67,74,68,73,66,75,67,75,70,74,68,77,65,64,74,74,68,162,68,153,64,165,67,121,64,162,67,0,67,153,67,162,68,162,68,67,74,67,74,66,74,67,74,67,74,66,74,69,68,69,79,69,66,74,75,69,69,74,75,69,78,68,65,73,68,74,68,67,74,66,74,66,74,66,74,66,94,64,75,64,75,64,75,66,69,73,73,65,72,66,72,66,72,66,72,66,72,66,72,73,73,73,66,72,66,72,66,74,66,74,66,74,66,74,74,69],[78,72,86,76,72,72,76,72,75,74,72,74,72,75,71,84,75,72,72,78,78,78,78,78,78,78,66,78,77,78,78,78,78,56,76,76,77,76,78,78,78,68,76,78,78,53,72,73,72,73,70,66,79,73,83,72,73,73,72,73,76,73,76,72,86,78,71,71,144,71,154,71,123,71,126,72,123,71,6863,71,0,71,6862,71,144,71,88,74,73,71,73,72,73,69,73,72,73,73,73,77,76,75,71,83,70,71,71,75,75,71,71,75,71,76,86,72,75,72,76,60,72,67,73,61,72,63,73,54,72,61,73,56,73,73,73,66,76,71,71,65,69,60,69,62,71,64,69,59,69,64,71,71,71,70,60,68,59,68,59,71,69,73,67,72,67,73,72,76],[69,78,69,68,78,78,68,77,72,72,77,72,77,72,77,72,70,77,78,72,72,72,72,72,72,72,69,72,72,72,72,72,72,70,72,72,72,72,72,72,72,69,72,72,72,71,71,78,71,78,70,74,71,78,72,77,70,78,71,78,73,78,72,79,69,68,78,79,72,157,72,162,68,157,71,123,68,157,71,157,71,0,71,157,72,157,72,71,78,71,78,69,78,71,78,71,78,70,78,73,72,73,78,73,70,78,79,73,73,78,78,73,78,72,69,78,72,78,72,71,78,70,78,70,78,70,78,70,98,68,79,68,79,68,79,70,73,77,77,69,76,70,76,70,76,70,76,70,76,70,76,77,77,77,70,76,70,76,70,78,69,78,69,78,69,78,78,73],[79,67,72,77,67,67,77,67,89,76,67,78,67,89,66,69,77,66,66,70,70,70,70,70,70,70,59,70,70,70,70,70,70,48,68,68,69,69,70,70,70,61,69,70,70,43,75,67,87,67,72,68,65,67,69,66,75,67,75,67,71,67,77,67,72,79,67,67,151,65,138,65,127,65,126,67,129,65,7256,65,6857,65,0,65,174,65,70,79,67,75,67,76,67,74,67,77,67,75,67,75,74,80,65,69,74,65,65,78,76,65,65,80,65,74,72,67,78,67,74,51,67,58,67,54,66,62,67,47,66,68,67,66,67,57,67,61,70,65,65,59,63,56,63,61,65,57,63,54,63,64,65,65,65,65,54,63,53,63,51,66,61,67,61,66,67,68,67,74],[63,76,63,62,72,72,62,72,66,66,72,66,71,66,72,66,64,71,71,66,66,66,66,66,66,66,64,66,66,66,66,66,66,64,66,66,66,66,66,66,66,63,66,66,66,65,65,72,65,72,64,68,65,72,66,71,64,72,65,72,67,73,66,75,63,62,72,72,66,160,66,151,62,160,65,119,62,160,65,160,65,151,65,0,66,162,66,65,72,65,72,64,73,65,73,65,73,64,72,67,66,67,76,67,64,73,73,67,67,72,74,67,79,66,63,71,66,72,66,65,72,64,72,64,72,64,72,64,92,62,73,62,73,62,73,64,67,71,71,63,70,64,70,64,70,64,70,64,70,64,70,71,71,71,64,70,64,70,64,72,64,72,64,72,64,72,72,67],[76,68,69,78,68,68,78,68,91,79,68,81,68,91,67,72,79,67,67,71,71,71,71,71,71,71,66,71,71,71,71,71,71,66,71,71,71,71,71,71,71,66,71,71,71,65,80,68,93,68,141,137,110,68,109,67,78,68,80,68,72,68,119,68,69,78,68,68,516,68,501,68,125,68,507,68,127,68,151,68,138,68,175,68,0,68,112,82,68,79,68,80,68,81,68,82,68,78,68,76,75,102,68,91,80,68,68,101,99,68,68,102,68,75,68,68,79,68,75,68,68,68,68,68,68,75,68,70,68,70,68,70,68,76,68,68,71,66,66,68,66,68,66,73,67,68,66,68,66,73,67,66,66,67,67,66,67,66,69,68,68,68,68,68,73,69,68,76],[64,77,64,63,73,73,63,72,67,67,72,67,72,67,72,67,65,73,72,67,67,67,67,67,67,67,64,67,67,67,67,67,67,65,67,67,67,67,67,67,67,64,67,67,67,66,66,73,66,73,65,69,66,73,67,72,65,73,66,73,68,73,67,76,64,63,74,73,67,161,67,152,63,161,66,120,63,164,66,161,66,152,66,163,67,0,67,66,74,66,74,65,73,66,73,66,73,65,74,68,67,68,77,68,65,73,74,68,68,73,74,68,79,67,64,72,67,73,67,66,73,65,73,65,73,65,73,65,93,63,74,63,74,63,74,65,68,72,72,64,71,65,71,65,71,65,71,65,71,65,71,72,72,72,65,71,65,71,65,73,65,73,65,73,65,73,73,68],[135,76,145,89,77,76,137,76,134,136,76,136,76,134,76,200,133,76,76,82,82,82,82,82,82,82,73,82,82,82,82,82,82,73,82,82,82,82,82,82,82,78,82,82,82,103,79,77,79,77,143,139,135,77,124,76,79,77,79,77,80,77,525,76,134,89,76,76,126,77,134,77,78,77,124,76,78,77,79,77,91,77,79,77,126,77,0,79,77,78,77,78,77,78,77,78,77,79,77,81,80,94,77,102,80,77,77,94,94,77,77,94,77,80,159,76,136,77,80,77,77,77,77,75,77,75,77,77,77,77,77,75,77,76,77,81,80,76,76,85,75,83,75,76,75,85,75,83,75,76,75,76,76,76,83,75,83,75,79,77,80,77,78,77,78,77,76,81],[76,67,68,77,67,67,74,67,81,77,67,85,67,80,67,67,77,66,66,71,70,70,70,70,70,70,64,72,71,70,70,69,69,66,71,71,71,71,71,70,69,65,71,70,70,63,1063,68,1050,68,80,76,73,68,72,67,838,68,1053,68,74,68,79,67,68,76,67,67,81,67,72,67,73,67,75,68,80,67,77,67,68,67,79,67,83,67,71,0,68,1060,68,1047,68,1059,68,1065,68,838,68,75,74,80,67,70,74,67,67,85,79,67,67,77,67,75,68,67,80,67,76,64,68,57,68,57,67,76,68,62,66,63,67,68,66,74,67,59,70,65,65,66,65,66,64,64,66,66,65,65,64,64,66,64,64,65,64,64,64,64,61,67,69,68,68,68,75,69,67,75],[67,73,67,67,73,73,67,72,67,67,72,67,72,67,72,67,67,73,72,67,67,67,67,67,67,67,65,67,67,67,67,67,67,64,67,67,67,67,67,67,67,64,67,67,67,67,67,126,67,124,67,71,67,107,67,72,66,104,67,104,70,103,67,73,67,67,75,74,67,73,67,73,64,73,67,75,64,74,67,73,67,73,67,73,67,74,67,67,0,67,132,67,127,67,127,66,127,66,107,68,67,67,73,67,64,73,73,67,67,73,73,67,73,67,67,73,67,73,67,67,76,66,76,66,76,63,76,62,73,64,73,63,73,64,73,66,68,71,71,61,71,61,71,61,71,61,71,61,71,61,71,71,71,71,61,71,61,71,65,73,64,73,64,73,64,73,73,68],[74,67,66,75,67,67,74,67,80,78,67,85,67,79,67,68,76,66,66,70,70,70,70,70,70,70,64,71,70,70,70,69,69,63,70,70,71,70,70,70,69,62,70,70,70,63,1055,68,1046,68,79,75,72,68,72,67,837,68,1045,68,74,68,77,67,66,77,67,67,76,67,68,67,71,67,74,68,77,67,74,67,66,67,76,67,78,67,69,1058,68,0,68,1046,68,1050,68,1058,68,837,68,74,74,78,67,69,74,67,67,82,77,67,67,76,67,75,66,67,80,67,76,63,68,61,68,58,67,70,68,59,66,70,67,69,66,73,67,59,70,65,65,69,64,65,63,67,66,68,64,62,63,67,66,64,64,65,61,63,61,63,60,67,64,68,64,68,71,69,67,75],[67,73,67,67,73,73,67,72,67,67,72,67,72,67,72,67,67,73,72,67,67,67,67,67,67,67,65,67,67,67,67,67,67,64,67,67,67,67,67,67,67,64,67,67,67,67,67,126,67,124,67,71,67,107,67,72,66,104,67,104,70,103,67,73,67,67,75,74,67,73,67,73,64,73,67,75,64,74,67,73,67,73,67,73,67,74,67,67,132,67,0,67,127,67,127,66,127,66,107,68,67,67,73,67,64,73,73,67,67,73,73,67,73,67,67,73,67,73,67,67,76,66,76,66,76,63,76,62,73,64,73,63,73,64,73,66,68,71,71,61,71,61,71,61,71,61,71,61,71,61,71,71,71,71,61,71,61,71,65,73,64,73,64,73,64,73,73,68],[70,68,62,76,68,68,75,68,78,76,68,83,68,82,68,69,79,67,67,69,68,69,69,69,69,69,52,70,69,69,69,69,69,63,69,69,70,69,69,69,69,60,69,69,69,59,1043,67,1037,67,78,74,71,67,71,66,1059,67,1036,67,73,66,77,68,64,76,68,68,78,66,70,66,71,66,71,67,79,66,74,66,66,66,76,66,80,66,69,1045,67,1047,67,0,67,1042,67,1047,67,1059,67,74,74,76,66,66,74,66,66,80,74,66,66,74,66,74,62,68,77,68,75,71,67,196,66,188,66,185,67,61,66,70,66,71,66,73,66,71,69,66,66,78,68,79,67,81,66,78,68,76,67,80,66,65,65,65,78,66,76,66,63,65,76,67,76,67,75,67,68,74],[66,72,66,66,72,72,66,72,66,66,72,66,71,66,72,66,66,71,71,66,66,66,66,66,66,66,64,66,66,66,66,66,66,63,66,66,66,66,66,66,66,63,66,66,66,66,66,125,66,123,66,70,66,106,66,71,65,103,66,103,69,104,66,72,66,66,73,73,66,72,66,72,63,72,66,74,63,72,66,72,66,72,66,73,66,72,66,66,126,66,126,66,0,66,129,65,129,65,105,67,66,66,72,66,63,73,72,66,66,72,73,66,73,66,66,72,66,72,66,66,75,65,75,65,75,62,75,61,72,63,72,62,72,63,72,65,67,70,70,60,70,60,70,60,70,60,70,60,70,60,70,70,70,70,60,70,60,70,64,72,63,72,63,72,63,72,72,67],[74,66,66,76,66,66,74,66,80,77,66,85,66,79,66,66,76,65,65,70,70,70,70,70,70,70,63,71,70,70,70,70,70,65,70,70,70,70,70,70,70,64,70,69,70,56,1052,67,1042,67,78,74,72,67,71,66,837,67,1051,67,73,67,78,66,66,76,66,66,79,66,70,66,73,66,74,67,80,66,72,66,63,66,74,66,81,66,70,1056,67,1049,67,1040,67,0,67,1056,67,837,67,74,73,79,66,69,75,66,66,84,78,66,66,76,66,74,66,66,79,66,75,61,67,58,67,53,66,75,67,64,65,68,66,64,65,76,66,58,69,64,64,68,64,68,63,69,65,68,64,68,63,69,65,63,63,64,67,63,67,63,65,66,66,67,61,67,71,68,66,74],[66,72,66,66,72,72,66,72,66,66,72,66,71,66,72,66,66,71,71,66,66,66,66,66,66,66,64,66,66,66,66,66,66,63,66,66,66,66,66,66,66,63,66,66,66,66,66,125,66,123,66,70,66,106,66,71,65,103,66,103,69,103,66,72,66,66,73,73,66,72,66,72,63,72,66,74,63,72,66,72,66,72,66,73,66,72,66,66,126,66,126,66,129,66,0,65,130,65,103,67,66,66,72,66,63,73,72,66,66,72,73,66,73,66,66,72,66,72,66,66,75,65,75,65,75,62,75,61,72,63,72,62,72,63,72,65,67,70,70,60,70,60,70,60,70,60,70,60,70,60,70,70,70,70,60,70,60,70,64,72,63,72,63,72,63,72,72,67],[75,65,67,76,66,65,74,66,80,77,66,85,66,78,66,65,75,65,65,70,70,70,70,70,70,70,63,71,70,70,70,70,70,65,70,70,69,70,70,70,70,56,70,69,70,60,1062,66,1049,66,79,75,72,66,71,66,837,67,1052,67,73,66,77,65,67,76,66,65,80,66,71,66,75,66,75,67,82,66,75,66,66,66,77,66,82,66,69,1065,66,1059,66,1047,66,1058,66,0,66,837,67,74,73,79,66,69,73,66,66,84,78,66,66,76,66,74,66,64,79,66,75,53,67,55,66,56,65,72,66,60,65,67,66,67,65,76,66,58,69,64,64,65,64,64,63,65,65,65,64,63,63,66,65,63,63,64,62,63,62,63,60,66,65,67,64,67,72,68,65,74],[66,72,66,66,72,72,66,72,66,66,72,66,71,66,72,66,66,71,71,66,66,66,66,66,66,66,64,66,66,66,66,66,66,63,66,66,66,66,66,66,66,63,66,66,66,66,66,125,66,123,66,70,66,106,66,71,65,103,66,103,69,103,66,72,66,66,73,73,66,72,66,72,63,72,66,74,63,72,66,72,66,72,66,73,66,72,66,66,126,66,126,66,129,66,130,65,0,65,103,67,66,66,72,66,63,73,72,66,66,72,73,66,73,66,66,72,66,72,66,66,75,65,75,65,75,62,75,61,72,63,72,62,72,63,72,65,67,70,70,60,70,60,70,60,70,60,70,60,70,60,70,70,70,70,60,70,60,70,64,72,63,72,63,72,63,72,72,67],[75,73,69,76,73,73,75,73,78,79,73,82,73,83,73,69,74,72,72,71,71,71,70,71,71,71,51,71,71,71,71,71,71,58,71,71,71,71,71,71,71,61,71,70,71,63,838,65,830,65,79,73,71,66,72,67,4354,66,842,66,73,66,78,73,69,76,72,72,77,66,69,66,69,66,85,65,71,66,76,66,68,66,77,66,78,66,70,838,65,839,65,1062,65,840,65,838,65,0,66,75,74,78,67,68,77,67,67,81,78,67,67,74,67,75,69,72,79,73,75,159,66,1208,66,1428,66,717,66,56,67,108,67,108,67,108,66,69,71,69,69,85,68,83,68,90,68,86,68,83,68,89,68,69,69,70,83,69,84,69,69,68,101,70,98,70,105,69,73,76],[67,73,67,67,73,73,67,72,67,67,72,67,72,66,72,67,67,73,72,67,67,67,67,67,67,67,62,67,67,67,67,67,67,65,67,67,67,67,67,67,67,64,67,67,67,67,67,104,67,102,67,71,67,102,67,72,66,138,67,138,70,107,67,73,66,66,74,73,67,73,67,73,64,73,67,73,64,74,67,73,67,73,67,73,67,74,67,67,108,67,108,67,107,67,105,67,105,66,0,68,67,67,73,67,66,73,73,67,67,73,73,67,73,67,67,72,67,73,67,67,77,65,76,65,76,63,76,62,73,65,73,65,73,64,73,65,68,71,71,61,71,61,71,61,71,61,71,61,71,61,71,71,71,71,61,71,61,71,66,73,64,73,64,73,64,73,73,68],[78,71,74,77,71,71,79,71,79,79,71,78,71,78,70,73,77,71,71,74,74,74,74,74,74,74,68,75,74,74,74,74,74,69,74,74,74,74,74,74,74,68,74,74,74,68,78,71,78,71,78,73,74,71,74,70,77,71,78,71,74,71,78,71,76,80,71,71,78,71,74,71,77,71,76,71,77,71,78,71,74,71,78,71,78,71,74,77,71,77,71,76,71,77,71,77,71,77,71,0,90,77,71,73,76,71,71,77,77,71,71,77,71,80,76,71,78,71,80,69,71,71,71,71,71,77,71,72,71,72,71,72,71,74,71,72,75,71,69,73,69,73,69,74,70,73,69,73,69,74,70,71,69,70,71,69,71,69,73,71,73,71,73,71,75,72,71,80],[78,71,74,77,71,71,77,71,77,78,71,78,71,78,70,73,78,71,71,74,74,74,74,74,74,74,69,75,74,74,74,74,74,70,74,74,74,74,74,74,74,68,74,74,74,68,78,71,78,71,78,73,74,71,74,70,77,71,78,71,74,71,78,71,74,77,71,71,78,71,74,71,77,71,76,71,77,71,78,71,74,71,78,71,78,71,74,77,71,78,71,76,71,78,71,77,71,77,71,92,0,77,71,73,77,71,71,77,77,71,71,77,71,80,74,71,78,71,80,69,71,71,71,70,71,75,71,73,71,71,71,71,71,75,71,69,74,69,69,71,69,71,69,72,70,71,69,71,69,76,70,69,69,70,68,69,70,69,72,71,73,71,73,71,76,72,71,80],[81,69,70,77,69,69,79,69,78,79,69,80,69,76,68,71,80,68,68,72,72,72,71,72,72,72,65,72,72,72,72,72,72,63,72,72,71,72,72,71,71,64,72,71,72,64,81,69,80,69,112,107,71,69,97,68,78,69,81,69,73,69,107,69,71,74,69,69,90,69,74,69,73,69,73,69,74,69,80,69,66,69,75,69,85,69,96,80,69,79,69,80,69,79,69,82,69,78,69,76,75,0,69,1707,1016,69,69,1813,1823,69,69,1799,69,76,71,68,81,69,77,63,69,65,69,63,68,74,69,65,69,67,69,69,68,71,69,64,72,67,67,61,67,63,66,66,68,60,67,67,66,66,68,66,66,67,65,66,67,66,123,68,75,69,72,69,76,70,69,77],[67,78,67,67,75,74,67,73,67,68,73,68,73,69,73,66,67,74,74,68,68,68,68,68,68,68,66,68,68,68,68,68,68,67,68,68,68,68,68,68,68,66,68,68,68,67,67,74,67,74,68,72,68,74,68,73,67,75,67,75,70,74,68,77,68,67,74,74,68,78,68,74,65,79,67,74,65,78,66,79,66,74,66,78,68,78,68,67,74,67,74,67,74,67,74,67,74,67,74,69,68,68,0,68,65,130,138,68,68,142,143,68,146,68,68,73,68,74,68,64,74,67,74,66,74,65,74,65,74,63,74,62,74,62,74,64,69,73,73,63,73,63,73,62,73,63,73,63,73,63,73,73,73,73,63,73,63,73,66,105,66,74,66,74,66,74,74,70],[74,73,82,72,73,73,75,71,74,75,71,75,71,72,71,83,75,71,72,78,78,78,77,78,78,78,68,78,78,78,78,78,78,66,78,78,77,78,78,77,77,69,78,77,78,70,75,73,75,73,102,97,83,73,109,72,72,73,75,73,76,73,100,73,82,69,71,71,78,73,86,73,69,73,71,72,69,73,70,73,76,73,70,73,78,73,108,74,73,74,73,75,73,73,73,76,73,72,73,76,75,1711,73,0,1011,73,73,1708,1708,73,73,1706,73,76,81,71,76,73,76,69,73,72,73,68,72,69,73,70,73,70,73,69,72,65,73,69,76,70,70,67,72,66,71,66,72,67,72,71,71,66,72,70,70,70,68,70,71,70,129,72,82,73,77,73,76,73,73,77],[72,65,63,69,62,65,69,62,75,75,62,82,62,77,63,49,66,66,65,66,67,68,67,67,67,67,34,68,67,67,67,67,67,41,68,68,68,67,67,67,67,51,67,67,67,61,72,63,73,63,71,66,67,62,69,65,74,65,72,65,72,64,76,65,59,70,62,65,76,65,69,65,85,65,64,64,92,65,76,65,69,65,78,65,78,65,68,76,63,77,63,82,63,73,63,76,63,74,65,72,72,1012,62,1003,0,62,62,1018,1012,62,62,1010,62,73,59,64,74,62,74,70,64,56,64,40,64,72,64,67,66,81,64,80,64,103,64,33,68,63,63,18,58,15,64,24,59,27,58,25,64,32,59,62,62,63,15,64,25,64,1812,64,781,66,779,65,751,67,65,74],[65,72,65,65,72,72,65,72,65,66,72,66,71,67,72,64,65,72,72,66,66,66,66,66,66,66,64,66,66,66,66,66,66,65,66,66,66,66,66,66,66,63,66,66,66,65,65,72,65,72,66,70,66,72,66,71,65,72,65,72,67,73,66,72,66,65,72,72,66,72,66,72,63,72,66,72,63,72,64,72,64,72,64,73,66,72,66,65,72,65,72,65,73,65,73,65,73,65,72,67,66,66,128,66,63,0,127,66,66,127,131,66,131,66,66,71,66,72,66,62,72,65,72,64,72,63,72,63,72,61,72,60,72,60,72,62,67,71,71,61,71,61,71,60,71,61,71,61,71,61,71,71,71,71,61,71,61,71,65,102,64,72,64,72,64,72,72,68],[71,79,71,71,78,78,71,77,71,72,77,72,77,73,77,70,71,78,79,72,72,72,72,72,72,72,70,72,72,72,72,72,72,71,72,72,72,72,72,72,72,70,72,72,72,71,71,78,71,78,72,76,72,78,72,77,71,78,71,78,73,78,72,80,72,71,78,79,72,79,72,78,69,79,71,78,69,79,70,79,70,79,70,79,72,79,72,71,78,71,78,71,78,71,78,71,78,71,78,73,72,72,142,72,69,133,0,72,72,141,142,72,142,72,72,78,72,78,72,68,78,71,78,70,78,69,78,69,78,67,78,66,78,66,78,68,73,77,77,67,77,67,77,66,77,67,77,67,77,67,77,77,77,77,67,77,67,77,70,109,70,78,70,78,70,78,78,74],[76,67,68,76,67,67,78,67,79,78,67,85,67,77,66,69,79,66,66,70,69,70,69,70,70,70,62,70,70,70,70,70,70,61,70,70,69,70,70,69,69,58,70,69,70,62,78,67,79,67,103,98,69,67,95,66,77,67,78,67,73,67,102,67,69,73,67,67,80,67,72,67,72,67,71,67,79,67,70,67,64,67,72,67,82,67,94,83,67,82,67,83,67,82,67,85,67,77,67,74,73,1811,67,1702,1020,67,67,0,2765,67,67,1795,67,74,69,66,80,67,75,58,67,63,67,59,66,72,67,63,67,61,67,64,66,67,67,62,70,65,65,57,65,59,64,62,66,56,65,63,64,60,66,64,64,65,61,64,63,64,121,66,64,67,62,67,69,68,67,75],[73,64,65,73,64,64,75,64,74,75,64,76,64,72,63,66,76,63,63,67,66,67,66,67,67,67,59,67,67,67,67,67,67,58,67,67,66,67,67,66,66,55,67,66,67,59,75,64,74,64,100,95,66,64,92,63,71,64,75,64,68,64,99,64,66,70,64,64,77,64,69,64,69,64,66,64,70,64,67,64,61,64,67,64,77,64,91,74,64,74,64,74,64,73,64,76,64,71,64,71,70,1818,64,1699,1011,64,64,2762,0,64,64,1790,64,71,66,63,77,64,72,55,64,60,64,56,63,66,64,60,64,58,64,61,63,62,64,59,67,62,62,54,62,56,61,58,63,53,62,60,61,56,63,61,61,62,58,61,60,61,118,63,61,64,60,64,63,65,64,72],[62,69,62,62,69,69,62,68,62,63,68,63,68,64,68,61,62,69,69,63,63,63,63,63,63,63,61,63,63,63,63,63,63,62,63,63,63,63,63,63,63,61,63,63,63,62,62,69,62,69,63,67,63,69,63,68,62,69,62,69,64,69,63,69,63,62,69,69,63,69,63,69,60,69,62,69,60,69,61,69,61,69,61,69,63,69,63,62,69,62,69,62,69,62,69,62,69,62,69,64,63,63,137,63,60,124,132,63,63,0,143,63,137,63,63,68,63,69,63,59,69,62,70,61,70,60,69,60,69,58,69,57,69,57,69,59,64,68,68,58,69,58,69,57,68,58,68,58,68,58,68,68,68,68,58,68,58,68,61,100,61,69,61,69,61,69,69,65],[65,73,65,65,72,72,65,72,65,66,72,66,71,67,72,64,65,72,72,66,66,66,66,66,66,66,64,66,66,66,66,66,66,65,66,66,66,66,66,66,66,64,66,66,66,65,65,72,65,72,66,70,66,72,66,71,65,72,65,72,67,73,66,73,66,65,72,72,66,73,66,72,63,73,65,72,63,73,64,73,64,72,64,74,66,73,66,65,72,65,72,65,73,65,73,65,73,65,72,67,66,66,141,66,63,131,136,66,66,146,0,66,145,66,66,71,66,72,66,62,72,65,72,64,72,63,72,63,72,61,72,60,72,60,72,62,67,71,71,61,71,61,71,60,71,61,71,61,71,61,71,71,71,71,61,71,61,71,64,103,64,72,64,72,64,72,72,68],[73,67,68,71,67,67,74,67,79,74,67,76,67,77,66,69,74,66,66,70,70,70,69,70,70,70,63,70,70,70,70,70,70,60,70,70,69,70,70,69,69,60,70,69,70,65,74,67,80,67,101,96,69,67,94,66,74,67,74,67,71,67,99,67,69,68,67,67,77,67,72,67,68,67,70,67,70,67,67,67,64,67,73,67,83,67,94,75,67,75,67,76,67,74,67,77,67,74,67,74,73,1798,67,1701,1012,67,67,1796,1794,67,67,0,67,74,69,66,75,67,74,59,67,63,67,61,66,67,67,63,67,61,67,65,66,63,67,60,70,65,65,57,64,59,63,65,65,58,64,65,63,65,65,64,64,65,61,63,65,63,120,66,72,67,69,67,74,68,67,75],[65,76,65,65,72,72,65,72,65,66,72,66,71,67,72,64,65,72,72,66,66,66,66,66,66,66,64,66,66,66,66,66,66,65,66,66,66,66,66,66,66,64,66,66,66,65,65,72,65,72,66,70,66,72,66,71,65,72,65,72,67,73,66,75,66,65,72,72,66,76,66,72,63,76,65,72,63,76,64,76,64,72,64,79,66,78,66,65,72,65,72,65,73,65,73,65,73,65,72,67,66,66,144,66,63,131,136,66,66,140,145,66,0,66,66,71,66,72,66,62,72,65,72,64,72,63,72,63,72,61,72,60,72,60,72,62,67,71,71,61,71,61,71,60,71,61,71,61,71,61,71,71,71,71,61,71,61,71,64,103,64,72,64,72,64,72,72,68],[78,71,74,77,71,71,77,71,78,77,71,77,71,77,70,74,77,70,70,74,74,74,74,74,74,74,70,75,74,74,74,74,74,70,74,74,74,74,74,74,74,70,74,74,74,69,78,71,78,71,78,74,74,71,74,70,78,71,78,71,74,71,78,71,75,79,71,71,78,71,74,71,78,71,77,71,78,71,78,71,74,71,78,71,78,71,74,78,71,78,71,78,71,78,71,78,71,78,71,81,80,78,71,74,78,71,71,78,78,71,71,78,71,0,75,71,78,71,80,73,71,73,71,73,71,77,71,74,71,74,71,74,71,77,71,73,74,69,69,74,69,74,69,76,70,74,69,74,69,76,70,69,69,70,74,69,74,69,74,71,74,71,74,71,77,72,71,80],[1912,72,2153,1193,73,72,1208,71,127,100,71,100,71,97,72,913,550,72,72,78,77,78,77,77,77,77,69,78,78,78,77,78,78,65,78,78,78,78,78,78,78,79,78,78,78,71,73,73,73,73,75,71,84,73,84,72,72,73,73,73,76,73,147,72,2417,1310,72,72,76,72,84,72,67,72,67,71,67,72,72,72,80,72,72,72,76,72,155,72,73,73,73,72,73,69,73,71,73,72,73,79,76,72,73,81,67,73,73,72,72,73,73,72,73,78,0,72,99,73,76,67,73,64,72,70,73,63,73,73,72,69,73,67,72,70,73,150,76,71,71,78,72,76,71,62,70,78,72,76,71,70,70,71,71,71,76,71,76,71,66,73,72,73,70,73,70,73,72,76],[72,121,72,70,100,125,70,114,74,72,114,72,114,92,99,73,73,111,116,72,72,72,72,72,72,72,69,72,72,72,72,72,72,68,72,72,72,72,72,72,72,69,72,72,72,69,71,79,71,79,72,76,72,80,72,77,77,78,71,78,73,78,72,122,72,70,160,198,72,78,72,78,71,78,77,79,71,78,72,78,71,79,72,78,72,78,72,71,79,71,79,73,79,71,79,69,79,77,78,73,72,71,78,71,66,78,79,71,71,78,78,71,78,72,72,0,72,100,72,73,78,76,77,76,77,76,77,74,78,77,78,77,78,77,78,72,72,107,107,80,107,78,106,78,98,82,107,80,106,80,98,107,107,98,78,106,80,106,69,78,81,79,81,79,79,79,125,73],[96,72,80,164,72,72,222,74,488,495,74,493,74,474,71,127,223,71,71,75,75,75,75,75,75,75,70,75,75,75,75,75,75,68,75,75,75,75,75,75,75,66,75,75,75,100,84,72,83,72,82,78,75,72,75,71,83,72,84,72,76,72,147,72,80,159,72,72,83,72,75,72,83,72,79,72,84,72,83,72,74,72,83,72,83,72,131,84,72,84,72,82,72,84,72,84,72,83,72,80,79,84,72,75,81,72,72,85,85,72,72,80,72,78,97,72,0,72,83,72,72,72,72,71,72,77,72,72,72,73,72,73,72,77,72,73,75,70,70,75,69,74,69,76,70,75,69,74,69,76,70,70,70,71,74,69,74,69,73,72,72,72,72,72,78,73,72,80],[71,127,71,71,158,127,71,141,70,71,141,71,141,132,157,71,71,125,113,71,71,71,71,71,71,71,70,71,71,71,71,71,71,66,71,71,71,71,71,71,71,69,71,71,71,69,71,77,71,78,71,75,71,78,71,77,77,77,71,77,72,77,71,127,71,71,126,98,71,77,71,77,69,77,77,78,69,77,70,77,70,77,70,77,71,77,71,70,77,71,77,72,77,71,77,70,77,77,77,72,71,71,77,71,65,77,77,71,71,77,77,71,77,71,71,98,71,0,71,73,77,75,77,80,77,75,77,73,77,76,77,76,77,76,77,73,72,102,102,74,101,74,101,74,88,75,101,74,101,74,88,102,102,87,73,101,73,101,69,77,81,78,81,78,79,78,126,72],[84,74,77,84,74,74,81,74,81,80,74,82,74,81,73,77,84,73,73,77,77,77,77,77,77,77,73,78,77,77,77,77,77,73,77,77,77,77,77,77,77,73,77,77,77,72,82,74,81,74,82,78,77,74,77,73,81,74,82,74,78,74,84,74,77,84,74,74,81,74,77,74,81,74,81,74,82,74,81,74,77,74,81,74,81,74,77,82,74,82,74,82,74,82,74,82,74,81,74,84,83,82,74,77,82,74,74,82,82,74,74,81,74,83,77,74,84,74,0,76,74,76,74,76,74,80,74,77,74,77,74,77,74,80,74,76,77,72,72,77,72,77,72,80,73,77,72,77,72,80,73,72,72,73,77,72,77,72,77,74,77,74,77,74,80,75,74,83],[54,64,56,55,65,64,54,65,66,62,65,64,65,67,65,63,61,63,62,66,67,67,64,62,62,62,43,68,67,63,66,65,67,49,68,68,68,67,63,62,66,20,67,67,63,45,59,59,60,59,57,70,61,59,65,63,164,60,59,60,68,60,62,64,59,59,65,64,65,60,67,60,47,60,47,64,47,60,51,60,53,60,51,60,66,60,64,57,59,59,59,79,59,60,59,50,59,164,60,63,64,52,60,54,62,60,60,53,51,60,60,53,60,66,58,62,64,65,66,0,60,24254,61,21131,61,17160,61,68,60,82,59,70,59,84,59,67,64,63,63,65,60,51,56,68,60,65,60,53,56,69,60,61,61,62,53,57,55,57,85,59,86,63,78,63,102,63,64,65],[64,70,64,64,70,70,64,69,64,64,69,64,69,63,69,63,64,69,69,64,64,64,64,64,64,64,61,64,64,64,64,64,64,61,64,64,64,64,64,64,64,59,64,64,64,61,64,73,64,73,64,67,64,73,64,71,62,74,64,74,65,73,64,70,64,64,70,70,64,70,64,70,61,70,64,70,61,70,63,70,63,70,63,70,64,70,64,64,73,63,73,63,73,64,73,63,73,62,74,65,64,64,70,64,61,70,70,64,64,70,70,64,70,64,64,69,64,70,64,65,0,69,97,67,97,67,100,60,75,61,74,61,74,63,70,62,75,78,78,58,69,58,69,60,72,59,69,59,69,60,68,78,78,72,58,69,59,69,64,76,63,74,62,74,63,70,70,65],[55,67,59,58,67,67,58,65,58,59,65,59,65,69,66,63,59,64,64,67,67,66,65,66,66,66,40,69,70,66,66,67,68,45,69,68,69,70,67,66,67,24,69,64,66,47,57,61,57,61,55,50,62,61,64,62,1192,60,57,60,65,62,61,67,53,54,67,67,62,59,65,59,34,59,64,62,34,59,52,59,55,59,53,59,63,59,64,53,61,52,61,192,61,57,61,55,61,1201,60,63,62,55,61,58,33,61,61,55,54,61,61,55,61,65,50,67,63,67,65,24259,67,0,65,39851,63,29641,66,57,61,115,61,87,61,100,61,64,66,63,63,119,62,89,62,71,62,113,62,85,62,62,62,62,62,63,89,64,85,64,65,62,108,62,78,62,72,60,67,65],[63,69,63,63,69,69,63,68,63,63,68,63,68,63,68,63,63,69,69,63,63,63,63,63,63,63,61,63,63,63,63,63,63,60,63,63,63,63,63,63,63,57,63,63,63,60,63,72,63,72,63,66,63,72,63,68,62,72,63,72,64,73,63,69,63,62,68,68,63,69,63,69,60,69,63,68,60,69,63,69,63,69,63,69,63,69,63,63,72,63,72,62,72,63,72,62,72,62,72,64,63,63,69,63,60,69,69,63,63,70,69,63,69,63,62,68,63,69,63,60,95,66,0,67,126,66,103,58,69,59,75,59,70,60,70,60,64,67,67,58,79,58,74,59,70,59,74,59,69,59,69,67,67,69,58,69,59,69,63,69,62,77,62,72,62,71,69,64],[54,68,55,54,69,68,55,68,57,60,68,61,68,70,68,60,56,67,67,63,64,63,62,63,61,63,38,65,66,63,64,64,65,38,65,64,65,66,63,63,64,15,65,61,63,42,59,61,61,61,58,54,61,61,63,62,1416,60,59,60,65,62,61,68,55,51,69,68,62,58,63,58,35,58,72,62,35,58,51,58,52,58,52,58,63,58,62,55,61,58,61,189,61,61,61,58,61,1423,60,63,62,58,61,59,35,61,61,59,58,61,61,58,61,65,52,67,61,69,65,21130,65,39852,66,0,66,30404,65,52,59,111,59,141,58,102,59,56,64,68,68,92,73,138,76,76,73,84,73,133,76,67,73,68,68,68,138,78,132,78,54,62,92,63,108,63,77,62,68,65],[63,69,63,63,69,69,63,68,63,63,68,63,68,62,68,63,63,69,69,63,63,63,63,63,63,63,61,63,63,63,63,63,63,60,63,63,63,63,63,63,63,58,63,63,63,60,62,72,62,72,63,66,63,72,63,69,61,72,62,72,64,72,63,69,63,63,68,68,63,69,63,69,58,69,63,68,58,69,62,69,62,69,62,69,63,69,63,62,72,62,72,62,72,62,72,61,72,61,72,64,63,62,69,62,60,69,69,62,62,70,69,62,69,63,63,68,63,69,63,59,95,64,126,66,0,64,103,58,69,58,70,60,76,59,70,59,64,67,67,56,74,63,78,59,70,57,69,63,73,59,69,67,67,69,63,73,63,73,63,69,62,72,61,78,62,71,69,64],[62,68,58,62,68,68,61,67,66,64,67,70,67,75,67,60,62,65,65,62,61,61,62,62,62,62,28,63,63,62,61,64,63,37,63,63,63,63,62,62,62,30,63,62,62,45,61,60,62,60,63,59,61,60,62,63,706,59,61,59,68,60,68,68,53,58,68,68,67,59,63,59,56,59,82,62,62,59,56,59,52,59,57,59,68,59,63,67,60,64,60,182,60,68,60,69,60,710,59,70,67,61,62,57,75,62,62,69,58,62,62,62,62,70,48,68,68,68,69,17151,66,29639,66,30405,64,0,65,69,62,91,62,88,62,147,62,56,65,64,64,86,63,89,61,98,64,86,63,84,61,94,64,62,62,66,90,62,83,62,56,63,85,61,81,61,119,61,68,69],[64,70,64,64,70,70,64,69,64,64,69,64,69,64,69,64,64,69,69,64,64,64,64,64,64,64,63,64,64,64,64,64,64,61,64,64,64,64,64,64,64,60,64,64,64,61,64,73,64,73,63,66,63,73,64,69,63,73,64,73,65,73,64,70,64,64,69,69,64,70,64,70,62,70,63,69,62,70,64,70,64,70,64,70,64,70,64,64,73,64,73,64,73,64,73,63,73,63,73,65,64,64,70,64,61,70,70,64,64,70,70,64,70,64,64,69,64,70,64,60,99,68,104,67,104,66,0,60,70,61,75,61,75,61,75,62,69,72,72,59,71,59,71,60,78,60,70,60,70,60,73,72,72,77,59,70,60,70,64,70,62,76,62,76,62,77,70,65],[53,66,54,61,67,67,60,66,67,64,66,64,66,70,67,59,54,64,65,68,66,67,66,66,66,66,38,69,69,65,62,64,64,31,69,67,69,69,68,64,62,49,69,67,67,43,62,60,61,60,61,55,67,66,66,64,59,64,62,64,69,63,67,66,55,60,66,65,64,63,64,63,6878,63,893,63,6878,63,55,63,55,63,54,63,63,63,68,63,60,60,60,53,60,60,60,57,60,59,64,67,66,59,63,59,92,63,63,55,55,63,63,59,63,68,54,65,65,67,68,88,59,80,60,52,60,69,61,0,65,8514,65,7981,64,7024,65,65,66,64,64,59,63,52,63,51,63,65,63,56,63,51,63,64,64,63,52,62,56,62,156,65,45,66,28,65,44,66,67,66],[64,71,64,64,71,71,64,71,65,65,71,65,72,64,71,64,64,70,70,66,65,65,65,65,65,65,61,65,65,65,65,65,65,63,65,65,65,65,65,65,65,62,65,65,65,62,63,71,63,71,65,69,65,71,65,72,63,71,63,71,66,71,65,71,64,64,71,71,65,91,65,91,62,91,64,93,62,91,64,91,64,91,64,91,65,91,65,63,71,63,71,63,71,63,71,62,71,63,71,66,65,65,71,65,62,71,71,65,65,71,71,65,71,65,64,71,65,71,65,61,76,62,71,63,71,62,71,63,0,66,94,65,94,66,91,63,71,74,74,62,69,62,69,62,69,62,69,62,69,62,69,76,76,69,62,69,62,69,64,80,63,71,62,71,63,75,71,66],[62,71,63,64,70,71,63,70,63,64,70,64,70,73,71,61,60,68,68,66,71,71,66,77,77,77,39,67,67,81,81,80,80,33,67,67,67,67,66,80,81,22,67,73,74,63,62,59,61,59,55,49,60,59,67,63,107,59,62,59,65,61,65,71,61,61,70,70,65,61,65,61,563,61,4333,62,563,61,60,61,62,61,60,61,65,61,67,57,59,61,59,69,59,59,59,61,59,107,59,66,65,57,60,59,94,60,60,59,59,60,60,57,60,67,60,70,63,70,67,85,62,113,58,126,58,65,59,8510,63,0,65,39650,65,32055,65,65,67,67,67,79,64,54,64,51,63,82,64,58,64,56,63,67,67,67,57,63,61,63,57,63,191,64,161,64,160,62,71,66],[64,70,64,63,70,70,63,70,64,64,70,64,70,64,70,64,64,69,69,65,64,64,64,64,64,64,60,64,64,64,64,64,64,60,64,64,64,64,64,64,64,60,64,64,64,62,63,70,63,70,64,68,64,70,64,69,63,70,63,70,65,70,64,70,64,63,70,70,64,70,64,70,61,70,64,71,61,70,64,70,64,70,64,70,64,70,64,63,70,63,70,63,70,63,70,62,70,63,70,65,64,64,70,64,60,70,70,64,64,70,70,64,70,64,64,70,64,70,64,60,74,59,76,59,71,60,75,63,94,63,0,63,149,63,120,62,69,72,72,62,74,62,69,61,73,62,74,62,69,61,69,72,72,73,62,69,62,69,62,70,62,80,61,75,62,71,70,65],[65,71,65,64,70,71,63,70,64,64,70,64,70,74,70,60,59,68,68,62,68,68,63,74,74,74,24,63,63,78,78,77,77,28,63,63,63,63,65,77,78,28,63,70,71,57,62,59,61,59,55,50,58,59,65,63,107,59,62,59,65,61,65,71,63,61,70,70,65,61,63,61,563,61,4280,62,563,61,58,61,58,61,58,61,65,61,65,55,59,61,59,68,59,59,59,62,59,107,59,66,65,58,60,58,96,60,60,59,59,60,60,58,60,67,58,70,63,70,67,81,62,85,58,147,61,60,59,7977,64,39650,65,0,64,32099,65,54,67,67,67,56,64,90,68,54,63,58,64,97,68,60,63,67,67,67,94,64,100,64,40,62,161,64,191,63,159,62,71,67],[63,70,63,63,70,70,63,70,64,64,70,64,70,64,70,63,64,69,69,65,64,64,64,64,64,64,60,64,64,64,64,64,64,60,64,64,64,64,64,64,64,60,64,64,64,62,64,70,64,70,64,68,64,70,64,70,63,70,64,70,65,70,64,70,63,63,70,70,64,70,64,70,62,70,64,71,62,70,64,70,64,70,64,70,64,70,64,63,70,64,70,63,70,64,70,62,70,63,70,65,64,63,70,63,59,70,70,63,63,70,70,63,70,64,63,70,64,70,64,59,74,58,71,60,77,60,75,62,94,63,149,65,0,63,120,61,69,72,72,60,69,61,74,60,73,60,69,61,74,60,69,72,72,73,62,74,62,74,64,70,62,75,61,80,62,71,70,65],[68,71,61,68,70,71,68,70,70,65,70,68,70,78,70,60,64,69,69,66,67,64,65,64,64,64,25,66,65,62,61,60,60,36,66,65,65,66,66,64,61,14,65,65,66,60,68,61,67,61,61,56,59,61,65,64,113,61,68,61,69,61,69,71,61,66,70,70,70,62,66,62,522,62,3969,63,523,62,67,62,63,62,68,62,71,62,66,70,61,65,61,73,61,73,61,74,61,113,61,68,70,62,61,58,103,61,61,65,63,61,61,63,61,71,60,70,67,70,70,81,64,91,61,120,61,113,60,7020,64,32061,65,32105,65,0,65,58,68,67,67,66,63,66,63,108,62,66,63,65,63,113,62,67,67,66,68,63,67,63,47,64,158,64,156,64,202,62,71,70],[65,71,65,64,71,71,64,71,65,65,71,65,72,65,71,65,65,70,70,66,65,65,65,65,65,65,62,65,65,65,65,65,65,61,65,65,65,65,65,65,65,61,65,65,65,63,64,71,64,71,65,69,65,71,65,70,63,71,64,71,66,71,65,71,65,64,71,71,65,71,65,71,63,71,65,71,63,71,65,71,65,71,65,71,65,71,65,64,71,64,71,64,71,64,71,63,71,63,71,66,65,65,71,65,61,71,71,65,65,71,71,65,71,65,65,71,65,71,65,60,71,60,72,59,72,60,76,64,91,64,121,64,121,64,0,63,66,69,69,63,70,63,70,62,73,63,70,63,70,62,73,69,69,73,63,70,63,70,63,75,63,72,62,72,62,80,71,66],[54,65,57,60,65,65,60,62,66,65,62,66,62,63,63,64,66,63,63,68,68,68,67,67,66,66,53,69,67,67,67,66,66,54,67,66,69,68,68,67,67,43,69,68,67,63,62,63,62,63,60,59,65,63,68,63,67,62,62,62,67,62,64,65,55,59,64,65,64,62,68,62,40,62,60,60,40,62,51,62,52,62,51,62,65,62,66,58,63,61,63,69,63,62,63,59,63,67,62,65,65,59,59,60,38,60,59,59,59,59,59,57,59,66,140,64,60,65,66,79,63,66,62,63,62,48,62,51,61,64,60,48,59,45,60,0,69,69,69,8874,67,8798,68,8270,68,8365,67,8297,68,7699,68,69,69,62,8759,63,8258,63,82,63,77,63,67,62,55,63,65,67],[66,64,66,65,64,64,67,63,66,67,63,66,63,66,63,65,65,63,63,66,66,66,66,66,66,66,61,66,66,66,66,66,66,62,66,66,66,66,66,66,66,62,66,66,66,62,65,64,65,64,66,62,66,64,66,65,66,64,65,64,67,64,66,64,66,65,64,64,66,64,66,64,66,64,66,64,66,64,66,64,66,64,66,64,66,64,66,65,64,65,64,65,64,65,64,65,64,66,64,68,66,66,64,66,66,64,64,66,66,64,64,66,64,66,66,63,66,64,66,65,74,66,64,65,64,64,68,65,69,65,68,65,68,65,64,68,0,92,78,65,68,65,68,65,72,65,66,65,66,65,66,92,78,72,65,66,65,66,65,70,66,68,65,68,66,64,64,67],[62,99,62,61,94,98,62,95,59,60,95,58,95,86,98,58,59,86,86,61,61,61,61,61,61,61,59,62,61,61,61,61,61,58,61,61,61,61,61,61,61,59,61,61,61,61,59,66,59,66,60,64,61,67,61,68,64,66,59,66,62,67,60,99,62,60,93,97,60,66,61,66,55,66,64,66,55,66,61,66,61,66,61,66,60,66,61,58,66,59,66,63,66,58,66,60,66,64,66,63,60,59,67,59,54,67,67,59,59,67,67,58,67,60,62,97,60,94,60,59,76,58,66,68,66,58,70,60,71,63,70,63,70,64,66,64,92,0,639,65,200,65,191,63,166,66,198,65,189,62,160,631,610,435,62,186,62,186,63,73,72,71,72,71,70,67,98,61],[65,102,65,65,97,101,64,98,62,61,98,61,98,89,101,62,63,89,89,64,64,64,64,64,64,64,62,65,64,64,64,64,64,61,64,64,64,64,64,64,64,62,64,64,64,64,62,69,62,69,63,67,64,70,64,71,66,69,62,69,65,70,63,102,65,64,96,100,63,69,64,69,57,69,67,69,57,69,62,69,62,69,62,69,63,69,64,62,69,62,69,66,69,61,69,62,69,66,69,64,63,62,70,62,57,70,70,62,62,70,70,61,70,63,65,100,63,97,63,61,79,61,69,71,69,61,73,63,74,66,73,66,73,67,69,67,80,642,0,68,203,68,194,67,169,69,201,68,192,66,163,613,619,439,65,189,65,189,65,76,75,74,75,74,73,70,101,64],[67,66,69,49,65,66,49,70,65,64,70,64,70,62,64,69,51,65,65,67,66,69,66,66,65,65,37,68,67,68,67,67,67,64,68,68,68,67,66,68,67,69,68,66,66,56,59,62,60,62,53,48,60,62,65,62,84,60,58,60,66,59,67,66,69,49,71,71,62,62,67,62,44,62,47,59,44,62,52,62,54,62,52,62,62,62,69,56,62,59,62,78,62,57,62,61,62,84,60,64,63,57,61,60,33,62,61,59,59,61,61,58,61,65,68,71,64,65,65,80,59,114,59,72,59,69,59,59,60,81,59,49,58,57,59,8866,65,63,63,0,94,35235,90,25113,89,35681,94,32266,90,22960,89,63,63,64,34945,92,31976,92,69,62,127,64,98,62,87,64,66,65],[62,98,63,62,94,98,61,93,63,61,93,61,93,87,93,61,61,93,97,63,63,63,63,63,63,63,60,63,63,63,63,63,63,58,63,63,63,63,63,63,63,61,63,63,63,62,61,68,61,68,61,65,63,68,63,68,67,68,61,68,64,68,61,98,63,62,94,98,62,68,63,68,60,68,64,68,60,68,59,68,59,68,59,68,62,68,62,61,68,61,68,66,68,60,68,61,68,67,68,63,63,62,69,63,60,69,69,62,62,70,69,61,69,62,63,98,61,94,62,62,69,63,80,72,75,62,71,61,68,62,74,62,69,60,69,65,69,204,204,95,0,94,538,87,389,95,619,94,531,87,386,204,204,167,92,513,92,513,65,69,71,76,73,71,72,71,98,62],[67,65,67,50,65,65,51,70,61,65,70,65,70,62,65,67,56,62,62,63,62,65,62,62,61,61,32,65,63,64,63,63,63,59,65,65,64,65,62,64,63,63,65,62,62,53,58,62,58,62,53,48,58,62,63,62,81,60,57,60,66,59,67,65,67,49,70,70,62,62,65,62,41,62,47,59,41,62,49,62,49,62,49,62,62,62,67,56,62,57,62,78,62,55,62,61,62,81,60,64,63,58,61,58,27,62,61,59,59,61,61,58,61,65,66,70,63,65,65,71,59,81,59,88,59,65,59,48,60,50,59,111,58,63,59,8790,65,62,62,34661,93,0,98,25382,89,31655,93,36731,98,23221,89,62,62,64,40178,103,36390,103,62,62,94,64,111,63,87,64,65,64],[60,98,61,63,94,98,63,93,63,61,93,61,93,87,93,61,61,93,97,62,62,62,62,62,62,62,61,62,62,62,62,62,62,58,62,62,62,62,62,62,62,60,62,62,62,61,63,68,63,68,61,65,63,68,63,69,66,68,63,68,64,68,61,98,61,63,93,97,62,68,63,68,59,68,64,68,59,68,59,68,59,68,59,68,62,68,62,62,68,63,68,65,68,63,68,62,68,66,68,64,63,62,69,62,56,69,69,62,62,70,69,62,69,62,61,97,61,94,62,61,69,59,75,73,79,58,71,61,68,62,69,63,75,60,69,65,69,195,195,92,538,99,0,85,389,92,531,99,653,85,386,194,194,167,97,615,97,615,63,69,73,71,71,76,72,71,98,62],[58,67,54,51,65,67,52,70,68,63,70,65,70,73,65,54,59,64,66,62,62,65,62,61,62,64,20,65,63,66,65,62,62,59,63,63,63,63,62,61,63,54,63,66,62,50,66,63,68,63,59,55,59,61,63,63,86,63,65,63,67,61,64,67,53,51,70,70,70,63,66,63,47,63,52,60,48,63,56,63,52,63,57,63,71,63,60,62,63,66,63,74,63,64,63,58,63,86,63,67,66,63,62,59,42,63,62,65,64,62,62,64,62,68,54,69,67,65,70,66,62,62,59,70,58,88,59,59,61,47,60,45,59,112,60,8284,66,65,65,25113,88,25383,86,0,99,22953,88,23215,86,37820,99,64,65,65,25247,88,23079,88,65,63,96,65,96,63,135,63,67,68],[64,91,63,64,89,91,63,88,62,63,88,63,88,82,88,62,63,88,90,64,64,64,64,64,64,64,63,64,64,64,64,64,64,59,64,64,64,64,64,64,64,61,64,64,64,64,63,69,63,69,63,67,64,69,64,69,67,69,63,69,65,69,63,91,62,64,88,90,64,69,64,69,63,69,66,69,63,69,63,69,62,69,63,69,64,69,63,63,69,63,69,66,69,63,69,63,69,67,69,65,64,64,70,64,61,70,70,64,64,70,70,63,70,64,62,90,63,89,64,63,73,63,72,74,72,66,79,64,69,65,74,65,74,64,73,69,74,170,170,89,390,89,390,101,0,89,387,89,387,101,655,170,170,222,89,382,89,382,64,70,75,76,75,76,74,77,91,64],[63,62,65,40,62,62,40,66,61,60,66,60,66,59,61,65,44,60,61,64,62,65,62,62,62,62,29,64,63,63,62,62,62,59,64,64,64,63,62,63,62,75,64,62,62,56,55,58,56,58,51,46,58,58,61,58,79,56,55,56,62,57,63,62,65,39,68,68,58,58,63,58,40,58,41,55,40,58,53,58,55,58,53,58,58,58,65,52,58,55,58,72,58,53,58,57,58,79,56,60,59,54,57,57,37,58,57,56,56,57,57,55,57,61,64,68,60,62,61,77,55,108,56,68,55,64,55,59,56,83,55,47,55,65,55,8351,61,60,60,35677,90,32262,86,22949,85,0,90,35328,86,25217,85,60,60,62,31972,88,35038,88,64,58,122,57,92,56,88,58,62,61],[58,94,59,58,90,94,57,89,59,57,89,57,89,83,89,57,57,89,93,59,59,59,59,59,59,59,56,59,59,59,59,59,59,54,59,59,59,59,59,59,59,57,59,59,59,58,57,64,57,64,57,61,59,64,59,64,63,64,57,64,60,64,57,94,59,58,90,94,58,64,59,64,56,64,60,64,56,64,55,64,55,64,55,64,58,64,58,57,64,57,64,62,64,56,64,57,64,63,64,59,59,58,65,59,56,65,65,58,58,65,65,57,65,58,59,94,57,90,58,58,65,59,71,68,66,58,66,57,64,58,70,58,65,56,65,61,63,198,198,91,615,90,527,83,382,91,0,90,538,83,389,198,198,160,88,509,88,513,61,65,67,71,69,66,68,66,94,58],[63,61,63,42,61,61,43,66,57,61,66,61,66,58,60,63,47,58,58,60,58,61,58,58,58,58,23,61,59,59,58,58,58,54,60,60,60,59,60,59,58,70,60,58,58,53,55,58,55,58,51,46,56,58,59,58,76,56,55,56,62,57,63,61,63,41,66,66,58,58,61,58,37,58,40,55,37,58,52,58,52,58,52,58,58,58,63,52,58,54,58,72,58,52,58,57,58,76,56,60,59,55,57,55,31,58,57,56,56,57,57,55,57,61,62,66,59,61,61,66,55,77,56,96,55,62,55,50,56,53,55,132,55,65,55,8283,61,58,58,31651,89,36727,94,23210,85,34749,89,0,94,25482,85,58,58,61,36386,99,40265,99,58,57,90,57,106,59,87,58,61,60],[56,94,57,59,90,94,59,89,59,57,89,57,89,83,89,57,57,89,93,58,58,58,58,58,58,58,57,58,58,58,58,58,58,54,58,58,58,58,58,58,58,56,58,58,58,57,59,64,59,64,57,61,59,64,59,65,62,64,59,64,60,64,57,94,57,59,89,93,58,64,59,64,55,64,60,64,55,64,55,64,55,64,55,64,58,64,58,58,64,59,64,61,64,59,64,58,64,62,64,60,59,58,65,58,52,65,65,58,58,65,65,58,65,58,57,93,57,90,58,57,65,55,66,69,70,54,66,57,64,58,65,59,71,56,65,61,63,189,189,88,527,95,649,81,382,88,538,95,0,81,389,188,188,160,93,611,93,615,59,65,69,66,67,71,68,66,94,58],[48,63,44,42,61,63,42,66,64,58,66,60,66,69,61,47,52,60,62,59,59,61,59,59,58,60,24,62,60,62,61,59,59,45,60,60,60,60,59,58,59,61,60,62,59,47,61,59,63,59,55,51,56,57,59,59,81,59,61,59,63,58,60,63,43,41,67,68,66,59,62,59,44,59,49,56,45,59,57,59,52,59,58,59,67,59,56,58,59,61,59,70,59,59,59,54,59,81,59,63,64,59,58,55,45,59,58,61,60,58,58,60,58,64,44,67,63,61,66,58,58,62,56,68,55,80,55,56,57,44,56,39,56,107,56,7703,62,61,61,22956,84,23218,82,37816,95,25217,84,25483,82,0,95,60,61,61,23082,84,25347,84,60,59,95,58,94,57,132,60,63,64],[60,87,59,60,85,87,59,84,58,59,84,59,84,78,84,58,59,84,86,60,60,60,60,60,60,60,59,60,60,60,60,60,60,55,60,60,60,60,60,60,60,57,60,60,60,60,59,65,59,65,59,63,60,65,60,65,63,65,59,65,61,65,59,87,58,60,84,86,60,65,60,65,59,65,62,65,59,65,59,65,58,65,59,65,60,65,59,59,65,59,65,62,65,59,65,59,65,63,65,61,60,60,66,60,57,66,66,60,60,66,66,59,66,60,58,86,59,85,60,59,65,59,67,70,67,62,70,60,65,61,66,61,66,60,69,65,64,160,160,85,383,85,383,97,651,85,390,85,390,97,0,160,160,211,85,378,85,382,60,66,71,67,71,67,70,72,87,60],[59,96,59,58,91,95,59,92,57,57,92,55,92,83,95,55,56,83,83,58,58,58,58,58,58,58,56,59,58,58,58,58,58,55,57,57,58,58,58,58,58,56,58,58,58,58,55,63,55,63,57,61,58,64,58,65,61,63,55,63,59,64,57,96,59,57,90,94,57,63,58,63,53,63,59,63,53,63,58,63,58,63,58,63,57,63,58,55,63,55,63,60,63,54,63,57,63,61,63,60,57,55,63,55,48,63,63,55,55,63,63,54,63,57,59,94,57,91,57,56,73,55,63,65,63,55,67,57,69,60,67,56,67,61,63,61,89,629,608,62,198,61,188,60,163,63,196,62,186,59,157,0,661,457,58,183,59,183,60,70,69,68,69,68,66,64,95,58],[62,99,62,62,94,98,61,95,60,58,95,58,95,86,98,59,60,86,86,61,61,61,61,61,61,61,59,62,61,61,61,61,61,58,60,60,61,61,61,61,61,59,61,61,61,61,58,66,58,66,60,64,61,67,61,68,63,66,58,66,62,67,60,99,62,61,93,97,60,66,61,66,55,66,62,66,55,66,59,66,59,66,59,66,60,66,61,59,66,58,66,63,66,57,66,57,66,63,66,61,60,58,66,58,51,66,66,58,58,66,66,58,66,60,62,97,60,94,60,58,76,58,66,68,66,58,70,60,72,63,70,59,70,64,66,64,77,611,617,65,201,64,191,64,166,66,199,65,189,63,160,664,0,461,61,186,62,186,62,73,72,71,72,71,69,67,98,61],[61,89,61,61,87,90,61,88,61,60,88,60,88,79,91,59,60,90,92,61,61,61,61,61,61,61,59,62,61,61,61,61,61,58,60,60,61,61,61,61,61,59,61,61,61,62,59,66,59,66,61,65,61,67,61,66,64,66,59,66,62,67,61,89,61,61,86,88,61,66,61,66,55,66,63,66,55,66,59,66,59,66,59,66,61,66,61,58,66,59,66,63,66,59,66,58,66,64,66,62,61,59,66,58,57,66,66,59,59,66,66,59,66,61,61,88,61,87,61,56,70,58,68,68,68,58,75,60,66,63,71,59,71,63,69,65,71,435,436,65,164,64,164,63,218,66,161,65,161,62,211,460,461,0,61,161,62,161,63,67,72,73,72,73,70,73,89,61],[61,60,62,44,60,60,45,65,59,57,65,57,65,60,60,62,50,58,58,58,57,60,57,57,56,56,45,60,58,59,58,58,58,54,60,60,59,60,57,59,58,58,60,57,57,51,53,57,53,57,49,44,53,57,58,57,77,55,52,55,61,54,61,60,62,43,65,65,60,57,60,57,36,57,41,54,36,57,45,57,44,57,45,57,60,57,62,51,57,52,57,74,57,50,57,56,57,77,55,59,57,52,55,53,16,56,55,50,50,55,55,52,55,61,61,65,58,60,61,66,54,75,54,92,54,61,54,43,56,47,54,108,54,60,54,8746,60,54,54,34366,86,40173,92,25241,82,31360,86,36385,92,23080,82,55,55,57,0,96,36704,96,58,57,87,59,105,58,75,57,60,59],[55,93,56,58,89,93,58,88,58,56,88,56,88,82,88,56,57,88,92,57,57,57,57,57,57,57,56,57,57,57,57,57,57,54,57,57,57,57,57,57,57,56,57,57,57,57,58,63,58,63,56,60,58,63,58,64,62,63,58,63,59,63,56,93,56,58,88,92,57,63,58,63,54,63,59,63,54,63,53,63,53,63,53,63,57,63,57,57,63,58,63,60,63,58,63,57,63,62,63,59,58,56,64,56,51,64,64,56,56,64,64,56,64,57,56,92,56,89,57,55,64,57,65,70,69,55,65,56,63,58,64,58,69,56,64,61,62,185,185,89,508,100,610,82,376,89,508,100,610,82,376,184,184,159,100,0,100,655,60,64,70,65,68,70,69,65,93,57],[57,56,58,36,55,56,37,61,55,50,61,50,61,55,54,58,41,54,54,55,53,56,53,53,53,53,44,56,54,54,53,53,53,49,55,55,55,54,55,54,53,65,55,53,53,51,50,53,50,53,47,42,51,53,54,53,72,51,50,51,57,52,57,56,58,35,61,61,56,53,56,53,32,53,35,50,32,53,44,53,47,53,44,53,56,53,58,47,53,49,53,68,53,47,53,52,53,72,51,55,55,49,51,50,19,52,51,47,47,51,51,49,51,57,57,61,54,55,57,61,50,71,51,92,50,59,50,45,52,50,50,130,50,62,50,8239,56,50,50,31356,82,36381,88,23069,78,34454,82,40260,88,25341,78,51,51,54,36700,92,0,92,54,53,83,52,99,54,71,54,56,55],[51,89,52,54,85,89,54,84,54,52,84,52,84,78,84,52,53,84,88,53,53,53,53,53,53,53,52,53,53,53,53,53,53,50,53,53,53,53,53,53,53,52,53,53,53,53,54,59,54,59,52,56,54,59,54,60,58,59,54,59,55,59,52,89,52,54,84,88,53,59,54,59,50,59,55,59,50,59,49,59,49,59,49,59,53,59,53,53,59,54,59,56,59,54,59,53,59,58,59,55,54,52,60,52,47,60,60,52,52,60,60,52,60,53,52,88,52,85,53,51,60,53,61,66,65,51,61,52,59,54,60,54,65,52,60,57,58,181,181,85,504,96,606,78,372,85,508,96,610,78,376,180,180,155,96,651,96,0,56,60,66,61,64,66,65,61,89,53],[56,64,58,61,64,64,60,62,64,63,62,63,62,65,63,62,54,60,59,69,69,69,69,69,68,69,42,70,68,69,69,69,69,44,70,69,69,68,69,69,69,56,68,69,69,46,62,63,62,63,69,64,69,63,68,64,58,63,62,63,69,64,67,64,63,60,62,62,67,62,69,62,79,62,69,63,79,62,59,62,60,62,59,62,67,62,68,63,63,62,63,59,63,59,63,58,63,58,63,68,66,117,63,118,1812,63,63,117,117,63,63,116,63,68,62,61,63,64,68,92,64,75,66,63,66,64,66,109,61,63,64,78,64,57,64,82,67,66,65,65,64,55,64,45,66,65,64,59,64,46,66,66,65,66,55,66,59,66,0,63,9169,64,9139,64,8305,64,64,68],[65,71,65,65,71,71,65,70,65,65,70,65,71,64,70,62,63,71,71,65,65,65,65,65,65,65,64,65,65,65,65,65,65,63,65,65,65,65,65,65,65,63,65,65,65,63,65,71,65,71,65,69,65,71,65,72,65,71,65,71,66,71,65,71,65,65,71,71,65,71,65,71,64,71,65,71,64,71,63,71,63,71,63,71,65,71,65,64,71,65,71,63,71,65,71,64,71,65,71,66,65,64,102,64,63,101,102,64,64,102,102,64,102,65,65,70,65,71,65,59,77,63,71,63,71,62,71,64,80,62,71,62,71,60,75,64,72,76,76,63,70,62,70,62,70,61,70,60,70,61,70,76,76,70,62,70,60,70,62,0,64,84,64,84,64,84,71,66],[55,73,57,59,73,73,58,72,65,62,72,62,72,74,73,57,55,72,73,71,71,71,71,71,70,71,36,72,70,71,71,71,71,53,71,71,71,71,71,71,71,38,71,71,71,59,66,62,66,62,61,57,67,62,69,63,79,62,66,62,66,62,63,73,55,58,72,73,64,62,67,62,49,62,64,59,49,62,57,62,59,62,57,62,65,62,66,62,62,66,62,72,62,60,62,62,62,79,62,67,66,69,62,72,764,62,62,68,66,62,62,69,62,66,55,72,65,73,66,77,62,96,62,90,62,68,62,38,61,177,61,150,61,146,61,74,66,74,74,109,75,76,75,93,75,111,75,78,75,94,75,74,74,75,77,76,79,76,9164,62,0,65,25935,65,21362,65,73,67],[64,71,64,64,71,71,64,71,64,64,71,64,71,65,71,64,64,70,70,64,64,64,64,64,64,64,63,64,64,64,64,64,64,63,64,64,64,64,64,64,64,64,64,64,64,63,63,70,63,70,64,68,64,70,64,69,66,70,63,70,65,70,64,71,64,64,71,71,64,70,64,70,62,70,63,70,62,70,64,70,64,70,64,70,64,70,64,63,70,63,70,64,70,63,70,63,70,66,70,65,64,64,70,64,63,70,70,64,64,70,70,64,70,64,64,71,64,71,64,61,74,61,78,65,73,60,76,65,70,64,80,64,75,63,71,64,69,73,73,63,76,63,71,64,75,63,75,63,70,63,70,73,73,75,63,70,63,70,63,82,66,0,66,135,66,101,71,65],[53,73,53,57,73,73,56,72,65,62,72,62,72,73,72,55,52,71,71,67,67,67,67,67,66,67,30,68,66,67,67,67,67,48,67,67,67,67,67,67,67,35,67,67,67,57,65,62,65,62,61,57,65,62,67,63,77,62,65,62,66,62,63,73,52,56,72,73,64,61,65,61,45,61,64,59,45,61,57,61,57,61,57,61,65,61,64,57,62,65,62,72,62,59,62,61,62,77,62,67,66,68,62,69,761,62,62,66,65,62,62,68,62,66,52,72,64,73,66,69,62,67,62,117,62,64,62,33,61,148,61,181,61,143,61,66,65,74,74,83,75,94,77,92,75,85,75,105,77,93,75,74,74,75,95,78,104,78,9135,62,25935,65,0,65,21356,65,73,67],[64,71,64,64,71,71,64,71,64,64,71,64,71,65,71,64,64,71,71,64,64,64,64,64,64,64,63,64,64,64,64,64,64,63,64,64,64,64,64,64,64,64,64,64,64,63,63,70,63,70,64,68,64,70,64,70,66,70,63,70,65,70,64,71,64,64,71,71,64,70,64,70,61,70,63,70,61,70,63,70,63,70,63,70,64,70,64,63,70,63,70,64,70,63,70,63,70,66,70,65,64,64,70,64,61,70,70,64,64,70,70,64,70,64,64,71,64,71,64,61,74,60,73,64,79,59,76,64,70,64,75,63,80,63,71,63,69,73,73,62,71,66,77,62,75,62,70,66,76,62,70,73,73,75,66,76,66,76,63,82,66,135,66,0,66,101,71,65],[60,72,56,63,72,72,63,71,71,67,71,73,71,75,72,56,60,71,72,62,66,67,66,66,65,65,39,65,65,65,65,63,61,54,65,65,65,65,61,64,64,50,65,65,66,56,70,63,73,63,67,63,66,63,68,64,89,63,70,63,69,63,69,72,55,62,71,72,71,63,67,63,52,63,68,63,70,63,62,63,58,63,63,63,72,63,65,69,63,67,63,78,63,70,63,68,63,89,63,70,71,58,63,54,749,63,63,72,58,63,63,59,63,71,53,71,70,72,70,72,64,64,63,84,63,103,63,64,62,144,60,144,60,174,61,67,67,73,73,77,72,74,72,138,74,78,72,75,72,135,74,72,72,73,75,74,74,74,8300,63,21363,66,21357,66,0,67,72,70],[66,72,65,66,72,72,66,72,66,66,72,66,73,66,72,65,66,71,71,65,65,65,65,65,65,65,66,65,65,65,65,65,65,63,65,65,65,65,65,65,65,65,65,65,65,64,66,71,66,71,66,70,65,71,65,70,66,71,66,71,66,71,66,72,65,66,72,72,66,71,65,71,66,71,64,71,66,71,66,71,65,71,66,71,66,71,65,66,71,66,71,64,71,66,71,66,71,66,71,67,66,66,71,65,66,71,71,66,66,71,71,66,71,66,65,72,66,72,66,63,71,63,73,66,73,61,78,66,75,64,72,64,72,63,80,65,66,70,70,65,72,65,72,66,77,65,71,65,71,66,76,70,70,76,65,71,65,71,64,83,67,102,67,102,67,0,72,67],[76,144,76,76,131,159,76,127,75,76,127,76,127,122,130,76,76,108,112,76,76,76,76,76,76,76,74,76,76,76,76,76,76,72,76,76,76,76,76,76,76,73,76,76,76,75,75,82,75,82,76,80,76,82,76,81,82,82,75,82,77,82,76,144,75,76,115,128,76,82,76,82,73,82,82,82,73,82,75,82,75,82,75,82,76,82,76,75,82,75,82,77,82,75,82,74,82,82,82,77,76,76,82,76,74,82,82,76,76,82,82,76,82,76,75,128,76,131,76,77,82,80,82,85,82,80,82,78,82,81,82,81,82,81,82,79,77,111,111,80,110,80,110,80,102,81,110,80,110,80,102,111,111,102,79,110,79,110,76,82,86,83,86,83,84,83,0,77],[75,69,71,76,69,69,76,69,76,76,69,76,69,76,68,71,75,69,69,72,72,72,72,72,72,72,68,73,72,72,72,72,72,68,72,72,72,72,72,72,72,66,72,72,72,66,76,69,76,69,76,72,72,69,72,68,76,69,76,69,72,69,76,69,72,76,69,69,76,69,72,69,74,69,75,69,74,69,75,69,71,69,75,69,76,69,72,75,69,76,69,75,69,76,69,75,69,76,69,78,77,76,70,72,76,70,70,76,76,70,70,76,70,77,71,69,76,69,77,68,69,70,69,70,69,74,69,67,69,71,69,70,69,73,69,71,72,67,67,71,67,70,67,73,68,71,67,70,67,73,68,67,67,68,70,67,70,67,71,69,71,69,70,69,73,70,69,0]] \ No newline at end of file diff --git a/external/cmapscompress/README.md b/external/cmapscompress/README.md index 9796eb20b9b52d..ee6eaca1747e64 100644 --- a/external/cmapscompress/README.md +++ b/external/cmapscompress/README.md @@ -1,6 +1,6 @@ # Quick notes about binary CMap format (bcmap) -The format is designed to package some information from the CMap files located at external/cmap. Please notice for size optimization reasons, the original information blocks can be changed (split or joined) and items in the blocks can be swaped. +The format is designed to package some information from the CMap files located at external/cmap. Please notice for size optimization reasons, the original information blocks can be changed (split or joined) and items in the blocks can be swapped. The data stored in binary format in network byte order (big-endian). @@ -15,6 +15,55 @@ The following primitives used during encoding of the file: - signed fixed number (SB[n]) – similar to the SN, but it represents a signed number that is stored in B[n] - string (S) – the string is encoded as sequence of bytes. First comes length is characters encoded as UN, when UTF16 characters encoded as UN. +# Differential compression + +The contents of each CMap file is either stored normally or differentially. In the latter case, a second CMap file (the 'base file') is needed for file decoding. + +The first record in each file indicates if the file is stored normally or differentially. +It is a *baseFileName* string (S) which + - is empty ('') if the file is stored normally, or + - contains the file name of the base file (without path or extension) if it is stored differentially. + +The second record, *contentSize*, is an unsigned number (UN) which contains + - the number of bytes to follow if the file is stored normally ('the file contents'), or + - the number of bytes to reconstruct via differential compression (see below). + +In either case, the (possibly decoded) file contents are then structured as described in the [file structure](#file-structure) section. + +### Decoding differential data + +If a CMap file (let's name it *A*) is stored differentially, file contents are to be constructed from the contents of *A* and from the base file (which we shall call *B*). +The records to follow are alternately of the following type, starting with *copy*. + +A **copy**-type instruction specified by + - startDelta as UN + - length as UN + +which instructs to read *length* bytes from *B*, where startDelta specifies the start position as an offset from the previously used array end. (The previous array end is initialized with the position of the start of content, i.e., after *baseFileName* and *contentSize* in *B*). + +An **insert**-type instruction is specified by + - length as UN + +and instructs to read append the following *length* bytes from *A* and append it to the contents. + +It may happen that file *B* itself is stored differentially and depends on a further file. In this case, *B* has to be restored before restoring *A*. The following pseudocode accomplishes the decoding +``` +var contents = ''; +var previousEnd = 0; // position after *baseFileName* and *contentSize* in baseFile +for (var copy = true; contents.length < contentSize; copy = !copy) { + if (copy) { + var start = previousEnd + A.readUN(); + var length = A.readUN(); + contents.append(B.subarray(start, start + length)); + previousEnd = start + length; + } else { + var length = A.readUN(); + contents.append(A.readBytes(length)); + } +} +``` + + # File structure The first byte is a header: diff --git a/external/cmapscompress/compress.js b/external/cmapscompress/compress.js index 078cfe63f28ab0..82b2199805167f 100644 --- a/external/cmapscompress/compress.js +++ b/external/cmapscompress/compress.js @@ -13,6 +13,8 @@ * limitations under the License. */ +'use strict'; + var fs = require('fs'); var path = require('path'); var parseAdobeCMap = require('./parse.js').parseAdobeCMap; @@ -112,8 +114,8 @@ function compressCmap(srcPath, destPath, verify) { fs.writeFileSync(destPath, new Buffer(out, 'hex')); if (verify) { - var result2 = parseCMap(out); - var isGood = JSON.stringify(inputData) == JSON.stringify(result2); + var result2 = new BinaryCMapReader(out).parse(); + var isGood = JSON.stringify(inputData) === JSON.stringify(result2); if (!isGood) { throw new Error('Extracted data does not match the expected result'); } @@ -125,193 +127,195 @@ function compressCmap(srcPath, destPath, verify) { }; } -function parseCMap(binaryData) { - var reader = { - buffer: binaryData, - pos: 0, - end: binaryData.length, - readByte: function () { - if (this.pos >= this.end) { - return -1; +function BinaryCMapReader(binaryData) { + this.buffer = binaryData; + this.pos = 0; + this.end = binaryData.length; +} + +BinaryCMapReader.prototype = { + readByte: function () { + if (this.pos >= this.end) { + return -1; + } + var d1 = fromHexDigit(this.buffer[this.pos]); + var d2 = fromHexDigit(this.buffer[this.pos + 1]); + this.pos += 2; + return (d1 << 4) | d2; + }, + readNumber: function () { + var n = 0; + var last; + do { + var b = this.readByte(); + last = !(b & 0x80); + n = (n << 7) | (b & 0x7F); + } while (!last); + return n; + }, + readSigned: function () { + var n = this.readNumber(); + return (n & 1) ? -(n >>> 1) - 1 : n >>> 1; + }, + readHex: function (size) { + var lengthInChars = (size + 1) << 1; + var s = this.buffer.substr(this.pos, lengthInChars); + this.pos += lengthInChars; + return s; + }, + readHexNumber: function (size) { + var lengthInChars = (size + 1) << 1; + var stack = []; + do { + var b = this.readByte(); + var last = !(b & 0x80); + stack.push(b & 0x7F); + } while (!last); + var s = '', buffer = 0, bufferSize = 0; + while (s.length < lengthInChars) { + while (bufferSize < 4 && stack.length > 0) { + buffer = (stack.pop() << bufferSize) | buffer; + bufferSize += 7; } - var d1 = fromHexDigit(this.buffer[this.pos]); - var d2 = fromHexDigit(this.buffer[this.pos + 1]); - this.pos += 2; - return (d1 << 4) | d2; - }, - readNumber: function () { - var n = 0; - var last; - do { - var b = this.readByte(); - last = !(b & 0x80); - n = (n << 7) | (b & 0x7F); - } while (!last); - return n; - }, - readSigned: function () { - var n = this.readNumber(); - return (n & 1) ? -(n >>> 1) - 1 : n >>> 1; - }, - readHex: function (size) { - var lengthInChars = (size + 1) << 1; - var s = this.buffer.substr(this.pos, lengthInChars); - this.pos += lengthInChars; - return s; - }, - readHexNumber: function (size) { - var lengthInChars = (size + 1) << 1; - var stack = []; - do { - var b = this.readByte(); - last = !(b & 0x80); - stack.push(b & 0x7F); - } while (!last); - var s = '', buffer = 0, bufferSize = 0; - while (s.length < lengthInChars) { - while (bufferSize < 4 && stack.length > 0) { - buffer = (stack.pop() << bufferSize) | buffer; - bufferSize += 7; + s = toHexDigit(buffer & 15) + s; + buffer >>= 4; + bufferSize -= 4; + } + return s; + }, + readHexSigned: function (size) { + var num = this.readHexNumber(size); + var sign = fromHexDigit(num[num.length - 1]) & 1 ? 15 : 0; + var c = 0; + var result = ''; + for (var i = 0; i < num.length; i++) { + c = (c << 4) | fromHexDigit(num[i]); + result += toHexDigit(sign ? (c >> 1) ^ sign : (c >> 1)); + c &= 1; + } + return result; + }, + readString: function () { + var len = this.readNumber(); + var s = ''; + for (var i = 0; i < len; i++) { + s += String.fromCharCode(this.readNumber()); + } + return s; + }, + parse: function() { + var header = this.readByte(); + var result = { + type: header >> 1, + wmode: header & 1, + comment: null, + usecmap: null, + body: [] + }; + + var b; + while ((b = this.readByte()) >= 0) { + var type = b >> 5; + if (type === 7) { + switch (b & 0x1F) { + case 0: + result.comment = this.readString(); + break; + case 1: + result.usecmap = this.readString(); + break; } - s = toHexDigit(buffer & 15) + s; - buffer >>= 4; - bufferSize -= 4; + continue; } - return s; - }, - readHexSigned: function (size) { - var num = this.readHexNumber(size); - var sign = fromHexDigit(num[num.length - 1]) & 1 ? 15 : 0; - var c = 0; - var result = ''; - for (var i = 0; i < num.length; i++) { - c = (c << 4) | fromHexDigit(num[i]); - result += toHexDigit(sign ? (c >> 1) ^ sign : (c >> 1)); - c &= 1; + var sequence = !!(b & 0x10); + var dataSize = b & 15; + var subitems = []; + var item = { + type: type, + items: subitems + }; + if (sequence) { + item.sequence = true; } - return result; - }, - readString: function () { - var len = this.readNumber(); - var s = ''; - for (var i = 0; i < len; i++) { - s += String.fromCharCode(this.readNumber()); - } - return s; - } - }; - - var header = reader.readByte(); - var result = { - type: header >> 1, - wmode: header & 1, - comment: null, - usecmap: null, - body: [] - }; - - var b; - while ((b = reader.readByte()) >= 0) { - var type = b >> 5; - if (type === 7) { - switch (b & 0x1F) { + var ucs2DataSize = 1; + var subitemsCount = this.readNumber(); + var start, end, code, char; + switch (type) { case 0: - result.comment = reader.readString(); + start = this.readHex(dataSize); + end = addHex(this.readHexNumber(dataSize), start); + subitems.push({start: start, end: end}); + for (var i = 1; i < subitemsCount; i++) { + start = addHex(this.readHexNumber(dataSize), incHex(end)); + end = addHex(this.readHexNumber(dataSize), start); + subitems.push({start: start, end: end}); + } break; case 1: - result.usecmap = reader.readString(); - break; - } - continue; - } - var sequence = !!(b & 0x10); - var dataSize = b & 15; - var subitems = []; - var item = { - type: type, - items: subitems - }; - if (sequence) { - item.sequence = true; - } - var ucs2DataSize = 1; - var subitemsCount = reader.readNumber(); - var start, end, code, char; - switch (type) { - case 0: - start = reader.readHex(dataSize); - end = addHex(reader.readHexNumber(dataSize), start); - subitems.push({start: start, end: end}); - for (var i = 1; i < subitemsCount; i++) { - start = addHex(reader.readHexNumber(dataSize), incHex(end)); - end = addHex(reader.readHexNumber(dataSize), start); - subitems.push({start: start, end: end}); - } - break; - case 1: - start = reader.readHex(dataSize); - end = addHex(reader.readHexNumber(dataSize), start); - code = reader.readNumber(); - subitems.push({start: start, end: end, code: code}); - for (var i = 1; i < subitemsCount; i++) { - start = addHex(reader.readHexNumber(dataSize), incHex(end)); - end = addHex(reader.readHexNumber(dataSize), start); - code = reader.readNumber(); + start = this.readHex(dataSize); + end = addHex(this.readHexNumber(dataSize), start); + code = this.readNumber(); subitems.push({start: start, end: end, code: code}); - } - break; - case 2: - char = reader.readHex(dataSize); - code = reader.readNumber(); - subitems.push({char: char, code: code}); - for (var i = 1; i < subitemsCount; i++) { - char = sequence ? incHex(char) : addHex(reader.readHexNumber(dataSize), incHex(char)); - code = reader.readSigned() + (code + 1); + for (var i = 1; i < subitemsCount; i++) { + start = addHex(this.readHexNumber(dataSize), incHex(end)); + end = addHex(this.readHexNumber(dataSize), start); + code = this.readNumber(); + subitems.push({start: start, end: end, code: code}); + } + break; + case 2: + char = this.readHex(dataSize); + code = this.readNumber(); subitems.push({char: char, code: code}); - } - break; - case 3: - start = reader.readHex(dataSize); - end = addHex(reader.readHexNumber(dataSize), start); - code = reader.readNumber(); - subitems.push({start: start, end: end, code: code}); - for (var i = 1; i < subitemsCount; i++) { - start = sequence ? incHex(end) : addHex(reader.readHexNumber(dataSize), incHex(end)); - end = addHex(reader.readHexNumber(dataSize), start); - code = reader.readNumber(); + for (var i = 1; i < subitemsCount; i++) { + char = sequence ? incHex(char) : addHex(this.readHexNumber(dataSize), incHex(char)); + code = this.readSigned() + (code + 1); + subitems.push({char: char, code: code}); + } + break; + case 3: + start = this.readHex(dataSize); + end = addHex(this.readHexNumber(dataSize), start); + code = this.readNumber(); subitems.push({start: start, end: end, code: code}); - } - break; - case 4: - char = reader.readHex(ucs2DataSize); - code = reader.readHex(dataSize); - subitems.push({char: char, code: code}); - for (var i = 1; i < subitemsCount; i++) { - char = sequence ? incHex(char) : addHex(reader.readHexNumber(ucs2DataSize), incHex(char)); - code = addHex(reader.readHexSigned(dataSize), incHex(code)); + for (var i = 1; i < subitemsCount; i++) { + start = sequence ? incHex(end) : addHex(this.readHexNumber(dataSize), incHex(end)); + end = addHex(this.readHexNumber(dataSize), start); + code = this.readNumber(); + subitems.push({start: start, end: end, code: code}); + } + break; + case 4: + char = this.readHex(ucs2DataSize); + code = this.readHex(dataSize); subitems.push({char: char, code: code}); - } - break; - case 5: - start = reader.readHex(ucs2DataSize); - end = addHex(reader.readHexNumber(ucs2DataSize), start); - code = reader.readHex(dataSize); - subitems.push({start: start, end: end, code: code}); - for (var i = 1; i < subitemsCount; i++) { - start = sequence ? incHex(end) : addHex(reader.readHexNumber(ucs2DataSize), incHex(end)); - end = addHex(reader.readHexNumber(ucs2DataSize), start); - code = reader.readHex(dataSize); + for (var i = 1; i < subitemsCount; i++) { + char = sequence ? incHex(char) : addHex(this.readHexNumber(ucs2DataSize), incHex(char)); + code = addHex(this.readHexSigned(dataSize), incHex(code)); + subitems.push({char: char, code: code}); + } + break; + case 5: + start = this.readHex(ucs2DataSize); + end = addHex(this.readHexNumber(ucs2DataSize), start); + code = this.readHex(dataSize); subitems.push({start: start, end: end, code: code}); - } - break; - default: - throw new Error('Unknown type: ' + type) + for (var i = 1; i < subitemsCount; i++) { + start = sequence ? incHex(end) : addHex(this.readHexNumber(ucs2DataSize), incHex(end)); + end = addHex(this.readHexNumber(ucs2DataSize), start); + code = this.readHex(dataSize); + subitems.push({start: start, end: end, code: code}); + } + break; + default: + throw new Error('Unknown type: ' + type); + } + result.body.push(item); } - result.body.push(item); + + return result; } - - return result; -} +}; function toHexDigit(n) { return n.toString(16); @@ -423,15 +427,41 @@ function incHex(a) { return s; } +function padRight(s, length) { + s = '' + s; + return s + new Array(Math.max(0, length - s.length + 1)).join(' '); +} + +function padLeft(s, length) { + s = '' + s; + return new Array(Math.max(0, length - s.length + 1)).join(' ') + s; +} + exports.compressCmaps = function (src, dest, verify) { var files = fs.readdirSync(src).filter(function (fn) { return fn.indexOf('.') < 0; // skipping files with the extension }); + + var sumPacked = 0; + var sumOrig = 0; files.forEach(function (fn) { var srcPath = path.join(src, fn); var destPath = path.join(dest, fn + '.bcmap'); var stats = compressCmap(srcPath, destPath, verify); - console.log('Compressing ' + fn + ': ' + stats.orig + ' vs ' + stats.packed + - ' ' + (stats.packed / stats.orig * 100).toFixed(1) + '%'); + sumOrig += stats.orig; + sumPacked += stats.packed; +// console.log(padRight(fn, 25) + +// padLeft(stats.packed, 7) + '/' + padLeft(stats.orig, 7) + ',' + +// padLeft((stats.packed / stats.orig * 100).toFixed(1) + '%', 7)); }); + console.log('-------------------------------------------------------'); + console.log(padRight('TOTAL', 25) + + padLeft(sumPacked, 7) + '/' + padLeft(sumOrig, 7) + ',' + + padLeft((sumPacked / sumOrig * 100).toFixed(1) + '%', 7)); }; + +exports.writeNumber = writeNumber; +exports.writeString = writeString; +exports.padLeft = padLeft; +exports.padRight = padRight; +exports.BinaryCMapReader = BinaryCMapReader; diff --git a/external/cmapscompress/differentialStorage.js b/external/cmapscompress/differentialStorage.js new file mode 100644 index 00000000000000..e2f78099320a74 --- /dev/null +++ b/external/cmapscompress/differentialStorage.js @@ -0,0 +1,844 @@ +/* Copyright 2014 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +var fs = require('fs'); +var path = require('path'); +var optimize = require('./optimize.js'); +var compress = require('./compress.js'); +var writeNumber = compress.writeNumber; +var writeString = compress.writeString; +var padLeft = compress.padLeft; +var padRight = compress.padRight; +var BinaryCMapReader = compress.BinaryCMapReader; +try { + var difflib = require('difflib'); +} catch (e) { + console.log('\ndifflib is not installed -- ' + + 'to intall, run "npm install difflib"'); + process.exit(0); +} + +function readFile(srcPath, filename) { + var content = fs.readFileSync(srcPath + '/' + filename, {encoding: 'hex'}); + return content; +} + +function hexToArray(content) { + var bytesAsArray = []; + for (var i = 0; i < content.length; i += 2) { + var hexByte = content.substring(i, i+2); + var intByte = parseInt(hexByte, 16); + bytesAsArray.push(intByte); + } + return bytesAsArray; +} + +function hexify(arr) { + return arr.map(function(e) { + var hex = e.toString(16); + if (hex.length === 1) { + hex = '0' + hex; + } + return hex; + }); +} + +function insert(patch, arg) { + // if last command was insert, just append arg to the args + // of the previous insert command + var last = patch[patch.length - 1]; + if (last && last.cmd === 'insert') { + last.arg = last.arg.concat(arg); + } else { + patch.push({ + cmd: 'insert', + arg: arg + }); + } +} +function copy(patch, arg) { + // if the last command was copy, add empty insert command + // to assure that copy and insert are always alternating. + var last = patch[patch.length - 1]; + if (last && last.cmd === 'copy') { + insert(patch, []); + } + patch.push({ + cmd: 'copy', + arg: arg + }); +} + + +//generate a patch that turns fileI into fileJ +function generatePatch(fileI, fileJ, ops) { + var patch = []; + var previousEnd = 0; + for (var c = 0; c < ops.length; c++) { + var op = ops[c]; + var cmd = op[0]; + var i1 = op[1]; + var i2 = op[2]; + var j1 = op[3]; + var j2 = op[4]; + switch (cmd) { + case 'replace': + insert(patch, fileJ.slice(j1, j2)); + break; + case 'delete': + break; + case 'insert': + insert(patch, fileJ.slice(j1, j2)); + break; + case 'equal': + var start = i1; + var startOffset = start - previousEnd; + var length = i2 - i1; + if (length === 1) { + insert(patch, [fileI[start]]); + } else if (length === 2) { + insert(patch, [fileI[start], fileI[start + 1]]); + } else { + copy(patch, [startOffset, length]); + previousEnd = start + length; + } + break; + default: + throw 'unknown opcode'; + } + } + + // make sure that 1st command is copy + if (patch.length > 0 && patch[0].cmd !== 'copy') { + patch.unshift({ + cmd: 'copy', + arg: [0, 0] + }); + } + + return patch; +} + + +function decodeDifferenceData(diffData, path) { + var diffStream = new BinaryCMapReader(diffData); + + var baseFileName = diffStream.readString(); + var originalSize = diffStream.readNumber(); + if (baseFileName === '') { // no dependency + return diffData.slice(diffStream.pos, diffData.length); + } + var baseDiffData = readFile(path, baseFileName + '.bcmap'); + var baseData = decodeDifferenceData(baseDiffData, path); + var decoded = applyPatch(baseData, diffStream, originalSize); + + return decoded; +} + +function applyPatch(base, diffStream, originalSize) { + var data = ''; + var pos = 0; + var copyCommand = true; + var start, startOffset, length, subarray; + var previousEnd = 0; + while (diffStream.pos + 1 < diffStream.end) { + if (copyCommand) { + startOffset = diffStream.readNumber(); + start = previousEnd + startOffset; + length = diffStream.readNumber(); + subarray = base.slice(start << 1, (start + length) << 1); + data += subarray; + pos += length; + previousEnd = start + length; + } else { + length = diffStream.readNumber(); + subarray = diffStream.buffer.slice(diffStream.pos, + diffStream.pos + (length << 1)); + diffStream.pos += length << 1; + data += subarray; + pos += length; + } + copyCommand = !copyCommand; // switch between copy and insert + } + return data; +} + + +function toString(patch, filename, originalSize) { + var s = writeString(filename.replace('.bcmap', '')) + + writeNumber(originalSize); + for (var i = 0; i < patch.length; i++) { + var arg = patch[i].arg; + if (i % 2 === 0) { // copy + s += writeNumber(arg[0]) + writeNumber(arg[1]); + } else { // insert + s += writeNumber(arg.length); + s += hexify(arg).join(''); + } + } + return s; +} + + +function writePatches(srcPath, destPath, filenames, dependencies, verify) { + var totalInBytes = 0; + var totalOutBytes = 0; + var dependency = dependencies.dependencies; + var ordering = dependencies.ordering; + for (var o = 0; o < filenames.length; o++) { + var i = ordering[o]; + var filename = filenames[i]; + var hexContent = readFile(srcPath, filenames[i]); + var file = hexToArray(hexContent); + var fileSize = hexContent.length >> 1; + var j = dependency[i]; + var destFile = destPath + '/' + filename; + + var isBase = j < 0; + var out; + if (isBase) { + out = writeString('') + writeNumber(fileSize) + hexContent; + } else { + var baseName = filenames[j]; + var baseHexContent = readFile(srcPath, baseName); + var baseFile = hexToArray(baseHexContent); + var sm = new difflib.SequenceMatcher(null, baseFile, file, false); + var opcodes = sm.getOpcodes(); + var patch = generatePatch(baseFile, file, opcodes); + out = toString(patch, baseName, fileSize); + } + + var outBytes = out.length >> 1; + totalOutBytes += outBytes; + totalInBytes += fileSize; + var paddedFilename = padRight(filename.slice(0, -6), 25); + var percent = (100 * outBytes / fileSize).toFixed(1); + console.log(padLeft(i, 3) + ': ' + paddedFilename + ' ' + + padLeft(outBytes, 7) + ' /' + padLeft(fileSize, 8) + + padLeft('(' + percent + '%)', 11) + ' ---> ' + + (isBase ? '' : filenames[j].slice(0, -6))); + + fs.writeFileSync(destFile, new Buffer(out, 'hex')); + + if (verify) { + var decoded = decodeDifferenceData(out, destPath); + var hexContentStr = JSON.stringify(hexContent); + var decodedStr = JSON.stringify(decoded); + var isGood = (hexContentStr === decodedStr); + if (!isGood) { + var origLen = 'original (' + (hexContent.length >> 1) + ' bytes): '; + var decodedLen = 'decoded (' + (decoded.length >> 1) + ' bytes): '; + console.log(padRight(origLen, 20) + limitLength(hexContentStr, 100)); + console.log(padRight(decodedLen, 20) + limitLength(decodedStr, 100)); + throw new Error('Reconstructed differential data differs from ' + + 'original'); + } + } + } + + var totalPercent = '(' + (100 * totalOutBytes / totalInBytes).toFixed(1) + + '%)'; + console.log('--------------------------------------------------------------'); + console.log('TOTAL: ' + + padLeft(totalOutBytes, 34) + ' /' + padLeft(totalInBytes, 8) + + padLeft(totalPercent, 11)); +} + + +function computeSavings(srcPath, filenames, savingsFilePath) { + var MAX_NUM_CMAP_FILES = 1000; // use a smaller number (< 168) for debugging + var n = filenames.length; + var forceComputation = false; // ignore/update values in savings.tmp + + // savings[i][j] = fileSizeJ minus size of patch from i to j, + // ie, the number of bytes that are saved when using the patch. + var savings; + + // try to load savings matrix from disk + try { + var count = 0; + var savingsFileContents = fs.readFileSync(savingsFilePath); + var storedSavings = JSON.parse(savingsFileContents); + if (storedSavings) { + for (var i = 0; i < n; i++) { + for (var j = 0; j < n; j++) { + if (storedSavings[i][j] >= 0) { + count++; + } + } + } + console.log('Restored ' + count + ' of ' + (n * n) + ' entries from ' + + savingsFilePath + '.'); + savings = storedSavings; + if (!forceComputation && count === n * n) { + return savings; + } + } + } catch (e) { + console.log('No savings file found, computing file diffs from scratch.' + + ' This may take hours.'); + + // initialize with -1. + savings = []; + for (var i = 0; i < n; i++) { + savings[i] = []; + for (var j = 0; j < n; j++) { + savings[i][j] = -1; + } + savings[i][i] = 0; + } + } + + var ii = Math.min(MAX_NUM_CMAP_FILES, n); + + // prepare console output + var totalTicks = (ii * ii - ii); + var numTicksToDisplay = Math.min(80, totalTicks); + var tickEvery = (totalTicks / numTicksToDisplay) | 0; + numTicksToDisplay = Math.ceil(totalTicks / tickEvery); + var tick = 0; + var spaces = new Array(numTicksToDisplay + 1).join(' '); + console.log('.' + spaces + '.'); + process.stdout.write(' '); // log without newline + + // generate patches and compute sizes + for (var i = 0; i < ii; i++) { + var filenameI = filenames[i]; + var hexContentI = readFile(srcPath, filenames[i]); + var fileI = hexToArray(hexContentI); + var sizeI = hexContentI.length >> 1; + sizeI += (writeString('') + writeNumber(sizeI)).length >> 1; + // Savings are almost symmetric, difference is usually below 0.3%, + // so we could also run up to i. But let's be precise :-]. + for (var j = 0; j < ii ; j++) { + if (j === i) { + savings[i][j] = 0; + continue; + } + tick++; + if ((tick + (tickEvery >> 1)) % tickEvery === 0) { + process.stdout.write('°'); // log without newline + } + if (!forceComputation && savings[i][j] >= 0) { + continue; + } + var filenameJ = filenames[j]; + var hexContentJ = readFile(srcPath, filenameJ); + var fileJ = hexToArray(hexContentJ); + var sizeJ = hexContentJ.length >> 1; + sizeJ += (writeString('') + writeNumber(sizeJ)).length >> 1; + var sm = new difflib.SequenceMatcher(null, fileI, fileJ, false); + var ops = sm.getOpcodes(); + var patchJ = generatePatch(fileI, fileJ, ops); + var patchSizeJ = toString(patchJ, filenameI, sizeI).length >> 1; + // neg values are reserved for undefined in savings file + savings[i][j] = Math.max(0, sizeJ - patchSizeJ); + } + } + console.log(''); + + // save matrix to disk + try { + var numEntries = 0; + for (var i = 0; i < n; i++) { + for (var j = 0; j < n; j++) { + if (savings[i][j] >= 0) { + numEntries++; + } + } + } + var savingsToStore = JSON.stringify(savings); + fs.writeFileSync(savingsFilePath, new Buffer(savingsToStore, 'ascii')); + console.log('Saved ' + numEntries + ' of ' + (n * n) + ' entries to ' + + savingsFilePath + '.'); + } catch (e) { + console.log('Could not save savings file: ' + e); + } + + return savings; +} + + +// Use a breadth first search to choose an orientation of each edge that is +// connected to one of the roots. Edges always point away from the root +// (ie, first argument has smaller distance to root). +function BFS(edges, roots, n, fileSizes, savings) { + var orientedEdges = []; + var queue = roots.slice(0, roots.length); + var isSelected = new Uint8Array(n); + var parent = []; + + for (var i = 0; i < n; i++) { + parent[i] = -1; + } + for (var i = 0; i < queue.length; i++) { + isSelected[queue[i]] = 1; + } + while (queue.length > 0) { + var v = queue.pop(); + // add all neighbors of v to queue + for (var i = 0; i < edges.length; i++) { + var e = edges[i]; + var s = e[0]; + var t = e[1]; + if (s === v && !isSelected[t]) { + orientedEdges.push(e); + queue.push(t); + isSelected[t] = 1; + } else if (t === v && !isSelected[s]) { + orientedEdges.push([t, s]); + queue.push(s); + isSelected[s] = 1; + } + parent[t] = s; + } + } + + var tree = { + orientedEdges: orientedEdges, + roots: roots, + n: n, + parent: parent + }; + computeTreeMetrics(tree, fileSizes, savings); + return tree; +} + + +function computeTreeMetrics(tree, fileSizes, savings) { + var orientedEdges = tree.orientedEdges; + var roots = tree.roots; + var n = tree.n; + + var distanceFromRoot = []; + var sizeOfOverhead = []; + var nodesAtRoot = []; + var rootOfNode = []; + + // initalize vars + for (var i = 0; i < n; i++) { + distanceFromRoot[i] = -1; + sizeOfOverhead[i] = -1; + rootOfNode[i] = -1; + } + for (var i = 0; i < roots.length; i++) { + var r = roots[i]; + distanceFromRoot[r] = 0; + sizeOfOverhead[r] = 0; + nodesAtRoot[r] = [r]; + rootOfNode[r] = r; + } + + // loop through tree, from root to children + var newNodes = true; + var d = 0; + while (newNodes) { + newNodes = false; + for (var i = 0; i < orientedEdges.length; i++) { + var e = orientedEdges[i]; + var s = e[0]; + var t = e[1]; + if (distanceFromRoot[s] === d && distanceFromRoot[t] === -1) { + newNodes = true; + distanceFromRoot[t] = distanceFromRoot[s] + 1; + sizeOfOverhead[t] = sizeOfOverhead[s] + fileSizes[s] - savings[s][t]; + rootOfNode[t] = rootOfNode[s]; + nodesAtRoot[rootOfNode[t]].push(t); + } + } + d++; + } + + // loop through nodes, compute stats + var totalDistanceFromRoot = 0; + var totalSizeOfOverhead = 0; + var totalSize = 0; + var numberOfNodes = 0; + var totalSavings = 0; + for (var i = 0; i < n; i++) { + if (rootOfNode[i] >= 0) { + numberOfNodes++; + totalSizeOfOverhead += sizeOfOverhead[i]; + totalDistanceFromRoot += distanceFromRoot[i]; + totalSize += fileSizes[i]; + var p = tree.parent[i]; + if (p > 0) { + totalSavings += savings[p][i]; + } + } + } + + // number of edges between v and root + tree.distanceFromRoot = distanceFromRoot; + // sizeOfOverhead[v] is the number of overhead bytes to load, + // that is, fileSize[v] + sizeOfOverhead[v] is the number + // of bytes read to decode file v + tree.sizeOfOverhead = sizeOfOverhead; + // pointer to the root of v + tree.rootOfNode = rootOfNode; + // nodesAtRoot[r]: list of nodes that have r as root + tree.nodesAtRoot = nodesAtRoot; + + tree.totalSize = totalSize; + tree.totalSavings = totalSavings; + tree.totalSizeOfOverhead = totalSizeOfOverhead; + tree.totalDistanceFromRoot = totalDistanceFromRoot; + tree.numberOfNodes = numberOfNodes; +} + + +// find a maximal spanning tree in the (complete) graph +// of possible dependencies. +function maximalSpanningTree(savings, minSavingsPerDependency) { + var n = savings.length; + var isSelected = new Uint8Array(n); + isSelected[0] = true; + var roots = [0]; + var edges = []; + var addedEdges = 0; + while (addedEdges < n - 1) { + // find largest edge between a selected and unselected node. + var maxSavings = -1; + var maxI = 0; + var maxJ = 0; + for (var i = 0; i < n; i++) { + if (isSelected[i]) { + for (var j = 0; j < n; j++) { + if ((!isSelected[j]) && (savings[i][j] > maxSavings)) { + maxSavings = Math.max(minSavingsPerDependency, savings[i][j]); + maxI = i; + maxJ = j; + } + } + } + } + // use this largest edge if greater than minimum savings + if (maxSavings > minSavingsPerDependency) { + edges.push([maxI, maxJ]); + } else { + roots.push(maxJ); + } + addedEdges++; + isSelected[maxJ] = true; + } + return { + edges: edges, + roots: roots, + n: n + }; +} + + +function selectBestRootInComponent(edges, r, fileSizes, savings, + overheadFunction) { + var n = savings.length; + var tree = BFS(edges, [r], n, fileSizes, savings); + var nodesInComponent = tree.nodesAtRoot[r]; + var bestValue = 1 << 30; + var bestRoot; + for (var j = 0; j < nodesInComponent.length; j++) { + var rootJ = nodesInComponent[j]; + var treeJ = BFS(edges, [rootJ], n, fileSizes, savings); + var value = overheadFunction(treeJ); + if (value < bestValue) { + bestRoot = rootJ; + bestValue = value; + } + } + return bestRoot; +} + +function limitLength(s, maxLength) { + return s.length > maxLength ? s.slice(0, maxLength - 3) + '...' : s; +} + +function logStatistics(tree, filenames, originalFileSizes, fileSizes, savings, + dependencies) { + var roots = tree.roots; + var edges = tree.orientedEdges; + var n = tree.n; + + var totNodes = 0; + var totSize = 0; + var totDiffedSize = 0; + var totOverhead = 0; + var totDependencies = 0; + var singleNodes = 0; + var singleSize = 0; + var singleDiffedSize = 0; + var singleOverhead = 0; + var singleDependencies = 0; + console.log(' Files | Original | DiffedSize | Overhead | ' + + 'Dependencies | Filenames (starting with base file)'); + console.log('-------|----------|------------|----------|-' + + '-------------|-------------------------------------'); + for (var i = 0; i < roots.length; i++) { + var r = roots[i]; + var tr = BFS(edges, [r], n, fileSizes, savings); + var nodes = tr.nodesAtRoot[tr.roots[0]]; + var out = ''; + var originalSize = 0; + var diffedSize = 0; + for (var j = 0; j < nodes.length; j++) { + var v = nodes[j]; + var name = filenames[v].replace('.bcmap', ''); + var parent = dependencies[v]; + var depName; + diffedSize += originalFileSizes[v] + ((writeString('') + + writeNumber(originalFileSizes[v])).length >> 1); + out = out + name + ', '; + originalSize += originalFileSizes[v]; + } + diffedSize -= tr.totalSavings; + out = out.slice(0, -2); + out = limitLength(out, 60); + var numNodes = tr.numberOfNodes; + if (numNodes > 1) { + var avgDependencies = (tr.totalDistanceFromRoot / numNodes).toFixed(2); + console.log(padLeft(numNodes, 5) + ' |' + + padLeft(originalSize / numNodes | 0, 8) + ' |' + + padLeft(diffedSize / numNodes | 0, 9) + ' |' + + padLeft((tr.totalSizeOfOverhead / numNodes) | 0, 8) + ' |' + + padLeft(avgDependencies, 12) + ' | ' + out); + } else { + singleNodes += numNodes; + singleSize += originalSize; + singleDiffedSize += diffedSize; + singleOverhead += tr.totalSizeOfOverhead; + singleDependencies += 0; + } + totSize += originalSize; + totNodes += numNodes; + totDiffedSize += diffedSize; + totOverhead += tr.totalSizeOfOverhead; + totDependencies += tr.totalDistanceFromRoot; + } + console.log(padLeft(singleNodes, 5) + '* |' + + padLeft(singleSize / singleNodes | 0, 8) + ' |' + + padLeft(singleDiffedSize / singleNodes | 0, 9) + ' |' + + padLeft((singleOverhead / singleNodes) | 0, 8) + ' |' + + padLeft(singleDependencies / singleNodes | 0, 12) + + ' | * single files' ); + console.log('-------|----------|------------|----------|--------------|'); + console.log(padLeft(totNodes, 5) + ' |' + + padLeft(totSize, 8) + '° |' + + padLeft(totDiffedSize, 9) + '° |' + + padLeft((totOverhead / totNodes) | 0, 8) + ' |' + + padLeft((totDependencies / totNodes).toFixed(2), 12) + + ' | ° marked numbers are sums, other values are averages.'); +} + + +/** + * Computes a combination of dependencies, so that the file with index i + * can be stored as a difference patch with respect to the file with index + * dependencies[i]. This will save 'savings[dependencies[i]][i]' bytes + * compared to raw storage. Dependencies are built with the following goals: + * + * (1) Small file sizes: + * The total number of bytes saved should be maximized + * (to keep the pdf.js extension small). + * (2) Small overhead: + * Minimize the number of extra bytes that have to be loaded from base files + * to reconstruct a particular file (to minimize the amount of data required + * to view a single file in the viewer) + * (3) Small number of dependencies: + * Minimize the number of base files to reconstruct a particular file + * (To minimize the required number of connections to view a single file in + * the viewer) + * + * The algorithm works in three stages: + * (I) Construct a maximal spaning tree: each edge[i][j] represents that + * file j depends on file i, saving 'savings[i][j]' bytes. + * Since it's a tree, there is a path from each node to the root, + * representing a chain of dependencies that have to be resolved + * for each file, until reaching the base file that is stored rawly. + * (II) Remove all edges whose overhead is outweights the savings + * (as defined in the 'overheadFunction'). + * (III) Now that we have removed some edges, we have several connected + * components. In each component, select the best base file that all + * other files in this component depend on (directly or indirectly). + * As this corresponds to just a re-orientation of edges, it + * does (almost) not affect the total bytes saved (because savings + * are almost symmetric) nor the number total number of dependencies + * (because the number of edges remains constant), but it might reduce the + * average length of depenedency chains, and so helps goals (2) and (3). + * + * @returns {Object} Object that contains + * dependencies: An array which contains for each file the index of the + * base file, or -1 if it is a base file itself. + * ordering: An ordering of indices in which the base file index + * ( = dependencies[i]) appears before i (for each i). + */ +function chooseDependencies(savings, srcPath, filenames) { + + /* ****** Parameters ******************************/ + + // Do not create dependencies that save less than this many bytes. + var MIN_SAVINGS_PER_DEPENDENCY = 200; + + // How many average overhead bytes (including file penalty) + // is allowed to save one byte of total size? + var MAX_OVERHEAD_PER_SAVED_BYTE = 0.02; + + // Penalty for creating a new dependency. + // A large penalty will favor short dependency lengths, + // a small penalty will favor small overhead. + var FILE_PENALTY = 5000; + + // The objective funtion to minimize when choosing the root + // in a group of dependent files. + var overheadFunction = function(tree) { + var value = tree.totalSizeOfOverhead; + // Add penalty for each file that has to be loaded. + value += tree.totalDistanceFromRoot * FILE_PENALTY; + return value; + }; + /* ***************************************************/ + + var fileSizes = []; + var originalFileSizes = []; + for (var i = 0; i < filenames.length; i++) { + var fileSize = readFile(srcPath, filenames[i]).length >> 1; + originalFileSizes[i] = fileSize; + fileSize += (writeString('') + writeNumber(fileSize)).length >> 1; + fileSizes[i] = fileSize; + } + + var time = new Date(); + var n = savings.length; + + var mst = maximalSpanningTree(savings, MIN_SAVINGS_PER_DEPENDENCY); + var edges = mst.edges; + var roots = mst.roots; + + + // Remove all edges whose removal improves + // MAX_OVERHEAD_PER_SAVED_BYTE * overhead - savings + while (true) { + var improved = false; + // loop through all tree components + for (var i = 0; i < roots.length; i++) { + // compute metrics of current tree component + var r = selectBestRootInComponent(edges, roots[i], fileSizes, savings, + overheadFunction); + var tree = BFS(edges, [r], n, fileSizes, savings); + var overheadWithEdge = overheadFunction(tree); + var savingsWithEdge = tree.totalSavings; + var valueWithEdge = MAX_OVERHEAD_PER_SAVED_BYTE * overheadWithEdge - + savingsWithEdge; + var componentEdges = tree.orientedEdges; + + // loop though all edges and check if metrics improve when removing + // that edge + for (var j = 0; j < componentEdges.length; j++) { + var e = componentEdges[j]; + var s = e[0]; + var t = e[1]; + // split graph at edge e + var newEdges = componentEdges.slice(0); + newEdges.splice(j, 1); + var bestRoot1 = selectBestRootInComponent(newEdges, s, fileSizes, + savings, overheadFunction); + var bestRoot2 = selectBestRootInComponent(newEdges, t, fileSizes, + savings, overheadFunction); + var newTrees = BFS(newEdges, [bestRoot1, bestRoot2], n, fileSizes, + savings); + + var savingsWithoutEdge = savingsWithEdge - savings[s][t]; + var overheadWithoutEdge = overheadFunction(newTrees); + var valueWithoutEdge = MAX_OVERHEAD_PER_SAVED_BYTE * + overheadWithoutEdge - savingsWithoutEdge; + if (valueWithoutEdge < valueWithEdge) { + var rPos = roots.indexOf(r); + roots.splice(i, 1); + roots.push(bestRoot1); + roots.push(bestRoot2); + i = roots.length; // break outer loop afterwards + // remove [s,t] from edges, to remove it permanently + for (var k = 0; k < edges.length; k++) { + var f = edges[k]; + if ((s === f[0] && t === f[1]) || (t === f[0] && s === f[1])) { + edges.splice(k, 1); + break; + } + } + improved = true; + break; + } + } + } + if (!improved) { + break; + } + } + + // Select the best root in each connected component + var bestRoots = []; + for (var i = 0; i < roots.length; i++) { + var bestRoot = selectBestRootInComponent(edges, roots[i], fileSizes, + savings, overheadFunction); + bestRoots.push(bestRoot); + } + var bestTree = BFS(edges, bestRoots, n, fileSizes, savings); + + + // generate dependencies + var dependencies = []; + for (var i = 0; i < n; i++) { + dependencies[i] = -1; + } + for (var i = 0; i < bestTree.orientedEdges.length; i++) { + var e = bestTree.orientedEdges[i]; + dependencies[e[1]] = e[0]; + } + + // generate write order: + // an ordering so that dependency[i] appears before i (for each i). + var writeOrder = []; + for (var i = 0; i < bestRoots.length; i++) { + var nodesAtRoot = bestTree.nodesAtRoot[bestRoots[i]]; + writeOrder = writeOrder.concat(nodesAtRoot ? nodesAtRoot : []); + } + + console.log(''); + logStatistics(bestTree, filenames, originalFileSizes, fileSizes, savings, + dependencies); + console.log(''); + + return { + dependencies: dependencies, + ordering: writeOrder + }; +} + +exports.generateDifferences = function (srcPath, destPath, verify) { + var t = Date.now(); + console.log('### Generating diffs'); + var filenames = fs.readdirSync(srcPath); + filenames = filenames.filter(function (fn) { + return /\.bcmap/.test(fn); // skipping files with the extension + }); + + var savingsFilePath = srcPath + '/savings.json'; + var savings = computeSavings(srcPath, filenames, savingsFilePath); + + var dependencies = chooseDependencies(savings, srcPath, filenames); + writePatches(srcPath, destPath, filenames, dependencies, verify); + + console.log(((Date.now() - t) / 1000).toFixed(2) + ' seconds'); +}; diff --git a/make.js b/make.js index 55945af0bb6196..776ce7220aecb0 100644 --- a/make.js +++ b/make.js @@ -299,6 +299,7 @@ target.locale = function() { target.cmaps = function (args) { var CMAP_INPUT = 'external/cmaps'; var VIEWER_CMAP_OUTPUT = 'external/bcmaps'; + var VIEWER_CMAP_TEMP = 'external/bcmaps_temp'; cd(ROOT_DIR); echo(); @@ -310,12 +311,22 @@ target.cmaps = function (args) { echo(' http://sourceforge.net/adobe/cmap/wiki/Home/'); exit(1); } + - rm(VIEWER_CMAP_OUTPUT + '*.bcmap'); + rm(VIEWER_CMAP_OUTPUT + '/*.bcmap'); + if (fs.existsSync(VIEWER_CMAP_TEMP)) { + rm(VIEWER_CMAP_TEMP + '/*.bcmap'); + } else { + mkdir(VIEWER_CMAP_TEMP); + } + + var srcPath = './external/cmapscompress/'; + var compressCmaps = require(srcPath + 'compress.js').compressCmaps; + compressCmaps(CMAP_INPUT, VIEWER_CMAP_TEMP, true); - var compressCmaps = - require('./external/cmapscompress/compress.js').compressCmaps; - compressCmaps(CMAP_INPUT, VIEWER_CMAP_OUTPUT, true); + var generateDifferences = + require(srcPath + 'differentialStorage.js').generateDifferences; + generateDifferences(VIEWER_CMAP_TEMP, VIEWER_CMAP_OUTPUT, true); }; // diff --git a/src/core/cmap.js b/src/core/cmap.js index 5d69d17cbf3112..532d406952235b 100644 --- a/src/core/cmap.js +++ b/src/core/cmap.js @@ -448,6 +448,14 @@ var BinaryCMapReader = (function BinaryCMapReaderClosure() { } BinaryCMapStream.prototype = { + readArray: function(len) { + if (this.pos + len > this.end) { + error('unexpected EOF while reading bcmap'); + } + var start = this.pos; + this.pos += len; + return this.buffer.subarray(start, start + len); + }, readByte: function () { if (this.pos >= this.end) { return -1; @@ -518,8 +526,50 @@ var BinaryCMapReader = (function BinaryCMapReaderClosure() { } }; - function processBinaryCMap(url, cMap, extend) { - var data = fetchBinaryData(url); + function decodeDifferenceData(diffData, path) { + var diffStream = new BinaryCMapStream(diffData); + + var baseFileName = diffStream.readString(); + var originalSize = diffStream.readNumber(); + if (baseFileName === '') { // no dependency + return diffData.subarray(diffStream.pos, diffData.length); + } + var baseDiffData = fetchBinaryData(path + baseFileName + '.bcmap'); + var baseData = decodeDifferenceData(baseDiffData, path); + var decoded = applyPatch(baseData, diffStream, originalSize); + + return decoded; + } + + function applyPatch(base, diffStream, originalSize) { + var data = new Uint8Array(originalSize); + var pos = 0; + var copyCommand = true; + var start, startOffset, length, subarray; + var previousEnd = 0; + while (diffStream.pos + 1 < diffStream.end) { + if (copyCommand) { + startOffset = diffStream.readNumber(); + start = previousEnd + startOffset; + length = diffStream.readNumber(); + subarray = base.subarray(start, start + length); + data.set(subarray, pos); + pos += length; + previousEnd = start + length; + } else { + length = diffStream.readNumber(); + data.set(diffStream.readArray(length), pos); + pos += length; + } + copyCommand = !copyCommand; // switch between copy and insert + } + return data; + } + + + function processBinaryCMap(url, name, cMap, extend) { + var diffData = fetchBinaryData(url + name + '.bcmap'); + var data = decodeDifferenceData(diffData, url); var stream = new BinaryCMapStream(data); var header = stream.readByte(); @@ -900,9 +950,9 @@ var CMapFactory = (function CMapFactoryClosure() { } function parseBinaryCMap(name, builtInCMapParams) { - var url = builtInCMapParams.url + name + '.bcmap'; + var url = builtInCMapParams.url; var cMap = new CMap(true); - new BinaryCMapReader().read(url, cMap, function (useCMap) { + new BinaryCMapReader().read(url, name, cMap, function (useCMap) { extendCMap(cMap, builtInCMapParams, useCMap); }); return cMap;