test flow working
authorThomas Walker Lynch <eknp9n@reasoningtechnology.com>
Mon, 17 Feb 2025 14:02:33 +0000 (14:02 +0000)
committerThomas Walker Lynch <eknp9n@reasoningtechnology.com>
Mon, 17 Feb 2025 14:02:33 +0000 (14:02 +0000)
19 files changed:
developer/python/N64.lib.c [deleted file]
developer/python/fill_template
developer/python/gen_N32_8_by_4.py [deleted file]
developer/python/gen_n64_lib.py [deleted file]
developer/python/get_template.py [deleted file]
developer/python/template_N.py [new file with mode: 0644]
developer/tool馃枆/clean
developer/tool馃枆/make
release/x86_64/fedora41/glibc_2.40/N32.lib.c [new file with mode: 0644]
release/x86_64/fedora41/glibc_2.40/N32_4x8.lib.c [new file with mode: 0644]
release/x86_64/fedora41/glibc_2.40/libN.a
tester/cc/N32.lib.c [new file with mode: 0644]
tester/cc/N32_4x8.lib.c [new file with mode: 0644]
tester/cc/test_N32PN.cli.c [deleted file]
tester/python/#fill_templates.py# [deleted file]
tester/python/fill_template
tester/tool馃枆/release_clean [deleted file]
tester/tool馃枆/release_remove [new file with mode: 0755]
tool_shared/bespoke馃枆/version

diff --git a/developer/python/N64.lib.c b/developer/python/N64.lib.c
deleted file mode 100644 (file)
index 8827b35..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-#define N64路DEBUG
-
-#ifndef FACE
-  #define N64路IMPLEMENTATION
-  #define FACE
-#endif
-
-#ifndef N64路FACE
-#define N64路FACE
-
-  #include <stdint.h>
-  #include <stdbool.h>
-  #include <stdarg.h>
-  #include <stdlib.h>
-
-  typedef uint8_t Digit;
-
-  // Digit count is (DIGIT_EXTENT + 1)
-  #define N64路DIGIT_COUNT ( 8 + 1 )
-
-  typedef struct N64路T{
-    Digit d[N64路DIGIT_COUNT];
-  } N64路T;
-
-  // forward declarations for constants
-  extern N64路T *N64路zero;
-  extern N64路T *N64路one;
-  extern N64路T *N64路all_one_bit;
-  extern N64路T *N64路msb;
-
-  // forward declarations for allocations, etc.
-
-#endif // N64路FACE
-
-#ifdef N64路IMPLEMENTATION
-
-#ifndef LOCAL
-  #include <stdarg.h>
-  #include <stdlib.h>
-
-  // compile-time constants
-  static N64路T N64路constant[4] = {
-  {
-    // zero
-    { 0, 0, 0, 0, 0, 0, 0, 0, 0 }
-  },
-  {
-    // one
-    { 1, 0, 0, 0, 0, 0, 0, 0, 0 }
-  },
-  {
-    // all one bits
-    { ( uint8_t )( -1 ), ( uint8_t )( -1 ), ( uint8_t )( -1 ), ( uint8_t )( -1 ), ( uint8_t )( -1 ), ( uint8_t )( -1 ), ( uint8_t )( -1 ), ( uint8_t )( -1 ), ( uint8_t )( -1 ) }
-  },
-  {
-    // msb
-    { 0, 0, 0, 0, 0, 0, 0, 0, ( uint8_t )1 << ((sizeof(uint8_t)*8) - 1) }
-  }
-};
-
-  N64路T *N64路zero        = &N64路constant[0];
-  N64路T *N64路one         = &N64路constant[1];
-  N64路T *N64路all_one_bit = &N64路constant[2];
-  N64路T *N64路msb         = &N64路constant[3];
-
-  // memory allocation prototypes, etc.
-
-#endif // not LOCAL
-
-#ifdef LOCAL
-  // local code: actual function bodies, add, subtract, etc.
-#endif // LOCAL
-
-#endif // N64路IMPLEMENTATION
index bf73da9..f22e5cc 100755 (executable)
@@ -1,27 +1,43 @@
-#+BEGIN_SRC python
 #!/usr/bin/env python3
 
-from get_template import get_template
+import sys
+from template_N import N
 from make_constants import make_constants_block
 
