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
    
}.

Theorem groupExp_distrib : forall n x y, (x * y)^n = x^n * y^n.