1:- module(punary, [
    2	unary/1,
    3    pow/3,
    4    string_unary/2,
    5    unary_string/2,
    6    add/3,
    7    mul/3,
    8    div/4
    9]).   10
   11:- use_module(purity).   12
   13:- multifile purity:pcompare/4.   14
   15purity:pcompare(punary, A, B, C) :- unary_compare(A, B, C).
   16
   17
   18% unary(Unary).
   19%
   20% Unary is a valid unary number
   21%
   22unary(zero).
   23unary(c(Z)) :- unary(Z).
   24
   25% unary_compare(Unary1, Unary2, Comparator).
   26%
   27% Comparator is the different type of Unary1 and Unary2 
   28% Comparator is one of =, <, or >
   29%
   30unary_compare(zero, U2, C) :- unary_compare_z(U2, C).
   31unary_compare(c(Z), U2, C) :- unary_compare_c(U2, c(Z), C).
   32
   33unary_compare_z(zero, =).
   34unary_compare_z(c(_), <).
   35
   36unary_compare_c(zero, _, >).
   37unary_compare_c(c(Z2), c(Z1), C) :- 
   38	unary_compare(Z1, Z2, C).
   39
   40% add(UnaryA, UnaryB, Sum).
   41%
   42% Sum is the value of UnaryA + UnaryB
   43%
   44add(zero, Z, Z).
   45add(c(X), Y, c(Z)) :- 
   46	add(X, Y, Z).
   47
   48% mul(UnaryA, UnaryB, Product)
   49%
   50% Product is the result of UnaryA * UnaryB
   51%
   52mul(zero, _, zero).
   53mul(c(X), Y, R) :- 
   54	add(Y, S, R), 
   55	mul(X, Y, S).
   56
   57% div(Divide, By, Quotient, Remainder)
   58%
   59% division with remainder
   60%
   61div(S, D, Q, R) :-
   62	unary_compare(zero, R, C),
   63	unary_div(C, S, D, Q, R).	
   64
   65unary_div(=, S, D, Q, zero) :- 
   66	mul(D, Q, S).
   67unary_div(>, S, D, Q, zero) :- 
   68	mul(D, Q, S).
   69unary_div(<, S, D, Q, R) :- 	
   70	unary_compare(R, D, <),
   71	add(Is, R, S), 
   72	mul(D, Q, Is).
   73
   74% upow(Unary, Factor, Power)
   75%
   76% Power is Unary^Factor
   77%
   78pow(zero, zero, zero).
   79pow(N, c(zero), N).
   80pow(N, c(c(Z)), R) :-
   81    mul(N, R1, R),
   82    pow(N, c(Z), R1).
   83
   84
   85
   86
   87
   88
   89
   90%
   91% convert 0 - 9 into a unary value
   92%
   93d_to_u(U, N) :-
   94	d_to_u_(['0','1','2','3','4','5','6','7','8','9'], N, U).
   95
   96d_to_u_([A|T], N, U) :-
   97	pdif(pchar, A, N, C),
   98	d_to_u_(C, N, T, U).
   99
  100d_to_u_(false, _, _, zero).
  101d_to_u_(true, N, T, c(Z)) :-
  102	d_to_u_(T, N, Z).
  103
  104%
  105% convert a unary value below 10 into 0 - 9
  106%
  107u_to_d(U, D) :-
  108	u_to_d_(U, ['0','1','2','3','4','5','6','7','8','9'], D).
  109
  110u_to_d_(zero, [D|_], D).
  111u_to_d_(c(Z), [_|T], D) :-
  112	u_to_d_(Z, T, D).
  113
  114% this is required for overlows, but is not a character that is used
  115unary_10( c(c(c(c(c(c(c(c(c(c(zero)))))))))) ).
  116
  117%
  118% Convert strings to unary numbers
  119%
  120% NEEDS TESTING
  121%
  122u_dec_unary_([], _, Sum, Sum).
  123u_dec_unary_([D|T], Mult, Sum, R) :-	
  124	u_to_d(X, D),
  125	mul(Mult, X, Num),
  126	add(Sum, Num, Sum1),
  127	
  128	unary_10(M),	
  129	mul(Mult, M, NewMult),
  130	
  131	u_dec_unary_(T, NewMult, Sum1, R).
  132	
  133% string_unary(String, Unary).
  134%
  135% Unary is the punary version of String
  136%	
  137string_unary(D, C) :- 
  138	reverse(D, DR),
  139	u_dec_unary_(DR, c(zero), zero, C).
  140
  141%
  142% convert unary numbers to strings
  143%
  144% NEEDS TESTING
  145%
  146u_unary_dec(zero, _, []).
  147u_unary_dec(c(Z), Mul, [V|T]) :-
  148	unary_10(U_10),
  149	mul(Mul, U_10, NewMul),
  150	div(c(Z), NewMul, LeftOver, R),
  151	u_to_d(R, V),
  152	
  153	u_unary_dec(LeftOver, NewMul, T).
  154	
  155% unary_string(Unary, String).
  156%
  157% String is the pstring version of Unary
  158%	
  159unary_string(U, S) :- 
  160	u_unary_dec(U, c(zero), R),
  161	reverse(R, S)