From 918ebf5a8fa10c53505d5af9347af22ca23f4021 Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Mon, 27 Jan 2025 21:06:08 -0800 Subject: [PATCH] shuffle poset - initial commit --- .gitignore | 2 + bin/begin_bld_session.sh | 12 + bin/bld/bld_cmd.sh | 26 ++ bin/bld/bld_core.sh | 757 +++++++++++++++++++++++++++++++ bin/build.sh | 9 + bin/initfiles/init.exe_paths.txt | 6 + bin/initfiles/init.local_vars.sh | 8 + bin/options/assembler_flags.txt | 2 + bin/options/compiler_flags.txt | 41 ++ bin/options/file_extensions.txt | 12 + bin/options/linker_flags.txt | 53 +++ local/exe_paths.txt | 6 + local/local_vars.sh | 8 + project.4coder | 35 ++ src/shuffle_poset.c | 449 ++++++++++++++++++ src/shuffle_poset.h | 72 +++ 16 files changed, 1498 insertions(+) create mode 100644 .gitignore create mode 100644 bin/begin_bld_session.sh create mode 100644 bin/bld/bld_cmd.sh create mode 100644 bin/bld/bld_core.sh create mode 100644 bin/build.sh create mode 100644 bin/initfiles/init.exe_paths.txt create mode 100644 bin/initfiles/init.local_vars.sh create mode 100644 bin/options/assembler_flags.txt create mode 100644 bin/options/compiler_flags.txt create mode 100644 bin/options/file_extensions.txt create mode 100644 bin/options/linker_flags.txt create mode 100644 local/exe_paths.txt create mode 100644 local/local_vars.sh create mode 100644 project.4coder create mode 100644 src/shuffle_poset.c create mode 100644 src/shuffle_poset.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3dfc7a7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +build/* +papers/* \ No newline at end of file diff --git a/bin/begin_bld_session.sh b/bin/begin_bld_session.sh new file mode 100644 index 0000000..f5f1d75 --- /dev/null +++ b/bin/begin_bld_session.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +root_path=$PWD +opts_path="$root_path/bin/options" +bld_path="$root_path/bin/bld" +local_path="$root_path/local" +src_path="$root_path/src" +build_path="$root_path/build" +program_pather="$local_path/exe_paths.txt" + +. $local_path/local_vars.sh +. $bld_path/bld_core.sh diff --git a/bin/bld/bld_cmd.sh b/bin/bld/bld_cmd.sh new file mode 100644 index 0000000..a3ce5ac --- /dev/null +++ b/bin/bld/bld_cmd.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +###### Parse Arguments ######################################################## +command=$1 +args=() +for ((i=2; i<=$#; i+=1)); do + args+=(${!i}) +done + +###### Source the Core ######################################################## +bld_path="$(dirname $(realpath "$0"))" +source "$bld_path/bld_core.sh" + +###### Dispatch ############################################################### +if [ "$command" == "cmp" ]; then + bld_compile "${args[@]}" +elif [ "$command" == "lnk" ]; then + bld_link "${args[@]}" +elif [ "$command" == "lib" ]; then + bld_lib "${args[@]}" +elif [ "$command" == "unit" ]; then + bld_unit "${args[@]}" +else + echo "unknown command '$command'" +fi + diff --git a/bin/bld/bld_core.sh b/bin/bld/bld_core.sh new file mode 100644 index 0000000..718aeeb --- /dev/null +++ b/bin/bld/bld_core.sh @@ -0,0 +1,757 @@ +#!/bin/bash + +###### Usage ################################################################## +# To use the bld build system in a bash script, some setup is required: +# 1. Define paths: +# root_path, opts_path, bld_path, local_path, src_path, +# build_path, program_pather +# 2. Define local variables: +# compiler, compile_mode, arch, linker, ctx_opts +# 3. Then include this core file with "." prefix: +# . $bld_path/bld_core.sh +# +# +# The following bld functions form the core "commands": +# bld_compile, bld_link, bld_lib, bld_unit +# +# And there are several more helper functions: +# bld_print_implicit_opts, bld_load_local_opts +# +# +# Signatures: +# bld_compile +# bld_link -- \ +# +# bld_lib -- \ +# +# bld_unit +# +# bld_print_implicit_opts (no arguments) +# bld_load_local_opts (no arguments) +# +# +# Shared notes for all: +# + Options are gathered from the arguments, from the local context, and +# in the case of the commands bld_compile and bld_unit, from the source file. +# + Options gathered from local context are prefixed with their context +# variable like so [var:val]. So for example, on windows the options list +# includes [os:windows]. +# + Options in source files are specified between the strings //$ and //. +# + Object file extensions should be named based on whether they were +# generated by a compiler or assembler. Compiled objects should have the +# extension .cmp:o and assembled objects should have the extension +# .asm:o. The system automatically changes the name to match the correct +# extension given the context. +# + Static library files should have the extension .lib. The system +# automatically changes the name to match the correct extension given the +# context. +# + When the option "diagnostics" is included, extra details will be printed +# from the bld commands. Showing the full list of options, invokation lines, +# and the build path. +# +# bld_compile: +# + Creates an object file from a single source file via the selected compiler. +# +# bld_link: +# + Creates executables and shared binaries from source files, object files, +# and static libraries. First uses the bld_compile command on the source +# files. +# + Uses the selected linker. +# + If the short name for the linker does not work for any reason, the +# full path to the linker may be specified in a filter file pointed to by +# the setup variable `program_pather` +# + The output is a shared binary (.dll or .so) when the option "dll" is +# included. +# +# bld_lib: +# + Creates a static library from source files and object files. First uses +# the bld_compile command on the source files. Uses the OS to determine the +# correct archiver. +# +# bld_unit: +# + Creates an executable (or shared binary) from a single source file. +# This command essentially does a single bld_compile then bld_link. With +# two differences: +# 1. The options from the source file are visible to the bld_link. +# 2. The name of the executable is determined either from the first option +# in the list or from the source file name if there are no options. +# +# bld_print_implicit_opts: +# + Shows the implicit options loaded from the local parameters script. +# +# bld_load_local_opts: +# + It is possible and sometimes useful to modify the local parameters after +# they are loaded to create certain kinds of build scripts. This function +# resets the local parameters to their original states by rerunning the +# local parameters script. + + +###### Flags From Opts ######################################################## + +function bld_flags_from_opts { + ###### parse arguments #################################################### + local in_file=$1 + local opts=() + for ((i=2; i<=$#; i+=1)); do + opts+=(${!i}) + done + + ###### load file ########################################################## + local flags_raw=() + IFS=$'\r\n' GLOBIGNORE='*' command eval 'flags_raw=($(cat $in_file))' + + ###### filter ############################################################# + local flags=() + for ((i=0;i<${#flags_raw[@]};i+=1)); do + local flag=${flags_raw[i]} + + ###### skip blanks and comments ####################################### + if [[ -z "${flag// }" ]]; then + continue + fi + if [[ "${flag:0:1}" == "#" ]]; then + continue + fi + + ###### parse line filters ############################################# + local line_filters=() + while [[ $flag = *">"* ]]; do + line_filters+=("${flag%%>*}") + flag="${flag#*>}" + done + + ###### check filters ################################################## + local can_include=1 + for ((j=0;j<${#line_filters[@]};j+=1)); do + can_include=0 + for ((k=0;k<${#opts[@]};k+=1)); do + if [[ ${opts[k]} = ${line_filters[j]} ]]; then + can_include=1 + break + fi + done + if [[ "$can_include" = "0" ]]; then + break + fi + done + if [[ "$can_include" = "1" ]]; then + flags+=("${flag}") + fi + done + + echo "${flags[@]}" +} + +###### Opts From Src ########################################################## + +function bld_opts_from_src { + ###### split file into tokens ############################################# + local in_file=$1 + local tokens=($(grep "//\\$" $in_file)) + + ###### parse ############################################################## + local in_params_range="0" + local params=() + for ((i=0; i<${#tokens[@]}; i+=1)); do + local string="${tokens[i]}" + if [[ "$in_params_range" == "0" ]]; then + if [[ "$string" == "//$" ]]; then + in_params_range="1" + fi + elif [[ "$in_params_range" == "1" ]]; then + if [[ "${string:0:2}" == "//" ]]; then + break + fi + params+=($string) + fi + done + + echo "${params[@]}" +} + +###### Dedup ################################################################## + +function bld_dedup { + ###### parse arguments #################################################### + local in=() + for ((i=1; i<=$#; i+=1)); do + in+=(${!i}) + done + + ###### dedup ############################################################## + local out=() + for ((i=0; i<${#in[@]}; i+=1)); do + local string=${in[i]} + local is_dup="0" + for ((j=0; j<${#out[@]}; j+=1)); do + if [[ "$string" == "${out[j]}" ]]; then + is_dup="1" + break + fi + done + if [[ "$is_dup" == "0" ]]; then + out+=($string) + fi + done + + echo "${out[@]}" +} + +###### Has Opt ################################################################ + +function bld_has_opt { + ###### parse arguments #################################################### + local key_opt=$1 + local opts=() + for ((i=2; i<=$#; i+=1)); do + opts+=(${!i}) + done + + ###### scan ############################################################### + local has_key=0 + for ((i=0;i<${#opts[@]};i+=1)); do + local opt=${opts[i]} + if [[ "$opt" == "$key_opt" ]]; then + has_key=1 + break + fi + done + + echo $has_key +} + +###### Load Local Options ##################################################### + +function bld_load_local_opts { + ###### os cracking ######################################################## + os="undefined" + if [ "$OSTYPE" == "win32" ] || + [ "$OSTYPE" == "msys" ]; then + os="windows" + elif [ "$OSTYPE" == "linux-gnu" ]; then + os="linux" + elif [ "$OSTYPE" == "darwin" ]; then + os="mac" + fi + ###### load parameters from the local script ################################ + if [ -f "$local_path/local_vars.sh" ]; then + source "$local_path/local_vars.sh" + fi +} + +###### Implicit Opts ########################################################## + +function bld_implicit_opts { + local linker_opt="" + if [[ "$linker" == "link" || "$linker" == "lld-link" ]]; then + linker_opt="link:msvc" + fi + echo $ctx_opts cmp:$compiler mode:$compile_mode asm:$assembler + echo link:$linker $linker_opt os:$os arch:$arch +} + +###### Print Implicit Options ################################################# + +function bld_print_implicit_opts { + local opts=($(bld_implicit_opts)) + local bracketed=() + for ((i=0; i<=${#opts[@]}; i+=1)); do + local opt="${opts[i]}" + if [ "$opt" != "" ]; then + bracketed+=("[${opts[i]}]") + fi + done + echo "${bracketed[@]}" +} + +###### Print Help ############################################################# + +function bld_print_obj_note { + echo "NOTE: the interface does not use standard object file extensions" + echo "NOTE: use 'cmp:o' for object files produced by a compiler" + echo "NOTE: use 'asm:o' for object files produced by an assembler" +} + +###### Compile ################################################################ + +function bld_compile { + local i=0 + + ###### parse arguments #################################################### + local in_file=$1 + local opts=() + for ((i=2; i<=$#; i+=1)); do + opts+=(${!i}) + done + if [ "$in_file" == "" ]; then + echo "ERROR(compile): missing input file" + return 1 + fi + + ###### finish in file ##################################################### + local final_in_file=$in_file + + ###### determine build kind ############################################### + local ext="${final_in_file##*.}" + local build_kind="undetermined" + if [[ "$ext" == "c" || "$ext" == "cpp" ]]; then + build_kind="compile" + elif [[ "$ext" == "asm" ]]; then + build_kind="assemble" + else + echo "ERROR(compile): unrecgonized source type $final_in_file" + return 1 + fi + + ###### finish options ##################################################### + local src_opts=($(bld_opts_from_src $final_in_file)) + local impl_opts=($(bld_implicit_opts)) + local all_opts=($(bld_dedup ${impl_opts[@]} ${opts[@]} ${src_opts[@]})) + + ###### diagnostics ######################################################## + local diagnostics=$(bld_has_opt diagnostics ${all_opts[@]}) + + ###### out file name ###################################################### + local dot_ext_o="" + if [[ "$build_kind" == "compile" ]]; then + dot_ext_o=$(bld_ext_cmpo) + elif [[ "$build_kind" == "assemble" ]]; then + dot_ext_o=$(bld_ext_asmo) + fi + local file_base=${final_in_file##*/} + local file_base_no_ext=${file_base%.*} + local out_file="$file_base_no_ext$dot_ext_o" + + ###### get real flags ##################################################### + local flags="" + if [[ "$build_kind" == "compile" ]]; then + flags=$(bld_flags_from_opts $opts_path/compiler_flags.txt ${all_opts[@]}) + else + flags=$(bld_flags_from_opts $opts_path/assembler_flags.txt ${all_opts[@]}) + fi + + ###### move to output folder ############################################## + mkdir -p "$build_path" + cd $build_path + if [ "$diagnostics" == "1" ]; then + echo "build path: $build_path" + fi + + ###### delete existing object file ######################################## + rm -f "$out_file_base.o" + rm -f "$out_file_base.obj" + + ###### final flags ######################################################## + local final_flags="" + if [[ "$build_kind" == "compile" ]]; then + final_flags="-c -I$src_path ${flags}" + elif [[ "$build_kind" == "assemble" ]]; then + final_flags="-c ${flags}" + fi + + ###### compile ############################################################ + if [[ "$build_kind" == "compile" ]]; then + if [ "$diagnostics" == "1" ]; then + echo "cmp $final_in_file -- ${all_opts[@]}" + echo $compiler "$final_in_file" $final_flags + fi + if [ "$compiler" == "clang" ]; then + echo "$file_base" + fi + $compiler "$final_in_file" $final_flags + elif [[ "$build_kind" == "assemble" ]]; then + if [ "$diagnostics" == "1" ]; then + echo "asm $final_in_file -- ${all_opts[@]}" + echo $assembler $final_flags "$final_in_file" + fi + $assembler $final_flags "$final_in_file" + fi + + # return of status from compiler is automatic here. +} + +###### Link ################################################################### + +function bld_link { + local i=0 + + ###### parse arguments #################################################### + local out_name=$1 + local in_files=() + for ((i=2; i<=$#; i+=1)); do + if [ "${!i}" == "--" ]; then + break + fi + in_files+=(${!i}) + done + local opts=() + for ((i+=1; i<=$#; i+=1)); do + opts+=(${!i}) + done + if [ "$out_name" == "" ]; then + echo "link: missing output name" + return 1 + fi + if [ "${#in_files}" == "0" ]; then + echo "link: missing input file(s)" + return 1 + fi + + ###### finish options ##################################################### + local impl_opts=($(bld_implicit_opts)) + local all_opts=($(bld_dedup ${opts[@]} ${impl_opts[@]})) + + ###### diagnostics ######################################################## + local diagnostics=$(bld_has_opt diagnostics ${all_opts[@]}) + + ###### sort in files ###################################################### + local in_src=() + local in_cmpo=() + local in_asmo=() + local in_lib=() + for ((i=0; i<${#in_files[@]}; i+=1)); do + local file="${in_files[i]}" + local ext="${file##*.}" + if [[ "$ext" == "c" || "$ext" == "cpp" || "$ext" == "asm" ]]; then + in_src+=($file) + elif [[ "$ext" == "cmp:o" ]]; then + in_cmpo+=($file) + elif [[ "$ext" == "asm:o" ]]; then + in_asmo+=($file) + elif [[ "$ext" == "lib" ]]; then + in_lib+=($file) + else + echo "WARNING: ignoring unrecgonized file type $file" + if [[ "$ext" == "obj" || "$ext" == "o" ]]; then + bld_print_obj_note + fi + fi + done + + ###### auto correct compiled object files ################################# + local dot_ext_cmpo=$(bld_ext_cmpo) + for ((i=0; i<${#in_cmpo[@]}; i+=1)); do + local file_name="${in_cmpo[i]}" + local base_name="${file_name%.*}" + in_cmpo[$i]="$base_name$dot_ext_cmpo" + done + + ###### auto correct assembled object files ################################ + local dot_ext_asmo=$(bld_ext_asmo) + for ((i=0; i<${#in_asmo[@]}; i+=1)); do + local file_name="${in_asmo[i]}" + local base_name="${file_name%.*}" + in_asmo[$i]="$base_name$dot_ext_asmo" + done + + ###### combine object files ############################################### + local in_obj=() + for ((i=0; i<${#in_cmpo[@]}; i+=1)); do + local file="${in_cmpo[i]}" + in_obj+=($file) + done + for ((i=0; i<${#in_asmo[@]}; i+=1)); do + local file="${in_asmo[i]}" + in_obj+=($file) + done + + ###### compile source files ############################################### + for ((i=0; i<${#in_src[@]}; i+=1)); do + local file="${in_src[i]}" + bld_compile "$file" ${all_opts[@]} + local status=$? + if [ $status -ne 0 ]; then + return $status + fi + done + + ###### intermediate object files ########################################## + local interm_obj=() + for ((i=0; i<${#in_src[@]}; i+=1)); do + local file_name="${in_src[i]}" + local base_name="${file_name##*/}" + local base_name_no_ext="${base_name%.*}" + local ext="${base_name##*.}" + if [[ "$ext" == "c" || "$ext" == "cpp" ]]; then + interm_obj+=($base_name_no_ext$dot_ext_cmpo) + elif [[ "$ext" == "asm" ]]; then + interm_obj+=($base_name_no_ext$dot_ext_asmo) + fi + done + + ###### get real flags ##################################################### + local flags=$(bld_flags_from_opts $opts_path/linker_flags.txt ${all_opts[@]}) + + ###### out file name ###################################################### + local dot_ext_out="" + local is_dll=$(bld_has_opt dll ${all_opts[@]}) + if [ "$is_dll" == "0" ]; then + dot_ext_out=$(bld_ext_exe) + else + dot_ext_out=$(bld_ext_dll) + fi + out_file="$out_name$dot_ext_out" + + ###### move to output folder ############################################## + mkdir -p "$build_path" + cd $build_path + if [ "$diagnostics" == "1" ]; then + echo "build path: $build_path" + fi + + ###### final files to linker ############################################## + local final_in_files="${interm_obj[@]} ${in_obj[@]} ${in_lib[@]}" + + ###### set first diagnostic string ######################################## + local first_diagnostic_string="lnk $final_in_files -- ${all_opts[@]}" + + ###### linker executable name ############################################# + local linker_exe=$linker + local linker_rename=$(bld_flags_from_opts $program_pather "link:$linker") + if [[ "$linker_rename" != "" ]]; then + if [ "$diagnostics" == "1" ]; then + echo "linker rename: $linker_rename" + fi + linker_exe=$linker_rename + fi + + ###### link ############################################################### + local status=0 + local invokation="" + if [[ "$linker" == "link" || "$linker" == "lld-link" ]]; then + invokation="-OUT:$out_file $flags $final_in_files" + elif [ "$linker" == "clang" ]; then + invokation="-o $out_file $flags $final_in_files" + else + echo "ERROR(link): invokation not defined for this linker" + status=1 + fi + if [ "$invokation" != "" ]; then + if [ "$diagnostics" == "1" ]; then + echo $first_diagnostic_string + echo $linker_exe $invokation + fi + echo "$out_file" + "$linker_exe" $invokation + status=$? + fi + + return $status +} + +###### Library ################################################################ + +function bld_lib { + local i=0 + + ###### parse arguments #################################################### + local out_name=$1 + local in_files=() + for ((i=2; i<=$#; i+=1)); do + if [ "${!i}" == "--" ]; then + break + fi + in_files+=(${!i}) + done + local opts=() + for ((i+=1; i<=$#; i+=1)); do + opts+=(${!i}) + done + if [ "$out_name" == "" ]; then + echo "lib: missing output name" + return 1 + fi + if [ "${#in_files}" == "0" ]; then + echo "lib: missing input file(s)" + return 1 + fi + + ###### finish options ##################################################### + local impl_opts=($(bld_implicit_opts)) + local all_opts=($(bld_dedup ${opts[@]} ${impl_opts[@]})) + + ###### diagnostics ######################################################## + local diagnostics=$(bld_has_opt diagnostics ${all_opts[@]}) + + ###### sort in files ###################################################### + local in_src=() + local in_cmpo=() + local in_asmo=() + for ((i=0; i<${#in_files[@]}; i+=1)); do + local file="${in_files[i]}" + local ext="${file##*.}" + if [[ "$ext" == "c" || "$ext" == "cpp" ]]; then + in_src+=($file) + elif [[ "$ext" == "cmp:o" ]]; then + in_cmpo+=($file) + elif [[ "$ext" == "asm:o" ]]; then + in_asmo+=($file) + else + echo "WARNING: ignoring unrecgonized file type $file" + if [[ "$ext" == "obj" || "$ext" == "o" ]]; then + bld_print_obj_note + fi + fi + done + + ###### auto correct compiled object files ################################# + local dot_ext_cmpo=$(bld_ext_cmpo) + for ((i=0; i<${#in_cmpo[@]}; i+=1)); do + local file_name="${in_cmpo[i]}" + local base_name="${file_name%.*}" + in_cmpo[$i]=$base_name$dot_ext_cmpo + done + + ###### auto correct assembled object files ################################ + local dot_ext_asmo=$(bld_ext_asmo) + for ((i=0; i<${#in_asmo[@]}; i+=1)); do + local file_name="${in_asmo[i]}" + local base_name="${file_name%.*}" + in_asmo[$i]="$base_name$dot_ext_asmo" + done + + ###### combine object files ############################################### + local in_obj=() + for ((i=0; i<${#in_cmpo[@]}; i+=1)); do + local file="${in_cmpo[i]}" + in_obj+=($file) + done + for ((i=0; i<${#in_asmo[@]}; i+=1)); do + local file="${in_asmo[i]}" + in_obj+=($file) + done + + ###### compile source files ############################################### + for ((i=0; i<${#in_src[@]}; i+=1)); do + bld_compile "${in_src[i]}" ${all_opts[@]} + local status=$? + if [ $status -ne 0 ]; then + return $status + fi + done + + ###### intermediate object files ########################################## + local interm_obj=() + for ((i=0; i<${#in_src[@]}; i+=1)); do + local file_name="${in_src[i]}" + local base_name="${file_name##*/}" + local base_name_no_ext="${base_name%.*}" + local ext="${base_name##*.}" + if [[ "$ext" == "c" || "$ext" == "cpp" ]]; then + interm_obj+=($base_name_no_ext$dot_ext_cmpo) + elif [[ "$ext" == "asm" ]]; then + interm_obj+=($base_name_no_ext$dot_ext_asmo) + fi + done + + ###### out file name ###################################################### + local out_file="" + if [ "$os" == "windows" ]; then + out_file="$out_name.lib" + elif [ "$os" == "linux" || "$os" == "mac" ]; then + out_file="lib$out_name.a" + else + echo "ERROR(lib): static library output not defined for OS: $os" + fi + + ###### final library build input files #################################### + local final_in_files="${interm_obj[@]} ${in_obj[@]}" + + ###### move to output folder ############################################## + mkdir -p "$build_path" + cd $build_path + if [ "$diagnostics" == "1" ]; then + echo "build path: $build_path" + fi + + ###### set first diagnostic string ######################################## + local first_diagnostic_string="lib $final_in_files -- ${all_opts[@]}" + + ###### build library ###################################################### + local status=0 + if [ "$os" == "windows" ]; then + if [ "$diagnostics" == "1" ]; then + echo $first_diagnostic_string + echo lib -nologo -OUT:"$out_file" $final_in_files + fi + echo "$out_file" + lib -nologo -OUT:"$out_file" $final_in_files + status=$? + elif [ "$os" == "linux" || "$os" == "mac" ]; then + # TODO(allen): invoke ar here - make sure to delete the original .a first + # because ar does not (seem) to replace the output file, just append + echo "TODO: implement ar path in bld_core.sh:bld_lib" + status=1 + else + echo "ERROR(lib): static library invokation not defined for OS: $os" + status=1 + fi + + return $status +} + +###### Unit ################################################################### + +function bld_unit { + local i=0 + + ###### parse arguments #################################################### + local main_file=$1 + local opts=() + for ((i=2; i<=$#; i+=1)); do + opts+=(${!i}) + done + if [ "$main_file" == "" ]; then + echo "unit: missing main file" + return 1 + fi + + ###### set out name ####################################################### + local out_name="" + if [ "${#opts}" == "0" ]; then + local file_base=${main_file##*/} + local file_base_no_ext=${file_base%.*} + out_name=$file_base_no_ext + else + out_name="${opts[0]}" + fi + + ###### finish options ##################################################### + local src_opts=$(bld_opts_from_src $main_file) + local impl_opts=($(bld_implicit_opts)) + local all_opts=($(bld_dedup $out_name ${opts[@]} ${src_opts[@]} ${impl_opts[@]})) + + ###### link ############################################################### + bld_link $out_name $main_file ${in_files[@]} -- ${all_opts[@]} +} + +###### Special Ifs ############################################################ + +function bld_ext_cmpo { + echo $(bld_flags_from_opts $opts_path/file_extensions.txt cmp:$compiler "cmp:o") +} +function bld_ext_asmo { + echo $(bld_flags_from_opts $opts_path/file_extensions.txt asm:$assembler "asm:o") +} +function bld_ext_exe { + echo $(bld_flags_from_opts $opts_path/file_extensions.txt os:$os exe) +} +function bld_ext_dll { + echo $(bld_flags_from_opts $opts_path/file_extensions.txt os:$os dll) +} + +###### Load Locals ############################################################ +bld_load_local_opts + +############################################################################### +# TODO: Notes for future itations on this sytem +# - With the addition of the assembler, it is now becoming clear that the +# bld_compile path is feeling a bit overloaded and that the mapping of +# interface extensions to real extensions, and the mapping of interface +# extensions to inferred build steps, are major complicating factors. +# A new strategy for organizing multiple builders, and multiple conversion +# paths that may be inferred from a set of possible starting points would +# stand to simplify a lot of the system. +# - Switching out object file extensions +# - Subtlties of invoking different build kinds in bld_compile +# - Tracking subkinds through bld_link and bld_lib diff --git a/bin/build.sh b/bin/build.sh new file mode 100644 index 0000000..14a1200 --- /dev/null +++ b/bin/build.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +. bin/begin_bld_session.sh +bld_print_implicit_opts + +bld_unit /c/mr4th/mr4th/src/mr4th_base.target.c mr4th_base -- dll + +bld_unit $src_path/shuffle_poset.c shuffle_poset + diff --git a/bin/initfiles/init.exe_paths.txt b/bin/initfiles/init.exe_paths.txt new file mode 100644 index 0000000..8454833 --- /dev/null +++ b/bin/initfiles/init.exe_paths.txt @@ -0,0 +1,6 @@ +link:link>??? + +## The MSVC linker has been known to reside at this/these location(s) +## in some installations +# /c/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.31.31103/bin/Hostx64/x64/link.exe + diff --git a/bin/initfiles/init.local_vars.sh b/bin/initfiles/init.local_vars.sh new file mode 100644 index 0000000..41d574b --- /dev/null +++ b/bin/initfiles/init.local_vars.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +compiler="cl" +compile_mode="debug" +assembler="ml64" +arch="x64" +linker="link" +ctx_opts="" diff --git a/bin/options/assembler_flags.txt b/bin/options/assembler_flags.txt new file mode 100644 index 0000000..bd2ad4b --- /dev/null +++ b/bin/options/assembler_flags.txt @@ -0,0 +1,2 @@ +asm:ml64>-nologo +asm:ml64>mode:debug>-Zi \ No newline at end of file diff --git a/bin/options/compiler_flags.txt b/bin/options/compiler_flags.txt new file mode 100644 index 0000000..01c8932 --- /dev/null +++ b/bin/options/compiler_flags.txt @@ -0,0 +1,41 @@ +###### Include Paths ########################################################## +-I/c/mr4th/mr4th/src +-I/c/mr4th/mr4th/src/dependencies +freetype>-I/c/mr4th/mr4th/src/dependencies/freetype-2.12.1/include + + +###### CL ##################################################################### +cmp:cl>-nologo +cmp:cl>-FC +cmp:cl>-GR- +cmp:cl>-EHa + +cmp:cl>sanitizer>-fsanitize=address + +cmp:cl>dll>-LD + +###### Clang ################################################################## +cmp:clang>-Wno-writable-strings +cmp:clang>-Wno-switch +cmp:clang>-Wno-deprecated-declarations + +cmp:clang>sanitizer>-fsanitize=address +cmp:clang>sanitizer>-fsanitize=undefined +cmp:clang>os:linux>sanitizer>-fsanitize=safe-stack +cmp:clang>fuzzer>-fsanitize=fuzzer + +# TODO: DLL support + +###### Debug ################################################################## +mode:debug>-DMR4TH_ASSERTS=1 +mode:release>-DMR4TH_ASSERTS=0 +cmp:cl>mode:debug>-Zi +cmp:clang>mode:debug>-g + +sanitizer>-DMR4TH_SANITIZER=1 + +###### Profiling ############################################################## +manualprofile>-DMR4TH_PROFILING_MANUAL=1 + +autoprofile>-DMR4TH_PROFILING_AUTO=1 +cmp:clang>autoprofile>-finstrument-functions diff --git a/bin/options/file_extensions.txt b/bin/options/file_extensions.txt new file mode 100644 index 0000000..c1be22f --- /dev/null +++ b/bin/options/file_extensions.txt @@ -0,0 +1,12 @@ +cmp:o>cmp:cl>.obj +cmp:o>cmp:clang>.o +cmp:o>cmp:gcc>.o + +asm:o>asm:ml64>.obj + +exe>os:windows>.exe +dll>os:windows>.dll +dll>os:linux>.so +dll>os:mac>.so + + diff --git a/bin/options/linker_flags.txt b/bin/options/linker_flags.txt new file mode 100644 index 0000000..03f7059 --- /dev/null +++ b/bin/options/linker_flags.txt @@ -0,0 +1,53 @@ +###### MSVC ################################################################### +link:msvc>-nologo +link:msvc>-DEFAULTLIB:libcmt +link:msvc>-OPT:REF +link:msvc>-INCREMENTAL:NO +link:msvc>-DEBUG +link:msvc>arch:x64>-MACHINE:X64 +link:msvc>console>-SUBSYSTEM:CONSOLE +link:msvc>console_graphical>-SUBSYSTEM:CONSOLE +link:msvc>graphical>-SUBSYSTEM:WINDOWS +link:msvc>dll>-DLL + +###### Clang ################################################################## +link:clang>mode:debug>-g +link:clang>dll>-shared + +###### Windows ################################################################ + +link:msvc>os:windows>Winmm.lib +link:msvc>os:windows>Userenv.lib +link:msvc>os:windows>Advapi32.lib +link:msvc>os:windows>User32.lib +link:msvc>os:windows>graphical>Gdi32.lib +link:msvc>os:windows>graphical>Dwmapi.lib +link:msvc>os:windows>console_graphical>Gdi32.lib +link:msvc>os:windows>console_graphical>Dwmapi.lib +link:msvc>os:windows>audio>Ole32.lib +link:msvc>os:windows>audio>onecore.lib +link:msvc>os:windows>audio>Avrt.lib + +link:clang>os:windows>-lWinmm.lib +link:clang>os:windows>-lUserenv.lib +link:clang>os:windows>-lAdvapi32.lib +link:clang>os:windows>-lUser32.lib +link:clang>os:windows>graphical>-lGdi32.lib +link:clang>os:windows>graphical>-lDwmapi.lib +link:clang>os:windows>console_graphical>-lGdi32.lib +link:clang>os:windows>console_graphical>-lDwmapi.lib +link:clang>os:windows>audio>-lOle32.lib +link:clang>os:windows>audio>-lonecore.lib +link:clang>os:windows>audio>-lAvrt.lib + +link:msvc>freetype>freetype.lib +link:clang>freetype>-lfreetype.lib + +spall>base_profiling_by_spall.o + +###### Sanitizer ############################################################## + +link:clang>sanitizer>-fsanitize=address +link:clang>sanitizer>-fsanitize=undefined +link:clang>os:linux>sanitizer>-fsanitize=safe-stack +link:clang>fuzzer>-fsanitize=fuzzer diff --git a/local/exe_paths.txt b/local/exe_paths.txt new file mode 100644 index 0000000..c07756e --- /dev/null +++ b/local/exe_paths.txt @@ -0,0 +1,6 @@ +link:link>/c/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.31.31103/bin/Hostx64/x64/link.exe + +## The MSVC linker has been known to reside at this/these location(s) +## in some installations +# /c/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.31.31103/bin/Hostx64/x64/link.exe + diff --git a/local/local_vars.sh b/local/local_vars.sh new file mode 100644 index 0000000..41d574b --- /dev/null +++ b/local/local_vars.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +compiler="cl" +compile_mode="debug" +assembler="ml64" +arch="x64" +linker="link" +ctx_opts="" diff --git a/project.4coder b/project.4coder new file mode 100644 index 0000000..e104bdc --- /dev/null +++ b/project.4coder @@ -0,0 +1,35 @@ +version(2); +project_name = "shuffle_poset"; +patterns = { +"*.c", +"*.cpp", +"*.h", +"*.m", +"*.bat", +"*.sh", +"*.4coder", +}; +blacklist_patterns = { +".*", +}; +load_paths_base = { + { ".", .relative = true, .recursive = true, }, +}; +load_paths = { + .win = load_paths_base, + .linux = load_paths_base, + .mac = load_paths_base, +}; + +commands = { + .build = { .out = "*compilation*", .footer_panel = true, + .save_dirty_files = true, + .win = "git_bash bin/build.sh", }, + .run = { .out = "*run*", .footer_panel = false, + .save_dirty_files = false, + .win = "build\\shuffle_poset", }, +}; +fkey_command = { + .F1 = "build", + .F2 = "run", +}; diff --git a/src/shuffle_poset.c b/src/shuffle_poset.c new file mode 100644 index 0000000..ebf8b8c --- /dev/null +++ b/src/shuffle_poset.c @@ -0,0 +1,449 @@ +/* +** +** Shuffle Poset Implementation & Test +** +*/ + +#include "mr4th_base.h" +#include "mr4th_base.stdio.h" +#include "mr4th_keywords.h" +#include "mr4th_prng.h" + +#include "shuffle_poset.h" + +#include "mr4th_base.c" +#include "mr4th_prng.c" + +//////////////////////////////// +// Functions + +// poset + +function POSET_Loose* +poset_new(Arena *arena, U32 element_count){ + POSET_Loose *poset = push_array(arena, POSET_Loose, 1); + poset->element_count = element_count; + return(poset); +} + +function void +poset_order(Arena *arena, POSET_Loose *poset, U32 ls, U32 gr){ + Assert(ls < poset->element_count); + Assert(gr < poset->element_count); + + POSET_Pair *pair = push_array(arena, POSET_Pair, 1); + SLLQueuePush(poset->first, poset->last, pair); + poset->pair_count += 1; + pair->ls = ls; + pair->gr = gr; +} + +function POSET* +poset_bake(Arena *arena, POSET_Loose *loose){ + U32 element_count = loose->element_count; + POSET *poset = push_array(arena, POSET, 1); + S8 *compare_grid = push_array(arena, S8, element_count*element_count); + + // write pairs into compare grid + for (POSET_Pair *pair = loose->first; + pair != 0; + pair = pair->next){ + compare_grid[pair->ls + pair->gr*element_count] = -1; + compare_grid[pair->gr + pair->ls*element_count] = +1; + } + + // close the graph paths + for (;;){ + B32 update = 0; + for (U32 i = 0; i < element_count; i += 1){ + for (U32 j = i + 1; j < element_count; j += 1){ + for (U32 k = j + 1; k < element_count; k += 1){ + if (compare_grid[i + j*element_count] < 0 && + compare_grid[j + k*element_count] < 0){ + if (compare_grid[i + k*element_count] == 0){ + compare_grid[i + k*element_count] = -1; + compare_grid[k + i*element_count] = +1; + update = 1; + } + } + } + } + } + if (!update){ + break; + } + } + + poset->compare = compare_grid; + poset->element_count = element_count; + return(poset); +} + +function U32* +poset_topological_sort(Arena *arena, POSET *poset){ + U32 element_count = poset->element_count; + + // initialize array {0,...,n-1} + U32 *array = push_array(arena, U32, element_count); + for (U32 i = 0; i < element_count; i += 1){ + array[i] = i; + } + + // topological sort + for (U32 i = 0; i + 1 < element_count; i += 1){ + U32 j = i; + U32 je = array[j]; + for (U32 k = j + 1; k < element_count; k += 1){ + U32 ke = array[k]; + if (poset->compare[je + ke*element_count] > 0){ + j = k; + je = ke; + } + } + Swap(U32, array[i], array[j]); + } + + return(array); +} + +function U32* +poset_shuffle(Arena *arena, PRNG *prng, POSET *poset){ + U32 element_count = poset->element_count; + U32 *array = poset_topological_sort(arena, poset); + + F32 n = (F32)element_count; + F32 t = (4.f/(pi_F32*pi_F32)*n*n*n*ln_F32(n)); + U64 num_swaps = (U64)ceil_F32(t); + U64 num_passes = CeilIntDiv(num_swaps, element_count); + + for (U64 p = 0; p < num_passes; p += 1){ + // even pass + for (U32 i = 0; i + 1 < element_count; i += 2){ + U32 je = array[i]; + U32 ke = array[i + 1]; + if (poset->compare[je + ke*element_count] == 0 && + prng_roll_bounded(prng, 2)){ + Swap(U32, array[i], array[i + 1]); + } + } + + // odd pass + for (U32 i = 1; i + 1 < element_count; i += 2){ + U32 je = array[i]; + U32 ke = array[i + 1]; + if (poset->compare[je + ke*element_count] == 0 && + prng_roll_bounded(prng, 2)){ + Swap(U32, array[i], array[i + 1]); + } + } + + } + + return(array); +} + +// distribution + +function DISTRIBUTION* +distribution_new(Arena *arena, U32 element_count){ + DISTRIBUTION *distribution = push_array(arena, DISTRIBUTION, 1); + distribution->element_count = element_count; + return(distribution); +} + +function void +distribution_add(Arena *arena, DISTRIBUTION *distribution, F32 weight, ...){ + ArenaTemp scratch = arena_get_scratch(&arena, 1); + + U32 element_count = distribution->element_count; + U32 *order = push_array(scratch.arena, U32, element_count); + { + va_list args; + va_start(args, weight); + for (U32 idx = 0; idx < distribution->element_count; idx += 1){ + U32 x = va_arg(args, U32); + if (x = max_U32){ + break; + } + order[idx] = x; + } + va_end(args); + } + + distribution_add_order(arena, distribution, weight, order); + + arena_release_scratch(&scratch); +} + +function void +distribution_add_order(Arena *arena, DISTRIBUTION *distribution, F32 weight, U32 *order){ + U32 element_count = distribution->element_count; + + U32 hash = 1337; + for (U32 idx = 0; idx < element_count; idx += 1){ + hash = (hash << 5) - hash + (idx + 1)*order[idx]; + } + + U32 bucket_idx = hash%ArrayCount(distribution->buckets); + DISTRIBUTION_Bucket *match_bucket = 0; + for (DISTRIBUTION_Bucket *bucket = distribution->buckets[bucket_idx]; + bucket != 0; + bucket = bucket->next_hash){ + if (bucket->hash == hash && + memcmp(bucket->order, order, sizeof(*order)*element_count) == 0){ + match_bucket = bucket; + break; + } + } + + if (match_bucket == 0){ + match_bucket = push_array(arena, DISTRIBUTION_Bucket, 1); + SLLQueuePush(distribution->first, distribution->last, match_bucket); + + U32 *order_cpy = push_array(arena, U32, element_count); + MemoryCopy(order_cpy, order, sizeof(*order)*element_count); + + match_bucket->order = order_cpy; + match_bucket->hash = hash; + + SLLStackPush_N(distribution->buckets[bucket_idx], match_bucket, next_hash); + + distribution->bucket_count += 1; + } + + match_bucket->weight += weight; +} + + +function void +distribution_normalize(DISTRIBUTION *distribution){ + F32 total_weight = 0.f; + for (DISTRIBUTION_Bucket *bucket = distribution->first; + bucket != 0; + bucket = bucket->next){ + total_weight += bucket->weight; + } + + if (total_weight > 0.f){ + F32 norm = 1.f/total_weight; + for (DISTRIBUTION_Bucket *bucket = distribution->first; + bucket != 0; + bucket = bucket->next){ + bucket->weight *= norm; + } + } +} + +function void +distribution_sort(DISTRIBUTION *distribution){ + ArenaTemp scratch = arena_get_scratch(0, 0); + + // flatten buckets + U32 bucket_count = distribution->bucket_count; + DISTRIBUTION_Bucket **buckets = + push_array(scratch.arena, DISTRIBUTION_Bucket*, bucket_count); + { + U32 idx = 0; + for (DISTRIBUTION_Bucket *bucket = distribution->first; + bucket != 0; + bucket = bucket->next, idx += 1){ + buckets[idx] = bucket; + } + } + + // sort + sort_merge(buckets, sizeof(*buckets), bucket_count, + distribution_bucket_compare, + PtrFromInt(distribution->element_count)); + + // reorder buckets + distribution->first = 0; + distribution->last = 0; + for (U32 i = 0; i < bucket_count; i += 1){ + DISTRIBUTION_Bucket *bucket = buckets[i]; + bucket->next = 0; + SLLQueuePush(distribution->first, distribution->last, bucket); + } + + arena_release_scratch(&scratch); +} + +function S32 +distribution_bucket_compare(void *a, void *b, void *udata){ + U32 element_count = (U32)IntFromPtr(udata); + DISTRIBUTION_Bucket *abucket = *(DISTRIBUTION_Bucket**)a; + DISTRIBUTION_Bucket *bbucket = *(DISTRIBUTION_Bucket**)b; + S32 result = memcmp(abucket->order, bbucket->order, sizeof(*abucket->order)*element_count); + return(result); +} + +// tests + +function TEST +make_test1(Arena *arena){ + // POSET: + // 0 1 + // / \ / \ + // 2 3 4 + // + // ORDERS: + // 01234 + // 01243 + // 01324 + // 01342 + // 01423 + // 01432 + // 02134 + // 02143 + // 10234 + // 10243 + // 10324 + // 10342 + // 10423 + // 10432 + // 14023 + // 14032 + + ArenaTemp scratch = arena_get_scratch(&arena, 1); + + POSET_Loose *poset = poset_new(scratch.arena, 5); + poset_order(scratch.arena, poset, 0, 2); + poset_order(scratch.arena, poset, 0, 3); + poset_order(scratch.arena, poset, 1, 3); + poset_order(scratch.arena, poset, 1, 4); + + DISTRIBUTION *distribution = distribution_new(arena, 5); + distribution_add(arena, distribution, 1, 0,1,2,3,4); + distribution_add(arena, distribution, 1, 0,1,2,4,3); + distribution_add(arena, distribution, 1, 0,1,3,2,4); + distribution_add(arena, distribution, 1, 0,1,3,4,2); + distribution_add(arena, distribution, 1, 0,1,4,2,3); + distribution_add(arena, distribution, 1, 0,1,4,3,2); + distribution_add(arena, distribution, 1, 0,2,1,3,4); + distribution_add(arena, distribution, 1, 0,2,1,4,3); + + distribution_add(arena, distribution, 1, 1,0,2,3,4); + distribution_add(arena, distribution, 1, 1,0,2,4,3); + distribution_add(arena, distribution, 1, 1,0,3,2,4); + distribution_add(arena, distribution, 1, 1,0,3,4,2); + distribution_add(arena, distribution, 1, 1,0,4,2,3); + distribution_add(arena, distribution, 1, 1,0,4,3,2); + distribution_add(arena, distribution, 1, 1,4,0,3,2); + distribution_add(arena, distribution, 1, 1,4,0,2,3); + + distribution_normalize(distribution); + + TEST test = {0}; + test.poset = poset_bake(arena, poset); + test.distribution = distribution; + + arena_release_scratch(&scratch); + + return(test); +} + +function POSET* +make_big_poset(Arena *arena){ + + ArenaTemp scratch = arena_get_scratch(&arena, 1); + + POSET_Loose *poset = poset_new(scratch.arena, 10); + for (U32 i = 1; i < 10; i += 1){ + for (U32 j = i + 1; j < 10; j += 1){ + if ((j%i) == 0){ + poset_order(arena, poset, i, j); + } + } + } + + POSET *result = poset_bake(arena, poset); + + arena_release_scratch(&scratch); + + return(result); +} + +int main(void){ + Arena *arena = arena_alloc(); + PRNG prng = {0}; + { + PRNG_Seed seed = {0}; + os_get_entropy(&seed, sizeof(seed)); + prng = prng_init_from_seed(&seed); + } + +#if 1 + TEST test1 = make_test1(arena); + POSET *poset = test1.poset; +#endif + +#if 0 + POSET *poset = make_big_poset(arena); +#endif + +#if 0 + { + m4_printf("MATRIX:\n"); + U32 element_count = poset->element_count;; + for (U32 row = 0; row < element_count; row += 1){ + for (U32 col = 0; col < element_count; col += 1){ + S8 v = poset->compare[row + col*element_count]; + if (v < 0){ + m4_printf("-"); + } + else if (v == 0){ + m4_printf("0"); + } + else if (v > 0){ + m4_printf("+"); + } + } + m4_printf("\n"); + } + m4_printf("\n"); + } +#endif + +#if 0 + { + U32 *array = poset_topological_sort(arena, poset); + { + m4_printf("INITIAL SORT: { "); + for (U32 i = 0; i < poset->element_count; i += 1){ + m4_printf("%u, ", array[i]); + } + m4_printf("}\n"); + } + } +#endif + +#if 1 + DISTRIBUTION *test_distribution = distribution_new(arena, poset->element_count); + + Arena *test_arena = arena_alloc(); + for (U32 r = 0; r < Million(100); r += 1){ + U32 *array = poset_shuffle(test_arena, &prng, poset); + distribution_add_order(arena, test_distribution, 1.f, array); + arena_pop_to(test_arena, 0); + } + + distribution_normalize(test_distribution); + distribution_sort(test_distribution); + + { + m4_printf("DISTRIBUTION:\n"); + for (DISTRIBUTION_Bucket *bucket = test_distribution->first; + bucket != 0; + bucket = bucket->next){ + m4_printf("{ "); + for (U32 i = 0; i < poset->element_count; i += 1){ + m4_printf("%u, ", bucket->order[i]); + } + m4_printf("} - %.5f\n", bucket->weight); + } + m4_printf("\n"); + } +#endif + + return(0); +} diff --git a/src/shuffle_poset.h b/src/shuffle_poset.h new file mode 100644 index 0000000..6376d15 --- /dev/null +++ b/src/shuffle_poset.h @@ -0,0 +1,72 @@ +#ifndef SHUFFLE_POSET_H +#define SHUFFLE_POSET_H + +//////////////////////////////// +// Types + +typedef struct POSET_Pair{ + struct POSET_Pair *next; + U32 ls; + U32 gr; +} POSET_Pair; + +typedef struct POSET_Loose{ + POSET_Pair *first; + POSET_Pair *last; + U64 pair_count; + U32 element_count; +} POSET_Loose; + +typedef struct POSET{ + S8 *compare; + U32 element_count; +} POSET; + +typedef struct DISTRIBUTION_Bucket{ + struct DISTRIBUTION_Bucket *next; + struct DISTRIBUTION_Bucket *next_hash; + U32 *order; + U32 hash; + F32 weight; +} DISTRIBUTION_Bucket; + +typedef struct DISTRIBUTION{ + DISTRIBUTION_Bucket *first; + DISTRIBUTION_Bucket *last; + DISTRIBUTION_Bucket *buckets[32]; + U32 element_count; + U32 bucket_count; +} DISTRIBUTION; + +typedef struct TEST{ + POSET *poset; + DISTRIBUTION *distribution; +} TEST; + +//////////////////////////////// +// Functions + +// poset + +function POSET_Loose* poset_new(Arena *arena, U32 element_count); +function void poset_order(Arena *arena, POSET_Loose *poset, U32 ls, U32 gr); +function POSET* poset_bake(Arena *arena, POSET_Loose *loose); + +function U32* poset_topological_sort(Arena *arena, POSET *poset); +function U32* poset_shuffle(Arena *arena, PRNG *prng, POSET *poset); + +// distribution + +function DISTRIBUTION* distribution_new(Arena *arena, U32 element_count); +function void distribution_add(Arena *arena, DISTRIBUTION *distribution, F32 weight, ...); +function void distribution_add_order(Arena *arena, DISTRIBUTION *distribution, F32 weight, U32 *order); +function void distribution_normalize(DISTRIBUTION *distribution); +function void distribution_sort(DISTRIBUTION *distribution); +function S32 distribution_bucket_compare(void *a, void *b, void *udata); + +// test cases + +function TEST make_test1(Arena *arena); +function POSET*make_big_poset(Arena *arena); + +#endif //SHUFFLE_POSET_H