Implementation of a Python encription code in PHP or NodeJS - php

I am trying to implement a python encription code based on gzip and crypto library but i dont know the equivalent modules or functions in either php or node js
from Crypto.Cipher import DES, AES
def enclen(p):
return ((16 - p % 16) & 0xF) + p + 4
def rsb(a, b):
return (0 - a + b) & 0xffffffff
def ands(a, b):
return (a & b) & 0xffffffff
def _ror(val, bits, bit_size):
return ((val & (2 ** bit_size - 1)) >> bits % bit_size) | \
(val << (bit_size - (bits % bit_size)) & (2 ** bit_size - 1))
def __ROR4__(a, b):
return _ror(a, b, 32)
def eor(a, b):
return (a ^ b) & 0xffffffff
class Crypto(object):
def __init__(self):
self.key = b'!*ss!_defaul%t54'
self.kl = 0x10
self.sbox0 = bytes.fromhex(
'637C777BF26B6FC53001672BFED7AB76CA82C97DFA5947F0ADD4A2AF9CA472'
'C0B7FD9326363FF7CC34A5E5F171D8311504C723C31896059A071280E2EB27'
'B27509832C1A1B6E5AA0523BD6B329E32F8453D100ED20FCB15B6ACBBE394A'
'4C58CFD0EFAAFB434D338545F9027F503C9FA851A3408F929D38F5BCB6DA21'
'10FFF3D2CD0C13EC5F974417C4A77E3D645D197360814FDC222A908846EEB8'
'14DE5E0BDBE0323A0A4906245CC2D3AC629195E479E7C8376D8DD54EA96C56'
'F4EA657AAE08BA78252E1CA6B4C6E8DD741F4BBD8B8A703EB5664803F60E61'
'3557B986C11D9EE1F8981169D98E949B1E87E9CE5528DF8CA1890DBFE64268'
'41992D0FB054BB16')
self.plen = 0
def crypt(self, payload):
if not isinstance(payload, bytes):
payload = payload.encode('utf8')
self.plen = len(payload)
i = 0
r = [00] * 16
while i < self.kl:
a = self.key[i]
r[i] = self.sbox0[a]
i += 1
t = int.from_bytes(r[:4], 'big')
r[:4] = int.to_bytes(t, 4, 'little')
t = int.from_bytes(r[4:8], 'big')
r[4:8] = int.to_bytes(t, 4, 'little')
t = int.from_bytes(r[8:12], 'big')
r[8:12] = int.to_bytes(t, 4, 'little')
t = int.from_bytes(r[12:16], 'big')
r[12:16] = int.to_bytes(t, 4, 'little')
b = rsb(self.plen, 0)
b = ands(b, 0xf)
c = b + self.plen + 4
result = [00] * enclen(self.plen)
result[0] = 0x74
result[1] = 0x63
result[2] = 0x02
result[3] = b
result[4:len(payload) + 4] = payload
i = 4
while i != c:
a = result[i]
result[i] = self.sbox0[a]
i += 1
a = c - 4
b = 0
a = a >> 4
d = 4
while b < a:
c = int.from_bytes(result[d:d + 4], 'big')
e = int.from_bytes(r[:4], 'little')
c ^= e
result[d:d + 4] = int.to_bytes(c, 4, 'big')
c = int.from_bytes(result[d + 4:d + 8], 'big')
e = int.from_bytes(r[4:8], 'little')
c = eor(e, __ROR4__(c, 24))
result[d + 4:d + 8] = int.to_bytes(c, 4, 'big')
c = int.from_bytes(result[d + 8:d + 12], 'big')
e = int.from_bytes(r[8:12], 'little')
c = eor(e, __ROR4__(c, 16))
result[d + 8:d + 12] = int.to_bytes(c, 4, 'big')
c = int.from_bytes(result[d + 12:d + 16], 'big')
e = int.from_bytes(r[12:16], 'little')
c = eor(e, __ROR4__(c, 8))
result[d + 12:d + 16] = int.to_bytes(c, 4, 'big')
b += 1
d += 0x10
return bytes(result)
I dont have much idea what really goes behind this code some byte size operations but i dont know what exactly happens
Either nodejs or php equivalent of this code or any idea to how to implement it in those lang or if those languages are supported this kind of operations I dont know

Node.js has really good modules that can handle compression and encryption.
Crypto for cryptography related operations. It supports many algorithms to encrypt/hash stuff
Zlib for compression. Supports algorithms like gzip, deflate, zip, etc...
The docs also include examples on how to use these modules, so make sure to check them

Related

Write a program to get N number of positive non-zero integers, so that the sum and product of these numbers are equal

Let's say, the numbers are A, B, C, D and E.
So, what I want is-
A + B + C + D + E = A * B * C * D * E
I want to write a program (preferably PHP) that solves it.
Note: The numbers can be repeated. I mean, we can have A, B, B, D and E for example.
Yes. I solved it myself.
The answer is number of numbers, 2 and (number of numbers - 2) of 1s!
Say, if we consider 5 numbers, they'll be 5, 2, 1, 1 and 1.
If we consider 6 numbers, they'll be 6, 2, 1, 1, 1 and 1.
Here is php program-
<?php
$n = 5;
$numbers = array();
$numbers[] = $n;
$numbers[] = 2;
for($i=1; $i<=($n-2); $i++){
$numbers[] = 1;
}
$numbers array will contain the numbers!

How to convert REAL48 float into a double

