XdmfArrayType.cpp 11.3 KB
Newer Older
Kenneth Leiter's avatar
Kenneth Leiter committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*****************************************************************************/
/*                                    XDMF                                   */
/*                       eXtensible Data Model and Format                    */
/*                                                                           */
/*  Id : XdmfArrayType.cpp                                                   */
/*                                                                           */
/*  Author:                                                                  */
/*     Kenneth Leiter                                                        */
/*     kenneth.leiter@arl.army.mil                                           */
/*     US Army Research Laboratory                                           */
/*     Aberdeen Proving Ground, MD                                           */
/*                                                                           */
/*     Copyright @ 2011 US Army Research Laboratory                          */
/*     All Rights Reserved                                                   */
/*     See Copyright.txt for details                                         */
/*                                                                           */
/*     This software is distributed WITHOUT ANY WARRANTY; without            */
/*     even the implied warranty of MERCHANTABILITY or FITNESS               */
/*     FOR A PARTICULAR PURPOSE.  See the above copyright notice             */
/*     for more information.                                                 */
/*                                                                           */
/*****************************************************************************/
23

24
#include <sstream>
25
#include <utility>
26
#include "XdmfArrayType.hpp"
27
#include "XdmfError.hpp"
28
29

// Supported XdmfArrayTypes
30
shared_ptr<const XdmfArrayType>
31
XdmfArrayType::Uninitialized()
32
{
33
  static shared_ptr<const XdmfArrayType> p(new XdmfArrayType("None", 0, XdmfArrayType::Unsigned));
34
  return p;
35
36
}

37
shared_ptr<const XdmfArrayType>
38
XdmfArrayType::Int8()
39
{
40
  static shared_ptr<const XdmfArrayType> p(new XdmfArrayType("Char", 1, XdmfArrayType::Signed));
41
  return p;
42
43
}

44
shared_ptr<const XdmfArrayType>
45
XdmfArrayType::Int16()
46
{
47
  static shared_ptr<const XdmfArrayType> p(new XdmfArrayType("Short", 2, XdmfArrayType::Signed));
48
  return p;
49
50
}

51
shared_ptr<const XdmfArrayType>
52
XdmfArrayType::Int32()
53
{
54
  static shared_ptr<const XdmfArrayType> p(new XdmfArrayType("Int", 4, XdmfArrayType::Signed));
55
  return p;
56
57
}

58
shared_ptr<const XdmfArrayType>
59
XdmfArrayType::Int64()
60
{
61
  static shared_ptr<const XdmfArrayType> p(new XdmfArrayType("Int", 8, XdmfArrayType::Signed));
62
  return p;
63
64
}

65
shared_ptr<const XdmfArrayType>
66
XdmfArrayType::Float32()
67
{
68
  static shared_ptr<const XdmfArrayType> p(new XdmfArrayType("Float", 4, XdmfArrayType::Float));
69
  return p;
70
71
}

72
shared_ptr<const XdmfArrayType>
73
XdmfArrayType::Float64()
74
{
75
  static shared_ptr<const XdmfArrayType> p(new XdmfArrayType("Float", 8, XdmfArrayType::Float));
76
  return p;
77
78
}

79
shared_ptr<const XdmfArrayType>
80
XdmfArrayType::UInt8()
81
{
82
  static shared_ptr<const XdmfArrayType> p(new XdmfArrayType("UChar", 1, XdmfArrayType::Unsigned));
83
  return p;
84
85
}

86
shared_ptr<const XdmfArrayType>
87
XdmfArrayType::UInt16()
88
{
89
  static shared_ptr<const XdmfArrayType> p(new XdmfArrayType("UShort", 2, XdmfArrayType::Unsigned));
90
  return p;
91
92
}

93
shared_ptr<const XdmfArrayType>
94
XdmfArrayType::UInt32()
95
{
96
  static shared_ptr<const XdmfArrayType> p(new XdmfArrayType("UInt", 4, XdmfArrayType::Unsigned));
97
  return p;
98
99
}

Kenneth Leiter's avatar
Kenneth Leiter committed
100
101
102
shared_ptr<const XdmfArrayType>
XdmfArrayType::String()
{
103
  static shared_ptr<const XdmfArrayType> p(new XdmfArrayType("String", 0, XdmfArrayType::Unsigned));
Kenneth Leiter's avatar
Kenneth Leiter committed
104
105
106
  return p;
}

107
XdmfArrayType::XdmfArrayType(const std::string & name,
108
109
                             const unsigned int precision,
                             const Format typeFormat) :
110
  mName(name),
111
112
  mPrecision(precision),
  mTypeFormat(typeFormat)
113
{
114
115
116
  std::stringstream precisionString;
  precisionString << precision;
  mPrecisionString = precisionString.str();
117
118
119
120
121
122
}

XdmfArrayType::~XdmfArrayType()
{
}

123
shared_ptr<const XdmfArrayType>
124
XdmfArrayType::New(const std::map<std::string, std::string> & itemProperties)
125
{
126
127
128
129
130
  std::map<std::string, std::string>::const_iterator type =
    itemProperties.find("DataType");
  if(type == itemProperties.end()) {
    type = itemProperties.find("NumberType");
  }
131
  if(type == itemProperties.end()) {
132
133
    // to support old xdmf defaults, return Float32()
    return Float32();
134
135
136
  }
  const std::string & typeVal = type->second;

137
138
  std::map<std::string, std::string>::const_iterator precision =
    itemProperties.find("Precision");
139
140
141
142
143
  const unsigned int precisionVal = 
    (precision == itemProperties.end()) ? 0 : atoi(precision->second.c_str()); 

  if(typeVal.compare("Float") == 0) {
    if(precisionVal == 8) {
144
145
      return Float64();
    }
146
147
148
149
150
    return Float32();
  }
  else if(typeVal.compare("Int") == 0) {
    if(precisionVal == 8) {
      return Int64();
151
    }
152
153
    return Int32();
  }
Kenneth Leiter's avatar
Kenneth Leiter committed
154
155
156
  else if(typeVal.compare("String") == 0) {
    return String();
  }
157
158
159
160
161
  else if(typeVal.compare("Char") == 0) {
    return Int8();
  }
  else if(typeVal.compare("Short") == 0) {
    return Int16();
162
  }
163
164
165
166
167
168
169
170
171
172
173
174
175
  else if(typeVal.compare("UChar") == 0) {
    return UInt8();
  }
  else if(typeVal.compare("UShort") == 0) {
    return UInt16();
  }
  else if(typeVal.compare("UInt") == 0) {
    return UInt32();
  }
  else if(typeVal.compare("None") == 0) {
    return Uninitialized();
  }

176
177
178
179
180
  XdmfError::message(XdmfError::FATAL,
                     "Type not one of accepted values: " + typeVal +
                     " in XdmfArrayType::New");
  
  // unreachable
181
  return shared_ptr<const XdmfArrayType>();
182
183
}

184
shared_ptr<const XdmfArrayType>
185
186
XdmfArrayType::comparePrecision(shared_ptr<const XdmfArrayType> type1,
                                shared_ptr<const XdmfArrayType> type2)
