Skip to content
Snippets Groups Projects
Verified Commit 36576604 authored by Michaël El Kharroubi's avatar Michaël El Kharroubi :satellite:
Browse files

Add comments

parent dabad862
No related branches found
No related tags found
No related merge requests found
...@@ -3,20 +3,30 @@ ...@@ -3,20 +3,30 @@
#include "vector.h" #include "vector.h"
/** @brief
* An exemple of mathematical function
* in 1 dimension.
*
* @param x A double variable.
* @return f(x) = 2.0*sin(x) - 3.0*cos(x)
*/
double my_function(double x) double my_function(double x)
{ {
// 2.0*sin(x) - 3.0*cos(x)
return 2.0 * sin(x) - 3.0 * cos(x); return 2.0 * sin(x) - 3.0 * cos(x);
} }
int main() int main()
{ {
// Create a vector X = [0,1,2...99]
double_vector_t *X = iota(100); double_vector_t *X = iota(100);
// Create a vector Y = my_function(x)
double_vector_t *Y = apply_function(X, my_function); double_vector_t *Y = apply_function(X, my_function);
// Export our vectors into files
export_vector("../X.vec", X); export_vector("../X.vec", X);
export_vector("../Y.vec", Y); export_vector("../Y.vec", Y);
// Free our vectors
destroy_vector(&Y); destroy_vector(&Y);
destroy_vector(&X); destroy_vector(&X);
} }
\ No newline at end of file
...@@ -3,7 +3,27 @@ ...@@ -3,7 +3,27 @@
#include "vector.h" #include "vector.h"
double_vector_t *init_vector(uint_t N) /** @brief
* Compute the endianness used by
* the architecture.
*
* @return 1 if little-endian, 0 if big-endian
*/
uint8_t get_endianness()
{
uint32_t endianness = 0x01020304;
// Return the endianness by accessing the first byte in memory
// which should be 1 if big-endian and 4 if little-endian
return *((uint8_t *)(&endianness)) == 4;
}
/** @brief
* Create a vector of a given dimension.
*
* @param N The number of dimensions.
* @return A dynamically allocated vector
*/
double_vector_t *init_vector(uint32_t N)
{ {
double_vector_t *vec = malloc(sizeof(double_vector_t)); double_vector_t *vec = malloc(sizeof(double_vector_t));
vec->components = malloc(N * sizeof(double)); vec->components = malloc(N * sizeof(double));
...@@ -15,40 +35,52 @@ double_vector_t *init_vector(uint_t N) ...@@ -15,40 +35,52 @@ double_vector_t *init_vector(uint_t N)
} }
return vec; return vec;
} }
double_vector_t *iota(uint_t N) /** @brief
* Create a vector of a given dimension,
* with values from 0 to N excluded.
*
* @param N The number of dimensions.
* @return A dynamically allocated vector : [0,1..N]
*/
double_vector_t *iota(uint32_t N)
{ {
double_vector_t *vec = init_vector(N); double_vector_t *vec = init_vector(N);
for (uint_t i = 0; i < N; i++) for (uint32_t i = 0; i < N; i++)
{ {
vec->components[i] = i; vec->components[i] = i;
} }
return vec; return vec;
} }
/** @brief
* Apply a 1d function element-wise
* to a given vector, and return the
* result in a new vector.
*
* @param vec The argument vector
* @param f The 1d function to apply
* @return A dynamically allocated vector : f(X)
*/
double_vector_t *apply_function(double_vector_t *vec, double_function_t f) double_vector_t *apply_function(double_vector_t *vec, double_function_t f)
{ {
double_vector_t *res = init_vector(vec->N); double_vector_t *res = init_vector(vec->N);
for (uint_t i = 0; i < vec->N; i++) for (uint32_t i = 0; i < vec->N; i++)
{ {
res->components[i] = f(vec->components[i]); res->components[i] = f(vec->components[i]);
} }
return res; return res;
} }
void fill_vector(double_vector_t *vec, double value) /** @brief
{ * Export a vector into a file.
for (uint_t i = 0; i < vec->N; i++) *
{ * @param filename The name of the output file
vec->components[i] = value; * @param vec The vector to export
} */
}
void export_vector(const char *filename, double_vector_t *vec) void export_vector(const char *filename, double_vector_t *vec)
{ {
FILE *output = fopen(filename, "w"); FILE *output = fopen(filename, "w");
uint_t endianness = 0x01020304;
vector_metadata_t metadata; vector_metadata_t metadata;
// Return the endianness by accessing the first byte in memory metadata.endianness = get_endianness();
// which should be 1 if big-endian and 4 if little-endian
metadata.endianness = *((byte_t *)(&endianness)) == 4;
metadata.size_of_a_component = sizeof(double); metadata.size_of_a_component = sizeof(double);
metadata.number_of_component = vec->N; metadata.number_of_component = vec->N;
...@@ -60,7 +92,11 @@ void export_vector(const char *filename, double_vector_t *vec) ...@@ -60,7 +92,11 @@ void export_vector(const char *filename, double_vector_t *vec)
fclose(output); fclose(output);
} }
/** @brief
* Free a vector.
*
* @param vec A double pointer on a vector
*/
void destroy_vector(double_vector_t **vec) void destroy_vector(double_vector_t **vec)
{ {
free((*vec)->components); free((*vec)->components);
......
typedef unsigned int uint_t; #include <stdint.h>
typedef unsigned char byte_t;
typedef struct double_vector typedef struct double_vector
{ {
uint_t N; uint32_t N; // The dimmension of the vector
double *components; double *components;
} double_vector_t; } double_vector_t;
// Function pointer, example : double f(double x);
typedef double (*double_function_t)(double); typedef double (*double_function_t)(double);
/*
* The attribute "packed" tells the compiler,
* that the struct should be stored in memory
* without padding. It's highly recommended,
* if we want to serialize the structure.
* (for example to store it in a file)
*/
typedef struct vector_metadata typedef struct vector_metadata
{ {
byte_t endianness; // 1 = little, 0 = big uint8_t endianness; // 1 = little, 0 = big
byte_t size_of_a_component; // in bytes uint8_t size_of_a_component; // in bytes
uint_t number_of_component; uint32_t number_of_component;
} __attribute__((packed)) vector_metadata_t; } __attribute__((packed)) vector_metadata_t;
double_vector_t *init_vector(uint_t N); /** @brief
double_vector_t *iota(uint_t N); * Create a vector of a given dimension.
*
* @param N The number of dimensions.
* @return A dynamically allocated vector
*/
double_vector_t *init_vector(uint32_t N);
/** @brief
* Create a vector of a given dimension,
* with values from 0 to N excluded.
*
* @param N The number of dimensions.
* @return A dynamically allocated vector : [0,1..N]
*/
double_vector_t *iota(uint32_t N);
/** @brief
* Apply a 1d function element-wise
* to a given vector, and return the
* result in a new vector.
*
* @param vec The argument vector
* @param f The 1d function to apply
* @return A dynamically allocated vector : f(X)
*/
double_vector_t *apply_function(double_vector_t *vec, double_function_t f); double_vector_t *apply_function(double_vector_t *vec, double_function_t f);
void fill_vector(double_vector_t *vec, double value); /** @brief
void export_vector(const char *file, double_vector_t *vec); * Export a vector into a file.
*
* @param filename The name of the output file
* @param vec The vector to export
*/
void export_vector(const char *filename, double_vector_t *vec);
/** @brief
* Free a vector.
*
* @param vec A double pointer on a vector
*/
void destroy_vector(double_vector_t **vec); void destroy_vector(double_vector_t **vec);
\ No newline at end of file
import numpy as np import numpy as np
from typing import Tuple
METADATA_SIZE = 6
def _parse_metada(metadata: bytes) -> Tuple[type, int]:
"""
Parse the metadata for a vec file.
Parameters:
metadata (bytes): The metadata bytes
Returns:
(type, int): The type and the number of component of the vector
"""
little_endian = bool(metadata[0])
endianness = 'little' if little_endian else 'big'
size_of_components = int(metadata[1])
# For now we only consider two types
datatype = np.float64 if size_of_components == 8 else np.float
# Recover our 32 bit integer specifying the endianness
nb_components = int.from_bytes(metadata[2:], endianness)
return datatype, nb_components
def load_vector(filename: str) -> np.ndarray: def load_vector(filename: str) -> np.ndarray:
"""
Load a vector from a file.
Parameters:
filename (str): The name of the file containing the vector
Returns:
np.ndarray: The vector
"""
file = open(filename, 'rb') file = open(filename, 'rb')
header = file.read(6) # Read our metadata struct
metadata = file.read(METADATA_SIZE)
little_endian = bool(header[0]) datatype, nb_components = _parse_metada(metadata)
size_of_components = int(header[1])
nb_components = int.from_bytes(
header[2:], 'little' if little_endian else 'big')
datatype = np.float64 if size_of_components == 8 else np.float
array = np.fromfile(file, dtype=datatype, count=nb_components) array = np.fromfile(file, dtype=datatype, count=nb_components)
file.close() file.close()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment