Class FiniteCyclicGroup `{G: Group}
      (g : GroupElement)(order : posnat)(groupLog : GroupElement -> GroupElement -> nat) := {
                                                                             
  generator : GroupElement -> Prop;
  g_generator : generator g;
  group_cyclic: forall (g a : GroupElement),
    generator g ->
    g^(groupLog g a) = a;
  groupLog_correct: forall g x,
    generator g ->
    modNat (groupLog g (g^x)) order = modNat x order;
  groupIdent : forall g,
    generator g -> 
    g^0 = ident;
  groupOrder : forall g,
    generator g ->
    g^order = g^0
    
}.Class FiniteCyclicGroup `{G: Group}
      (g : GroupElement)(order : posnat)(groupLog : GroupElement -> GroupElement -> nat) := {
                                                                             
  generator : GroupElement -> Prop;
  g_generator : generator g;
  group_cyclic: forall (g a : GroupElement),
    generator g ->
    g^(groupLog g a) = a;
  groupLog_correct: forall g x,
    generator g ->
    modNat (groupLog g (g^x)) order = modNat x order;
  groupIdent : forall g,
    generator g -> 
    g^0 = ident;
  groupOrder : forall g,
    generator g ->
    g^order = g^0
    
}.Class FiniteCyclicGroup `{G: Group}
      (g : GroupElement)(order : posnat)(groupLog : GroupElement -> GroupElement -> nat) := {
                                                                             
  generator : GroupElement -> Prop;
  g_generator : generator g;
  group_cyclic: forall (g a : GroupElement),
    generator g ->
    g^(groupLog g a) = a;
  groupLog_correct: forall g x,
    generator g ->
    modNat (groupLog g (g^x)) order = modNat x order;
  groupIdent : forall g,
    generator g -> 
    g^0 = ident;
  groupOrder : forall g,
    generator g ->
    g^order = g^0
    
}.Class FiniteCyclicGroup `{G: Group}
      (g : GroupElement)(order : posnat)(groupLog : GroupElement -> GroupElement -> nat) := {
                                                                             
  generator : GroupElement -> Prop;
  g_generator : generator g;
  group_cyclic: forall (g a : GroupElement),
    generator g ->
    g^(groupLog g a) = a;
  groupLog_correct: forall g x,
    generator g ->
    modNat (groupLog g (g^x)) order = modNat x order;
  groupIdent : forall g,
    generator g -> 
    g^0 = ident;
  groupOrder : forall g,
    generator g ->
    g^order = g^0
    
}.Class FiniteCyclicGroup `{G: Group}
      (g : GroupElement)(order : posnat)(groupLog : GroupElement -> GroupElement -> nat) := {
                                                                             
  generator : GroupElement -> Prop;
  g_generator : generator g;
  group_cyclic: forall (g a : GroupElement),
    generator g ->
    g^(groupLog g a) = a;
  groupLog_correct: forall g x,
    generator g ->
    modNat (groupLog g (g^x)) order = modNat x order;
  groupIdent : forall g,
    generator g -> 
    g^0 = ident;
  groupOrder : forall g,
    generator g ->
    g^order = g^0
    
}.Class FiniteCyclicGroup `{G: Group}
      (g : GroupElement)(order : posnat)(groupLog : GroupElement -> GroupElement -> nat) := {
                                                                             
  generator : GroupElement -> Prop;
  g_generator : generator g;
  group_cyclic: forall (g a : GroupElement),
    generator g ->
    g^(groupLog g a) = a;
  groupLog_correct: forall g x,
    generator g ->
    modNat (groupLog g (g^x)) order = modNat x order;
  groupIdent : forall g,
    generator g -> 
    g^0 = ident;
  groupOrder : forall g,
    generator g ->
    g^order = g^0
    
}.Class FiniteCyclicGroup `{G: Group}
      (g : GroupElement)(order : posnat)(groupLog : GroupElement -> GroupElement -> nat) := {
                                                                             
  generator : GroupElement -> Prop;
  g_generator : generator g;
  group_cyclic: forall (g a : GroupElement),
    generator g ->
    g^(groupLog g a) = a;
  groupLog_correct: forall g x,
    generator g ->
    modNat (groupLog g (g^x)) order = modNat x order;
  groupIdent : forall g,
    generator g -> 
    g^0 = ident;
  groupOrder : forall g,
    generator g ->
    g^order = g^0
    
}.

Lemma groupExp_eq_h : forall g c1 v, generator g -> v < order -> g^(c1 * order + v) = g^v.