1 /++ 2 This module contains functions for converting between different number bases. 3 Like converting to/from hex... 4 +/ 5 module utils.baseconv; 6 7 import utils.misc; 8 import std.math; 9 10 private uinteger toDenary(ushort fromBase, ubyte[] dat){ 11 uinteger r = 0, i = 0; 12 foreach_reverse(cur; dat){ 13 r += pow(fromBase,i)*cur; 14 i++; 15 } 16 return r; 17 } 18 /// 19 unittest{ 20 assert(toDenary(2, [1, 0, 0, 1]) == 9); 21 } 22 23 private ubyte[] fromDenary(ushort toBase, uinteger dat){ 24 ubyte rem; 25 ubyte[] r; 26 while (dat>0){ 27 rem = cast(ubyte)dat%toBase; 28 dat = (dat-rem)/toBase; 29 r = [rem]~r; 30 } 31 32 return r; 33 } 34 /// 35 unittest{ 36 assert(fromDenary(2, 9) == [1, 0, 0, 1]); 37 } 38 39 private string toFormat(ubyte[] ar, char[] rep){ 40 uinteger i; 41 char[] r; 42 r.length = ar.length; 43 for (i=0; i<ar.length; i++){ 44 r[i] = rep[ar[i]]; 45 } 46 return cast(string)r; 47 } 48 /// 49 unittest{ 50 assert([1, 0, 0, 1].toFormat(['0', '1']) == "1001"); 51 } 52 53 private ubyte[] fromFormat(string ar, char[] rep){ 54 uinteger i; 55 ubyte[] r; 56 r.length = ar.length; 57 for (i=0; i<ar.length; i++){ 58 r[i] = cast(ubyte)rep.indexOf(ar[i]); 59 } 60 return r; 61 } 62 /// 63 unittest{ 64 assert("1001".fromFormat(['0', '1']) == [1, 0, 0, 1]); 65 } 66 //exported functions: 67 68 /// Converts from denary to another base 69 /// 70 /// denaryNumber is the denary to convert 71 /// newBaseDigits are the digits of the new base in the ascending order, for hex, this will be `cast(char[])"0123456789ABCDEF"` 72 /// newbaseDigits must have at least 2 digits 73 string denaryToBase(uinteger denaryNumber, char[] newBaseDigits){ 74 assert(newBaseDigits.length >= 2); 75 return toFormat(fromDenary(cast(ushort)newBaseDigits.length, denaryNumber), newBaseDigits); 76 } 77 /// 78 unittest{ 79 assert(denaryToBase(161,cast(char[])"0123456789ABCDEF") == "A1"); 80 } 81 82 /// Converts from any base to denary using the digits of the provided base 83 /// 84 /// baseNumber is the number in another base to convert to denary 85 /// baseDigits is the digits of the base to convert from, in asennding order 86 uinteger baseToDenary(string baseNumber, char[] baseDigits){ 87 assert(baseDigits.length >= 2); 88 return toDenary(cast(ushort)baseDigits.length, fromFormat(baseNumber, baseDigits)); 89 } 90 /// 91 unittest{ 92 assert(baseToDenary("A1", cast(char[])"0123456789ABCDEF") == 161); 93 } 94 95 /// To 'encode' an unsigned integer into anarray of char 96 char[] denaryToChar(uinteger den){ 97 return cast(char[])fromDenary(256,den); 98 } 99 /// 100 unittest{ 101 assert(255.denaryToChar == cast(char[])[255]); 102 } 103 104 /// To decode 'stream of char' into unsigned integer 105 uinteger charToDenary(char[] ch){ 106 return toDenary(256,cast(ubyte[])ch); 107 } 108 /// 109 unittest{ 110 assert(charToDenary(cast(char[])[255]) == 255); 111 } 112 113 /// Converts a hex from string into unsigned integer 114 uinteger hexToDenary(string hex){ 115 return baseToDenary(hex, cast(char[])"0123456789ABCDEF"); 116 } 117 /// 118 unittest{ 119 assert("A1".hexToDenary == 161); 120 } 121 122 /// Converts unsigned integer into hex 123 string denaryToHex(uinteger den){ 124 return denaryToBase(den, cast(char[])"0123456789ABCDEF"); 125 } 126 /// 127 unittest{ 128 assert(162.denaryToHex == "A2"); 129 } 130 131 /// Converts a binary number from string into denary 132 uinteger binaryToDenary(string bin){ 133 return baseToDenary(bin, ['0', '1']); 134 } 135 /// 136 unittest{ 137 assert("1001".binaryToDenary == 9); 138 } 139 140 /// Converts a denary number into a binary number in string 141 string denaryToBinary(uinteger den){ 142 return denaryToBase(den, ['0', '1']); 143 } 144 /// 145 unittest{ 146 assert(9.denaryToBinary == "1001"); 147 }