~vbursian/research-assistant/intervers

« back to all changes in this revision

Viewing changes to RANet/Ranges.cpp

  • Committer: Viktor Bursian
  • Date: 2013-06-06 15:10:08 UTC
  • Revision ID: vbursian@gmail.com-20130606151008-6641eh62f0lgx8jt
Tags: version_0.3.0
version 0.3.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
                     Viktor.Bursian@mail.ioffe.ru
6
6
*///////////////////////////////////////////////////////////////////////////////
7
7
#include "Ranges.h"
 
8
#include "Symbols.h"
 
9
#include "Log.h"
 
10
#include "Trace.h"
8
11
namespace RA {
9
12
//------------------------------------------------------------------------------
10
13
 
16
19
    :TheUnits()
17
20
    ,UnitsAreFixedFlag(false)
18
21
    ,TheOrder(0)
19
 
    ,TheFromMantissa( - std::numeric_limits<real>::infinity() )
20
 
    ,TheToMantissa( std::numeric_limits<real>::infinity() )
 
22
    ,TheFromMantissa( - real_inf )
 
23
    ,TheToMantissa( real_inf )
21
24
    ,ThePrecisionMantissa(0.0)
22
25
    ,TheDigits(sPhysValue::MaxDigits-1)
23
 
{
24
 
};
25
 
 
26
 
 
27
 
sPhysRange::sPhysRange (real  from  ,real  to  ,sUnits  units  ,real  precision)
28
 
    :TheUnits(units)
29
 
    ,UnitsAreFixedFlag(true)
30
 
    ,TheOrder(0)
31
 
    ,TheFromMantissa(from)
32
 
    ,TheToMantissa(to)
33
 
    ,ThePrecisionMantissa(fabs(precision))
34
 
{
35
 
  Normalize();
36
 
};
37
 
 
38
 
 
39
 
//sPhysRange::sPhysRange (sPhysValue from ,sPhysValue to)
40
 
//    :TheUnits(to.Units())
41
 
//    ,UnitsAreFixedFlag(true)
42
 
//    ,TheOrder(0)
43
 
//    ,ThePrecisionMantissa(0.0)
44
 
//    ,TheDigits(sPhysValue::MaxDigits-1)
45
 
//{
46
 
//  real                        C;
47
 
//  if( ! to.Units().Comparable(from.Units(),C) )
48
 
//    throw xRealAlgebra();
49
 
//  TheToMantissa=to.Value();
50
 
//  TheFromMantissa=from.Value() / C;
51
 
//  ...
52
 
//  Normalize();
53
 
//};
54
 
 
55
 
 
56
 
sPhysRange::sPhysRange (rcsPhysRange range)
57
 
    :sStorable()
58
 
    ,TheUnits(range.TheUnits)
59
 
    ,UnitsAreFixedFlag(range.UnitsAreFixedFlag)
60
 
    ,TheOrder(range.TheOrder)
61
 
    ,TheFromMantissa(range.TheFromMantissa)
62
 
    ,TheToMantissa(range.TheToMantissa)
63
 
    ,ThePrecisionMantissa(range.ThePrecisionMantissa)
64
 
    ,TheDigits(range.TheDigits)
 
26
    ,NormalizationLevel(99)
65
27
{
66
28
};
67
29
 
75
37
  a_stream.READ_INTO(TheFromMantissa);
76
38
  a_stream.READ_INTO(TheToMantissa);
77
39
  a_stream.READ_INTO(ThePrecisionMantissa);
78
 
  Normalize();
 
40
  a_stream.READ_INTO(TheDigits);
 
41
  a_stream.READ_INTO(NormalizationLevel);
79
42
};
80
43
 
81
44
 
88
51
  a_stream.WRITE_FROM(TheFromMantissa);
89
52
  a_stream.WRITE_FROM(TheToMantissa);
90
53
  a_stream.WRITE_FROM(ThePrecisionMantissa);
 
54
  a_stream.WRITE_FROM(TheDigits);
 
55
  a_stream.WRITE_FROM(NormalizationLevel);
 
56
};
 
57
 
 
58
 
 
59
sPhysRange::sPhysRange (rcsUnits  units)
 
60
    :TheUnits(units)
 
61
    ,UnitsAreFixedFlag(true)
 
62
    ,TheOrder(0)
 
63
    ,TheFromMantissa( - real_inf )
 
64
    ,TheToMantissa( real_inf )
 
65
    ,ThePrecisionMantissa(0.0)
 
66
    ,TheDigits(sPhysValue::MaxDigits-1)
 
67
    ,NormalizationLevel(1)
 
