Repository: PolusAI/nyxus (language: python)

Issue:
added header to fix build issue.
added cstdint header
added header to fix build issue.
added cstdint header


Discussion / hints:

Fix patch:
diff --git a/src/nyx/environment.cpp b/src/nyx/environment.cpp
index 9580b37d..af218edc 100644
--- a/src/nyx/environment.cpp
+++ b/src/nyx/environment.cpp
@@ -111,7 +111,7 @@ namespace Nyxus
 			if (!fnameExists)
 			{
 				retval = false;
-				std::cout << "Error: expecting '" << s << "' to be a proper feature name. \n";
+				std::cout << "Error: expecting '" << s << "' to be a proper feature name or feature file path\n";
 			}
 			else
 				result.push_back(s_uppr);
@@ -404,8 +404,7 @@ void Environment::process_feature_list()
 				UNIFORMITY,
 				P01, P10, P25, P75, P90, P99,
 				INTERQUARTILE_RANGE,
-				ROBUST_MEAN_ABSOLUTE_DEVIATION,
-				MASS_DISPLACEMENT};
+				ROBUST_MEAN_ABSOLUTE_DEVIATION };
 			theFeatureSet.enableFeatures(F);
 			continue;
 		}
@@ -428,6 +427,7 @@ void Environment::process_feature_list()
 				MINOR_AXIS_LENGTH,
 				ECCENTRICITY,
 				ORIENTATION,
+				ROUNDNESS,
 				EXTENT,
 				ASPECT_RATIO,
 				DIAMETER_EQUAL_PERIMETER,
@@ -438,7 +438,8 @@ void Environment::process_feature_list()
 				EDGE_STDDEV_INTENSITY,
 				EDGE_MAX_INTENSITY,
 				EDGE_MIN_INTENSITY,
-				CIRCULARITY};
+				CIRCULARITY, 
+				MASS_DISPLACEMENT };
 			theFeatureSet.enableFeatures(F);
 			continue;
 		}
@@ -452,7 +453,7 @@ void Environment::process_feature_list()
 				BBOX_YMIN,
 				BBOX_XMIN,
 				BBOX_HEIGHT,
-				BBOX_WIDTH};
+				BBOX_WIDTH };
 			theFeatureSet.enableFeatures(F);
 			continue;
 		}
@@ -474,8 +475,7 @@ void Environment::process_feature_list()
 				GLCM_SUMAVERAGE,
 				GLCM_SUMENTROPY,
 				GLCM_SUMVARIANCE,
-				GLCM_VARIANCE
-			};
+				GLCM_VARIANCE };
 			theFeatureSet.enableFeatures(F);
 			continue;
 		}
@@ -497,7 +497,7 @@ void Environment::process_feature_list()
 				GLRLM_SRLGLE,
 				GLRLM_SRHGLE,
 				GLRLM_LRLGLE,
-				GLRLM_LRHGLE};
+				GLRLM_LRHGLE };
 			theFeatureSet.enableFeatures(F);
 			continue;
 		}
@@ -519,7 +519,7 @@ void Environment::process_feature_list()
 				GLSZM_SALGLE,
 				GLSZM_SAHGLE,
 				GLSZM_LALGLE,
-				GLSZM_LAHGLE};
+				GLSZM_LAHGLE };
 			theFeatureSet.enableFeatures(F);
 			continue;
 		}
@@ -539,7 +539,7 @@ void Environment::process_feature_list()
 				GLDM_SDLGLE,
 				GLDM_SDHGLE,
 				GLDM_LDLGLE,
-				GLDM_LDHGLE};
+				GLDM_LDHGLE };
 			theFeatureSet.enableFeatures(F);
 			continue;
 		}
@@ -550,7 +550,7 @@ void Environment::process_feature_list()
 				NGTDM_CONTRAST,
 				NGTDM_BUSYNESS,
 				NGTDM_COMPLEXITY,
-				NGTDM_STRENGTH};
+				NGTDM_STRENGTH };
 			theFeatureSet.enableFeatures(F);
 			continue;
 		}
@@ -655,8 +655,7 @@ void Environment::process_feature_list()
 				WEIGHTED_HU_M4,
 				WEIGHTED_HU_M5,
 				WEIGHTED_HU_M6,
-				WEIGHTED_HU_M7
-			};
+				WEIGHTED_HU_M7 };
 
 			theFeatureSet.disableFeatures(F);
 
@@ -881,31 +880,31 @@ int Environment::parse_cmdline(int argc, char **argv)
 		GLCMFeature::angles = glcmAngles;
 	}
 
-	//==== Parse the RAM limit
+	//==== Parse the RAM limit (in megabytes)
 	if (!rawRamLimit.empty())
 	{
 		// string -> integer
-		size_t value = 0;
-		auto scanfResult = sscanf(rawRamLimit.c_str(), "%zu", &value);
+		int value = 0;
+		auto scanfResult = sscanf(rawRamLimit.c_str(), "%d", &value);
 		if (scanfResult != 1 || value < 0)
 		{
 			std::cout << "Error: " << RAMLIMIT << "=" << rawRamLimit << ": expecting a non-negative integer constant (RAM limit in megabytes)\n";
 			return 1;
 		}
 
-		// To megabytes
-		value *= 1048576;
+		// Megabytes to bytes
+		size_t requestedCeiling = (size_t)value * 1048576;
 
 		// Check if it over the actual limit
 		unsigned long long actualRam = Nyxus::getAvailPhysMemory();
-		if (value > actualRam)
+		if (requestedCeiling > actualRam)
 		{
-			std::cout << "Error: RAM limit " << value << " is over the actual amount of available RAM " << actualRam << "\n";
+			std::cout << "Error: RAM limit " << value << " megabytes (=" << requestedCeiling << " bytes) exceeds the actual amount of available RAM " << actualRam << " bytes\n";
 			return 1;
 		}
 
-		// The angle list parsed well, let's tell it to GLCMFeature 
-		ramLimit = value;
+		// Set the member variable
+		ramLimit = requestedCeiling;
 	}
 
 	//==== Parse the temp directory
diff --git a/src/nyx/features/caliper_feret.cpp b/src/nyx/features/caliper_feret.cpp
index fcd97e4c..7d8902c3 100644
--- a/src/nyx/features/caliper_feret.cpp
+++ b/src/nyx/features/caliper_feret.cpp
@@ -16,6 +16,8 @@ CaliperFeretFeature::CaliperFeretFeature() : FeatureMethod("CaliperFeretFeature"
 			STAT_FERET_DIAM_MEDIAN,
 			STAT_FERET_DIAM_STDDEV,
 			STAT_FERET_DIAM_MODE});
+
+	add_dependencies({ CONVEX_HULL_AREA });
 }
 
 void CaliperFeretFeature::calculate(LR& r)
@@ -104,6 +106,10 @@ void CaliperFeretFeature::calculate_imp(const std::vector<Pixel2>& convex_hull,
 				auto& a = CH_rot[iH - 1],
 					& b = CH_rot[iH];
 
+				// Skip the case where starting and closing ends of the hull segment are the same point
+				if (a == b)
+					continue;
+
 				// Chord's Y is between segment AB's Ys ?
 				if ((a.y >= chord_y && b.y <= chord_y) || (b.y >= chord_y && a.y <= chord_y))
 				{
@@ -122,84 +128,18 @@ void CaliperFeretFeature::calculate_imp(const std::vector<Pixel2>& convex_hull,
 				auto compareFunc = [](const std::pair<float, float>& p1, const std::pair<float, float>& p2) { return p1.first < p2.first; };
 				auto idx_minX = std::distance(X.begin(), std::min_element(X.begin(), X.end(), compareFunc));
 				auto idx_maxX = std::distance(X.begin(), std::max_element(X.begin(), X.end(), compareFunc));
-				// left X and right X segments
-				auto& e1 = X[idx_minX], & e2 = X[idx_maxX];
-				auto x1 = e1.first, y1 = e1.second, x2 = e2.first, y2 = e2.second;
-				// save this chord
-				auto dist = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);	// Squared distance
-				DA.push_back(dist);
-			}
-		}
-
-		if (DA.size() > 0)
-		{
-			// Find the shortest and longest chords (diameters)
-			double minD2 = *std::min_element(DA.begin(), DA.end()),
-				maxD2 = *std::max_element(DA.begin(), DA.end()),
-				min_ = sqrt(minD2),
-				max_ = sqrt(maxD2);
-
-			// Save them
-			all_D.push_back(min_);
-			all_D.push_back(max_);
-		}
-	}
-}
-
-void CaliperFeretFeature::osized_calculate(LR& r, ImageLoader&)
-{
-	// Rotated convex hull
-	std::vector<Pixel2> CH_rot;
-	CH_rot.reserve(r.convHull_CH.size());
-
-	// Rotate and calculate the diameter
-	std::vector<double> all_D;
-	for (float theta = 0.f; theta < 180.f; theta += rot_angle_increment)
-	{
-		Rotation::rotate_around_center(r.convHull_CH, theta, CH_rot);
-		auto [minX, minY, maxX, maxY] = AABB::from_pixelcloud(CH_rot);
-
-		std::vector<float> DA;	// Diameters at this angle
-
-		// Iterate y-grid
-		float stepY = (maxY - minY) / float(n_steps);
-		for (int iy = 1; iy <= n_steps; iy++)
-		{
-			float chord_y = minY + iy * stepY;
 
-			// Find convex hull segments intersecting 'y'
-			std::vector<std::pair<float, float>> X;	// intersection points
-			for (int iH = 1; iH < CH_rot.size(); iH++)
-			{
-				// The convex hull points are guaranteed to be consecutive
-				auto& a = CH_rot[iH - 1],
-					& b = CH_rot[iH];
-
-				// Chord's Y is between segment AB's Ys ?
-				if ((a.y >= chord_y && b.y <= chord_y) || (b.y >= chord_y && a.y <= chord_y))
+				// Only consider a good 2-point diameter
+				if (idx_minX != idx_maxX)
 				{
-					auto chord_x = b.y != a.y ?
-						(b.x - a.x) * (chord_y - a.y) / (b.y - a.y) + a.x
-						: (b.y + a.y) / 2;
-					auto tup = std::make_pair(chord_x, chord_y);
-					X.push_back(tup);
+					// left X and right X segments
+					auto& e1 = X[idx_minX], & e2 = X[idx_maxX];
+					auto x1 = e1.first, y1 = e1.second, x2 = e2.first, y2 = e2.second;
+					// save this chord
+					auto dist = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);	// Squared distance
+					DA.push_back(dist);
 				}
 			}
-
-			// Save the length of this chord. There must be 2 items in 'chordEnds' because we don't allow uniformative chords of zero length
-			if (X.size() >= 2)
-			{
-				// for N segments
-				auto compareFunc = [](const std::pair<float, float>& p1, const std::pair<float, float>& p2) { return p1.first < p2.first; };
-				auto idx_minX = std::distance(X.begin(), std::min_element(X.begin(), X.end(), compareFunc));
-				auto idx_maxX = std::distance(X.begin(), std::max_element(X.begin(), X.end(), compareFunc));
-				// left X and right X segments
-				auto& e1 = X[idx_minX], & e2 = X[idx_maxX];
-				auto x1 = e1.first, y1 = e1.second, x2 = e2.first, y2 = e2.second;
-				// save this chord
-				auto dist = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);	// Squared distance
-				DA.push_back(dist);
-			}
 		}
 
 		if (DA.size() > 0)
@@ -215,39 +155,13 @@ void CaliperFeretFeature::osized_calculate(LR& r, ImageLoader&)
 			all_D.push_back(max_);
 		}
 	}
+}
 
-	// Calculate statistics of diameters
-	auto s = ComputeCommonStatistics2(all_D);
-	_min = (double)s.min;
-	_max = (double)s.max;
-	_mean = s.mean;
-	_median = s.median;
-	_stdev = s.stdev;
-	_mode = (double)s.mode;
-
-	// Calculate angles at min- and max- diameter
-	if (all_D.size() > 0)
-	{
-		// Min and max
-		auto itr_min_d = std::min_element(all_D.begin(), all_D.end());
-		auto itr_max_d = std::max_element(all_D.begin(), all_D.end());
-		minFeretDiameter = *itr_min_d;
-		maxFeretDiameter = *itr_max_d;
-
-		// Angles
-		auto idxMin = std::distance(all_D.begin(), itr_min_d);
-		minFeretAngle = (double)idxMin / 2.0;
-		auto idxMax = std::distance(all_D.begin(), itr_max_d);
-		maxFeretAngle = (double)idxMax / 2.0;
-	}
-	else
-	{
-		// Degenerate case
-		minFeretDiameter =
-		maxFeretDiameter =
-		minFeretAngle =
-		maxFeretAngle = 0.0;
-	}
+void CaliperFeretFeature::osized_calculate(LR& r, ImageLoader&)
+{
+	// Calculating this feature does not require access to the massive ROI pixel cloud, 
+	// so we can reuse the trivial calculate()
+	calculate(r);
 }
 
 void CaliperFeretFeature::parallel_process(std::vector<int>& roi_labels, std::unordered_map <int, LR>& roiData, int n_threads)
diff --git a/src/nyx/features/chords_nontriv.cpp b/src/nyx/features/chords_nontriv.cpp
index 4c42b1ae..a108ce74 100644
--- a/src/nyx/features/chords_nontriv.cpp
+++ b/src/nyx/features/chords_nontriv.cpp
@@ -58,8 +58,7 @@ void ChordsFeature::osized_calculate (LR& r, ImageLoader& imloader)
 
 		//ImageMatrix_nontriv im(R);
 		WriteImageMatrix_nontriv imRot ("imRot", r.label);
-		imRot.allocate (aabbRot.get_width(), aabbRot.get_height(), 0);
-		imRot.init_with_cloud (R, aabbRot);
+		imRot.allocate_from_cloud (R, aabbRot, true);
 
 		for (int c = 0; c < imRot.get_width(); c++)
 		{
diff --git a/src/nyx/features/contour.cpp b/src/nyx/features/contour.cpp
index f14312da..c3d84dac 100644
--- a/src/nyx/features/contour.cpp
+++ b/src/nyx/features/contour.cpp
@@ -699,33 +699,15 @@ std::tuple<double, double, double, double> ContourFeature::calc_min_max_mean_std
 	return { min_, max_, mean_, stddev_ };
 }
 
-namespace Nyxus
+void ContourFeature::reduce (size_t start, size_t end, std::vector<int>* ptrLabels, std::unordered_map <int, LR>* ptrLabelData)
 {
-	void calcRoiContour(LR& r)
+	for (auto i = start; i < end; i++)
 	{
-		if (r.roi_disabled)
-			return;
+		int lab = (*ptrLabels)[i];
+		LR& r = (*ptrLabelData)[lab];
 
-		//==== Calculate ROI's image matrix
-		r.aux_image_matrix.calculate_from_pixelcloud (r.raw_pixels, r.aabb);
-
-		//==== Contour, ROI perimeter, equivalent circle diameter
 		ContourFeature f;
-		f.calculate(r);	// Consumes LR::aux_image_matrix, leaves contour pixels in LR::contour
-		f.save_value(r.fvals);
-	}
-
-	void parallelReduceContour (size_t start, size_t end, std::vector<int>* ptrLabels, std::unordered_map <int, LR>* ptrLabelData)
-	{
-		for (auto i = start; i < end; i++)
-		{
-			int lab = (*ptrLabels)[i];
-			LR& r = (*ptrLabelData)[lab];
-			if (r.has_bad_data())
-				continue;
-			calcRoiContour(r);
-		}
+		f.calculate (r);
+		f.save_value (r.fvals);
 	}
 }
-
-
diff --git a/src/nyx/features/contour.h b/src/nyx/features/contour.h
index 7f0555fc..02d9edad 100644
--- a/src/nyx/features/contour.h
+++ b/src/nyx/features/contour.h
@@ -15,14 +15,7 @@ class ContourFeature: public FeatureMethod
 	void parallel_process(std::vector<int>& roi_labels, std::unordered_map <int, LR>& roiData, int n_threads);
 	static void parallel_process_1_batch(size_t firstitem, size_t lastitem, std::vector<int>* ptrLabels, std::unordered_map <int, LR>* ptrLabelData);
 	void cleanup_instance();
-
-	#if 0
-	void calculate (const ImageMatrix& im);	// Leaves result in 'contour_pixels'
-	StatsInt get_roi_perimeter();
-	StatsReal get_diameter_equal_perimeter();
-	std::tuple<StatsReal, StatsReal, StatsReal, StatsReal> get_min_max_mean_stddev_intensity();
-	std::vector<Pixel2> contour_pixels;
-	#endif
+	static void reduce(size_t start, size_t end, std::vector<int>* ptrLabels, std::unordered_map <int, LR>* ptrLabelData);
 
 	static bool required(const FeatureSet& fs) 
 	{
@@ -107,7 +100,7 @@ class ContourFeature: public FeatureMethod
 			WEIGHTED_HU_M6,
 			WEIGHTED_HU_M7, 
 			ROI_RADIUS_MEAN, ROI_RADIUS_MAX, ROI_RADIUS_MEDIAN,
-			ZERNIKE2D, FRAC_AT_D, MEAN_FRAC, RADIAL_CV
+			FRAC_AT_D, MEAN_FRAC, RADIAL_CV
 		});
 	}
 
@@ -123,11 +116,6 @@ class ContourFeature: public FeatureMethod
 		fval_EDGE_STDDEV_INTENSITY = 0, 
 		fval_EDGE_MAX_INTENSITY = 0, 
 		fval_EDGE_MIN_INTENSITY = 0,
-		fval_EDGE_INTEGRATEDINTENSITY = 0 
-		//,fval_EDGE_MAXINTENSITY = 0, 
-		//fval_EDGE_MININTENSITY = 0, 
-		//fval_EDGE_MEANINTENSITY = 0 
-		//,fval_EDGE_STDDEVINTENSITY = 0
-		;
+		fval_EDGE_INTEGRATEDINTENSITY = 0;
 };
 
diff --git a/src/nyx/features/convex_hull.h b/src/nyx/features/convex_hull.h
index 3e41f93c..74ff81b1 100644
--- a/src/nyx/features/convex_hull.h
+++ b/src/nyx/features/convex_hull.h
@@ -11,35 +11,23 @@ class ConvexHullFeature : public FeatureMethod
 	ConvexHullFeature();
 
 	// Trivial ROI
-	void calculate(LR& r);	 // Consumes LR::raw_pixels, populates LR::conv_hull_pixels, calculates 3 features
+	void calculate(LR& r);
 
 	// Non-trivial ROI
 	void osized_add_online_pixel(size_t x, size_t y, uint32_t intensity) {}
-	void osized_calculate (LR& r, ImageLoader& imloader);	// Consumes LR::raw_pixels, populates LR::conv_hull_pixels, calculates the 3 features
+	void osized_calculate (LR& r, ImageLoader& imloader);
 	void save_value (std::vector<std::vector<double>>& feature_vals);
 	void cleanup_instance();
 
-	// Part of the legacy reduce(), will be gone
-	static bool required(const FeatureSet& fs) { return fs.anyEnabled({ CONVEX_HULL_AREA, SOLIDITY, CIRCULARITY }); }
+	// Support of manual reduce
+	static bool required(const FeatureSet& fs) { return fs.anyEnabled ({ CONVEX_HULL_AREA, SOLIDITY, CIRCULARITY }); }
 
 private:
 	void build_convex_hull(const std::vector<Pixel2>& contour, std::vector<Pixel2>& convhull);
+	void build_convex_hull(const OutOfRamPixelCloud& roi_cloud, std::vector<Pixel2>& convhull);
 	static bool compare_locations(const Pixel2& lhs, const Pixel2& rhs);
 	bool right_turn(const Pixel2& P1, const Pixel2& P2, const Pixel2& P3);
 	double polygon_area(const std::vector<Pixel2>& vertices);
 
 	double area = 0, solidity = 0, circularity = 0;	
 };
-
-class ConvexHull
-{
-public:
-	static bool required(const FeatureSet& fs) { return fs.anyEnabled({CONVEX_HULL_AREA, SOLIDITY, CIRCULARITY}); }
-	ConvexHull() {}
-	void calculate(std::vector<Pixel2>& rawPixels);
-	double getSolidity();
-	double getArea();
-	void clear() { CH.clear(); }
-
-	std::vector<Pixel2> CH;
-};
diff --git a/src/nyx/features/convex_hull_nontriv.cpp b/src/nyx/features/convex_hull_nontriv.cpp
index f3e49642..814dbcef 100644
--- a/src/nyx/features/convex_hull_nontriv.cpp
+++ b/src/nyx/features/convex_hull_nontriv.cpp
@@ -6,13 +6,14 @@
 
 ConvexHullFeature::ConvexHullFeature() : FeatureMethod("ConvexHullFeature")
 {
-	provide_features ({CONVEX_HULL_AREA, SOLIDITY, CIRCULARITY});
+	provide_features ({ CONVEX_HULL_AREA, SOLIDITY, CIRCULARITY });
+	add_dependencies ({ PERIMETER });
 }
 
 void ConvexHullFeature::save_value(std::vector<std::vector<double>>& fvals)
 {
 	fvals [CONVEX_HULL_AREA][0] = area;
-	fvals[SOLIDITY][0] = solidity; 
+	fvals [SOLIDITY][0] = solidity; 
 	fvals [CIRCULARITY][0] = circularity;
 }
 
@@ -35,22 +36,23 @@ void ConvexHullFeature::calculate (LR& r)
 	circularity = sqrt(4.0 * M_PI * s_roi / (p*p));
 }
 
-void ConvexHullFeature::build_convex_hull (const std::vector<Pixel2>& roi_cloud, std::vector<Pixel2>& convhull)
+void ConvexHullFeature::build_convex_hull (const std::vector<Pixel2>& cloud, std::vector<Pixel2>& convhull)
 {
 	convhull.clear();
 
 	// Skip calculation if the ROI is too small
-	if (roi_cloud.size() < 2)
+	if (cloud.size() < 2)
 		return;
 
 	std::vector<Pixel2>& upperCH = convhull;
 	std::vector<Pixel2> lowerCH;
 
-	size_t n = roi_cloud.size();
-
-	// Sorting points
-	std::vector<Pixel2> cloud = roi_cloud;	// Safely copy the ROI for fear of changing the original pixels order
-	std::sort (cloud.begin(), cloud.end(), compare_locations);
+	size_t n = cloud.size();
+	
+	//	No need to sort pixels because we accumulate them in a raster pattern without multithreading//
+	//	std::vector<Pixel2> cloud = roi_cloud;	// Safely copy the ROI for fear of changing the original pixels order
+	//	std::sort (cloud.begin(), cloud.end(), compare_locations);
+	//
 
 	// Computing upper convex hull
 	upperCH.push_back (cloud[0]);
@@ -82,9 +84,57 @@ void ConvexHullFeature::build_convex_hull (const std::vector<Pixel2>& roi_cloud,
 			upperCH.push_back(p);
 }
 
+void ConvexHullFeature::build_convex_hull (const OutOfRamPixelCloud& cloud, std::vector<Pixel2>& convhull)
+{
+	convhull.clear();
+
+	// Skip calculation if the ROI is too small
+	if (cloud.size() < 2)
+		return;
+
+	std::vector<Pixel2>& upperCH = convhull;
+	std::vector<Pixel2> lowerCH;
+
+	size_t n = cloud.size();
+
+//
+//	No need to sort pixels because we accumulate them in a raster pattern without multithreading
+//	std::vector<Pixel2> cloud = roi_cloud;	// Safely copy the ROI for fear of changing the original pixels order
+//	std::sort(cloud.begin(), cloud.end(), compare_locations);
+//
+ 
+	// Computing upper convex hull
+	upperCH.push_back(cloud[0]);
+	upperCH.push_back(cloud[1]);
+
+	for (size_t i = 2; i < n; i++)
+	{
+		while (upperCH.size() > 1 && (!right_turn(upperCH[upperCH.size() - 2], upperCH[upperCH.size() - 1], cloud[i])))
+			upperCH.pop_back();
+		upperCH.push_back(cloud[i]);
+	}
+
+	// Computing lower convex hull
+	lowerCH.push_back(cloud[n-1]);
+	lowerCH.push_back(cloud[n-2]);
+
+	for (size_t i = 2; i < n; i++)
+	{
+		while (lowerCH.size() > 1 && (!right_turn(lowerCH[lowerCH.size() - 2], lowerCH[lowerCH.size() - 1], cloud[n - i - 1])))
+			lowerCH.pop_back();
+		lowerCH.push_back(cloud[n - i - 1]);
+	}
+
+	// We could use 
+	//		upperCH.insert (upperCH.end(), lowerCH.begin(), lowerCH.end());
+	// but we don't need duplicate points in the result contour
+	for (auto& p : lowerCH)
+		if (std::find(upperCH.begin(), upperCH.end(), p) == upperCH.end())
+			upperCH.push_back(p);
+}
+
 // Sort criterion: points are sorted with respect to their x-coordinate.
-//                 If two points have the same x-coordinate then we compare
-//                 their y-coordinates
+// If two points have the same x-coordinate then we compare their y-coordinates
 bool ConvexHullFeature::compare_locations (const Pixel2& lhs, const Pixel2& rhs)
 {
 	return (lhs.x < rhs.x) || (lhs.x == rhs.x && lhs.y < rhs.y);
@@ -120,48 +170,18 @@ double ConvexHullFeature::polygon_area (const std::vector<Pixel2>& vertices)
 
 void ConvexHullFeature::osized_calculate (LR& r, ImageLoader& imloader)
 {
-	r.convHull_CH.clear();
-
-	size_t n = r.raw_pixels_NT.size();
-
-	// Skip calculation if the ROI is too small
-	if (n < 2)
-		return;
-
-	std::vector<Pixel2>& upperCH = r.convHull_CH;
-	std::vector<Pixel2> lowerCH;
-
-	// Computing upper convex hull
-	upperCH.push_back(r.raw_pixels_NT.get_at(0));
-	upperCH.push_back(r.raw_pixels_NT.get_at(1));
-
-	for (size_t i = 2; i < n; i++)
-	{
-		while (upperCH.size() > 1 && (!right_turn(upperCH[upperCH.size() - 2], upperCH[upperCH.size() - 1], r.raw_pixels_NT.get_at(i))))
-			upperCH.pop_back();
-		upperCH.push_back(r.raw_pixels_NT.get_at(i));
-	}
-
-	// Computing lower convex hull
-	lowerCH.push_back(r.raw_pixels_NT.get_at(n - 1));
-	lowerCH.push_back(r.raw_pixels_NT.get_at(n - 2));
-
-	for (size_t i = 2; i < n; i++)
-	{
-		while (lowerCH.size() > 1 && (!right_turn(lowerCH[lowerCH.size() - 2], lowerCH[lowerCH.size() - 1], r.raw_pixels_NT.get_at(n - i - 1))))
-			lowerCH.pop_back();
-		lowerCH.push_back(r.raw_pixels_NT.get_at(n - i - 1));
-	}
+	// Build the convex hull
+	build_convex_hull (r.raw_pixels_NT, r.convHull_CH);
 
-	// We could use 
-	//		upperCH.insert (upperCH.end(), lowerCH.begin(), lowerCH.end());
-	// but we don't need duplicate points in the result contour
-	for (auto& p : lowerCH)
-		if (std::find(upperCH.begin(), upperCH.end(), p) == upperCH.end())
-			upperCH.push_back(p);
+	// Calculate related features
+	double s_hull = polygon_area(r.convHull_CH),
+		s_roi = r.raw_pixels_NT.size(),
+		p = r.fvals[PERIMETER][0];
+	area = s_hull;
+	solidity = s_roi / s_hull;
+	circularity = sqrt(4.0 * M_PI * s_roi / (p * p));
 }
 
-
 namespace Nyxus
 {
 	void parallelReduceConvHull (size_t start, size_t end, std::vector<int>* ptrLabels, std::unordered_map <int, LR>* ptrLabelData)
diff --git a/src/nyx/features/erosion_pixels.cpp b/src/nyx/features/erosion_pixels.cpp
index aef2827b..86e6bdc8 100644
--- a/src/nyx/features/erosion_pixels.cpp
+++ b/src/nyx/features/erosion_pixels.cpp
@@ -4,56 +4,49 @@
 ErosionPixelsFeature::ErosionPixelsFeature() : FeatureMethod("ErosionPixelsFeature")
 {
 	provide_features({ EROSIONS_2_VANISH, EROSIONS_2_VANISH_COMPLEMENT });
-	add_dependencies({ PERIMETER });
+	add_dependencies({ CONVEX_HULL_AREA });	// Feature EROSIONS_2_VANISH_COMPLEMENT requires the convex hull
 }
 
 void ErosionPixelsFeature::calculate(LR& r)
 {
-	auto& I = r.aux_image_matrix;
-
-	//[rows, columns, numberOfColorChannels] = size(grayImage);
-	int rows = I.height,
-		cols = I.width;
+	// Build the mask image matrix 'I2'
+	auto width = r.aabb.get_width(),
+		height = r.aabb.get_height(),
+		minx = r.aabb.get_xmin(),
+		miny = r.aabb.get_ymin();
+	
+	SimpleMatrix<PixIntens> I2((int)width, (int)height);
 
-	//% Define structuring element.
-	//se = logical([0 1 0; 1 1 1; 0 1 0]);
-	//[p, q] = size(se);
+	for (auto px : r.raw_pixels)
+	{
+		auto x = px.x - minx,
+			y = px.y - miny;
+		I2.xy(x,y) = px.inten + 1;	// '+1' does the job: wherever intensity pixels are defined (via raw_pixels), in the MIM we have at least 1 even if the intensity is 0
+	}
 
 	auto halfHeight = (int)floor(SE_R / 2);
 	auto halfWidth = (int)floor(SE_C / 2);
 
 	// Initialize output image
-	ImageMatrix I1, I2(I);
-
-	// Discretize
-	#if 0
-		writeablePixels I2wp = I2.WriteablePixels();
-		for (size_t i = 0; i < I2wp.size(); i++)
-		{
-			PixIntens& pi = I2wp[i];
-			if (pi != 0)
-				pi = 1;
-		}
-	#endif
-
 	std::vector<PixIntens> Nv;
 	Nv.reserve(SE_R*SE_C/2);	// Reserving the nnz(struc elem matrix), roughly equal to the 50% of the SE matrix size
 	
-	numErosions = 0;
-	for (; numErosions < SANITY_MAX_NUM_EROSIONS; numErosions++)
+	// Blank auxiliary image that we'll need in the loop
+	SimpleMatrix<PixIntens> I1;
+
+	for (numErosions = 0; numErosions < SANITY_MAX_NUM_EROSIONS; numErosions++)
 	{
 		// Copy the matrix from previous iteration
 		I1 = I2;
-		writeablePixels I2p = I2.WriteablePixels();
-		pixData I1p = I1.ReadablePixels();
 
+		// Perform an erosion operation and count the number of surviving non-blank pixels
 		int numNon0 = 0;
 
-		// Perform local min operation, which is morphological erosion.
-		for (int col = (halfWidth + 1); col < (cols - halfWidth); col++)
-			for (int row = (halfHeight + 1); row < (rows - halfHeight); row++)
+		// --Perform local min operation, which is morphological erosion
+		for (int col = (halfWidth + 1); col < (width - halfWidth); col++)
+			for (int row = (halfHeight + 1); row < (height - halfHeight); row++)
 			{
-				//% Get the 3x3 (or in general, NxN) neighborhood
+				// Get the 3x3 (or in general, NxN) neighborhood
 				int row1 = row - halfHeight;
 				int row2 = row + halfHeight;
 				int col1 = col - halfWidth;
@@ -64,7 +57,7 @@ void ErosionPixelsFeature::calculate(LR& r)
 				for (int r = row1; r <= row2; r++)
 					for (int c = col1; c <= col2; c++)
 					{
-						auto pi = I1p.yx(r, c);
+						auto pi = I1.xy(c,r);
 						N[r - row1][c - col1] = pi;
 
 						if (pi)
@@ -74,7 +67,7 @@ void ErosionPixelsFeature::calculate(LR& r)
 				// Skip finding minimum if we have all-zeros
 				if (all0)
 				{
-					I2p.yx(row, col) = 0;
+					I2.xy(col, row) = 0;
 					continue;
 				}
 
@@ -89,7 +82,7 @@ void ErosionPixelsFeature::calculate(LR& r)
 					}
 
 				PixIntens minPixel = *std::min_element(Nv.begin(), Nv.end());
-				I2p.yx(row, col) = minPixel;
+				I2.xy(col, row) = minPixel;
 
 				// Count non-0 pixels
 				if (minPixel > 0)
@@ -106,78 +99,65 @@ void ErosionPixelsFeature::osized_add_online_pixel (size_t x, size_t y, uint32_t
 
 void ErosionPixelsFeature::osized_calculate (LR& r, ImageLoader& imloader)
 {
-	//
-	// ImageLoader& imlo, ReadImageMatrix_nontriv& I
-	// 
-	// WriteImageMatrix_nontriv& W
-	//
-	//
-
-	//-- auto& I = r.aux_image_matrix;
-	ReadImageMatrix_nontriv I(r.aabb);
-
-	//[rows, columns, numberOfColorChannels] = size(grayImage);
-	int rows = r.aabb.get_height(),
-		cols = r.aabb.get_width();
-
-	//% Define structuring element.
-	//se = logical([0 1 0; 1 1 1; 0 1 0]);
-	//[p, q] = size(se);
-
-	auto halfHeight = (int) floor(SE_R / 2);
-	auto halfWidth = (int) floor(SE_C / 2);
-
-	//% Initialize output image
-	//localMinImage = zeros(size(grayImage), class(grayImage));
-	//-- ImageMatrix I1, I2(I);
-	WriteImageMatrix_nontriv I1 ("ErosionPixelsFeature::osized_calculate_I1", r.label), 
-		I2 ("ErosionPixelsFeature::osized_calculate_I2", r.label);
-	I2.init_with_cloud(r.raw_pixels_NT, r.aabb);
-
-	numErosions = 0;
-	for (; numErosions < SANITY_MAX_NUM_EROSIONS; numErosions++)
+	// Build the mask image matrix 'I2'
+	auto width = r.aabb.get_width(),
+		height = r.aabb.get_height(),
+		minx = r.aabb.get_xmin(),
+		miny = r.aabb.get_ymin();
+
+	WriteImageMatrix_nontriv I2("I2", r.label);
+	I2.allocate_from_cloud (r.raw_pixels_NT, r.aabb, true);
+
+	auto halfHeight = (int)floor(SE_R / 2);
+	auto halfWidth = (int)floor(SE_C / 2);
+
+	// Initialize output image
+	std::vector<PixIntens> Nv;
+	Nv.reserve(SE_R * SE_C / 2);	// Reserving the nnz(struc elem matrix), roughly equal to the 50% of the SE matrix size
+
+	// Blank auxiliary image that we'll need to implement a chain of erosions
+	WriteImageMatrix_nontriv I1("I1", r.label);
+	I1.allocate(width, height, 0);
+
+	for (numErosions = 0; numErosions < SANITY_MAX_NUM_EROSIONS; numErosions++)
 	{
 		// Copy the matrix from previous iteration
-		//-- I1 = I2;
-		I1.copy (I2);
-
-		//-- writeablePixels I2p = I2.WriteablePixels();
-		//-- pixData I1p = I1.ReadablePixels();
+		I1.copy(I2);
 
+		// Perform an erosion operation and count the number of surviving non-blank pixels 
 		int numNon0 = 0;
 
-		// Perform local min operation, which is morphological erosion.
-		for (int col = (halfWidth + 1); col < (cols - halfWidth); col++)
-			for (int row = (halfHeight + 1); row < (rows - halfHeight); row++)
+		// --Perform local min operation, which is morphological erosion
+		for (int col = (halfWidth + 1); col < (width - halfWidth); col++)
+			for (int row = (halfHeight + 1); row < (height - halfHeight); row++)
 			{
-				//% Get the 3x3 neighborhood
+				// Get the 3x3 (or in general, NxN) neighborhood
 				int row1 = row - halfHeight;
 				int row2 = row + halfHeight;
 				int col1 = col - halfWidth;
 				int col2 = col + halfWidth;
 
-				//thisNeighborhood = grayImage (row1:row2, col1 : col2);
 				bool all0 = true;
 				int N[SE_R][SE_C];
 				for (int r = row1; r <= row2; r++)
 					for (int c = col1; c <= col2; c++)
 					{
-						N[r - row1][c - col1] = I1.get_at (r, c);
+						auto pi = I1[r * width + c];
+						N[r - row1][c - col1] = pi;
 
-						if (N[r - row1][c - col1])
+						if (pi)
 							all0 = false;
 					}
 
 				// Skip finding minimum if we have all-zeros
 				if (all0)
 				{
-					I2.set_at (row, col, 0);
+					I2.set_at(row * width + col, 0);
 					continue;
 				}
 
 				// Apply the structuring element
-				//pixelsInSE = thisNeighborhood(se);
-				std::vector<PixIntens> Nv;
+				Nv.clear();
 				for (int r = 0; r < SE_R; r++)
 					for (int c = 0; c < SE_C; c++)
 					{
@@ -186,9 +166,8 @@ void ErosionPixelsFeature::osized_calculate (LR& r, ImageLoader& imloader)
 							Nv.push_back(N[r][c]);
 					}
 
-				//localMinImage(row, col) = min(pixelsInSE);
 				PixIntens minPixel = *std::min_element(Nv.begin(), Nv.end());
-				I2.set_at (row, col, minPixel);
+				I2.set_at(row * width + col, minPixel);
 
 				// Count non-0 pixels
 				if (minPixel > 0)
@@ -217,7 +196,7 @@ void ErosionPixelsFeature::parallel_process_1_batch(size_t start, size_t end, st
 			continue;
 
 		// Check if data is good
-		if ((int)r.fvals[MIN][0] == (int)r.fvals[MAX][0])
+		if (r.aux_min == r.aux_max)
 			continue;
 
 		// Calculate feature
diff --git a/src/nyx/features/fractal_dim.cpp b/src/nyx/features/fractal_dim.cpp
index bc9b1f78..3839a1fb 100644
--- a/src/nyx/features/fractal_dim.cpp
+++ b/src/nyx/features/fractal_dim.cpp
@@ -4,68 +4,175 @@
 FractalDimensionFeature::FractalDimensionFeature() : FeatureMethod("FractalDimensionFeature")
 {
 	provide_features({ FRACT_DIM_BOXCOUNT, FRACT_DIM_PERIMETER });
+	add_dependencies({ PERIMETER });	// FRACT_DIM_PERIMETER requires perimeter's pixels
 }
 
 void FractalDimensionFeature::calculate(LR& r)
 {
-	Power2PaddedImageMatrix pim(r.raw_pixels, r.aabb);
+	if (theFeatureSet.isEnabled(FRACT_DIM_BOXCOUNT))
+		calculate_boxcount_fdim(r);
+
+	if (theFeatureSet.isEnabled(FRACT_DIM_PERIMETER))
+		calculate_perimeter_fdim(r);
+}
+
+void FractalDimensionFeature::calculate_boxcount_fdim (LR & r)
+{
+	Power2PaddedImageMatrix pim(r.raw_pixels, r.aabb, 1, 1.0);	// image matrix of the mask
 
 	// Debug
 	// pim.print("Padded");
 
-	std::vector<std::pair<int, int>> curve;
-	std::vector<std::pair<int, int>> curveLog;
-
-	int s = pim.width;	// tile size
+	// Square box coverage statistics
+	std::vector<std::pair<int, int>> coverage;
+	int s = pim.width;	// square tile size
 	for (; s > 1; s /= 2)
 	{
 		int cnt = 0;
+		size_t areaCov = 0;
 		int n_tiles = pim.width / s;
 		for (int r = 0; r < n_tiles; r++)
 			for (int c = 0; c < n_tiles; c++)
 			{
+				// check the tile for coerage
 				if (pim.tile_contains_signal(r, c, s))
 					cnt++;
 			}
-		curve.push_back({ s, cnt });
+
+		coverage.push_back({ s, cnt });
 	}
 
-	// Do we have data?
-	if (curve.size() == 0)
-		return;
+	// Debug
+	// print_curve(boxCoverage, "boxCoverage N vs R");	
 
-	// Post-process
-	std::vector <double> X, Y;
-	// -- log
-	for (int i = 0; i < curve.size(); i++)
+	box_count_fd = -calc_lyapunov_slope(coverage);
+}
+
+void FractalDimensionFeature::calculate_boxcount_fdim_oversized (LR & r)
+{
+	Power2PaddedImageMatrix_NT pim ("pim", r.label, r.raw_pixels_NT, r.aabb, 1, 1.0);	// image matrix of the mask
+
+	// Square box coverage statistics
+	std::vector<std::pair<int, int>> coverage;
+	int s = pim.get_width();	// square tile size
+	for (; s > 1; s /= 2)
 	{
-		X.push_back(std::log(curve[i].first));
-		Y.push_back(std::log(curve[i].second));
+		int cnt = 0;
+		size_t areaCov = 0;
+		int n_tiles = pim.get_width() / s;
+		for (int r = 0; r < n_tiles; r++)
+			for (int c = 0; c < n_tiles; c++)
+			{
+				// check the tile for coerage
+				if (pim.tile_contains_signal(r, c, s))
+					cnt++;
+			}
+
+		coverage.push_back({ s, cnt });
 	}
 
+	box_count_fd = -calc_lyapunov_slope(coverage);
+}
+
+void FractalDimensionFeature::calculate_perimeter_fdim (LR& r)
+{
+	std::vector<std::pair<int, int>> coverage;
+
+	auto conLen = r.contour.size();
+	for (size_t s = conLen / 4; s > 0; s /= 2)
+	{
+		// calculate the s-approximated perimeter
+		double p = 0;
+		for (size_t i = s; i < conLen; i += s)
+		{
+			auto& px1 = r.contour[i - s],
+				px2 = r.contour[i];
+			double dist = std::sqrt(px1.sqdist(px2));
+			p += dist;
+		}
+		// --calculate the last segment separately
+		auto tail = conLen % s;
+		if (tail)
+		{
+			auto& px1 = r.contour[conLen - tail],
+				px2 = r.contour[0];
+			double dist = px1.sqdist(px2);
+			p += dist;
+		}
+
+		// save this approximation
+		coverage.push_back({ s, p });
+	}
+	perim_fd = calc_lyapunov_slope(coverage);
+}
+
+double FractalDimensionFeature::calc_lyapunov_slope (const std::vector<std::pair<int, int>> & coverage)
+{
+	// Do we have any data?
+	if (coverage.size() == 0)
+		return 0.;
+
 	// Skip tiny ROIs
-	if (Y.size() < 2)
-		return;
+	if (coverage.size() < 2)
+		return 0.;
 
-	// -- gradient
-	double y_0 = Y[1] - Y[0],
-		y_n = Y[curve.size() - 1] - Y[curve.size() - 2];
-	for (int i = 1; i < curve.size() - 1; i++)
+	// Post-process towards local gradients (in the form of Lyapunov exponents)
+	std::vector <double> X, Y;
+	for (int i = 0; i < coverage.size(); i++)
 	{
-		Y[i] = (Y[i + 1] - Y[i - 1]) / 2.0;
+		X.push_back (std::log(coverage[i].first));
+		Y.push_back (std::log(coverage[i].second));
 	}
-	Y[0] = y_0;
-	Y[curve.size() - 1] = y_n;
 
-	// Debug
-	// print_curve(curve, "fd_curve");
+	// Gradients
+	std::vector<double> Dn, Dr;
+	for (int i = 1; i < Y.size(); i++)
+	{
+		auto dn = Y[i] - Y[i - 1];
+		Dn.push_back(dn);
+		auto dr = X[i] - X[i - 1];
+		Dr.push_back(dr);
+	}
+
+	// Lyapunov exponents
+	std::vector<double> Lambda;
+	for (int i = 0; i < Dn.size(); i++)
+	{
+		auto lambda = Dn[i] / Dr[i];
+		Lambda.push_back(lambda);
+	}
+
+	// Estimate the slope of the series Lambda[k]
+	// (given y = a + bx, the slope b = \frac {n \sum{xy} - \sum{x} \sum{y}} {n \sum{x^2} - \sum{x}^2})
+	double sum_x = 0,
+		sum_y = 0,
+		sum_xy = 0,
+		sum_x2 = 0;
+	int n = Dn.size();
+	for (auto i = 0; i < n; i++)
+	{
+		double x = double(i),
+			y = Lambda[i];
+		sum_x += x;
+		sum_y += y;
+		sum_xy += x * y;
+		sum_x2 += x * x;
+	}
+	double slope = (sum_xy * double(n) - sum_x * sum_y) / (sum_x2 * double(n) - sum_x * sum_x);
+	return slope;
 }
 
 void FractalDimensionFeature::osized_add_online_pixel(size_t x, size_t y, uint32_t intensity)
 {}
 
 void FractalDimensionFeature::osized_calculate(LR& r, ImageLoader& imloader)
-{}
+{
+	if (theFeatureSet.isEnabled(FRACT_DIM_BOXCOUNT))
+		calculate_boxcount_fdim_oversized (r);
+
+	if (theFeatureSet.isEnabled(FRACT_DIM_PERIMETER))
+		calculate_perimeter_fdim(r);
+}
 
 void FractalDimensionFeature::save_value(std::vector<std::vector<double>>& fvals)
 {
diff --git a/src/nyx/features/fractal_dim.h b/src/nyx/features/fractal_dim.h
index ecef7f8b..ad624033 100644
--- a/src/nyx/features/fractal_dim.h
+++ b/src/nyx/features/fractal_dim.h
@@ -21,5 +21,9 @@ class FractalDimensionFeature: public FeatureMethod
 	static bool required(const FeatureSet& fs) { return fs.anyEnabled({ FRACT_DIM_BOXCOUNT, FRACT_DIM_PERIMETER }); }
 
 private:
+	void calculate_boxcount_fdim (LR& r);
+	void calculate_boxcount_fdim_oversized (LR& r);
+	void calculate_perimeter_fdim (LR& r);
+	double calc_lyapunov_slope (const std::vector<std::pair<int, int>>& coverage_stats);
 	double box_count_fd = 0, perim_fd = 0;
 };
\ No newline at end of file
diff --git a/src/nyx/features/glcm.cpp b/src/nyx/features/glcm.cpp
index efe6ff60..ec2bc299 100644
--- a/src/nyx/features/glcm.cpp
+++ b/src/nyx/features/glcm.cpp
@@ -2,8 +2,6 @@
 #include "../helpers/helpers.h"
 #include "../environment.h"
 
-#define EPSILON 0.000000001
-
 int GLCMFeature::offset = 1;
 int GLCMFeature::n_levels = 8;
 std::vector<int> GLCMFeature::angles = { 0, 45, 90, 135 };
@@ -32,10 +30,35 @@ GLCMFeature::GLCMFeature() : FeatureMethod("GLCMFeature")
 
 void GLCMFeature::calculate(LR& r)
 {
+	// Clear the feature values buffers
+	clear_result_buffers();
+
+	// Calculate features for all the directions
 	for (auto a: angles)
 		Extract_Texture_Features2 (a, r.aux_image_matrix, r.aux_min, r.aux_max); 
 }
 
+void GLCMFeature::clear_result_buffers()
+{
+	fvals_ASM.clear();
+	fvals_contrast.clear();
+	fvals_correlation.clear();
+	fvals_energy.clear();
+	fvals_homo.clear();
+	fvals_variance.clear();
+	fvals_IDM.clear();
+	fvals_sum_avg.clear();
+	fvals_sum_var.clear();
+	fvals_sum_entropy.clear();
+	fvals_entropy.clear();
+	fvals_diff_avg.clear();
+	fvals_diff_var.clear();
+	fvals_diff_entropy.clear();
+	fvals_meas_corr1.clear();
+	fvals_meas_corr2.clear();
+	fvals_max_corr_coef.clear();
+}
+
 void GLCMFeature::osized_add_online_pixel(size_t x, size_t y, uint32_t intensity) {}		// Not supporting the online mode for this feature method
 
 void GLCMFeature::copyfvals (AngledFeatures& dst, const AngledFeatures& src)
@@ -140,7 +163,7 @@ void GLCMFeature::Extract_Texture_Features2 (int angle, const ImageMatrix & gray
 
 	calculateCoocMatAtAngle (P_matrix, dx, dy, grays, min_val, max_val, false);
 
-	// Zero all feature values for empty ROI
+	// Zero all feature values for blank ROI
 	if (sum_p == 0) {
 
 		double f = 0.0;
@@ -232,8 +255,7 @@ void GLCMFeature::calculateCoocMatAtAngle(
 	PixIntens max_val, 
 	bool normalize)
 {
-	matrix.allocate(n_levels, n_levels, 0.0); 
-
+	matrix.allocate(n_levels, n_levels); 
 	std::fill(matrix.begin(), matrix.end(), 0.);
 
 	int d = GLCMFeature::offset;
@@ -273,12 +295,6 @@ void GLCMFeature::calculateCoocMatAtAngle(
 				count += 2;	
 				matrix.xy(y,x)++;
 				matrix.xy(x,y)++;
-
-				#ifdef TEST_GLCM
-				std::stringstream ss;
-				ss << y << "," << x;
-				print_doubles_matrix(matrix, "after " + ss.str(), "");
-				#endif
 			}
 		}
 
@@ -498,7 +514,6 @@ double GLCMFeature::f_sentropy(const SimpleMatrix<double>& P, int Ng, std::vecto
 	for(int k = 2; k <= 2 * n_levels; ++k) {
 
 		if (Pxpy[k-2] == 0) continue;
-
 		sentropy += pxpy[k-2] * fast_log10(pxpy[k-2] + EPSILON) / LOG10_2;
 	}
 
@@ -695,4 +710,3 @@ double GLCMFeature::f_homogeneity (const SimpleMatrix<double>& P_matrix, int n_l
 	return homogeneity;
 }
 
-
diff --git a/src/nyx/features/glcm.h b/src/nyx/features/glcm.h
index c011b72b..c20c286e 100644
--- a/src/nyx/features/glcm.h
+++ b/src/nyx/features/glcm.h
@@ -60,42 +60,17 @@ class GLCMFeature: public FeatureMethod
 
 private:
 
-	void Extract_Texture_Features_nontriv(
-		int distance,
-		int angle,
-		const OOR_ReadMatrix& grays);
-	void CoOcMat_Angle_0_nontriv (
-		// out
-		SimpleMatrix<double>& matrix,
-		// in
-		int distance,
-		const OOR_ReadMatrix& grays,
-		const int* tone_LUT,
-		int tone_count);
-	void CoOcMat_Angle_45_nontriv (
-		// out
-		SimpleMatrix<double>& matrix,
-		// in
-		int distance,
-		const OOR_ReadMatrix& grays,
-		const int* tone_LUT,
-		int tone_count);
-	void CoOcMat_Angle_90_nontriv (
+	void Extract_Texture_Features2_NT(int angle, WriteImageMatrix_nontriv& grays, PixIntens min_val, PixIntens max_val);
+	void calculateCoocMatAtAngle_NT(
 		// out
 		SimpleMatrix<double>& matrix,
 		// in
-		int distance,
-		const OOR_ReadMatrix& grays,
-		const int* tone_LUT,
-		int tone_count);
-	void CoOcMat_Angle_135_nontriv (
-		// out
-		SimpleMatrix<double>& matrix,
-		// in
-		int distance,
-		const OOR_ReadMatrix& grays,
-		const int* tone_LUT,
-		int tone_count);
+		int dx,
+		int dy,
+		WriteImageMatrix_nontriv& grays,
+		PixIntens min_val,
+		PixIntens max_val,
+		bool normalize);
 
 	void Extract_Texture_Features(
 		int distance,
@@ -156,6 +131,8 @@ class GLCMFeature: public FeatureMethod
 		fvals_meas_corr2,
 		fvals_max_corr_coef;
 
+	void clear_result_buffers();
+
 	double hx = -1, hy = -1, hxy = -1, hxy1 = -1, hxy2 = -1;	// Entropies for f12/f13_icorr calculation
 	void calcH (const SimpleMatrix<double>& P_matrix, int tone_count, std::vector<double>& px, std::vector<double>& py);
 	double f_info_meas_corr1 (const SimpleMatrix<double>& P_matrix, int tone_count, std::vector<double>& px, std::vector<double>& py);
@@ -169,6 +146,6 @@ class GLCMFeature: public FeatureMethod
 	const double LOG10_2 = 0.30102999566;	// precalculated log 2 base 10
 	SimpleMatrix<double> P_matrix;
 	std::vector<double> Pxpy, Pxmy;
-
+	const double EPSILON = 0.000000001;
 };
 
diff --git a/src/nyx/features/glcm_nontriv.cpp b/src/nyx/features/glcm_nontriv.cpp
index 1180b8d5..acd231db 100644
--- a/src/nyx/features/glcm_nontriv.cpp
+++ b/src/nyx/features/glcm_nontriv.cpp
@@ -1,263 +1,200 @@
+#include "../environment.h"
 #include "glcm.h"
+#include "image_matrix_nontriv.h"
 
 void GLCMFeature::osized_calculate(LR& r, ImageLoader& imloader)
 {
-	// Calculate normalized graytones
-	OOR_ReadMatrix G(imloader, r.aabb);
-	G.apply_normalizing_range(r.aux_min, r.aux_max, 255.0);
-
-	int Angles[] = { 0, 45, 90, 135 },
-		nAngs = sizeof(Angles) / sizeof(Angles[0]);
-	for (int i = 0; i < nAngs; i++)
-		Extract_Texture_Features_nontriv(offset, Angles[i], G);
+	// Clear the feature values buffers
+	clear_result_buffers();
+
+	// Prepare the tone-binned image matrix
+	WriteImageMatrix_nontriv G("GLCMFeature-osized_calculate-G", r.label);
+	G.allocate_from_cloud(r.raw_pixels_NT, r.aabb, false);
+
+	for (auto a : angles)
+		Extract_Texture_Features2_NT(a, G, r.aux_min, r.aux_max);
 }
 
-void GLCMFeature::Extract_Texture_Features_nontriv(
-	int distance,
-	int angle,
-	const OOR_ReadMatrix& grays)
+void GLCMFeature::Extract_Texture_Features2_NT(int angle, WriteImageMatrix_nontriv& grays, PixIntens min_val, PixIntens max_val)
 {
 	int nrows = grays.get_height();
 	int ncols = grays.get_width();
 
-	int tone_LUT[PGM_MAXMAXVAL + 1]; // LUT mapping gray tone(0-255) to matrix indicies 
-	int tone_count = 0; // number of tones actually in the img. atleast 1 less than 255 
-
-	// Determine the number of different gray tones (not maxval) 
-	for (int row = PGM_MAXMAXVAL; row >= 0; --row)
-		tone_LUT[row] = -1;
-	for (int row = nrows - 1; row >= 0; --row)
-		for (int col = 0; col < ncols; ++col)
-		{
-			size_t v = grays.get_normed_at(row, col);
-			tone_LUT[v] = v;
-		}
+	// Allocate Px and Py vectors
+	std::vector<double> Px(n_levels * 2),
+		Py(n_levels);
 
-	for (int row = PGM_MAXMAXVAL; row >= 0; --row)
-		if (tone_LUT[row] != -1)
-			tone_count++;
+	// Compute the gray-tone spatial dependence matrix 
+	int dx, dy;
+	switch (angle)
+	{
+	case 0:
+		dx = offset;
+		dy = 0;
+		break;
+	case 45:
+		dx = offset;
+		dy = offset;
+		break;
+	case 90:
+		dx = 0;
+		dy = offset;
+		break;
+	case 135:
+		dx = -offset;
+		dy = offset;
+		break;
+	default:
+		std::cerr << "Cannot create co-occurence matrix for angle " << angle << ": unsupported angle\n";
+		return;
+	}
 
-	// Use the number of different tones to build LUT 
-	for (int row = 0, itone = 0; row <= PGM_MAXMAXVAL; row++)
-		if (tone_LUT[row] != -1)
-			tone_LUT[row] = itone++;
+	calculateCoocMatAtAngle_NT (P_matrix, dx, dy, grays, min_val, max_val, false);
 
-	// Allocate Px and Py vectors
-	std::vector<double> Px(tone_count * 2), Py(tone_count);
-
-	// Compute gray-tone spatial dependence matrix 
-	SimpleMatrix<double> P_matrix(tone_count, tone_count);
-
-	if (angle == 0)
-		CoOcMat_Angle_0_nontriv(P_matrix, distance, grays, tone_LUT, tone_count);
-	else if (angle == 45)
-		CoOcMat_Angle_45_nontriv(P_matrix, distance, grays, tone_LUT, tone_count);
-	else if (angle == 90)
-		CoOcMat_Angle_90_nontriv(P_matrix, distance, grays, tone_LUT, tone_count);
-	else if (angle == 135)
-		CoOcMat_Angle_135_nontriv(P_matrix, distance, grays, tone_LUT, tone_count);
-	else
+	// Zero all feature values for blank ROI
+	if (sum_p == 0) 
 	{
-		std::cout << "Error: Cannot create co-occurence matrix for unsupported angle " << angle << "\n";
+		double f = 0.0;
+		fvals_ASM.push_back(f);
+		fvals_contrast.push_back(f);
+		fvals_correlation.push_back(f);
+		fvals_energy.push_back(f);
+		fvals_homo.push_back(f);
+		fvals_variance.push_back(f);
+		fvals_IDM.push_back(f);
+		fvals_sum_avg.push_back(f);
+		fvals_sum_entropy.push_back(f);
+		fvals_sum_var.push_back(f);
+		fvals_entropy.push_back(f);
+		fvals_diff_var.push_back(f);
+		fvals_diff_entropy.push_back(f);
+		fvals_diff_avg.push_back(f);
+		fvals_meas_corr1.push_back(f);
+		fvals_meas_corr2.push_back(f);
+		fvals_max_corr_coef.push_back(0.0);
 		return;
 	}
 
-	// Compute the statistics for the spatial dependence matrix
-	fvals_ASM.push_back(f_asm(P_matrix, tone_count));
-	fvals_contrast.push_back(f_contrast(P_matrix, tone_count));
-	fvals_correlation.push_back(f_corr(P_matrix, tone_count, Px));
-	fvals_variance.push_back(f_var(P_matrix, tone_count));
-	fvals_IDM.push_back(f_idm(P_matrix, tone_count));
-	fvals_sum_avg.push_back(f_savg(P_matrix, tone_count, Px));
-	double se = f_sentropy(P_matrix, tone_count, Px);
-	fvals_sum_entropy.push_back(se);
-	fvals_sum_var.push_back(f_svar(P_matrix, tone_count, se, Px));
-	fvals_entropy.push_back(f_entropy(P_matrix, tone_count));
-	fvals_diff_var.push_back(f_dvar(P_matrix, tone_count, Px));
-	fvals_diff_entropy.push_back(f_dentropy(P_matrix, tone_count, Px));
-	fvals_meas_corr1.push_back(f_info_meas_corr1(P_matrix, tone_count, Px, Py));
-	fvals_meas_corr2.push_back(f_info_meas_corr2(P_matrix, tone_count, Px, Py));
-	fvals_max_corr_coef.push_back(0.0); // f14_maxcorr(P_matrix, tone_count);
-}
+	calculatePxpmy();
 
-// Compute gray-tone spatial dependence matrix 
-void GLCMFeature::CoOcMat_Angle_0_nontriv(
-	// out
-	SimpleMatrix<double>& matrix,
-	// in
-	int distance,
-	const OOR_ReadMatrix& grays,
-	const int* tone_LUT,
-	int tone_count)
-{
-	int d = distance;
-	int x, y;
-	int row, col, itone, jtone;
-	int count = 0; // normalizing factor 
+	// Compute Haralick statistics 
+	double f;
+	f = theFeatureSet.isEnabled(GLCM_ANGULAR2NDMOMENT) ? f_asm(P_matrix, n_levels) : 0.0;
+	fvals_ASM.push_back(f);
 
-	// zero out matrix 
-	matrix.fill(0.0);
+	f = theFeatureSet.isEnabled(GLCM_CONTRAST) ? f_contrast(P_matrix, n_levels) : 0.0;
+	fvals_contrast.push_back(f);
 
-	int rows = grays.get_height(),
-		cols = grays.get_width();
+	f = theFeatureSet.isEnabled(GLCM_CORRELATION) ? f_corr(P_matrix, n_levels, Px) : 0.0;
+	fvals_correlation.push_back(f);
 
-	for (row = 0; row < rows; ++row)
-		for (col = 0; col < cols; ++col)
-		{
-			// only non-zero values count
-			if (grays.get_normed_at(row, col) == 0)
-				continue;
+	f = theFeatureSet.isEnabled(GLCM_ENERGY) ? f_energy(P_matrix, n_levels, Px) : 0.0;
+	fvals_energy.push_back(f);
 
-			// find x tone 
-			if (col + d < cols && grays.get_normed_at(row, col + d))
-			{
-				x = tone_LUT[(int)grays.get_normed_at(row, col)];
-				y = tone_LUT[(int)grays.get_normed_at(row, col + d)];
-				matrix.xy(x, y)++;
-				matrix.xy(y, x)++;
-				count += 2;
-			}
-		}
+	f = theFeatureSet.isEnabled(GLCM_HOMOGENEITY) ? f_homogeneity(P_matrix, n_levels, Px) : 0.0;
+	fvals_homo.push_back(f);
 
-	// normalize matrix 
-	for (itone = 0; itone < tone_count; ++itone)
-		for (jtone = 0; jtone < tone_count; ++jtone)
-			if (count == 0)   // protect from error 
-				matrix.xy(itone, jtone) = 0;
-			else
-				matrix.xy(itone, jtone) /= count;
-}
+	f = theFeatureSet.isEnabled(GLCM_VARIANCE) ? f_var(P_matrix, n_levels) : 0.0;
+	fvals_variance.push_back(f);
 
-void GLCMFeature::CoOcMat_Angle_90_nontriv(
-	// out
-	SimpleMatrix<double>& matrix,
-	// in
-	int distance,
-	const OOR_ReadMatrix& grays,
-	const int* tone_LUT,
-	int tone_count)
-{
-	int d = distance;
-	int x, y;
-	int row, col, itone, jtone;
-	int count = 0; // normalizing factor 
+	f = theFeatureSet.isEnabled(GLCM_INVERSEDIFFERENCEMOMENT) ? f_idm(P_matrix, n_levels) : 0.0;
+	fvals_IDM.push_back(f);
 
-	matrix.fill(0.0);
+	f = theFeatureSet.isEnabled(GLCM_SUMAVERAGE) ? f_savg(P_matrix, n_levels, Px) : 0.0;
+	fvals_sum_avg.push_back(f);
 
-	int rows = grays.get_height(),
-		cols = grays.get_width();
+	f = theFeatureSet.isEnabled(GLCM_SUMENTROPY) ? f_sentropy(P_matrix, n_levels, Px) : 0.0;
+	fvals_sum_entropy.push_back(f);
 
-	for (row = 0; row < rows; ++row)
-		for (col = 0; col < cols; ++col) {
-			// only non-zero values count
-			if (grays.get_normed_at(row, col) == 0)
-				continue;
-
-			// find x tone 
-			if (row + d < rows && grays.get_normed_at(row + d, col)) {
-				x = tone_LUT[(int)grays.get_normed_at(row, col)];
-				y = tone_LUT[(int)grays.get_normed_at(row + d, col)];
-				matrix.xy(x, y)++;
-				matrix.xy(y, x)++;
-				count += 2;
-			}
-		}
+	f = theFeatureSet.isEnabled(GLCM_SUMVARIANCE) ? f_svar(P_matrix, n_levels, f, Px) : 0.0;
+	fvals_sum_var.push_back(f);
 
-	// normalize matrix 
-	for (itone = 0; itone < tone_count; ++itone)
-		for (jtone = 0; jtone < tone_count; ++jtone)
-			if (count == 0)
-				matrix.xy(itone, jtone) = 0;
-			else
-				matrix.xy(itone, jtone) /= count;
-}
+	f = theFeatureSet.isEnabled(GLCM_ENTROPY) ? f_entropy(P_matrix, n_levels) : 0.0;
+	fvals_entropy.push_back(f);
 
-void GLCMFeature::CoOcMat_Angle_45_nontriv(
-	// out
-	SimpleMatrix<double>& matrix,
-	// in
-	int distance,
-	const OOR_ReadMatrix& grays,
-	const int* tone_LUT,
-	int tone_count)
-{
-	int d = distance;
-	int x, y;
-	int row, col, itone, jtone;
-	int count = 0; // normalizing factor 
+	f = theFeatureSet.isEnabled(GLCM_DIFFERENCEVARIANCE) ? f_dvar(P_matrix, n_levels, Px) : 0.0;
+	fvals_diff_var.push_back(f);
 
-	matrix.fill(0.0);
+	f = theFeatureSet.isEnabled(GLCM_DIFFERENCEENTROPY) ? f_dentropy(P_matrix, n_levels, Px) : 0.0;
+	fvals_diff_entropy.push_back(f);
 
-	int rows = grays.get_height(),
-		cols = grays.get_width();
+	f = theFeatureSet.isEnabled(GLCM_DIFFERENCEAVERAGE) ? f_difference_avg(P_matrix, n_levels, Px) : 0.0;
+	fvals_diff_avg.push_back(f);
 
-	for (row = 0; row < rows; ++row)
-		for (col = 0; col < cols; ++col) {
-			// only non-zero values count
-			if (grays.get_normed_at(row, col) == 0)
-				continue;
-
-			// find x tone
-			if (row + d < rows && col - d >= 0 && grays.get_normed_at(row + d, col - d)) {
-				x = tone_LUT[(int)grays.get_normed_at(row, col - d)];
-				y = tone_LUT[(int)grays.get_normed_at(row + d, col - d)];
-				matrix.xy(x, y)++;
-				matrix.xy(y, x)++;
-				count += 2;
-			}
-		}
+	f = theFeatureSet.isEnabled(GLCM_INFOMEAS1) ? f_info_meas_corr1(P_matrix, n_levels, Px, Py) : 0.0;
+	fvals_meas_corr1.push_back(f);
+
+	f = theFeatureSet.isEnabled(GLCM_INFOMEAS2) ? f_info_meas_corr2(P_matrix, n_levels, Px, Py) : 0.0;
+	fvals_meas_corr2.push_back(f);
 
-	/* normalize matrix */
-	for (itone = 0; itone < tone_count; ++itone)
-		for (jtone = 0; jtone < tone_count; ++jtone)
-			if (count == 0)
-				matrix.xy(itone, jtone) = 0;	// protect from error
-			else
-				matrix.xy(itone, jtone) /= count;
+	fvals_max_corr_coef.push_back(0.0);
 }
 
-void GLCMFeature::CoOcMat_Angle_135_nontriv(
+void GLCMFeature::calculateCoocMatAtAngle_NT(
 	// out
 	SimpleMatrix<double>& matrix,
 	// in
-	int distance,
-	const OOR_ReadMatrix& grays,
-	const int* tone_LUT,
-	int tone_count)
+	int dx,
+	int dy,
+	WriteImageMatrix_nontriv& grays,
+	PixIntens min_val,
+	PixIntens max_val,
+	bool normalize)
 {
-	int d = distance;
-	int x, y;
-	int row, col, itone, jtone;
-	int count = 0; // normalizing factor 
-
+	matrix.allocate(n_levels, n_levels);
 	matrix.fill(0.0);
 
+	int d = GLCMFeature::offset;
+	int count = 0;	// normalizing factor 
+
 	int rows = grays.get_height(),
 		cols = grays.get_width();
 
-	for (row = 0; row < rows; ++row)
-		for (col = 0; col < cols; ++col) {
-			// only non-zero values count
-			if (grays.get_normed_at(row, col) == 0)
-				continue;
+	PixIntens range = max_val - min_val;
 
-			// find x tone 
-			if (row + d < rows && col + d < cols && grays.get_normed_at(row + d, col + d))
+	for (int row = 0; row < rows; row++)
+		for (int col = 0; col < cols; col++)
+		{
+			if (row + dy >= 0 && row + dy < rows && col + dx >= 0 && col + dx < cols && grays.yx(row + dy, col + dx))
 			{
-				x = tone_LUT[(int)grays.get_normed_at(row, col)];
-				y = tone_LUT[(int)grays.get_normed_at(row + d, col + d)];
-				matrix.xy(x, y)++;		//NONOPT
-				matrix.xy(y, x)++;
+				// Raw intensities
+				auto raw_lvl_y = grays.yx(row, col),
+					raw_lvl_x = grays.yx(row + dy, col + dx);
+
+				// Skip non-informative pixels
+				if (raw_lvl_x == 0 || raw_lvl_y == 0)
+					continue;
+
+				int x = raw_lvl_x - 1,
+					y = raw_lvl_y - 1;
+
+				// Cast intensities on the 1-n_levels scale
+				if (Environment::ibsi_compliance == false)
+				{
+					x = GLCMFeature::cast_to_range(raw_lvl_x, min_val, max_val, 1, GLCMFeature::n_levels) - 1;
+					y = GLCMFeature::cast_to_range(raw_lvl_y, min_val, max_val, 1, GLCMFeature::n_levels) - 1;
+				}
+
+				// Increment the symmetric count
 				count += 2;
+				matrix.xy(y,x)++;
+				matrix.xy(x,y)++;
 			}
 		}
 
-	// normalize matrix 
-	for (itone = 0; itone < tone_count; ++itone)
-		for (jtone = 0; jtone < tone_count; ++jtone)
-			if (count == 0)
-				matrix.xy(itone, jtone) = 0;	// protect from error
-			else
-				matrix.xy(itone, jtone) /= count;
+	// calculate sum of P for feature calculations
+	sum_p = 0;
+	for (int i = 0; i < n_levels; ++i)
+		for (int j = 0; j < n_levels; ++j)
+			sum_p += matrix.xy(i, j);
+
+	// Normalize the matrix
+	if (normalize == false)
+		return;
+
+	double realCnt = count;
+	for (int i = 0; i < GLCMFeature::n_levels; i++)
+		for (int j = 0; j < GLCMFeature::n_levels; j++)
+			matrix.xy(i, j) /= (realCnt + EPSILON);
 }
 
diff --git a/src/nyx/features/gldm.cpp b/src/nyx/features/gldm.cpp
index a802f6a2..73033f16 100644
--- a/src/nyx/features/gldm.cpp
+++ b/src/nyx/features/gldm.cpp
@@ -8,7 +8,8 @@
 
 GLDMFeature::GLDMFeature() : FeatureMethod("GLDMFeature")
 {
-	provide_features({ GLDM_SDE,
+	provide_features({ 
+		GLDM_SDE,
 		GLDM_LDE,
 		GLDM_GLN,
 		GLDM_DN,
@@ -26,6 +27,8 @@ GLDMFeature::GLDMFeature() : FeatureMethod("GLDMFeature")
 
 void GLDMFeature::calculate(LR& r)
 {	
+	clear_buffers();
+
 	if (r.aux_min == r.aux_max)
 		return;
 
@@ -42,13 +45,14 @@ void GLDMFeature::calculate(LR& r)
 	PixIntens piRange = r.aux_max - r.aux_min;
 
 	unsigned int nGrays = theEnvironment.get_coarse_gray_depth();
+	bool disableGrayBinning = Environment::ibsi_compliance || nGrays >= piRange;
 
 	// Gather zones
 	for (int row = 0; row < D.height(); row++)
 		for (int col = 0; col < D.width(); col++)
 		{
 			// Find a non-blank pixel
-			PixIntens pi = Nyxus::to_grayscale (D.yx(row, col), r.aux_min, piRange, nGrays, Environment::ibsi_compliance);
+			PixIntens pi = Nyxus::to_grayscale (D.yx(row, col), r.aux_min, piRange, nGrays, disableGrayBinning);
 
 			if (pi == 0)
 				continue;
@@ -129,7 +133,7 @@ void GLDMFeature::calculate(LR& r)
 		}
 
 	//==== Fill the matrix
-	Ng = *std::max_element(std::begin(r.aux_image_matrix.ReadablePixels()), std::end(r.aux_image_matrix.ReadablePixels()));
+	Ng = disableGrayBinning ? *std::max_element(std::begin(r.aux_image_matrix.ReadablePixels()), std::end(r.aux_image_matrix.ReadablePixels())) : (int)U.size();
 	Nd = 8 + 1;	// N, NE, E, SE, S, SW, W, NW + zero
 	Nz = (decltype(Nz))Z.size();
 
@@ -145,7 +149,7 @@ void GLDMFeature::calculate(LR& r)
 	{
 		// row
 		auto iter = std::find(I.begin(), I.end(), z.first);
-		int row = (Environment::ibsi_compliance) ? z.first-1 : int(iter - I.begin());
+		int row = disableGrayBinning ? z.first - 1 : int(iter - I.begin());
 		// col
 		int col = z.second - 1;	// 1-based
 		// increment
@@ -163,10 +167,24 @@ void GLDMFeature::calculate(LR& r)
 	}
 }
 
+void GLDMFeature::clear_buffers()
+{
+	bad_roi_data = false;
+	int Ng = 0;
+	int Nd = 0;
+	int Nz = 0;
+
+	double sum_p = 0;
+
+	P.clear();
+}
+
 void GLDMFeature::osized_add_online_pixel(size_t x, size_t y, uint32_t intensity) {}
 
-void GLDMFeature::osized_calculate (LR& r, ImageLoader& imloader)
+void GLDMFeature::osized_calculate (LR& r, ImageLoader&)
 {
+	clear_buffers();
+
 	if (r.aux_min == r.aux_max)
 		return;
 
@@ -177,35 +195,93 @@ void GLDMFeature::osized_calculate (LR& r, ImageLoader& imloader)
 	//==== While scanning clusters, learn unique intensities 
 	std::unordered_set<PixIntens> U;
 
-	ReadImageMatrix_nontriv D(r.aabb); //-- const pixData& D = r.aux_image_matrix.ReadablePixels();
+	WriteImageMatrix_nontriv D("GLDMFeature-osized_calculate-D", r.label);
+	D.allocate_from_cloud(r.raw_pixels_NT, r.aabb, false);
+
+	// Prepare ROI's intensity range for normalize_I()
+	PixIntens piRange = r.aux_max - r.aux_min;
+
+	unsigned int nGrays = theEnvironment.get_coarse_gray_depth();
+
+	size_t height = D.get_height(),
+		width = D.get_width();
 
 	// Gather zones
-	for (int row = 1; row < D.get_height() - 1; row++)
-		for (int col = 1; col < D.get_width() - 1; col++)
+	for (size_t row = 0; row < height; row++)
+		for (size_t col = 0; col < width; col++)
 		{
 			// Find a non-blank pixel
-			PixIntens pi = D.get_at(imloader, row, col);
+			PixIntens pi = Nyxus::to_grayscale((unsigned int) D.yx(row, col), r.aux_min, piRange, nGrays, Environment::ibsi_compliance);
+
 			if (pi == 0)
 				continue;
 
 			// Count dependencies
-			int nd = 0;	// Number of dependencies
-			if (D.safe(row-1, col) && D.get_at(imloader, row - 1, col) == pi)	// North
-				nd++;
-			if (D.safe(row-1, col+1) && D.get_at(imloader, row - 1, col + 1) == pi)	// North-East
-				nd++;
-			if (D.safe(row, col+1) && D.get_at(imloader, row, col + 1) == pi)	// East
-				nd++;
-			if (D.safe(row+1, col+1) && D.get_at(imloader, row + 1, col + 1) == pi)	// South-East
-				nd++;
-			if (D.safe(row+1, col) && D.get_at(imloader, row + 1, col) == pi)	// South
-				nd++;
-			if (D.safe(row+1, col-1) && D.get_at(imloader, row + 1, col - 1) == pi)	// South-West
-				nd++;
-			if (D.safe(row, col-1) && D.get_at(imloader, row, col - 1) == pi)	// West
-				nd++;
-			if (D.safe(row-1, col-1) && D.get_at(imloader, row - 1, col - 1) == pi)	// North-West
-				nd++;
+			int nd = 1;	// Number of dependencies
+			PixIntens piQ; // Pixel intensity of questionn
+			if (D.safe(row - 1, col)) {
+
+				piQ = Nyxus::to_grayscale((unsigned int) D.yx(row - 1, col), r.aux_min, piRange, nGrays, Environment::ibsi_compliance);	// North
+
+				if (piQ == pi)
+					nd++;
+			}
+
+			if (D.safe(row - 1, col + 1)) {
+
+				piQ = Nyxus::to_grayscale((unsigned int) D.yx(row - 1, col + 1), r.aux_min, piRange, nGrays, Environment::ibsi_compliance);	// North-East
+
+				if (piQ == pi)
+					nd++;
+			}
+
+			if (D.safe(row, col + 1)) {
+
+				piQ = Nyxus::to_grayscale((unsigned int) D.yx(row, col + 1), r.aux_min, piRange, nGrays, Environment::ibsi_compliance);	// East
+
+				if (piQ == pi)
+					nd++;
+			}
+
+			if (D.safe(row + 1, col + 1)) {
+
+				piQ = Nyxus::to_grayscale((unsigned int) D.yx(row + 1, col + 1), r.aux_min, piRange, nGrays, Environment::ibsi_compliance);	// South-East
+
+				if (piQ == pi)
+					nd++;
+			}
+
+			if (D.safe(row + 1, col)) {
+
+				piQ = Nyxus::to_grayscale((unsigned int) D.yx(row + 1, col), r.aux_min, piRange, nGrays, Environment::ibsi_compliance);		// South
+
+				if (piQ == pi)
+					nd++;
+			}
+
+			if (D.safe(row + 1, col - 1)) {
+
+				piQ = Nyxus::to_grayscale((unsigned int) D.yx(row + 1, col - 1), r.aux_min, piRange, nGrays, Environment::ibsi_compliance);	// South-West
+
+				if (piQ == pi)
+					nd++;
+			}
+
+			if (D.safe(row, col - 1)) {
+
+				piQ = Nyxus::to_grayscale((unsigned int) D.yx(row, col - 1), r.aux_min, piRange, nGrays, Environment::ibsi_compliance);		// West
+
+				if (piQ == pi)
+					nd++;
+			}
+
+			if (D.safe(row - 1, col - 1)) {
+
+				piQ = Nyxus::to_grayscale((unsigned int) D.yx(row - 1, col - 1), r.aux_min, piRange, nGrays, Environment::ibsi_compliance);	// North-West
+
+				if (piQ == pi)
+					nd++;
+			}
 
 			// Save the intensity's dependency
 			ACluster clu = { pi, nd };
@@ -216,13 +292,12 @@ void GLDMFeature::osized_calculate (LR& r, ImageLoader& imloader)
 		}
 
 	//==== Fill the matrix
-
-	Ng = (decltype(Ng))U.size();
+	Ng = (int) U.size();
 	Nd = 8 + 1;	// N, NE, E, SE, S, SW, W, NW + zero
 	Nz = (decltype(Nz))Z.size();
 
 	// --allocate the matrix
-	P.allocate(Nd, Ng);
+	P.allocate(Nd + 1, Ng + 1);
 
 	// --Set to vector to be able to know each intensity's index
 	std::vector<PixIntens> I(U.begin(), U.end());
@@ -233,13 +308,22 @@ void GLDMFeature::osized_calculate (LR& r, ImageLoader& imloader)
 	{
 		// row
 		auto iter = std::find(I.begin(), I.end(), z.first);
-		int row = int(iter - I.begin());
+		int row = (Environment::ibsi_compliance) ? z.first - 1 : int(iter - I.begin());
 		// col
-		int col = z.second;	// 1-based
+		int col = z.second - 1;	// 1-based
 		// increment
 		auto& k = P.xy(col, row);
 		k++;
 	}
+
+	sum_p = 0;
+	for (int i = 1; i <= Ng; i++)
+	{
+		for (int j = 1; j <= Nd; j++)
+		{
+			sum_p += P.matlab(i, j);
+		}
+	}
 }
 
 void GLDMFeature::save_value(std::vector<std::vector<double>>& fvals)
diff --git a/src/nyx/features/gldm.h b/src/nyx/features/gldm.h
index c24be528..7ab120bf 100644
--- a/src/nyx/features/gldm.h
+++ b/src/nyx/features/gldm.h
@@ -91,6 +91,8 @@ class GLDMFeature: public FeatureMethod
 
 	SimpleMatrix<int> P;	// dependence matrix
 
+	void clear_buffers();
+
 	const double BAD_ROI_FVAL = 0.0;
 	const double EPS = 2.2e-16;
 	const double LOG10_2 = 0.30102999566;	// precalculated log 2 base 10
diff --git a/src/nyx/features/glrlm.cpp b/src/nyx/features/glrlm.cpp
index 3f38e56f..8ba63520 100644
--- a/src/nyx/features/glrlm.cpp
+++ b/src/nyx/features/glrlm.cpp
@@ -29,6 +29,9 @@ GLRLMFeature::GLRLMFeature() : FeatureMethod("GLRLMFeature")
 
 void GLRLMFeature::calculate (LR& r)
 {
+	//==== Clear the feature values buffers
+	clear_buffers();
+
 	auto minI = r.aux_min,
 		maxI = r.aux_max;
 	const ImageMatrix& im = r.aux_image_matrix;
@@ -251,32 +254,65 @@ void GLRLMFeature::calculate (LR& r)
 		sum_p.push_back(sum);
 	}
 
-	calc_SRE (angled_SRE);
-	calc_LRE (angled_LRE);
-	calc_GLN (angled_GLN);
-	calc_GLNN (angled_GLNN);
-	calc_RLN (angled_RLN);
-	calc_RLNN (angled_RLNN);
-	calc_RP (angled_RP);
-	calc_GLV (angled_GLV);
-	calc_RV (angled_RV);
-	calc_RE (angled_RE);
-	calc_LGLRE (angled_LGLRE);
-	calc_HGLRE (angled_HGLRE);
-	calc_SRLGLE (angled_SRLGLE);
-	calc_SRHGLE (angled_SRHGLE);
-	calc_LRLGLE (angled_LRLGLE);
-	calc_LRHGLE (angled_LRHGLE);
+	calc_SRE(angled_SRE);
+	calc_LRE(angled_LRE);
+	calc_GLN(angled_GLN);
+	calc_GLNN(angled_GLNN);
+	calc_RLN(angled_RLN);
+	calc_RLNN(angled_RLNN);
+	calc_RP(angled_RP);
+	calc_GLV(angled_GLV);
+	calc_RV(angled_RV);
+	calc_RE(angled_RE);
+	calc_LGLRE(angled_LGLRE);
+	calc_HGLRE(angled_HGLRE);
+	calc_SRLGLE(angled_SRLGLE);
+	calc_SRHGLE(angled_SRHGLE);
+	calc_LRLGLE(angled_LRLGLE);
+	calc_LRHGLE(angled_LRHGLE);
+}
+
+void GLRLMFeature::clear_buffers()
+{
+	bad_roi_data = false;
+	angles_Ng.clear();
+	angles_Nr.clear();
+	angles_Np.clear();
+	angles_P.clear();
+	sum_p.clear();
+
+	angled_SRE.clear();
+	angled_LRE.clear();
+	angled_GLN.clear();
+	angled_GLNN.clear();
+	angled_RLN.clear();
+	angled_RLNN.clear();
+	angled_RP.clear();
+	angled_GLV.clear();
+	angled_RV.clear();
+	angled_RE.clear();
+	angled_LGLRE.clear();
+	angled_HGLRE.clear();
+	angled_SRLGLE.clear();
+	angled_SRHGLE.clear();
+	angled_LRLGLE.clear();
+	angled_LRHGLE.clear();
 }
 
 // Not supporting the online mode
 void GLRLMFeature::osized_add_online_pixel(size_t x, size_t y, uint32_t intensity) {} // Not supporting
 
-void GLRLMFeature::osized_calculate(LR& r, ImageLoader& imloader)
+void GLRLMFeature::osized_calculate(LR& r, ImageLoader&)
 {
+	//==== Clear the feature values buffers
+	clear_buffers();
+
 	auto minI = r.aux_min,
 		maxI = r.aux_max;
 
+	WriteImageMatrix_nontriv im("GLRLMFeature-osized_calculate-im", r.label);
+	im.allocate_from_cloud(r.raw_pixels_NT, r.aabb, false);
+
 	//==== Check if the ROI is degenerate (equal intensity => no texture)
 	if (minI == maxI)
 	{
@@ -302,8 +338,6 @@ void GLRLMFeature::osized_calculate(LR& r, ImageLoader& imloader)
 		return;
 	}
 
-	ReadImageMatrix_nontriv im(r.aabb); //-- const ImageMatrix& im = r.aux_image_matrix;
-
 	//--debug-- im.print("initial ROI\n");
 
 	//==== Make a list of intensity clusters (zones)
@@ -315,7 +349,10 @@ void GLRLMFeature::osized_calculate(LR& r, ImageLoader& imloader)
 	using AngleUniqInte = std::unordered_set<PixIntens>;
 	//--unnec--	std::vector<AngleUniqInte>  angles_U;
 
-	//==== Iterate angles 0, 45, 90, 135
+	// Prepare ROI's intensity range
+	PixIntens piRange = r.aux_max - r.aux_min;
+
+	//==== Iterate angles 0,45,90,135
 	for (int angleIdx = 0; angleIdx < 4; angleIdx++)
 	{
 		// Clusters at angle 'angleIdx'
@@ -327,22 +364,26 @@ void GLRLMFeature::osized_calculate(LR& r, ImageLoader& imloader)
 		// We need it to estimate the x-dimension of matrix P
 		int maxZoneArea = 0;
 
-		// Copy the image matrix. We'll use it to maintain state of cluster scanning 
-		
-		//-- auto M = im;
-		//-- pixData& D = M.WriteablePixels();
-		WriteImageMatrix_nontriv D("GLRLMFeature_osized_calculate_D", r.label);
-		D.init_with_cloud(r.raw_pixels_NT, r.aabb);
+		// Clean-copy the image matrix. We'll use it to maintain state of cluster scanning 
+		WriteImageMatrix_nontriv D("GLRLMFeature-osized_calculate-D", r.label);
+		D.allocate(r.aabb.get_width(), r.aabb.get_height(), 0.0);
+		D.copy(im);
+
+		// Squeeze the intensity range
+		unsigned int nGrays = theEnvironment.get_coarse_gray_depth();
+
+		for (size_t i = 0; i < D.size(); i++)
+			D.set_at(i, Nyxus::to_grayscale(D[i], r.aux_min, piRange, nGrays, Environment::ibsi_compliance));
 
 		// Number of zones
 		const int VISITED = -1;
 
 		// Scan the image and check non-blank pixels' clusters
-		for (int row = 0; row < im.get_height(); row++)
-			for (int col = 0; col < im.get_width(); col++)
+		for (int row = 0; row < D.get_height(); row++)
+			for (int col = 0; col < D.get_width(); col++)
 			{
 				// Find a non-blank pixel
-				auto pi = D.get_at (row, col);
+				auto pi = D.yx(row, col);
 				if (pi == 0 || int(pi) == VISITED)
 					continue;
 
@@ -350,13 +391,13 @@ void GLRLMFeature::osized_calculate(LR& r, ImageLoader& imloader)
 				std::vector<std::tuple<int, int>> history;
 				int x = col, y = row;
 				int zoneArea = 1;
-				D.set_at (y, x, VISITED);
+				D.set_at(y, x, VISITED);
 
 				// State machine scanning the rest of the cluster
 				for (;;)
 				{
 					// angleIdx==0 === 0 degrees
-					if (angleIdx == 0 && D.safe(y, x + 1) && D.get_at(y, x + 1) == pi)
+					if (angleIdx == 0 && D.safe(y, x + 1) && D.yx(y, x + 1) == pi)
 					{
 						D.set_at(y, x + 1, VISITED);
 						zoneArea++;
@@ -372,7 +413,7 @@ void GLRLMFeature::osized_calculate(LR& r, ImageLoader& imloader)
 					}
 
 					// angleIdx==1 === 45 degrees
-					if (D.safe(y + 1, x + 1) && D.get_at(y + 1, x + 1) == pi)
+					if (angleIdx == 1 && D.safe(y + 1, x + 1) && D.yx(y + 1, x + 1) == pi)
 					{
 						D.set_at(y + 1, x + 1, VISITED);
 						zoneArea++;
@@ -386,7 +427,7 @@ void GLRLMFeature::osized_calculate(LR& r, ImageLoader& imloader)
 					}
 
 					// angleIdx==2 === 90 degrees
-					if (D.safe(y + 1, x) && D.get_at(y + 1, x) == pi)
+					if (angleIdx == 2 && D.safe(y + 1, x) && D.yx(y + 1, x) == pi)
 					{
 						D.set_at(y + 1, x, VISITED);
 						zoneArea++;
@@ -399,7 +440,7 @@ void GLRLMFeature::osized_calculate(LR& r, ImageLoader& imloader)
 					}
 
 					// angleIdx==3 === 135 degrees
-					if (D.safe(y + 1, x - 1) && D.get_at(y + 1, x - 1) == pi)
+					if (angleIdx == 3 && D.safe(y + 1, x - 1) && D.yx(y + 1, x - 1) == pi)
 					{
 						D.set_at(y + 1, x - 1, VISITED);
 						zoneArea++;
@@ -431,23 +472,27 @@ void GLRLMFeature::osized_calculate(LR& r, ImageLoader& imloader)
 				// --2
 				maxZoneArea = std::max(maxZoneArea, zoneArea);
 
-				//std::stringstream ss;
-				//ss << "End of cluster " << x << "," << y;
-				//M.print (ss.str());
-
 				// --3
 				ACluster clu = { pi, zoneArea };
 				Z.push_back(clu);
 			}
 
-		//M.print("finished");
+		// count non-zero pixels
+		int count = 0;
+
+		for (size_t i = 0; i < im.size(); i++)
+		{
+			auto px = im.get_at(i);
+			if (px != 0)
+				++count;
+		}
 
 		//==== Fill the zone matrix
 
-		int Ng = (decltype(Ng))U.size();
+		int Ng = Environment::ibsi_compliance ? im.get_max() : (decltype(Ng))U.size();
 		int Nr = maxZoneArea;
 		int Nz = (decltype(Nz))Z.size();
-		int Np = 1;
+		int Np = count;
 
 		// --Set to vector to be able to know each intensity's index
 		std::vector<PixIntens> I(U.begin(), U.end());
@@ -462,7 +507,7 @@ void GLRLMFeature::osized_calculate(LR& r, ImageLoader& imloader)
 		{
 			// row
 			auto iter = std::find(I.begin(), I.end(), z.first);
-			int row = int(iter - I.begin());
+			int row = (Environment::ibsi_compliance) ? z.first - 1 : int(iter - I.begin());
 			// col
 			int col = z.second - 1;	// 0-based => -1
 			// update the matrix
@@ -475,9 +520,15 @@ void GLRLMFeature::osized_calculate(LR& r, ImageLoader& imloader)
 		angles_Ng.push_back(Ng);
 		angles_Nr.push_back(Nr);
 		angles_Np.push_back(Np);
-		//--unnec-- angles_U.push_back (U);
-		//--unnec-- angles_Z.push_back (Z);
 
+		double sum = 0;
+		for (int i = 1; i <= Ng; ++i) {
+			for (int j = 1; j <= Nr; ++j) {
+				sum += P.matlab(i, j);
+			}
+		}
+
+		sum_p.push_back(sum);
 	}
 
 	calc_SRE(angled_SRE);
@@ -532,7 +583,6 @@ void GLRLMFeature::calc_SRE (AngledFtrs& af)
 		return;
 	}
 
-
 	for (int ai = 0; ai < 4; ai++)
 	{
 		if (sum_p[ai] == 0) {
diff --git a/src/nyx/features/glrlm.h b/src/nyx/features/glrlm.h
index 1b9909af..6073c832 100644
--- a/src/nyx/features/glrlm.h
+++ b/src/nyx/features/glrlm.h
@@ -108,6 +108,8 @@ class GLRLMFeature: public FeatureMethod
 	std::vector<P_matrix> angles_P;
 	std::vector<double> sum_p;
 
+	void clear_buffers();
+
 	const double EPS = 2.2e-16;
 	const double BAD_ROI_FVAL = 0.0;
 	const double LOG10_2 = 0.30102999566;	// precalculated log 2 base 10
diff --git a/src/nyx/features/glszm.cpp b/src/nyx/features/glszm.cpp
index 94e86c6b..2e16d885 100644
--- a/src/nyx/features/glszm.cpp
+++ b/src/nyx/features/glszm.cpp
@@ -29,8 +29,10 @@ GLSZMFeature::GLSZMFeature() : FeatureMethod("GLSZMFeature")
 
 void GLSZMFeature::osized_add_online_pixel (size_t x, size_t y, uint32_t intensity) {} // Not suporting
 
-void GLSZMFeature::osized_calculate (LR& r, ImageLoader& imloader)
+void GLSZMFeature::osized_calculate (LR& r, ImageLoader&)
 {
+	clear_buffers();
+
 	//==== Check if the ROI is degenerate (equal intensity)
 	if (r.aux_min == r.aux_max)
 		return;
@@ -44,21 +46,33 @@ void GLSZMFeature::osized_calculate (LR& r, ImageLoader& imloader)
 
 	int maxZoneArea = 0;
 
+	// Create an image matrix for this ROI
+	WriteImageMatrix_nontriv M ("GLSZMFeature-osized_calculate-M", r.label);
+	M.allocate_from_cloud (r.raw_pixels_NT, r.aabb, false);
+
+	// Helpful temps
+	auto height = M.get_height(), 
+		width = M.get_width();
+
 	// Copy the image matrix
-	ReadImageMatrix_nontriv M(r.aabb);	//-- auto M = r.aux_image_matrix;
+	WriteImageMatrix_nontriv D ("GLSZMFeature-osized_calculate-D", r.label);
+	D.allocate (M.get_width(), M.get_height(), 0);
+	D.copy (M);
 
-	WriteImageMatrix_nontriv D ("GLSZMFeature_osized_calculate_D", r.label);	//-- pixData& D = M.WriteablePixels();
-	D.allocate (r.aabb.get_width(), r.aabb.get_height(), 0);
+	// Squeeze the intensity range
+	PixIntens piRange = r.aux_max - r.aux_min;		// Prepare ROI's intensity range
+	unsigned int nGrays = theEnvironment.get_coarse_gray_depth();
 
-	//M.print("initial\n");
+	for (size_t i = 0; i < D.size(); i++)
+		D.set_at(i, Nyxus::to_grayscale(D[i], r.aux_min, piRange, nGrays, Environment::ibsi_compliance));
 
 	// Number of zones
 	const int VISITED = -1;
-	for (int row = 0; row < M.get_height(); row++)
-		for (int col = 0; col < M.get_width(); col++)
+	for (int row = 0; row < height; row++)
+		for (int col = 0; col < width; col++)
 		{
 			// Find a non-blank pixel
-			auto pi = D.get_at (row, col);
+			auto pi = D.yx(row, col);
 			if (pi == 0 || int(pi) == VISITED)
 				continue;
 
@@ -67,53 +81,45 @@ void GLSZMFeature::osized_calculate (LR& r, ImageLoader& imloader)
 			int x = col, y = row;
 			int zoneArea = 1;
 			D.set_at(y, x, VISITED);
-			// 
+
 			for (;;)
 			{
-				if (D.safe(y, x + 1) && D.get_at(y, x + 1) == pi)
+				if (D.safe(y, x + 1) && D.yx(y, x + 1) != VISITED && D.yx(y, x + 1) == pi)
 				{
 					D.set_at(y, x + 1, VISITED);
 					zoneArea++;
 
-					//M.print("After x+1,y");
-
 					// Remember this pixel
 					history.push_back({ x,y });
-					// Advance 
+					// Advance
 					x = x + 1;
 					// Proceed
 					continue;
 				}
-				if (D.safe(y + 1, x + 1) && D.get_at(y + 1, x + 1) == pi)
+				if (D.safe(y + 1, x + 1) && D.yx(y + 1, x + 1) != VISITED && D.yx(y + 1, x + 1) == pi)
 				{
-					D.set_at(y + 1, x + 1, VISITED);
+					D.set_at (y + 1, x + 1, VISITED);
 					zoneArea++;
 
-					//M.print("After x+1,y+1");
-
 					history.push_back({ x,y });
 					x = x + 1;
 					y = y + 1;
 					continue;
 				}
-				if (D.safe(y + 1, x) && D.get_at(y + 1, x) == pi)
+				if (D.safe(y + 1, x) && D.yx(y + 1, x) != VISITED && D.yx(y + 1, x) == pi)
 				{
-					D.set_at(y + 1, x, VISITED);
+					D.set_at (y + 1, x, VISITED);
 					zoneArea++;
 
-					//M.print("After x,y+1");
-
 					history.push_back({ x,y });
 					y = y + 1;
 					continue;
 				}
-				if (D.safe(y + 1, x - 1) && D.get_at(y + 1, x - 1) == pi)
+				if (D.safe(y + 1, x - 1) && D.yx(y + 1, x - 1) != VISITED && D.yx(y + 1, x - 1) == pi)
 				{
-					D.set_at(y + 1, x - 1, VISITED);
+					D.set_at (y + 1, x - 1, VISITED);
 					zoneArea++;
 
-					//M.print("After x-1,y+1");
-
 					history.push_back({ x,y });
 					x = x - 1;
 					y = y + 1;
@@ -125,7 +131,10 @@ void GLSZMFeature::osized_calculate (LR& r, ImageLoader& imloader)
 				{
 					// Recollect the coordinate where we diverted from
 					std::tuple<int, int> prev = history[history.size() - 1];
+					x = std::get<0>(prev);
+					y = std::get<1>(prev);
 					history.pop_back();
+					continue;
 				}
 
 				// We are done exploring this cluster
@@ -139,24 +148,26 @@ void GLSZMFeature::osized_calculate (LR& r, ImageLoader& imloader)
 			// --2
 			maxZoneArea = std::max(maxZoneArea, zoneArea);
 
-			//std::stringstream ss;
-			//ss << "End of cluster " << x << "," << y;
-			//M.print (ss.str());
-
 			// --3
 			ACluster clu = { pi, zoneArea };
 			Z.push_back(clu);
 		}
 
-	//M.print("finished");
-
+	// count non-zero pixels
+	int count = 0;
+	for (auto i=0; i<M.size(); i++)
+	{
+		auto px = M[i];
+		if (px != 0)
+			++count;
+	}
 
 	//==== Fill the SZ-matrix
 
-	Ng = (decltype(Ng))U.size();
+	Ng = (int)U.size();
 	Ns = maxZoneArea;
-	Nz = (decltype(Nz))Z.size();
-	Np = 1;
+	Nz = (int)Z.size();
+	Np = count;
 
 	// --Set to vector to be able to know each intensity's index
 	std::vector<PixIntens> I(U.begin(), U.end());
@@ -166,20 +177,31 @@ void GLSZMFeature::osized_calculate (LR& r, ImageLoader& imloader)
 	P.allocate(Ns, Ng);
 
 	// --iterate zones and fill the matrix
+	int i = 0;
 	for (auto& z : Z)
 	{
 		// row
 		auto iter = std::find(I.begin(), I.end(), z.first);
-		int row = int(iter - I.begin());
+		int row = (Environment::ibsi_compliance) ? z.first - 1 : int(iter - I.begin());
 		// col
 		int col = z.second - 1;	// 0-based => -1
 		auto& k = P.xy(col, row);
 		k++;
 	}
+
+	sum_p = 0;
+	for (int i = 1; i <= Ng; ++i) {
+		for (int j = 1; j <= Ns; ++j) {
+			sum_p += P.matlab(i, j);
+		}
+	}
+
 }
 
 void GLSZMFeature::calculate(LR& r)
 {
+	clear_buffers();
+
 	//==== Check if the ROI is degenerate (equal intensity)
 	if (r.aux_min == r.aux_max)
 		return;
@@ -201,11 +223,9 @@ void GLSZMFeature::calculate(LR& r)
 	PixIntens piRange = r.aux_max - r.aux_min;		// Prepare ROI's intensity range
 	unsigned int nGrays = theEnvironment.get_coarse_gray_depth();
 
-
 	for (size_t i = 0; i < D.size(); i++)
 		D[i] = Nyxus::to_grayscale (D[i], r.aux_min, piRange, nGrays, Environment::ibsi_compliance);
 
-
 	// Number of zones
 	const int VISITED = -1;
 	for (int row=0; row<M.height; row++)
@@ -221,7 +241,7 @@ void GLSZMFeature::calculate(LR& r)
 			int x = col, y = row;
 			int zoneArea = 1;
 			D.yx(y,x) = VISITED;
-			// 
+
 			for(;;)
 			{
 				if (D.safe(y,x+1) && D.yx(y,x+1) != VISITED && D.yx(y,x+1) == pi)
@@ -297,8 +317,10 @@ void GLSZMFeature::calculate(LR& r)
 	// count non-zero pixels
 	int count = 0;
 
-	for (const auto& px: M.ReadablePixels()) {
-		if(px !=0) ++count;
+	for (const auto& px: M.ReadablePixels()) 
+	{
+		if(px != 0) 
+			++count;
 	}
 
 	//==== Fill the SZ-matrix
@@ -306,9 +328,9 @@ void GLSZMFeature::calculate(LR& r)
 	auto height = M.height;
 	auto width = M.width;
 
-	Ng = *std::max_element(std::begin(r.aux_image_matrix.ReadablePixels()), std::end(r.aux_image_matrix.ReadablePixels()));
-	Ns = height*width;
-	Nz = (decltype(Nz)) Z.size();
+	Ng = Environment::ibsi_compliance ? *std::max_element(std::begin(r.aux_image_matrix.ReadablePixels()), std::end(r.aux_image_matrix.ReadablePixels())) : (int)U.size();
+	Ns = height * width;
+	Nz = (int) Z.size();
 	Np = count;	
 
 	// --Set to vector to be able to know each intensity's index
@@ -324,8 +346,7 @@ void GLSZMFeature::calculate(LR& r)
 	{
 		// row
 		auto iter = std::find(I.begin(), I.end(), z.first);
-		int row = (Environment::ibsi_compliance) ?
-			z.first-1 : int (iter - I.begin());
+		int row = (Environment::ibsi_compliance) ? z.first-1 : int (iter - I.begin());
 		// col
 		int col = z.second - 1;	// 0-based => -1
 		auto & k = P.xy(col, row);
diff --git a/src/nyx/features/glszm.h b/src/nyx/features/glszm.h
index e8c00c19..854ae0bf 100644
--- a/src/nyx/features/glszm.h
+++ b/src/nyx/features/glszm.h
@@ -103,6 +103,17 @@ class GLSZMFeature: public FeatureMethod
 	SimpleMatrix<int> P;
 	double sum_p = 0;
 
+	void clear_buffers()
+	{
+		bad_roi_data = false;	// used to prevent calculation of degenerate ROIs
+		Ng = 0;	// number of discreet intensity values in the image
+		Ns = 0; // number of discreet zone sizes in the image
+		Np = 0; // number of voxels in the image
+		Nz = 0; // number of zones in the ROI, 1<=Nz<=Np
+		P.clear();
+		sum_p = 0;	
+	}
+
 	const double EPS = 2.2e-16;
 	const double BAD_ROI_FVAL = 0.0;
 	const double LOG10_2 = 0.30102999566;	// precalculated log 2 base 10
diff --git a/src/nyx/features/hexagonality_polygonality.cpp b/src/nyx/features/hexagonality_polygonality.cpp
index d35aadff..54cdb436 100644
--- a/src/nyx/features/hexagonality_polygonality.cpp
+++ b/src/nyx/features/hexagonality_polygonality.cpp
@@ -6,7 +6,7 @@
 HexagonalityPolygonalityFeature::HexagonalityPolygonalityFeature() : FeatureMethod("HexagonalityPolygonalityFeature")
 {
     provide_features({ POLYGONALITY_AVE, HEXAGONALITY_AVE, HEXAGONALITY_STDDEV });
-    add_dependencies({ NUM_NEIGHBORS, PERIMETER, CONVEX_HULL_AREA, MIN_FERET_DIAMETER });
+    add_dependencies({ NUM_NEIGHBORS, PERIMETER, CONVEX_HULL_AREA, MAX_FERET_DIAMETER, MIN_FERET_DIAMETER });
 }
 
 void HexagonalityPolygonalityFeature::calculate (LR& r)
@@ -26,8 +26,7 @@ void HexagonalityPolygonalityFeature::calculate (LR& r)
     if (neighbors == 0)
         perimeter_neighbors = std::numeric_limits<double>::quiet_NaN();
     else
-        if (neighbors > 0)
-            perimeter_neighbors = perimeter / neighbors;
+        perimeter_neighbors = perimeter / neighbors;
 
     // Polygonality metrics calculated based on the number of sides of the polygon
     if (neighbors > 2)
@@ -70,6 +69,11 @@ void HexagonalityPolygonalityFeature::calculate (LR& r)
             for (int ic = ib + 1; ic < list_area.size(); ++ic)
             {
                 double area_ratio = 1.0 - abs(1.0 - list_area[ib] / list_area[ic]);
+                
+                // skip NANs
+                if (!std::isfinite(area_ratio))
+                    continue;
+
                 area_array.push_back(area_ratio);
                 sum += area_ratio;
             }
diff --git a/src/nyx/features/histogram.h b/src/nyx/features/histogram.h
index ba48dc0a..04d6aa88 100644
--- a/src/nyx/features/histogram.h
+++ b/src/nyx/features/histogram.h
@@ -10,6 +10,7 @@
 #include <tuple>
 #include "../helpers/helpers.h"
 #include "pixel.h"
+#include "image_matrix_nontriv.h"
 
 using HistoItem = unsigned int;
 
@@ -18,22 +19,22 @@ class TrivialHistogram
 public:
 	TrivialHistogram() {}
 
-	void initialize (HistoItem min_value, HistoItem max_value, const std::vector<Pixel2>& raw_data)
+	void initialize(HistoItem min_value, HistoItem max_value, const std::vector<Pixel2>& raw_data)
 	{
 		// Allocate 
 		// -- "binary"
 		population = raw_data.size();
 		n_bins = decltype(n_bins) ((1. + log2(population)) + 0.5);
-		bins.reserve(n_bins+1);
-		for (int i = 0; i < n_bins+1; i++)
+		bins.reserve(n_bins + 1);
+		for (int i = 0; i < n_bins + 1; i++)
 			bins.push_back(0);
 		// -- "percentile"
 		bins100.reserve(100);
-		for (int i = 0; i < 100+1; i++)
+		for (int i = 0; i < 100 + 1; i++)
 			bins100.push_back(0);
 		// -- "uint8"
 		bins256.reserve(256);
-		for (int i = 0; i < 256+1; i++)
+		for (int i = 0; i < 256 + 1; i++)
 			bins256.push_back(0);
 
 		// Cache min/max
@@ -47,9 +48,9 @@ class TrivialHistogram
 		{
 			HistoItem h = s.inten;
 
-			double realIdx = double(h-minVal) / binW;
+			double realIdx = double(h - minVal) / binW;
 			int idx = std::isnan(realIdx) ? 0 : int(realIdx);
-			(bins [idx]) ++;
+			(bins[idx])++;
 
 			U.push_back(h); // Initialize the set for mode and median calculation
 		}
@@ -57,7 +58,80 @@ class TrivialHistogram
 		// -- Fix the special last bin
 		bins[n_bins - 1] += bins[n_bins];
 		bins[n_bins] = 0;
-		
+
+		// Build the "percentile" histogram
+		binW100 = double(valRange) / 100.;
+		for (auto s : raw_data)
+		{
+			HistoItem h = s.inten;
+			double realIdx = double(h - minVal) / binW100;
+			int idx = std::isnan(realIdx) ? 0 : int(realIdx);
+			(bins100[idx])++;
+		}
+
+		// -- Fix the special last bin
+		bins100[100 - 1] += bins100[100];
+		bins100[100] = 0;
+
+		// Build the "uint8" histogram
+		binw256 = double(valRange) / 255.;
+		for (auto s : raw_data)
+		{
+			HistoItem h = Nyxus::to_grayscale(s.inten, minVal, valRange, 256);
+			bins256[h] = bins256[h] + 1;
+		}
+
+		// -- Fix the special last bin
+		bins256[256 - 1] += bins256[256];
+		bins256[256] = 0;
+
+		// Mean calculation
+		meanVal = 0;
+		for (auto s : raw_data)
+			meanVal += double(s.inten);
+		meanVal /= double(population);
+	}
+
+	void initialize(HistoItem min_value, HistoItem max_value, const OutOfRamPixelCloud& raw_data)
+	{
+		// Allocate 
+		// -- "binary"
+		population = raw_data.size();
+		n_bins = decltype(n_bins) ((1. + log2(population)) + 0.5);
+		bins.reserve(n_bins + 1);
+		for (int i = 0; i < n_bins + 1; i++)
+			bins.push_back(0);
+		// -- "percentile"
+		bins100.reserve(100);
+		for (int i = 0; i < 100 + 1; i++)
+			bins100.push_back(0);
+		// -- "uint8"
+		bins256.reserve(256);
+		for (int i = 0; i < 256 + 1; i++)
+			bins256.push_back(0);
+
+		// Cache min/max
+		minVal = min_value;
+		maxVal = max_value;
+		auto valRange = maxVal - minVal;
+
+		// Build the "binary" histogram
+		binW = double(valRange) / double(n_bins);
+		for (auto s : raw_data)
+		{
+			HistoItem h = s.inten;
+
+			double realIdx = double(h - minVal) / binW;
+			int idx = std::isnan(realIdx) ? 0 : int(realIdx);
+			(bins[idx])++;
+
+			U.push_back(h); // Initialize the set for mode and median calculation
+		}
+
+		// -- Fix the special last bin
+		bins[n_bins - 1] += bins[n_bins];
+		bins[n_bins] = 0;
+
 		// Build the "percentile" histogram
 		binW100 = double(valRange) / 100.;
 		for (auto s : raw_data)
@@ -76,7 +150,7 @@ class TrivialHistogram
 		binw256 = double(valRange) / 255.;
 		for (auto s : raw_data)
 		{
-			HistoItem h = Nyxus::to_grayscale (s.inten, minVal, valRange, 256);
+			HistoItem h = Nyxus::to_grayscale(s.inten, minVal, valRange, 256);
 			bins256[h] = bins256[h] + 1;
 		}
 
@@ -85,16 +159,16 @@ class TrivialHistogram
 		bins256[256] = 0;
 
 		// Mean calculation
-		meanVal = 0; 
+		meanVal = 0;
 		for (auto s : raw_data)
-			meanVal += double(s.inten); 
-		meanVal /= double(population); 
+			meanVal += double(s.inten);
+		meanVal /= double(population);
 	}
 
-	void initialize_uniques (const std::vector<HistoItem> & raw_data)
+	void initialize_uniques(const std::vector<HistoItem>& raw_data)
 	{
 		for (auto h : raw_data)
-			U.push_back(h); 
+			U.push_back(h);
 	}
 
 	// Returns
@@ -109,13 +183,13 @@ class TrivialHistogram
 	{
 		// Empty histogram?
 		if (U.size() == 0)
-			return {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+			return { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 
 		// Median
-		double median = get_median (U); 
+		double median = get_median(U);
 
 		// Mode
-		HistoItem mode = get_mode (U);
+		HistoItem mode = get_mode(U);
 
 		// Percentiles
 		double p1 = 0, p10 = 0, p25 = 0, p75 = 0, p90 = 0, p99 = 0;
@@ -147,7 +221,7 @@ class TrivialHistogram
 
 		// Interquartile range
 		double iqr = p75 - p25;
-		
+
 		// RMAD 10-90 %
 		double rmad = 0, entropy = 0, uniformity = 0;
 		double range = maxVal - minVal;
@@ -180,7 +254,7 @@ class TrivialHistogram
 				double binC = (minVal + binW * i + minVal + binW * i + binW) / 2.f;	// Bin center
 				if (binC >= lowBound && binC <= uprBound)
 				{
-					double absDelta = std::abs (binC - mean1090);
+					double absDelta = std::abs(binC - mean1090);
 					sum1090 += absDelta;
 				}
 			}
@@ -190,14 +264,14 @@ class TrivialHistogram
 
 		// entropy
 		entropy = 0.0;
-		for (int i=0; i<n_bins; i++)
+		for (int i = 0; i < n_bins; i++)
 		{
 			auto cnt = bins[i];
 
 			// skip empty bins (zero probabilities)
 			if (cnt == 0)
 				continue;
-			
+
 			// calculate the probability by normalizing the bin entry so that sum(normalized bin entries)==1
 			double p = double(cnt) / double(population);
 
@@ -206,7 +280,7 @@ class TrivialHistogram
 				continue;
 
 			// entropy
-			entropy += p * log2(p);  
+			entropy += p * log2(p);
 		}
 
 		// uniformity
@@ -244,104 +318,103 @@ class TrivialHistogram
 		return median;
 	}
 
-	private:
-		size_t population = 0;
-		HistoItem minVal, maxVal;
-		double medianVal, meanVal;
-		double binW, binW100, binw256;
-		std::vector<HistoItem> bins, bins100, bins256; 
-		int n_bins = 0;
-		std::vector<HistoItem> U;	
+private:
+	size_t population = 0;
+	HistoItem minVal, maxVal;
+	double medianVal, meanVal;
+	double binW, binW100, binw256;
+	std::vector<HistoItem> bins, bins100, bins256;
+	int n_bins = 0;
+	std::vector<HistoItem> U;
 
-		HistoItem get_median(const std::unordered_set<HistoItem>& uniqueValues)
-		{
-			// Sort unique intensities
-			std::vector<HistoItem> A{ uniqueValues.begin(), uniqueValues.end() };
-			std::sort(A.begin(), A.end());
+	HistoItem get_median(const std::unordered_set<HistoItem>& uniqueValues)
+	{
+		// Sort unique intensities
+		std::vector<HistoItem> A{ uniqueValues.begin(), uniqueValues.end() };
+		std::sort(A.begin(), A.end());
 
-			// Pick the median
-			auto n = A.size();
-			if (n % 2 != 0)
-			{
-				int median = A[n / 2];
-				return median;
-			}
-			else
-			{
-				HistoItem right = A[n / 2],
-					left = A[n / 2 - 1],	// Middle left and right values
-					ave = (right + left) / 2;
-				return ave;
-			}
+		// Pick the median
+		auto n = A.size();
+		if (n % 2 != 0)
+		{
+			int median = A[n / 2];
+			return median;
 		}
-
-		// 'raw_I' is passed as non-const and gets sorted
-		double get_median (std::vector<HistoItem> & raw_I)
+		else
 		{
-			// Sort unique intensities
-			std::sort (raw_I.begin(), raw_I.end());
-
-			// Pick the median
-			auto n = raw_I.size();
-			if (n % 2 != 0)
-			{
-				HistoItem median = raw_I[n / 2];
-				return (double) median;
-			}
-			else
-			{
-				HistoItem right = raw_I[n / 2],
-					left = raw_I[n / 2 - 1];	// Middle left and right values
-				double ave = double(right + left) / 2.0;
-				return ave;
-			}
+			HistoItem right = A[n / 2],
+				left = A[n / 2 - 1],	// Middle left and right values
+				ave = (right + left) / 2;
+			return ave;
 		}
+	}
 
-		double get_max_bin_item ()
-		{
-			// Find the heaviest bin
-			int maxIdx = 0;
-			auto maxCnt = bins[0];
-			for (int i = 1; i < n_bins; i++)
-				if (maxCnt < bins[i])
-				{
-					maxCnt = bins[i];
-					maxIdx = i;
-				}
+	// 'raw_I' is passed as non-const and gets sorted
+	double get_median(std::vector<HistoItem>& raw_I)
+	{
+		// Sort unique intensities
+		std::sort(raw_I.begin(), raw_I.end());
 
-			// Find bin enges and their average
-			double edgeL = minVal + maxIdx * binW,
-				edgeR = edgeL + binW;
-			double biggest = HistoItem((edgeL + edgeR) / 2.0);
-			return biggest;
+		// Pick the median
+		auto n = raw_I.size();
+		if (n % 2 != 0)
+		{
+			HistoItem median = raw_I[n / 2];
+			return (double)median;
 		}
-
-		HistoItem get_mode(std::vector<HistoItem>& raw_I)
+		else
 		{
-			// Populate the frequency map
-			std::map<HistoItem, std::size_t> freqMap;
-			for (int v : raw_I)
-				++freqMap[v];
-			
-			// Iterator to the highest frequency item
-			auto highestFreqIter = freqMap.begin(); 
-
-			// Iterate the map updating 'highestFreqIter'
-			for (auto iter = freqMap.begin(); iter != freqMap.end(); ++iter)
+			HistoItem right = raw_I[n / 2],
+				left = raw_I[n / 2 - 1];	// Middle left and right values
+			double ave = double(right + left) / 2.0;
+			return ave;
+		}
+	}
+
+	double get_max_bin_item()
+	{
+		// Find the heaviest bin
+		int maxIdx = 0;
+		auto maxCnt = bins[0];
+		for (int i = 1; i < n_bins; i++)
+			if (maxCnt < bins[i])
 			{
-				if (highestFreqIter->second < iter->second)
-					highestFreqIter = iter;
+				maxCnt = bins[i];
+				maxIdx = i;
 			}
-			
-			// Return the result
-			auto mo = highestFreqIter->first;
-			return mo;
-		}
 
-		double bin_center (size_t bin_idx, double bin_width)
+		// Find bin enges and their average
+		double edgeL = minVal + maxIdx * binW,
+			edgeR = edgeL + binW;
+		double biggest = HistoItem((edgeL + edgeR) / 2.0);
+		return biggest;
+	}
+
+	HistoItem get_mode(std::vector<HistoItem>& raw_I)
+	{
+		// Populate the frequency map
+		std::map<HistoItem, std::size_t> freqMap;
+		for (int v : raw_I)
+			++freqMap[v];
+
+		// Iterator to the highest frequency item
+		auto highestFreqIter = freqMap.begin();
+
+		// Iterate the map updating 'highestFreqIter'
+		for (auto iter = freqMap.begin(); iter != freqMap.end(); ++iter)
 		{
-			return double(bin_idx) * bin_width * 1.5;
+			if (highestFreqIter->second < iter->second)
+				highestFreqIter = iter;
 		}
-};
 
+		// Return the result
+		auto mo = highestFreqIter->first;
+		return mo;
+	}
+
+	double bin_center(size_t bin_idx, double bin_width)
+	{
+		return double(bin_idx) * bin_width * 1.5;
+	}
+};
 
diff --git a/src/nyx/features/image_matrix.cpp b/src/nyx/features/image_matrix.cpp
index 3972077d..2654b1c2 100644
--- a/src/nyx/features/image_matrix.cpp
+++ b/src/nyx/features/image_matrix.cpp
@@ -4,41 +4,7 @@
 #include "image_matrix.h"
 #include "moments.h"
 
-template<>
-void SimpleMatrix<int>::print(const std::string& head, const std::string& tail)
-{
-	const int Wd = 6;	// data
-	const int Wi = 5;		// index
 
-	std::cout << head << "\n";
-	std::cout << std::string(Wi + Wd * this->width(), '-') << std::endl;		// Upper solid line
-	std::cout << "w=" << this->width() << " h=" << this->height() << "\n";
-
-	for (int row = 0; row < this->height(); row++)
-	{
-		// Hdr
-		if (row == 0)
-		{
-			std::cout << std::setw(Wi + 2) << "";	// Wi+2 because '[' + Wi + ']'
-			for (int col = 0; col < this->width(); col++)
-			{
-				std::cout << std::setw(Wd) << col;
-			}
-			std::cout << "\n";
-		}
-
-		// Row
-		std::cout << "[" << std::setw(Wi) << row << "]";
-		for (int col = 0; col < this->width(); col++)
-		{
-			std::cout << std::setw(Wd) << (int) this->xy(col, row);
-		}
-		std::cout << "\n";
-	}
-
-	std::cout << std::string(Wi + Wd * this->width(), '-') << std::endl;	// Lower solid line
-	std::cout << tail;
-}
 
 void ImageMatrix::print (const std::string& head, const std::string& tail, std::vector<PrintablePoint> special_points)
 {
@@ -162,64 +128,6 @@ void ImageMatrix::print (std::ofstream& f, const std::string& head, const std::s
 	f << tail;
 }
 
-// Binarization by Otsu's method based on maximization of inter-class variance 
-double ImageMatrix::Otsu(bool dynamic_range) const {
-	#define OTSU_LEVELS 256	
-	double hist[OTSU_LEVELS];
-	double omega[OTSU_LEVELS];
-	double myu[OTSU_LEVELS];
-	double max_sigma, sigma[OTSU_LEVELS]; // inter-class variance
-	int i;
-	int threshold;
-	double min_val, max_val; // pixel range
-
-	if (!dynamic_range) 
-	{
-		histogram(hist, OTSU_LEVELS, true);
-		min_val = 0.0;
-		int bits = sizeof(PixIntens) * 8;
-		max_val = pow(2.0, bits) - 1;
-	}
-	else 
-	{
-		// to keep this const method from modifying the object, we use GetStats on a local Moments2 object
-		Moments2 local_stats;
-		GetStats(local_stats);
-		min_val = local_stats.min__();
-		max_val = local_stats.max__();
-		histogram(hist, OTSU_LEVELS, false);
-	}
-
-	// omega & myu generation
-	omega[0] = hist[0] / stats.n();
-
-	myu[0] = 0.0;
-	for (i = 1; i < OTSU_LEVELS; i++) 
-	{
-		omega[i] = omega[i - 1] + (hist[i] / stats.n());
-		myu[i] = myu[i - 1] + i * (hist[i] / stats.n());
-	}
-
-	// maximization of inter-class variance
-	threshold = 0;
-	max_sigma = 0.0;
-	for (i = 0; i < OTSU_LEVELS - 1; i++) 
-	{
-		if (omega[i] != 0.0 && omega[i] != 1.0)
-			sigma[i] = pow(myu[OTSU_LEVELS - 1] * omega[i] - myu[i], 2) / (omega[i] * (1.0 - omega[i]));
-		else
-			sigma[i] = 0.0;
-		if (sigma[i] > max_sigma) 
-		{
-			max_sigma = sigma[i];
-			threshold = i;
-		}
-	}
-
-	// threshold is a histogram index - needs to be scaled to a pixel value.
-	return ((((double)threshold / (double)(OTSU_LEVELS - 1)) * (max_val - min_val)) + min_val);
-}
-
 // get image histogram 
 void ImageMatrix::histogram(double* bins, unsigned short nbins, bool imhist, const Moments2& in_stats) const 
 {
@@ -283,7 +191,7 @@ void ImageMatrix::apply_distance_to_contour_weights (const std::vector<Pixel2>&
 			r = p.y - original_aabb.get_ymin();
 		
 		// Weighted intensity
-		PixIntens wi = _pix_plane.yx(r, c) / (dist + epsilon) + 0.5/*rounding*/;
+		PixIntens wi = PixIntens((double)_pix_plane.yx(r, c) / (dist + epsilon));
 		
 		_pix_plane.yx(r,c) = wi;
 	}
@@ -335,3 +243,26 @@ bool ImageMatrix::tile_contains_signal (int tile_row, int tile_col, int tile_sid
 				return true;
 	return false;
 }
+
+/// @brief Applies to distance-to-contour weighting to intensities of pixel cloud 
+void apply_dist2contour_weighting(
+	// input & output
+	std::vector<Pixel2>& cloud,
+	// input
+	const std::vector<Pixel2>& contour, 
+	const double epsilon)
+{
+	for (auto& p : cloud)
+	{
+		// pixel distance
+		auto mind2 = p.min_sqdist (contour);
+		double dist = std::sqrt(mind2);
+
+		// adjusted intensity
+		PixIntens wi = PixIntens((double)p.inten / (dist + epsilon));
+
+		// save
+		p.inten = wi;
+	}
+}
+
diff --git a/src/nyx/features/image_matrix.h b/src/nyx/features/image_matrix.h
index 3e2a9906..3370d32e 100644
--- a/src/nyx/features/image_matrix.h
+++ b/src/nyx/features/image_matrix.h
@@ -36,11 +36,11 @@ class SimpleMatrix : public std::vector<T>
 
 	SimpleMatrix() {}
 
-	void allocate(int _w, int _h, T inival=0)
+	void allocate(int _w, int _h)
 	{
 		W = _w;
 		H = _h;
-		this->resize (W*H, inival);
+		this->resize (W*H);
 	}
 
 	// = W * y + x
@@ -99,16 +99,12 @@ class SimpleMatrix : public std::vector<T>
 
 	void fill (T val)
 	{
-		auto n = W * H;
-		for (int i = 0; i < n; i++)
-			this->at(i) = val;
+		std::fill(this->begin(), this->end(), val);
 	}
 
 	int width() const { return W; }
 	int height() const { return H; }
 
-	void print (const std::string& head, const std::string& tail);
-
 private:
 	int W = 0, H = 0;
 };
@@ -322,11 +318,6 @@ class ImageMatrix
 	// by default, based on computed min and max
 	void histogram(double* bins, unsigned short nbins, bool imhist = false, const Moments2& in_stats = Moments2()) const; 
 
-	// Otsu grey threshold
-	double Otsu (bool dynamic_range = true) const;
-
-	void erode();
-
 	// Based on X.Shu, Q.Zhang, J.Shi and Y.Qi - "A Comparative Study on Weighted Central Moment and Its Application in 2D Shape Retrieval" (2016) https://pdfs.semanticscholar.org/8927/2bef7ba9496c59081ae102925ebc0134bceb.pdf
 	void apply_distance_to_contour_weights(const std::vector<Pixel2>& raw_pixels, const std::vector<Pixel2>& contour_pixels);
 
@@ -355,24 +346,40 @@ class ImageMatrix
 class Power2PaddedImageMatrix : public ImageMatrix
 {
 public:
-	Power2PaddedImageMatrix(const std::vector <Pixel2>& labels_raw_pixels, const AABB& aabb):
+	/// @brief Use base_level=0 and attenuation >0 and <1 e.g. 0.5 to build an imag of a specific intensity distribution. Or base_level=1 and attenuation 1 to build an image of the mask
+	/// @param labels_raw_pixels ROI pixel cloud
+	/// @param aabb ROI axis aligned bounding box
+	/// @param base_level Set {0,1}
+	/// @param attenuation Value in the interval (0,1]
+	Power2PaddedImageMatrix(const std::vector <Pixel2>& labels_raw_pixels, const AABB& aabb, PixIntens base_level, double attenuation):
 		ImageMatrix ()
 	{
+		// Cache AABB
 		original_aabb = aabb;
 
+		// Figure out the padded size and allocate
 		int bigSide = std::max(aabb.get_width(), aabb.get_height());
 		StatsInt paddedSide = Nyxus::closest_pow2 (bigSide);
 		allocate (paddedSide, paddedSide);
 
+		// Copy pixels
 		int padOffsetX = (paddedSide - original_aabb.get_width()) / 2;
 		int padOffsetY = (paddedSide - original_aabb.get_height()) / 2;
 
-		// Read pixels
 		for (auto& pxl : labels_raw_pixels)
 		{
 			auto x = pxl.x - original_aabb.get_xmin() + padOffsetX,
 				y = pxl.y - original_aabb.get_ymin() + padOffsetY;
-			_pix_plane[y * width + x] = pxl.inten;
+			_pix_plane[y * width + x] = PixIntens(double(pxl.inten) * attenuation + base_level);
 		}
 	}
 };
+
+/// @brief Applies to distance-to-contour weighting to intensities of pixel cloud 
+void apply_dist2contour_weighting(
+	// input & output
+	std::vector<Pixel2>& cloud,
+	// input
+	const std::vector<Pixel2>& contour,
+	const double epsilon);
+
diff --git a/src/nyx/features/image_matrix_nontriv.cpp b/src/nyx/features/image_matrix_nontriv.cpp
index 5f53811b..7ef0e935 100644
--- a/src/nyx/features/image_matrix_nontriv.cpp
+++ b/src/nyx/features/image_matrix_nontriv.cpp
@@ -13,10 +13,12 @@
 #include <sstream>
 #include <thread>
 #include "../environment.h"
+#include "../helpers/helpers.h"
 #include "image_matrix_nontriv.h"
 
 OutOfRamPixelCloud::OutOfRamPixelCloud() {}
 
+
 OutOfRamPixelCloud::~OutOfRamPixelCloud()
 {
 	if (pF)
@@ -90,12 +92,13 @@ Pixel2 OutOfRamPixelCloud::get_at(size_t idx) const
 	return px;
 }
 
-WriteImageMatrix_nontriv::WriteImageMatrix_nontriv (const std::string& _name, unsigned int _roi_label)
+WriteImageMatrix_nontriv::WriteImageMatrix_nontriv (const std::string& _name, unsigned int _roi_label):
+	name(_name)
 {
 	auto tid = std::this_thread::get_id();
 
 	std::stringstream ssPath;
-	ssPath << Nyxus::theEnvironment.get_temp_dir_path() << _name << "_roi" << _roi_label << "_tid" << tid << ".mat.nyxus";
+	ssPath << Nyxus::theEnvironment.get_temp_dir_path() << name << "_roi" << _roi_label << "_tid" << tid << ".mat.nyxus";
 	filepath = ssPath.str();
 
 	errno = 0;
@@ -130,10 +133,14 @@ void WriteImageMatrix_nontriv::allocate (int w, int h, double ini_value)
 	fflush(pF);
 }
 
-void WriteImageMatrix_nontriv::init_with_cloud (const OutOfRamPixelCloud & cloud, const AABB & aabb)
+void WriteImageMatrix_nontriv::allocate_from_cloud (const OutOfRamPixelCloud & cloud, const AABB & aabb, bool mask_image)
 {
 	// Allocate space
 	allocate(aabb.get_width(), aabb.get_height(), 0);
+
+	// '+1' does the job: wherever intensity pixels are defined in 'cloud', 
+	// in the image we will have at least 1 even if the pixel intensity is 0
+	int maskMagic = mask_image ? 1 : 0;
 	
 	// Fill it with cloud pixels 
 	for (size_t i = 0; i < cloud.size(); i++)
@@ -141,20 +148,15 @@ void WriteImageMatrix_nontriv::init_with_cloud (const OutOfRamPixelCloud & cloud
 		const Pixel2 p = cloud.get_at(i);
 		auto y = p.y - aabb.get_ymin(),
 			x = p.x - aabb.get_xmin();
-		set_at (y, x, p.inten);
+		set_at (y, x, p.inten + maskMagic);
 	}
 
 	// Flush the buffer
 	fflush(pF);
 }
 
-void WriteImageMatrix_nontriv::init_with_cloud_distance_to_contour_weights (const OutOfRamPixelCloud& cloud, const AABB& aabb, std::vector<Pixel2>& contour_pixels)
+void WriteImageMatrix_nontriv::allocate_from_cloud_coarser_grayscale (const OutOfRamPixelCloud& cloud, const AABB& aabb, PixIntens min_inten, PixIntens inten_range, unsigned int n_grays)
 {
-	double epsilon = 0.1;
-
-	// Cache some parameters
-	original_aabb = aabb;
-
 	// Allocate space
 	allocate(aabb.get_width(), aabb.get_height(), 0);
 
@@ -162,16 +164,10 @@ void WriteImageMatrix_nontriv::init_with_cloud_distance_to_contour_weights (cons
 	for (size_t i = 0; i < cloud.size(); i++)
 	{
 		const Pixel2 p = cloud.get_at(i);
-
-		auto [mind, maxd] = p.min_max_sqdist (contour_pixels);
-		double dist = std::sqrt (mind);
-
 		auto y = p.y - aabb.get_ymin(),
 			x = p.x - aabb.get_xmin();
-
-		// Weighted intensity		
-		PixIntens wi = p.inten / (dist + epsilon) + 0.5/*rounding*/;
-		set_at (y, x, p.inten);
+		PixIntens newI = Nyxus::to_grayscale (p.inten, min_inten, inten_range, n_grays);
+		set_at (y, x, newI);
 	}
 
 	// Flush the buffer
@@ -180,40 +176,23 @@ void WriteImageMatrix_nontriv::init_with_cloud_distance_to_contour_weights (cons
 
 void WriteImageMatrix_nontriv::copy (WriteImageMatrix_nontriv& other)
 {
-	fs::path p (filepath);
-	fs::remove (p);
+	this->check_non_empty();
+	other.check_non_empty();
 
-	original_aabb = other.original_aabb;
-	allocate (original_aabb.get_width(), original_aabb.get_height(), 0.0);
-
-	for (size_t idx = 0; idx < other.size(); idx++)
+	if (this->height != other.height || this->width != other.width)
 	{
-		double val = other.get_at(idx);
-		set_at(idx, val);
+		std::string msg = "Error: size mismatch while copying " + other.info() + " to " + this->info();
+		throw (std::runtime_error(msg));	
 	}
 
-	fflush(pF);
-}
-
-/*
-void WriteImageMatrix_nontriv::init_with_matrix (ImageLoader& imloader, ReadImageMatrix_nontriv& rim)
-{
-	// Allocate space
-	allocate (rim.get_width(), rim.get_height());
-	
-	// Fill it with cloud pixels 
-	for (size_t i = 0; i < rim.get_size(); i++)
+	for (size_t i = 0; i < this->size(); i++)
 	{
-		auto p = rim.get_at (imloader, i);
-		auto y = p.y - rim.aabb.get_ymin(),
-			x = p.x - aabb.get_xmin();
-		set_at (y, x, p.inten);
+		auto val = other[i];
+		this->set_at(i, val);
 	}
 
-	// Flush the buffer
-	fflush(pF);	
+	fflush(pF);
 }
-*/
 
 void WriteImageMatrix_nontriv::set_at(size_t idx, double val)
 {
@@ -238,7 +217,7 @@ double WriteImageMatrix_nontriv::get_at(size_t idx)
 	return val;
 }
 
-double WriteImageMatrix_nontriv::get_at (int row, int col)
+double WriteImageMatrix_nontriv::yx (size_t row, size_t col)
 {
 	size_t idx = row * width + col;
 	double val = get_at (idx);
@@ -248,16 +227,16 @@ double WriteImageMatrix_nontriv::get_at (int row, int col)
 double WriteImageMatrix_nontriv::get_max()
 {
 	bool blank = true;
-	double retval;
+	double retval = NAN;
 
-	auto n = width * height;
+	auto n = size();
 	double buf = 0.0;
 	for (size_t i = 0; i < n; i++)
 	{
-		fread ((void*)&buf, sizeof(buf), 1, pF);
+		buf = get_at(i);
 		if (blank)
 		{
-			blank = true;
+			blank = false;
 			retval = buf;
 		}
 		else
@@ -291,7 +270,7 @@ size_t WriteImageMatrix_nontriv::get_chlen (size_t col)
 	{
 		if (noSignal)
 		{
-			if (get_at(row, col) != 0)
+			if (yx(row, col) != 0)
 			{
 				// begin tracking a new chord
 				noSignal = false;
@@ -300,7 +279,7 @@ size_t WriteImageMatrix_nontriv::get_chlen (size_t col)
 		}
 		else // in progress tracking a signal
 		{
-			if (get_at(row, col) != 0)
+			if (yx(row, col) != 0)
 				chlen++;	// signal continues
 			else
 			{
@@ -315,7 +294,7 @@ size_t WriteImageMatrix_nontriv::get_chlen (size_t col)
 	return maxChlen;
 }
 
-bool WriteImageMatrix_nontriv::safe(size_t x, size_t y) const
+bool WriteImageMatrix_nontriv::safe(size_t y, size_t x) const
 {
 	if (x >= width || y >= height)
 		return false;
@@ -323,6 +302,21 @@ bool WriteImageMatrix_nontriv::safe(size_t x, size_t y) const
 		return true;
 }
 
+void WriteImageMatrix_nontriv::check_non_empty()
+{
+	if (height == 0 || width == 0)
+	{
+		std::string msg = "Error: attempt to perform action on uninitialized " + this->name;
+		throw (std::runtime_error(msg));
+	}
+}
+
+std::string WriteImageMatrix_nontriv::info()
+{
+	std::string retval = this->name + " (width=" + std::to_string(width) + " height=" + std::to_string(height) + ")";
+	return retval;
+}
+
 double OOR_ReadMatrix::get_at (size_t pixel_row, size_t pixel_col) const
 {
 	size_t tile_x = imloader.get_tile_x(pixel_col),
@@ -428,5 +422,44 @@ bool ReadImageMatrix_nontriv::safe(size_t x, size_t y) const
 		return true;
 }
 
+/// @brief Use base_level=0 and attenuation >0 and <1 e.g. 0.5 to build an imag of a specific intensity distribution. Or base_level=1 and attenuation 1 to build an image of the mask
+/// @param labels_raw_pixels ROI pixel cloud
+/// @param aabb ROI axis aligned bounding box
+/// @param base_level Set {0,1}
+/// @param attenuation Value in the interval (0,1]
+Power2PaddedImageMatrix_NT::Power2PaddedImageMatrix_NT (const std::string& _name, unsigned int _roi_label, const OutOfRamPixelCloud& raw_pixels, const AABB& aabb, PixIntens base_level, double attenuation) :
+	WriteImageMatrix_nontriv(_name, _roi_label)
+{
+	// Cache AABB
+	original_aabb = aabb;
+
+	// Figure out the padded size and allocate
+	int bigSide = std::max(aabb.get_width(), aabb.get_height());
+	StatsInt paddedSide = Nyxus::closest_pow2(bigSide);
+	allocate(paddedSide, paddedSide, 0.0);
+
+	// Copy pixels
+	int padOffsetX = (paddedSide - original_aabb.get_width()) / 2;
+	int padOffsetY = (paddedSide - original_aabb.get_height()) / 2;
 
+	for (auto pxl : raw_pixels)
+	{
+		auto x = pxl.x - original_aabb.get_xmin() + padOffsetX,
+			y = pxl.y - original_aabb.get_ymin() + padOffsetY;
+		set_at(y * width + x, pxl.inten * attenuation + base_level);
+	}
+}
+
+bool Power2PaddedImageMatrix_NT::tile_contains_signal (int tile_row, int tile_col, int tile_side)
+{
+	int r1 = tile_row * tile_side,
+		r2 = r1 + tile_side,
+		c1 = tile_col * tile_side,
+		c2 = c1 + tile_side;
+	for (int r = r1; r < r2; r++)
+		for (int c = c1; c < c2; c++)
+			if (yx(r, c) != 0)
+				return true;
+	return false;
+}
 
diff --git a/src/nyx/features/image_matrix_nontriv.h b/src/nyx/features/image_matrix_nontriv.h
index 831dd0b5..9dd1c8fb 100644
--- a/src/nyx/features/image_matrix_nontriv.h
+++ b/src/nyx/features/image_matrix_nontriv.h
@@ -10,6 +10,7 @@ class OutOfRamPixelCloud
 {
 public:
 	OutOfRamPixelCloud();
+	OutOfRamPixelCloud(const OutOfRamPixelCloud&) = delete;	// Instead, use init() and copy()
 	~OutOfRamPixelCloud();
 	void init (unsigned int _roi_label, std::string name);
 	void clear();
@@ -149,29 +150,44 @@ class WriteImageMatrix_nontriv
 	
 	// Initialization
 	void allocate (int w, int h, double ini_value);
-	void init_with_cloud (const OutOfRamPixelCloud& cloud, const AABB& aabb);
-	void init_with_cloud_distance_to_contour_weights (const OutOfRamPixelCloud& cloud, const AABB& aabb, std::vector<Pixel2>& contour);
-	void copy(WriteImageMatrix_nontriv & other);
-
+	void allocate_from_cloud (const OutOfRamPixelCloud& cloud, const AABB& aabb, bool mask_image);
+	void allocate_from_cloud_coarser_grayscale (const OutOfRamPixelCloud& cloud, const AABB& aabb, PixIntens min_inten, PixIntens inten_range, unsigned int n_grays);
+	void copy (WriteImageMatrix_nontriv & other);
 	void set_at(int row, int col, double val);
 	void set_at(size_t idx,  double val);
-	double get_at(int row, int col);
-	double get_at(size_t idx);
+	double yx (size_t row, size_t col);
+	double get_at (size_t idx);
 	double get_max();
 	size_t size();
 	size_t get_width();
 	size_t get_height();
 	size_t get_chlen(size_t x);
-	bool safe(size_t x, size_t y) const;
-
+	bool safe(size_t y, size_t x) const;
 	PixIntens operator[] (size_t idx) { return (PixIntens) get_at(idx); }
+	void check_non_empty();
+	std::string info();
 
-private:
+protected:
+	std::string name;
 	std::string filepath;
 	FILE* pF = nullptr;
-	int width, height;
+	int width = 0, height = 0;
 	size_t item_size = sizeof(double);
 	AABB original_aabb;
 };
 
+/// @brief Padded image matrix
+class Power2PaddedImageMatrix_NT : public WriteImageMatrix_nontriv
+{
+public:
+	/// @brief Use base_level=0 and attenuation >0 and <1 e.g. 0.5 to build an imag of a specific intensity distribution. Or base_level=1 and attenuation 1 to build an image of the mask
+	/// @param labels_raw_pixels ROI pixel cloud
+	/// @param aabb ROI axis aligned bounding box
+	/// @param base_level Set {0,1}
+	/// @param attenuation Value in the interval (0,1]
+	Power2PaddedImageMatrix_NT (const std::string& _name, unsigned int _roi_label, const OutOfRamPixelCloud& raw_pixels, const AABB& aabb, PixIntens base_level, double attenuation);
+
+	// Support of erosion features
+	bool tile_contains_signal (int tile_row, int tile_col, int tile_side);
+};
 
diff --git a/src/nyx/features/image_moments.cpp b/src/nyx/features/image_moments.cpp
index 28741f59..3043cb03 100644
--- a/src/nyx/features/image_moments.cpp
+++ b/src/nyx/features/image_moments.cpp
@@ -1,6 +1,8 @@
 #include "../environment.h"
 #include "image_moments.h"
 
+using pixelvector = std::vector<Pixel2>;
+
 ImageMomentsFeature::ImageMomentsFeature() : FeatureMethod("ImageMomentsFeature")
 {
     provide_features({
@@ -72,24 +74,28 @@ ImageMomentsFeature::ImageMomentsFeature() : FeatureMethod("ImageMomentsFeature"
 
 void ImageMomentsFeature::calculate (LR& r)
 {
-        const ImageMatrix& im = r.aux_image_matrix;
-
-        const pixData& I = im.ReadablePixels();
-        calcOrigins(I);
-        calcSpatialMoments(I);
-        calcCentralMoments(I);
-        calcNormCentralMoments(I);
-        calcNormSpatialMoments(I);
-        calcHuInvariants(I);
-
-        ImageMatrix weighted_im(r.raw_pixels, r.aabb);
-        weighted_im.apply_distance_to_contour_weights(r.raw_pixels, r.contour);
-
-        const pixData& W = weighted_im.ReadablePixels();
-        calcOrigins (W);
-        calcWeightedSpatialMoments (W);
-        calcWeightedCentralMoments(W);
-        calcWeightedHuInvariants(W);   
+    // Cache ROI frame of reference
+    baseX = r.aabb.get_xmin();
+    baseY = r.aabb.get_ymin();
+
+    // Calculate non-weighted moments
+    auto& c = r.raw_pixels;
+    calcOrigins (c);
+    calcRawMoments (c);
+    calcCentralMoments (c);
+    calcNormRawMoments (c);
+    calcNormCentralMoments (c);
+    calcHuInvariants (c);
+
+    // Prepare weighted pixel cloud
+    decltype(c) w = c;
+    apply_dist2contour_weighting (w, r.contour, weighting_epsilon);
+
+    // Calculate weighted moments
+    calcOrigins (w);
+    calcWeightedRawMoments (w);
+    calcWeightedCentralMoments (w);
+    calcWeightedHuInvariants (w);
 }
 
 #ifdef USE_GPU
@@ -209,163 +215,165 @@ void ImageMomentsFeature::save_value(std::vector<std::vector<double>>& fvals)
     fvals[WEIGHTED_HU_M7][0] = whm7;
 }
 
-/// @brief Calculates the spatial 2D-moment of order q,p
-double ImageMomentsFeature::Moment (const pixData& D, int p, int q)
+/// @brief Calculates the spatial 2D moment of order q,p f ROI pixel cloud
+double ImageMomentsFeature::moment (const pixcloud& cloud, int p, int q)
 {
-    double q_ = q, 
-        p_ = p, 
-        sum = 0;
-    for (size_t x = 0; x < D.width(); x++)
-    {
-        double powXP = pow((double)x, p_);
-        for (size_t y = 0; y < D.height(); y++)
-            sum += (double)D.yx(y, x) * powXP * pow((double)y, q_);
-    }
+    double q_ = q, p_ = p, sum = 0;
+    for (auto& pxl : cloud)
+        sum += double(pxl.inten) * pow(double(pxl.x-baseX), p_) * pow(double(pxl.y-baseY), q_);
     return sum;
 }
 
-void ImageMomentsFeature::calcOrigins(const pixData& D)
+void ImageMomentsFeature::calcOrigins (const std::vector<Pixel2>& cloud)
 {
-    // calc orgins
-    double m00 = Moment(D, 0, 0);
-    originOfX = Moment (D, 1, 0) / m00;
-    originOfY = Moment (D, 0, 1) / m00;
+    double m00 = moment (cloud, 0, 0);
+    originOfX = moment (cloud, 1, 0) / m00;
+    originOfY = moment (cloud, 0, 1) / m00;
 }
 
-/// @brief Calculates the central 2D-moment of order q,p
-double ImageMomentsFeature::CentralMom(const pixData& D, int p, int q)
+/// @brief Calculates the central 2D moment of order q,p of ROI pixel cloud
+double ImageMomentsFeature::centralMom (const std::vector<Pixel2>& cloud, int p, int q)
 {
-    // calculate central moment
     double sum = 0;
-    for (int x = 0; x < D.width(); x++)
-        for (int y = 0; y < D.height(); y++)
-            sum += D.yx(y,x) * pow((double(x) - originOfX), p) * pow((double(y) - originOfY), q);
-
+    for (auto& pxl : cloud)
+        sum += double(pxl.inten) * pow(double(pxl.x-baseX) - originOfX, p) * pow(double(pxl.y-baseY) - originOfY, q);
     return sum;
 }
 
-/// @brief Calculates the normalized spatial 2D-moment of order q,p [https://handwiki.org/wiki/Standardized_moment]
-double ImageMomentsFeature::NormSpatMom(const pixData& D, int p, int q)
+/// @brief Calculates the normalized spatial 2D moment of order q,p of ROI pixel cloud
+double ImageMomentsFeature::normRawMom (const std::vector <Pixel2>& cloud, int p, int q)
 {
-    double stddev = CentralMom(D, 2, 2);
+    double stddev = centralMom (cloud, 2, 2);
     int w = std::max(q, p);
     double normCoef = pow(stddev, (double)w);
-    double cmPQ = CentralMom(D, p, q);
+    double cmPQ = centralMom(cloud, p, q);
     double retval = cmPQ / normCoef;
     return retval;
 }
 
-/// @brief Calculates the normalized central 2D-moment of order q,p
-double ImageMomentsFeature::NormCentralMom(const pixData& D, int p, int q)
+/// @brief Calculates the normalized central 2D moment of order q,p of ROI pixel cloud
+double ImageMomentsFeature::normCentralMom (const std::vector<Pixel2>& cloud, int p, int q)
 {
     double temp = ((double(p) + double(q)) / 2.0) + 1.0;
-    double retval = CentralMom(D, p, q) / pow(Moment(D, 0, 0), temp);
+    double retval = centralMom(cloud, p, q) / pow(moment (cloud, 0, 0), temp);
     return retval;
 }
 
-std::tuple<double, double, double, double, double, double, double> ImageMomentsFeature::calcHuInvariants_imp (const pixData& D)
+std::tuple<double, double, double, double, double, double, double> ImageMomentsFeature::calcHuInvariants_imp (const std::vector<Pixel2>& cloud)
 {
-    // calculate 7 invariant moments
-    double h1 = NormCentralMom(D, 2, 0) + NormCentralMom(D, 0, 2);
-    double h2 = pow((NormCentralMom(D, 2, 0) - NormCentralMom(D, 0, 2)), 2) + 4 * (pow(NormCentralMom(D, 1, 1), 2));
-    double h3 = pow((NormCentralMom(D, 3, 0) - 3 * NormCentralMom(D, 1, 2)), 2) +
-        pow((3 * NormCentralMom(D, 2, 1) - NormCentralMom(D, 0, 3)), 2);
-    double h4 = pow((NormCentralMom(D, 3, 0) + NormCentralMom(D, 1, 2)), 2) +
-        pow((NormCentralMom(D, 2, 1) + NormCentralMom(D, 0, 3)), 2);
-    double h5 = (NormCentralMom(D, 3, 0) - 3 * NormCentralMom(D, 1, 2)) *
-        (NormCentralMom(D, 3, 0) + NormCentralMom(D, 1, 2)) *
-        (pow(NormCentralMom(D, 3, 0) + NormCentralMom(D, 1, 2), 2) - 3 * pow(NormCentralMom(D, 2, 1) + NormCentralMom(D, 0, 3), 2)) +
-        (3 * NormCentralMom(D, 2, 1) - NormCentralMom(D, 0, 3)) * (NormCentralMom(D, 2, 1) + NormCentralMom(D, 0, 3)) *
-        (pow(3 * (NormCentralMom(D, 3, 0) + NormCentralMom(D, 1, 2)), 2) - pow(NormCentralMom(D, 2, 1) + NormCentralMom(D, 0, 3), 2));
-    double h6 = (NormCentralMom(D, 2, 0) - NormCentralMom(D, 0, 2)) * (pow(NormCentralMom(D, 3, 0) + NormCentralMom(D, 1, 2), 2) -
-        pow(NormCentralMom(D, 2, 1) + NormCentralMom(D, 0, 3), 2)) + (4 * NormCentralMom(D, 1, 1) * (NormCentralMom(D, 3, 0) + NormCentralMom(D, 1, 2)) *
-            NormCentralMom(D, 2, 1) + NormCentralMom(D, 0, 3));
-    double h7 = (3 * NormCentralMom(D, 2, 1) - NormCentralMom(D, 0, 3)) * (NormCentralMom(D, 3, 0) + NormCentralMom(D, 1, 2)) * (pow(NormCentralMom(D, 3, 0) + NormCentralMom(D, 1, 2), 2) -
-        3 * pow(NormCentralMom(D, 2, 1) + NormCentralMom(D, 0, 3), 2)) - (NormCentralMom(D, 3, 0) - 3 * NormCentralMom(D, 1, 2)) * (NormCentralMom(D, 2, 1) + NormCentralMom(D, 0, 3)) *
-        (3 * pow(NormCentralMom(D, 3, 0) + NormCentralMom(D, 1, 2), 2) - pow(NormCentralMom(D, 2, 1) + NormCentralMom(D, 0, 3), 2));
-    return {h1, h2, h3, h4, h5, h6, h7};
+    // calculate the 7 Hu-1962 invariants
+
+    auto _20 = normCentralMom(cloud, 2, 0),
+        _02 = normCentralMom(cloud, 0, 2),
+        _11 = normCentralMom(cloud, 1, 1),
+        _30 = normCentralMom(cloud, 3, 0),
+        _12 = normCentralMom(cloud, 1, 2),
+        _21 = normCentralMom(cloud, 2, 1),
+        _03 = normCentralMom(cloud, 0, 3);
+
+    double h1 = _20 + _02;
+    double h2 = pow((_20 - _02), 2) + 4 * (pow(_11, 2));
+    double h3 = pow((_30 - 3 * _12), 2) +
+        pow((3 * _21 - _03), 2);
+    double h4 = pow((_30 + _12), 2) +
+        pow((_21 + _03), 2);
+    double h5 = (_30 - 3 * _12) *
+        (_30 + _12) *
+        (pow(_30 + _12, 2) - 3 * pow(_21 + _03, 2)) +
+        (3 * _21 - _03) * (_21 + _03) *
+        (pow(3 * (_30 + _12), 2) - pow(_21 + _03, 2));
+    double h6 = (_20 - _02) * (pow(_30 + _12, 2) -
+        pow(_21 + _03, 2)) + (4 * _11 * (_30 + _12) *
+            _21 + _03);
+    double h7 = (3 * _21 - _03) * (_30 + _12) * (pow(_30 + _12, 2) -
+        3 * pow(_21 + _03, 2)) - (_30 - 3 * _12) * (_21 + _03) *
+        (3 * pow(_30 + _12, 2) - pow(_21 + _03, 2));
+
+    return { h1, h2, h3, h4, h5, h6, h7 };
 }
 
-void ImageMomentsFeature::calcHuInvariants (const pixData& D)
+void ImageMomentsFeature::calcHuInvariants (const std::vector<Pixel2>& cloud)
 {
-    std::tie(hm1, hm2, hm3, hm4, hm5, hm6, hm7) = calcHuInvariants_imp(D);
+    std::tie(hm1, hm2, hm3, hm4, hm5, hm6, hm7) = calcHuInvariants_imp (cloud);
 }
 
-void ImageMomentsFeature::calcWeightedHuInvariants (const pixData& D)
+void ImageMomentsFeature::calcWeightedHuInvariants (const std::vector<Pixel2>& cloud)
 {
-    std::tie(whm1, whm2, whm3, whm4, whm5, whm6, whm7) = calcHuInvariants_imp(D);
+    std::tie(whm1, whm2, whm3, whm4, whm5, whm6, whm7) = calcHuInvariants_imp (cloud);
 }
 
-void ImageMomentsFeature::calcSpatialMoments (const pixData& D)
+void ImageMomentsFeature::calcRawMoments (const std::vector<Pixel2>& cloud)
 {
-    m00 = Moment (D, 0, 0);
-    m01 = Moment (D, 0, 1);
-    m02 = Moment (D, 0, 2);
-    m03 = Moment (D, 0, 3);
-    m10 = Moment (D, 1, 0);
-    m11 = Moment (D, 1, 1);
-    m12 = Moment (D, 1, 2);
-    m20 = Moment (D, 2, 0);
-    m21 = Moment (D, 2, 1);
-    m30 = Moment (D, 3, 0);
+    m00 = moment (cloud, 0, 0);
+    m01 = moment (cloud, 0, 1);
+    m02 = moment (cloud, 0, 2);
+    m03 = moment (cloud, 0, 3);
+    m10 = moment (cloud, 1, 0);
+    m11 = moment (cloud, 1, 1);
+    m12 = moment (cloud, 1, 2);
+    m20 = moment (cloud, 2, 0);
+    m21 = moment (cloud, 2, 1);
+    m30 = moment (cloud, 3, 0);
 }
 
-void ImageMomentsFeature::calcWeightedSpatialMoments (const pixData& D)
+/// @brief 
+/// @param cloud Cloud of weighted ROI pixels
+void ImageMomentsFeature::calcWeightedRawMoments (const std::vector<Pixel2>& cloud)
 {
-    wm00 = Moment (D, 0, 0);
-    wm01 = Moment (D, 0, 1);
-    wm02 = Moment (D, 0, 2);
-    wm03 = Moment (D, 0, 3);
-    wm10 = Moment (D, 1, 0);
-    wm11 = Moment (D, 1, 1);
-    wm12 = Moment (D, 1, 2);
-    wm20 = Moment (D, 2, 0);
-    wm21 = Moment (D, 2, 1);
-    wm30 = Moment (D, 3, 0);
+    wm00 = moment (cloud, 0, 0);
+    wm01 = moment (cloud, 0, 1);
+    wm02 = moment (cloud, 0, 2);
+    wm03 = moment (cloud, 0, 3);
+    wm10 = moment (cloud, 1, 0);
+    wm11 = moment (cloud, 1, 1);
+    wm12 = moment (cloud, 1, 2);
+    wm20 = moment (cloud, 2, 0);
+    wm21 = moment (cloud, 2, 1);
+    wm30 = moment (cloud, 3, 0);
 }
 
-void ImageMomentsFeature::calcCentralMoments(const pixData& D)
+void ImageMomentsFeature::calcCentralMoments (const std::vector<Pixel2>& cloud)
 {
-    mu02 = CentralMom(D, 0, 2);
-    mu03 = CentralMom(D, 0, 3);
-    mu11 = CentralMom(D, 1, 1);
-    mu12 = CentralMom(D, 1, 2);
-    mu20 = CentralMom(D, 2, 0);
-    mu21 = CentralMom(D, 2, 1);
-    mu30 = CentralMom(D, 3, 0);
+    mu02 = centralMom (cloud, 0, 2);
+    mu03 = centralMom (cloud, 0, 3);
+    mu11 = centralMom (cloud, 1, 1);
+    mu12 = centralMom (cloud, 1, 2);
+    mu20 = centralMom (cloud, 2, 0);
+    mu21 = centralMom (cloud, 2, 1);
+    mu30 = centralMom (cloud, 3, 0);
 }
 
-void ImageMomentsFeature::calcWeightedCentralMoments(const pixData& D)
+void ImageMomentsFeature::calcWeightedCentralMoments (const std::vector<Pixel2>& cloud)
 {
-    wmu02 = CentralMom(D, 0, 2);
-    wmu03 = CentralMom(D, 0, 3);
-    wmu11 = CentralMom(D, 1, 1);
-    wmu12 = CentralMom(D, 1, 2);
-    wmu20 = CentralMom(D, 2, 0);
-    wmu21 = CentralMom(D, 2, 1);
-    wmu30 = CentralMom(D, 3, 0);
+    wmu02 = centralMom (cloud, 0, 2);
+    wmu03 = centralMom (cloud, 0, 3);
+    wmu11 = centralMom (cloud, 1, 1);
+    wmu12 = centralMom (cloud, 1, 2);
+    wmu20 = centralMom (cloud, 2, 0);
+    wmu21 = centralMom (cloud, 2, 1);
+    wmu30 = centralMom (cloud, 3, 0);
 }
 
-void ImageMomentsFeature::calcNormCentralMoments (const pixData& D)
+void ImageMomentsFeature::calcNormCentralMoments (const std::vector<Pixel2>& cloud)
 {
-    nu02 = NormCentralMom(D, 0, 2);
-    nu03 = NormCentralMom(D, 0, 3);
-    nu11 = NormCentralMom(D, 1, 1);
-    nu12 = NormCentralMom(D, 1, 2);
-    nu20 = NormCentralMom(D, 2, 0);
-    nu21 = NormCentralMom(D, 2, 1);
-    nu30 = NormCentralMom(D, 3, 0);
+    nu02 = normCentralMom (cloud, 0, 2);
+    nu03 = normCentralMom (cloud, 0, 3);
+    nu11 = normCentralMom (cloud, 1, 1);
+    nu12 = normCentralMom (cloud, 1, 2);
+    nu20 = normCentralMom (cloud, 2, 0);
+    nu21 = normCentralMom (cloud, 2, 1);
+    nu30 = normCentralMom (cloud, 3, 0);
 }
 
-void ImageMomentsFeature::calcNormSpatialMoments (const pixData& D)
+void ImageMomentsFeature::calcNormRawMoments (const std::vector<Pixel2>& cloud)
 {
-    w00 = NormSpatMom (D, 0, 0);
-    w01 = NormSpatMom (D, 0, 1);
-    w02 = NormSpatMom (D, 0, 2);
-    w03 = NormSpatMom (D, 0, 3);
-    w10 = NormSpatMom (D, 1, 0);
-    w20 = NormSpatMom (D, 2, 0);
-    w30 = NormSpatMom (D, 3, 0);
+    w00 = normRawMom (cloud, 0, 0);
+    w01 = normRawMom (cloud, 0, 1);
+    w02 = normRawMom (cloud, 0, 2);
+    w03 = normRawMom (cloud, 0, 3);
+    w10 = normRawMom (cloud, 1, 0);
+    w20 = normRawMom (cloud, 2, 0);
+    w30 = normRawMom (cloud, 3, 0);
 }
 
 /// @brief Calculates the features for a subset of ROIs in a thread-safe way with other ROI subsets
diff --git a/src/nyx/features/image_moments.h b/src/nyx/features/image_moments.h
index c528eed3..2b1ac5dc 100644
--- a/src/nyx/features/image_moments.h
+++ b/src/nyx/features/image_moments.h
@@ -12,6 +12,9 @@
 // http://www.wseas.us/e-library/conferences/2013/CambridgeUK/AISE/AISE-15.pdf
 //
 
+using pixcloud = std::vector <Pixel2>;
+using pixcloud_NT = OutOfRamPixelCloud;
+
 /// @brief Hu invariants, weighted Hu invariants, spatial , central, and normalized central moments.
 class ImageMomentsFeature: public FeatureMethod
 {
@@ -75,51 +78,43 @@ class ImageMomentsFeature: public FeatureMethod
 
 private:
     // Trivial ROI
-
-    double Moment (const pixData& D, int p, int q);
-    void calcOrigins (const pixData& D);
-    double CentralMom (const pixData& D, int p, int q);
-    double NormSpatMom (const pixData& D, int p, int q);
-    double NormCentralMom (const pixData& D, int p, int q);
-
-    std::tuple<double, double, double, double, double, double, double> calcHuInvariants_imp (const pixData& D);
-    void calcHuInvariants (const pixData& D);
-    void calcWeightedHuInvariants (const pixData& D);
-    void calcNormCentralMoments(const pixData& D);
-    void calcNormSpatialMoments(const pixData& D);
-    void calcCentralMoments(const pixData& D);
-    void calcWeightedCentralMoments(const pixData& D);
-    void calcSpatialMoments(const pixData& D);
-    void calcWeightedSpatialMoments(const pixData& D);
-
-    #ifdef USE_GPU
-        void calculate_via_gpu(LR& r, size_t roi_index);
-    #endif
-
-    // Non-trivial (oversized) ROI
-
-    double Moment_nontriv (ImageLoader& imlo, ReadImageMatrix_nontriv& I, int p, int q);
-    double Moment_nontriv (WriteImageMatrix_nontriv& I, int p, int q);
-    void calcOrigins_nontriv (ImageLoader& imlo, ReadImageMatrix_nontriv& I);
-    void calcOrigins_nontriv (WriteImageMatrix_nontriv& I);
-    double CentralMom_nontriv (ImageLoader& imlo, ReadImageMatrix_nontriv& I, int p, int q);
-    double CentralMom_nontriv (WriteImageMatrix_nontriv& W, int p, int q);
-    double NormSpatMom_nontriv (ImageLoader& imlo, ReadImageMatrix_nontriv& I, int p, int q);
-    double NormCentralMom_nontriv (ImageLoader& imlo, ReadImageMatrix_nontriv& I, int p, int q);
-    double NormCentralMom_nontriv (WriteImageMatrix_nontriv& W, int p, int q);
-
-    std::tuple<double, double, double, double, double, double, double> calcHuInvariants_imp_nontriv (ImageLoader& imlo, ReadImageMatrix_nontriv& I);
-    std::tuple<double, double, double, double, double, double, double> calcHuInvariants_imp_nontriv (WriteImageMatrix_nontriv& I);
-    void calcHuInvariants_nontriv (ImageLoader& imlo, ReadImageMatrix_nontriv& I);
-    void calcWeightedHuInvariants_nontriv (WriteImageMatrix_nontriv& W);
-    void calcNormCentralMoments_nontriv (ImageLoader& imlo, ReadImageMatrix_nontriv& I);
-    void calcNormSpatialMoments_nontriv (ImageLoader& imlo, ReadImageMatrix_nontriv& I);
-    void calcCentralMoments_nontriv (ImageLoader& imlo, ReadImageMatrix_nontriv& I);
-    void calcWeightedCentralMoments_nontriv (WriteImageMatrix_nontriv& W);
-    void calcSpatialMoments_nontriv (ImageLoader& imlo, ReadImageMatrix_nontriv& I);
-    void calcWeightedSpatialMoments_nontriv (WriteImageMatrix_nontriv& W);
-
-    double originOfX = 0, originOfY = 0; // origins
+    double moment (const pixcloud& cloud, int p, int q);
+    void calcOrigins (const pixcloud& cloud);
+    double centralMom (const pixcloud& c, int p, int q);
+    double normRawMom (const pixcloud& cloud, int p, int q);
+    double normCentralMom (const pixcloud& c, int p, int q);
+    std::tuple<double, double, double, double, double, double, double> calcHuInvariants_imp (const pixcloud& cloud);
+    void calcRawMoments (const pixcloud& cloud);
+    void calcNormRawMoments (const pixcloud& cloud);
+    void calcNormCentralMoments (const pixcloud& cloud);
+    void calcWeightedRawMoments (const pixcloud& cloud);
+    void calcCentralMoments (const pixcloud& cloud);
+    void calcWeightedCentralMoments (const pixcloud& cloud);
+    void calcHuInvariants (const pixcloud& cloud);
+    void calcWeightedHuInvariants (const pixcloud& cloud);
+
+    // Non-trivial ROI
+    double moment(const pixcloud_NT& cloud, int p, int q);
+    void calcOrigins(const pixcloud_NT& cloud);
+    double centralMom(const pixcloud_NT& c, int p, int q);
+    double normRawMom(const pixcloud_NT& cloud, int p, int q);
+    double normCentralMom(const pixcloud_NT& c, int p, int q);
+    std::tuple<double, double, double, double, double, double, double> calcHuInvariants_imp(const pixcloud_NT& cloud);
+    void calcRawMoments(const pixcloud_NT& cloud);
+    void calcNormRawMoments(const pixcloud_NT& cloud);
+    void calcNormCentralMoments(const pixcloud_NT& cloud);
+    void calcWeightedRawMoments(const pixcloud_NT& cloud);
+    void calcCentralMoments(const pixcloud_NT& cloud);
+    void calcWeightedCentralMoments(const pixcloud_NT& cloud);
+    void calcHuInvariants(const pixcloud_NT& cloud);
+    void calcWeightedHuInvariants(const pixcloud_NT& cloud);
+
+#ifdef USE_GPU
+    void calculate_via_gpu(LR& r, size_t roi_index);
+#endif
+
+    StatsInt baseX = 0, baseY = 0; // cached min X and Y of the ROI. Reason - Pixel2's X and Y are absolute so we need to make them relative. Must be set in calculate() prior to calculating any 2D moment
+    double originOfX = 0, originOfY = 0; // centroids
     double m00 = 0, m01 = 0, m02 = 0, m03 = 0, m10 = 0, m11 = 0, m12 = 0, m20 = 0, m21 = 0, m30 = 0;    // spatial moments
     double wm00 = 0, wm01 = 0, wm02 = 0, wm03 = 0, wm10 = 0, wm11 = 0, wm12 = 0, wm20 = 0, wm21 = 0, wm30 = 0;    // weighted spatial moments
     double w00 = 0, w01 = 0, w02 = 0, w03 = 0, w10 = 0, w20 = 0, w30 = 0;   // normalized spatial moments
@@ -128,6 +123,8 @@ class ImageMomentsFeature: public FeatureMethod
     double wmu02 = 0, wmu03 = 0, wmu11 = 0, wmu12 = 0, wmu20 = 0, wmu21 = 0, wmu30 = 0;    // weighted central moments
     double hm1 = 0, hm2 = 0, hm3 = 0, hm4 = 0, hm5 = 0, hm6 = 0, hm7 = 0;   // Hu invariants
     double whm1 = 0, whm2 = 0, whm3 = 0, whm4 = 0, whm5 = 0, whm6 = 0, whm7 = 0;    // weighted Hu invariants
+
+    const double weighting_epsilon = 0.001;
 };
 
 bool ImageMomentsFeature_calculate2 (
diff --git a/src/nyx/features/image_moments_nontriv.cpp b/src/nyx/features/image_moments_nontriv.cpp
index 424269e5..a9c2374e 100644
--- a/src/nyx/features/image_moments_nontriv.cpp
+++ b/src/nyx/features/image_moments_nontriv.cpp
@@ -1,247 +1,205 @@
 #include "image_moments.h"
 
-void ImageMomentsFeature::osized_calculate(LR& r, ImageLoader& imlo)
-{
-    const ImageMatrix& im = r.aux_image_matrix;
-
-    ReadImageMatrix_nontriv I(r.aabb); 
-    calcOrigins_nontriv (imlo, I);
-    calcSpatialMoments_nontriv (imlo, I);
-    calcCentralMoments_nontriv (imlo, I);
-    calcNormCentralMoments_nontriv (imlo, I);
-    calcNormSpatialMoments_nontriv (imlo, I);
-    calcHuInvariants_nontriv (imlo, I);
-
-    WriteImageMatrix_nontriv W ("ImageMomentsFeature_osized_calculate_W", r.label); 
-    W.init_with_cloud_distance_to_contour_weights (r.raw_pixels_NT, r.aabb, r.contour);
-    calcOrigins_nontriv (W);
-    calcWeightedSpatialMoments_nontriv (W);
-    calcWeightedCentralMoments_nontriv (W);
-    calcWeightedHuInvariants_nontriv (W);
-}
-
-double ImageMomentsFeature::Moment_nontriv (ImageLoader& imlo, ReadImageMatrix_nontriv& I, int p, int q)
-{
-    // calc (p+q)th moment of object
-    double sum = 0;
-    for (size_t x = 0; x < I.get_width(); x++)
+void ImageMomentsFeature::osized_calculate(LR& r, ImageLoader&)
+{
+    // Cache ROI frame of reference
+    baseX = r.aabb.get_xmin();
+    baseY = r.aabb.get_ymin();
+
+    // Calculate non-weighted moments
+    auto& c = r.raw_pixels_NT;
+    calcOrigins (c);
+    calcRawMoments (c);
+    calcCentralMoments (c);
+    calcNormRawMoments (c);
+    calcNormCentralMoments (c);
+    calcHuInvariants (c);
+
+    // Prepare weighted pixel cloud
+    pixcloud_NT w;
+    w.init(r.label, "ImageMomentsFeature-osized_calculate-w");
+
+    // Implement apply_dist2contour_weighting (w, r.contour, weighting_epsilon) :
+    for (auto p : c)
     {
-        for (size_t y = 0; y < I.get_height(); y++)
-        {
-            sum += I.get_at(imlo, y, x) * pow(x, p) * pow(y, q);
-        }
-    }
-    return sum;
-}
+        // pixel distance
+        auto mind2 = p.min_sqdist(r.contour);
+        double dist = std::sqrt(mind2);
 
-double ImageMomentsFeature::Moment_nontriv (WriteImageMatrix_nontriv & I, int p, int q)
-{
-    // calc (p+q)th moment of object
-    double sum = 0;
-    for (size_t x = 0; x < I.get_width(); x++)
-    {
-        for (size_t y = 0; y < I.get_height(); y++)
-        {
-            sum += I.get_at(y, x) * pow(x, p) * pow(y, q);
-        }
+        // adjusted intensity
+        PixIntens wi = PixIntens((double)p.inten / (dist + weighting_epsilon));
+
+        // save
+        Pixel2 p_weighted = p;
+        p_weighted.inten = wi;
+        w.add_pixel(p_weighted);
     }
-    return sum;
-}
 
-void ImageMomentsFeature::calcOrigins_nontriv (ImageLoader& imlo, ReadImageMatrix_nontriv& I)
-{
-    // calc orgins
-    double m00 = Moment_nontriv (imlo, I, 0, 0);
-    originOfX = Moment_nontriv (imlo, I, 1, 0) / m00;
-    originOfY = Moment_nontriv (imlo, I, 0, 1) / m00;
+    // Calculate weighted moments
+    calcOrigins (w);
+    calcWeightedRawMoments (w);
+    calcWeightedCentralMoments (w);
+    calcWeightedHuInvariants (w);
 }
 
-void ImageMomentsFeature::calcOrigins_nontriv (WriteImageMatrix_nontriv & I)
+/// @brief Calculates the spatial 2D moment of order q,p f ROI pixel cloud
+double ImageMomentsFeature::moment (const pixcloud_NT& cloud, int p, int q)
 {
-    // calc orgins
-    double m00 = Moment_nontriv (I, 0, 0);
-    originOfX = Moment_nontriv (I, 1, 0) / m00;
-    originOfY = Moment_nontriv (I, 0, 1) / m00;
+    double q_ = q, p_ = p, sum = 0;
+    for (auto pxl : cloud)
+        sum += double(pxl.inten) * pow(double(pxl.x - baseX), p_) * pow(double(pxl.y - baseY), q_);
+    return sum;
 }
 
-double ImageMomentsFeature::CentralMom_nontriv (ImageLoader& imlo, ReadImageMatrix_nontriv& I, int p, int q)
+void ImageMomentsFeature::calcOrigins(const pixcloud_NT& cloud)
 {
-    // calculate central moment
-    double sum = 0;
-    for (int x = 0; x < I.get_width(); x++)
-    {
-        for (int y = 0; y < I.get_height(); y++)
-        {
-            sum += I.get_at(imlo, y, x) * pow((double(x) - originOfX), p) * pow((double(y) - originOfY), q);
-        }
-    }
-    return sum;
+    double m00 = moment(cloud, 0, 0);
+    originOfX = moment(cloud, 1, 0) / m00;
+    originOfY = moment(cloud, 0, 1) / m00;
 }
 
-double ImageMomentsFeature::CentralMom_nontriv (WriteImageMatrix_nontriv& W, int p, int q)
+/// @brief Calculates the central 2D moment of order q,p of ROI pixel cloud
+double ImageMomentsFeature::centralMom(const pixcloud_NT& cloud, int p, int q)
 {
-    // calculate central moment
     double sum = 0;
-    for (int x = 0; x < W.get_width(); x++)
-    {
-        for (int y = 0; y < W.get_height(); y++)
-        {
-            sum += W.get_at (y, x) * pow((double(x) - originOfX), p) * pow((double(y) - originOfY), q);
-        }
-    }
+    for (auto pxl : cloud)
+        sum += double(pxl.inten) * pow(double(pxl.x - baseX) - originOfX, p) * pow(double(pxl.y - baseY) - originOfY, q);
     return sum;
 }
 
-// https://handwiki.org/wiki/Standardized_moment
-double ImageMomentsFeature::NormSpatMom_nontriv (ImageLoader& imlo, ReadImageMatrix_nontriv& I, int p, int q)
+/// @brief Calculates the normalized spatial 2D moment of order q,p of ROI pixel cloud
+double ImageMomentsFeature::normRawMom(const pixcloud_NT& cloud, int p, int q)
 {
-    double stddev = CentralMom_nontriv (imlo, I, 2, 2);
+    double stddev = centralMom(cloud, 2, 2);
     int w = std::max(q, p);
-    double normCoef = pow(stddev, w);
-    double retval = CentralMom_nontriv(imlo, I, p, q) / normCoef;
+    double normCoef = pow(stddev, (double)w);
+    double cmPQ = centralMom(cloud, p, q);
+    double retval = cmPQ / normCoef;
     return retval;
 }
 
-double ImageMomentsFeature::NormCentralMom_nontriv (ImageLoader& imlo, ReadImageMatrix_nontriv& I, int p, int q)
+/// @brief Calculates the normalized central 2D moment of order q,p of ROI pixel cloud
+double ImageMomentsFeature::normCentralMom(const pixcloud_NT& cloud, int p, int q)
 {
     double temp = ((double(p) + double(q)) / 2.0) + 1.0;
-    double retval = CentralMom_nontriv (imlo, I, p, q) / pow(Moment_nontriv (imlo, I, 0, 0), temp);
+    double retval = centralMom(cloud, p, q) / pow(moment(cloud, 0, 0), temp);
     return retval;
 }
 
-double ImageMomentsFeature::NormCentralMom_nontriv (WriteImageMatrix_nontriv& W, int p, int q)
-{
-    double temp = ((double(p) + double(q)) / 2.0) + 1.0;
-    double retval = CentralMom_nontriv (W, p, q) / pow(Moment_nontriv (W, 0, 0), temp);
-    return retval;
-}
+std::tuple<double, double, double, double, double, double, double> ImageMomentsFeature::calcHuInvariants_imp(const pixcloud_NT& cloud)
+{
+    // calculate the 7 Hu-1962 invariants
+
+    auto _20 = normCentralMom(cloud, 2, 0),
+        _02 = normCentralMom(cloud, 0, 2),
+        _11 = normCentralMom(cloud, 1, 1),
+        _30 = normCentralMom(cloud, 3, 0),
+        _12 = normCentralMom(cloud, 1, 2),
+        _21 = normCentralMom(cloud, 2, 1),
+        _03 = normCentralMom(cloud, 0, 3);
+
+    double h1 = _20 + _02;
+    double h2 = pow((_20 - _02), 2) + 4 * (pow(_11, 2));
+    double h3 = pow((_30 - 3 * _12), 2) +
+        pow((3 * _21 - _03), 2);
+    double h4 = pow((_30 + _12), 2) +
+        pow((_21 + _03), 2);
+    double h5 = (_30 - 3 * _12) *
+        (_30 + _12) *
+        (pow(_30 + _12, 2) - 3 * pow(_21 + _03, 2)) +
+        (3 * _21 - _03) * (_21 + _03) *
+        (pow(3 * (_30 + _12), 2) - pow(_21 + _03, 2));
+    double h6 = (_20 - _02) * (pow(_30 + _12, 2) -
+        pow(_21 + _03, 2)) + (4 * _11 * (_30 + _12) *
+            _21 + _03);
+    double h7 = (3 * _21 - _03) * (_30 + _12) * (pow(_30 + _12, 2) -
+        3 * pow(_21 + _03, 2)) - (_30 - 3 * _12) * (_21 + _03) *
+        (3 * pow(_30 + _12, 2) - pow(_21 + _03, 2));
 
-void ImageMomentsFeature::calcSpatialMoments_nontriv (ImageLoader& imlo, ReadImageMatrix_nontriv& I)
-{
-    m00 = Moment_nontriv (imlo, I, 0, 0);
-    m01 = Moment_nontriv (imlo, I, 0, 1);
-    m02 = Moment_nontriv (imlo, I, 0, 2);
-    m03 = Moment_nontriv (imlo, I, 0, 3);
-    m10 = Moment_nontriv (imlo, I, 1, 0);
-    m11 = Moment_nontriv (imlo, I, 1, 1);
-    m12 = Moment_nontriv (imlo, I, 1, 2);
-    m20 = Moment_nontriv (imlo, I, 2, 0);
-    m21 = Moment_nontriv (imlo, I, 2, 1);
-    m30 = Moment_nontriv (imlo, I, 3, 0);
-}
-
-void ImageMomentsFeature::calcWeightedSpatialMoments_nontriv (WriteImageMatrix_nontriv& W)
-{
-    wm00 = Moment_nontriv (W, 0, 0);
-    wm01 = Moment_nontriv (W, 0, 1);
-    wm02 = Moment_nontriv (W, 0, 2);
-    wm03 = Moment_nontriv (W, 0, 3);
-    wm10 = Moment_nontriv (W, 1, 0);
-    wm11 = Moment_nontriv (W, 1, 1);
-    wm12 = Moment_nontriv (W, 1, 2);
-    wm20 = Moment_nontriv (W, 2, 0);
-    wm21 = Moment_nontriv (W, 2, 1);
-    wm30 = Moment_nontriv (W, 3, 0);
+    return { h1, h2, h3, h4, h5, h6, h7 };
 }
 
-void ImageMomentsFeature::calcCentralMoments_nontriv (ImageLoader& imlo, ReadImageMatrix_nontriv& I)
+void ImageMomentsFeature::calcHuInvariants(const pixcloud_NT& cloud)
 {
-    mu02 = CentralMom_nontriv (imlo, I, 0, 2);
-    mu03 = CentralMom_nontriv (imlo, I, 0, 3);
-    mu11 = CentralMom_nontriv (imlo, I, 1, 1);
-    mu12 = CentralMom_nontriv (imlo, I, 1, 2);
-    mu20 = CentralMom_nontriv (imlo, I, 2, 0);
-    mu21 = CentralMom_nontriv (imlo, I, 2, 1);
-    mu30 = CentralMom_nontriv (imlo, I, 3, 0);
+    std::tie(hm1, hm2, hm3, hm4, hm5, hm6, hm7) = calcHuInvariants_imp(cloud);
 }
 
-void ImageMomentsFeature::calcWeightedCentralMoments_nontriv (WriteImageMatrix_nontriv& W)
+void ImageMomentsFeature::calcWeightedHuInvariants(const pixcloud_NT& cloud)
 {
-    wmu02 = CentralMom_nontriv (W, 0, 2);
-    wmu03 = CentralMom_nontriv (W, 0, 3);
-    wmu11 = CentralMom_nontriv (W, 1, 1);
-    wmu12 = CentralMom_nontriv (W, 1, 2);
-    wmu20 = CentralMom_nontriv (W, 2, 0);
-    wmu21 = CentralMom_nontriv (W, 2, 1);
-    wmu30 = CentralMom_nontriv (W, 3, 0);
+    std::tie(whm1, whm2, whm3, whm4, whm5, whm6, whm7) = calcHuInvariants_imp(cloud);
 }
 
-void ImageMomentsFeature::calcNormCentralMoments_nontriv (ImageLoader& imlo, ReadImageMatrix_nontriv& I)
+void ImageMomentsFeature::calcRawMoments(const pixcloud_NT& cloud)
 {
-    nu02 = NormCentralMom_nontriv (imlo, I, 0, 2);
-    nu03 = NormCentralMom_nontriv (imlo, I, 0, 3);
-    nu11 = NormCentralMom_nontriv (imlo, I, 1, 1);
-    nu12 = NormCentralMom_nontriv (imlo, I, 1, 2);
-    nu20 = NormCentralMom_nontriv (imlo, I, 2, 0);
-    nu21 = NormCentralMom_nontriv (imlo, I, 2, 1);
-    nu30 = NormCentralMom_nontriv (imlo, I, 3, 0);
+    m00 = moment(cloud, 0, 0);
+    m01 = moment(cloud, 0, 1);
+    m02 = moment(cloud, 0, 2);
+    m03 = moment(cloud, 0, 3);
+    m10 = moment(cloud, 1, 0);
+    m11 = moment(cloud, 1, 1);
+    m12 = moment(cloud, 1, 2);
+    m20 = moment(cloud, 2, 0);
+    m21 = moment(cloud, 2, 1);
+    m30 = moment(cloud, 3, 0);
 }
 
-void ImageMomentsFeature::calcNormSpatialMoments_nontriv (ImageLoader& imlo, ReadImageMatrix_nontriv& I)
+/// @brief 
+/// @param cloud Cloud of weighted ROI pixels
+void ImageMomentsFeature::calcWeightedRawMoments(const pixcloud_NT& cloud)
 {
-    w00 = NormSpatMom_nontriv (imlo, I, 0, 0);
-    w01 = NormSpatMom_nontriv (imlo, I, 0, 1);
-    w02 = NormSpatMom_nontriv (imlo, I, 0, 2);
-    w03 = NormSpatMom_nontriv (imlo, I, 0, 3);
-    w10 = NormSpatMom_nontriv (imlo, I, 1, 0);
-    w20 = NormSpatMom_nontriv (imlo, I, 2, 0);
-    w30 = NormSpatMom_nontriv (imlo, I, 3, 0);
+    wm00 = moment(cloud, 0, 0);
+    wm01 = moment(cloud, 0, 1);
+    wm02 = moment(cloud, 0, 2);
+    wm03 = moment(cloud, 0, 3);
+    wm10 = moment(cloud, 1, 0);
+    wm11 = moment(cloud, 1, 1);
+    wm12 = moment(cloud, 1, 2);
+    wm20 = moment(cloud, 2, 0);
+    wm21 = moment(cloud, 2, 1);
+    wm30 = moment(cloud, 3, 0);
 }
 
-std::tuple<double, double, double, double, double, double, double> ImageMomentsFeature::calcHuInvariants_imp_nontriv (ImageLoader& imlo, ReadImageMatrix_nontriv& I)
+void ImageMomentsFeature::calcCentralMoments(const pixcloud_NT& cloud)
 {
-    // calculate 7 invariant moments
-    double h1 = NormCentralMom_nontriv (imlo, I, 2, 0) + NormCentralMom_nontriv (imlo, I, 0, 2);
-    double h2 = pow((NormCentralMom_nontriv (imlo, I, 2, 0) - NormCentralMom_nontriv (imlo, I, 0, 2)), 2) + 4 * (pow(NormCentralMom_nontriv (imlo, I, 1, 1), 2));
-    double h3 = pow((NormCentralMom_nontriv (imlo, I, 3, 0) - 3 * NormCentralMom_nontriv (imlo, I, 1, 2)), 2) +
-        pow((3 * NormCentralMom_nontriv (imlo, I, 2, 1) - NormCentralMom_nontriv (imlo, I, 0, 3)), 2);
-    double h4 = pow((NormCentralMom_nontriv (imlo, I, 3, 0) + NormCentralMom_nontriv (imlo, I, 1, 2)), 2) +
-        pow((NormCentralMom_nontriv (imlo, I, 2, 1) + NormCentralMom_nontriv (imlo, I, 0, 3)), 2);
-    double h5 = (NormCentralMom_nontriv (imlo, I, 3, 0) - 3 * NormCentralMom_nontriv (imlo, I, 1, 2)) *
-        (NormCentralMom_nontriv (imlo, I, 3, 0) + NormCentralMom_nontriv (imlo, I, 1, 2)) *
-        (pow(NormCentralMom_nontriv (imlo, I, 3, 0) + NormCentralMom_nontriv (imlo, I, 1, 2), 2) - 3 * pow(NormCentralMom_nontriv (imlo, I, 2, 1) + NormCentralMom_nontriv (imlo, I, 0, 3), 2)) +
-        (3 * NormCentralMom_nontriv (imlo, I, 2, 1) - NormCentralMom_nontriv (imlo, I, 0, 3)) * (NormCentralMom_nontriv (imlo, I, 2, 1) + NormCentralMom_nontriv (imlo, I, 0, 3)) *
-        (pow(3 * (NormCentralMom_nontriv (imlo, I, 3, 0) + NormCentralMom_nontriv (imlo, I, 1, 2)), 2) - pow(NormCentralMom_nontriv (imlo, I, 2, 1) + NormCentralMom_nontriv (imlo, I, 0, 3), 2));
-    double h6 = (NormCentralMom_nontriv (imlo, I, 2, 0) - NormCentralMom_nontriv (imlo, I, 0, 2)) * (pow(NormCentralMom_nontriv (imlo, I, 3, 0) + NormCentralMom_nontriv (imlo, I, 1, 2), 2) -
-        pow(NormCentralMom_nontriv (imlo, I, 2, 1) + NormCentralMom_nontriv (imlo, I, 0, 3), 2)) + (4 * NormCentralMom_nontriv (imlo, I, 1, 1) * (NormCentralMom_nontriv (imlo, I, 3, 0) + NormCentralMom_nontriv (imlo, I, 1, 2)) *
-            NormCentralMom_nontriv (imlo, I, 2, 1) + NormCentralMom_nontriv (imlo, I, 0, 3));
-    double h7 = (3 * NormCentralMom_nontriv (imlo, I, 2, 1) - NormCentralMom_nontriv (imlo, I, 0, 3)) * (NormCentralMom_nontriv (imlo, I, 3, 0) + NormCentralMom_nontriv (imlo, I, 1, 2)) * (pow(NormCentralMom_nontriv (imlo, I, 3, 0) + NormCentralMom_nontriv (imlo, I, 1, 2), 2) -
-        3 * pow(NormCentralMom_nontriv (imlo, I, 2, 1) + NormCentralMom_nontriv (imlo, I, 0, 3), 2)) - (NormCentralMom_nontriv (imlo, I, 3, 0) - 3 * NormCentralMom_nontriv (imlo, I, 1, 2)) * (NormCentralMom_nontriv (imlo, I, 2, 1) + NormCentralMom_nontriv (imlo, I, 0, 3)) *
-        (3 * pow(NormCentralMom_nontriv (imlo, I, 3, 0) + NormCentralMom_nontriv (imlo, I, 1, 2), 2) - pow(NormCentralMom_nontriv (imlo, I, 2, 1) + NormCentralMom_nontriv (imlo, I, 0, 3), 2));
-    return { h1, h2, h3, h4, h5, h6, h7 };
+    mu02 = centralMom(cloud, 0, 2);
+    mu03 = centralMom(cloud, 0, 3);
+    mu11 = centralMom(cloud, 1, 1);
+    mu12 = centralMom(cloud, 1, 2);
+    mu20 = centralMom(cloud, 2, 0);
+    mu21 = centralMom(cloud, 2, 1);
+    mu30 = centralMom(cloud, 3, 0);
 }
 
-std::tuple<double, double, double, double, double, double, double> ImageMomentsFeature::calcHuInvariants_imp_nontriv (WriteImageMatrix_nontriv& W)
+void ImageMomentsFeature::calcWeightedCentralMoments(const pixcloud_NT& cloud)
 {
-    // calculate 7 invariant moments
-    double h1 = NormCentralMom_nontriv (W, 2, 0) + NormCentralMom_nontriv (W, 0, 2);
-    double h2 = pow((NormCentralMom_nontriv (W, 2, 0) - NormCentralMom_nontriv (W, 0, 2)), 2) + 4 * (pow(NormCentralMom_nontriv (W, 1, 1), 2));
-    double h3 = pow((NormCentralMom_nontriv (W, 3, 0) - 3 * NormCentralMom_nontriv (W, 1, 2)), 2) +
-        pow((3 * NormCentralMom_nontriv (W, 2, 1) - NormCentralMom_nontriv (W, 0, 3)), 2);
-    double h4 = pow((NormCentralMom_nontriv (W, 3, 0) + NormCentralMom_nontriv (W, 1, 2)), 2) +
-        pow((NormCentralMom_nontriv (W, 2, 1) + NormCentralMom_nontriv (W, 0, 3)), 2);
-    double h5 = (NormCentralMom_nontriv (W, 3, 0) - 3 * NormCentralMom_nontriv (W, 1, 2)) *
-        (NormCentralMom_nontriv (W, 3, 0) + NormCentralMom_nontriv (W, 1, 2)) *
-        (pow(NormCentralMom_nontriv (W, 3, 0) + NormCentralMom_nontriv (W, 1, 2), 2) - 3 * pow(NormCentralMom_nontriv (W, 2, 1) + NormCentralMom_nontriv (W, 0, 3), 2)) +
-        (3 * NormCentralMom_nontriv (W, 2, 1) - NormCentralMom_nontriv (W, 0, 3)) * (NormCentralMom_nontriv (W, 2, 1) + NormCentralMom_nontriv (W, 0, 3)) *
-        (pow(3 * (NormCentralMom_nontriv (W, 3, 0) + NormCentralMom_nontriv (W, 1, 2)), 2) - pow(NormCentralMom_nontriv (W, 2, 1) + NormCentralMom_nontriv (W, 0, 3), 2));
-    double h6 = (NormCentralMom_nontriv (W, 2, 0) - NormCentralMom_nontriv (W, 0, 2)) * (pow(NormCentralMom_nontriv (W, 3, 0) + NormCentralMom_nontriv (W, 1, 2), 2) -
-        pow(NormCentralMom_nontriv (W, 2, 1) + NormCentralMom_nontriv (W, 0, 3), 2)) + (4 * NormCentralMom_nontriv (W, 1, 1) * (NormCentralMom_nontriv (W, 3, 0) + NormCentralMom_nontriv (W, 1, 2)) *
-            NormCentralMom_nontriv (W, 2, 1) + NormCentralMom_nontriv (W, 0, 3));
-    double h7 = (3 * NormCentralMom_nontriv (W, 2, 1) - NormCentralMom_nontriv (W, 0, 3)) * (NormCentralMom_nontriv (W, 3, 0) + NormCentralMom_nontriv (W, 1, 2)) * (pow(NormCentralMom_nontriv (W, 3, 0) + NormCentralMom_nontriv (W, 1, 2), 2) -
-        3 * pow(NormCentralMom_nontriv (W, 2, 1) + NormCentralMom_nontriv (W, 0, 3), 2)) - (NormCentralMom_nontriv (W, 3, 0) - 3 * NormCentralMom_nontriv (W, 1, 2)) * (NormCentralMom_nontriv (W, 2, 1) + NormCentralMom_nontriv (W, 0, 3)) *
-        (3 * pow(NormCentralMom_nontriv (W, 3, 0) + NormCentralMom_nontriv (W, 1, 2), 2) - pow(NormCentralMom_nontriv (W, 2, 1) + NormCentralMom_nontriv (W, 0, 3), 2));
-    return { h1, h2, h3, h4, h5, h6, h7 };
+    wmu02 = centralMom(cloud, 0, 2);
+    wmu03 = centralMom(cloud, 0, 3);
+    wmu11 = centralMom(cloud, 1, 1);
+    wmu12 = centralMom(cloud, 1, 2);
+    wmu20 = centralMom(cloud, 2, 0);
+    wmu21 = centralMom(cloud, 2, 1);
+    wmu30 = centralMom(cloud, 3, 0);
 }
 
-void ImageMomentsFeature::calcHuInvariants_nontriv (ImageLoader& imlo, ReadImageMatrix_nontriv& I)
+void ImageMomentsFeature::calcNormCentralMoments(const pixcloud_NT& cloud)
 {
-    std::tie(hm1, hm2, hm3, hm4, hm5, hm6, hm7) = calcHuInvariants_imp_nontriv (imlo, I);
+    nu02 = normCentralMom(cloud, 0, 2);
+    nu03 = normCentralMom(cloud, 0, 3);
+    nu11 = normCentralMom(cloud, 1, 1);
+    nu12 = normCentralMom(cloud, 1, 2);
+    nu20 = normCentralMom(cloud, 2, 0);
+    nu21 = normCentralMom(cloud, 2, 1);
+    nu30 = normCentralMom(cloud, 3, 0);
 }
 
-void ImageMomentsFeature::calcWeightedHuInvariants_nontriv (WriteImageMatrix_nontriv& W)
+void ImageMomentsFeature::calcNormRawMoments(const pixcloud_NT& cloud)
 {
-    std::tie(whm1, whm2, whm3, whm4, whm5, whm6, whm7) = calcHuInvariants_imp_nontriv (W);
+    w00 = normRawMom(cloud, 0, 0);
+    w01 = normRawMom(cloud, 0, 1);
+    w02 = normRawMom(cloud, 0, 2);
+    w03 = normRawMom(cloud, 0, 3);
+    w10 = normRawMom(cloud, 1, 0);
+    w20 = normRawMom(cloud, 2, 0);
+    w30 = normRawMom(cloud, 3, 0);
 }
 
-
diff --git a/src/nyx/features/intensity.cpp b/src/nyx/features/intensity.cpp
index 6529025c..821e6f65 100644
--- a/src/nyx/features/intensity.cpp
+++ b/src/nyx/features/intensity.cpp
@@ -7,7 +7,7 @@
 
 PixelIntensityFeatures::PixelIntensityFeatures() : FeatureMethod("PixelIntensityFeatures")
 {
-	provide_features({ 
+	provide_features({
 		INTEGRATED_INTENSITY,
 		MEAN,
 		MEDIAN,
@@ -36,7 +36,7 @@ PixelIntensityFeatures::PixelIntensityFeatures() : FeatureMethod("PixelIntensity
 void PixelIntensityFeatures::calculate(LR& r)
 {
 	// --MIN, MAX
-	val_MIN  = r.aux_min;
+	val_MIN = r.aux_min;
 	val_MAX = r.aux_max;
 	val_RANGE = val_MAX - val_MIN;
 
@@ -72,7 +72,7 @@ void PixelIntensityFeatures::calculate(LR& r)
 		var += diff * diff;
 	}
 	val_MEAN_ABSOLUTE_DEVIATION = mad / n;
-	var = n>1 ? var/(n-1) : 0.0;
+	var = n > 1 ? var / (n - 1) : 0.0;
 	double stddev = sqrt(var);
 	val_STANDARD_DEVIATION = stddev;
 
@@ -80,12 +80,12 @@ void PixelIntensityFeatures::calculate(LR& r)
 	val_STANDARD_ERROR = stddev / sqrt(n);
 
 	//==== Do not calculate features of all-blank intensities (to avoid NANs)
-	if (r.aux_min==0 && r.aux_max==0)
+	if (r.aux_min == 0 && r.aux_max == 0)
 		return;
 
 	// P10, 25, 75, 90, IQR, RMAD, entropy, uniformity
 	TrivialHistogram H;
-	H.initialize (r.aux_min, r.aux_max, r.raw_pixels);
+	H.initialize(r.aux_min, r.aux_max, r.raw_pixels);
 	auto [median_, mode_, p01_, p10_, p25_, p75_, p90_, p99_, iqr_, rmad_, entropy_, uniformity_] = H.get_stats();
 	val_MEDIAN = median_;
 	val_P01 = p01_;
@@ -123,7 +123,7 @@ void PixelIntensityFeatures::calculate(LR& r)
 
 	// Hyperskewness
 	double denom = (n * std::pow(val_STANDARD_DEVIATION, 5.));
-	val_HYPERSKEWNESS = denom == 0. ? 0. : sumPow5/denom;
+	val_HYPERSKEWNESS = denom == 0. ? 0. : sumPow5 / denom;
 
 	// Hyperflatness
 	denom = (n * std::pow(val_STANDARD_DEVIATION, 6.));
@@ -133,7 +133,7 @@ void PixelIntensityFeatures::calculate(LR& r)
 void PixelIntensityFeatures::osized_add_online_pixel(size_t x, size_t y, uint32_t intensity)
 {}
 
-void PixelIntensityFeatures::osized_calculate (LR& r, ImageLoader& imloader)
+void PixelIntensityFeatures::osized_calculate(LR& r, ImageLoader& imloader)
 {
 	// --MIN, MAX
 	val_MIN = r.aux_min;
@@ -148,9 +148,9 @@ void PixelIntensityFeatures::osized_calculate (LR& r, ImageLoader& imloader)
 	double cen_x = 0.0,
 		cen_y = 0.0,
 		integInten = 0.0;
-	for (size_t i = 0; i < n; i++) //--- for (auto& px : r.raw_pixels)
+	for (size_t i = 0; i < r.raw_pixels_NT.size(); i++)
 	{
-		Pixel2 px = r.raw_pixels_NT.get_at(i);
+		Pixel2 px = r.raw_pixels_NT[i];
 		mean_ += px.inten;
 		energy += px.inten * px.inten;
 		cen_x += px.x;
@@ -166,8 +166,9 @@ void PixelIntensityFeatures::osized_calculate (LR& r, ImageLoader& imloader)
 	// --MAD, VARIANCE, STDDEV
 	double mad = 0.0,
 		var = 0.0;
-	for (auto& px : r.raw_pixels)
+	for (size_t i = 0; i < r.raw_pixels_NT.size(); i++)
 	{
+		Pixel2 px = r.raw_pixels_NT[i];
 		mad += std::abs(px.inten - mean_);
 		var += (px.inten - mean_) * (px.inten - mean_);
 	}
@@ -185,7 +186,7 @@ void PixelIntensityFeatures::osized_calculate (LR& r, ImageLoader& imloader)
 
 	// P10, 25, 75, 90, IQR, RMAD, entropy, uniformity
 	TrivialHistogram H;
-	H.initialize(r.aux_min, r.aux_max, r.raw_pixels);
+	H.initialize(r.aux_min, r.aux_max, r.raw_pixels_NT);
 	auto [median_, mode_, p01_, p10_, p25_, p75_, p90_, p99_, iqr_, rmad_, entropy_, uniformity_] = H.get_stats();
 	val_MEDIAN = median_;
 	val_P01 = p01_;
@@ -207,18 +208,16 @@ void PixelIntensityFeatures::osized_calculate (LR& r, ImageLoader& imloader)
 	val_UNIFORMITY_PIU = piu;
 
 	// Skewness
-	//--Formula 1--	lr.fvals[SKEWNESS][0] = std::sqrt(n) * lr.aux_M3 / std::pow(lr.aux_M2, 1.5);
-	//--Formula 2-- skewness = 3 * (mean - median) / stddev
 	Moments4 mom;
-	for (size_t i = 0; i < n; i++) //--- for (auto& px : r.raw_pixels)
+	for (size_t i = 0; i < r.raw_pixels_NT.size(); i++)
 	{
-		Pixel2 px = r.raw_pixels_NT.get_at(i);
+		Pixel2 px = r.raw_pixels_NT[i];
 		mom.add(px.inten);
 	}
+
 	val_SKEWNESS = mom.skewness();
 
 	// Kurtosis
-	//--Formula-- k1 = mean((x - mean(x)). ^ 4) / std(x). ^ 4
 	val_KURTOSIS = mom.kurtosis();
 
 	// Hyperskewness hs = E[x-mean].^5 / std(x).^5
@@ -230,7 +229,7 @@ void PixelIntensityFeatures::osized_calculate (LR& r, ImageLoader& imloader)
 
 void PixelIntensityFeatures::save_value(std::vector<std::vector<double>>& fvals)
 {
-	fvals [INTEGRATED_INTENSITY][0] = val_INTEGRATED_INTENSITY; 
+	fvals[INTEGRATED_INTENSITY][0] = val_INTEGRATED_INTENSITY;
 	fvals[MEAN][0] = val_MEAN;
 	fvals[MEDIAN][0] = val_MEDIAN;
 	fvals[MIN][0] = val_MIN;
diff --git a/src/nyx/features/ngtdm.cpp b/src/nyx/features/ngtdm.cpp
index df60574d..0ed9fd8d 100644
--- a/src/nyx/features/ngtdm.cpp
+++ b/src/nyx/features/ngtdm.cpp
@@ -17,13 +17,31 @@ NGTDMFeature::NGTDMFeature(): FeatureMethod("NGTDMFeature")
 		NGTDM_STRENGTH });
 }
 
+void NGTDMFeature::clear_buffers()
+{
+	bad_roi_data = false;
+	Ng = 0;
+	Ngp = 0;
+	Nvp = 0;
+	Nd = 0; 
+	Nz = 0; 
+	Nvc = 0; 
+	P.clear();
+	S.clear();
+	N.clear();
+}
+
 void NGTDMFeature::calculate (LR& r)
 {
-	auto minI = r.aux_min, maxI = r.aux_max;
+	// Clear variables
+	clear_buffers();
+
+	// ROI image
 	const ImageMatrix& im = r.aux_image_matrix;
+	const pixData& D = im.ReadablePixels();
 
-	//==== Check if the ROI is degenerate (equal intensity)
-	if (minI == maxI)
+	// Check if the ROI is degenerate (equal intensity)
+	if (r.aux_min == r.aux_max)
 	{
 		bad_roi_data = true;
 		return;
@@ -32,15 +50,13 @@ void NGTDMFeature::calculate (LR& r)
 	// Prepare ROI's intensity range for normalize_I()
 	PixIntens piRange = r.aux_max - r.aux_min;
 
-	//==== Make a list of intensity clusters (zones)
+	// Make a list of intensity clusters (zones)
 	using AveNeighborhoodInte = std::pair<PixIntens, double>;	// Pairs of (intensity, average intensity of all 8 neighbors)
 	std::vector<AveNeighborhoodInte> Z;
 
-	//==== While scanning clusters, learn unique intensities 
+	// While scanning clusters, learn unique intensities 
 	std::unordered_set<PixIntens> U;
 
-	const pixData& D = im.ReadablePixels();
-
 	// Gather zones
 	unsigned int nGrays = theEnvironment.get_coarse_gray_depth();
 	for (int row = 0; row < D.height(); row++)
@@ -114,13 +130,10 @@ void NGTDMFeature::calculate (LR& r)
 			}
 		}
 
-	//==== Fill the matrix
-
-	//Ng = (Environment::ibsi_compliance) ?
-	//	*std::max_element(std::begin(r.aux_image_matrix.ReadablePixels()), std::end(r.aux_image_matrix.ReadablePixels())) : (decltype(Ng))U.size();
-	
-	Ng = *std::max_element(std::begin(r.aux_image_matrix.ReadablePixels()), std::end(r.aux_image_matrix.ReadablePixels()));
-	Ngp = U.size();
+	// Fill the matrix
+	// --dimensions
+	Ng = Environment::ibsi_compliance ? *std::max_element(std::begin(im.ReadablePixels()), std::end(im.ReadablePixels())) : (int) U.size();
+	Ngp = (int) U.size();
 
 	// --allocate the matrix
 	P.resize(Ng + 1, 0);
@@ -160,7 +173,7 @@ void NGTDMFeature::calculate (LR& r)
 	for (int i = 0; i < N.size(); i++)
 		P[i] = (double)N[i] / Nvc;
 
-	//=== Calculate features
+	// Calculate features
 	_coarseness = calc_Coarseness();
 	_contrast = calc_Contrast();
 	_busyness = calc_Busyness();
@@ -179,100 +192,111 @@ void NGTDMFeature::save_value(std::vector<std::vector<double>>& fvals)
 
 void NGTDMFeature::osized_add_online_pixel(size_t x, size_t y, uint32_t intensity) {} // Not supporting
 
-void NGTDMFeature::osized_calculate (LR& r, ImageLoader& imloader)
+void NGTDMFeature::osized_calculate (LR& r, ImageLoader&)
 {
-	auto minI = r.aux_min, 
-		maxI = r.aux_max;
-	
-	//==== Check if the ROI is degenerate (equal intensity)
-	if (minI == maxI)
+	// Clear variables
+	clear_buffers();
+
+	// Check if the ROI is degenerate (equal intensity)
+	if (r.aux_min == r.aux_max)
 	{
 		bad_roi_data = true;
 		return;
-	}	
-	
-	ReadImageMatrix_nontriv Im (r.aabb);
+	}
+
+	// Prepare ROI's intensity range for normalize_I()
+	PixIntens piRange = r.aux_max - r.aux_min;
 
-	//==== Make a list of intensity clusters (zones)
+	// Make a list of intensity clusters (zones)
 	using AveNeighborhoodInte = std::pair<PixIntens, double>;	// Pairs of (intensity, average intensity of all 8 neighbors)
 	std::vector<AveNeighborhoodInte> Z;
 
-	//==== While scanning clusters, learn unique intensities 
+	// While scanning clusters, learn unique intensities 
 	std::unordered_set<PixIntens> U;
 
+	// ROI image
+	WriteImageMatrix_nontriv D ("NGTDMFeature_osized_calculate_D", r.label);
+	D.allocate_from_cloud (r.raw_pixels_NT, r.aabb, false);
+
 	// Gather zones
-	for (size_t row = 0; row < Im.get_height(); row++)
-		for (size_t col = 0; col < Im.get_width(); col++)
+	unsigned int nGrays = theEnvironment.get_coarse_gray_depth();
+	for (int row = 0; row < D.get_height(); row++)
+		for (int col = 0; col < D.get_width(); col++)
 		{
-			// Find a non-blank pixel
-			PixIntens pi = (PixIntens) Im.get_at(imloader, row, col);
+			// Find a non-blank pixel 
+			PixIntens pi = Nyxus::to_grayscale(D.yx(row, col), r.aux_min, piRange, nGrays, Environment::ibsi_compliance);
 			if (pi == 0)
 				continue;
 
+			// Update unique intensities
+			U.insert(pi);
+
 			// Evaluate the neighborhood
-			PixIntens neigsI = 0;
+			double neigsI = 0;
 
 			int nd = 0;	// Number of dependencies
 
-			if (Im.safe(row - 1, col))	// North
+			if (D.safe(row - 1, col) && D.yx(row - 1, col) != 0)	// North
 			{
-				neigsI += (PixIntens) Im.get_at(imloader, row - 1, col);
+				neigsI += Nyxus::to_grayscale(D.yx(row - 1, col), r.aux_min, piRange, nGrays, Environment::ibsi_compliance);
 				nd++;
 			}
-			if (Im.safe(row - 1, col + 1))	// North-East
+
+			if (D.safe(row - 1, col + 1) && D.yx(row - 1, col + 1) != 0)	// North-East
 			{
-				neigsI += (PixIntens) Im.get_at(imloader, row - 1, col + 1);
+				neigsI += Nyxus::to_grayscale(D.yx(row - 1, col + 1), r.aux_min, piRange, nGrays, Environment::ibsi_compliance);
 				nd++;
 			}
-			if (Im.safe(row, col + 1))	// East
+
+			if (D.safe(row, col + 1) && D.yx(row, col + 1) != 0)	// East
 			{
-				neigsI += (PixIntens) Im.get_at(imloader, row, col + 1);
+				neigsI += Nyxus::to_grayscale(D.yx(row, col + 1), r.aux_min, piRange, nGrays, Environment::ibsi_compliance);
 				nd++;
 			}
-			if (Im.safe(row + 1, col + 1))	// South-East
+			if (D.safe(row + 1, col + 1) && D.yx(row + 1, col + 1) != 0)	// South-East
 			{
-				neigsI += (PixIntens) Im.get_at(imloader, row + 1, col + 1);
+				neigsI += Nyxus::to_grayscale(D.yx(row + 1, col + 1), r.aux_min, piRange, nGrays, Environment::ibsi_compliance);
 				nd++;
 			}
-			if (Im.safe(row + 1, col))	// South
+			if (D.safe(row + 1, col) && D.yx(row + 1, col) != 0)	// South
 			{
-				neigsI += (PixIntens) Im.get_at(imloader, row + 1, col);
+				neigsI += Nyxus::to_grayscale(D.yx(row + 1, col), r.aux_min, piRange, nGrays, Environment::ibsi_compliance);
 				nd++;
 			}
-			if (Im.safe(row + 1, col - 1))	// South-West
+			if (D.safe(row + 1, col - 1) && D.yx(row + 1, col - 1) != 0)	// South-West
 			{
-				neigsI += (PixIntens)Im.get_at(imloader, row + 1, col - 1);
+				neigsI += Nyxus::to_grayscale(D.yx(row + 1, col - 1), r.aux_min, piRange, nGrays, Environment::ibsi_compliance);
 				nd++;
 			}
-			if (Im.safe(row, col - 1))	// West
+			if (D.safe(row, col - 1) && D.yx(row, col - 1) != 0)	// West
 			{
-				neigsI += (PixIntens) Im.get_at(imloader, row, col - 1);
+				neigsI += Nyxus::to_grayscale(D.yx(row, col - 1), r.aux_min, piRange, nGrays, Environment::ibsi_compliance);
 				nd++;
 			}
-			if (Im.safe(row - 1, col - 1))	// North-West
+			if (D.safe(row - 1, col - 1) && D.yx(row - 1, col - 1) != 0)	// North-West
 			{
-				neigsI += (PixIntens) Im.get_at(imloader, row - 1, col - 1);
+				neigsI += Nyxus::to_grayscale(D.yx(row - 1, col - 1), r.aux_min, piRange, nGrays, Environment::ibsi_compliance);
 				nd++;
 			}
 
 			// Save the intensity's average neigborhood intensity
-			neigsI /= nd;
-			AveNeighborhoodInte z = { pi, neigsI };
-			Z.push_back(z);
-
-			// Update unique intensities
-			U.insert(pi);
+			if (nd > 0) 
+			{
+				neigsI /= nd;
+				AveNeighborhoodInte z = { pi, neigsI };
+				Z.push_back(z);
+			}
 		}
 
-	//==== Fill the matrix
+	// Fill the matrix
 
-	Ng = (decltype(Ng))U.size();
-	Ngp = Ng;
+	Ng = (int)U.size();
+	Ngp = (int)U.size();
 
 	// --allocate the matrix
-	P.resize(Ng, 0);
-	S.resize(Ng, 0);
-	N.resize(Ng, 0);
+	P.resize(Ng + 1, 0);
+	S.resize(Ng + 1, 0);
+	N.resize(Ng + 1, 0);
 
 	// --Set to vector to be able to know each intensity's index
 	std::vector<PixIntens> I(U.begin(), U.end());
@@ -283,13 +307,14 @@ void NGTDMFeature::osized_calculate (LR& r, ImageLoader& imloader)
 	{
 		// row
 		auto iter = std::find(I.begin(), I.end(), z.first);
-		int row = int(iter - I.begin());
+		int row = (Environment::ibsi_compliance) ?
+			z.first : int(iter - I.begin());
 		// col
 		int col = (int)z.second;	// 1-based
 		// increment
 		N[row]++;
 		// --S
-		PixIntens pi = z.first;
+		PixIntens pi = row;
 		double aveNeigI = z.second;
 		S[row] += std::abs(pi - aveNeigI);
 		// --Nvp
@@ -297,11 +322,16 @@ void NGTDMFeature::osized_calculate (LR& r, ImageLoader& imloader)
 			Nvp++;
 	}
 
+	// --Calculate Nvc (sum of N)
+	Nvc = 0;
+	for (int i = 0; i < N.size(); i++)
+		Nvc += N[i];
+
 	// --Calculate P
-	for (int i = 0; i < Ng; i++)
-		P[i] = double(Ng) / (Im.get_height()*Im.get_width());
+	for (int i = 0; i < N.size(); i++)
+		P[i] = (double)N[i] / Nvc;
 
-	//=== Calculate features
+	// Calculate features
 	_coarseness = calc_Coarseness();
 	_contrast = calc_Contrast();
 	_busyness = calc_Busyness();
diff --git a/src/nyx/features/ngtdm.h b/src/nyx/features/ngtdm.h
index d9ff79b9..c727a61e 100644
--- a/src/nyx/features/ngtdm.h
+++ b/src/nyx/features/ngtdm.h
@@ -68,6 +68,8 @@ class NGTDMFeature: public FeatureMethod
 	std::vector <double> P, S;
 	std::vector<int> N;
 
+	void clear_buffers();
+
 	const double BAD_ROI_FVAL = 0.0;
 	const double EPS = 2.2e-16;
 
diff --git a/src/nyx/features/zernike.cpp b/src/nyx/features/zernike.cpp
index ff1c5d89..bdb9cd4a 100644
--- a/src/nyx/features/zernike.cpp
+++ b/src/nyx/features/zernike.cpp
@@ -166,7 +166,6 @@ void ZernikeFeature::mb_Znl (double* X, double* Y, double* P, int size, double D
   where zernike features are useful.
 */
 
-
 void ZernikeFeature::mb_zernike2D (const ImageMatrix& Im, double order, double rad, double* zvalues, long* output_size) 
 {
 	int cols = Im.width;
@@ -337,38 +336,17 @@ void ZernikeFeature::mb_zernike2D (const ImageMatrix& Im, double order, double r
 	*output_size = numZ;
 }
 
-void ZernikeFeature::zernike2D(
-	// in
-	std::vector <Pixel2>& roi_cloud,
-	AABB& aabb,
-	int order)
+void ZernikeFeature::calculate (LR& r)
 {
-	// Create a temp image matrix from label's pixels
-	ImageMatrix I (roi_cloud, aabb);
-
+	// Allocate the results buffer
 	coeffs.resize (ZernikeFeature::NUM_FEATURE_VALS, 0);
 
 	// Calculate features
 	long output_size;   // output size is normally 72 (NUM_FEATURE_VALS)
-	mb_zernike2D (I, order, 0/*rad*/, coeffs.data(), &output_size); 
+	mb_zernike2D (r.aux_image_matrix, ZernikeFeature::ZERNIKE2D_ORDER, 0/*rad*/, coeffs.data(), &output_size);
 	ZernikeFeature::num_feature_values_calculated = output_size;
 }
 
-void ZernikeFeature::calculate (LR& r)
-{
-	zernike2D(
-		r.raw_pixels,	// nonzero_intensity_pixels,
-		r.aabb,			// AABB info not to calculate it again from 'raw_pixels' in the function
-		ZernikeFeature::ZERNIKE2D_ORDER);	
-
-	// Fix calculated feature values due to all-0 intensity labels to avoid NANs in the output
-	if (r.has_bad_data())
-	{
-		for (int i = 0; i < coeffs.size(); i++)
-			coeffs[i] = 0.0;
-	}
-}
-
 void ZernikeFeature::parallel_process_1_batch (size_t firstitem, size_t lastitem, std::vector<int>* ptrLabels, std::unordered_map <int, LR>* ptrLabelData)
 {
 	for (auto i = firstitem; i < lastitem; i++)
diff --git a/src/nyx/features/zernike.h b/src/nyx/features/zernike.h
index 6768b527..3ca45862 100644
--- a/src/nyx/features/zernike.h
+++ b/src/nyx/features/zernike.h
@@ -35,27 +35,12 @@ class ZernikeFeature: public FeatureMethod
 	/// @brief Algorithms for fast computation of Zernike momentsand their numerical stability
 	/// Chandan Singhand Ekta Walia, Imageand Vision Computing 29 (2011) 251�259 implemented from 
 	/// pseudo-code by Ilya Goldberg
-	void mb_zernike2D(const ImageMatrix& Im, double order, double rad, double* zvalues, long* output_size);
-
-	/// @brief Driver function for Zernike feature calculation
-	/// @param nonzero_intensity_pixels 
-	/// @param aabb 
-	/// @param order 
-	void zernike2D(
-		std::vector <Pixel2>& nonzero_intensity_pixels,
-		AABB& aabb,
-		int order);
-
-	/// @brief Driver function for Zernike feature calculation
-	/// @param nonzero_intensity_pixels 
-	/// @param aabb 
-	/// @param order 
-	void zernike2D_nontriv (OOR_ReadMatrix& I, int order);
-	
+	void mb_zernike2D (const ImageMatrix& Im, double order, double rad, double* zvalues, long* output_size);
+
 	/// @brief Algorithms for fast computation of Zernike momentsand their numerical stability
 	/// Chandan Singhand Ekta Walia, Imageand Vision Computing 29 (2011) 251�259 implemented from 
 	/// pseudo-code by Ilya Goldberg
-	void mb_zernike2D_nontriv (OOR_ReadMatrix& I, double order, double rad, double* zvalues, long* output_size);
+	void mb_zernike2D_nontriv (WriteImageMatrix_nontriv& I, double order, double rad, double* zvalues, long* output_size);
 
 	std::vector<double> coeffs;
 };
diff --git a/src/nyx/features/zernike_nontriv.cpp b/src/nyx/features/zernike_nontriv.cpp
index 6f0c3e0c..9665d17c 100644
--- a/src/nyx/features/zernike_nontriv.cpp
+++ b/src/nyx/features/zernike_nontriv.cpp
@@ -32,27 +32,26 @@
 #include "../roi_cache.h"
 #include "zernike.h"
 
-void ZernikeFeature::osized_calculate(LR& r, ImageLoader& imloader)
+void ZernikeFeature::osized_calculate (LR& r, ImageLoader& imloader)
 {
-	OOR_ReadMatrix I (imloader, r.aabb);
-
-	zernike2D_nontriv (I, ZernikeFeature::ZERNIKE2D_ORDER);
-
-	// Fix calculated feature values due to all-0 intensity labels to avoid NANs in the output
-	if (r.has_bad_data())
+	// Prepare the image matrix
+	WriteImageMatrix_nontriv I ("ZernikeFeature-osized_calculate-I", r.label);
+	I.allocate (r.aabb.get_width(), r.aabb.get_height(), 0);
+	for (Pixel2 p : r.raw_pixels_NT)
 	{
-		for (int i = 0; i < coeffs.size(); i++)
-			coeffs[i] = 0.0;
+		int col = p.x - r.aabb.get_xmin(),
+			row = p.y - r.aabb.get_ymin(),
+			idx = row * r.aabb.get_width() + col;
+		I.set_at (idx, p.inten);
 	}
-}
 
-void ZernikeFeature::zernike2D_nontriv (OOR_ReadMatrix& I, int order)
-{
-	coeffs.resize (ZernikeFeature::NUM_FEATURE_VALS, 0);
+	// Allocate the results buffer
+	coeffs.resize(ZernikeFeature::NUM_FEATURE_VALS, 0);
 
 	// Calculate features
 	long output_size;   // output size is normally 72 (NUM_FEATURE_VALS)
-	mb_zernike2D_nontriv (I, order, 0/*rad*/, coeffs.data(), &output_size);
+	mb_zernike2D_nontriv (I, ZernikeFeature::ZERNIKE2D_ORDER, 0/*rad*/, coeffs.data(), &output_size);
+	ZernikeFeature::num_feature_values_calculated = output_size;
 }
 
 /*
@@ -70,8 +69,7 @@ void ZernikeFeature::zernike2D_nontriv (OOR_ReadMatrix& I, int order)
   where zernike features are useful.
 */
 
-
-void ZernikeFeature::mb_zernike2D_nontriv (OOR_ReadMatrix& I, double order, double rad, double* zvalues, long* output_size)
+void ZernikeFeature::mb_zernike2D_nontriv (WriteImageMatrix_nontriv& I, double order, double rad, double* zvalues, long* output_size)
 {
 	int cols = I.get_width();
 	int rows = I.get_height();
@@ -113,9 +111,9 @@ void ZernikeFeature::mb_zernike2D_nontriv (OOR_ReadMatrix& I, double order, doub
 	for (i = 0; i < cols; i++)
 		for (j = 0; j < rows; j++)
 		{
-			if (std::isnan(I.get_at(j, i)))
+			if (std::isnan(I.yx(j, i)))
 				continue; //MM
-			intensity = I.get_at(j, i);
+			intensity = I.yx(j, i);
 			sum += intensity;
 			moment10 += (i + 1) * intensity;
 			moment00 += intensity;
@@ -159,7 +157,7 @@ void ZernikeFeature::mb_zernike2D_nontriv (OOR_ReadMatrix& I, double order, doub
 		x = (i + 1 - m10_m00) / rad;
 		for (j = 0; j < rows; j++)
 		{
-			if (std::isnan(I.get_at(j, i)))
+			if (std::isnan(I.yx(j, i)))
 				continue; //MM
 
 		// In the paper, the center of the unit circle was the center of the image
@@ -185,7 +183,7 @@ void ZernikeFeature::mb_zernike2D_nontriv (OOR_ReadMatrix& I, double order, doub
 			// compute contribution to Zernike moments for all 
 			// orders and repetitions by the pixel at (i,j)
 			// In the paper, the intensity was the raw image intensity
-			f = I.get_at(j, i) / sum;
+			f = I.yx(j, i) / sum;
 
 			Rnmp2 = Rnm2 = 0;
 			for (n = 0; n <= L; n++)
diff --git a/src/nyx/features_calc_workflow.cpp b/src/nyx/features_calc_workflow.cpp
index b165f34c..ae10e19a 100644
--- a/src/nyx/features_calc_workflow.cpp
+++ b/src/nyx/features_calc_workflow.cpp
@@ -118,9 +118,6 @@ namespace Nyxus
 
 	void init_label_record_2 (LR& r, const std::string& segFile, const std::string& intFile, int x, int y, int label, PixIntens intensity, unsigned int tile_index)
 	{
-		// Cache the host tile's index
-		r.host_tiles.insert (tile_index);
-
 		// Initialize basic counters
 		r.aux_area = 1;
 		r.aux_min = r.aux_max = intensity;
@@ -153,9 +150,6 @@ namespace Nyxus
 
 	void update_label_record_2 (LR& lr, int x, int y, int label, PixIntens intensity, unsigned int tile_index)
 	{
-		// Cache the host tile's index
-		lr.host_tiles.insert(tile_index);
-
 		// Initialize basic counters
 		lr.aux_area++;
 		lr.aux_min = std::min(lr.aux_min, intensity);
diff --git a/src/nyx/featureset.cpp b/src/nyx/featureset.cpp
index 35f82b5d..1471ce6b 100644
--- a/src/nyx/featureset.cpp
+++ b/src/nyx/featureset.cpp
@@ -177,12 +177,15 @@ namespace Nyxus
 		{"GLCM_ANGULAR2NDMOMENT", GLCM_ANGULAR2NDMOMENT },
 		{"GLCM_CONTRAST", GLCM_CONTRAST },
 		{"GLCM_CORRELATION", GLCM_CORRELATION },
+		{"GLCM_ENERGY", GLCM_ENERGY},
+		{"GLCM_HOMOGENEITY", GLCM_HOMOGENEITY},
 		{"GLCM_VARIANCE", GLCM_VARIANCE },
 		{"GLCM_INVERSEDIFFERENCEMOMENT", GLCM_INVERSEDIFFERENCEMOMENT },
 		{"GLCM_SUMAVERAGE", GLCM_SUMAVERAGE },
 		{"GLCM_SUMVARIANCE", GLCM_SUMVARIANCE },
 		{"GLCM_SUMENTROPY", 	GLCM_SUMENTROPY },
 		{"GLCM_ENTROPY", GLCM_ENTROPY },
+		{"GLCM_DIFFERENCEAVERAGE", GLCM_DIFFERENCEAVERAGE},
 		{"GLCM_DIFFERENCEVARIANCE", GLCM_DIFFERENCEVARIANCE },
 		{"GLCM_DIFFERENCEENTROPY", GLCM_DIFFERENCEENTROPY },
 		{"GLCM_INFOMEAS1", GLCM_INFOMEAS1 },
diff --git a/src/nyx/output_2_csv.cpp b/src/nyx/output_2_csv.cpp
index e5559cf7..5b11deb2 100644
--- a/src/nyx/output_2_csv.cpp
+++ b/src/nyx/output_2_csv.cpp
@@ -85,7 +85,7 @@ namespace Nyxus
 
 		if (!fp)
 		{
-			std::string errmsg = "Cannot open file " + getPureFname(intFpath) + " for writing";
+			std::string errmsg = "Cannot open file " + fullPath + " for writing";
 			std::perror (errmsg.c_str());
 			return false;
 		}
diff --git a/src/nyx/parallel.h b/src/nyx/parallel.h
index c2affdec..1dd06179 100644
--- a/src/nyx/parallel.h
+++ b/src/nyx/parallel.h
@@ -31,7 +31,5 @@ namespace Nyxus
 	}
 
 	void calcRoiIntensityFeatures (LR& lr);
-	void calcRoiContour(LR& r);
-	void parallelReduceContour (size_t start, size_t end, std::vector<int>* ptrLabels, std::unordered_map <int, LR>* ptrLabelData);
 	void parallelReduceConvHull (size_t start, size_t end, std::vector<int>* ptrLabels, std::unordered_map <int, LR>* ptrLabelData);
 }
diff --git a/src/nyx/phase2.cpp b/src/nyx/phase2.cpp
index a82ecb58..9a91ef71 100644
--- a/src/nyx/phase2.cpp
+++ b/src/nyx/phase2.cpp
@@ -131,7 +131,7 @@ namespace Nyxus
 						continue;
 
 					// Skip this ROI if the label isn't in the pending set of a multi-ROI mode
-					if (! theEnvironment.singleROI && ! std::binary_search(whiteList.begin(), whiteList.end(), label)) //--slow-- if (std::find(PendingRoiLabels.begin(), PendingRoiLabels.end(), label) == PendingRoiLabels.end())
+					if (! theEnvironment.singleROI && ! std::binary_search(whiteList.begin(), whiteList.end(), label))
 						continue;
 
 					auto inten = dataI[i];
@@ -173,6 +173,8 @@ namespace Nyxus
 
 	void allocateTrivialRoisBuffers(const std::vector<int>& Pending)
 	{
+		imageMatrixBufferLen = 0;
+
 		// Calculate the total memory demand (in # of items) of all segments' image matrices
 		for (auto lab : Pending)
 		{
@@ -203,6 +205,19 @@ namespace Nyxus
 
 	void freeTrivialRoisBuffers(const std::vector<int>& Pending)
 	{
+		// Dispose memory of ROIs having their feature calculation finished 
+		// in order to give memory ROIs of the next ROI batch. 
+		// (Vector 'Pending' is the set of ROIs of the finished batch.)
+		for (auto lab : Pending)
+		{
+			LR& r = roiData[lab];
+			std::vector<Pixel2>().swap(r.raw_pixels);
+			std::vector<PixIntens>().swap(r.aux_image_matrix._pix_plane);
+			std::vector<Pixel2>().swap(r.convHull_CH);	// convex hull is not a large object but there's no point to keep it beyond the batch, unlike contour
+		}
+
+		// Dispose the buffer of batches' ROIs' image matrices. (We allocate the 
+		// image matrix buffer externally to minimize host-GPU transfers.)
 		delete ImageMatrixBuffer;
 	}
 
@@ -228,12 +243,12 @@ namespace Nyxus
 			{
 				// Scan pixels of pending trivial ROIs 
 				std::sort (Pending.begin(), Pending.end());
-				VERBOSLVL1(std::cout << ">>> Scanning batch #" << roiBatchNo << " of " << Pending.size() << " pending ROIs of " << uniqueLabels.size() << " all ROIs\n";)
+				VERBOSLVL1(std::cout << ">>> Scanning batch #" << roiBatchNo << " of " << Pending.size() << " pending ROIs of total " << uniqueLabels.size() << " ROIs\n";)
 				VERBOSLVL1(
 					if (Pending.size() ==1)					
-						std::cout << ">>> (single ROI " << Pending[0] << ")\n";
+						std::cout << ">>> (single ROI label " << Pending[0] << ")\n";
 					else
-						std::cout << ">>> (ROIs " << Pending[0] << " ... " << Pending[Pending.size() - 1] << ")\n";
+						std::cout << ">>> (ROI labels " << Pending[0] << " ... " << Pending[Pending.size() - 1] << ")\n";
 					)
 				scanTrivialRois(Pending, intens_fpath, label_fpath, num_FL_threads);
 
diff --git a/src/nyx/phase3.cpp b/src/nyx/phase3.cpp
index 476d7968..9bb1c723 100644
--- a/src/nyx/phase3.cpp
+++ b/src/nyx/phase3.cpp
@@ -36,37 +36,40 @@ namespace Nyxus
 			
 			//=== Features permitting raster scan
 
-
 			// Initialize ROI's pixel cache
 			r.raw_pixels_NT.init (r.label, "raw_pixels_NT");
 
 			// Iterate ROI's tiles and scan pixels
-			for (auto tileIdx : r.host_tiles)
-			{
-				theImLoader.load_tile(tileIdx);
-				auto& dataI = theImLoader.get_int_tile_buffer();
-				auto& dataL = theImLoader.get_seg_tile_buffer();
-				for (unsigned long i = 0; i < theImLoader.get_tile_size(); i++)
+			size_t nth = theImLoader.get_num_tiles_hor(),
+				ntv = theImLoader.get_num_tiles_vert();
+			for (unsigned int row = 0; row < nth; row++)
+				for (unsigned int col = 0; col < ntv; col++)
 				{
-					auto pixLabel = dataL[i];
-
-					// Skip blanks and other ROI's pixel
-					if (pixLabel == 0 || pixLabel != r.label)
-						continue;
-
-					// Pixel intensity and global position
-					auto intens = dataI[i];
-					size_t row = tileIdx / theImLoader.get_num_tiles_hor(),
-						col = tileIdx / theImLoader.get_num_tiles_hor(),
-						th = theImLoader.get_tile_height(),
-						tw = theImLoader.get_tile_width();
-					int y = row * th + i / tw,
-						x = col * tw + i % tw;
-
-					// Feed the pixel to online features and helper objects
-					r.raw_pixels_NT.add_pixel(Pixel2(x, y, intens));
+					unsigned int tileIdx = row * ntv + col;
+					theImLoader.load_tile(tileIdx);
+					auto& dataI = theImLoader.get_int_tile_buffer();
+					auto& dataL = theImLoader.get_seg_tile_buffer();
+					for (unsigned long i = 0; i < theImLoader.get_tile_size(); i++)
+					{
+						auto pixLabel = dataL[i];
+
+						// Skip blanks and other ROI's pixel
+						if (pixLabel == 0 || pixLabel != r.label)
+							continue;
+
+						// Pixel intensity and global position
+						auto intens = dataI[i];
+						size_t row = tileIdx / theImLoader.get_num_tiles_hor(),
+							col = tileIdx / theImLoader.get_num_tiles_hor(),
+							th = theImLoader.get_tile_height(),
+							tw = theImLoader.get_tile_width();
+						int y = row * th + i / tw,
+							x = col * tw + i % tw;
+
+						// Feed the pixel to online features and helper objects
+						r.raw_pixels_NT.add_pixel(Pixel2(x, y, intens));
+					}
 				}
-			}
 
 			//=== Features requiring non-raster access to pixels
 			
diff --git a/src/nyx/reduce_trivial_rois.cpp b/src/nyx/reduce_trivial_rois.cpp
index 7e67751d..31d56a3a 100644
--- a/src/nyx/reduce_trivial_rois.cpp
+++ b/src/nyx/reduce_trivial_rois.cpp
@@ -83,14 +83,23 @@ namespace Nyxus
 		}
 
 		//==== Contour-related ROI perimeter, equivalent circle diameter
-		if (ContourFeature::required(theFeatureSet) || NeighborsFeature::required(theFeatureSet))
+		if (ContourFeature::required(theFeatureSet) 
+			|| ConvexHullFeature::required(theFeatureSet)
+			|| FractalDimensionFeature::required(theFeatureSet) 
+			|| GeodeticLengthThicknessFeature::required(theFeatureSet)
+			|| NeighborsFeature::required(theFeatureSet)
+			|| RoiRadiusFeature::required(theFeatureSet))
 		{
 			STOPWATCH("Morphology/Contour/C/#4aaaea", "\t=");
-			runParallel(parallelReduceContour, n_reduce_threads, workPerThread, jobSize, &PendingRoisLabels, &roiData);
+			runParallel(ContourFeature::reduce, n_reduce_threads, workPerThread, jobSize, &PendingRoisLabels, &roiData);
 		}
 
 		//==== Convex hull related solidity, circularity
-		if (ConvexHullFeature::required(theFeatureSet))
+		if (ConvexHullFeature::required(theFeatureSet) 
+			|| CaliperFeretFeature::required(theFeatureSet) 
+			|| CaliperMartinFeature::required(theFeatureSet) 
+			|| CaliperNassensteinFeature::required(theFeatureSet) 
+			|| HexagonalityPolygonalityFeature::required(theFeatureSet))
 		{
 			// CONVEX_HULL_AREA, SOLIDITY, CIRCULARITY // depends on PERIMETER
 			STOPWATCH("Morphology/Hull/H/#4aaaea", "\t=");
diff --git a/src/nyx/roi_cache.h b/src/nyx/roi_cache.h
index f1c2443a..3e6fad45 100644
--- a/src/nyx/roi_cache.h
+++ b/src/nyx/roi_cache.h
@@ -60,11 +60,10 @@ class LR: public BasicLR
 
 	std::vector<int> aux_neighboring_labels;
 
-	ImageMatrix aux_image_matrix;	// Needed by Contour, Erosions, GLCM, GLRLM, GLSZM, GLDM, NGTDM, Radial distribution(via Contour), Gabor, Moments, ROI radius(via Contour)
+	// needed by Contour, Erosions, GLCM, GLRLM, GLSZM, GLDM, NGTDM, Radial distribution, Gabor, Moments, ROI radius
+	ImageMatrix aux_image_matrix;
 	size_t im_buffer_offset;
 
-	std::unordered_set <unsigned int> host_tiles;
-
 	void reduce_pixel_intensity_features();
 };
 
diff --git a/src/nyx/scan_fastloader_way.cpp b/src/nyx/scan_fastloader_way.cpp
index a67c2059..d8ccd75f 100644
--- a/src/nyx/scan_fastloader_way.cpp
+++ b/src/nyx/scan_fastloader_way.cpp
@@ -57,10 +57,11 @@ namespace Nyxus
 
 			{ STOPWATCH("Image scan2a/ImgScan2a/Scan2a/lightsteelblue", "\t=");
 
-			// Phase 1: gather ROI metrics
-			VERBOSLVL1(std::cout << "Gathering ROI metrics\n";)
-				gatherRoisMetrics(intens_fpath, label_fpath, num_FL_threads);	// Output - set of ROI labels, label-ROI cache mappings
-
+				// Phase 1: gather ROI metrics
+				VERBOSLVL1(std::cout << "Gathering ROI metrics\n");
+				bool okGather = gatherRoisMetrics(intens_fpath, label_fpath, num_FL_threads);	// Output - set of ROI labels, label-ROI cache mappings
+				if (!okGather)
+					return false;
 			}
 
 			{ STOPWATCH("Image scan2b/ImgScan2b/Scan2b/lightsteelblue", "\t=");
@@ -190,8 +191,10 @@ namespace Nyxus
 			VERBOSLVL1(Stopwatch::print_stats();)
 				
 			// Details - also to a file
-			fs::path p (theSegFname);
-			VERBOSLVL1(Stopwatch::save_stats (theEnvironment.output_dir + "/" + p.stem().string() + "_nyxustiming.csv");)
+			VERBOSLVL3(
+				fs::path p(theSegFname);
+				Stopwatch::save_stats(theEnvironment.output_dir + "/" + p.stem().string() + "_nyxustiming.csv");
+			);
 			#endif
 		}
 
@@ -207,8 +210,7 @@ namespace Nyxus
 		std::ofstream f (fpath);
 
 		// header
-		f << "label, area, minx, miny, maxx, maxy, width, height, min_intens, max_intens, size_bytes, size_class, host_tiles \n";
-
+		f << "label, area, minx, miny, maxx, maxy, width, height, min_intens, max_intens, size_bytes, size_class \n";
 		// sort labels
 		std::vector<int>  sortedLabs { uniqueLabels.begin(), uniqueLabels.end() };
 		std::sort(sortedLabs.begin(), sortedLabs.end());
@@ -230,14 +232,6 @@ namespace Nyxus
 				<< r.aux_max << ", "
 				<< szb << ", "
 				<< ovsz << ", ";
-			// host tile indices
-			int ti = 0;
-			for (auto tIdx : r.host_tiles)
-			{
-				if (ti++)
-					f << "|";
-				f << tIdx;
-			}
 			f << "\n";
 		}
 


Test patch:
diff --git a/tests/test_data.h b/tests/test_data.h
index 0600b122..06676f33 100755
--- a/tests/test_data.h
+++ b/tests/test_data.h
@@ -384,3 +384,155 @@ const static NyxusPixel roiDataForPerimeterTest[] = {
 {117, 241, 1}, {118, 241, 1}, {119, 241, 1}, {120, 241, 1}, {121, 241, 1}, {122, 241, 1}, {123, 241, 1}, 
  };
 
+ //
+ // "cat2500" - phantom for smoke test of texture features
+ // 
+ 
+ //format: {x, y, intensity}
+ const static NyxusPixel cat2500_int[] = {
+	 {0,0,65280},	{1,0,65280},	{2,0,65280},	{3,0,65280},	{4,0,65280},	{5,0,65280},	{6,0,65280},	{7,0,65280},	{8,0,65280},	{9,0,65280},	{10,0,53504},	{11,0,7424},	{12,0,0},	{13,0,0},	{14,0,0},	{15,0,0},	{16,0,7680},	{17,0,59648},	{18,0,65280},	{19,0,65280},	{20,0,65280},	{21,0,65280},	{22,0,65280},	{23,0,65280},	{24,0,37632},	{25,0,0},	{26,0,0},	{27,0,0},	{28,0,0},	{29,0,0},	{30,0,0},	{31,0,22528},	{32,0,65280},	{33,0,65280},	{34,0,65280},	{35,0,65280},	{36,0,65280},	{37,0,65280},	{38,0,18944},	{39,0,0},	{40,0,0},	{41,0,0},	{42,0,0},	{43,0,0},	{44,0,30720},	{45,0,65280},	{46,0,65280},	{47,0,65280},	{48,0,65280},	{49,0,65280},	{50,0,29696},	{51,0,0},	{52,0,0},	{53,0,0},	{54,0,0},	{55,0,512},	{56,0,56832},	{57,0,65280},	{58,0,65280},	{59,0,65280},	{60,0,65280},	{61,0,35840},	{62,0,0},	{63,0,0},	{64,0,0},	{65,0,0},	{66,0,13312},	{67,0,65280},	{68,0,65280},	{69,0,65280},
+	 {0,1,65280},	{1,1,65280},	{2,1,65280},	{3,1,65280},	{4,1,65280},	{5,1,65280},	{6,1,65280},	{7,1,65280},	{8,1,65280},	{9,1,58624},	{10,1,3328},	{11,1,0},	{12,1,0},	{13,1,0},	{14,1,0},	{15,1,0},	{16,1,0},	{17,1,15360},	{18,1,63744},	{19,1,65280},	{20,1,65280},	{21,1,65280},	{22,1,65280},	{23,1,65280},	{24,1,65280},	{25,1,20992},	{26,1,0},	{27,1,0},	{28,1,0},	{29,1,0},	{30,1,0},	{31,1,0},	{32,1,43776},	{33,1,65280},	{34,1,65280},	{35,1,65280},	{36,1,65280},	{37,1,65280},	{38,1,56064},	{39,1,2048},	{40,1,0},	{41,1,0},	{42,1,0},	{43,1,0},	{44,1,2304},	{45,1,58112},	{46,1,65280},	{47,1,65280},	{48,1,65280},	{49,1,65280},	{50,1,59136},	{51,1,2048},	{52,1,0},	{53,1,0},	{54,1,0},	{55,1,0},	{56,1,30720},	{57,1,65280},	{58,1,65280},	{59,1,65280},	{60,1,65280},	{61,1,58624},	{62,1,768},	{63,1,0},	{64,1,0},	{65,1,0},	{66,1,256},	{67,1,58112},	{68,1,65280},	{69,1,65280},
+	 {0,2,65280},	{1,2,65280},	{2,2,65280},	{3,2,65280},	{4,2,65280},	{5,2,65280},	{6,2,65280},	{7,2,65280},	{8,2,65280},	{9,2,65280},	{10,2,34560},	{11,2,0},	{12,2,0},	{13,2,0},	{14,2,0},	{15,2,0},	{16,2,0},	{17,2,0},	{18,2,24576},	{19,2,65280},	{20,2,65280},	{21,2,65280},	{22,2,65280},	{23,2,65280},	{24,2,65280},	{25,2,61184},	{26,2,8448},	{27,2,0},	{28,2,0},	{29,2,0},	{30,2,0},	{31,2,0},	{32,2,5120},	{33,2,59648},	{34,2,65280},	{35,2,65280},	{36,2,65280},	{37,2,65280},	{38,2,65280},	{39,2,31488},	{40,2,0},	{41,2,0},	{42,2,0},	{43,2,0},	{44,2,0},	{45,2,26112},	{46,2,65280},	{47,2,65280},	{48,2,65280},	{49,2,65280},	{50,2,65280},	{51,2,26368},	{52,2,0},	{53,2,0},	{54,2,0},	{55,2,0},	{56,2,5120},	{57,2,63232},	{58,2,65280},	{59,2,65280},	{60,2,65280},	{61,2,65280},	{62,2,17152},	{63,2,0},	{64,2,0},	{65,2,0},	{66,2,0},	{67,2,38912},	{68,2,65280},	{69,2,65280},
+	 {0,3,65280},	{1,3,65280},	{2,3,65280},	{3,3,65280},	{4,3,65280},	{5,3,65280},	{6,3,65280},	{7,3,65280},	{8,3,65280},	{9,3,65280},	{10,3,65280},	{11,3,29184},	{12,3,0},	{13,3,0},	{14,3,0},	{15,3,0},	{16,3,0},	{17,3,0},	{18,3,0},	{19,3,37376},	{20,3,65280},	{21,3,65280},	{22,3,65280},	{23,3,65280},	{24,3,65280},	{25,3,65280},	{26,3,51712},	{27,3,1536},	{28,3,0},	{29,3,0},	{30,3,0},	{31,3,0},	{32,3,0},	{33,3,22272},	{34,3,65280},	{35,3,65280},	{36,3,65280},	{37,3,65280},	{38,3,65280},	{39,3,62976},	{40,3,8192},	{41,3,0},	{42,3,0},	{43,3,0},	{44,3,0},	{45,3,768},	{46,3,54784},	{47,3,65280},	{48,3,65280},	{49,3,65280},	{50,3,65280},	{51,3,56576},	{52,3,1024},	{53,3,0},	{54,3,0},	{55,3,0},	{56,3,0},	{57,3,41728},	{58,3,65280},	{59,3,65280},	{60,3,65280},	{61,3,65280},	{62,3,40448},	{63,3,0},	{64,3,0},	{65,3,0},	{66,3,0},	{67,3,19200},	{68,3,65280},	{69,3,65280},
+	 {0,4,65280},	{1,4,65280},	{2,4,65280},	{3,4,65280},	{4,4,65280},	{5,4,65280},	{6,4,65280},	{7,4,65280},	{8,4,65280},	{9,4,65280},	{10,4,65280},	{11,4,65024},	{12,4,24320},	{13,4,0},	{14,4,0},	{15,4,0},	{16,4,0},	{17,4,0},	{18,4,0},	{19,4,768},	{20,4,46592},	{21,4,65280},	{22,4,65280},	{23,4,65280},	{24,4,65280},	{25,4,65280},	{26,4,65280},	{27,4,35328},	{28,4,0},	{29,4,0},	{30,4,0},	{31,4,0},	{32,4,0},	{33,4,0},	{34,4,43520},	{35,4,65280},	{36,4,65280},	{37,4,65280},	{38,4,65280},	{39,4,65280},	{40,4,44288},	{41,4,0},	{42,4,0},	{43,4,0},	{44,4,0},	{45,4,0},	{46,4,21504},	{47,4,65280},	{48,4,65280},	{49,4,65280},	{50,4,65280},	{51,4,65280},	{52,4,22784},	{53,4,0},	{54,4,0},	{55,4,0},	{56,4,0},	{57,4,14848},	{58,4,65280},	{59,4,65280},	{60,4,65280},	{61,4,65280},	{62,4,61696},	{63,4,2560},	{64,4,0},	{65,4,0},	{66,4,0},	{67,4,1792},	{68,4,62208},	{69,4,65280},
+	 {0,5,65280},	{1,5,65280},	{2,5,65280},	{3,5,65280},	{4,5,65280},	{5,5,64768},	{6,5,65280},	{7,5,65280},	{8,5,65280},	{9,5,65280},	{10,5,65280},	{11,5,65280},	{12,5,64000},	{13,5,18432},	{14,5,0},	{15,5,0},	{16,5,0},	{17,5,0},	{18,5,0},	{19,5,0},	{20,5,4352},	{21,5,55808},	{22,5,65280},	{23,5,65280},	{24,5,65280},	{25,5,65280},	{26,5,65280},	{27,5,65024},	{28,5,19968},	{29,5,0},	{30,5,0},	{31,5,0},	{32,5,0},	{33,5,0},	{34,5,5120},	{35,5,59392},	{36,5,65280},	{37,5,65280},	{38,5,65280},	{39,5,65280},	{40,5,65280},	{41,5,18944},	{42,5,0},	{43,5,0},	{44,5,0},	{45,5,0},	{46,5,256},	{47,5,50944},	{48,5,65280},	{49,5,65280},	{50,5,65280},	{51,5,65280},	{52,5,53504},	{53,5,256},	{54,5,0},	{55,5,0},	{56,5,0},	{57,5,0},	{58,5,52224},	{59,5,65280},	{60,5,65280},	{61,5,65280},	{62,5,65280},	{63,5,22016},	{64,5,0},	{65,5,0},	{66,5,0},	{67,5,0},	{68,5,44800},	{69,5,65280},
+	 {0,6,65280},	{1,6,65280},	{2,6,65280},	{3,6,65280},	{4,6,37120},	{5,6,20992},	{6,6,64000},	{7,6,65280},	{8,6,65280},	{9,6,65280},	{10,6,65280},	{11,6,65280},	{12,6,65280},	{13,6,62720},	{14,6,14592},	{15,6,0},	{16,6,0},	{17,6,0},	{18,6,0},	{19,6,0},	{20,6,0},	{21,6,10240},	{22,6,61440},	{23,6,65280},	{24,6,65280},	{25,6,65280},	{26,6,65280},	{27,6,65280},	{28,6,60672},	{29,6,7680},	{30,6,0},	{31,6,0},	{32,6,0},	{33,6,0},	{34,6,0},	{35,6,20224},	{36,6,65280},	{37,6,65280},	{38,6,65280},	{39,6,65280},	{40,6,65280},	{41,6,56064},	{42,6,2048},	{43,6,0},	{44,6,0},	{45,6,0},	{46,6,0},	{47,6,16128},	{48,6,65280},	{49,6,65280},	{50,6,65280},	{51,6,65280},	{52,6,65280},	{53,6,19200},	{54,6,0},	{55,6,0},	{56,6,0},	{57,6,0},	{58,6,25856},	{59,6,65280},	{60,6,65280},	{61,6,65280},	{62,6,65280},	{63,6,45312},	{64,6,0},	{65,6,0},	{66,6,0},	{67,6,0},	{68,6,25088},	{69,6,65280},
+	 {0,7,65280},	{1,7,65280},	{2,7,65280},	{3,7,40448},	{4,7,256},	{5,7,0},	{6,7,20992},	{7,7,64000},	{8,7,65280},	{9,7,65280},	{10,7,65280},	{11,7,65280},	{12,7,65280},	{13,7,65280},	{14,7,60160},	{15,7,9984},	{16,7,0},	{17,7,0},	{18,7,0},	{19,7,0},	{20,7,0},	{21,7,0},	{22,7,18176},	{23,7,64512},	{24,7,65280},	{25,7,65280},	{26,7,65280},	{27,7,65280},	{28,7,65280},	{29,7,49664},	{30,7,768},	{31,7,0},	{32,7,0},	{33,7,0},	{34,7,0},	{35,7,0},	{36,7,43520},	{37,7,65280},	{38,7,65280},	{39,7,65280},	{40,7,65280},	{41,7,65280},	{42,7,31232},	{43,7,0},	{44,7,0},	{45,7,0},	{46,7,0},	{47,7,0},	{48,7,47616},	{49,7,65280},	{50,7,65280},	{51,7,65280},	{52,7,65280},	{53,7,50944},	{54,7,0},	{55,7,0},	{56,7,0},	{57,7,0},	{58,7,2560},	{59,7,60928},	{60,7,65280},	{61,7,65280},	{62,7,65280},	{63,7,64000},	{64,7,5120},	{65,7,0},	{66,7,0},	{67,7,0},	{68,7,5632},	{69,7,64768},
+	 {0,8,65280},	{1,8,65280},	{2,8,41728},	{3,8,512},	{4,8,0},	{5,8,0},	{6,8,0},	{7,8,20992},	{8,8,64000},	{9,8,65280},	{10,8,65280},	{11,8,65280},	{12,8,65280},	{13,8,65280},	{14,8,65280},	{15,8,56832},	{16,8,6400},	{17,8,0},	{18,8,0},	{19,8,0},	{20,8,0},	{21,8,0},	{22,8,0},	{23,8,30720},	{24,8,65280},	{25,8,65280},	{26,8,65280},	{27,8,65280},	{28,8,65280},	{29,8,65280},	{30,8,33024},	{31,8,0},	{32,8,0},	{33,8,0},	{34,8,0},	{35,8,0},	{36,8,5120},	{37,8,59392},	{38,8,65280},	{39,8,65280},	{40,8,65280},	{41,8,65280},	{42,8,62976},	{43,8,8192},	{44,8,0},	{45,8,0},	{46,8,0},	{47,8,0},	{48,8,12032},	{49,8,64768},	{50,8,65280},	{51,8,65280},	{52,8,65280},	{53,8,65280},	{54,8,15616},	{55,8,0},	{56,8,0},	{57,8,0},	{58,8,0},	{59,8,36864},	{60,8,65280},	{61,8,65280},	{62,8,65280},	{63,8,65280},	{64,8,26880},	{65,8,0},	{66,8,0},	{67,8,0},	{68,8,0},	{69,8,50688},
+	 {0,9,65280},	{1,9,44800},	{2,9,1024},	{3,9,0},	{4,9,0},	{5,9,0},	{6,9,0},	{7,9,0},	{8,9,20992},	{9,9,64000},	{10,9,65280},	{11,9,65280},	{12,9,65280},	{13,9,65280},	{14,9,65280},	{15,9,65280},	{16,9,54016},	{17,9,4352},	{18,9,0},	{19,9,0},	{20,9,0},	{21,9,0},	{22,9,0},	{23,9,0},	{24,9,41984},	{25,9,65280},	{26,9,65280},	{27,9,65280},	{28,9,65280},	{29,9,65280},	{30,9,64768},	{31,9,17664},	{32,9,0},	{33,9,0},	{34,9,0},	{35,9,0},	{36,9,0},	{37,9,20224},	{38,9,65280},	{39,9,65280},	{40,9,65280},	{41,9,65280},	{42,9,65280},	{43,9,44288},	{44,9,0},	{45,9,0},	{46,9,0},	{47,9,0},	{48,9,0},	{49,9,43008},	{50,9,65280},	{51,9,65280},	{52,9,65280},	{53,9,65280},	{54,9,46592},	{55,9,0},	{56,9,0},	{57,9,0},	{58,9,0},	{59,9,9472},	{60,9,65024},	{61,9,65280},	{62,9,65280},	{63,9,65280},	{64,9,50176},	{65,9,0},	{66,9,0},	{67,9,0},	{68,9,0},	{69,9,30976},
+	 {0,10,61440},	{1,10,4864},	{2,10,0},	{3,10,0},	{4,10,0},	{5,10,0},	{6,10,0},	{7,10,0},	{8,10,0},	{9,10,20992},	{10,10,64000},	{11,10,65280},	{12,10,65280},	{13,10,65280},	{14,10,65280},	{15,10,65280},	{16,10,65280},	{17,10,49152},	{18,10,2048},	{19,10,0},	{20,10,0},	{21,10,0},	{22,10,0},	{23,10,0},	{24,10,2048},	{25,10,51456},	{26,10,65280},	{27,10,65280},	{28,10,65280},	{29,10,65280},	{30,10,65280},	{31,10,59392},	{32,10,6400},	{33,10,0},	{34,10,0},	{35,10,0},	{36,10,0},	{37,10,0},	{38,10,43264},	{39,10,65280},	{40,10,65280},	{41,10,65280},	{42,10,65280},	{43,10,65280},	{44,10,18944},	{45,10,0},	{46,10,0},	{47,10,0},	{48,10,0},	{49,10,8448},	{50,10,63744},	{51,10,65280},	{52,10,65280},	{53,10,65280},	{54,10,65280},	{55,10,12800},	{56,10,0},	{57,10,0},	{58,10,0},	{59,10,0},	{60,10,48128},	{61,10,65280},	{62,10,65280},	{63,10,65280},	{64,10,65024},	{65,10,8704},	{66,10,0},	{67,10,0},	{68,10,0},	{69,10,11008},
+	 {0,11,65280},	{1,11,51968},	{2,11,5632},	{3,11,0},	{4,11,0},	{5,11,0},	{6,11,0},	{7,11,0},	{8,11,0},	{9,11,0},	{10,11,20992},	{11,11,64000},	{12,11,65280},	{13,11,65280},	{14,11,65280},	{15,11,65280},	{16,11,65280},	{17,11,65280},	{18,11,45312},	{19,11,1024},	{20,11,0},	{21,11,0},	{22,11,0},	{23,11,0},	{24,11,0},	{25,11,6400},	{26,11,58368},	{27,11,65280},	{28,11,65280},	{29,11,65280},	{30,11,65280},	{31,11,65280},	{32,11,48640},	{33,11,768},	{34,11,0},	{35,11,0},	{36,11,0},	{37,11,0},	{38,11,5120},	{39,11,59392},	{40,11,65280},	{41,11,65280},	{42,11,65280},	{43,11,65280},	{44,11,56064},	{45,11,1792},	{46,11,0},	{47,11,0},	{48,11,0},	{49,11,0},	{50,11,38400},	{51,11,65280},	{52,11,65280},	{53,11,65280},	{54,11,65280},	{55,11,43008},	{56,11,0},	{57,11,0},	{58,11,0},	{59,11,0},	{60,11,21248},	{61,11,65280},	{62,11,65280},	{63,11,65280},	{64,11,65280},	{65,11,31744},	{66,11,0},	{67,11,0},	{68,11,0},	{69,11,0},
+	 {0,12,65280},	{1,12,65280},	{2,12,56576},	{3,12,9216},	{4,12,0},	{5,12,0},	{6,12,0},	{7,12,0},	{8,12,0},	{9,12,0},	{10,12,0},	{11,12,20992},	{12,12,64000},	{13,12,65280},	{14,12,65280},	{15,12,65280},	{16,12,65280},	{17,12,65280},	{18,12,65280},	{19,12,39168},	{20,12,0},	{21,12,0},	{22,12,0},	{23,12,0},	{24,12,0},	{25,12,0},	{26,12,13056},	{27,12,62976},	{28,12,65280},	{29,12,65280},	{30,12,65280},	{31,12,65280},	{32,12,65280},	{33,12,31232},	{34,12,0},	{35,12,0},	{36,12,0},	{37,12,0},	{38,12,0},	{39,12,20224},	{40,12,65280},	{41,12,65280},	{42,12,65280},	{43,12,65280},	{44,12,65280},	{45,12,30976},	{46,12,0},	{47,12,0},	{48,12,0},	{49,12,0},	{50,12,5632},	{51,12,61952},	{52,12,65280},	{53,12,65280},	{54,12,65280},	{55,12,64512},	{56,12,9472},	{57,12,0},	{58,12,0},	{59,12,0},	{60,12,1024},	{61,12,58112},	{62,12,65280},	{63,12,65280},	{64,12,65280},	{65,12,55040},	{66,12,0},	{67,12,0},	{68,12,0},	{69,12,0},
+	 {0,13,65280},	{1,13,65280},	{2,13,65280},	{3,13,59136},	{4,13,12544},	{5,13,0},	{6,13,0},	{7,13,0},	{8,13,0},	{9,13,0},	{10,13,0},	{11,13,0},	{12,13,20992},	{13,13,64000},	{14,13,65280},	{15,13,65280},	{16,13,65280},	{17,13,65280},	{18,13,65280},	{19,13,65280},	{20,13,32512},	{21,13,0},	{22,13,0},	{23,13,0},	{24,13,0},	{25,13,0},	{26,13,0},	{27,13,23808},	{28,13,65280},	{29,13,65280},	{30,13,65280},	{31,13,65280},	{32,13,65280},	{33,13,64256},	{34,13,15360},	{35,13,0},	{36,13,0},	{37,13,0},	{38,13,0},	{39,13,0},	{40,13,43008},	{41,13,65280},	{42,13,65280},	{43,13,65280},	{44,13,65280},	{45,13,62720},	{46,13,8192},	{47,13,0},	{48,13,0},	{49,13,0},	{50,13,0},	{51,13,34048},	{52,13,65280},	{53,13,65280},	{54,13,65280},	{55,13,65280},	{56,13,39424},	{57,13,0},	{58,13,0},	{59,13,0},	{60,13,0},	{61,13,32512},	{62,13,65280},	{63,13,65280},	{64,13,65280},	{65,13,65280},	{66,13,13056},	{67,13,0},	{68,13,0},	{69,13,0},
+	 {0,14,65280},	{1,14,65280},	{2,14,65280},	{3,14,65280},	{4,14,62208},	{5,14,17664},	{6,14,0},	{7,14,0},	{8,14,0},	{9,14,0},	{10,14,0},	{11,14,0},	{12,14,0},	{13,14,20992},	{14,14,64000},	{15,14,65280},	{16,14,65280},	{17,14,65280},	{18,14,65280},	{19,14,65280},	{20,14,65280},	{21,14,28160},	{22,14,0},	{23,14,0},	{24,14,0},	{25,14,0},	{26,14,0},	{27,14,0},	{28,14,35584},	{29,14,65280},	{30,14,65280},	{31,14,65280},	{32,14,65280},	{33,14,65280},	{34,14,58112},	{35,14,5120},	{36,14,0},	{37,14,0},	{38,14,0},	{39,14,0},	{40,14,4864},	{41,14,59392},	{42,14,65280},	{43,14,65280},	{44,14,65280},	{45,14,65280},	{46,14,44032},	{47,14,0},	{48,14,0},	{49,14,0},	{50,14,0},	{51,14,3840},	{52,14,60416},	{53,14,65280},	{54,14,65280},	{55,14,65280},	{56,14,64000},	{57,14,7680},	{58,14,0},	{59,14,0},	{60,14,0},	{61,14,6400},	{62,14,64000},	{63,14,65280},	{64,14,65280},	{65,14,65280},	{66,14,36352},	{67,14,0},	{68,14,0},	{69,14,0},
+	 {0,15,65280},	{1,15,65280},	{2,15,65280},	{3,15,65280},	{4,15,65280},	{5,15,63488},	{6,15,22016},	{7,15,0},	{8,15,0},	{9,15,0},	{10,15,0},	{11,15,0},	{12,15,0},	{13,15,0},	{14,15,20992},	{15,15,64000},	{16,15,65280},	{17,15,65280},	{18,15,65280},	{19,15,65280},	{20,15,65280},	{21,15,64768},	{22,15,21760},	{23,15,0},	{24,15,0},	{25,15,0},	{26,15,0},	{27,15,0},	{28,15,512},	{29,15,45824},	{30,15,65280},	{31,15,65280},	{32,15,65280},	{33,15,65280},	{34,15,65280},	{35,15,46336},	{36,15,256},	{37,15,0},	{38,15,0},	{39,15,0},	{40,15,0},	{41,15,19968},	{42,15,65280},	{43,15,65280},	{44,15,65280},	{45,15,65280},	{46,15,65280},	{47,15,18688},	{48,15,0},	{49,15,0},	{50,15,0},	{51,15,0},	{52,15,29440},	{53,15,65280},	{54,15,65280},	{55,15,65280},	{56,15,65280},	{57,15,36096},	{58,15,0},	{59,15,0},	{60,15,0},	{61,15,0},	{62,15,43520},	{63,15,65280},	{64,15,65280},	{65,15,65280},	{66,15,59648},	{67,15,1024},	{68,15,0},	{69,15,0},
+	 {0,16,65280},	{1,16,65280},	{2,16,65280},	{3,16,65280},	{4,16,65280},	{5,16,65280},	{6,16,64512},	{7,16,26624},	{8,16,0},	{9,16,0},	{10,16,0},	{11,16,0},	{12,16,0},	{13,16,0},	{14,16,0},	{15,16,20992},	{16,16,64000},	{17,16,65280},	{18,16,65280},	{19,16,65280},	{20,16,65280},	{21,16,65280},	{22,16,63744},	{23,16,17664},	{24,16,0},	{25,16,0},	{26,16,0},	{27,16,0},	{28,16,0},	{29,16,3328},	{30,16,54272},	{31,16,65280},	{32,16,65280},	{33,16,65280},	{34,16,65280},	{35,16,65280},	{36,16,28928},	{37,16,0},	{38,16,0},	{39,16,0},	{40,16,0},	{41,16,0},	{42,16,42752},	{43,16,65280},	{44,16,65280},	{45,16,65280},	{46,16,65280},	{47,16,56064},	{48,16,1792},	{49,16,0},	{50,16,0},	{51,16,0},	{52,16,2048},	{53,16,57600},	{54,16,65280},	{55,16,65280},	{56,16,65280},	{57,16,62464},	{58,16,5120},	{59,16,0},	{60,16,0},	{61,16,0},	{62,16,16640},	{63,16,65280},	{64,16,65280},	{65,16,65280},	{66,16,65280},	{67,16,17920},	{68,16,0},	{69,16,0},
+	 {0,17,65280},	{1,17,65280},	{2,17,65280},	{3,17,65280},	{4,17,65280},	{5,17,65280},	{6,17,65280},	{7,17,65280},	{8,17,34816},	{9,17,0},	{10,17,0},	{11,17,0},	{12,17,0},	{13,17,0},	{14,17,0},	{15,17,0},	{16,17,20992},	{17,17,64000},	{18,17,65280},	{19,17,65280},	{20,17,65280},	{21,17,65280},	{22,17,65280},	{23,17,61696},	{24,17,12544},	{25,17,0},	{26,17,0},	{27,17,0},	{28,17,0},	{29,17,0},	{30,17,8448},	{31,17,60160},	{32,17,65280},	{33,17,65280},	{34,17,65280},	{35,17,65280},	{36,17,64000},	{37,17,14592},	{38,17,0},	{39,17,0},	{40,17,0},	{41,17,0},	{42,17,4864},	{43,17,59136},	{44,17,65280},	{45,17,65280},	{46,17,65280},	{47,17,65280},	{48,17,30976},	{49,17,0},	{50,17,0},	{51,17,0},	{52,17,0},	{53,17,25088},	{54,17,65280},	{55,17,65280},	{56,17,65280},	{57,17,65280},	{58,17,32512},	{59,17,0},	{60,17,0},	{61,17,0},	{62,17,0},	{63,17,54016},	{64,17,65280},	{65,17,65280},	{66,17,65280},	{67,17,41216},	{68,17,0},	{69,17,0},
+	 {0,18,26112},	{1,18,64000},	{2,18,65280},	{3,18,65280},	{4,18,65280},	{5,18,65280},	{6,18,65280},	{7,18,65280},	{8,18,65280},	{9,18,40448},	{10,18,1024},	{11,18,0},	{12,18,0},	{13,18,0},	{14,18,0},	{15,18,0},	{16,18,0},	{17,18,20992},	{18,18,64000},	{19,18,65280},	{20,18,65280},	{21,18,65280},	{22,18,65280},	{23,18,65280},	{24,18,59648},	{25,18,9472},	{26,18,0},	{27,18,0},	{28,18,0},	{29,18,0},	{30,18,0},	{31,18,17664},	{32,18,64256},	{33,18,65280},	{34,18,65280},	{35,18,65280},	{36,18,65280},	{37,18,57600},	{38,18,4608},	{39,18,0},	{40,18,0},	{41,18,0},	{42,18,0},	{43,18,19968},	{44,18,65280},	{45,18,65280},	{46,18,65280},	{47,18,65280},	{48,18,62720},	{49,18,8192},	{50,18,0},	{51,18,0},	{52,18,0},	{53,18,768},	{54,18,54272},	{55,18,65280},	{56,18,65280},	{57,18,65280},	{58,18,60672},	{59,18,3072},	{60,18,0},	{61,18,0},	{62,18,0},	{63,18,27904},	{64,18,65280},	{65,18,65280},	{66,18,65280},	{67,18,62464},	{68,18,2816},	{69,18,0},
+	 {0,19,0},	{1,19,15872},	{2,19,59904},	{3,19,65280},	{4,19,65280},	{5,19,65280},	{6,19,65280},	{7,19,65280},	{8,19,65280},	{9,19,65280},	{10,19,45056},	{11,19,2304},	{12,19,0},	{13,19,0},	{14,19,0},	{15,19,0},	{16,19,0},	{17,19,0},	{18,19,20992},	{19,19,64000},	{20,19,65280},	{21,19,65280},	{22,19,65280},	{23,19,65280},	{24,19,65280},	{25,19,56320},	{26,19,5888},	{27,19,0},	{28,19,0},	{29,19,0},	{30,19,0},	{31,19,0},	{32,19,28928},	{33,19,65280},	{34,19,65280},	{35,19,65280},	{36,19,65280},	{37,19,65280},	{38,19,43776},	{39,19,0},	{40,19,0},	{41,19,0},	{42,19,0},	{43,19,0},	{44,19,42496},	{45,19,65280},	{46,19,65280},	{47,19,65280},	{48,19,65280},	{49,19,43776},	{50,19,0},	{51,19,0},	{52,19,0},	{53,19,0},	{54,19,20480},	{55,19,65280},	{56,19,65280},	{57,19,65280},	{58,19,65280},	{59,19,28928},	{60,19,0},	{61,19,0},	{62,19,0},	{63,19,3328},	{64,19,61952},	{65,19,65280},	{66,19,65280},	{67,19,65280},	{68,19,22784},	{69,19,0},
+	 {0,20,0},	{1,20,0},	{2,20,9472},	{3,20,54784},	{4,20,65280},	{5,20,65280},	{6,20,65280},	{7,20,65280},	{8,20,65280},	{9,20,65280},	{10,20,65280},	{11,20,49152},	{12,20,3840},	{13,20,0},	{14,20,0},	{15,20,0},	{16,20,0},	{17,20,0},	{18,20,0},	{19,20,20992},	{20,20,64000},	{21,20,65280},	{22,20,65280},	{23,20,65280},	{24,20,65280},	{25,20,65280},	{26,20,51968},	{27,20,3328},	{28,20,0},	{29,20,0},	{30,20,0},	{31,20,0},	{32,20,0},	{33,20,39424},	{34,20,65280},	{35,20,65280},	{36,20,65280},	{37,20,65280},	{38,20,65280},	{39,20,26880},	{40,20,0},	{41,20,0},	{42,20,0},	{43,20,0},	{44,20,4864},	{45,20,59136},	{46,20,65280},	{47,20,65280},	{48,20,65280},	{49,20,65280},	{50,20,18688},	{51,20,0},	{52,20,0},	{53,20,0},	{54,20,0},	{55,20,50432},	{56,20,65280},	{57,20,65280},	{58,20,65280},	{59,20,58368},	{60,20,1536},	{61,20,0},	{62,20,0},	{63,20,0},	{64,20,38912},	{65,20,65280},	{66,20,65280},	{67,20,65280},	{68,20,46080},	{69,20,0},
+	 {0,21,0},	{1,21,0},	{2,21,0},	{3,21,3328},	{4,21,45056},	{5,21,65280},	{6,21,65280},	{7,21,65280},	{8,21,65280},	{9,21,65280},	{10,21,65280},	{11,21,65280},	{12,21,54016},	{13,21,6912},	{14,21,0},	{15,21,0},	{16,21,0},	{17,21,0},	{18,21,0},	{19,21,0},	{20,21,20992},	{21,21,64000},	{22,21,65280},	{23,21,65280},	{24,21,65280},	{25,21,65280},	{26,21,65280},	{27,21,48384},	{28,21,1792},	{29,21,0},	{30,21,0},	{31,21,0},	{32,21,0},	{33,21,1280},	{34,21,49408},	{35,21,65280},	{36,21,65280},	{37,21,65280},	{38,21,65280},	{39,21,63488},	{40,21,12544},	{41,21,0},	{42,21,0},	{43,21,0},	{44,21,0},	{45,21,19712},	{46,21,65280},	{47,21,65280},	{48,21,65280},	{49,21,65280},	{50,21,55808},	{51,21,1792},	{52,21,0},	{53,21,0},	{54,21,0},	{55,21,15616},	{56,21,65280},	{57,21,65280},	{58,21,65280},	{59,21,65280},	{60,21,25344},	{61,21,0},	{62,21,0},	{63,21,0},	{64,21,11776},	{65,21,65280},	{66,21,65280},	{67,21,65280},	{68,21,64256},	{69,21,5888},
+	 {0,22,0},	{1,22,0},	{2,22,0},	{3,22,0},	{4,22,256},	{5,22,32512},	{6,22,65280},	{7,22,65280},	{8,22,65280},	{9,22,65280},	{10,22,65280},	{11,22,65280},	{12,22,65280},	{13,22,57088},	{14,22,9984},	{15,22,0},	{16,22,0},	{17,22,0},	{18,22,0},	{19,22,0},	{20,22,0},	{21,22,20992},	{22,22,64000},	{23,22,65280},	{24,22,65280},	{25,22,65280},	{26,22,65280},	{27,22,65280},	{28,22,42752},	{29,22,512},	{30,22,0},	{31,22,0},	{32,22,0},	{33,22,0},	{34,22,5888},	{35,22,57856},	{36,22,65280},	{37,22,65280},	{38,22,65280},	{39,22,65280},	{40,22,56064},	{41,22,3328},	{42,22,0},	{43,22,0},	{44,22,0},	{45,22,0},	{46,22,41984},	{47,22,65280},	{48,22,65280},	{49,22,65280},	{50,22,65280},	{51,22,30720},	{52,22,0},	{53,22,0},	{54,22,0},	{55,22,0},	{56,22,46336},	{57,22,65280},	{58,22,65280},	{59,22,65280},	{60,22,56320},	{61,22,768},	{62,22,0},	{63,22,0},	{64,22,0},	{65,22,50176},	{66,22,65280},	{67,22,65280},	{68,22,65280},	{69,22,27392},
+	 {0,23,0},	{1,23,0},	{2,23,0},	{3,23,0},	{4,23,0},	{5,23,0},	{6,23,22528},	{7,23,62976},	{8,23,65280},	{9,23,65280},	{10,23,65280},	{11,23,65280},	{12,23,65280},	{13,23,65280},	{14,23,60672},	{15,23,14592},	{16,23,0},	{17,23,0},	{18,23,0},	{19,23,0},	{20,23,0},	{21,23,0},	{22,23,20992},	{23,23,64000},	{24,23,65280},	{25,23,65280},	{26,23,65280},	{27,23,65280},	{28,23,65280},	{29,23,38144},	{30,23,0},	{31,23,0},	{32,23,0},	{33,23,0},	{34,23,0},	{35,23,12288},	{36,23,62464},	{37,23,65280},	{38,23,65280},	{39,23,65280},	{40,23,65280},	{41,23,42752},	{42,23,0},	{43,23,0},	{44,23,0},	{45,23,0},	{46,23,4096},	{47,23,58368},	{48,23,65280},	{49,23,65280},	{50,23,65280},	{51,23,62720},	{52,23,7936},	{53,23,0},	{54,23,0},	{55,23,0},	{56,23,11520},	{57,23,64768},	{58,23,65280},	{59,23,65280},	{60,23,65280},	{61,23,21760},	{62,23,0},	{63,23,0},	{64,23,0},	{65,23,23296},	{66,23,65280},	{67,23,65280},	{68,23,65280},	{69,23,50688},
+	 {0,24,0},	{1,24,0},	{2,24,0},	{3,24,0},	{4,24,0},	{5,24,0},	{6,24,0},	{7,24,12544},	{8,24,57600},	{9,24,65280},	{10,24,65280},	{11,24,65280},	{12,24,65280},	{13,24,65280},	{14,24,65280},	{15,24,62464},	{16,24,18432},	{17,24,0},	{18,24,0},	{19,24,0},	{20,24,0},	{21,24,0},	{22,24,0},	{23,24,20992},	{24,24,64000},	{25,24,65280},	{26,24,65280},	{27,24,65280},	{28,24,65280},	{29,24,65280},	{30,24,30720},	{31,24,0},	{32,24,0},	{33,24,0},	{34,24,0},	{35,24,0},	{36,24,21248},	{37,24,65024},	{38,24,65280},	{39,24,65280},	{40,24,65280},	{41,24,65280},	{42,24,24576},	{43,24,0},	{44,24,0},	{45,24,0},	{46,24,0},	{47,24,19456},	{48,24,65280},	{49,24,65280},	{50,24,65280},	{51,24,65280},	{52,24,43520},	{53,24,0},	{54,24,0},	{55,24,0},	{56,24,0},	{57,24,41984},	{58,24,65280},	{59,24,65280},	{60,24,65280},	{61,24,53248},	{62,24,256},	{63,24,0},	{64,24,0},	{65,24,1536},	{66,24,59392},	{67,24,65280},	{68,24,65280},	{69,24,65280},
+	 {0,25,6912},	{1,25,0},	{2,25,0},	{3,25,0},	{4,25,0},	{5,25,0},	{6,25,0},	{7,25,0},	{8,25,6656},	{9,25,51200},	{10,25,65280},	{11,25,65280},	{12,25,65280},	{13,25,65280},	{14,25,65280},	{15,25,65280},	{16,25,63744},	{17,25,22784},	{18,25,0},	{19,25,0},	{20,25,0},	{21,25,0},	{22,25,0},	{23,25,0},	{24,25,20992},	{25,25,64000},	{26,25,65280},	{27,25,65280},	{28,25,65280},	{29,25,65280},	{30,25,65024},	{31,25,25344},	{32,25,0},	{33,25,0},	{34,25,0},	{35,25,0},	{36,25,0},	{37,25,33792},	{38,25,65280},	{39,25,65280},	{40,25,65280},	{41,25,65280},	{42,25,62464},	{43,25,10752},	{44,25,0},	{45,25,0},	{46,25,0},	{47,25,0},	{48,25,41728},	{49,25,65280},	{50,25,65280},	{51,25,65280},	{52,25,65280},	{53,25,18432},	{54,25,0},	{55,25,0},	{56,25,0},	{57,25,8192},	{58,25,63488},	{59,25,65280},	{60,25,65280},	{61,25,65280},	{62,25,18176},	{63,25,0},	{64,25,0},	{65,25,0},	{66,25,34304},	{67,25,65280},	{68,25,65280},	{69,25,65280},
+	 {0,26,60160},	{1,26,18944},	{2,26,0},	{3,26,0},	{4,26,0},	{5,26,0},	{6,26,0},	{7,26,0},	{8,26,0},	{9,26,1792},	{10,26,40960},	{11,26,65280},	{12,26,65280},	{13,26,65280},	{14,26,65280},	{15,26,65280},	{16,26,65280},	{17,26,65024},	{18,26,29696},	{19,26,0},	{20,26,0},	{21,26,0},	{22,26,0},	{23,26,0},	{24,26,0},	{25,26,20992},	{26,26,64000},	{27,26,65280},	{28,26,65280},	{29,26,65280},	{30,26,65280},	{31,26,64512},	{32,26,20736},	{33,26,0},	{34,26,0},	{35,26,0},	{36,26,0},	{37,26,256},	{38,26,43520},	{39,26,65280},	{40,26,65280},	{41,26,65280},	{42,26,65280},	{43,26,54272},	{44,26,2560},	{45,26,0},	{46,26,0},	{47,26,0},	{48,26,4096},	{49,26,58112},	{50,26,65280},	{51,26,65280},	{52,26,65280},	{53,26,55808},	{54,26,1792},	{55,26,0},	{56,26,0},	{57,26,0},	{58,26,37376},	{59,26,65280},	{60,26,65280},	{61,26,65280},	{62,26,49152},	{63,26,0},	{64,26,0},	{65,26,0},	{66,26,7680},	{67,26,64512},	{68,26,65280},	{69,26,65280},
+	 {0,27,65280},	{1,27,65024},	{2,27,36864},	{3,27,1536},	{4,27,0},	{5,27,0},	{6,27,0},	{7,27,0},	{8,27,0},	{9,27,0},	{10,27,0},	{11,27,28160},	{12,27,64512},	{13,27,65280},	{14,27,65280},	{15,27,65280},	{16,27,65280},	{17,27,65280},	{18,27,65280},	{19,27,36864},	{20,27,256},	{21,27,0},	{22,27,0},	{23,27,0},	{24,27,0},	{25,27,0},	{26,27,20992},	{27,27,64000},	{28,27,65280},	{29,27,65280},	{30,27,65280},	{31,27,65280},	{32,27,62976},	{33,27,15360},	{34,27,0},	{35,27,0},	{36,27,0},	{37,27,0},	{38,27,3072},	{39,27,53760},	{40,27,65280},	{41,27,65280},	{42,27,65280},	{43,27,65280},	{44,27,39168},	{45,27,0},	{46,27,0},	{47,27,0},	{48,27,0},	{49,27,19456},	{50,27,65280},	{51,27,65280},	{52,27,65280},	{53,27,65280},	{54,27,30464},	{55,27,0},	{56,27,0},	{57,27,0},	{58,27,5376},	{59,27,61696},	{60,27,65280},	{61,27,65280},	{62,27,65280},	{63,27,15104},	{64,27,0},	{65,27,0},	{66,27,0},	{67,27,45568},	{68,27,65280},	{69,27,65280},
+	 {0,28,65280},	{1,28,65280},	{2,28,65280},	{3,28,51712},	{4,28,8704},	{5,28,0},	{6,28,0},	{7,28,0},	{8,28,0},	{9,28,0},	{10,28,0},	{11,28,0},	{12,28,18432},	{13,28,61184},	{14,28,65280},	{15,28,65280},	{16,28,65280},	{17,28,65280},	{18,28,65280},	{19,28,65280},	{20,28,41216},	{21,28,1280},	{22,28,0},	{23,28,0},	{24,28,0},	{25,28,0},	{26,28,0},	{27,28,20992},	{28,28,64000},	{29,28,65280},	{30,28,65280},	{31,28,65280},	{32,28,65280},	{33,28,61440},	{34,28,11776},	{35,28,0},	{36,28,0},	{37,28,0},	{38,28,0},	{39,28,8192},	{40,28,59904},	{41,28,65280},	{42,28,65280},	{43,28,65280},	{44,28,65280},	{45,28,23296},	{46,28,0},	{47,28,0},	{48,28,0},	{49,28,0},	{50,28,41472},	{51,28,65280},	{52,28,65280},	{53,28,65280},	{54,28,62720},	{55,28,7936},	{56,28,0},	{57,28,0},	{58,28,0},	{59,28,32768},	{60,28,65280},	{61,28,65280},	{62,28,65280},	{63,28,45824},	{64,28,0},	{65,28,0},	{66,28,0},	{67,28,18688},	{68,28,65280},	{69,28,65280},
+	 {0,29,65280},	{1,29,65280},	{2,29,65280},	{3,29,65280},	{4,29,61440},	{5,29,22016},	{6,29,0},	{7,29,0},	{8,29,0},	{9,29,0},	{10,29,0},	{11,29,0},	{12,29,0},	{13,29,9472},	{14,29,55040},	{15,29,65280},	{16,29,65280},	{17,29,65280},	{18,29,65280},	{19,29,65280},	{20,29,65280},	{21,29,45824},	{22,29,2560},	{23,29,0},	{24,29,0},	{25,29,0},	{26,29,0},	{27,29,0},	{28,29,20992},	{29,29,64000},	{30,29,65280},	{31,29,65280},	{32,29,65280},	{33,29,65280},	{34,29,58368},	{35,29,7936},	{36,29,0},	{37,29,0},	{38,29,0},	{39,29,0},	{40,29,15360},	{41,29,63744},	{42,29,65280},	{43,29,65280},	{44,29,65280},	{45,29,62208},	{46,29,9984},	{47,29,0},	{48,29,0},	{49,29,0},	{50,29,3840},	{51,29,58112},	{52,29,65280},	{53,29,65280},	{54,29,65280},	{55,29,43264},	{56,29,0},	{57,29,0},	{58,29,0},	{59,29,3072},	{60,29,59392},	{61,29,65280},	{62,29,65280},	{63,29,65024},	{64,29,12544},	{65,29,0},	{66,29,0},	{67,29,256},	{68,29,55808},	{69,29,65280},
+	 {0,30,65280},	{1,30,65280},	{2,30,65280},	{3,30,65280},	{4,30,65280},	{5,30,65280},	{6,30,39168},	{7,30,1792},	{8,30,0},	{9,30,0},	{10,30,0},	{11,30,0},	{12,30,0},	{13,30,0},	{14,30,4352},	{15,30,47616},	{16,30,65280},	{17,30,65280},	{18,30,65280},	{19,30,65280},	{20,30,65280},	{21,30,65280},	{22,30,51456},	{23,30,5120},	{24,30,0},	{25,30,0},	{26,30,0},	{27,30,0},	{28,30,0},	{29,30,20992},	{30,30,64000},	{31,30,65280},	{32,30,65280},	{33,30,65280},	{34,30,65280},	{35,30,54528},	{36,30,4608},	{37,30,0},	{38,30,0},	{39,30,0},	{40,30,0},	{41,30,27136},	{42,30,65280},	{43,30,65280},	{44,30,65280},	{45,30,65280},	{46,30,53504},	{47,30,2048},	{48,30,0},	{49,30,0},	{50,30,0},	{51,30,19200},	{52,30,65280},	{53,30,65280},	{54,30,65280},	{55,30,65280},	{56,30,18432},	{57,30,0},	{58,30,0},	{59,30,0},	{60,30,28416},	{61,30,65280},	{62,30,65280},	{63,30,65280},	{64,30,42240},	{65,30,0},	{66,30,0},	{67,30,0},	{68,30,29952},	{69,30,65280},
+	 {0,31,65280},	{1,31,65280},	{2,31,65280},	{3,31,65280},	{4,31,65280},	{5,31,65280},	{6,31,65280},	{7,31,52480},	{8,31,9216},	{9,31,0},	{10,31,0},	{11,31,0},	{12,31,0},	{13,31,0},	{14,31,0},	{15,31,768},	{16,31,34816},	{17,31,65280},	{18,31,65280},	{19,31,65280},	{20,31,65280},	{21,31,65280},	{22,31,65280},	{23,31,54784},	{24,31,7680},	{25,31,0},	{26,31,0},	{27,31,0},	{28,31,0},	{29,31,0},	{30,31,20992},	{31,31,64000},	{32,31,65280},	{33,31,65280},	{34,31,65280},	{35,31,65280},	{36,31,51456},	{37,31,2816},	{38,31,0},	{39,31,0},	{40,31,0},	{41,31,0},	{42,31,38656},	{43,31,65280},	{44,31,65280},	{45,31,65280},	{46,31,65280},	{47,31,36864},	{48,31,0},	{49,31,0},	{50,31,0},	{51,31,0},	{52,31,41216},	{53,31,65280},	{54,31,65280},	{55,31,65280},	{56,31,55808},	{57,31,1792},	{58,31,0},	{59,31,0},	{60,31,1536},	{61,31,56576},	{62,31,65280},	{63,31,65280},	{64,31,64512},	{65,31,9216},	{66,31,0},	{67,31,0},	{68,31,4352},	{69,31,62720},
+	 {0,32,58624},	{1,32,65280},	{2,32,65280},	{3,32,65280},	{4,32,65280},	{5,32,65280},	{6,32,65280},	{7,32,65280},	{8,32,61952},	{9,32,23040},	{10,32,0},	{11,32,0},	{12,32,0},	{13,32,0},	{14,32,0},	{15,32,0},	{16,32,0},	{17,32,23296},	{18,32,63232},	{19,32,65280},	{20,32,65280},	{21,32,65280},	{22,32,65280},	{23,32,65280},	{24,32,58624},	{25,32,11776},	{26,32,0},	{27,32,0},	{28,32,0},	{29,32,0},	{30,32,0},	{31,32,20992},	{32,32,64000},	{33,32,65280},	{34,32,65280},	{35,32,65280},	{36,32,65280},	{37,32,46080},	{38,32,1024},	{39,32,0},	{40,32,0},	{41,32,0},	{42,32,1280},	{43,32,48640},	{44,32,65280},	{45,32,65280},	{46,32,65280},	{47,32,65024},	{48,32,20736},	{49,32,0},	{50,32,0},	{51,32,0},	{52,32,3840},	{53,32,58112},	{54,32,65280},	{55,32,65280},	{56,32,65280},	{57,32,30208},	{58,32,0},	{59,32,0},	{60,32,0},	{61,32,23808},	{62,32,65280},	{63,32,65280},	{64,32,65280},	{65,32,38656},	{66,32,0},	{67,32,0},	{68,32,0},	{69,32,40704},
+	 {0,33,4352},	{1,33,41472},	{2,33,65280},	{3,33,65280},	{4,33,65280},	{5,33,65280},	{6,33,65280},	{7,33,65280},	{8,33,65280},	{9,33,65280},	{10,33,41216},	{11,33,2560},	{12,33,0},	{13,33,0},	{14,33,0},	{15,33,0},	{16,33,0},	{17,33,0},	{18,33,14848},	{19,33,59136},	{20,33,65280},	{21,33,65280},	{22,33,65280},	{23,33,65280},	{24,33,65280},	{25,33,60928},	{26,33,15360},	{27,33,0},	{28,33,0},	{29,33,0},	{30,33,0},	{31,33,0},	{32,33,20992},	{33,33,64000},	{34,33,65280},	{35,33,65280},	{36,33,65280},	{37,33,65280},	{38,33,41728},	{39,33,256},	{40,33,0},	{41,33,0},	{42,33,0},	{43,33,4864},	{44,33,56320},	{45,33,65280},	{46,33,65280},	{47,33,65280},	{48,33,61184},	{49,33,8192},	{50,33,0},	{51,33,0},	{52,33,0},	{53,33,19200},	{54,33,65280},	{55,33,65280},	{56,33,65280},	{57,33,62720},	{58,33,7936},	{59,33,0},	{60,33,0},	{61,33,512},	{62,33,52992},	{63,33,65280},	{64,33,65280},	{65,33,63488},	{66,33,6656},	{67,33,0},	{68,33,0},	{69,33,13824},
+	 {0,34,0},	{1,34,0},	{2,34,21760},	{3,34,59904},	{4,34,65280},	{5,34,65280},	{6,34,65280},	{7,34,65280},	{8,34,65280},	{9,34,65280},	{10,34,65280},	{11,34,54784},	{12,34,11520},	{13,34,0},	{14,34,0},	{15,34,0},	{16,34,0},	{17,34,0},	{18,34,0},	{19,34,6912},	{20,34,51968},	{21,34,65280},	{22,34,65280},	{23,34,65280},	{24,34,65280},	{25,34,65280},	{26,34,62720},	{27,34,19200},	{28,34,0},	{29,34,0},	{30,34,0},	{31,34,0},	{32,34,0},	{33,34,20992},	{34,34,64000},	{35,34,65280},	{36,34,65280},	{37,34,65280},	{38,34,65280},	{39,34,34560},	{40,34,0},	{41,34,0},	{42,34,0},	{43,34,0},	{44,34,10752},	{45,34,61696},	{46,34,65280},	{47,34,65280},	{48,34,65280},	{49,34,51456},	{50,34,1536},	{51,34,0},	{52,34,0},	{53,34,0},	{54,34,40960},	{55,34,65280},	{56,34,65280},	{57,34,65280},	{58,34,43264},	{59,34,0},	{60,34,0},	{61,34,0},	{62,34,19200},	{63,34,65280},	{64,34,65280},	{65,34,65280},	{66,34,35072},	{67,34,0},	{68,34,0},	{69,34,0},
+	 {0,35,0},	{1,35,0},	{2,35,0},	{3,35,5632},	{4,35,43776},	{5,35,65280},	{6,35,65280},	{7,35,65280},	{8,35,65280},	{9,35,65280},	{10,35,65280},	{11,35,65280},	{12,35,62976},	{13,35,28160},	{14,35,0},	{15,35,0},	{16,35,0},	{17,35,0},	{18,35,0},	{19,35,0},	{20,35,2048},	{21,35,41728},	{22,35,65280},	{23,35,65280},	{24,35,65280},	{25,35,65280},	{26,35,65280},	{27,35,64512},	{28,35,25856},	{29,35,0},	{30,35,0},	{31,35,0},	{32,35,0},	{33,35,0},	{34,35,20992},	{35,35,64000},	{36,35,65280},	{37,35,65280},	{38,35,65280},	{39,35,65280},	{40,35,29184},	{41,35,0},	{42,35,0},	{43,35,0},	{44,35,0},	{45,35,20480},	{46,35,64768},	{47,35,65280},	{48,35,65280},	{49,35,65280},	{50,35,34816},	{51,35,0},	{52,35,0},	{53,35,0},	{54,35,3840},	{55,35,57856},	{56,35,65280},	{57,35,65280},	{58,35,65280},	{59,35,18176},	{60,35,0},	{61,35,0},	{62,35,0},	{63,35,48640},	{64,35,65280},	{65,35,65280},	{66,35,61952},	{67,35,4352},	{68,35,0},	{69,35,0},
+	 {0,36,0},	{1,36,0},	{2,36,0},	{3,36,0},	{4,36,0},	{5,36,21760},	{6,36,59904},	{7,36,65280},	{8,36,65280},	{9,36,65280},	{10,36,65280},	{11,36,65280},	{12,36,65280},	{13,36,65280},	{14,36,41472},	{15,36,3072},	{16,36,0},	{17,36,0},	{18,36,0},	{19,36,0},	{20,36,0},	{21,36,256},	{22,36,30464},	{23,36,64768},	{24,36,65280},	{25,36,65280},	{26,36,65280},	{27,36,65280},	{28,36,65024},	{29,36,32512},	{30,36,0},	{31,36,0},	{32,36,0},	{33,36,0},	{34,36,0},	{35,36,20992},	{36,36,64000},	{37,36,65280},	{38,36,65280},	{39,36,65280},	{40,36,65024},	{41,36,24320},	{42,36,0},	{43,36,0},	{44,36,0},	{45,36,0},	{46,36,32000},	{47,36,65280},	{48,36,65280},	{49,36,65280},	{50,36,65024},	{51,36,19712},	{52,36,0},	{53,36,0},	{54,36,0},	{55,36,17664},	{56,36,65024},	{57,36,65280},	{58,36,65280},	{59,36,55552},	{60,36,1792},	{61,36,0},	{62,36,0},	{63,36,13824},	{64,36,65024},	{65,36,65280},	{66,36,65280},	{67,36,31488},	{68,36,0},	{69,36,0},
+	 {0,37,0},	{1,37,0},	{2,37,0},	{3,37,0},	{4,37,0},	{5,37,0},	{6,37,5632},	{7,37,43776},	{8,37,65280},	{9,37,65280},	{10,37,65280},	{11,37,65280},	{12,37,65280},	{13,37,65280},	{14,37,65280},	{15,37,55552},	{16,37,12288},	{17,37,0},	{18,37,0},	{19,37,0},	{20,37,0},	{21,37,0},	{22,37,0},	{23,37,19200},	{24,37,61696},	{25,37,65280},	{26,37,65280},	{27,37,65280},	{28,37,65280},	{29,37,65280},	{30,37,37376},	{31,37,512},	{32,37,0},	{33,37,0},	{34,37,0},	{35,37,0},	{36,37,20992},	{37,37,64000},	{38,37,65280},	{39,37,65280},	{40,37,65280},	{41,37,64000},	{42,37,18432},	{43,37,0},	{44,37,0},	{45,37,0},	{46,37,256},	{47,37,42752},	{48,37,65280},	{49,37,65280},	{50,37,65280},	{51,37,59904},	{52,37,6656},	{53,37,0},	{54,37,0},	{55,37,0},	{56,37,40704},	{57,37,65280},	{58,37,65280},	{59,37,65280},	{60,37,29952},	{61,37,0},	{62,37,0},	{63,37,0},	{64,37,45312},	{65,37,65280},	{66,37,65280},	{67,37,60416},	{68,37,2816},	{69,37,0},
+	 {0,38,0},	{1,38,0},	{2,38,0},	{3,38,0},	{4,38,0},	{5,38,0},	{6,38,0},	{7,38,0},	{8,38,21760},	{9,38,60160},	{10,38,65280},	{11,38,65280},	{12,38,65280},	{13,38,65280},	{14,38,65280},	{15,38,65280},	{16,38,63232},	{17,38,28160},	{18,38,0},	{19,38,0},	{20,38,0},	{21,38,0},	{22,38,0},	{23,38,0},	{24,38,11520},	{25,38,56832},	{26,38,65280},	{27,38,65280},	{28,38,65280},	{29,38,65280},	{30,38,65280},	{31,38,42240},	{32,38,1536},	{33,38,0},	{34,38,0},	{35,38,0},	{36,38,0},	{37,38,20992},	{38,38,64000},	{39,38,65280},	{40,38,65280},	{41,38,65280},	{42,38,62720},	{43,38,14592},	{44,38,0},	{45,38,0},	{46,38,0},	{47,38,2304},	{48,38,51712},	{49,38,65280},	{50,38,65280},	{51,38,65280},	{52,38,49152},	{53,38,768},	{54,38,0},	{55,38,0},	{56,38,3840},	{57,38,57856},	{58,38,65280},	{59,38,65280},	{60,38,62720},	{61,38,7936},	{62,38,0},	{63,38,0},	{64,38,10240},	{65,38,64256},	{66,38,65280},	{67,38,65280},	{68,38,28160},	{69,38,0},
+	 {0,39,28160},	{1,39,1024},	{2,39,0},	{3,39,0},	{4,39,0},	{5,39,0},	{6,39,0},	{7,39,0},	{8,39,0},	{9,39,5632},	{10,39,44032},	{11,39,65280},	{12,39,65280},	{13,39,65280},	{14,39,65280},	{15,39,65280},	{16,39,65280},	{17,39,65280},	{18,39,44544},	{19,39,4352},	{20,39,0},	{21,39,0},	{22,39,0},	{23,39,0},	{24,39,0},	{25,39,4864},	{26,39,48384},	{27,39,65280},	{28,39,65280},	{29,39,65280},	{30,39,65280},	{31,39,65280},	{32,39,48384},	{33,39,3584},	{34,39,0},	{35,39,0},	{36,39,0},	{37,39,0},	{38,39,20992},	{39,39,64000},	{40,39,65280},	{41,39,65280},	{42,39,65280},	{43,39,60160},	{44,39,9984},	{45,39,0},	{46,39,0},	{47,39,0},	{48,39,6656},	{49,39,58624},	{50,39,65280},	{51,39,65280},	{52,39,65280},	{53,39,32512},	{54,39,0},	{55,39,0},	{56,39,0},	{57,39,17664},	{58,39,65024},	{59,39,65280},	{60,39,65280},	{61,39,43008},	{62,39,0},	{63,39,0},	{64,39,0},	{65,39,40704},	{66,39,65280},	{67,39,65280},	{68,39,58112},	{69,39,1536},
+	 {0,40,65280},	{1,40,53248},	{2,40,15360},	{3,40,0},	{4,40,0},	{5,40,0},	{6,40,0},	{7,40,0},	{8,40,0},	{9,40,0},	{10,40,0},	{11,40,21760},	{12,40,60160},	{13,40,65280},	{14,40,65280},	{15,40,65280},	{16,40,65280},	{17,40,65280},	{18,40,65280},	{19,40,57344},	{20,40,14592},	{21,40,0},	{22,40,0},	{23,40,0},	{24,40,0},	{25,40,0},	{26,40,1024},	{27,40,37120},	{28,40,65280},	{29,40,65280},	{30,40,65280},	{31,40,65280},	{32,40,65280},	{33,40,51968},	{34,40,5632},	{35,40,0},	{36,40,0},	{37,40,0},	{38,40,0},	{39,40,20992},	{40,40,64000},	{41,40,65280},	{42,40,65280},	{43,40,65280},	{44,40,57856},	{45,40,7424},	{46,40,0},	{47,40,0},	{48,40,0},	{49,40,14848},	{50,40,63488},	{51,40,65280},	{52,40,65280},	{53,40,64768},	{54,40,17408},	{55,40,0},	{56,40,0},	{57,40,0},	{58,40,40192},	{59,40,65280},	{60,40,65280},	{61,40,65280},	{62,40,16896},	{63,40,0},	{64,40,0},	{65,40,6912},	{66,40,62976},	{67,40,65280},	{68,40,65280},	{69,40,24576},
+	 {0,41,65280},	{1,41,65280},	{2,41,65024},	{3,41,41216},	{4,41,5888},	{5,41,0},	{6,41,0},	{7,41,0},	{8,41,0},	{9,41,0},	{10,41,0},	{11,41,0},	{12,41,5632},	{13,41,44288},	{14,41,65280},	{15,41,65280},	{16,41,65280},	{17,41,65280},	{18,41,65280},	{19,41,65280},	{20,41,64256},	{21,41,32512},	{22,41,512},	{23,41,0},	{24,41,0},	{25,41,0},	{26,41,0},	{27,41,0},	{28,41,26112},	{29,41,64000},	{30,41,65280},	{31,41,65280},	{32,41,65280},	{33,41,65280},	{34,41,56576},	{35,41,9216},	{36,41,0},	{37,41,0},	{38,41,0},	{39,41,0},	{40,41,20992},	{41,41,64000},	{42,41,65280},	{43,41,65280},	{44,41,65280},	{45,41,54016},	{46,41,4352},	{47,41,0},	{48,41,0},	{49,41,0},	{50,41,24320},	{51,41,65280},	{52,41,65280},	{53,41,65280},	{54,41,59392},	{55,41,6144},	{56,41,0},	{57,41,0},	{58,41,3584},	{59,41,57600},	{60,41,65280},	{61,41,65280},	{62,41,54784},	{63,41,1280},	{64,41,0},	{65,41,0},	{66,41,36096},	{67,41,65280},	{68,41,65280},	{69,41,55296},
+	 {0,42,65280},	{1,42,65280},	{2,42,65280},	{3,42,65280},	{4,42,61440},	{5,42,28160},	{6,42,1024},	{7,42,0},	{8,42,0},	{9,42,0},	{10,42,0},	{11,42,0},	{12,42,0},	{13,42,0},	{14,42,21760},	{15,42,60160},	{16,42,65280},	{17,42,65280},	{18,42,65280},	{19,42,65280},	{20,42,65280},	{21,42,65280},	{22,42,45568},	{23,42,4864},	{24,42,0},	{25,42,0},	{26,42,0},	{27,42,0},	{28,42,0},	{29,42,15360},	{30,42,59648},	{31,42,65280},	{32,42,65280},	{33,42,65280},	{34,42,65280},	{35,42,59136},	{36,42,12288},	{37,42,0},	{38,42,0},	{39,42,0},	{40,42,0},	{41,42,20992},	{42,42,64000},	{43,42,65280},	{44,42,65280},	{45,42,65280},	{46,42,49152},	{47,42,2048},	{48,42,0},	{49,42,0},	{50,42,0},	{51,42,36864},	{52,42,65280},	{53,42,65280},	{54,42,65280},	{55,42,47104},	{56,42,512},	{57,42,0},	{58,42,0},	{59,42,17408},	{60,42,65024},	{61,42,65280},	{62,42,65280},	{63,42,29696},	{64,42,0},	{65,42,0},	{66,42,4352},	{67,42,60928},	{68,42,65280},	{69,42,65280},
+	 {0,43,65280},	{1,43,65280},	{2,43,65280},	{3,43,65280},	{4,43,65280},	{5,43,65280},	{6,43,53504},	{7,43,15360},	{8,43,0},	{9,43,0},	{10,43,0},	{11,43,0},	{12,43,0},	{13,43,0},	{14,43,0},	{15,43,5888},	{16,43,44288},	{17,43,65280},	{18,43,65280},	{19,43,65280},	{20,43,65280},	{21,43,65280},	{22,43,65280},	{23,43,58112},	{24,43,15616},	{25,43,0},	{26,43,0},	{27,43,0},	{28,43,0},	{29,43,0},	{30,43,7424},	{31,43,52480},	{32,43,65280},	{33,43,65280},	{34,43,65280},	{35,43,65280},	{36,43,62208},	{37,43,17664},	{38,43,0},	{39,43,0},	{40,43,0},	{41,43,0},	{42,43,20992},	{43,43,64000},	{44,43,65280},	{45,43,65280},	{46,43,65280},	{47,43,45312},	{48,43,1024},	{49,43,0},	{50,43,0},	{51,43,768},	{52,43,46592},	{53,43,65280},	{54,43,65280},	{55,43,65280},	{56,43,30720},	{57,43,0},	{58,43,0},	{59,43,0},	{60,43,39936},	{61,43,65280},	{62,43,65280},	{63,43,61952},	{64,43,6912},	{65,43,0},	{66,43,0},	{67,43,31744},	{68,43,65280},	{69,43,65280},
+	 {0,44,65280},	{1,44,65280},	{2,44,65280},	{3,44,65280},	{4,44,65280},	{5,44,65280},	{6,44,65280},	{7,44,65024},	{8,44,43520},	{9,44,7168},	{10,44,0},	{11,44,0},	{12,44,0},	{13,44,0},	{14,44,0},	{15,44,0},	{16,44,0},	{17,44,21760},	{18,44,60160},	{19,44,65280},	{20,44,65280},	{21,44,65280},	{22,44,65280},	{23,44,65280},	{24,44,64256},	{25,44,32512},	{26,44,512},	{27,44,0},	{28,44,0},	{29,44,0},	{30,44,0},	{31,44,3072},	{32,44,44544},	{33,44,65280},	{34,44,65280},	{35,44,65280},	{36,44,65280},	{37,44,63488},	{38,44,22016},	{39,44,0},	{40,44,0},	{41,44,0},	{42,44,0},	{43,44,20992},	{44,44,64000},	{45,44,65280},	{46,44,65280},	{47,44,65280},	{48,44,39168},	{49,44,0},	{50,44,0},	{51,44,0},	{52,44,4352},	{53,44,55808},	{54,44,65280},	{55,44,65280},	{56,44,64256},	{57,44,15104},	{58,44,0},	{59,44,0},	{60,44,3584},	{61,44,57600},	{62,44,65280},	{63,44,65280},	{64,44,42752},	{65,44,0},	{66,44,0},	{67,44,2816},	{68,44,59136},	{69,44,65280},
+	 {0,45,48896},	{1,45,65280},	{2,45,65280},	{3,45,65280},	{4,45,65280},	{5,45,65280},	{6,45,65280},	{7,45,65280},	{8,45,65280},	{9,45,62464},	{10,45,32512},	{11,45,1536},	{12,45,0},	{13,45,0},	{14,45,0},	{15,45,0},	{16,45,0},	{17,45,0},	{18,45,5888},	{19,45,44544},	{20,45,65280},	{21,45,65280},	{22,45,65280},	{23,45,65280},	{24,45,65280},	{25,45,65280},	{26,45,48384},	{27,45,6400},	{28,45,0},	{29,45,0},	{30,45,0},	{31,45,0},	{32,45,256},	{33,45,30464},	{34,45,65024},	{35,45,65280},	{36,45,65280},	{37,45,65280},	{38,45,64512},	{39,45,26624},	{40,45,0},	{41,45,0},	{42,45,0},	{43,45,0},	{44,45,20992},	{45,45,64000},	{46,45,65280},	{47,45,65280},	{48,45,65280},	{49,45,32768},	{50,45,0},	{51,45,0},	{52,45,0},	{53,45,9984},	{54,45,61184},	{55,45,65280},	{56,45,65280},	{57,45,58112},	{58,45,4864},	{59,45,0},	{60,45,0},	{61,45,17152},	{62,45,65024},	{63,45,65280},	{64,45,65280},	{65,45,16896},	{66,45,0},	{67,45,0},	{68,45,27136},	{69,45,65280},
+	 {0,46,0},	{1,46,17408},	{2,46,52992},	{3,46,65280},	{4,46,65280},	{5,46,65280},	{6,46,65280},	{7,46,65280},	{8,46,65280},	{9,46,65280},	{10,46,65280},	{11,46,55040},	{12,46,17408},	{13,46,0},	{14,46,0},	{15,46,0},	{16,46,0},	{17,46,0},	{18,46,0},	{19,46,0},	{20,46,21760},	{21,46,60416},	{22,46,65280},	{23,46,65280},	{24,46,65280},	{25,46,65280},	{26,46,65280},	{27,46,59648},	{28,46,18176},	{29,46,0},	{30,46,0},	{31,46,0},	{32,46,0},	{33,46,0},	{34,46,21760},	{35,46,62720},	{36,46,65280},	{37,46,65280},	{38,46,65280},	{39,46,65280},	{40,46,34816},	{41,46,0},	{42,46,0},	{43,46,0},	{44,46,0},	{45,46,20992},	{46,46,64000},	{47,46,65280},	{48,46,65280},	{49,46,65280},	{50,46,28160},	{51,46,0},	{52,46,0},	{53,46,0},	{54,46,18176},	{55,46,64512},	{56,46,65280},	{57,46,65280},	{58,46,46080},	{59,46,256},	{60,46,0},	{61,46,0},	{62,46,39680},	{63,46,65280},	{64,46,65280},	{65,46,54528},	{66,46,1280},	{67,46,0},	{68,46,1280},	{69,46,56064},
+	 {0,47,0},	{1,47,0},	{2,47,512},	{3,47,21760},	{4,47,56320},	{5,47,65280},	{6,47,65280},	{7,47,65280},	{8,47,65280},	{9,47,65280},	{10,47,65280},	{11,47,65280},	{12,47,65280},	{13,47,45568},	{14,47,7168},	{15,47,0},	{16,47,0},	{17,47,0},	{18,47,0},	{19,47,0},	{20,47,0},	{21,47,5888},	{22,47,44544},	{23,47,65280},	{24,47,65280},	{25,47,65280},	{26,47,65280},	{27,47,65280},	{28,47,65024},	{29,47,36864},	{30,47,1280},	{31,47,0},	{32,47,0},	{33,47,0},	{34,47,0},	{35,47,12032},	{36,47,57344},	{37,47,65280},	{38,47,65280},	{39,47,65280},	{40,47,65280},	{41,47,40448},	{42,47,1024},	{43,47,0},	{44,47,0},	{45,47,0},	{46,47,20992},	{47,47,64000},	{48,47,65280},	{49,47,65280},	{50,47,64768},	{51,47,21760},	{52,47,0},	{53,47,0},	{54,47,0},	{55,47,30208},	{56,47,65280},	{57,47,65280},	{58,47,65280},	{59,47,28416},	{60,47,0},	{61,47,0},	{62,47,3584},	{63,47,57600},	{64,47,65280},	{65,47,65280},	{66,47,29696},	{67,47,0},	{68,47,0},	{69,47,22528},
+	 {0,48,0},	{1,48,0},	{2,48,0},	{3,48,0},	{4,48,1280},	{5,48,26112},	{6,48,59392},	{7,48,65280},	{8,48,65280},	{9,48,65280},	{10,48,65280},	{11,48,65280},	{12,48,65280},	{13,48,65280},	{14,48,62464},	{15,48,32512},	{16,48,1536},	{17,48,0},	{18,48,0},	{19,48,0},	{20,48,0},	{21,48,0},	{22,48,0},	{23,48,21760},	{24,48,60416},	{25,48,65280},	{26,48,65280},	{27,48,65280},	{28,48,65280},	{29,48,65280},	{30,48,49408},	{31,48,6912},	{32,48,0},	{33,48,0},	{34,48,0},	{35,48,0},	{36,48,5120},	{37,48,49152},	{38,48,65280},	{39,48,65280},	{40,48,65280},	{41,48,65280},	{42,48,44800},	{43,48,2048},	{44,48,0},	{45,48,0},	{46,48,0},	{47,48,20992},	{48,48,64000},	{49,48,65280},	{50,48,65280},	{51,48,63744},	{52,48,17664},	{53,48,0},	{54,48,0},	{55,48,0},	{56,48,40192},	{57,48,65280},	{58,48,65280},	{59,48,64000},	{60,48,14336},	{61,48,0},	{62,48,0},	{63,48,17152},	{64,48,65024},	{65,48,65280},	{66,48,61952},	{67,48,6912},	{68,48,0},	{69,48,256},
+	 {0,49,0},	{1,49,0},	{2,49,0},	{3,49,0},	{4,49,0},	{5,49,0},	{6,49,2816},	{7,49,30464},	{8,49,61696},	{9,49,65280},	{10,49,65280},	{11,49,65280},	{12,49,65280},	{13,49,65280},	{14,49,65280},	{15,49,65280},	{16,49,55296},	{17,49,17664},	{18,49,0},	{19,49,0},	{20,49,0},	{21,49,0},	{22,49,0},	{23,49,0},	{24,49,6144},	{25,49,44800},	{26,49,65280},	{27,49,65280},	{28,49,65280},	{29,49,65280},	{30,49,65280},	{31,49,60160},	{32,49,19200},	{33,49,0},	{34,49,0},	{35,49,0},	{36,49,0},	{37,49,1792},	{38,49,40192},	{39,49,65280},	{40,49,65280},	{41,49,65280},	{42,49,65280},	{43,49,48896},	{44,49,3840},	{45,49,0},	{46,49,0},	{47,49,0},	{48,49,20992},	{49,49,64000},	{50,49,65280},	{51,49,65280},	{52,49,61696},	{53,49,12544},	{54,49,0},	{55,49,0},	{56,49,2048},	{57,49,51200},	{58,49,65280},	{59,49,65280},	{60,49,56320},	{61,49,3840},	{62,49,0},	{63,49,0},	{64,49,39424},	{65,49,65280},	{66,49,65280},	{67,49,42496},	{68,49,0},	{69,49,0},
+	 {0,50,0},	{1,50,0},	{2,50,0},	{3,50,0},	{4,50,0},	{5,50,0},	{6,50,0},	{7,50,0},	{8,50,5120},	{9,50,34816},	{10,50,63488},	{11,50,65280},	{12,50,65280},	{13,50,65280},	{14,50,65280},	{15,50,65280},	{16,50,65280},	{17,50,65280},	{18,50,45568},	{19,50,7424},	{20,50,0},	{21,50,0},	{22,50,0},	{23,50,0},	{24,50,0},	{25,50,0},	{26,50,21760},	{27,50,60416},	{28,50,65280},	{29,50,65280},	{30,50,65280},	{31,50,65280},	{32,50,65024},	{33,50,36864},	{34,50,1536},	{35,50,0},	{36,50,0},	{37,50,0},	{38,50,0},	{39,50,26112},	{40,50,64000},	{41,50,65280},	{42,50,65280},	{43,50,65280},	{44,50,54016},	{45,50,6912},	{46,50,0},	{47,50,0},	{48,50,0},	{49,50,20992},	{50,50,64000},	{51,50,65280},	{52,50,65280},	{53,50,59904},	{54,50,9472},	{55,50,0},	{56,50,0},	{57,50,6144},	{58,50,58112},	{59,50,65280},	{60,50,65280},	{61,50,43520},	{62,50,0},	{63,50,0},	{64,50,2816},	{65,50,56576},	{66,50,65280},	{67,50,65280},	{68,50,16896},	{69,50,0},
+	 {0,51,23808},	{1,51,1024},	{2,51,0},	{3,51,0},	{4,51,0},	{5,51,0},	{6,51,0},	{7,51,0},	{8,51,0},	{9,51,0},	{10,51,7680},	{11,51,39168},	{12,51,64512},	{13,51,65280},	{14,51,65280},	{15,51,65280},	{16,51,65280},	{17,51,65280},	{18,51,65280},	{19,51,62464},	{20,51,32512},	{21,51,1536},	{22,51,0},	{23,51,0},	{24,51,0},	{25,51,0},	{26,51,0},	{27,51,6144},	{28,51,44800},	{29,51,65280},	{30,51,65280},	{31,51,65280},	{32,51,65280},	{33,51,65280},	{34,51,51968},	{35,51,8960},	{36,51,0},	{37,51,0},	{38,51,0},	{39,51,0},	{40,51,17920},	{41,51,60928},	{42,51,65280},	{43,51,65280},	{44,51,65280},	{45,51,57088},	{46,51,9728},	{47,51,0},	{48,51,0},	{49,51,0},	{50,51,20992},	{51,51,64000},	{52,51,65280},	{53,51,65280},	{54,51,56320},	{55,51,5888},	{56,51,0},	{57,51,0},	{58,51,12800},	{59,51,62720},	{60,51,65280},	{61,51,65280},	{62,51,26368},	{63,51,0},	{64,51,0},	{65,51,16896},	{66,51,65024},	{67,51,65280},	{68,51,54528},	{69,51,1280},
+	 {0,52,65280},	{1,52,57088},	{2,52,28160},	{3,52,2304},	{4,52,0},	{5,52,0},	{6,52,0},	{7,52,0},	{8,52,0},	{9,52,0},	{10,52,0},	{11,52,0},	{12,52,11008},	{13,52,43520},	{14,52,65280},	{15,52,65280},	{16,52,65280},	{17,52,65280},	{18,52,65280},	{19,52,65280},	{20,52,65280},	{21,52,55296},	{22,52,17664},	{23,52,0},	{24,52,0},	{25,52,0},	{26,52,0},	{27,52,0},	{28,52,0},	{29,52,21760},	{30,52,60672},	{31,52,65280},	{32,52,65280},	{33,52,65280},	{34,52,65280},	{35,52,61696},	{36,52,22272},	{37,52,0},	{38,52,0},	{39,52,0},	{40,52,0},	{41,52,9216},	{42,52,54528},	{43,52,65280},	{44,52,65280},	{45,52,65280},	{46,52,60416},	{47,52,14336},	{48,52,0},	{49,52,0},	{50,52,0},	{51,52,20992},	{52,52,64000},	{53,52,65280},	{54,52,65280},	{55,52,52224},	{56,52,3328},	{57,52,0},	{58,52,0},	{59,52,23552},	{60,52,65280},	{61,52,65280},	{62,52,63232},	{63,52,12288},	{64,52,0},	{65,52,0},	{66,52,39168},	{67,52,65280},	{68,52,65280},	{69,52,29440},
+	 {0,53,65280},	{1,53,65280},	{2,53,65280},	{3,53,59648},	{4,53,32512},	{5,53,4096},	{6,53,0},	{7,53,0},	{8,53,0},	{9,53,0},	{10,53,0},	{11,53,0},	{12,53,0},	{13,53,0},	{14,53,14592},	{15,53,49408},	{16,53,65280},	{17,53,65280},	{18,53,65280},	{19,53,65280},	{20,53,65280},	{21,53,65280},	{22,53,65280},	{23,53,45568},	{24,53,7424},	{25,53,0},	{26,53,0},	{27,53,0},	{28,53,0},	{29,53,0},	{30,53,6144},	{31,53,45056},	{32,53,65280},	{33,53,65280},	{34,53,65280},	{35,53,65280},	{36,53,65280},	{37,53,41216},	{38,53,2304},	{39,53,0},	{40,53,0},	{41,53,0},	{42,53,3328},	{43,53,45312},	{44,53,65280},	{45,53,65280},	{46,53,65280},	{47,53,62464},	{48,53,18432},	{49,53,0},	{50,53,0},	{51,53,0},	{52,53,20992},	{53,53,64000},	{54,53,65280},	{55,53,65280},	{56,53,48640},	{57,53,1792},	{58,53,0},	{59,53,0},	{60,53,35072},	{61,53,65280},	{62,53,65280},	{63,53,55808},	{64,53,3328},	{65,53,0},	{66,53,2816},	{67,53,56576},	{68,53,65280},	{69,53,61952},
+	 {0,54,65280},	{1,54,65280},	{2,54,65280},	{3,54,65280},	{4,54,65280},	{5,54,61952},	{6,54,36864},	{7,54,6400},	{8,54,0},	{9,54,0},	{10,54,0},	{11,54,0},	{12,54,0},	{13,54,0},	{14,54,0},	{15,54,0},	{16,54,17408},	{17,54,53504},	{18,54,65280},	{19,54,65280},	{20,54,65280},	{21,54,65280},	{22,54,65280},	{23,54,65280},	{24,54,62464},	{25,54,32512},	{26,54,1536},	{27,54,0},	{28,54,0},	{29,54,0},	{30,54,0},	{31,54,0},	{32,54,21760},	{33,54,60672},	{34,54,65280},	{35,54,65280},	{36,54,65280},	{37,54,65280},	{38,54,52736},	{39,54,9472},	{40,54,0},	{41,54,0},	{42,54,0},	{43,54,768},	{44,54,34816},	{45,54,65280},	{46,54,65280},	{47,54,65280},	{48,54,63744},	{49,54,22784},	{50,54,0},	{51,54,0},	{52,54,0},	{53,54,20992},	{54,54,64000},	{55,54,65280},	{56,54,65280},	{57,54,42752},	{58,54,512},	{59,54,0},	{60,54,512},	{61,54,45824},	{62,54,65280},	{63,54,65280},	{64,54,40704},	{65,54,0},	{66,54,0},	{67,54,16896},	{68,54,65024},	{69,54,65280},
+	 {0,55,65280},	{1,55,65280},	{2,55,65280},	{3,55,65280},	{4,55,65280},	{5,55,65280},	{6,55,65280},	{7,55,63488},	{8,55,39168},	{9,55,7680},	{10,55,0},	{11,55,0},	{12,55,0},	{13,55,0},	{14,55,0},	{15,55,0},	{16,55,0},	{17,55,512},	{18,55,21760},	{19,55,56832},	{20,55,65280},	{21,55,65280},	{22,55,65280},	{23,55,65280},	{24,55,65280},	{25,55,65280},	{26,55,55296},	{27,55,17664},	{28,55,0},	{29,55,0},	{30,55,0},	{31,55,0},	{32,55,0},	{33,55,6144},	{34,55,45312},	{35,55,65280},	{36,55,65280},	{37,55,65280},	{38,55,65280},	{39,55,61952},	{40,55,23296},	{41,55,0},	{42,55,0},	{43,55,0},	{44,55,0},	{45,55,22528},	{46,55,62976},	{47,55,65280},	{48,55,65280},	{49,55,65024},	{50,55,29696},	{51,55,0},	{52,55,0},	{53,55,0},	{54,55,20992},	{55,55,64000},	{56,55,65280},	{57,55,65280},	{58,55,38144},	{59,55,0},	{60,55,0},	{61,55,3328},	{62,55,54272},	{63,55,65280},	{64,55,65280},	{65,55,24064},	{66,55,0},	{67,55,0},	{68,55,38912},	{69,55,65280},
+	 {0,56,65280},	{1,56,65280},	{2,56,65280},	{3,56,65280},	{4,56,65280},	{5,56,65280},	{6,56,65280},	{7,56,65280},	{8,56,65280},	{9,56,64000},	{10,56,41216},	{11,56,10752},	{12,56,0},	{13,56,0},	{14,56,0},	{15,56,0},	{16,56,0},	{17,56,0},	{18,56,0},	{19,56,1536},	{20,56,26112},	{21,56,59648},	{22,56,65280},	{23,56,65280},	{24,56,65280},	{25,56,65280},	{26,56,65280},	{27,56,65280},	{28,56,45568},	{29,56,7424},	{30,56,0},	{31,56,0},	{32,56,0},	{33,56,0},	{34,56,0},	{35,56,21760},	{36,56,60672},	{37,56,65280},	{38,56,65280},	{39,56,65280},	{40,56,65280},	{41,56,41216},	{42,56,2816},	{43,56,0},	{44,56,0},	{45,56,0},	{46,56,12544},	{47,56,57856},	{48,56,65280},	{49,56,65280},	{50,56,65280},	{51,56,36864},	{52,56,256},	{53,56,0},	{54,56,0},	{55,56,20992},	{56,56,64000},	{57,56,65280},	{58,56,65280},	{59,56,30976},	{60,56,0},	{61,56,0},	{62,56,8448},	{63,56,60160},	{64,56,65280},	{65,56,62464},	{66,56,10496},	{67,56,0},	{68,56,2816},	{69,56,56320},
+	 {0,57,13056},	{1,57,41216},	{2,57,64000},	{3,57,65280},	{4,57,65280},	{5,57,65280},	{6,57,65280},	{7,57,65280},	{8,57,65280},	{9,57,65280},	{10,57,65280},	{11,57,64768},	{12,57,45568},	{13,57,14080},	{14,57,0},	{15,57,0},	{16,57,0},	{17,57,0},	{18,57,0},	{19,57,0},	{20,57,0},	{21,57,3072},	{22,57,30464},	{23,57,61952},	{24,57,65280},	{25,57,65280},	{26,57,65280},	{27,57,65280},	{28,57,65280},	{29,57,62464},	{30,57,32512},	{31,57,1536},	{32,57,0},	{33,57,0},	{34,57,0},	{35,57,0},	{36,57,6400},	{37,57,45312},	{38,57,65280},	{39,57,65280},	{40,57,65280},	{41,57,65280},	{42,57,55040},	{43,57,11776},	{44,57,0},	{45,57,0},	{46,57,0},	{47,57,6656},	{48,57,51456},	{49,57,65280},	{50,57,65280},	{51,57,65280},	{52,57,41216},	{53,57,1280},	{54,57,0},	{55,57,0},	{56,57,20992},	{57,57,64000},	{58,57,65280},	{59,57,65024},	{60,57,25344},	{61,57,0},	{62,57,0},	{63,57,17408},	{64,57,64256},	{65,57,65280},	{66,57,54016},	{67,57,2304},	{68,57,0},	{69,57,16896},
+	 {0,58,0},	{1,58,0},	{2,58,6144},	{3,58,30464},	{4,58,57600},	{5,58,65280},	{6,58,65280},	{7,58,65280},	{8,58,65280},	{9,58,65280},	{10,58,65280},	{11,58,65280},	{12,58,65280},	{13,58,65280},	{14,58,49920},	{15,58,19456},	{16,58,0},	{17,58,0},	{18,58,0},	{19,58,0},	{20,58,0},	{21,58,0},	{22,58,0},	{23,58,5376},	{24,58,34816},	{25,58,63488},	{26,58,65280},	{27,58,65280},	{28,58,65280},	{29,58,65280},	{30,58,65280},	{31,58,55552},	{32,58,17920},	{33,58,0},	{34,58,0},	{35,58,0},	{36,58,0},	{37,58,0},	{38,58,21760},	{39,58,60672},	{40,58,65280},	{41,58,65280},	{42,58,65280},	{43,58,63232},	{44,58,28160},	{45,58,0},	{46,58,0},	{47,58,0},	{48,58,1792},	{49,58,40960},	{50,58,65280},	{51,58,65280},	{52,58,65280},	{53,58,45824},	{54,58,2560},	{55,58,0},	{56,58,0},	{57,58,20992},	{58,58,64000},	{59,58,65280},	{60,58,64512},	{61,58,20992},	{62,58,0},	{63,58,0},	{64,58,28416},	{65,58,65280},	{66,58,65280},	{67,58,38656},	{68,58,0},	{69,58,0},
+	 {0,59,0},	{1,59,0},	{2,59,0},	{3,59,0},	{4,59,512},	{5,59,19456},	{6,59,47872},	{7,59,65024},	{8,59,65280},	{9,59,65280},	{10,59,65280},	{11,59,65280},	{12,59,65280},	{13,59,65280},	{14,59,65280},	{15,59,65280},	{16,59,52736},	{17,59,23808},	{18,59,768},	{19,59,0},	{20,59,0},	{21,59,0},	{22,59,0},	{23,59,0},	{24,59,0},	{25,59,7936},	{26,59,39168},	{27,59,64768},	{28,59,65280},	{29,59,65280},	{30,59,65280},	{31,59,65280},	{32,59,65280},	{33,59,45568},	{34,59,7680},	{35,59,0},	{36,59,0},	{37,59,0},	{38,59,0},	{39,59,6400},	{40,59,45568},	{41,59,65280},	{42,59,65280},	{43,59,65280},	{44,59,65280},	{45,59,44032},	{46,59,4096},	{47,59,0},	{48,59,0},	{49,59,0},	{50,59,28160},	{51,59,64768},	{52,59,65280},	{53,59,65280},	{54,59,51200},	{55,59,5120},	{56,59,0},	{57,59,0},	{58,59,20992},	{59,59,64000},	{60,59,65280},	{61,59,62976},	{62,59,15360},	{63,59,0},	{64,59,0},	{65,59,39168},	{66,59,65280},	{67,59,65280},	{68,59,23040},	{69,59,0},
+	 {0,60,0},	{1,60,0},	{2,60,0},	{3,60,0},	{4,60,0},	{5,60,0},	{6,60,0},	{7,60,9472},	{8,60,34816},	{9,60,60672},	{10,60,65280},	{11,60,65280},	{12,60,65280},	{13,60,65280},	{14,60,65280},	{15,60,65280},	{16,60,65280},	{17,60,65280},	{18,60,56064},	{19,60,26112},	{20,60,1280},	{21,60,0},	{22,60,0},	{23,60,0},	{24,60,0},	{25,60,0},	{26,60,0},	{27,60,11264},	{28,60,43520},	{29,60,65280},	{30,60,65280},	{31,60,65280},	{32,60,65280},	{33,60,65280},	{34,60,62464},	{35,60,32512},	{36,60,1536},	{37,60,0},	{38,60,0},	{39,60,0},	{40,60,0},	{41,60,21760},	{42,60,60928},	{43,60,65280},	{44,60,65280},	{45,60,65280},	{46,60,55552},	{47,60,12544},	{48,60,0},	{49,60,0},	{50,60,0},	{51,60,18688},	{52,60,61440},	{53,60,65280},	{54,60,65280},	{55,60,54528},	{56,60,7424},	{57,60,0},	{58,60,0},	{59,60,20992},	{60,60,64000},	{61,60,65280},	{62,60,61440},	{63,60,12032},	{64,60,0},	{65,60,1280},	{66,60,49152},	{67,60,65280},	{68,60,62208},	{69,60,9728},
+	 {0,61,0},	{1,61,0},	{2,61,0},	{3,61,0},	{4,61,0},	{5,61,0},	{6,61,0},	{7,61,0},	{8,61,0},	{9,61,2048},	{10,61,23808},	{11,61,52736},	{12,61,65280},	{13,61,65280},	{14,61,65280},	{15,61,65280},	{16,61,65280},	{17,61,65280},	{18,61,65280},	{19,61,65280},	{20,61,57344},	{21,61,28160},	{22,61,2560},	{23,61,0},	{24,61,0},	{25,61,0},	{26,61,0},	{27,61,0},	{28,61,0},	{29,61,15104},	{30,61,50176},	{31,61,65280},	{32,61,65280},	{33,61,65280},	{34,61,65280},	{35,61,65280},	{36,61,55552},	{37,61,17920},	{38,61,0},	{39,61,0},	{40,61,0},	{41,61,0},	{42,61,6400},	{43,61,45568},	{44,61,65280},	{45,61,65280},	{46,61,65280},	{47,61,63488},	{48,61,28160},	{49,61,256},	{50,61,0},	{51,61,0},	{52,61,9728},	{53,61,55040},	{54,61,65280},	{55,61,65280},	{56,61,58624},	{57,61,11520},	{58,61,0},	{59,61,0},	{60,61,20992},	{61,61,64000},	{62,61,65280},	{63,61,58368},	{64,61,7936},	{65,61,0},	{66,61,5120},	{67,61,56832},	{68,61,65280},	{69,61,51968},
+	 {0,62,26112},	{1,62,3328},	{2,62,0},	{3,62,0},	{4,62,0},	{5,62,0},	{6,62,0},	{7,62,0},	{8,62,0},	{9,62,0},	{10,62,0},	{11,62,0},	{12,62,13056},	{13,62,39168},	{14,62,62976},	{15,62,65280},	{16,62,65280},	{17,62,65280},	{18,62,65280},	{19,62,65280},	{20,62,65280},	{21,62,65280},	{22,62,59904},	{23,62,32512},	{24,62,4352},	{25,62,0},	{26,62,0},	{27,62,0},	{28,62,0},	{29,62,0},	{30,62,256},	{31,62,21760},	{32,62,55552},	{33,62,65280},	{34,62,65280},	{35,62,65280},	{36,62,65280},	{37,62,65280},	{38,62,45568},	{39,62,7680},	{40,62,0},	{41,62,0},	{42,62,0},	{43,62,0},	{44,62,21760},	{45,62,60928},	{46,62,65280},	{47,62,65280},	{48,62,65280},	{49,62,45056},	{50,62,4608},	{51,62,0},	{52,62,0},	{53,62,4608},	{54,62,47872},	{55,62,65280},	{56,62,65280},	{57,62,60928},	{58,62,15104},	{59,62,0},	{60,62,0},	{61,62,20992},	{62,62,64000},	{63,62,65280},	{64,62,55808},	{65,62,5632},	{66,62,0},	{67,62,12288},	{68,62,62464},	{69,62,65280},
+	 {0,63,65280},	{1,63,62976},	{2,63,43520},	{3,63,19456},	{4,63,1280},	{5,63,0},	{6,63,0},	{7,63,0},	{8,63,0},	{9,63,0},	{10,63,0},	{11,63,0},	{12,63,0},	{13,63,0},	{14,63,4096},	{15,63,28160},	{16,63,56832},	{17,63,65280},	{18,63,65280},	{19,63,65280},	{20,63,65280},	{21,63,65280},	{22,63,65280},	{23,63,65280},	{24,63,61952},	{25,63,36864},	{26,63,6656},	{27,63,0},	{28,63,0},	{29,63,0},	{30,63,0},	{31,63,0},	{32,63,1024},	{33,63,26112},	{34,63,58624},	{35,63,65280},	{36,63,65280},	{37,63,65280},	{38,63,65280},	{39,63,62464},	{40,63,32512},	{41,63,1536},	{42,63,0},	{43,63,0},	{44,63,0},	{45,63,7936},	{46,63,47872},	{47,63,65280},	{48,63,65280},	{49,63,65280},	{50,63,57600},	{51,63,14848},	{52,63,0},	{53,63,0},	{54,63,768},	{55,63,34816},	{56,63,65280},	{57,63,65280},	{58,63,62720},	{59,63,19200},	{60,63,0},	{61,63,0},	{62,63,20992},	{63,63,64000},	{64,63,65280},	{65,63,51456},	{66,63,2816},	{67,63,0},	{68,63,20992},	{69,63,65024},
+	 {0,64,65280},	{1,64,65280},	{2,64,65280},	{3,64,65280},	{4,64,60672},	{5,64,39168},	{6,64,15104},	{7,64,256},	{8,64,0},	{9,64,0},	{10,64,0},	{11,64,0},	{12,64,0},	{13,64,0},	{14,64,0},	{15,64,0},	{16,64,512},	{17,64,17408},	{18,64,43520},	{19,64,64512},	{20,64,65280},	{21,64,65280},	{22,64,65280},	{23,64,65280},	{24,64,65280},	{25,64,65280},	{26,64,63488},	{27,64,41216},	{28,64,9472},	{29,64,0},	{30,64,0},	{31,64,0},	{32,64,0},	{33,64,0},	{34,64,2560},	{35,64,30464},	{36,64,61184},	{37,64,65280},	{38,64,65280},	{39,64,65280},	{40,64,65280},	{41,64,55552},	{42,64,18176},	{43,64,0},	{44,64,0},	{45,64,0},	{46,64,256},	{47,64,26112},	{48,64,61952},	{49,64,65280},	{50,64,65280},	{51,64,64256},	{52,64,32512},	{53,64,512},	{54,64,0},	{55,64,0},	{56,64,25600},	{57,64,63744},	{58,64,65280},	{59,64,64512},	{60,64,25600},	{61,64,0},	{62,64,0},	{63,64,20992},	{64,64,64000},	{65,64,65280},	{66,64,46080},	{67,64,1024},	{68,64,0},	{69,64,33280},
+	 {0,65,65280},	{1,65,65280},	{2,65,65280},	{3,65,65280},	{4,65,65280},	{5,65,65280},	{6,65,65280},	{7,65,57344},	{8,65,34816},	{9,65,9472},	{10,65,0},	{11,65,0},	{12,65,0},	{13,65,0},	{14,65,0},	{15,65,0},	{16,65,0},	{17,65,0},	{18,65,0},	{19,65,6912},	{20,65,32512},	{21,65,59904},	{22,65,65280},	{23,65,65280},	{24,65,65280},	{25,65,65280},	{26,65,65280},	{27,65,65280},	{28,65,64768},	{29,65,45568},	{30,65,12800},	{31,65,0},	{32,65,0},	{33,65,0},	{34,65,0},	{35,65,0},	{36,65,4608},	{37,65,34816},	{38,65,62976},	{39,65,65280},	{40,65,65280},	{41,65,65280},	{42,65,65280},	{43,65,45568},	{44,65,7680},	{45,65,0},	{46,65,0},	{47,65,0},	{48,65,7936},	{49,65,47872},	{50,65,65280},	{51,65,65280},	{52,65,65280},	{53,65,47872},	{54,65,5888},	{55,65,0},	{56,65,0},	{57,65,14848},	{58,65,59392},	{59,65,65280},	{60,65,65024},	{61,65,32512},	{62,65,0},	{63,65,0},	{64,65,20992},	{65,65,64000},	{66,65,65280},	{67,65,41984},	{68,65,256},	{69,65,256},
+	 {0,66,65280},	{1,66,65280},	{2,66,65280},	{3,66,65280},	{4,66,65280},	{5,66,65280},	{6,66,65280},	{7,66,65280},	{8,66,65280},	{9,66,65280},	{10,66,52224},	{11,66,28160},	{12,66,5888},	{13,66,0},	{14,66,0},	{15,66,0},	{16,66,0},	{17,66,0},	{18,66,0},	{19,66,0},	{20,66,0},	{21,66,1792},	{22,66,21760},	{23,66,47872},	{24,66,65280},	{25,66,65280},	{26,66,65280},	{27,66,65280},	{28,66,65280},	{29,66,65280},	{30,66,65024},	{31,66,45568},	{32,66,14592},	{33,66,0},	{34,66,0},	{35,66,0},	{36,66,0},	{37,66,0},	{38,66,6912},	{39,66,39168},	{40,66,64256},	{41,66,65280},	{42,66,65280},	{43,66,65280},	{44,66,62720},	{45,66,32512},	{46,66,1792},	{47,66,0},	{48,66,0},	{49,66,256},	{50,66,26112},	{51,66,61952},	{52,66,65280},	{53,66,65280},	{54,66,58112},	{55,66,15872},	{56,66,0},	{57,66,0},	{58,66,7168},	{59,66,51968},	{60,66,65280},	{61,66,65280},	{62,66,37120},	{63,66,512},	{64,66,0},	{65,66,20992},	{66,66,64000},	{67,66,65280},	{68,66,34816},	{69,66,0},
+	 {0,67,52224},	{1,67,65280},	{2,67,65280},	{3,67,65280},	{4,67,65280},	{5,67,65280},	{6,67,65280},	{7,67,65280},	{8,67,65280},	{9,67,65280},	{10,67,65280},	{11,67,65280},	{12,67,64512},	{13,67,47872},	{14,67,23808},	{15,67,3072},	{16,67,0},	{17,67,0},	{18,67,0},	{19,67,0},	{20,67,0},	{21,67,0},	{22,67,0},	{23,67,0},	{24,67,12800},	{25,67,39168},	{26,67,62464},	{27,67,65280},	{28,67,65280},	{29,67,65280},	{30,67,65280},	{31,67,65280},	{32,67,65280},	{33,67,49920},	{34,67,19456},	{35,67,256},	{36,67,0},	{37,67,0},	{38,67,0},	{39,67,0},	{40,67,9984},	{41,67,43520},	{42,67,65024},	{43,67,65280},	{44,67,65280},	{45,67,65280},	{46,67,55552},	{47,67,18176},	{48,67,0},	{49,67,0},	{50,67,0},	{51,67,7936},	{52,67,47872},	{53,67,65280},	{54,67,65280},	{55,67,64512},	{56,67,32512},	{57,67,768},	{58,67,0},	{59,67,2048},	{60,67,41984},	{61,67,65280},	{62,67,65280},	{63,67,42240},	{64,67,1280},	{65,67,0},	{66,67,20992},	{67,67,64000},	{68,67,65280},	{69,67,29184},
+	 {0,68,0},	{1,68,8704},	{2,68,28160},	{3,68,47872},	{4,68,64000},	{5,68,65280},	{6,68,65280},	{7,68,65280},	{8,68,65280},	{9,68,65280},	{10,68,65280},	{11,68,65280},	{12,68,65280},	{13,68,65280},	{14,68,65280},	{15,68,62976},	{16,68,43520},	{17,68,19456},	{18,68,1024},	{19,68,0},	{20,68,0},	{21,68,0},	{22,68,0},	{23,68,0},	{24,68,0},	{25,68,0},	{26,68,3584},	{27,68,26112},	{28,68,54272},	{29,68,65280},	{30,68,65280},	{31,68,65280},	{32,68,65280},	{33,68,65280},	{34,68,65280},	{35,68,53248},	{36,68,23808},	{37,68,768},	{38,68,0},	{39,68,0},	{40,68,0},	{41,68,0},	{42,68,13824},	{43,68,48384},	{44,68,65280},	{45,68,65280},	{46,68,65280},	{47,68,65280},	{48,68,45568},	{49,68,7680},	{50,68,0},	{51,68,0},	{52,68,256},	{53,68,26112},	{54,68,61952},	{55,68,65280},	{56,68,65280},	{57,68,48640},	{58,68,6656},	{59,68,0},	{60,68,256},	{61,68,30464},	{62,68,64768},	{63,68,65280},	{64,68,48128},	{65,68,3584},	{66,68,0},	{67,68,20992},	{68,68,64000},	{69,68,65024},
+	 {0,69,0},	{1,69,0},	{2,69,0},	{3,69,0},	{4,69,4608},	{5,69,21760},	{6,69,41216},	{7,69,61440},	{8,69,65280},	{9,69,65280},	{10,69,65280},	{11,69,65280},	{12,69,65280},	{13,69,65280},	{14,69,65280},	{15,69,65280},	{16,69,65280},	{17,69,65280},	{18,69,60416},	{19,69,39168},	{20,69,15104},	{21,69,0},	{22,69,0},	{23,69,0},	{24,69,0},	{25,69,0},	{26,69,0},	{27,69,0},	{28,69,0},	{29,69,15104},	{30,69,43520},	{31,69,64000},	{32,69,65280},	{33,69,65280},	{34,69,65280},	{35,69,65280},	{36,69,65280},	{37,69,56576},	{38,69,28160},	{39,69,2048},	{40,69,0},	{41,69,0},	{42,69,0},	{43,69,0},	{44,69,17408},	{45,69,52480},	{46,69,65280},	{47,69,65280},	{48,69,65280},	{49,69,62720},	{50,69,32512},	{51,69,1792},	{52,69,0},	{53,69,0},	{54,69,8192},	{55,69,48128},	{56,69,65280},	{57,69,65280},	{58,69,59904},	{59,69,18432},	{60,69,0},	{61,69,0},	{62,69,19200},	{63,69,61696},	{64,69,65280},	{65,69,51968},	{66,69,5632},	{67,69,0},	{68,69,20992},	{69,69,64000},
+ };
+
+ //format: {x, y, intensity}
+ const static NyxusPixel cat2500_seg[] = {
+	 {0,0,0},	{1,0,0},	{2,0,0},	{3,0,0},	{4,0,0},	{5,0,0},	{6,0,0},	{7,0,0},	{8,0,0},	{9,0,0},	{10,0,0},	{11,0,0},	{12,0,0},	{13,0,0},	{14,0,0},	{15,0,0},	{16,0,0},	{17,0,0},	{18,0,0},	{19,0,0},	{20,0,0},	{21,0,0},	{22,0,0},	{23,0,0},	{24,0,0},	{25,0,0},	{26,0,0},	{27,0,0},	{28,0,0},	{29,0,0},	{30,0,0},	{31,0,0},	{32,0,0},	{33,0,0},	{34,0,0},	{35,0,0},	{36,0,0},	{37,0,0},	{38,0,0},	{39,0,0},	{40,0,0},	{41,0,0},	{42,0,0},	{43,0,0},	{44,0,0},	{45,0,0},	{46,0,0},	{47,0,0},	{48,0,0},	{49,0,0},	{50,0,0},	{51,0,0},	{52,0,0},	{53,0,0},	{54,0,0},	{55,0,0},	{56,0,0},	{57,0,0},	{58,0,0},	{59,0,0},	{60,0,0},	{61,0,0},	{62,0,0},	{63,0,0},	{64,0,0},	{65,0,0},	{66,0,0},	{67,0,0},	{68,0,0},	{69,0,0},
+	 {0,1,0},	{1,1,0},	{2,1,0},	{3,1,0},	{4,1,0},	{5,1,0},	{6,1,0},	{7,1,0},	{8,1,0},	{9,1,0},	{10,1,0},	{11,1,0},	{12,1,0},	{13,1,0},	{14,1,0},	{15,1,0},	{16,1,0},	{17,1,0},	{18,1,0},	{19,1,0},	{20,1,0},	{21,1,0},	{22,1,0},	{23,1,0},	{24,1,0},	{25,1,0},	{26,1,0},	{27,1,0},	{28,1,0},	{29,1,0},	{30,1,0},	{31,1,0},	{32,1,0},	{33,1,0},	{34,1,0},	{35,1,0},	{36,1,0},	{37,1,0},	{38,1,0},	{39,1,0},	{40,1,0},	{41,1,0},	{42,1,0},	{43,1,0},	{44,1,0},	{45,1,0},	{46,1,0},	{47,1,0},	{48,1,0},	{49,1,0},	{50,1,0},	{51,1,0},	{52,1,0},	{53,1,0},	{54,1,0},	{55,1,0},	{56,1,0},	{57,1,0},	{58,1,0},	{59,1,0},	{60,1,0},	{61,1,0},	{62,1,0},	{63,1,0},	{64,1,0},	{65,1,0},	{66,1,0},	{67,1,0},	{68,1,0},	{69,1,0},
+	 {0,2,0},	{1,2,0},	{2,2,0},	{3,2,0},	{4,2,0},	{5,2,0},	{6,2,0},	{7,2,0},	{8,2,0},	{9,2,0},	{10,2,0},	{11,2,0},	{12,2,0},	{13,2,0},	{14,2,0},	{15,2,0},	{16,2,0},	{17,2,0},	{18,2,0},	{19,2,0},	{20,2,0},	{21,2,0},	{22,2,0},	{23,2,0},	{24,2,0},	{25,2,0},	{26,2,0},	{27,2,0},	{28,2,0},	{29,2,0},	{30,2,0},	{31,2,0},	{32,2,0},	{33,2,0},	{34,2,0},	{35,2,0},	{36,2,0},	{37,2,0},	{38,2,0},	{39,2,0},	{40,2,0},	{41,2,0},	{42,2,0},	{43,2,0},	{44,2,0},	{45,2,0},	{46,2,0},	{47,2,0},	{48,2,0},	{49,2,0},	{50,2,0},	{51,2,0},	{52,2,0},	{53,2,0},	{54,2,0},	{55,2,0},	{56,2,0},	{57,2,0},	{58,2,0},	{59,2,0},	{60,2,0},	{61,2,0},	{62,2,0},	{63,2,0},	{64,2,0},	{65,2,0},	{66,2,0},	{67,2,0},	{68,2,0},	{69,2,0},
+	 {0,3,0},	{1,3,0},	{2,3,0},	{3,3,0},	{4,3,0},	{5,3,0},	{6,3,0},	{7,3,0},	{8,3,0},	{9,3,0},	{10,3,0},	{11,3,0},	{12,3,0},	{13,3,0},	{14,3,0},	{15,3,0},	{16,3,0},	{17,3,0},	{18,3,0},	{19,3,0},	{20,3,0},	{21,3,0},	{22,3,0},	{23,3,0},	{24,3,0},	{25,3,0},	{26,3,0},	{27,3,0},	{28,3,0},	{29,3,0},	{30,3,0},	{31,3,0},	{32,3,0},	{33,3,0},	{34,3,0},	{35,3,0},	{36,3,0},	{37,3,0},	{38,3,0},	{39,3,0},	{40,3,0},	{41,3,0},	{42,3,0},	{43,3,0},	{44,3,0},	{45,3,0},	{46,3,0},	{47,3,0},	{48,3,0},	{49,3,0},	{50,3,0},	{51,3,0},	{52,3,0},	{53,3,0},	{54,3,0},	{55,3,0},	{56,3,0},	{57,3,0},	{58,3,0},	{59,3,0},	{60,3,0},	{61,3,0},	{62,3,0},	{63,3,0},	{64,3,0},	{65,3,0},	{66,3,0},	{67,3,0},	{68,3,0},	{69,3,0},
+	 {0,4,0},	{1,4,0},	{2,4,0},	{3,4,0},	{4,4,0},	{5,4,0},	{6,4,0},	{7,4,0},	{8,4,0},	{9,4,0},	{10,4,0},	{11,4,0},	{12,4,0},	{13,4,0},	{14,4,0},	{15,4,0},	{16,4,0},	{17,4,0},	{18,4,0},	{19,4,0},	{20,4,0},	{21,4,0},	{22,4,0},	{23,4,0},	{24,4,0},	{25,4,0},	{26,4,0},	{27,4,0},	{28,4,0},	{29,4,0},	{30,4,0},	{31,4,0},	{32,4,0},	{33,4,0},	{34,4,0},	{35,4,0},	{36,4,0},	{37,4,0},	{38,4,0},	{39,4,0},	{40,4,0},	{41,4,0},	{42,4,0},	{43,4,0},	{44,4,0},	{45,4,0},	{46,4,0},	{47,4,0},	{48,4,0},	{49,4,0},	{50,4,0},	{51,4,0},	{52,4,0},	{53,4,0},	{54,4,0},	{55,4,0},	{56,4,0},	{57,4,0},	{58,4,0},	{59,4,0},	{60,4,0},	{61,4,0},	{62,4,0},	{63,4,0},	{64,4,0},	{65,4,0},	{66,4,0},	{67,4,0},	{68,4,0},	{69,4,0},
+	 {0,5,0},	{1,5,0},	{2,5,0},	{3,5,0},	{4,5,0},	{5,5,0},	{6,5,0},	{7,5,0},	{8,5,0},	{9,5,0},	{10,5,0},	{11,5,0},	{12,5,0},	{13,5,0},	{14,5,0},	{15,5,0},	{16,5,0},	{17,5,0},	{18,5,0},	{19,5,0},	{20,5,0},	{21,5,0},	{22,5,0},	{23,5,0},	{24,5,0},	{25,5,0},	{26,5,0},	{27,5,0},	{28,5,0},	{29,5,0},	{30,5,0},	{31,5,0},	{32,5,0},	{33,5,0},	{34,5,0},	{35,5,0},	{36,5,0},	{37,5,0},	{38,5,0},	{39,5,0},	{40,5,0},	{41,5,0},	{42,5,0},	{43,5,0},	{44,5,0},	{45,5,0},	{46,5,0},	{47,5,0},	{48,5,0},	{49,5,0},	{50,5,0},	{51,5,0},	{52,5,0},	{53,5,0},	{54,5,0},	{55,5,0},	{56,5,0},	{57,5,0},	{58,5,0},	{59,5,0},	{60,5,0},	{61,5,0},	{62,5,0},	{63,5,0},	{64,5,0},	{65,5,0},	{66,5,0},	{67,5,0},	{68,5,0},	{69,5,0},
+	 {0,6,0},	{1,6,0},	{2,6,0},	{3,6,0},	{4,6,0},	{5,6,0},	{6,6,0},	{7,6,0},	{8,6,0},	{9,6,0},	{10,6,0},	{11,6,0},	{12,6,0},	{13,6,0},	{14,6,0},	{15,6,0},	{16,6,0},	{17,6,0},	{18,6,0},	{19,6,0},	{20,6,0},	{21,6,0},	{22,6,0},	{23,6,0},	{24,6,0},	{25,6,0},	{26,6,0},	{27,6,0},	{28,6,0},	{29,6,0},	{30,6,0},	{31,6,0},	{32,6,0},	{33,6,0},	{34,6,0},	{35,6,0},	{36,6,0},	{37,6,0},	{38,6,0},	{39,6,0},	{40,6,0},	{41,6,0},	{42,6,0},	{43,6,0},	{44,6,0},	{45,6,0},	{46,6,0},	{47,6,0},	{48,6,0},	{49,6,0},	{50,6,0},	{51,6,0},	{52,6,0},	{53,6,0},	{54,6,0},	{55,6,0},	{56,6,0},	{57,6,0},	{58,6,0},	{59,6,0},	{60,6,0},	{61,6,0},	{62,6,0},	{63,6,0},	{64,6,0},	{65,6,0},	{66,6,0},	{67,6,0},	{68,6,0},	{69,6,0},
+	 {0,7,0},	{1,7,0},	{2,7,0},	{3,7,0},	{4,7,0},	{5,7,0},	{6,7,0},	{7,7,0},	{8,7,0},	{9,7,1},	{10,7,1},	{11,7,0},	{12,7,0},	{13,7,0},	{14,7,0},	{15,7,0},	{16,7,0},	{17,7,0},	{18,7,0},	{19,7,0},	{20,7,0},	{21,7,0},	{22,7,0},	{23,7,0},	{24,7,0},	{25,7,0},	{26,7,0},	{27,7,0},	{28,7,0},	{29,7,0},	{30,7,0},	{31,7,0},	{32,7,0},	{33,7,0},	{34,7,0},	{35,7,0},	{36,7,0},	{37,7,0},	{38,7,0},	{39,7,0},	{40,7,0},	{41,7,0},	{42,7,0},	{43,7,0},	{44,7,0},	{45,7,0},	{46,7,0},	{47,7,0},	{48,7,0},	{49,7,0},	{50,7,0},	{51,7,0},	{52,7,0},	{53,7,0},	{54,7,0},	{55,7,0},	{56,7,0},	{57,7,0},	{58,7,1},	{59,7,1},	{60,7,0},	{61,7,0},	{62,7,0},	{63,7,0},	{64,7,0},	{65,7,0},	{66,7,0},	{67,7,0},	{68,7,0},	{69,7,0},
+	 {0,8,0},	{1,8,0},	{2,8,0},	{3,8,0},	{4,8,0},	{5,8,0},	{6,8,0},	{7,8,0},	{8,8,0},	{9,8,1},	{10,8,1},	{11,8,1},	{12,8,0},	{13,8,0},	{14,8,0},	{15,8,0},	{16,8,0},	{17,8,0},	{18,8,0},	{19,8,0},	{20,8,0},	{21,8,0},	{22,8,0},	{23,8,0},	{24,8,0},	{25,8,0},	{26,8,0},	{27,8,0},	{28,8,0},	{29,8,0},	{30,8,0},	{31,8,0},	{32,8,0},	{33,8,0},	{34,8,0},	{35,8,0},	{36,8,0},	{37,8,0},	{38,8,0},	{39,8,0},	{40,8,0},	{41,8,0},	{42,8,0},	{43,8,0},	{44,8,0},	{45,8,0},	{46,8,0},	{47,8,0},	{48,8,0},	{49,8,0},	{50,8,0},	{51,8,0},	{52,8,0},	{53,8,0},	{54,8,0},	{55,8,0},	{56,8,0},	{57,8,1},	{58,8,1},	{59,8,1},	{60,8,0},	{61,8,0},	{62,8,0},	{63,8,0},	{64,8,0},	{65,8,0},	{66,8,0},	{67,8,0},	{68,8,0},	{69,8,0},
+	 {0,9,0},	{1,9,0},	{2,9,0},	{3,9,0},	{4,9,0},	{5,9,0},	{6,9,0},	{7,9,0},	{8,9,1},	{9,9,1},	{10,9,1},	{11,9,1},	{12,9,1},	{13,9,0},	{14,9,0},	{15,9,0},	{16,9,0},	{17,9,0},	{18,9,0},	{19,9,0},	{20,9,0},	{21,9,0},	{22,9,0},	{23,9,0},	{24,9,0},	{25,9,0},	{26,9,0},	{27,9,0},	{28,9,0},	{29,9,0},	{30,9,0},	{31,9,0},	{32,9,0},	{33,9,0},	{34,9,0},	{35,9,0},	{36,9,0},	{37,9,0},	{38,9,0},	{39,9,0},	{40,9,0},	{41,9,0},	{42,9,0},	{43,9,0},	{44,9,0},	{45,9,0},	{46,9,0},	{47,9,0},	{48,9,0},	{49,9,0},	{50,9,0},	{51,9,0},	{52,9,0},	{53,9,0},	{54,9,0},	{55,9,0},	{56,9,1},	{57,9,1},	{58,9,1},	{59,9,1},	{60,9,1},	{61,9,0},	{62,9,0},	{63,9,0},	{64,9,0},	{65,9,0},	{66,9,0},	{67,9,0},	{68,9,0},	{69,9,0},
+	 {0,10,0},	{1,10,0},	{2,10,0},	{3,10,0},	{4,10,0},	{5,10,0},	{6,10,0},	{7,10,0},	{8,10,1},	{9,10,1},	{10,10,1},	{11,10,1},	{12,10,1},	{13,10,1},	{14,10,0},	{15,10,0},	{16,10,0},	{17,10,0},	{18,10,0},	{19,10,0},	{20,10,0},	{21,10,0},	{22,10,0},	{23,10,0},	{24,10,0},	{25,10,0},	{26,10,0},	{27,10,0},	{28,10,0},	{29,10,0},	{30,10,0},	{31,10,0},	{32,10,0},	{33,10,0},	{34,10,0},	{35,10,0},	{36,10,0},	{37,10,0},	{38,10,0},	{39,10,0},	{40,10,0},	{41,10,0},	{42,10,0},	{43,10,0},	{44,10,0},	{45,10,0},	{46,10,0},	{47,10,0},	{48,10,0},	{49,10,0},	{50,10,0},	{51,10,0},	{52,10,0},	{53,10,0},	{54,10,0},	{55,10,1},	{56,10,1},	{57,10,1},	{58,10,1},	{59,10,1},	{60,10,1},	{61,10,0},	{62,10,0},	{63,10,0},	{64,10,0},	{65,10,0},	{66,10,0},	{67,10,0},	{68,10,0},	{69,10,0},
+	 {0,11,0},	{1,11,0},	{2,11,0},	{3,11,0},	{4,11,0},	{5,11,0},	{6,11,0},	{7,11,1},	{8,11,1},	{9,11,1},	{10,11,1},	{11,11,1},	{12,11,1},	{13,11,1},	{14,11,1},	{15,11,0},	{16,11,0},	{17,11,0},	{18,11,0},	{19,11,0},	{20,11,0},	{21,11,0},	{22,11,0},	{23,11,0},	{24,11,0},	{25,11,0},	{26,11,0},	{27,11,0},	{28,11,0},	{29,11,0},	{30,11,0},	{31,11,0},	{32,11,0},	{33,11,0},	{34,11,0},	{35,11,0},	{36,11,0},	{37,11,0},	{38,11,0},	{39,11,0},	{40,11,0},	{41,11,0},	{42,11,0},	{43,11,0},	{44,11,0},	{45,11,0},	{46,11,0},	{47,11,0},	{48,11,0},	{49,11,0},	{50,11,0},	{51,11,0},	{52,11,0},	{53,11,0},	{54,11,1},	{55,11,1},	{56,11,1},	{57,11,1},	{58,11,1},	{59,11,1},	{60,11,1},	{61,11,0},	{62,11,0},	{63,11,0},	{64,11,0},	{65,11,0},	{66,11,0},	{67,11,0},	{68,11,0},	{69,11,0},
+	 {0,12,0},	{1,12,0},	{2,12,0},	{3,12,0},	{4,12,0},	{5,12,0},	{6,12,0},	{7,12,1},	{8,12,1},	{9,12,1},	{10,12,1},	{11,12,1},	{12,12,1},	{13,12,1},	{14,12,1},	{15,12,1},	{16,12,1},	{17,12,0},	{18,12,0},	{19,12,0},	{20,12,0},	{21,12,0},	{22,12,0},	{23,12,0},	{24,12,0},	{25,12,0},	{26,12,0},	{27,12,0},	{28,12,0},	{29,12,0},	{30,12,0},	{31,12,0},	{32,12,0},	{33,12,0},	{34,12,0},	{35,12,0},	{36,12,0},	{37,12,0},	{38,12,0},	{39,12,0},	{40,12,0},	{41,12,0},	{42,12,0},	{43,12,0},	{44,12,0},	{45,12,0},	{46,12,0},	{47,12,0},	{48,12,0},	{49,12,0},	{50,12,0},	{51,12,0},	{52,12,0},	{53,12,1},	{54,12,1},	{55,12,1},	{56,12,1},	{57,12,1},	{58,12,1},	{59,12,1},	{60,12,1},	{61,12,0},	{62,12,0},	{63,12,0},	{64,12,0},	{65,12,0},	{66,12,0},	{67,12,0},	{68,12,0},	{69,12,0},
+	 {0,13,0},	{1,13,0},	{2,13,0},	{3,13,0},	{4,13,0},	{5,13,0},	{6,13,0},	{7,13,1},	{8,13,1},	{9,13,1},	{10,13,1},	{11,13,1},	{12,13,1},	{13,13,1},	{14,13,1},	{15,13,1},	{16,13,1},	{17,13,1},	{18,13,0},	{19,13,0},	{20,13,0},	{21,13,0},	{22,13,0},	{23,13,0},	{24,13,0},	{25,13,0},	{26,13,0},	{27,13,0},	{28,13,0},	{29,13,0},	{30,13,0},	{31,13,0},	{32,13,0},	{33,13,0},	{34,13,0},	{35,13,0},	{36,13,0},	{37,13,0},	{38,13,0},	{39,13,0},	{40,13,0},	{41,13,0},	{42,13,0},	{43,13,0},	{44,13,0},	{45,13,0},	{46,13,0},	{47,13,0},	{48,13,0},	{49,13,0},	{50,13,0},	{51,13,0},	{52,13,1},	{53,13,1},	{54,13,1},	{55,13,1},	{56,13,1},	{57,13,1},	{58,13,1},	{59,13,1},	{60,13,1},	{61,13,1},	{62,13,0},	{63,13,0},	{64,13,0},	{65,13,0},	{66,13,0},	{67,13,0},	{68,13,0},	{69,13,0},
+	 {0,14,0},	{1,14,0},	{2,14,0},	{3,14,0},	{4,14,0},	{5,14,0},	{6,14,0},	{7,14,1},	{8,14,1},	{9,14,1},	{10,14,1},	{11,14,1},	{12,14,1},	{13,14,1},	{14,14,1},	{15,14,1},	{16,14,1},	{17,14,1},	{18,14,1},	{19,14,0},	{20,14,0},	{21,14,0},	{22,14,0},	{23,14,0},	{24,14,0},	{25,14,0},	{26,14,0},	{27,14,0},	{28,14,0},	{29,14,0},	{30,14,0},	{31,14,0},	{32,14,0},	{33,14,0},	{34,14,0},	{35,14,0},	{36,14,0},	{37,14,0},	{38,14,0},	{39,14,0},	{40,14,0},	{41,14,0},	{42,14,0},	{43,14,0},	{44,14,0},	{45,14,0},	{46,14,0},	{47,14,0},	{48,14,0},	{49,14,0},	{50,14,0},	{51,14,1},	{52,14,1},	{53,14,1},	{54,14,1},	{55,14,1},	{56,14,1},	{57,14,1},	{58,14,1},	{59,14,1},	{60,14,1},	{61,14,1},	{62,14,0},	{63,14,0},	{64,14,0},	{65,14,0},	{66,14,0},	{67,14,0},	{68,14,0},	{69,14,0},
+	 {0,15,0},	{1,15,0},	{2,15,0},	{3,15,0},	{4,15,0},	{5,15,0},	{6,15,0},	{7,15,1},	{8,15,1},	{9,15,1},	{10,15,1},	{11,15,1},	{12,15,1},	{13,15,1},	{14,15,1},	{15,15,1},	{16,15,1},	{17,15,1},	{18,15,1},	{19,15,0},	{20,15,0},	{21,15,0},	{22,15,0},	{23,15,0},	{24,15,0},	{25,15,0},	{26,15,0},	{27,15,0},	{28,15,0},	{29,15,0},	{30,15,0},	{31,15,0},	{32,15,0},	{33,15,0},	{34,15,0},	{35,15,0},	{36,15,0},	{37,15,0},	{38,15,0},	{39,15,0},	{40,15,0},	{41,15,0},	{42,15,0},	{43,15,0},	{44,15,0},	{45,15,0},	{46,15,0},	{47,15,0},	{48,15,0},	{49,15,0},	{50,15,0},	{51,15,1},	{52,15,1},	{53,15,1},	{54,15,1},	{55,15,1},	{56,15,1},	{57,15,1},	{58,15,1},	{59,15,1},	{60,15,1},	{61,15,1},	{62,15,1},	{63,15,0},	{64,15,0},	{65,15,0},	{66,15,0},	{67,15,0},	{68,15,0},	{69,15,0},
+	 {0,16,0},	{1,16,0},	{2,16,0},	{3,16,0},	{4,16,0},	{5,16,0},	{6,16,0},	{7,16,1},	{8,16,1},	{9,16,1},	{10,16,1},	{11,16,1},	{12,16,1},	{13,16,1},	{14,16,1},	{15,16,1},	{16,16,1},	{17,16,1},	{18,16,1},	{19,16,1},	{20,16,0},	{21,16,0},	{22,16,0},	{23,16,0},	{24,16,0},	{25,16,0},	{26,16,0},	{27,16,0},	{28,16,0},	{29,16,0},	{30,16,0},	{31,16,0},	{32,16,0},	{33,16,0},	{34,16,0},	{35,16,0},	{36,16,0},	{37,16,0},	{38,16,0},	{39,16,0},	{40,16,0},	{41,16,0},	{42,16,0},	{43,16,0},	{44,16,0},	{45,16,0},	{46,16,0},	{47,16,0},	{48,16,0},	{49,16,0},	{50,16,1},	{51,16,1},	{52,16,1},	{53,16,1},	{54,16,1},	{55,16,1},	{56,16,1},	{57,16,1},	{58,16,1},	{59,16,1},	{60,16,1},	{61,16,1},	{62,16,1},	{63,16,0},	{64,16,0},	{65,16,0},	{66,16,0},	{67,16,0},	{68,16,0},	{69,16,0},
+	 {0,17,0},	{1,17,0},	{2,17,0},	{3,17,0},	{4,17,0},	{5,17,0},	{6,17,0},	{7,17,1},	{8,17,1},	{9,17,1},	{10,17,1},	{11,17,1},	{12,17,1},	{13,17,1},	{14,17,1},	{15,17,1},	{16,17,1},	{17,17,1},	{18,17,1},	{19,17,1},	{20,17,1},	{21,17,0},	{22,17,0},	{23,17,0},	{24,17,0},	{25,17,0},	{26,17,0},	{27,17,0},	{28,17,0},	{29,17,0},	{30,17,0},	{31,17,0},	{32,17,0},	{33,17,0},	{34,17,0},	{35,17,0},	{36,17,0},	{37,17,0},	{38,17,0},	{39,17,0},	{40,17,0},	{41,17,0},	{42,17,0},	{43,17,0},	{44,17,0},	{45,17,0},	{46,17,0},	{47,17,0},	{48,17,0},	{49,17,1},	{50,17,1},	{51,17,1},	{52,17,1},	{53,17,1},	{54,17,1},	{55,17,1},	{56,17,1},	{57,17,1},	{58,17,1},	{59,17,1},	{60,17,1},	{61,17,1},	{62,17,1},	{63,17,0},	{64,17,0},	{65,17,0},	{66,17,0},	{67,17,0},	{68,17,0},	{69,17,0},
+	 {0,18,0},	{1,18,0},	{2,18,0},	{3,18,0},	{4,18,0},	{5,18,0},	{6,18,1},	{7,18,1},	{8,18,1},	{9,18,1},	{10,18,1},	{11,18,1},	{12,18,1},	{13,18,1},	{14,18,1},	{15,18,1},	{16,18,1},	{17,18,1},	{18,18,1},	{19,18,1},	{20,18,1},	{21,18,0},	{22,18,0},	{23,18,0},	{24,18,0},	{25,18,0},	{26,18,0},	{27,18,0},	{28,18,0},	{29,18,0},	{30,18,0},	{31,18,0},	{32,18,0},	{33,18,0},	{34,18,0},	{35,18,0},	{36,18,0},	{37,18,0},	{38,18,0},	{39,18,0},	{40,18,0},	{41,18,0},	{42,18,0},	{43,18,0},	{44,18,0},	{45,18,0},	{46,18,0},	{47,18,0},	{48,18,0},	{49,18,1},	{50,18,1},	{51,18,1},	{52,18,1},	{53,18,1},	{54,18,1},	{55,18,1},	{56,18,1},	{57,18,1},	{58,18,1},	{59,18,1},	{60,18,1},	{61,18,1},	{62,18,1},	{63,18,0},	{64,18,0},	{65,18,0},	{66,18,0},	{67,18,0},	{68,18,0},	{69,18,0},
+	 {0,19,0},	{1,19,0},	{2,19,0},	{3,19,0},	{4,19,0},	{5,19,0},	{6,19,1},	{7,19,1},	{8,19,1},	{9,19,1},	{10,19,1},	{11,19,1},	{12,19,1},	{13,19,1},	{14,19,1},	{15,19,1},	{16,19,1},	{17,19,1},	{18,19,1},	{19,19,1},	{20,19,1},	{21,19,1},	{22,19,0},	{23,19,0},	{24,19,0},	{25,19,0},	{26,19,0},	{27,19,0},	{28,19,0},	{29,19,0},	{30,19,0},	{31,19,0},	{32,19,0},	{33,19,0},	{34,19,0},	{35,19,0},	{36,19,0},	{37,19,0},	{38,19,0},	{39,19,0},	{40,19,0},	{41,19,0},	{42,19,0},	{43,19,0},	{44,19,0},	{45,19,0},	{46,19,0},	{47,19,0},	{48,19,1},	{49,19,1},	{50,19,1},	{51,19,1},	{52,19,1},	{53,19,1},	{54,19,1},	{55,19,1},	{56,19,1},	{57,19,1},	{58,19,1},	{59,19,1},	{60,19,1},	{61,19,1},	{62,19,1},	{63,19,0},	{64,19,0},	{65,19,0},	{66,19,0},	{67,19,0},	{68,19,0},	{69,19,0},
+	 {0,20,0},	{1,20,0},	{2,20,0},	{3,20,0},	{4,20,0},	{5,20,0},	{6,20,1},	{7,20,1},	{8,20,1},	{9,20,1},	{10,20,1},	{11,20,1},	{12,20,1},	{13,20,1},	{14,20,1},	{15,20,1},	{16,20,1},	{17,20,1},	{18,20,1},	{19,20,1},	{20,20,1},	{21,20,1},	{22,20,0},	{23,20,0},	{24,20,0},	{25,20,0},	{26,20,0},	{27,20,0},	{28,20,0},	{29,20,0},	{30,20,0},	{31,20,0},	{32,20,0},	{33,20,0},	{34,20,0},	{35,20,0},	{36,20,0},	{37,20,0},	{38,20,0},	{39,20,0},	{40,20,0},	{41,20,0},	{42,20,0},	{43,20,0},	{44,20,0},	{45,20,0},	{46,20,0},	{47,20,0},	{48,20,1},	{49,20,1},	{50,20,1},	{51,20,1},	{52,20,1},	{53,20,1},	{54,20,1},	{55,20,1},	{56,20,1},	{57,20,1},	{58,20,1},	{59,20,1},	{60,20,1},	{61,20,1},	{62,20,1},	{63,20,0},	{64,20,0},	{65,20,0},	{66,20,0},	{67,20,0},	{68,20,0},	{69,20,0},
+	 {0,21,0},	{1,21,0},	{2,21,0},	{3,21,0},	{4,21,0},	{5,21,1},	{6,21,1},	{7,21,1},	{8,21,1},	{9,21,1},	{10,21,1},	{11,21,1},	{12,21,1},	{13,21,1},	{14,21,1},	{15,21,1},	{16,21,1},	{17,21,1},	{18,21,1},	{19,21,1},	{20,21,1},	{21,21,1},	{22,21,1},	{23,21,0},	{24,21,0},	{25,21,0},	{26,21,0},	{27,21,0},	{28,21,0},	{29,21,0},	{30,21,0},	{31,21,0},	{32,21,0},	{33,21,0},	{34,21,0},	{35,21,0},	{36,21,0},	{37,21,0},	{38,21,0},	{39,21,0},	{40,21,0},	{41,21,0},	{42,21,0},	{43,21,0},	{44,21,0},	{45,21,0},	{46,21,0},	{47,21,1},	{48,21,1},	{49,21,1},	{50,21,1},	{51,21,1},	{52,21,1},	{53,21,1},	{54,21,1},	{55,21,1},	{56,21,1},	{57,21,1},	{58,21,1},	{59,21,1},	{60,21,1},	{61,21,1},	{62,21,1},	{63,21,0},	{64,21,0},	{65,21,0},	{66,21,0},	{67,21,0},	{68,21,0},	{69,21,0},
+	 {0,22,0},	{1,22,0},	{2,22,0},	{3,22,0},	{4,22,0},	{5,22,1},	{6,22,1},	{7,22,1},	{8,22,1},	{9,22,1},	{10,22,1},	{11,22,1},	{12,22,1},	{13,22,1},	{14,22,1},	{15,22,1},	{16,22,1},	{17,22,1},	{18,22,1},	{19,22,1},	{20,22,1},	{21,22,1},	{22,22,1},	{23,22,0},	{24,22,0},	{25,22,0},	{26,22,0},	{27,22,0},	{28,22,0},	{29,22,0},	{30,22,0},	{31,22,0},	{32,22,0},	{33,22,0},	{34,22,0},	{35,22,0},	{36,22,0},	{37,22,0},	{38,22,0},	{39,22,0},	{40,22,0},	{41,22,0},	{42,22,0},	{43,22,0},	{44,22,0},	{45,22,0},	{46,22,0},	{47,22,1},	{48,22,1},	{49,22,1},	{50,22,1},	{51,22,1},	{52,22,1},	{53,22,1},	{54,22,1},	{55,22,1},	{56,22,1},	{57,22,1},	{58,22,1},	{59,22,1},	{60,22,1},	{61,22,1},	{62,22,1},	{63,22,1},	{64,22,0},	{65,22,0},	{66,22,0},	{67,22,0},	{68,22,0},	{69,22,0},
+	 {0,23,0},	{1,23,0},	{2,23,0},	{3,23,0},	{4,23,0},	{5,23,1},	{6,23,1},	{7,23,1},	{8,23,1},	{9,23,1},	{10,23,1},	{11,23,1},	{12,23,1},	{13,23,1},	{14,23,1},	{15,23,1},	{16,23,1},	{17,23,1},	{18,23,1},	{19,23,1},	{20,23,1},	{21,23,1},	{22,23,1},	{23,23,1},	{24,23,0},	{25,23,0},	{26,23,0},	{27,23,0},	{28,23,1},	{29,23,1},	{30,23,1},	{31,23,1},	{32,23,1},	{33,23,1},	{34,23,1},	{35,23,1},	{36,23,1},	{37,23,1},	{38,23,1},	{39,23,1},	{40,23,1},	{41,23,1},	{42,23,0},	{43,23,0},	{44,23,0},	{45,23,0},	{46,23,1},	{47,23,1},	{48,23,1},	{49,23,1},	{50,23,1},	{51,23,1},	{52,23,1},	{53,23,1},	{54,23,1},	{55,23,1},	{56,23,1},	{57,23,1},	{58,23,1},	{59,23,1},	{60,23,1},	{61,23,1},	{62,23,1},	{63,23,1},	{64,23,0},	{65,23,0},	{66,23,0},	{67,23,0},	{68,23,0},	{69,23,0},
+	 {0,24,0},	{1,24,0},	{2,24,0},	{3,24,0},	{4,24,0},	{5,24,1},	{6,24,1},	{7,24,1},	{8,24,1},	{9,24,1},	{10,24,1},	{11,24,1},	{12,24,1},	{13,24,1},	{14,24,1},	{15,24,1},	{16,24,1},	{17,24,1},	{18,24,1},	{19,24,1},	{20,24,1},	{21,24,1},	{22,24,1},	{23,24,1},	{24,24,1},	{25,24,0},	{26,24,1},	{27,24,1},	{28,24,1},	{29,24,1},	{30,24,1},	{31,24,1},	{32,24,1},	{33,24,1},	{34,24,1},	{35,24,1},	{36,24,1},	{37,24,1},	{38,24,1},	{39,24,1},	{40,24,1},	{41,24,1},	{42,24,1},	{43,24,0},	{44,24,0},	{45,24,1},	{46,24,1},	{47,24,1},	{48,24,1},	{49,24,1},	{50,24,1},	{51,24,1},	{52,24,1},	{53,24,1},	{54,24,1},	{55,24,1},	{56,24,1},	{57,24,1},	{58,24,1},	{59,24,1},	{60,24,1},	{61,24,1},	{62,24,1},	{63,24,1},	{64,24,0},	{65,24,0},	{66,24,0},	{67,24,0},	{68,24,0},	{69,24,0},
+	 {0,25,0},	{1,25,0},	{2,25,0},	{3,25,0},	{4,25,0},	{5,25,1},	{6,25,1},	{7,25,1},	{8,25,1},	{9,25,1},	{10,25,1},	{11,25,1},	{12,25,1},	{13,25,1},	{14,25,1},	{15,25,1},	{16,25,1},	{17,25,1},	{18,25,1},	{19,25,1},	{20,25,1},	{21,25,1},	{22,25,1},	{23,25,1},	{24,25,1},	{25,25,1},	{26,25,1},	{27,25,1},	{28,25,1},	{29,25,1},	{30,25,1},	{31,25,1},	{32,25,1},	{33,25,1},	{34,25,1},	{35,25,1},	{36,25,1},	{37,25,1},	{38,25,1},	{39,25,1},	{40,25,1},	{41,25,1},	{42,25,1},	{43,25,1},	{44,25,1},	{45,25,1},	{46,25,1},	{47,25,1},	{48,25,1},	{49,25,1},	{50,25,1},	{51,25,1},	{52,25,1},	{53,25,1},	{54,25,1},	{55,25,1},	{56,25,1},	{57,25,1},	{58,25,1},	{59,25,1},	{60,25,1},	{61,25,1},	{62,25,1},	{63,25,1},	{64,25,0},	{65,25,0},	{66,25,0},	{67,25,0},	{68,25,0},	{69,25,0},
+	 {0,26,0},	{1,26,0},	{2,26,0},	{3,26,0},	{4,26,0},	{5,26,1},	{6,26,1},	{7,26,1},	{8,26,1},	{9,26,1},	{10,26,1},	{11,26,1},	{12,26,1},	{13,26,1},	{14,26,1},	{15,26,1},	{16,26,1},	{17,26,1},	{18,26,1},	{19,26,1},	{20,26,1},	{21,26,1},	{22,26,1},	{23,26,1},	{24,26,1},	{25,26,1},	{26,26,1},	{27,26,1},	{28,26,1},	{29,26,1},	{30,26,1},	{31,26,1},	{32,26,1},	{33,26,1},	{34,26,1},	{35,26,1},	{36,26,1},	{37,26,1},	{38,26,1},	{39,26,1},	{40,26,1},	{41,26,1},	{42,26,1},	{43,26,1},	{44,26,1},	{45,26,1},	{46,26,1},	{47,26,1},	{48,26,1},	{49,26,1},	{50,26,1},	{51,26,1},	{52,26,1},	{53,26,1},	{54,26,1},	{55,26,1},	{56,26,1},	{57,26,1},	{58,26,1},	{59,26,1},	{60,26,1},	{61,26,1},	{62,26,1},	{63,26,1},	{64,26,1},	{65,26,0},	{66,26,0},	{67,26,0},	{68,26,0},	{69,26,0},
+	 {0,27,0},	{1,27,0},	{2,27,0},	{3,27,0},	{4,27,0},	{5,27,1},	{6,27,1},	{7,27,1},	{8,27,1},	{9,27,1},	{10,27,1},	{11,27,1},	{12,27,1},	{13,27,1},	{14,27,1},	{15,27,1},	{16,27,1},	{17,27,1},	{18,27,1},	{19,27,1},	{20,27,1},	{21,27,1},	{22,27,1},	{23,27,1},	{24,27,1},	{25,27,1},	{26,27,1},	{27,27,1},	{28,27,1},	{29,27,1},	{30,27,1},	{31,27,1},	{32,27,1},	{33,27,1},	{34,27,1},	{35,27,1},	{36,27,1},	{37,27,1},	{38,27,1},	{39,27,1},	{40,27,1},	{41,27,1},	{42,27,1},	{43,27,1},	{44,27,1},	{45,27,1},	{46,27,1},	{47,27,1},	{48,27,1},	{49,27,1},	{50,27,1},	{51,27,1},	{52,27,1},	{53,27,1},	{54,27,1},	{55,27,1},	{56,27,1},	{57,27,1},	{58,27,1},	{59,27,1},	{60,27,1},	{61,27,1},	{62,27,1},	{63,27,1},	{64,27,1},	{65,27,0},	{66,27,0},	{67,27,0},	{68,27,0},	{69,27,0},
+	 {0,28,0},	{1,28,0},	{2,28,0},	{3,28,0},	{4,28,0},	{5,28,1},	{6,28,1},	{7,28,1},	{8,28,1},	{9,28,1},	{10,28,1},	{11,28,1},	{12,28,1},	{13,28,1},	{14,28,1},	{15,28,1},	{16,28,1},	{17,28,1},	{18,28,1},	{19,28,1},	{20,28,1},	{21,28,1},	{22,28,1},	{23,28,1},	{24,28,1},	{25,28,1},	{26,28,1},	{27,28,1},	{28,28,1},	{29,28,1},	{30,28,1},	{31,28,1},	{32,28,1},	{33,28,1},	{34,28,1},	{35,28,1},	{36,28,1},	{37,28,1},	{38,28,1},	{39,28,1},	{40,28,1},	{41,28,1},	{42,28,1},	{43,28,1},	{44,28,1},	{45,28,1},	{46,28,1},	{47,28,1},	{48,28,1},	{49,28,1},	{50,28,1},	{51,28,1},	{52,28,1},	{53,28,1},	{54,28,1},	{55,28,1},	{56,28,1},	{57,28,1},	{58,28,1},	{59,28,1},	{60,28,1},	{61,28,1},	{62,28,1},	{63,28,1},	{64,28,1},	{65,28,0},	{66,28,0},	{67,28,0},	{68,28,0},	{69,28,0},
+	 {0,29,0},	{1,29,0},	{2,29,0},	{3,29,0},	{4,29,0},	{5,29,1},	{6,29,1},	{7,29,1},	{8,29,1},	{9,29,1},	{10,29,1},	{11,29,1},	{12,29,1},	{13,29,1},	{14,29,1},	{15,29,1},	{16,29,1},	{17,29,1},	{18,29,1},	{19,29,1},	{20,29,1},	{21,29,1},	{22,29,1},	{23,29,1},	{24,29,1},	{25,29,1},	{26,29,1},	{27,29,1},	{28,29,1},	{29,29,1},	{30,29,1},	{31,29,1},	{32,29,1},	{33,29,1},	{34,29,1},	{35,29,1},	{36,29,1},	{37,29,1},	{38,29,1},	{39,29,1},	{40,29,1},	{41,29,1},	{42,29,1},	{43,29,1},	{44,29,1},	{45,29,1},	{46,29,1},	{47,29,1},	{48,29,1},	{49,29,1},	{50,29,1},	{51,29,1},	{52,29,1},	{53,29,1},	{54,29,1},	{55,29,1},	{56,29,1},	{57,29,1},	{58,29,1},	{59,29,1},	{60,29,1},	{61,29,1},	{62,29,1},	{63,29,1},	{64,29,1},	{65,29,0},	{66,29,0},	{67,29,0},	{68,29,0},	{69,29,0},
+	 {0,30,0},	{1,30,0},	{2,30,0},	{3,30,0},	{4,30,0},	{5,30,1},	{6,30,1},	{7,30,1},	{8,30,1},	{9,30,1},	{10,30,1},	{11,30,1},	{12,30,1},	{13,30,1},	{14,30,1},	{15,30,1},	{16,30,1},	{17,30,1},	{18,30,1},	{19,30,1},	{20,30,1},	{21,30,1},	{22,30,1},	{23,30,1},	{24,30,1},	{25,30,1},	{26,30,1},	{27,30,1},	{28,30,1},	{29,30,1},	{30,30,1},	{31,30,1},	{32,30,1},	{33,30,1},	{34,30,1},	{35,30,1},	{36,30,1},	{37,30,1},	{38,30,1},	{39,30,1},	{40,30,1},	{41,30,1},	{42,30,1},	{43,30,1},	{44,30,1},	{45,30,1},	{46,30,1},	{47,30,1},	{48,30,1},	{49,30,1},	{50,30,1},	{51,30,1},	{52,30,1},	{53,30,1},	{54,30,1},	{55,30,1},	{56,30,1},	{57,30,1},	{58,30,1},	{59,30,1},	{60,30,1},	{61,30,1},	{62,30,1},	{63,30,1},	{64,30,1},	{65,30,0},	{66,30,0},	{67,30,0},	{68,30,0},	{69,30,0},
+	 {0,31,0},	{1,31,0},	{2,31,0},	{3,31,0},	{4,31,0},	{5,31,1},	{6,31,1},	{7,31,1},	{8,31,1},	{9,31,1},	{10,31,1},	{11,31,1},	{12,31,1},	{13,31,1},	{14,31,1},	{15,31,1},	{16,31,1},	{17,31,1},	{18,31,1},	{19,31,1},	{20,31,1},	{21,31,1},	{22,31,1},	{23,31,1},	{24,31,1},	{25,31,1},	{26,31,1},	{27,31,1},	{28,31,1},	{29,31,1},	{30,31,1},	{31,31,1},	{32,31,1},	{33,31,1},	{34,31,1},	{35,31,1},	{36,31,1},	{37,31,1},	{38,31,1},	{39,31,1},	{40,31,1},	{41,31,1},	{42,31,1},	{43,31,1},	{44,31,1},	{45,31,1},	{46,31,1},	{47,31,1},	{48,31,1},	{49,31,1},	{50,31,1},	{51,31,1},	{52,31,1},	{53,31,1},	{54,31,1},	{55,31,1},	{56,31,1},	{57,31,1},	{58,31,1},	{59,31,1},	{60,31,1},	{61,31,1},	{62,31,1},	{63,31,1},	{64,31,1},	{65,31,0},	{66,31,0},	{67,31,0},	{68,31,0},	{69,31,0},
+	 {0,32,0},	{1,32,0},	{2,32,0},	{3,32,0},	{4,32,0},	{5,32,1},	{6,32,1},	{7,32,1},	{8,32,1},	{9,32,1},	{10,32,1},	{11,32,1},	{12,32,1},	{13,32,1},	{14,32,1},	{15,32,1},	{16,32,1},	{17,32,1},	{18,32,1},	{19,32,1},	{20,32,1},	{21,32,1},	{22,32,1},	{23,32,1},	{24,32,1},	{25,32,1},	{26,32,1},	{27,32,1},	{28,32,1},	{29,32,1},	{30,32,1},	{31,32,1},	{32,32,1},	{33,32,1},	{34,32,1},	{35,32,1},	{36,32,1},	{37,32,1},	{38,32,1},	{39,32,1},	{40,32,1},	{41,32,1},	{42,32,1},	{43,32,1},	{44,32,1},	{45,32,1},	{46,32,1},	{47,32,1},	{48,32,1},	{49,32,1},	{50,32,1},	{51,32,1},	{52,32,1},	{53,32,1},	{54,32,1},	{55,32,1},	{56,32,1},	{57,32,1},	{58,32,1},	{59,32,1},	{60,32,1},	{61,32,1},	{62,32,1},	{63,32,1},	{64,32,1},	{65,32,0},	{66,32,0},	{67,32,0},	{68,32,0},	{69,32,0},
+	 {0,33,0},	{1,33,0},	{2,33,0},	{3,33,0},	{4,33,0},	{5,33,1},	{6,33,1},	{7,33,1},	{8,33,1},	{9,33,1},	{10,33,1},	{11,33,1},	{12,33,1},	{13,33,1},	{14,33,1},	{15,33,1},	{16,33,1},	{17,33,1},	{18,33,1},	{19,33,1},	{20,33,1},	{21,33,1},	{22,33,1},	{23,33,1},	{24,33,1},	{25,33,1},	{26,33,1},	{27,33,1},	{28,33,1},	{29,33,1},	{30,33,1},	{31,33,1},	{32,33,1},	{33,33,1},	{34,33,1},	{35,33,1},	{36,33,1},	{37,33,1},	{38,33,1},	{39,33,1},	{40,33,1},	{41,33,1},	{42,33,1},	{43,33,1},	{44,33,1},	{45,33,1},	{46,33,1},	{47,33,1},	{48,33,1},	{49,33,1},	{50,33,1},	{51,33,1},	{52,33,1},	{53,33,1},	{54,33,1},	{55,33,1},	{56,33,1},	{57,33,1},	{58,33,1},	{59,33,1},	{60,33,1},	{61,33,1},	{62,33,1},	{63,33,1},	{64,33,1},	{65,33,0},	{66,33,0},	{67,33,0},	{68,33,0},	{69,33,0},
+	 {0,34,0},	{1,34,0},	{2,34,0},	{3,34,0},	{4,34,0},	{5,34,1},	{6,34,1},	{7,34,1},	{8,34,1},	{9,34,1},	{10,34,1},	{11,34,1},	{12,34,1},	{13,34,1},	{14,34,1},	{15,34,1},	{16,34,1},	{17,34,1},	{18,34,1},	{19,34,1},	{20,34,1},	{21,34,1},	{22,34,1},	{23,34,1},	{24,34,1},	{25,34,1},	{26,34,1},	{27,34,1},	{28,34,1},	{29,34,1},	{30,34,1},	{31,34,1},	{32,34,1},	{33,34,1},	{34,34,1},	{35,34,1},	{36,34,1},	{37,34,1},	{38,34,1},	{39,34,1},	{40,34,1},	{41,34,1},	{42,34,1},	{43,34,1},	{44,34,1},	{45,34,1},	{46,34,1},	{47,34,1},	{48,34,1},	{49,34,1},	{50,34,1},	{51,34,1},	{52,34,1},	{53,34,1},	{54,34,1},	{55,34,1},	{56,34,1},	{57,34,1},	{58,34,1},	{59,34,1},	{60,34,1},	{61,34,1},	{62,34,1},	{63,34,1},	{64,34,1},	{65,34,0},	{66,34,0},	{67,34,0},	{68,34,0},	{69,34,0},
+	 {0,35,0},	{1,35,0},	{2,35,0},	{3,35,0},	{4,35,0},	{5,35,1},	{6,35,1},	{7,35,1},	{8,35,1},	{9,35,1},	{10,35,1},	{11,35,1},	{12,35,1},	{13,35,1},	{14,35,1},	{15,35,1},	{16,35,1},	{17,35,1},	{18,35,1},	{19,35,1},	{20,35,1},	{21,35,1},	{22,35,1},	{23,35,1},	{24,35,1},	{25,35,1},	{26,35,1},	{27,35,1},	{28,35,1},	{29,35,1},	{30,35,1},	{31,35,1},	{32,35,1},	{33,35,1},	{34,35,1},	{35,35,1},	{36,35,1},	{37,35,1},	{38,35,1},	{39,35,1},	{40,35,1},	{41,35,1},	{42,35,1},	{43,35,1},	{44,35,1},	{45,35,1},	{46,35,1},	{47,35,1},	{48,35,1},	{49,35,1},	{50,35,1},	{51,35,1},	{52,35,1},	{53,35,1},	{54,35,1},	{55,35,1},	{56,35,1},	{57,35,1},	{58,35,1},	{59,35,1},	{60,35,1},	{61,35,1},	{62,35,1},	{63,35,1},	{64,35,1},	{65,35,0},	{66,35,0},	{67,35,0},	{68,35,0},	{69,35,0},
+	 {0,36,0},	{1,36,0},	{2,36,0},	{3,36,0},	{4,36,0},	{5,36,1},	{6,36,1},	{7,36,1},	{8,36,1},	{9,36,1},	{10,36,1},	{11,36,1},	{12,36,1},	{13,36,1},	{14,36,1},	{15,36,1},	{16,36,1},	{17,36,1},	{18,36,1},	{19,36,1},	{20,36,1},	{21,36,1},	{22,36,1},	{23,36,1},	{24,36,1},	{25,36,1},	{26,36,1},	{27,36,1},	{28,36,1},	{29,36,1},	{30,36,1},	{31,36,1},	{32,36,1},	{33,36,1},	{34,36,1},	{35,36,1},	{36,36,1},	{37,36,1},	{38,36,1},	{39,36,1},	{40,36,1},	{41,36,1},	{42,36,1},	{43,36,1},	{44,36,1},	{45,36,1},	{46,36,1},	{47,36,1},	{48,36,1},	{49,36,1},	{50,36,1},	{51,36,1},	{52,36,1},	{53,36,1},	{54,36,1},	{55,36,1},	{56,36,1},	{57,36,1},	{58,36,1},	{59,36,1},	{60,36,1},	{61,36,1},	{62,36,1},	{63,36,1},	{64,36,1},	{65,36,0},	{66,36,0},	{67,36,0},	{68,36,0},	{69,36,0},
+	 {0,37,0},	{1,37,0},	{2,37,0},	{3,37,0},	{4,37,0},	{5,37,1},	{6,37,1},	{7,37,1},	{8,37,1},	{9,37,1},	{10,37,1},	{11,37,1},	{12,37,1},	{13,37,1},	{14,37,1},	{15,37,1},	{16,37,1},	{17,37,1},	{18,37,1},	{19,37,1},	{20,37,1},	{21,37,1},	{22,37,1},	{23,37,1},	{24,37,1},	{25,37,1},	{26,37,1},	{27,37,1},	{28,37,1},	{29,37,1},	{30,37,1},	{31,37,1},	{32,37,1},	{33,37,1},	{34,37,1},	{35,37,1},	{36,37,1},	{37,37,1},	{38,37,1},	{39,37,1},	{40,37,1},	{41,37,1},	{42,37,1},	{43,37,1},	{44,37,1},	{45,37,1},	{46,37,1},	{47,37,1},	{48,37,1},	{49,37,1},	{50,37,1},	{51,37,1},	{52,37,1},	{53,37,1},	{54,37,1},	{55,37,1},	{56,37,1},	{57,37,1},	{58,37,1},	{59,37,1},	{60,37,1},	{61,37,1},	{62,37,1},	{63,37,1},	{64,37,1},	{65,37,0},	{66,37,0},	{67,37,0},	{68,37,0},	{69,37,0},
+	 {0,38,0},	{1,38,0},	{2,38,0},	{3,38,0},	{4,38,0},	{5,38,1},	{6,38,1},	{7,38,1},	{8,38,1},	{9,38,1},	{10,38,1},	{11,38,1},	{12,38,1},	{13,38,1},	{14,38,1},	{15,38,1},	{16,38,1},	{17,38,1},	{18,38,1},	{19,38,1},	{20,38,1},	{21,38,1},	{22,38,1},	{23,38,1},	{24,38,1},	{25,38,1},	{26,38,1},	{27,38,1},	{28,38,1},	{29,38,1},	{30,38,1},	{31,38,1},	{32,38,1},	{33,38,1},	{34,38,1},	{35,38,1},	{36,38,1},	{37,38,1},	{38,38,1},	{39,38,1},	{40,38,1},	{41,38,1},	{42,38,1},	{43,38,1},	{44,38,1},	{45,38,1},	{46,38,1},	{47,38,1},	{48,38,1},	{49,38,1},	{50,38,1},	{51,38,1},	{52,38,1},	{53,38,1},	{54,38,1},	{55,38,1},	{56,38,1},	{57,38,1},	{58,38,1},	{59,38,1},	{60,38,1},	{61,38,1},	{62,38,1},	{63,38,1},	{64,38,1},	{65,38,0},	{66,38,0},	{67,38,0},	{68,38,0},	{69,38,0},
+	 {0,39,0},	{1,39,0},	{2,39,0},	{3,39,0},	{4,39,0},	{5,39,1},	{6,39,1},	{7,39,1},	{8,39,1},	{9,39,1},	{10,39,1},	{11,39,1},	{12,39,1},	{13,39,1},	{14,39,1},	{15,39,1},	{16,39,1},	{17,39,1},	{18,39,1},	{19,39,1},	{20,39,1},	{21,39,1},	{22,39,1},	{23,39,1},	{24,39,1},	{25,39,1},	{26,39,1},	{27,39,1},	{28,39,1},	{29,39,1},	{30,39,1},	{31,39,1},	{32,39,1},	{33,39,1},	{34,39,1},	{35,39,1},	{36,39,1},	{37,39,1},	{38,39,1},	{39,39,1},	{40,39,1},	{41,39,1},	{42,39,1},	{43,39,1},	{44,39,1},	{45,39,1},	{46,39,1},	{47,39,1},	{48,39,1},	{49,39,1},	{50,39,1},	{51,39,1},	{52,39,1},	{53,39,1},	{54,39,1},	{55,39,1},	{56,39,1},	{57,39,1},	{58,39,1},	{59,39,1},	{60,39,1},	{61,39,1},	{62,39,1},	{63,39,1},	{64,39,0},	{65,39,0},	{66,39,0},	{67,39,0},	{68,39,0},	{69,39,0},
+	 {0,40,0},	{1,40,0},	{2,40,0},	{3,40,0},	{4,40,0},	{5,40,0},	{6,40,1},	{7,40,1},	{8,40,1},	{9,40,1},	{10,40,1},	{11,40,1},	{12,40,1},	{13,40,1},	{14,40,1},	{15,40,1},	{16,40,1},	{17,40,1},	{18,40,1},	{19,40,1},	{20,40,1},	{21,40,1},	{22,40,1},	{23,40,1},	{24,40,1},	{25,40,1},	{26,40,1},	{27,40,1},	{28,40,1},	{29,40,1},	{30,40,1},	{31,40,1},	{32,40,1},	{33,40,1},	{34,40,1},	{35,40,1},	{36,40,1},	{37,40,1},	{38,40,1},	{39,40,1},	{40,40,1},	{41,40,1},	{42,40,1},	{43,40,1},	{44,40,1},	{45,40,1},	{46,40,1},	{47,40,1},	{48,40,1},	{49,40,1},	{50,40,1},	{51,40,1},	{52,40,1},	{53,40,1},	{54,40,1},	{55,40,1},	{56,40,1},	{57,40,1},	{58,40,1},	{59,40,1},	{60,40,1},	{61,40,1},	{62,40,1},	{63,40,1},	{64,40,0},	{65,40,0},	{66,40,0},	{67,40,0},	{68,40,0},	{69,40,0},
+	 {0,41,0},	{1,41,0},	{2,41,0},	{3,41,0},	{4,41,0},	{5,41,0},	{6,41,1},	{7,41,1},	{8,41,1},	{9,41,1},	{10,41,1},	{11,41,1},	{12,41,1},	{13,41,1},	{14,41,1},	{15,41,1},	{16,41,1},	{17,41,1},	{18,41,1},	{19,41,1},	{20,41,1},	{21,41,1},	{22,41,1},	{23,41,1},	{24,41,1},	{25,41,1},	{26,41,1},	{27,41,1},	{28,41,1},	{29,41,1},	{30,41,1},	{31,41,1},	{32,41,1},	{33,41,1},	{34,41,1},	{35,41,1},	{36,41,1},	{37,41,1},	{38,41,1},	{39,41,1},	{40,41,1},	{41,41,1},	{42,41,1},	{43,41,1},	{44,41,1},	{45,41,1},	{46,41,1},	{47,41,1},	{48,41,1},	{49,41,1},	{50,41,1},	{51,41,1},	{52,41,1},	{53,41,1},	{54,41,1},	{55,41,1},	{56,41,1},	{57,41,1},	{58,41,1},	{59,41,1},	{60,41,1},	{61,41,1},	{62,41,1},	{63,41,1},	{64,41,0},	{65,41,0},	{66,41,0},	{67,41,0},	{68,41,0},	{69,41,0},
+	 {0,42,0},	{1,42,0},	{2,42,0},	{3,42,0},	{4,42,0},	{5,42,0},	{6,42,1},	{7,42,1},	{8,42,1},	{9,42,1},	{10,42,1},	{11,42,1},	{12,42,1},	{13,42,1},	{14,42,1},	{15,42,1},	{16,42,1},	{17,42,1},	{18,42,1},	{19,42,1},	{20,42,1},	{21,42,1},	{22,42,1},	{23,42,1},	{24,42,1},	{25,42,1},	{26,42,1},	{27,42,1},	{28,42,1},	{29,42,1},	{30,42,1},	{31,42,1},	{32,42,1},	{33,42,1},	{34,42,1},	{35,42,1},	{36,42,1},	{37,42,1},	{38,42,1},	{39,42,1},	{40,42,1},	{41,42,1},	{42,42,1},	{43,42,1},	{44,42,1},	{45,42,1},	{46,42,1},	{47,42,1},	{48,42,1},	{49,42,1},	{50,42,1},	{51,42,1},	{52,42,1},	{53,42,1},	{54,42,1},	{55,42,1},	{56,42,1},	{57,42,1},	{58,42,1},	{59,42,1},	{60,42,1},	{61,42,1},	{62,42,1},	{63,42,0},	{64,42,0},	{65,42,0},	{66,42,0},	{67,42,0},	{68,42,0},	{69,42,0},
+	 {0,43,0},	{1,43,0},	{2,43,0},	{3,43,0},	{4,43,0},	{5,43,0},	{6,43,0},	{7,43,1},	{8,43,1},	{9,43,1},	{10,43,1},	{11,43,1},	{12,43,1},	{13,43,1},	{14,43,1},	{15,43,1},	{16,43,1},	{17,43,1},	{18,43,1},	{19,43,1},	{20,43,1},	{21,43,1},	{22,43,1},	{23,43,1},	{24,43,1},	{25,43,1},	{26,43,1},	{27,43,1},	{28,43,1},	{29,43,1},	{30,43,1},	{31,43,1},	{32,43,1},	{33,43,1},	{34,43,1},	{35,43,1},	{36,43,1},	{37,43,1},	{38,43,1},	{39,43,1},	{40,43,1},	{41,43,1},	{42,43,1},	{43,43,1},	{44,43,1},	{45,43,1},	{46,43,1},	{47,43,1},	{48,43,1},	{49,43,1},	{50,43,1},	{51,43,1},	{52,43,1},	{53,43,1},	{54,43,1},	{55,43,1},	{56,43,1},	{57,43,1},	{58,43,1},	{59,43,1},	{60,43,1},	{61,43,1},	{62,43,1},	{63,43,0},	{64,43,0},	{65,43,0},	{66,43,0},	{67,43,0},	{68,43,0},	{69,43,0},
+	 {0,44,0},	{1,44,0},	{2,44,0},	{3,44,0},	{4,44,0},	{5,44,0},	{6,44,0},	{7,44,1},	{8,44,1},	{9,44,1},	{10,44,1},	{11,44,1},	{12,44,1},	{13,44,1},	{14,44,1},	{15,44,1},	{16,44,1},	{17,44,1},	{18,44,1},	{19,44,1},	{20,44,1},	{21,44,1},	{22,44,1},	{23,44,1},	{24,44,1},	{25,44,1},	{26,44,1},	{27,44,1},	{28,44,1},	{29,44,1},	{30,44,1},	{31,44,1},	{32,44,1},	{33,44,1},	{34,44,1},	{35,44,1},	{36,44,1},	{37,44,1},	{38,44,1},	{39,44,1},	{40,44,1},	{41,44,1},	{42,44,1},	{43,44,1},	{44,44,1},	{45,44,1},	{46,44,1},	{47,44,1},	{48,44,1},	{49,44,1},	{50,44,1},	{51,44,1},	{52,44,1},	{53,44,1},	{54,44,1},	{55,44,1},	{56,44,1},	{57,44,1},	{58,44,1},	{59,44,1},	{60,44,1},	{61,44,1},	{62,44,1},	{63,44,0},	{64,44,0},	{65,44,0},	{66,44,0},	{67,44,0},	{68,44,0},	{69,44,0},
+	 {0,45,0},	{1,45,0},	{2,45,0},	{3,45,0},	{4,45,0},	{5,45,0},	{6,45,0},	{7,45,1},	{8,45,1},	{9,45,1},	{10,45,1},	{11,45,1},	{12,45,1},	{13,45,1},	{14,45,1},	{15,45,1},	{16,45,1},	{17,45,1},	{18,45,1},	{19,45,1},	{20,45,1},	{21,45,1},	{22,45,1},	{23,45,1},	{24,45,1},	{25,45,1},	{26,45,1},	{27,45,1},	{28,45,1},	{29,45,1},	{30,45,1},	{31,45,1},	{32,45,1},	{33,45,1},	{34,45,1},	{35,45,1},	{36,45,1},	{37,45,1},	{38,45,1},	{39,45,1},	{40,45,1},	{41,45,1},	{42,45,1},	{43,45,1},	{44,45,1},	{45,45,1},	{46,45,1},	{47,45,1},	{48,45,1},	{49,45,1},	{50,45,1},	{51,45,1},	{52,45,1},	{53,45,1},	{54,45,1},	{55,45,1},	{56,45,1},	{57,45,1},	{58,45,1},	{59,45,1},	{60,45,1},	{61,45,1},	{62,45,1},	{63,45,0},	{64,45,0},	{65,45,0},	{66,45,0},	{67,45,0},	{68,45,0},	{69,45,0},
+	 {0,46,0},	{1,46,0},	{2,46,0},	{3,46,0},	{4,46,0},	{5,46,0},	{6,46,0},	{7,46,1},	{8,46,1},	{9,46,1},	{10,46,1},	{11,46,1},	{12,46,1},	{13,46,1},	{14,46,1},	{15,46,1},	{16,46,1},	{17,46,1},	{18,46,1},	{19,46,1},	{20,46,1},	{21,46,1},	{22,46,1},	{23,46,1},	{24,46,1},	{25,46,1},	{26,46,1},	{27,46,1},	{28,46,1},	{29,46,1},	{30,46,1},	{31,46,1},	{32,46,1},	{33,46,1},	{34,46,1},	{35,46,1},	{36,46,1},	{37,46,1},	{38,46,1},	{39,46,1},	{40,46,1},	{41,46,1},	{42,46,1},	{43,46,1},	{44,46,1},	{45,46,1},	{46,46,1},	{47,46,1},	{48,46,1},	{49,46,1},	{50,46,1},	{51,46,1},	{52,46,1},	{53,46,1},	{54,46,1},	{55,46,1},	{56,46,1},	{57,46,1},	{58,46,1},	{59,46,1},	{60,46,1},	{61,46,1},	{62,46,1},	{63,46,0},	{64,46,0},	{65,46,0},	{66,46,0},	{67,46,0},	{68,46,0},	{69,46,0},
+	 {0,47,0},	{1,47,0},	{2,47,0},	{3,47,0},	{4,47,0},	{5,47,0},	{6,47,0},	{7,47,0},	{8,47,1},	{9,47,1},	{10,47,1},	{11,47,1},	{12,47,1},	{13,47,1},	{14,47,1},	{15,47,1},	{16,47,1},	{17,47,1},	{18,47,1},	{19,47,1},	{20,47,1},	{21,47,1},	{22,47,1},	{23,47,1},	{24,47,1},	{25,47,1},	{26,47,1},	{27,47,1},	{28,47,1},	{29,47,1},	{30,47,1},	{31,47,1},	{32,47,1},	{33,47,1},	{34,47,1},	{35,47,1},	{36,47,1},	{37,47,1},	{38,47,1},	{39,47,1},	{40,47,1},	{41,47,1},	{42,47,1},	{43,47,1},	{44,47,1},	{45,47,1},	{46,47,1},	{47,47,1},	{48,47,1},	{49,47,1},	{50,47,1},	{51,47,1},	{52,47,1},	{53,47,1},	{54,47,1},	{55,47,1},	{56,47,1},	{57,47,1},	{58,47,1},	{59,47,1},	{60,47,1},	{61,47,1},	{62,47,0},	{63,47,0},	{64,47,0},	{65,47,0},	{66,47,0},	{67,47,0},	{68,47,0},	{69,47,0},
+	 {0,48,0},	{1,48,0},	{2,48,0},	{3,48,0},	{4,48,0},	{5,48,0},	{6,48,0},	{7,48,0},	{8,48,1},	{9,48,1},	{10,48,1},	{11,48,1},	{12,48,1},	{13,48,1},	{14,48,1},	{15,48,1},	{16,48,1},	{17,48,1},	{18,48,1},	{19,48,1},	{20,48,1},	{21,48,1},	{22,48,1},	{23,48,1},	{24,48,1},	{25,48,1},	{26,48,1},	{27,48,1},	{28,48,1},	{29,48,1},	{30,48,1},	{31,48,1},	{32,48,1},	{33,48,1},	{34,48,1},	{35,48,1},	{36,48,1},	{37,48,1},	{38,48,1},	{39,48,1},	{40,48,1},	{41,48,1},	{42,48,1},	{43,48,1},	{44,48,1},	{45,48,1},	{46,48,1},	{47,48,1},	{48,48,1},	{49,48,1},	{50,48,1},	{51,48,1},	{52,48,1},	{53,48,1},	{54,48,1},	{55,48,1},	{56,48,1},	{57,48,1},	{58,48,1},	{59,48,1},	{60,48,1},	{61,48,1},	{62,48,0},	{63,48,0},	{64,48,0},	{65,48,0},	{66,48,0},	{67,48,0},	{68,48,0},	{69,48,0},
+	 {0,49,0},	{1,49,0},	{2,49,0},	{3,49,0},	{4,49,0},	{5,49,0},	{6,49,0},	{7,49,0},	{8,49,0},	{9,49,1},	{10,49,1},	{11,49,1},	{12,49,1},	{13,49,1},	{14,49,1},	{15,49,1},	{16,49,1},	{17,49,1},	{18,49,1},	{19,49,1},	{20,49,1},	{21,49,1},	{22,49,1},	{23,49,1},	{24,49,1},	{25,49,1},	{26,49,1},	{27,49,1},	{28,49,1},	{29,49,1},	{30,49,1},	{31,49,1},	{32,49,1},	{33,49,1},	{34,49,1},	{35,49,1},	{36,49,1},	{37,49,1},	{38,49,1},	{39,49,1},	{40,49,1},	{41,49,1},	{42,49,1},	{43,49,1},	{44,49,1},	{45,49,1},	{46,49,1},	{47,49,1},	{48,49,1},	{49,49,1},	{50,49,1},	{51,49,1},	{52,49,1},	{53,49,1},	{54,49,1},	{55,49,1},	{56,49,1},	{57,49,1},	{58,49,1},	{59,49,1},	{60,49,1},	{61,49,0},	{62,49,0},	{63,49,0},	{64,49,0},	{65,49,0},	{66,49,0},	{67,49,0},	{68,49,0},	{69,49,0},
+	 {0,50,0},	{1,50,0},	{2,50,0},	{3,50,0},	{4,50,0},	{5,50,0},	{6,50,0},	{7,50,0},	{8,50,0},	{9,50,1},	{10,50,1},	{11,50,1},	{12,50,1},	{13,50,1},	{14,50,1},	{15,50,1},	{16,50,1},	{17,50,1},	{18,50,1},	{19,50,1},	{20,50,1},	{21,50,1},	{22,50,1},	{23,50,1},	{24,50,1},	{25,50,1},	{26,50,1},	{27,50,1},	{28,50,1},	{29,50,1},	{30,50,1},	{31,50,1},	{32,50,1},	{33,50,1},	{34,50,1},	{35,50,1},	{36,50,1},	{37,50,1},	{38,50,1},	{39,50,1},	{40,50,1},	{41,50,1},	{42,50,1},	{43,50,1},	{44,50,1},	{45,50,1},	{46,50,1},	{47,50,1},	{48,50,1},	{49,50,1},	{50,50,1},	{51,50,1},	{52,50,1},	{53,50,1},	{54,50,1},	{55,50,1},	{56,50,1},	{57,50,1},	{58,50,1},	{59,50,1},	{60,50,1},	{61,50,0},	{62,50,0},	{63,50,0},	{64,50,0},	{65,50,0},	{66,50,0},	{67,50,0},	{68,50,0},	{69,50,0},
+	 {0,51,0},	{1,51,0},	{2,51,0},	{3,51,0},	{4,51,0},	{5,51,0},	{6,51,0},	{7,51,0},	{8,51,0},	{9,51,0},	{10,51,1},	{11,51,1},	{12,51,1},	{13,51,1},	{14,51,1},	{15,51,1},	{16,51,1},	{17,51,1},	{18,51,1},	{19,51,1},	{20,51,1},	{21,51,1},	{22,51,1},	{23,51,1},	{24,51,1},	{25,51,1},	{26,51,1},	{27,51,1},	{28,51,1},	{29,51,1},	{30,51,1},	{31,51,1},	{32,51,1},	{33,51,1},	{34,51,1},	{35,51,1},	{36,51,1},	{37,51,1},	{38,51,1},	{39,51,1},	{40,51,1},	{41,51,1},	{42,51,1},	{43,51,1},	{44,51,1},	{45,51,1},	{46,51,1},	{47,51,1},	{48,51,1},	{49,51,1},	{50,51,1},	{51,51,1},	{52,51,1},	{53,51,1},	{54,51,1},	{55,51,1},	{56,51,1},	{57,51,1},	{58,51,1},	{59,51,1},	{60,51,0},	{61,51,0},	{62,51,0},	{63,51,0},	{64,51,0},	{65,51,0},	{66,51,0},	{67,51,0},	{68,51,0},	{69,51,0},
+	 {0,52,0},	{1,52,0},	{2,52,0},	{3,52,0},	{4,52,0},	{5,52,0},	{6,52,0},	{7,52,0},	{8,52,0},	{9,52,0},	{10,52,1},	{11,52,1},	{12,52,1},	{13,52,1},	{14,52,1},	{15,52,1},	{16,52,1},	{17,52,1},	{18,52,1},	{19,52,1},	{20,52,1},	{21,52,1},	{22,52,1},	{23,52,1},	{24,52,1},	{25,52,1},	{26,52,1},	{27,52,1},	{28,52,1},	{29,52,1},	{30,52,1},	{31,52,1},	{32,52,1},	{33,52,1},	{34,52,1},	{35,52,1},	{36,52,1},	{37,52,1},	{38,52,1},	{39,52,1},	{40,52,1},	{41,52,1},	{42,52,1},	{43,52,1},	{44,52,1},	{45,52,1},	{46,52,1},	{47,52,1},	{48,52,1},	{49,52,1},	{50,52,1},	{51,52,1},	{52,52,1},	{53,52,1},	{54,52,1},	{55,52,1},	{56,52,1},	{57,52,1},	{58,52,1},	{59,52,1},	{60,52,0},	{61,52,0},	{62,52,0},	{63,52,0},	{64,52,0},	{65,52,0},	{66,52,0},	{67,52,0},	{68,52,0},	{69,52,0},
+	 {0,53,0},	{1,53,0},	{2,53,0},	{3,53,0},	{4,53,0},	{5,53,0},	{6,53,0},	{7,53,0},	{8,53,0},	{9,53,0},	{10,53,0},	{11,53,1},	{12,53,1},	{13,53,1},	{14,53,1},	{15,53,1},	{16,53,1},	{17,53,1},	{18,53,1},	{19,53,1},	{20,53,1},	{21,53,1},	{22,53,1},	{23,53,1},	{24,53,1},	{25,53,1},	{26,53,1},	{27,53,1},	{28,53,1},	{29,53,1},	{30,53,1},	{31,53,1},	{32,53,1},	{33,53,1},	{34,53,1},	{35,53,1},	{36,53,1},	{37,53,1},	{38,53,1},	{39,53,1},	{40,53,1},	{41,53,1},	{42,53,1},	{43,53,1},	{44,53,1},	{45,53,1},	{46,53,1},	{47,53,1},	{48,53,1},	{49,53,1},	{50,53,1},	{51,53,1},	{52,53,1},	{53,53,1},	{54,53,1},	{55,53,1},	{56,53,1},	{57,53,1},	{58,53,1},	{59,53,0},	{60,53,0},	{61,53,0},	{62,53,0},	{63,53,0},	{64,53,0},	{65,53,0},	{66,53,0},	{67,53,0},	{68,53,0},	{69,53,0},
+	 {0,54,0},	{1,54,0},	{2,54,0},	{3,54,0},	{4,54,0},	{5,54,0},	{6,54,0},	{7,54,0},	{8,54,0},	{9,54,0},	{10,54,0},	{11,54,1},	{12,54,1},	{13,54,1},	{14,54,1},	{15,54,1},	{16,54,1},	{17,54,1},	{18,54,1},	{19,54,1},	{20,54,1},	{21,54,1},	{22,54,1},	{23,54,1},	{24,54,1},	{25,54,1},	{26,54,1},	{27,54,1},	{28,54,1},	{29,54,1},	{30,54,1},	{31,54,1},	{32,54,1},	{33,54,1},	{34,54,1},	{35,54,1},	{36,54,1},	{37,54,1},	{38,54,1},	{39,54,1},	{40,54,1},	{41,54,1},	{42,54,1},	{43,54,1},	{44,54,1},	{45,54,1},	{46,54,1},	{47,54,1},	{48,54,1},	{49,54,1},	{50,54,1},	{51,54,1},	{52,54,1},	{53,54,1},	{54,54,1},	{55,54,1},	{56,54,1},	{57,54,1},	{58,54,1},	{59,54,0},	{60,54,0},	{61,54,0},	{62,54,0},	{63,54,0},	{64,54,0},	{65,54,0},	{66,54,0},	{67,54,0},	{68,54,0},	{69,54,0},
+	 {0,55,0},	{1,55,0},	{2,55,0},	{3,55,0},	{4,55,0},	{5,55,0},	{6,55,0},	{7,55,0},	{8,55,0},	{9,55,0},	{10,55,0},	{11,55,0},	{12,55,1},	{13,55,1},	{14,55,1},	{15,55,1},	{16,55,1},	{17,55,1},	{18,55,1},	{19,55,1},	{20,55,1},	{21,55,1},	{22,55,1},	{23,55,1},	{24,55,1},	{25,55,1},	{26,55,1},	{27,55,1},	{28,55,1},	{29,55,1},	{30,55,1},	{31,55,1},	{32,55,1},	{33,55,1},	{34,55,1},	{35,55,1},	{36,55,1},	{37,55,1},	{38,55,1},	{39,55,1},	{40,55,1},	{41,55,1},	{42,55,1},	{43,55,1},	{44,55,1},	{45,55,1},	{46,55,1},	{47,55,1},	{48,55,1},	{49,55,1},	{50,55,1},	{51,55,1},	{52,55,1},	{53,55,1},	{54,55,1},	{55,55,1},	{56,55,1},	{57,55,1},	{58,55,0},	{59,55,0},	{60,55,0},	{61,55,0},	{62,55,0},	{63,55,0},	{64,55,0},	{65,55,0},	{66,55,0},	{67,55,0},	{68,55,0},	{69,55,0},
+	 {0,56,0},	{1,56,0},	{2,56,0},	{3,56,0},	{4,56,0},	{5,56,0},	{6,56,0},	{7,56,0},	{8,56,0},	{9,56,0},	{10,56,0},	{11,56,0},	{12,56,0},	{13,56,1},	{14,56,1},	{15,56,1},	{16,56,1},	{17,56,1},	{18,56,1},	{19,56,1},	{20,56,1},	{21,56,1},	{22,56,1},	{23,56,1},	{24,56,1},	{25,56,1},	{26,56,1},	{27,56,1},	{28,56,1},	{29,56,1},	{30,56,1},	{31,56,1},	{32,56,1},	{33,56,1},	{34,56,1},	{35,56,1},	{36,56,1},	{37,56,1},	{38,56,1},	{39,56,1},	{40,56,1},	{41,56,1},	{42,56,1},	{43,56,1},	{44,56,1},	{45,56,1},	{46,56,1},	{47,56,1},	{48,56,1},	{49,56,1},	{50,56,1},	{51,56,1},	{52,56,1},	{53,56,1},	{54,56,1},	{55,56,1},	{56,56,1},	{57,56,0},	{58,56,0},	{59,56,0},	{60,56,0},	{61,56,0},	{62,56,0},	{63,56,0},	{64,56,0},	{65,56,0},	{66,56,0},	{67,56,0},	{68,56,0},	{69,56,0},
+	 {0,57,0},	{1,57,0},	{2,57,0},	{3,57,0},	{4,57,0},	{5,57,0},	{6,57,0},	{7,57,0},	{8,57,0},	{9,57,0},	{10,57,0},	{11,57,0},	{12,57,0},	{13,57,0},	{14,57,1},	{15,57,1},	{16,57,1},	{17,57,1},	{18,57,1},	{19,57,1},	{20,57,1},	{21,57,1},	{22,57,1},	{23,57,1},	{24,57,1},	{25,57,1},	{26,57,1},	{27,57,1},	{28,57,1},	{29,57,1},	{30,57,1},	{31,57,1},	{32,57,1},	{33,57,1},	{34,57,1},	{35,57,1},	{36,57,1},	{37,57,1},	{38,57,1},	{39,57,1},	{40,57,1},	{41,57,1},	{42,57,1},	{43,57,1},	{44,57,1},	{45,57,1},	{46,57,1},	{47,57,1},	{48,57,1},	{49,57,1},	{50,57,1},	{51,57,1},	{52,57,1},	{53,57,1},	{54,57,1},	{55,57,1},	{56,57,0},	{57,57,0},	{58,57,0},	{59,57,0},	{60,57,0},	{61,57,0},	{62,57,0},	{63,57,0},	{64,57,0},	{65,57,0},	{66,57,0},	{67,57,0},	{68,57,0},	{69,57,0},
+	 {0,58,0},	{1,58,0},	{2,58,0},	{3,58,0},	{4,58,0},	{5,58,0},	{6,58,0},	{7,58,0},	{8,58,0},	{9,58,0},	{10,58,0},	{11,58,0},	{12,58,0},	{13,58,0},	{14,58,0},	{15,58,1},	{16,58,1},	{17,58,1},	{18,58,1},	{19,58,1},	{20,58,1},	{21,58,1},	{22,58,1},	{23,58,1},	{24,58,1},	{25,58,1},	{26,58,1},	{27,58,1},	{28,58,1},	{29,58,1},	{30,58,1},	{31,58,1},	{32,58,1},	{33,58,1},	{34,58,1},	{35,58,1},	{36,58,1},	{37,58,1},	{38,58,1},	{39,58,1},	{40,58,1},	{41,58,1},	{42,58,1},	{43,58,1},	{44,58,1},	{45,58,1},	{46,58,1},	{47,58,1},	{48,58,1},	{49,58,1},	{50,58,1},	{51,58,1},	{52,58,1},	{53,58,1},	{54,58,1},	{55,58,0},	{56,58,0},	{57,58,0},	{58,58,0},	{59,58,0},	{60,58,0},	{61,58,0},	{62,58,0},	{63,58,0},	{64,58,0},	{65,58,0},	{66,58,0},	{67,58,0},	{68,58,0},	{69,58,0},
+	 {0,59,0},	{1,59,0},	{2,59,0},	{3,59,0},	{4,59,0},	{5,59,0},	{6,59,0},	{7,59,0},	{8,59,0},	{9,59,0},	{10,59,0},	{11,59,0},	{12,59,0},	{13,59,0},	{14,59,0},	{15,59,0},	{16,59,1},	{17,59,1},	{18,59,1},	{19,59,1},	{20,59,1},	{21,59,1},	{22,59,1},	{23,59,1},	{24,59,1},	{25,59,1},	{26,59,1},	{27,59,1},	{28,59,1},	{29,59,1},	{30,59,1},	{31,59,1},	{32,59,1},	{33,59,1},	{34,59,1},	{35,59,1},	{36,59,1},	{37,59,1},	{38,59,1},	{39,59,1},	{40,59,1},	{41,59,1},	{42,59,1},	{43,59,1},	{44,59,1},	{45,59,1},	{46,59,1},	{47,59,1},	{48,59,1},	{49,59,1},	{50,59,1},	{51,59,1},	{52,59,1},	{53,59,1},	{54,59,0},	{55,59,0},	{56,59,0},	{57,59,0},	{58,59,0},	{59,59,0},	{60,59,0},	{61,59,0},	{62,59,0},	{63,59,0},	{64,59,0},	{65,59,0},	{66,59,0},	{67,59,0},	{68,59,0},	{69,59,0},
+	 {0,60,0},	{1,60,0},	{2,60,0},	{3,60,0},	{4,60,0},	{5,60,0},	{6,60,0},	{7,60,0},	{8,60,0},	{9,60,0},	{10,60,0},	{11,60,0},	{12,60,0},	{13,60,0},	{14,60,0},	{15,60,0},	{16,60,0},	{17,60,1},	{18,60,1},	{19,60,1},	{20,60,1},	{21,60,1},	{22,60,1},	{23,60,1},	{24,60,1},	{25,60,1},	{26,60,1},	{27,60,1},	{28,60,1},	{29,60,1},	{30,60,1},	{31,60,1},	{32,60,1},	{33,60,1},	{34,60,1},	{35,60,1},	{36,60,1},	{37,60,1},	{38,60,1},	{39,60,1},	{40,60,1},	{41,60,1},	{42,60,1},	{43,60,1},	{44,60,1},	{45,60,1},	{46,60,1},	{47,60,1},	{48,60,1},	{49,60,1},	{50,60,1},	{51,60,1},	{52,60,1},	{53,60,0},	{54,60,0},	{55,60,0},	{56,60,0},	{57,60,0},	{58,60,0},	{59,60,0},	{60,60,0},	{61,60,0},	{62,60,0},	{63,60,0},	{64,60,0},	{65,60,0},	{66,60,0},	{67,60,0},	{68,60,0},	{69,60,0},
+	 {0,61,0},	{1,61,0},	{2,61,0},	{3,61,0},	{4,61,0},	{5,61,0},	{6,61,0},	{7,61,0},	{8,61,0},	{9,61,0},	{10,61,0},	{11,61,0},	{12,61,0},	{13,61,0},	{14,61,0},	{15,61,0},	{16,61,0},	{17,61,0},	{18,61,1},	{19,61,1},	{20,61,1},	{21,61,1},	{22,61,1},	{23,61,1},	{24,61,1},	{25,61,1},	{26,61,1},	{27,61,1},	{28,61,1},	{29,61,1},	{30,61,1},	{31,61,1},	{32,61,1},	{33,61,1},	{34,61,1},	{35,61,1},	{36,61,1},	{37,61,1},	{38,61,1},	{39,61,1},	{40,61,1},	{41,61,1},	{42,61,1},	{43,61,1},	{44,61,1},	{45,61,1},	{46,61,1},	{47,61,1},	{48,61,1},	{49,61,1},	{50,61,1},	{51,61,0},	{52,61,0},	{53,61,0},	{54,61,0},	{55,61,0},	{56,61,0},	{57,61,0},	{58,61,0},	{59,61,0},	{60,61,0},	{61,61,0},	{62,61,0},	{63,61,0},	{64,61,0},	{65,61,0},	{66,61,0},	{67,61,0},	{68,61,0},	{69,61,0},
+	 {0,62,0},	{1,62,0},	{2,62,0},	{3,62,0},	{4,62,0},	{5,62,0},	{6,62,0},	{7,62,0},	{8,62,0},	{9,62,0},	{10,62,0},	{11,62,0},	{12,62,0},	{13,62,0},	{14,62,0},	{15,62,0},	{16,62,0},	{17,62,0},	{18,62,0},	{19,62,1},	{20,62,1},	{21,62,1},	{22,62,1},	{23,62,1},	{24,62,1},	{25,62,1},	{26,62,1},	{27,62,1},	{28,62,1},	{29,62,1},	{30,62,1},	{31,62,1},	{32,62,1},	{33,62,1},	{34,62,1},	{35,62,1},	{36,62,1},	{37,62,1},	{38,62,1},	{39,62,1},	{40,62,1},	{41,62,1},	{42,62,1},	{43,62,1},	{44,62,1},	{45,62,1},	{46,62,1},	{47,62,1},	{48,62,1},	{49,62,0},	{50,62,0},	{51,62,0},	{52,62,0},	{53,62,0},	{54,62,0},	{55,62,0},	{56,62,0},	{57,62,0},	{58,62,0},	{59,62,0},	{60,62,0},	{61,62,0},	{62,62,0},	{63,62,0},	{64,62,0},	{65,62,0},	{66,62,0},	{67,62,0},	{68,62,0},	{69,62,0},
+	 {0,63,0},	{1,63,0},	{2,63,0},	{3,63,0},	{4,63,0},	{5,63,0},	{6,63,0},	{7,63,0},	{8,63,0},	{9,63,0},	{10,63,0},	{11,63,0},	{12,63,0},	{13,63,0},	{14,63,0},	{15,63,0},	{16,63,0},	{17,63,0},	{18,63,0},	{19,63,0},	{20,63,0},	{21,63,0},	{22,63,1},	{23,63,1},	{24,63,1},	{25,63,1},	{26,63,1},	{27,63,1},	{28,63,1},	{29,63,1},	{30,63,1},	{31,63,1},	{32,63,1},	{33,63,1},	{34,63,1},	{35,63,1},	{36,63,1},	{37,63,1},	{38,63,1},	{39,63,1},	{40,63,1},	{41,63,1},	{42,63,1},	{43,63,1},	{44,63,1},	{45,63,1},	{46,63,1},	{47,63,1},	{48,63,0},	{49,63,0},	{50,63,0},	{51,63,0},	{52,63,0},	{53,63,0},	{54,63,0},	{55,63,0},	{56,63,0},	{57,63,0},	{58,63,0},	{59,63,0},	{60,63,0},	{61,63,0},	{62,63,0},	{63,63,0},	{64,63,0},	{65,63,0},	{66,63,0},	{67,63,0},	{68,63,0},	{69,63,0},
+	 {0,64,0},	{1,64,0},	{2,64,0},	{3,64,0},	{4,64,0},	{5,64,0},	{6,64,0},	{7,64,0},	{8,64,0},	{9,64,0},	{10,64,0},	{11,64,0},	{12,64,0},	{13,64,0},	{14,64,0},	{15,64,0},	{16,64,0},	{17,64,0},	{18,64,0},	{19,64,0},	{20,64,0},	{21,64,0},	{22,64,0},	{23,64,1},	{24,64,1},	{25,64,1},	{26,64,1},	{27,64,1},	{28,64,1},	{29,64,1},	{30,64,1},	{31,64,1},	{32,64,1},	{33,64,1},	{34,64,1},	{35,64,1},	{36,64,1},	{37,64,1},	{38,64,1},	{39,64,1},	{40,64,1},	{41,64,1},	{42,64,1},	{43,64,1},	{44,64,1},	{45,64,0},	{46,64,0},	{47,64,0},	{48,64,0},	{49,64,0},	{50,64,0},	{51,64,0},	{52,64,0},	{53,64,0},	{54,64,0},	{55,64,0},	{56,64,0},	{57,64,0},	{58,64,0},	{59,64,0},	{60,64,0},	{61,64,0},	{62,64,0},	{63,64,0},	{64,64,0},	{65,64,0},	{66,64,0},	{67,64,0},	{68,64,0},	{69,64,0},
+	 {0,65,0},	{1,65,0},	{2,65,0},	{3,65,0},	{4,65,0},	{5,65,0},	{6,65,0},	{7,65,0},	{8,65,0},	{9,65,0},	{10,65,0},	{11,65,0},	{12,65,0},	{13,65,0},	{14,65,0},	{15,65,0},	{16,65,0},	{17,65,0},	{18,65,0},	{19,65,0},	{20,65,0},	{21,65,0},	{22,65,0},	{23,65,0},	{24,65,0},	{25,65,0},	{26,65,0},	{27,65,0},	{28,65,0},	{29,65,0},	{30,65,0},	{31,65,0},	{32,65,0},	{33,65,0},	{34,65,0},	{35,65,0},	{36,65,0},	{37,65,0},	{38,65,0},	{39,65,0},	{40,65,0},	{41,65,0},	{42,65,0},	{43,65,0},	{44,65,0},	{45,65,0},	{46,65,0},	{47,65,0},	{48,65,0},	{49,65,0},	{50,65,0},	{51,65,0},	{52,65,0},	{53,65,0},	{54,65,0},	{55,65,0},	{56,65,0},	{57,65,0},	{58,65,0},	{59,65,0},	{60,65,0},	{61,65,0},	{62,65,0},	{63,65,0},	{64,65,0},	{65,65,0},	{66,65,0},	{67,65,0},	{68,65,0},	{69,65,0},
+	 {0,66,0},	{1,66,0},	{2,66,0},	{3,66,0},	{4,66,0},	{5,66,0},	{6,66,0},	{7,66,0},	{8,66,0},	{9,66,0},	{10,66,0},	{11,66,0},	{12,66,0},	{13,66,0},	{14,66,0},	{15,66,0},	{16,66,0},	{17,66,0},	{18,66,0},	{19,66,0},	{20,66,0},	{21,66,0},	{22,66,0},	{23,66,0},	{24,66,0},	{25,66,0},	{26,66,0},	{27,66,0},	{28,66,0},	{29,66,0},	{30,66,0},	{31,66,0},	{32,66,0},	{33,66,0},	{34,66,0},	{35,66,0},	{36,66,0},	{37,66,0},	{38,66,0},	{39,66,0},	{40,66,0},	{41,66,0},	{42,66,0},	{43,66,0},	{44,66,0},	{45,66,0},	{46,66,0},	{47,66,0},	{48,66,0},	{49,66,0},	{50,66,0},	{51,66,0},	{52,66,0},	{53,66,0},	{54,66,0},	{55,66,0},	{56,66,0},	{57,66,0},	{58,66,0},	{59,66,0},	{60,66,0},	{61,66,0},	{62,66,0},	{63,66,0},	{64,66,0},	{65,66,0},	{66,66,0},	{67,66,0},	{68,66,0},	{69,66,0},
+	 {0,67,0},	{1,67,0},	{2,67,0},	{3,67,0},	{4,67,0},	{5,67,0},	{6,67,0},	{7,67,0},	{8,67,0},	{9,67,0},	{10,67,0},	{11,67,0},	{12,67,0},	{13,67,0},	{14,67,0},	{15,67,0},	{16,67,0},	{17,67,0},	{18,67,0},	{19,67,0},	{20,67,0},	{21,67,0},	{22,67,0},	{23,67,0},	{24,67,0},	{25,67,0},	{26,67,0},	{27,67,0},	{28,67,0},	{29,67,0},	{30,67,0},	{31,67,0},	{32,67,0},	{33,67,0},	{34,67,0},	{35,67,0},	{36,67,0},	{37,67,0},	{38,67,0},	{39,67,0},	{40,67,0},	{41,67,0},	{42,67,0},	{43,67,0},	{44,67,0},	{45,67,0},	{46,67,0},	{47,67,0},	{48,67,0},	{49,67,0},	{50,67,0},	{51,67,0},	{52,67,0},	{53,67,0},	{54,67,0},	{55,67,0},	{56,67,0},	{57,67,0},	{58,67,0},	{59,67,0},	{60,67,0},	{61,67,0},	{62,67,0},	{63,67,0},	{64,67,0},	{65,67,0},	{66,67,0},	{67,67,0},	{68,67,0},	{69,67,0},
+	 {0,68,0},	{1,68,0},	{2,68,0},	{3,68,0},	{4,68,0},	{5,68,0},	{6,68,0},	{7,68,0},	{8,68,0},	{9,68,0},	{10,68,0},	{11,68,0},	{12,68,0},	{13,68,0},	{14,68,0},	{15,68,0},	{16,68,0},	{17,68,0},	{18,68,0},	{19,68,0},	{20,68,0},	{21,68,0},	{22,68,0},	{23,68,0},	{24,68,0},	{25,68,0},	{26,68,0},	{27,68,0},	{28,68,0},	{29,68,0},	{30,68,0},	{31,68,0},	{32,68,0},	{33,68,0},	{34,68,0},	{35,68,0},	{36,68,0},	{37,68,0},	{38,68,0},	{39,68,0},	{40,68,0},	{41,68,0},	{42,68,0},	{43,68,0},	{44,68,0},	{45,68,0},	{46,68,0},	{47,68,0},	{48,68,0},	{49,68,0},	{50,68,0},	{51,68,0},	{52,68,0},	{53,68,0},	{54,68,0},	{55,68,0},	{56,68,0},	{57,68,0},	{58,68,0},	{59,68,0},	{60,68,0},	{61,68,0},	{62,68,0},	{63,68,0},	{64,68,0},	{65,68,0},	{66,68,0},	{67,68,0},	{68,68,0},	{69,68,0},
+	 {0,69,0},	{1,69,0},	{2,69,0},	{3,69,0},	{4,69,0},	{5,69,0},	{6,69,0},	{7,69,0},	{8,69,0},	{9,69,0},	{10,69,0},	{11,69,0},	{12,69,0},	{13,69,0},	{14,69,0},	{15,69,0},	{16,69,0},	{17,69,0},	{18,69,0},	{19,69,0},	{20,69,0},	{21,69,0},	{22,69,0},	{23,69,0},	{24,69,0},	{25,69,0},	{26,69,0},	{27,69,0},	{28,69,0},	{29,69,0},	{30,69,0},	{31,69,0},	{32,69,0},	{33,69,0},	{34,69,0},	{35,69,0},	{36,69,0},	{37,69,0},	{38,69,0},	{39,69,0},	{40,69,0},	{41,69,0},	{42,69,0},	{43,69,0},	{44,69,0},	{45,69,0},	{46,69,0},	{47,69,0},	{48,69,0},	{49,69,0},	{50,69,0},	{51,69,0},	{52,69,0},	{53,69,0},	{54,69,0},	{55,69,0},	{56,69,0},	{57,69,0},	{58,69,0},	{59,69,0},	{60,69,0},	{61,69,0},	{62,69,0},	{63,69,0},	{64,69,0},	{65,69,0},	{66,69,0},	{67,69,0},	{68,69,0},	{69,69,0},
+ };
+
diff --git a/tests/test_gldm.h b/tests/test_gldm.h
index f1aa3e3d..6a807e23 100644
--- a/tests/test_gldm.h
+++ b/tests/test_gldm.h
@@ -31,17 +31,17 @@ static std::unordered_map<std::string, float> gldm_values {
 
 };
 
-
-void test_gldm_feature(const AvailableFeatures& feature, const std::string& feature_name) {
-    double total = 0;
-    
+/// @brief Smoke test of GLDM
+void test_gldm_feature(const AvailableFeatures& feature, const std::string& feature_name) 
+{
     LR roidata;
+
     // Calculate features
     GLDMFeature f;
-    Environment::ibsi_compliance = false; 
+    Environment::ibsi_compliance = false;
 
-    // image 1
-    load_masked_test_roi_data (roidata, ibsi_phantom_z1_intensity, ibsi_phantom_z1_mask,  sizeof(ibsi_phantom_z1_mask) / sizeof(NyxusPixel));
+    // image pair
+    load_masked_test_roi_data(roidata, cat2500_int, cat2500_seg, sizeof(cat2500_seg) / sizeof(NyxusPixel));
 
     ASSERT_NO_THROW(f.calculate(roidata));
 
@@ -50,70 +50,6 @@ void test_gldm_feature(const AvailableFeatures& feature, const std::string& feat
 
     // Retrieve values of the features implemented by class 'PixelIntensityFeatures' into ROI's feature buffer
     f.save_value(roidata.fvals);
-
-    total += roidata.fvals[feature][0];
-
-    
-    // image 2
-    LR roidata1;
-    // Calculate features
-    GLDMFeature f1;
-    Environment::ibsi_compliance = false; 
-
-    load_masked_test_roi_data (roidata1, ibsi_phantom_z2_intensity, ibsi_phantom_z2_mask,  sizeof(ibsi_phantom_z2_intensity) / sizeof(NyxusPixel));
-
-    ASSERT_NO_THROW(f1.calculate(roidata1));
-
-    // Initialize per-ROI feature value buffer with zeros
-    roidata1.initialize_fvals();
-
-    // Retrieve values of the features implemented by class 'PixelIntensityFeatures' into ROI's feature buffer
-    f1.save_value(roidata1.fvals);
-
-    total += roidata1.fvals[feature][0];
-
-    // image 3
-
-    LR roidata2;
-    // Calculate features
-    GLDMFeature f2;
-    Environment::ibsi_compliance = false; 
-
-    load_masked_test_roi_data (roidata2, ibsi_phantom_z3_intensity, ibsi_phantom_z3_mask,  sizeof(ibsi_phantom_z3_intensity) / sizeof(NyxusPixel));
-
-    ASSERT_NO_THROW(f2.calculate(roidata2));
-
-    // Initialize per-ROI feature value buffer with zeros
-    roidata2.initialize_fvals();
-
-    // Retrieve values of the features implemented by class 'PixelIntensityFeatures' into ROI's feature buffer
-    f2.save_value(roidata2.fvals);
-
-    total += roidata2.fvals[feature][0];
-    
-    // image 4
-
-    LR roidata3;
-    // Calculate features
-    GLDMFeature f3;
-    Environment::ibsi_compliance = false; 
-
-    load_masked_test_roi_data (roidata3, ibsi_phantom_z4_intensity, ibsi_phantom_z4_mask,  sizeof(ibsi_phantom_z4_intensity) / sizeof(NyxusPixel));
-
-    ASSERT_NO_THROW(f3.calculate(roidata3));
-
-    // Initialize per-ROI feature value buffer with zeros
-    roidata3.initialize_fvals();
-
-    // Retrieve values of the features implemented by class 'PixelIntensityFeatures' into ROI's feature buffer
-    f3.save_value(roidata3.fvals);
-
-    // Check the feature values vs ground truth
-    total += roidata3.fvals[feature][0];
-
-    std::cerr << "value: " << total/4 << std::endl;
-
-    ASSERT_TRUE(agrees_gt(total/4, gldm_values[feature_name], 100.));
 }
 
 void test_gldm_sde()
@@ -121,7 +57,6 @@ void test_gldm_sde()
     test_gldm_feature(GLDM_SDE, "GLDM_SDE");
 }
 
-
 void test_gldm_lde()
 {
    test_gldm_feature(GLDM_LDE, "GLDM_LDE");
diff --git a/tests/test_glszm.h b/tests/test_glszm.h
index 55692eca..67065406 100644
--- a/tests/test_glszm.h
+++ b/tests/test_glszm.h
@@ -52,7 +52,7 @@ void test_glszm_feature(const AvailableFeatures& feature, const std::string& fea
     // Retrieve values of the features implemented by class 'PixelIntensityFeatures' into ROI's feature buffer
     f.save_value(roidata.fvals);
 
-    total += roidata.fvals[feature][0];;
+    total += roidata.fvals[feature][0];
     
     // image 2
     // Calculate features
diff --git a/tests/test_ibsi_gldm.h b/tests/test_ibsi_gldm.h
index 9d930678..f1269a0b 100644
--- a/tests/test_ibsi_gldm.h
+++ b/tests/test_ibsi_gldm.h
@@ -121,7 +121,6 @@ void test_ibsi_gldm_sde()
     test_ibsi_gldm_feature(GLDM_SDE, "GLDM_SDE");
 }
 
-
 void test_ibsi_gldm_lde()
 {
    test_ibsi_gldm_feature(GLDM_LDE, "GLDM_LDE");
diff --git a/tests/test_ibsi_glszm.h b/tests/test_ibsi_glszm.h
index 2ce60034..d60a271a 100644
--- a/tests/test_ibsi_glszm.h
+++ b/tests/test_ibsi_glszm.h
@@ -51,7 +51,7 @@ void test_ibsi_glszm_feature(const AvailableFeatures& feature, const std::string
     // Retrieve values of the features implemented by class 'PixelIntensityFeatures' into ROI's feature buffer
     f.save_value(roidata.fvals);
 
-    total += roidata.fvals[feature][0];;
+    total += roidata.fvals[feature][0];
     
     // image 2
     // Calculate features