2
0
Эх сурвалжийг харах

Using 64 bit indices and exposing unsafe access for Field.

David Piuva 2 жил өмнө
parent
commit
ccaa05f890

+ 20 - 14
Source/DFPSR/collection/Field.h

@@ -30,34 +30,40 @@
 
 namespace dsr {
 
+// TODO: Should this be cloned automatically for consistency with List?
+// TODO: Implement generic operations for Field.
+
 // A 2D version of Array with built-in support for accessing elements out of bound.
+//   If you need more speed, pack elements into a Buffer and iterate
+//     over them using SafePointer with SIMD aligned stride between rows.
 template <typename T>
 class Field {
 private:
-	const int32_t elementWidth, elementHeight;
+	const int64_t elementWidth, elementHeight;
 	T *elements = nullptr;
 public:
 	// Constructor
-	Field(const int32_t width, const int32_t height, const T& defaultValue)
+	Field(const int64_t width, const int64_t height, const T& defaultValue)
 	  : elementWidth(width), elementHeight(height) {
 		impl_nonZeroLengthCheck(width, "New array width");
   		impl_nonZeroLengthCheck(height, "New array height");
-		int32_t size = width * height;
+		int64_t size = width * height;
 		this->elements = new T[size];
-		for (int32_t index = 0; index < size; index++) {
+		for (int64_t index = 0; index < size; index++) {
 			this->elements[index] = defaultValue;
 		}
 	}
-private:
-	// Direct memory access
+	// Direct memory access where bound checks are only applied in debug mode, so access out of bound will crash.
 	// Precondition: this->inside(location.x, location.y)
-	T& writeAccess(const IVector2D& location) {
+	T& unsafe_writeAccess(const IVector2D& location) {
+		assert(this->inside(location));
 		return this->elements[location.x + location.y * this->elementWidth];
 	}
-	const T& readAccess(const IVector2D& location) const {
+	// Precondition: this->inside(location.x, location.y)
+	const T& unsafe_readAccess(const IVector2D& location) const {
+		assert(this->inside(location));
 		return this->elements[location.x + location.y * this->elementWidth];
 	}
-public:
 	// No implicit copies, only pass by reference
 	Field(const Field&) = delete;
 	Field& operator=(const Field&) = delete;
@@ -70,7 +76,7 @@ public:
 	// Read access
 	T read_border(const IVector2D& location, const T& outside) const {
 		if (this->inside(location)) {
-			return this->readAccess(location);
+			return this->unsafe_readAccess(location);
 		} else {
 			return outside;
 		}
@@ -80,18 +86,18 @@ public:
 		if (location.x >= this->elementWidth) location.x = this->elementWidth - 1;
 		if (location.y < 0) location.y = 0;
 		if (location.y >= this->elementHeight) location.y = this->elementHeight - 1;
-		return this->readAccess(location);
+		return this->unsafe_readAccess(location);
 	}
 	// Write access
 	void write_ignore(const IVector2D& location, const T& value) {
 		if (this->inside(location)) {
-			this->writeAccess(location) = value;
+			this->unsafe_writeAccess(location) = value;
 		}
 	}
-	int32_t width() const {
+	int64_t width() const {
 		return this->elementWidth;
 	}
-	int32_t height() const {
+	int64_t height() const {
 		return this->elementHeight;
 	}
 };