/[escript]/trunk/escript/src/DataTagged.cpp
ViewVC logotype

Annotation of /trunk/escript/src/DataTagged.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 775 - (hide annotations)
Mon Jul 10 04:00:08 2006 UTC (13 years ago) by ksteube
File size: 19728 byte(s)
Modified the following python methods in escript/py_src/util.py to
call faster C++ methods:
	escript_trace
	escript_transpose
	escript_symmetric
	escript_nonsymmetric

1 jgs 82 // $Id$
2 jgs 121
3 jgs 82 /*
4 elspeth 615 ************************************************************
5     * Copyright 2006 by ACcESS MNRF *
6     * *
7     * http://www.access.edu.au *
8     * Primary Business: Queensland, Australia *
9     * Licensed under the Open Software License version 3.0 *
10     * http://www.opensource.org/licenses/osl-3.0.php *
11     * *
12     ************************************************************
13 jgs 82 */
14    
15 jgs 474 #include "DataTagged.h"
16 jgs 496
17 jgs 474 #include "DataConstant.h"
18     #include "DataException.h"
19 jgs 82
20     using namespace std;
21    
22     namespace escript {
23    
24 jgs 121 DataTagged::DataTagged()
25     : DataAbstract(FunctionSpace())
26 jgs 82 {
27 jgs 509 // default constructor
28    
29 jgs 82 // create a scalar default value
30 jgs 151 m_data.resize(1,0.,1);
31 jgs 82 DataArrayView temp(m_data,DataArrayView::ShapeType());
32     setPointDataView(temp);
33     }
34    
35     DataTagged::DataTagged(const TagListType& tagKeys,
36     const ValueListType& values,
37     const DataArrayView& defaultValue,
38 jgs 102 const FunctionSpace& what)
39     : DataAbstract(what)
40 jgs 82 {
41 jgs 509 // constructor
42    
43 jgs 121 // initialise the array of data values
44     // the default value is always the first item in the values list
45 jgs 151 int len = defaultValue.noValues();
46     m_data.resize(len,0.,len);
47 jgs 121 for (int i=0; i<defaultValue.noValues(); i++) {
48     m_data[i]=defaultValue.getData(i);
49     }
50    
51 jgs 119 // create the data view
52 jgs 82 DataArrayView temp(m_data,defaultValue.getShape());
53     setPointDataView(temp);
54 jgs 121
55 jgs 82 // add remaining tags and values
56     addTaggedValues(tagKeys,values);
57     }
58    
59 jgs 119 DataTagged::DataTagged(const FunctionSpace& what,
60     const DataArrayView::ShapeType &shape,
61     const int tags[],
62 jgs 500 const ValueType& data)
63 jgs 119 : DataAbstract(what)
64     {
65 jgs 509 // alternative constructor
66     // not unit_tested tested yet
67    
68 jgs 121 // copy the data
69 jgs 119 m_data=data;
70 jgs 121
71 jgs 119 // create the view of the data
72     DataArrayView tempView(m_data,shape);
73     setPointDataView(tempView);
74 jgs 121
75 jgs 119 // create the tag lookup map
76     for (int sampleNo=0; sampleNo<getNumSamples(); sampleNo++) {
77     m_offsetLookup.insert(DataMapType::value_type(sampleNo,tags[sampleNo]));
78     }
79     }
80    
81 woo409 757 DataTagged::DataTagged(const FunctionSpace& what,
82     const DataArrayView::ShapeType &shape,
83     const TagListType& tags,
84     const ValueType& data)
85     : DataAbstract(what)
86     {
87     // alternative constructor
88     // not unit_tested tested yet
89    
90     // copy the data
91     m_data=data;
92    
93     // create the view of the data
94     DataArrayView tempView(m_data,shape);
95     setPointDataView(tempView);
96    
97     // create the tag lookup map
98     for (int sampleNo=0; sampleNo<getNumSamples(); sampleNo++) {
99     m_offsetLookup.insert(DataMapType::value_type(sampleNo,tags[sampleNo]));
100     }
101     }
102    
103    
104 jgs 102 DataTagged::DataTagged(const DataTagged& other)
105     : DataAbstract(other.getFunctionSpace()),
106 jgs 82 m_data(other.m_data),
107     m_offsetLookup(other.m_offsetLookup)
108     {
109 jgs 509 // copy constructor
110    
111 jgs 119 // create the data view
112 jgs 82 DataArrayView temp(m_data,other.getPointDataView().getShape());
113     setPointDataView(temp);
114     }
115    
116 jgs 102 DataTagged::DataTagged(const DataConstant& other)
117     : DataAbstract(other.getFunctionSpace())
118 jgs 82 {
119 jgs 509 // copy constructor
120    
121 jgs 121 // fill the default value with the constant value item from "other"
122 jgs 82 const DataArrayView& value=other.getPointDataView();
123 jgs 151 int len = value.noValues();
124     m_data.resize(len,0.,len);
125 jgs 121 for (int i=0; i<value.noValues(); i++) {
126     m_data[i]=value.getData(i);
127     }
128    
129 jgs 119 // create the data view
130 jgs 82 DataArrayView temp(m_data,value.getShape());
131     setPointDataView(temp);
132     }
133    
134     void
135     DataTagged::reshapeDataPoint(const DataArrayView::ShapeType& shape)
136     {
137     // can only reshape a rank zero data point
138     if (getPointDataView().getRank()!=0) {
139     stringstream temp;
140     temp << "Error - Can only reshape Data with data points of rank 0. "
141     << "This Data has data points with rank: "
142     << getPointDataView().getRank();
143     throw DataException(temp.str());
144     }
145 jgs 121
146 jgs 82 // allocate enough space for all values
147     DataArrayView::ValueType newData(DataArrayView::noValues(shape)*(m_offsetLookup.size()+1));
148     DataArrayView newView(newData,shape);
149     newView.copy(0,getDefaultValue()());
150 jgs 121
151     // loop through the tag values
152 jgs 82 DataMapType::iterator pos;
153     DataArrayView::ValueType::size_type tagOffset=DataArrayView::noValues(shape);
154 jgs 121 for (pos=m_offsetLookup.begin();pos!=m_offsetLookup.end();pos++){
155 jgs 82 newView.copy(tagOffset,m_data[pos->second]);
156     pos->second=tagOffset;
157     tagOffset+=DataArrayView::noValues(shape);
158     }
159     m_data=newData;
160     DataArrayView temp(m_data,shape);
161     setPointDataView(temp);
162     }
163    
164     DataAbstract*
165     DataTagged::getSlice(const DataArrayView::RegionType& region) const
166     {
167 jgs 513 return new DataTagged(*this, region);
168 jgs 82 }
169    
170 jgs 513 DataTagged::DataTagged(const DataTagged& other,
171     const DataArrayView::RegionType& region)
172     : DataAbstract(other.getFunctionSpace())
173     {
174     // slice constructor
175    
176     // get the shape of the slice to copy from other
177     DataArrayView::ShapeType regionShape(DataArrayView::getResultSliceShape(region));
178     DataArrayView::RegionLoopRangeType regionLoopRange=getSliceRegionLoopRange(region);
179    
180     // allocate enough space in this for all values
181     // (need to add one to allow for the default value)
182     int len = DataArrayView::noValues(regionShape)*(other.m_offsetLookup.size()+1);
183     m_data.resize(len,0.0,len);
184    
185     // create the data view
186     DataArrayView temp(m_data,regionShape);
187     setPointDataView(temp);
188    
189     // copy the default value from other to this
190     getDefaultValue().copySlice(other.getDefaultValue(), regionLoopRange);
191    
192     // loop through the tag values copying these
193     DataMapType::const_iterator pos;
194     DataArrayView::ValueType::size_type tagOffset=getPointDataView().noValues();
195     for (pos=other.m_offsetLookup.begin();pos!=other.m_offsetLookup.end();pos++){
196     getPointDataView().copySlice(tagOffset,other.getPointDataView(),pos->second,regionLoopRange);
197     m_offsetLookup.insert(DataMapType::value_type(pos->first,tagOffset));
198     tagOffset+=getPointDataView().noValues();
199     }
200     }
201    
202 jgs 82 void
203 jgs 513 DataTagged::setSlice(const DataAbstract* other,
204     const DataArrayView::RegionType& region)
205 jgs 82 {
206 jgs 513
207     // other must be another DataTagged object
208     // Data:setSlice implementation should ensure this
209     const DataTagged* otherTemp=dynamic_cast<const DataTagged*>(other);
210     if (otherTemp==0) {
211 jgs 82 throw DataException("Programming error - casting to DataTagged.");
212     }
213 jgs 121
214 jgs 513 // determine shape of the specified region
215     DataArrayView::ShapeType regionShape(DataArrayView::getResultSliceShape(region));
216    
217     // modify region specification as needed to match rank of this object
218     DataArrayView::RegionLoopRangeType regionLoopRange=getSliceRegionLoopRange(region);
219    
220     // ensure rank/shape of this object is compatible with specified region
221 jgs 82 if (getPointDataView().getRank()!=region.size()) {
222     throw DataException("Error - Invalid slice region.");
223     }
224 woo409 757 if (otherTemp->getPointDataView().getRank()>0 && !other->getPointDataView().checkShape(regionShape)) {
225 jgs 513 throw DataException (other->getPointDataView().createShapeErrorMessage(
226     "Error - Couldn't copy slice due to shape mismatch.",regionShape));
227 jgs 82 }
228 jgs 121
229 jgs 513 // copy slice from other default value to this default value
230     getDefaultValue().copySliceFrom(otherTemp->getDefaultValue(), regionLoopRange);
231 jgs 121
232 jgs 541 // loop through tag values in other, adding any which aren't in this, using default value
233     DataMapType::const_iterator pos;
234     for (pos=otherTemp->m_offsetLookup.begin();pos!=otherTemp->m_offsetLookup.end();pos++) {
235     if (!isCurrentTag(pos->first)) {
236     addTaggedValue(pos->first,getDefaultValue());
237     }
238     }
239    
240 jgs 513 // loop through the tag values copying slices from other to this
241 jgs 121 for (pos=m_offsetLookup.begin();pos!=m_offsetLookup.end();pos++) {
242 jgs 513 getDataPointByTag(pos->first).copySliceFrom(otherTemp->getDataPointByTag(pos->first), regionLoopRange);
243 jgs 121 }
244 jgs 513
245 jgs 82 }
246    
247 jgs 149 int
248     DataTagged::getTagNumber(int dpno)
249     {
250     //
251     // Get the number of samples and data-points per sample
252     int numSamples = getNumSamples();
253     int numDataPointsPerSample = getNumDPPSample();
254     int numDataPoints = numSamples * numDataPointsPerSample;
255    
256     if (numDataPointsPerSample==0) {
257     throw DataException("DataTagged::getTagNumber error: no data-points associated with this object.");
258     }
259    
260 jgs 496 if (dpno<0 || dpno>numDataPoints-1) {
261 jgs 149 throw DataException("DataTagged::getTagNumber error: invalid data-point number supplied.");
262     }
263    
264     //
265     // Determine the sample number which corresponds to this data-point number
266     int sampleNo = dpno / numDataPointsPerSample;
267    
268     //
269     // Determine the tag number which corresponds to this sample number
270     int tagNo = getFunctionSpace().getTagFromSampleNo(sampleNo);
271    
272     //
273     // return the tag number
274     return(tagNo);
275     }
276    
277 jgs 82 void
278 jgs 509 DataTagged::setTaggedValues(const TagListType& tagKeys,
279     const ValueListType& values)
280     {
281     addTaggedValues(tagKeys,values);
282     }
283    
284     void
285 jgs 82 DataTagged::setTaggedValue(int tagKey,
286     const DataArrayView& value)
287     {
288 jgs 121 if (!getPointDataView().checkShape(value.getShape())) {
289     throw DataException(getPointDataView().createShapeErrorMessage(
290     "Error - Cannot setTaggedValue due to shape mismatch.", value.getShape()));
291     }
292 jgs 82 DataMapType::iterator pos(m_offsetLookup.find(tagKey));
293     if (pos==m_offsetLookup.end()) {
294 jgs 121 // tag couldn't be found so use addTaggedValue
295 jgs 82 addTaggedValue(tagKey,value);
296     } else {
297 jgs 121 // copy the values into the data array at the offset determined by m_offsetLookup
298     int offset=pos->second;
299     for (int i=0; i<getPointDataView().noValues(); i++) {
300     m_data[offset+i]=value.getData(i);
301 jgs 82 }
302     }
303     }
304    
305     void
306 jgs 509 DataTagged::addTaggedValues(const TagListType& tagKeys,
307     const ValueListType& values)
308     {
309     if (values.size()==0) {
310     // copy the current default value for each of the tags
311     TagListType::const_iterator iT;
312     for (iT=tagKeys.begin();iT!=tagKeys.end();iT++) {
313     // the point data view for DataTagged points at the default value
314     addTaggedValue(*iT,getPointDataView());
315     }
316     } else if (values.size()==1 && tagKeys.size()>1) {
317     // assume the one given value will be used for all tag values
318     TagListType::const_iterator iT;
319     for (iT=tagKeys.begin();iT!=tagKeys.end();iT++) {
320     addTaggedValue(*iT,values[0]);
321     }
322     } else {
323     if (tagKeys.size()!=values.size()) {
324     stringstream temp;
325     temp << "Error - (addTaggedValue) Number of tags: " << tagKeys.size()
326     << " doesn't match number of values: " << values.size();
327     throw DataException(temp.str());
328     } else {
329     for (int i=0;i<tagKeys.size();i++) {
330     addTaggedValue(tagKeys[i],values[i]);
331     }
332     }
333     }
334     }
335    
336     void
337 jgs 82 DataTagged::addTaggedValue(int tagKey,
338     const DataArrayView& value)
339     {
340     if (!getPointDataView().checkShape(value.getShape())) {
341     throw DataException(getPointDataView().createShapeErrorMessage(
342 jgs 121 "Error - Cannot addTaggedValue due to shape mismatch.", value.getShape()));
343 jgs 82 }
344 jgs 121 DataMapType::iterator pos(m_offsetLookup.find(tagKey));
345     if (pos!=m_offsetLookup.end()) {
346     // tag already exists so use setTaggedValue
347     setTaggedValue(tagKey,value);
348     } else {
349     // save the key and the location of its data in the lookup tab
350     m_offsetLookup.insert(DataMapType::value_type(tagKey,m_data.size()));
351     // add the data given in "value" at the end of m_data
352     // need to make a temp copy of m_data, resize m_data, then copy
353     // all the old values plus the value to be added back into m_data
354     ValueType m_data_temp(m_data);
355     int oldSize=m_data.size();
356     int newSize=m_data.size()+value.noValues();
357 jgs 151 m_data.resize(newSize,0.,newSize);
358 jgs 121 for (int i=0;i<oldSize;i++) {
359     m_data[i]=m_data_temp[i];
360     }
361     for (int i=0;i<value.noValues();i++) {
362     m_data[oldSize+i]=value.getData(i);
363     }
364     }
365 jgs 82 }
366    
367     double*
368     DataTagged::getSampleDataByTag(int tag)
369     {
370     DataMapType::iterator pos(m_offsetLookup.find(tag));
371     if (pos==m_offsetLookup.end()) {
372     // tag couldn't be found so return the default value
373     return &(m_data[0]);
374     } else {
375     // return the data-point corresponding to the given tag
376     return &(m_data[pos->second]);
377     }
378     }
379    
380     string
381     DataTagged::toString() const
382     {
383     stringstream temp;
384     DataMapType::const_iterator i;
385     temp << "Tag(Default)" << endl;
386     temp << getDefaultValue().toString() << endl;
387     // create a temporary view as the offset will be changed
388     DataArrayView tempView(getPointDataView().getData(), getPointDataView().getShape());
389     for (i=m_offsetLookup.begin();i!=m_offsetLookup.end();++i) {
390     temp << "Tag(" << i->first << ")" << endl;
391     tempView.setOffset(i->second);
392     temp << tempView.toString() << endl;
393     }
394     return temp.str();
395     }
396    
397 jgs 496 DataArrayView::ValueType::size_type
398     DataTagged::getPointOffset(int sampleNo,
399     int dataPointNo) const
400 jgs 82 {
401 jgs 496 int tagKey=getFunctionSpace().getTagFromSampleNo(sampleNo);
402     DataMapType::const_iterator pos(m_offsetLookup.find(tagKey));
403 jgs 82 DataArrayView::ValueType::size_type offset=m_defaultValueOffset;
404     if (pos!=m_offsetLookup.end()) {
405     offset=pos->second;
406     }
407 jgs 496 return offset;
408 jgs 82 }
409    
410 jgs 496 DataArrayView
411     DataTagged::getDataPointByTag(int tag) const
412 jgs 82 {
413 jgs 496 DataMapType::const_iterator pos(m_offsetLookup.find(tag));
414 jgs 82 DataArrayView::ValueType::size_type offset=m_defaultValueOffset;
415     if (pos!=m_offsetLookup.end()) {
416     offset=pos->second;
417     }
418 jgs 496 DataArrayView temp(getPointDataView());
419     temp.setOffset(offset);
420     return temp;
421 jgs 82 }
422    
423     DataArrayView
424     DataTagged::getDataPoint(int sampleNo,
425     int dataPointNo)
426     {
427     EsysAssert(validSampleNo(sampleNo),"(getDataPoint) Invalid sampleNo: " << sampleNo);
428     int tagKey=getFunctionSpace().getTagFromSampleNo(sampleNo);
429     return getDataPointByTag(tagKey);
430     }
431    
432 jgs 123 int
433     DataTagged::archiveData(ofstream& archiveFile,
434     const DataArrayView::ValueType::size_type noValues) const
435     {
436     return(m_data.archiveData(archiveFile, noValues));
437     }
438    
439     int
440     DataTagged::extractData(ifstream& archiveFile,
441     const DataArrayView::ValueType::size_type noValues)
442     {
443     return(m_data.extractData(archiveFile, noValues));
444     }
445 gross 580 void
446 ksteube 775 DataTagged::symmetric(DataAbstract* ev)
447     {
448     DataTagged* temp_ev=dynamic_cast<DataTagged*>(ev);
449     if (temp_ev==0) {
450     throw DataException("Error - DataTagged::symmetric casting to DataTagged failed (probably a programming error).");
451     }
452     const DataTagged::DataMapType& thisLookup=getTagLookup();
453     DataTagged::DataMapType::const_iterator i;
454     DataTagged::DataMapType::const_iterator thisLookupEnd=thisLookup.end();
455     for (i=thisLookup.begin();i!=thisLookupEnd;i++) {
456     temp_ev->addTaggedValue(i->first,temp_ev->getDefaultValue());
457     DataArrayView thisView=getDataPointByTag(i->first);
458     DataArrayView evView=temp_ev->getDataPointByTag(i->first);
459     DataArrayView::symmetric(thisView,0,evView,0);
460     }
461     DataArrayView::symmetric(getDefaultValue(),0,temp_ev->getDefaultValue(),0);
462     }
463     void
464     DataTagged::nonsymmetric(DataAbstract* ev)
465     {
466     DataTagged* temp_ev=dynamic_cast<DataTagged*>(ev);
467     if (temp_ev==0) {
468     throw DataException("Error - DataTagged::nonsymmetric casting to DataTagged failed (probably a programming error).");
469     }
470     const DataTagged::DataMapType& thisLookup=getTagLookup();
471     DataTagged::DataMapType::const_iterator i;
472     DataTagged::DataMapType::const_iterator thisLookupEnd=thisLookup.end();
473     for (i=thisLookup.begin();i!=thisLookupEnd;i++) {
474     temp_ev->addTaggedValue(i->first,temp_ev->getDefaultValue());
475     DataArrayView thisView=getDataPointByTag(i->first);
476     DataArrayView evView=temp_ev->getDataPointByTag(i->first);
477     DataArrayView::nonsymmetric(thisView,0,evView,0);
478     }
479     DataArrayView::nonsymmetric(getDefaultValue(),0,temp_ev->getDefaultValue(),0);
480     }
481     void
482     DataTagged::matrixtrace(DataAbstract* ev, int axis_offset)
483     {
484     DataTagged* temp_ev=dynamic_cast<DataTagged*>(ev);
485     if (temp_ev==0) {
486     throw DataException("Error - DataTagged::matrixtrace casting to DataTagged failed (probably a programming error).");
487     }
488     const DataTagged::DataMapType& thisLookup=getTagLookup();
489     DataTagged::DataMapType::const_iterator i;
490     DataTagged::DataMapType::const_iterator thisLookupEnd=thisLookup.end();
491     for (i=thisLookup.begin();i!=thisLookupEnd;i++) {
492     temp_ev->addTaggedValue(i->first,temp_ev->getDefaultValue());
493     DataArrayView thisView=getDataPointByTag(i->first);
494     DataArrayView evView=temp_ev->getDataPointByTag(i->first);
495     DataArrayView::matrixtrace(thisView,0,evView,0, axis_offset);
496     }
497     DataArrayView::matrixtrace(getDefaultValue(),0,temp_ev->getDefaultValue(),0,axis_offset);
498     }
499     void
500     DataTagged::transpose(DataAbstract* ev, int axis_offset)
501     {
502     DataTagged* temp_ev=dynamic_cast<DataTagged*>(ev);
503     if (temp_ev==0) {
504     throw DataException("Error - DataTagged::transpose casting to DataTagged failed (probably a programming error).");
505     }
506     const DataTagged::DataMapType& thisLookup=getTagLookup();
507     DataTagged::DataMapType::const_iterator i;
508     DataTagged::DataMapType::const_iterator thisLookupEnd=thisLookup.end();
509     for (i=thisLookup.begin();i!=thisLookupEnd;i++) {
510     temp_ev->addTaggedValue(i->first,temp_ev->getDefaultValue());
511     DataArrayView thisView=getDataPointByTag(i->first);
512     DataArrayView evView=temp_ev->getDataPointByTag(i->first);
513     DataArrayView::transpose(thisView,0,evView,0, axis_offset);
514     }
515     DataArrayView::transpose(getDefaultValue(),0,temp_ev->getDefaultValue(),0,axis_offset);
516     }
517     void
518 gross 580 DataTagged::eigenvalues(DataAbstract* ev)
519     {
520     DataTagged* temp_ev=dynamic_cast<DataTagged*>(ev);
521     if (temp_ev==0) {
522     throw DataException("Error - DataTagged::eigenvalues casting to DataTagged failed (propably a programming error).");
523     }
524     const DataTagged::DataMapType& thisLookup=getTagLookup();
525     DataTagged::DataMapType::const_iterator i;
526     DataTagged::DataMapType::const_iterator thisLookupEnd=thisLookup.end();
527     for (i=thisLookup.begin();i!=thisLookupEnd;i++) {
528     temp_ev->addTaggedValue(i->first,temp_ev->getDefaultValue());
529     DataArrayView thisView=getDataPointByTag(i->first);
530     DataArrayView evView=temp_ev->getDataPointByTag(i->first);
531     DataArrayView::eigenvalues(thisView,0,evView,0);
532     }
533     DataArrayView::eigenvalues(getDefaultValue(),0,temp_ev->getDefaultValue(),0);
534     }
535     void
536     DataTagged::eigenvalues_and_eigenvectors(DataAbstract* ev,DataAbstract* V,const double tol)
537     {
538     DataTagged* temp_ev=dynamic_cast<DataTagged*>(ev);
539     if (temp_ev==0) {
540     throw DataException("Error - DataTagged::eigenvalues_and_eigenvectors casting to DataTagged failed (propably a programming error).");
541     }
542     DataTagged* temp_V=dynamic_cast<DataTagged*>(V);
543     if (temp_V==0) {
544     throw DataException("Error - DataTagged::eigenvalues_and_eigenvectors casting to DataTagged failed (propably a programming error).");
545     }
546     const DataTagged::DataMapType& thisLookup=getTagLookup();
547     DataTagged::DataMapType::const_iterator i;
548     DataTagged::DataMapType::const_iterator thisLookupEnd=thisLookup.end();
549     for (i=thisLookup.begin();i!=thisLookupEnd;i++) {
550     temp_ev->addTaggedValue(i->first,temp_ev->getDefaultValue());
551     temp_V->addTaggedValue(i->first,temp_V->getDefaultValue());
552     DataArrayView thisView=getDataPointByTag(i->first);
553     DataArrayView evView=temp_ev->getDataPointByTag(i->first);
554     DataArrayView VView=temp_V->getDataPointByTag(i->first);
555     DataArrayView::eigenvalues_and_eigenvectors(thisView,0,evView,0,VView,0,tol);
556     }
557     DataArrayView::eigenvalues_and_eigenvectors(getDefaultValue(),0,
558     temp_ev->getDefaultValue(),0,
559     temp_V->getDefaultValue(),0,
560     tol);
561 jgs 123
562 gross 580
563     }
564    
565    
566 jgs 82 } // end of namespace

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.26