68
{
 
69
  Normalize(sPhysValue::DraftNormalization);
 
70
};
 
71
 
 
72
 
 
73
sPhysRange::sPhysRange (real      from
 
74
                       ,real      to
 
75
                       ,rcsUnits  units
 
76
                       ,real      precision)
 
77
    :TheUnits(units)
 
78
    ,UnitsAreFixedFlag(true)
 
79
    ,TheOrder(0)
 
80
    ,TheFromMantissa(from)
 
81
    ,TheToMantissa(to)
 
82
    ,ThePrecisionMantissa(rabs(precision))
 
83
    ,TheDigits(sPhysValue::MaxDigits-1)
 
84
    ,NormalizationLevel(0)
 
85
{
 
86
  Normalize(sPhysValue::DraftNormalization);
 
87
};
 
88
 
 
89
 
 
90
sPhysRange::sPhysRange (sString  unitsstr)
 
91
    :TheUnits(unitsstr)
 
92
    ,UnitsAreFixedFlag(true)
 
93
    ,TheOrder(0)
 
94
    ,TheFromMantissa( - real_inf )
 
95
    ,TheToMantissa( real_inf )
 
96
    ,ThePrecisionMantissa(0.0)
 
97
    ,TheDigits(sPhysValue::MaxDigits-1)
 
98
    ,NormalizationLevel(1)
 
99
{
 
100
  Normalize(sPhysValue::DraftNormalization);
 
101
};
 
102
 
 
103
 
 
104
sPhysRange::sPhysRange (real     from
 
105
                       ,real     to
 
106
                       ,sString  unitsstr
 
107
                       ,real     precision)
 
108
    :TheUnits(unitsstr)
 
109
    ,UnitsAreFixedFlag(true)
 
110
    ,TheOrder(0)
 
111
    ,TheFromMantissa(from)
 
112
    ,TheToMantissa(to)
 
113
    ,ThePrecisionMantissa(rabs(precision))
 
114
    ,TheDigits(sPhysValue::MaxDigits-1)
 
115
    ,NormalizationLevel(0)
 
116
{
 
117
  Normalize(sPhysValue::DraftNormalization);
 
118
};
 
119
 
 
120
 
 
121
sPhysRange::sPhysRange (rcsPhysValue from ,rcsPhysValue to)
 
122
    :TheUnits(from.Units())
 
123
    ,UnitsAreFixedFlag(true)
 
124
    ,TheOrder(0)
 
125
    ,ThePrecisionMantissa(0.0)
 
126
    ,TheDigits(sPhysValue::MaxDigits-1)
 
127
    ,NormalizationLevel(0)
 
128
{
 
129
  real                        Ratio;
 
130
  if( ! from.Units().Comparable(to.Units(),Ratio) )
 
131
    throw xRAlgebra();
 
132
  TheFromMantissa=from.ArbValue();
 
133
  TheToMantissa=to.ArbValue() / Ratio;
 
134
  ThePrecisionMantissa = rabs(to.ArbError() / Ratio);
 
135
  if( ThePrecisionMantissa < rabs(from.ArbError()) )
 
136
    ThePrecisionMantissa = rabs(from.ArbError());
 
137
  Normalize(sPhysValue::DraftNormalization);
 
138
//  RANet::Log.Put(sLog::Debug,"sPhysRange::sPhysRange"
 
139
//      ,sString("sPhysRange::sPhysRange(")+from.Text()+","+to.Text()+")="+Txt()
 
140
//      +(sString("         Ratio=")<<Ratio)
 
141
//      );
 
142
};
 
143
 
 
144
 
 
145
sPhysRange::sPhysRange (rcsPhysRange range)
 
146
    :sStorable()
 
147
    ,TheUnits(range.TheUnits)
 
148
    ,UnitsAreFixedFlag(range.UnitsAreFixedFlag)
 
149
    ,TheOrder(range.TheOrder)
 
150
    ,TheFromMantissa(range.TheFromMantissa)
 
151
    ,TheToMantissa(range.TheToMantissa)
 
152
    ,ThePrecisionMantissa(range.ThePrecisionMantissa)
 
153
    ,TheDigits(range.TheDigits)
 
154
    ,NormalizationLevel(range.NormalizationLevel)
 
155
{
91
156
};
92
157
 
93
158
 
