//#pragma GCC optimize("Ofast")
//#pragma GCC optimize("unroll-loops")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
using db = double;
using ld = long double;
template<typename T> using V = vector<T>;
template<typename T> using VV = vector<vector<T>>;
#define fs first
#define sc second
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define eb emplace_back
#define lb lower_bound
#define ub upper_bound
#define all(v) (v).begin(),(v).end()
#define siz(v) (ll)(v).size()
#define rep(i,a,n) for(ll i=a;i<(ll)(n);++i)
#define repr(i,a,n) for(ll i=n-1;(ll)a<=i;--i)
#define ENDL '\n'
typedef pair<int,int> Pi;
typedef pair<ll,ll> PL;
constexpr ll mod = 1000000007;
constexpr ll INF = 1000000099;
constexpr ll LINF = (ll)(1e18 +99);
const vector<ll> dx={-1,1,0,0},dy={0,0,-1,1};
template<typename T,typename U> inline bool chmin(T& t, const U& u){if(t>u){t=u;return 1;}return 0;}
template<typename T,typename U> inline bool chmax(T& t, const U& u){if(t<u){t=u;return 1;}return 0;}
template<typename T> inline T gcd(T a,T b){return b?gcd(b,a%b):a;}

template<typename T,typename Y> inline T mpow(T a, Y n) {
  T res = 1;
  for(;n;n>>=1) {
    if (n & 1) res = res * a;
    a = a * a;
  }
  return res;
}

template<typename T,typename Y>
ostream& operator<<(ostream& os,const pair<T,Y>& p){
   return os<<"{"<<p.fs<<","<<p.sc<<"}";
}
template<typename T> ostream& operator<<(ostream& os,const V<T>& v){
   os<<"{";
  for(auto e:v)os<<e<<",";
  return os<<"}";
}
template<typename ...Args>
void debug(Args&... args){
  for(auto const& x:{args...}){
    cerr<<x<<' ';
  }
  cerr<<ENDL;
}

template <long long MOD = 1000000007> //MODを適宜設定すること
struct Mint
{
   using M = Mint;
   ll a;
   Mint(ll x=0){a=x%MOD;if(a<0) a+=MOD;}//Mintで

   M pow(ll n){
      M b=*this,r=1%MOD;
      while(n){
         if(n&1)r*=b;
         b*=b;
         n>>=1;
      }
      return r;
   }

   M inv(){return pow(MOD-2);}

   M& operator+=(M r){a+=r.a;if(a>=MOD)a-=MOD;return *this;}
   M& operator-=(M r){a+=MOD-r.a;if(a>=MOD)a-=MOD;return *this;}
   M& operator*=(M r){a=1LL*a*r.a%MOD;return *this;}
   M& operator/=(M r){return (*this)*=r.inv();}
   M operator+(M r) const{return M(a)+=r;};
   M operator-(M r) const{return M(a)-=r;};
   M operator*(M r) const{return M(a)*=r;};
   M operator/(M r) const{return M(a)/=r;};

   friend ostream& operator<<(ostream& os,const M& r){return os<<r.a;}
};
using M = Mint<mod>;

const int MAX=500010;

M fac[MAX], finv[MAX], inv[MAX];

void COMinit() {
    fac[0] = fac[1] = 1;
    finv[0] = finv[1] = 1;
    inv[1] = 1;
    for (int i = 2; i < MAX; i++){
        fac[i] = fac[i - 1] * i;
        inv[i] = M{mod}-inv[mod%i] * (mod / i);
        finv[i] = finv[i - 1] * inv[i];
    }
}

M COM(int n, int k){
    if (n < k) return 0;
    if (n < 0 || k < 0) return 0;
    return fac[n] * finv[k] * finv[n - k] ;
}


signed main(){
  cin.tie(0);cerr.tie(0);ios::sync_with_stdio(false);
  cout<<fixed<<setprecision(20);
  ll n,m;cin>>n>>m;
  COMinit();

  M ans=0;

  rep(i,0,n+1){
    if(i%2==0) ans+=COM(m,i)*COM(m-i,n-i)*COM(m-i,n-i)*fac[n]*fac[n-i];
    else ans-=COM(m,i)*COM(m-i,n-i)*COM(m-i,n-i)*fac[n]*fac[n-i];
  }


  cout<<ans<<ENDL;

}
//! ( . _ . ) ! 
//CHECK overflow,vector_size,what to output?

Measured memory_bytes: 15328