Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 48 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
cmake_minimum_required(VERSION 3.18)

# Set CUDA flags early for compiler ID test
# Check if cuda backend is requested before project() call
if(DEFINED QOCO_ALGEBRA_BACKEND AND QOCO_ALGEBRA_BACKEND STREQUAL "cuda")
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -allow-unsupported-compiler")
set(CMAKE_CUDA_FLAGS_INIT "${CMAKE_CUDA_FLAGS_INIT} -allow-unsupported-compiler")
# Also set via cache to ensure it's picked up during compiler detection
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -allow-unsupported-compiler" CACHE STRING "Flags for CUDA compiler")
endif()

set(QOCO_VERSION_MAJOR "0")
set(QOCO_VERSION_MINOR "1")
set(QOCO_VERSION_PATCH "6")
set(QOCO_VERSION ${QOCO_VERSION_MAJOR}.${QOCO_VERSION_MINOR}.${QOCO_VERSION_PATCH})

# Project name
project(qoco VERSION ${QOCO_VERSION})
project(qoco VERSION ${QOCO_VERSION} LANGUAGES C CXX)
message(STATUS "Building QOCO v${QOCO_VERSION}")

# Detect operating system.
Expand Down Expand Up @@ -112,15 +121,21 @@ endif()
set(QOCO_ALGEBRA_BACKEND
"builtin"
CACHE STRING "The Algebra to use")

# CUDA flags are set early if needed
add_subdirectory(algebra)

get_property(qoco_sources GLOBAL PROPERTY QOCO_SOURCES)
get_property(qoco_headers GLOBAL PROPERTY QOCO_HEADERS)
get_property(qoco_include GLOBAL PROPERTY QOCO_INCLUDE)

# Get CUDA libraries if using CUDA backend
get_property(qoco_cuda_libs GLOBAL PROPERTY QOCO_CUDA_LIBS)

# Build qoco shared library.
add_library(qoco SHARED)
target_link_libraries(qoco qdldlobject amd)
target_link_libraries(qoco ${qoco_cuda_libs})

if(IS_LINUX OR IS_MACOS)
target_link_libraries(qoco m)
Expand All @@ -129,9 +144,25 @@ endif()
target_include_directories(qoco PUBLIC ${qoco_include})
target_sources(qoco PRIVATE ${qoco_sources})

# Enable CUDA if using CUDA backend
if(${QOCO_ALGEBRA_BACKEND} STREQUAL "cuda")
enable_language(CUDA)
set_target_properties(qoco PROPERTIES
CUDA_SEPARABLE_COMPILATION ON
CUDA_RESOLVE_DEVICE_SYMBOLS ON
)
# Add HAVE_CUDSS definition if cuDSS library was found
get_property(qoco_cuda_libs GLOBAL PROPERTY QOCO_CUDA_LIBS)
if("${qoco_cuda_libs}" MATCHES "cudss")
target_compile_definitions(qoco PRIVATE HAVE_CUDSS)
message(STATUS "Added HAVE_CUDSS to qoco target")
endif()
endif()

# Build qoco static library.
add_library(qocostatic STATIC)
target_link_libraries(qocostatic qdldlobject amd)
target_link_libraries(qocostatic ${qoco_cuda_libs})

if(IS_LINUX OR IS_MACOS)
target_link_libraries(qocostatic m)
Expand All @@ -140,6 +171,22 @@ endif()
target_include_directories(qocostatic PUBLIC ${qoco_include})
target_sources(qocostatic PRIVATE ${qoco_sources})

# Enable CUDA if using CUDA backend
if(${QOCO_ALGEBRA_BACKEND} STREQUAL "cuda")
set_target_properties(qocostatic PROPERTIES
CUDA_SEPARABLE_COMPILATION ON
CUDA_RESOLVE_DEVICE_SYMBOLS ON
)
# Add HAVE_CUDSS definition if cuDSS library was found
get_property(qoco_cuda_libs GLOBAL PROPERTY QOCO_CUDA_LIBS)
if("${qoco_cuda_libs}" MATCHES "cudss")
target_compile_definitions(qocostatic PRIVATE HAVE_CUDSS)
endif()
endif()

target_include_directories(qocostatic PUBLIC ${qoco_include})
target_sources(qocostatic PRIVATE ${qoco_sources})

