///////////////////////////////////////////////////////////////////////////////
//  Pluto Utilities Class
//
//  This is a static class containing utility functions.
//
//                             Author:  M.A. Kagarlis
//                             Written: 15.12.98
//                             Revised: 15.06.00
//
// Ref 1: CERNLIB function FLPSOR, R.S. Scowen, Algorithm 271 QUICKERSORT,
//        Collected Algorithms from CACM (1965) (sorting function dsort)
// Ref 2: D.M. Brink and G.R. Satchler, Angular Momentum, Oxford Library (1961)
///////////////////////////////////////////////////////////////////////////////

#include <iostream>
#include "TString.h"
#include "TObjArray.h"
#include "TObjString.h"
#include "TMath.h"


const Double_t fact[34]={1.,1.,2.,6.,2.4e1,1.2e2,7.2e2,5.04e3,4.032e4,
			 3.6288e5,3.6288e6,3.99168e7,4.790016e8,6.2270208e9,
			 8.71782912e10,1.307674368e12,2.0922789888e13,
			 3.556874281e14,6.4023737057e15,1.2164510041e17,
			 2.4329020082e18,5.1090942172e19,1.1240007278e21,
			 2.5852016739e22,6.2044840173e23,1.5511210043e25,
			 4.0329146113e26,1.088886945e28,3.0488834461e29,
			 8.8417619937e30,2.6525285981e32,8.2228386542e33,
			 2.6313083693e35,8.6833176188e36}; // factorials to 33!

#include "PUtils.h"


void PUtils::correct_histo(TH1 *histo) {
    Int_t nbins=0;
    for(int i=0; i<histo->GetNbinsX(); i++)
	if (histo->GetBinContent(i)) nbins++;
    histo->Scale(nbins);
}

void PUtils::correct(TH1 *histo) {
    histo->Scale(1./histo->GetBinWidth(1));
}

void PUtils::dsort(Double_t *a, int n) {
    // Sort in ascending order the first n entries of the array *a.
  int i, j, l, m, r, rt[20], lt[20], level=1;
  Double_t x, w;
  lt[0] = 1;
  rt[0] = n;
 a: 
  l = lt[level-1];
  r = rt[level-1];
  --level;
 b:
  if (r <= l) {
    if (level > 0) goto a;
    else return;
  }
  i = l;
  j = r;
  m = (l+r)/2;
  x = *(a+m-1);
//  cout << "X: " << x << endl;
 c:
  while (*(a+i-1) < x) ++i;
  while (*(a+j-1) > x) --j;
  while (i <= j) {
    w = *(a+i-1);
    *(a+i-1) = *(a+j-1);
    *(a+j-1) = w;
    ++i;
    --j;
    if (i < j) goto c;
  }
  ++level;
  if (r-i >= j-l) {
    lt[level-1] = i;
    rt[level-1] = r;
    r = j;
  } else {
    lt[level-1] = l;
    rt[level-1] = j;
  }
  goto b;
}

