| 108 | } |
| 109 | |
| 110 | String |
| 111 | sub(StringView const lhs, StringView const rhs) |
| 112 | { |
| 113 | String result; |
| 114 | |
| 115 | // ensure result length gte rhs length |
| 116 | if (lhs.length() < rhs.length()) { |
| 117 | result.append(rhs.length() - lhs.length(), '0'); |
| 118 | result.append(lhs); |
| 119 | } else { |
| 120 | result = lhs; |
| 121 | } |
| 122 | |
| 123 | PrefetchDebug("sub init result: '%s', rhs: '%.*s'", result.c_str(), (int)rhs.length(), rhs.data()); |
| 124 | |
| 125 | bool borrow = false; |
| 126 | |
| 127 | // top and bottom of subtraction |
| 128 | auto itr = result.rbegin(); |
| 129 | auto itb = rhs.crbegin(); |
| 130 | |
| 131 | while (result.rend() != itr && rhs.crend() != itb) { |
| 132 | int8_t val = tonum(*itr) - tonum(*itb); |
| 133 | if (borrow) { |
| 134 | --val; |
| 135 | } |
| 136 | if (val < 0) { |
| 137 | borrow = true; |
| 138 | val += 10; |
| 139 | } else { |
| 140 | borrow = false; |
| 141 | } |
| 142 | |
| 143 | *itr = tochar(val); |
| 144 | |
| 145 | ++itr; |
| 146 | ++itb; |
| 147 | } |
| 148 | |
| 149 | // keep pushing borrow |
| 150 | while (result.rend() != itr && borrow) { |
| 151 | int8_t val = tonum(*itr) - 1; |
| 152 | if (val < 0) { |
| 153 | borrow = true; |
| 154 | val += 10; |
| 155 | } else { |
| 156 | borrow = false; |
| 157 | } |
| 158 | |
| 159 | *itr = tochar(val); |
| 160 | ++itr; |
| 161 | } |
| 162 | |
| 163 | PrefetchDebug("sub result: '%s', borrow: '%s'", result.c_str(), borrow ? "true" : "false"); |
| 164 | |
| 165 | // if result would have been negative. |
| 166 | if (borrow) { |
| 167 | result = std::string{"0"}; |