NS路Status (*arithmetic_shift_right)(Address, NS路T*, NS路T*);
// import/export
- char *(*to_string)(NS路T *);
+ char *(*to_hex)(NS路T *);
#ifdef UINT8_MAX
NS路TO_TYPE(uint8_t)
free(unencumbered);
}
- char *to_string(NS路T *n) {
+ char *to_hex(NS路T *n) {
// Each byte requires two hex characters, plus "0x" prefix and null terminator
const Address string_length = (sizeof(Digit) * (digit_array_extent + 1) * 2) + 3;
char *buffer = malloc(string_length);
/*
Copy - Memory copy operations with attention to alignment.
Provides optimized copy and byte order reversal functions.
+
*/
#define Copy路DEBUG
#include <stdint.h>
#include <stddef.h>
- void *Copy路region(void *read0 ,void *read1 ,void *write0);
- void *Copy路reverse_byte_order(void *read0 ,void *read1 ,void *write0);
+ typedef struct{
+ void *read0;
+ size_t read_size;
+ void *write0;
+ size_t write_size;
+ } Copy路it;
+
+ typedef enum{
+ Copy路Status路perfect_fit = 0
+ ,Copy路Status路argument_guard
+ ,Copy路Status路read_surplus
+ ,Copy路Status路read_surplus_write_gap
+ ,Copy路Status路write_available
+ ,Copy路Status路write_gap // write allocation has a terminal gap
+ } Copy路Status;
+
+ typedef struct{
+ void *region(void *read0 ,void *read1 ,void *write0);
+ void *reverse_byte_order(void *read0 ,void *read1 ,void *write0);
+ } Copy路M;
+
#endif
#ifdef LOCAL
+
+
+
+ #ifdef Copy路DEBUG
+ #include <stdio.h> // Only for debug prints, not used in production.
+
+typedef enum{
+ Copy路StatusWFIt路none = 0x00
+ ,Copy路StatusWFIt路null_read = 0x01
+ ,Copy路StatusWFIt路null_write = 0x02
+ ,Copy路StatusWFIt路zero_read_size = 0x04
+ ,Copy路StatusWFIt路zero_write_size = 0x08
+ ,Copy路StatusWFIt路write_too_small_hex = 0x10
+ ,Copy路StatusWFIt路read_too_small_hex = 0x20
+ ,Copy路StatusWFIt路read_larger_than_write = 0x40
+ ,Copy路StatusWFIt路overlapping_buffers = 0x80
+} Copy路StatusWFIt;
+
+typedef enum{
+ Copy路ModeWFIt路none = 0x00
+ ,Copy路ModeWFIt路bytes = 0x01
+ ,Copy路ModeWFIt路reverse = 0x02
+ ,Copy路ModeWFIt路write_hex = 0x03
+ ,Copy路ModeWFIt路from_hex = 0x04
+} Copy路ModeWFIt;
+
+
+
+
+#endif
+
+
/*
Copy路region - Copies a memory region while preserving byte order.
- Aligns reads for performance.
- Writes are assumed to be buffered and do not require alignment.
- Returns the updated write pointer.
*/
- void *Copy路region(void *read0 ,void *read1 ,void *write0){
+ Local void *Copy路bytes(void *read0 ,void *read1 ,void *write0){
uint8_t *r = (uint8_t *)read0;
uint8_t *r1 = (uint8_t *)read1;
/*
Copy路reverse_byte_order - Copies a memory region while reversing byte order.
- - Reads in reverse order while writing in forward order.
+ - Reads from read1 down
+ - writes from write0 up
- Uses `__builtin_bswap64` for efficient 64-bit swaps.
- Returns the updated write pointer.
*/
- void *Copy路reverse_byte_order(void *read0 ,void *read1 ,void *write0){
+ Local void *Copy路bytes_reverse_order(void *read0 ,void *read1 ,void *write0){
uint8_t *r = (uint8_t *)read1; // Start from the last byte
uint8_t *r0 = (uint8_t *)read0;
return w;
}
+ /*
+ Read buffer is read from the lowest address, working toward higher addresses.
+
+ Write buffer is written from the lowest address, working to higher addresses.
+
+ To force data to be left in the read buffer, or for capacity to be left in the
+ write buffer, reduce sizes.
+ */
+ Local Copy路Status Copy路step(
+ Copy路it *it
+ ){
+ uint8_t *r = (uint8_t *)it->read0;
+ uint8_t *w = (uint8_t *)it->write0;
+
+ size_t rs = it->read_size;
+ size_t ws = it->write_size;
+
+ if(ws >= rs){
+ Copy路bytes(r ,r + rs ,w);
+ it->read0 += rs;
+ it->read_size = 0;
+ it->write0 += rs;
+ it->write_size -= rs;
+ if(ws == rs) return Copy路Status路perfect_fit;
+ return Copy路Status路write_available;;
+ }
+
+ // ws < rs
+ Copy路bytes(r ,r + ws ,w);
+ it->read0 += ws;
+ it->read_size -= ws;
+ it->write_size = 0;
+ it->write0 += ws;
+ return Copy路Status路read_surplus;
+ }
+
+ /*
+ Read buffer is read from top down. Start with the largest address
+ just above the read buffer. Continue into lower addresses.
+
+ write buffer is written from bottom up. Start with the lowest address,
+ continue into higher addresses.
+ */
+ Local Copy路Status Copy路step_reverse_order(Copy路it *it){
+ // How many bytes remain to be read/written
+ if( it->read_size == 0) return Copy路Status路complete;
+ size_t rs = it->read_size;
+ uint8_t *r1 = (uint8_t *)it->read0 + rs;
+ size_t ws = it->write_size;
+ uint8_t *w0 = (uint8_t *)it->write0;
+
+ if(ws >= rs){
+ uint8_t *r0 = (uint8_t *)it->read0;
+ Copy路bytes_reverse_order(r0, r1, w0);
+ it->read_size = 0;
+ it->write0 += rs;
+ it->write_size -= rs;
+ if(it->write_size == 0) return Copy路Status路perfect_fit;
+ return Copy路Status路write_available;
+ }
+
+ // ws < rs
+ uint8_t *r0 = r1 - ws;
+ Copy路bytes_reverse_order(r0, r1, w0);
+ it->read0 -= ws;
+ it->read_size -= ws;
+ it->write_size = 0;
+ it->write0 += ws;
+ return Copy路Status路read_surplus;
+ }
+
+ /*
+ Read bytes, write hex pairs.
+ Read and write are low address to high address.
+ Each read byte value -> 2 write allocation bytes
+ */
+ Local Copy路Status Copy路step_write_hex(
+ Copy路it *it
+ ){
+
+ uint8_t *r = (uint8_t *)it->read0;
+ size_t rs = it->read_size;
+
+ uint8_t *w = (uint8_t *)it->write0;
+ size_t ws = it->write_size & ~1; // even number write_size
+ size_t ews = it->write_size >> 1; // effective write size
+
+ // If ews >= rs, read bytes all coped
+ if(ews >= rs){
+ size_t ers = it->read_size << 1; // effective read size
+ it->write0 += ers;
+ it->write_size -= ers;
+ while(rs--){
+ *(uint16_t *)w = Copy路byte_to_hex(*r++);
+ w += 2;
+ }
+ it->read0 = r;
+ it->read_size = 0;
+
+ if(it->write_size == 0) return Copy路Status路perfect_fit;
+ if(it->write_size == 1) return Copy路Status路write_gap;
+ return Copy路Status路write_available;
+ }
+
+ // ews < rs, write allocation all used, read bytes surplus
+ it->read0 += ews;
+ it->read_size -= ews;
+ while(ews--){
+ *(uint16_t *)w = Copy路byte_to_hex(*r++);
+ w += 2;
+ }
+ it->write0 = w;
+ it->write_size -= ws;
+
+ if(it->write_size == 1) return Copy路Status路read_surplus_write_gap;
+ return Copy路Status路read_surplus;
+ }
+
+ /*
+ Read hex pairs, write bytes.
+ Read is low address to high address.
+ Write is low address to high address.
+ Each read hex pair -> 1 write byte.
+ */
+ Local Copy路Status Copy路step_from_hex(
+ Copy路it *it
+ ){
+ uint8_t *r = (uint8_t *)it->read0;
+ size_t rs = it->read_size & ~1; // Must be even for hex pairs.
+ size_t ers = rs >> 1; // Effective read size: half the number of bytes.
+
+ uint8_t *w = (uint8_t *)it->write0;
+ size_t ws = it->write_size; // Write size already in bytes.
+
+ // If ws >= ers, all hex values are processed
+ if(ws >= ers){
+ while(ers--){
+ *w++ = Copy路hex_to_byte(*(uint16_t *)r);
+ r += 2;
+ }
+
+ it->read0 = r;
+ it->read_size -= rs;
+ it->write0 = w;
+ it->write_size -= rs >> 1; // Each byte consumes two hex chars.
+
+ if(it->write_size == 0) return Copy路Status路perfect_fit;
+ return Copy路Status路write_available;
+ }
+
+ // ws < ers, read allocation surplus
+ while(ws--){
+ *w++ = Copy路hex_to_byte(*(uint16_t *)r);
+ r += 2;
+ }
+
+ it->read0 = r;
+ it->read_size -= ws << 1; // Each write byte consumes two hex chars.
+ it->write0 = w;
+ it->write_size = 0;
+
+ return Copy路Status路read_surplus;
+ }
+
+
#endif // LOCAL
+
#endif // IMPLEMENTATION
--- /dev/null
+* Copy - Memory Copy Operations
+
+** Overview
+
+The Copy module provides optimized memory copy operations that account for memory alignment and byte order. It contains functions for standard memory copying, as well as specialized routines for reversing byte order during copying. The design ensures efficient memory operations by aligning read pointers and assuming write operations are buffered.
+
+** Features
+
+- Optimized memory copy operations
+- Byte order reversal during copy
+- Handles unaligned read memory
+- Ensures efficient bulk transfers using 64-bit word copies
+- Provides step-based copying with status reporting
+
+** Interface
+
+- `Copy路bytes(read0, read1, write0) -> void*`
+ - Copies memory from `read0` to `write0`, preserving byte order.
+ - Returns the updated write pointer.
+
+- `Copy路reverse_byte_order(read0, read1, write0) -> void*`
+ - Copies memory while reversing byte order.
+ - Reads from `read1` downward, writes from `write0` upward.
+ - Returns the updated write pointer.
+
+- `Copy路step(Copy路it *it) -> Copy路Status`
+ - Uses the `Copy路it` struct, which defines read and write intervals.
+ - Does the maximum sized copy without going outside the intervals.
+ - Updates `it` for continuation of the block copy.
+ - Returns a status indicating there is surplus data, or available write allocation.
+
+- `Copy路step_reverse_order(Copy路it *it) -> Copy路Status`
+ - Performs a copy of the block while reversing the byte order and updating the iterator.
+ - Returns a status indicating there is surplus data, or available write allocation.
+
+- `Copy路step_write_hex(Copy路it *it) -> Copy路Status`
+ - Converts read bytes into hexadecimal representation during writing.
+ - Two bytes are written for each byte read.buffer.
+ - Returns a status indicating there is surplus data, or available write allocation.
+
+** Status Codes
+
+- `Copy路Status路perfect_fit`
+ - Read and write buffers are fully utilized without remainder.
+- `Copy路Status路read_data_surplus`
+ - The write allocation was filled before the read values were all read.
+- `Copy路Status路write_allocation_available`
+ - The write allocation has space for more values.
+- `Copy路Status路write_allocation_gap`
+ - The write allocation has space, but it is not large enough to hold another value.
+
+** Implementation Notes
+
+- Alignment is only enforced on the read side to maximize efficiency.
+- Writes are assumed to be buffered, allowing unaligned writes without performance degradation.
+- The `step` functions allow for incremental processing of data streams.
+
+** Example Usage
+
+```c
+Copy路it copy_instance = {
+ .read0 = source_data,
+ .read_size = source_size,
+ .write0 = destination_buffer,
+ .write_size = destination_size
+};
+
+Copy路Status result = Copy路step(©_instance);
+```
+
+This module provides an efficient and flexible memory copying framework suitable for low-level data manipulation tasks.
+
copy version that works when there is not even a unint32_t type.
+* 2025-02-24T08:09:57Z Copy.lib.c forced alginment machine might have issues with the block copy.
+
+ The block copy aligns the read pointer by copying some initial
+ bytes. It ignores the alignment on the write pointer. Then at the end it does a byte
+ by byte copy of the ragged tail (less than a full word number of bytes).
+
+ For a system that forces alignment, the initial alignment of the read pointer will get skipped. The write pointer will be aligned, so there is no problem in not checking it.
+
+ However, the ragged tail loop can fire on a forced aligned
+ system. This will happen if the bounding read pointer passed in to
+ the block copy is not pointing to the first byte of a word. This can
+ happen if it is created adding `sizeof` of an object with that is not an even number
+ of bytes in a word long.
+
+ The solution is probably to set a 'force align' macro based on the
+ architecture macro and gating the ragged tail code to do a word
+ copy, or affecting the bulk section to do one more loop -- or having
+ a differnt block copy an bytes_reversed block copy that loops on
+ words.
--- /dev/null
+/*
+ Copy - Memory copy operations with attention to alignment.
+ Provides optimized copy and byte order reversal functions.
+*/
+
+#define Copy路DEBUG
+
+#ifndef FACE
+#define Copy路IMPLEMENTATION
+#define FACE
+#endif
+
+//--------------------------------------------------------------------------------
+// Interface
+
+#ifndef Copy路FACE
+#define Copy路FACE
+
+ #include <stdint.h>
+ #include <stddef.h>
+
+ void *Copy路region(void *read0 ,void *read1 ,void *write0);
+ void *Copy路reverse_byte_order(void *read0 ,void *read1 ,void *write0);
+
+#endif
+
+//--------------------------------------------------------------------------------
+// Implementation
+
+#ifdef Copy路IMPLEMENTATION
+
+ // this part goes into Nlib.a
+ #ifndef LOCAL
+ #endif
+
+ #ifdef LOCAL
+
+ /*
+ Copy路region - Copies a memory region while preserving byte order.
+ - Aligns reads for performance.
+ - Writes are assumed to be buffered and do not require alignment.
+ - Returns the updated write pointer.
+ */
+ void *Copy路region(void *read0 ,void *read1 ,void *write0){
+
+ uint8_t *r = (uint8_t *)read0;
+ uint8_t *r1 = (uint8_t *)read1;
+ uint8_t *w = (uint8_t *)write0;
+
+ //----------
+ // The potentially unaligned initial part (align read pointer).
+ if( (uintptr_t)r & 0x7 ){
+
+ // ORing in `0x7` adds at most six bytes to r.
+ uint8_t *r01 = (uint8_t *)((uintptr_t)r | 0x7);
+
+ // If the read interval is very small
+ if(r01 >= r1){
+ while(r < r1){
+ *w++ = *r++;
+ }
+ return w;
+ }
+
+ // Copy up to alignment boundary
+ do{
+ *w++ = *r++;
+ }while(r <= r01);
+ }
+ // r is now aligned, but *r has not yet been copied
+
+ //----------
+ // The bulk copy part (w is still possibly unaligned, but r is aligned)
+ uint8_t *r10 = (uint8_t *)((uintptr_t)r1 & ~(uintptr_t)0x7);
+
+ while(r < r10){
+ *(uint64_t *)w = *(uint64_t *)r;
+ w += 8;
+ r += 8;
+ }
+
+ // If r1 was aligned then r10 == r1 and we are done
+ if(r == r1) return w;
+
+ //----------
+ // The ragged tail, up to 7 bytes
+ do{
+ *w++ = *r++;
+ }while(r < r1);
+
+ return w;
+ }
+
+ /*
+ Copy路reverse_byte_order - Copies a memory region while reversing byte order.
+ - Reads in reverse order while writing in forward order.
+ - Uses `__builtin_bswap64` for efficient 64-bit swaps.
+ - Returns the updated write pointer.
+ */
+ void *Copy路reverse_byte_order(void *read0 ,void *read1 ,void *write0){
+
+ uint8_t *r = (uint8_t *)read1; // Start from the last byte
+ uint8_t *r0 = (uint8_t *)read0;
+ uint8_t *w = (uint8_t *)write0;
+
+ //----------
+ // The potentially unaligned initial part (align read pointer).
+ if( (uintptr_t)r & 0x7 ){
+
+ // ANDing with `~0x7` moves it downward to the nearest lower alignment.
+ uint8_t *r10 = (uint8_t *)((uintptr_t)r & ~(uintptr_t)0x7);
+
+ // If the read interval is very small
+ if(r10 < r0){
+ while(r > r0){
+ *w++ = *--r;
+ }
+ return w;
+ }
+
+ // Copy down to alignment boundary
+ do{
+ *w++ = *--r;
+ }while(r > r10);
+ }
+ // r is now aligned, and *r has been copied
+
+ //----------
+ // The bulk copy part
+ uint8_t *r01 = (uint8_t *)( ((uintptr_t)r0 + (uintptr_t)0x7) & ~(uintptr_t)0x7);
+
+ while(r > r01){
+ r -= 8;
+ *(uint64_t *)w = __builtin_bswap64(*(uint64_t *)r);
+ w += 8;
+ }
+
+ // If r0 was aligned then r01 == r0 and we are done
+ if(r < r0) return w;
+
+ //----------
+ // The ragged tail, up to 7 bytes
+ do{
+ *w++ = *--r;
+ }while(r >= r0);
+
+ return w;
+ }
+
+ #endif // LOCAL
+
+#endif // IMPLEMENTATION
N16路T* (*access)(N16路T*, Extent);
void (*from_uint32)(N16路T *destination ,uint32_t value);
- } N16路螞;
+ } N16路M;
- Local const N16路螞 N16路位; // initialized in the LOCAL section
+ Local const N16路M N16路m; // initialized in the LOCAL section
#endif
return N16路shift_right(shift_count, spill, operand, fill);
}
- Local const N16路螞 N16路位 = {
+ Local const N16路M N16路m = {
.allocate_array = N16路allocate_array
,.allocate_array_zero = N16路allocate_array_zero
N32路T* (*access)(N32路T*, Extent);
void (*from_uint32)(N32路T *destination ,uint32_t value);
- } N32路螞;
+ } N32路M;
- Local const N32路螞 N32路位; // initialized in the LOCAL section
+ Local const N32路M N32路m; // initialized in the LOCAL section
#endif
return N32路shift_right(shift_count, spill, operand, fill);
}
- Local const N32路螞 N32路位 = {
+ Local const N32路M N32路m = {
.allocate_array = N32路allocate_array
,.allocate_array_zero = N32路allocate_array_zero
-/*
- N32 - a processor native type
-
- For binary operations: a op b -> c
-
- See the document on the proper use of the Natural types.
-
- On the subject of multiple pointers indicating the same location in memory:
-
- When a routine has multiple results, and one or more of the result location
- pointers point to the same storage, the routine will either return an error
- status, or have defined behavior.
-
- When a routine has multiple operands, in any combination, those
- pointers can point to the same location, and the routine will
- function as advertised.
- When an operand functions as both an input and a result, perhaps due
- to a result pointer pointing to the same place as an operand
- pointer, the routine will function as advertised. (Internally the
- routine might make a temporary copy of the operand to accomplish
- this.)
+/*
+ M - The type for the function dictionary (manifold).
+ m - a manifold instance, there can be many, m0, m1 ...
+ T - Is the type for the tableau.
*/
-
#define N32_1x32路DEBUG
#ifndef FACE
//----------------------------------------
// Instance Data (Declaration Only)
- typedef uint32_t Extent;
- typedef uint32_t Digit;
+ typedef uint64_t Address;
+ // tableau type, encapsulated data is unavailable to user code
typedef struct N32_1x32路T N32_1x32路T;
extern N32_1x32路T *N32_1x32路zero;
// Return/Error Status and handlers
typedef enum{
- N32_1x32路Status路ok = 0
- ,N32_1x32路Status路overflow = 1
- ,N32_1x32路Status路accumulator1_overflow = 2
- ,N32_1x32路Status路carry = 3
- ,N32_1x32路Status路borrow = 4
- ,N32_1x32路Status路undefined_divide_by_zero = 5
- ,N32_1x32路Status路undefined_modulus_zero = 6
- ,N32_1x32路Status路gt_max_shift_count = 7
- ,N32_1x32路Status路spill_eq_operand = 8 // not currently signaled, result will be spill value
- ,N32_1x32路Status路one_word_product = 9
- ,N32_1x32路Status路two_word_product = 10
+ N32_1x32路Status路ok,
+ N32_1x32路Status路overflow,
+ N32_1x32路Status路accumulator_overflow,
+ N32_1x32路Status路carry,
+ N32_1x32路Status路borrow,
+ N32_1x32路Status路undefined_divide_by_zero,
+ N32_1x32路Status路undefined_modulus_zero,
+ N32_1x32路Status路gt_max_shift_count,
+ N32_1x32路Status路spill_eq_operand, // not currently signaled, result will be spill value
+ N32_1x32路Status路one_word_product,
+ N32_1x32路Status路two_word_product,
+ N32_1x32路Status路ConversionOverflow
} N32_1x32路Status;
typedef enum{
,N32_1x32路Order_gt = 1
} N32_1x32路Order;
- typedef N32_1x32路T *( *N32_1x32路Allocate_MemoryFault )(Extent);
+ // Incomplete conversion N32_1x32路T -> PNT, N32_1x32路T leftovers
+ typedef struct {
+ size_t scale; // this is in bytes
+ N32_1x32路T *d; // digits, programmer must point this to a register
+ } N32_1x32路Leftover_N;
+
+ // Incomplete conversion PNT -> N32_1x32路T, PNT leftovers
+ #define N32_1x32路LEFTOVER_PNT(PNT)\
+ typedef struct {\
+ size_t scale; // this is in bytes\
+ PNT leftover; // Residual value in PNT format\
+ } N32_1x32路Leftover_##PNT;
+
+ #ifdef UINT8_MAX
+ N32_1x32路LEFTOVER_PNT(uint8_t)
+ #endif
+ #ifdef UINT16_MAX
+ N32_1x32路LEFTOVER_PNT(uint16_t)
+ #endif
+ #ifdef UINT32_MAX
+ N32_1x32路LEFTOVER_PNT(uint32_t)
+ #endif
+ #ifdef UINT64_MAX
+ N32_1x32路LEFTOVER_PNT(uint64_t)
+ #endif
+ #ifdef __UINT128_MAX
+ N32_1x32路LEFTOVER_PNT(__uint128_t)
+ #endif
+
+ // when alloc runs out of memory
+ typedef N32_1x32路T *( *N32_1x32路Allocate_MemoryFault )(Address);
//----------------------------------------
// Interface
+ #define N32_1x32路TO_TYPE(PNT) N32_1x32路Status (*to_##PNT)(const N32_1x32路T *, PNT *, N32_1x32路Leftover_N *)
+ #define N32_1x32路FROM_TYPE(PNT) N32_1x32路Status (*from_##PNT)(const PNT *, N32_1x32路T * ,N32_1x32路Leftover_##PNT *)
+
typedef struct{
- N32_1x32路T *(*allocate_array_zero)(Extent, N32_1x32路Allocate_MemoryFault);
- N32_1x32路T *(*allocate_array)(Extent, N32_1x32路Allocate_MemoryFault);
+ // memory allocation
+ N32_1x32路T *(*allocate_array_zero)(Address, N32_1x32路Allocate_MemoryFault);
+ N32_1x32路T *(*allocate_array)(Address, N32_1x32路Allocate_MemoryFault);
void (*deallocate)(N32_1x32路T*);
+ N32_1x32路T* (*access)(N32_1x32路T*, Address);
+ // results fits in operand type functions
void (*copy)(N32_1x32路T*, N32_1x32路T*);
void (*bit_and)(N32_1x32路T*, N32_1x32路T*, N32_1x32路T*);
void (*bit_or)(N32_1x32路T*, N32_1x32路T*, N32_1x32路T*);
void (*bit_complement)(N32_1x32路T*, N32_1x32路T*);
void (*bit_twos_complement)(N32_1x32路T*, N32_1x32路T*);
+
+ // tests
N32_1x32路Order (*compare)(N32_1x32路T*, N32_1x32路T*);
bool (*lt)(N32_1x32路T*, N32_1x32路T*);
bool (*gt)(N32_1x32路T*, N32_1x32路T*);
bool (*eq)(N32_1x32路T*, N32_1x32路T*);
bool (*eq_zero)(N32_1x32路T*);
+
+ // arithmetic
N32_1x32路Status (*accumulate)(N32_1x32路T *accumulator1 ,N32_1x32路T *accumulator0 ,...);
N32_1x32路Status (*add)(N32_1x32路T*, N32_1x32路T*, N32_1x32路T*);
bool (*increment)(N32_1x32路T *a);
N32_1x32路Status (*multiply)(N32_1x32路T*, N32_1x32路T*, N32_1x32路T*, N32_1x32路T*);
N32_1x32路Status (*divide)(N32_1x32路T*, N32_1x32路T*, N32_1x32路T*, N32_1x32路T*);
N32_1x32路Status (*modulus)(N32_1x32路T*, N32_1x32路T*, N32_1x32路T*);
- N32_1x32路Status (*shift_left)(Extent, N32_1x32路T*, N32_1x32路T*, N32_1x32路T*);
- N32_1x32路Status (*shift_right)(Extent, N32_1x32路T*, N32_1x32路T*, N32_1x32路T*);
- N32_1x32路Status (*arithmetic_shift_right)(Extent, N32_1x32路T*, N32_1x32路T*);
-
- N32_1x32路T* (*access)(N32_1x32路T*, Extent);
- void (*from_uint32)(N32_1x32路T *destination ,uint32_t value);
- } N32_1x32路螞;
- Local const N32_1x32路螞 N32_1x32路位; // initialized in the LOCAL section
+ // shift
+ N32_1x32路Status (*shift_left)(Address, N32_1x32路T*, N32_1x32路T*, N32_1x32路T*);
+ N32_1x32路Status (*shift_right)(Address, N32_1x32路T*, N32_1x32路T*, N32_1x32路T*);
+ N32_1x32路Status (*arithmetic_shift_right)(Address, N32_1x32路T*, N32_1x32路T*);
+
+ // import/export
+ char *(*to_string)(N32_1x32路T *);
+
+ #ifdef UINT8_MAX
+ N32_1x32路TO_TYPE(uint8_t)
+ N32_1x32路FROM_TYPE(uint8_t)
+ #endif
+ #ifdef UINT16_MAX
+ N32_1x32路TO_TYPE(uint16_t)
+ N32_1x32路FROM_TYPE(uint16_t)
+ #endif
+ #ifdef UINT32_MAX
+ N32_1x32路TO_TYPE(uint32_t)
+ N32_1x32路FROM_TYPE(uint32_t)
+ #endif
+ #ifdef UINT64_MAX
+ N32_1x32路TO_TYPE(uint64_t)
+ N32_1x32路FROM_TYPE(uint64_t)
+ #endif
+ #ifdef __UINT128_MAX
+ N32_1x32路TO_TYPE(__uint128_t)
+ N32_1x32路FROM_TYPE(__uint128_t)
+ #endif
+
+ } N32_1x32路M;
+
+ Local const N32_1x32路M N32_1x32路m; // initialized in the LOCAL section
#endif
#ifdef N32_1x32路IMPLEMENTATION
- // this part goes into the library
+ typedef uint32_t Digit;
+ const uint8_t digit_array_extent = {3};
+
+ // full type definition for Tableau
+ struct N32_1x32路T{
+ Digit d[digit_array_extent + 1];
+ };
+
+ // this part goes into Nlib.a
#ifndef LOCAL
#include <stdarg.h>
#include <stdlib.h>
-
- struct N32_1x32路T{
- Digit d0;
- };
-
- N32_1x32路T N32_1x32路constant[4] = {
- {.d0 = 0},
- {.d0 = 1},
- {.d0 = ~(uint32_t)0},
- {.d0 = 1 << 31}
- };
-
- N32_1x32路T *N32_1x32路zero = &N32_1x32路constant[0];
- N32_1x32路T *N32_1x32路one = &N32_1x32路constant[1];
- N32_1x32路T *N32_1x32路all_one_bit = &N32_1x32路constant[2];
- N32_1x32路T *N32_1x32路msb = &N32_1x32路constant[3];
- N32_1x32路T *N32_1x32路lsb = &N32_1x32路constant[1];
+ #include <stdio.h>
// the allocate an array of N32
- N32_1x32路T *N32_1x32路allocate_array(Extent extent ,N32_1x32路Allocate_MemoryFault memory_fault){
+ N32_1x32路T *N32_1x32路allocate_array(Address extent ,N32_1x32路Allocate_MemoryFault memory_fault){
N32_1x32路T *instance = malloc((extent + 1) * sizeof(N32_1x32路T) );
if(!instance){
return memory_fault ? memory_fault(extent) : NULL;
return instance;
}
- N32_1x32路T *N32_1x32路allocate_array_zero(Extent extent ,N32_1x32路Allocate_MemoryFault memory_fault){
+ N32_1x32路T *N32_1x32路allocate_array_zero(Address extent ,N32_1x32路Allocate_MemoryFault memory_fault){
N32_1x32路T *instance = calloc( extent + 1 ,sizeof(N32_1x32路T) );
if(!instance){
return memory_fault ? memory_fault(extent) : NULL;
free(unencumbered);
}
+ char *to_string(N32_1x32路T *n) {
+ // Each byte requires two hex characters, plus "0x" prefix and null terminator
+ const Address string_length = (sizeof(Digit) * (digit_array_extent + 1) * 2) + 3;
+ char *buffer = malloc(string_length);
+ if (!buffer) {
+ return NULL; // Handle allocation failure
+ }
+
+ strcpy(buffer, "0x"); // Prefix the hex representation
+ char *ps = buffer + 2; // Pointer to string buffer (after "0x")
+
+ // Pointer to the most significant digit
+ Digit *pd = n->d + digit_array_extent;
+
+ for (; pd >= n->d; pd--) {
+ sprintf(ps, "%0*X", (int)(sizeof(Digit) * 2), *pd);
+ ps += sizeof(Digit) * 2; // Move forward in buffer
+ }
+
+ return buffer; // Caller must free the allocated buffer
+ }
+
#endif
- // This part is included after the library user's code
+ // This part is included after the user's code. If the code at top is a 'header, then this is a 'tailer'.
#ifdef LOCAL
- // instance
+ #include "Copy.lib.c"
- struct N32_1x32路T{
- Digit d0;
- };
+ CON32_1x32TANTS_BLOCK
+
+ N32_1x32路T *N32_1x32路zero = N32_1x32路constant + 0;
+ N32_1x32路T *N32_1x32路one = N32_1x32路constant + 1;
+ N32_1x32路T *N32_1x32路all_one_bit = N32_1x32路constant + 2;
+ N32_1x32路T *N32_1x32路msb = &N32_1x32路constant + 3;
+ N32_1x32路T *N32_1x32路lsb = &N32_1x32路constant + 1;
// temporary variables
// making these LOCAL rather than reserving one block in the library is thread safe
// allocation
- extern N32_1x32路T *N32_1x32路allocate_array(Extent, N32_1x32路Allocate_MemoryFault);
- extern N32_1x32路T *N32_1x32路allocate_array_zero(Extent, N32_1x32路Allocate_MemoryFault);
+ extern N32_1x32路T *N32_1x32路allocate_array(Address, N32_1x32路Allocate_MemoryFault);
+ extern N32_1x32路T *N32_1x32路allocate_array_zero(Address, N32_1x32路Allocate_MemoryFault);
extern void N32_1x32路deallocate(N32_1x32路T *);
// so the user can access numbers in an array allocation
- Local N32_1x32路T* N32_1x32路access(N32_1x32路T *array ,Extent index){
- return &array[index];
- }
-
- Local void N32_1x32路from_uint32(N32_1x32路T *destination ,uint32_t value){
- if(destination == NULL) return;
- destination->d0 = value;
+ Local N32_1x32路T* N32_1x32路access(N32_1x32路T *array ,Address index){
+ return array + index;
}
- // copy, convenience copy
+ // copy
Local void N32_1x32路copy(N32_1x32路T *destination ,N32_1x32路T *source){
if(source == destination) return; // that was easy!
return (diff > a->d0) ? N32_1x32路Status路borrow : N32_1x32路Status路ok;
}
-
Local N32_1x32路Status N32_1x32路multiply(N32_1x32路T *product1 ,N32_1x32路T *product0 ,N32_1x32路T *a ,N32_1x32路T *b){
uint64_t product = (uint64_t)a->d0 * (uint64_t)b->d0;
product0->d0 = (uint32_t)product;
return N32_1x32路shift_right(shift_count, spill, operand, fill);
}
- Local const N32_1x32路螞 N32_1x32路位 = {
+ #ifdef UINT8_MAX
+ #endif
+ #ifdef UINT16_MAX
+ #endif
+ #ifdef UINT32_MAX
+ #endif
+ #ifdef UINT64_MAX
+ #endif
+
+ // Tableau share dictionary
+ Local const N32_1x32路M N32_1x32路m = {
.allocate_array = N32_1x32路allocate_array
,.allocate_array_zero = N32_1x32路allocate_array_zero
,.access = N32_1x32路access
,.from_uint32 = N32_1x32路from_uint32
+
+ #ifdef UINT8_MAX
+ #endif
+ #ifdef UINT16_MAX
+ #endif
+ #ifdef UINT32_MAX
+ #endif
+ #ifdef UINT64_MAX
+ #endif
+ #ifdef __UINT128_MAX
+ #endif
+
};
+ #undef FACE
+ #include "Copy.lib.c"
+
#endif
#endif
N32_4x8路T* (*access)(N32_4x8路T*, Extent);
void (*from_uint32)(N32_4x8路T *destination ,uint32_t value);
- } N32_4x8路螞;
+ } N32_4x8路M;
- Local const N32_4x8路螞 N32_4x8路位; // initialized in the LOCAL section
+ Local const N32_4x8路M N32_4x8路m; // initialized in the LOCAL section
#endif
return N32_4x8路shift_right(shift_count, spill, operand, fill);
}
- Local const N32_4x8路螞 N32_4x8路位 = {
+ Local const N32_4x8路M N32_4x8路m = {
.allocate_array = N32_4x8路allocate_array
,.allocate_array_zero = N32_4x8路allocate_array_zero
N64路T* (*access)(N64路T*, Extent);
void (*from_uint64)(N64路T *destination, uint64_t value);
- } N64路螞;
+ } N64路M;
- Local const N64路螞 N64路位; // initialized in the LOCAL section
+ Local const N64路M N64路m; // initialized in the LOCAL section
#endif
return N64路shift_right(shift_count, spill, operand, fill);
}
- Local const N64路螞 N64路位 = {
+ Local const N64路M N64路m = {
.allocate_array = N64路allocate_array
,.allocate_array_zero = N64路allocate_array_zero
,.deallocate = N64路deallocate
N8路T* (*access)(N8路T*, Extent);
void (*from_uint32)(N8路T *destination ,uint32_t value);
- } N8路螞;
+ } N8路M;
- Local const N8路螞 N8路位; // initialized in the LOCAL section
+ Local const N8路M N8路m; // initialized in the LOCAL section
#endif
return N8路shift_right(shift_count, spill, operand, fill);
}
- Local const N8路螞 N8路位 = {
+ Local const N8路M N8路m = {
.allocate_array = N8路allocate_array
,.allocate_array_zero = N8路allocate_array_zero
--- /dev/null
+/*
+ Copy - Memory copy operations with attention to alignment.
+ Provides optimized copy and byte order reversal functions.
+*/
+
+#define Copy路DEBUG
+
+#ifndef FACE
+#define Copy路IMPLEMENTATION
+#define FACE
+#endif
+
+//--------------------------------------------------------------------------------
+// Interface
+
+#ifndef Copy路FACE
+#define Copy路FACE
+
+ #include <stdint.h>
+ #include <stddef.h>
+
+ void *Copy路region(void *read0 ,void *read1 ,void *write0);
+ void *Copy路reverse_byte_order(void *read0 ,void *read1 ,void *write0);
+
+#endif
+
+//--------------------------------------------------------------------------------
+// Implementation
+
+#ifdef Copy路IMPLEMENTATION
+
+ // this part goes into Nlib.a
+ #ifndef LOCAL
+ #endif
+
+ #ifdef LOCAL
+
+ /*
+ Copy路region - Copies a memory region while preserving byte order.
+ - Aligns reads for performance.
+ - Writes are assumed to be buffered and do not require alignment.
+ - Returns the updated write pointer.
+ */
+ void *Copy路region(void *read0 ,void *read1 ,void *write0){
+
+ uint8_t *r = (uint8_t *)read0;
+ uint8_t *r1 = (uint8_t *)read1;
+ uint8_t *w = (uint8_t *)write0;
+
+ //----------
+ // The potentially unaligned initial part (align read pointer).
+ if( (uintptr_t)r & 0x7 ){
+
+ // ORing in `0x7` adds at most six bytes to r.
+ uint8_t *r01 = (uint8_t *)((uintptr_t)r | 0x7);
+
+ // If the read interval is very small
+ if(r01 >= r1){
+ while(r < r1){
+ *w++ = *r++;
+ }
+ return w;
+ }
+
+ // Copy up to alignment boundary
+ do{
+ *w++ = *r++;
+ }while(r <= r01);
+ }
+ // r is now aligned, but *r has not yet been copied
+
+ //----------
+ // The bulk copy part (w is still possibly unaligned, but r is aligned)
+ uint8_t *r10 = (uint8_t *)((uintptr_t)r1 & ~(uintptr_t)0x7);
+
+ while(r < r10){
+ *(uint64_t *)w = *(uint64_t *)r;
+ w += 8;
+ r += 8;
+ }
+
+ // If r1 was aligned then r10 == r1 and we are done
+ if(r == r1) return w;
+
+ //----------
+ // The ragged tail, up to 7 bytes
+ do{
+ *w++ = *r++;
+ }while(r < r1);
+
+ return w;
+ }
+
+ /*
+ Copy路reverse_byte_order - Copies a memory region while reversing byte order.
+ - Reads in reverse order while writing in forward order.
+ - Uses `__builtin_bswap64` for efficient 64-bit swaps.
+ - Returns the updated write pointer.
+ */
+ void *Copy路reverse_byte_order(void *read0 ,void *read1 ,void *write0){
+
+ uint8_t *r = (uint8_t *)read1; // Start from the last byte
+ uint8_t *r0 = (uint8_t *)read0;
+ uint8_t *w = (uint8_t *)write0;
+
+ //----------
+ // The potentially unaligned initial part (align read pointer).
+ if( (uintptr_t)r & 0x7 ){
+
+ // ANDing with `~0x7` moves it downward to the nearest lower alignment.
+ uint8_t *r10 = (uint8_t *)((uintptr_t)r & ~(uintptr_t)0x7);
+
+ // If the read interval is very small
+ if(r10 < r0){
+ while(r > r0){
+ *w++ = *--r;
+ }
+ return w;
+ }
+
+ // Copy down to alignment boundary
+ do{
+ *w++ = *--r;
+ }while(r > r10);
+ }
+ // r is now aligned, and *r has been copied
+
+ //----------
+ // The bulk copy part
+ uint8_t *r01 = (uint8_t *)( ((uintptr_t)r0 + (uintptr_t)0x7) & ~(uintptr_t)0x7);
+
+ while(r > r01){
+ r -= 8;
+ *(uint64_t *)w = __builtin_bswap64(*(uint64_t *)r);
+ w += 8;
+ }
+
+ // If r0 was aligned then r01 == r0 and we are done
+ if(r < r0) return w;
+
+ //----------
+ // The ragged tail, up to 7 bytes
+ do{
+ *w++ = *--r;
+ }while(r >= r0);
+
+ return w;
+ }
+
+ #endif // LOCAL
+
+#endif // IMPLEMENTATION
N16PN路T* (*access)(N16PN路T*, Extent);
void (*from_uint32)(N16PN路T *destination ,uint32_t value);
- } N16PN路M;
+ } N16PN路螞;
- Local const N16PN路M N16PN路m; // initialized in the LOCAL section
+ Local const N16PN路螞 N16PN路位; // initialized in the LOCAL section
#endif
return N16PN路shift_right(shift_count, spill, operand, fill);
}
- Local const N16PN路M N16PN路m = {
+ Local const N16PN路螞 N16PN路位 = {
.allocate_array = N16PN路allocate_array
,.allocate_array_zero = N16PN路allocate_array_zero
N32PN路T* (*access)(N32PN路T*, Extent);
void (*from_uint32)(N32PN路T *destination ,uint32_t value);
- } N32PN路M;
+ } N32PN路螞;
- Local const N32PN路M N32PN路m; // initialized in the LOCAL section
+ Local const N32PN路螞 N32PN路位; // initialized in the LOCAL section
#endif
return N32PN路shift_right(shift_count, spill, operand, fill);
}
- Local const N32PN路M N32PN路m = {
+ Local const N32PN路螞 N32PN路位 = {
.allocate_array = N32PN路allocate_array
,.allocate_array_zero = N32PN路allocate_array_zero
-/*
- N32 - a processor native type
-
- For binary operations: a op b -> c
-
- See the document on the proper use of the Natural types.
-
- On the subject of multiple pointers indicating the same location in memory:
-
- When a routine has multiple results, and one or more of the result location
- pointers point to the same storage, the routine will either return an error
- status, or have defined behavior.
-
- When a routine has multiple operands, in any combination, those
- pointers can point to the same location, and the routine will
- function as advertised.
- When an operand functions as both an input and a result, perhaps due
- to a result pointer pointing to the same place as an operand
- pointer, the routine will function as advertised. (Internally the
- routine might make a temporary copy of the operand to accomplish
- this.)
+/*
+ M - The type for the function dictionary (manifold).
+ m - a manifold instance, there can be many, m0, m1 ...
+ T - Is the type for the tableau.
*/
-
#define N32_1x32路DEBUG
#ifndef FACE
//----------------------------------------
// Instance Data (Declaration Only)
- typedef uint32_t Extent;
- typedef uint32_t Digit;
+ typedef uint64_t Address;
+ // tableau type, encapsulated data is unavailable to user code
typedef struct N32_1x32路T N32_1x32路T;
extern N32_1x32路T *N32_1x32路zero;
// Return/Error Status and handlers
typedef enum{
- N32_1x32路Status路ok = 0
- ,N32_1x32路Status路overflow = 1
- ,N32_1x32路Status路accumulator1_overflow = 2
- ,N32_1x32路Status路carry = 3
- ,N32_1x32路Status路borrow = 4
- ,N32_1x32路Status路undefined_divide_by_zero = 5
- ,N32_1x32路Status路undefined_modulus_zero = 6
- ,N32_1x32路Status路gt_max_shift_count = 7
- ,N32_1x32路Status路spill_eq_operand = 8 // not currently signaled, result will be spill value
- ,N32_1x32路Status路one_word_product = 9
- ,N32_1x32路Status路two_word_product = 10
+ N32_1x32路Status路ok,
+ N32_1x32路Status路overflow,
+ N32_1x32路Status路accumulator_overflow,
+ N32_1x32路Status路carry,
+ N32_1x32路Status路borrow,
+ N32_1x32路Status路undefined_divide_by_zero,
+ N32_1x32路Status路undefined_modulus_zero,
+ N32_1x32路Status路gt_max_shift_count,
+ N32_1x32路Status路spill_eq_operand, // not currently signaled, result will be spill value
+ N32_1x32路Status路one_word_product,
+ N32_1x32路Status路two_word_product,
+ N32_1x32路Status路ConversionOverflow
} N32_1x32路Status;
typedef enum{
,N32_1x32路Order_gt = 1
} N32_1x32路Order;
- typedef N32_1x32路T *( *N32_1x32路Allocate_MemoryFault )(Extent);
+ // Incomplete conversion N32_1x32路T -> PNT, N32_1x32路T leftovers
+ typedef struct {
+ size_t scale; // this is in bytes
+ N32_1x32路T *d; // digits, programmer must point this to a register
+ } N32_1x32路Leftover_N;
+
+ // Incomplete conversion PNT -> N32_1x32路T, PNT leftovers
+ #define N32_1x32路LEFTOVER_PNT(PNT)\
+ typedef struct {\
+ size_t scale; // this is in bytes\
+ PNT leftover; // Residual value in PNT format\
+ } N32_1x32路Leftover_##PNT;
+
+ #ifdef UINT8_MAX
+ N32_1x32路LEFTOVER_PNT(uint8_t)
+ #endif
+ #ifdef UINT16_MAX
+ N32_1x32路LEFTOVER_PNT(uint16_t)
+ #endif
+ #ifdef UINT32_MAX
+ N32_1x32路LEFTOVER_PNT(uint32_t)
+ #endif
+ #ifdef UINT64_MAX
+ N32_1x32路LEFTOVER_PNT(uint64_t)
+ #endif
+ #ifdef __UINT128_MAX
+ N32_1x32路LEFTOVER_PNT(__uint128_t)
+ #endif
+
+ // when alloc runs out of memory
+ typedef N32_1x32路T *( *N32_1x32路Allocate_MemoryFault )(Address);
//----------------------------------------
// Interface
+ #define N32_1x32路TO_TYPE(PNT) N32_1x32路Status (*to_##PNT)(const N32_1x32路T *, PNT *, N32_1x32路Leftover_N *)
+ #define N32_1x32路FROM_TYPE(PNT) N32_1x32路Status (*from_##PNT)(const PNT *, N32_1x32路T * ,N32_1x32路Leftover_##PNT *)
+
typedef struct{
- N32_1x32路T *(*allocate_array_zero)(Extent, N32_1x32路Allocate_MemoryFault);
- N32_1x32路T *(*allocate_array)(Extent, N32_1x32路Allocate_MemoryFault);
+ // memory allocation
+ N32_1x32路T *(*allocate_array_zero)(Address, N32_1x32路Allocate_MemoryFault);
+ N32_1x32路T *(*allocate_array)(Address, N32_1x32路Allocate_MemoryFault);
void (*deallocate)(N32_1x32路T*);
+ N32_1x32路T* (*access)(N32_1x32路T*, Address);
+ // results fits in operand type functions
void (*copy)(N32_1x32路T*, N32_1x32路T*);
void (*bit_and)(N32_1x32路T*, N32_1x32路T*, N32_1x32路T*);
void (*bit_or)(N32_1x32路T*, N32_1x32路T*, N32_1x32路T*);
void (*bit_complement)(N32_1x32路T*, N32_1x32路T*);
void (*bit_twos_complement)(N32_1x32路T*, N32_1x32路T*);
+
+ // tests
N32_1x32路Order (*compare)(N32_1x32路T*, N32_1x32路T*);
bool (*lt)(N32_1x32路T*, N32_1x32路T*);
bool (*gt)(N32_1x32路T*, N32_1x32路T*);
bool (*eq)(N32_1x32路T*, N32_1x32路T*);
bool (*eq_zero)(N32_1x32路T*);
+
+ // arithmetic
N32_1x32路Status (*accumulate)(N32_1x32路T *accumulator1 ,N32_1x32路T *accumulator0 ,...);
N32_1x32路Status (*add)(N32_1x32路T*, N32_1x32路T*, N32_1x32路T*);
bool (*increment)(N32_1x32路T *a);
N32_1x32路Status (*multiply)(N32_1x32路T*, N32_1x32路T*, N32_1x32路T*, N32_1x32路T*);
N32_1x32路Status (*divide)(N32_1x32路T*, N32_1x32路T*, N32_1x32路T*, N32_1x32路T*);
N32_1x32路Status (*modulus)(N32_1x32路T*, N32_1x32路T*, N32_1x32路T*);
- N32_1x32路Status (*shift_left)(Extent, N32_1x32路T*, N32_1x32路T*, N32_1x32路T*);
- N32_1x32路Status (*shift_right)(Extent, N32_1x32路T*, N32_1x32路T*, N32_1x32路T*);
- N32_1x32路Status (*arithmetic_shift_right)(Extent, N32_1x32路T*, N32_1x32路T*);
- N32_1x32路T* (*access)(N32_1x32路T*, Extent);
- void (*from_uint32)(N32_1x32路T *destination ,uint32_t value);
+ // shift
+ N32_1x32路Status (*shift_left)(Address, N32_1x32路T*, N32_1x32路T*, N32_1x32路T*);
+ N32_1x32路Status (*shift_right)(Address, N32_1x32路T*, N32_1x32路T*, N32_1x32路T*);
+ N32_1x32路Status (*arithmetic_shift_right)(Address, N32_1x32路T*, N32_1x32路T*);
+
+ // import/export
+ char *(*to_string)(N32_1x32路T *);
+
+ #ifdef UINT8_MAX
+ N32_1x32路TO_TYPE(uint8_t)
+ N32_1x32路FROM_TYPE(uint8_t)
+ #endif
+ #ifdef UINT16_MAX
+ N32_1x32路TO_TYPE(uint16_t)
+ N32_1x32路FROM_TYPE(uint16_t)
+ #endif
+ #ifdef UINT32_MAX
+ N32_1x32路TO_TYPE(uint32_t)
+ N32_1x32路FROM_TYPE(uint32_t)
+ #endif
+ #ifdef UINT64_MAX
+ N32_1x32路TO_TYPE(uint64_t)
+ N32_1x32路FROM_TYPE(uint64_t)
+ #endif
+ #ifdef __UINT128_MAX
+ N32_1x32路TO_TYPE(__uint128_t)
+ N32_1x32路FROM_TYPE(__uint128_t)
+ #endif
+
} N32_1x32路M;
Local const N32_1x32路M N32_1x32路m; // initialized in the LOCAL section
#ifdef N32_1x32路IMPLEMENTATION
- // this part goes into the library
+ typedef uint32_t Digit;
+ const uint8_t digit_array_extent = {3};
+
+ // full type definition for Tableau
+ struct N32_1x32路T{
+ Digit d[digit_array_extent + 1];
+ };
+
+ // this part goes into Nlib.a
#ifndef LOCAL
#include <stdarg.h>
#include <stdlib.h>
-
- struct N32_1x32路T{
- Digit d0;
- };
-
- N32_1x32路T N32_1x32路constant[4] = {
- {.d0 = 0},
- {.d0 = 1},
- {.d0 = ~(uint32_t)0},
- {.d0 = 1 << 31}
- };
-
- N32_1x32路T *N32_1x32路zero = &N32_1x32路constant[0];
- N32_1x32路T *N32_1x32路one = &N32_1x32路constant[1];
- N32_1x32路T *N32_1x32路all_one_bit = &N32_1x32路constant[2];
- N32_1x32路T *N32_1x32路msb = &N32_1x32路constant[3];
- N32_1x32路T *N32_1x32路lsb = &N32_1x32路constant[1];
+ #include <stdio.h>
// the allocate an array of N32
- N32_1x32路T *N32_1x32路allocate_array(Extent extent ,N32_1x32路Allocate_MemoryFault memory_fault){
+ N32_1x32路T *N32_1x32路allocate_array(Address extent ,N32_1x32路Allocate_MemoryFault memory_fault){
N32_1x32路T *instance = malloc((extent + 1) * sizeof(N32_1x32路T) );
if(!instance){
return memory_fault ? memory_fault(extent) : NULL;
return instance;
}
- N32_1x32路T *N32_1x32路allocate_array_zero(Extent extent ,N32_1x32路Allocate_MemoryFault memory_fault){
+ N32_1x32路T *N32_1x32路allocate_array_zero(Address extent ,N32_1x32路Allocate_MemoryFault memory_fault){
N32_1x32路T *instance = calloc( extent + 1 ,sizeof(N32_1x32路T) );
if(!instance){
return memory_fault ? memory_fault(extent) : NULL;
free(unencumbered);
}
+ char *to_string(N32_1x32路T *n) {
+ // Each byte requires two hex characters, plus "0x" prefix and null terminator
+ const Address string_length = (sizeof(Digit) * (digit_array_extent + 1) * 2) + 3;
+ char *buffer = malloc(string_length);
+ if (!buffer) {
+ return NULL; // Handle allocation failure
+ }
+
+ strcpy(buffer, "0x"); // Prefix the hex representation
+ char *ps = buffer + 2; // Pointer to string buffer (after "0x")
+
+ // Pointer to the most significant digit
+ Digit *pd = n->d + digit_array_extent;
+
+ for (; pd >= n->d; pd--) {
+ sprintf(ps, "%0*X", (int)(sizeof(Digit) * 2), *pd);
+ ps += sizeof(Digit) * 2; // Move forward in buffer
+ }
+
+ return buffer; // Caller must free the allocated buffer
+ }
+
#endif
- // This part is included after the library user's code
+ // This part is included after the user's code. If the code at top is a 'header, then this is a 'tailer'.
#ifdef LOCAL
- // instance
+ #include "Copy.lib.c"
- struct N32_1x32路T{
- Digit d0;
- };
+ CON32_1x32TANTS_BLOCK
+
+ N32_1x32路T *N32_1x32路zero = N32_1x32路constant + 0;
+ N32_1x32路T *N32_1x32路one = N32_1x32路constant + 1;
+ N32_1x32路T *N32_1x32路all_one_bit = N32_1x32路constant + 2;
+ N32_1x32路T *N32_1x32路msb = &N32_1x32路constant + 3;
+ N32_1x32路T *N32_1x32路lsb = &N32_1x32路constant + 1;
// temporary variables
// making these LOCAL rather than reserving one block in the library is thread safe
// allocation
- extern N32_1x32路T *N32_1x32路allocate_array(Extent, N32_1x32路Allocate_MemoryFault);
- extern N32_1x32路T *N32_1x32路allocate_array_zero(Extent, N32_1x32路Allocate_MemoryFault);
+ extern N32_1x32路T *N32_1x32路allocate_array(Address, N32_1x32路Allocate_MemoryFault);
+ extern N32_1x32路T *N32_1x32路allocate_array_zero(Address, N32_1x32路Allocate_MemoryFault);
extern void N32_1x32路deallocate(N32_1x32路T *);
// so the user can access numbers in an array allocation
- Local N32_1x32路T* N32_1x32路access(N32_1x32路T *array ,Extent index){
- return &array[index];
- }
-
- Local void N32_1x32路from_uint32(N32_1x32路T *destination ,uint32_t value){
- if(destination == NULL) return;
- destination->d0 = value;
+ Local N32_1x32路T* N32_1x32路access(N32_1x32路T *array ,Address index){
+ return array + index;
}
- // copy, convenience copy
+ // copy
Local void N32_1x32路copy(N32_1x32路T *destination ,N32_1x32路T *source){
if(source == destination) return; // that was easy!
return (diff > a->d0) ? N32_1x32路Status路borrow : N32_1x32路Status路ok;
}
-
Local N32_1x32路Status N32_1x32路multiply(N32_1x32路T *product1 ,N32_1x32路T *product0 ,N32_1x32路T *a ,N32_1x32路T *b){
uint64_t product = (uint64_t)a->d0 * (uint64_t)b->d0;
product0->d0 = (uint32_t)product;
return N32_1x32路shift_right(shift_count, spill, operand, fill);
}
+ #ifdef UINT8_MAX
+ #endif
+ #ifdef UINT16_MAX
+ #endif
+ #ifdef UINT32_MAX
+ #endif
+ #ifdef UINT64_MAX
+ #endif
+
+ // Tableau share dictionary
Local const N32_1x32路M N32_1x32路m = {
.allocate_array = N32_1x32路allocate_array
,.access = N32_1x32路access
,.from_uint32 = N32_1x32路from_uint32
+
+ #ifdef UINT8_MAX
+ #endif
+ #ifdef UINT16_MAX
+ #endif
+ #ifdef UINT32_MAX
+ #endif
+ #ifdef UINT64_MAX
+ #endif
+ #ifdef __UINT128_MAX
+ #endif
+
};
+ #undef FACE
+ #include "Copy.lib.c"
+
#endif
#endif
N64PN路T* (*access)(N64PN路T*, Extent);
void (*from_uint64)(N64PN路T *destination, uint64_t value);
- } N64PN路M;
+ } N64PN路螞;
- Local const N64PN路M N64PN路m; // initialized in the LOCAL section
+ Local const N64PN路螞 N64PN路位; // initialized in the LOCAL section
#endif
return N64PN路shift_right(shift_count, spill, operand, fill);
}
- Local const N64PN路M N64PN路m = {
+ Local const N64PN路螞 N64PN路位 = {
.allocate_array = N64PN路allocate_array
,.allocate_array_zero = N64PN路allocate_array_zero
,.deallocate = N64PN路deallocate
N8PN路T* (*access)(N8PN路T*, Extent);
void (*from_uint32)(N8PN路T *destination ,uint32_t value);
- } N8PN路M;
+ } N8PN路螞;
- Local const N8PN路M N8PN路m; // initialized in the LOCAL section
+ Local const N8PN路螞 N8PN路位; // initialized in the LOCAL section
#endif
return N8PN路shift_right(shift_count, spill, operand, fill);
}
- Local const N8PN路M N8PN路m = {
+ Local const N8PN路螞 N8PN路位 = {
.allocate_array = N8PN路allocate_array
,.allocate_array_zero = N8PN路allocate_array_zero
--- /dev/null
+/*
+ Black Box test for Copy.lib.c
+
+*/
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <string.h>
+
+// Pull in the interface portion of the Copy library
+#define FACE
+#include "Copy.lib.c"
+#undef FACE
+
+static sigjmp_buf jump_buffer;
+
+void signal_handler( int sig ){
+ siglongjmp( jump_buffer ,1 );
+}
+
+typedef bool ( *TestFunction )();
+typedef struct{
+ TestFunction function;
+ const char *name;
+} TestEntry;
+
+// -----------------------------------------------------------------------------
+// Test Declarations
+// -----------------------------------------------------------------------------
+
+bool test_copy_bytes();
+bool test_copy_bytes_reverse();
+bool test_copy_step();
+bool test_copy_step_reverse();
+
+// -----------------------------------------------------------------------------
+// Test List and Runner
+// -----------------------------------------------------------------------------
+
+TestEntry test_list[] = {
+ { test_copy_bytes ,"test_copy_bytes" }
+ ,{ test_copy_bytes_reverse ,"test_copy_bytes_reverse" }
+ ,{ test_copy_step ,"test_copy_step" }
+ ,{ test_copy_step_reverse ,"test_copy_step_reverse" }
+ ,{ NULL ,NULL } // terminator
+};
+
+int test_head(){
+ int pass_count = 0;
+ int fail_count = 0;
+
+ // Catch common signals
+ signal( SIGSEGV ,signal_handler );
+ signal( SIGFPE ,signal_handler );
+ signal( SIGABRT ,signal_handler );
+
+ for( TestEntry *entry = test_list ; entry->function != NULL ; entry++ ){
+ if( sigsetjmp( jump_buffer ,1 ) == 0 ){
+ // Normal path
+ if( !entry->function() ){
+ printf( "Failed: %s\n" ,entry->name );
+ fail_count++;
+ }else{
+ pass_count++;
+ }
+ }else{
+ // Signal caught
+ printf( "Failed due to signal: %s\n" ,entry->name );
+ fail_count++;
+ }
+ }
+
+ printf( "Tests passed: %d\n" ,pass_count );
+ printf( "Tests failed: %d\n" ,fail_count );
+
+ return ( fail_count == 0 ) ? 0 : 1;
+}
+
+int main( int argc ,char **argv ){
+ return test_head();
+}
+
+// -----------------------------------------------------------------------------
+// Test Definitions
+// -----------------------------------------------------------------------------
+
+bool test_copy_bytes(){
+ // Test that Copy路bytes() copies data verbatim from src to dst
+ uint8_t src[8] = { 0x01 ,0x02 ,0x03 ,0x04 ,0xA0 ,0xB0 ,0xC0 ,0xFF };
+ uint8_t dst[8];
+ memset( dst ,0x00 ,8 );
+
+ // Copy entire buffer
+ Copy路bytes( src ,src + 8 ,dst );
+
+ // Check
+ for( int i = 0 ; i < 8 ; i++ ){
+ if( dst[i] != src[i] ){
+ return false;
+ }
+ }
+ return true;
+}
+
+bool test_copy_bytes_reverse(){
+ // Test that Copy路bytes_reverse_order() reverses the entire buffer
+ uint8_t src[6] = { 'H' ,'e' ,'l' ,'l' ,'o' ,'!' };
+ uint8_t dst[6];
+ memset( dst ,0x00 ,6 );
+
+ // Reverse copy: Expect "!olleH"
+ Copy路bytes_reverse_order( src ,src + 6 ,dst );
+
+ static const uint8_t expected[6] = { '!' ,'o' ,'l' ,'l' ,'e' ,'H' };
+ for( int i = 0 ; i < 6 ; i++ ){
+ if( dst[i] != expected[i] ){
+ return false;
+ }
+ }
+ return true;
+}
+
+bool test_copy_step(){
+ // Test partial copying with Copy路step()
+ // We'll create a source of 10 bytes but allow only 4 bytes of write at a time.
+ uint8_t src[10];
+ for( int i = 0 ; i < 10 ; i++ ){
+ src[i] = (uint8_t)( i + 1 ); // 1..10
+ }
+
+ uint8_t dst[10];
+ memset( dst ,0 ,10 );
+
+ // Create a Copy路it descriptor
+ Copy路it it;
+ it.read0 = src;
+ it.read_size = 10;
+ it.write0 = dst;
+ it.write_size = 4;
+
+ // First step: expect incomplete_read (only 4 bytes written)
+ {
+ Copy路Status st = Copy路step( &it );
+ if( st != Copy路Status路incomplete_read ){
+ return false;
+ }
+ // Check that first 4 bytes got copied
+ for( int i = 0 ; i < 4 ; i++ ){
+ if( dst[i] != (uint8_t)( i + 1 ) ){
+ return false;
+ }
+ }
+ // read_size=6, write_size=0, read0 advanced by 4, write0 advanced by 4
+ if( it.read_size != 6 || it.write_size != 0 ){
+ return false;
+ }
+ }
+
+ // Provide more write space
+ it.write_size = 3;
+ // Second step: expect incomplete_read again (only 3 more bytes copied)
+ {
+ Copy路Status st = Copy路step( &it );
+ if( st != Copy路Status路incomplete_read ){
+ return false;
+ }
+ // Check next 3 bytes: now in dst[4..6]
+ for( int i = 0 ; i < 3 ; i++ ){
+ // i=0 => index=4 => src[4]=5
+ if( dst[4 + i] != (uint8_t)( 5 + i ) ){
+ return false;
+ }
+ }
+ if( it.read_size != 3 || it.write_size != 0 ){
+ return false;
+ }
+ }
+
+ // Provide final 3 bytes of write space
+ it.write_size = 3;
+ {
+ Copy路Status st = Copy路step( &it );
+ // Now we expect either complete or incomplete_write if exactly matched
+ // Actually we have 3 left to read, 3 left to write => it should be 'complete'
+ if( st != Copy路Status路complete ){
+ return false;
+ }
+ // Check last 3 bytes
+ for( int i = 0 ; i < 3 ; i++ ){
+ if( dst[7 + i] != (uint8_t)( 8 + i ) ){
+ return false;
+ }
+ }
+ }
+
+ // Verify the entire dst array
+ for( int i = 0 ; i < 10 ; i++ ){
+ if( dst[i] != (uint8_t)( i + 1 ) ){
+ return false;
+ }
+ }
+ return true;
+}
+
+bool test_copy_step_reverse(){
+ // Test partial copying in reverse using Copy路step_reverse_order()
+
+ // Source: 7 bytes => {1,2,3,4,5,6,7}
+ uint8_t src[7];
+ for( int i = 0 ; i < 7 ; i++ ){
+ src[i] = (uint8_t)( i + 1 );
+ }
+
+ uint8_t dst[7];
+ memset( dst ,0 ,7 );
+
+ Copy路it it;
+ it.read0 = src; // Base of read
+ it.read_size = 7; // 7 bytes total
+ it.write0 = dst;
+ it.write_size = 4; // Only 4 bytes can be written initially
+
+ // 1st step: we copy the top 4 bytes in reverse => should be {7,6,5,4}
+ {
+ Copy路Status st = Copy路step_reverse_order( &it );
+ if( st != Copy路Status路incomplete_read ){
+ return false;
+ }
+ // Check that the first 4 reversed bytes ended up in dst
+ // We expect: dst[0]=7, dst[1]=6, dst[2]=5, dst[3]=4
+ if( dst[0] != 7 || dst[1] != 6 || dst[2] != 5 || dst[3] != 4 ){
+ return false;
+ }
+ // read_size should now be 3, write_size=0
+ if( it.read_size != 3 || it.write_size != 0 ){
+ return false;
+ }
+ }
+
+ // Provide 3 more bytes of write space
+ it.write_size = 3;
+ {
+ // 2nd step: copy the remaining 3 bytes in reverse => {3,2,1}
+ Copy路Status st = Copy路step_reverse_order( &it );
+ // With 3 left to read, 3 left to write => expect complete or incomplete_write
+ if( st != Copy路Status路complete ){
+ return false;
+ }
+ // Check we wrote them after the first 4
+ if( dst[4] != 3 || dst[5] != 2 || dst[6] != 1 ){
+ return false;
+ }
+ // Now read_size=0, write_size=0
+ if( it.read_size != 0 || it.write_size != 0 ){
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// for block box testing this goes at the bottom
+// for white box testing this goes at the top
+
+#define LOCAL
+#include "Copy.lib.c"
+#endif
*/
-#define IFACE
+#define FACE
#include <stdio.h>
#include <stdlib.h>
+#undef FACE
// No need to define IMPLEMENTATION as `main` is one and done.
return 0;
}
+
+
+#define LOCAL
+#undef LOCAL
# input guards
env_must_be="tester/tool馃枆/env"
if [ "$ENV" != "$env_must_be" ]; then
- echo "$(script_afp):: error: must be run in the $env_must_be environment"
+ echo "$(script_fp):: error: must be run in the $env_must_be environment"
exit 1
fi
cd "$REPO_HOME"/tester || exit 1
if [ ! -d scratchpad ]; then
- echo "$(script_afp):: no scratchpad directory"
+ echo "$(script_fp):: no scratchpad directory"
exit 1
fi
release_dir=$(release_dir)
if [ ! -d "$release_dir" ]; then
- echo "$(script_afp):: no release directory to pull install files from"
+ echo "$(script_fp):: no release directory to pull install files from"
exit 1
fi
# Copy release files and track them
if ! cp -f "$release_dir/libN.a" scratchpad && realpath scratchpad/libN.a >> "$log_file"; then
- echo "$(script_afp):: warning: no libN.a found" >&2
+ echo "$(script_fp):: warning: no libN.a found" >&2
fi
for file in "$release_dir"/*.lib.c; do
if cp -f "$file" cc; then
realpath "cc/$(basename "$file")" >> "$log_file"
else
- echo "$(script_afp):: warning: failed to copy $file" >&2
+ echo "$(script_fp):: warning: failed to copy $file" >&2
fi
else
- echo "$(script_afp):: warning: skipping non-regular file $file" >&2
+ echo "$(script_fp):: warning: skipping non-regular file $file" >&2
fi
done
-echo "$(script_afp) done."
+echo "$(script_fn) done."
# Input guards
env_must_be="tester/tool馃枆/env"
if [ "$ENV" != "$env_must_be" ]; then
- echo "$(script_afp):: error: must be run in the $env_must_be environment"
+ echo "$(script_fp):: error: must be run in the $env_must_be environment"
exit 1
fi
# Ensure log file exists and is not empty
if [ ! -s "$log_file" ]; then
- echo "$(script_afp):: no release log found, nothing to remove." >&2
+ echo "$(script_fp):: no release log found, nothing to remove." >&2
exit 0
fi
if [ -f "$file" ]; then
rm_na "$file"
else
- echo "$(script_afp):: warning: expected release file not found: $file" >&2
+ echo "$(script_fp):: warning: expected release file not found: $file" >&2
fi
done < "$log_file"
# Cleanup log file after successful removal
: > "$log_file"
-echo "$(script_afp) done."
+echo "$(script_fn) done."