code: func calcDifficultyFrontier(time uint64, parent *types.Header) *big.Int {
  	diff := new(big.Int)
  	adjust := new(big.Int).Div(parent.Difficulty, params.DifficultyBoundDivisor)
  	bigTime := new(big.Int)
  	bigParentTime := new(big.Int)
  
  	bigTime.SetUint64(time)
  	bigParentTime.SetUint64(parent.Time)
  
  	if bigTime.Sub(bigTime, bigParentTime).Cmp(params.DurationLimit) < 0 {
  		diff.Add(parent.Difficulty, adjust)
  	} else {
  		diff.Sub(parent.Difficulty, adjust)
  	}
  	if diff.Cmp(params.MinimumDifficulty) < 0 {
  		diff.Set(params.MinimumDifficulty)
  	}
  
  	periodCount := new(big.Int).Add(parent.Number, big1)
  	periodCount.Div(periodCount, expDiffPeriod)
  	if periodCount.Cmp(big1) > 0 {
  		// diff = diff + 2^(periodCount - 2)
  		expDiff := periodCount.Sub(periodCount, big2)
  		expDiff.Exp(big2, expDiff, nil)
  		diff.Add(diff, expDiff)
  		diff = math.BigMax(diff, params.MinimumDifficulty)
  	}
  	return diff
  }
docs: // calcDifficultyFrontier is the difficulty adjustment algorithm. It returns the
  // difficulty that a new block should have when created at time given the parent
  // block's time and difficulty. The calculation uses the Frontier rules.