#include <bits/stdc++.h>
using namespace std;
struct point {
  double x, y;
  point() { x = 0.0, y = 0.0; }
  point(double _x, double _y) { x = _x, y = _y; }
  bool operator<(point other) const {
    if (fabs(x - other.x) > 1e-9) return x < other.x;
    return y < other.y;
  }
};
struct line {
  double a, b, c;
  line(point p1, point p2) {
    if (fabs(p1.x - p2.x) < 1e-9) {
      a = 1.0;
      b = 0.0;
      c = -p1.x;
    } else {
      a = -(double)(p1.y - p2.y) / (p1.x - p2.x);
      b = 1.0;
      c = -(double)(a * p1.x) - p1.y;
    }
  }
};
bool areParallel(line l1, line l2) {
  return (fabs(l1.a - l2.a) < 1e-9) && (fabs(l1.b - l2.b) < 1e-9);
}
bool areSame(line l1, line l2) {
  return (areParallel(l1, l2)) && (fabs(l1.c - l2.c) < 1e-9);
}
bool areIntersect(line l1, line l2, point &p) {
  if (areParallel(l1, l2)) return false;
  p.x = (l1.c * l2.b - l1.b * l2.c) / (l2.a * l1.b - l2.b * l1.a);
  if (fabs(l1.b) > 1e-9)
    p.y = -(l1.a * p.x + l1.c);
  else
    p.y = -(l2.a * p.x + l2.c);
  return true;
}
double dist(point a, point b) {
  return sqrt((a.x - b.x) * (a.x - b.x) + ((a.y - b.y) * (a.y - b.y)));
}
vector<string> split(const string &s, char delimiter) {
  vector<string> tokens;
  string token;
  istringstream tokenStream(s);
  while (getline(tokenStream, token, delimiter)) {
    tokens.push_back(token);
  }
  return tokens;
}
struct vec {
  double x, y;
  double mag = sqrt(x * x + y * y);
  double ang = (x == 0.0 ? 3.14159265358979323846 / 2.0 : atan(y / x));
  vec() { x = 0.0, y = 0.0; }
  vec(double _x, double _y) : x(_x), y(_y) {}
};
vec toVec(point a, point b) { return vec(b.x - a.x, b.y - a.y); }
vec scale(vec v, double s) { return vec(v.x * s, v.y * s); }
point translate(point p, vec v) { return point(p.x + v.x, p.y + v.y); }
double dot(vec a, vec b) { return (a.x * b.x + a.y * b.y); }
double cross(vec a, vec b) { return a.x * b.y - a.y * b.x; }
double norm_sq(vec v) { return v.x * v.x + v.y * v.y; }
bool areCollinear(point a, point b, point c) {
  if (cross(toVec(b, a), toVec(c, a)) == 0.0) return true;
  return false;
}
double distToLineSegment(point p, point a, point b, point &c) {
  vec ap = toVec(a, p), ab = toVec(a, b);
  double u = dot(ap, ab) / norm_sq(ab);
  if (u < 0.0) {
    c = point(a.x, a.y);
    return dist(a, p);
  }
  if (u > 1.0) {
    c = point(b.x, b.y);
    return dist(b, p);
  }
  c = translate(a, scale(ab, u));
  return dist(c, p);
}
bool onSegment(point p, point q, point r) {
  if (q.x <= max(p.x, r.x) && q.x >= min(p.x, r.x) && q.y <= max(p.y, r.y) &&
      q.y >= min(p.y, r.y))
    return true;
  return false;
}
int orientation(point p, point q, point r) {
  int val = (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
  if (val == 0) return 0;
  return (val > 0) ? 1 : 2;
}
bool doIntersect(point p1, point q1, point p2, point q2) {
  int o1 = orientation(p1, q1, p2);
  int o2 = orientation(p1, q1, q2);
  int o3 = orientation(p2, q2, p1);
  int o4 = orientation(p2, q2, q1);
  if (o1 != o2 && o3 != o4) return true;
  if (o1 == 0 && onSegment(p1, p2, q1)) return true;
  if (o2 == 0 && onSegment(p1, q2, q1)) return true;
  if (o3 == 0 && onSegment(p2, p1, q2)) return true;
  if (o4 == 0 && onSegment(p2, q1, q2)) return true;
  return false;
}
int main() {
  point c1, c2;
  int ri1, ro1;
  cin >> c1.x >> c1.y >> ri1 >> ro1;
  int ri2, ro2;
  cin >> c2.x >> c2.y >> ri2 >> ro2;
  double d = dist(c1, c2);
  int tot = 0;
  if (d + ro1 <= ri2 or d >= ro1 + ro2 or d + ro2 <= ro1) tot++;
  if (d + ro2 <= ri1 or d >= ro2 + ro1 or d + ro1 <= ro2) tot++;
  if (d + ri1 <= ri2 or d >= ri1 + ro2 or d + ro2 <= ri1) tot++;
  if (d + ri2 <= ri1 or d >= ri2 + ro1 or d + ro1 <= ri2) tot++;
  cout << tot;
}