-def fill_template(namespace: str,
-                  digit_extent: int,
-                  digit_type: str) -> str:
-    """
-    Renders the final .lib.c code by merging:
-      - the base template from get_template()
-      - the compile-time constants block from make_constants_block()
-      - placeholders for namespace, digit_extent, digit_type, extent_type
-    """
-    template = get_template()
-    constants_block = make_constants_block(namespace, digit_type, digit_extent)
-
-    # Substitute placeholders
-    code = template.format(
-        NAMESPACE = namespace,
-        DIGIT_EXTENT = digit_extent,
-        DIGIT_TYPE = digit_type,
-        CONSTANTS_BLOCK = constants_block
-    )
-    return code
-#+END_SRC
+def write(code ,basename):
+  filepath = "../cc/" + basename + ".lib.c" 
+  with open(filepath, "w") as f:
+    f.write(code)
+  print("Generated " + filepath)
+  
+
+def main():
+  """
+  generates `.c` source code from templates
+  """
+
+  #----------------------------------------
+  # N32 made from 1 digit, of 32 bits.
+  
+  type_name = "N32"
+  digit_type = "uint32_t"
+  digit_extent = 0
+
+  constants_block = make_constants_block(type_name, digit_type, digit_extent)
+  code = N(type_name ,digit_type ,digit_extent ,constants_block)
+  write(code ,type_name);
+
+  #----------------------------------------
+  # N32 made from 4 digits, each 8 bits.
+
+  type_name = "N32_4x8"
+  digit_type = "uint8_t"
+  digit_extent = 3
+
+  constants_block = make_constants_block(type_name, digit_type, digit_extent)
+  code = N(type_name ,digit_type ,digit_extent ,constants_block)
+  write(code ,type_name);
+
+if __name__ == "__main__":
+  main()
+
diff --git a/developer/python/gen_N32_8_by_4.py b/developer/python/gen_N32_8_by_4.py
deleted file mode 100755 (executable)
index 22ef30e..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/usr/bin/env python3
-
-import sys
-from fill_template import fill_template
-
-def main():
-    """
-    Example: generate an N<type_name>.lib.c 
-    """
-
-    type_name = "N32";
-
-    # 4 x 8 bit 
-    code = fill_template(
-        namespace = type_name + "路",
-        digit_extent = 3,     
-        digit_type = "uint8_t",
-    )
-
-
-    filename = "../cc/" + type_name + ".lib.c" 
-    with open(filename, "w") as f:
-        f.write(code)
-    print("Generated " + filename)
-
-if __name__ == "__main__":
-    main()
diff --git a/developer/python/gen_n64_lib.py b/developer/python/gen_n64_lib.py
deleted file mode 100755 (executable)
index 6288b1d..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/env python3
-
-import sys
-from fill_template import fill_template
-
-def main():
-    """
-    Example: generate a .lib.c with an 'N64路' namespace,
-    """
-    code = fill_template(
-        namespace = "N64路",
-        digit_extent = 8,     # => digit_count = 1 => 32-bit
-        digit_type = "uint8_t",
-    )
-
-    with open("N64.lib.c", "w") as f:
-        f.write(code)
-    print("Generated N64.lib.c")
-
-if __name__ == "__main__":
-    main()
diff --git a/developer/python/get_template.py b/developer/python/get_template.py
deleted file mode 100755 (executable)
index a25336b..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-def get_template():
-    """
-    Returns the base RT C code template, with placeholders like:
-      {NAMESPACE}, {DIGIT_EXTENT}, {DIGIT_TYPE}, {EXTENT_TYPE}, {CONSTANTS_BLOCK}.
-    
-    The final generated .lib.c will replace these with user-specified values.
-    """
-    return r'''#define {NAMESPACE}DEBUG
-
-#ifndef FACE
-  #define {NAMESPACE}IMPLEMENTATION
-  #define FACE
-#endif
-
-#ifndef {NAMESPACE}FACE
-#define {NAMESPACE}FACE
-
-  #include <stdint.h>
-  #include <stdbool.h>
-  #include <stdarg.h>
-  #include <stdlib.h>
-
-  typedef {DIGIT_TYPE} Digit;
-
-  // Digit count is (DIGIT_EXTENT + 1)
-  #define {NAMESPACE}DIGIT_COUNT ( {DIGIT_EXTENT} + 1 )
-
-  typedef struct {NAMESPACE}T{{
-    Digit d[{NAMESPACE}DIGIT_COUNT];
-  }} {NAMESPACE}T;
-
-  // forward declarations for constants
-  extern {NAMESPACE}T *{NAMESPACE}zero;
-  extern {NAMESPACE}T *{NAMESPACE}one;
-  extern {NAMESPACE}T *{NAMESPACE}all_one_bit;
-  extern {NAMESPACE}T *{NAMESPACE}msb;
-
-  // forward declarations for allocations, etc.
-
-#endif // {NAMESPACE}FACE
-
-#ifdef {NAMESPACE}IMPLEMENTATION
-
-#ifndef LOCAL
-  #include <stdarg.h>
-  #include <stdlib.h>
-
-  // compile-time constants
-  {CONSTANTS_BLOCK}
-
-  {NAMESPACE}T *{NAMESPACE}zero        = &{NAMESPACE}constant[0];
-  {NAMESPACE}T *{NAMESPACE}one         = &{NAMESPACE}constant[1];
-  {NAMESPACE}T *{NAMESPACE}all_one_bit = &{NAMESPACE}constant[2];
-  {NAMESPACE}T *{NAMESPACE}msb         = &{NAMESPACE}constant[3];
-
-  // memory allocation prototypes, etc.
-
-#endif // not LOCAL
-
-#ifdef LOCAL
-  // local code: actual function bodies, add, subtract, etc.
-#endif // LOCAL
-
-#endif // {NAMESPACE}IMPLEMENTATION
-'''
diff --git a/developer/python/template_N.py b/developer/python/template_N.py
new file mode 100644 (file)
index 0000000..45a4b9e
--- /dev/null
@@ -0,0 +1,472 @@
+def N(namespace: str ,digit_type: str ,digit_extent: int ,constants_block: str) -> str:
+    """
+    Returns a source code file for cc to munch on
+    """
+    template = template_N()
+    code = template.format(
+        NAMESPACE = namespace
+        ,DIGIT_TYPE = digit_type
+        ,DIGIT_EXTENT = digit_extent
+        ,CONSTANTS_BLOCK = constants_block
+    )
+    return code
+
+def template_N():
+    return r'''/*
+  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 {NAMESPACE}路DEBUG
+
+#ifndef FACE
+#define {NAMESPACE}路IMPLEMENTATION
+#define FACE
+#endif
+
+//--------------------------------------------------------------------------------
+// Interface
+
+#ifndef {NAMESPACE}路FACE
+#define {NAMESPACE}路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 {NAMESPACE}路T {NAMESPACE}路T;
+
+  extern {NAMESPACE}路T *{NAMESPACE}路zero;
+  extern {NAMESPACE}路T *{NAMESPACE}路one;
+  extern {NAMESPACE}路T *{NAMESPACE}路all_one_bit;
+  extern {NAMESPACE}路T *{NAMESPACE}路lsb;
+  extern {NAMESPACE}路T *{NAMESPACE}路msb;
+
+  //----------------------------------------
+  // Return/Error Status and handlers
+
+  typedef enum{{
+    {NAMESPACE}路Status路ok = 0
+    ,{NAMESPACE}路Status路overflow = 1
+    ,{NAMESPACE}路Status路accumulator1_overflow = 2
+    ,{NAMESPACE}路Status路carry = 3
+    ,{NAMESPACE}路Status路borrow = 4
+    ,{NAMESPACE}路Status路undefined_divide_by_zero = 5
+    ,{NAMESPACE}路Status路undefined_modulus_zero = 6
+    ,{NAMESPACE}路Status路gt_max_shift_count = 7
+    ,{NAMESPACE}路Status路spill_eq_operand = 8 // not currently signaled, result will be spill value
+    ,{NAMESPACE}路Status路one_word_product = 9
+    ,{NAMESPACE}路Status路two_word_product = 10
+  }} {NAMESPACE}路Status;
+
+  typedef enum{{
+    {NAMESPACE}路Order_lt = -1
+    ,{NAMESPACE}路Order_eq = 0
+    ,{NAMESPACE}路Order_gt = 1
+  }} {NAMESPACE}路Order;
+
+  typedef {NAMESPACE}路T *( *{NAMESPACE}路Allocate_MemoryFault )(Extent);
+
+  //----------------------------------------
+  // Interface
+
+  typedef struct{{
+
+    {NAMESPACE}路T *(*allocate_array_zero)(Extent, {NAMESPACE}路Allocate_MemoryFault);
+    {NAMESPACE}路T *(*allocate_array)(Extent, {NAMESPACE}路Allocate_MemoryFault);
+    void (*deallocate)({NAMESPACE}路T*);
+
+    void (*copy)({NAMESPACE}路T*, {NAMESPACE}路T*);
+    void (*bit_and)({NAMESPACE}路T*, {NAMESPACE}路T*, {NAMESPACE}路T*);
+    void (*bit_or)({NAMESPACE}路T*, {NAMESPACE}路T*, {NAMESPACE}路T*);
+    void (*bit_complement)({NAMESPACE}路T*, {NAMESPACE}路T*);
+    void (*bit_twos_complement)({NAMESPACE}路T*, {NAMESPACE}路T*);
+    {NAMESPACE}路Order (*compare)({NAMESPACE}路T*, {NAMESPACE}路T*);
+    bool (*lt)({NAMESPACE}路T*, {NAMESPACE}路T*);
+    bool (*gt)({NAMESPACE}路T*, {NAMESPACE}路T*);
+    bool (*eq)({NAMESPACE}路T*, {NAMESPACE}路T*);
+    bool (*eq_zero)({NAMESPACE}路T*);
+    {NAMESPACE}路Status (*accumulate)({NAMESPACE}路T *accumulator1 ,{NAMESPACE}路T *accumulator0 ,...);
+    {NAMESPACE}路Status (*add)({NAMESPACE}路T*, {NAMESPACE}路T*, {NAMESPACE}路T*);
+    bool (*increment)({NAMESPACE}路T *a);
+    {NAMESPACE}路Status (*subtract)({NAMESPACE}路T*, {NAMESPACE}路T*, {NAMESPACE}路T*);
+    {NAMESPACE}路Status (*multiply)({NAMESPACE}路T*, {NAMESPACE}路T*, {NAMESPACE}路T*, {NAMESPACE}路T*);
+    {NAMESPACE}路Status (*divide)({NAMESPACE}路T*, {NAMESPACE}路T*, {NAMESPACE}路T*, {NAMESPACE}路T*);
+    {NAMESPACE}路Status (*modulus)({NAMESPACE}路T*, {NAMESPACE}路T*, {NAMESPACE}路T*);
+    {NAMESPACE}路Status (*shift_left)(Extent, {NAMESPACE}路T*, {NAMESPACE}路T*, {NAMESPACE}路T*);
+    {NAMESPACE}路Status (*shift_right)(Extent, {NAMESPACE}路T*, {NAMESPACE}路T*, {NAMESPACE}路T*);
+    {NAMESPACE}路Status (*arithmetic_shift_right)(Extent, {NAMESPACE}路T*, {NAMESPACE}路T*);
+
+    {NAMESPACE}路T* (*access)({NAMESPACE}路T*, Extent);
+    void (*from_uint32)({NAMESPACE}路T *destination ,uint32_t value);
+  }} {NAMESPACE}路螞;
+
+  Local const {NAMESPACE}路螞 {NAMESPACE}路位; // initialized in the LOCAL section
+
+#endif
+
+//--------------------------------------------------------------------------------
+// Implementation
+
+#ifdef {NAMESPACE}路IMPLEMENTATION
+
+  // this part goes into the library
+  #ifndef LOCAL
+
+    #include <stdarg.h>
+    #include <stdlib.h>
+
+    struct {NAMESPACE}路T{{
+      Digit d0;
+    }};
+
+    {NAMESPACE}路T {NAMESPACE}路constant[4] = {{
+      {{.d0 = 0}},
+      {{.d0 = 1}},
+      {{.d0 = ~(uint32_t)0}},
+      {{.d0 = 1 << 31}}
+    }};
+
+    {NAMESPACE}路T *{NAMESPACE}路zero = &{NAMESPACE}路constant[0];
+    {NAMESPACE}路T *{NAMESPACE}路one = &{NAMESPACE}路constant[1];
+    {NAMESPACE}路T *{NAMESPACE}路all_one_bit = &{NAMESPACE}路constant[2];
+    {NAMESPACE}路T *{NAMESPACE}路msb = &{NAMESPACE}路constant[3];
+    {NAMESPACE}路T *{NAMESPACE}路lsb = &{NAMESPACE}路constant[1];
+
+    // the allocate an array of N32
+    {NAMESPACE}路T *{NAMESPACE}路allocate_array(Extent extent ,{NAMESPACE}路Allocate_MemoryFault memory_fault){{
+      {NAMESPACE}路T *instance = malloc((extent + 1) * sizeof({NAMESPACE}路T) );
+      if(!instance){{
+        return memory_fault ? memory_fault(extent) : NULL;
+      }}
+      return instance;
+    }}
+
+    {NAMESPACE}路T *{NAMESPACE}路allocate_array_zero(Extent extent ,{NAMESPACE}路Allocate_MemoryFault memory_fault){{
+      {NAMESPACE}路T *instance = calloc( extent + 1 ,sizeof({NAMESPACE}路T) );
+      if(!instance){{
+        return memory_fault ? memory_fault(extent) : NULL;
+      }}
+      return instance;
+    }}
+
+    void {NAMESPACE}路deallocate({NAMESPACE}路T *unencumbered){{
+      free(unencumbered);
+    }}
+
+  #endif
+
+  // This part is included after the library user's code
+  #ifdef LOCAL
+
+    // instance
+
+    struct {NAMESPACE}路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 {NAMESPACE}路T {NAMESPACE}路t[4];
+
+
+    // allocation 
+
+    extern {NAMESPACE}路T *{NAMESPACE}路allocate_array(Extent, {NAMESPACE}路Allocate_MemoryFault);
+    extern {NAMESPACE}路T *{NAMESPACE}路allocate_array_zero(Extent, {NAMESPACE}路Allocate_MemoryFault);
+    extern void {NAMESPACE}路deallocate({NAMESPACE}路T *);
+
+    // so the user can access numbers in an array allocation
+    Local {NAMESPACE}路T* {NAMESPACE}路access({NAMESPACE}路T *array ,Extent index){{
+      return &array[index];
+    }}
+
+    Local void {NAMESPACE}路from_uint32({NAMESPACE}路T *destination ,uint32_t value){{
+      if(destination == NULL) return;
+      destination->d0 = value;
+    }}
+
+    // copy, convenience copy
+
+    Local void {NAMESPACE}路copy({NAMESPACE}路T *destination ,{NAMESPACE}路T *source){{
+      if(source == destination) return; // that was easy! 
+      *destination = *source;
+    }}
+
+    Local void {NAMESPACE}路set_to_zero({NAMESPACE}路T *instance){{
+      instance->d0 = 0;
+    }}
+
+    Local void {NAMESPACE}路set_to_one({NAMESPACE}路T *instance){{
+      instance->d0 = 1;
+    }}
+
+    // bit operations
+
+    Local void {NAMESPACE}路bit_and({NAMESPACE}路T *result, {NAMESPACE}路T *a, {NAMESPACE}路T *b){{
+      result->d0 = a->d0 & b->d0;
+    }}
+
+    // result can be one of the operands
+    Local void {NAMESPACE}路bit_or({NAMESPACE}路T *result, {NAMESPACE}路T *a, {NAMESPACE}路T *b){{
+      result->d0 = a->d0 | b->d0;
+    }}
+
+    // result can the same as the operand
+    Local void {NAMESPACE}路bit_complement({NAMESPACE}路T *result, {NAMESPACE}路T *a){{
+      result->d0 = ~a->d0;
+    }}
+
+    // result can the same as the operand
+    Local void {NAMESPACE}路bit_twos_complement({NAMESPACE}路T *result ,{NAMESPACE}路T *a){{
+      result->d0 = ~a->d0 + 1;
+    }}
+
+    // test functions
+
+    Local {NAMESPACE}路Order {NAMESPACE}路compare({NAMESPACE}路T *a, {NAMESPACE}路T *b){{
+      if(a->d0 < b->d0) return {NAMESPACE}路Order_lt;
+      if(a->d0 > b->d0) return {NAMESPACE}路Order_gt;
+      return {NAMESPACE}路Order_eq;
+    }}
+
+    Local bool {NAMESPACE}路lt({NAMESPACE}路T *a ,{NAMESPACE}路T *b){{
+      return  a->d0 < b->d0;
+    }}    
+
+    Local bool {NAMESPACE}路gt({NAMESPACE}路T *a ,{NAMESPACE}路T *b){{
+      return  a->d0 > b->d0;
+    }}    
+
+    Local bool {NAMESPACE}路eq({NAMESPACE}路T *a ,{NAMESPACE}路T *b){{
+      return  a->d0 == b->d0;
+    }}    
+
+    Local bool {NAMESPACE}路eq_zero({NAMESPACE}路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 {NAMESPACE}路Status路accumulator1_overflow
+    //
+    // When accumulator1 and accumulator0 point to the same location, the result is the accumulator1 value.
+    Local {NAMESPACE}路Status {NAMESPACE}路accumulate({NAMESPACE}路T *accumulator1 ,{NAMESPACE}路T *accumulator0 ,...){{
+
+      va_list args;
+      va_start(args ,accumulator0);
+      uint32_t sum = accumulator0->d0;
+      uint32_t carry = 0;
+      {NAMESPACE}路T *current;
+
+      while( (current = va_arg(args ,{NAMESPACE}路T *)) ){{
+        sum += current->d0;
+        if(sum < current->d0){{  // Accumulator1 into carry
+          (carry)++;
+          if(carry == 0){{
+            va_end(args);
+            return {NAMESPACE}路Status路accumulator1_overflow;
+          }}
+        }}
+      }}
+      va_end(args);
+
+      // wipes out prior value of accumulator1
+      accumulator1->d0 = carry;
+
+      return {NAMESPACE}路Status路ok;
+    }}
+
+    Local {NAMESPACE}路Status {NAMESPACE}路add({NAMESPACE}路T *sum ,{NAMESPACE}路T *a ,{NAMESPACE}路T *b){{
+      uint64_t result = (uint64_t)a->d0 + (uint64_t)b->d0;
+      sum->d0 = (uint32_t)result;
+      return (result >> 32) ? {NAMESPACE}路Status路carry : {NAMESPACE}路Status路ok;
+    }}
+
+    Local bool {NAMESPACE}路increment({NAMESPACE}路T *a){{
+      a->d0++;
+      return a->d0 == 0;
+    }}
+
+    Local {NAMESPACE}路Status {NAMESPACE}路subtract({NAMESPACE}路T *difference ,{NAMESPACE}路T *a ,{NAMESPACE}路T *b){{
+      uint64_t diff = (uint64_t) a->d0 - (uint64_t) b->d0;
+      difference->d0 = (uint32_t)diff;
+      return (diff > a->d0) ? {NAMESPACE}路Status路borrow : {NAMESPACE}路Status路ok;
+    }}
+
+
+    Local {NAMESPACE}路Status {NAMESPACE}路multiply({NAMESPACE}路T *product1 ,{NAMESPACE}路T *product0 ,{NAMESPACE}路T *a ,{NAMESPACE}路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 {NAMESPACE}路Status路one_word_product;
+      return {NAMESPACE}路Status路two_word_product;
+    }}
+
+    Local {NAMESPACE}路Status {NAMESPACE}路divide({NAMESPACE}路T *remainder ,{NAMESPACE}路T *quotient ,{NAMESPACE}路T *a ,{NAMESPACE}路T *b){{
+      if(b->d0 == 0) return {NAMESPACE}路Status路undefined_divide_by_zero; 
+
+      quotient->d0 = a->d0 / b->d0;
+      remainder->d0 = a->d0 - (quotient->d0 * b->d0);
+
+      return {NAMESPACE}路Status路ok;
+    }}
+
+    Local {NAMESPACE}路Status {NAMESPACE}路modulus({NAMESPACE}路T *remainder ,{NAMESPACE}路T *a ,{NAMESPACE}路T *b){{
+      if(b->d0 == 0) return {NAMESPACE}路Status路undefined_modulus_zero; 
+      uint32_t quotient = a->d0 / b->d0;
+      remainder->d0 = a->d0 - (quotient * b->d0);
+      return {NAMESPACE}路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 {NAMESPACE}路Status {NAMESPACE}路shift
+    (
+     uint32_t shift_count
+     ,{NAMESPACE}路T *spill
+     ,{NAMESPACE}路T *operand
+     ,{NAMESPACE}路T *fill
+     ,ShiftOp shift_op
+     ,ShiftOp complement_shift_op
+     ){{
+
+      // If no result is needed, return immediately.
+      if(operand == NULL && spill == NULL) return {NAMESPACE}路Status路ok;
+
+      // Treat NULL operand as zero.
+      if(operand == NULL){{
+        operand = &{NAMESPACE}路t[0];
+        {NAMESPACE}路copy(operand, {NAMESPACE}路zero);
+      }}
+
+      // Shifting more than one word breaks our fill/spill model.
+      if(shift_count > 31) return {NAMESPACE}路Status路gt_max_shift_count;
+
+      // The given operand is still required after it is modified, so we copy it.
+      {NAMESPACE}路T *given_operand = &{NAMESPACE}路t[1];
+      {NAMESPACE}路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));
+        {NAMESPACE}路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 {NAMESPACE}路Status路ok;
+    }}
+
+    // Define concrete shift functions using valid C function pointers
+    Local {NAMESPACE}路Status 
+    {NAMESPACE}路shift_left(uint32_t shift_count, {NAMESPACE}路T *spill, {NAMESPACE}路T *operand, {NAMESPACE}路T *fill){{
+      return {NAMESPACE}路shift(shift_count, spill, operand, fill, shift_left_op, shift_right_op);
+    }}
+
+    Local {NAMESPACE}路Status 
+    {NAMESPACE}路shift_right(uint32_t shift_count, {NAMESPACE}路T *spill, {NAMESPACE}路T *operand, {NAMESPACE}路T *fill){{
+      return {NAMESPACE}路shift(shift_count, spill, operand, fill, shift_right_op, shift_left_op);
+    }}
+
+    Local {NAMESPACE}路Status 
+    {NAMESPACE}路arithmetic_shift_right(uint32_t shift_count, {NAMESPACE}路T *operand, {NAMESPACE}路T *spill){{
+
+      // Guard against excessive shift counts
+      if(shift_count > 31) return {NAMESPACE}路Status路gt_max_shift_count;
+
+      // A NULL operand is treated as zero
+      if(operand == NULL){{
+        operand = &{NAMESPACE}路t[0];
+        {NAMESPACE}路copy(operand, {NAMESPACE}路zero);
+      }}
+
+      // Pick the fill value based on the sign bit
+      {NAMESPACE}路T *fill = (operand->d0 & 0x80000000) ? {NAMESPACE}路all_one_bit : {NAMESPACE}路zero;
+
+      // Call shift_right with the appropriate fill
+      return {NAMESPACE}路shift_right(shift_count, spill, operand, fill);
+    }}
+
+    Local const {NAMESPACE}路螞 {NAMESPACE}路位 = {{
+
+      .allocate_array = {NAMESPACE}路allocate_array
+      ,.allocate_array_zero = {NAMESPACE}路allocate_array_zero
+      ,.deallocate = {NAMESPACE}路deallocate
+
+      ,.copy = {NAMESPACE}路copy
+      ,.bit_and = {NAMESPACE}路bit_and
+      ,.bit_or = {NAMESPACE}路bit_or
+      ,.bit_complement = {NAMESPACE}路bit_complement
+      ,.bit_twos_complement = {NAMESPACE}路bit_twos_complement
+      ,.compare = {NAMESPACE}路compare
+      ,.lt = {NAMESPACE}路lt
+      ,.gt = {NAMESPACE}路gt
+      ,.eq = {NAMESPACE}路eq
+      ,.eq_zero = {NAMESPACE}路eq_zero
+      ,.accumulate = {NAMESPACE}路accumulate
+      ,.add = {NAMESPACE}路add
+      ,.increment = {NAMESPACE}路increment
+      ,.subtract = {NAMESPACE}路subtract
+      ,.multiply = {NAMESPACE}路multiply
+      ,.divide = {NAMESPACE}路divide
+      ,.modulus = {NAMESPACE}路modulus
+      ,.shift_left = {NAMESPACE}路shift_left
+      ,.shift_right = {NAMESPACE}路shift_right
+      ,.arithmetic_shift_right = {NAMESPACE}路arithmetic_shift_right
+
+      ,.access = {NAMESPACE}路access
+      ,.from_uint32 = {NAMESPACE}路from_uint32
+    }};
+
+  #endif
+
+#endif
+'''
index cbb86b8..48d4f35 100755 (executable)
@@ -15,8 +15,11 @@ set -x
 
 cd "$REPO_HOME"/developer || exit 1
 