Double_t PUtils::cgc(const int &jx1, const int &jx2, const int &jx3,
		     const int &mx1, const int &mx2) {
    // Clebsch-Gordan coefficients (arguments are 2x the corresponding j and m)
    int j1=jx1, j2=jx2, j3=jx3, m1=mx1, m2=mx2, icntr, it, jz1, jz2, jz3,
	jt1, jt2, jt3, jt4, jt5, j4, j5, numin, numax;
    Double_t vcc = 0., fctor, phas;
    if ((j1+j2+j3)%2 || (j1+m1)%2 || (j2+m2)%2) return vcc;
    j1 = jx1;
    j2 = jx2;
    j3 = jx3;
    m1 = mx1;
    m2 = mx2;
    if (j1 < j2) goto a;
    if (j3 < j2) goto b;
    icntr = 0;
    goto c;
 a:
    if (j3 < j1) goto b;
    icntr = -1;
    it = j1;
    j1 = j2;
    j2 = it;
    it = m1;
    m1 = m2;
    m2 = it;
    goto c;
 b:
    icntr = 1;
    it = j2;
    j2 = j3;
    j3 = it;
    m2 = -m1-m2;
 c:
    jz1 = (j1+j2-j3)/2;
    if (jz1 < 0) return vcc;
    jz2 = (j1+j3-j2)/2;
    if (jz2 < 0) return vcc;
    jz3 = (j2+j3-j1)/2;
    if (jz3<0 || j1-abs(m1)<0 || j2-abs(m2)<0 || j3-abs(m1+m2)<0) return vcc;
    jt1 = (j1-j3+m2)/2;
    jt2 = (j2-j3-m1)/2;
    numin = TMath::Max(TMath::Max(jt1,jt2), 0);
    jt3 = (j1-m1)/2;
    jt4 = (j2+m2)/2;
    numax = TMath::Min(TMath::Min(jt3,jt4), jz1);
    jt5 = (j2-m2)/2;
    if (numax < numin) return vcc;
    j4 = j1/2;
    j5 = j3/2;
    phas = phasef(numin);
    for (int nu=numin; nu<=numax; ++nu) {
	vcc += phas*fact[j4]*fact[j5]/
	    (fact[jt3-nu]*fact[nu-jt2]*fact[jt4-nu]*
	     fact[nu-jt1]*fact[jz1-nu]*fact[nu]);
	phas = -phas;
    }
    fctor = fact[(j1+m1)/2]*fact[jt3]*fact[jz2]*fact[(j3+m1+m2)/2]*
	fact[(j3-m1-m2)/2]*fact[jz1]*fact[jz3]*fact[jt4]*fact[jt5]*(j3+1)/
	(fact[j4]*fact[j4]*fact[(j1+j2+j3)/2+1]*fact[j5]*fact[j5]);
    vcc *= sqrt(fctor);
    if (icntr < 0) 
	vcc *= phasef(jz1);
    else if (icntr > 0) 
	vcc *= sqrt(Double_t(j2+1)/Double_t(j3+1))*phasef(jt3);
    return vcc;
}

Double_t PUtils::s3j(const Double_t &jx1, const Double_t &jx2, const Double_t &jx3,
		     const Double_t &jm1, const Double_t &jm2, Double_t jm3) {
    // 3j-symbol, related to Clebsch-Gordan coefficient
    if (jm3!=0 && jm1+jm2+jm3!=0.) return 0.;
    int j1 = 2*int(jx1), 
	j2 = 2*int(jx2), 
	j3 = 2*int(jx3),
	m1 = 2*int(jm1), 
	m2 = 2*int(jm2);
    return cgc(j1,j2,j3,m1,m2)*phasef((j1-j2+m1+m2)/2)/sqrt(1.+j3);
}

Double_t PUtils::racah(const int &j1, const int &j2, const int &j3,
		       const int &j4, const int &j5, const int &j6) {
    // Racah coefficients (arguments are 2 x j or m)
    Double_t z1 = j123(j1, j2, j5), 
	z2 = j123(j1, j3, j6);
    if (z1==0. || z2==0.) return 0.;
    z1 *= j123(j3, j4, j5);
    if (z1 == 0.) return 0.;
    z2 *= j123(j2, j4, j6);
    if (z2 == 0.) return 0.;
    z1 = z2*sqrt(z1/z2);
    int jt1 = (j1+j2+j5)/2, 
	jt2 = (j3+j4+j5)/2, 
	jt3 = (j1+j3+j6)/2,
	jt4 = (j2+j4+j6)/2, 
	jz1 = (j1+j2+j3+j4)/2, 
	jz2 = (j1+j4+j5+j6)/2,
	jz3 = (j2+j3+j5+j6)/2, 
	numin = TMath::Max(TMath::Max(jt1,jt2), TMath::Max(jt3,jt4)),
	numax = TMath::Min(TMath::Min(jz1,jz2), jz3);
    if (numax < numin) return 0.;
    Double_t phase = phasef(numin+jz1)*z1, 
	r = 0.;
    for (int nu=numin; nu<=numax; ++nu) {
	int jy1 = nu-jt1, 
	    jy2 = nu-jt2, 
	    jy3 = nu-jt3,
	    jy4 = jz1-nu, 
	    jy5 = jz2-nu, 
	    jy6 = jz3-nu;
	Double_t fctor = fact[jy1]*fact[jy2]*fact[jy3]*fact[nu-jt4]*
	    fact[jy4]*fact[jy5]*fact[jy6]/fact[nu+1];
	if (fctor > 0.) 
	    r += phase/fctor;
    }
    return r;
}

Double_t PUtils::s6j(const Double_t &x1, const Double_t &x2, const Double_t &x3,
		     const Double_t &x4, const Double_t &x5, const Double_t &x6) {
    // 6j-symbol, related to Racah coefficient
    int j1 = 2*int(x1), 
	j2 = 2*int(x2), 
	j3 = 2*int(x3),
	j4 = 2*int(x4), 
	j5 = 2*int(x5), 
	j6 = 2*int(x6);
    return racah(j1,j2,j5,j4,j3,j6)*phasef((j1+j2+j4+j5)/2);
}

