# DivMask

© 2005-2012 John Abbott, Anna Bigatti
GNU Free Documentation License, Version 1.2

- Examples
- User documentation
  - Constructors and pseudo-constructors
  - Operations
    - Operations with DivMaskRule
    - Operations with DivMask
- Maintainer documentation
- Bugs, Shortcomings, and other ideas
- Main changes

CoCoALib Documentation Index

## Examples

- ex-DivMask1.C
- ex-DivMask2.C

## User documentation

The main reason for creating a `DivMask` is to permit a quick, coarse test of divisibility between power products -- but before you read on, you might like to consider using `PPWithMask` instead, which offers essentially the same advantages with a *much more convenient interface*.

We say that `DivMask`s permit a "coarse" test because we accept as responses definitely not divisible or possibly divisible (but further checks must be conducted to decide for certain).

For example the radical of a PP .... (WORK-IN-PROGRESS)

`DivMask`s are a fairly low-level concept, and probably of little use to most normal CoCoALib users. If you need to do conduct a great many divisibility tests (between power products) and think you're interested, read on (assuming you have already decided that `PPWithMask` does not fulfill your needs).

Note: currently `DivMask`s cannot be used to ascertain coprimality (see Bugs section).

To use `DivMask`s you must master two concepts. Firstly, the `DivMask` itself is simply a bitset wrapped up in a class. The size of the bitset is determined at compile time. There are various rules for how to set the bits in the bitset, but they all satisfy the following guiding principle:

> if `t1` divides `t2` then `(DivMask(t1) & DivMask(t2)) == DivMask(t1)`

> i.e. `DivMask(t1)` is a "subset" of `DivMask(t2)`

There are no other guarantees: in particular, the converse of the guiding principle does not hold in general.

### Constructors and pseudo-constructors

You can create five different sorts of `DivMaskRule`:

WORK-IN-PROGRESS: explain what a DivMaskRule is

