/**
 * x % y == x xor y というのは、
 * 2進数の桁数が同じ (違うとxorがyより大きくなる)
 * かつxはyの0である桁を1に変えたもの (%もxorも、変えた桁が1、変えない桁が0になる)
 *
 * 図にすると
 *   1 2 3 4 5 6 7 8 9 x
 * 1 *
 * 2   * *
 * 3     *
 * 4       * * * *
 * 5         *   *
 * 6           * *
 * 7             *
 * 8               * *
 * 9                 *
 * y
 *
 * 2**nで一つのブロックであり、n+1のブロックはnのブロックを3個並べた形になる
 *
 * よって方針としては
 * 1. L,Rが所属するブロックを算出
 * 2-1. L,Rが同じブロックの場合、そのブロックを分割して計算
 * 2-2. 違う場合は、L,Rの間にあるブロック + Lが分割するブロック + Rが分割するブロック
 */

#include <iostream>
#include <stack>
#include <unordered_map>
#include <vector>
#include <queue>
#include <algorithm>
#include <cmath>
#include <functional>
#include <iterator>
#include <tuple>

using namespace std;

// mod計算クラス
template <class T>
struct calc_mod {
  T n;
  T mod;

  calc_mod(T n, T mod) {
    this->n = n;
    this->mod = mod;
  }

  T plus(const T& a, const T& b) const { return (a + b) % mod; }
  calc_mod<T> operator+(const calc_mod<T>& other) const { return calc_mod<T>(plus(this->n, other.n), mod); }
  calc_mod<T> operator+(const T& other) const { return calc_mod<T>(plus(this->n, other), mod); }
  void operator+=(const calc_mod<T>& other) { this->n = plus(this->n, other.n); }
  void operator+=(const T& other) { this->n = plus(this->n, other); }

  T sub(const T& a, const T& b) const { return (a - b + mod) % mod; }
  calc_mod<T> operator-(const calc_mod<T>& other) const { return calc_mod<T>(sub(this->n, other.n), mod); }
  calc_mod<T> operator-(const T& other) const { return calc_mod<T>(sub(this->n, other), mod); }
  void operator-=(const calc_mod<T>& other) { this->n = sub(this->n, other.n); }
  void operator-=(const T& other) { this->n = sub(this->n, other); }

  T multi(const T& a, const T& b) const { return (a * b) % mod; }
  calc_mod<T> operator*(const calc_mod<T>& other) const { return calc_mod<T>(multi(this->n, other.n), mod); }
  calc_mod<T> operator*(const T& other) const { return calc_mod<T>(multi(this->n, other), mod); }
  void operator*=(const calc_mod<T>& other) { this->n = multi(this->n, other.n); }
  void operator*=(const T& other) { this->n = multi(this->n, other); }

  T div(const T& a, const T& b) const { return a / b; }
  calc_mod<T> operator/(const calc_mod<T>& other) const { return calc_mod<T>(div(this->n, other.n), mod); }
  calc_mod<T> operator/(const T& other) const { return calc_mod<T>(div(this->n, other), mod); }
  void operator/=(const calc_mod<T>& other) { this->n = div(this->n, other.n); }
  void operator/=(const T& other) { this->n = div(this->n, other); }

  T modu(const T& a, const T& b) const { return a % b; }
  calc_mod<T> operator%(const calc_mod<T>& other) const { return calc_mod<T>(modu(this->n, other.n), mod); }
  calc_mod<T> operator%(const T& other) const { return calc_mod<T>(modu(this->n, other), mod); }
  void operator%=(const calc_mod<T>& other) { this->n = modu(this->n, other.n); }
  void operator%=(const T& other) { this->n = modu(this->n, other); }

  //TODO: このあたり、haskellのeqみたいに定義できないか？
  bool operator==(const calc_mod<T>& other) const { return this->n == other.n; }
  bool operator==(const T& other) const { return this->n == other; }
  bool operator!=(const calc_mod<T>& other) const { return this->n != other.n; }
  bool operator!=(const T& other) const { return this->n != other; }

  bool operator>(const calc_mod<T>& other) const { return this->n > other.n; }
  bool operator>(const T& other) const { return this->n > other; }
  bool operator>=(const calc_mod<T>& other) const { return this->n >= other.n; }
  bool operator>=(const T& other) const { return this->n >= other; }
  bool operator<(const calc_mod<T>& other) const { return this->n < other.n; }
  bool operator<(const T& other) const { return this->n < other; }
  bool operator<=(const calc_mod<T>& other) const { return this->n <= other.n; }
  bool operator<=(const T& other) const { return this->n <= other; }

