* Abstract operator does not hide predefined operator
@ 2010-11-12 15:04 Stefan.Lucks
2010-11-12 16:56 ` Adam Beneschan
0 siblings, 1 reply; 3+ messages in thread
From: Stefan.Lucks @ 2010-11-12 15:04 UTC (permalink / raw)
Hi all,
I've implemented a small generic package for modular arithmetic. Note that
Ada's "mod N" types define addition subtraction and multiplication right,
but use the integer division for "/" instead of the proper modular
division, where A/B is A * Inverse(B). I also tried to get rid of the
unary "not" operator, who's purpose I don't understand for general
modular arithmetic. (I understand that it is useful if the modulus is a
power of two, just like the binary xor operator.)
This is the spec of my generic package:
generic
type Mod_T is mod <>;
package Mod_Arith is
type Modular is new Mod_T;
function "/"(Left, Right: Modular) return Modular;
function Inverse(Value: Modular) return Modular;
function "not"(Value: Modular) return Modular is abstract;
end Mod_Arith;
For testing that package, I first instantiated it:
type M3343 is mod 3343;
package M is new Mod_Arith(Mod_T => M3343);
use type M.Modular;
S,T,U: M.Modular;
(Sidenote: 3343 is a prime, so addition and multiplication over M.Modular
are field operations, mathematically.)
Now, my freshly defined division works as expected. The multiplication
(and addition and subtraction) are inherited from the type M3343:
S := 3;
T := S/(2*S); -- T becomes the multiplicative Inverse of 2 mod 3343;
-- the same expression's result in M3343 would be zero.
Ada.Text_IO.Put_Line(M.Modular'Image(T) &
M.Modular'Image(M.Inverse(2)));
-- The output is "1672 1672", as expected.
But, unfortunately, the compiler (gnat) also accepts the following:
U := not S; -- this should not be possible, because the "not" operator
-- has been defined abstract ... but instead, the
-- predefined "not" from M3343 seems to be used
Ada.Text_IO.Put_Line(M.Modular'Image(U));
-- The output is "3339", which actually is not(M3343(S)) = 3342-S.
What can I do to get rid of the predefined "not"? If I change the "not"
from an abstract function to a function always raising an exception, the
statement
U := not S;
raises the desired exception. But I would prefer to be told at compile
time that I must not use "not", rather than at run time. Also, I would
prefer not to define the type Mod_Arith.Modular as a private type.
Any ideas?
Stefan
--
------ Stefan Lucks -- Bauhaus-University Weimar -- Germany ------
Stefan dot Lucks at uni minus weimar dot de
------ I love the taste of Cryptanalysis in the morning! ------
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: Abstract operator does not hide predefined operator
2010-11-12 15:04 Abstract operator does not hide predefined operator Stefan.Lucks
@ 2010-11-12 16:56 ` Adam Beneschan
2010-11-12 17:39 ` Alex Mentis
0 siblings, 1 reply; 3+ messages in thread
From: Adam Beneschan @ 2010-11-12 16:56 UTC (permalink / raw)
On Nov 12, 7:04 am, Stefan.Lu...@uni-weimar.de wrote:
> Hi all,
>
> I've implemented a small generic package for modular arithmetic. Note that
> Ada's "mod N" types define addition subtraction and multiplication right,
> but use the integer division for "/" instead of the proper modular
> division, where A/B is A * Inverse(B). I also tried to get rid of the
> unary "not" operator, who's purpose I don't understand for general
> modular arithmetic. (I understand that it is useful if the modulus is a
> power of two, just like the binary xor operator.)
>
> This is the spec of my generic package:
>
> generic
> type Mod_T is mod <>;
> package Mod_Arith is
> type Modular is new Mod_T;
> function "/"(Left, Right: Modular) return Modular;
> function Inverse(Value: Modular) return Modular;
> function "not"(Value: Modular) return Modular is abstract;
> end Mod_Arith;
>
> For testing that package, I first instantiated it:
>
> type M3343 is mod 3343;
> package M is new Mod_Arith(Mod_T => M3343);
> use type M.Modular;
> S,T,U: M.Modular;
>
> (Sidenote: 3343 is a prime, so addition and multiplication over M.Modular
> are field operations, mathematically.)
>
> Now, my freshly defined division works as expected. The multiplication
> (and addition and subtraction) are inherited from the type M3343:
>
> S := 3;
> T := S/(2*S); -- T becomes the multiplicative Inverse of 2 mod 3343;
> -- the same expression's result in M3343 would be zero.
> Ada.Text_IO.Put_Line(M.Modular'Image(T) &
> M.Modular'Image(M.Inverse(2)));
> -- The output is "1672 1672", as expected.
>
> But, unfortunately, the compiler (gnat) also accepts the following:
>
> U := not S; -- this should not be possible, because the "not" operator
> -- has been defined abstract ... but instead, the
> -- predefined "not" from M3343 seems to be used
> Ada.Text_IO.Put_Line(M.Modular'Image(U));
> -- The output is "3339", which actually is not(M3343(S)) = 3342-S.
>
> What can I do to get rid of the predefined "not"? If I change the "not"
> from an abstract function to a function always raising an exception, the
> statement
>
> U := not S;
>
> raises the desired exception. But I would prefer to be told at compile
> time that I must not use "not", rather than at run time. Also, I would
> prefer not to define the type Mod_Arith.Modular as a private type.
>
> Any ideas?
This appears to be a GNAT bug; the inherited "not" subprogram of
Modular, which is inherited from the predefined function of M3343,
exists but should be hidden from all visibility, and therefore cannot
be a possible meaning of "not" in the expression "not S". So what
you're doing should work, I think. (P.S. I've confirmed that the
version of GNAT I'm using also accepts the program if I write out M
instead of making it a generic instantiation, and if I use "use"
instead of "use type". So neither of those appears to be an issue.)
-- Adam
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: Abstract operator does not hide predefined operator
2010-11-12 16:56 ` Adam Beneschan
@ 2010-11-12 17:39 ` Alex Mentis
0 siblings, 0 replies; 3+ messages in thread
From: Alex Mentis @ 2010-11-12 17:39 UTC (permalink / raw)
Adam Beneschan wrote:
> On Nov 12, 7:04�am, Stefan.Lu...@uni-weimar.de wrote:
> > Hi all,
> >
> > I've implemented a small generic package for modular arithmetic.
> > Note that Ada's "mod N" types define addition subtraction and
> > multiplication right, but use the integer division for "/" instead
> > of the proper modular division, where A/B is A * Inverse(B). I also
> > tried to get rid of the unary "not" operator, who's purpose I don't
> > understand for general modular arithmetic. (I understand that it is
> > useful if the modulus is a power of two, just like the binary xor
> > operator.)
> >
> > This is the spec of my generic package:
> >
> > generic
> > � �type Mod_T is mod <>;
> > package Mod_Arith is
> > � �type Modular is new Mod_T;
> > � �function "/"(Left, Right: Modular) return Modular;
> > � �function Inverse(Value: Modular) return Modular;
> > � �function "not"(Value: Modular) return Modular is abstract;
> > end Mod_Arith;
> >
> > For testing that package, I first instantiated it:
> >
> > � �type M3343 is mod 3343;
> > � �package M is new Mod_Arith(Mod_T => M3343);
> > � �use type M.Modular;
> > � �S,T,U: M.Modular;
> >
> > (Sidenote: 3343 is a prime, so addition and multiplication over
> > M.Modular are field operations, mathematically.)
> >
> > Now, my freshly defined division works as expected. The
> > multiplication (and addition and subtraction) are inherited from
> > the type M3343:
> >
> > � �S := 3;
> > � �T := S/(2*S); -- T becomes the multiplicative Inverse of 2 mod
> > 3343; � � � � � � � � �-- the same expression's result in M3343
> > would be zero. � �Ada.Text_IO.Put_Line(M.Modular'Image(T) &
> > � � � � � � � � � � � � � M.Modular'Image(M.Inverse(2)));
> > � �-- The output is "1672 1672", as expected.
> >
> > But, unfortunately, the compiler (gnat) also accepts the following:
> >
> > � �U := not S; -- this should not be possible, because the "not"
> > operator � � � � � � � �-- has been defined abstract ... but
> > instead, the � � � � � � � �-- predefined "not" from M3343 seems to
> > be used � �Ada.Text_IO.Put_Line(M.Modular'Image(U));
> > � �-- The output is "3339", which actually is not(M3343(S)) =
> > 3342-S.
> >
> > What can I do to get rid of the predefined "not"? If I change the
> > "not" from an abstract function to a function always raising an
> > exception, the statement
> >
> > � �U := not S;
> >
> > raises the desired exception. But I would prefer to be told at
> > compile time that I must not use "not", rather than at run time.
> > Also, I would prefer not to define the type Mod_Arith.Modular as a
> > private type.
> >
> > Any ideas?
>
> This appears to be a GNAT bug; the inherited "not" subprogram of
> Modular, which is inherited from the predefined function of M3343,
> exists but should be hidden from all visibility, and therefore cannot
> be a possible meaning of "not" in the expression "not S". So what
> you're doing should work, I think. (P.S. I've confirmed that the
> version of GNAT I'm using also accepts the program if I write out M
> instead of making it a generic instantiation, and if I use "use"
> instead of "use type". So neither of those appears to be an issue.)
>
> -- Adam
Agree that it smells buggy. It seems that the problem only affects
making unary operators abstract ("-" and "not"). Testing with "+", "-",
"/", "*", "and", "or", and "xor" operators as abstract refused to
compile as expected for me.
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2010-11-12 17:39 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-11-12 15:04 Abstract operator does not hide predefined operator Stefan.Lucks
2010-11-12 16:56 ` Adam Beneschan
2010-11-12 17:39 ` Alex Mentis
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox