SIRF  3.4.0
ANumRef.h
1 /*
2 SyneRBI Synergistic Image Reconstruction Framework (SIRF)
3 Copyright 2018 Rutherford Appleton Laboratory STFC
4 Copyright 2020 University College London
5 
6 This is software developed for the Collaborative Computational
7 Project in Synergistic Reconstruction for Biomedical Imaging (formerly CCP PETMR)
8 (http://www.ccpsynerbi.ac.uk/).
9 
10 Licensed under the Apache License, Version 2.0 (the "License");
11 you may not use this file except in compliance with the License.
12 You may obtain a copy of the License at
13 http://www.apache.org/licenses/LICENSE-2.0
14 Unless required by applicable law or agreed to in writing, software
15 distributed under the License is distributed on an "AS IS" BASIS,
16 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 See the License for the specific language governing permissions and
18 limitations under the License.
19 
20 */
21 
22 #pragma once
23 
24 // in case #pragma once not supported
25 #ifndef SIRF_NUMBER_REFERENCE
26 #define SIRF_NUMBER_REFERENCE
27 
28 #include <complex>
29 #include <typeinfo>
30 #include <stdexcept>
35 {
36 public:
37  enum Type {
38  USHORT = 1,
39  SHORT = 2,
40  UINT = 3,
41  INT = 4,
42  FLOAT = 5,
43  DOUBLE = 6,
44  CXFLOAT = 7,
45  CXDOUBLE = 8
46  };
47 };
48 typedef std::complex<float> complex_float_t;
49 typedef std::complex<double> complex_double_t;
50 
51 namespace sirf {
52 
53  class ANumRef {
54  public:
55  virtual complex_double_t complex_double() const = 0;
56  virtual complex_float_t complex_float() const = 0;
57  virtual operator float() const = 0;
58  virtual void assign(const ANumRef& ref) = 0;
59  ANumRef& operator=(const ANumRef& ref)
60  {
61  assign(ref);
62  return *this;
63  }
64  virtual void set_ptr(void* ptr) = 0;
65  virtual NumberType::Type get_typeID() const = 0;
66  };
67 
68  class FloatRef : public ANumRef {
69  public:
70  FloatRef(float* ptr = 0, int dummy = 0) : ptr_(ptr)
71  {}
72  virtual complex_double_t complex_double() const
73  {
74  return complex_double_t(*ptr_);
75  }
76  virtual complex_float_t complex_float() const
77  {
78  return complex_float_t(*ptr_);
79  }
80  virtual operator float() const
81  {
82  return *ptr_;
83  }
84  template<typename T>
85  FloatRef& operator=(T v)
86  {
87  *ptr_ = v;
88  return *this;
89  }
90  virtual void assign(const ANumRef& a_ref)
91  {
92  const FloatRef& ref = (const FloatRef&)a_ref;
93  *ptr_ = float(ref);
94  }
95  ANumRef& operator=(const ANumRef& ref)
96  {
97  assign(ref);
98  return *this;
99  }
100  void set_ptr(void* ptr)
101  {
102  ptr_ = (float*)ptr;
103  }
104  void copy(const FloatRef& ref)
105  {
106  ptr_ = ref.ptr_;
107  }
108  virtual NumberType::Type get_typeID() const
109  {
110  return NumberType::FLOAT;
111  }
112  private:
113  float* ptr_;
114  };
115 
116  template <typename Type>
117  NumberType::Type TypeID(Type t)
118  {
119  if (typeid(Type) == typeid(complex_double_t))
120  return NumberType::CXDOUBLE;
121  else if (typeid(Type) == typeid(complex_float_t))
122  return NumberType::CXFLOAT;
123  else if (typeid(Type) == typeid(double))
124  return NumberType::DOUBLE;
125  else if (typeid(Type) == typeid(float))
126  return NumberType::FLOAT;
127  else if (typeid(Type) == typeid(int))
128  return NumberType::INT;
129  else if (typeid(Type) == typeid(unsigned int))
130  return NumberType::UINT;
131  else if (typeid(Type) == typeid(short))
132  return NumberType::SHORT;
133  else if (typeid(Type) == typeid(unsigned short))
134  return NumberType::USHORT;
135  else
136  throw std::invalid_argument
137  (std::string("unsupported numeric type ") + typeid(Type).name());
138  }
139 
140  class NumRef : public ANumRef {
141  public:
142  NumRef(void* ptr = 0, int type = (int)NumberType::FLOAT) :
143  ptr_(ptr), abs_(true), type_(type)
144  {}
145  NumRef(const NumRef& ref) :
146  ptr_(ref.ptr_), abs_(ref.abs_), type_(ref.type_)
147  {}
148  void set_complex_to_real_mode(char m)
149  {
150  abs_ = (m == 'a');
151  }
152  virtual void set_ptr(void* ptr)
153  {
154  ptr_ = ptr;
155  }
156  virtual void copy(const NumRef& ref)
157  {
158  ptr_ = ref.ptr_;
159  abs_ = ref.abs_;
160  type_ = ref.type_;
161  }
162  complex_double_t complex_double() const
163  {
164  complex_double_t z;
165  switch (type_) {
167  z = *(complex_double_t*)ptr_;
168  break;
169  case NumberType::CXFLOAT:
170  z = *(complex_float_t*)ptr_;
171  break;
172  case NumberType::DOUBLE:
173  z = float(*(double*)ptr_);
174  break;
175  case NumberType::FLOAT:
176  z = *(float*)ptr_;
177  break;
178  case NumberType::INT:
179  z = complex_float_t(float(*(int*)ptr_));
180  break;
181  case NumberType::UINT:
182  z = complex_float_t(float(*(unsigned int*)ptr_));
183  break;
184  case NumberType::SHORT:
185  z = complex_float_t(float(*(short*)ptr_));
186  break;
187  case NumberType::USHORT:
188  z = complex_float_t(float(*(unsigned short*)ptr_));
189  }
190  return z;
191  }
192  virtual complex_float_t complex_float() const
193  {
194  complex_float_t z;
195  switch (type_) {
197  z = *(complex_double_t*)ptr_;
198  break;
199  case NumberType::CXFLOAT:
200  z = *(complex_float_t*)ptr_;
201  break;
202  case NumberType::DOUBLE:
203  z = float(*(double*)ptr_);
204  break;
205  case NumberType::FLOAT:
206  z = *(float*)ptr_;
207  break;
208  case NumberType::INT:
209  z = complex_float_t(float(*(int*)ptr_));
210  break;
211  case NumberType::UINT:
212  z = complex_float_t(float(*(unsigned int*)ptr_));
213  break;
214  case NumberType::SHORT:
215  z = complex_float_t(float(*(short*)ptr_));
216  break;
217  case NumberType::USHORT:
218  z = complex_float_t(float(*(unsigned short*)ptr_));
219  }
220  return z;
221  }
222  virtual operator float() const
223  {
224  float v;
225  complex_float_t c;
226  complex_double_t z;
227  switch (type_) {
229  z = *(complex_double_t*)ptr_;
230  v = float(abs_ ? abs(z) : z.real());
231  break;
232  case NumberType::CXFLOAT:
233  c = *(complex_float_t*)ptr_;
234  v = abs_ ? abs(c) : c.real();
235  break;
236  case NumberType::DOUBLE:
237  v = float(*(double*)ptr_);
238  break;
239  case NumberType::FLOAT:
240  v = *(float*)ptr_;
241  break;
242  case NumberType::INT:
243  v = float(*(int*)ptr_);
244  break;
245  case NumberType::UINT:
246  v = float(*(unsigned int*)ptr_);
247  break;
248  case NumberType::SHORT:
249  v = float(*(short*)ptr_);
250  break;
251  case NumberType::USHORT:
252  v = float(*(unsigned short*)ptr_);
253  }
254  return v;
255  }
256  NumRef& operator=(const NumRef& ref)
257  {
258  assign(ref);
259  return *this;
260  }
261  virtual void assign(const ANumRef& a_ref)
262  {
263  const NumRef& ref = (const NumRef&)a_ref;
264  switch (type_) {
266  *(complex_double_t*)ptr_ = ref.complex_double();
267  break;
268  case NumberType::CXFLOAT:
269  *(complex_float_t*)ptr_ = ref.complex_float();
270  break;
271  case NumberType::DOUBLE:
272  *(double*)ptr_ = double(ref);
273  break;
274  case NumberType::FLOAT:
275  *(float*)ptr_ = float(ref);
276  break;
277  case NumberType::INT:
278  *(int*)ptr_ = int(ref);
279  break;
280  case NumberType::UINT:
281  *(unsigned int*)ptr_ = (unsigned int)ref;
282  break;
283  case NumberType::SHORT:
284  *(short*)ptr_ = short(ref);
285  break;
286  case NumberType::USHORT:
287  *(unsigned short*)ptr_ = (unsigned short)ref;
288  }
289  }
290  NumRef& operator/=(float s)
291  {
292  switch (type_) {
294  *(complex_double_t*)ptr_ /= s;
295  break;
296  case NumberType::CXFLOAT:
297  *(complex_float_t*)ptr_ /= s;
298  break;
299  case NumberType::DOUBLE:
300  *(double*)ptr_ /= s;
301  break;
302  case NumberType::FLOAT:
303  *(float*)ptr_ /= s;
304  break;
305  case NumberType::INT:
306  *(int*)ptr_ /= s;
307  break;
308  case NumberType::UINT:
309  *(unsigned int*)ptr_ /= s;
310  break;
311  case NumberType::SHORT:
312  *(short*)ptr_ /= s;
313  break;
314  case NumberType::USHORT:
315  *(unsigned short*)ptr_ /= s;
316  }
317  return *this;
318  }
319  template <typename T>
320  NumRef& operator=(std::complex<T> v)
321  {
322  switch (type_) {
324  *(complex_double_t*)ptr_ = complex_double_t(v);
325  break;
326  case NumberType::CXFLOAT:
327  *(complex_float_t*)ptr_ = complex_float_t(v);
328  break;
329  case NumberType::DOUBLE:
330  *(double*)ptr_ = double(abs_ ? abs(v) : v.real());
331  break;
332  case NumberType::FLOAT:
333  *(float*)ptr_ = float(abs_ ? abs(v) : v.real());
334  break;
335  case NumberType::INT:
336  *(int*)ptr_ = int(abs_ ? abs(v) : v.real());
337  break;
338  case NumberType::UINT:
339  *(unsigned int*)ptr_ = (unsigned int)(abs_ ? abs(v) : v.real());
340  break;
341  case NumberType::SHORT:
342  *(short*)ptr_ = short(abs_ ? abs(v) : v.real());
343  break;
344  case NumberType::USHORT:
345  *(unsigned short*)ptr_ = (unsigned short)(abs_ ? abs(v) : v.real());
346  }
347  return *this;
348  }
349  template <typename T>
350  NumRef& operator=(T v)
351  {
352  switch (type_) {
354  *(complex_double_t*)ptr_ = complex_double_t(v);
355  break;
356  case NumberType::CXFLOAT:
357  *(complex_float_t*)ptr_ = complex_float_t(v);
358  break;
359  case NumberType::DOUBLE:
360  *(double*)ptr_ = double(v);
361  break;
362  case NumberType::FLOAT:
363  *(float*)ptr_ = float(v);
364  break;
365  case NumberType::INT:
366  *(int*)ptr_ = int(v);
367  break;
368  case NumberType::UINT:
369  *(unsigned int*)ptr_ = (unsigned int)v;
370  break;
371  case NumberType::SHORT:
372  *(short*)ptr_ = short(v);
373  break;
374  case NumberType::USHORT:
375  *(unsigned short*)ptr_ = (unsigned short)v;
376  }
377  return *this;
378  }
379  virtual NumberType::Type get_typeID() const
380  {
381  return NumberType::Type(type_);
382  }
383 
384  private:
385  bool abs_;
386  int type_;
387  void* ptr_;
388  };
389 
390 } // namespace sirf
391 
392 #endif
Definition: ANumRef.h:68
Definition: ANumRef.h:40
Type
Definition: ANumRef.h:37
Definition: ANumRef.h:41
Definition: ANumRef.h:140
Definition: ANumRef.h:53
Definition: ANumRef.h:38
Definition: ANumRef.h:42
Abstract data container.
Definition: GeometricalInfo.cpp:141
Definition: ANumRef.h:39
Definition: ANumRef.h:43
Definition: ANumRef.h:44
Definition: ANumRef.h:34
Definition: ANumRef.h:45