3 % Copyright
2006-2010 Taco Hoekwater
<taco@@luatex.org
>
5 % This file is part of LuaTeX.
7 % LuaTeX is free software
; you can redistribute it and
/or modify it under
8 % the terms of the GNU General Public License as published by the Free
9 % Software Foundation
; either version
2 of the License
, or
(at your
10 % option
) any later version.
12 % LuaTeX is distributed in the hope that it will be useful
, but WITHOUT
13 % ANY WARRANTY
; without even the implied warranty of MERCHANTABILITY or
14 % FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 % License for more details.
17 % You should have received a copy of the GNU General Public License along
18 % with LuaTeX
; if not
, see
<http
://www.gnu.org
/licenses
/>.
20 @
* Sparse arrays with an embedded save stack.
22 These functions are called very often but a few days of experimenting proved that
23 there is not much to gain
(if at all
) from using macros or optimizations like
24 preallocating and fast access to the first
128 entries. In practice the overhead
25 is mostly in accessing memory and not in
(probably inlined
) calls. So
, we should
26 accept fate and wait for faster memory. It's the price we pay for being unicode
27 on the one hand and sparse on the other.
34 static void store_sa_stack
(sa_tree a
, int n
, sa_tree_item v
, int gl
)
40 if
(a-
>stack
== NULL) {
41 a-
>stack
= Mxmalloc_array
(sa_stack_item
, a-
>stack_size
);
42 } else if
(((a-
>stack_ptr
) + 1) >= a-
>stack_size
) {
43 a-
>stack_size
+= a-
>stack_step
;
44 a-
>stack
= Mxrealloc_array
(a-
>stack
, sa_stack_item
, a-
>stack_size
);
47 a-
>stack
[a-
>stack_ptr
] = st
;
51 static void skip_in_stack
(sa_tree a
, int n
)
57 if
(a-
>stack
[p
].code
== n
&& a->stack[p].level > 0) {
58 a-
>stack
[p
].level
= -(a-
>stack
[p
].level
);
65 sa_tree_item get_sa_item
(const sa_tree head
, const int n
)
67 if
(head-
>tree
!= NULL) {
68 register int h
= HIGHPART_PART
(n
);
69 if
(head-
>tree
[h
] != NULL) {
70 register int m
= MIDPART_PART
(n
);
71 if
(head-
>tree
[h
][m
] != NULL) {
72 return head-
>tree
[h
][m
][LOWPART_PART
(n
)];
80 void set_sa_item
(sa_tree head
, int n
, sa_tree_item v
, int gl
)
82 int h
= HIGHPART_PART
(n
);
83 int m
= MIDPART_PART
(n
);
84 int l
= LOWPART_PART
(n
);
85 if
(head-
>tree
== NULL) {
86 head-
>tree
= (sa_tree_item
***) Mxcalloc_array
(sa_tree_item
**, HIGHPART
);
88 if
(head-
>tree
[h
] == NULL) {
89 head-
>tree
[h
] = (sa_tree_item
**) Mxcalloc_array
(sa_tree_item
*, MIDPART
);
91 if
(head-
>tree
[h
][m
] == NULL) {
93 head-
>tree
[h
][m
] = (sa_tree_item
*) Mxmalloc_array
(sa_tree_item
, LOWPART
);
94 for
(i
= 0; i
< LOWPART
; i
++) {
95 head-
>tree
[h
][m
][i
] = head-
>dflt
;
99 skip_in_stack
(head
, n
);
101 store_sa_stack
(head
, n
, head-
>tree
[h
][m
][l
], gl
);
103 head-
>tree
[h
][m
][l
] = v
;
107 void rawset_sa_item
(sa_tree head
, int n
, sa_tree_item v
)
109 head-
>tree
[HIGHPART_PART
(n
)][MIDPART_PART
(n
)][LOWPART_PART
(n
)] = v
;
113 void clear_sa_stack
(sa_tree a
)
117 a-
>stack_size
= a-
>stack_step
;
121 void destroy_sa_tree
(sa_tree a
)
125 if
(a-
>tree
!= NULL) {
127 for
(h
= 0; h
< HIGHPART
; h
++) {
128 if
(a-
>tree
[h
] != NULL) {
129 for
(m
= 0; m
< MIDPART
; m
++) {
130 xfree
(a-
>tree
[h
][m
]);
142 sa_tree copy_sa_tree
(sa_tree b
)
144 sa_tree a
= (sa_tree
) Mxmalloc_array
(sa_tree_head
, 1);
145 a-
>stack_step
= b-
>stack_step
;
146 a-
>stack_size
= b-
>stack_size
;
147 a-
>stack_type
= b-
>stack_type
;
152 if
(b-
>tree
!= NULL) {
154 a-
>tree
= (sa_tree_item
***) Mxcalloc_array
(void
*, HIGHPART
);
155 for
(h
= 0; h
< HIGHPART
; h
++) {
156 if
(b-
>tree
[h
] != NULL) {
157 a-
>tree
[h
] = (sa_tree_item
**) Mxcalloc_array
(void
*, MIDPART
);
158 for
(m
= 0; m
< MIDPART
; m
++) {
159 if
(b-
>tree
[h
][m
] != NULL) {
160 a-
>tree
[h
][m
] = Mxmalloc_array
(sa_tree_item
, LOWPART
);
161 memcpy
(a-
>tree
[h
][m
], b-
>tree
[h
][m
],
162 sizeof
(sa_tree_item
) * LOWPART
);
171 @ The main reason to fill in the lowest entry branches here immediately
172 is that most of the sparse arrays have a bias toward ASCII values.
174 Allocating those here immediately improves the chance of the structure
175 |a-
>tree
[0][0][x
]| being close together in actual memory locations
179 /* we could save less for type
0 stacks
*/
181 sa_tree new_sa_tree
(int size
, int type
, sa_tree_item dflt
)
184 a
= (sa_tree_head
*) xmalloc
(sizeof
(sa_tree_head
));
187 a-
>tree
= (sa_tree_item
***) Mxcalloc_array
(sa_tree_item
**, HIGHPART
);
188 a-
>tree
[0] = (sa_tree_item
**) Mxcalloc_array
(sa_tree_item
*, MIDPART
);
189 a-
>stack_size
= size
;
190 a-
>stack_step
= size
;
191 a-
>stack_type
= type
;
193 /* printf
("creating sa tree of type %d\n",type
); */
198 void restore_sa_stack
(sa_tree head
, int gl
)
201 if
(head-
>stack
== NULL)
203 while
(head-
>stack_ptr
> 0 && abs(head->stack[head->stack_ptr].level) >= gl) {
204 st
= head-
>stack
[head-
>stack_ptr
];
206 rawset_sa_item
(head
, st.code
, st.value
);
213 void dump_sa_tree
(sa_tree a
, const char
* name
)
218 dump_int
(a-
>stack_step
);
219 x
= a-
>dflt.int_value
;
221 if
(a-
>tree
!= NULL) {
222 dump_int
(1); /* marker
*/
225 /* printf
("dumping sa tree %s with type %d\n",name
,n
); */
226 for
(h
= 0; h
< HIGHPART
; h
++) {
227 if
(a-
>tree
[h
] != NULL) {
230 for
(m
= 0; m
< MIDPART
; m
++) {
231 if
(a-
>tree
[h
][m
] != NULL) {
234 for
(l
= 0; l
< LOWPART
; l
++) {
236 x
= a-
>tree
[h
][m
][l
].dump_uint.value_1
;
238 x
= a-
>tree
[h
][m
][l
].dump_uint.value_2
;
241 x
= a-
>tree
[h
][m
][l
].uint_value
;
256 dump_int
(0); /* marker
*/
261 sa_tree undump_sa_tree
(const char
* name
)
266 sa_tree a
= (sa_tree
) Mxmalloc_array
(sa_tree_head
, 1);
271 a-
>dflt.int_value
= x
;
272 a-
>stack
= Mxmalloc_array
(sa_stack_item
, a-
>stack_size
);
275 undump_int
(x
); /* marker
*/
278 a-
>tree
= (sa_tree_item
***) Mxcalloc_array
(void
*, HIGHPART
);
281 /* printf
("undumping sa tree %s with type %d\n",name
,n
); */
282 for
(h
= 0; h
< HIGHPART
; h
++) {
285 a-
>tree
[h
] = (sa_tree_item
**) Mxcalloc_array
(void
*, MIDPART
);
286 for
(m
= 0; m
< MIDPART
; m
++) {
289 a-
>tree
[h
][m
] = Mxmalloc_array
(sa_tree_item
, LOWPART
);
290 for
(l
= 0; l
< LOWPART
; l
++) {
293 a-
>tree
[h
][m
][l
].dump_uint.value_1
= x
;
295 a-
>tree
[h
][m
][l
].dump_uint.value_2
= x
;
298 a-
>tree
[h
][m
][l
].uint_value
= x
;