Double_t PUtils::j123(const int &j1, const int &j2, const int &j3) {
    // used by Racah
    int jz1 = (j1+j2-j3)/2, 
	jz2 = (j1-j2+j3)/2, 
	jz3 = (j2+j3-j1)/2, 
	jz4 = (j1+j2+j3)/2+1;
    return (jz1<0||jz2<0||jz3<0) ? 0. : fact[jz1]*fact[jz2]*fact[jz3]/fact[jz4];
}
  
Int_t PUtils::FindIndex(Int_t n, Double_t *a, Double_t r) {
    // return index i of first element a[i] which is larger than r.
    // a[] is assumed to be sorted in ascending order
    Int_t imin  = 0;
    Int_t imax  = n-1;
    Int_t ihalf = (imin+imax)/2;
    if (a[0] > r) return 0;
    while (ihalf > imin) {  // algorithm is by binary search
	if (a[ihalf] < r) 
	    imin = ihalf;
	else 
	    imax = ihalf;
	ihalf = (imin+imax)/2;
    }
    return imax;
}

//TRandom3 PUtils::REngine;

Bool_t PUtils::Tokenize(const char *options, const char *delimiter, char **array, int *size) {
    //Tokenize the string "options" using
    //the "delimiter" 
    //(like "+" or ",")
    //The char array is constructed but never deleted
    //in addition, any spaces before and after the delimiter are cleaned
    //-> for setup phase, but not for event loops
    //The user has to provide the pointer to the char array pointers
    //with "size", these pointers are updated
    //In addition, the size is also updated
    //
    //The ROOT version is buggy:
    //TString spattern("a - b -> c");
    //TObjArray *carray = spattern.Tokenize(TString("->"));     
    //carray->GetEntriesFast()
    //(const Int_t)3
    

    //cout << options << " -> " << delimiter << endl;
    for (int i=0; i<*size; i++) 
	array[i] = NULL;
    
    char *mystack = new char[strlen(options)+1];
    strcpy(mystack, options);

    Int_t pat = 1;
    array[0] = mystack;

    while (strstr(mystack, delimiter)) {
	if (pat == *size) {
	    cout << "Warning (PUtils::Tokenize): Size " << *size<< " is too small for " << 
		options << ", delim:" << delimiter << endl;
	}
	char *pos = strstr(mystack, delimiter);
	*pos = '\0';
	mystack = pos + strlen(delimiter);
	array[pat] = mystack;
	pat++;
    }

    *size = pat;

    for (int i=0; i<*size; i++) {
	//remove leading/trailing spaces
	remove_spaces(&array[i]);
    }

    return kTRUE;
}

void PUtils::remove_spaces(char **partc) {
    
    while (**partc == ' ') 
	(*partc)++;
    
    if (strlen(*partc)) {
	int partend = strlen(*partc)-1;
//	    cout << partc << ":" << partc[partend] << endl;
	while ((*partc)[partend]==' ' && partend>=0) {
	    (*partc)[partend] = '\0';
	    partend--;
	}
    }
}

Int_t PUtils::remove_brackets(char **partc, char a, char b) {
    //remove matching brackets like a=(, b=)
    //cout << "in: " << *partc << endl;
    
    remove_spaces(partc);

    if ((*partc)[0] != a) return 0;

    Int_t loop   = 1;
    Int_t found  = 0;
    Int_t max_br = 0;

    while (loop) {
	loop = 0;

	if (((*partc)[0] == a) && ((*partc)[(strlen(*partc)-1)] == b)) {
	    //brackets at begin and end

	    //do they match?
	    Int_t match    = 1;
	    Int_t brackets = 0;
	    for (UInt_t i=0; i<strlen(*partc); i++) {

		if ((*partc)[i] == a) { 
		    max_br++;
		    brackets++;
		}
		if (((*partc)[i] == b) && max_br) {
		    brackets--;
		    if (!brackets && i != (strlen(*partc)-1)) {
			//matching bracket is not last character
			match = 0;
		    }
		}
	    }
	    if (match) {
		found++;
		(*partc)[(strlen(*partc)-1)] = '\0';
		(*partc)++;
		
		remove_spaces(partc);
		loop=1;
	    }
	}
    }

    //cout << "out: " << *partc << endl;

    return found;
}

