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.