mdarrtst.cpp
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C++ 代码 · 共 429 行
CPP
429 行
#include "assert.hpp"
#include <iostream.h>
#include <iomanip.h>
#include <fstream.h>
#include <stdlib.h>
#include <new.h>
#include <NewLog.h>
#include <List.h>
#include <OrdSet.h>
#include <OrdKeyMa.h> //## p
typedef JAM_List<int> IntList;
typedef JAM_Iter<IntList> IntLIter;
typedef JAM_Muter<IntList> IntLMuter;
typedef IntList IndexList;
ostream& operator<<(ostream& os, const IndexList& list) {
os << "<";
for (IntLIter it(&list); !it.offEnd(); ) {
os << it();
if (++it) os << ",";
}
os << ">";
return os;
}
struct IndexListComp {
static int lessthan(const IndexList& a, const IndexList& b);
inline static int equal(const IndexList& a, const IndexList& b)
{ return a==b; }
};
int IndexListComp::lessthan(const IndexList& list1, const IndexList& list2)
{
assert(list1.length()==list2.length());
for (IntLIter i1(&list1), i2(&list2); !i1.offEnd(); i1.next(), i2.next()) {
if (i1()<i2()) return 1;
else if (i1()>i2()) return 0;
}
return 0;
}
inline int operator<(const IndexList& a, const IndexList& b)
{ return IndexListComp::lessthan(a,b); }
typedef JAM_OrdKeyMapCompIter<IndexList, int, IndexListComp > KeyIterator;
template<class T> class MDSlice;
template<class T>
class MDArray {
friend class MDSlice<T>;
friend ostream& operator<<(ostream&, const MDArray<T>&);
friend int operator==(const MDArray<T>& arr1, const MDArray<T>& arr2);
public:
MDArray();
MDArray(int sz) : _dimensions(IntList::of(sz)) {}
MDArray(int m, int n) : _dimensions(IntList::of(m, n)) {}
MDArray(int x, int y, int z) : _dimensions(IntList::of(x, y, z)) {}
MDArray(const IntList& dimensions)
: _dimensions(dimensions), _data() {}
MDArray<T>& enter(const IndexList& idxs, const MDArray<T>& mdarr);
MDArray<T>& enter(const IndexList& idxs, T t);
MDArray<T>& enter(int i, T t)
{ return enter(IndexList::of(i), t); }
MDArray<T>& enter(int i, int j, T t)
{ return enter(IndexList::of(i, j), t); }
MDArray<T>& enter(int x, int y, int z, T t)
{ return enter(IndexList::of(x, y, z), t); }
MDArray<T> operator[](const IndexList& idxs) const;
MDArray<T> operator()(int subscript) const;
MDSlice<T> operator()() const;
operator T() const {
assert(_dimensions.length()==0);
return _data.elem(IndexList());
}
int rank() const
{ return _dimensions.length(); }
protected:
IntList _dimensions;
JAM_OrdKeyMapComp<IndexList, T, IndexListComp > _data;
};
typedef MDArray<int> IntMDArray;
typedef JAM_KeyValue<IndexList,int,IndexListComp> E;
//void JAM_construct(E&, const E&);
void __dummy(E&d,E const &s) {
JAM_construct(d,s);
}
void JAM_ControlledVector<E,JAM_MemDefault>::move(E* dst, E* src, size_t n, int overlap)
{
memmove(dst, src, n*sizeof(E));
}
template<class T>
class MDSlice {
protected:
MDSlice(const MDArray<T>& arr, int n)
: _arr(arr), _n(n) {}
public:
MDSlice(const MDArray<T>& arr)
: _arr(arr), _n(1) {}
MDSlice<T> operator()();
MDArray<T> operator()(int subscript);
protected:
MDArray<T> _arr;
int _n;
};
//************************************************************************
// class MDArray definition
//************************************************************************
template<class T>
MDArray<T>& MDArray<T>::enter(const IndexList& idxs, T t)
{
if (idxs.length()!=_dimensions.length()) {
cout << "idxs.length()=" << idxs.length() << " " << "_dim.length()=" << _dimensions.length() << endl;
abort();
}
else if (!(IndexListComp::lessthan(idxs,_dimensions))) {
cout << "Index " << idxs << " out of range of " << _dimensions << endl;
abort();
}
else
_data.enter(idxs, t);
return *this;
}
template<class T>
MDArray<T>& MDArray<T>::enter(const IndexList& idxs, const MDArray<T>& mdarr)
{
if (idxs.length() + mdarr.rank() != rank()) {
// mdarr not correct rank for idxs into this array
cout << "IndexList " << idxs << " + " << mdarr._dimensions << " not correct rank for " << _dimensions << endl;
abort();
}
else {
// make sure the array size is okay
int range_error = 0;
IntLIter mydims(&_dimensions);
for (IntLIter idx(&idxs); !idx.offEnd(); idx.next(), mydims.next())
if (idx() >= mydims()) range_error = 1;
for (IntLIter dims(&mdarr._dimensions); !dims.offEnd(); dims.next(), mydims.next())
if (dims() != mydims()) range_error = 1;
if (range_error) {
cout << "Array " << mdarr._dimensions << " too big for " << _dimensions << " at " << idxs << endl;
abort();
}
else { // enter mdarr -- it's the right rank and size
assert(idxs.length()>0);
IndexList begrange = idxs; // start index: (m,n,0,0,0)
IndexList endrange = idxs; // finish index: (m,n,D2-1,D3-1,D4-1)
for (IntLIter mydim(&_dimensions, idxs.length()); mydim; ++mydim) {
begrange += 0;
endrange += mydim()-1;
}
// remove current data
_data.remove(begrange, endrange);
// enter new mdarr data (slow! -- needs to insert a lot into map)
for (KeyIterator kv(&mdarr._data); !kv.offEnd(); kv.next()) {
_data.enter(concat(idxs, kv.key()), kv.value());
}
} // end enter mdarr
}
return *this;
}
template<class T>
MDArray<T> MDArray<T>::operator[](const IndexList& idxs) const
{
int range_error = 0;
IntLIter mydims(&_dimensions);
for (IntLIter idx(&idxs); !idx.offEnd(); idx.next(), mydims.next())
if (idx() >= mydims()) range_error = 1;
if (range_error) {
cout << "Index " << idxs << " out of range in operator[] for array " << _dimensions << "." << endl;
abort();
}
IndexList resdims;
for (; !mydims.offEnd(); mydims.next())
resdims.append(mydims());
MDArray<T> result(resdims);
assert(idxs.length()>0);
IndexList begrange = idxs; // start index: (m,n,0,0,0)
IndexList endrange = idxs; // finish index: (m,n+1,0,0,0)
endrange.remove_last();
endrange += idxs.last() + 1;
int num_zeroes = rank() - idxs.length();
for (int i=0; i<num_zeroes; i++) {
begrange += 0;
endrange += 0;
}
int idxlen = idxs.length();
for (KeyIterator kv(&_data,_data.search(begrange)); !kv.offEnd() && kv.key()<endrange; kv.next()) {
IndexList residxs = kv.key();
for (int i=0; i<idxlen; i++)
residxs.remove_first();
result._data.enter(residxs, kv.value());
}
return result;
}
template<class T>
MDArray<T> MDArray<T>::operator()(int subscript) const
{
if (rank()==0 || subscript>= _dimensions.first()) {
cout << "Subscript " << subscript << " out of range in operator()(index) for array " << _dimensions << "." << endl;
abort();
}
IndexList resdims = _dimensions;
resdims.remove_first();
MDArray<T> result(resdims);
IndexList begrange = IndexList::of(subscript);
IndexList endrange = IndexList::of(subscript+1);
int num_zeroes = rank() - 1;
for (int i=0; i<num_zeroes; i++) {
begrange += 0;
endrange += 0;
}
for (KeyIterator kv(/*##*/&_data, _data.search(begrange)); !kv.offEnd() && kv.key()<endrange; kv.next()) {
IndexList residxs = kv.key();
residxs.remove_first();
result._data.enter(residxs, kv.value());
}
return result;
}
template<class T>
MDSlice<T> MDArray<T>::operator()() const
{
return MDSlice<T>(*this);
}
template<class T>
ostream& operator<<(ostream& os, const MDArray<T>& mdarr)
{
if (mdarr.rank()==0) {
os << mdarr._data.elem(IntList());
return os;
}
else {
for (IntLIter iter(&mdarr._dimensions); !iter.offEnd(); ) {
os << "[" << iter() << "]";
if (!++iter) os << endl;
}
}
for (KeyIterator kv(&mdarr._data); !kv.offEnd(); ) {
os << kv.key() << "=" << setw(3) << setfill('0') << kv.value();
if (++kv) os << '\t';
else os << '\n';
}
return os;
}
template<class T>
int operator==(const MDArray<T>& arr1, const MDArray<T>& arr2)
{
if (!(arr1._dimensions == arr2._dimensions)) return 0;
if (arr1._data.num() != arr2._data.num()) return 0;
for (KeyIterator kv1(&arr1._data), kv2(&arr2._data);
kv1; ++kv1, ++kv2)
if (kv1.key()!=kv2.key() || kv1.value()!=kv2.value()) {
cout << kv1.key() << "!=" << kv2.key() << " || "
<< kv1.value() << "!=" << kv2.value() << endl;
return 0;
}
return 1;
}
//************************************************************************
// class MDSlice definition
//************************************************************************
template<class T>
MDSlice<T> MDSlice<T>::operator()()
{
return MDSlice<T>(this->_arr, _n+1);
}
template<class T>
MDArray<T> MDSlice<T>::operator()(int subscript)
{
assert(_arr.rank()>_n);
// remove nth dim
IntList new_dims = _arr._dimensions;
IntLMuter iter(&new_dims);
for (int i=0; i<_n; i++) iter.next();
assert(subscript < *iter);
iter.remove();
MDArray<T> result(new_dims);
for (KeyIterator kv(&_arr._data); !kv.offEnd(); kv.next()) {
IndexList new_idx = kv.key();
IntLMuter iter(&new_idx);
for (int i=0; i<_n; i++) iter.next();
if (iter()==subscript) {
iter.remove();
result.enter(new_idx, kv.value());
}
}
return result;
}
//************************************************************************
// main() definition
//************************************************************************
#ifdef XX
IntList input_dimensions(istream& is)
{
IntList il;
for (;;) {
char c = 0;
cin >> ws;
if (c.peek()!='[') return il;
cin >> c; // get "["
assert(c=='[');
int i;
cin >> i >> c; // get dimension and "]"
assert(c==']');
il.append(i);
}
}
#endif
void MEM_ERROR()
{
cout << "yea!" << endl;
abort();
}
extern unsigned _stklen = 10000U; // originally 20000
void hack() {
JAM_Vector<int> a, b; a.resize(5); b = a;
}
main()
{
ofstream output("output");
cout << "main()" << endl;
set_new_handler(JAM_out_of_mem);
JAM_NewLog newlog;
IntList dims;
dims.append(1); dims.append(2); dims.append(3); dims.append(4); dims.append(5);
const N1=5, N2=5, N3=5, N4=5; // 7 is test, 5 shows bug
IntList nn; nn.append(N1); nn.append(N2); nn.append(N3); nn.append(N4);
MDArray<int> darr(nn);
for (int i1=0; i1<N1; i1++) {
output << (N1-i1) << " ";
int v1 = i1;
for (int i2=0; i2<N2; i2++) {
int v2 = i2 + v1*10;
for (int i3=0; i3<N3; i3++) {
int v3 = i3 + v2*10;
for (int i4=0; i4<N4; i4++) {
int v4 = i4 + v3*10;
IndexList ii; ii.append(i1).append(i2).append(i3).append(i4);
darr.enter(ii, v4);
}
}
}
}
output << darr << endl;
{ output << "(N1-1)()(N3-1):\n" << darr(N1-1)()(N3-1) << endl; }
{ output << "()()(1):\n" << darr()()(1) << endl; }
{ output << "(0)(1)(1):\n" << darr(0)(1)(1) << endl; }
MDArray<int> x(N3, N4);
for (int j=0; j<N3; j++)
for (int k=0; k<N4; k++)
x.enter(j, k, (j+1)*5);
output << "x 2d array = " << x << endl;
IndexList i; i.append(1); i.append(1);
cout << "entering...\n"; //###
darr.enter(i, x);
cout << "Finished entering.\n"; //###
output << "new darr: " << darr << endl;
output << "darr[i]: " << darr[i] << endl;
assert(darr[i]==x);
return 0;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?