Bool_t PUtils::ValidVariableName(const char *name, unsigned int len) {
    //We check if "name" is a variable name
    //or a possible command
    //Allowed names for variables is alphanumeric + "_"
    //First char must be alpha or "#"

    if (!len) len = strlen(name);

    Bool_t isvar = kTRUE;
    if (!(name[0]=='#') and !(name[0]=='_') and !isalpha(name[0])) isvar = kFALSE;

    for (unsigned int i=1; i<len; i++)
	if (!(name[i]=='_') and !isalnum(name[i])) isvar = kFALSE;

    return isvar;
}

Bool_t PUtils::IsInt(const char *name) {
    //We check if "name" is an integer variable name

    Bool_t isvar = kTRUE;

    for (unsigned int i=1; i<strlen(name); i++)
	if (!isdigit(name[i])) isvar = kFALSE;
    
    return isvar;
}

PUtilsREngine &fPUtilsREngine() {
    static PUtilsREngine *ans = new PUtilsREngine();
    return *ans;
}

PUtilsREngine *makePUtilsREngine() {
    return &fPUtilsREngine();
}


PUtilsREngine::PUtilsREngine () {  
    rnd = new TRandom3();     
    SetSeed(SEED);  
} 

void PUtilsREngine::SetSeed(UInt_t s) { 
    rnd->SetSeed(s); 
    UInt_t seed = (UInt_t)rnd->Rndm()*kMaxUInt; // get a different seed for gRandom
    gRandom->SetSeed(seed);//TODOv6 

    if (s)
	Warning("PUtilsREngine", "Seed set FIXED to %i", s);
    else
	Info("PUtilsREngine", "Random seed set to %i", rnd->GetSeed());
}