  calc_mod<T> pow(calc_mod<T> other) {
    return this->pow(other.n);
  }
  calc_mod<T> pow(T other) {
    // 累乗は繰り返し自乗法で
    calc_mod<T> result(1, this->mod);
    calc_mod<T> x = *this;
    T b = other;

    for (;b > 0;b /= 2) {
      if (b%2 == 1) {
        result *= x;
      }

      x *= x;
    }

    return result;
  }
};
template <class T>
string to_string(calc_mod<T> data) { //標準の数値型のように、to_stringで呼べるように
  return to_string(data.n);
}
template <class T>
ostream& operator<<(ostream& stream, calc_mod<T> data) { // cout<<でも呼べるように
  stream << to_string(data);
  return stream;
}

using point_value = long long int;
using modtype = calc_mod<long long int>;
const long long int MOD = 1000000007;

modtype count_in_block(int i) {
  return modtype(3, MOD).pow(i - 1);
}

int block_number(point_value b) {
  // log2がdoubleなので返し切れない？ data4 参照
  // return ceil(log2(b+1));
  int count = 0;
  while (b > 1) {
    count++;
    b /= 2;
  }

  return count+1;
}

point_value block_min_bound(int i) {
  return pow(2, i - 1);
}

//TODO: 複数に対応したい
#define dv(var) " "#var":" << var

//TODO: tuple使ってhashとか省略しようと思ったができない・・ boostではtupleも対応されている模様
using normalize_value = tuple<point_value, point_value, point_value>;
namespace std{
    template<>
    class hash<normalize_value>{
        public:
        size_t operator () ( const normalize_value &p ) const{
          return get<0>(p) ^ get<1>(p) ^ get<2>(p);
        }
    };
}
ostream& operator<<(ostream& stream, const normalize_value& p) { // cout<<でも呼べるように
  stream << "(" << get<0>(p) << "," << get<1>(p) << "," << get<2>(p) << ")";
  return stream;
}

normalize_value normalize(point_value l, point_value r, point_value min_x, point_value max_x, point_value min_y, point_value max_y) {
  point_value width = max_x - min_x + 1;
  l = l - min_x + 1;
  l = min(l, width);
  r = r - min_y + 1;
  r = min(r, width);

  if (l>r) {
    swap(l, r);
  }

  return normalize_value(l, r, width);
}

unordered_map<normalize_value, modtype> cache;

modtype sub_block(point_value l, point_value r, point_value min_x, point_value max_x, point_value min_y, point_value max_y) {
  //debug cout << "sub_block2 called" << endl;
  //debug cout << dv(l) << dv(r) << dv(min_x) << dv(max_x) << dv(min_y) << dv(max_y) << endl;

  if (l >= max_x && r >= max_y) {
    return count_in_block(log2(max_x-min_x+1)+1);
  }

  if (l < min_x || r < min_y) {
    return modtype(0, MOD);
  }

  // キャッシュ化のため、正規化してmin_x,min_yを0にする
  normalize_value n = normalize(l, r, min_x, max_x, min_y, max_y);
  const auto& ite = cache.find(n);
  if (ite != cache.end()) {
    //debug cout << "hit cache" << dv(n) << endl;
    return ite->second;
  }

  point_value len = max_x - min_x + 1;
  point_value mid_x = min_x + len/2 - 1;
  point_value mid_y = min_y + len/2 - 1;

  // 4分割して計算
  modtype result = modtype(0, MOD) // +sub_block(l, r, min_x, mid_x, min_y, mid_y) // 回転しているので、左上が空
    + sub_block(l, r, min_x, mid_x, mid_y+1, max_y) // 右上
    + sub_block(l, r, mid_x+1, max_x, min_y, mid_y) // 左下
    + sub_block(l, r, mid_x+1, max_x, mid_y+1, max_y) // 右下
    ;

  cache.emplace(n, result);
  //debug cout << "emplace cache:" << dv(n) << dv(result) << endl;

  return result;
}

modtype sub_block(point_value l, point_value r, int block) {
  //debug cout << "sub_block1 called" << endl;

  point_value min_x = block_min_bound(block);
  point_value max_x = block_min_bound(block+1) - 1;
  l = max_x-(l-min_x); // ブロックを回転させて、左上が空になるようにする。4分割したときにキャッシュが効くように
  return sub_block(l, r, min_x, max_x, min_x, max_x);
}

int main() {
  point_value l, r;
  cin >> l >> r;
  modtype result(0, MOD);

  int l_block = block_number(l);
  int r_block = block_number(r);

  //debug cout << l_block << " " << r_block << endl;

  if (l_block == r_block) { // 2-1
    //debug cout << "2-1" << endl;
    result = sub_block(l, r, l_block);
    //debug cout << dv(result) << endl;
  } else { // 2-2
    //debug cout << "2-2" << endl;
    for (int i = l_block + 1; i < r_block; i++) {
      result += count_in_block(i);
      //debug cout << dv(result) << endl;
    }

    result += sub_block(l, r, l_block);
    //debug cout << dv(result) << endl;
    result += sub_block(l, r, r_block);
    //debug cout << dv(result) << endl;
  }

  cout << result << endl;
}


Measured memory_bytes: 384