nsresult nsSkeletonState::GetDuration(const nsTArray<PRUint32>& aTracks, PRInt64& aDuration) { if (!mActive || mVersion < SKELETON_VERSION(4,0) || !HasIndex() || aTracks.Length() == 0) { return NS_ERROR_FAILURE; } PRInt64 endTime = PR_INT64_MIN; PRInt64 startTime = PR_INT64_MAX; for (PRUint32 i=0; i<aTracks.Length(); i++) { nsKeyFrameIndex* index = nsnull; mIndex.Get(aTracks[i], &index); if (!index) { // Can't get the timestamps for one of the required tracks, fail. return NS_ERROR_FAILURE; } if (index->mEndTime > endTime) { endTime = index->mEndTime; } if (index->mStartTime < startTime) { startTime = index->mStartTime; } } NS_ASSERTION(endTime > startTime, "Duration must be positive"); return AddOverflow(endTime, -startTime, aDuration) ? NS_OK : NS_ERROR_FAILURE; }
PRInt64 nsTheoraState::Time(PRInt64 granulepos) { if (granulepos < 0 || !mActive || mInfo.fps_numerator == 0) { return -1; } PRInt64 t = 0; PRInt64 frameno = th_granule_frame(mCtx, granulepos); if (!AddOverflow(frameno, 1, t)) return -1; if (!MulOverflow(t, 1000, t)) return -1; if (!MulOverflow(t, mInfo.fps_denominator, t)) return -1; return t / mInfo.fps_numerator; }
PRInt64 nsTheoraState::Time(th_info* aInfo, PRInt64 aGranulepos) { if (aGranulepos < 0 || aInfo->fps_numerator == 0) { return -1; } PRInt64 t = 0; // Implementation of th_granule_frame inlined here to operate // on the th_info structure instead of the theora_state. int shift = aInfo->keyframe_granule_shift; ogg_int64_t iframe = aGranulepos >> shift; ogg_int64_t pframe = aGranulepos - (iframe << shift); PRInt64 frameno = iframe + pframe - TH_VERSION_CHECK(aInfo, 3, 2, 1); if (!AddOverflow(frameno, 1, t)) return -1; if (!MulOverflow(t, 1000, t)) return -1; if (!MulOverflow(t, aInfo->fps_denominator, t)) return -1; return t / aInfo->fps_numerator; }
void ARMul_AddOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result) { ASSIGNV (AddOverflow (a, b, result)); }
PRBool nsSkeletonState::DecodeIndex(ogg_packet* aPacket) { NS_ASSERTION(aPacket->bytes >= SKELETON_4_0_MIN_INDEX_LEN, "Index must be at least minimum size"); if (!mActive) { return PR_FALSE; } PRUint32 serialno = LEUint32(aPacket->packet + INDEX_SERIALNO_OFFSET); PRInt64 numKeyPoints = LEInt64(aPacket->packet + INDEX_NUM_KEYPOINTS_OFFSET); PRInt64 n = 0; PRInt64 endTime = 0, startTime = 0; const unsigned char* p = aPacket->packet; PRInt64 timeDenom = LEInt64(aPacket->packet + INDEX_TIME_DENOM_OFFSET); if (timeDenom == 0) { LOG(PR_LOG_DEBUG, ("Ogg Skeleton Index packet for stream %u has 0 " "timestamp denominator.", serialno)); return (mActive = PR_FALSE); } // Extract the start time. n = LEInt64(p + INDEX_FIRST_NUMER_OFFSET); PRInt64 t; if (!MulOverflow(n, 1000, t)) { return (mActive = PR_FALSE); } else { startTime = t / timeDenom; } // Extract the end time. n = LEInt64(p + INDEX_LAST_NUMER_OFFSET); if (!MulOverflow(n, 1000, t)) { return (mActive = PR_FALSE); } else { endTime = t / timeDenom; } // Check the numKeyPoints value read, ensure we're not going to run out of // memory while trying to decode the index packet. PRInt64 minPacketSize; if (!MulOverflow(numKeyPoints, MIN_KEY_POINT_SIZE, minPacketSize) || !AddOverflow(INDEX_KEYPOINT_OFFSET, minPacketSize, minPacketSize)) { return (mActive = PR_FALSE); } PRInt64 sizeofIndex = aPacket->bytes - INDEX_KEYPOINT_OFFSET; PRInt64 maxNumKeyPoints = sizeofIndex / MIN_KEY_POINT_SIZE; if (aPacket->bytes < minPacketSize || numKeyPoints > maxNumKeyPoints || numKeyPoints < 0) { // Packet size is less than the theoretical minimum size, or the packet is // claiming to store more keypoints than it's capable of storing. This means // that the numKeyPoints field is too large or small for the packet to // possibly contain as many packets as it claims to, so the numKeyPoints // field is possibly malicious. Don't try decoding this index, we may run // out of memory. LOG(PR_LOG_DEBUG, ("Possibly malicious number of key points reported " "(%lld) in index packet for stream %u.", numKeyPoints, serialno)); return (mActive = PR_FALSE); } nsAutoPtr<nsKeyFrameIndex> keyPoints(new nsKeyFrameIndex(startTime, endTime)); p = aPacket->packet + INDEX_KEYPOINT_OFFSET; const unsigned char* limit = aPacket->packet + aPacket->bytes; PRInt64 numKeyPointsRead = 0; PRInt64 offset = 0; PRInt64 time = 0; while (p < limit && numKeyPointsRead < numKeyPoints) { PRInt64 delta = 0; p = ReadVariableLengthInt(p, limit, delta); if (p == limit || !AddOverflow(offset, delta, offset) || offset > mLength || offset < 0) { return (mActive = PR_FALSE); } p = ReadVariableLengthInt(p, limit, delta); if (!AddOverflow(time, delta, time) || time > endTime || time < startTime) { return (mActive = PR_FALSE); } PRInt64 timeMs = 0; if (!MulOverflow(time, 1000, timeMs)) return mActive = PR_FALSE; timeMs /= timeDenom; keyPoints->Add(offset, timeMs); numKeyPointsRead++; } PRInt32 keyPointsRead = keyPoints->Length(); if (keyPointsRead > 0) { mIndex.Put(serialno, keyPoints.forget()); } LOG(PR_LOG_DEBUG, ("Loaded %d keypoints for Skeleton on stream %u", keyPointsRead, serialno)); return PR_TRUE; }
// 64 bit integer multiplication with overflow checking. Returns PR_TRUE // if the multiplication was successful, or PR_FALSE if the operation resulted // in an integer overflow. PRBool MulOverflow(PRInt64 a, PRInt64 b, PRInt64& aResult) { // We break a multiplication a * b into of sign_a * sign_b * abs(a) * abs(b) // // This is equivalent to: // // (sign_a * sign_b) * ((a_hi * 2^32) + a_lo) * ((b_hi * 2^32) + b_lo) // // Which is equivalent to: // // (sign_a * sign_b) * // ((a_hi * b_hi << 64) + // (a_hi * b_lo << 32) + (a_lo * b_hi << 32) + // a_lo * b_lo) // // So to check if a*b overflows, we must check each sub part of the above // sum. // // Note: -1 * PR_INT64_MIN == PR_INT64_MIN ; we can't negate PR_INT64_MIN! // Note: Shift of negative numbers is undefined. // // Figure out the sign after multiplication. Then we can just work with // unsigned numbers. PRInt64 sign = (!(a < 0) == !(b < 0)) ? 1 : -1; PRInt64 abs_a = (a < 0) ? -a : a; PRInt64 abs_b = (b < 0) ? -b : b; if (abs_a < 0) { NS_ASSERTION(a == PR_INT64_MIN, "How else can this happen?"); if (b == 0 || b == 1) { aResult = a * b; return PR_TRUE; } else { return PR_FALSE; } } if (abs_b < 0) { NS_ASSERTION(b == PR_INT64_MIN, "How else can this happen?"); if (a == 0 || a == 1) { aResult = a * b; return PR_TRUE; } else { return PR_FALSE; } } NS_ASSERTION(abs_a >= 0 && abs_b >= 0, "abs values must be non-negative"); PRInt64 a_hi = abs_a >> 32; PRInt64 a_lo = abs_a & 0xFFFFFFFF; PRInt64 b_hi = abs_b >> 32; PRInt64 b_lo = abs_b & 0xFFFFFFFF; NS_ASSERTION((a_hi<<32) + a_lo == abs_a, "Partition must be correct"); NS_ASSERTION((b_hi<<32) + b_lo == abs_b, "Partition must be correct"); // In the sub-equation (a_hi * b_hi << 64), if a_hi or b_hi // are non-zero, this will overflow as it's shifted by 64. // Abort if this overflows. if (a_hi != 0 && b_hi != 0) { return PR_FALSE; } // We can now assume that either a_hi or b_hi is 0. NS_ASSERTION(a_hi == 0 || b_hi == 0, "One of these must be 0"); // Next we calculate: // (a_hi * b_lo << 32) + (a_lo * b_hi << 32) // We can factor this as: // (a_hi * b_lo + a_lo * b_hi) << 32 PRInt64 q = a_hi * b_lo + a_lo * b_hi; if (q > PR_INT32_MAX) { // q will overflow when we shift by 32; abort. return PR_FALSE; } q <<= 32; // Both a_lo and b_lo are less than INT32_MAX, so can't overflow. PRUint64 lo = a_lo * b_lo; if (lo > PR_INT64_MAX) { return PR_FALSE; } // Add the final result. We must check for overflow during addition. if (!AddOverflow(q, static_cast<PRInt64>(lo), aResult)) { return PR_FALSE; } aResult *= sign; NS_ASSERTION(a * b == aResult, "We didn't overflow, but result is wrong!"); return PR_TRUE; }
//////////////////////////////////////////////////////////// // // Plot a page with several histograms // void PlotNHistograms(const TString& pdfFile, TDirectory* rdir, TDirectory* sdir, const TString& rcollname, const TString& scollname, const char* canvasName, const char* canvasTitle, const TString& refLabel, const TString& newLabel, unsigned int nhistos, const TString* hnames, const TString* htitles, const char** drawopt, bool* logy = 0, bool* logx = 0, bool* doKolmo = 0, Double_t* norm = 0, Double_t* minx = 0, Double_t* maxx = 0, Double_t* miny = 0, Double_t* maxy = 0) { if (DEBUGP) { cout << " + Plotting histograms for " << canvasTitle << endl; cerr << " + Plotting histograms for " << canvasTitle << endl; } TH1* rh_raw = 0; TH1* rh = 0; TH1* sh_raw = 0; TH1* sh = 0; TCanvas* canvas = 0; if (nhistos >4) canvas = new TCanvas(canvasName, canvasTitle, 1000, 1400); else canvas = new TCanvas(canvasName, canvasTitle, 1000, 1050); canvas->Draw(); canvas->Divide(2,(nhistos+1)/2); //This way we print in 2 columns for (unsigned int i = 0; i < nhistos; i++) { if (DEBUGP) cout << " [" << i << "] histogram name: " << flush << hnames[i] << endl; //draw option for the new histogram TString drawoption = drawopt[i]; // Skip histogram if no name is provided if (hnames[i] == "") continue; // Get Histograms // + Reference release rdir->cd(rcollname); if (DEBUGP) cout << " Getting object for reference sample " << (rcollname + "/" + hnames[i]) << endl; rdir->GetObject(rcollname + "/" + hnames[i], rh_raw); if (! rh_raw) { cout << "WARNING: Could not find a reference histogram or profile named " << hnames[i] << " in " << rdir->GetName() << endl; cout << " Skipping" << endl; continue; } //If it is a 2D project it in Y... is this what we always want? if (TString(rh_raw->IsA()->GetName()) == "TH2F") { if (DEBUGP) cout << " It is a TH2F object... project in Y!" << endl; TH1* proj = ((TH2F*) rh_raw)->ProjectionY(); rh_raw = proj; } // + New release sdir->cd(scollname); if (DEBUGP) cout << " Getting object for target sample " << (scollname + "/" + hnames[i]) << endl; sdir->GetObject(scollname + "/" + hnames[i], sh_raw); if (! sh_raw) { cout << "WARNING: Could not find a signal histogram or profile named " << hnames[i] << " in " << sdir->GetName() << endl; cout << " Skipping" << endl; continue; } //If it is a 2D project it in Y... is this what we always want? if (TString(sh_raw->IsA()->GetName()) == "TH2F") { if (DEBUGP) cout << hnames[i] << " is a TH2F object... project in Y!" << endl; TH1* proj = ((TH2F*) sh_raw)->ProjectionY(); sh_raw = proj; } rh = AddOverflow(rh_raw); sh = AddOverflow(sh_raw); // Set styles if (DEBUGP) cout << " Setting style..." << endl; SetHistogramStyle(rh, 21, 4); SetHistogramStyle(sh, 20, 2); //Change titles if (htitles) { rh->SetTitle(htitles[i]); sh->SetTitle(htitles[i]); rh->GetYaxis()->SetTitle(htitles[i]); sh->GetYaxis()->SetTitle(htitles[i]); } // SET X AXIS RANGE in plots Bool_t ChangeXRange = false ; Double_t Xleft = rh->GetXaxis()->GetXmin(); Double_t Xright = rh->GetXaxis()->GetXmax(); if (DEBUGP) cout << "ref histo Xleft, Xright = "<< Xleft << ", "<< Xright << endl; if (sh->GetXaxis()->GetXmin() < rh->GetXaxis()->GetXmin()) { Xleft = sh->GetXaxis()->GetXmin(); ChangeXRange = true; if (DEBUGP) cout << "automatic reset MIN (new < ref) Xleft = "<< Xleft << endl; } if (sh->GetXaxis()->GetXmax() > rh->GetXaxis()->GetXmax()) { Xright = sh->GetXaxis()->GetXmax(); ChangeXRange = true; if (DEBUGP) cout << "automatic reset MAX (new > ref) Xright = "<< Xright << endl; } if (minx[i]!=0) { ChangeXRange = true ; Xleft = minx[i]; if (DEBUGP) cout << "user reset Xleft = "<< Xleft << endl; } if (maxx[i]!=0) { ChangeXRange = true ; Xright = maxx[i]; if (DEBUGP) cout << "user reset Xright = "<< Xleft << endl; } if (ChangeXRange) { if (DEBUGP) { cout << "Ref histo Xmin, Xmax = "<< rh->GetXaxis()->GetXmin() << ", " << rh->GetXaxis()->GetXmax() <<endl; cout << "New histo Xmin, Xmax = "<< sh->GetXaxis()->GetXmin() << ", " << sh->GetXaxis()->GetXmax() <<endl; } rh->GetXaxis()->SetRangeUser(Xleft,Xright); sh->GetXaxis()->SetRangeUser(Xleft,Xright); if (DEBUGP) { cout << "reset Ref histo Xmin, Xmax = "<< rh->GetXaxis()->GetXmin() << ", " << rh->GetXaxis()->GetXmax() <<endl; cout << "reset New histo Xmin, Xmax = "<< sh->GetXaxis()->GetXmin() << ", " << sh->GetXaxis()->GetXmax() <<endl; cout << "resetting Ref and New histo Xleft, Xright = "<< Xleft << ", " << Xright <<endl; } } // =============================================================================================== // Normalize if (norm[i] < 0.) ; // Default: do not normalize at all ! else if (norm[i] == 0.) NormalizeHistogramsToFirst(rh,sh); else if (norm[i] == 1.) NormalizeHistogramsToOne(rh,sh); else if (norm[i] == 2.) NormalizeHistogramsAsDensity(rh,sh); // =============================================================================================== // =============================================================================================== // SET Y AXIS RANGE in plots // // MINIMUM // Double_t Ybottom; // if user-defined range force it ! if (miny[i]!=0) { Ybottom = miny[i]; if (DEBUGP) cout << "setting Minimum Y to user defined value: "<< miny[i] << endl; } else if (logy[i]) { // automatic setting for log scale Double_t yminr = rh->GetMinimum(0.); // min value larger than zero Double_t ymins = sh->GetMinimum(0.); Ybottom = yminr < ymins ? yminr*0.5 : ymins*0.5; if (DEBUGP) cout << "LOG scale, yminr, ymins: "<<yminr<<", "<<ymins <<" ==>> Ybottom = "<<Ybottom<< endl; } else { // automatic setting for linear scale Double_t yminr = rh->GetMinimum(); // min value larger than zero Double_t ymins = sh->GetMinimum(); Ybottom = yminr < ymins ? yminr-0.1*abs(yminr) : ymins-0.1*abs(ymins) ; // limit the scale to -1,+1 for relative pt bias to avoid failing fits if ((hnames[i] == "ptres_vs_eta_Mean") && (Ybottom <-1.)) Ybottom = -1.; if ((hnames[i] == "ptres_vs_pt_Mean") && (Ybottom <-1.)) Ybottom = -1.; if (DEBUGP) cout << "LIN scale, yminr, ymins: "<<yminr<<", "<<ymins <<" ==>> Ybottom = "<<Ybottom<< endl; } /////////////////// // MAXIMUM // Double_t Ytop; // if user-defined range force it ! if (maxy[i]!=0) { Ytop = maxy[i]; if (DEBUGP) cout << "setting Maximum Y to user defined value: "<< maxy[i] << endl; } else { Double_t ymaxr = rh->GetMaximum(); // max value Double_t ymaxs = sh->GetMaximum(); Ytop = ymaxr > ymaxs ? ymaxr : ymaxs ; // automatic setting for log scale if (logy[i]) { Ytop = Ytop*2; if (DEBUGP) cout << "LOG scale, ymaxr, ymaxs: "<<ymaxr<<", "<<ymaxs <<" ==>> Ytop = "<<Ytop<< endl; } else { Ytop = Ytop+0.1*abs(Ytop); // limit the scale to -1,+1 for relative pt bias to avoid failing fits if ((hnames[i] == "ptres_vs_eta_Mean") && (Ytop >1.)) Ytop = 1.; if ((hnames[i] == "ptres_vs_pt_Mean") && (Ytop >1.)) Ytop = 1.; if (DEBUGP) cout << "LIN scale, ymaxr, ymaxs: "<<ymaxr<<", "<<ymaxs <<" ==>> Ytop = "<<Ytop<< endl; } } // +++++++++++++++++++++++++++++++++++++++++ rh->GetYaxis()->SetRangeUser(Ybottom,Ytop); sh->GetYaxis()->SetRangeUser(Ybottom,Ytop); // +++++++++++++++++++++++++++++++++++++++++ // Move to subpad canvas->cd(i+1); TPad* pad1 = NULL; TPad* pad2 = NULL; pad1 = new TPad("pad1", "pad1", 0, 0.3, 1, 1.0); pad2 = new TPad("pad2", "pad2", 0, 0.0, 1, 0.3); pad1->SetTopMargin (0.08); pad1->SetBottomMargin(0.01); pad1->Draw(); pad2->SetTopMargin (0.05); pad2->SetBottomMargin(0.45); pad2->Draw();// Set stat boxes pad1->cd(); // Check Logy if (logy[i]) gPad->SetLogy(); if (logx[i]) {gPad->SetLogx(); pad2->SetLogx();} // Set stat boxes if (DEBUGP) cout << " Setting statistics..." << endl; setStats(sh, rh, -1, 0, false); // /////////// DRAW histograms ////////////////////////////////////// // // FIRST plot: reference (blue) SECOND plot: new (red) if (DEBUGP) cout << " Drawing histograms..." << endl; if (ChangeXRange) { sh->Draw(drawoption); rh->Draw("same"+drawoption); sh->Draw("same"+drawoption); } else { rh->Draw(drawoption); sh->Draw("same"+drawoption); } // Perform Kolmogorov test if needed if (doKolmo) { if (doKolmo[i]) { if (DEBUGP) cout << " Performing Kolmogorov test..." << endl; // TPad* c1_1 = canvas->GetPad(i+1); double kstest = KolmogorovTest(sh,rh); if(kstest<0.7) gPad->SetFillColor(kBlue-10); } } pad2->cd(); TH1* ratioplot = PlotRatiosHistograms(rh, sh); SetHistogramStyle(ratioplot, 21, 4); ratioplot->Draw("ep"); } // End loop // Draw Legend if (DEBUGP) cout << " Drawing legend..." << endl; canvas->cd(); TLegend* l = 0; if (nhistos > 4) l = new TLegend(0.20,0.665,0.80,0.685); else l = new TLegend(0.20,0.50,0.80,0.53); l->SetTextSize(0.011); l->SetLineColor(1); l->SetLineWidth(1); l->SetLineStyle(1); l->SetFillColor(0); l->SetBorderSize(2); l->AddEntry(rh,refLabel,"LPF"); l->AddEntry(sh,newLabel,"LPF"); l->Draw(); // Print Canvas canvas->SaveAs(pdfFile+".pdf"); canvas->SaveAs(pdfFile+".png"); // Clean memory // delete l; delete canvas; if (DEBUGP) cout << " ... plotted histograms for " << canvasTitle << endl; }