ClassImp(PUtils)
ClassImp(PUtilsREngine)
 PUtils.cc:1
 PUtils.cc:2
 PUtils.cc:3
 PUtils.cc:4
 PUtils.cc:5
 PUtils.cc:6
 PUtils.cc:7
 PUtils.cc:8
 PUtils.cc:9
 PUtils.cc:10
 PUtils.cc:11
 PUtils.cc:12
 PUtils.cc:13
 PUtils.cc:14
 PUtils.cc:15
 PUtils.cc:16
 PUtils.cc:17
 PUtils.cc:18
 PUtils.cc:19
 PUtils.cc:20
 PUtils.cc:21
 PUtils.cc:22
 PUtils.cc:23
 PUtils.cc:24
 PUtils.cc:25
 PUtils.cc:26
 PUtils.cc:27
 PUtils.cc:28
 PUtils.cc:29
 PUtils.cc:30
 PUtils.cc:31
 PUtils.cc:32
 PUtils.cc:33
 PUtils.cc:34
 PUtils.cc:35
 PUtils.cc:36
 PUtils.cc:37
 PUtils.cc:38
 PUtils.cc:39
 PUtils.cc:40
 PUtils.cc:41
 PUtils.cc:42
 PUtils.cc:43
 PUtils.cc:44
 PUtils.cc:45
 PUtils.cc:46
 PUtils.cc:47
 PUtils.cc:48
 PUtils.cc:49
 PUtils.cc:50
 PUtils.cc:51
 PUtils.cc:52
 PUtils.cc:53
 PUtils.cc:54
 PUtils.cc:55
 PUtils.cc:56
 PUtils.cc:57
 PUtils.cc:58
 PUtils.cc:59
 PUtils.cc:60
 PUtils.cc:61
 PUtils.cc:62
 PUtils.cc:63
 PUtils.cc:64
 PUtils.cc:65
 PUtils.cc:66
 PUtils.cc:67
 PUtils.cc:68
 PUtils.cc:69
 PUtils.cc:70
 PUtils.cc:71
 PUtils.cc:72
 PUtils.cc:73
 PUtils.cc:74
 PUtils.cc:75
 PUtils.cc:76
 PUtils.cc:77
 PUtils.cc:78
 PUtils.cc:79
 PUtils.cc:80
 PUtils.cc:81
 PUtils.cc:82
 PUtils.cc:83
 PUtils.cc:84
 PUtils.cc:85
 PUtils.cc:86
 PUtils.cc:87
 PUtils.cc:88
 PUtils.cc:89
 PUtils.cc:90
 PUtils.cc:91
 PUtils.cc:92
 PUtils.cc:93
 PUtils.cc:94
 PUtils.cc:95
 PUtils.cc:96
 PUtils.cc:97
 PUtils.cc:98
 PUtils.cc:99
 PUtils.cc:100
 PUtils.cc:101
 PUtils.cc:102
 PUtils.cc:103
 PUtils.cc:104
 PUtils.cc:105
 PUtils.cc:106
 PUtils.cc:107
 PUtils.cc:108
 PUtils.cc:109
 PUtils.cc:110
 PUtils.cc:111
 PUtils.cc:112
 PUtils.cc:113
 PUtils.cc:114
 PUtils.cc:115
 PUtils.cc:116
 PUtils.cc:117
 PUtils.cc:118
 PUtils.cc:119
 PUtils.cc:120
 PUtils.cc:121
 PUtils.cc:122
 PUtils.cc:123
 PUtils.cc:124
 PUtils.cc:125
 PUtils.cc:126
 PUtils.cc:127
 PUtils.cc:128
 PUtils.cc:129
 PUtils.cc:130
 PUtils.cc:131
 PUtils.cc:132
 PUtils.cc:133
 PUtils.cc:134
 PUtils.cc:135
 PUtils.cc:136
 PUtils.cc:137
 PUtils.cc:138
 PUtils.cc:139
 PUtils.cc:140
 PUtils.cc:141
 PUtils.cc:142
 PUtils.cc:143
 PUtils.cc:144
 PUtils.cc:145
 PUtils.cc:146
 PUtils.cc:147
 PUtils.cc:148
 PUtils.cc:149
 PUtils.cc:150
 PUtils.cc:151
 PUtils.cc:152
 PUtils.cc:153
 PUtils.cc:154
 PUtils.cc:155
 PUtils.cc:156
 PUtils.cc:157
 PUtils.cc:158
 PUtils.cc:159
 PUtils.cc:160
 PUtils.cc:161
 PUtils.cc:162
 PUtils.cc:163
 PUtils.cc:164
 PUtils.cc:165
 PUtils.cc:166
 PUtils.cc:167
 PUtils.cc:168
 PUtils.cc:169
 PUtils.cc:170
 PUtils.cc:171
 PUtils.cc:172
 PUtils.cc:173
 PUtils.cc:174
 PUtils.cc:175
 PUtils.cc:176
 PUtils.cc:177
 PUtils.cc:178
 PUtils.cc:179
 PUtils.cc:180
 PUtils.cc:181
 PUtils.cc:182
 PUtils.cc:183
 PUtils.cc:184
 PUtils.cc:185
 PUtils.cc:186
 PUtils.cc:187
 PUtils.cc:188
 PUtils.cc:189
 PUtils.cc:190
 PUtils.cc:191
 PUtils.cc:192
 PUtils.cc:193
 PUtils.cc:194
 PUtils.cc:195
 PUtils.cc:196
 PUtils.cc:197
 PUtils.cc:198
 PUtils.cc:199
 PUtils.cc:200
 PUtils.cc:201
 PUtils.cc:202
 PUtils.cc:203
 PUtils.cc:204
 PUtils.cc:205
 PUtils.cc:206
 PUtils.cc:207
 PUtils.cc:208
 PUtils.cc:209
 PUtils.cc:210
 PUtils.cc:211
 PUtils.cc:212
 PUtils.cc:213
 PUtils.cc:214
 PUtils.cc:215
 PUtils.cc:216
 PUtils.cc:217
 PUtils.cc:218
 PUtils.cc:219
 PUtils.cc:220
 PUtils.cc:221
 PUtils.cc:222
 PUtils.cc:223
 PUtils.cc:224
 PUtils.cc:225
 PUtils.cc:226
 PUtils.cc:227
 PUtils.cc:228
 PUtils.cc:229
 PUtils.cc:230
 PUtils.cc:231
 PUtils.cc:232
 PUtils.cc:233
 PUtils.cc:234
 PUtils.cc:235
 PUtils.cc:236
 PUtils.cc:237
 PUtils.cc:238
 PUtils.cc:239
 PUtils.cc:240
 PUtils.cc:241
 PUtils.cc:242
 PUtils.cc:243
 PUtils.cc:244
 PUtils.cc:245
 PUtils.cc:246
 PUtils.cc:247
 PUtils.cc:248
 PUtils.cc:249
 PUtils.cc:250
 PUtils.cc:251
 PUtils.cc:252
 PUtils.cc:253
 PUtils.cc:254
 PUtils.cc:255
 PUtils.cc:256
 PUtils.cc:257
 PUtils.cc:258
 PUtils.cc:259
 PUtils.cc:260
 PUtils.cc:261
 PUtils.cc:262
 PUtils.cc:263
 PUtils.cc:264
 PUtils.cc:265
 PUtils.cc:266
 PUtils.cc:267
 PUtils.cc:268
 PUtils.cc:269
 PUtils.cc:270
 PUtils.cc:271
 PUtils.cc:272
 PUtils.cc:273
 PUtils.cc:274
 PUtils.cc:275
 PUtils.cc:276
 PUtils.cc:277
 PUtils.cc:278
 PUtils.cc:279
 PUtils.cc:280
 PUtils.cc:281
 PUtils.cc:282
 PUtils.cc:283
 PUtils.cc:284
 PUtils.cc:285
 PUtils.cc:286
 PUtils.cc:287
 PUtils.cc:288
 PUtils.cc:289
 PUtils.cc:290
 PUtils.cc:291
 PUtils.cc:292
 PUtils.cc:293
 PUtils.cc:294
 PUtils.cc:295
 PUtils.cc:296
 PUtils.cc:297
 PUtils.cc:298
 PUtils.cc:299
 PUtils.cc:300
 PUtils.cc:301
 PUtils.cc:302
 PUtils.cc:303
 PUtils.cc:304
 PUtils.cc:305
 PUtils.cc:306
 PUtils.cc:307
 PUtils.cc:308
 PUtils.cc:309
 PUtils.cc:310
 PUtils.cc:311
 PUtils.cc:312
 PUtils.cc:313
 PUtils.cc:314
 PUtils.cc:315
 PUtils.cc:316
 PUtils.cc:317
 PUtils.cc:318
 PUtils.cc:319
 PUtils.cc:320
 PUtils.cc:321
 PUtils.cc:322
 PUtils.cc:323
 PUtils.cc:324
 PUtils.cc:325
 PUtils.cc:326
 PUtils.cc:327
 PUtils.cc:328
 PUtils.cc:329
 PUtils.cc:330
 PUtils.cc:331
 PUtils.cc:332
 PUtils.cc:333
 PUtils.cc:334
 PUtils.cc:335
 PUtils.cc:336
 PUtils.cc:337
 PUtils.cc:338
 PUtils.cc:339
 PUtils.cc:340
 PUtils.cc:341
 PUtils.cc:342
 PUtils.cc:343
 PUtils.cc:344
 PUtils.cc:345
 PUtils.cc:346
 PUtils.cc:347
 PUtils.cc:348
 PUtils.cc:349
 PUtils.cc:350
 PUtils.cc:351
 PUtils.cc:352
 PUtils.cc:353
 PUtils.cc:354
 PUtils.cc:355
 PUtils.cc:356
 PUtils.cc:357
 PUtils.cc:358
 PUtils.cc:359
 PUtils.cc:360
 PUtils.cc:361
 PUtils.cc:362
 PUtils.cc:363
 PUtils.cc:364
 PUtils.cc:365
 PUtils.cc:366
 PUtils.cc:367
 PUtils.cc:368
 PUtils.cc:369
 PUtils.cc:370
 PUtils.cc:371
 PUtils.cc:372
 PUtils.cc:373
 PUtils.cc:374
 PUtils.cc:375
 PUtils.cc:376
 PUtils.cc:377
 PUtils.cc:378
 PUtils.cc:379
 PUtils.cc:380
 PUtils.cc:381
 PUtils.cc:382
 PUtils.cc:383
 PUtils.cc:384
 PUtils.cc:385
 PUtils.cc:386
 PUtils.cc:387
 PUtils.cc:388
 PUtils.cc:389
 PUtils.cc:390
 PUtils.cc:391
 PUtils.cc:392
 PUtils.cc:393
 PUtils.cc:394
 PUtils.cc:395
 PUtils.cc:396
 PUtils.cc:397
 PUtils.cc:398
 PUtils.cc:399
 PUtils.cc:400
 PUtils.cc:401
 PUtils.cc:402
 PUtils.cc:403
 PUtils.cc:404
 PUtils.cc:405
 PUtils.cc:406
 PUtils.cc:407
 PUtils.cc:408
 PUtils.cc:409
 PUtils.cc:410
 PUtils.cc:411
 PUtils.cc:412
 PUtils.cc:413
 PUtils.cc:414
 PUtils.cc:415
 PUtils.cc:416
 PUtils.cc:417