#include <compression.h>

// encoding
const unit8_t * src; // 압축할 데이터
size_t src_size; // src의 크기
uint8_t * dst; // 결과를 받을 포인터
size_t dst_capacity; // dst에 할당된 포인터
compression_algorithm algorithm = COMPRESSION_LZFSE;

size_t dst_size = compression_encode_buffer(
		dst, dst_capacity,
		src, src_size.
		NULL, algorithm
		);

// decoding 
#include <compression.h>

const_uint8_t *src; // data to decompress
size_t src_size;
uint8_t * dst;
size_t dst_capacity;
compression_algorithm algorithm = COMPRESSION_LZFSE;

// 할당량이 부족하면 결과값이 잘린다.
size_t dst_size = compression_decode_buffer(
				dst, dst_capacity,
				src, src_size,
				NULL, algorithm
			);

# include <compression.h>

// encode
// init
compression_stream stream;
compression_stream_operation op = COMPRESSION_STREAM_ENCODE;
compression_algorithm algorithm = COMPRESSION_LZFSE;

int status = compression_stream_init(&stream, op, algorithm)

// COMPRESSION_STATUS_OK: success
// COMPRESSION_STATUS_ERROR: an error occurred

// process
stream.src_ptr = src;
stream.src_size = src_size;
stream.dst_ptr = dst;
stream.dst_size = dst_capacity;

int status = compression_stream_process(&stream, 0);

// COMPRESSION_STATUS_OK: src empty or dst full, more calls needed
// COMPRESSION_STATUS_ERROR: an error occurred

// src_ptr, src_size, dst_ptr, dst_size가 업데이트 되었다.

// process(end)
stream.src_ptr = src;
stream.src_size = src_size;
stream.dst_ptr = dst;
stream.dst_size = dst_capacity;

int status = compression_stream_process(&stream, COMPRESSION_STREAM_FINALIZE);

// COMPRESSION_STATUS_OK: src empty or dst full, more calls needed
// COMPRESSION_STATUS_END: all data has been processed
// COMPRESSION_STATUS_ERROR: an error occurred

// src_ptr, src_size, dst_ptr, dst_size가 업데이트 되었다.
(destroy)
int status = compression_stream_destroy(&stream);

// COMPRESSION_STATUS_OK: success
// COMPRESSION_STATUS_ERROR: an error occurred

// decode도 encode와 유사

func replect(x: float3, y: float3) -> float3 {
	return x- 2 * dot(x,n) * n
}

sparse_matrix_float A = sparse_matrix_create_float(M,N);
sparse_insert_entry_float(A, 2.0, row, col);

float val[] = { ... };
sparse_index indx[] = { ... };

sparse_dimension nz = sizeof(val)/sizeof(*val);
sparse_insert_row_float(A, row, nz,val,indx);
spard_insert_col_float(A, col,nz, val, indx);

sparse_commit(A); // batch 처리를 위해 commit 전까지 실제 처리가 유보됨. operation을 하면 자동으로 수행됨
...

sparse_destroy(A);

// C = aAB+C
sparse_status sparse_matrix_product_dense_float (
	enum CBLAS_ORDER order,
	enum CBLAS_TRANSPOSE transa,
	sparse_dimension nCol,
  float alpha,
  sparse_matrix_float A,
  const float *B,
  sparse_dimension ldb,
	float * C,
	sparse_dimension ldc
);

sparse_matrix_float T = sparse_matrix_create_float(M, M)
sparse_set_matrix_property(T, SPARSE_UPPER_TRIANGULAR);
// T에 데이터 넣기
...

sparse_matrix_triangular_solve_dense_float(
	CblasRowMajor, CblasNoTrans, nCol, alpha, T, B, ldb);