1 /**************************************************************************
\r
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
\r
4 * Author: The ALICE Off-line Project. *
\r
5 * Contributors are mentioned in the code where appropriate. *
\r
7 * Permission to use, copy, modify and distribute this software and its *
\r
8 * documentation strictly for non-commercial purposes is hereby granted *
\r
9 * without fee, provided that the above copyright notice appears in all *
\r
10 * copies and that both the copyright notice and this permission notice *
\r
11 * appear in the supporting documentation. The authors make no claims *
\r
12 * about the suitability of this software for any purpose. It is *
\r
13 * provided "as is" without express or implied warranty. *
\r
14 **************************************************************************/
\r
16 /* $Id: AliTRDtrapAlu.cxx 25891 2008-05-19 14:58:18Z fca $ */
\r
18 ///////////////////////////////////////////////////////////////////////////////
\r
20 // TRAP-ALU implementation //
\r
23 // Clemens Haltebourg <halteb@physi.uni-heidelberg.de> //
\r
25 // Usage of the class: //
\r
26 // Declaration of class instances: AliTRDtrapAlu a,b,c; //
\r
27 // Initialization: a.Init(2,11); b.Init(4,4); c.Init(5,4);//
\r
28 // Assigning values: a.AssignDouble(5.7); b.AssignInt(3); //
\r
29 // (you can also do b.AssignDouble(3) with same effect); //
\r
30 // Calculation: c = a*b; //
\r
31 // Test if c has right value: c.WriteWord(); //
\r
32 // Don't declare pointers; operators not overridden for pointer types; //
\r
33 // You have to dereference yourself; //
\r
34 // Use operators +,-,*,/ only with instances of the class; don't do //
\r
35 // things like c=a*2 but rather b.AssignInt(2); c=a*b; //
\r
37 ///////////////////////////////////////////////////////////////////////////////
\r
39 #include "AliTRDtrapAlu.h"
\r
41 ClassImp(AliTRDtrapAlu)
\r
43 //_____________________________________________________________________________
\r
44 AliTRDtrapAlu::AliTRDtrapAlu():TObject()
\r
55 // default constructor
\r
59 //_____________________________________________________________________________
\r
60 AliTRDtrapAlu::~AliTRDtrapAlu(){
\r
64 //_____________________________________________________________________________
\r
65 void AliTRDtrapAlu::Init(const Int_t& precom, const Int_t& postcom, const Int_t& lRestriction, const Int_t& uRestriction){
\r
66 // initialization: characterizes the bit-word (nr of pre- and post-comma bits, boundaries)
\r
69 fValue = 0; //currently, re-initialization kills the value
\r
72 if (fPreCom + fPostCom > 32 || fPreCom > 31) {fPreCom = 1; fPostCom = 0;return;} // prevent pre-comma part exceeding 31 spaces
\r
73 if (fPreCom <= 0) {fPreCom = 1;}
\r
74 if (fPostCom < 0) {fPostCom = 0;}
\r
76 Int_t lut = LUT(fPreCom + fPostCom)-1;
\r
77 if (uRestriction <= -1 || uRestriction > lut) {fuRestriction = lut;}
\r
78 else {fuRestriction = uRestriction;}
\r
79 if (lRestriction <= -1 || lRestriction > fuRestriction) {flRestriction = -lut;}
\r
80 else {flRestriction = lRestriction;}
\r
81 // up to now you can only choose a non-negative lower restriction (e.g. if you want your values to be >=0) ; can't deal with asymmetric borders; have to be implemented if needed
\r
84 //_____________________________________________________________________________
\r
85 Double_t AliTRDtrapAlu::GetValueWhole() const {
\r
86 // get the actual value (respecting pre- and post-comma parts) in integer-description
\r
87 Double_t valPre = (Double_t)(fValue>>fPostCom);
\r
88 Double_t valPost = 0.0;
\r
89 for(Int_t i = 0; i<=fPostCom-1; i++){
\r
90 Double_t num = (fValue>>i)&1;
\r
91 Double_t denom = LUT(fPostCom-i);
\r
92 valPost = valPost + num/denom;
\r
94 Double_t val = valPre + valPost;
\r
98 //_____________________________________________________________________________
\r
99 void AliTRDtrapAlu::WriteWord(){
\r
100 // for debugging purposes
\r
101 printf("bit-word: ");
\r
102 if (fSigned == true) printf("-");
\r
103 for(Int_t i = fPostCom + fPreCom - 1; i >= fPostCom; i--){ //read from behind in order to write the word from left to right
\r
104 printf("%d",(fValue>>i) & 1);
\r
107 for (Int_t j = fPostCom - 1; j >= 0; j--){
\r
108 printf("%d",(fValue>>j) & 1);
\r
114 //_____________________________________________________________________________
\r
115 AliTRDtrapAlu& AliTRDtrapAlu::AssignInt(const Int_t& first){
\r
116 // assign an integer
\r
118 // parameter "first" is an integer for the pre-comma part (not UInt in order to match the error case first<0)
\r
120 Int_t exponent = fPreCom + fPostCom;
\r
124 fValue = 0; //setting fValue to 0; first should not be negative
\r
125 fValue = fValue & 0;
\r
129 if (CheckUSize(first<<fPostCom) == kFALSE){
\r
131 //setting fValue to maximum; first was to big
\r
132 fValue = fuRestriction;
\r
133 fValue = fValue & (LUT(exponent)-1);
\r
137 if (CheckLSize(first<<fPostCom) == kFALSE){
\r
139 //setting fValue to minimum; first was to small
\r
140 fValue = flRestriction;
\r
141 fValue = fValue & (LUT(exponent)-1);
\r
147 fValue = fValue<<fPostCom;
\r
148 fValue = fValue & (LUT(exponent)-1);
\r
154 //_____________________________________________________________________________
\r
155 AliTRDtrapAlu& AliTRDtrapAlu::AssignDouble(const Double_t& first){
\r
159 Int_t exponent = fPreCom + fPostCom;
\r
160 Int_t firstPre = 0; //integer part of first
\r
161 Int_t firstPost = 0; //comma part of first (cut off with enough accuracy
\r
163 Double_t firstPreFloat = 0;
\r
166 Int_t power1 = LUT(exponent);
\r
168 firstPre = (Int_t)first;
\r
169 firstPreFloat = firstPre;
\r
173 fValue = fValue & 0;
\r
177 if(CheckUSize((Int_t)(first*LUT(fPostCom))) == kFALSE){
\r
179 //fValue = MakePower(2,fPreCom) - 1;
\r
180 fValue = fuRestriction;
\r
181 fValue = fValue & (power1 - 1);
\r
185 if(CheckLSize((Int_t)(first*LUT(fPostCom))) == kFALSE){
\r
187 //fValue = MakePower(2,fPreCom) - 1;
\r
188 fValue = flRestriction;
\r
189 fValue = fValue & (power1 - 1);
\r
196 //get post comma part with adequate accuracy
\r
197 firstPost = (Int_t)((first - firstPreFloat)*LUT(fPostCom));
\r
198 for(Int_t i = 1; i <= fPostCom; i++) {
\r
199 c = (firstPost>>(fPostCom - i)) & 1;
\r
200 fValue = fValue<<1;
\r
201 fValue = fValue | c;
\r
204 fValue = fValue & (power1 - 1);
\r
208 //_____________________________________________________________________________
\r
209 AliTRDtrapAlu& AliTRDtrapAlu::operator=(const AliTRDtrapAlu& binary){
\r
210 // assign an object of type AliTRDtrapAlu
\r
213 //Int_t exponent = fPreCom + fPostCom;
\r
216 Int_t power1 = LUT(fPreCom + fPostCom);
\r
218 fValue = binary.GetValue(); // in case this==&binary : binary's values are overwritten
\r
219 Int_t diffPost = binary.GetPost()-fPostCom;
\r
221 if(diffPost<0) check = fValue<<(-diffPost);
\r
222 else check = fValue>>(diffPost);
\r
223 if (CheckUSize(check)==kFALSE){ //checking size of pre-comma part
\r
225 //setting fValue to maximum
\r
228 fValue = fuRestriction; // fuRestriction >= 0
\r
229 fValue = fValue & (power1 - 1);
\r
234 Int_t val = (binary.GetSign()==kFALSE) ? check : -check;
\r
235 if (CheckLSize(val)==kFALSE){ //checking size of pre-comma part
\r
237 //setting fValue to minimum
\r
240 if (flRestriction < 0) {
\r
241 fValue = -flRestriction;
\r
245 fValue = flRestriction;
\r
248 fValue = fValue & (power1 - 1);
\r
252 if (this == & binary) return *this;
\r
255 Int_t iValue = fValue;
\r
256 fValue = fValue>>(binary.GetPost()); //only keep the valid pre-comma bits
\r
258 //append existing post-comma bits to fValue; cut off or add 0 if post-comma numbers don`t match
\r
259 for(Int_t i = 1; i <= fPostCom; i++){
\r
260 if(i <= (binary.GetPost())){
\r
261 c = ((iValue)>>(binary.GetPost()-i)) & 1;
\r
266 fValue = fValue<<1;
\r
267 fValue = fValue | c;
\r
270 fValue = fValue & (power1 - 1);
\r
271 fSigned = binary.GetSign();
\r
275 //_____________________________________________________________________________
\r
276 AliTRDtrapAlu AliTRDtrapAlu::operator+(const AliTRDtrapAlu& binary){
\r
279 //no const parameter because referenced object will be changed
\r
283 Int_t binPre = binary.GetPre();
\r
284 Int_t binPost = binary.GetPost();
\r
285 Int_t binVal = binary.GetValue();
\r
287 Int_t min = Min(binPost,fPostCom);
\r
288 Int_t max = Max(binPre,fPreCom);
\r
290 Int_t shift = binPost - min;
\r
291 Int_t add1 = (binVal)>>(shift); //for addition: cut off at minimum accuracy
\r
292 shift = fPostCom - min;
\r
293 Int_t add2 = fValue>>(shift);
\r
294 if(binary.GetSign() == kTRUE) add1 = -add1;
\r
295 if(fSigned == kTRUE) add2 = -add2;
\r
296 Int_t add = add1 + add2;
\r
299 //because the parameter "binary" could be a reference to the object to which Mem() is a reference, do not change Mem() until you have extracted all information from "binary"; otherwise you change the information you would like to read
\r
300 Mem().Init(max + 1,min); //buffer: enough space for pre-comma,post-comma according to accuracy
\r
301 Mem().AssignFormatted(Max(add,-add));
\r
302 Mem().SetSign(add);
\r
305 //Mem().FastInit(max+1,min,add);
\r
308 alu.Init(max + 1,min); //buffer: enough space for pre-comma,post-comma according to accuracy
\r
309 alu.AssignFormatted(Max(add,-add));
\r
316 //_____________________________________________________________________________
\r
317 AliTRDtrapAlu AliTRDtrapAlu::operator-(const AliTRDtrapAlu& binary){
\r
322 Int_t binPre = binary.GetPre();
\r
323 Int_t binPost = binary.GetPost();
\r
324 Int_t binVal = binary.GetValue();
\r
327 Int_t min = Min(binPost,fPostCom);
\r
328 Int_t max = Max(binPre,fPreCom);
\r
330 Int_t shift = binPost - min;
\r
331 Int_t sub1 = (binVal)>>(shift); //for addition: cut off at minimum accuracy
\r
332 shift = fPostCom - min;
\r
333 Int_t sub2 = fValue>>(shift);
\r
334 if(binary.GetSign() == kTRUE) sub1 = -sub1;
\r
335 if(fSigned == kTRUE) sub2 = -sub2;
\r
336 Int_t sub = sub2 - sub1; // order of subtraction is important
\r
339 Mem().Init(max + 1,min); //buffer: enough space for pre-comma, post-comma according to accuracy
\r
340 Mem().AssignFormatted(Max(sub,-sub));
\r
341 Mem().SetSign(sub);
\r
342 //Mem().FastInit(max+1,min,sub);
\r
345 alu.Init(max + 1,min);
\r
346 alu.AssignFormatted(Max(sub,-sub));
\r
353 //_____________________________________________________________________________
\r
354 AliTRDtrapAlu AliTRDtrapAlu::operator*(const AliTRDtrapAlu& binary){
\r
359 Int_t binPre = binary.GetPre();
\r
360 Int_t binPost = binary.GetPost();
\r
363 Int_t min = Min(binPost,fPostCom);
\r
364 Int_t max = Max(binPre,fPreCom);
\r
367 Int_t mult1 = binary.GetValue();
\r
368 Int_t mult2 = fValue;
\r
369 Int_t shift = (Int_t)(fPostCom + binPost - min);
\r
370 Double_t fmult1 = (Double_t)mult1;
\r
371 Double_t fmult2 = (Double_t)mult2;
\r
372 (fmult1 > fmult2) ? fmult1 = fmult1/LUT(shift) : fmult2 = fmult2/LUT(shift);
\r
375 if (binary.GetSign() == kTRUE) fmult1 = -fmult1;
\r
376 if (fSigned == kTRUE) fmult2 = -fmult2;
\r
377 Double_t fmult = fmult1*fmult2;
\r
378 Int_t mult = (Int_t)fmult;
\r
380 if(mult<0) sign = -1;
\r
381 mult = Max(mult,-mult);
\r
382 //Int_t shift = fPostCom + binPost - min;
\r
383 //mult = mult>>(shift);
\r
386 Mem().Init(2 * max + 1, min); // +1 to consider the borrow from the past-comma part; accuracy of past-comma part is determined by the minimum; therefore, for the result not more accuracy is guaranteed
\r
387 // be aware that this only works if 2*max+1+min <= 32!! adjusting the pre-comma place to the value would consume too much time
\r
389 Mem().AssignFormatted(mult);
\r
390 Mem().SetSign(sign);
\r
391 //mult = sign*mult;
\r
392 //Mem().FastInit(2*max+1,min,mult);
\r
395 alu.Init(2 * max + 1, min); // +1 to consider the borrow from the past-comma part; accuracy of past-comma part is determined by the minimum; therefore, for the result not more accuracy is guaranteed
\r
396 // be aware that this only works if 2*max+1+min <= 32!! adjusting the pre-comma place to the value would consume too much time
\r
398 alu.AssignFormatted(mult);
\r
404 //_____________________________________________________________________________
\r
405 AliTRDtrapAlu AliTRDtrapAlu::operator/(const AliTRDtrapAlu& binary){
\r
410 Int_t binPre = binary.GetPre();
\r
411 Int_t binPost = binary.GetPost();
\r
412 Int_t min = Min(binPost,fPostCom);
\r
413 Int_t max = Max(binPre,fPreCom);
\r
415 Int_t div1 = binary.GetValue(); //value in integer format
\r
416 Int_t div2 = fValue;
\r
418 // this approach does not always work because it can exceed the range of integers
\r
419 //Int_t numerator = div2 * LUT(min);
\r
420 Int_t numerator = div2;
\r
421 if (fSigned == kTRUE) numerator = numerator*(-1);
\r
422 Int_t denominator = div1;
\r
423 if (binary.GetSign() == kTRUE) denominator = denominator*(-1);
\r
424 Double_t fdiv = 0.0;
\r
425 Double_t fLUT = 0.0;
\r
430 /*Mem().Init(max + 1,min);
\r
431 Mem().AssignFormatted(LUT(max+min+1)-1); // division by 0: set to max value
\r
432 //Mem().FastInit(max+1,min,div1);
\r
434 alu.Init(max + 1,min);
\r
435 alu.AssignFormatted(LUT(max+min+1)-1); // division by 0: set to max value
\r
439 fdiv = (Double_t)numerator/denominator;
\r
441 Int_t shift = fPostCom - binPost;
\r
444 //denominator = denominator * LUT(shift);
\r
445 fLUT = (Double_t)LUT(min)/LUT(shift);
\r
450 //numerator = numerator * LUT(shift);
\r
451 fLUT = (Double_t)LUT(min)*LUT(shift);
\r
454 fLUT = (Double_t)LUT(min);
\r
461 Int_t sign = (div>=0) ? 1 : -1;
\r
462 div = Max(div,-div);
\r
464 // chose min as past-comma part because from a division of integers you can't get only an integer
\r
466 /*Mem().Init(max + 1,min); // max+1+min must <= 32!!
\r
467 Mem().SetSign(sign);
\r
468 Mem().AssignFormatted(div);
\r
472 alu.Init(max + 1,min); // max+1+min must <= 32!!
\r
474 alu.AssignFormatted(div);
\r
481 //_____________________________________________________________________________
\r
482 Int_t AliTRDtrapAlu::MakePower(const Int_t& base,const Int_t& exponent)const{
\r
483 // calculate "base" to the power of "exponent"
\r
486 for(Int_t i = 1; i <= exponent; i++){
\r
487 result = result * base;
\r
492 //_____________________________________________________________________________
\r
493 Int_t AliTRDtrapAlu::LUT(const Int_t& index){
\r
494 // simple look-up table for base=2
\r
498 static Bool_t fLUT = kFALSE;
\r
499 static Int_t gLUT[30];
\r
500 if (fLUT == kFALSE) {
\r
502 for(Int_t i = 1; i<30; i++) {
\r
503 gLUT[i] = gLUT[i-1] * 2;
\r
507 if (index >=0 && index < 30){
\r
508 return gLUT[index];
\r
512 //return Mem().MakePower(2,index);
\r
513 return alu.MakePower(2,index);
\r