Hi all,
Is it possible to get a reference to a hash table in maxima?
Specifically, I'm trying to write a function which will re-group an
(expanded) expression of a special form
\sum z_j e^{iwk} x^n
where x^n and e^{iwk} are not unique, to a list or a hash table, where
at the top level would be unique x^n's, and at the next level --
unique e^{iwk} terms, and at the last level -- sums of z_j's:
{
x^{n_1} => {
e^{iw_1k} => { z_1 + z_2 + ... + z_s },
e^{iw_2k} => { u_1 + u_2 + ... + u_t },
...
},
x^{n_2} => { ... },
...
}
My plan is to use hash tables to accumulate and efficiently find x^n's
and corresponding e^{iwk} terms, by simply using expressions as
indexes into undeclared arrays (i.e., hash tables).
The rough code sketch is like this:
merge_parts_by_eiwk(k, expr, B) :=
/* basic checks skipped */
block(
[eiwk, rst], /* split expr somehow into eiwk: e^{iwk}, and rst: the rest */
/* check if unassigned */
if subvarp(B[eiwk]) then B[eiwk]: rst
else B[eiwk]: B[eiwk] + rst,
B);
parts_by_eiwk(k, expr) := merge_parts_by_ewik(k, expr, B /* [1] */);
merge_parts_by_xn(x, k, expr, A) :=
if atom(expr) then error("merge_parts_by_xp: atom")
else if op(expr) = "+" then map(lambda([t], merge_parts_by_xn(x, k,
t, A)), to_list(expr))
else if op(expr) = "*" then block(
[xn, rst], /* split expr somehow into xn: x^n, and rst: the rest */
/* check if unassigned */
if subvarp(A[xn]) then A[xn]: parts_by_eiwk(k, rst)
else merge_parts_by_eiwk(k, rst, A[xn]),
A);
parts_by_xn(x, k, expr) := merge_parts_by_xn(x, k, expr, A /* [2] */);
/* [1,2] a function like makehashtable() would fit greatly here */
This kinda works, but the problem is that global namespace is polluted
by 'A' and 'B' indexes, so when parts_by_eiwk() is called for a second
time, it doesn't work with a clean 'B', but with one used in the first
invokation.
If it would be possible to create a new hash table with some function
every time, it would be really great.
Any pointers?
--
Alex