#include <bits/stdc++.h>
using namespace std;
using lint = long long int;
template<class T = int> using V  = vector<T>;
template<class T = int> using VV = V< V<T> >;
template<class T> void assign(V<T>& v, int n, const T& a = T()) { v.assign(n, a); }
template<class T, class... Args> void assign(V<T>& v, int n, const Args&... args) { v.resize(n); for (auto&& e : v) assign(e, args...); }


constexpr lint mod = 1e9 + 7;
inline lint emod(lint a, lint p = mod) { return (a % p + p) % p; }

struct Monoid {
  using T = struct { lint v, fib; };
  static T op(const T& lhs, const T& rhs) { return {(lhs.v + rhs.v) % mod, (lhs.fib + rhs.fib) % mod}; }
  static constexpr T e() { return {0, 0}; }
};

template<class Monoid> struct MonoidAct {
  using T = struct { lint a, b, c; };
  static void ap(const T& f, typename Monoid::T& a, int len) { a.v = (f.a * a.v + f.b * len + f.c * a.fib) % mod; }
  static void cp(const T& f, T& g) { (g.a *= f.a) %= mod, g.b = (f.a * g.b + f.b) % mod, g.c = (f.a * g.c + f.c) % mod; }
  static constexpr T id() { return {1, 0, 0}; }
};

template<class Monoid, class MonoidAct> struct SegmentTree {
  using Tv = typename Monoid::T;
  using Ta = typename MonoidAct::T;
  struct node {
    lint l, r;
    Tv val = Monoid::e();
    Ta act = MonoidAct::id();
    unique_ptr<node> cl = nullptr, cr = nullptr;
  };

  lint n;
  unique_ptr<node> root;

  SegmentTree(lint n) : n(n), root(new node {0, n}) {}

  Tv get(lint l, lint r) {
    auto get = [&](auto get, const unique_ptr<node>& v) {
      if (l <= v->l and v->r <= r) return v->val;

      lint m = v->l + v->r >> 1;
      if (v->cl == nullptr) v->cl.reset(new node {v->l, m});
      MonoidAct::ap(v->act, v->cl->val, v->cl->r - v->cl->l);
      MonoidAct::cp(v->act, v->cl->act);
      if (v->cr == nullptr) v->cr.reset(new node {m, v->r});
      MonoidAct::ap(v->act, v->cr->val, v->cr->r - v->cr->l);
      MonoidAct::cp(v->act, v->cr->act);
      v->act = MonoidAct::id();

      Tv resl = Monoid::e(), resr = Monoid::e();
      if (l < m) resl = get(get, v->cl);
      if (m < r) resr = get(get, v->cr);
      return Monoid::op(resl, resr);
    };
    return get(get, root);
  }

  void set(lint l, lint r, const Ta& f) {
    auto set = [&](auto set, const unique_ptr<node>& v) {
      if (l <= v->l and v->r <= r) {
        MonoidAct::ap(f, v->val, v->r - v->l);
        MonoidAct::cp(f, v->act);
        return;
      }

      lint m = v->l + v->r >> 1;
      if (v->cl == nullptr) v->cl.reset(new node {v->l, m});
      MonoidAct::ap(v->act, v->cl->val, v->cl->r - v->cl->l);
      MonoidAct::cp(v->act, v->cl->act);
      if (v->cr == nullptr) v->cr.reset(new node {m, v->r});
      MonoidAct::ap(v->act, v->cr->val, v->cr->r - v->cr->l);
      MonoidAct::cp(v->act, v->cr->act);
      v->act = MonoidAct::id();

      if (l < m) set(set, v->cl);
      if (m < r) set(set, v->cr);
      v->val = Monoid::op(v->cl->val, v->cr->val);
    };
    set(set, root);
  }
};

struct RMQ {
  using T = int;
  static T op(const T& lhs, const T& rhs) { return min(lhs, rhs); }
  static constexpr T e() { return numeric_limits<T>::max(); }
};

template<class RMQ> struct RUQ {
  using T = int;
  static void ap(const T& f, typename RMQ::T& a, int len) { a = f == -1 ? a : f; }
  static void cp(const T& f, T& g) { g = f == -1 ? g : f; }
  static constexpr T id() { return -1; }
};

int main() {
  cin.tie(nullptr); ios::sync_with_stdio(false);
  int n, q; cin >> n >> q;
  SegmentTree< RMQ, RUQ<RMQ> > st(n);
  for (int iq = 0; iq < q; ++iq) {
    int c; cin >> c;
    if (!c) {
      int l, r, x; cin >> l >> r >> x, ++r;
      st.set(l, r, x);
    } else {
      int l, r; cin >> l >> r, ++r;
      cout << st.get(l, r) << '\n';
    }
  }
}


Measured memory_bytes: 12064