Rosetta
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
Dimension.cc
Go to the documentation of this file.
1 // Dimension: Dynamic Dimension
2 //
3 // Project: Objexx Fortran Compatibility Library (ObjexxFCL)
4 //
5 // Version: 3.0.0
6 //
7 // Language: C++
8 //
9 // Copyright (c) 2000-2009 Objexx Engineering, Inc. All Rights Reserved.
10 // Use of this source code or any derivative of it is restricted by license.
11 // Licensing is available from Objexx Engineering, Inc.: http://objexx.com Objexx@objexx.com
12 
13 
14 // ObjexxFCL Headers
15 #include <ObjexxFCL/Dimension.hh>
22 
23 // C++ Headers
24 #include <cassert>
25 #include <cstdlib>
26 #include <iostream>
27 #include <sstream>
28 #include <string>
29 
30 
31 namespace ObjexxFCL {
32 
33 
34 // Dimension: Dynamic Dimension
35 
36 
37  /// @brief Copy Constructor
39  ObserverMulti(),
40  exp_p_( new DimensionExpressionRef( dim ) ),
41  initialized_( exp_p_->initialized() ),
42  value_( dim.value_ )
43  {
44  insert_as_observer_of( dim );
45  }
46 
47 
48  /// @brief int Constructor
49  Dimension::Dimension( int const i ) :
50  exp_p_( new DimensionExpressionCon( i ) ),
51  initialized_( true ),
52  value_( i )
53  {}
54 
55 
56  /// @brief double Constructor
57  Dimension::Dimension( double const d ) :
58  exp_p_( new DimensionExpressionCon( d ) ),
59  initialized_( true ),
60  value_( static_cast< int >( d ) )
61  {}
62 
63 
64  /// @brief Copy Assignment
65  Dimension &
67  {
68  if ( this != &dim ) {
70  delete exp_p_; exp_p_ = new DimensionExpressionRef( dim );
71  insert_as_observer_of( dim );
72  update();
73  }
74  notify();
75  return *this;
76  }
77 
78 
79  /// @brief int Assignment
80  Dimension &
81  Dimension::operator =( int const i )
82  {
84  delete exp_p_; exp_p_ = new DimensionExpressionCon( i );
85  update_notify();
86  return *this;
87  }
88 
89 
90  /// @brief double Assignment
91  Dimension &
92  Dimension::operator =( double const d )
93  {
95  delete exp_p_; exp_p_ = new DimensionExpressionCon( d );
96  update_notify();
97  return *this;
98  }
99 
100 
101  /// @brief += Dimension
102  Dimension &
104  {
105  assert( exp_p_ );
106  if ( this != &dim ) {
108  insert_as_observer_of( dim );
109  } else {
112  }
113  update_notify();
114  return *this;
115  }
116 
117 
118  /// @brief += Expression
119  Dimension &
121  {
122  assert( exp_p_ );
123  exp_p_ = new DimensionExpressionSum( exp_p_, exp.clone( *this ) );
125  insert_as_observer_of( exp );
126  update_notify();
127  return *this;
128  }
129 
130 
131  /// @brief += int
132  Dimension &
133  Dimension::operator +=( int const i )
134  {
135  assert( exp_p_ );
136  if ( i != 0 ) {
139  update();
140  }
141  notify();
142  return *this;
143  }
144 
145 
146  /// @brief += double
147  Dimension &
148  Dimension::operator +=( double const d )
149  {
150  assert( exp_p_ );
151  if ( d != 0.0 ) {
154  update();
155  }
156  notify();
157  return *this;
158  }
159 
160 
161  /// @brief -= Dimension
162  Dimension &
164  {
165  assert( exp_p_ );
166  if ( this != &dim ) {
168  insert_as_observer_of( dim );
169  } else {
171  delete exp_p_; exp_p_ = new DimensionExpressionCon( 0 );
172  }
173  update_notify();
174  return *this;
175  }
176 
177 
178  /// @brief -= Expression
179  Dimension &
181  {
182  assert( exp_p_ );
183  exp_p_ = new DimensionExpressionSub( exp_p_, exp.clone( *this ) );
185  insert_as_observer_of( exp );
186  update_notify();
187  return *this;
188  }
189 
190 
191  /// @brief -= int
192  Dimension &
193  Dimension::operator -=( int const i )
194  {
195  assert( exp_p_ );
196  if ( i != 0 ) {
199  update();
200  }
201  notify();
202  return *this;
203  }
204 
205 
206  /// @brief -= double
207  Dimension &
208  Dimension::operator -=( double const d )
209  {
210  assert( exp_p_ );
211  if ( d != 0.0 ) {
214  update();
215  }
216  notify();
217  return *this;
218  }
219 
220 
221  /// @brief *= Dimension
222  Dimension &
224  {
225  assert( exp_p_ );
226  if ( this != &dim ) {
228  insert_as_observer_of( dim );
229  } else {
232  }
233  update_notify();
234  return *this;
235  }
236 
237 
238  /// @brief *= Expression
239  Dimension &
241  {
242  assert( exp_p_ );
243  exp_p_ = new DimensionExpressionMul( exp_p_, exp.clone( *this ) );
245  insert_as_observer_of( exp );
246  update_notify();
247  return *this;
248  }
249 
250 
251  /// @brief *= int
252  Dimension &
253  Dimension::operator *=( int const i )
254  {
255  assert( exp_p_ );
256  if ( i != 1 ) {
259  update();
260  }
261  notify();
262  return *this;
263  }
264 
265 
266  /// @brief *= double
267  Dimension &
268  Dimension::operator *=( double const d )
269  {
270  assert( exp_p_ );
271  if ( d != 1.0 ) {
274  update();
275  }
276  notify();
277  return *this;
278  }
279 
280 
281  /// @brief /= Dimension
282  Dimension &
284  {
285  assert( exp_p_ );
286  if ( this != &dim ) {
288  insert_as_observer_of( dim );
289  } else { // Keep as a ratio to catch 0/0 cases
292  }
293  update_notify();
294  return *this;
295  }
296 
297 
298  /// @brief /= Expression
299  Dimension &
301  {
302  assert( exp_p_ );
303  exp_p_ = new DimensionExpressionDiv( exp_p_, exp.clone( *this ) );
305  insert_as_observer_of( exp );
306  update_notify();
307  return *this;
308  }
309 
310 
311  /// @brief /= int
312  Dimension &
313  Dimension::operator /=( int const i )
314  {
315  assert( exp_p_ );
316  assert( i != 0 );
317  if ( i != 1 ) {
320  update();
321  }
322  notify();
323  return *this;
324  }
325 
326 
327  /// @brief /= double
328  Dimension &
329  Dimension::operator /=( double const d )
330  {
331  assert( exp_p_ );
332  assert( d != 0.0 );
333  if ( d != 1.0 ) {
336  update();
337  }
338  notify();
339  return *this;
340  }
341 
342 
343  /// @brief int Assignment if Bigger than Value or Smaller than Multiplier * Value
344  Dimension &
345  Dimension::assign_if( int const i, double const m )
346  {
347  if ( ( ! initialized_ ) || ( i > value_ ) || ( i < m * value_ ) ) {
349  delete exp_p_; exp_p_ = new DimensionExpressionCon( i );
350  update();
351  }
352  notify();
353  return *this;
354  }
355 
356 
357  /// @brief double Assignment if Bigger than Value or Smaller than Multiplier * Value
358  Dimension &
359  Dimension::assign_if( double const d, double const m )
360  {
361  if ( ( ! initialized_ ) || ( d > value_ ) || ( d < m * value_ ) ) {
363  delete exp_p_; exp_p_ = new DimensionExpressionCon( d );
364  update();
365  }
366  notify();
367  return *this;
368  }
369 
370 
371  /// @brief int Assignment if Bigger than Value or Smaller than Half Value
372  Dimension &
374  {
375  if ( ( ! initialized_ ) || ( i > value_ ) || ( i < 0.5 * value_ ) ) {
377  delete exp_p_; exp_p_ = new DimensionExpressionCon( i );
378  update();
379  }
380  notify();
381  return *this;
382  }
383 
384 
385  /// @brief double Assignment if Bigger than Value or Smaller than Half Value
386  Dimension &
387  Dimension::assign_if_half( double const d )
388  {
389  if ( ( ! initialized_ ) || ( d > value_ ) || ( d < 0.5 * value_ ) ) {
391  delete exp_p_; exp_p_ = new DimensionExpressionCon( d );
392  update();
393  }
394  notify();
395  return *this;
396  }
397 
398 
399  /// @brief int Assignment if Bigger than Value
400  Dimension &
402  {
403  if ( ( ! initialized_ ) || ( i > value_ ) ) {
405  delete exp_p_; exp_p_ = new DimensionExpressionCon( i );
406  update();
407  }
408  notify();
409  return *this;
410  }
411 
412 
413  /// @brief double Assignment if Bigger than Value
414  Dimension &
415  Dimension::assign_if_bigger( double const d )
416  {
417  if ( ( ! initialized_ ) || ( d > value_ ) ) {
419  delete exp_p_; exp_p_ = new DimensionExpressionCon( d );
420  update();
421  }
422  notify();
423  return *this;
424  }
425 
426 
427  /// @brief int Assignment if Bigger than Value or Smaller than Multiplier * Value: Notify if Changed
428  Dimension &
429  Dimension::assign_if_nic( int const i, double const m )
430  {
431  if ( ( ! initialized_ ) || ( i > value_ ) || ( i < m * value_ ) ) {
433  delete exp_p_; exp_p_ = new DimensionExpressionCon( i );
435  }
436  return *this;
437  }
438 
439 
440  /// @brief double Assignment if Bigger than Value or Smaller than Multiplier * Value: Notify if Changed
441  Dimension &
442  Dimension::assign_if_nic( double const d, double const m )
443  {
444  if ( ( ! initialized_ ) || ( d > value_ ) || ( d < m * value_ ) ) {
446  delete exp_p_; exp_p_ = new DimensionExpressionCon( d );
448  }
449  return *this;
450  }
451 
452 
453  /// @brief int Assignment if Bigger than Value or Smaller than Half Value: Notify if Changed
454  Dimension &
456  {
457  if ( ( ! initialized_ ) || ( i > value_ ) || ( i < 0.5 * value_ ) ) {
459  delete exp_p_; exp_p_ = new DimensionExpressionCon( i );
461  }
462  return *this;
463  }
464 
465 
466  /// @brief double Assignment if Bigger than Value or Smaller than Half Value: Notify if Changed
467  Dimension &
469  {
470  if ( ( ! initialized_ ) || ( d > value_ ) || ( d < 0.5 * value_ ) ) {
472  delete exp_p_; exp_p_ = new DimensionExpressionCon( d );
474  }
475  return *this;
476  }
477 
478 
479  /// @brief int Assignment if Bigger than Value: Notify if Changed
480  Dimension &
482  {
483  if ( ( ! initialized_ ) || ( i > value_ ) ) {
485  delete exp_p_; exp_p_ = new DimensionExpressionCon( i );
487  }
488  return *this;
489  }
490 
491 
492  /// @brief double Assignment if Bigger than Value: Notify if Changed
493  Dimension &
495  {
496  if ( ( ! initialized_ ) || ( d > value_ ) ) {
498  delete exp_p_; exp_p_ = new DimensionExpressionCon( d );
500  }
501  return *this;
502  }
503 
504 
505  /// @brief ++Dimension
506  Dimension &
508  {
509  assert( exp_p_ );
512  update();
513  notify();
514  return *this;
515  }
516 
517 
518  /// @brief --Dimension
519  Dimension &
521  {
522  assert( exp_p_ );
525  update();
526  notify();
527  return *this;
528  }
529 
530 
531 // Dimension
532 
533 
534 /// @brief Stream Input
535 std::istream &
536 operator >>( std::istream & stream, Dimension & dim )
537 {
538  std::string input_string;
539  stream >> input_string;
540  std::istringstream num_stream( input_string );
541  int ival;
542  num_stream >> ival;
543  if ( ( num_stream ) && ( num_stream.eof() ) ) { // OK as int
544  dim = ival;
545  } else {
546  num_stream.clear();
547  num_stream.seekg( std::ios_base::beg );
548  double dval;
549  num_stream >> dval;
550  if ( ( num_stream ) && ( num_stream.eof() ) ) { // OK as double
551  dim = dval;
552  } else { // Invalid
553  std::cerr << "\n*** ObjexxFCL Error: " <<
554  "Invalid stream input to Dimension: " << input_string << std::endl;
555  std::exit( EXIT_FAILURE );
556  }
557  }
558  return stream;
559 }
560 
561 
562 /// @brief Stream Output
563 std::ostream &
564 operator <<( std::ostream & stream, Dimension const & dim )
565 {
566  stream << dim.value();
567  return stream;
568 }
569 
570 
571 } // namespace ObjexxFCL
std::istream & operator>>(std::istream &stream, byte &b)
Stream Input.
Definition: byte.hh:409
ocstream cerr(std::cerr)
Wrapper around std::cerr.
Definition: ocstream.hh:290
virtual DimensionExpression * clone() const =0
Clone.
DimensionExpressionSum: DimensionExpression Binary Sum.
void update()
Update.
Definition: Dimension.hh:541
Dimension & assign_if_bigger_nic(int const i)
int Assignment if Bigger than Value: Notify if Changed
Definition: Dimension.cc:481
void reduce_expression()
Reduce Expression.
Definition: Dimension.hh:586
void update_notify_if_changed()
Update and Notify if External State Changed.
Definition: Dimension.hh:645
DimensionExpressionCon: Constant-Valued DimensionExpression.
Dimension & operator-=(Dimension const &dim)
-= Dimension
Definition: Dimension.cc:163
Dimension & operator*=(Dimension const &dim)
*= Dimension
Definition: Dimension.cc:223
Dimension & assign_if_half_nic(int const i)
int Assignment if Bigger than Value or Smaller than Half Value: Notify if Changed ...
Definition: Dimension.cc:455
void remove_as_observer()
Remove as Observer of the Expression's Referenced Dimensions.
Definition: Dimension.hh:625
Expression * exp_p_
Expression pointer (owned)
Definition: Dimension.hh:661
Dimension & operator++()
++Dimension
Definition: Dimension.cc:507
Dimension & assign_if(int const i, double const m=1.0)
int Assignment if Bigger than Value or Smaller than Multiplier * Value
Definition: Dimension.cc:345
DimensionExpressionDiv: DimensionExpression Binary Division.
Dimension & operator/=(Dimension const &dim)
/= Dimension
Definition: Dimension.cc:283
Dimension & assign_if_bigger(int const i)
int Assignment if Bigger than Value
Definition: Dimension.cc:401
DimensionExpressionRef: Dimension Reference DimensionExpression.
Dimension & operator=(Dimension const &dim)
Copy Assignment: Creates a reference to the passed Dimension.
Definition: Dimension.cc:66
int value_
Cached value: Kept in synch with expression value (0 if uninitialized)
Definition: Dimension.hh:667
ObserverMulti: Combined Subject + Multi Observer Abstract Base Class.
void insert_as_observer_of(Dimension const &dim)
Insert as Observer of an Expression's Referenced Dimensions.
Definition: Dimension.hh:598
Dimension & assign_if_nic(int const i, double const m=1.0)
int Assignment if Bigger than Value or Smaller than Multiplier * Value: Notify if Changed ...
Definition: Dimension.cc:429
void notify() const
Notify Observers That This Subject Has Changed.
Definition: Observer.cc:27
Dimension & operator--()
–Dimension
Definition: Dimension.cc:520
DimensionExpression: DimensionExpression Interface Class.
BooleanOptionKey const exit("options:exit")
Definition: OptionKeys.hh:51
Dimension & clear()
Clear the Dimension.
Definition: Dimension.hh:470
DimensionExpressionMul: DimensionExpression Binary Product.
Dimension & operator+=(Dimension const &dim)
+= Dimension
Definition: Dimension.cc:103
int value() const
Value.
Definition: Dimension.hh:420
Dimension: Dynamic Dimension.
Definition: Dimension.hh:38
DimensionExpressionSub: DimensionExpression Binary Subtraction.
std::ostream & operator<<(std::ostream &stream, CArray< T > const &a)
stream << CArray
Definition: CArray.io.hh:33
Dimension & assign_if_half(int const i)
int Assignment if Bigger than Value or Smaller than Half Value
Definition: Dimension.cc:373
bool initialized_
Cached initialization state.
Definition: Dimension.hh:664
Dimension()
Default Constructor.
Definition: Dimension.hh:60
void update_notify()
Update and Notify.
Definition: Dimension.hh:634