# Build qoco demo.
if(BUILD_QOCO_DEMO)
add_executable(qoco_demo ${PROJECT_SOURCE_DIR}/examples/qoco_demo.c)
Expand Down
9 changes: 9 additions & 0 deletions algebra/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,13 @@ if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${QOCO_ALGEBRA_BACKEND})
endif()

set_property(GLOBAL APPEND PROPERTY QOCO_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/${QOCO_ALGEBRA_BACKEND})
set_property(GLOBAL APPEND PROPERTY QOCO_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR})

# Set backend define
if(${QOCO_ALGEBRA_BACKEND} STREQUAL "cuda")
add_compile_definitions(QOCO_ALGEBRA_BACKEND_CUDA)
else()
add_compile_definitions(QOCO_ALGEBRA_BACKEND_BUILTIN)
endif()

add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${QOCO_ALGEBRA_BACKEND})
27 changes: 27 additions & 0 deletions algebra/backend.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* @file backend.h
* @author Govind M. Chari <govindchari1@gmail.com>
*
* @section LICENSE
*
* Copyright (c) 2025, Govind M. Chari
* This source code is licensed under the BSD 3-Clause License
*
* @section DESCRIPTION
*
* Includes the appropriate backend header based on QOCO_ALGEBRA_BACKEND.
*/

#ifndef QOCO_BACKEND_H
#define QOCO_BACKEND_H

#if defined(QOCO_ALGEBRA_BACKEND_BUILTIN) || !defined(QOCO_ALGEBRA_BACKEND_CUDA)
#include "builtin/qdldl_backend.h"
#elif defined(QOCO_ALGEBRA_BACKEND_CUDA)
#include "cuda/cudss_backend.h"
#else
#error "Unknown algebra backend. Define QOCO_ALGEBRA_BACKEND_BUILTIN or QOCO_ALGEBRA_BACKEND_CUDA"
#endif

#endif /* #ifndef QOCO_BACKEND_H */

172 changes: 171 additions & 1 deletion algebra/builtin/builtin_linalg.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,162 @@
* This source code is licensed under the BSD 3-Clause License
*/

#include "qoco_linalg.h"
#include "builtin_types.h"

QOCOMatrix* new_qoco_matrix(const QOCOCscMatrix* A)
{
QOCOMatrix* M = qoco_malloc(sizeof(QOCOMatrix));
QOCOCscMatrix* Mcsc = qoco_malloc(sizeof(QOCOCscMatrix));

if (A) {
QOCOInt m = A->m;
QOCOInt n = A->n;
QOCOInt nnz = A->nnz;

QOCOFloat* x = qoco_malloc(nnz * sizeof(QOCOFloat));
QOCOInt* p = qoco_malloc((n + 1) * sizeof(QOCOInt));
QOCOInt* i = qoco_malloc(nnz * sizeof(QOCOInt));

copy_arrayf(A->x, x, nnz);
copy_arrayi(A->i, i, nnz);
copy_arrayi(A->p, p, n + 1);

Mcsc->m = m;
Mcsc->n = n;
Mcsc->nnz = nnz;
Mcsc->x = x;
Mcsc->i = i;
Mcsc->p = p;
}
else {
Mcsc->m = 0;
Mcsc->n = 0;
Mcsc->nnz = 0;
Mcsc->x = NULL;
Mcsc->i = NULL;
Mcsc->p = NULL;
}

M->csc = Mcsc;

return M;
}

QOCOVectorf* new_qoco_vectorf(const QOCOFloat* x, QOCOInt n)
{
QOCOVectorf* v = qoco_malloc(sizeof(QOCOVectorf));
QOCOFloat* vdata = qoco_malloc(sizeof(QOCOFloat) * n);
if (x) {
copy_arrayf(x, vdata, n);
} else {
// Initialize to zero if x is NULL
for (QOCOInt i = 0; i < n; ++i) {
vdata[i] = 0.0;
}
}

v->len = n;
v->data = vdata;

return v;
}

void free_qoco_matrix(QOCOMatrix* A)
{
free_qoco_csc_matrix(A->csc);
qoco_free(A);
}

void free_qoco_vectorf(QOCOVectorf* x)
{
qoco_free(x->data);
qoco_free(x);
}