187
188
189
190
191
192
193
194
195
196
197
198
199
200
{
  std::string type1Name = type1->getName();
  std::string type2Name = type2->getName();

  if (type2Name.compare(type1Name) == 0) {
    if (type1->getElementSize() >= type2->getElementSize()) {
      return type1;
    }
    else {
      return type2;
    }
  }

  bool firstIsSigned = false;
201
202
203
  if (type1Name.compare("UChar") != 0 &&
      type1Name.compare("UShort") != 0 &&
      type1Name.compare("UInt") != 0) {
204
205
206
207
    firstIsSigned = true;
  }

  bool secondIsSigned = false;
208
209
210
  if (type2Name.compare("UChar") != 0 &&
      type2Name.compare("UShort") != 0 &&
      type2Name.compare("UInt") != 0) {
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
    secondIsSigned = true;
  }

  std::map<std::string, int> controlmap;
  controlmap["Char"] = 1;
  controlmap["UChar"] = 2;
  controlmap["Short"] = 3;
  controlmap["UShort"] = 4;
  controlmap["Int"] = 5;
  controlmap["UInt"] = 6;
  controlmap["Float"] = 7;
  controlmap["String"] = 8;

  int control = controlmap[type1Name];


  // In this switch the starting location is determined by
  // the first type and then the algorithm cascades
  // until it finds the second type
  switch (control) {
    case 1:
      // Char
    case 2:
      // UChar
235
236
      if (type2Name.compare("Char") == 0 ||
          type2Name.compare("UChar") == 0) {
237
238
239
240
241
242
243
244
        // This statement would be called in the case
        // where there is a mixed type of Char and UChar
        // The resulting type should be a Short
        return Int16();
        break;
      }
    case 3:
      // Short
245
246
247
      if (type2Name.compare("Char") == 0 ||
          type2Name.compare("UChar") == 0 ||
          type2Name.compare("Short") == 0) {
248
249
250
251
252
253
254
255
        // This will be called for any combination of
        // Char/UChar and Short
        // In all of these cases the result shoule be a Short
        return Int16();
        break;
      }
    case 4:
      // UShort
256
257
      if (type2Name.compare("Char") == 0 ||
          type2Name.compare("Short") == 0) {
258
259
260
261
262
        // When mixing UShort with a signed type that has a lower precision
        // the resulting type should be an int
        return Int32();
        break;
      }
263
264
      else if (type2Name.compare("UChar") == 0 ||
               type2Name.compare("UShort") == 0) {
265
266
267
268
269
270
271
272
273
274
275
276
        // When mixing UShort with an unsigned type that has a lower precision
        // a Ushort should be the resulting type
        if (!firstIsSigned) {
          return UInt16();
        }
        else {
          return Int32();
        }
        break;
      }
    case 5:
      // Int
277
278
279
280
      if (type2Name.compare("Int") != 0 &&
          type2Name.compare("UInt") != 0 &&
          type2Name.compare("Float") != 0 &&
          type2Name.compare("String") != 0) {
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
        // When mixing an Int with a type of lower precision
        // the resulting type should match the Int's precision
        if (type1->getElementSize() == 4) {
          return Int32();
        }
        else {
          return Int64();
        }
        break;
      }
      if (type2Name.compare("Int") == 0) {
        if (type2->getElementSize() == 4) {
          return Int32();
        }
        else {
          return Int64();
        }
        break;
      }
    case 6:
      // UInt
302
303
304
305
      if (type2Name.compare("UInt") != 0 &&
          type2Name.compare("Int") != 0 &&
          type2Name.compare("Float") != 0 &&
          type2Name.compare("String") != 0) {
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
        // When mixing UInt with another non-floating-point type
        // the result should be either long or unsigned int
        // depending on the if the mixed type is signed or not
        if (!secondIsSigned) {
          return UInt32();
        }
        else {
          return Int64();
        }
        break;
      }
      else if (type2Name.compare("UInt") == 0) {
        if (firstIsSigned) {
          return Int64();
        }
        else {
          return UInt32();
        }
        break;
      }
      else if (type2Name.compare("Int") == 0) {
        return Int64();
        break;
      }
    case 7:
      // Float
332
333
334
      if (type2Name.compare("String") != 0 &&
          type2Name.compare("Float") != 0 &&
          type2Name.compare("UInt") != 0) {
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
        // String is the only type that has priority over a float
        // This case occurs when type1 is a float
        return type1;
        break;
      }
      else if (type2Name.compare("UInt") == 0) {
        return Float64();
      }
      else if (type2Name.compare("Float") == 0) {
        // Since there was a check earlier to see if the type names matched
        // This is the case when type2 is a float
        if (type1Name.compare("UInt") == 0) {
          return Float64();
        }
	else {
          return type2;
        }
        break;
      }
    case 8:
      // String
      // String has priority over everything
      return String();
      break;
    default:
      break;
  }
  // Double is the default value
  // Should all of the above manage to fail to return a value
  return Float64();
}

367
368
unsigned int
XdmfArrayType::getElementSize() const
369
{
370
  return mPrecision;
371
372
}

373
374
375
376
377
378
std::string
XdmfArrayType::getName() const
{
  return mName;
}

379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
bool
XdmfArrayType::getIsFloat() const
{
  if (mTypeFormat == XdmfArrayType::Float) {
    return true;
  }
  else {
    return false;
  }
}

bool
XdmfArrayType::getIsSigned() const
{
  if (mTypeFormat == XdmfArrayType::Float ||
      mTypeFormat == XdmfArrayType::Signed) {
    return true;
  }
  else {
    return false;
  }
}

402
403
void
XdmfArrayType::getProperties(std::map<std::string, std::string> & collectedProperties) const
404
{
405
  collectedProperties.insert(std::make_pair("DataType", mName));
406
  collectedProperties.insert(std::make_pair("Precision", mPrecisionString));
407
}