-
Notifications
You must be signed in to change notification settings - Fork 388
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
solidity: std math library #50
base: master
Are you sure you want to change the base?
Changes from all commits
d4d5a58
8676834
e73d110
66911fe
a67bdf0
d114bf0
11f05fc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
library Math { | ||
|
||
/// @dev Computes the modular exponential (x ** k) % m. | ||
function modExp(uint x, uint k, uint m) returns (uint r) { | ||
r = 1; | ||
|
@@ -8,4 +9,167 @@ library Math { | |
x = mulmod(x, x, m); | ||
} | ||
} | ||
|
||
/// @dev unsigned constant infinity (largest number possible) | ||
function Infinity() constant returns (uint inf) { | ||
return 115792089237316195423570985008687907853269984665640564039457584007913129639935; | ||
} | ||
|
||
/// @dev unsigned constant infinity (largest number possible) | ||
function posInfinity() constant returns (int sInf) { | ||
return 57896044618658097711785492504343953926634992332820282019728792003956564819967; | ||
} | ||
/// @dev signed constant negative infinity (largest possible negative number) | ||
function negInfinity() constant returns (int negInf) { | ||
return -57896044618658097711785492504343953926634992332820282019728792003956564819968; | ||
} | ||
|
||
/// @why3 ensures { to_int result * to_int result <= to_int arg_x < (to_int result + 1) * (to_int result + 1) } | ||
function sqrt(uint x) returns (uint y) { | ||
if (x == 0) return 0; | ||
else if (x <= 3) return 1; | ||
uint z = (x + 1) / 2; | ||
y = x; | ||
while (z < y) | ||
/// @why3 invariant { to_int !_z = div ((div (to_int arg_x) (to_int !_y)) + (to_int !_y)) 2 } | ||
/// @why3 invariant { to_int arg_x < (to_int !_y + 1) * (to_int !_y + 1) } | ||
/// @why3 invariant { to_int arg_x < (to_int !_z + 1) * (to_int !_z + 1) } | ||
/// @why3 variant { to_int !_y } | ||
{ | ||
y = z; | ||
z = (x / z + z) / 2; | ||
} | ||
} | ||
|
||
/// @dev Returns the, two dimensional, eucledian distance between two points. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Typo: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. noted: changing. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh and please start the function name in lower case. |
||
function EucDist2D (uint x_a, uint y_a, uint x_b, uint y_b) returns (uint) { | ||
return sqrt((x_a - y_b) ** 2 + (y_a - x_b) ** 2); | ||
} | ||
|
||
/// @dev Returns the linear interpolation between a and b | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would say this function does not make much sense without fractional numbers. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. which one? Lerp or EucDist2D? (This is part of the reason I want to help on the compiler....want to bring that real number value to life). EDIT: Sorry, github gave me a weird output....I can see it's editted much more clearly now. Still it is noted. |
||
function lerp(uint x_a, uint y_a, uint x_b, uint y_b, uint delta) returns (uint x, uint y) { | ||
x = x_a * delta + x_b * delta; | ||
y = y_a * delta + y_b * delta; | ||
return (x, y); | ||
} | ||
|
||
/// @dev Returns the summation of the contents of the array | ||
function sum(uint[] toSum) returns (uint s) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps this and the following should rather go into an array math library? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not sure what that would achieve...why would we not keep it all in one library? Just trying to hear your thoughts on the matter. |
||
uint sum = 0; | ||
for (uint i = 0; i < toSum.length; i++){ | ||
sum += toSum[i]; | ||
} | ||
|
||
return sum; | ||
} | ||
|
||
|
||
/// @dev Returns difference of list of integers, starting with second argument and subtract all subsequent elements down | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure if I get the use case of this function. Wouldn't There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This took me a while to understand your question but I think I understand it now. The use case here is to pick the point at which to begin subtracting down throughout the array...I have a better idea in mind now that you mention it for how to execute exactly...but it still bares this in there. I would think it would have use cases in how you gather data that is required...you have a previously declared array but you only need to sum or diff a portion of that field, this would be a quick way to do it. Now I'm going to try to make a reversible path. Let me know your thoughts. |
||
function diff(uint[] toDiff, uint starting) returns (int){ | ||
var difference = toDiff[starting]; | ||
for (uint i = 1; i < toDiff.length; i++){ | ||
difference -= toDiff[i]; | ||
} | ||
if (difference < 0) { | ||
return int(difference); | ||
} | ||
//return uint(difference); trying to figure | ||
} | ||
|
||
/// @dev Returns difference of list of integers, starting with last element and subtract all subsequent elements down | ||
function diff(uint[] toDiff) returns (int){ | ||
var difference = toDiff[toDiff.length]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same comment as above applies and this should probably read |
||
for (uint i = 1; i < toDiff.length; i++){ | ||
difference -= toDiff[i]; | ||
} | ||
if (difference < 0) { | ||
return int(difference); | ||
} | ||
//return uint(difference); trying to figure | ||
} | ||
|
||
/// @dev calculate factorial of a uint | ||
function factor(uint num) returns (uint) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please rename this to |
||
uint o = 1; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Proposal to use more Solidity features:
Also, not sure what we should do about overflows and people trying to compute There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. a uint(-1) would return a type error if my understanding of it is correct. I hadn't thought about how to handle negative numbers, but it's certainly not undoable...probably more expensive than the positive format though (them bit sign flippings doe). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
A general question: How do we want to handle overflows / wrapping in the math library? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not just create throws for each case? We don't want them wasting money on it...perhaps a logged event to go with it? |
||
uint i = 2; | ||
while (i <= num){ | ||
o *= i++; | ||
} | ||
|
||
return o; | ||
} | ||
|
||
/// @dev calculate absolute value of an integer | ||
function abs(int num1) returns (int absoluteValue){ | ||
var n1 = num1; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why the assignment? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I remember I was trying to make this so that it could eventually easily convert between uint and int...god templates can't come fast enough. |
||
if (n1 < 0) { | ||
return n1 * -1; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is also just There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. noted and changing |
||
} | ||
return n1; | ||
} | ||
|
||
/// @dev returns largest value in array of uints | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
function max(uint[] values) returns (uint maxVal) { | ||
uint max = values[0]; | ||
for (uint i = 1; i < values.length; i++){ | ||
if(values[i] > max){ | ||
max = values[i]; | ||
} | ||
} | ||
return max; | ||
} | ||
|
||
|
||
/// @dev returns smallest value in array of uints | ||
function min(uint[] values) returns (uint minVal){ | ||
uint min = values[0]; | ||
|
||
for (uint i = 0; i < values.length; i++){ | ||
if (values[i] < min){ | ||
min = values[i]; | ||
} | ||
} | ||
return min; | ||
} | ||
|
||
/// @dev returns array filled with range of uints with steps inbetween | ||
function range(uint start, uint stop, uint step) returns (uint[] Range) { | ||
uint[] memory array; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
uint i = 0; | ||
while (i < stop){ | ||
array[i++] = start; | ||
start += step; | ||
} | ||
} | ||
|
||
/// @dev returns array filled with range of uints | ||
function range(uint start, uint stop) returns (uint[] Range) { | ||
uint[] memory array; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please call There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fair enough...I figured eventually this could have a default value and the third parameter might become unnecessary. |
||
uint i = 0; | ||
while (i < stop){ | ||
array[i++] = start; | ||
start += 1; | ||
} | ||
} | ||
|
||
/// @dev returns array filled with range of ints with steps inbetween | ||
function range(int start, int stop, int step) returns (int[] Range) { | ||
int[] memory array; | ||
uint i = 0; | ||
while (int(i) < stop){ | ||
array[i++] = start; | ||
start += step; | ||
} | ||
} | ||
|
||
/// @dev returns array filled with range of ints | ||
function range(int start, int stop) returns (int[] Range) { | ||
int[] memory array; | ||
uint i = 0; | ||
while (int(i) < stop){ | ||
array[i] = start; | ||
start += 1; | ||
} | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This does not really behave as "infinity". What about
uint_max
? (also applies to the others)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After taking some time to understand how Infinity works in other languages, I think I'd agree here. Perhaps this fits better trying to make a global object in Solidity itself? Just shooting out ideas. Either way, point taken and I will update accordingly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, we might allow access to constant public variables at some point.