% first line Data.PcSets.Compact
% This file is part of gpcsets: Pitch Class Sets for Haskell
% Copyright 2009 by Bruce H. McCosar.
% Distributed under a BSD3 license; see the file 'LICENSE' for details.
\chapter{Data.PcSets.Compact}
\section{Introduction}
\begin{quote}
{\bf Important Note.} My philosophy in designing these modules has been to
avoid pointless errors and exceptions, that is, to create acceptable, sane
default operations. I assume if someone is going to try to run the text of
Tolstoy's "War and Peace" through the String-to-Pitch-Class-Set routines
in this module, they are prepared to accept the default behavior, which
is to silently ignore much of the input. This makes much more sense than
attempting to handle every possible input string (and provide a suitable
error message for each case).
\end{quote}
\subsection{The Module Export List}
\begin{code}
module Data.PcSets.Compact
(
toGenSet
, toStdSet
, toStdSet'
, toGenRow
, toStdRow
, toStdRow'
, compact
, compact'
)
where
\end{code}
\subsection{The Module Import List}
\begin{code}
import qualified Data.PcSets as P
\end{code}
\section{Constructors: Compact Format to PcSet}
\subsection{Pitch Class Sets}
\subsubsection{toGenSet}
\begin{code}
toGenSet :: Int -> String -> P.GenSet
toGenSet n = P.genset n . trBase36
\end{code}
\subsubsection{toStdSet}
\begin{code}
toStdSet :: String -> P.StdSet
toStdSet = P.stdset . trBase36
\end{code}
\subsubsection{toStdSet'}
\begin{code}
toStdSet' :: String -> P.StdSet
toStdSet' = P.stdset . trBase12
\end{code}
\subsection{Tone Rows}
\subsubsection{toGenRow}
\begin{code}
toGenRow :: Int -> String -> P.GenRow
toGenRow n = P.genrow n . trBase36
\end{code}
\subsubsection{toStdRow}
\begin{code}
toStdRow :: String -> P.StdRow
toStdRow = P.stdrow . trBase36
\end{code}
\subsubsection{toStdRow'}
\begin{code}
toStdRow' :: String -> P.StdRow
toStdRow' = P.stdrow . trBase12
\end{code}
\section{Abbreviators: PcSet to Compact Format}
\subsection{General Case}
\begin{code}
compact :: P.PcSet a => a -> String
compact = filter (/= '#') . map f . P.elements
where f n
| 0 <= n && n <= 9 = toEnum (n + 48)
| 9 < n && n < 37 = toEnum (n + 55)
| otherwise = '#'
\end{code}
\subsection{Specialized Standard}
\begin{code}
compact' :: P.PcSet a => a -> String
compact' ps = if P.modulus ps /= 12 then compact ps
else filter (/= '#') . map f . P.elements $ ps
where f n
| 0 <= n && n <= 9 = toEnum (n + 48)
| n == 10 = 'T'
| n == 11 = 'E'
| otherwise = '#'
\end{code}
\section{Not Exported}
\subsection{Alphanumeric Translators}
\subsubsection{Base 36}
\begin{code}
trBase36 :: String -> [Int]
trBase36 = filter (>= 0) . map f
where f c
| '0' <= c && c <= '9' = fromEnum c 48
| 'A' <= c && c <= 'Z' = fromEnum c 55
| otherwise = 1
\end{code}
\subsubsection{Duodecimal}
\begin{code}
trBase12 :: String -> [Int]
trBase12 = filter (>= 0) . map f
where f c
| '0' <= c && c <= '9' = fromEnum c 48
| c == 'T' = 10
| c == 'E' = 11
| otherwise = 1
\end{code}
% last line Data.PcSets.Compact