From Coq Require Import ZArith Lia.

Local Open Scope Z_scope.
Module Z2Nat.
  Definition inj_nonpos n : n <= 0 -> Z.to_nat n = 0%nat.
  Proof.
    destruct n; try reflexivity; lia.
  Qed.
End Z2Nat.

Module Z.
  Lemma pos_pow_nat_pos : forall x n,
    Z.pos x ^ Z.of_nat n > 0.
  Proof. intros; apply Z.lt_gt, Z.pow_pos_nonneg; lia. Qed.

  Lemma pow_Z2N_Zpow : forall a n, 0 <= a ->
                                   ((Z.to_nat a) ^ n = Z.to_nat (a ^ Z.of_nat n)%Z)%nat.
  Proof.
    intros a n H; induction n as [|n IHn]; try reflexivity.
    rewrite Nat2Z.inj_succ.
    rewrite Nat.pow_succ_r by apply le_0_n.
    rewrite Z.pow_succ_r by apply Zle_0_nat.
    rewrite IHn.
    rewrite Z2Nat.inj_mul; auto using Z.pow_nonneg.
  Qed.

  Lemma pow_Zpow : forall a n : nat, Z.of_nat (a ^ n) = Z.of_nat a ^ Z.of_nat n.
  Proof with auto using Zle_0_nat, Z.pow_nonneg.
    intros; apply Z2Nat.inj...
    rewrite <- pow_Z2N_Zpow, !Nat2Z.id...
  Qed.
#[global]
  Hint Rewrite pow_Zpow : push_Zof_nat.
#[global]
  Hint Rewrite <- pow_Zpow : pull_Zof_nat.

  Lemma Zpow_sub_1_nat_pow a v
    : (Z.pos a^Z.of_nat v - 1 = Z.of_nat (Z.to_nat (Z.pos a)^v - 1))%Z.
  Proof.
    rewrite <- (Z2Nat.id (Z.pos a)) at 1 by lia.
    change 2%Z with (Z.of_nat 2); change 1%Z with (Z.of_nat 1);
      autorewrite with pull_Zof_nat.
    rewrite Nat2Z.inj_sub
      by (change 1%nat with (Z.to_nat (Z.pos a)^0)%nat; apply Nat.pow_le_mono_r; simpl; lia).
    reflexivity.
  Qed.
#[global]
  Hint Rewrite Zpow_sub_1_nat_pow : pull_Zof_nat.
#[global]
  Hint Rewrite <- Zpow_sub_1_nat_pow : push_Zof_nat.
End Z.
