You can also see Python, Cython, Java, Js, C++, or C# repository.
- First install conan.
pip install conan
Instructions are given in the following page:
https://docs.conan.io/2/installation.html
- Add conan remote 'ozyegin' with IP: 104.247.163.162 with the following command:
conan remote add ozyegin http://104.247.163.162:8081/artifactory/api/conan/conan-local --insert
- Use the comman conan list to check for installed packages. Probably there are no installed packages.
conan list
- Put the correct dependencies in the requires part
requires = ["math_c/1.0.0", "data_structure_c/1.0.0", "classification_c/1.0.0"]
- Default settings are:
settings = "os", "compiler", "build_type", "arch"
options = {"shared": [True, False], "fPIC": [True, False]}
default_options = {"shared": True, "fPIC": True}
exports_sources = "src/*", "Test/*"
def layout(self):
cmake_layout(self, src_folder="src")
def generate(self):
tc = CMakeToolchain(self)
tc.generate()
deps = CMakeDeps(self)
deps.generate()
def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()
def package(self):
copy(conanfile=self, keep_path=False, src=join(self.source_folder), dst=join(self.package_folder, "include"), pattern="*.h")
copy(conanfile=self, keep_path=False, src=self.build_folder, dst=join(self.package_folder, "lib"), pattern="*.a")
copy(conanfile=self, keep_path=False, src=self.build_folder, dst=join(self.package_folder, "lib"), pattern="*.so")
copy(conanfile=self, keep_path=False, src=self.build_folder, dst=join(self.package_folder, "lib"), pattern="*.dylib")
copy(conanfile=self, keep_path=False, src=self.build_folder, dst=join(self.package_folder, "bin"), pattern="*.dll")
def package_info(self):
self.cpp_info.libs = ["ComputationalGraph"]
- Set the C standard with compiler flags.
set(CMAKE_C_STANDARD 17)
set(CMAKE_C_FLAGS "-O3")
- Dependent packages should be given with find_package.
find_package(util_c REQUIRED)
find_package(data_structure_c REQUIRED)
- For library part, use add_library and target_link_libraries commands. Use m library for math linker in Linux.
add_library(Math src/Distribution.c src/Distribution.h src/DiscreteDistribution.c src/DiscreteDistribution.h src/Vector.c src/Vector.h src/Eigenvector.c src/Eigenvector.h src/Matrix.c src/Matrix.h src/Tensor.c src/Tensor.h)
target_link_libraries(Math util_c::util_c data_structure_c::data_structure_c m)
- For executable tests, use add_executable and target_link_libraries commands. Use m library for math linker in Linux.
add_executable(DiscreteDistributionTest src/Distribution.c src/Distribution.h src/DiscreteDistribution.c src/DiscreteDistribution.h src/Vector.c src/Vector.h src/Eigenvector.c src/Eigenvector.h src/Matrix.c src/Matrix.h src/Tensor.c src/Tensor.h Test/DiscreteDistributionTest.c)
target_link_libraries(DiscreteDistributionTest util_c::util_c data_structure_c::data_structure_c m)
- Add data files to the cmake-build-debug folder.
- Define structs as class counterparts.
typedef struct {
double *data; // Flattened data array
int *shape; // Shape of the tensor
int *strides; // Strides for each dimension
int dimensions; // Number of dimensions
int total_elements;
} Tensor;
- Define also typedefs for pointer to those structs.
typedef Tensor *Tensor_ptr;
- Put all those definitions to the header files with prototypes of functions.
- Constructor method(s) should allocate a pointer of struct and fill the details and return the pointer.
Vector_ptr create_vector(Array_list_ptr values) {
Vector_ptr result = malloc_(sizeof(Vector));
result->values = values;
result->size = values->size;
return result;
}
- Destructor method should be defined for each struct and deallocate the object and its contents if allocated.
void free_vector(Vector_ptr vector) {
free_array_list(vector->values, free_);
free_(vector);
}
- If there is multiple inheritance, then define the super class inside the subclass, which also should be defined inside its own subclass etc.
struct sgd_momentum {
Optimizer optimizer;
Hash_map_ptr velocity_map;
double momentum;
};
struct Adam {
Sgd_momentum sgd;
Hash_map_ptr momentum_map;
double beta2;
double epsilon;
double current_beta1;
double current_beta2;
};
struct AdamW {
Adam adam;
double weight_decay;
};
- If there is overloading, and subclasses should override the method, you can add pointers to the functions and set them in the constructor.
struct function {
Function_type function_type;
Tensor_ptr (*calculate)(const void*, const Tensor*);
Tensor_ptr (*derivative)(const void*, const Tensor*, const Tensor*);
};
Elu_ptr create_elu(const double a) {
Elu_ptr delu = malloc_(sizeof(Elu));
delu->a = a;
delu->function.function_type = ELU;
delu->function.calculate = calculate_elu;
delu->function.derivative = derivative_elu;
return delu;
}
- Instanceof could be done using an enumerated type defined in the parent class.
enum optimizer_type {
OPTIMIZER, ADAM, ADAM_W, SGD_MOMENTUM, SGD,
};
typedef enum optimizer_type Optimizer_type;
struct optimizer {
Optimizer_type type;
- If needed, hash function should be declared for the struct.
unsigned int hash_function_computational_node(const Computational_node *node, int N) {
return ((uintptr_t)node) % N;
}
- If needed, comparator function should be declared for the struct.
int compare_annotated_word(const Annotated_word *word1, const Annotated_word *word2) {
return compare_string(word1->name, word2->name);
}
- Data Structures: For hashmap, linked hash map and hashset, use create_hash_map, create_linked_hash_map, and create_hash_set in data structure library. There are default string and integer versions of hash_map.
Hash_map_ptr create_hash_map(unsigned int (*hash_function)(const void *, int), int (*key_compare)(const void *, const void *));
Linked_hash_map_ptr create_linked_hash_map(unsigned int (*hash_function)(const void *, int), int (*compare)(const void *, const void *));
Hash_map_ptr create_string_hash_map();
Hash_map_ptr create_integer_hash_map();
Hash_set_ptr create_hash_set(unsigned int (*hash_function)(const void *, int), int (*compare)(const void *, const void *));
- Data Structures: For array list, use create_array_list in data structure library..
Array_list_ptr create_array_list();
- Data Structures: For linked list, use linked_list in data structure library..
Linked_list_ptr create_linked_list(int (*compare)(const void *, const void *));
- Data Structures: For queue and stack, use queue and stack in data structure library.
Queue_ptr create_queue();
Stack_ptr create_stack();
- Data Structures: For hash map that is counting items, use counter hash map in data structure library.
Counter_hash_map_ptr
create_counter_hash_map(unsigned int (*hash_function)(const void *, int), int (*key_compare)(const void *, const void *));
- Do not forget to comment each function.
/**
* Initializes a tensor with given data and shape. Data is cloned in the tensor
*
* @param data Flattened array representing the tensor data.
* @param shape Array representing the shape of the tensor.
* @param dimensions Size of the shape array.
* @return Pointer to the created tensor. Returns NULL on failure.
*/
Tensor_ptr create_tensor(const double *data, const int *shape, int dimensions) {
- Function names should follow snake case case.
Tensor_ptr tensor_get(const Tensor *tensor, const int *dimensions, int size) {
- All heap allocations should be done with malloc_, calloc_, realloc_ taken from the memory management library.
int *new_shape = malloc_((tensor->dimensions - size) * sizeof(int));
- All heap deallocations should be done with free_ taken from the memory management library.
free_(new_shape);
- DO NOT write getter and setter methods.
- If there are multiple constructors for a class, define them as constructor1, constructor2, ....
Tensor_ptr create_tensor(const double *data, const int *shape, int dimensions);
Tensor_ptr create_tensor2(const int *shape, int dimensions);
Tensor_ptr create_tensor3(double *data, const int *shape, int dimensions);
Tensor_ptr create_tensor4(const int *shape, int dimensions);
- Use separate main method for testing purposes.
int main() {
start_medium_memory_check();
testColumnWiseNormalize();
testMultiplyWithConstant();
testDivideByConstant();
end_memory_check();
}
- Testing main method should start with memory check and end with memory check.
int main() {
start_medium_memory_check();
testColumnWiseNormalize();
testMultiplyWithConstant();
testDivideByConstant();
end_memory_check();
}
- Enumerated types should be declared with enum.
enum category_type{
MATHEMATICS, SPORT, MUSIC, SLANG, BOTANIC,
PLURAL, MARINE, HISTORY, THEOLOGY, ZOOLOGY,
METAPHOR, PSYCHOLOGY, ASTRONOMY, GEOGRAPHY, GRAMMAR,
MILITARY, PHYSICS, PHILOSOPHY, MEDICAL, THEATER,
ECONOMY, LAW, ANATOMY, GEOMETRY, BUSINESS,
PEDAGOGY, TECHNOLOGY, LOGIC, LITERATURE, CINEMA,
TELEVISION, ARCHITECTURE, TECHNICAL, SOCIOLOGY, BIOLOGY,
CHEMISTRY, GEOLOGY, INFORMATICS, PHYSIOLOGY, METEOROLOGY,
MINERALOGY
};
- Every header file should start with
#ifndef MATH_DISTRIBUTION_H
#define MATH_DISTRIBUTION_H
and end with
#endif //MATH_DISTRIBUTION_H
- Use regular package for regular expression handling.
void check_match(char* expression, char* word){
Regular_expression_ptr re = create_regular_expression(expression);
if (!full_matches(re, word)){
printf("Mismatch %s %s\n", re->expression, word);
}
free_regular_expression(re);
}
- Do not forget to use const expression for parameters, if they will not be changed in the function.
bool frame_lexical_unit_exists(const Frame* frame, const char *synSetId);
- For dynamic string handling, use util package with stringutils.
struct string {
char *s;
int max_size;
};
typedef struct string String;
typedef String *String_ptr;
String_ptr create_string();
String_ptr create_string2(const char *s);
String_ptr create_string3(const char* s1, const char* s2);
String_ptr create_string4(const char* s1, const char* s2, const char* s3);
- Foor boolean type, use bool.
bool check_definition(const Data_set* data_set, const Instance* instance);
- Use xmlparser package for parsing xml files.
Xml_document_ptr doc = create_xml_document("test.xml");












