Skip to content

Commit

Permalink
improving docs
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewcooke committed Jul 8, 2015
1 parent bec26db commit de3e8f9
Show file tree
Hide file tree
Showing 4 changed files with 180 additions and 156 deletions.
59 changes: 50 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ of crypto code.
* [Examples](#examples)
* [Types](#types)
* [Integers Modulo N](#integers-modulo-n)
* [Polynomials](#polynomials)
* [Polynomials with Integral Coefficients](#polynomials-with-integral-coefficients)
* [Polynomials over GF(2)](#polynomials-over-gf-2)


Incomplete; pull requests welcome.

Expand Down Expand Up @@ -125,23 +129,24 @@ integers).

### Integers Modulo N

`ZModN{N,I<:Integer} <: Residue` - abstract superclass for *integers* modulo
`ZModN{N,I<:Integer} <: Residue` - abstract superclass for integers modulo
some value, where `N` is the modulus, and so typically an `Int` (yes, that's a
integer as a *type*, not a value), and `I`

This has two concrete subclasses, because when `N` is a prime number we can do
more stuff.
This has two concrete subclasses, because when `N` is a prime number we can
define a multiplicative inverse.

`ZRing{N, I<:Integer} <: ZModN{N,I}` - the general case.

`ZField{N, I<:Integer} <: ZModN{N,I}` - assumes that `N` is prime.
`ZField{N, I<:Integer} <: ZModN{N,I}` - assumes that `N` is prime, and so
includes division.

These constructors can be used directly, but do not check that arguments are
consistent with assumptoins made in the code (primality, values within range,
etc).
consistent with assumptions made in the code (values within range, etc).

The associated functions `ZR()` and `ZF()` are more suitable for "normal" use,
and include support for factory functions:
The associated functions `ZR()` and `ZF()` are more suitable for "normal" use
(but still do not check primality for fields), and include support for factory
functions:

```julia
julia> ZF(3, 5, UInt8)
Expand All @@ -167,4 +172,40 @@ julia> @zring 4 begin
1x5 Array{IntModN.ZRing{4,Int64},2}:
1 2 3 0 1
```
`

### Polynomials

`Poly <: Residue` - abstract superclass for polynomials. All share some basic
conventions about accessing coefficients (with `[]`) and iterators.

Note: Originally, the code used
[Polynomial.jl](https://github.com/vtjnash/Polynomial.jl), but that had some
weird design decisions so I wrote my own code. Since then,
[Polynomials.jl](https://github.com/Keno/Polynomials.jl) fixed some of the
issues, so at some point it may make sense to revert to that package.

#### Polynomials With Integral Coefficients

`ZPoly{I<:Integer} <: Poly` - a simple wrapper around an array of integral
coefficients (including `ZModN` subclasses). The coefficients are in the
"usual" order, so `[i]` gives the ith coefficient, and the leading coefficient
is always non-zero (or the array is empty).

As with integers mod N, the constructor can be used directly, but it is
generally preferable to use `ZP()`, which has various forms.

In addition, there's support for the natural syntax `x^n...` via `X()`:

```julia
julia> x = X(ZF(2))
ZP(IntModN.ZField{2,Int64},1,0)

julia> x^3 + x
ZP(IntModN.ZField{2,Int64},1,0,1,0)
```

#### Polynomials over GF(2)

`GF2Poly{I<:Unsigned} <: Poly` - specialized support for polynomials over
GF(2). Coefficients can be only 0 or 1, so we can use bit fields (integers)
for their values.
52 changes: 16 additions & 36 deletions src/IntModN.jl
Original file line number Diff line number Diff line change
Expand Up @@ -209,12 +209,12 @@ end

# --- supertype for all polynomial representations

abstract PModN <: Residue
abstract Poly <: Residue

endof(a::PModN) = length(a)
start(::PModN) = 1
done(a::PModN, i) = i > length(a)
next(a::PModN, i) = (a[i], i+1)
endof(a::Poly) = length(a)
start(::Poly) = 1
done(a::Poly, i) = i > length(a)
next(a::Poly, i) = (a[i], i+1)


# --- arbitrary (but "integer") coeff polynomials
Expand All @@ -227,7 +227,7 @@ next(a::PModN, i) = (a[i], i+1)
# contents unless you have a new instance whose contents you know to be
# owned.

immutable ZPoly{I<:Integer} <: PModN
immutable ZPoly{I<:Integer} <: Poly
a::Vector{I}
ZPoly(a) = length(a) == 0 || a[end] != zero(I) ? new(a) : error("zero leading coeff")
end
Expand Down Expand Up @@ -507,7 +507,7 @@ end
# --- GF(2) polynomials encoded as bits


immutable GF2Poly{I<:Unsigned} <: PModN
immutable GF2Poly{I<:Unsigned} <: Poly
i::I
end

Expand Down Expand Up @@ -638,29 +638,29 @@ degree{U<:Unsigned}(p::GF2Poly{U}) = 8*sizeof(U) - leading_zeros(p)

# this all assumes that the factor poynomial is irreducible

abstract FModN{P<:PModN, F} <: Residue
abstract FModN{P<:Poly, F} <: Residue

# assumes already reduced
immutable FRing{P<:PModN, F} <: FModN{P,F}
immutable FRing{P<:Poly, F} <: FModN{P,F}
p::P
end

function prepare_f{P<:PModN}(p::P, f::P)
function prepare_f{P<:Poly}(p::P, f::P)
p % f
end

FR{P<:PModN}(p::P, f::P) = FRing{P, encode_factor(f)}(prepare_f(p, f))
FR{P<:Poly}(p::P, f::P) = FRing{P, encode_factor(f)}(prepare_f(p, f))

factor{P<:PModN, F}(::Type{FRing{P, F}}) = decode_factor(P, F)
factor{P<:PModN, F}(::FRing{P, F}) = factor(FRing{P, F})
modulus{P<:PModN, F}(::Type{FModN{P,F}}) = modulus(P)
factor{P<:Poly, F}(::Type{FRing{P, F}}) = decode_factor(P, F)
factor{P<:Poly, F}(::FRing{P, F}) = factor(FRing{P, F})
modulus{P<:Poly, F}(::Type{FModN{P,F}}) = modulus(P)
modulus{F<:FModN}(::F) = modulus(F)
# assuming irreducible factor
order{F<:FModN}(::Type{F}) = modulus(F) ^ degree(factor(F)) - 1
order{F<:FModN}(::F) = order(F)

zero{P<:PModN, F}(::Type{FRing{P, F}}) = FR(zero(P), decode_factor(P, F))
one{P<:PModN, F}(::Type{FRing{P, F}}) = FR(one(P), decode_factor(P, F))
zero{P<:Poly, F}(::Type{FRing{P, F}}) = FR(zero(P), decode_factor(P, F))
one{P<:Poly, F}(::Type{FRing{P, F}}) = FR(one(P), decode_factor(P, F))
zero{F<:FModN}(f::F) = zero(F)
one{F<:FModN}(f::F) = one(F)

Expand Down Expand Up @@ -690,24 +690,4 @@ liftf{F<:FRing}(f, a::F, b::F) = FR(f(a.p, b.p), factor(F))
inv{F<:FRing}(f::F) = FR(extended_euclidean(f.p, factor(f)), factor(f))
/{F<:FRing}(a::F, b::F) = a * inv(b)



# --- pull in tests (does this need ot be so ugly?)


# TODO - try include (relative path) here
# TODO - move to Pkg.test etc

#d = Pkg.dir("IntModN")
#d = "$d/src"
#push!(LOAD_PATH, d)
#import Tests
#import PTests
#pop!(LOAD_PATH)
#
#function tests()
# Tests.tests()
# PTests.tests()
#end

end
4 changes: 2 additions & 2 deletions test/PTests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

module PTests

using Polynomial, IntModN, Compat
using Polynomial, IntModN, Compat, Base.Test

import Base: promote_rule, convert

Expand Down Expand Up @@ -125,7 +125,7 @@ function test_eq(a, T, op)
println("($p2) $x ($q2)")
println("r2 $(typeof(r2)) $(r2)")
end
@assert r1 == r2
@test r1 == r2
end
end
end
Expand Down

0 comments on commit de3e8f9

Please sign in to comment.