commit 06227a27310424de3f349a3610d929b73805a9cb Author: Michael Sippel <micha@fragmental.art> Date: Tue Jan 28 22:33:08 2025 +0100 posint morphisms in C diff --git a/morphisms/Makefile b/morphisms/Makefile new file mode 100644 index 0000000..4eb2d4d --- /dev/null +++ b/morphisms/Makefile @@ -0,0 +1,11 @@ +TARGETS=lib/posint.so + +all: $(TARGETS) + +lib/%.so: src/%.c + gcc -shared -o $@ -fPIC $< + +clean: + rm $(TARGETS) + +.PHONY: all clean diff --git a/morphisms/posint.morphism-base b/morphisms/posint.morphism-base new file mode 100644 index 0000000..417618c --- /dev/null +++ b/morphisms/posint.morphism-base @@ -0,0 +1,36 @@ +morph_digit_as_char_to_uint8 (Radix:ℤ_16) + <Digit Radix> ~ Char ~ Ascii ~ Byte +--> <Digit Radix> ~ x86.UInt8 ~ Byte +@lib/posint.so:src/posint.c + +morph_digit_as_uint8_to_char (Radix:ℤ_16) + <Digit Radix> ~ x86.UInt8 ~ Byte +--> <Digit Radix> ~ Char ~ Ascii ~ Byte +@lib/posint.so:src/posint.c + +morph_posint_radix (SrcRadix:ℤ, DstRadix:ℤ) + ℕ + ~ <PosInt SrcRadix LittleEndian> + ~ [~<LengthPrefix x86.UInt64> <Digit SrcRadix>~x86.UInt64] +--> ℕ + ~ <PosInt DstRadix LittleEndian> + ~ [~<LengthPrefix x86.UInt64> <Digit DstRadix>~x86.UInt64] +@lib/posint.so:src/posint.c + +morph_posint_endianness (Radix:ℤ) + ℕ + ~ <PosInt Radix LittleEndian> + ~ [~<LengthPrefix x86.UInt64> <Digit Radix> ~ x86.UInt64] +--> ℕ + ~ <PosInt Radix BigEndian> + ~ [~<LengthPrefix x86.UInt64> <Digit Radix> ~ x86.UInt64] +@lib/posint.so:src/posint.c + +morph_posint_endianness (Radix:ℤ) + ℕ + ~ <PosInt Radix BigEndian> + ~ [~<LengthPrefix x86.UInt64> <Digit Radix> ~ x86.UInt64] +--> ℕ + ~ <PosInt Radix LittleEndian> + ~ [~<LengthPrefix x86.UInt64> <Digit Radix> ~ x86.UInt64] +@lib/posint.so:src/posint.c diff --git a/morphisms/src/length_prefix_array.c b/morphisms/src/length_prefix_array.c new file mode 100644 index 0000000..4f908e6 --- /dev/null +++ b/morphisms/src/length_prefix_array.c @@ -0,0 +1,42 @@ +#include <stdio.h> +#include <stdint.h> + +struct LengthPrefixUInt64Array { + uint64_t len; + uint64_t items[]; +}; + +void length_prefix_uint64_array_clear( + struct LengthPrefixUInt64Array * data +) { + data->len = 0; +} + +void length_prefix_uint64_array_push( + struct LengthPrefixUInt64Array * data, + uint64_t value +) { + data->items[ data->len ] = value; + data->len += 1; +} + +int length_prefix_uint64_array_reverse( + struct LengthPrefixUInt64Array const * restrict src, + struct LengthPrefixUInt64Array * restrict dst +) { + dst->len = src->len; + for(uint64_t i = 0; i < src->len; ++i) { + dst->items[i] = src->items[src->len - i - 1]; + } + return 0; +} + +void length_prefix_uint64_array_dump( + struct LengthPrefixUInt64Array const * data +) { + printf("Len = %d, [", data->len); + for( uint64_t i = 0; i < data->len; ++i ) { + printf("%d; ", data->items[i]); + } + printf("]\n"); +} diff --git a/morphisms/src/posint.c b/morphisms/src/posint.c new file mode 100644 index 0000000..5d25f20 --- /dev/null +++ b/morphisms/src/posint.c @@ -0,0 +1,85 @@ +#include <stdint.h> +#include "length_prefix_array.c" + +int morph_digit_as_char_to_uint8( + char const * restrict src, + uint8_t * restrict dst +) { + if( *src >= '0' && *src <= '9' ) + *dst = *src - '0'; + else if( *src >= 'a' && *src <= 'f') + *dst = 0xa + *src - 'a'; + else if( *src >= 'A' && *src <= 'F') + *dst = 0xa + *src - 'A'; + else + return -1; + + return 0; +} + +int morph_digit_as_char_to_uint64( + char const * restrict src, + uint64_t * restrict dst +) { + if( *src >= '0' && *src <= '9' ) + *dst = *src - '0'; + else if( *src >= 'a' && *src <= 'f') + *dst = 0xa + *src - 'a'; + else if( *src >= 'A' && *src <= 'F') + *dst = 0xa + *src - 'A'; + else + return -1; + + return 0; +} + +int morph_digit_as_uint8_to_char( + uint8_t const * restrict src, + char * restrict dst +) { + if ( *src < 10 ) + *dst = *src + '0'; + else if( *dst < 16 ) + *dst = *src - 0xa + 'a'; + else + return -1; + + return 0; +} + +/* switches endianness by reversing the digit sequence + */ +int morph_posint_endianness( + uint64_t const radix, + + struct LengthPrefixUInt64Array const * restrict src, + struct LengthPrefixUInt64Array * restrict dst +) { + return length_prefix_uint64_array_reverse( src, dst ); +} + +/* morph radix in little endian + */ +int morph_posint_radix( + uint64_t const src_radix, + uint64_t const dst_radix, + + struct LengthPrefixUInt64Array const * restrict src, + struct LengthPrefixUInt64Array * restrict dst +) { + uint64_t value = 0; + + for( uint64_t i = 0; i < src->len; ++i ) { + value *= src_radix; + value += src->items[src->len - i - 1]; + } + + length_prefix_uint64_array_clear( dst ); + + while( value > 0 ) { + length_prefix_uint64_array_push( dst, value % dst_radix ); + value /= dst_radix; + } + + return 0; +}