94
159
rsPhysRange  sPhysRange::operator = (rcsPhysRange range)
95
160
{
96
 
  real                        C=1.0;
 
161
  real                        Ratio=1.0;
97
162
  if( ! UnitsAreFixedFlag ){
98
 
    TheUnits=range.TheUnits;
99
 
    TheOrder=range.TheOrder;
100
 
    TheFromMantissa=range.TheFromMantissa;
101
 
    TheToMantissa=range.TheToMantissa;
102
 
    ThePrecisionMantissa=range.ThePrecisionMantissa;
103
 
    TheDigits=range.TheDigits;
104
 
  }else if( TheUnits.Comparable(range.TheUnits,C) ){
105
 
    TheOrder=range.TheOrder;
106
 
    TheFromMantissa=range.TheFromMantissa / C;
107
 
    TheToMantissa=range.TheToMantissa / C;
108
 
    ThePrecisionMantissa=range.ThePrecisionMantissa / C;
109
 
    Normalize();
 
163
    TheUnits = range.TheUnits;
 
164
    TheOrder = range.TheOrder;
 
165
    TheFromMantissa = range.TheFromMantissa;
 
166
    TheToMantissa = range.TheToMantissa;
 
167
    ThePrecisionMantissa = range.ThePrecisionMantissa;
 
168
    TheDigits = range.TheDigits;
 
169
    NormalizationLevel = range.NormalizationLevel;
 
170
  }else if( TheUnits.Comparable(range.TheUnits,Ratio) ){
 
171
    TheOrder = range.TheOrder;
 
172
    TheFromMantissa = range.TheFromMantissa / Ratio;
 
173
    TheToMantissa = range.TheToMantissa / Ratio;
 
174
    ThePrecisionMantissa = rabs(range.ThePrecisionMantissa / Ratio);
 
175
    NormalizationLevel = 0;
 
176
    Normalize(sPhysValue::DraftNormalization);
110
177
  }else{
111
 
    throw xRealAlgebra();
 
178
    throw xRAlgebra();
112
179
  };
113
180
  return *this;
114
181
};
128
195
{
129
196
  real                        C=1.0;
130
197
  if( ! TheUnits.Comparable(range.TheUnits,C) )
131
 
    throw xRealAlgebra();
 
198
    throw xRAlgebra();
132
199
  C *= power10(TheOrder-range.TheOrder);
133
200
  if( TheFromMantissa < range.TheFromMantissa / C ){
134
201
    TheFromMantissa=range.TheFromMantissa / C;
135
202
    ThePrecisionMantissa=std::max(ThePrecisionMantissa
136
203
                                 ,range.ThePrecisionMantissa / C);
137
 
    Normalize();
138
 
  }else if( range.TheToMantissa / C < TheToMantissa ){
 
204
  }else if( TheToMantissa > range.TheToMantissa / C ){
139
205
    TheToMantissa=range.TheToMantissa / C;
140
206
    ThePrecisionMantissa=std::max(ThePrecisionMantissa
 
207
                                 ,rabs(range.ThePrecisionMantissa / C));
 
208
  };
 
209
  NormalizationLevel = 0;
 
210
  Normalize(sPhysValue::DraftNormalization);
 
211
  return *this;
 
212
};
 
213
 
 
214
 
 
215
rsPhysRange  sPhysRange::operator |= (sPhysRange  range)
 
216
{
 
217
  real                        C=1.0;
 
218
  if( ! TheUnits.Comparable(range.TheUnits,C) )
 
219
    throw xRAlgebra();
 
220
  C *= power10(TheOrder-range.TheOrder);
 
221
  if( TheFromMantissa > range.TheFromMantissa / C ){
 
222
    TheFromMantissa=range.TheFromMantissa / C;
 
223
    ThePrecisionMantissa=std::max(ThePrecisionMantissa
141
224
                                 ,range.ThePrecisionMantissa / C);
142
 
    Normalize();
 
225
  }else if( TheToMantissa < range.TheToMantissa / C ){
 
226
    TheToMantissa=range.TheToMantissa / C;
 
227
    ThePrecisionMantissa=std::max(ThePrecisionMantissa
 
228
                                 ,rabs(range.ThePrecisionMantissa / C));
143
229
  };
 
230
  NormalizationLevel = 0;
 
231
  Normalize(sPhysValue::DraftNormalization);
144
232
  return *this;
145
233
};
146
234
 
147
235
 
 
236
void  sPhysRange::Normalize (unsigned short int  level)
 
