before next stage
This commit is contained in:
commit
c6f08be676
|
@ -0,0 +1,60 @@
|
||||||
|
---
|
||||||
|
Language: Cpp
|
||||||
|
BasedOnStyle: LLVM
|
||||||
|
AccessModifierOffset: -4
|
||||||
|
AlignEscapedNewlinesLeft: false
|
||||||
|
AlignOperands: true
|
||||||
|
AlignTrailingComments: true
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: true
|
||||||
|
AllowShortBlocksOnASingleLine: false
|
||||||
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
|
AllowShortFunctionsOnASingleLine: All
|
||||||
|
AllowShortIfStatementsOnASingleLine: false
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
AlwaysBreakBeforeMultilineStrings: false
|
||||||
|
AlwaysBreakTemplateDeclarations: false
|
||||||
|
BinPackArguments: true
|
||||||
|
BinPackParameters: true
|
||||||
|
BreakBeforeBinaryOperators: None
|
||||||
|
BreakBeforeBraces: Allman
|
||||||
|
BreakBeforeTernaryOperators: true
|
||||||
|
BreakConstructorInitializersBeforeComma: false
|
||||||
|
ColumnLimit: 120
|
||||||
|
CommentPragmas: ""
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||||
|
ConstructorInitializerIndentWidth: 8
|
||||||
|
ContinuationIndentWidth: 4
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
DerivePointerAlignment: false
|
||||||
|
DisableFormat: false
|
||||||
|
ExperimentalAutoDetectBinPacking: false
|
||||||
|
ForEachMacros: [foreach, Q_FOREACH, BOOST_FOREACH]
|
||||||
|
IndentCaseLabels: false
|
||||||
|
IndentWidth: 4
|
||||||
|
IndentWrappedFunctionNames: false
|
||||||
|
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||||
|
MaxEmptyLinesToKeep: 3
|
||||||
|
NamespaceIndentation: All
|
||||||
|
ObjCBlockIndentWidth: 2
|
||||||
|
ObjCSpaceAfterProperty: false
|
||||||
|
ObjCSpaceBeforeProtocolList: true
|
||||||
|
PenaltyBreakBeforeFirstCallParameter: 19
|
||||||
|
PenaltyBreakComment: 300
|
||||||
|
PenaltyBreakFirstLessLess: 120
|
||||||
|
PenaltyBreakString: 1000
|
||||||
|
PenaltyExcessCharacter: 1000000
|
||||||
|
PenaltyReturnTypeOnItsOwnLine: 60
|
||||||
|
PointerAlignment: Left
|
||||||
|
SpaceAfterCStyleCast: false
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
SpaceBeforeParens: ControlStatements
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
SpacesBeforeTrailingComments: 1
|
||||||
|
SpacesInAngles: false
|
||||||
|
SpacesInContainerLiterals: true
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
|
SpacesInParentheses: false
|
||||||
|
SpacesInSquareBrackets: false
|
||||||
|
Standard: Cpp11
|
||||||
|
TabWidth: 4
|
||||||
|
UseTab: Never
|
|
@ -0,0 +1,8 @@
|
||||||
|
/cmake_install.cmake
|
||||||
|
/build
|
||||||
|
/.vscode
|
||||||
|
/CMakeFiles
|
||||||
|
/Makefile
|
||||||
|
/CMakeCache.txt
|
||||||
|
*.profdata
|
||||||
|
*.profraw
|
|
@ -0,0 +1,44 @@
|
||||||
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
|
||||||
|
project (homework_11)
|
||||||
|
|
||||||
|
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||||
|
message("Setting build type to 'Debug' as none was specified.")
|
||||||
|
set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build." FORCE)
|
||||||
|
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include_directories(/usr/include)
|
||||||
|
|
||||||
|
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=x86-64-v3" CACHE STRING "Set C Compiler Flags to use x86 feature level V3" FORCE)
|
||||||
|
# set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -I -march=x86-64-v3" CACHE STRING "Set C++ Compiler Flags to use x86 feature level V3" FORCE)
|
||||||
|
|
||||||
|
set(CMAKE_C_FLAGS_RELEASE_INIT "${CMAKE_C_FLAGS} -Ofast -flto")
|
||||||
|
set(CMAKE_CXX_FLAGS_RELEASE_INIT "${CMAKE_CXX_FLAGS} -Ofast -flto")
|
||||||
|
|
||||||
|
set(SOURCES
|
||||||
|
include/hashmap.h
|
||||||
|
include/state.h
|
||||||
|
include/linklist.h
|
||||||
|
include/clock.h
|
||||||
|
include/rust.h
|
||||||
|
include/v1.h
|
||||||
|
include/v2.h
|
||||||
|
include/v3.h
|
||||||
|
src/hashmap.c
|
||||||
|
src/state.c
|
||||||
|
src/linklist.c
|
||||||
|
src/clock.c
|
||||||
|
src/rust.c
|
||||||
|
src/v1.c
|
||||||
|
src/v2.c
|
||||||
|
src/v3.c
|
||||||
|
src/main.c
|
||||||
|
)
|
||||||
|
|
||||||
|
add_executable(homework_11 ${SOURCES})
|
||||||
|
|
||||||
|
target_include_directories(
|
||||||
|
homework_11
|
||||||
|
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||||
|
)
|
|
@ -0,0 +1,6 @@
|
||||||
|
# set(TOOLCHAIN_PREFIX "x86_64-w64-mingw32-")
|
||||||
|
|
||||||
|
set(CMAKE_C_COMPILER "clang" CACHE STRING "clang compiler" FORCE)
|
||||||
|
set(CMAKE_CXX_COMPILER "clang++" CACHE STRING "clang++ compiler" FORCE)
|
||||||
|
|
||||||
|
# set(CMAKE_MAKE_PROGRAM "mingw32-make" CACHE STRING "make command" FORCE)
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,14 @@
|
||||||
|
# Chart with suffix -1.png
|
||||||
|
|
||||||
|
In those three chart, we know that they all have similar instruction, the distribution wasn't similar to linklist, but the average time is.
|
||||||
|
|
||||||
|
It's because two reason, one cause high baseline time, another is the data structure I use.
|
||||||
|
|
||||||
|
The first reason which cause high baseline time is bad IO optimization, It read from file for every prefix, even worse, I open file to write the chart before calling `usize end=rdtsc_64bits();`, which block.
|
||||||
|
|
||||||
|
The second reason is the addition of HashMap, rather than placing linklist(xor linklist) in vector(slice), I placed linklist in a custom hashmap, moreover, when the key is missing in the hashmap, the `hash_get()` function iterating all elements in hashmap, and hash collusion was discovered in one of the bucket, so there are several operation took significantly more time.
|
||||||
|
|
||||||
|
# Chart with suffix -2.png
|
||||||
|
|
||||||
|
After optimize some IO, I get correct result for combination of hashmap and linklist.
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 34 KiB |
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
Binary file not shown.
After Width: | Height: | Size: 38 KiB |
Binary file not shown.
After Width: | Height: | Size: 38 KiB |
Binary file not shown.
After Width: | Height: | Size: 29 KiB |
Binary file not shown.
After Width: | Height: | Size: 27 KiB |
Binary file not shown.
|
@ -0,0 +1,13 @@
|
||||||
|
#define clock_start usize freq=0;\
|
||||||
|
u64 begin=rdtsc_64bits();
|
||||||
|
#define clock_end u64 end=rdtsc_64bits(); \
|
||||||
|
printf(" execute cycle(s) %llu, %zu operation(s) take place!\n",end-begin,freq);
|
||||||
|
|
||||||
|
#define record_start u64 r_begin=rdtsc_64bits();
|
||||||
|
#define record_end(x) output_csv(x,r_begin);
|
||||||
|
|
||||||
|
// #define record_start ;
|
||||||
|
// #define record_end(x) ;
|
||||||
|
|
||||||
|
unsigned long long int rdtsc_64bits();
|
||||||
|
void output_csv(char * filename,unsigned long long int old);
|
|
@ -0,0 +1,22 @@
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "rust.h"
|
||||||
|
#define B 100
|
||||||
|
|
||||||
|
struct Entries{
|
||||||
|
void* key;
|
||||||
|
void* val;
|
||||||
|
};
|
||||||
|
struct Entry{
|
||||||
|
usize size;
|
||||||
|
usize cap;
|
||||||
|
struct Entries* list;
|
||||||
|
};
|
||||||
|
struct HashMap{
|
||||||
|
struct Entry entry[B];
|
||||||
|
usize (*hasher)(void *);
|
||||||
|
bool (*eq)(void *,void *);
|
||||||
|
};
|
||||||
|
void hash_new(struct HashMap* map,usize (*hasher)(void *), bool (*eq)(void *,void *));
|
||||||
|
void hash_insert(struct HashMap* map,void* key,void* val);
|
||||||
|
void* hash_get(struct HashMap* map,void* key);
|
||||||
|
void* hash_pop(struct HashMap* map,void* key);
|
|
@ -0,0 +1,13 @@
|
||||||
|
#include "rust.h"
|
||||||
|
|
||||||
|
struct Node{
|
||||||
|
void* val;
|
||||||
|
__INTPTR_TYPE__ xor_;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Node* xor_new(void * val);
|
||||||
|
struct Node* xor_next(struct Node* previous,struct Node* current);
|
||||||
|
struct Node* xor_insert_front(struct Node* head,void* val);
|
||||||
|
struct Node* xor_insert_mid(struct Node* previous,struct Node* current,void * val);
|
||||||
|
void * xor_remove(struct Node * previous,struct Node* current);
|
||||||
|
usize xor_count(struct Node* head);
|
|
@ -0,0 +1,13 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#define u8 unsigned char
|
||||||
|
#define u16 unsigned short int
|
||||||
|
#define u32 unsigned int
|
||||||
|
#define u64 unsigned long int
|
||||||
|
#define i8 char
|
||||||
|
#define i16 short int
|
||||||
|
#define i32 int
|
||||||
|
#define i64 long int
|
||||||
|
#define usize size_t
|
||||||
|
|
||||||
|
void panic(char * msg);
|
||||||
|
void log_warn(char * msg);
|
|
@ -0,0 +1,26 @@
|
||||||
|
#include "rust.h"
|
||||||
|
|
||||||
|
struct HashMap;
|
||||||
|
|
||||||
|
union Submask
|
||||||
|
{
|
||||||
|
u8 mask[4];
|
||||||
|
u32 raw;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SizedSubmask
|
||||||
|
{
|
||||||
|
union Submask mask;
|
||||||
|
usize len;
|
||||||
|
};
|
||||||
|
|
||||||
|
usize display_submask(struct SizedSubmask *mask);
|
||||||
|
usize display_ip(struct SizedSubmask *mask);
|
||||||
|
void parse_submask(char* cstr, struct SizedSubmask *mask);
|
||||||
|
struct SizedSubmask* clone_submask(struct SizedSubmask *mask);
|
||||||
|
bool reduce_submask(struct SizedSubmask* source);
|
||||||
|
|
||||||
|
struct State{
|
||||||
|
struct Node* head;
|
||||||
|
struct HashMap* hashmap;
|
||||||
|
};
|
|
@ -0,0 +1,2 @@
|
||||||
|
void input(struct State* state);
|
||||||
|
void length_distribution(struct State* state);
|
|
@ -0,0 +1,3 @@
|
||||||
|
#include "state.h"
|
||||||
|
|
||||||
|
void segment(struct State* state);
|
|
@ -0,0 +1,3 @@
|
||||||
|
void prefix_insert(struct State* state);
|
||||||
|
void prefix_delete(struct State* state);
|
||||||
|
void search(struct State* state);
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,21 @@
|
||||||
|
profile:
|
||||||
|
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS="-fprofile-instr-generate" -DCMAKE_CXX_FLAGS="-fprofile-instr-generate" -DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=lld" -C clang-cmakeinit.cmake .
|
||||||
|
make
|
||||||
|
LLVM_PROFILE_FILE="homework_11.profraw" ./homework_11
|
||||||
|
|
||||||
|
release-profile:
|
||||||
|
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS="-fprofile-instr-use=homework_11.profdata" -DCMAKE_CXX_FLAGS="-fprofile-instr-use=homework_11.profdata" -C clang-cmakeinit.cmake .
|
||||||
|
llvm-profdata merge -output=homework_11.profdata homework_11.profraw
|
||||||
|
make VERBOSE=1
|
||||||
|
|
||||||
|
release:
|
||||||
|
cmake -C clang-cmakeinit.cmake .
|
||||||
|
make
|
||||||
|
|
||||||
|
run:
|
||||||
|
cmake -DCMAKE_C_FLAGS="-fstandalone-debug" -DCMAKE_BUILD_TYPE=Debug -C clang-cmakeinit.cmake .
|
||||||
|
make VERBOSE=1
|
||||||
|
./homework_11
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -fr CMakeFiles build CMakeCache.txt Makefile cmake_install.cmake *.csv *.profdata *.profraw
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,55 @@
|
||||||
|
# homework 11 (HW11)
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
1. Get a computer with x86 feature level v3
|
||||||
|
2. Run `./homework_11`
|
||||||
|
3. See `./Doc` to skip running the actual program
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
1. install `clang` and `just`
|
||||||
|
2. run `just profile`
|
||||||
|
3. run `just release-profile`
|
||||||
|
4. run `./homework_11`
|
||||||
|
|
||||||
|
## Shellshot?~~Screenshot~~
|
||||||
|
|
||||||
|
```console
|
||||||
|
[34mWelcome to homework 11 (HW11)![0m
|
||||||
|
Does it look very familiar?
|
||||||
|
|
||||||
|
[ [32mOK[0m ] Reached target [33minput[0m.
|
||||||
|
There are 1 prefix which have prefix len of 3
|
||||||
|
There are 1 prefix which have prefix len of 5
|
||||||
|
There are 3 prefix which have prefix len of 6
|
||||||
|
There are 4 prefix which have prefix len of 7
|
||||||
|
There are 107 prefix which have prefix len of 8
|
||||||
|
There are 3 prefix which have prefix len of 9
|
||||||
|
There are 5 prefix which have prefix len of 10
|
||||||
|
There are 9 prefix which have prefix len of 11
|
||||||
|
There are 47 prefix which have prefix len of 12
|
||||||
|
There are 70 prefix which have prefix len of 13
|
||||||
|
There are 164 prefix which have prefix len of 14
|
||||||
|
There are 317 prefix which have prefix len of 15
|
||||||
|
There are 6117 prefix which have prefix len of 16
|
||||||
|
There are 1083 prefix which have prefix len of 17
|
||||||
|
There are 1769 prefix which have prefix len of 18
|
||||||
|
There are 4489 prefix which have prefix len of 19
|
||||||
|
There are 5553 prefix which have prefix len of 20
|
||||||
|
There are 4246 prefix which have prefix len of 21
|
||||||
|
There are 6090 prefix which have prefix len of 22
|
||||||
|
There are 7772 prefix which have prefix len of 23
|
||||||
|
There are 43679 prefix which have prefix len of 24
|
||||||
|
There are 383 prefix which have prefix len of 25
|
||||||
|
There are 387 prefix which have prefix len of 26
|
||||||
|
There are 439 prefix which have prefix len of 27
|
||||||
|
There are 338 prefix which have prefix len of 28
|
||||||
|
There are 989 prefix which have prefix len of 29
|
||||||
|
There are 454 prefix which have prefix len of 30
|
||||||
|
There are 1 prefix which have prefix len of 31
|
||||||
|
There are 113 prefix which have prefix len of 32
|
||||||
|
[ [32mOK[0m ] Reached target [33mlength_distribution[0m.
|
||||||
|
'd' is 8
|
||||||
|
There are 4949 prefix in group 3355443200 (200.0.0.0/8)
|
||||||
|
```
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,24 @@
|
||||||
|
#include "rust.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
unsigned long long int rdtsc_64bits()//64-bit
|
||||||
|
{
|
||||||
|
unsigned long long int x;
|
||||||
|
unsigned a, d;
|
||||||
|
|
||||||
|
__asm__ volatile("rdtsc" : "=a" (a), "=d" (d));
|
||||||
|
|
||||||
|
return ((unsigned long long)a) | (((unsigned long long)d) << 32);;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void output_csv(char * filename,u64 old){
|
||||||
|
u64 new=rdtsc_64bits();
|
||||||
|
|
||||||
|
FILE* file = fopen(filename , "a");
|
||||||
|
|
||||||
|
fprintf(file, "%ld,",new-old);
|
||||||
|
|
||||||
|
fflush(file);
|
||||||
|
fclose(file);
|
||||||
|
}
|
|
@ -0,0 +1,110 @@
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "rust.h"
|
||||||
|
#define B 100
|
||||||
|
|
||||||
|
struct Entries{
|
||||||
|
void* key;
|
||||||
|
void* val;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Entry{
|
||||||
|
usize size;
|
||||||
|
usize cap;
|
||||||
|
struct Entries* list;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HashMap{
|
||||||
|
struct Entry entry[B];
|
||||||
|
usize (*hasher)(void *);
|
||||||
|
bool (*eq)(void *,void *);
|
||||||
|
};
|
||||||
|
|
||||||
|
//.please return '1' in clang, because only exactly '1' are guarantee to be true,
|
||||||
|
// value other than '0' and '1' in bool can cause UB.
|
||||||
|
void hash_new(struct HashMap* map,usize (*hasher)(void *), bool (*eq)(void *,void *)){
|
||||||
|
map->eq=eq;
|
||||||
|
map->hasher=hasher;
|
||||||
|
for(usize i=0;i<B;i++){
|
||||||
|
map->entry[i].cap=1;
|
||||||
|
map->entry[i].list=malloc(sizeof(struct Entries));
|
||||||
|
map->entry[i].size=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void hash_insert(struct HashMap* map,void* key,void* val){
|
||||||
|
usize hashed=map->hasher(key);
|
||||||
|
struct Entry* entry=map->entry+(hashed%B);
|
||||||
|
|
||||||
|
entry->list[entry->size].key=key;
|
||||||
|
entry->list[entry->size++].val=val;
|
||||||
|
if(entry->size==entry->cap){
|
||||||
|
entry->cap*=2;
|
||||||
|
entry->list=realloc(entry->list,sizeof(struct Entries)*entry->cap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void* hash_get(struct HashMap* map,void* key){
|
||||||
|
usize hashed=map->hasher(key);
|
||||||
|
struct Entry* entry=map->entry+(hashed%B);
|
||||||
|
|
||||||
|
for(size_t i=0;i<(entry->size);i++){
|
||||||
|
if (map->eq(entry->list[i].key,key)){
|
||||||
|
return entry->list[i].val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* hash_pop(struct HashMap* map,void* key){
|
||||||
|
usize hashed=map->hasher(key);
|
||||||
|
struct Entry* entry=map->entry+(hashed%B);
|
||||||
|
|
||||||
|
for(size_t i=0;i<(entry->size);i++){
|
||||||
|
if (map->eq(entry->list[i].key,key)){
|
||||||
|
void* tmp=entry->list[i].val;
|
||||||
|
usize tail=(--entry->size);
|
||||||
|
entry->list[i]=entry->list[tail];
|
||||||
|
return entry->list[i].val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
// struct Point{
|
||||||
|
// usize x;
|
||||||
|
// usize y;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// bool eq(void* x,void* y){
|
||||||
|
// struct Point* a=x;
|
||||||
|
// struct Point* b=y;
|
||||||
|
// return (a->x==b->x)&&(a->y==b->y);
|
||||||
|
// }
|
||||||
|
// usize hasher(void* a){
|
||||||
|
// struct Point* p=a;
|
||||||
|
// return (p->x)+(p->y)/2;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// int test()
|
||||||
|
// {
|
||||||
|
// struct HashMap map;
|
||||||
|
// struct Point pa;
|
||||||
|
// usize va=2;
|
||||||
|
// pa.x=2;
|
||||||
|
// pa.y=7;
|
||||||
|
// struct Point pb;
|
||||||
|
// usize vb=3;
|
||||||
|
// pb.x=1;
|
||||||
|
// pb.y=9;
|
||||||
|
// hash_new(&map,hasher,eq);
|
||||||
|
// hash_insert(&map,&pa,&va);
|
||||||
|
// hash_insert(&map,&pb,&vb);
|
||||||
|
|
||||||
|
// printf("pa has address of %zu\npb has address of %zu\n",&pa,&pb);
|
||||||
|
|
||||||
|
// usize * assert=hash_get(&map,&pb);
|
||||||
|
// printf("address: %zu\n",assert);
|
||||||
|
// printf("value: %zu\n",*assert);
|
||||||
|
|
||||||
|
// return 0;
|
||||||
|
// }
|
|
@ -0,0 +1,78 @@
|
||||||
|
// https://github.com/Seppel3210/rust-xor_-list
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "rust.h"
|
||||||
|
|
||||||
|
struct Node{
|
||||||
|
void* val;
|
||||||
|
__INTPTR_TYPE__ xor_;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Node* xor_new(void * val){
|
||||||
|
struct Node* node=malloc(sizeof(struct Node));
|
||||||
|
node->xor_=(__INTPTR_TYPE__)NULL;
|
||||||
|
node->val=val;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Node* xor_next(struct Node* previous,struct Node* current){
|
||||||
|
if(current==NULL) return NULL;
|
||||||
|
return (struct Node*)((current->xor_)^((__INTPTR_TYPE__)previous));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Node* xor_insert_mid(struct Node* previous,struct Node* current,void * val){
|
||||||
|
struct Node* node=malloc(sizeof(struct Node));
|
||||||
|
if(previous!=NULL)previous->xor_^=((__INTPTR_TYPE__)current)^((__INTPTR_TYPE__)node);
|
||||||
|
if(current!=NULL)current->xor_^=((__INTPTR_TYPE__)previous)^((__INTPTR_TYPE__)node);
|
||||||
|
node->val=val;
|
||||||
|
node->xor_=((__INTPTR_TYPE__)current)^((__INTPTR_TYPE__)previous);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Node* xor_insert_front(struct Node* head,void* val){
|
||||||
|
struct Node* next=xor_next(NULL,head);
|
||||||
|
return xor_insert_mid(head,next,val);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Node * xor_remove(struct Node * previous,struct Node* current){
|
||||||
|
// printf("previous: %zu, current: %zu\n",previous,current);
|
||||||
|
struct Node * next=xor_next(previous,current);
|
||||||
|
if(previous!=NULL) previous->xor_^=(__INTPTR_TYPE__)current^(__INTPTR_TYPE__)next;
|
||||||
|
if(next!=NULL) next->xor_^=(__INTPTR_TYPE__)current^(__INTPTR_TYPE__)previous;
|
||||||
|
free(current);
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
usize xor_count(struct Node* head){
|
||||||
|
struct Node* previous=NULL;
|
||||||
|
struct Node* current=head;
|
||||||
|
|
||||||
|
usize amount=0;
|
||||||
|
while(current!=NULL){
|
||||||
|
struct Node* next=xor_next(previous,current);
|
||||||
|
// printf("previous: %zu, current: %zu, next: %zu\n",previous,current,next);
|
||||||
|
struct SizedSubmask* mask=current->val;
|
||||||
|
amount++;
|
||||||
|
|
||||||
|
previous=current;
|
||||||
|
current=next;
|
||||||
|
}
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// int test()
|
||||||
|
// {
|
||||||
|
// usize my_item=10;
|
||||||
|
|
||||||
|
// struct Node* first=xor_new(&my_item);
|
||||||
|
// struct Node* second=xor_insert(NULL,first,&my_item);
|
||||||
|
// struct Node* third=xor_insert(second,second,&my_item);
|
||||||
|
|
||||||
|
// usize* my_item_ptr=xor_remove(first,second);
|
||||||
|
|
||||||
|
// printf("%zu",*my_item_ptr);
|
||||||
|
|
||||||
|
// return 0;
|
||||||
|
// }
|
|
@ -0,0 +1,83 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "linklist.h"
|
||||||
|
#include "hashmap.h"
|
||||||
|
#include "v1.h"
|
||||||
|
#include "v2.h"
|
||||||
|
#include "v3.h"
|
||||||
|
#include "rust.h"
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
struct State state;
|
||||||
|
state.head=NULL;
|
||||||
|
|
||||||
|
printf("\x1B[34mWelcome to homework 11 (HW11)!\x1B[0m\nDoes it look very familiar?\n\n");
|
||||||
|
|
||||||
|
input(&state);
|
||||||
|
printf(" [ \x1B[32mOK\x1B[0m ] Reached target \x1B[33minput\x1B[0m.\n");
|
||||||
|
length_distribution(&state);
|
||||||
|
printf(" [ \x1B[32mOK\x1B[0m ] Reached target \x1B[33mlength_distribution\x1B[0m.\n");
|
||||||
|
segment(&state);
|
||||||
|
printf(" [ \x1B[32mOK\x1B[0m ] Reached target \x1B[33msegment\x1B[0m.\n");
|
||||||
|
prefix_insert(&state);
|
||||||
|
printf(" [ \x1B[32mOK\x1B[0m ] Reached target \x1B[33mprefix_insert\x1B[0m.\n");
|
||||||
|
prefix_delete(&state);
|
||||||
|
printf(" [ \x1B[32mOK\x1B[0m ] Reached target \x1B[33mprefix_delete\x1B[0m.\n");
|
||||||
|
search(&state);
|
||||||
|
printf(" [ \x1B[32mOK\x1B[0m ] Reached target \x1B[33msearch\x1B[0m.\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// struct Point{
|
||||||
|
// usize x;
|
||||||
|
// usize y;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// bool eqa(void* x,void* y){
|
||||||
|
// struct Point* a=x;
|
||||||
|
// struct Point* b=y;
|
||||||
|
// return (a->x==b->x)&&(a->y==b->y);
|
||||||
|
// }
|
||||||
|
// usize hashera(void* a){
|
||||||
|
// struct Point* p=a;
|
||||||
|
// return (p->x)+(p->y)/2;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// int main()
|
||||||
|
// {
|
||||||
|
// struct HashMap map;
|
||||||
|
// hash_new(&map,hashera,eqa);
|
||||||
|
|
||||||
|
// // struct Point pa;
|
||||||
|
// // usize va=2;
|
||||||
|
// // pa.x=2;
|
||||||
|
// // pa.y=7;
|
||||||
|
// // struct Point pb;
|
||||||
|
// // usize vb=3;
|
||||||
|
// // pb.x=1;
|
||||||
|
// // pb.y=9;
|
||||||
|
// // hash_insert(&map,&pa,&va);
|
||||||
|
// // hash_insert(&map,&pb,&vb);
|
||||||
|
|
||||||
|
// // printf("pa has address of %zu\npb has address of %zu\n",&pa,&pb);
|
||||||
|
|
||||||
|
// // usize * assert=hash_get(&map,&pb);
|
||||||
|
// // printf("address: %zu\n",assert);
|
||||||
|
// // printf("value: %zu\n",*assert);
|
||||||
|
|
||||||
|
|
||||||
|
// for(usize i=0;i<B;i++){
|
||||||
|
// struct Entry *entry=map.entry+i;
|
||||||
|
// printf("entry size: %zu\n",entry->size);
|
||||||
|
// // for(usize j=0;j<entry[i].size;j++){
|
||||||
|
// // struct SizedSubmask* mask=entry->list[j].key;
|
||||||
|
// // struct Node* ll=entry->list[j].val;
|
||||||
|
// // // usize count=xor_count(ll);
|
||||||
|
// // printf("one entry\n");
|
||||||
|
// // // printf("There are _ prefix in group %u\n",mask->mask.raw);
|
||||||
|
// // }
|
||||||
|
// }
|
||||||
|
// return 0;
|
||||||
|
// }
|
|
@ -0,0 +1,19 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#define u8 unsigned char
|
||||||
|
#define u16 unsigned short int
|
||||||
|
#define u32 unsigned int
|
||||||
|
#define u64 unsigned long int
|
||||||
|
#define i8 char
|
||||||
|
#define i16 short int
|
||||||
|
#define i32 int
|
||||||
|
#define i64 long int
|
||||||
|
#define usize size_t
|
||||||
|
|
||||||
|
void panic(char * msg){
|
||||||
|
fprintf(stderr," [\x1B[31mERROR\x1B[0m ] %s\n",msg);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
void log_warn(char * msg){
|
||||||
|
fprintf(stderr," [ \x1B[33mWARN\x1B[0m ] %s\n",msg);
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "rust.h"
|
||||||
|
#include "linklist.h"
|
||||||
|
#include "hashmap.h"
|
||||||
|
#define D 8
|
||||||
|
|
||||||
|
union Submask
|
||||||
|
{
|
||||||
|
u8 mask[4];
|
||||||
|
u32 raw;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SizedSubmask
|
||||||
|
{
|
||||||
|
union Submask mask;
|
||||||
|
usize len;
|
||||||
|
};
|
||||||
|
|
||||||
|
usize parse_number(char** cstr_ptr){
|
||||||
|
usize tmp=0;
|
||||||
|
while((**cstr_ptr<='9')&&(**cstr_ptr>='0')){
|
||||||
|
tmp=tmp*10+(usize)(**cstr_ptr-'0');
|
||||||
|
(*cstr_ptr)++;
|
||||||
|
}
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
usize display_submask(struct SizedSubmask *mask){
|
||||||
|
printf("%3hd.%hd.%hd.%hd/%zu",mask->mask.mask[3],mask->mask.mask[2],mask->mask.mask[1],mask->mask.mask[0],mask->len);
|
||||||
|
}
|
||||||
|
|
||||||
|
usize display_ip(struct SizedSubmask *mask){
|
||||||
|
printf("%3hd.%3hd.%3hd.%3hd",mask->mask.mask[3],mask->mask.mask[2],mask->mask.mask[1],mask->mask.mask[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void parse_submask(char* cstr, struct SizedSubmask *mask){
|
||||||
|
for (usize i=0;i<4;i++){
|
||||||
|
mask->mask.mask[3-i]=(u8)parse_number(&cstr);
|
||||||
|
cstr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(*cstr<'0'||*cstr>'9'){
|
||||||
|
usize i=0;
|
||||||
|
for (i=0;i<4;i++)
|
||||||
|
if(mask->mask.mask[3-i]==0)break;
|
||||||
|
mask->len=i*8;
|
||||||
|
}else mask->len=parse_number(&cstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SizedSubmask* clone_submask(struct SizedSubmask *mask){
|
||||||
|
struct SizedSubmask *new=malloc(sizeof(struct SizedSubmask));
|
||||||
|
new->len=mask->len;
|
||||||
|
new->mask.raw=mask->mask.raw;
|
||||||
|
return new;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool reduce_submask(struct SizedSubmask* source){
|
||||||
|
if(source->len<D)return false;
|
||||||
|
|
||||||
|
u32 mask=source->mask.raw;
|
||||||
|
source->len=D;
|
||||||
|
source->mask.raw=((mask>>(32-D))<<(32-D));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct State{
|
||||||
|
struct Node* head;
|
||||||
|
struct HashMap hashmap;
|
||||||
|
};
|
||||||
|
|
||||||
|
// int test()
|
||||||
|
// {
|
||||||
|
// char *example = "192.168.1.1/24";
|
||||||
|
// struct SizedSubmask mask;
|
||||||
|
// parse_submask(example, &mask);
|
||||||
|
|
||||||
|
// printf("CIDR: %u.%u.%u.%u/%u\n", mask.mask.mask[3], mask.mask.mask[2], mask.mask.mask[1], mask.mask.mask[0],mask.len);
|
||||||
|
|
||||||
|
// return 0;
|
||||||
|
// }
|
|
@ -0,0 +1,48 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "linklist.h"
|
||||||
|
#include "state.h"
|
||||||
|
|
||||||
|
void input(struct State* state){
|
||||||
|
FILE * table = fopen("routing_table.txt","r");
|
||||||
|
|
||||||
|
struct Node* head=NULL;
|
||||||
|
while(true){
|
||||||
|
char buffer[20]={'\0'};
|
||||||
|
fgets(buffer,20,table);
|
||||||
|
if(*buffer=='\0') break;
|
||||||
|
|
||||||
|
struct SizedSubmask* mask=malloc(sizeof(struct SizedSubmask));
|
||||||
|
// printf("address of new mask: %zu\n",mask);
|
||||||
|
parse_submask(buffer,mask);
|
||||||
|
|
||||||
|
if(head==NULL)head=xor_new(mask);
|
||||||
|
else head=xor_insert_mid(NULL,head,mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
state->head=head;
|
||||||
|
}
|
||||||
|
|
||||||
|
void length_distribution(struct State* state){
|
||||||
|
usize lens[33]={0};
|
||||||
|
|
||||||
|
struct Node* previous=NULL;
|
||||||
|
struct Node* current=state->head;
|
||||||
|
|
||||||
|
while(current!=NULL){
|
||||||
|
struct Node* next=xor_next(previous,current);
|
||||||
|
struct SizedSubmask* mask=current->val;
|
||||||
|
lens[mask->len]++;
|
||||||
|
|
||||||
|
// printf("address of scanning mask: %zu\n",mask);
|
||||||
|
|
||||||
|
previous=current;
|
||||||
|
current=next;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(usize i=0;i<=32;i++){
|
||||||
|
if(lens[i]!=0) printf(" There are %5zu prefix which have prefix len of %2zu\n",lens[i],i);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "linklist.h"
|
||||||
|
#include "hashmap.h"
|
||||||
|
#include "state.h"
|
||||||
|
#define D 8
|
||||||
|
|
||||||
|
// assume there is no prefix like this 192.0.0.0/1, this is a strange prefix,
|
||||||
|
// because 192.0.0.0 has first two bit set, but is has submask smaller than two
|
||||||
|
bool eq(void* a,void* b){
|
||||||
|
struct SizedSubmask* mask_a=a;
|
||||||
|
struct SizedSubmask* mask_b=b;
|
||||||
|
return mask_a->mask.raw==mask_b->mask.raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
usize hasher(void* a){
|
||||||
|
struct SizedSubmask* mask=a;
|
||||||
|
return mask->mask.raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
// std::collections::HashMap<SizedSubmask,XorLinklist<SizeSubmask>>
|
||||||
|
void segment(struct State* state){
|
||||||
|
printf(" \'d\' is %2d, and empty group are skipped!\n",D);
|
||||||
|
|
||||||
|
state->hashmap=malloc(sizeof(struct HashMap));
|
||||||
|
hash_new(state->hashmap,hasher,eq);
|
||||||
|
|
||||||
|
struct Node* previous=NULL;
|
||||||
|
struct Node* current=state->head;
|
||||||
|
|
||||||
|
while (current!=NULL){
|
||||||
|
struct SizedSubmask* mask= current->val;
|
||||||
|
struct SizedSubmask* ip=clone_submask(mask);
|
||||||
|
if(reduce_submask(mask)){
|
||||||
|
current=xor_remove(previous,current);
|
||||||
|
struct Node* ll=hash_get(state->hashmap,mask);
|
||||||
|
if(ll==NULL){
|
||||||
|
struct Node* ll=xor_new(ip);
|
||||||
|
hash_insert(state->hashmap,mask,ll);
|
||||||
|
}else{
|
||||||
|
xor_insert_front(ll,ip);
|
||||||
|
free(mask);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
struct Node* next=xor_next(previous,current);
|
||||||
|
previous=current;
|
||||||
|
current=next;
|
||||||
|
free(ip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
state->head=previous;
|
||||||
|
|
||||||
|
for(usize i=0;i<B;i++){
|
||||||
|
struct Entry *entry=state->hashmap->entry+i;
|
||||||
|
for(usize j=0;j<entry->size;j++){
|
||||||
|
struct SizedSubmask* mask=entry->list[j].key;
|
||||||
|
struct Node* ll=entry->list[j].val;
|
||||||
|
usize count=xor_count(ll);
|
||||||
|
if(count!=0){
|
||||||
|
printf(" There are %5zu prefix in group %10u (",count,mask->mask.raw);
|
||||||
|
display_submask(mask);
|
||||||
|
printf(")\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,168 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "linklist.h"
|
||||||
|
#include "state.h"
|
||||||
|
#include "hashmap.h"
|
||||||
|
#include "clock.h"
|
||||||
|
|
||||||
|
bool eq_v3(void* a,void* b){
|
||||||
|
struct SizedSubmask* mask_a=a;
|
||||||
|
struct SizedSubmask* mask_b=b;
|
||||||
|
return mask_a->mask.raw==mask_b->mask.raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Node* xor_remove_match(struct Node* head,void* target,bool (*eq)(void *,void *)){
|
||||||
|
struct Node* previous=NULL;
|
||||||
|
struct Node* current=head;
|
||||||
|
while(current!=NULL){
|
||||||
|
struct Node* next=xor_next(previous,current);
|
||||||
|
if(eq(current->val,target)){
|
||||||
|
free(current->val);
|
||||||
|
xor_remove(previous,current);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
previous=current;
|
||||||
|
current=next;
|
||||||
|
}
|
||||||
|
if(previous==NULL) return xor_next(previous,current);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool xor_contain(struct Node* head,void* target,bool (*eq)(void *,void *)){
|
||||||
|
struct Node* previous=NULL;
|
||||||
|
struct Node* current=head;
|
||||||
|
while(current!=NULL){
|
||||||
|
struct Node* next=xor_next(previous,current);
|
||||||
|
if(eq(current->val,target)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
previous=current;
|
||||||
|
current=next;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void prefix_insert(struct State* state){
|
||||||
|
FILE * table = fopen("inserted_prefixes.txt","r");
|
||||||
|
|
||||||
|
clock_start
|
||||||
|
|
||||||
|
while(true){
|
||||||
|
char buffer[20]={'\0'};
|
||||||
|
fgets(buffer,20,table);
|
||||||
|
if(*buffer=='\0') break;
|
||||||
|
|
||||||
|
struct SizedSubmask* mask=malloc(sizeof(struct SizedSubmask));
|
||||||
|
parse_submask(buffer,mask);
|
||||||
|
struct SizedSubmask* ip=clone_submask(mask);
|
||||||
|
|
||||||
|
record_start
|
||||||
|
|
||||||
|
if(reduce_submask(mask)){
|
||||||
|
struct Node* ll=hash_get(state->hashmap,mask);
|
||||||
|
if(ll==NULL){
|
||||||
|
struct Node* ll=xor_new(ip);
|
||||||
|
hash_insert(state->hashmap,mask,ll);
|
||||||
|
}else{
|
||||||
|
xor_insert_front(ll,ip);
|
||||||
|
free(mask);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
free(ip);
|
||||||
|
if(state->head==NULL)state->head=xor_new(mask);
|
||||||
|
else state->head=xor_insert_mid(NULL,state->head,mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
record_end("prefix_insert.csv")
|
||||||
|
|
||||||
|
freq++;
|
||||||
|
}
|
||||||
|
|
||||||
|
clock_end
|
||||||
|
}
|
||||||
|
|
||||||
|
void prefix_delete(struct State* state){
|
||||||
|
FILE * table = fopen("deleted_prefixes.txt","r");
|
||||||
|
|
||||||
|
clock_start
|
||||||
|
|
||||||
|
while(true){
|
||||||
|
char buffer[20]={'\0'};
|
||||||
|
fgets(buffer,20,table);
|
||||||
|
if(*buffer=='\0') break;
|
||||||
|
|
||||||
|
|
||||||
|
struct SizedSubmask* mask=malloc(sizeof(struct SizedSubmask));
|
||||||
|
parse_submask(buffer,mask);
|
||||||
|
struct SizedSubmask* ip=clone_submask(mask);
|
||||||
|
|
||||||
|
record_start
|
||||||
|
|
||||||
|
if(reduce_submask(mask)){
|
||||||
|
struct Node* ll=hash_pop(state->hashmap,mask);
|
||||||
|
if(ll==NULL) {
|
||||||
|
log_warn("removal fail, cannot find index!");
|
||||||
|
goto drop;
|
||||||
|
}
|
||||||
|
struct Node* new_head=xor_remove_match(ll,ip,eq_v3);
|
||||||
|
if(new_head==NULL) hash_insert(state->hashmap,mask,ll);
|
||||||
|
else hash_insert(state->hashmap,mask,new_head);
|
||||||
|
}else{
|
||||||
|
struct Node* ll=state->head;
|
||||||
|
if(ll==NULL) {
|
||||||
|
log_warn("removal fail, cannot find index!");
|
||||||
|
goto drop;
|
||||||
|
}
|
||||||
|
struct Node* new_head=xor_remove_match(ll,ip,eq_v3);
|
||||||
|
if(new_head!=NULL) state->head=new_head;
|
||||||
|
}
|
||||||
|
freq++;
|
||||||
|
|
||||||
|
record_end("prefix_delete.csv")
|
||||||
|
|
||||||
|
drop:
|
||||||
|
free(ip);
|
||||||
|
free(mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
clock_end
|
||||||
|
}
|
||||||
|
|
||||||
|
void search(struct State* state){
|
||||||
|
FILE * table = fopen("trace_file.txt","r");
|
||||||
|
|
||||||
|
clock_start
|
||||||
|
|
||||||
|
while(true){
|
||||||
|
char buffer[20]={'\0'};
|
||||||
|
fgets(buffer,20,table);
|
||||||
|
if(*buffer=='\0') break;
|
||||||
|
|
||||||
|
struct SizedSubmask* mask=malloc(sizeof(struct SizedSubmask));
|
||||||
|
parse_submask(buffer,mask);
|
||||||
|
struct SizedSubmask* ip=clone_submask(mask);
|
||||||
|
|
||||||
|
record_start
|
||||||
|
|
||||||
|
struct Node* ll;
|
||||||
|
if(reduce_submask(mask))ll=hash_get(state->hashmap,mask);
|
||||||
|
else ll=state->head;
|
||||||
|
|
||||||
|
freq++;
|
||||||
|
|
||||||
|
record_end("search.csv")
|
||||||
|
|
||||||
|
printf(" submask: ");
|
||||||
|
display_ip(ip);
|
||||||
|
|
||||||
|
if (xor_contain(ll,ip,eq_v3)) printf(" can be found among entries\n");
|
||||||
|
else printf(" cannot be found among entries\n");
|
||||||
|
|
||||||
|
free(ip);
|
||||||
|
free(mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
clock_end
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue