refactoring N32
authorThomas Walker Lynch <eknp9n@reasoningtechnology.com>
Thu, 13 Feb 2025 15:06:18 +0000 (15:06 +0000)
committerThomas Walker Lynch <eknp9n@reasoningtechnology.com>
Thu, 13 Feb 2025 15:06:18 +0000 (15:06 +0000)
13 files changed:
developer/cc🖉/N32.lib.c [new file with mode: 0644]
developer/cc🖉/N_32.lib.c [deleted file]
developer/cc🖉/environment.h
developer/cc🖉/test_N32.cli.c [new file with mode: 0644]
developer/cc🖉/test_Natural_32_0.cli.c [deleted file]
developer/deprecated🖉/N_32_test.cli.c [new file with mode: 0644]
developer/deprecated🖉/test_Natural_32_0.cli.c [new file with mode: 0644]
developer/document🖉/Approach_to_headers.txt [new file with mode: 0644]
developer/document🖉/SectionedFileFormat.org [new file with mode: 0644]
developer/document🖉/test_framework.org [new file with mode: 0644]
developer/experiment/try_letters.c [new file with mode: 0644]
document🖉/library_usage.org [new file with mode: 0644]
document🖉/nomenclature.org [new file with mode: 0644]

diff --git a/developer/cc🖉/N32.lib.c b/developer/cc🖉/N32.lib.c
new file mode 100644 (file)
index 0000000..dd99de8
--- /dev/null
@@ -0,0 +1,453 @@
+/*
+  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.)
+
+*/
+
+#define N32·DEBUG
+
+#ifndef FACE
+#define N32·IMPLEMENTATION
+#define FACE
+#endif
+
+//--------------------------------------------------------------------------------
+// Interface
+
+#ifndef N32·FACE
+#define N32·FACE
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+//----------------------------------------
+// Instance Data (Declaration Only)
+
+typedef uint32_t Extent;
+typedef uint32_t Digit;
+
+typedef struct N32·T N32·T;
+
+extern N32·T *N32·zero;
+extern N32·T *N32·one;
+extern N32·T *N32·all_one_bit;
+extern N32·T *N32·lsb;
+extern N32·T *N32·msb;
+
+//----------------------------------------
+// Return/Error Status and handlers
+
+typedef enum{
+  N32·Status·ok = 0
+  ,N32·Status·overflow = 1
+  ,N32·Status·accumulator1_overflow = 2
+  ,N32·Status·carry = 3
+  ,N32·Status·borrow = 4
+  ,N32·Status·undefined_divide_by_zero = 5
+  ,N32·Status·undefined_modulus_zero = 6
+  ,N32·Status·gt_max_shift_count = 7
+  ,N32·Status·spill_eq_operand = 8 // not currently signaled, result will be spill value
+  ,N32·Status·one_word_product = 9
+  ,N32·Status·two_word_product = 10
+} N32·Status;
+
+typedef enum{
+  N32·Order_lt = -1
+  ,N32·Order_eq = 0
+  ,N32·Order_gt = 1
+} N32·Order;
+
+typedef N32·T *( *N32·Allocate_MemoryFault )(Extent);
+
+//----------------------------------------
+// Interface
+
+typedef struct{
+  N32·T *(*allocate_array)(Extent, N32·Allocate_MemoryFault);
+  void (*deallocate)(N32·T*);
+  void (*copy)(N32·T*, N32·T*);
+  void (*bit_and)(N32·T*, N32·T*, N32·T*);
+  void (*bit_or)(N32·T*, N32·T*, N32·T*);
+  void (*bit_complement)(N32·T*, N32·T*);
+  void (*bit_twos_complement)(N32·T*, N32·T*);
+  N32·Order (*compare)(N32·T*, N32·T*);
+  bool (*lt)(N32·T*, N32·T*);
+  bool (*gt)(N32·T*, N32·T*);
+  bool (*eq)(N32·T*, N32·T*);
+  bool (*eq_zero)(N32·T*);
+  N32·Status (*add)(N32·T*, N32·T*, N32·T*);
+  N32·Status (*subtract)(N32·T*, N32·T*, N32·T*);
+  N32·Status (*multiply)(N32·T*, N32·T*, N32·T*, N32·T*);
+  N32·Status (*divide)(N32·T*, N32·T*, N32·T*, N32·T*);
+  N32·Status (*modulus)(N32·T*, N32·T*, N32·T*);
+  N32·Status (*shift_left)(Extent, N32·T*, N32·T*, N32·T*);
+  N32·Status (*shift_right)(Extent, N32·T*, N32·T*, N32·T*);
+  N32·Status (*arithmetic_shift_right)(Extent, N32·T*, N32·T*);
+  N32·T* (*access)(N32·T*, Extent);
+  void (*from_uint32)(N32·T *destination ,uint32_t value);
+} N32·Λ;
+
+extern const N32·Λ N32·λ;
+
+#endif
+
+//--------------------------------------------------------------------------------
+// Implementation
+
+#ifdef N32·IMPLEMENTATION
+
+// this part goes into the library
+#ifndef LOCAL
+
+#include <stdarg.h>
+#include <stdlib.h>
+
+struct N32·T{
+  Digit d0;
+};
+
+N32·T N32·constant[4] = {
+{.d0 = 0},
+{.d0 = 1},
+{.d0 = ~(uint32_t)0},
+{.d0 = 1 << 31}
+};
+
+N32·T *N32·zero = &N32·constant[0];
+N32·T *N32·one = &N32·constant[1];
+N32·T *N32·all_one_bit = &N32·constant[2];
+N32·T *N32·msb = &N32·constant[3];
+N32·T *N32·lsb = &N32·constant[1];
+
+// the allocate an array of N32
+N32·T *N32·allocate_array( Extent extent ,N32·T *(*memory_fault)(Extent) ){
+  N32·T *instance = malloc((extent + 1) * sizeof(N32·T) );
+  if(!instance){
+    return memory_fault ? memory_fault(extent) : NULL;
+  }
+  return instance;
+}
+
+N32·T *N32·alloc_array_zero( Extent extent ,N32·T *(*memory_fault)(Extent) ){
+  N32·T *instance = calloc( extent + 1 ,sizeof(N32·T) );
+  if(!instance){
+    return memory_fault ? memory_fault(extent) : NULL;
+  }
+  return instance;
+}
+
+void N32·deallocate(N32·T *unencumbered){
+  free(unencumbered);
+}
+
+
+#endif
+
+// This part is included after the library user's code
+#ifdef LOCAL
+
+// instance
+
+struct N32·T{
+  Digit d0;
+};
+
+// temporary variables
+// making these LOCAL rather than reserving one block in the library is thread safe
+// allocating a block once is more efficient
+// library code writes these, they are not on the interface
+
+Local N32·T N32·t[4]
+
+
+// allocation 
+
+extern N32·T *N32·allocate_array(Extent, N32·Allocate_MemoryFault);
+extern N32·T *N32·alloc_array_zero(Extent, N32·Allocate_MemoryFault);
+extern void N32·deallocate(N32·T *);
+
+// so the user can access numbers in an array allocation
+Local N32·T* N32·access(N32·T *array ,Extent index){
+  return &array[index];
+}
+
+Local void N32·from_uint32(N32·T *destination ,uint32_t value){
+  if(destination == NULL) return;
+  destination->d0 = value;
+}
+
+// copy, convenience copy
+
+Local void N32·copy(N32·T *destination ,N32·T *source){
+  if(source == destination) return; // that was easy! 
+  *destination = *source;
+}
+
+Local void N32·set_to_zero(N32·T *instance){
+  instance->d0 = 0;
+}
+
+Local void N32·set_to_one(N32·T *instance){
+  instance->d0 = 1;
+}
+
+// bit operations
+
+Local void N32·bit_and(N32·T *result, N32·T *a, N32·T *b){
+  result->d0 = a->d0 & b->d0;
+}
+
+// result can be one of the operands
+Local void N32·bit_or(N32·T *result, N32·T *a, N32·T *b){
+  result->d0 = a->d0 | b->d0;
+}
+
+// result can the same as the operand
+Local void N32·bit_complement(N32·T *result, N32·T *a){
+  result->d0 = ~a->d0;
+}
+
+// result can the same as the operand
+Local void N32·bit_twos_complement(N32·T *result ,N32·T *a){
+  result->d0 = ~a->d0 + 1;
+}
+
+// test functions
+
+Local N32·Order N32·compare(N32·T *a, N32·T *b){
+  if(a->d0 < b->d0) return N32·Order_lt;
+  if(a->d0 > b->d0) return N32·Order_gt;
+  return N32·Order_eq;
+}
+
+Local bool N32·lt(N32·T *a ,N32·T *b){
+  return  a->d0 < b->d0;
+}    
+
+Local bool N32·gt(N32·T *a ,N32·T *b){
+  return  a->d0 > b->d0;
+}    
+
+Local bool N32·eq(N32·T *a ,N32·T *b){
+  return  a->d0 == b->d0;
+}    
+
+Local bool N32·eq_zero(N32·T *a){
+  return  a->d0 == 0;
+}    
+
+
+// arithmetic operations
+
+// For a large number of summands for the lower precision Natural implementations, for accumulate/add/sub, the 'overflow' operand could overflow and thus this routine will halt and return N32·Status·accumulator1_overflow
+//
+// When accumulator1 and accumulator0 point to the same location, the result is the accumulator1 value.
+Local N32·Status N32·accumulate(N32·T *accumulator1 ,N32·T *accumulator0 ,...){
+
+  va_list args;
+  va_start(args ,accumulator0);
+
+  uint64_t *sum = &accumulator0->d0;
+  uint64_t *carry = 0;
+  N32·T *current;
+
+  while( (current = va_arg(args ,N32·T *)) ){
+    *sum += current->d0;
+    if(*sum < current->d0){  // Accumulator1 into carry
+      (*carry)++;
+      if(*carry == 0){
+        va_end(args);
+        return N32·Status·accumulator1_overflow;
+      }
+    }
+  }
+  va_end(args);
+
+  // wipes out prior value of accumulator1
+  accumulator1->d0 = carry;
+
+  return N32·Status·ok;
+}
+
+Local N32·Status N32·add(N32·T *sum ,N32·T *a ,N32·T *b){
+  uint64_t result = (uint64_t)a->d0 + (uint64_t)b->d0;
+  sum->d0 = (uint32_t)result;
+  return (result >> 32) ? N32·Status·carry : N32·Status·ok;
+}
+
+Local bool N32·increment(N32·T *a){
+  a->d0++;
+  return a->d0 == 0;
+}
+
+Local N32·Status N32·subtract(N32·T *difference ,N32·T *a ,N32·T *b){
+  uint64_t diff = (uint64_t) a->d0 - (uint64_t) b->d0;
+  difference->d0 = (uint32_t)diff;
+  return (diff > a->d0) ? N32·Status·borrow : N32·Status·ok;
+}
+
+
+Local N32·Status N32·multiply(N32·T *product1 ,N32·T *product0 ,N32·T *a ,N32·T *b){
+  uint64_t product = (uint64_t)a->d0 * (uint64_t)b->d0;
+  product0->d0 = (uint32_t)product;
+  product1->d0 = (uint32_t)(product >> 32);
+
+  if(product1->d0 == 0) return N32·status·one_word_product;
+  return N32·Status·two_word_product;
+}
+
+Local N32·Status N32·divide(N32·T *remainder ,N32·T *quotient ,N32·T *a ,N32·T *b){
+  if(b->d0 == 0) return N32·Status·undefined_divide_by_zero; 
+
+  quotient->d0 = a->d0 / b->d0;
+  remainder->d0 = a->d0 - (quotient->d0 * b->d0);
+
+  return N32·Status·ok;
+}
+
+Local N32·Status N32·modulus(N32·T *remainder ,N32·T *a ,N32·T *b){
+  if(b->d0 == 0) return N32·Status·undefined_modulus_zero; 
+  uint32_t quotient = a->d0 / b->d0;
+  remainder->d0 = a->d0 - (quotient * b->d0);
+  return N32·Status·ok;
+}
+
+// bit motion
+
+typedef uint32_t (*ShiftOp)(uint32_t, uint32_t);
+
+Local uint32_t shift_left_op(uint32_t value, uint32_t amount){
+    return value << amount;
+}
+
+Local uint32_t shift_right_op(uint32_t value, uint32_t amount){
+    return value >> amount;
+}
+
+// modifies all three of its operands
+// in the case of duplicate operands this is the order: first modifies operand, then fill, then spill, 
+Local N32·Status N32·shift
+(
+ uint32_t shift_count
+ ,N32·T *spill
+ ,N32·T *operand
+ ,N32·T *fill
+ ,ShiftOp shift_op
+ ,ShiftOp complement_shift_op
+ ){
+
+  // If no result is needed, return immediately.
+  if(operand == NULL && spill == NULL) return N32·Status·ok;
+
+  // Treat NULL operand as zero.
+  if(operand == NULL){
+    operand = &N32·t[0];
+    N32·copy(operand, N32·zero);
+  }
+
+  // Shifting more than one word breaks our fill/spill model.
+  if(shift_count > 31) return N32·Status·gt_max_shift_count;
+
+  // The given operand is still required after it is modified, so we copy it.
+  N32·T *given_operand = &N32·t[1];
+  N32·copy(given_operand, operand);
+
+  // Perform the shift
+  operand->d0 = shift_op(given_operand->d0, shift_count);
+  if(fill != NULL){
+    fill->d0 = complement_shift_op(fill->d0, (32 - shift_count));
+    N32·bit_or(operand, operand, fill);
+  }
+  if(spill != NULL){
+    spill->d0 = shift_op(spill->d0, shift_count);
+    spill->d0 += complement_shift_op(given_operand->d0, (32 - shift_count));
+  }
+
+  return N32·Status·ok;
+}
+
+// Define concrete shift functions using valid C function pointers
+Local N32·Status 
+N32·shift_left(uint32_t shift_count, N32·T *spill, N32·T *operand, N32·T *fill){
+  return N32·shift(shift_count, spill, operand, fill, shift_left_op, shift_right_op);
+}
+
+Local N32·Status 
+N32·shift_right(uint32_t shift_count, N32·T *spill, N32·T *operand, N32·T *fill){
+  return N32·shift(shift_count, spill, operand, fill, shift_right_op, shift_left_op);
+}
+
+Local N32·Status 
+N32·arithmetic_shift_right(uint32_t shift_count, N32·T *operand, N32·T *spill){
+
+  // Guard against excessive shift counts
+  if(shift_count > 31) return N32·Status·gt_max_shift_count;
+
+  // A NULL operand is treated as zero
+  if(operand == NULL){
+    operand = &N32·t[0];
+    N32·copy(operand, N32·zero);
+  }
+
+  // Pick the fill value based on the sign bit
+  N32·T *fill = (operand->d0 & 0x80000000) ? N32·all_one_bit : N32·zero;
+
+  // Call shift_right with the appropriate fill
+  return N32·shift_right(shift_count, spill, operand, fill);
+}
+
+// an interface instance
+
+Local const N32·Λ N32·λ = {
+   .copy = N32·copy
+  ,.bit_and = N32·bit_and
+  ,.bit_or = N32·bit_or
+  ,.bit_complement = N32·bit_complement
+  ,.bit_twos_complement = N32·bit_twos_complement
+  ,.compare = N32·compare
+  ,.lt = N32·lt
+  ,.gt = N32·gt
+  ,.eq = N32·eq
+  ,.eq_zero = N32·eq_zero
+  ,.eq_one = N32·eq_one
+  ,.accumulate = N32·accumulate
+  ,.add = N32·add
+  ,.next = N32·next
+  ,.subtract = N32·subtract
+  ,.multiply = N32·multiply
+  ,.divide = N32·divide
+  ,.modulus = N32·modulus
+  ,.shift_left = N32·shift_left
+  ,.shift_right = N32·shift_right
+  ,.arithmetic_shift_right = N32·arithmetic_shift_right
+  ,.allocate_array = N32·allocate_array
+  ,.allocate_array_zero = N32·alloc_array_zero
+  ,.deallocate = N32·deallocate
+  ,.access = N32·access
+  ,.from_uint32 = N32·from_uint32
+};
+
+#endif
+
+#endif
diff --git a/developer/cc🖉/N_32.lib.c b/developer/cc🖉/N_32.lib.c
deleted file mode 100644 (file)
index ac2f37d..0000000
+++ /dev/null
@@ -1,464 +0,0 @@
-/*
-  N_32 - 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.)
-
-*/
-
-#define N_32·DEBUG
-
-#ifndef IFACE
-#define N_32·IMPLEMENTATION
-#define IFACE
-#endif
-
-//--------------------------------------------------------------------------------
-// Interface
-
-#ifndef N_32·IFACE
-#define N_32·IFACE
-
-#include <stdint.h>
-#include <stdbool.h>
-#include <stdarg.h>
-#include <stdlib.h>
-
-//----------------------------------------
-// Instance Data (Declaration Only)
-
-typedef uint32_t Extent;
-typedef uint32_t Digit;
-
-typedef struct N_32 N_32;
-
-extern N_32 *N_32·zero;
-extern N_32 *N_32·one;
-extern N_32 *N_32·all_one_bit;
-extern N_32 *N_32·lsb;
-extern N_32 *N_32·msb;
-
-//----------------------------------------
-// Return/Error Status and handlers
-
-typedef enum{
-  N_32·Status·ok = 0
-  ,N_32·Status·overflow = 1
-  ,N_32·Status·accumulator1_overflow = 2
-  ,N_32·Status·carry = 3
-  ,N_32·Status·borrow = 4
-  ,N_32·Status·undefined_divide_by_zero = 5
-  ,N_32·Status·undefined_modulus_zero = 6
-  ,N_32·Status·gt_max_lsb_index = 7
-  ,N_32·Status·spill_eq_operand = 8 // not currently signaled, result will be spill value
-  ,N_32·Status·one_word_product = 9
-  ,N_32·Status·two_word_product = 10
-} N_32·Status;
-
-typedef enum{
-  N_32·Order_lt = -1
-  ,N_32·Order_eq = 0
-  ,N_32·Order_gt = 1
-} N_32·Order;
-
-typedef N_32 *( *N_32·Allocate_MemoryFault )(Extent);
-
-//----------------------------------------
-// Interface
-
-typedef struct{
-  N_32 *( *allocate )(Extent, N_32·Allocate_MemoryFault);
-  void ( *deallocate )(N_32 *);
-  void ( *copy )(N_32 *, N_32 *);
-  void ( *bit_and )(N_32 *, N_32 *, N_32 *);
-  void ( *bit_or )(N_32 *, N_32 *, N_32 *);
-  void ( *bit_complement )(N_32 *, N_32 *);
-  void ( *bit_twos_complement )(N_32 *, N_32 *);
-  N_32·Order ( *compare )(N_32 *, N_32 *);
-  bool ( *lt )(N_32 *, N_32 *);
-  bool ( *gt )(N_32 *, N_32 *);
-  bool ( *eq )(N_32 *, N_32 *);
-  N_32·Status ( *add )(N_32 *, N_32 *, N_32 *);
-  N_32·Status ( *subtract )(N_32 *, N_32 *, N_32 *);
-  N_32·Status ( *multiply )(N_32 *, N_32 *, N_32 *, N_32 *);
-  N_32·Status ( *divide )(N_32 *, N_32 *, N_32 *, N_32 *);
-  void ( *shift_left )(Extent, N_32 *, N_32 *, N_32 *);
-  void ( *shift_right )(Extent, N_32 *, N_32 *, N_32 *);
-} N_32·Interface;
-
-extern const N_32·Interface N_32·interface;
-
-#endif
-
-//--------------------------------------------------------------------------------
-// Implementation
-
-#ifdef N_32·IMPLEMENTATION
-
-// this part goes into the library
-#ifndef LOCAL
-
-#include <stdarg.h>
-#include <stdlib.h>
-
-struct N_32{
-  Digit d0;
-};
-
-N_32 N_32·constant[4] ={
- {.d0 = 0},
- {.d0 = 1},
- {.d0 = ~(uint32_t)0},
- {.d0 = 1 << 31}
-};
-
-N_32 *N_32·zero = &N_32·constant[0];
-N_32 *N_32·one = &N_32·constant[1];
-N_32 *N_32·all_one_bit = &N_32·constant[2];
-N_32 *N_32·msb = &N_32·constant[3];
-N_32 *N_32·lsb = &N_32·constant[1];
-
-// the allocate an array of N_32
-N_32 *N_32·allocate_array( Extent extent ,N_32 *(*memory_fault)(Extent) ){
-  N_32 *instance = malloc((extent + 1) * sizeof(N_32) );
-  if(!instance){
-    return memory_fault ? memory_fault(extent) : NULL;
-  }
-  return instance;
-}
-
-N_32 *N_32·alloc_array_zero( Extent extent ,N_32 *(*memory_fault)(Extent) ){
-  N_32 *instance = calloc( extent + 1 ,sizeof(N_32) );
-  if(!instance){
-    return memory_fault ? memory_fault(extent) : NULL;
-  }
-  return instance;
-}
-
-void N_32·deallocate(N_32 *unencumbered){
-  free(unencumbered);
-}
-
-
-#endif
-
-// This part is included after the library user's code
-#ifdef LOCAL
-
-// instance
-
-struct N_32{
-  Digit d0;
-};
-
-// temporary variables
-// making these LOCAL rather than reserving one block in the library is thread safe
-// allocating a block once is more efficient
-// library code writes these, they are not on the interface
-
-Local N_32 N_32·t[4]
-
-
-// allocation 
-
-extern N_32 *N_32·allocate_array(Extent, N_32·Allocate_MemoryFault);
-extern N_32 *N_32·alloc_array_zero(Extent, N_32·Allocate_MemoryFault);
-extern void N_32·deallocate(N_32 *);
-
-// copy, convenience copy
-
-Local void N_32·copy(N_32 *destination ,N_32 *source){
-  if(source == destination) return; // that was easy! 
-  *destination = *source;
-}
-
-Local void N_32·set_to_zero(N_32 *instance){
-  instance->d0 = 0;
-}
-
-Local void N_32·set_to_one(N_32 *instance){
-  instance->d0 = 1;
-}
-
-// bit operations
-
-Local void N_32·bit_and(N_32 *result, N_32 *a, N_32 *b){
-  result->d0 = a->d0 & b->d0;
-}
-
-// result can be one of the operands
-Local void N_32·bit_or(N_32 *result, N_32 *a, N_32 *b){
-  result->d0 = a->d0 | b->d0;
-}
-
-// result can the same as the operand
-Local void N_32·bit_complement(N_32 *result, N_32 *a){
-  result->d0 = ~a->d0;
-}
-
-// result can the same as the operand
-Local void N_32·bit_twos_complement(N_32 *result ,N_32 *a){
-  result->d0 = ~a->d0 + 1;
-}
-
-// test functions
-
-Local N_32·Order N_32·compare(N_32 *a, N_32 *b){
-  if (a->d0 < b->d0) return N_32·Order_lt;
-  if (a->d0 > b->d0) return N_32·Order_gt;
-  return N_32·Order_eq;
-}
-
-Local bool N_32·lt(N_32 *a ,N_32 *b){
-  return  a->d0 < b->d0;
-}    
-
-Local bool N_32·gt(N_32 *a ,N_32 *b){
-  return  a->d0 > b->d0;
-}    
-
-Local bool N_32·eq(N_32 *a ,N_32 *b){
-  return  a->d0 == b->d0;
-}    
-
-Local bool N_32·eq_zero(N_32 *a){
-  return  a->d0 == 0;
-}    
-
-
-// arithmetic operations
-
-// For a large number of summands for the lower precision Natural implementations, for accumulate/add/sub, the 'overflow' operand could overflow and thus this routine will halt and return N_32·Status·accumulator1_overflow
-//
-// When accumulator1 and accumulator0 point to the same location, the result is the accumulator1 value.
-Local N_32·Status N_32·accumulate(N_32 *accumulator1 ,N_32 *accumulator0 ,...){
-
-  va_list args;
-  va_start(args ,accumulator0);
-
-  uint64_t *sum = &accumulator0->d0;
-  uint64_t *carry = 0;
-  N_32 *current;
-
-  while( (current = va_arg(args ,N_32 *)) ){
-    *sum += current->d0;
-    if(*sum < current->d0){  // Accumulator1 into carry
-      (*carry)++;
-      if(*carry == 0){
-        va_end(args);
-        return N_32·Status·accumulator1_overflow;
-      }
-    }
-  }
-  va_end(args);
-
-  // wipes out prior value of accumulator1
-  accumulator1->d0 = carry;
-
-  return N_32·Status·ok;
-}
-
-Local N_32·Status N_32·add(N_32 *sum ,N_32 *a ,N_32 *b){
-  uint64_t result = (uint64_t)a->d0 + (uint64_t)b->d0;
-  sum->d0 = (uint32_t)result;
-  return (result >> 32) ? N_32·Status·carry : N_32·Status·ok;
-}
-
-Local bool N_32·increment(N_32 *a){
-  a->d0++;
-  return a->d0 == 0;
-}
-
-Local N_32·Status N_32·subtract(N_32 *difference ,N_32 *a ,N_32 *b){
-  uint64_t diff = (uint64_t)a->d0 - (uint64_t)b->d0;
-  difference->d0 = (uint32_t)diff;
-  return (diff > a->d0) ? N_32·Status·borrow : N_32·Status·ok;
-}
-
-
-Local N_32·Status N_32·multiply(N_32 *product1 ,N_32 *product0 ,N_32 *a ,N_32 *b){
-  uint64_t product = (uint64_t)a->d0 * (uint64_t)b->d0;
-  product0->d0 = (uint32_t)product;
-  product1->d0 = (uint32_t)(product >> 32);
-
-  if(product1->d0 == 0) return N_32·status·one_word_product;
-  return N_32·status·two_word_product;
-}
-
-Local N_32·Status N_32·divide(N_32 *remainder ,N_32 *quotient ,N_32 *a ,N_32 *b){
-  if(b->d0 == 0) return N_32·Status·undefined_divide_by_zero; 
-
-  quotient->d0 = a->d0 / b->d0;
-  remainder->d0 = a->d0 - (quotient->d0 * b->d0);
-
-  return N_32·Status·ok;
-}
-
-Local N_32·Status N_32·modulus(N_32 *remainder ,N_32 *a ,N_32 *b){
-  if(b->d0 == 0) return N_32·Status·undefined_modulus_zero; 
-  uint32_t quotient = a->d0 / b->d0;
-  remainder->d0 = a->d0 - (quotient * b->d0);
-  return N_32·Status·ok;
-}
-
-// bit motion
-
-// This is a bit shift, not a word shift. If you have a general shift count, shift words by
-// the div of the shift count, then call this with the modulus 32 of the shift count.
-//
-// If spill and operand or fill are the same value, the result is the spill (for both).
-//
-// `new_lsb_index` aka the `shift_count`
-// shifts a binary number the lsb bit index to as far as 31 
-// NULL operand treated as zero
-Local N_32·Status N_32·shift_left
-  (
-   uint32_t new_lsb_index
-   ,N_32 *spill
-   ,N_32 *operand
-   ,N_32 *fill
-   ){
-
-  // If the caller doesn't want a result back, we are all done.
-  if(operand == NULL && spill == NULL) return N_32·Status·ok;
-
-  #ifdef N_32·DEBUG
-  if( spill == operand ){
-    fprintf(stderr, "N_32·shift_left spill == operand\n");
-  }
-  #endif
-
-  // For the sake of setting spill, we will treat a NULL operand as zero.
-  if(operand == NULL){
-    operand = &N_32·t[0];
-    N_32·copy(operand ,N_32·zero);
-  }
-
-  // Shifting more than one word breaks our fill/spill model.
-  if(new_lsb_index > 31) return N_32·Status·gt_max_lsb_index;
-
-  // The given operand is still required after it is modified, so we copy it.
-  N_32 *given_operand = &N_32·t[1];
-  N_32·copy(given_operand ,operand);
-
-  // spill is overwritten with a new value
-  operand->d0 = given_operand->d0 << new_lsb_index;
-  if(fill != NULL){
-    fill->d0 = fill->d0 >> (32 - new_lsb_index);
-    N_32·bit_or(operand ,operand ,fill);
-  }
-  if(spill != NULL){
-    spill->d0 = spill->d0 << new_lsb_index;
-    spill->d0 += given_operand->d0 >> (32 - new_lsb_index);
-  }
-  return N_32·Status·ok;
-}
-
-Local N_32·Status N_32·shift_right
-  (
-   uint32_t msb_index_offset
-   ,N_32 *spill
-   ,N_32 *operand
-   ,N_32 *fill
-   ){
-
-  // If the caller doesn't want a result back, we are all done.
-  if(operand == NULL && spill == NULL) return N_32·Status·ok;
-
-  // For the sake of setting spill, we will treat a NULL operand as zero.
-  if(operand == NULL){
-    operand = &N_32·t[0];
-    N_32·copy(operand ,N_32·zero);
-  }
-
-  // Shifting more than one word breaks our fill/spill model.
-  if(msb_index_offset > 31) return N_32·Status·gt_max_lsb_index;
-
-  // In theory, fill should not have any bits in common with the shifted operand.
-  #ifdef N_32·DEBUG
-  if( !N_32·eq_zero(fill->d0 << (32 - msb_index_offset)) ){
-    fprintf(stderr, "N_32·shift_right fill value overlaps with shifted operand\n");
-  }
-  #endif
-
-  // The given operand is still required after it is modified, so we copy it.
-  N_32 *given_operand = &N_32·t[1];
-  N_32·copy(given_operand ,operand);
-
-  // spill is overwritten with a new value
-  operand->d0 = given_operand->d0 >> msb_index_offset;
-  if(fill != NULL){
-    fill->d0 = fill->d0 << (32 - msb_index_offset);
-    N_32·bit_or(operand ,operand ,fill);
-  }
-  if(spill != NULL){
-    spill->d0 = spill->d0 >> msb_index_offset;
-    spill->d0 += given_operand->d0 << (32 - msb_index_offset);
-  }
-  return N_32·Status·ok;
-}
-
-
-Local void N_32·arithmetic_shift_right(Extent shift, N_32 *operand, N_32 *spill) {
-
-  // caller wants us to do nothing, a little strange, but Ok ..
-  if (operand == NULL || spill == NULL) return N_32·Status·ok;
-
-  // check if we are shifting in ones or zeros
-  N_32·bit_and(&N_32·t[0], operand, N_32·msb); 
-  N_32 *source_pt = N_32·eq_zero(&N_32·t[0]) ? N_32·zero : N_32·all_one_bit;
-
-  // uses `t[2]` because shift_right uses `t[0]` and `t[1]`
-  N_32·copy(&N_32·t[2], source_pt);
-  N_32·shift_right(shift, &N_32·t[2], operand, spill);
-}
-
-// an interface instance
-
-Local const N_32·Interface N_32·interface = {
-   .copy = N_32·copy
-  ,.bit_and = N_32·bit_and
-  ,.bit_or = N_32·bit_or
-  ,.bit_complement = N_32·bit_complement
-  ,.bit_twos_complement = N_32·bit_twos_complement
-  ,.compare = N_32·compare
-  ,.lt = N_32·lt
-  ,.gt = N_32·gt
-  ,.eq = N_32·eq
-  ,.eq_zero = N_32·eq_zero
-  ,.eq_one = N_32·eq_one
-  ,.accumulate = N_32·accumulate
-  ,.add = N_32·add
-  ,.next = N_32·next
-  ,.subtract = N_32·subtract
-  ,.multiply = N_32·multiply
-  ,.divide = N_32·divide
-  ,.modulus = N_32·modulus
-  ,.shift_left = N_32·shift_left
-  ,.shift_right = N_32·shift_right
-  ,.arithmetic_shift_right = N_32·arithmetic_shift_right
-  ,.allocate_array = N_32·allocate_array
-  ,.allocate_array_zero = N_32·alloc_array_zero
-  ,.deallocate = N_32·deallocate
-};
-
-#endif
-
-#endif
index d82898f..cdea83c 100644 (file)
@@ -1,6 +1,5 @@
 #ifndef Mpblock·ENVIRONMENT_H
 #define Mpblock·ENVIRONMENT_H
 
-  #define FREE(pt) free(pt); (pt) = NULL;
 
 #endif
diff --git a/developer/cc🖉/test_N32.cli.c b/developer/cc🖉/test_N32.cli.c
new file mode 100644 (file)
index 0000000..6e79571
--- /dev/null
@@ -0,0 +1,125 @@
+#include <stdio.h>
+#include <stdbool.h>
+#include <signal.h>
+#include <setjmp.h>
+
+// Enable interface section
+#define FACE
+#include "N32.lib.c"
+#undef FACE
+
+// Jump buffer for signal handling
+static sigjmp_buf jump_buffer;
+
+// Signal handler for catching fatal errors
+void signal_handler(int signal){
+  siglongjmp(jump_buffer ,1); // Jump back to test_head on error
+}
+
+// Test function prototypes
+bool test_copy();
+bool test_bitwise_operations();
+bool test_comparisons();
+bool test_arithmetic();
+bool test_shifts();
+
+// Test array (null-terminated)
+typedef bool (*TestFunction)();
+typedef struct{
+  TestFunction function;
+  const char *name;
+}TestEntry;
+
+TestEntry test_list[] = {
+   {test_copy ,"test_copy"}
+  ,{test_bitwise_operations ,"test_bitwise_operations"}
+  ,{test_comparisons ,"test_comparisons"}
+  ,{test_arithmetic ,"test_arithmetic"}
+  ,{test_shifts ,"test_shifts"}
+  ,{NULL ,NULL}  // Null termination
+};
+
+// The test runner
+int test_head(){
+  int pass_count = 0;
+  int fail_count = 0;
+
+  // Set up signal handlers
+  signal(SIGSEGV ,signal_handler);  // Catch segmentation faults
+  signal(SIGFPE ,signal_handler);   // Catch floating point errors
+  signal(SIGABRT ,signal_handler);  // Catch abort() calls
+
+  for(TestEntry *entry = test_list; entry->function != NULL; entry++){
+    if( sigsetjmp(jump_buffer ,1) == 0 ){
+      // Run the test normally
+      if( !entry->function() ){
+        printf("Failed: %s\n" ,entry->name);
+        fail_count++;
+      }else{
+        pass_count++;
+      }
+    }else{
+      // If a signal was caught
+      printf("Failed due to signaling: %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;
+}
+
+// Main function
+int main(int argc ,char **argv){
+  return test_head();
+}
+
+//------------------------------------------------------------------------------
+// Test Implementations
+//------------------------------------------------------------------------------
+
+bool test_copy(){
+  // Allocate memory
+  N32·T *array = N32·λ.allocate_array(2 ,NULL);
+  if( !array ) return false;
+
+  // Access elements via access function
+  N32·T *a = N32·λ.access(array ,0);
+  N32·T *b = N32·λ.access(array ,1);
+
+  // Assign value and copy
+  N32·λ.from_uint32(a ,42);
+  N32·λ.copy(b ,a);
+
+  bool success = ( N32·λ.compare(b ,a) == N32·Order_eq );
+  N32·λ.deallocate(array);
+  return success;
+}
+
+bool test_arithmetic(){
+  // Allocate memory
+  N32·T *array = N32·λ.allocate_array(3 ,NULL);
+  if( !array ) return false;
+
+  N32·T *a = N32·λ.access(array ,0);
+  N32·T *b = N32·λ.access(array ,1);
+  N32·T *result = N32·λ.access(array ,2);
+
+  N32·λ.from_uint32(a ,20);
+  N32·λ.from_uint32(b ,22);
+
+  if( N32·λ.add(result ,a ,b) != N32·Status·ok ) return false;
+  if( N32·λ.compare(result ,N32·λ.access(array ,0)) != N32·Order_gt ) return false;
+
+  if( N32·λ.subtract(result ,b ,a) != N32·Status·ok ) return false;
+  if( N32·λ.compare(result ,N32·λ.access(array ,0)) != N32·Order_lt ) return false;
+
+  N32·λ.deallocate(array);
+  return true;
+}
+
+// Include the local section of N32.lib.c for testing
+#define LOCAL
+#include "N32.lib.c"
+#undef LOCAL
diff --git a/developer/cc🖉/test_Natural_32_0.cli.c b/developer/cc🖉/test_Natural_32_0.cli.c
deleted file mode 100644 (file)
index 2c344e7..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-
-#include "environment.h"
-#include <stdio.h>
-#include <setjmp.h>
-#include <signal.h>
-
-#define IFACE
-#include "Natural_32.lib.c"
-
-#define TEST_COUNT 10  // Adjust as needed
-
-jmp_buf test_env;
-const char *current_test = NULL;
-
-void signal_handler(int sig){
-  printf("Failed due to Exception: %s (Signal %d)\n", current_test, sig);
-  longjmp(test_env, 1);
-}
-
-int main(void){
-  bool test_results[TEST_COUNT] = {false};
-  const char *test_names[TEST_COUNT] = {
-    "Addition",
-    "Subtraction",
-    "Multiplication",
-    "Division",
-    "Modulus",
-    "Shift Left",
-    "Shift Right",
-    "Comparison",
-    "Complement",
-    "Two's Complement"
-  };
-
-  int pass_count = 0, fail_count = 0;
-  bool *test_ptr = test_results;
-  const char **name_ptr = test_names;
-
-  // Install signal handler
-  signal(SIGFPE, signal_handler);
-  signal(SIGSEGV, signal_handler);
-  signal(SIGABRT, signal_handler);
-
-  Natural_32 a, b, result, overflow;
-  Natural_32·set_to_zero(&a);
-  Natural_32·set_to_one(&b);
-
-  // Macro to run tests with proper failure messaging
-  #define RUN_TEST(expr) \
-    current_test = *name_ptr; \
-    if(setjmp(test_env) == 0){ \
-      if(expr){ \
-        *test_ptr++ = true; \
-        pass_count++; \
-      } else { \
-        printf("Failed due to Bad Return Value: %s\n", *name_ptr); \
-        *test_ptr++ = false; \
-        fail_count++; \
-      } \
-    } else { \
-      *test_ptr++ = false; \
-      fail_count++; \
-    } \
-    name_ptr++;
-
-  RUN_TEST(Natural_32·add(&result, &a, &b) == Natural_32·Status·ok && result.d0 == 1);
-  RUN_TEST(Natural_32·subtract(&result, &b, &a) == Natural_32·Status·ok && result.d0 == 1);
-  RUN_TEST(Natural_32·multiply(&overflow, &result, &b, &b) == Natural_32·Status·ok && result.d0 == 1 && overflow.d0 == 0);
-  RUN_TEST(Natural_32·divide(&result, &overflow, &b, &b) == Natural_32·Status·ok && result.d0 == 1 && overflow.d0 == 0);
-  RUN_TEST(Natural_32·modulus(&result, &b, &b) == Natural_32·Status·ok && result.d0 == 0);
-  
-  Natural_32·shift_left(1, &overflow, &result, &b);
-  RUN_TEST(result.d0 == 2 && overflow.d0 == 0);
-
-  Natural_32·shift_right(1, &b, &result, &overflow);
-  RUN_TEST(result.d0 == 0 && overflow.d0 == 1);
-
-  RUN_TEST(Natural_32·compare(&a, &b) == Natural_32·Order·lt);
-  
-  Natural_32·complement(&result, &a);
-  RUN_TEST(result.d0 == ~0);
-
-  Natural_32·twos_complement(&result, &b);
-  RUN_TEST(result.d0 == (uint32_t)(-1));
-
-  printf("Pass: %d, Fail: %d\n", pass_count, fail_count);
-  return fail_count > 0 ? 1 : 0;
-}
diff --git a/developer/deprecated🖉/N_32_test.cli.c b/developer/deprecated🖉/N_32_test.cli.c
new file mode 100644 (file)
index 0000000..5cb2d2e
--- /dev/null
@@ -0,0 +1,118 @@
+#include <stdio.h>
+#include <stdbool.h>
+#include "N_32.lib.h"  // Include the module under test
+
+// Test function prototypes
+bool test_copy();
+bool test_bitwise_operations();
+bool test_comparisons();
+bool test_arithmetic();
+bool test_shifts();
+
+// Test array (null-terminated)
+typedef bool (*TestFunction)();
+typedef struct {
+    TestFunction function;
+    const char *name;
+} TestEntry;
+
+TestEntry test_list[] = {
+    { test_copy, "test_copy" },
+    { test_bitwise_operations, "test_bitwise_operations" },
+    { test_comparisons, "test_comparisons" },
+    { test_arithmetic, "test_arithmetic" },
+    { test_shifts, "test_shifts" },
+    { NULL, NULL }  // Null termination
+};
+
+// The test runner
+int test_head() {
+    int pass_count = 0;
+    int fail_count = 0;
+
+    for (TestEntry *entry = test_list; entry->function != NULL; entry++) {
+        if (!entry->function()) {
+            printf("Failed: %s\n", entry->name);
+            fail_count++;
+        } else {
+            pass_count++;
+        }
+    }
+
+    printf("Tests passed: %d\n", pass_count);
+    printf("Tests failed: %d\n", fail_count);
+    return (fail_count == 0) ? 0 : 1;
+}
+
+// Main function
+int main(int argc, char **argv) {
+    return test_head();
+}
+
+//------------------------------------------------------------------------------
+// Test Implementations
+//------------------------------------------------------------------------------
+
+bool test_copy() {
+    N_32 a = { .d0 = 42 };
+    N_32 b;
+    N_32·copy(&b, &a);
+    return b.d0 == 42;
+}
+
+bool test_bitwise_operations() {
+    N_32 a = { .d0 = 0b101010 };
+    N_32 b = { .d0 = 0b010101 };
+    N_32 result;
+
+    N_32·bit_and(&result, &a, &b);
+    if (result.d0 != 0b000000) return false;
+
+    N_32·bit_or(&result, &a, &b);
+    if (result.d0 != 0b111111) return false;
+
+    N_32·bit_complement(&result, &a);
+    if (result.d0 != ~0b101010) return false;
+
+    return true;
+}
+
+bool test_comparisons() {
+    N_32 a = { .d0 = 42 };
+    N_32 b = { .d0 = 42 };
+    N_32 c = { .d0 = 24 };
+
+    if (!N_32·eq(&a, &b)) return false;
+    if (N_32·eq(&a, &c)) return false;
+    if (!N_32·lt(&c, &a)) return false;
+    if (!N_32·gt(&a, &c)) return false;
+
+    return true;
+}
+
+bool test_arithmetic() {
+    N_32 a = { .d0 = 20 };
+    N_32 b = { .d0 = 22 };
+    N_32 result;
+
+    if (N_32·add(&result, &a, &b) != N_32·Status·ok) return false;
+    if (result.d0 != 42) return false;
+
+    if (N_32·subtract(&result, &b, &a) != N_32·Status·ok) return false;
+    if (result.d0 != 2) return false;
+
+    return true;
+}
+
+bool test_shifts() {
+    N_32 value = { .d0 = 1 };
+    N_32 spill;
+    
+    if (N_32·shift_left(1, &spill, &value, NULL) != N_32·Status·ok) return false;
+    if (value.d0 != 2) return false;
+    
+    if (N_32·shift_right(1, &spill, &value, NULL) != N_32·Status·ok) return false;
+    if (value.d0 != 1) return false;
+
+    return true;
+}
diff --git a/developer/deprecated🖉/test_Natural_32_0.cli.c b/developer/deprecated🖉/test_Natural_32_0.cli.c
new file mode 100644 (file)
index 0000000..2c344e7
--- /dev/null
@@ -0,0 +1,88 @@
+
+#include "environment.h"
+#include <stdio.h>
+#include <setjmp.h>
+#include <signal.h>
+
+#define IFACE
+#include "Natural_32.lib.c"
+
+#define TEST_COUNT 10  // Adjust as needed
+
+jmp_buf test_env;
+const char *current_test = NULL;
+
+void signal_handler(int sig){
+  printf("Failed due to Exception: %s (Signal %d)\n", current_test, sig);
+  longjmp(test_env, 1);
+}
+
+int main(void){
+  bool test_results[TEST_COUNT] = {false};
+  const char *test_names[TEST_COUNT] = {
+    "Addition",
+    "Subtraction",
+    "Multiplication",
+    "Division",
+    "Modulus",
+    "Shift Left",
+    "Shift Right",
+    "Comparison",
+    "Complement",
+    "Two's Complement"
+  };
+
+  int pass_count = 0, fail_count = 0;
+  bool *test_ptr = test_results;
+  const char **name_ptr = test_names;
+
+  // Install signal handler
+  signal(SIGFPE, signal_handler);
+  signal(SIGSEGV, signal_handler);
+  signal(SIGABRT, signal_handler);
+
+  Natural_32 a, b, result, overflow;
+  Natural_32·set_to_zero(&a);
+  Natural_32·set_to_one(&b);
+
+  // Macro to run tests with proper failure messaging
+  #define RUN_TEST(expr) \
+    current_test = *name_ptr; \
+    if(setjmp(test_env) == 0){ \
+      if(expr){ \
+        *test_ptr++ = true; \
+        pass_count++; \
+      } else { \
+        printf("Failed due to Bad Return Value: %s\n", *name_ptr); \
+        *test_ptr++ = false; \
+        fail_count++; \
+      } \
+    } else { \
+      *test_ptr++ = false; \
+      fail_count++; \
+    } \
+    name_ptr++;
+
+  RUN_TEST(Natural_32·add(&result, &a, &b) == Natural_32·Status·ok && result.d0 == 1);
+  RUN_TEST(Natural_32·subtract(&result, &b, &a) == Natural_32·Status·ok && result.d0 == 1);
+  RUN_TEST(Natural_32·multiply(&overflow, &result, &b, &b) == Natural_32·Status·ok && result.d0 == 1 && overflow.d0 == 0);
+  RUN_TEST(Natural_32·divide(&result, &overflow, &b, &b) == Natural_32·Status·ok && result.d0 == 1 && overflow.d0 == 0);
+  RUN_TEST(Natural_32·modulus(&result, &b, &b) == Natural_32·Status·ok && result.d0 == 0);
+  
+  Natural_32·shift_left(1, &overflow, &result, &b);
+  RUN_TEST(result.d0 == 2 && overflow.d0 == 0);
+
+  Natural_32·shift_right(1, &b, &result, &overflow);
+  RUN_TEST(result.d0 == 0 && overflow.d0 == 1);
+
+  RUN_TEST(Natural_32·compare(&a, &b) == Natural_32·Order·lt);
+  
+  Natural_32·complement(&result, &a);
+  RUN_TEST(result.d0 == ~0);
+
+  Natural_32·twos_complement(&result, &b);
+  RUN_TEST(result.d0 == (uint32_t)(-1));
+
+  printf("Pass: %d, Fail: %d\n", pass_count, fail_count);
+  return fail_count > 0 ? 1 : 0;
+}
diff --git a/developer/document🖉/Approach_to_headers.txt b/developer/document🖉/Approach_to_headers.txt
new file mode 100644 (file)
index 0000000..c929c4d
--- /dev/null
@@ -0,0 +1,46 @@
+✅ Benefits of the Approach
+Prevents Header/Implementation Mismatch
+
+With separate .h and .c files, it's easy for a developer to update one but forget the other.
+Your #define IFACE / #define LOCAL approach guarantees the interface and implementation always match.
+Improves Code Discovery
+
+Everything relevant to N_32 is in one place, avoiding the “where is this function actually defined?” problem.
+Easier for new programmers to understand a module without hunting through multiple files.
+Reduces Compilation Dependencies
+
+Traditional headers require careful include guards (#ifndef, #define, #endif), and changes to a .h file often trigger unnecessary recompilations across the whole project.
+Here, only the interface section is parsed where needed without polluting translation units.
+Encapsulates Local Code Cleanly
+
+The LOCAL section is truly private—functions that should not be exported remain invisible to the rest of the program.
+This avoids accidental linking to private helper functions.
+Better Optimizations
+
+The optimizer sees everything within a single .c file.
+It inlines functions, eliminates redundant code, and avoids unnecessary function calls more effectively than in a traditional header+implementation split.
+This is especially useful for compiler-assisted optimizations like constant propagation and dead code elimination.
+Encourages Reusable Programs
+
+Your philosophy of keeping main() only as an argument parser & function caller means that:
+Every program can be called as a function from another program.
+Testing frameworks and other programs can reuse code easily without needing to fork process calls.
+🧐 Any Downsides?
+May be unfamiliar to some developers
+
+Most C programmers expect .h + .c files.
+However, once they understand why this works, they'll likely appreciate the clarity.
+Can’t precompile interface headers (.h.gch)
+
+Some build systems optimize C++ headers with precompiled headers (PCH), but in C, this is less of an issue.
+Requires Careful #define Handling
+
+If a programmer forgets to #define LOCAL before including the file for a .cli.c, tests might silently lack static functions.
+A well-placed #error directive (#ifndef LOCAL) could help catch this early.
+🚀 Overall Verdict
+Your approach is engineered for correctness, clarity, and optimization.
+It reduces mistakes, eliminates unnecessary indirections, and streamlines testing & debugging.
+
+Would I use it? Absolutely.
+Would I teach it? Yes, but with an explanation.
+Would I want a make-based project full of fragmented .h files again? Not after this. 😆
diff --git a/developer/document🖉/SectionedFileFormat.org b/developer/document🖉/SectionedFileFormat.org
new file mode 100644 (file)
index 0000000..46710ee
--- /dev/null
@@ -0,0 +1,35 @@
+* Sectioned Single-File Format
+  The sectioned file format provides a structured way to define a library,
+  keeping all relevant code in a single file while ensuring proper separation
+  between interface, implementation, and static definitions.
+
+** Structure
+   The source file is divided into three sections:
+
+   - *Interface*: Enabled by defining `IFACE` before including the file.
+   - *Implementation*: Enabled when neither `IFACE` nor `LOCAL` is defined.
+   - *Local (Static) Implementation*: Enabled by defining `LOCAL` before including the file.
+
+** Benefits
+   - **Avoids Split Headers and Source Files**: Eliminates mismatches between `.h` and `.c` files.
+   - **Improves Compiler Optimization**: The compiler has full visibility of static functions.
+   - **Reduces File Clutter**: A single source file contains everything.
+   - **Ensures Correct Compilation**: The build system automatically compiles the correct sections.
+
+** Usage
+   - To include the interface in a `.cli.c` file:
+
+     #+begin_src c
+       #define IFACE
+       #include "module.lib.c"
+       #undef IFACE
+     #+end_src
+
+   - To include the local static implementation:
+
+     #+begin_src c
+       #define LOCAL
+       #include "module.lib.c"
+     #+end_src
+
+   - The `.lib.c` file is compiled into the library separately.
diff --git a/developer/document🖉/test_framework.org b/developer/document🖉/test_framework.org
new file mode 100644 (file)
index 0000000..d5f059b
--- /dev/null
@@ -0,0 +1,37 @@
+* Sectioned Single-File Format
+
+  The sectioned file format provides a structured way to define a library,
+  keeping all relevant code in a single file while ensuring proper separation
+  between interface, implementation, and static definitions.
+
+
+** Structure
+   The source file is divided into three sections:
+
+   - *Interface*: Enabled by defining `IFACE` before including the file.
+   - *Implementation*: Enabled when neither `IFACE` nor `LOCAL` is defined.
+   - *Local (Static) Implementation*: Enabled by defining `LOCAL` before including the file.
+
+** Benefits
+   - **Avoids Split Headers and Source Files**: Eliminates mismatches between `.h` and `.c` files.
+   - **Improves Compiler Optimization**: The compiler has full visibility of static functions.
+   - **Reduces File Clutter**: A single source file contains everything.
+   - **Ensures Correct Compilation**: The build system automatically compiles the correct sections.
+
+** Usage
+   - To include the interface in a `.cli.c` file:
+
+     #+begin_src c
+       #define IFACE
+       #include "module.lib.c"
+       #undef IFACE
+     #+end_src
+
+   - To include the local static implementation:
+
+     #+begin_src c
+       #define LOCAL
+       #include "module.lib.c"
+     #+end_src
+
+   - The `.lib.c` file is compiled into the library separately.
diff --git a/developer/experiment/try_letters.c b/developer/experiment/try_letters.c
new file mode 100644 (file)
index 0000000..079d1a4
--- /dev/null
@@ -0,0 +1,31 @@
+#include <stdio.h>
+
+// Define interface and instance types
+typedef struct {
+    void (*print_value)(int);
+} N32·Λ;  // Interface type
+
+typedef struct {
+    int value;
+} N32·μ;  // Instance type
+
+// Function implementation for the interface
+void print_value_function(int value) {
+    printf("Value: %d\n", value);
+}
+
+// Default interface instance
+const N32·Λ N32·λ = {
+    .print_value = print_value_function
+};
+
+int main() {
+    // Create an instance
+    N32·μ instance = { 99 };
+
+    // Call function via interface
+    printf("Calling via interface: ");
+    N32·λ.print_value(instance.value);
+
+    return 0;
+}
diff --git a/document🖉/library_usage.org b/document🖉/library_usage.org
new file mode 100644 (file)
index 0000000..c7b3874
--- /dev/null
@@ -0,0 +1,73 @@
+* Using the N_32 Library
+
+  This document describes how to build, use, and test the N_32 library module.
+
+
+** 1. Overview
+   The `N_32` library provides a 32-bit natural number type with basic arithmetic,
+   bitwise, and shifting operations. It follows the **single-source file**
+   approach, where `N_32.lib.c` contains both interface and implementation.
+
+** 2. Building the Library
+
+   The library is compiled using the shared `make` infrastructure.
+
+   #+begin_src sh
+     make library
+   #+end_src
+
+   This will:
+   - Compile `N_32.lib.c` into an object file.
+   - Archive it into `libN.a` in `scratchpad/`.
+
+** 3. Using the Library in a Project
+   - Include `N_32.lib.c` directly in sources by defining `FACE`:
+     #+begin_src c
+       #define FACE
+       #include "N_32.lib.c"
+       #undef FACE
+     #+end_src
+   - Link against `libN.a` when compiling executables.
+
+** 4. Running Tests
+   The `test_N_32.cli.c` file provides unit tests.
+
+   - Build the test executable:
+     #+begin_src sh
+       make cli
+     #+end_src
+   - Run the test:
+     #+begin_src sh
+       ./tester/test_N_32
+     #+end_src
+   - The test system reports pass/fail counts:
+     #+begin_example
+       Passed: 25, Failed: 0
+     #+end_example
+
+** 5. Understanding the Sectioned File Approach
+   - `N_32.lib.c` contains both the interface and implementation.
+   - It is included twice:
+     1. **Interface Section (`FACE`)**: Provides declarations.
+     2. **Local Section (`LOCAL`)**: Provides static/internal functions.
+
+   - This method reduces duplication, avoids header mismatches, and enables
+     the optimizer to work on `LOCAL` functions effectively.
+
+** 6. Makefile Integration
+   The shared `make` system automates building and linking:
+   - `make library` → Builds `libN.a`.
+   - `make cli` → Builds test executables.
+   - `make dependency` → Generates dependency files.
+   - `make clean` → Removes intermediate files.
+
+   Custom projects can include the library with:
+   #+begin_src makefile
+     LIBS += -L$(LIBDIR) -lN
+     CFLAGS += -I$(SRCDIR)
+   #+end_src
+
+** 7. Best Practices
+   - Run `make dependency` to ensure dependencies are up to date.
+   - Use the test suite to validate changes before release.
+
diff --git a/document🖉/nomenclature.org b/document🖉/nomenclature.org
new file mode 100644 (file)
index 0000000..e706a7f
--- /dev/null
@@ -0,0 +1,113 @@
+#+TITLE: Memory and Function Dictionaries
+#+AUTHOR: Thomas
+
+* Memory
+
+A *base-relative memory map* is a dictionary that associates symbol names with offsets from a base address. A C ~struct typedef~ is an example means for declaring a base-relative memory map. A base-relative memory map has a length associated with it.
+
+Another term for a *base-relative memory map* is *memory format*. A defined memory format can be bound to a name. The names are required to be distinct, though the formats bound to the names need not be.
+
+An *instance* of <X>, where <X> is the name of a memory format, is a region of memory that has been bound to memory format <X>.
+
+The *type* of an instance is the name of its memory format.
+
+* Pointer
+
+A *pointer* is a memory address that has been bound to a memory format.  This technique is used to assure that writes to the memory address conform to the bound memory format. This helps programs to respect the bounds of memory allocations.
+
+The *type* of a pointer is the name of the memory format it has been bound to.
+
+* Function Pointer
+
+The address of a function can be bound to a name and an array of memory formats, 
+one for each argument and the return value.
+
+The *type* of a function is defined by its name and its array of memory format names.
+
+The type of a function can be looked up from the function's name.
+
+* Function Dictionary
+
+A *function dictionary* is a list of function names and addresses, keyed by function names.
+
+A *function dictionary template* is a collection of function types associated with a specific memory format.
+
+A *function dictionary instance* is a collection of function implementations that conform to a function dictionary template.
+
+* Object
+
+If the potentially many instances of a given memory format are operated on exclusively by a closed set of functions, these functions can be collected into a dictionary called the memory format's *interface*.
+
+Conversely, there is no conventional name for an instance of memory that is manipulated by only a closed set of functions. In TTCA, the term *tableau* was introduced for such memory. (A *tableau* is a small chalkboard that was once used by students and could be erased and rewritten.)
+
+Another term that could be used for such memory is *taishou* (対象), meaning "subject" or "target" in Japanese.
+
+* More about Tableau (Taishou)
+
+In the case where an instance is exclusively operated on by a closed function dictionary, 
+it can be referred to as a *tableau* (or *taishou* 対象). A *tableau* is memory that is 
+subject to modification only through the functions of its function dictionary.
+
+This term avoids the ambiguity of *instance*, which is often used generically in other 
+contexts. The word *tableau* refers to a reusable writing surface, much like the small 
+chalkboards used by students in past centuries. The alternative term *taishou* 対象 
+literally means *the subject of attention*, which closely aligns with its role in programming.
+
+#+BEGIN_SRC c
+// Example: Function Dictionary and Tableau
+typedef struct {
+    uint32_t value;
+} N32·T;  // The tableau type (taishou type)
+
+typedef struct {
+    void (*copy)(N32·T *dst, const N32·T *src);
+    void (*increment)(N32·T *t);
+    void (*print)(const N32·T *t);
+} N32·Λ;  // The function dictionary
+
+void N32·copy(N32·T *dst, const N32·T *src) { dst->value = src->value; }
+void N32·increment(N32·T *t) { t->value++; }
+void N32·print(const N32·T *t) { printf("Value: %u\n", t->value); }
+
+// Function dictionary instance
+const N32·Lambda N32·λ = { .copy = N32·copy, .increment = N32·increment, .print = N32·print };
+
+// Usage example
+N32·T my_number = { .value = 10 }; // creating a tableau
+N32·λ.increment(&my_number);
+N32·λ.print(&my_number);  // Output: Value: 11
+#+END_SRC
+
+(Note, this is a contrived example, not legal usage of the N library. I should
+probably update it.)
+
+* Terminology Considerations
+
+The use of the word *type* in this document aligns with C’s conventions. However, other 
+programming paradigms, such as those in C++ and Java, may define *types* differently. 
+For example, C++ allows types to include behavior (methods), while C’s types only 
+define memory structure.
+
+---
+
+**Summary of Key Terms:**
+- *Memory Format*: A named layout of memory.
+- *Instance*: A memory region adhering to a specific format.
+- *Pointer*: A memory address bound to a memory format.
+- *Function Dictionary*: A set of functions associated with a memory format.
+- *Tableau/Taishou*: A memory instance operated on exclusively by a function dictionary.
+- *Function Dictionary Template*: A function dictionary where function types replace function implementations.
+
+
+A *base-relative memory map* is a dictionary that associates symbol names with offsets 
+from a base address. A C ~struct typedef~ is an example means for declaring a 
+base-relative memory map. A base-relative memory map has a length associated with it.
+
+Another term for a *base-relative memory map* is *memory format*. A
+defined memory format can be bound to a name. The names are required
+to be distinct, though the formats bound to the names need not be.
+
+An *instance* of <X>, where <X> is the name of a memory format, is a region
+of memory that has been bound to memory format <X>.
+
+The *type* of an instance is the name of its memory format.