237
{
 
238
  if( level <= NormalizationLevel )
 
239
    return;
 
240
  RANet::Log.OpenBlock(sLog::Debug,"sPhysRange::Normalize",Txt());
 
241
  real                        MaxMantissa;
 
242
  if(     ( isnan(TheFromMantissa) || isinf(TheFromMantissa) )
 
243
       && ( isnan(TheToMantissa) || isinf(TheToMantissa) ) ){
 
244
    if( level > 1 )  TheUnits.DissolveOrder(level);
 
245
    TheOrder = 0;
 
246
  }else{
 
247
    if( isnan(TheFromMantissa) || isinf(TheFromMantissa) ){
 
248
      MaxMantissa = fabs(TheToMantissa);
 
249
    }else if( isnan(TheToMantissa) || isinf(TheToMantissa) ){
 
250
      MaxMantissa = fabs(TheFromMantissa);
 
251
    }else{
 
252
      MaxMantissa = std::max( fabs(TheFromMantissa) , fabs(TheToMantissa) );
 
253
    };
 
254
    if( (MaxMantissa == 0) && (ThePrecisionMantissa == 0) ){
 
255
      if( level > 1 )  TheUnits.DissolveOrder(level);
 
256
      TheOrder = 0;
 
257
      TheDigits = sPhysValue::MaxDigits;
 
258
    }else{
 
259
      int                         Shift = 0;
 
260
      bool                        TryToIncreaseExpectedRest = false;
 
261
      int                         ExpectedRest = 0;
 
262
      real                        C = 1.0;
 
263
      //приведение мантисс: V к [0.1,1) или если |V|<E, то E к [0.1,1)
 
264
      //и вычисление максимального сдвига,
 
265
      //допустимого после приведения единиц
 
266
      {
 
267
        if( rabs(MaxMantissa) < ThePrecisionMantissa ){
 
268
//          TRACENOCR("|V|<E");
 
269
          real                        LgE = log10(ThePrecisionMantissa);
 
270
          if( LgE == - real_inf ){
 
271
            TRACENOCR("АБЗДАЧА-LgE-1");
 
272
          }else if( LgE == real_inf ){
 
273
            TRACENOCR("АБЗДАЧА-LgE-2");
 
274
          }else if( isnan(LgE) ){
 
275
            TRACENOCR("АБЗДАЧА-LgE-3");
 
276
          }else{
 
277
            Shift = floor(LgE)+1;
 
278
          };
 
279
        }else{
 
280
          real                        LgV = log10(rabs(MaxMantissa));
 
281
          if( LgV == -real_inf ){
 
282
            TRACENOCR("АБЗДАЧА-LgV-1");
 
283
          }else if( LgV == real_inf ){
 
284
            TRACENOCR("АБЗДАЧА-LgV-2");
 
285
          }else if( isnan(LgV) ){
 
286
            TRACENOCR("АБЗДАЧА-LgV-3");
 
287
          }else{
 
288
            Shift = floor(LgV)+1;
 
289
          };
 
290
          TryToIncreaseExpectedRest = true;
 
291
        };
 
292
      };
 
293
      if( Shift != 0 ){
 
294
        C = power10(Shift);
 
295
        TheFromMantissa /= C;
 
296
        TheToMantissa /= C;
 
297
        ThePrecisionMantissa /= C;
 
298
        TheOrder += Shift;
 
299
      };
 
300
      if( TryToIncreaseExpectedRest ){
 
301
        if( ThePrecisionMantissa < 0.1 )  ExpectedRest = 1;
 
302
        if( ThePrecisionMantissa < 0.01 )  ExpectedRest = 2;
 
303
        if( ThePrecisionMantissa < 0.001 )  ExpectedRest = 3;
 
304
      };
 
305
      if( level > 1 ){
 
306
        TheOrder = TheUnits.DissolveOrder(level,TheOrder
 
307
                                         ,ExpectedRest-2,ExpectedRest);
 
308
      };
 
309
      if( TheOrder < 0 ){
 
310
        Shift = TheOrder - floor(TheOrder/3)*3;
 
311
      }else{
 
312
        Shift = TheOrder - floor((TheOrder-1)/3)*3;
 
313
      };
 
314
      if( Shift != 0 ){
 
315
        TheOrder = TheOrder - Shift;
 
316
        C = power10(Shift);
 
317
        TheFromMantissa *= C;
 
318
        TheToMantissa *= C;
 
319
        ThePrecisionMantissa *= C;
 
320
      };
 
321
      real                        D = log10(0.3/ThePrecisionMantissa);
 
322
      TheDigits = ( D > sPhysValue::MaxDigits ? sPhysValue::MaxDigits
 
323
                                              : ( D < 0 ? 0 : ceil(D) ) );
 
324
    };
 
325
  };
 
326
  NormalizationLevel = level;
 
327
  RANet::Log.Put(sLog::Debug,"sPhysRange::Normalize",sString("finally ")+Txt());
 
328
  RANet::Log.CloseBlock(sLog::Debug,"sPhysRange::Normalize");
 
329
};
 