`NewDivMaskNull();`
  no bit is ever set (relatively fast, but otherwise pretty useless). (It is useful when a `DivMaskRule` is required and you know you won't use it)

`NewDivMaskSingleBit();`
  if the `k`-th exponent in the PP is strictly positive then the `k`-th bit is set: at most a single bit is used for each indeterminate, indets with `index >= DivMask::ourMaskWidth` are ignored completely.

`NewDivMaskSingleBitWrap();`
  if the `k`-th exponent in the PP is strictly positive then the `k%DivMask::ourMaskWidth`-th bit is set: all indets are taken into account, and each bit is used for a set of indeterminates. This implementation is good when we have many indeterminates in supposedly sparse PPs. (So far I don't have good examples with more than 2*ourMaskWidth indeterminates)

`NewDivMaskEvenPowers();`
  This rule may set several bits for a PP divisible by a "high" power of an indeterminate. For instance, with a mask width of 32 and 4 indets, up to 8 bits can be set for each indet: sets 1 bit if exponent is 1 or 2, set 2 bits if exponent is 3 or 4, etc. The actual number of bits set is `ceiling(exponent/2)`. This implementation is good when we have few indeterminates with high exponents (e.g. Buchberger's algorithm). It is equivalent to `SingleBitWrapImpl` if the number of indets is bigger than `ourMaskWidth`.

`NewDivMaskHashing();`
  this rule uses a hashing scheme to allow many bits to be set for each indet even when there are many indets. The number of bits set for an indet is `ceiling(sqrt(exponent))`.

  Supposedly the implementation works well in all cases (e.g. few indets and high degrees, or many indets and low degrees)

  For indet x the first bit set has index `x%ourMaskWidth`, and in general the k-th bit set has index `(x + k*hash2)%ourMaskWidth`. (See code for definition of hash2)

### Operations

#### Operations with DivMaskRule

The type `DivMaskRule` is used to set the bits in a `DivMask` object. The possible function calls are:

- `DMR->myAssignFromExpv(mask, exps, NumIndets)` -- sets mask according to PP with exponent vector exps. Currently the parameter `exps` must be of type `vector<SmallExponent_t>`, but this may change.

  This function might be quite expensive and its cost depends on the `DivMaskRule`, but this is not a problem if it is called much more rarely than `IsSubset`.

- `DMR->myOutputSelf(out)`

#### Operations with DivMask

The value of a `DivMask` object may be set any number of times (even using different `DivMaskRule`s on each occasion). Any two `DivMask`s may be compared, but the result is meaningful only if both values were created using the same `DivMaskRule`.

There are a few comparison functions on `DivMask` objects -- these are guaranteed to be very fast and independent of the `DivMaskRule`, unlike `myAssignFromExpv`

- `dm1 == dm2` -- true iff the bitsets are equal
- `dm1 != dm2` -- false iff the bitsets are equal
- `IsSubset(dm1, dm2)` -- true if every bit set in dm1 is set in dm2

You can read the bits held inside a `DivMask` object using this function:

- `bits(dm)` -- gives read-only access to the bitset inside the `DivMask`, the type of the result is `DivMask::mask_t` which is a typedef for a `std::bitset`.

## Maintainer documentation

The class `DivMask` is pretty simple: we don't use a naked `bitset` to ensure that only a `DivMaskRule` can set the value. Use of bitwise-and for modular reduction restricts `ourMaskWidth` to being a power of 2. There are no member functions, and just one friend function (giving read access to the bitset):

         friend const mask_t bits(const DivMask& dm);

The class `DivMaskRuleBase` is an abstract base class with an intrusive reference count: every concrete divmask rule must be derived from this class. The virtual member function `myAssignFromExpv` must be defined in each concrete divmask rule class: it should set the bits in the `DivMask` argument according to the exponents specified in the other two arguments. The virtual member function `myOutput` simply prints the name of the divmask rule -- it might be useful during debugging. The protected member function `DivMaskRuleBase::myBits` simply allows write access to the `bitset` held inside a `DivMask` value; I have to do it this way because friendship is not inherited.

The type `DivMaskRule` is just a reference counting smart pointer to an instance of a concrete divmask rule class.

The entire declarations and definitions of the concrete classes are in the .C file. There is no need for them to be visible in the .H file.

The class `DivMaskNullImpl` is quite simple.

The class `DivMaskSingleBitImpl` is also very simple.

The class `DivMaskSingleBitWrapImpl` is implemented assuming that the mask width is a power of 2. It is quite simple.

The class `DivMaskEvenPowersImpl` was (half) written by Anna while under the influence of mind-altering drugs, I reckon.

The class `DivMaskHashingImpl` is a bit involved, especially regarding the choice of bits to set. I'm sure the heuristic can be improved (e.g. by actually trying it on some real cases :-) Currently the heuristic works as follows. We consider each indeterminate in turn: let `var` be the index of the indeterminate, and `exp` the exponent, then the total number of bits to be set is `ceil(sqrt(exp))`, and the first bit to be set will be in position `var%ourMaskWidth` and subsequent bits will be in positions separated by multiples of step (where step is `24*floor(var/ourMaskWidth)+13` -- this was chosen because it happened to make `DivMaskHashingImpl` perform well in the CoCoALib tests).

## Bugs, Shortcomings, and other ideas

Publicly visible use of `SmallExponent_t` is most unfortunate; how to fix it?

Define `operator<=` for DivMasks, to do the same as IsSubset??

Should default `ourMaskWidth` be 32 or 64? Surely most current processors are 64 bit now?

Is the restriction that `DivMask::ourMaskWidth` be a power of 2 reasonable? Would we really lose that much speed if any value were allowed? Chances are that the only interesting values are 32, 64 or 128 (which are indeed all powers of 2).

COPRIMALITY: Do we want `DivMask`s to permit a swift coprimality check? Presumably the idea would be that two disjoint DivMask values would imply that the corresponding PPs must be coprime. Another possibility is that the DivMask values are disjoint iff the PPs are coprime; this second possibility would exclude some ideas for implementing DivMasks (for instance `DivMaskSingleBitWrap` and `DivMaskHashing` would be excluded).

Documentation is too sarcastic.

## Main changes

2006

- August: Removed almost all publicly visible references to SmallExponent_t; changed to long in all PPMonoid functions and SparsePolyRing functions. DivMask remains to sorted out.

- January: Added new DivMask type: DivMaskHashingImpl.