Hone logo
Hone
Problems

TypeScript Sized Integer Implementation

Many programming languages offer fixed-size integer types (e.g., int8, uint32). These types guarantee that a value will always fit within a specific bit range, preventing overflow errors and enabling efficient memory usage. In TypeScript, we typically work with the number type, which is a double-precision floating-point number and doesn't inherently enforce size constraints. This challenge asks you to implement custom sized integer types in TypeScript.

Problem Description

Your task is to create a mechanism in TypeScript that allows for the definition and usage of integers with specific bit sizes. This should include both signed and unsigned integers. You need to handle:

  • Type Definition: Create distinct types for different bit sizes (e.g., Int8, Uint8, Int16, Uint16, Int32, Uint32).
  • Value Representation: Ensure that values assigned to these types adhere to their defined size and signedness.
  • Arithmetic Operations: Implement basic arithmetic operations (addition, subtraction, multiplication) that respect the size constraints and perform appropriate wrapping or saturation on overflow.
  • Type Safety: Leverage TypeScript's type system to enforce these constraints at compile time where possible, and at runtime otherwise.

You should aim to create a flexible system that can be extended to other bit sizes if needed, though focusing on the common 8, 16, and 32-bit integers is sufficient for this challenge.

Examples

Example 1: Uint8 (Unsigned 8-bit Integer)

// Assuming you have implemented Uint8
const u8_max = new Uint8(255);
const u8_one = new Uint8(1);

const result_add = u8_max.add(u8_one); // Should wrap around
console.log(result_add.getValue()); // Expected output: 0

const result_sub = u8_one.subtract(new Uint8(2)); // Should wrap around
console.log(result_sub.getValue()); // Expected output: 255

Explanation: Adding 1 to the maximum Uint8 value (255) should result in 0 due to unsigned 8-bit integer wrapping. Subtracting 2 from 1 should wrap around from 0 to 255.

Example 2: Int16 (Signed 16-bit Integer)

// Assuming you have implemented Int16
const i16_min = new Int16(-32768);
const i16_one = new Int16(1);

const result_sub = i16_min.subtract(i16_one); // Should saturate at minimum
console.log(result_sub.getValue()); // Expected output: -32768

const i16_max = new Int16(32767);
const result_add_overflow = i16_max.add(new Int16(2)); // Should saturate at maximum
console.log(result_add_overflow.getValue()); // Expected output: 32767

Explanation: Subtracting 1 from the minimum Int16 value (-32768) should result in saturation at -32768 because the value would become -32769, which is out of range for a signed 16-bit integer. Similarly, adding 2 to the maximum Int16 value (32767) should saturate at 32767.

Example 3: Uint32 Addition with Intermediate Overflow

// Assuming you have implemented Uint32
const u32_large1 = new Uint32(0xFFFFFFFF); // Max Uint32
const u32_large2 = new Uint32(1);

const result_overflow = u32_large1.add(u32_large2); // Should wrap around
console.log(result_overflow.getValue()); // Expected output: 0

Explanation: Adding 1 to the maximum Uint32 value results in wrapping around to 0, demonstrating correct overflow behavior for unsigned 32-bit integers.

Constraints

  • The implementation should focus on Int8, Uint8, Int16, Uint16, Int32, and Uint32.
  • Arithmetic operations (add, subtract, multiply) must be implemented for each type.
  • For signed types, overflow should result in saturation (clamping to the minimum or maximum representable value).
  • For unsigned types, overflow should result in wrapping (circular behavior).
  • The internal representation of the numbers can be TypeScript's number type, but you must ensure that the operations and values are managed according to the specified bit sizes.
  • You should provide a method (e.g., getValue()) to retrieve the underlying numeric value, which should be within the correct range for the type.
  • When constructing a new instance, if the provided value is out of range for the target type, it should be clamped or wrapped appropriately during initialization.

Notes

  • Consider how to best represent the bit size and signedness. A factory pattern or class inheritance might be useful.
  • Think about the mathematical formulas for signed and unsigned integer ranges and overflow/underflow behavior.
  • TypeScript's number type is a 64-bit float, so you'll need to be careful about precision when dealing with large 32-bit integer values and avoid JavaScript's automatic conversion to floats that might lose precision if not handled correctly (though for the specified 32-bit integers, standard number should suffice if operations are managed carefully).
  • The primary goal is to enforce the behavior of sized integers using TypeScript.
Loading editor...
typescript