QOCOInt get_nnz(const QOCOMatrix* A) { return A->csc->nnz; }

QOCOFloat get_element_vectorf(const QOCOVectorf* x, QOCOInt idx)
{
return x->data[idx];
}

QOCOFloat* get_pointer_vectorf(const QOCOVectorf* x, QOCOInt idx)
{
return &x->data[idx];
}

QOCOFloat* get_data_vectorf(const QOCOVectorf* x)
{
return x->data;
}

QOCOInt get_length_vectorf(const QOCOVectorf* x)
{
return x->len;
}

void sync_vector_to_device_if_needed(QOCOVectorf* v)
{
// No-op for builtin backend (no device memory)
(void)v;
}

void set_solve_phase(int active)
{
// No-op for builtin backend (no device memory)
(void)active;
}

int get_solve_phase(void)
{
// Always return 0 for builtin backend (no device memory)
return 0;
}

void copy_vector_from_device(QOCOVectorf* src, QOCOFloat* dst, QOCOInt n)
{
// For builtin backend, just copy from host memory
if (src && dst) {
copy_arrayf(src->data, dst, n);
}
}

QOCOCscMatrix* get_csc_matrix(const QOCOMatrix* M)
{
return M->csc;
}

void col_inf_norm_USymm_matrix(const QOCOMatrix* M, QOCOFloat* norm)
{
col_inf_norm_USymm(get_csc_matrix(M), norm);
}

void col_inf_norm_matrix(const QOCOMatrix* M, QOCOFloat* norm)
{
col_inf_norm(get_csc_matrix(M), norm);
}

void row_inf_norm_matrix(const QOCOMatrix* M, QOCOFloat* norm)
{
row_inf_norm(get_csc_matrix(M), norm);
}

void row_col_scale_matrix(QOCOMatrix* M, const QOCOFloat* E, const QOCOFloat* D)
{
row_col_scale(get_csc_matrix(M), (QOCOFloat*)E, (QOCOFloat*)D);
}

void set_element_vectorf(QOCOVectorf* x, QOCOInt idx, QOCOFloat data)
{
x->data[idx] = data;
}

void reciprocal_vectorf(const QOCOVectorf* input, QOCOVectorf* output)
{
for (QOCOInt i = 0; i < input->len; ++i) {
output->data[i] = safe_div(1.0, input->data[i]);
}
}

QOCOCscMatrix* new_qoco_csc_matrix(const QOCOCscMatrix* A)
{
Expand Down Expand Up @@ -181,6 +336,21 @@ void SpMtv(const QOCOCscMatrix* M, const QOCOFloat* v, QOCOFloat* r)
}
}

void USpMv_matrix(const QOCOMatrix* M, const QOCOFloat* v, QOCOFloat* r)
{
USpMv(M->csc, v, r);
}

void SpMv_matrix(const QOCOMatrix* M, const QOCOFloat* v, QOCOFloat* r)
{
SpMv(M->csc, v, r);
}

void SpMtv_matrix(const QOCOMatrix* M, const QOCOFloat* v, QOCOFloat* r)
{
SpMtv(M->csc, v, r);
}

QOCOFloat inf_norm(const QOCOFloat* x, QOCOInt n)
{
qoco_assert(x || n == 0);
Expand Down
36 changes: 36 additions & 0 deletions algebra/builtin/builtin_types.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* @file builtin_types.h
* @author Govind M. Chari <govindchari1@gmail.com>
*
* @section LICENSE
*
* Copyright (c) 2025, Govind M. Chari
* This source code is licensed under the BSD 3-Clause License
*
* @section DESCRIPTION
*
* Defines the vector and matrices for builtin linear algebra.
*/

#ifndef BUILTIN_TYPES_H
#define BUILTIN_TYPES_H

#include "common_linalg.h"
#include "definitions.h"
#include "qoco_linalg.h"

struct QOCOVectori_ {
QOCOInt* data;
QOCOInt len;
};

struct QOCOVectorf_ {
QOCOFloat* data;
QOCOInt len;
};

struct QOCOMatrix_ {
QOCOCscMatrix* csc;
};

#endif /* ifndef BUILTIN_TYPES_H */
Loading
Loading