File size: 4,344 Bytes
f7ccd08 32b4893 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 | { SPDX-License-Identifier: LicenseRef-Sovereign-Leviathan-SL-AGPL3-001
Licensing: see LICENSE in the repository root. }
{ Materialization Barrier: Copy-on-write with governance state restoration.
Restores B_layout=1 and B_own=1 by copying viewed elements to contiguous buffer.
Algorithm:
1. Check if already materialized (B_layout=1 AND B_own=1): return OK
2. Allocate new contiguous buffer of size len(t)
3. Copy viewed elements in row-major order using strides
4. Increment generation on new buffer
5. Replace old buffer reference with new buffer
6. Reset strides to canonical
7. Set B_layout=1, B_own=1
Governance Property: "Preserving order, strict and bound"
}
unit materialize;
{$MODE FPC}
interface
uses
descriptor, buffer, tensor_array;
type
{ Materialization result }
TMaterializationResult = record
success: boolean;
old_generation: uint32;
new_generation: uint32;
copied_elements: uint32;
end;
{ Materialize a tensor array in-place }
function MaterializeTensorArray(
var arr: TTensorArray;
const desc: TTensorDescriptor
): TMaterializationResult;
{ Copy viewed elements in row-major order }
procedure CopyViewedElements(
const desc: TTensorDescriptor;
src_data: ^single;
dst_data: ^single
);
{ Compute row-major index from multi-dimensional coordinate }
function ComputeRowMajorIndex(
const desc: TTensorDescriptor;
coord: array of uint32
): uint32;
{ Materialize with strict bounds checking }
function MaterializeStrict(
var arr: TTensorArray;
const desc: TTensorDescriptor
): TMaterializationResult;
implementation
procedure CopyViewedRecursive(
const desc: TTensorDescriptor;
src_data: ^single;
dst_data: ^single;
var dst_idx: uint32;
dim: uint32;
current_offset: uint32
);
var
i: uint32;
begin
if dim = desc.rank then
begin
if current_offset < desc.len then
dst_data^[dst_idx] := src_data^[current_offset];
inc(dst_idx);
end
else
begin
for i := 0 to desc.shape_ptr^[dim] - 1 do
CopyViewedRecursive(
desc, src_data, dst_data, dst_idx, dim + 1,
current_offset + i * desc.strides_ptr^[dim]
);
end;
end;
procedure CopyViewedElements(
const desc: TTensorDescriptor;
src_data: ^single;
dst_data: ^single
);
var
dst_idx: uint32;
begin
dst_idx := 0;
CopyViewedRecursive(desc, src_data, dst_data, dst_idx, 0, desc.offset);
end;
function ComputeRowMajorIndex(
const desc: TTensorDescriptor;
coord: array of uint32
): uint32;
var
i: uint32;
begin
result := 0;
for i := 0 to desc.rank - 1 do
result := result + coord[i] * desc.strides_ptr^[i];
end;
function MaterializeTensorArray(
var arr: TTensorArray;
const desc: TTensorDescriptor
): TMaterializationResult;
var
new_buf: PBuffer;
new_data: ^single;
begin
with result do
begin
success := false;
old_generation := 0;
new_generation := 0;
copied_elements := 0;
if arr.buffer = nil then
exit;
{ Check if already materialized }
if (desc.is_contiguous = 1) and (desc.owns_storage = 1) then
begin
success := true;
old_generation := arr.buffer^.generation;
new_generation := arr.buffer^.generation;
copied_elements := 0;
exit;
end;
{ Allocate new contiguous buffer }
new_buf := AllocateBuffer(desc.len);
if new_buf = nil then
exit;
new_data := new_buf^.data;
{ Copy viewed elements in row-major order }
CopyViewedElements(desc, arr.buffer^.data, new_data);
old_generation := arr.buffer^.generation;
new_generation := new_buf^.generation;
copied_elements := desc.len;
{ Release old buffer (may free if refcount becomes 0) }
ReleaseBuffer(arr.buffer);
{ Adopt new buffer }
arr.buffer := new_buf;
arr.generation := new_buf^.generation;
success := true;
end;
end;
function MaterializeStrict(
var arr: TTensorArray;
const desc: TTensorDescriptor
): TMaterializationResult;
begin
{ Perform strict bounds checking before materialization }
if (desc.len = 0) or (arr.buffer = nil) or (arr.buffer^.size = 0) then
begin
result.success := false;
result.old_generation := 0;
result.new_generation := 0;
result.copied_elements := 0;
exit;
end;
{ Materialize }
result := MaterializeTensorArray(arr, desc);
end;
end.
|