-# remove library pulled from release and other scratchpad files
-  rm_na scratchpad/{makefile-cc.deps,*.o} || true
+# remove synthesized .c files
+  rm_na cc/*
+
+# remove object files, deps file, library, and whatever else is on the scratchpad if anything
+  rm_na scratchpad/* || true
 
 # remove built executables
   rm_na -f machine/* || true
index 0df0712..cfc2138 100755 (executable)
@@ -14,6 +14,9 @@ set -x
 
   cd "$REPO_HOME"/developer || exit 1
 
+  pushd python
+    ./fill_template
+  popd
   /bin/make -f tool馃枆/makefile $@
 
 set +x
diff --git a/release/x86_64/fedora41/glibc_2.40/N32.lib.c b/release/x86_64/fedora41/glibc_2.40/N32.lib.c
new file mode 100644 (file)
index 0000000..fba3c21
--- /dev/null
@@ -0,0 +1,457 @@
+/*
+  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_zero)(Extent, N32路Allocate_MemoryFault);
+    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 (*accumulate)(N32路T *accumulator1 ,N32路T *accumulator0 ,...);
+    N32路Status (*add)(N32路T*, N32路T*, N32路T*);
+    bool (*increment)(N32路T *a);
+    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路螞;
+
+  Local const N32路螞 N32路位; // initialized in the LOCAL section
+
+#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路Allocate_MemoryFault memory_fault){
+      N32路T *instance = malloc((extent + 1) * sizeof(N32路T) );
+      if(!instance){
+        return memory_fault ? memory_fault(extent) : NULL;
+      }
+      return instance;
+    }
+
+    N32路T *N32路allocate_array_zero(Extent extent ,N32路Allocate_MemoryFault memory_fault){
+      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路allocate_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);
+      uint32_t sum = accumulator0->d0;
+      uint32_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);
+    }
+
+    Local const N32路螞 N32路位 = {
+
+      .allocate_array = N32路allocate_array
+      ,.allocate_array_zero = N32路allocate_array_zero
+      ,.deallocate = N32路deallocate
+
+      ,.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
+      ,.accumulate = N32路accumulate
+      ,.add = N32路add
+      ,.increment = N32路increment
+      ,.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
+
+      ,.access = N32路access
+      ,.from_uint32 = N32路from_uint32
+    };
+
+  #endif
+
+#endif
diff --git a/release/x86_64/fedora41/glibc_2.40/N32_4x8.lib.c b/release/x86_64/fedora41/glibc_2.40/N32_4x8.lib.c
new file mode 100644 (file)
index 0000000..22cced5
--- /dev/null
@@ -0,0 +1,457 @@
+/*
+  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_4x8路DEBUG
+
+#ifndef FACE
+#define N32_4x8路IMPLEMENTATION
+#define FACE
+#endif
+
+//--------------------------------------------------------------------------------
+// Interface
+
+#ifndef N32_4x8路FACE
+#define N32_4x8路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_4x8路T N32_4x8路T;
+
+  extern N32_4x8路T *N32_4x8路zero;
+  extern N32_4x8路T *N32_4x8路one;
+  extern N32_4x8路T *N32_4x8路all_one_bit;
+  extern N32_4x8路T *N32_4x8路lsb;
+  extern N32_4x8路T *N32_4x8路msb;
+
+  //----------------------------------------
+  // Return/Error Status and handlers
+
+  typedef enum{
+    N32_4x8路Status路ok = 0
+    ,N32_4x8路Status路overflow = 1
+    ,N32_4x8路Status路accumulator1_overflow = 2
+    ,N32_4x8路Status路carry = 3
+    ,N32_4x8路Status路borrow = 4
+    ,N32_4x8路Status路undefined_divide_by_zero = 5
+    ,N32_4x8路Status路undefined_modulus_zero = 6
+    ,N32_4x8路Status路gt_max_shift_count = 7
+    ,N32_4x8路Status路spill_eq_operand = 8 // not currently signaled, result will be spill value
+    ,N32_4x8路Status路one_word_product = 9
+    ,N32_4x8路Status路two_word_product = 10
+  } N32_4x8路Status;
+
+  typedef enum{
+    N32_4x8路Order_lt = -1
+    ,N32_4x8路Order_eq = 0
+    ,N32_4x8路Order_gt = 1
+  } N32_4x8路Order;
+
+  typedef N32_4x8路T *( *N32_4x8路Allocate_MemoryFault )(Extent);
+
+  //----------------------------------------
+  // Interface
+
+  typedef struct{
+
+    N32_4x8路T *(*allocate_array_zero)(Extent, N32_4x8路Allocate_MemoryFault);
+    N32_4x8路T *(*allocate_array)(Extent, N32_4x8路Allocate_MemoryFault);
+    void (*deallocate)(N32_4x8路T*);
+
+    void (*copy)(N32_4x8路T*, N32_4x8路T*);
+    void (*bit_and)(N32_4x8路T*, N32_4x8路T*, N32_4x8路T*);
+    void (*bit_or)(N32_4x8路T*, N32_4x8路T*, N32_4x8路T*);
+    void (*bit_complement)(N32_4x8路T*, N32_4x8路T*);
+    void (*bit_twos_complement)(N32_4x8路T*, N32_4x8路T*);
+    N32_4x8路Order (*compare)(N32_4x8路T*, N32_4x8路T*);
+    bool (*lt)(N32_4x8路T*, N32_4x8路T*);
+    bool (*gt)(N32_4x8路T*, N32_4x8路T*);
+    bool (*eq)(N32_4x8路T*, N32_4x8路T*);
+    bool (*eq_zero)(N32_4x8路T*);
+    N32_4x8路Status (*accumulate)(N32_4x8路T *accumulator1 ,N32_4x8路T *accumulator0 ,...);
+    N32_4x8路Status (*add)(N32_4x8路T*, N32_4x8路T*, N32_4x8路T*);
+    bool (*increment)(N32_4x8路T *a);
+    N32_4x8路Status (*subtract)(N32_4x8路T*, N32_4x8路T*, N32_4x8路T*);
+    N32_4x8路Status (*multiply)(N32_4x8路T*, N32_4x8路T*, N32_4x8路T*, N32_4x8路T*);
+    N32_4x8路Status (*divide)(N32_4x8路T*, N32_4x8路T*, N32_4x8路T*, N32_4x8路T*);
+    N32_4x8路Status (*modulus)(N32_4x8路T*, N32_4x8路T*, N32_4x8路T*);
+    N32_4x8路Status (*shift_left)(Extent, N32_4x8路T*, N32_4x8路T*, N32_4x8路T*);
+    N32_4x8路Status (*shift_right)(Extent, N32_4x8路T*, N32_4x8路T*, N32_4x8路T*);
+    N32_4x8路Status (*arithmetic_shift_right)(Extent, N32_4x8路T*, N32_4x8路T*);
+
+    N32_4x8路T* (*access)(N32_4x8路T*, Extent);
+    void (*from_uint32)(N32_4x8路T *destination ,uint32_t value);
+  } N32_4x8路螞;
+
+  Local const N32_4x8路螞 N32_4x8路位; // initialized in the LOCAL section
+
+#endif
+
+//--------------------------------------------------------------------------------
+// Implementation
+
+#ifdef N32_4x8路IMPLEMENTATION
+
+  // this part goes into the library
+  #ifndef LOCAL
+
+    #include <stdarg.h>
+    #include <stdlib.h>
+
+    struct N32_4x8路T{
+      Digit d0;
+    };
+
+    N32_4x8路T N32_4x8路constant[4] = {
+      {.d0 = 0},
+      {.d0 = 1},
+      {.d0 = ~(uint32_t)0},
+      {.d0 = 1 << 31}
+    };
+
+    N32_4x8路T *N32_4x8路zero = &N32_4x8路constant[0];
+    N32_4x8路T *N32_4x8路one = &N32_4x8路constant[1];
+    N32_4x8路T *N32_4x8路all_one_bit = &N32_4x8路constant[2];
+    N32_4x8路T *N32_4x8路msb = &N32_4x8路constant[3];
+    N32_4x8路T *N32_4x8路lsb = &N32_4x8路constant[1];
+
+    // the allocate an array of N32
+    N32_4x8路T *N32_4x8路allocate_array(Extent extent ,N32_4x8路Allocate_MemoryFault memory_fault){
+      N32_4x8路T *instance = malloc((extent + 1) * sizeof(N32_4x8路T) );
+      if(!instance){
+        return memory_fault ? memory_fault(extent) : NULL;
+      }
+      return instance;
+    }
+
+    N32_4x8路T *N32_4x8路allocate_array_zero(Extent extent ,N32_4x8路Allocate_MemoryFault memory_fault){
+      N32_4x8路T *instance = calloc( extent + 1 ,sizeof(N32_4x8路T) );
+      if(!instance){
+        return memory_fault ? memory_fault(extent) : NULL;
+      }
+      return instance;
+    }
+
+    void N32_4x8路deallocate(N32_4x8路T *unencumbered){
+      free(unencumbered);
+    }
+
+  #endif
+
+  // This part is included after the library user's code
+  #ifdef LOCAL
+
+    // instance
+
+    struct N32_4x8路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_4x8路T N32_4x8路t[4];
+
+
+    // allocation 
+
+    extern N32_4x8路T *N32_4x8路allocate_array(Extent, N32_4x8路Allocate_MemoryFault);
+    extern N32_4x8路T *N32_4x8路allocate_array_zero(Extent, N32_4x8路Allocate_MemoryFault);
+    extern void N32_4x8路deallocate(N32_4x8路T *);
+
+    // so the user can access numbers in an array allocation
+    Local N32_4x8路T* N32_4x8路access(N32_4x8路T *array ,Extent index){
+      return &array[index];
+    }
+
+    Local void N32_4x8路from_uint32(N32_4x8路T *destination ,uint32_t value){
+      if(destination == NULL) return;
+      destination->d0 = value;
+    }
+
+    // copy, convenience copy
+
+    Local void N32_4x8路copy(N32_4x8路T *destination ,N32_4x8路T *source){
+      if(source == destination) return; // that was easy! 
+      *destination = *source;
+    }
+
+    Local void N32_4x8路set_to_zero(N32_4x8路T *instance){
+      instance->d0 = 0;
+    }
+
+    Local void N32_4x8路set_to_one(N32_4x8路T *instance){
+      instance->d0 = 1;
+    }
+
+    // bit operations
+
+    Local void N32_4x8路bit_and(N32_4x8路T *result, N32_4x8路T *a, N32_4x8路T *b){
+      result->d0 = a->d0 & b->d0;
+    }
+
+    // result can be one of the operands
+    Local void N32_4x8路bit_or(N32_4x8路T *result, N32_4x8路T *a, N32_4x8路T *b){
+      result->d0 = a->d0 | b->d0;
+    }
+
+    // result can the same as the operand
+    Local void N32_4x8路bit_complement(N32_4x8路T *result, N32_4x8路T *a){
+      result->d0 = ~a->d0;
+    }
+
+    // result can the same as the operand
+    Local void N32_4x8路bit_twos_complement(N32_4x8路T *result ,N32_4x8路T *a){
+      result->d0 = ~a->d0 + 1;
+    }
+
+    // test functions
+
+    Local N32_4x8路Order N32_4x8路compare(N32_4x8路T *a, N32_4x8路T *b){
+      if(a->d0 < b->d0) return N32_4x8路Order_lt;
+      if(a->d0 > b->d0) return N32_4x8路Order_gt;
+      return N32_4x8路Order_eq;
+    }
+
+    Local bool N32_4x8路lt(N32_4x8路T *a ,N32_4x8路T *b){
+      return  a->d0 < b->d0;
+    }    
+
+    Local bool N32_4x8路gt(N32_4x8路T *a ,N32_4x8路T *b){
+      return  a->d0 > b->d0;
+    }    
+
+    Local bool N32_4x8路eq(N32_4x8路T *a ,N32_4x8路T *b){
+      return  a->d0 == b->d0;
+    }    
+
+    Local bool N32_4x8路eq_zero(N32_4x8路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_4x8路Status路accumulator1_overflow
+    //
+    // When accumulator1 and accumulator0 point to the same location, the result is the accumulator1 value.
+    Local N32_4x8路Status N32_4x8路accumulate(N32_4x8路T *accumulator1 ,N32_4x8路T *accumulator0 ,...){
+
+      va_list args;
+      va_start(args ,accumulator0);
+      uint32_t sum = accumulator0->d0;
+      uint32_t carry = 0;
+      N32_4x8路T *current;
+
+      while( (current = va_arg(args ,N32_4x8路T *)) ){
+        sum += current->d0;
+        if(sum < current->d0){  // Accumulator1 into carry
+          (carry)++;
+          if(carry == 0){
+            va_end(args);
+            return N32_4x8路Status路accumulator1_overflow;
+          }
+        }
+      }
+      va_end(args);
+
+      // wipes out prior value of accumulator1
+      accumulator1->d0 = carry;
+
+      return N32_4x8路Status路ok;
+    }
+
+    Local N32_4x8路Status N32_4x8路add(N32_4x8路T *sum ,N32_4x8路T *a ,N32_4x8路T *b){
+      uint64_t result = (uint64_t)a->d0 + (uint64_t)b->d0;
+      sum->d0 = (uint32_t)result;
+      return (result >> 32) ? N32_4x8路Status路carry : N32_4x8路Status路ok;
+    }
+
+    Local bool N32_4x8路increment(N32_4x8路T *a){
+      a->d0++;
+      return a->d0 == 0;
+    }
+
+    Local N32_4x8路Status N32_4x8路subtract(N32_4x8路T *difference ,N32_4x8路T *a ,N32_4x8路T *b){
+      uint64_t diff = (uint64_t) a->d0 - (uint64_t) b->d0;
+      difference->d0 = (uint32_t)diff;
+      return (diff > a->d0) ? N32_4x8路Status路borrow : N32_4x8路Status路ok;
+    }
+
+
+    Local N32_4x8路Status N32_4x8路multiply(N32_4x8路T *product1 ,N32_4x8路T *product0 ,N32_4x8路T *a ,N32_4x8路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_4x8路Status路one_word_product;
+      return N32_4x8路Status路two_word_product;
+    }
+
+    Local N32_4x8路Status N32_4x8路divide(N32_4x8路T *remainder ,N32_4x8路T *quotient ,N32_4x8路T *a ,N32_4x8路T *b){
+      if(b->d0 == 0) return N32_4x8路Status路undefined_divide_by_zero; 
+
+      quotient->d0 = a->d0 / b->d0;
+      remainder->d0 = a->d0 - (quotient->d0 * b->d0);
+
+      return N32_4x8路Status路ok;
+    }
+
+    Local N32_4x8路Status N32_4x8路modulus(N32_4x8路T *remainder ,N32_4x8路T *a ,N32_4x8路T *b){
+      if(b->d0 == 0) return N32_4x8路Status路undefined_modulus_zero; 
+      uint32_t quotient = a->d0 / b->d0;
+      remainder->d0 = a->d0 - (quotient * b->d0);
+      return N32_4x8路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_4x8路Status N32_4x8路shift
+    (
+     uint32_t shift_count
+     ,N32_4x8路T *spill
+     ,N32_4x8路T *operand
+     ,N32_4x8路T *fill
+     ,ShiftOp shift_op
+     ,ShiftOp complement_shift_op
+     ){
+
+      // If no result is needed, return immediately.
+      if(operand == NULL && spill == NULL) return N32_4x8路Status路ok;
+
+      // Treat NULL operand as zero.
+      if(operand == NULL){
+        operand = &N32_4x8路t[0];
+        N32_4x8路copy(operand, N32_4x8路zero);
+      }
+
+      // Shifting more than one word breaks our fill/spill model.
+      if(shift_count > 31) return N32_4x8路Status路gt_max_shift_count;
+
+      // The given operand is still required after it is modified, so we copy it.
+      N32_4x8路T *given_operand = &N32_4x8路t[1];
+      N32_4x8路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_4x8路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_4x8路Status路ok;
+    }
+
+    // Define concrete shift functions using valid C function pointers
+    Local N32_4x8路Status 
+    N32_4x8路shift_left(uint32_t shift_count, N32_4x8路T *spill, N32_4x8路T *operand, N32_4x8路T *fill){
+      return N32_4x8路shift(shift_count, spill, operand, fill, shift_left_op, shift_right_op);
+    }
+
+    Local N32_4x8路Status 
+    N32_4x8路shift_right(uint32_t shift_count, N32_4x8路T *spill, N32_4x8路T *operand, N32_4x8路T *fill){
+      return N32_4x8路shift(shift_count, spill, operand, fill, shift_right_op, shift_left_op);
+    }
+
+    Local N32_4x8路Status 
+    N32_4x8路arithmetic_shift_right(uint32_t shift_count, N32_4x8路T *operand, N32_4x8路T *spill){
+
+      // Guard against excessive shift counts
+      if(shift_count > 31) return N32_4x8路Status路gt_max_shift_count;
+
+      // A NULL operand is treated as zero
+      if(operand == NULL){
+        operand = &N32_4x8路t[0];
+        N32_4x8路copy(operand, N32_4x8路zero);
+      }
+
+      // Pick the fill value based on the sign bit
+      N32_4x8路T *fill = (operand->d0 & 0x80000000) ? N32_4x8路all_one_bit : N32_4x8路zero;
+
+      // Call shift_right with the appropriate fill
+      return N32_4x8路shift_right(shift_count, spill, operand, fill);
+    }
+
+    Local const N32_4x8路螞 N32_4x8路位 = {
+
+      .allocate_array = N32_4x8路allocate_array
+      ,.allocate_array_zero = N32_4x8路allocate_array_zero
+      ,.deallocate = N32_4x8路deallocate
+
+      ,.copy = N32_4x8路copy
+      ,.bit_and = N32_4x8路bit_and
+      ,.bit_or = N32_4x8路bit_or
+      ,.bit_complement = N32_4x8路bit_complement
+      ,.bit_twos_complement = N32_4x8路bit_twos_complement
+      ,.compare = N32_4x8路compare
+      ,.lt = N32_4x8路lt
+      ,.gt = N32_4x8路gt
+      ,.eq = N32_4x8路eq
+      ,.eq_zero = N32_4x8路eq_zero
+      ,.accumulate = N32_4x8路accumulate
+      ,.add = N32_4x8路add
+      ,.increment = N32_4x8路increment
+      ,.subtract = N32_4x8路subtract
+      ,.multiply = N32_4x8路multiply
+      ,.divide = N32_4x8路divide
+      ,.modulus = N32_4x8路modulus
+      ,.shift_left = N32_4x8路shift_left
+      ,.shift_right = N32_4x8路shift_right
+      ,.arithmetic_shift_right = N32_4x8路arithmetic_shift_right
+
+      ,.access = N32_4x8路access
+      ,.from_uint32 = N32_4x8路from_uint32
+    };
+
+  #endif
+
+#endif
index 15d0154..82a1f5c 100644 (file)
Binary files a/release/x86_64/fedora41/glibc_2.40/libN.a and b/release/x86_64/fedora41/glibc_2.40/libN.a differ
diff --git a/tester/cc/N32.lib.c b/tester/cc/N32.lib.c
new file mode 100644 (file)
index 0000000..fba3c21
--- /dev/null
@@ -0,0 +1,457 @@
+/*
+  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_zero)(Extent, N32路Allocate_MemoryFault);
+    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 (*accumulate)(N32路T *accumulator1 ,N32路T *accumulator0 ,...);
+    N32路Status (*add)(N32路T*, N32路T*, N32路T*);
+    bool (*increment)(N32路T *a);
+    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路螞;
+
+  Local const N32路螞 N32路位; // initialized in the LOCAL section
+
+#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路Allocate_MemoryFault memory_fault){
+      N32路T *instance = malloc((extent + 1) * sizeof(N32路T) );
+      if(!instance){
+        return memory_fault ? memory_fault(extent) : NULL;
+      }
+      return instance;
+    }
+
+    N32路T *N32路allocate_array_zero(Extent extent ,N32路Allocate_MemoryFault memory_fault){
+      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路allocate_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);
+      uint32_t sum = accumulator0->d0;
+      uint32_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);
+    }
+
+    Local const N32路螞 N32路位 = {
+
+      .allocate_array = N32路allocate_array
+      ,.allocate_array_zero = N32路allocate_array_zero
+      ,.deallocate = N32路deallocate
+
+      ,.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
+      ,.accumulate = N32路accumulate
+      ,.add = N32路add
+      ,.increment = N32路increment
+      ,.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
+
+      ,.access = N32路access
+      ,.from_uint32 = N32路from_uint32
+    };
+
+  #endif
+
+#endif
diff --git a/tester/cc/N32_4x8.lib.c b/tester/cc/N32_4x8.lib.c
new file mode 100644 (file)
index 0000000..22cced5
--- /dev/null
@@ -0,0 +1,457 @@
+/*
+  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_4x8路DEBUG
+
+#ifndef FACE
+#define N32_4x8路IMPLEMENTATION
+#define FACE
+#endif
+
+//--------------------------------------------------------------------------------
+// Interface
+
+#ifndef N32_4x8路FACE
+#define N32_4x8路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_4x8路T N32_4x8路T;
+
+  extern N32_4x8路T *N32_4x8路zero;
+  extern N32_4x8路T *N32_4x8路one;
+  extern N32_4x8路T *N32_4x8路all_one_bit;
+  extern N32_4x8路T *N32_4x8路lsb;
+  extern N32_4x8路T *N32_4x8路msb;
+
+  //----------------------------------------
+  // Return/Error Status and handlers
+
+  typedef enum{
+    N32_4x8路Status路ok = 0
+    ,N32_4x8路Status路overflow = 1
+    ,N32_4x8路Status路accumulator1_overflow = 2
+    ,N32_4x8路Status路carry = 3
+    ,N32_4x8路Status路borrow = 4
+    ,N32_4x8路Status路undefined_divide_by_zero = 5
+    ,N32_4x8路Status路undefined_modulus_zero = 6
+    ,N32_4x8路Status路gt_max_shift_count = 7
+    ,N32_4x8路Status路spill_eq_operand = 8 // not currently signaled, result will be spill value
+    ,N32_4x8路Status路one_word_product = 9
+    ,N32_4x8路Status路two_word_product = 10
+  } N32_4x8路Status;
+
+  typedef enum{
+    N32_4x8路Order_lt = -1
+    ,N32_4x8路Order_eq = 0
+    ,N32_4x8路Order_gt = 1
+  } N32_4x8路Order;
+
+  typedef N32_4x8路T *( *N32_4x8路Allocate_MemoryFault )(Extent);
+
+  //----------------------------------------
+  // Interface
+
+  typedef struct{
+
+    N32_4x8路T *(*allocate_array_zero)(Extent, N32_4x8路Allocate_MemoryFault);
+    N32_4x8路T *(*allocate_array)(Extent, N32_4x8路Allocate_MemoryFault);
+    void (*deallocate)(N32_4x8路T*);
+
+    void (*copy)(N32_4x8路T*, N32_4x8路T*);
+    void (*bit_and)(N32_4x8路T*, N32_4x8路T*, N32_4x8路T*);
+    void (*bit_or)(N32_4x8路T*, N32_4x8路T*, N32_4x8路T*);
+    void (*bit_complement)(N32_4x8路T*, N32_4x8路T*);
+    void (*bit_twos_complement)(N32_4x8路T*, N32_4x8路T*);
+    N32_4x8路Order (*compare)(N32_4x8路T*, N32_4x8路T*);
+    bool (*lt)(N32_4x8路T*, N32_4x8路T*);
+    bool (*gt)(N32_4x8路T*, N32_4x8路T*);
+    bool (*eq)(N32_4x8路T*, N32_4x8路T*);
+    bool (*eq_zero)(N32_4x8路T*);
+    N32_4x8路Status (*accumulate)(N32_4x8路T *accumulator1 ,N32_4x8路T *accumulator0 ,...);
+    N32_4x8路Status (*add)(N32_4x8路T*, N32_4x8路T*, N32_4x8路T*);
+    bool (*increment)(N32_4x8路T *a);
+    N32_4x8路Status (*subtract)(N32_4x8路T*, N32_4x8路T*, N32_4x8路T*);
+    N32_4x8路Status (*multiply)(N32_4x8路T*, N32_4x8路T*, N32_4x8路T*, N32_4x8路T*);
+    N32_4x8路Status (*divide)(N32_4x8路T*, N32_4x8路T*, N32_4x8路T*, N32_4x8路T*);
+    N32_4x8路Status (*modulus)(N32_4x8路T*, N32_4x8路T*, N32_4x8路T*);
+    N32_4x8路Status (*shift_left)(Extent, N32_4x8路T*, N32_4x8路T*, N32_4x8路T*);
+    N32_4x8路Status (*shift_right)(Extent, N32_4x8路T*, N32_4x8路T*, N32_4x8路T*);
+    N32_4x8路Status (*arithmetic_shift_right)(Extent, N32_4x8路T*, N32_4x8路T*);
+
+    N32_4x8路T* (*access)(N32_4x8路T*, Extent);
+    void (*from_uint32)(N32_4x8路T *destination ,uint32_t value);
+  } N32_4x8路螞;
+
+  Local const N32_4x8路螞 N32_4x8路位; // initialized in the LOCAL section
+
+#endif
+
+//--------------------------------------------------------------------------------
+// Implementation
+
+#ifdef N32_4x8路IMPLEMENTATION
+
+  // this part goes into the library
+  #ifndef LOCAL
+
+    #include <stdarg.h>
+    #include <stdlib.h>
+
+    struct N32_4x8路T{
+      Digit d0;
+    };
+
+    N32_4x8路T N32_4x8路constant[4] = {
+      {.d0 = 0},
+      {.d0 = 1},
+      {.d0 = ~(uint32_t)0},
+      {.d0 = 1 << 31}
+    };
+
+    N32_4x8路T *N32_4x8路zero = &N32_4x8路constant[0];
+    N32_4x8路T *N32_4x8路one = &N32_4x8路constant[1];
+    N32_4x8路T *N32_4x8路all_one_bit = &N32_4x8路constant[2];
+    N32_4x8路T *N32_4x8路msb = &N32_4x8路constant[3];
+    N32_4x8路T *N32_4x8路lsb = &N32_4x8路constant[1];
+
+    // the allocate an array of N32
+    N32_4x8路T *N32_4x8路allocate_array(Extent extent ,N32_4x8路Allocate_MemoryFault memory_fault){
+      N32_4x8路T *instance = malloc((extent + 1) * sizeof(N32_4x8路T) );
+      if(!instance){
+        return memory_fault ? memory_fault(extent) : NULL;
+      }
+      return instance;
+    }
+
+    N32_4x8路T *N32_4x8路allocate_array_zero(Extent extent ,N32_4x8路Allocate_MemoryFault memory_fault){
+      N32_4x8路T *instance = calloc( extent + 1 ,sizeof(N32_4x8路T) );
+      if(!instance){
+        return memory_fault ? memory_fault(extent) : NULL;
+      }
+      return instance;
+    }
+
+    void N32_4x8路deallocate(N32_4x8路T *unencumbered){
+      free(unencumbered);
+    }
+
+  #endif
+
+  // This part is included after the library user's code
+  #ifdef LOCAL
+
+    // instance
+
+    struct N32_4x8路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_4x8路T N32_4x8路t[4];
+
+
+    // allocation 
+
+    extern N32_4x8路T *N32_4x8路allocate_array(Extent, N32_4x8路Allocate_MemoryFault);
+    extern N32_4x8路T *N32_4x8路allocate_array_zero(Extent, N32_4x8路Allocate_MemoryFault);
+    extern void N32_4x8路deallocate(N32_4x8路T *);
+
+    // so the user can access numbers in an array allocation
+    Local N32_4x8路T* N32_4x8路access(N32_4x8路T *array ,Extent index){
+      return &array[index];
+    }
+
+    Local void N32_4x8路from_uint32(N32_4x8路T *destination ,uint32_t value){
+      if(destination == NULL) return;
+      destination->d0 = value;
+    }
+
+    // copy, convenience copy
+
+    Local void N32_4x8路copy(N32_4x8路T *destination ,N32_4x8路T *source){
+      if(source == destination) return; // that was easy! 
+      *destination = *source;
+    }
+
+    Local void N32_4x8路set_to_zero(N32_4x8路T *instance){
+      instance->d0 = 0;
+    }
+
+    Local void N32_4x8路set_to_one(N32_4x8路T *instance){
+      instance->d0 = 1;
+    }
+
+    // bit operations
+
+    Local void N32_4x8路bit_and(N32_4x8路T *result, N32_4x8路T *a, N32_4x8路T *b){
+      result->d0 = a->d0 & b->d0;
+    }
+
+    // result can be one of the operands
+    Local void N32_4x8路bit_or(N32_4x8路T *result, N32_4x8路T *a, N32_4x8路T *b){
+      result->d0 = a->d0 | b->d0;
+    }
+
+    // result can the same as the operand
+    Local void N32_4x8路bit_complement(N32_4x8路T *result, N32_4x8路T *a){
+      result->d0 = ~a->d0;
+    }
+
+    // result can the same as the operand
+    Local void N32_4x8路bit_twos_complement(N32_4x8路T *result ,N32_4x8路T *a){
+      result->d0 = ~a->d0 + 1;
+    }
+
+    // test functions
+
+    Local N32_4x8路Order N32_4x8路compare(N32_4x8路T *a, N32_4x8路T *b){
+      if(a->d0 < b->d0) return N32_4x8路Order_lt;
+      if(a->d0 > b->d0) return N32_4x8路Order_gt;
+      return N32_4x8路Order_eq;
+    }
+
+    Local bool N32_4x8路lt(N32_4x8路T *a ,N32_4x8路T *b){
+      return  a->d0 < b->d0;
+    }    
+
+    Local bool N32_4x8路gt(N32_4x8路T *a ,N32_4x8路T *b){
+      return  a->d0 > b->d0;
+    }    
+
+    Local bool N32_4x8路eq(N32_4x8路T *a ,N32_4x8路T *b){
+      return  a->d0 == b->d0;
+    }    
+
+    Local bool N32_4x8路eq_zero(N32_4x8路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_4x8路Status路accumulator1_overflow
+    //
+    // When accumulator1 and accumulator0 point to the same location, the result is the accumulator1 value.
+    Local N32_4x8路Status N32_4x8路accumulate(N32_4x8路T *accumulator1 ,N32_4x8路T *accumulator0 ,...){
+
+      va_list args;
+      va_start(args ,accumulator0);
+      uint32_t sum = accumulator0->d0;
+      uint32_t carry = 0;
+      N32_4x8路T *current;
+
+      while( (current = va_arg(args ,N32_4x8路T *)) ){
+        sum += current->d0;
+        if(sum < current->d0){  // Accumulator1 into carry
+          (carry)++;
+          if(carry == 0){
+            va_end(args);
+            return N32_4x8路Status路accumulator1_overflow;
+          }
+        }
+      }
+      va_end(args);
+
+      // wipes out prior value of accumulator1
+      accumulator1->d0 = carry;
+
+      return N32_4x8路Status路ok;
+    }
+
+    Local N32_4x8路Status N32_4x8路add(N32_4x8路T *sum ,N32_4x8路T *a ,N32_4x8路T *b){
+      uint64_t result = (uint64_t)a->d0 + (uint64_t)b->d0;
+      sum->d0 = (uint32_t)result;
+      return (result >> 32) ? N32_4x8路Status路carry : N32_4x8路Status路ok;
+    }
+
+    Local bool N32_4x8路increment(N32_4x8路T *a){
+      a->d0++;
+      return a->d0 == 0;
+    }
+
+    Local N32_4x8路Status N32_4x8路subtract(N32_4x8路T *difference ,N32_4x8路T *a ,N32_4x8路T *b){
+      uint64_t diff = (uint64_t) a->d0 - (uint64_t) b->d0;
+      difference->d0 = (uint32_t)diff;
+      return (diff > a->d0) ? N32_4x8路Status路borrow : N32_4x8路Status路ok;
+    }
+
+
+    Local N32_4x8路Status N32_4x8路multiply(N32_4x8路T *product1 ,N32_4x8路T *product0 ,N32_4x8路T *a ,N32_4x8路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_4x8路Status路one_word_product;
+      return N32_4x8路Status路two_word_product;
+    }
+
+    Local N32_4x8路Status N32_4x8路divide(N32_4x8路T *remainder ,N32_4x8路T *quotient ,N32_4x8路T *a ,N32_4x8路T *b){
+      if(b->d0 == 0) return N32_4x8路Status路undefined_divide_by_zero; 
+
+      quotient->d0 = a->d0 / b->d0;
+      remainder->d0 = a->d0 - (quotient->d0 * b->d0);
+
+      return N32_4x8路Status路ok;
+    }
+
+    Local N32_4x8路Status N32_4x8路modulus(N32_4x8路T *remainder ,N32_4x8路T *a ,N32_4x8路T *b){
+      if(b->d0 == 0) return N32_4x8路Status路undefined_modulus_zero; 
+      uint32_t quotient = a->d0 / b->d0;
+      remainder->d0 = a->d0 - (quotient * b->d0);
+      return N32_4x8路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_4x8路Status N32_4x8路shift
+    (
+     uint32_t shift_count
+     ,N32_4x8路T *spill
+     ,N32_4x8路T *operand
+     ,N32_4x8路T *fill
+     ,ShiftOp shift_op
+     ,ShiftOp complement_shift_op
+     ){
+
+      // If no result is needed, return immediately.
+      if(operand == NULL && spill == NULL) return N32_4x8路Status路ok;
+
+      // Treat NULL operand as zero.
+      if(operand == NULL){
+        operand = &N32_4x8路t[0];
+        N32_4x8路copy(operand, N32_4x8路zero);
+      }
+
+      // Shifting more than one word breaks our fill/spill model.
+      if(shift_count > 31) return N32_4x8路Status路gt_max_shift_count;
+
+      // The given operand is still required after it is modified, so we copy it.
+      N32_4x8路T *given_operand = &N32_4x8路t[1];
+      N32_4x8路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_4x8路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_4x8路Status路ok;
+    }
+
+    // Define concrete shift functions using valid C function pointers
+    Local N32_4x8路Status 
+    N32_4x8路shift_left(uint32_t shift_count, N32_4x8路T *spill, N32_4x8路T *operand, N32_4x8路T *fill){
+      return N32_4x8路shift(shift_count, spill, operand, fill, shift_left_op, shift_right_op);
+    }
+
+    Local N32_4x8路Status 
+    N32_4x8路shift_right(uint32_t shift_count, N32_4x8路T *spill, N32_4x8路T *operand, N32_4x8路T *fill){
+      return N32_4x8路shift(shift_count, spill, operand, fill, shift_right_op, shift_left_op);
+    }
+
+    Local N32_4x8路Status 
+    N32_4x8路arithmetic_shift_right(uint32_t shift_count, N32_4x8路T *operand, N32_4x8路T *spill){
+
+      // Guard against excessive shift counts
+      if(shift_count > 31) return N32_4x8路Status路gt_max_shift_count;
+
+      // A NULL operand is treated as zero
+      if(operand == NULL){
+        operand = &N32_4x8路t[0];
+        N32_4x8路copy(operand, N32_4x8路zero);
+      }
+
+      // Pick the fill value based on the sign bit
+      N32_4x8路T *fill = (operand->d0 & 0x80000000) ? N32_4x8路all_one_bit : N32_4x8路zero;
+
+      // Call shift_right with the appropriate fill
+      return N32_4x8路shift_right(shift_count, spill, operand, fill);
+    }
+
+    Local const N32_4x8路螞 N32_4x8路位 = {
+
+      .allocate_array = N32_4x8路allocate_array
+      ,.allocate_array_zero = N32_4x8路allocate_array_zero
+      ,.deallocate = N32_4x8路deallocate
+
+      ,.copy = N32_4x8路copy
+      ,.bit_and = N32_4x8路bit_and
+      ,.bit_or = N32_4x8路bit_or
+      ,.bit_complement = N32_4x8路bit_complement
+      ,.bit_twos_complement = N32_4x8路bit_twos_complement
+      ,.compare = N32_4x8路compare
+      ,.lt = N32_4x8路lt
+      ,.gt = N32_4x8路gt
+      ,.eq = N32_4x8路eq
+      ,.eq_zero = N32_4x8路eq_zero
+      ,.accumulate = N32_4x8路accumulate
+      ,.add = N32_4x8路add
+      ,.increment = N32_4x8路increment
+      ,.subtract = N32_4x8路subtract
+      ,.multiply = N32_4x8路multiply
+      ,.divide = N32_4x8路divide
+      ,.modulus = N32_4x8路modulus
+      ,.shift_left = N32_4x8路shift_left
+      ,.shift_right = N32_4x8路shift_right
+      ,.arithmetic_shift_right = N32_4x8路arithmetic_shift_right
+
+      ,.access = N32_4x8路access
+      ,.from_uint32 = N32_4x8路from_uint32
+    };
+
+  #endif
+
+#endif
diff --git a/tester/cc/test_N32PN.cli.c b/tester/cc/test_N32PN.cli.c
deleted file mode 100644 (file)
index e17581a..0000000
+++ /dev/null
@@ -1,364 +0,0 @@
-#include <stdio.h>
-#include <stdbool.h>
-#include <signal.h>
-#include <setjmp.h>
-
-// Enable interface section
-#define FACE
-#include "N32PN.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
-  N32PN路T *array = N32PN路位.allocate_array(2 ,NULL);
-  if( !array ) return false;
-
-  // Access elements via access function
-  N32PN路T *a = N32PN路位.access(array ,0);
-  N32PN路T *b = N32PN路位.access(array ,1);
-
-  // Assign value and copy
-  N32PN路位.from_uint32(a ,42);
-  N32PN路位.copy(b ,a);
-
-  bool success = ( N32PN路位.compare(b ,a) == N32PN路Order_eq );
-  N32PN路位.deallocate(array);
-  return success;
-}
-
-bool test_arithmetic(){
-  // Allocate memory
-  N32PN路T *array = N32PN路位.allocate_array(3 ,NULL);
-  if( !array ) return false;
-
-  N32PN路T *a = N32PN路位.access(array ,0);
-  N32PN路T *b = N32PN路位.access(array ,1);
-  N32PN路T *result = N32PN路位.access(array ,2);
-
-  N32PN路位.from_uint32(a ,20);
-  N32PN路位.from_uint32(b ,22);
-
-  if( N32PN路位.add(result ,a ,b) != N32PN路Status路ok ) return false;
-  if( N32PN路位.compare(result ,N32PN路位.access(array ,0)) != N32PN路Order_gt ) return false;
-
-  if( N32PN路位.subtract(result ,b ,a) != N32PN路Status路ok ) return false;
-  if( N32PN路位.compare(result ,N32PN路位.access(array ,0)) != N32PN路Order_lt ) return false;
-
-  N32PN路位.deallocate(array);
-  return true;
-}
-
-bool test_bitwise_operations(){
-  // Allocate memory
-  N32PN路T *array = N32PN路位.allocate_array(3, NULL);
-  if(!array) return false;
-
-  N32PN路T *a = N32PN路位.access(array, 0);
-  N32PN路T *b = N32PN路位.access(array, 1);
-  N32PN路T *result = N32PN路位.access(array, 2);
-
-  // a = 0x0F0F0F0F, b = 0xF0F0F0F0
-  N32PN路位.from_uint32(a, 0x0F0F0F0F);
-  N32PN路位.from_uint32(b, 0xF0F0F0F0);
-
-  // bit_and => expect 0x00000000
-  N32PN路位.bit_and(result, a, b);
-  N32PN路位.from_uint32(a, 0x00000000);
-  if(N32PN路位.compare(result, a) != N32PN路Order_eq){
-    N32PN路位.deallocate(array);
-    return false;
-  }
-
-  // Reset a to 0x0F0F0F0F for next tests
-  N32PN路位.from_uint32(a, 0x0F0F0F0F);
-
-  // bit_or => expect 0xFFFFFFFF
-  N32PN路位.bit_or(result, a, b);
-  N32PN路位.from_uint32(b, 0xFFFFFFFF);
-  if(N32PN路位.compare(result, b) != N32PN路Order_eq){
-    N32PN路位.deallocate(array);
-    return false;
-  }
-
-  // bit_complement(a=0x0F0F0F0F) => expect 0xF0F0F0F0
-  N32PN路位.from_uint32(a, 0x0F0F0F0F);
-  N32PN路位.bit_complement(result, a);
-  N32PN路位.from_uint32(b, 0xF0F0F0F0);
-  if(N32PN路位.compare(result, b) != N32PN路Order_eq){
-    N32PN路位.deallocate(array);
-    return false;
-  }
-
-  // bit_twos_complement(a=0x0F0F0F0F) => expect 0xF0F0F0F1
-  N32PN路位.from_uint32(a, 0x0F0F0F0F);
-  N32PN路位.bit_twos_complement(result, a);
-  N32PN路位.from_uint32(b, 0xF0F0F0F1);
-  if(N32PN路位.compare(result, b) != N32PN路Order_eq){
-    N32PN路位.deallocate(array);
-    return false;
-  }
-
-  N32PN路位.deallocate(array);
-  return true;
-}
-
-bool test_comparisons(){
-  // Allocate memory
-  N32PN路T *array = N32PN路位.allocate_array(3, NULL);
-  if(!array) return false;
-
-  N32PN路T *a = N32PN路位.access(array, 0);
-  N32PN路T *b = N32PN路位.access(array, 1);
-  N32PN路T *c = N32PN路位.access(array, 2);
-
-  // First set: a=0, b=42, c=42
-  N32PN路位.from_uint32(a, 0);
-  N32PN路位.from_uint32(b, 42);
-  N32PN路位.from_uint32(c, 42);
-
-  // eq_zero(a) => true
-  if(!N32PN路位.eq_zero(a)){
-    N32PN路位.deallocate(array);
-    return false;
-  }
-  // eq_zero(b) => false
-  if(N32PN路位.eq_zero(b)){
-    N32PN路位.deallocate(array);
-    return false;
-  }
-  // eq(b, c) => true
-  if(!N32PN路位.eq(b, c)){
-    N32PN路位.deallocate(array);
-    return false;
-  }
-  // eq(a, b) => false
-  if(N32PN路位.eq(a, b)){
-    N32PN路位.deallocate(array);
-    return false;
-  }
-  // compare(a, b) => N32PN路Order_lt
-  if(N32PN路位.compare(a, b) != N32PN路Order_lt){
-    N32PN路位.deallocate(array);
-    return false;
-  }
-  // compare(b, a) => N32PN路Order_gt
-  if(N32PN路位.compare(b, a) != N32PN路Order_gt){
-    N32PN路位.deallocate(array);
-    return false;
-  }
-  // compare(b, c) => N32PN路Order_eq
-  if(N32PN路位.compare(b, c) != N32PN路Order_eq){
-    N32PN路位.deallocate(array);
-    return false;
-  }
-  // lt(a, b) => true, gt(b, a) => true
-  if(!N32PN路位.lt(a, b) || !N32PN路位.gt(b, a)){
-    N32PN路位.deallocate(array);
-    return false;
-  }
-
-  // Second set: a=100, b=50
-  N32PN路位.from_uint32(a, 100);
-  N32PN路位.from_uint32(b, 50);
-  if(N32PN路位.compare(a, b) != N32PN路Order_gt){
-    N32PN路位.deallocate(array);
-    return false;
-  }
-  // eq_zero(a) => false
-  if(N32PN路位.eq_zero(a)){
-    N32PN路位.deallocate(array);
-    return false;
-  }
-  // eq_zero(b) => false
-  if(N32PN路位.eq_zero(b)){
-    N32PN路位.deallocate(array);
-    return false;
-  }
-
-  N32PN路位.deallocate(array);
-  return true;
-}
-
-bool test_shifts(){
-  // Allocate memory for operand, fill, spill
-  N32PN路T *array = N32PN路位.allocate_array(3, NULL);
-  if(!array) return false;
-
-  N32PN路T *operand = N32PN路位.access(array, 0);
-  N32PN路T *fill    = N32PN路位.access(array, 1);
-  N32PN路T *spill   = N32PN路位.access(array, 2);
-
-  // Subtest A: shift_left(4) with operand=1 => expect operand=16, fill=0, spill=0
-  N32PN路位.from_uint32(operand, 1);
-  N32PN路位.from_uint32(fill, 0);
-  N32PN路位.from_uint32(spill, 0);
-  if(N32PN路位.shift_left(4, spill, operand, fill) != N32PN路Status路ok){
-    N32PN路位.deallocate(array);
-    return false;
-  }
-  N32PN路T *temp = N32PN路位.allocate_array(1, NULL);
-  if(!temp){
-    N32PN路位.deallocate(array);
-    return false;
-  }
-  N32PN路位.from_uint32(temp, 16);
-  if(N32PN路位.compare(operand, temp) != N32PN路Order_eq){
-    N32PN路位.deallocate(temp);
-    N32PN路位.deallocate(array);
-    return false;
-  }
-  if(N32PN路位.compare(fill, N32PN路zero) != N32PN路Order_eq){
-    N32PN路位.deallocate(temp);
-    N32PN路位.deallocate(array);
-    return false;
-  }
-  if(N32PN路位.compare(spill, N32PN路zero) != N32PN路Order_eq){
-    N32PN路位.deallocate(temp);
-    N32PN路位.deallocate(array);
-    return false;
-  }
-
-  // Subtest B: shift_left(1) with operand=0x80000000 => expect operand=0, spill=1
-  N32PN路位.from_uint32(operand, 0x80000000);
-  N32PN路位.from_uint32(fill, 0);
-  N32PN路位.from_uint32(spill, 0);
-  if(N32PN路位.shift_left(1, spill, operand, fill) != N32PN路Status路ok){
-    N32PN路位.deallocate(temp);
-    N32PN路位.deallocate(array);
-    return false;
-  }
-  if(!N32PN路位.eq_zero(operand)){
-    N32PN路位.deallocate(temp);
-    N32PN路位.deallocate(array);
-    return false;
-  }
-  N32PN路位.from_uint32(temp, 1);
-  if(N32PN路位.compare(spill, temp) != N32PN路Order_eq){
-    N32PN路位.deallocate(temp);
-    N32PN路位.deallocate(array);
-    return false;
-  }
-
-  // Subtest C: shift_right(1) with operand=0x80000000 => expect operand=0x40000000, spill=0
-  N32PN路位.from_uint32(operand, 0x80000000);
-  N32PN路位.from_uint32(fill, 0);
-  N32PN路位.from_uint32(spill, 0);
-  if(N32PN路位.shift_right(1, spill, operand, fill) != N32PN路Status路ok){
-    N32PN路位.deallocate(temp);
-    N32PN路位.deallocate(array);
-    return false;
-  }
-  N32PN路位.from_uint32(temp, 0x40000000);
-  if(N32PN路位.compare(operand, temp) != N32PN路Order_eq){
-    N32PN路位.deallocate(temp);
-    N32PN路位.deallocate(array);
-    return false;
-  }
-  if(!N32PN路位.eq_zero(spill)){
-    N32PN路位.deallocate(temp);
-    N32PN路位.deallocate(array);
-    return false;
-  }
-
-  // Subtest D: arithmetic_shift_right(1) with operand=0x80000000 => expect operand=0xC0000000, spill=0
-  N32PN路位.from_uint32(operand, 0x80000000);
-  N32PN路位.from_uint32(spill, 0);
-  if(N32PN路位.arithmetic_shift_right(1, operand, spill) != N32PN路Status路ok){
-    N32PN路位.deallocate(temp);
-    N32PN路位.deallocate(array);
-    return false;
-  }
-  N32PN路位.from_uint32(temp, 0xC0000000);
-  if(N32PN路位.compare(operand, temp) != N32PN路Order_eq){
-    N32PN路位.deallocate(temp);
-    N32PN路位.deallocate(array);
-    return false;
-  }
-  if(!N32PN路位.eq_zero(spill)){
-    N32PN路位.deallocate(temp);
-    N32PN路位.deallocate(array);
-    return false;
-  }
-
-  N32PN路位.deallocate(temp);
-  N32PN路位.deallocate(array);
-  return true;
-}
-
-
-
-// Include the local section of N32PN.lib.c for testing
-#define LOCAL
-#include "N32PN.lib.c"
-#undef LOCAL
diff --git a/tester/python/#fill_templates.py# b/tester/python/#fill_templates.py#
deleted file mode 100644 (file)
index 95519a3..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/usr/bin/env python3
-
-import sys
-from template_test_N32 import test_N32
-
-def write(code ,basename):
-    filepath = "../cc/" + "test_" + basename + ".cli.c" 
-    with open(filepath, "w") as f:
-      f.write(code)
-    print("Generated " + filepath)
-    
-
-def main():
-    """
-    generates `.c` source code from templates
-    """
-
-    # base line test N32 test
-    type_name = "N32PN"
-    code = test_N32(namespace = type_name)
-    write(code ,type_name);
-
-if __name__ == "__main__":
-    main()
index 95519a3..573f570 100755 (executable)
@@ -20,5 +20,12 @@ def main():
     code = test_N32(namespace = type_name)
     write(code ,type_name);
 
+    # a single digit N32
+    type_name = "N32"
+    code = test_N32(namespace = type_name)
+    write(code ,type_name);
+
+
+
 if __name__ == "__main__":
     main()
diff --git a/tester/tool馃枆/release_clean b/tester/tool馃枆/release_clean
deleted file mode 100755 (executable)
index 2e0da45..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/usr/bin/env bash
-script_afp=$(realpath "${BASH_SOURCE[0]}")
-
-# input guards
-
-  env_must_be="tester/tool馃枆/env"
-  if [ "$ENV" != "$env_must_be" ]; then
-    echo "$(script_fp):: error: must be run in the $env_must_be environment"
-    exit 1
-  fi
-
-set -e
-set -x
-
-
-cd "$REPO_HOME"/tester || exit 1
-
-# remove library pulled from release and other scratchpad files
-  rm_na -rf scratchpad/* || true
-
-# remove cc files pulled from release
-  rm_na -f cc/* || true
-
-# remove built executables
-  rm_na -f machine/* || true
-
-set +x
-echo "$(script_fn) done."
diff --git a/tester/tool馃枆/release_remove b/tester/tool馃枆/release_remove
new file mode 100755 (executable)
index 0000000..2e0da45
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/env bash
+script_afp=$(realpath "${BASH_SOURCE[0]}")
+
+# input guards
+
+  env_must_be="tester/tool馃枆/env"
+  if [ "$ENV" != "$env_must_be" ]; then
+    echo "$(script_fp):: error: must be run in the $env_must_be environment"
+    exit 1
+  fi
+
+set -e
+set -x
+
+
+cd "$REPO_HOME"/tester || exit 1
+
+# remove library pulled from release and other scratchpad files
+  rm_na -rf scratchpad/* || true
+
+# remove cc files pulled from release
+  rm_na -f cc/* || true
+
+# remove built executables
+  rm_na -f machine/* || true
+
+set +x
+echo "$(script_fn) done."
index 51abf9f..5934da2 100755 (executable)
@@ -1,9 +1,5 @@
 #!/bin/env bash
 script_afp=$(realpath "${BASH_SOURCE[0]}")
 
-# 0.1 pulled groovy files from GQL_to_Cypher build.gradle
-# 0.2 conversion to Java
-# 0.3 refactored, split into smaller pieces, made into package
-
-echo v0.3
+echo "N v0.1 2025-02-17"