330
 
 
331
 
 
332
sString  sPhysRange::Text (eTextFormat  F)
 
333
{
 
334
//  RANet::Log.Put(sLog::Debug,"sPhysRange::Text","");
 
335
  if( NormalizationLevel < sPhysValue::BriefNormalization ){
 
336
    Normalize(sPhysValue::BriefNormalization);
 
337
  };
 
338
  return Txt(F);
 
339
};
 
340
 
 
341
 
148
342
sString  sPhysRange::Text (eTextFormat  F) const
149
343
{
 
344
//  RANet::Log.Put(sLog::Debug,"sPhysRange::Text","const");
 
345
  if( NormalizationLevel < sPhysValue::BriefNormalization ){
 
346
    sPhysRange                  NormalizedForm(*this);
 
347
    NormalizedForm.Normalize(sPhysValue::BriefNormalization);
 
348
    return NormalizedForm.Txt(F);
 
349
  }else{
 
350
    return Txt(F);
 
351
  };
 
352
};
 
353
 
 
354
 
 
355
sString  sPhysRange::Txt (eTextFormat  F) const
 
356
{
150
357
  sString                     T("[");
151
 
  T += sString::from_real(TheFromMantissa,TheDigits);
 
358
  sString                     UT;
 
359
  T += sString::FromReal(TheFromMantissa,TheDigits);
152
360
  T += "…";
153
 
  T += sString::from_real(TheToMantissa,TheDigits);
 
361
  T += sString::FromReal(TheToMantissa,TheDigits);
154
362
  T += "]";
155
363
  if( TheOrder ){
156
364
    if( F == HTML ){
157
 
      T += "×10<sup>";
 
365
      T += Symbol::Multiplication;
 
366
      T += "10<sup>";
158
367
    }else{
159
368
      T += "*1e";
160
369
    };
161
370
    T << TheOrder;
162
371
    if( F == HTML ){
163
 
      T += "</sup>";
164
 
    }else{
165
 
      T += " ";
 
372
      T += "</sup> ";
166
373
    };
167
374
  };
168
 
  T += TheUnits.Text(F);
 
375
  UT = TheUnits.Text(F);
 
376
  if( ! UT.Empty() ){
 
377
    T += " ";
 
378
    T += UT;
 
379
  };
169
380
  return T;
170
381
};
171
382
 
172
 
 
173
 
void  sPhysRange::Normalize ()
174
 
{
175
 
  real                        V = std::max(fabs(TheFromMantissa)
176
 
                                          ,fabs(TheToMantissa)  );
177
 
  real                        LgV = log10(V);
178
 
  int                         FloorLgV;
179
 
  int                         BeforeDot = 1;
180
 
  int                         log_shift = 0;
181
 
  real                        C = 1.0;
182
 
  real                        D = 1.0;
183
 
  ThePrecisionMantissa = fabs(ThePrecisionMantissa);
184
 
  if( LgV == -std::numeric_limits<real>::infinity() ){
185
 
//    TRACE( "Normalize  -inf" );
186
 
    D = log10(fabs(0.3*C/ThePrecisionMantissa));
187
 
//    { sString T; TRACE( T<<D ); };
188
 
//    TRACE( BeforeDot );
189
 
//    TRACE( log_shift );
190
 
  }else if( LgV == std::numeric_limits<real>::infinity() ){
191
 
//    TRACE( "Normalize  +inf" );
192
 
//    { sString T; TRACE( T<<D ); };
193
 
//    TRACE( BeforeDot );
194
 
//    TRACE( log_shift );
195
 
  }else{
196
 
//    TRACE( "Normalize" );
197
 
    FloorLgV = floor(LgV / 3);
198
 
    log_shift = FloorLgV * 3;
199
 
    BeforeDot = floor(LgV) - log_shift + 1;
200
 
    C = power10(log_shift);
201
 
    D = log10(fabs(0.3*C/ThePrecisionMantissa));
202
 
  };
203
 
  TheDigits = ( D > sPhysValue::MaxDigits-BeforeDot
204
 
              ? sPhysValue::MaxDigits-BeforeDot
205
 
              : ( D < 0 ? 0 : ceil(D) ) );
206
 
//  TRACE( TheDigits );
207
 
  if( (V == 0.0) || isinf(V) || isnan(V) ){
208
 
    TheOrder=0;
209
 
  }else{
210
 
    TheFromMantissa /= C;
211
 
    TheToMantissa /= C;
212
 
    ThePrecisionMantissa /= C;
213
 
    TheOrder+=log_shift;
214
 
  };
215
 
};
216
 
 
217
383
//------------------------------------------------------------------------------
218
384
}; //namespace RA