I am connecting to a Pervasive SQL database which splits some data over two fields. DOUBLE fields are actually split into fieldName_1 and fieldName_2 where _1 is a 2 byte int and _2 is a 4 byte int.
I want to take these values and convert them using PHP into a usable value.
I have some example code to do the conversion, but it is written in Delphi which I do not understand:
{ Reconstitutes a SmallInt and LongInt that form }
{ a Real into a double. }
Function EntConvertInts (Const Int2 : SmallInt;
Const Int4 : LongInt) : Double; StdCall;
Var
TheRealArray : Array [1..6] Of Char;
TheReal : Real;
Begin
Move (Int2, TheRealArray[1], 2);
Move (Int4, TheRealArray[3], 4);
Move (TheRealArray[1], TheReal, 6);
Result := TheReal;
End;
Some data [fieldName_1,fieldName_2]
[132, 805306368] -> this should be 11
[132, 1073741824] -> this should be 12
I don't understand the logic enough to be able to port this into PHP. Any help would be most appreciated. Thanks
EDIT.
This is the C code that they provided, showing sign/exponent:
double real_to_double (real r)
/* takes Pascal real, return C double */
{
union doublearray da;
unsigned x;
x = r[0] & 0x00FF; /* Real biased exponent in x */
/* when exponent is 0, value is 0.0 */
if (x == 0)
da.d = 0.0;
else {
da.a[3] = ((x + 894) << 4) | /* adjust exponent bias */
(r[2] & 0x8000) | /* sign bit */
((r[2] & 0x7800) >> 11); /* begin significand */
da.a[2] = (r[2] << 5) | /* continue shifting significand */
(r[1] >> 11);
da.a[1] = (r[1] << 5) |
(r[0] >> 11);
da.a[0] = (r[0] & 0xFF00) << 5; /* mask real's exponent */
}
return da.d;
}
Adding this as another answer because I've finally figured this out. Here is PHP code which will convert the values. It has to be manually calculated because PHP does not know how to unpack a Real48 (non standard). Explanation in comments below.
function BiIntToReal48($f1, $f2){
$x = str_pad(decbin($f1), 16, "0", STR_PAD_LEFT);
$y = str_pad(decbin($f2), 32, "0", STR_PAD_LEFT);
//full Real48 binary string
$real48 = $y . $x;
//Real48 format is V = (-1)^s * 1.f * 2^(exp-129)
// rightmost eight bits are the exponent (bits 40-->47)
// subtract 129 to get the final value
$exp = (bindec(substr($real48, -8)) - 129);
//Sign bit is leftmost bit (bit[0])
$sign =$real48[0];
//Now work through the significand - bits are fractional binary
//(1/2s place, 1/4s place, 1/8ths place, etc)
// bits 1-->39
// significand is always 1.fffffffff... etc so start with 1.0
$sgf = "1.0";
for ($i = 1; $i <= 39; $i++){
if ($real48[$i] == 1){
$sgf = $sgf + pow(2,-$i);
}
}
//final calculation
$final = pow(-1, $sign) * $sgf * pow(2,$exp);
return($final);
}
$field_1 = 132;
$field_2 = 805306368;
$ConvVal = BiIntToReal48($field_1, $field_2);
// ^ gives $ConvVal = 11, qed
I've been working on this issue for about a week now trying to get it sorted out for our organisation.
Our Finance dept use IRIS Exchequer and we need to get costs out. Using the above PHP code, I managed to get it working in Excel VBA with the following code (includes dependent functions). If not properly attributed below, I got all the long dec to bin functions from www.sulprobil.com. If you copy and paste the following code block into a Module you can reference my ExchequerDouble function from a cell.
Before I continue, I have to point out one error in the C/PHP code above. If you look at the Significand loops:
C/PHP: Significand = Significand + 2 ^ (-i)
VBA: Significand = Significand + 2 ^ (1 - i)
I noticed during testing that the answers were very close but often incorrect. Drilling further down I narrowed it down to the Significand. It might be a problem with translating the code from one language/methodology to another, or may have simply been a typo, but adding that (1 - i) made all the difference.
Function ExchequerDouble(Val1 As Integer, Val2 As Long) As Double
Dim Int2 As String
Dim Int4 As String
Dim Real48 As String
Dim Exponent As String
Dim Sign As String
Dim Significand As String
'Convert each value to binary
Int2 = LongDec2Bin(Val1, 16, True)
Int4 = LongDec2Bin(Val2, 32, True)
'Concatenate the binary strings to produce a 48 bit "Real"
Real48 = Int4 & Int2
'Calculate the exponent
Exponent = LongBin2Dec(Right(Real48, 8)) - 129
'Calculate the sign
Sign = Left(Real48, 1)
'Begin calculation of Significand
Significand = "1.0"
For i = 2 To 40
If Mid(Real48, i, 1) = "1" Then
Significand = Significand + 2 ^ (1 - i)
End If
Next i
ExchequerDouble = CDbl(((-1) ^ Sign) * Significand * (2 ^ Exponent))
End Function
Function LongDec2Bin(ByVal sDecimal As String, Optional lBits As Long = 32, Optional blZeroize As Boolean = False) As String
'Transforms decimal number into binary number.
'Reverse("moc.LiborPlus.www") V0.3 P3 16-Jan-2011
Dim sDec As String
Dim sFrac As String
Dim sD As String 'Internal temp variable to represent decimal
Dim sB As String
Dim blNeg As Boolean
Dim i As Long
Dim lPosDec As Long
Dim lLenBinInt As Long
lPosDec = InStr(sDecimal, Application.DecimalSeparator)
If lPosDec > 0 Then
If Left(sDecimal, 1) = "-" Then 'negative fractions later..
LongDec2Bin = CVErr(xlErrValue)
Exit Function
End If
sDec = Left(sDecimal, lPosDec - 1)
sFrac = Right(sDecimal, Len(sDecimal) - lPosDec)
lPosDec = Len(sFrac)
Else
sDec = sDecimal
sFrac = ""
End If
sB = ""
If Left(sDec, 1) = "-" Then
blNeg = True
sD = Right(sDec, Len(sDec) - 1)
Else
blNeg = False
sD = sDec
End If
Do While Len(sD) > 0
Select Case Right(sD, 1)
Case "0", "2", "4", "6", "8"
sB = "0" & sB
Case "1", "3", "5", "7", "9"
sB = "1" & sB
Case Else
LongDec2Bin = CVErr(xlErrValue)
Exit Function
End Select
sD = sbDivBy2(sD, True)
If sD = "0" Then
Exit Do
End If
Loop
If blNeg And sB <> "1" & String(lBits - 1, "0") Then
sB = sbBinNeg(sB, lBits)
End If
'Test whether string representation is in range and correct
'If not, the user has to increase lbits
lLenBinInt = Len(sB)
If lLenBinInt > lBits Then
LongDec2Bin = CVErr(x1ErrNum)
Exit Function
Else
If (Len(sB) = lBits) And (Left(sB, 1) <> -blNeg & "") Then
LongDec2Bin = CVErr(xlErrNum)
Exit Function
End If
End If
If blZeroize Then sB = Right(String(lBits, "0") & sB, lBits)
If lPosDec > 0 And lLenBinInt + 1 < lBits Then
sB = sB & Application.DecimalSeparator
i = 1
Do While i + lLenBinInt < lBits
sFrac = sbDecAdd(sFrac, sFrac) 'Double fractional part
If Len(sFrac) > lPosDec Then
sB = sB & "1"
sFrac = Right(sFrac, lPosDec)
If sFrac = String(lPosDec, "0") Then
Exit Do
End If
Else
sB = sB & "0"
End If
i = i + 1
Loop
LongDec2Bin = sB
Else
LongDec2Bin = sB
End If
End Function
Function LongBin2Dec(sBinary As String, Optional lBits As Long = 32) As String
'Transforms binary number into decimal number.
'Reverse("moc.LiborPlus.www") V0.3 PB 16-Jan-2011
Dim sBin As String
Dim sB As String
Dim sFrac As String
Dim sD As String
Dim sR As String
Dim blNeg As Boolean
Dim i As Long
Dim lPosDec As Long
lPosDec = InStr(sBinary, Application.DecimalSeparator)
If lPosDec > 0 Then
If (Left(sBinary, 1) = "1") And Len(sBin) >= lBits Then 'negative fractions later..
LongBin2Dec = CVErr(xlErrVa1ue)
Exit Function
End If
sBin = Left(sBinary, lPosDec - 1)
sFrac = Right(sBinary, Len(sBinary) - lPosDec)
lPosDec = Len(sFrac)
Else
sBin = sBinary
sFrac = ""
End If
Select Case Sgn(Len(sBin) - lBits)
Case 1
LongBin2Dec = CVErr(x1ErrNum)
Exit Function
Case 0
If Left(sBin, 1) = "1" Then
sB = sbBinNeg(sBin, lBits)
blNeg = True
Else
sB = sBin
blNeg = False
End If
Case -1
sB = sBin
blNeg = False
End Select
sD = "1"
sR = "0"
For i = Len(sB) To 1 Step -1
Select Case Mid(sB, i, 1)
Case "1"
sR = sbDecAdd(sR, sD)
Case "0"
'Do Nothing
Case Else
LongBin2Dec = CVErr(xlErrNum)
Exit Function
End Select
sD = sbDecAdd(sD, sD) 'Double sd
Next i
If lPosDec > 0 Then 'now the fraction
sD = "0.5"
For i = 1 To lPosDec
If Mid(sFrac, i, 1) = "1" Then
sR = sbDecAdd(sR, sD)
End If
sD = sbDivBy2(sD, False)
Next i
End If
If blNeg Then
LongBin2Dec = "-" & sR
Else
LongBin2Dec = sR
End If
End Function
Function sbDivBy2(sDecimal As String, blInt As Boolean) As String
'Divide sDecimal by two, blInt = TRUE returns integer only
'Reverse("moc.LiborPlus.www") V0.3 PB 16-Jan-2011
Dim i As Long
Dim lPosDec As Long
Dim sDec As String
Dim sD As String
Dim lCarry As Long
If Not blInt Then
lPosDec = InStr(sDecimal, Application.DecimalSeparator)
If lPosDec > 0 Then
'Without decimal point lPosDec already defines location of decimal point
sDec = Left(sDecimal, lPosDec - 1) & Right(sDecimal, Len(sDecimal) - lPosDec)
Else
sDec = sDecimal
lPosDec = Len(sDec) + 1 'Location of decimal point
End If
If ((1 * Right(sDec, 1)) Mod 2) = 1 Then
sDec = sDec & "0" 'Append zero so that integer algorithm calculates division exactly
End If
Else
sDec = sDecimal
End If
lCarry = 0
For i = 1 To Len(sDec)
sD = sD & Int((lCarry * 10 + Mid(sDec, i, 1)) / 2)
lCarry = (lCarry * 10 + Mid(sDec, i, 1)) Mod 2
Next i
If Not blInt Then
If Right(sD, Len(sD) - lPosDec + 1) <> String(Len(sD) - lPosDec + 1, "0") Then
'frac part Is non - zero
i = Len(sD)
Do While Mid(sD, i, 1) = "0"
i = i - 1 'Skip trailing zeros
Loop
'Insert decimal point again
sD = Left(sD, lPosDec - 1) _
& Application.DecimalSeparator & Mid(sD, lPosDec, i - lPosDec + 1)
End If
End If
i = 1
Do While i < Len(sD)
If Mid(sD, i, 1) = "0" Then
i = i + 1
Else
Exit Do
End If
Loop
If Mid(sD, i, 1) = Application.DecimalSeparator Then
i = i - 1
End If
sbDivBy2 = Right(sD, Len(sD) - i + 1)
End Function
Function sbBinNeg(sBin As String, Optional lBits As Long = 32) As String
'Negate sBin: take the 2's-complement, then add one
'Reverse("moc.LiborPlus.www") V0.3 PB 16-Jan-2011
Dim i As Long
Dim sB As String
If Len(sBin) > lBits Or sBin = "1" & String(lBits - 1, "0") Then
sbBinNeg = CVErr(xlErrValue)
Exit Function
End If
'Calculate 2 's-complement
For i = Len(sBin) To 1 Step -1
Select Case Mid(sBin, i, 1)
Case "1"
sB = "0" & sB
Case "0"
sB = "1" & sB
Case Else
sbBinNeg = CVErr(xlErrValue)
Exit Function
End Select
Next i
sB = String(lBits - Len(sBin), "1") & sB
'Now add 1
i = lBits
Do While i > 0
If Mid(sB, i, 1) = "1" Then
Mid(sB, i, 1) = "0"
i = i - 1
Else
Mid(sB, i, 1) = "1"
i = 0
End If
Loop
'Finally strip leading zeros
i = InStr(sB, "1")
If i = 0 Then
sbBinNeg = "0"
Else
sbBinNeg = Right(sB, Len(sB) - i + 1)
End If
End Function
Function sbDecAdd(sOne As String, sTwo As String) As String
'Sum up two string decimals.
'Reverse("moc.LiborPlus.www") V0.3 PB 16-Jan-2011
Dim lStrLen As Long
Dim s1 As String
Dim s2 As String
Dim sA As String
Dim sB As String
Dim sR As String
Dim d As Long
Dim lCarry As Long
Dim lPosDec1 As Long
Dim lPosDec2 As Long
Dim sF1 As String
Dim sF2 As String
lPosDec1 = InStr(sOne, Application.DecimalSeparator)
If lPosDec1 > 0 Then
s1 = Left(sOne, lPosDec1 - 1)
sF1 = Right(sOne, Len(sOne) - lPosDec1)
lPosDec1 = Len(sF1)
Else
s1 = sOne
sF1 = ""
End If
lPosDec2 = InStr(sTwo, Application.DecimalSeparator)
If lPosDec2 > 0 Then
s2 = Left(sTwo, lPosDec2 - 1)
sF2 = Right(sTwo, Len(sTwo) - lPosDec2)
lPosDec2 = Len(sF2)
Else
s2 = sTwo
sF2 = ""
End If
If lPosDec1 + lPosDec2 > 0 Then
If lPosDecl > lPosDec2 Then
sF2 = sF2 & String(lPosDec1 - lPosDec2, "0")
Else
sF1 = sFl & String(lPosDec2 - lPosDec1, "0")
lPosDec1 = lPosDec2
End If
sF1 = sbDecAdd(sF1, sF2) 'Add fractions as integer numbers
If Len(sF1) > lPosDecl Then
lCarry = 1
sF1 = Right(sF1, lPosDec1)
Else
lCarry = 0
End If
Do While lPosDec1 > 0
If Mid(sF1, lPosDec1, 1) <> "0" Then
Exit Do
End If
lPosDec1 = lPosDec1 - 1
Loop
sF1 = Left(sF1, lPosDec1)
Else
lCarry = 0
End If
lStrLen = Len(sl)
If lStrLen < Len(s2) Then
lStrLen = Len(s2)
sA = String(lStrLen - Len(s1), "0") & s1
sB = s2
Else
sA = s1
sB = String(lStrLen - Len(s2), "0") & s2
End If
Do While lStrLen > 0
d = 0 + Mid(sA, lStrLen, 1) + Mid(sB, lStrLen, 1) + lCarry
If d > 9 Then
sR = (d - 10) & sR
lCarry = 1
Else
sR = d & sR
lCarry = 0
End If
lStrLen = lStrLen - 1
Loop
If lCarry > 0 Then
sR = lCarry & sR
End If
If lPosDec1 > 0 Then
sbDecAdd = sR & Application.DecimalSeparator & sF1
Else
sbDecAdd = sR
End If
End Function
This code works, but sometimes (around 1% of my test data) you end up a couple pennies out compared to Iris' EntDouble function from the Excel Addin. I'll attribute this to precision, unless someone can figure it out.
Ultimately getting this working in VBA was my proof of concept to check everything worked. The intended platform for this functionality was SQL Server. If you have your Exchequer DB linked to a SQL Server you should be able to run this function directly against the data from the Pervasive DB. In my case, we are going to dump out the last 2.5 years worth of transaction data into a static table on SQL Server, but we're only working with this data once a year so it's not an issue. The following two functions should sort you out. In terms of precision, they are equivalent to the VBA code above with some being out by a couple pennies sometimes, but it seems 99% of the time it's exactly the same. We use SQL Server 2000 so there are some things that can probably be optimised (Varchar(MAX) for one) for newer versions but ultimately this should work fine as far as I know.
CREATE FUNCTION dbo.FUNCTION_Exchequer_Double
(
#Val1 AS SmallInt,
#Val2 AS BigInt
)
RETURNS Decimal(38, 10)
AS
BEGIN
-- Declare and set decoy variables
DECLARE #Val1_Decoy AS SmallInt
DECLARE #Val2_Decoy AS BigInt
SELECT #Val1_Decoy = #Val1,
#Val2_Decoy = #Val2
-- Declare other variables
DECLARE #Val1_Binary AS Varchar(16)
DECLARE #Val2_Binary AS Varchar(32)
DECLARE #Real48_Binary AS Varchar(48)
DECLARE #Real48_Decimal AS BigInt
DECLARE #Exponent AS Int
DECLARE #Sign AS Bit
DECLARE #Significand AS Decimal(19, 10)
DECLARE #BitCounter AS Int
DECLARE #Two As Decimal(38, 10) -- Saves us casting inline in the code
DECLARE #Output AS Decimal(38, 10)
-- Convert values into two binary strings of the correct length (Val1 = 16 bits, Val2 = 32 bits)
SELECT #Val1_Binary = Replicate(0, 16 - Len(dbo.FUNCTION_Convert_To_Base(Cast(#Val1_Decoy AS Binary(2)), 2)))
+ dbo.FUNCTION_Convert_To_Base(Cast(#Val1_Decoy AS Binary(2)), 2),
#Val2_Binary = Replicate(0, 32 - Len(dbo.FUNCTION_Convert_To_Base(Cast(#Val2_Decoy AS Binary(4)), 2)))
+ dbo.FUNCTION_Convert_To_Base(Cast(#Val2_Decoy AS Binary(4)), 2)
-- Find the decimal value of the new 48 bit number and its binary value
SELECT #Real48_Decimal = #Val2_Decoy * Power(2, 16) + #Val1_Decoy
SELECT #Real48_Binary = #Val2_Binary + #Val1_Binary
-- Determine the Exponent (takes the first 8 bits and subtracts 129)
SELECT #Exponent = Cast(#Real48_Decimal AS Binary(1)) - 129
-- Determine the Sign
SELECT #Sign = Left(#Real48_Binary, 1)
-- A bit of setup for determining the Significand
SELECT #Significand = 1,
#Two = 2,
#BitCounter = 2
-- Determine the Significand
WHILE #BitCounter <= 40
BEGIN
IF Substring(#Real48_Binary, #BitCounter, 1) Like '1'
BEGIN
SELECT #Significand = #Significand + Power(#Two, 1 - #BitCounter)
END
SELECT #BitCounter = #BitCounter + 1
END
SELECT #Output = Power(-1, #Sign) * #Significand * Power(#Two, #Exponent)
-- Return the output
RETURN #Output
END
CREATE FUNCTION dbo.FUNCTION_Convert_To_Base
(
#value AS BigInt,
#base AS Int
)
RETURNS Varchar(8000)
AS
BEGIN
-- Code from http://dpatrickcaldwell.blogspot.co.uk/2009/05/converting-decimal-to-hexadecimal-with.html
-- some variables
DECLARE #characters Char(36)
DECLARE #result Varchar(8000)
-- the encoding string and the default result
SELECT #characters = '0123456789abcdefghijklmnopqrstuvwxyz',
#result = ''
-- make sure it's something we can encode. you can't have
-- base 1, but if we extended the length of our #character
-- string, we could have greater than base 36
IF #value < 0 Or #base < 2 Or #base > 36
RETURN Null
-- until the value is completely converted, get the modulus
-- of the value and prepend it to the result string. then
-- devide the value by the base and truncate the remainder
WHILE #value > 0
SELECT #result = Substring(#characters, #value % #base + 1, 1) + #result,
#value = #value / #base
-- return our results
RETURN #result
END
Feel free to use either my VBA or SQL code. The truly hard work was done by whoever converted it to PHP above. If anyone finds any way of improving anything please do let me know so we can make this code as perfect as possible.
Thanks!
Delphi's Move command is used for moving blocks of memory from one place to another. This looks like old Delphi code - the Real type is obsolete, replaced with Double (edit Real48 replaces 6-byte Real), and the Byte type is probably a better one to use than Char. Both are bytes, but Char is more meant for single byte characters (ascii). What this code is doing is:
1) Declare an array of Char(could use Byte here) which is six bytes in length. Also declare a Real (edit now Real48 type) to store the converted value.
TheRealArray : Array [1..6] Of Char;
TheReal : Real;
2) Move the two-byte Int value TO TheRealArray - start at index1 and move 2 bytes of data (ie: all of Int2, a SmallInt (16-bits)). Do the same with Int4 and start it at index [3], 4 bytes long.
Move (Int2, TheRealArray[1], 2);
Move (Int4, TheRealArray[3], 4);
if you started with (picture, not code)
Int2 = [2_byte0][2_byte1]
Int4 = [4_byte0][4_byte1][4_byte2][4_byte3]
you would have:
TheRealArray = [2_byte0][2_byte1][4_byte0][4_byte1][4_byte2][4_byte3]
The final move command copies this array to the memory location of TheReal, which is a real (6-byte float) type. It starts at index1 of the array, copies it to TheReal, and copies a total of six bytes (ie:the whole thing).
Move (TheRealArray[1], TheReal, 6);
Assuming that the data stored in Int2 and Int4, when concatenated like this, produce a properly formatted Real48 then you end up with TheReal holding the data in the proper format.
in PHP strings are fundamentally byte arrays (like Array[1..6] of Char in Delphi) so you could do the something similar using unpack() to convert to float.
Just spinning on J...'s answer.
Utilizing a variant record the code is somewhat simplified :
Function EntConvertInts (Const Int2 : SmallInt;
Const Int4 : LongInt) : Double; StdCall;
Type
TReal48PlaceHolder = record
case boolean of
true : (theRealArray : array [1..6] of byte);
false : (r48 : Real48);
end;
Var
R48Rec : TReal48PlaceHolder;
Begin
Move (Int2, R48Rec.theRealArray[1], 2);
Move (Int4, R48Rec.theRealArray[3], 4);
Result := R48Rec.r48;
End;
var
r : Double;
begin
r:= EntConvertInts(132,805306368);
WriteLn(r); // Should be 11
r:= EntConvertInts(141,1163395072);
WriteLn(r); // Should be 6315
ReadLn;
end.
That is nor answer in "PHP code" sense. I just wanted to warn any person who maybe would find this code by Delphi tag.
THAT WAS NOT DELPHI !!!
It is old Turbo Pascal code. Okay, maybe 16-bit Delphi 1, which really was TP on steroids.
Don't try this code on 32-bit Delphi, at least not before replacing Char and Real types that changed. Both those types are changed from Turbo Pascal times, especially 6-byte Real which never was hardware FPU-compatible!
Probably FreePascal can bear vanilla TurboPascal code if settled to proper mode, but better still use Delphi mode and updated code.
http://docwiki.embarcadero.com/Libraries/en/System.Real
http://docwiki.embarcadero.com/Libraries/en/System.Real48
http://docwiki.embarcadero.com/RADStudio/en/Real48_compatibility_(Delphi)
One should also ensure that SmallInt type is 16-bit integer (int16) and LongInt is 32-bit(int32). This seemes to hold for 16-bit, 32-bit and 64-bit Delphi compilers, yet probably may change in other Pascal implementations.
http://docwiki.embarcadero.com/Libraries/en/System.Longint
http://docwiki.embarcadero.com/Libraries/en/System.Smallint
Below i try to modify code compatible with modern Delphi. I was not able to test it though.
Hopefully that might help someone someday covert some similat old type-casting TurboPascal code to newer flavours.
This code is directly following original one, yet more compatible, concise and fast.
{ Reconstitutes a SmallInt and LongInt that form }
{ a Real into a double. }
Function EntConvertInts (Const Int2 : SmallInt;
Const Int4 : LongInt) : Double;
(* StdCall; - only needed for non-Pascal DLLs *)
Var
TheRealArray : Packed Array [1..6] Of Byte; //AnsiChar may suffice too
TheReal : Real48 absolute TheRealArray;
TheInt2 : SmallInt absolute TheRealArray[1];
TheInt4 : LongInt absolute TheRealArray[3];
Begin
Assert(SizeOf(TheInt2) = 2);
Assert(SizeOf(TheInt4) = 2);
Assert(SizeOf(TheReal) = 6);
TheInt2 := Int2; (* Move (Int2, TheRealArray[1], 2); *)
TheInt4 := Int4; (* Move (Int4, TheRealArray[3], 4); *)
(* Move (TheRealArray[1], TheReal, 6); *)
Result := TheReal;
End;
This code is directly using native Turbo Pascal features tagless variant record
{ Reconstitutes a SmallInt and LongInt that form }
{ a Real into a double. }
Function EntConvertInts (Const Int2 : SmallInt;
Const Int4 : LongInt) : Double;
(* StdCall; - only needed for non-Pascal DLLs *)
Var
Value : Packed Record
Case Byte of
0: (TheReal: Real48);
1: (Packed Record TheInt2: SmallInt;
TheInt4: LongInt; end; );
end;
Begin
Assert(SizeOf(Value.TheInt2) = 2);
Assert(SizeOf(Value.TheInt4) = 2);
Assert(SizeOf(Value.TheReal) = 6);
Value.TheInt2 := Int2; (* Move (Int2, TheRealArray[1], 2); *)
Value.TheInt4 := Int4; (* Move (Int4, TheRealArray[3], 4); *)
(* Move (TheRealArray[1], TheReal, 6); *)
Result := Value.TheReal;
End;

How can I rewrite this JavaScript to PHP?

Following are some individual JavaScript statements from a block of java-script code. I want to convert this JavaScript code in PHP so that I can execute it server-side. In the following snippet, there are some operators used, such as >>, >>>, ~, ^, <<, <<<, etc.
How can I translate these JavaScript functions to PHP?
function core_enc(K, F) {
K[F >> 5] |= 128 << ((F) %32);
K[(((F + 64) >>> 9) << 4) + 14] = F;
}
function enc_ff(C, B, G, F, A, E, D) {
return enc_cmn((B & G) | ((~B) & F), C, B, A, E, D);
}
function enc_hh(C, B, G, F, A, E, D) {
return enc_cmn(B ^ G ^ F, C, B, A, E, D);
}
function safe_add(A, D) {
var C = (A & 65535) + (D & 65535);
var B = (A >> 16) + (D >> 16) + (C >> 16);
return (B << 16) | (C & 65535);
}
function bit_rol(A, B) {
return (A << B) | (A >>> (32 - B));
}
That would be the exact same operators. See http://codepad.org/b5uZPCu4 for a demo.
The shift operators >> and << can be directly translated, as well as other basic bitwise operations such as | (or), & (and), ^ (xor), ~ (not), etcetera. PHP arrays also work in the same fashion, and the functions have about the same syntax. Your JavaScript code should work perfectly in PHP with minimal changes (e.g. variableName becomes $variableName, you remove var, and >>> doesn't work in PHP.)
Edit: If this is actually code for MD5 or something, PHP provides the convenient function md5 to do that for you.

Python equivalent of PHP's MCRYPT_RIJNDAEL_256 CBC

I need a Python implementation of this function - I want to use it on appengine.
I am not so good in Python so please help.
function encrypt($data) {
return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256 ,'oqufXQ(?bc=6_hR2I3sMZChDpb6dDlw4', $data , MCRYPT_MODE_CBC, utf8_encode('fOaiIOkD8*9Xeu_s4_bb87Ox_UG+D9GA')));
}
Have you tried this one (also included below)? It implements the Rijndael block cipher for 16, 24 or 32 bytes. You are using the 256 bit (32 byte) version of the block cipher.
"""
A pure python (slow) implementation of rijndael with a decent interface
To include -
from rijndael import rijndael
To do a key setup -
r = rijndael(key, block_size = 16)
key must be a string of length 16, 24, or 32
blocksize must be 16, 24, or 32. Default is 16
To use -
ciphertext = r.encrypt(plaintext)
plaintext = r.decrypt(ciphertext)
If any strings are of the wrong length a ValueError is thrown
"""
# ported from the Java reference code by Bram Cohen, April 2001
# this code is public domain, unless someone makes
# an intellectual property claim against the reference
# code, in which case it can be made public domain by
# deleting all the comments and renaming all the variables
import copy
import string
shifts = [[[0, 0], [1, 3], [2, 2], [3, 1]],
[[0, 0], [1, 5], [2, 4], [3, 3]],
[[0, 0], [1, 7], [3, 5], [4, 4]]]
# [keysize][block_size]
num_rounds = {16: {16: 10, 24: 12, 32: 14}, 24: {16: 12, 24: 12, 32: 14}, 32: {16: 14, 24: 14, 32: 14}}
A = [[1, 1, 1, 1, 1, 0, 0, 0],
[0, 1, 1, 1, 1, 1, 0, 0],
[0, 0, 1, 1, 1, 1, 1, 0],
[0, 0, 0, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 1, 1, 1, 1],
[1, 1, 0, 0, 0, 1, 1, 1],
[1, 1, 1, 0, 0, 0, 1, 1],
[1, 1, 1, 1, 0, 0, 0, 1]]
# produce log and alog tables, needed for multiplying in the
# field GF(2^m) (generator = 3)
alog = [1]
for i in range(255):
j = (alog[-1] << 1) ^ alog[-1]
if j & 0x100 != 0:
j ^= 0x11B
alog.append(j)
log = [0] * 256
for i in range(1, 255):
log[alog[i]] = i
# multiply two elements of GF(2^m)
def mul(a, b):
if a == 0 or b == 0:
return 0
return alog[(log[a & 0xFF] + log[b & 0xFF]) % 255]
# substitution box based on F^{-1}(x)
box = [[0] * 8 for i in range(256)]
box[1][7] = 1
for i in range(2, 256):
j = alog[255 - log[i]]
for t in range(8):
box[i][t] = (j >> (7 - t)) & 0x01
B = [0, 1, 1, 0, 0, 0, 1, 1]
# affine transform: box[i] <- B + A*box[i]
cox = [[0] * 8 for i in range(256)]
for i in range(256):
for t in range(8):
cox[i][t] = B[t]
for j in range(8):
cox[i][t] ^= A[t][j] * box[i][j]
# S-boxes and inverse S-boxes
S = [0] * 256
Si = [0] * 256
for i in range(256):
S[i] = cox[i][0] << 7
for t in range(1, 8):
S[i] ^= cox[i][t] << (7-t)
Si[S[i] & 0xFF] = i
# T-boxes
G = [[2, 1, 1, 3],
[3, 2, 1, 1],
[1, 3, 2, 1],
[1, 1, 3, 2]]
AA = [[0] * 8 for i in range(4)]
for i in range(4):
for j in range(4):
AA[i][j] = G[i][j]
AA[i][i+4] = 1
for i in range(4):
pivot = AA[i][i]
if pivot == 0:
t = i + 1
while AA[t][i] == 0 and t < 4:
t += 1
assert t != 4, 'G matrix must be invertible'
for j in range(8):
AA[i][j], AA[t][j] = AA[t][j], AA[i][j]
pivot = AA[i][i]
for j in range(8):
if AA[i][j] != 0:
AA[i][j] = alog[(255 + log[AA[i][j] & 0xFF] - log[pivot & 0xFF]) % 255]
for t in range(4):
if i != t:
for j in range(i+1, 8):
AA[t][j] ^= mul(AA[i][j], AA[t][i])
AA[t][i] = 0
iG = [[0] * 4 for i in range(4)]
for i in range(4):
for j in range(4):
iG[i][j] = AA[i][j + 4]
def mul4(a, bs):
if a == 0:
return 0
r = 0
for b in bs:
r <<= 8
if b != 0:
r = r | mul(a, b)
return r
T1 = []
T2 = []
T3 = []
T4 = []
T5 = []
T6 = []
T7 = []
T8 = []
U1 = []
U2 = []
U3 = []
U4 = []
for t in range(256):
s = S[t]
T1.append(mul4(s, G[0]))
T2.append(mul4(s, G[1]))
T3.append(mul4(s, G[2]))
T4.append(mul4(s, G[3]))
s = Si[t]
T5.append(mul4(s, iG[0]))
T6.append(mul4(s, iG[1]))
T7.append(mul4(s, iG[2]))
T8.append(mul4(s, iG[3]))
U1.append(mul4(t, iG[0]))
U2.append(mul4(t, iG[1]))
U3.append(mul4(t, iG[2]))
U4.append(mul4(t, iG[3]))
# round constants
rcon = [1]
r = 1
for t in range(1, 30):
r = mul(2, r)
rcon.append(r)
del A
del AA
del pivot
del B
del G
del box
del log
del alog
del i
del j
del r
del s
del t
del mul
del mul4
del cox
del iG
class rijndael:
def __init__(self, key, block_size = 16):
if block_size != 16 and block_size != 24 and block_size != 32:
raise ValueError('Invalid block size: ' + str(block_size))
if len(key) != 16 and len(key) != 24 and len(key) != 32:
raise ValueError('Invalid key size: ' + str(len(key)))
self.block_size = block_size
ROUNDS = num_rounds[len(key)][block_size]
BC = block_size // 4
# encryption round keys
Ke = [[0] * BC for i in range(ROUNDS + 1)]
# decryption round keys
Kd = [[0] * BC for i in range(ROUNDS + 1)]
ROUND_KEY_COUNT = (ROUNDS + 1) * BC
KC = len(key) // 4
# copy user material bytes into temporary ints
tk = []
for i in range(0, KC):
tk.append((ord(key[i * 4]) << 24) | (ord(key[i * 4 + 1]) << 16) |
(ord(key[i * 4 + 2]) << 8) | ord(key[i * 4 + 3]))
# copy values into round key arrays
t = 0
j = 0
while j < KC and t < ROUND_KEY_COUNT:
Ke[t // BC][t % BC] = tk[j]
Kd[ROUNDS - (t // BC)][t % BC] = tk[j]
j += 1
t += 1
tt = 0
rconpointer = 0
while t < ROUND_KEY_COUNT:
# extrapolate using phi (the round key evolution function)
tt = tk[KC - 1]
tk[0] ^= (S[(tt >> 16) & 0xFF] & 0xFF) << 24 ^ \
(S[(tt >> 8) & 0xFF] & 0xFF) << 16 ^ \
(S[ tt & 0xFF] & 0xFF) << 8 ^ \
(S[(tt >> 24) & 0xFF] & 0xFF) ^ \
(rcon[rconpointer] & 0xFF) << 24
rconpointer += 1
if KC != 8:
for i in range(1, KC):
tk[i] ^= tk[i-1]
else:
for i in range(1, KC // 2):
tk[i] ^= tk[i-1]
tt = tk[KC // 2 - 1]
tk[KC // 2] ^= (S[ tt & 0xFF] & 0xFF) ^ \
(S[(tt >> 8) & 0xFF] & 0xFF) << 8 ^ \
(S[(tt >> 16) & 0xFF] & 0xFF) << 16 ^ \
(S[(tt >> 24) & 0xFF] & 0xFF) << 24
for i in range(KC // 2 + 1, KC):
tk[i] ^= tk[i-1]
# copy values into round key arrays
j = 0
while j < KC and t < ROUND_KEY_COUNT:
Ke[t // BC][t % BC] = tk[j]
Kd[ROUNDS - (t // BC)][t % BC] = tk[j]
j += 1
t += 1
# inverse MixColumn where needed
for r in range(1, ROUNDS):
for j in range(BC):
tt = Kd[r][j]
Kd[r][j] = U1[(tt >> 24) & 0xFF] ^ \
U2[(tt >> 16) & 0xFF] ^ \
U3[(tt >> 8) & 0xFF] ^ \
U4[ tt & 0xFF]
self.Ke = Ke
self.Kd = Kd
def encrypt(self, plaintext):
if len(plaintext) != self.block_size:
raise ValueError('wrong block length, expected ' + str(self.block_size) + ' got ' + str(len(plaintext)))
Ke = self.Ke
BC = self.block_size // 4
ROUNDS = len(Ke) - 1
if BC == 4:
SC = 0
elif BC == 6:
SC = 1
else:
SC = 2
s1 = shifts[SC][1][0]
s2 = shifts[SC][2][0]
s3 = shifts[SC][3][0]
a = [0] * BC
# temporary work array
t = []
# plaintext to ints + key
for i in range(BC):
t.append((ord(plaintext[i * 4 ]) << 24 |
ord(plaintext[i * 4 + 1]) << 16 |
ord(plaintext[i * 4 + 2]) << 8 |
ord(plaintext[i * 4 + 3]) ) ^ Ke[0][i])
# apply round transforms
for r in range(1, ROUNDS):
for i in range(BC):
a[i] = (T1[(t[ i ] >> 24) & 0xFF] ^
T2[(t[(i + s1) % BC] >> 16) & 0xFF] ^
T3[(t[(i + s2) % BC] >> 8) & 0xFF] ^
T4[ t[(i + s3) % BC] & 0xFF] ) ^ Ke[r][i]
t = copy.copy(a)
# last round is special
result = []
for i in range(BC):
tt = Ke[ROUNDS][i]
result.append((S[(t[ i ] >> 24) & 0xFF] ^ (tt >> 24)) & 0xFF)
result.append((S[(t[(i + s1) % BC] >> 16) & 0xFF] ^ (tt >> 16)) & 0xFF)
result.append((S[(t[(i + s2) % BC] >> 8) & 0xFF] ^ (tt >> 8)) & 0xFF)
result.append((S[ t[(i + s3) % BC] & 0xFF] ^ tt ) & 0xFF)
return ''.join(map(chr, result))
def decrypt(self, ciphertext):
if len(ciphertext) != self.block_size:
raise ValueError('wrong block length, expected ' + str(self.block_size) + ' got ' + str(len(ciphertext)))
Kd = self.Kd
BC = self.block_size // 4
ROUNDS = len(Kd) - 1
if BC == 4:
SC = 0
elif BC == 6:
SC = 1
else:
SC = 2
s1 = shifts[SC][1][1]
s2 = shifts[SC][2][1]
s3 = shifts[SC][3][1]
a = [0] * BC
# temporary work array
t = [0] * BC
# ciphertext to ints + key
for i in range(BC):
t[i] = (ord(ciphertext[i * 4 ]) << 24 |
ord(ciphertext[i * 4 + 1]) << 16 |
ord(ciphertext[i * 4 + 2]) << 8 |
ord(ciphertext[i * 4 + 3]) ) ^ Kd[0][i]
# apply round transforms
for r in range(1, ROUNDS):
for i in range(BC):
a[i] = (T5[(t[ i ] >> 24) & 0xFF] ^
T6[(t[(i + s1) % BC] >> 16) & 0xFF] ^
T7[(t[(i + s2) % BC] >> 8) & 0xFF] ^
T8[ t[(i + s3) % BC] & 0xFF] ) ^ Kd[r][i]
t = copy.copy(a)
# last round is special
result = []
for i in range(BC):
tt = Kd[ROUNDS][i]
result.append((Si[(t[ i ] >> 24) & 0xFF] ^ (tt >> 24)) & 0xFF)
result.append((Si[(t[(i + s1) % BC] >> 16) & 0xFF] ^ (tt >> 16)) & 0xFF)
result.append((Si[(t[(i + s2) % BC] >> 8) & 0xFF] ^ (tt >> 8)) & 0xFF)
result.append((Si[ t[(i + s3) % BC] & 0xFF] ^ tt ) & 0xFF)
return ''.join(map(chr, result))
def encrypt(key, block):
return rijndael(key, len(block)).encrypt(block)
def decrypt(key, block):
return rijndael(key, len(block)).decrypt(block)
Note that the rijndael.py file only implements the block cipher. The encrypt / decrypt functions only handle plaintexts that are precisely the block size. This means that the caller of these functions will have to provide the block cipher mode of operation and the zero padding himself.
Example python code (from a Java programmer, beware):
class zeropad:
def __init__(self, block_size):
assert block_size > 0 and block_size < 256
self.block_size = block_size
def pad(self, pt):
ptlen = len(pt)
padsize = self.block_size - ((ptlen + self.block_size - 1) % self.block_size + 1)
return pt + "\0" * padsize
def unpad(self, ppt):
assert len(ppt) % self.block_size == 0
offset = len(ppt)
if (offset == 0):
return ''
end = offset - self.block_size + 1
while (offset > end):
offset -= 1;
if (ppt[offset] != "\0"):
return ppt[:offset + 1]
assert false
class cbc:
def __init__(self, padding, cipher, iv):
assert padding.block_size == cipher.block_size;
assert len(iv) == cipher.block_size;
self.padding = padding
self.cipher = cipher
self.iv = iv
def encrypt(self, pt):
ppt = self.padding.pad(pt)
offset = 0
ct = ''
v = self.iv
while (offset < len(ppt)):
block = ppt[offset:offset + self.cipher.block_size]
block = self.xorblock(block, v)
block = self.cipher.encrypt(block)
ct += block
offset += self.cipher.block_size
v = block
return ct;
def decrypt(self, ct):
assert len(ct) % self.cipher.block_size == 0
ppt = ''
offset = 0
v = self.iv
while (offset < len(ct)):
block = ct[offset:offset + self.cipher.block_size]
decrypted = self.cipher.decrypt(block)
ppt += self.xorblock(decrypted, v)
offset += self.cipher.block_size
v = block
pt = self.padding.unpad(ppt)
return pt;
def xorblock(self, b1, b2):
# sorry, not very Pythonesk
i = 0
r = '';
while (i < self.cipher.block_size):
r += chr(ord(b1[i]) ^ ord(b2[i]))
i += 1
return r

n random numbers within parameters

Let's say I have a number, such as 100, and I want to have 5 different random numbers generated, but they all must add up to 100, how would I do that? (preferably in PHP. For math wizards/statisticians, I don't need truly random numbers, but something that looks random).
So this function, would produce something like this:
5, 51, 9, 18, 19 = 100
34, 52, 3, 7, 4 =100
And so forth.
Ideally, something that takes 5, 100 and produces the rest:
generateRandom(100,5)
a = RandomInteger[{1, 96}]
b = RandomInteger[{1, 97 - a}]
c = RandomInteger[{1, 98 - a - b}]
d = RandomInteger[{1, 99 - a - b - c}]
e = 100 - a - b - c - d
Samples:
{34,25,26,3,12,Sum =,100}
{90,5,1,1,3,Sum =,100}
{29,16,21,9,25,Sum =,100}
{4,13,71,10,2,Sum =,100}
The numbers are no equally distributed, of course.
Edit
Here is a more homogeneous distribution:
a = RandomInteger[{1, 20}];
b = RandomInteger[{1, 40 - a}];
c = RandomInteger[{1, 60 - a - b}];
d = RandomInteger[{1, 80 - a - b - c}];
e = 100 - a - b - c - d;
Output:
{5,33,2,8,52,Sum =,100}
{14,9,50,5,22,Sum =,100}
{3,23,12,34,28,Sum =,100}
{1,16,4,5,74,Sum =,100}
{6,28,6,9,51,Sum =,100}
{11,25,7,1,56,Sum =,100}
{4,34,12,18,32,Sum =,100}
{6,13,25,26,30,Sum =,100}
{8,27,14,5,46,Sum =,100}
{17,13,23,25,22,Sum =,100}
Here are the frequencies for the numbers:
Edit
Perhaps a better one:
a = Max[#, 1] & /# Evaluate[RandomInteger[{1, 20}, 5] - 1];
b = 100 - Total#a;
c = Mod[b, 5];
d = (b - c)/ 5;
a = a + d + {c, 0, 0, 0, 0};
Distribution:
Edit
In Mathematica you can easily generate all 5-Tuples that add up 100 as:
IntegerPartitions[100, {5}]
There are 38225 different beasts, without counting permutations
Length#IntegerPartitions[100, {5}]
(* -> 38225 *)
The frequency for each number in those quintuplets is:
Histogram#Flatten#IntegerPartitions[100, {5}]
The curve is very similar if one take permutations into account:
t = Tally#Flatten#(Permutations[#] & /# IntegerPartitions[100, {5}]);
ListLinePlot#SortBy[t, #[[1]] &][[All, 2]]
Along the lines of belisarius:
// Generates an array (of $elements elements) full of random numbers whose
// total is equal to the $total_sum
function generate_random_array($elements = 5, $total_sum = 100)
{
// build result array
$result = Array();
// iterate over all elements (except for the last, last will be the delta)
for ($_ = 0; $_ < ($elements - 1); $_++)
{
// typical low value (non-zero)
$low_value = 1;
// high value, skewed to have high results first
//$high_value = ($total_sum - ($elements - $_) - array_sum($result));
// high value, non-skewed
$step = (int)floor($total_sum / $elements); // give "not-to-exceed" ranges
$high_value = (($_ + 1) * $step) - array_sum($result);
// produce the result and add it
$result[] = rand($low_value,$high_value);
//$result[] = rand(1,65535) % $high_value + 1; // alternate to make rand a little smoother
}
// add the final result as the remainder
$result[] = $total_sum - array_sum($result);
// now return it
return $result;
}

Categories