README.md
NumJ is a Java library inspired by NumPy, providing support for multi-dimensional arrays and mathematical operations. It aims to bring the functionality of NumPy to Java, enabling efficient numerical computations and array manipulations.
NDArray
)reshape
)flatten
)transpose
)arange
, array
)add
, subtract
, multiply
, divide
, modulo
)DType
)arange
method with customized shapesNumJ is available via JitPack and can be included in your project using Gradle or Maven.
Add the following to your build.gradle
file:
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
mavenCentral()
maven { url 'https://jitpack.io' }
}
}
dependencies {
implementation 'com.github.J-Libraries:numJ:1.0.1'
}
Add the following to your pom.xml
file:
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<dependency>
<groupId>com.github.J-Libraries</groupId>
<artifactId>numJ</artifactId>
<version>1.0.1</version>
</dependency>
The NDArray<T>
class represents an N-dimensional array and provides various methods for array manipulations.
Since the NDArray
constructor is package-private, you can create an NDArray
instance using the array
method provided by the NumJ
class.
// For a 2D array of integers
Integer[][] data = {{1, 2, 3}, {4, 5, 6}};
NumJ<Integer> numj = new NumJ<>();
NDArray<Integer> array = numj.array(data);
ndim()
: Returns the number of dimensions of the array.shape()
: Returns a list representing the size of the array along each dimension.size()
: Returns the total number of elements in the array.itemSize()
: Returns the size of each element in the array (includes dimensions).flatten()
: Flattens the array into a one-dimensional array.transpose()
: Transposes the array by reversing its dimensions.reshape(int... newShape)
: Reshapes the array to the specified shape.printArray()
: Prints the array in a readable format.Method Details:
flatten()
Flattens an N-dimensional array into a one-dimensional array.
NDArray<Integer> flatArray = array.flatten();
transpose()
Transposes the array by reversing its dimensions. For a 2D array, it swaps rows and columns.
NDArray<Integer> transposedArray = array.transpose();
reshape(int... newShape)
Reshapes the array to the new specified shape. The total number of elements must remain the same.
NDArray<Integer> reshapedArray = array.reshape(3, 2);
Note: Throws ShapeException
if the new shape is incompatible.
The NumJ<T>
class provides utility methods for creating arrays and other numerical operations.
array
MethodCreates an NDArray
from the provided multi-dimensional array.
Usage Example:
NumJ<Integer> numj = new NumJ<>();
Integer[][] data = {{1, 2, 3}, {4, 5, 6}};
NDArray<Integer> array = numj.array(data);
Note: Since the NDArray
constructor is package-private, you should use the array
method to create instances of NDArray
.
arange
MethodCreates an array with evenly spaced values within a given interval.
Overloads:
arange(int end)
: Creates an array from 0
to end - 1
.arange(int start, int end)
: Creates an array from start
to end - 1
.arange(int start, int end, DType dType)
: Creates an array with the specified data type.arange(int start, int end, int skip, int[] shape)
: Creates an array with dynamic steps and specified shape.Usage Examples:
// Creates [0, 1, 2, 3, 4]
NDArray<Integer> array1 = numj.arange(5);
// Creates [2, 3, 4, 5, 6]
NDArray<Integer> array2 = numj.arange(2, 7);
// Creates [1.0, 2.0, 3.0] with FLOAT32 data type
NumJ<Float> numjFloat = new NumJ<>();
NDArray<Float> array3 = numjFloat.arange(1, 4, DType.FLOAT32);
// Creates [0, 2, 4, 6] with a shape of 2x2
int[] shape = {2, 2};
NDArray<Integer> array4 = numj.arange(0, 8, 2, shape);
The NumJ
class now supports basic arithmetic operations on arrays: addition, subtraction, multiplication, and division. Arrays must have compatible shapes for broadcasting.
Supported Operations:
add(arr1, arr2)
: Element-wise addition of two arrays.subtract(arr1, arr2)
: Element-wise subtraction of two arrays.multiply(arr1, arr2)
: Element-wise multiplication of two arrays.divide(arr1, arr2)
: Element-wise division of two arrays.modulo(arr1, arr2)
: Element-wise modulo of two arrays.Usage Examples:
NumJ<Integer> numj = new NumJ<>();
NDArray<Integer> arr1 = numj.arange(5); // [0, 1, 2, 3, 4]
NDArray<Integer> arr2 = numj.arange(5); // [0, 1, 2, 3, 4]
// Addition
NDArray<Integer> sum = numj.add(arr1, arr2);
sum.printArray(); // [0, 2, 4, 6, 8]
// Subtraction
NDArray<Integer> diff = numj.subtract(arr1, arr2);
diff.printArray(); // [0, 0, 0, 0, 0]
The DType
enum defines the supported numerical data types for arrays:
public enum DType {
FLOAT32, // 32-bit floating-point (Float)
FLOAT64, // 64-bit floating-point (Double)
INT8, // 8-bit signed integer (Byte)
INT16, // 16-bit signed integer (Short)
INT32, // 32-bit signed integer (Integer)
INT64 // 64-bit signed integer (Long)
}
Example:
NumJ<Double> numjDouble = new NumJ<>();
NDArray<Double> doubleArray = numjDouble.arange(0, 10, DType.FLOAT64);
NumJ provides robust exception handling through the ShapeException
class for operations involving array shapes and sizes.
Common Exceptions:
ShapeException
: Thrown when an operation cannot be performed due to incompatible shapes.IllegalArgumentException
: Thrown when invalid arguments are provided (e.g., negative sizes or skips).Example:
try {
NDArray<Integer> reshapedArray = array.reshape(4, 2); // May throw ShapeException
} catch (ShapeException e) {
e.printStackTrace();
}
Integer[][] data = {{1, 2}, {3, 4}};
NumJ<Integer> numj = new NumJ<>();
NDArray<Integer> array = numj.array(data);
NDArray<Integer> flatArray = array.flatten();
flatArray.printArray(); // Output: [1, 2, 3, 4]
Integer[][] data = {{1, 2, 3}, {4, 5, 6}};
NumJ<Integer> numj = new NumJ<>();
NDArray<Integer> array = numj.array(data);
NDArray<Integer> transposedArray = array.transpose();
transposedArray.printArray(); // Output: [[1, 4], [2, 5], [3, 6]]
Integer[][] data = {{1, 2, 3}, {4, 5, 6}};
NumJ<Integer> numj = new NumJ<>();
NDArray<Integer> array = numj.array(data);
NDArray<Integer> reshapedArray = array.reshape(3, 2);
reshapedArray.printArray(); // Output: [[1, 2], [3, 4], [5, 6]]
arange
NumJ<Integer> numj = new NumJ<>();
// Create an array from 0 to 9
NDArray<Integer> array = numj.arange(10);
array.printArray(); // Output: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
NumJ<Integer> numj = new NumJ<>();
NDArray<Integer> arr1 = numj.arange(5); // [0, 1, 2, 3, 4]
NDArray<Integer> arr2 = numj.arange(5); // [0, 1, 2, 3, 4]
// Element-wise addition
NDArray<Integer> sum = numj.add(arr1, arr2);
sum.printArray(); // [0, 2, 4, 6, 8]
// Element-wise multiplication
NDArray<Integer> product = numj.multiply(arr1, arr2);
product.printArray(); // [0, 1, 4, 9, 16]
NumJ is continuously evolving. The future scope includes implementing more features from NumPy to enhance the library's capabilities. Below is a detailed list of planned additions:
zeros(shape, dtype)
: Create an array filled with zeros.ones(shape, dtype)
: Create an array filled with ones.empty(shape, dtype)
: Create an uninitialized array.full(shape, fill_value, dtype)
: Create an array filled with a specified value.linspace(start, stop, num, endpoint, dtype)
: Create an array of evenly spaced numbers over a specified interval.logspace(start, stop, num, base, dtype)
: Create an array of numbers spaced evenly on a log scale.expand_dims(a, axis)
: Expand the shape of an array.squeeze(a, axis)
: Remove single-dimensional entries from the shape.concatenate((a1, a2, ...), axis)
: Join a sequence of arrays along an existing axis.stack(arrays, axis)
: Join a sequence of arrays along a new axis.split(a, indices_or_sections, axis)
: Split an array into multiple sub-arrays.hsplit(a, indices_or_sections)
: Split an array horizontally.vsplit(a, indices_or_sections)
: Split an array vertically.sin(a)
, cos(a)
, tan(a)
: Trigonometric functions.exp(a)
, log(a)
, sqrt(a)
: Exponential, logarithmic, and square root functions.abs(a)
: Absolute value.sum(a, axis)
: Sum of array elements over a given axis.prod(a, axis)
: Product of array elements over a given axis.cumsum(a, axis)
: Cumulative sum.cumprod(a, axis)
: Cumulative product.dot(a, b)
: Dot product of two arrays.matmul(a, b)
: Matrix product.transpose(a)
: Transpose of an array.linalg.inv(a)
: Inverse of a matrix.linalg.det(a)
: Determinant of a matrix.linalg.eig(a)
: Eigenvalues and eigenvectors.random.rand(d0, d1, ..., dn)
: Random values in a given shape.random.randn(d0, d1, ..., dn)
: Sample from the standard normal distribution.random.randint(low, high, size, dtype)
: Random integers from low
(inclusive) to high
(exclusive).random.shuffle(a)
: Shuffle the array along the first axis.random.permutation(a)
: Randomly permute a sequence or return a permuted range.mean(a, axis)
: Compute the arithmetic mean.std(a, axis)
, var(a, axis)
: Compute the standard deviation and variance.min(a, axis)
, max(a, axis)
: Minimum and maximum values.corrcoef(x)
: Return Pearson product-moment correlation coefficients.cov(m)
: Estimate a covariance matrix.sort(a, axis)
: Return a sorted copy of an array.argsort(a, axis)
: Indirect sort indices.where(condition, x, y)
: Return elements chosen from x
or y
depending on condition
.nonzero(a)
: Return the indices of non-zero elements.argmax(a, axis)
, argmin(a, axis)
: Indices of the maximum and minimum values.loadtxt(fname, dtype, delimiter)
: Load data from a text file.savetxt(fname, X, fmt, delimiter)
: Save an array to a text file.save(file, arr)
: Save an array to a binary file in NumPy .npy
format.load(file)
: Load arrays from .npy
, .npz
files, or pickled files.isnan(a)
: Return a boolean array where NaN values are True
.isinf(a)
: Test element-wise for positive or negative infinity.nan_to_num(a)
: Replace NaN with zero and infinity with large finite numbers.bitwise_and(x1, x2)
: Compute bitwise AND.bitwise_or(x1, x2)
: Compute bitwise OR.invert(x)
: Compute bitwise NOT.left_shift(x1, x2)
: Shift bits of x1
left by x2
positions.right_shift(x1, x2)
: Shift bits of x1
right by x2
positions.unique(ar)
: Find the unique elements of an array.intersect1d(ar1, ar2)
: Intersection of two arrays.union1d(ar1, ar2)
: Union of two arrays.setdiff1d(ar1, ar2)
: Set difference of two arrays.memmap
: Memory-mapped file support for large datasets.astype(dtype)
: Copy of the array, cast to a specified type.can_cast(from_, to)
: Returns True
if cast between data types can occur without loss.result_type(*arrays_and_dtypes)
: Returns the type resulting from applying the NumPy type promotion rules.We welcome contributions to NumJ! Follow the steps below to get started:
Fork the Repository:
Select a Task:
Clone Your Fork:
git clone https://github.com/YOUR_USERNAME/NumJ.git
cd NumJ
Work on the Task:
main
for your task:
git checkout -b feature/task-name
git add .
git commit -m "Add description of the task you worked on"
git push origin feature/task-name
Create a Pull Request:
main
branch of the original NumJ repository.Review Process:
Merge:
For more details on how to contribute, refer to the Contributing Guidelines or reach out to the maintainers.
This project is licensed under the MIT License - see the LICENSE file for details.