Compare commits
18 Commits
BOBS_MPI_E
...
MAPI_NEW_D
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e953a4ea87 | ||
|
|
22ea3cb16d | ||
|
|
e021985dac | ||
|
|
37c7fe2cc1 | ||
|
|
92449d5f2b | ||
|
|
0f4c47bad2 | ||
|
|
66a09211ae | ||
|
|
4d276aa864 | ||
|
|
9a9d38606a | ||
|
|
7ef7f62f45 | ||
|
|
412bc70111 | ||
|
|
cf982c25ce | ||
|
|
dfb5dde44f | ||
|
|
5b5ddf1efb | ||
|
|
2765860524 | ||
|
|
95560e128c | ||
|
|
2c4edc911e | ||
|
|
82d37c5f89 |
@@ -1,5 +1,4 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
@@ -12,16 +11,15 @@
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Multi-precision Binary Polynomial Arithmetic Library.
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2001
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sheueling Chang Shantz <sheueling.chang@sun.com> and
|
||||
* Douglas Stebila <douglas@stebila.ca> of Sun Laboratories.
|
||||
* Srilatha Moturi <srilatha@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@@ -37,27 +35,36 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _MP_GF2M_H_
|
||||
#define _MP_GF2M_H_
|
||||
#include "nsISupports.idl"
|
||||
|
||||
#include "mpi.h"
|
||||
interface nsIDOMWindow;
|
||||
|
||||
mp_err mp_badd(const mp_int *a, const mp_int *b, mp_int *c);
|
||||
mp_err mp_bmul(const mp_int *a, const mp_int *b, mp_int *c);
|
||||
|
||||
/* For modular arithmetic, the irreducible polynomial f(t) is represented
|
||||
* as an array of int[], where f(t) is of the form:
|
||||
* f(t) = t^p[0] + t^p[1] + ... + t^p[k]
|
||||
* where m = p[0] > p[1] > ... > p[k] = 0.
|
||||
/**
|
||||
* This interface provides support for registering Mozilla as the default
|
||||
* Mail Client. This interface can also be used to get/set the user preference
|
||||
* for the default Mail Client.
|
||||
*
|
||||
*/
|
||||
mp_err mp_bmod(const mp_int *a, const unsigned int p[], mp_int *r);
|
||||
mp_err mp_bmulmod(const mp_int *a, const mp_int *b, const unsigned int p[],
|
||||
mp_int *r);
|
||||
mp_err mp_bsqrmod(const mp_int *a, const unsigned int p[], mp_int *r);
|
||||
mp_err mp_bdivmod(const mp_int *y, const mp_int *x, const mp_int *pp,
|
||||
const unsigned int p[], mp_int *r);
|
||||
[scriptable, uuid(c5be14ba-4e0a-4eec-a1b8-04363761d63c)]
|
||||
interface nsIMapiRegistry: nsISupports {
|
||||
|
||||
int mp_bpoly2arr(const mp_int *a, unsigned int p[], int max);
|
||||
mp_err mp_barr2poly(const unsigned int p[], mp_int *a);
|
||||
/** This is set to TRUE if Mozilla is the default Application
|
||||
*/
|
||||
attribute boolean isDefaultMailClient;
|
||||
|
||||
#endif /* _MP_GF2M_H_ */
|
||||
/** This is set TRUE only once per session.
|
||||
*/
|
||||
readonly attribute boolean showDialog;
|
||||
|
||||
/** This will bring the dialog asking the user if he/she wants to set
|
||||
* Mozilla as default Mail Client.
|
||||
* Call this only if Mozilla is not the default Mail client
|
||||
*/
|
||||
void showMailIntegrationDialog(in nsIDOMWindow parentWindow);
|
||||
|
||||
};
|
||||
|
||||
%{C++
|
||||
#define NS_IMAPIREGISTRY_CONTRACTID "@mozilla.org/mapiregistry;1"
|
||||
#define NS_IMAPIREGISTRY_CLASSNAME "Mozilla MAPI Registry"
|
||||
%}
|
||||
27
mozilla/mailnews/mapi/makefile.win
Normal file
27
mozilla/mailnews/mapi/makefile.win
Normal file
@@ -0,0 +1,27 @@
|
||||
#!nmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s): Srilatha Moturi <srilatha@netscape.com>
|
||||
# Krishna Mohan Khandrika <kkhandrika@netscape.com>
|
||||
|
||||
DEPTH=..\..
|
||||
|
||||
DIRS=mapihook resources mapiDll
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
54
mozilla/mailnews/mapi/mapiDll/Mapi32.DEF
Normal file
54
mozilla/mailnews/mapi/mapiDll/Mapi32.DEF
Normal file
@@ -0,0 +1,54 @@
|
||||
; ***** BEGIN LICENSE BLOCK *****
|
||||
; Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
;
|
||||
; The contents of this file are subject to the Mozilla Public License Version
|
||||
; 1.1 (the "License"); you may not use this file except in compliance with
|
||||
; the License. You may obtain a copy of the License at
|
||||
; http://www.mozilla.org/MPL/
|
||||
;
|
||||
; Software distributed under the License is distributed on an "AS IS" basis,
|
||||
; WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
; for the specific language governing rights and limitations under the
|
||||
; License.
|
||||
;
|
||||
; The Original Code is Mozilla.
|
||||
;
|
||||
; The Initial Developer of the Original Code is
|
||||
; Netscape Communications Corp.
|
||||
; Portions created by the Initial Developer are Copyright (C) 2001
|
||||
; the Initial Developer. All Rights Reserved.
|
||||
;
|
||||
; Contributor(s): Krishna Mohan Khandrika (kkhandrika@netscape.com)
|
||||
;
|
||||
; Alternatively, the contents of this file may be used under the terms of
|
||||
; either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
; the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
; in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
; of those above. If you wish to allow use of your version of this file only
|
||||
; under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
; use your version of this file under the terms of the MPL, indicate your
|
||||
; decision by deleting the provisions above and replace them with the notice
|
||||
; and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
; the provisions above, a recipient may use your version of this file under
|
||||
; the terms of any one of the MPL, the GPL or the LGPL.
|
||||
;
|
||||
; ***** END LICENSE BLOCK *****
|
||||
|
||||
LIBRARY mozMapi32.dll
|
||||
DESCRIPTION 'Mozilla Simple MAPI Support'
|
||||
|
||||
EXPORTS
|
||||
MAPILogon
|
||||
MAPILogoff
|
||||
MAPISendMail
|
||||
MAPISendDocuments
|
||||
MAPIFindNext
|
||||
MAPIReadMail
|
||||
MAPISaveMail
|
||||
MAPIDeleteMail
|
||||
MAPIAddress
|
||||
MAPIDetails
|
||||
MAPIResolveName
|
||||
MAPIFreeBuffer
|
||||
GetMapiDllVersion
|
||||
|
||||
346
mozilla/mailnews/mapi/mapiDll/MapiDll.cpp
Normal file
346
mozilla/mailnews/mapi/mapiDll/MapiDll.cpp
Normal file
@@ -0,0 +1,346 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corp.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2001
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Krishna Mohan Khandrika (kkhandrika@netscape.com)
|
||||
* Contributor(s): Rajiv Dayal (rdayal@netscape.com)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#include <mapidefs.h>
|
||||
#include <mapi.h>
|
||||
#include "msgMapi.h"
|
||||
#include "msgMapiMain.h"
|
||||
|
||||
#define MAX_RECIPS 100
|
||||
#define MAX_FILES 100
|
||||
|
||||
const CLSID CLSID_CMapiImp = {0x29f458be, 0x8866, 0x11d5,
|
||||
{0xa3, 0xdd, 0x0, 0xb0, 0xd0, 0xf3, 0xba, 0xa7}};
|
||||
const IID IID_nsIMapi = {0x6EDCD38E,0x8861,0x11d5,
|
||||
{0xA3,0xDD,0x00,0xB0,0xD0,0xF3,0xBA,0xA7}};
|
||||
|
||||
DWORD tId = 0;
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE aInstance, DWORD aReason, LPVOID aReserved)
|
||||
{
|
||||
switch (aReason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH : tId = TlsAlloc();
|
||||
if (tId == 0xFFFFFFFF)
|
||||
return FALSE;
|
||||
break;
|
||||
|
||||
case DLL_PROCESS_DETACH : TlsFree(tId);
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL InitMozillaReference(nsIMapi **aRetValue)
|
||||
{
|
||||
// Check wehther this thread has a valid Interface
|
||||
// by looking into thread-specific-data variable
|
||||
|
||||
*aRetValue = (nsIMapi *)TlsGetValue(tId);
|
||||
|
||||
// Check whether the pointer actually resolves to
|
||||
// a valid method call; otherwise mozilla is not running
|
||||
|
||||
if ((*aRetValue) && (*aRetValue)->IsValid() == S_OK)
|
||||
return TRUE;
|
||||
|
||||
HRESULT hRes = ::CoInitialize(nsnull) ;
|
||||
|
||||
hRes = ::CoCreateInstance(CLSID_CMapiImp, NULL, CLSCTX_LOCAL_SERVER,
|
||||
IID_nsIMapi, (LPVOID *)aRetValue);
|
||||
|
||||
if (hRes == S_OK && (*aRetValue)->Initialize() == S_OK)
|
||||
if (TlsSetValue(tId, (LPVOID)(*aRetValue)))
|
||||
return TRUE;
|
||||
|
||||
// Either CoCreate or TlsSetValue failed; so return FALSE
|
||||
|
||||
if ((*aRetValue))
|
||||
(*aRetValue)->Release();
|
||||
|
||||
::CoUninitialize();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// The MAPILogon function begins a Simple MAPI session, loading the default message ////
|
||||
// store and address book providers ////
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ULONG FAR PASCAL MAPILogon(ULONG aUIParam, LPTSTR aProfileName,
|
||||
LPTSTR aPassword, FLAGS aFlags,
|
||||
ULONG aReserved, LPLHANDLE aSession)
|
||||
{
|
||||
HRESULT hr = 0;
|
||||
ULONG nSessionId = 0;
|
||||
nsIMapi *pNsMapi = NULL;
|
||||
|
||||
if (!InitMozillaReference(&pNsMapi))
|
||||
return MAPI_E_FAILURE;
|
||||
|
||||
if (!(aFlags & MAPI_UNICODE))
|
||||
{
|
||||
// Need to convert the parameters to Unicode.
|
||||
|
||||
char *pUserName = (char *) aProfileName;
|
||||
char *pPassWord = (char *) aPassword;
|
||||
|
||||
TCHAR ProfileName[MAX_NAME_LEN] = {0};
|
||||
TCHAR PassWord[MAX_PW_LEN] = {0};
|
||||
|
||||
if (pUserName != NULL)
|
||||
{
|
||||
if (!MultiByteToWideChar(CP_ACP, 0, pUserName, -1, ProfileName,
|
||||
MAX_NAME_LEN))
|
||||
return MAPI_E_FAILURE;
|
||||
}
|
||||
|
||||
if (pPassWord != NULL)
|
||||
{
|
||||
if (!MultiByteToWideChar(CP_ACP, 0, pPassWord, -1, PassWord,
|
||||
MAX_NAME_LEN))
|
||||
return MAPI_E_FAILURE;
|
||||
}
|
||||
|
||||
hr = pNsMapi->Login(aUIParam, ProfileName, PassWord, aFlags,
|
||||
&nSessionId);
|
||||
}
|
||||
else
|
||||
hr = pNsMapi->Login(aUIParam, aProfileName, aPassword,
|
||||
aFlags, &nSessionId);
|
||||
if (hr == S_OK)
|
||||
(*aSession) = (LHANDLE) nSessionId;
|
||||
else
|
||||
return nSessionId;
|
||||
|
||||
return SUCCESS_SUCCESS;
|
||||
}
|
||||
|
||||
ULONG FAR PASCAL MAPILogoff (LHANDLE aSession, ULONG aUIParam,
|
||||
FLAGS aFlags, ULONG aReserved)
|
||||
{
|
||||
nsIMapi *pNsMapi = (nsIMapi *)TlsGetValue(tId);
|
||||
if (pNsMapi != NULL)
|
||||
{
|
||||
if (pNsMapi->Logoff((ULONG) aSession) == S_OK)
|
||||
pNsMapi->Release();
|
||||
pNsMapi = NULL;
|
||||
}
|
||||
|
||||
TlsSetValue(tId, NULL);
|
||||
|
||||
::CoUninitialize();
|
||||
|
||||
return SUCCESS_SUCCESS;
|
||||
}
|
||||
|
||||
ULONG FAR PASCAL MAPISendMail (LHANDLE lhSession, ULONG ulUIParam, lpnsMapiMessage lpMessage,
|
||||
FLAGS flFlags, ULONG ulReserved )
|
||||
{
|
||||
HRESULT hr = 0;
|
||||
BOOL bTempSession = FALSE ;
|
||||
nsIMapi *pNsMapi = NULL;
|
||||
|
||||
if (!InitMozillaReference(&pNsMapi))
|
||||
return MAPI_E_FAILURE;
|
||||
|
||||
if (lpMessage->nRecipCount > MAX_RECIPS)
|
||||
return MAPI_E_TOO_MANY_RECIPIENTS ;
|
||||
|
||||
if (lpMessage->nFileCount > MAX_FILES)
|
||||
return MAPI_E_TOO_MANY_FILES ;
|
||||
|
||||
if ( (!(flFlags & MAPI_DIALOG)) && (lpMessage->lpRecips == NULL) )
|
||||
return MAPI_E_UNKNOWN_RECIPIENT ;
|
||||
|
||||
if (!lhSession || pNsMapi->IsValidSession(lhSession) != S_OK)
|
||||
{
|
||||
FLAGS LoginFlag ;
|
||||
if ( (flFlags & MAPI_LOGON_UI) && (flFlags & MAPI_NEW_SESSION) )
|
||||
LoginFlag = MAPI_LOGON_UI | MAPI_NEW_SESSION ;
|
||||
else if (flFlags & MAPI_LOGON_UI)
|
||||
LoginFlag = MAPI_LOGON_UI ;
|
||||
|
||||
hr = MAPILogon (ulUIParam, (LPTSTR) NULL, (LPTSTR) NULL, LoginFlag, 0, &lhSession) ;
|
||||
if (hr != SUCCESS_SUCCESS)
|
||||
return MAPI_E_LOGIN_FAILURE ;
|
||||
bTempSession = TRUE ;
|
||||
}
|
||||
|
||||
// we need to deal with null data passed in by MAPI clients, specially when MAPI_DIALOG is set.
|
||||
// The MS COM type lib code generated by MIDL for the MS COM interfaces checks for these parameters
|
||||
// to be non null, although null is a valid value for them here.
|
||||
nsMapiRecipDesc * lpRecips ;
|
||||
nsMapiFileDesc * lpFiles ;
|
||||
|
||||
nsMapiMessage Message ;
|
||||
memset (&Message, 0, sizeof (nsMapiMessage) ) ;
|
||||
nsMapiRecipDesc Recipient ;
|
||||
memset (&Recipient, 0, sizeof (nsMapiRecipDesc) );
|
||||
nsMapiFileDesc Files ;
|
||||
memset (&Files, 0, sizeof (nsMapiFileDesc) ) ;
|
||||
|
||||
if(!lpMessage)
|
||||
{
|
||||
lpMessage = &Message ;
|
||||
}
|
||||
if(!lpMessage->lpRecips)
|
||||
{
|
||||
lpRecips = &Recipient ;
|
||||
}
|
||||
else
|
||||
lpRecips = lpMessage->lpRecips ;
|
||||
if(!lpMessage->lpFiles)
|
||||
{
|
||||
lpFiles = &Files ;
|
||||
}
|
||||
else
|
||||
lpFiles = lpMessage->lpFiles ;
|
||||
|
||||
HANDLE hEvent = CreateEvent (NULL, FALSE, FALSE, (LPCTSTR) MAPI_SENDCOMPLETE_EVENT) ;
|
||||
|
||||
hr = pNsMapi->SendMail (lhSession, lpMessage,
|
||||
(short) lpMessage->nRecipCount, lpRecips,
|
||||
(short) lpMessage->nFileCount, lpFiles,
|
||||
flFlags, ulReserved);
|
||||
|
||||
// we are seeing a problem when using Word, although we return success from the MAPI support
|
||||
// MS COM interface in mozilla, we are getting this error here. This is a temporary hack !!
|
||||
if (hr == 0x800703e6)
|
||||
hr = SUCCESS_SUCCESS;
|
||||
|
||||
if (hr == SUCCESS_SUCCESS)
|
||||
WaitForSingleObject (hEvent, INFINITE) ;
|
||||
CloseHandle (hEvent) ;
|
||||
|
||||
if (bTempSession)
|
||||
MAPILogoff (lhSession, ulUIParam, 0,0) ;
|
||||
|
||||
return hr ;
|
||||
}
|
||||
|
||||
|
||||
ULONG FAR PASCAL MAPISendDocuments(ULONG ulUIParam, LPTSTR lpszDelimChar, LPTSTR lpszFilePaths,
|
||||
LPTSTR lpszFileNames, ULONG ulReserved)
|
||||
{
|
||||
LHANDLE lhSession ;
|
||||
nsIMapi *pNsMapi = NULL;
|
||||
|
||||
if (!InitMozillaReference(&pNsMapi))
|
||||
return MAPI_E_FAILURE;
|
||||
|
||||
unsigned long result = MAPILogon (ulUIParam, (LPTSTR) NULL, (LPTSTR) NULL, MAPI_LOGON_UI, 0, &lhSession) ;
|
||||
if (result != SUCCESS_SUCCESS)
|
||||
return MAPI_E_LOGIN_FAILURE ;
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
HANDLE hEvent = CreateEvent (NULL, FALSE, FALSE, (LPCTSTR) MAPI_SENDCOMPLETE_EVENT) ;
|
||||
|
||||
hr = pNsMapi->SendDocuments(lhSession, (LPTSTR) lpszDelimChar, (LPTSTR) lpszFilePaths,
|
||||
(LPTSTR) lpszFileNames, ulReserved) ;
|
||||
|
||||
if (hr == SUCCESS_SUCCESS)
|
||||
WaitForSingleObject (hEvent, INFINITE) ;
|
||||
CloseHandle (hEvent) ;
|
||||
|
||||
MAPILogoff (lhSession, ulUIParam, 0,0) ;
|
||||
|
||||
return hr ;
|
||||
}
|
||||
|
||||
ULONG FAR PASCAL MAPIFindNext(LHANDLE lhSession, ULONG ulUIParam, LPTSTR lpszMessageType,
|
||||
LPTSTR lpszSeedMessageID, FLAGS flFlags, ULONG ulReserved,
|
||||
LPTSTR lpszMessageID)
|
||||
{
|
||||
return MAPI_E_FAILURE;
|
||||
}
|
||||
|
||||
ULONG FAR PASCAL MAPIReadMail(LHANDLE lhSession, ULONG ulUIParam, LPTSTR lpszMessageID,
|
||||
FLAGS flFlags, ULONG ulReserved, lpMapiMessage FAR *lppMessage)
|
||||
{
|
||||
return MAPI_E_FAILURE;
|
||||
}
|
||||
|
||||
ULONG FAR PASCAL MAPISaveMail(LHANDLE lhSession, ULONG ulUIParam, lpMapiMessage lpMessage,
|
||||
FLAGS flFlags, ULONG ulReserved, LPTSTR lpszMessageID)
|
||||
{
|
||||
return MAPI_E_FAILURE;
|
||||
}
|
||||
|
||||
ULONG FAR PASCAL MAPIDeleteMail(LHANDLE lhSession, ULONG ulUIParam, LPTSTR lpszMessageID,
|
||||
FLAGS flFlags, ULONG ulReserved)
|
||||
{
|
||||
return MAPI_E_FAILURE;
|
||||
}
|
||||
|
||||
ULONG FAR PASCAL MAPIAddress(LHANDLE lhSession, ULONG ulUIParam, LPTSTR lpszCaption,
|
||||
ULONG nEditFields, LPTSTR lpszLabels, ULONG nRecips,
|
||||
lpMapiRecipDesc lpRecips, FLAGS flFlags,
|
||||
ULONG ulReserved, LPULONG lpnNewRecips,
|
||||
lpMapiRecipDesc FAR *lppNewRecips)
|
||||
{
|
||||
return MAPI_E_FAILURE;
|
||||
}
|
||||
|
||||
ULONG FAR PASCAL MAPIDetails(LHANDLE lhSession, ULONG ulUIParam, lpMapiRecipDesc lpRecip,
|
||||
FLAGS flFlags, ULONG ulReserved)
|
||||
{
|
||||
return MAPI_E_FAILURE;
|
||||
}
|
||||
|
||||
ULONG FAR PASCAL MAPIResolveName(LHANDLE lhSession, ULONG ulUIParam, LPTSTR lpszName,
|
||||
FLAGS flFlags, ULONG ulReserved, lpMapiRecipDesc FAR *lppRecip)
|
||||
{
|
||||
return MAPI_E_FAILURE;
|
||||
}
|
||||
|
||||
ULONG FAR PASCAL MAPIFreeBuffer(LPVOID pv)
|
||||
{
|
||||
return MAPI_E_FAILURE;
|
||||
}
|
||||
|
||||
ULONG FAR PASCAL GetMapiDllVersion()
|
||||
{
|
||||
return 94;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
53
mozilla/security/nss/lib/freebl/mpi/utils/ptab.pl → mozilla/mailnews/mapi/mapiDll/makefile.win
Executable file → Normal file
53
mozilla/security/nss/lib/freebl/mpi/utils/ptab.pl → mozilla/mailnews/mapi/mapiDll/makefile.win
Executable file → Normal file
@@ -1,5 +1,3 @@
|
||||
#!/usr/linguist/bin/perl
|
||||
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
@@ -13,14 +11,14 @@
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the MPI Arbitrary Precision Integer Arithmetic library.
|
||||
# The Original Code is Mozilla.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Michael J. Fromberger <sting@linguist.dartmouth.edu>.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# Netscape Communications Corp.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2001
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Contributor(s): Krishna Mohan Khandrika (kkhandrika@netscape.com)
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@@ -34,28 +32,31 @@
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
# $Id: ptab.pl,v 1.2 2005-02-02 22:28:23 gerv%gerv.net Exp $
|
||||
#
|
||||
DEPTH=..\..\..
|
||||
|
||||
while(<>) {
|
||||
chomp;
|
||||
push(@primes, $_);
|
||||
}
|
||||
MODULE = mozMapi32
|
||||
EXPORT_LIBRARY = $(MODULE)
|
||||
LIBRARY_NAME = $(MODULE)
|
||||
DEFFILE = Mapi32.def
|
||||
|
||||
printf("mp_size prime_tab_size = %d;\n", ($#primes + 1));
|
||||
print "mp_digit prime_tab[] = {\n";
|
||||
REQUIRES = MapiProxy \
|
||||
msgMapi \
|
||||
xpcom \
|
||||
string \
|
||||
$(NULL)
|
||||
|
||||
print "\t";
|
||||
$last = pop(@primes);
|
||||
foreach $prime (sort {$a<=>$b} @primes) {
|
||||
printf("0x%04X, ", $prime);
|
||||
$brk = ($brk + 1) % 8;
|
||||
print "\n\t" if(!$brk);
|
||||
}
|
||||
printf("0x%04X", $last);
|
||||
print "\n" if($brk);
|
||||
print "};\n\n";
|
||||
include <$(DEPTH)\config\config.mak>
|
||||
###############################################################
|
||||
|
||||
LCFLAGS=-DUNICODE -D_UNICODE
|
||||
|
||||
OBJS= .\$(OBJDIR)\MapiDll.obj \
|
||||
$(NULL)
|
||||
|
||||
WIN_LIBS= ole32.lib \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
||||
exit 0;
|
||||
47
mozilla/mailnews/mapi/mapihook/build/MapiProxy.def
Normal file
47
mozilla/mailnews/mapi/mapihook/build/MapiProxy.def
Normal file
@@ -0,0 +1,47 @@
|
||||
; ***** BEGIN LICENSE BLOCK *****
|
||||
; Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
;
|
||||
; The contents of this file are subject to the Mozilla Public License Version
|
||||
; 1.1 (the "License"); you may not use this file except in compliance with
|
||||
; the License. You may obtain a copy of the License at
|
||||
; http://www.mozilla.org/MPL/
|
||||
;
|
||||
; Software distributed under the License is distributed on an "AS IS" basis,
|
||||
; WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
; for the specific language governing rights and limitations under the
|
||||
; License.
|
||||
;
|
||||
; The Original Code is Mozilla.
|
||||
;
|
||||
; The Initial Developer of the Original Code is
|
||||
; Netscape Communications Corp.
|
||||
; Portions created by the Initial Developer are Copyright (C) 2001
|
||||
; the Initial Developer. All Rights Reserved.
|
||||
;
|
||||
; Contributor(s): Krishna Mohan Khandrika (kkhandrika@netscape.com)
|
||||
;
|
||||
; Alternatively, the contents of this file may be used under the terms of
|
||||
; either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
; the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
; in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
; of those above. If you wish to allow use of your version of this file only
|
||||
; under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
; use your version of this file under the terms of the MPL, indicate your
|
||||
; decision by deleting the provisions above and replace them with the notice
|
||||
; and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
; the provisions above, a recipient may use your version of this file under
|
||||
; the terms of any one of the MPL, the GPL or the LGPL.
|
||||
;
|
||||
; ***** END LICENSE BLOCK *****
|
||||
|
||||
LIBRARY MapiProxy.dll
|
||||
DESCRIPTION 'Proxy/Stub DLL'
|
||||
|
||||
EXPORTS
|
||||
DllGetClassObject @1 PRIVATE
|
||||
DllCanUnloadNow @2 PRIVATE
|
||||
GetProxyDllInfo @3 PRIVATE
|
||||
DllRegisterServer @4 PRIVATE
|
||||
DllUnregisterServer @5 PRIVATE
|
||||
|
||||
|
||||
64
mozilla/security/nss/lib/freebl/mpi/make-logtab → mozilla/mailnews/mapi/mapihook/build/makefile.win
Executable file → Normal file
64
mozilla/security/nss/lib/freebl/mpi/make-logtab → mozilla/mailnews/mapi/mapihook/build/makefile.win
Executable file → Normal file
@@ -1,11 +1,3 @@
|
||||
#!/usr/linguist/bin/perl
|
||||
|
||||
#
|
||||
# make-logtab
|
||||
#
|
||||
# Generate a table of logarithms of 2 in various bases, for use in
|
||||
# estimating the output sizes of various bases.
|
||||
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
@@ -19,15 +11,14 @@
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the MPI Arbitrary Precision Integer Arithmetic
|
||||
# library.
|
||||
# The Original Code is Mozilla.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998, 2000
|
||||
# Netscape Communications Corp.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2001
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Contributor(s): Krishna Mohan Khandrika (kkhandrika@netscape.com)
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@@ -41,24 +32,37 @@
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
# $Id: make-logtab,v 1.4 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
DEPTH=..\..\..\..
|
||||
|
||||
$ARRAYNAME = $ENV{'ARRAYNAME'} || "s_logv_2";
|
||||
$ARRAYTYPE = $ENV{'ARRAYTYPE'} || "float";
|
||||
MODULE = MapiProxy
|
||||
EXPORT_LIBRARY = $(MODULE)
|
||||
LIBRARY_NAME = $(MODULE)
|
||||
DEFFILE = MapiProxy.def
|
||||
|
||||
include <$(DEPTH)\config\config.mak>
|
||||
|
||||
##################################################################
|
||||
|
||||
LCFLAGS=-DREGISTER_PROXY_DLL -DUNICODE -D_UNICODE
|
||||
|
||||
OBJS= .\$(OBJDIR)\dlldata.obj \
|
||||
.\$(OBJDIR)\msgMapi_p.obj \
|
||||
.\$(OBJDIR)\msgMapi_i.obj \
|
||||
$(NULL)
|
||||
|
||||
WIN_LIBS= rpcrt4.lib
|
||||
|
||||
EXPORTS= msgMapi.h \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
||||
msgMapi.h msgMapi_p.c msgMapi_i.c dlldata.c : msgMapi.idl
|
||||
midl $(UNICODE_FLAGS) msgMapi.idl
|
||||
|
||||
clobber::
|
||||
rm -f dlldata.c msgMapi_i.c msgMapi_p.c msgMapi.h
|
||||
|
||||
printf("const %s %s[] = {\n %0.9ff, %0.9ff, ",
|
||||
$ARRAYTYPE, $ARRAYNAME, 0, 0);
|
||||
$brk = 2;
|
||||
for($ix = 2; $ix < 64; $ix++) {
|
||||
printf("%0.9ff, ", (log(2)/log($ix)));
|
||||
$brk = ($brk + 1) & 3;
|
||||
if(!$brk) {
|
||||
printf(" /* %2d %2d %2d %2d */\n ",
|
||||
$ix - 3, $ix - 2, $ix - 1, $ix);
|
||||
}
|
||||
}
|
||||
printf("%0.9ff\n};\n\n", (log(2)/log($ix)));
|
||||
|
||||
exit 0;
|
||||
114
mozilla/mailnews/mapi/mapihook/build/msgMapi.idl
Normal file
114
mozilla/mailnews/mapi/mapihook/build/msgMapi.idl
Normal file
@@ -0,0 +1,114 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corp.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2001
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Krishna Mohan Khandrika (kkhandrika@netscape.com)
|
||||
* Contributor(s): Rajiv Dayal (rdayal@netscape.com)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
// This idl will be compiled by MIDL. MS-COM is used
|
||||
// as brdige between MAPI clients and the Mozilla.
|
||||
|
||||
import "unknwn.idl";
|
||||
|
||||
typedef wchar_t LOGIN_PW_TYPE[256];
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned long ulReserved;
|
||||
unsigned long flFlags; /* Flags */
|
||||
unsigned long nPosition_NotUsed; /* character in text to be replaced by attachment */
|
||||
LPTSTR lpszPathName; /* Full path name including file name */
|
||||
LPTSTR lpszFileName; /* Real (original) file name */
|
||||
unsigned char * lpFileType_NotUsed ;
|
||||
} nsMapiFileDesc, * lpnsMapiFileDesc;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned long ulReserved;
|
||||
unsigned long ulRecipClass; /* MAPI_TO, MAPI_CC, MAPI_BCC, MAPI_ORIG */
|
||||
LPTSTR lpszName; /* Recipient name to display */
|
||||
LPTSTR lpszAddress; /* Recipient email address */
|
||||
unsigned long ulEIDSize_NotUsed;
|
||||
unsigned char * lpEntryID_NotUsed ;
|
||||
} nsMapiRecipDesc, * lpnsMapiRecipDesc;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned long ulReserved;
|
||||
LPTSTR lpszSubject; /* Message Subject */
|
||||
LPTSTR lpszNoteText; /* Message Text */
|
||||
LPTSTR lpszMessageType_NotUsed;
|
||||
LPTSTR lpszDateReceived_notUsed; /* in YYYY/MM/DD HH:MM format */
|
||||
LPTSTR lpszConversationID_NotUsed; /* conversation thread ID */
|
||||
unsigned long flFlags; /* unread,return receipt */
|
||||
lpnsMapiRecipDesc lpOriginator; /* Originator descriptor */
|
||||
unsigned long nRecipCount; /* Number of recipients */
|
||||
lpnsMapiRecipDesc lpRecips; /* Recipient descriptors */
|
||||
unsigned long nFileCount; /* # of file attachments */
|
||||
lpnsMapiFileDesc lpFiles; /* Attachment descriptors */
|
||||
} nsMapiMessage, * lpnsMapiMessage;
|
||||
|
||||
|
||||
[
|
||||
object,
|
||||
uuid(6EDCD38E-8861-11d5-A3DD-00B0D0F3BAA7),
|
||||
helpstring("nsIMapi Inteface"),
|
||||
pointer_default(unique)
|
||||
]
|
||||
|
||||
interface nsIMapi : IUnknown
|
||||
{
|
||||
HRESULT Login(unsigned long aUIArg, LOGIN_PW_TYPE aLogin,
|
||||
LOGIN_PW_TYPE aPassWord, unsigned long aFlags,
|
||||
[out] unsigned long *aSessionId);
|
||||
|
||||
HRESULT Initialize();
|
||||
HRESULT IsValid();
|
||||
HRESULT IsValidSession([in] unsigned long aSession);
|
||||
|
||||
HRESULT SendMail([in] unsigned long aSession, [in] lpnsMapiMessage aMessage,
|
||||
[in] short aRecipCount, [in, size_is(aRecipCount)] lpnsMapiRecipDesc aRecips,
|
||||
[in] short aFileCount, [in, size_is(aFileCount)] lpnsMapiFileDesc aFiles,
|
||||
[in] unsigned long aFlags, [in] unsigned long aReserved) ;
|
||||
|
||||
HRESULT SendDocuments( [in] unsigned long aSession,
|
||||
[in] LPTSTR aDelimChar, [in] LPTSTR aFilePaths,
|
||||
[in] LPTSTR aFileNames, [in] ULONG aFlags ) ;
|
||||
|
||||
HRESULT Logoff (unsigned long aSession);
|
||||
HRESULT CleanUp();
|
||||
};
|
||||
|
||||
|
||||
|
||||
41
mozilla/security/nss/lib/freebl/mpi/doc/build → mozilla/mailnews/mapi/mapihook/makefile.win
Executable file → Normal file
41
mozilla/security/nss/lib/freebl/mpi/doc/build → mozilla/mailnews/mapi/mapihook/makefile.win
Executable file → Normal file
@@ -1,4 +1,3 @@
|
||||
#!/bin/sh
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
@@ -12,15 +11,14 @@
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the MPI Arbitrary Precision Integer Arithmetic library.
|
||||
# The Original Code is Mozilla.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Michael J. Fromberger <sting@linguist.dartmouth.edu>.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# Netscape Communications Corp.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2001
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Netscape Communications Corporation
|
||||
# Contributor(s): Srilatha Moturi (srilatha@netscape.com)
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@@ -34,33 +32,10 @@
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
# $Id: build,v 1.3 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
#
|
||||
DEPTH=..\..\..
|
||||
|
||||
VERS="1.7p6"
|
||||
SECT="1"
|
||||
NAME="MPI Tools"
|
||||
|
||||
echo "Building manual pages ..."
|
||||
case $# in
|
||||
0)
|
||||
files=`ls *.pod`
|
||||
;;
|
||||
*)
|
||||
files=$*
|
||||
;;
|
||||
esac
|
||||
|
||||
for name in $files
|
||||
do
|
||||
echo -n "$name ... "
|
||||
# sname=`noext $name`
|
||||
sname=`basename $name .pod`
|
||||
pod2man --section="$SECT" --center="$NAME" --release="$VERS" $name > $sname.$SECT
|
||||
echo "(done)"
|
||||
done
|
||||
|
||||
echo "Finished building."
|
||||
DIRS= build public src
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
@@ -1,5 +1,3 @@
|
||||
#/bin/sh
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
@@ -13,15 +11,15 @@
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is script to change the system id in an object file from PA-RISC 2.0 to 1.1.
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Hewlett-Packard Company.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1999
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2001
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# wrapped by Dennis Handly on Tue Mar 23 15:23:43 1999
|
||||
# Srilatha Moturi <srilatha@netscape.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@@ -37,18 +35,15 @@
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
# script to change the system id in an object file from PA-RISC 2.0 to 1.1
|
||||
DEPTH=..\..\..\..
|
||||
|
||||
adb -w $1 << EOF
|
||||
?m 0 -1 0
|
||||
0x0?X
|
||||
0x0?W (@0x0&~0x40000)|(~@0x0&0x40000)
|
||||
MODULE=msgMapi
|
||||
XPIDL_MODULE=mapihook
|
||||
|
||||
0?"change checksum"
|
||||
0x7c?X
|
||||
0x7c?W (@0x7c&~0x40000)|(~@0x7c&0x40000)
|
||||
$q
|
||||
EOF
|
||||
XPIDLSRCS = \
|
||||
.\nsIMapiRegistry.idl \
|
||||
.\nsIMapiSupport.idl \
|
||||
$(NULL)
|
||||
|
||||
exit 0
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
/*
|
||||
* Simple test driver for MPI library
|
||||
*
|
||||
* Test 1: Simple input test (drives single-digit multiply and add,
|
||||
* as well as I/O routines)
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
@@ -17,14 +11,15 @@
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic library.
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael J. Fromberger.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2001
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Srilatha Moturi <srilatha@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@@ -39,37 +34,37 @@
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: mptest-1.c,v 1.3 2004-04-27 23:04:37 gerv%gerv.net Exp $ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include "nsISupports.idl"
|
||||
|
||||
#ifdef MAC_CW_SIOUX
|
||||
#include <console.h>
|
||||
#endif
|
||||
interface nsIDOMWindow;
|
||||
|
||||
#include "mpi.h"
|
||||
/**
|
||||
* This interface provides support for registering Mozilla as the default
|
||||
* Mail Client. This interface can also be used to get/set the user preference
|
||||
* for the default Mail Client.
|
||||
*
|
||||
*/
|
||||
[scriptable, uuid(c5be14ba-4e0a-4eec-a1b8-04363761d63c)]
|
||||
interface nsIMapiRegistry: nsISupports {
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int ix;
|
||||
mp_int mp;
|
||||
/** This is set to TRUE if Mozilla is the default Application
|
||||
*/
|
||||
attribute boolean isDefaultMailClient;
|
||||
|
||||
#ifdef MAC_CW_SIOUX
|
||||
argc = ccommand(&argv);
|
||||
#endif
|
||||
/** This is set TRUE only once per session.
|
||||
*/
|
||||
readonly attribute boolean showDialog;
|
||||
|
||||
mp_init(&mp);
|
||||
|
||||
for(ix = 1; ix < argc; ix++) {
|
||||
mp_read_radix(&mp, argv[ix], 10);
|
||||
mp_print(&mp, stdout);
|
||||
fputc('\n', stdout);
|
||||
}
|
||||
/** This will bring the dialog asking the user if he/she wants to set
|
||||
* Mozilla as default Mail Client.
|
||||
* Call this only if Mozilla is not the default Mail client
|
||||
*/
|
||||
void showMailIntegrationDialog(in nsIDOMWindow parentWindow);
|
||||
|
||||
};
|
||||
|
||||
mp_clear(&mp);
|
||||
return 0;
|
||||
}
|
||||
%{C++
|
||||
#define NS_IMAPIREGISTRY_CONTRACTID "@mozilla.org/mapiregistry;1"
|
||||
#define NS_IMAPIREGISTRY_CLASSNAME "Mozilla MAPI Registry"
|
||||
%}
|
||||
@@ -11,15 +11,14 @@
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Solaris software cryptographic token.
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2005
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2001
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sun Microsystems, Inc.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@@ -35,31 +34,31 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef MPI_AMD64
|
||||
#error This file only works on AMD64 platforms.
|
||||
#endif
|
||||
#include "nsISupports.idl"
|
||||
|
||||
#include <mpi-priv.h>
|
||||
|
||||
/*
|
||||
* MPI glue
|
||||
*
|
||||
/**
|
||||
* This interface provides support for registering Mozilla as a COM component
|
||||
* for extending the use of Mail/News through Simple MAPI.
|
||||
*
|
||||
*/
|
||||
|
||||
/* Presently, this is only used by the Montgomery arithmetic code. */
|
||||
/* c += a * b */
|
||||
void MPI_ASM_DECL s_mpv_mul_d_add_prop(const mp_digit *a, mp_size a_len,
|
||||
mp_digit b, mp_digit *c)
|
||||
{
|
||||
mp_digit w;
|
||||
mp_digit d;
|
||||
[noscript, uuid(8967fed2-c8bb-11d5-a3e9-00b0d0f3baa7)]
|
||||
interface nsIMapiSupport : nsISupports {
|
||||
|
||||
/** Initiates MAPI support
|
||||
*/
|
||||
|
||||
void initializeMAPISupport();
|
||||
|
||||
/** Shuts down the MAPI support
|
||||
*/
|
||||
|
||||
void shutdownMAPISupport();
|
||||
};
|
||||
|
||||
%{C++
|
||||
#define NS_IMAPISUPPORT_CONTRACTID "@mozilla.org/mapisupport;1"
|
||||
#define NS_IMAPISUPPORT_CLASSNAME "Mozilla MAPI Support"
|
||||
%}
|
||||
|
||||
d = s_mpv_mul_add_vec64(c, a, a_len, b);
|
||||
c += a_len;
|
||||
while (d) {
|
||||
w = c[0] + d;
|
||||
d = (w < c[0] || w < d);
|
||||
*c++ = w;
|
||||
}
|
||||
}
|
||||
|
||||
323
mozilla/mailnews/mapi/mapihook/src/Registry.cpp
Normal file
323
mozilla/mailnews/mapi/mapihook/src/Registry.cpp
Normal file
@@ -0,0 +1,323 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corp.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2001
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Krishna Mohan Khandrika <kkhandrika@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#undef _UNICODE
|
||||
#undef UNICODE
|
||||
|
||||
#include <objbase.h>
|
||||
#include "nsString.h"
|
||||
#include "Registry.h"
|
||||
|
||||
#define MAPI_PROXY_DLL_NAME "MapiProxy.dll"
|
||||
#define MAPI_STARTUP_ARG " /MAPIStartUp"
|
||||
#define MAX_SIZE 2048
|
||||
|
||||
// Size of a CLSID as a string
|
||||
const int CLSID_STRING_SIZE = 39;
|
||||
|
||||
// Proxy/Stub Dll Routines
|
||||
|
||||
typedef HRESULT (__stdcall ProxyServer)();
|
||||
|
||||
|
||||
// Convert a CLSID to a char string.
|
||||
|
||||
BOOL CLSIDtochar(const CLSID& clsid, char* szCLSID,
|
||||
int length)
|
||||
{
|
||||
LPOLESTR wszCLSID = NULL;
|
||||
|
||||
// Get CLSID
|
||||
HRESULT hr = StringFromCLSID(clsid, &wszCLSID);
|
||||
if (FAILED(hr))
|
||||
return FALSE;
|
||||
|
||||
// Covert from wide characters to non-wide.
|
||||
wcstombs(szCLSID, wszCLSID, length);
|
||||
|
||||
// Free memory.
|
||||
CoTaskMemFree(wszCLSID);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Create a key and set its value.
|
||||
|
||||
BOOL setKeyAndValue(nsCAutoString keyName, const char* subKey,
|
||||
const char* theValue)
|
||||
{
|
||||
HKEY hKey;
|
||||
BOOL retValue = TRUE;
|
||||
|
||||
nsCAutoString theKey(keyName);
|
||||
if (subKey != NULL)
|
||||
{
|
||||
theKey += "\\";
|
||||
theKey += subKey;
|
||||
}
|
||||
|
||||
// Create and open key and subkey.
|
||||
long lResult = RegCreateKeyEx(HKEY_CLASSES_ROOT, theKey.get(),
|
||||
0, NULL, REG_OPTION_NON_VOLATILE,
|
||||
KEY_ALL_ACCESS, NULL, &hKey, NULL);
|
||||
if (lResult != ERROR_SUCCESS)
|
||||
return FALSE ;
|
||||
|
||||
// Set the Value.
|
||||
if (theValue != NULL)
|
||||
{
|
||||
lResult = RegSetValueEx(hKey, NULL, 0, REG_SZ, (BYTE *)theValue,
|
||||
strlen(theValue)+1);
|
||||
if (lResult != ERROR_SUCCESS)
|
||||
retValue = FALSE;
|
||||
}
|
||||
|
||||
RegCloseKey(hKey);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Delete a key and all of its descendents.
|
||||
|
||||
LONG recursiveDeleteKey(HKEY hKeyParent, // Parent of key to delete
|
||||
const char* lpszKeyChild) // Key to delete
|
||||
{
|
||||
// Open the child.
|
||||
HKEY hKeyChild ;
|
||||
LONG lRes = RegOpenKeyEx(hKeyParent, lpszKeyChild, 0,
|
||||
KEY_ALL_ACCESS, &hKeyChild) ;
|
||||
if (lRes != ERROR_SUCCESS)
|
||||
{
|
||||
return lRes ;
|
||||
}
|
||||
|
||||
// Enumerate all of the decendents of this child.
|
||||
FILETIME time ;
|
||||
char szBuffer[MAX_SIZE] ;
|
||||
DWORD dwSize = MAX_SIZE ;
|
||||
while (RegEnumKeyEx(hKeyChild, 0, szBuffer, &dwSize, NULL,
|
||||
NULL, NULL, &time) == S_OK)
|
||||
{
|
||||
// Delete the decendents of this child.
|
||||
lRes = recursiveDeleteKey(hKeyChild, szBuffer) ;
|
||||
if (lRes != ERROR_SUCCESS)
|
||||
{
|
||||
// Cleanup before exiting.
|
||||
RegCloseKey(hKeyChild) ;
|
||||
return lRes;
|
||||
}
|
||||
dwSize = MAX_SIZE;
|
||||
}
|
||||
|
||||
// Close the child.
|
||||
RegCloseKey(hKeyChild) ;
|
||||
|
||||
// Delete this child.
|
||||
return RegDeleteKey(hKeyParent, lpszKeyChild) ;
|
||||
}
|
||||
|
||||
void RegisterProxy()
|
||||
{
|
||||
HINSTANCE h = NULL;
|
||||
ProxyServer *RegisterFunc = NULL;
|
||||
|
||||
char szModule[MAX_SIZE];
|
||||
char *pTemp = NULL;
|
||||
|
||||
HMODULE hModule = GetModuleHandle(NULL);
|
||||
DWORD dwResult = ::GetModuleFileName(hModule, szModule,
|
||||
sizeof(szModule)/sizeof(char));
|
||||
if (dwResult == 0)
|
||||
return;
|
||||
|
||||
pTemp = strrchr(szModule, '\\');
|
||||
if (pTemp == NULL)
|
||||
return;
|
||||
|
||||
*pTemp = '\0';
|
||||
nsCAutoString proxyPath(szModule);
|
||||
|
||||
proxyPath += "\\";
|
||||
proxyPath += MAPI_PROXY_DLL_NAME;
|
||||
|
||||
h = LoadLibrary(proxyPath.get());
|
||||
if (h == NULL)
|
||||
return;
|
||||
|
||||
RegisterFunc = (ProxyServer *) GetProcAddress(h, "DllRegisterServer");
|
||||
if (RegisterFunc)
|
||||
RegisterFunc();
|
||||
|
||||
FreeLibrary(h);
|
||||
}
|
||||
|
||||
void UnRegisterProxy()
|
||||
{
|
||||
HINSTANCE h = NULL;
|
||||
ProxyServer *UnRegisterFunc = NULL;
|
||||
|
||||
char szModule[MAX_SIZE];
|
||||
char *pTemp = NULL;
|
||||
|
||||
HMODULE hModule = GetModuleHandle(NULL);
|
||||
DWORD dwResult = ::GetModuleFileName(hModule, szModule,
|
||||
sizeof(szModule)/sizeof(char));
|
||||
if (dwResult == 0)
|
||||
return;
|
||||
|
||||
pTemp = strrchr(szModule, '\\');
|
||||
if (pTemp == NULL)
|
||||
return;
|
||||
|
||||
*pTemp = '\0';
|
||||
nsCAutoString proxyPath(szModule);
|
||||
|
||||
proxyPath += "\\";
|
||||
proxyPath += MAPI_PROXY_DLL_NAME;
|
||||
|
||||
h = LoadLibrary(proxyPath.get());
|
||||
if (h == NULL)
|
||||
return;
|
||||
|
||||
UnRegisterFunc = (ProxyServer *) GetProcAddress(h, "DllUnregisterServer");
|
||||
if (UnRegisterFunc)
|
||||
UnRegisterFunc();
|
||||
|
||||
FreeLibrary(h);
|
||||
}
|
||||
|
||||
// Register the component in the registry.
|
||||
|
||||
HRESULT RegisterServer(const CLSID& clsid, // Class ID
|
||||
const char* szFriendlyName, // Friendly Name
|
||||
const char* szVerIndProgID, // Programmatic
|
||||
const char* szProgID) // IDs
|
||||
{
|
||||
HMODULE hModule = GetModuleHandle(NULL);
|
||||
char szModuleName[MAX_SIZE];
|
||||
char szCLSID[CLSID_STRING_SIZE];
|
||||
|
||||
nsCAutoString independentProgId(szVerIndProgID);
|
||||
nsCAutoString progId(szProgID);
|
||||
|
||||
DWORD dwResult = ::GetModuleFileName(hModule, szModuleName,
|
||||
sizeof(szModuleName)/sizeof(char));
|
||||
|
||||
if (dwResult == 0)
|
||||
return S_FALSE;
|
||||
|
||||
nsCAutoString moduleName(szModuleName);
|
||||
nsCAutoString registryKey("CLSID\\");
|
||||
|
||||
moduleName += MAPI_STARTUP_ARG;
|
||||
|
||||
// Convert the CLSID into a char.
|
||||
|
||||
if (!CLSIDtochar(clsid, szCLSID, sizeof(szCLSID)))
|
||||
return S_FALSE;
|
||||
registryKey += szCLSID;
|
||||
|
||||
// Add the CLSID to the registry.
|
||||
if (!setKeyAndValue(registryKey, NULL, szFriendlyName))
|
||||
return S_FALSE;
|
||||
|
||||
if (!setKeyAndValue(registryKey, "LocalServer32", moduleName.get()))
|
||||
return S_FALSE;
|
||||
|
||||
// Add the ProgID subkey under the CLSID key.
|
||||
if (!setKeyAndValue(registryKey, "ProgID", szProgID))
|
||||
return S_FALSE;
|
||||
|
||||
// Add the version-independent ProgID subkey under CLSID key.
|
||||
if (!setKeyAndValue(registryKey, "VersionIndependentProgID", szVerIndProgID))
|
||||
return S_FALSE;
|
||||
|
||||
// Add the version-independent ProgID subkey under HKEY_CLASSES_ROOT.
|
||||
if (!setKeyAndValue(independentProgId, NULL, szFriendlyName))
|
||||
return S_FALSE;
|
||||
if (!setKeyAndValue(independentProgId, "CLSID", szCLSID))
|
||||
return S_FALSE;
|
||||
if (!setKeyAndValue(independentProgId, "CurVer", szProgID))
|
||||
return S_FALSE;
|
||||
|
||||
// Add the versioned ProgID subkey under HKEY_CLASSES_ROOT.
|
||||
if (!setKeyAndValue(progId, NULL, szFriendlyName))
|
||||
return S_FALSE;
|
||||
if (!setKeyAndValue(progId, "CLSID", szCLSID))
|
||||
return S_FALSE;
|
||||
|
||||
RegisterProxy();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
LONG UnregisterServer(const CLSID& clsid, // Class ID
|
||||
const char* szVerIndProgID, // Programmatic
|
||||
const char* szProgID) // IDs
|
||||
{
|
||||
LONG lResult = S_OK;
|
||||
|
||||
// Convert the CLSID into a char.
|
||||
|
||||
char szCLSID[CLSID_STRING_SIZE];
|
||||
if (!CLSIDtochar(clsid, szCLSID, sizeof(szCLSID)))
|
||||
return S_FALSE;
|
||||
|
||||
UnRegisterProxy();
|
||||
|
||||
nsCAutoString registryKey("CLSID\\");
|
||||
registryKey += szCLSID;
|
||||
|
||||
lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT, registryKey.get());
|
||||
if (lResult == ERROR_SUCCESS || lResult == ERROR_FILE_NOT_FOUND)
|
||||
return lResult;
|
||||
|
||||
registryKey += "\\LocalServer32";
|
||||
|
||||
// Delete only the path for this server.
|
||||
|
||||
lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT, registryKey.get());
|
||||
if (lResult != ERROR_SUCCESS && lResult != ERROR_FILE_NOT_FOUND)
|
||||
return lResult;
|
||||
|
||||
// Delete the version-independent ProgID Key.
|
||||
lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT, szVerIndProgID);
|
||||
if (lResult != ERROR_SUCCESS && lResult != ERROR_FILE_NOT_FOUND)
|
||||
return lResult;
|
||||
|
||||
lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT, szProgID);
|
||||
|
||||
return lResult;
|
||||
}
|
||||
@@ -1,9 +1,4 @@
|
||||
/*
|
||||
* bbsrand.c
|
||||
*
|
||||
* Test driver for routines in bbs_rand.h
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
@@ -16,14 +11,15 @@
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic library.
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael J. Fromberger.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2001
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Krishna Mohan Khandrika <kkhandrika@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@@ -38,30 +34,23 @@
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: bbsrand.c,v 1.3 2004-04-27 23:04:37 gerv%gerv.net Exp $ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <limits.h>
|
||||
#ifndef _REGISTRY_H_
|
||||
#define _REGISTRY_H_
|
||||
|
||||
#include "bbs_rand.h"
|
||||
#include <objbase.h>
|
||||
|
||||
#define NUM_TESTS 100
|
||||
// This function will register a component in the Registry.
|
||||
|
||||
int main(void)
|
||||
{
|
||||
unsigned int seed, result, ix;
|
||||
HRESULT RegisterServer(const CLSID& clsid,
|
||||
const char* szFriendlyName,
|
||||
const char* szVerIndProgID,
|
||||
const char* szProgID) ;
|
||||
|
||||
seed = time(NULL);
|
||||
bbs_srand((unsigned char *)&seed, sizeof(seed));
|
||||
// This function will unregister a component.
|
||||
|
||||
for(ix = 0; ix < NUM_TESTS; ix++) {
|
||||
result = bbs_rand();
|
||||
|
||||
printf("Test %3u: %08X\n", ix + 1, result);
|
||||
}
|
||||
HRESULT UnregisterServer(const CLSID& clsid,
|
||||
const char* szVerIndProgID,
|
||||
const char* szProgID) ;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
107
mozilla/mailnews/mapi/mapihook/src/makefile.win
Normal file
107
mozilla/mailnews/mapi/mapihook/src/makefile.win
Normal file
@@ -0,0 +1,107 @@
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2001
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Srilatha Moturi <srilatha@netscape.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH=..\..\..\..
|
||||
|
||||
MODULE = msgMapi
|
||||
MAKE_OBJ_TYPE = DLL
|
||||
LIBRARY_NAME=$(MODULE)
|
||||
MODULE_NAME = $(MODULE)
|
||||
|
||||
REQUIRES = xpcom \
|
||||
string \
|
||||
MapiProxy \
|
||||
appshell \
|
||||
windowwatcher \
|
||||
dom \
|
||||
profile \
|
||||
msgbase \
|
||||
pref \
|
||||
msgbaseutil \
|
||||
msgcompo \
|
||||
mailnews \
|
||||
necko \
|
||||
intl \
|
||||
editor \
|
||||
msgdb \
|
||||
uriloader \
|
||||
appstartup \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)\config\config.mak>
|
||||
############################################################################
|
||||
|
||||
LCFLAGS=-DUNICODE -D_UNICODE
|
||||
|
||||
|
||||
|
||||
OBJS= \
|
||||
..\build\$(OBJDIR)\msgMapi_i.obj \
|
||||
.\$(OBJDIR)\msgMapiFactory.obj \
|
||||
.\$(OBJDIR)\msgMapiHook.obj \
|
||||
.\$(OBJDIR)\msgMapiImp.obj \
|
||||
.\$(OBJDIR)\msgMapiMain.obj \
|
||||
.\$(OBJDIR)\msgMapiSupport.obj \
|
||||
.\$(OBJDIR)\nsMapiRegistry.obj \
|
||||
.\$(OBJDIR)\nsMapiRegistryUtils.obj \
|
||||
.\$(OBJDIR)\Registry.obj \
|
||||
$(NULL)
|
||||
|
||||
|
||||
|
||||
LLIBS= \
|
||||
$(DIST)\lib\xpcom.lib \
|
||||
$(DIST)\lib\msgbsutl.lib \
|
||||
$(LIBNSPR) \
|
||||
$(NULL)
|
||||
|
||||
WIN_LIBS= \
|
||||
ole32.lib \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS= \
|
||||
msgMapiFactory.h \
|
||||
msgMapiHook.h \
|
||||
msgMapiImp.h \
|
||||
msgMapiMain.h \
|
||||
msgMapiSupport.h \
|
||||
nsMapiRegistry.h \
|
||||
nsMapiRegistryUtils.h \
|
||||
Registry.h \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
118
mozilla/mailnews/mapi/mapihook/src/msgMapiFactory.cpp
Normal file
118
mozilla/mailnews/mapi/mapihook/src/msgMapiFactory.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corp.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2001
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Krishna Mohan Khandrika (kkhandrika@netscape.com)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#undef UNICODE
|
||||
#undef _UNICODE
|
||||
|
||||
#include "msgMapiFactory.h"
|
||||
#include "msgMapiImp.h"
|
||||
#include "msgMapi.h"
|
||||
|
||||
CMapiFactory ::CMapiFactory()
|
||||
: m_cRef(1)
|
||||
{
|
||||
}
|
||||
|
||||
CMapiFactory::~CMapiFactory()
|
||||
{
|
||||
}
|
||||
|
||||
STDMETHODIMP CMapiFactory::QueryInterface(const IID& aIid, void** aPpv)
|
||||
{
|
||||
if ((aIid == IID_IUnknown) || (aIid == IID_IClassFactory))
|
||||
{
|
||||
*aPpv = static_cast<IClassFactory*>(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
*aPpv = nsnull;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
reinterpret_cast<IUnknown*>(*aPpv)->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) CMapiFactory::AddRef()
|
||||
{
|
||||
return (PR_AtomicIncrement(&m_cRef));
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) CMapiFactory::Release()
|
||||
{
|
||||
PRInt32 temp;
|
||||
temp = PR_AtomicDecrement(&m_cRef);
|
||||
if (m_cRef == 0)
|
||||
{
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
STDMETHODIMP CMapiFactory::CreateInstance(IUnknown* aUnknownOuter,
|
||||
const IID& aIid,
|
||||
void** aPpv)
|
||||
{
|
||||
// Cannot aggregate.
|
||||
|
||||
if (aUnknownOuter != nsnull)
|
||||
{
|
||||
return CLASS_E_NOAGGREGATION ;
|
||||
}
|
||||
|
||||
// Create component.
|
||||
|
||||
CMapiImp* pImp = new CMapiImp();
|
||||
if (pImp == nsnull)
|
||||
{
|
||||
return E_OUTOFMEMORY ;
|
||||
}
|
||||
|
||||
// Get the requested interface.
|
||||
HRESULT hr = pImp->QueryInterface(aIid, aPpv);
|
||||
|
||||
// Release the IUnknown pointer.
|
||||
// (If QueryInterface failed, component will delete itself.)
|
||||
|
||||
pImp->Release();
|
||||
return hr;
|
||||
}
|
||||
|
||||
STDMETHODIMP CMapiFactory::LockServer(PRBool aLock)
|
||||
{
|
||||
return S_OK ;
|
||||
}
|
||||
@@ -1,9 +1,4 @@
|
||||
/*
|
||||
* dec2hex.c
|
||||
*
|
||||
* Convert decimal integers into hexadecimal
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
@@ -16,14 +11,14 @@
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic library.
|
||||
* The Original Code is Mozilla
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael J. Fromberger.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* Netscape Communications Corp.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2001
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Contributor(s): Krishna Mohan Khandrika (kkhandrika@netscape.com)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@@ -38,34 +33,37 @@
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: dec2hex.c,v 1.3 2004-04-27 23:04:37 gerv%gerv.net Exp $ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifndef MSG_MAPI_FACTORY_H
|
||||
#define MSG_MAPI_FACTORY_H
|
||||
|
||||
#include "mpi.h"
|
||||
#include <windows.h>
|
||||
#include <objbase.h>
|
||||
#include "nspr.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
|
||||
class CMapiFactory : public IClassFactory
|
||||
{
|
||||
mp_int a;
|
||||
char *buf;
|
||||
int len;
|
||||
public :
|
||||
|
||||
if(argc < 2) {
|
||||
fprintf(stderr, "Usage: %s <a>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
// IUnknown
|
||||
|
||||
mp_init(&a); mp_read_radix(&a, argv[1], 10);
|
||||
len = mp_radix_size(&a, 16);
|
||||
buf = malloc(len);
|
||||
mp_toradix(&a, buf, 16);
|
||||
STDMETHODIMP QueryInterface (REFIID aIid, void** aPpv);
|
||||
STDMETHODIMP_(ULONG) AddRef(void);
|
||||
STDMETHODIMP_(ULONG) Release(void);
|
||||
|
||||
printf("%s\n", buf);
|
||||
// IClassFactory
|
||||
|
||||
free(buf);
|
||||
mp_clear(&a);
|
||||
STDMETHODIMP CreateInstance (LPUNKNOWN aUnkOuter, REFIID aIid, void **aPpv);
|
||||
STDMETHODIMP LockServer (BOOL aLock);
|
||||
|
||||
CMapiFactory ();
|
||||
~CMapiFactory ();
|
||||
|
||||
private :
|
||||
|
||||
PRInt32 m_cRef;
|
||||
};
|
||||
|
||||
#endif // MSG_MAPI_FACTORY_H
|
||||
|
||||
return 0;
|
||||
}
|
||||
777
mozilla/mailnews/mapi/mapihook/src/msgMapiHook.cpp
Normal file
777
mozilla/mailnews/mapi/mapihook/src/msgMapiHook.cpp
Normal file
@@ -0,0 +1,777 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corp.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2001
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Krishna Mohan Khandrika (kkhandrika@netscape.com)
|
||||
* Contributor(s): Srilatha Moturi (srilatha@netscape.com)
|
||||
* Contributor(s): Rajiv Dayal (rdayal@netscape.com)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#define MAPI_STARTUP_ARG "/MAPIStartUp"
|
||||
|
||||
#define MAPI_STARTUP_ARG "/MAPIStartUp"
|
||||
|
||||
#include <mapidefs.h>
|
||||
#include <mapi.h>
|
||||
#include <tchar.h>
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsIPromptService.h"
|
||||
#include "nsAppShellCIDs.h"
|
||||
#include "nsIDOMWindowInternal.h"
|
||||
#include "nsIAppShellService.h"
|
||||
#include "nsINativeAppSupport.h"
|
||||
#include "nsICmdLineService.h"
|
||||
#include "nsIProfileInternal.h"
|
||||
#include "nsIMsgAccountManager.h"
|
||||
#include "nsIDOMWindowInternal.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsMsgBaseCID.h"
|
||||
#include "nsIStringBundle.h"
|
||||
#include "nsIPref.h"
|
||||
#include "nsString.h"
|
||||
|
||||
#include "nsIMsgAttachment.h"
|
||||
#include "nsIMsgCompFields.h"
|
||||
#include "nsIMsgComposeParams.h"
|
||||
#include "nsIMsgCompose.h"
|
||||
#include "nsMsgCompCID.h"
|
||||
#include "nsIMsgSend.h"
|
||||
#include "nsIProxyObjectManager.h"
|
||||
#include "nsIMsgComposeService.h"
|
||||
#include "nsProxiedService.h"
|
||||
#include "nsSpecialSystemDirectory.h"
|
||||
#include "nsMsgI18N.h"
|
||||
|
||||
#include "msgMapi.h"
|
||||
#include "msgMapiHook.h"
|
||||
#include "msgMapiSupport.h"
|
||||
#include "msgMapiMain.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
static NS_DEFINE_CID(kCmdLineServiceCID, NS_COMMANDLINE_SERVICE_CID);
|
||||
|
||||
class nsMAPISendListener : public nsIMsgSendListener
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~nsMAPISendListener() { }
|
||||
|
||||
// nsISupports interface
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
/* void OnStartSending (in string aMsgID, in PRUint32 aMsgSize); */
|
||||
NS_IMETHOD OnStartSending(const char *aMsgID, PRUint32 aMsgSize) { return NS_OK; }
|
||||
|
||||
/* void OnProgress (in string aMsgID, in PRUint32 aProgress, in PRUint32 aProgressMax); */
|
||||
NS_IMETHOD OnProgress(const char *aMsgID, PRUint32 aProgress, PRUint32 aProgressMax) { return NS_OK;}
|
||||
|
||||
/* void OnStatus (in string aMsgID, in wstring aMsg); */
|
||||
NS_IMETHOD OnStatus(const char *aMsgID, const PRUnichar *aMsg) { return NS_OK;}
|
||||
|
||||
/* void OnStopSending (in string aMsgID, in nsresult aStatus, in wstring aMsg, in nsIFileSpec returnFileSpec); */
|
||||
NS_IMETHOD OnStopSending(const char *aMsgID, nsresult aStatus, const PRUnichar *aMsg,
|
||||
nsIFileSpec *returnFileSpec) {
|
||||
m_done = PR_TRUE;
|
||||
HANDLE hEvent = CreateEvent (NULL, FALSE, FALSE, (LPCTSTR) MAPI_SENDCOMPLETE_EVENT) ;
|
||||
SetEvent (hEvent) ;
|
||||
CloseHandle (hEvent) ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
/* void OnSendNotPerformed */
|
||||
NS_IMETHOD OnSendNotPerformed(const char *aMsgID, nsresult aStatus)
|
||||
{
|
||||
return OnStopSending(aMsgID, aStatus, nsnull, nsnull) ;
|
||||
}
|
||||
|
||||
/* void OnGetDraftFolderURI (); */
|
||||
NS_IMETHOD OnGetDraftFolderURI(const char *aFolderURI) {return NS_OK;}
|
||||
|
||||
static nsresult CreateMAPISendListener( nsIMsgSendListener **ppListener);
|
||||
|
||||
PRBool IsDone() { return m_done ; }
|
||||
|
||||
protected :
|
||||
nsMAPISendListener() {
|
||||
NS_INIT_REFCNT();
|
||||
m_done = PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool m_done;
|
||||
};
|
||||
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(nsMAPISendListener, nsIMsgSendListener)
|
||||
|
||||
nsresult nsMAPISendListener::CreateMAPISendListener( nsIMsgSendListener **ppListener)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(ppListener) ;
|
||||
|
||||
*ppListener = new nsMAPISendListener();
|
||||
if (! *ppListener)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(*ppListener);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool nsMapiHook::isMapiService = PR_FALSE;
|
||||
|
||||
PRBool nsMapiHook::Initialize()
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINativeAppSupport> native;
|
||||
|
||||
nsCOMPtr<nsICmdLineService> cmdLineArgs(do_GetService(kCmdLineServiceCID, &rv));
|
||||
if (NS_FAILED(rv)) return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIAppShellService> appShell (do_GetService( "@mozilla.org/appshell/appShellService;1", &rv));
|
||||
if (NS_FAILED(rv)) return PR_FALSE;
|
||||
|
||||
rv = appShell->GetNativeAppSupport( getter_AddRefs( native ));
|
||||
if (NS_FAILED(rv)) return PR_FALSE;
|
||||
|
||||
rv = native->EnsureProfile(cmdLineArgs);
|
||||
if (NS_FAILED(rv)) return PR_FALSE;
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void nsMapiHook::CleanUp()
|
||||
{
|
||||
// This routine will be fully implemented in future
|
||||
// to cleanup mapi related stuff inside mozilla code.
|
||||
}
|
||||
|
||||
PRBool nsMapiHook::DisplayLoginDialog(PRBool aLogin, PRUnichar **aUsername, \
|
||||
PRUnichar **aPassword)
|
||||
{
|
||||
nsresult rv;
|
||||
PRBool btnResult = PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIAppShellService> appShell(do_GetService( "@mozilla.org/appshell/appShellService;1", &rv));
|
||||
if (NS_FAILED(rv) || !appShell) return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIPromptService> dlgService(do_GetService("@mozilla.org/embedcomp/prompt-service;1", &rv));
|
||||
if (NS_SUCCEEDED(rv) && dlgService)
|
||||
{
|
||||
nsCOMPtr<nsIStringBundleService> bundleService(do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv));
|
||||
if (NS_FAILED(rv) || !bundleService) return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIStringBundle> bundle;
|
||||
rv = bundleService->CreateBundle(MAPI_PROPERTIES_CHROME, getter_AddRefs(bundle));
|
||||
if (NS_FAILED(rv) || !bundle) return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIStringBundle> brandBundle;
|
||||
rv = bundleService->CreateBundle(
|
||||
"chrome://global/locale/brand.properties",
|
||||
getter_AddRefs(brandBundle));
|
||||
if (NS_FAILED(rv)) return PR_FALSE;
|
||||
|
||||
nsXPIDLString brandName;
|
||||
rv = brandBundle->GetStringFromName(
|
||||
NS_LITERAL_STRING("brandShortName").get(),
|
||||
getter_Copies(brandName));
|
||||
if (NS_FAILED(rv)) return PR_FALSE;
|
||||
|
||||
nsXPIDLString loginTitle;
|
||||
const PRUnichar *brandStrings[] = { brandName.get() };
|
||||
NS_NAMED_LITERAL_STRING(loginTitlePropertyTag, "loginTitle");
|
||||
const PRUnichar *dTitlePropertyTag = loginTitlePropertyTag.get();
|
||||
rv = bundle->FormatStringFromName(dTitlePropertyTag, brandStrings, 1,
|
||||
getter_Copies(loginTitle));
|
||||
if (NS_FAILED(rv)) return PR_FALSE;
|
||||
|
||||
if (aLogin)
|
||||
{
|
||||
nsXPIDLString loginText;
|
||||
rv = bundle->GetStringFromName(NS_LITERAL_STRING("loginTextwithName").get(),
|
||||
getter_Copies(loginText));
|
||||
if (NS_FAILED(rv) || !loginText) return PR_FALSE;
|
||||
|
||||
|
||||
|
||||
rv = dlgService->PromptUsernameAndPassword(nsnull, loginTitle,
|
||||
loginText, aUsername, aPassword,
|
||||
nsnull, PR_FALSE, &btnResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
//nsString loginString;
|
||||
nsXPIDLString loginText;
|
||||
const PRUnichar *userNameStrings[] = { *aUsername };
|
||||
|
||||
NS_NAMED_LITERAL_STRING(loginTextPropertyTag, "loginText");
|
||||
const PRUnichar *dpropertyTag = loginTextPropertyTag.get();
|
||||
rv = bundle->FormatStringFromName(dpropertyTag, userNameStrings, 1,
|
||||
getter_Copies(loginText));
|
||||
if (NS_FAILED(rv)) return PR_FALSE;
|
||||
|
||||
rv = dlgService->PromptPassword(nsnull, loginTitle, loginText,
|
||||
aPassword, nsnull, PR_FALSE, &btnResult);
|
||||
}
|
||||
}
|
||||
|
||||
return btnResult;
|
||||
}
|
||||
|
||||
PRBool nsMapiHook::VerifyUserName(const PRUnichar *aUsername, char **aIdKey)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if (aUsername == nsnull)
|
||||
return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIMsgAccountManager> accountManager(do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv));
|
||||
if (NS_FAILED(rv)) return PR_FALSE;
|
||||
nsCOMPtr<nsISupportsArray> identities;
|
||||
rv = accountManager->GetAllIdentities(getter_AddRefs(identities));
|
||||
if (NS_FAILED(rv)) return PR_FALSE;
|
||||
PRUint32 numIndentities;
|
||||
identities->Count(&numIndentities);
|
||||
|
||||
for (PRUint32 i = 0; i < numIndentities; i++)
|
||||
{
|
||||
// convert supports->Identity
|
||||
nsCOMPtr<nsISupports> thisSupports;
|
||||
rv = identities->GetElementAt(i, getter_AddRefs(thisSupports));
|
||||
if (NS_FAILED(rv)) continue;
|
||||
nsCOMPtr<nsIMsgIdentity> thisIdentity(do_QueryInterface(thisSupports, &rv));
|
||||
if (NS_SUCCEEDED(rv) && thisIdentity)
|
||||
{
|
||||
nsXPIDLCString email;
|
||||
rv = thisIdentity->GetEmail(getter_Copies(email));
|
||||
if (NS_FAILED(rv)) continue;
|
||||
|
||||
// get the username from the email and compare with the username
|
||||
nsCAutoString aEmail(email.get());
|
||||
PRInt32 index = aEmail.FindChar('@');
|
||||
if (index != -1)
|
||||
aEmail.Truncate(index);
|
||||
|
||||
if (nsDependentString(aUsername) == NS_ConvertASCIItoUCS2(aEmail)) // == overloaded
|
||||
return NS_SUCCEEDED(thisIdentity->GetKey(aIdKey));
|
||||
}
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsMapiHook::IsBlindSendAllowed()
|
||||
{
|
||||
PRBool enabled = PR_FALSE;
|
||||
PRBool warn = PR_TRUE;
|
||||
nsCOMPtr<nsIPref> prefs = do_GetService(NS_PREF_CONTRACTID);
|
||||
if (prefs) {
|
||||
prefs->GetBoolPref(PREF_MAPI_WARN_PRIOR_TO_BLIND_SEND,&warn);
|
||||
prefs->GetBoolPref(PREF_MAPI_BLIND_SEND_ENABLED,&enabled);
|
||||
}
|
||||
if (!enabled)
|
||||
return PR_FALSE;
|
||||
|
||||
if (!warn)
|
||||
return PR_TRUE; // Everything is okay.
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIStringBundleService> bundleService(do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv));
|
||||
if (NS_FAILED(rv) || !bundleService) return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIStringBundle> bundle;
|
||||
rv = bundleService->CreateBundle(MAPI_PROPERTIES_CHROME, getter_AddRefs(bundle));
|
||||
if (NS_FAILED(rv) || !bundle) return PR_FALSE;
|
||||
|
||||
nsXPIDLString warningMsg;
|
||||
rv = bundle->GetStringFromName(NS_LITERAL_STRING("mapiBlindSendWarning").get(),
|
||||
getter_Copies(warningMsg));
|
||||
if (NS_FAILED(rv)) return PR_FALSE;
|
||||
|
||||
nsXPIDLString dontShowAgainMessage;
|
||||
rv = bundle->GetStringFromName(NS_LITERAL_STRING("mapiBlindSendDontShowAgain").get(),
|
||||
getter_Copies(dontShowAgainMessage));
|
||||
if (NS_FAILED(rv)) return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIPromptService> dlgService(do_GetService("@mozilla.org/embedcomp/prompt-service;1", &rv));
|
||||
if (NS_FAILED(rv) || !dlgService) return PR_FALSE;
|
||||
|
||||
PRBool continueToWarn = PR_TRUE;
|
||||
PRBool okayToContinue = PR_FALSE;
|
||||
dlgService->ConfirmCheck(nsnull, nsnull, warningMsg, dontShowAgainMessage, &continueToWarn, &okayToContinue);
|
||||
|
||||
if (!continueToWarn && okayToContinue && prefs)
|
||||
prefs->SetBoolPref(PREF_MAPI_WARN_PRIOR_TO_BLIND_SEND,PR_FALSE);
|
||||
|
||||
return okayToContinue;
|
||||
|
||||
}
|
||||
|
||||
// this is used for Send without UI
|
||||
nsresult nsMapiHook::BlindSendMail (unsigned long aSession, nsIMsgCompFields * aCompFields)
|
||||
{
|
||||
nsresult rv = NS_OK ;
|
||||
|
||||
if (!IsBlindSendAllowed())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
/** create nsIMsgComposeParams obj and other fields to populate it **/
|
||||
|
||||
// get parent window
|
||||
nsCOMPtr<nsIAppShellService> appService = do_GetService( "@mozilla.org/appshell/appShellService;1", &rv);
|
||||
if (NS_FAILED(rv)|| (!appService) ) return rv ;
|
||||
|
||||
nsCOMPtr<nsIDOMWindowInternal> hiddenWindow;
|
||||
rv = appService->GetHiddenDOMWindow(getter_AddRefs(hiddenWindow));
|
||||
|
||||
if ( NS_FAILED(rv) ) return rv ;
|
||||
|
||||
// smtp password and Logged in used IdKey from MapiConfig (session obj)
|
||||
nsMAPIConfiguration * pMapiConfig = nsMAPIConfiguration::GetMAPIConfiguration() ;
|
||||
if (!pMapiConfig) return NS_ERROR_FAILURE ; // get the singelton obj
|
||||
PRUnichar * password = pMapiConfig->GetPassword(aSession) ;
|
||||
// password
|
||||
nsCAutoString smtpPassword ;
|
||||
smtpPassword.AssignWithConversion (password) ;
|
||||
// Id key
|
||||
char * MsgIdKey = pMapiConfig->GetIdKey(aSession) ;
|
||||
|
||||
// get the MsgIdentity for the above key using AccountManager
|
||||
nsCOMPtr <nsIMsgAccountManager> accountManager = do_GetService (NS_MSGACCOUNTMANAGER_CONTRACTID) ;
|
||||
if (NS_FAILED(rv) || (!accountManager) ) return rv ;
|
||||
|
||||
nsCOMPtr <nsIMsgIdentity> pMsgId ;
|
||||
rv = accountManager->GetIdentity (MsgIdKey, getter_AddRefs(pMsgId)) ;
|
||||
if (NS_FAILED(rv) ) return rv ;
|
||||
|
||||
// create a send listener to get back the send status
|
||||
nsCOMPtr <nsIMsgSendListener> sendListener ;
|
||||
rv = nsMAPISendListener::CreateMAPISendListener(getter_AddRefs(sendListener)) ;
|
||||
if (NS_FAILED(rv) || (!sendListener) ) return rv;
|
||||
|
||||
// create the compose params object
|
||||
nsCOMPtr<nsIMsgComposeParams> pMsgComposeParams (do_CreateInstance(NS_MSGCOMPOSEPARAMS_CONTRACTID, &rv));
|
||||
if (NS_FAILED(rv) || (!pMsgComposeParams) ) return rv ;
|
||||
|
||||
// populate the compose params
|
||||
pMsgComposeParams->SetType(nsIMsgCompType::New);
|
||||
pMsgComposeParams->SetFormat(nsIMsgCompFormat::Default);
|
||||
pMsgComposeParams->SetIdentity(pMsgId);
|
||||
pMsgComposeParams->SetComposeFields(aCompFields);
|
||||
pMsgComposeParams->SetSendListener(sendListener) ;
|
||||
pMsgComposeParams->SetSmtpPassword(smtpPassword.get());
|
||||
|
||||
// create the nsIMsgCompose object to send the object
|
||||
nsCOMPtr<nsIMsgCompose> pMsgCompose (do_CreateInstance(NS_MSGCOMPOSE_CONTRACTID, &rv));
|
||||
if (NS_FAILED(rv) || (!pMsgCompose) ) return rv ;
|
||||
|
||||
/** initialize nsIMsgCompose, Send the message, wait for send completion response **/
|
||||
|
||||
rv = pMsgCompose->Initialize(hiddenWindow, pMsgComposeParams) ;
|
||||
if (NS_FAILED(rv)) return rv ;
|
||||
|
||||
pMsgCompose->SendMsg(nsIMsgSend::nsMsgDeliverNow, pMsgId, nsnull) ;
|
||||
if (NS_FAILED(rv)) return rv ;
|
||||
|
||||
// assign to interface pointer from nsCOMPtr to facilitate typecast below
|
||||
nsIMsgSendListener * pSendListener = sendListener ;
|
||||
|
||||
// we need to wait here to make sure that we return only after send is completed
|
||||
// so we will have a event loop here which will process the events till the Send IsDone.
|
||||
nsCOMPtr<nsIEventQueueService> pEventQService = do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv);
|
||||
nsCOMPtr<nsIEventQueue> eventQueue;
|
||||
pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD,getter_AddRefs(eventQueue));
|
||||
while ( !((nsMAPISendListener *) pSendListener)->IsDone() )
|
||||
eventQueue->ProcessPendingEvents();
|
||||
|
||||
return rv ;
|
||||
}
|
||||
|
||||
// this is used to populate comp fields with Unicode data
|
||||
nsresult nsMapiHook::PopulateCompFields(lpnsMapiMessage aMessage,
|
||||
nsIMsgCompFields * aCompFields)
|
||||
{
|
||||
nsresult rv = NS_OK ;
|
||||
|
||||
if (aMessage->lpOriginator)
|
||||
{
|
||||
PRUnichar * From = aMessage->lpOriginator->lpszAddress ;
|
||||
aCompFields->SetFrom (From) ;
|
||||
}
|
||||
|
||||
nsAutoString To ;
|
||||
nsAutoString Cc ;
|
||||
nsAutoString Bcc ;
|
||||
|
||||
nsAutoString Comma ;
|
||||
Comma.AssignWithConversion(",");
|
||||
|
||||
if (aMessage->lpRecips)
|
||||
{
|
||||
for (int i=0 ; i < (int) aMessage->nRecipCount ; i++)
|
||||
{
|
||||
if (aMessage->lpRecips[i].lpszAddress)
|
||||
{
|
||||
switch (aMessage->lpRecips[i].ulRecipClass)
|
||||
{
|
||||
case MAPI_TO :
|
||||
if (To.Length() > 0)
|
||||
To += Comma ;
|
||||
To += (PRUnichar *) aMessage->lpRecips[i].lpszAddress ;
|
||||
break ;
|
||||
|
||||
case MAPI_CC :
|
||||
if (Cc.Length() > 0)
|
||||
Cc += Comma ;
|
||||
Cc += (PRUnichar *) aMessage->lpRecips[i].lpszAddress ;
|
||||
break ;
|
||||
|
||||
case MAPI_BCC :
|
||||
if (Bcc.Length() > 0)
|
||||
Bcc += Comma ;
|
||||
Bcc += (PRUnichar *) aMessage->lpRecips[i].lpszAddress ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set To, Cc, Bcc
|
||||
aCompFields->SetTo (To.get()) ;
|
||||
aCompFields->SetCc (Cc.get()) ;
|
||||
aCompFields->SetBcc (Bcc.get()) ;
|
||||
|
||||
// set subject
|
||||
if (aMessage->lpszSubject)
|
||||
{
|
||||
PRUnichar * Subject = aMessage->lpszSubject ;
|
||||
aCompFields->SetSubject(Subject) ;
|
||||
}
|
||||
|
||||
// handle attachments as File URL
|
||||
rv = HandleAttachments (aCompFields, aMessage->nFileCount, aMessage->lpFiles, PR_TRUE) ;
|
||||
if (NS_FAILED(rv)) return rv ;
|
||||
|
||||
// set body
|
||||
if (aMessage->lpszNoteText)
|
||||
{
|
||||
PRUnichar * Body = aMessage->lpszNoteText ;
|
||||
rv = aCompFields->SetBody(Body) ;
|
||||
}
|
||||
|
||||
#ifdef RAJIV_DEBUG
|
||||
// testing what all was set in CompFields
|
||||
printf ("To : %S \n", To.get()) ;
|
||||
printf ("CC : %S \n", Cc.get() ) ;
|
||||
printf ("BCC : %S \n", Bcc.get() ) ;
|
||||
#endif
|
||||
|
||||
return rv ;
|
||||
|
||||
}
|
||||
|
||||
nsresult nsMapiHook::HandleAttachments (nsIMsgCompFields * aCompFields, PRInt32 aFileCount,
|
||||
lpnsMapiFileDesc aFiles, BOOL aIsUnicode)
|
||||
{
|
||||
nsresult rv = NS_OK ;
|
||||
|
||||
nsCAutoString Attachments ;
|
||||
nsCAutoString TempFiles ;
|
||||
|
||||
nsCOMPtr <nsILocalFile> pFile = do_CreateInstance (NS_LOCAL_FILE_CONTRACTID, &rv) ;
|
||||
if (NS_FAILED(rv) || (!pFile) ) return rv ;
|
||||
|
||||
for (int i=0 ; i < aFileCount ; i++)
|
||||
{
|
||||
if (aFiles[i].lpszPathName)
|
||||
{
|
||||
// check if attachment exists
|
||||
if (aIsUnicode)
|
||||
pFile->InitWithUnicodePath (aFiles[i].lpszPathName) ;
|
||||
else
|
||||
pFile->InitWithPath ((char *) aFiles[i].lpszPathName) ;
|
||||
PRBool bExist ;
|
||||
rv = pFile->Exists(&bExist) ;
|
||||
if (NS_FAILED(rv) || (!bExist) ) return NS_ERROR_FILE_TARGET_DOES_NOT_EXIST ;
|
||||
|
||||
// create Msg attachment object
|
||||
nsCOMPtr<nsIMsgAttachment> attachment = do_CreateInstance(NS_MSGATTACHMENT_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv) || (!attachment) ) return rv ;
|
||||
|
||||
// set url
|
||||
nsXPIDLCString pURL ;
|
||||
NS_GetURLSpecFromFile(pFile, getter_Copies(pURL));
|
||||
attachment->SetUrl(pURL) ;
|
||||
|
||||
if (aFiles[i].lpszFileName)
|
||||
{
|
||||
if (! aIsUnicode)
|
||||
{
|
||||
nsAutoString realFileName ;
|
||||
realFileName.AssignWithConversion ((char *) aFiles[i].lpszFileName) ;
|
||||
attachment->SetName(realFileName.get()) ;
|
||||
// attachment->SetName( (nsDependentString(aFiles[i].lpszFileName)).get() );
|
||||
}
|
||||
else
|
||||
attachment->SetName(aFiles[i].lpszFileName) ;
|
||||
}
|
||||
|
||||
attachment->SetTemporary(PR_FALSE) ;
|
||||
|
||||
rv = aCompFields->AddAttachment (attachment);
|
||||
}
|
||||
}
|
||||
return rv ;
|
||||
}
|
||||
|
||||
|
||||
// this is used to convert non Unicode data and then populate comp fields
|
||||
nsresult nsMapiHook::PopulateCompFieldsWithConversion(lpnsMapiMessage aMessage,
|
||||
nsIMsgCompFields * aCompFields)
|
||||
{
|
||||
nsresult rv = NS_OK ;
|
||||
|
||||
if (aMessage->lpOriginator)
|
||||
{
|
||||
nsAutoString From ;
|
||||
From.AssignWithConversion((char *) aMessage->lpOriginator->lpszAddress);
|
||||
aCompFields->SetFrom (From.get()) ;
|
||||
}
|
||||
|
||||
nsAutoString To ;
|
||||
nsAutoString Cc ;
|
||||
nsAutoString Bcc ;
|
||||
|
||||
nsAutoString Comma ;
|
||||
Comma.AssignWithConversion(",");
|
||||
|
||||
if (aMessage->lpRecips)
|
||||
{
|
||||
for (int i=0 ; i < (int) aMessage->nRecipCount ; i++)
|
||||
{
|
||||
if (aMessage->lpRecips[i].lpszAddress)
|
||||
{
|
||||
switch (aMessage->lpRecips[i].ulRecipClass)
|
||||
{
|
||||
case MAPI_TO :
|
||||
if (To.Length() > 0)
|
||||
To += Comma ;
|
||||
To.AppendWithConversion ((char *) aMessage->lpRecips[i].lpszAddress);
|
||||
break ;
|
||||
|
||||
case MAPI_CC :
|
||||
if (Cc.Length() > 0)
|
||||
Cc += Comma ;
|
||||
Cc.AppendWithConversion ((char *) aMessage->lpRecips[i].lpszAddress);
|
||||
break ;
|
||||
|
||||
case MAPI_BCC :
|
||||
if (Bcc.Length() > 0)
|
||||
Bcc += Comma ;
|
||||
Bcc.AppendWithConversion ((char *) aMessage->lpRecips[i].lpszAddress) ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set To, Cc, Bcc
|
||||
aCompFields->SetTo (To.get()) ;
|
||||
aCompFields->SetCc (Cc.get()) ;
|
||||
aCompFields->SetBcc (Bcc.get()) ;
|
||||
|
||||
nsCAutoString platformCharSet;
|
||||
// set subject
|
||||
if (aMessage->lpszSubject)
|
||||
{
|
||||
nsAutoString Subject ;
|
||||
if (platformCharSet.IsEmpty())
|
||||
platformCharSet.Assign(nsMsgI18NFileSystemCharset());
|
||||
rv = ConvertToUnicode(platformCharSet.get(), (char *) aMessage->lpszSubject, Subject);
|
||||
if (NS_FAILED(rv)) return rv ;
|
||||
aCompFields->SetSubject(Subject.get()) ;
|
||||
}
|
||||
|
||||
// handle attachments as File URL
|
||||
rv = HandleAttachments (aCompFields, aMessage->nFileCount, aMessage->lpFiles, PR_FALSE) ;
|
||||
if (NS_FAILED(rv)) return rv ;
|
||||
|
||||
// set body
|
||||
if (aMessage->lpszNoteText)
|
||||
{
|
||||
nsAutoString Body ;
|
||||
if (platformCharSet.IsEmpty())
|
||||
platformCharSet.Assign(nsMsgI18NFileSystemCharset());
|
||||
rv = ConvertToUnicode(platformCharSet.get(), (char *) aMessage->lpszNoteText, Body);
|
||||
if (NS_FAILED(rv)) return rv ;
|
||||
rv = aCompFields->SetBody(Body.get()) ;
|
||||
}
|
||||
|
||||
#ifdef RAJIV_DEBUG
|
||||
// testing what all was set in CompFields
|
||||
printf ("To : %S \n", To.get()) ;
|
||||
printf ("CC : %S \n", Cc.get() ) ;
|
||||
printf ("BCC : %S \n", Bcc.get() ) ;
|
||||
#endif
|
||||
|
||||
return rv ;
|
||||
}
|
||||
|
||||
// this is used to populate the docs as attachments in the Comp fields for Send Documents
|
||||
nsresult nsMapiHook::PopulateCompFieldsForSendDocs(nsIMsgCompFields * aCompFields, ULONG aFlags,
|
||||
PRUnichar * aDelimChar, PRUnichar * aFilePaths)
|
||||
{
|
||||
nsAutoString strDelimChars ;
|
||||
nsString strFilePaths;
|
||||
nsresult rv = NS_OK ;
|
||||
|
||||
if (aFlags & MAPI_UNICODE)
|
||||
{
|
||||
if (aDelimChar)
|
||||
strDelimChars.Assign (aDelimChar) ;
|
||||
if (aFilePaths)
|
||||
strFilePaths.Assign (aFilePaths) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (aDelimChar)
|
||||
strDelimChars.AssignWithConversion ((char*) aDelimChar) ;
|
||||
if (aFilePaths)
|
||||
strFilePaths.AssignWithConversion ((char *) aFilePaths) ;
|
||||
}
|
||||
|
||||
// check for comma in filename
|
||||
if (strDelimChars.Find (",") == kNotFound) // if comma is not in the delimiter specified by user
|
||||
{
|
||||
if (strFilePaths.Find(",") != kNotFound) // if comma found in filenames return error
|
||||
return NS_ERROR_FILE_INVALID_PATH ;
|
||||
}
|
||||
|
||||
nsCString Attachments ;
|
||||
|
||||
// only 1 file is to be sent, no delim specified
|
||||
if ((!strDelimChars.Length()) && (strFilePaths.Length()>0))
|
||||
{
|
||||
nsCOMPtr <nsILocalFile> pFile = do_CreateInstance (NS_LOCAL_FILE_CONTRACTID, &rv) ;
|
||||
if (NS_FAILED(rv) || (!pFile) ) return rv ;
|
||||
pFile->InitWithUnicodePath (strFilePaths.get()) ;
|
||||
|
||||
PRBool bExist ;
|
||||
rv = pFile->Exists(&bExist) ;
|
||||
if (NS_FAILED(rv) || (!bExist) ) return NS_ERROR_FILE_TARGET_DOES_NOT_EXIST ;
|
||||
|
||||
nsXPIDLCString pURL ;
|
||||
NS_GetURLSpecFromFile(pFile, getter_Copies(pURL));
|
||||
if (pURL)
|
||||
Attachments.Assign(pURL) ;
|
||||
|
||||
// set attachments for comp field and return
|
||||
rv = aCompFields->SetAttachments (Attachments.get());
|
||||
return rv ;
|
||||
}
|
||||
|
||||
// multiple files to be sent, delim specified
|
||||
nsCOMPtr <nsILocalFile> pFile = do_CreateInstance (NS_LOCAL_FILE_CONTRACTID, &rv) ;
|
||||
if (NS_FAILED(rv) || (!pFile) ) return rv ;
|
||||
PRInt32 offset = 0 ;
|
||||
PRInt32 FilePathsLen = strFilePaths.Length() ;
|
||||
if (FilePathsLen)
|
||||
{
|
||||
PRUnichar * newFilePaths = (PRUnichar *) strFilePaths.get() ;
|
||||
while (offset != kNotFound)
|
||||
{
|
||||
nsString RemainingPaths ;
|
||||
RemainingPaths.Assign(newFilePaths) ;
|
||||
offset = RemainingPaths.Find (strDelimChars) ;
|
||||
if (offset != kNotFound)
|
||||
{
|
||||
RemainingPaths.SetLength (offset) ;
|
||||
if ((offset + strDelimChars.Length()) < FilePathsLen)
|
||||
newFilePaths += offset + strDelimChars.Length() ;
|
||||
}
|
||||
|
||||
pFile->InitWithUnicodePath (RemainingPaths.get()) ;
|
||||
|
||||
#ifdef RAJIV_DEBUG
|
||||
printf ("File : %S \n", RemainingPaths.get()) ;
|
||||
#endif
|
||||
PRBool bExist ;
|
||||
rv = pFile->Exists(&bExist) ;
|
||||
if (NS_FAILED(rv) || (!bExist) ) return NS_ERROR_FILE_TARGET_DOES_NOT_EXIST ;
|
||||
|
||||
nsXPIDLCString pURL ;
|
||||
NS_GetURLSpecFromFile(pFile, getter_Copies(pURL));
|
||||
if (pURL)
|
||||
{
|
||||
if (Attachments.Length() > 0)
|
||||
Attachments.Append(",") ;
|
||||
Attachments.Append(pURL) ;
|
||||
}
|
||||
}
|
||||
rv = aCompFields->SetAttachments (Attachments.get());
|
||||
}
|
||||
|
||||
return rv ;
|
||||
}
|
||||
|
||||
// this used for Send with UI
|
||||
nsresult nsMapiHook::ShowComposerWindow (unsigned long aSession, nsIMsgCompFields * aCompFields)
|
||||
{
|
||||
nsresult rv = NS_OK ;
|
||||
|
||||
// create a send listener to get back the send status
|
||||
nsCOMPtr <nsIMsgSendListener> sendListener ;
|
||||
rv = nsMAPISendListener::CreateMAPISendListener(getter_AddRefs(sendListener)) ;
|
||||
if (NS_FAILED(rv) || (!sendListener) ) return rv ;
|
||||
|
||||
// create the compose params object
|
||||
nsCOMPtr<nsIMsgComposeParams> pMsgComposeParams (do_CreateInstance(NS_MSGCOMPOSEPARAMS_CONTRACTID, &rv));
|
||||
if (NS_FAILED(rv) || (!pMsgComposeParams) ) return rv ;
|
||||
|
||||
// populate the compose params
|
||||
pMsgComposeParams->SetType(nsIMsgCompType::New);
|
||||
pMsgComposeParams->SetFormat(nsIMsgCompFormat::Default);
|
||||
pMsgComposeParams->SetComposeFields(aCompFields);
|
||||
pMsgComposeParams->SetSendListener(sendListener) ;
|
||||
|
||||
/** get the nsIMsgComposeService object to open the compose window **/
|
||||
nsCOMPtr <nsIMsgComposeService> compService = do_GetService (NS_MSGCOMPOSESERVICE_CONTRACTID) ;
|
||||
if (NS_FAILED(rv)|| (!compService) ) return rv ;
|
||||
|
||||
rv = compService->OpenComposeWindowWithParams(nsnull, pMsgComposeParams) ;
|
||||
if (NS_FAILED(rv)) return rv ;
|
||||
|
||||
return rv ;
|
||||
}
|
||||
66
mozilla/mailnews/mapi/mapihook/src/msgMapiHook.h
Normal file
66
mozilla/mailnews/mapi/mapihook/src/msgMapiHook.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corp.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2001
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Krishna Mohan Khandrika (kkhandrika@netscape.com)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef MSG_MAPI_HOOK_H_
|
||||
#define MSG_MAPI_HOOK_H_
|
||||
|
||||
#include "prtypes.h"
|
||||
|
||||
class nsMapiHook
|
||||
{
|
||||
public :
|
||||
|
||||
static PRBool Initialize();
|
||||
static PRBool DisplayLoginDialog(PRBool aLogin, PRUnichar **aUsername,
|
||||
PRUnichar **aPassword);
|
||||
static PRBool VerifyUserName(const PRUnichar *aUsername, char **aIdKey);
|
||||
|
||||
static PRBool IsBlindSendAllowed () ;
|
||||
static nsresult BlindSendMail (unsigned long aSession, nsIMsgCompFields * aCompFields) ;
|
||||
static nsresult ShowComposerWindow (unsigned long aSession, nsIMsgCompFields * aCompFields) ;
|
||||
static nsresult PopulateCompFields(lpnsMapiMessage aMessage, nsIMsgCompFields * aCompFields) ;
|
||||
static nsresult PopulateCompFieldsWithConversion(lpnsMapiMessage aMessage,
|
||||
nsIMsgCompFields * aCompFields) ;
|
||||
static nsresult PopulateCompFieldsForSendDocs(nsIMsgCompFields * aCompFields,
|
||||
ULONG aFlags, LPTSTR aDelimChar, LPTSTR aFilePaths) ;
|
||||
static nsresult HandleAttachments (nsIMsgCompFields * aCompFields, PRInt32 aFileCount,
|
||||
lpnsMapiFileDesc aFiles, BOOL aIsUnicode) ;
|
||||
static void CleanUp();
|
||||
|
||||
static PRBool isMapiService;
|
||||
};
|
||||
|
||||
#endif // MSG_MAPI_HOOK_H_
|
||||
266
mozilla/mailnews/mapi/mapihook/src/msgMapiImp.cpp
Normal file
266
mozilla/mailnews/mapi/mapihook/src/msgMapiImp.cpp
Normal file
@@ -0,0 +1,266 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corp.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2001
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Krishna Mohan Khandrika (kkhandrika@netscape.com)
|
||||
* Contributor(s): Rajiv Dayal (rdayal@netscape.com)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <mapidefs.h>
|
||||
#include <mapi.h>
|
||||
#include "msgMapi.h"
|
||||
#include "msgMapiImp.h"
|
||||
#include "msgMapiFactory.h"
|
||||
#include "msgMapiMain.h"
|
||||
|
||||
#include "nsMsgCompFields.h"
|
||||
#include "msgMapiHook.h"
|
||||
#include "nsString.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsMsgCompCID.h"
|
||||
|
||||
|
||||
|
||||
CMapiImp::CMapiImp()
|
||||
: m_cRef(1)
|
||||
{
|
||||
m_Lock = PR_NewLock();
|
||||
}
|
||||
|
||||
CMapiImp::~CMapiImp()
|
||||
{
|
||||
if (m_Lock)
|
||||
PR_DestroyLock(m_Lock);
|
||||
}
|
||||
|
||||
STDMETHODIMP CMapiImp::QueryInterface(const IID& aIid, void** aPpv)
|
||||
{
|
||||
if (aIid == IID_IUnknown)
|
||||
{
|
||||
*aPpv = static_cast<nsIMapi*>(this);
|
||||
}
|
||||
else if (aIid == IID_nsIMapi)
|
||||
{
|
||||
*aPpv = static_cast<nsIMapi*>(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
*aPpv = nsnull;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
reinterpret_cast<IUnknown*>(*aPpv)->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) CMapiImp::AddRef()
|
||||
{
|
||||
return PR_AtomicIncrement(&m_cRef);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) CMapiImp::Release()
|
||||
{
|
||||
PRInt32 temp;
|
||||
temp = PR_AtomicDecrement(&m_cRef);
|
||||
if (m_cRef == 0)
|
||||
{
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
STDMETHODIMP CMapiImp::IsValid()
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CMapiImp::IsValidSession(unsigned long aSession)
|
||||
{
|
||||
nsMAPIConfiguration *pConfig = nsMAPIConfiguration::GetMAPIConfiguration();
|
||||
if (pConfig && pConfig->IsSessionValid(aSession))
|
||||
return S_OK;
|
||||
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
STDMETHODIMP CMapiImp::Initialize()
|
||||
{
|
||||
HRESULT hr = E_FAIL;
|
||||
|
||||
if (!m_Lock)
|
||||
return E_FAIL;
|
||||
|
||||
PR_Lock(m_Lock);
|
||||
|
||||
// Initialize MAPI Configuration
|
||||
|
||||
nsMAPIConfiguration *pConfig = nsMAPIConfiguration::GetMAPIConfiguration();
|
||||
if (pConfig != nsnull)
|
||||
if (nsMapiHook::Initialize())
|
||||
hr = S_OK;
|
||||
|
||||
PR_Unlock(m_Lock);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
STDMETHODIMP CMapiImp::Login(unsigned long aUIArg, LOGIN_PW_TYPE aLogin, LOGIN_PW_TYPE aPassWord,
|
||||
unsigned long aFlags, unsigned long *aSessionId)
|
||||
{
|
||||
HRESULT hr = E_FAIL;
|
||||
PRBool bNewSession = PR_FALSE;
|
||||
char *id_key = nsnull;
|
||||
|
||||
if (aFlags & MAPI_NEW_SESSION)
|
||||
bNewSession = PR_TRUE;
|
||||
|
||||
// Check For Profile Name
|
||||
|
||||
if (aLogin != nsnull && aLogin[0] != '\0')
|
||||
{
|
||||
if (nsMapiHook::VerifyUserName(aLogin, &id_key) == PR_FALSE)
|
||||
{
|
||||
*aSessionId = MAPI_E_LOGIN_FAILURE;
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
||||
// finally register(create) the session.
|
||||
|
||||
PRUint32 nSession_Id;
|
||||
PRInt16 nResult = 0;
|
||||
|
||||
nsMAPIConfiguration *pConfig = nsMAPIConfiguration::GetMAPIConfiguration();
|
||||
if (pConfig != nsnull)
|
||||
nResult = pConfig->RegisterSession(aUIArg, aLogin, aPassWord,
|
||||
(aFlags & MAPI_FORCE_DOWNLOAD), bNewSession,
|
||||
&nSession_Id, id_key);
|
||||
|
||||
switch (nResult)
|
||||
{
|
||||
case -1 :
|
||||
{
|
||||
*aSessionId = MAPI_E_TOO_MANY_SESSIONS;
|
||||
return hr;
|
||||
}
|
||||
case 0 :
|
||||
{
|
||||
*aSessionId = MAPI_E_INSUFFICIENT_MEMORY;
|
||||
return hr;
|
||||
}
|
||||
default :
|
||||
{
|
||||
*aSessionId = nSession_Id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CMapiImp::SendMail( unsigned long aSession, lpnsMapiMessage aMessage,
|
||||
short aRecipCount, lpnsMapiRecipDesc aRecips , short aFileCount, lpnsMapiFileDesc aFiles ,
|
||||
unsigned long aFlags, unsigned long aReserved)
|
||||
{
|
||||
nsresult rv = NS_OK ;
|
||||
|
||||
// Assign the pointers in the aMessage struct to the array of Recips and Files
|
||||
// recieved here from MS COM. These are used in BlindSendMail and ShowCompWin fns
|
||||
aMessage->lpRecips = aRecips ;
|
||||
aMessage->lpFiles = aFiles ;
|
||||
|
||||
/** create nsIMsgCompFields obj and populate it **/
|
||||
nsCOMPtr<nsIMsgCompFields> pCompFields = do_CreateInstance(NS_MSGCOMPFIELDS_CONTRACTID, &rv) ;
|
||||
if (NS_FAILED(rv) || (!pCompFields) ) return MAPI_E_INSUFFICIENT_MEMORY ;
|
||||
|
||||
if (aFlags & MAPI_UNICODE)
|
||||
rv = nsMapiHook::PopulateCompFields(aMessage, pCompFields) ;
|
||||
else
|
||||
rv = nsMapiHook::PopulateCompFieldsWithConversion(aMessage, pCompFields) ;
|
||||
|
||||
if (NS_SUCCEEDED (rv))
|
||||
{
|
||||
// see flag to see if UI needs to be brought up
|
||||
if (!(aFlags & MAPI_DIALOG))
|
||||
{
|
||||
rv = nsMapiHook::BlindSendMail(aSession, pCompFields);
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = nsMapiHook::ShowComposerWindow(aSession, pCompFields);
|
||||
}
|
||||
}
|
||||
|
||||
return nsMAPIConfiguration::GetMAPIErrorFromNSError (rv) ;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CMapiImp::SendDocuments( unsigned long aSession, LPTSTR aDelimChar,
|
||||
LPTSTR aFilePaths, LPTSTR aFileNames, ULONG aFlags)
|
||||
{
|
||||
nsresult rv = NS_OK ;
|
||||
|
||||
/** create nsIMsgCompFields obj and populate it **/
|
||||
nsCOMPtr<nsIMsgCompFields> pCompFields = do_CreateInstance(NS_MSGCOMPFIELDS_CONTRACTID, &rv) ;
|
||||
if (NS_FAILED(rv) || (!pCompFields) ) return MAPI_E_INSUFFICIENT_MEMORY ;
|
||||
|
||||
if (aFilePaths)
|
||||
{
|
||||
rv = nsMapiHook::PopulateCompFieldsForSendDocs(pCompFields, aFlags, aDelimChar, aFilePaths) ;
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED (rv))
|
||||
rv = nsMapiHook::ShowComposerWindow(aSession, pCompFields);
|
||||
|
||||
return nsMAPIConfiguration::GetMAPIErrorFromNSError (rv) ;
|
||||
}
|
||||
|
||||
STDMETHODIMP CMapiImp::Logoff (unsigned long aSession)
|
||||
{
|
||||
nsMAPIConfiguration *pConfig = nsMAPIConfiguration::GetMAPIConfiguration();
|
||||
|
||||
if (pConfig->UnRegisterSession((PRUint32)aSession))
|
||||
return S_OK;
|
||||
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
STDMETHODIMP CMapiImp::CleanUp()
|
||||
{
|
||||
nsMapiHook::CleanUp();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
92
mozilla/mailnews/mapi/mapihook/src/msgMapiImp.h
Normal file
92
mozilla/mailnews/mapi/mapihook/src/msgMapiImp.h
Normal file
@@ -0,0 +1,92 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corp.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2001
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Krishna Mohan Khandrika (kkhandrika@netscape.com)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef MSG_MAPI_IMP_H
|
||||
#define MSG_MAPI_IMP_H
|
||||
|
||||
#include <windows.h>
|
||||
#include <mapi.h>
|
||||
#include "msgMapi.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nspr.h"
|
||||
|
||||
const CLSID CLSID_CMapiImp = {0x29f458be, 0x8866, 0x11d5, {0xa3, 0xdd, 0x0, 0xb0, 0xd0, 0xf3, 0xba, 0xa7}};
|
||||
|
||||
// this class implements the MS COM interface nsIMapi that provides the methods
|
||||
// called by mapi32.dll to perform the mail operations as specified by MAPI.
|
||||
// These class methods in turn use the Mozilla Mail XPCOM interfaces to do so.
|
||||
class CMapiImp : public nsIMapi
|
||||
{
|
||||
|
||||
public :
|
||||
|
||||
// IUnknown
|
||||
|
||||
STDMETHODIMP QueryInterface(const IID& aIid, void** aPpv);
|
||||
STDMETHODIMP_(ULONG) AddRef();
|
||||
STDMETHODIMP_(ULONG) Release();
|
||||
|
||||
// Interface INsMapi
|
||||
|
||||
STDMETHODIMP Login(unsigned long aUIArg, LOGIN_PW_TYPE aLogin,
|
||||
LOGIN_PW_TYPE aPassWord, unsigned long aFlags,
|
||||
unsigned long *aSessionId);
|
||||
|
||||
STDMETHODIMP SendMail( unsigned long aSession, lpnsMapiMessage aMessage,
|
||||
short aRecipCount, lpnsMapiRecipDesc aRecips ,
|
||||
short aFileCount, lpnsMapiFileDesc aFiles ,
|
||||
unsigned long aFlags, unsigned long aReserved) ;
|
||||
|
||||
STDMETHODIMP SendDocuments( unsigned long aSession, LPTSTR aDelimChar,
|
||||
LPTSTR aFilePaths, LPTSTR aFileNames, ULONG aFlags);
|
||||
|
||||
STDMETHODIMP Initialize();
|
||||
STDMETHODIMP IsValid();
|
||||
STDMETHODIMP IsValidSession(unsigned long aSession);
|
||||
|
||||
STDMETHODIMP Logoff (unsigned long aSession);
|
||||
STDMETHODIMP CleanUp();
|
||||
|
||||
CMapiImp();
|
||||
~CMapiImp();
|
||||
|
||||
private :
|
||||
|
||||
PRLock *m_Lock;
|
||||
PRInt32 m_cRef;
|
||||
};
|
||||
|
||||
#endif // MSG_MAPI_IMP_H
|
||||
376
mozilla/mailnews/mapi/mapihook/src/msgMapiMain.cpp
Normal file
376
mozilla/mailnews/mapi/mapihook/src/msgMapiMain.cpp
Normal file
@@ -0,0 +1,376 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corp.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2001
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Krishna Mohan Khandrika (kkhandrika@netscape.com)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <mapidefs.h>
|
||||
#include <mapi.h>
|
||||
|
||||
#include "msgCore.h"
|
||||
#include "nsMsgComposeStringBundle.h"
|
||||
#include "msgMapiMain.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
// move to xpcom bug 81956.
|
||||
class nsPRUintKey : public nsHashKey {
|
||||
protected:
|
||||
PRUint32 mKey;
|
||||
public:
|
||||
nsPRUintKey(PRUint32 key) : mKey(key) {}
|
||||
|
||||
PRUint32 HashCode(void) const {
|
||||
return mKey;
|
||||
}
|
||||
|
||||
PRBool Equals(const nsHashKey *aKey) const {
|
||||
return mKey == ((const nsPRUintKey *) aKey)->mKey;
|
||||
}
|
||||
nsHashKey *Clone() const {
|
||||
return new nsPRUintKey(mKey);
|
||||
}
|
||||
PRUint32 GetValue() { return mKey; }
|
||||
};
|
||||
//
|
||||
|
||||
|
||||
nsMAPIConfiguration *nsMAPIConfiguration::m_pSelfRef = nsnull;
|
||||
PRUint32 nsMAPIConfiguration::session_generator = 0;
|
||||
PRUint32 nsMAPIConfiguration::sessionCount = 0;
|
||||
|
||||
nsMAPIConfiguration *nsMAPIConfiguration::GetMAPIConfiguration()
|
||||
{
|
||||
if (m_pSelfRef == nsnull)
|
||||
m_pSelfRef = new nsMAPIConfiguration();
|
||||
|
||||
return m_pSelfRef;
|
||||
}
|
||||
|
||||
nsMAPIConfiguration::nsMAPIConfiguration()
|
||||
: m_nMaxSessions(MAX_SESSIONS)
|
||||
{
|
||||
m_Lock = PR_NewLock();
|
||||
}
|
||||
|
||||
static PRBool
|
||||
FreeSessionMapEntries(nsHashKey *aKey, void *aData, void* aClosure)
|
||||
{
|
||||
nsMAPISession *pTemp = (nsMAPISession*) aData;
|
||||
if (pTemp)
|
||||
{
|
||||
delete pTemp;
|
||||
pTemp = nsnull;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
static PRBool
|
||||
FreeProfileMapEntries(nsHashKey *aKey, void *aData, void* aClosure)
|
||||
{
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
nsMAPIConfiguration::~nsMAPIConfiguration()
|
||||
{
|
||||
if (m_Lock)
|
||||
PR_DestroyLock(m_Lock);
|
||||
|
||||
m_SessionMap.Reset(FreeSessionMapEntries);
|
||||
m_ProfileMap.Reset(FreeProfileMapEntries);
|
||||
}
|
||||
|
||||
void nsMAPIConfiguration::OpenConfiguration()
|
||||
{
|
||||
// No. of max. sessions is set to MAX_SESSIONS. In future
|
||||
// if it is decided to have configuration (registry)
|
||||
// parameter, this function can be used to set the
|
||||
// max sessions;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
PRInt16 nsMAPIConfiguration::RegisterSession(PRUint32 aHwnd,
|
||||
const PRUnichar *aUserName, const PRUnichar *aPassword,
|
||||
PRBool aForceDownLoad, PRBool aNewSession,
|
||||
PRUint32 *aSession, char *aIdKey)
|
||||
{
|
||||
PRInt16 nResult = 0;
|
||||
PRUint32 n_SessionId = 0;
|
||||
|
||||
PR_Lock(m_Lock);
|
||||
|
||||
// Check whether max sessions is exceeded
|
||||
|
||||
if (sessionCount >= m_nMaxSessions)
|
||||
{
|
||||
PR_Unlock(m_Lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (aUserName != nsnull && aUserName[0] != '\0')
|
||||
{
|
||||
nsStringKey usernameKey(aUserName);
|
||||
n_SessionId = (PRUint32) m_ProfileMap.Get(&usernameKey);
|
||||
}
|
||||
|
||||
// try to share a session; if not create a session
|
||||
|
||||
if (n_SessionId > 0)
|
||||
{
|
||||
nsPRUintKey sessionKey(n_SessionId);
|
||||
nsMAPISession *pTemp = (nsMAPISession *)m_SessionMap.Get(&sessionKey);
|
||||
if (pTemp != nsnull)
|
||||
{
|
||||
pTemp->IncrementSession();
|
||||
*aSession = n_SessionId;
|
||||
nResult = 1;
|
||||
}
|
||||
}
|
||||
else if (aNewSession || n_SessionId == 0) // checking for n_SessionId is a concession
|
||||
{
|
||||
// create a new session ; if new session is specified OR there is no session
|
||||
nsMAPISession *pTemp = nsnull;
|
||||
pTemp = new nsMAPISession(aHwnd, aUserName,
|
||||
aPassword, aForceDownLoad, aIdKey);
|
||||
|
||||
if (pTemp != nsnull)
|
||||
{
|
||||
session_generator++;
|
||||
|
||||
// I don't think there will be (2 power 32) sessions alive
|
||||
// in a cycle. This is an assumption
|
||||
|
||||
if (session_generator == 0)
|
||||
session_generator++;
|
||||
|
||||
nsPRUintKey sessionKey(session_generator);
|
||||
m_SessionMap.Put(&sessionKey, pTemp);
|
||||
if (aUserName != nsnull && aUserName[0] != '\0')
|
||||
{
|
||||
nsStringKey usernameKey(aUserName);
|
||||
m_ProfileMap.Put(&usernameKey, (void*)session_generator);
|
||||
}
|
||||
|
||||
*aSession = session_generator;
|
||||
sessionCount++;
|
||||
nResult = 1;
|
||||
}
|
||||
}
|
||||
|
||||
PR_Unlock(m_Lock);
|
||||
return nResult;
|
||||
}
|
||||
|
||||
PRBool nsMAPIConfiguration::UnRegisterSession(PRUint32 aSessionID)
|
||||
{
|
||||
PRBool bResult = PR_FALSE;
|
||||
|
||||
PR_Lock(m_Lock);
|
||||
|
||||
if (aSessionID != 0)
|
||||
{
|
||||
nsPRUintKey sessionKey(aSessionID);
|
||||
nsMAPISession *pTemp = (nsMAPISession *)m_SessionMap.Get(&sessionKey);
|
||||
|
||||
if (pTemp != nsnull)
|
||||
{
|
||||
if (pTemp->DecrementSession() == 0)
|
||||
{
|
||||
if (pTemp->m_pProfileName.get() != nsnull)
|
||||
{
|
||||
nsStringKey stringKey(pTemp->m_pProfileName.get());
|
||||
m_ProfileMap.Remove(&stringKey);
|
||||
}
|
||||
m_SessionMap.Remove(&sessionKey);
|
||||
sessionCount--;
|
||||
bResult = PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PR_Unlock(m_Lock);
|
||||
return bResult;
|
||||
}
|
||||
|
||||
PRBool nsMAPIConfiguration::IsSessionValid(PRUint32 aSessionID)
|
||||
{
|
||||
if (aSessionID == 0)
|
||||
return PR_FALSE;
|
||||
|
||||
PRBool retValue = PR_FALSE;
|
||||
nsPRUintKey sessionKey(aSessionID);
|
||||
|
||||
PR_Lock(m_Lock);
|
||||
|
||||
retValue = m_SessionMap.Exists(&sessionKey);
|
||||
|
||||
PR_Unlock(m_Lock);
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
|
||||
PRUnichar *nsMAPIConfiguration::GetPassword(PRUint32 aSessionID)
|
||||
{
|
||||
PRUnichar *pResult = nsnull;
|
||||
|
||||
PR_Lock(m_Lock);
|
||||
|
||||
if (aSessionID != 0)
|
||||
{
|
||||
nsPRUintKey sessionKey(aSessionID);
|
||||
nsMAPISession *pTemp = (nsMAPISession *)m_SessionMap.Get(&sessionKey);
|
||||
|
||||
if (pTemp)
|
||||
{
|
||||
pResult = pTemp->GetPassword();
|
||||
}
|
||||
}
|
||||
|
||||
PR_Unlock(m_Lock);
|
||||
|
||||
return pResult;
|
||||
}
|
||||
|
||||
char *nsMAPIConfiguration::GetIdKey(PRUint32 aSessionID)
|
||||
{
|
||||
char *pResult = nsnull;
|
||||
|
||||
PR_Lock(m_Lock);
|
||||
|
||||
if (aSessionID != 0)
|
||||
{
|
||||
nsPRUintKey sessionKey(aSessionID);
|
||||
nsMAPISession *pTemp = (nsMAPISession *)m_SessionMap.Get(&sessionKey);
|
||||
if (pTemp)
|
||||
{
|
||||
pResult = pTemp->GetIdKey();
|
||||
}
|
||||
}
|
||||
|
||||
PR_Unlock(m_Lock);
|
||||
return pResult;
|
||||
}
|
||||
|
||||
// util func
|
||||
HRESULT nsMAPIConfiguration::GetMAPIErrorFromNSError (nsresult res)
|
||||
{
|
||||
HRESULT hr = SUCCESS_SUCCESS ;
|
||||
|
||||
if (NS_SUCCEEDED (hr)) return hr ;
|
||||
|
||||
// if failure return the related MAPI failure code
|
||||
switch (res)
|
||||
{
|
||||
case NS_MSG_NO_RECIPIENTS :
|
||||
hr = MAPI_E_BAD_RECIPTYPE ;
|
||||
break ;
|
||||
case NS_ERROR_COULD_NOT_GET_USERS_MAIL_ADDRESS :
|
||||
hr = MAPI_E_INVALID_RECIPS ;
|
||||
break ;
|
||||
case NS_ERROR_COULD_NOT_LOGIN_TO_SMTP_SERVER :
|
||||
hr = MAPI_E_LOGIN_FAILURE ;
|
||||
break ;
|
||||
case NS_MSG_UNABLE_TO_OPEN_FILE :
|
||||
case NS_MSG_UNABLE_TO_OPEN_TMP_FILE :
|
||||
case NS_MSG_COULDNT_OPEN_FCC_FOLDER :
|
||||
case NS_ERROR_FILE_INVALID_PATH :
|
||||
hr = MAPI_E_ATTACHMENT_OPEN_FAILURE ;
|
||||
break ;
|
||||
case NS_ERROR_FILE_TARGET_DOES_NOT_EXIST :
|
||||
hr = MAPI_E_ATTACHMENT_NOT_FOUND ;
|
||||
break ;
|
||||
case NS_MSG_CANCELLING :
|
||||
hr = MAPI_E_USER_ABORT ;
|
||||
break ;
|
||||
case NS_MSG_ERROR_WRITING_FILE :
|
||||
case NS_MSG_UNABLE_TO_SAVE_TEMPLATE :
|
||||
case NS_MSG_UNABLE_TO_SAVE_DRAFT :
|
||||
hr = MAPI_E_ATTACHMENT_WRITE_FAILURE ;
|
||||
break ;
|
||||
default :
|
||||
hr = MAPI_E_FAILURE ;
|
||||
break ;
|
||||
}
|
||||
|
||||
return hr ;
|
||||
}
|
||||
|
||||
|
||||
nsMAPISession::nsMAPISession(PRUint32 aHwnd, const PRUnichar *aUserName,\
|
||||
const PRUnichar *aPassword, \
|
||||
PRBool aForceDownLoad, char *aKey)
|
||||
: m_bIsForcedDownLoad(aForceDownLoad),
|
||||
m_hAppHandle(aHwnd),
|
||||
m_nShared(1),
|
||||
m_pIdKey(aKey)
|
||||
{
|
||||
m_pProfileName.Assign(aUserName);
|
||||
m_pPassword.Assign(aPassword);
|
||||
}
|
||||
|
||||
nsMAPISession::~nsMAPISession()
|
||||
{
|
||||
if (m_pIdKey != nsnull)
|
||||
{
|
||||
delete [] m_pIdKey;
|
||||
m_pIdKey = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
PRUint32 nsMAPISession::IncrementSession()
|
||||
{
|
||||
return ++m_nShared;
|
||||
}
|
||||
|
||||
PRUint32 nsMAPISession::DecrementSession()
|
||||
{
|
||||
return --m_nShared;
|
||||
}
|
||||
|
||||
PRUint32 nsMAPISession::GetSessionCount()
|
||||
{
|
||||
return m_nShared;
|
||||
}
|
||||
|
||||
PRUnichar *nsMAPISession::GetPassword()
|
||||
{
|
||||
return (PRUnichar *)m_pPassword.get();
|
||||
}
|
||||
|
||||
char *nsMAPISession::GetIdKey()
|
||||
{
|
||||
return m_pIdKey;
|
||||
}
|
||||
|
||||
112
mozilla/mailnews/mapi/mapihook/src/msgMapiMain.h
Normal file
112
mozilla/mailnews/mapi/mapihook/src/msgMapiMain.h
Normal file
@@ -0,0 +1,112 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corp.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2001
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Krishna Mohan Khandrika (kkhandrika@netscape.com)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef MSG_MAPI_MAIN_H_
|
||||
#define NSG_MAPI_MAIN_H_
|
||||
|
||||
#define MAX_NAME_LEN 256
|
||||
#define MAX_PW_LEN 256
|
||||
#define MAX_SESSIONS 50
|
||||
#define MAPI_SENDCOMPLETE_EVENT "SendCompletionEvent"
|
||||
|
||||
#define MAPI_PROPERTIES_CHROME "chrome://messenger-mapi/locale/mapi.properties"
|
||||
#define PREF_MAPI_WARN_PRIOR_TO_BLIND_SEND "mapi.blind-send.warn"
|
||||
#define PREF_MAPI_BLIND_SEND_ENABLED "mapi.blind-send.enabled"
|
||||
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nspr.h"
|
||||
#include "nsString.h"
|
||||
#include "nsHashtable.h"
|
||||
|
||||
class nsMAPIConfiguration
|
||||
{
|
||||
private :
|
||||
|
||||
static PRUint32 session_generator;
|
||||
static PRUint32 sessionCount;
|
||||
static nsMAPIConfiguration *m_pSelfRef;
|
||||
PRLock *m_Lock;
|
||||
PRUint32 m_nMaxSessions;
|
||||
|
||||
|
||||
nsHashtable m_ProfileMap;
|
||||
nsHashtable m_SessionMap;
|
||||
nsMAPIConfiguration();
|
||||
|
||||
public :
|
||||
static nsMAPIConfiguration *GetMAPIConfiguration();
|
||||
void OpenConfiguration();
|
||||
PRInt16 RegisterSession(PRUint32 aHwnd, const PRUnichar *aUserName, \
|
||||
const PRUnichar *aPassword, PRBool aForceDownLoad, \
|
||||
PRBool aNewSession, PRUint32 *aSession, char *aIdKey);
|
||||
PRBool IsSessionValid(PRUint32 aSessionID);
|
||||
PRBool UnRegisterSession(PRUint32 aSessionID);
|
||||
PRUnichar *GetPassword(PRUint32 aSessionID);
|
||||
char *GetIdKey(PRUint32 aSessionID);
|
||||
~nsMAPIConfiguration();
|
||||
|
||||
// a util func
|
||||
static HRESULT GetMAPIErrorFromNSError (nsresult res) ;
|
||||
};
|
||||
|
||||
class nsMAPISession
|
||||
{
|
||||
friend class nsMAPIConfiguration;
|
||||
|
||||
private :
|
||||
|
||||
PRBool m_bIsForcedDownLoad;
|
||||
PRBool m_bApp_or_Service;
|
||||
PRUint32 m_hAppHandle;
|
||||
PRUint32 m_nShared;
|
||||
char *m_pIdKey;
|
||||
nsString m_pProfileName;
|
||||
nsString m_pPassword;
|
||||
|
||||
public :
|
||||
|
||||
nsMAPISession(PRUint32 aHwnd, const PRUnichar *aUserName, \
|
||||
const PRUnichar *aPassword, \
|
||||
PRBool aForceDownLoad, char *aKey);
|
||||
PRUint32 IncrementSession();
|
||||
PRUint32 DecrementSession();
|
||||
PRUint32 GetSessionCount();
|
||||
PRUnichar *nsMAPISession::GetPassword();
|
||||
char *nsMAPISession::GetIdKey();
|
||||
~nsMAPISession();
|
||||
};
|
||||
|
||||
#endif // MSG_MAPI_MAIN_H_
|
||||
209
mozilla/mailnews/mapi/mapihook/src/msgMapiSupport.cpp
Normal file
209
mozilla/mailnews/mapi/mapihook/src/msgMapiSupport.cpp
Normal file
@@ -0,0 +1,209 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corp.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2001
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Krishna Mohan Khandrika (kkhandrika@netscape.com)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
#include "nsCOMPtr.h"
|
||||
#include "objbase.h"
|
||||
#include "nsISupports.h"
|
||||
|
||||
#include "nsIGenericFactory.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIAppStartupNotifier.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsICategoryManager.h"
|
||||
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsIPrefBranch.h"
|
||||
#include "nsIPrefBranchInternal.h"
|
||||
|
||||
#include "msgMapiSupport.h"
|
||||
#include "nsMapiRegistryUtils.h"
|
||||
#include "nsMapiRegistry.h"
|
||||
#include "msgMapiImp.h"
|
||||
|
||||
/** Implementation of the nsIMapiSupport interface.
|
||||
* Use standard implementation of nsISupports stuff.
|
||||
*/
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS2(nsMapiSupport, nsIMapiSupport, nsIObserver);
|
||||
|
||||
static NS_METHOD nsMapiRegistrationProc(nsIComponentManager *aCompMgr,
|
||||
nsIFile *aPath, const char *registryLocation, const char *componentType,
|
||||
const nsModuleComponentInfo *info)
|
||||
{
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsICategoryManager> categoryManager(do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = categoryManager->AddCategoryEntry(APPSTARTUP_CATEGORY, "Mapi Support",
|
||||
"service," NS_IMAPISUPPORT_CONTRACTID, PR_TRUE, PR_TRUE, nsnull);
|
||||
|
||||
return rv ;
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMapiSupport::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *aData)
|
||||
{
|
||||
nsresult rv = NS_OK ;
|
||||
|
||||
if (!nsCRT::strcmp(aTopic, "profile-after-change"))
|
||||
return InitializeMAPISupport();
|
||||
|
||||
if (!nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID))
|
||||
return ShutdownMAPISupport();
|
||||
|
||||
if (!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID))
|
||||
{
|
||||
nsCOMPtr<nsIPrefBranch> prefs = do_QueryInterface(aSubject, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
// which preference changed?
|
||||
if (!nsCRT::strcmp(MAILNEWS_ALLOW_DEFAULT_MAIL_CLIENT, NS_ConvertUCS2toUTF8(aData).get()))
|
||||
{
|
||||
PRBool bIsDefault = PR_FALSE ;
|
||||
rv = prefs->GetBoolPref(MAILNEWS_ALLOW_DEFAULT_MAIL_CLIENT, &bIsDefault);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
nsCOMPtr <nsIMapiRegistry> mapiRegistry = do_CreateInstance(NS_IMAPIREGISTRY_CONTRACTID, &rv) ;
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
return mapiRegistry->SetIsDefaultMailClient(bIsDefault) ;
|
||||
}
|
||||
return rv ;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserverService> observerService(do_GetService("@mozilla.org/observer-service;1", &rv));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = observerService->AddObserver(this,"profile-after-change", PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIPrefService> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIPrefBranchInternal> prefInternal = do_QueryInterface(prefs, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = prefInternal->AddObserver(MAILNEWS_ALLOW_DEFAULT_MAIL_CLIENT, this, PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
nsMapiSupport::nsMapiSupport()
|
||||
: m_dwRegister(0),
|
||||
m_nsMapiFactory(nsnull)
|
||||
{
|
||||
NS_INIT_ISUPPORTS();
|
||||
}
|
||||
|
||||
nsMapiSupport::~nsMapiSupport()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMapiSupport::InitializeMAPISupport()
|
||||
{
|
||||
::CoInitialize(nsnull) ;
|
||||
|
||||
if (m_nsMapiFactory == nsnull) // No Registering if already done. Sanity Check!!
|
||||
{
|
||||
m_nsMapiFactory = new CMapiFactory();
|
||||
|
||||
if (m_nsMapiFactory != nsnull)
|
||||
{
|
||||
HRESULT hr = ::CoRegisterClassObject(CLSID_CMapiImp, \
|
||||
m_nsMapiFactory, \
|
||||
CLSCTX_LOCAL_SERVER, \
|
||||
REGCLS_MULTIPLEUSE, \
|
||||
&m_dwRegister);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
m_nsMapiFactory->Release() ;
|
||||
m_nsMapiFactory = nsnull;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMapiSupport::ShutdownMAPISupport()
|
||||
{
|
||||
if (m_dwRegister != 0)
|
||||
::CoRevokeClassObject(m_dwRegister);
|
||||
|
||||
if (m_nsMapiFactory != nsnull)
|
||||
{
|
||||
m_nsMapiFactory->Release();
|
||||
m_nsMapiFactory = nsnull;
|
||||
}
|
||||
|
||||
::CoUninitialize();
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMapiRegistry);
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMapiSupport);
|
||||
|
||||
// The list of components we register
|
||||
static nsModuleComponentInfo components[] =
|
||||
{
|
||||
{
|
||||
NS_IMAPIREGISTRY_CLASSNAME,
|
||||
NS_IMAPIREGISTRY_CID,
|
||||
NS_IMAPIREGISTRY_CONTRACTID,
|
||||
nsMapiRegistryConstructor
|
||||
},
|
||||
|
||||
{
|
||||
NS_IMAPISUPPORT_CLASSNAME,
|
||||
NS_IMAPISUPPORT_CID,
|
||||
NS_IMAPISUPPORT_CONTRACTID,
|
||||
nsMapiSupportConstructor,
|
||||
nsMapiRegistrationProc,
|
||||
nsnull
|
||||
}
|
||||
};
|
||||
|
||||
NS_IMPL_NSGETMODULE(msgMapiModule, components);
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
/*
|
||||
* hex2dec.c
|
||||
*
|
||||
* Convert decimal integers into hexadecimal
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
@@ -16,14 +11,14 @@
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic library.
|
||||
* The Original Code is Mozilla
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael J. Fromberger.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corp.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2001
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Contributor(s): Krishna Mohan Khandrika (kkhandrika@netscape.com)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@@ -38,34 +33,34 @@
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: hex2dec.c,v 1.3 2004-04-27 23:04:37 gerv%gerv.net Exp $ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifndef MSG_MAPI_SUPPORT_H_
|
||||
#define MSG_MAPI_SUPPORT_H_
|
||||
|
||||
#include "mpi.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsIMapiSupport.h"
|
||||
#include "msgMapiFactory.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
#define NS_IMAPISUPPORT_CID \
|
||||
{0x8967fed2, 0xc8bb, 0x11d5, \
|
||||
{ 0xa3, 0xe9, 0x00, 0xb0, 0xd0, 0xf3, 0xba, 0xa7 }}
|
||||
|
||||
class nsMapiSupport : public nsIMapiSupport,
|
||||
public nsIObserver
|
||||
{
|
||||
mp_int a;
|
||||
char *buf;
|
||||
int len;
|
||||
public :
|
||||
nsMapiSupport();
|
||||
~nsMapiSupport();
|
||||
|
||||
if(argc < 2) {
|
||||
fprintf(stderr, "Usage: %s <a>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
// Declare all interface methods we must implement.
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
NS_DECL_NSIMAPISUPPORT
|
||||
|
||||
mp_init(&a); mp_read_radix(&a, argv[1], 16);
|
||||
len = mp_radix_size(&a, 10);
|
||||
buf = malloc(len);
|
||||
mp_toradix(&a, buf, 10);
|
||||
private :
|
||||
|
||||
printf("%s\n", buf);
|
||||
DWORD m_dwRegister;
|
||||
CMapiFactory *m_nsMapiFactory;
|
||||
};
|
||||
|
||||
free(buf);
|
||||
mp_clear(&a);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif // MSG_MAPI_SUPPORT_H_
|
||||
167
mozilla/mailnews/mapi/mapihook/src/nsMapiRegistry.cpp
Normal file
167
mozilla/mailnews/mapi/mapihook/src/nsMapiRegistry.cpp
Normal file
@@ -0,0 +1,167 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2001
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Srilatha Moturi <srilatha@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsIPromptService.h"
|
||||
#include "nsIProxyObjectManager.h"
|
||||
#include "nsProxiedService.h"
|
||||
|
||||
#include "nsMapiRegistryUtils.h"
|
||||
#include "nsMapiRegistry.h"
|
||||
|
||||
static NS_DEFINE_CID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID);
|
||||
|
||||
/** Implementation of the nsIMapiRegistry interface.
|
||||
* Use standard implementation of nsISupports stuff.
|
||||
*/
|
||||
NS_IMPL_ISUPPORTS1(nsMapiRegistry, nsIMapiRegistry);
|
||||
|
||||
nsMapiRegistry::nsMapiRegistry() {
|
||||
NS_INIT_ISUPPORTS();
|
||||
m_ShowDialog = ! m_registryUtils.verifyRestrictedAccess();
|
||||
m_DefaultMailClient = m_registryUtils.IsDefaultMailClient();
|
||||
}
|
||||
|
||||
nsMapiRegistry::~nsMapiRegistry() {
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMapiRegistry::GetIsDefaultMailClient(PRBool * retval) {
|
||||
// we need to get the value from registry everytime
|
||||
// because the registry settings can be changed from
|
||||
// other mail applications.
|
||||
*retval = m_registryUtils.IsDefaultMailClient();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMapiRegistry::GetShowDialog(PRBool * retval) {
|
||||
*retval = m_ShowDialog;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMapiRegistry::SetIsDefaultMailClient(PRBool aIsDefaultMailClient)
|
||||
{
|
||||
nsresult rv = NS_OK ;
|
||||
|
||||
if (aIsDefaultMailClient)
|
||||
{
|
||||
rv = m_registryUtils.setDefaultMailClient();
|
||||
if (NS_SUCCEEDED(rv))
|
||||
m_DefaultMailClient = PR_TRUE;
|
||||
else
|
||||
m_registryUtils.ShowMapiErrorDialog();
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = m_registryUtils.unsetDefaultMailClient();
|
||||
if (NS_SUCCEEDED(rv))
|
||||
m_DefaultMailClient = PR_FALSE;
|
||||
else
|
||||
m_registryUtils.ShowMapiErrorDialog();
|
||||
}
|
||||
|
||||
return rv ;
|
||||
}
|
||||
|
||||
/** This will bring up the dialog box only once per session and
|
||||
* only if the current app is not default Mail Client.
|
||||
* This also checks the registry if the registry key
|
||||
* showMapiDialog is set
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsMapiRegistry::ShowMailIntegrationDialog(nsIDOMWindow *aParentWindow) {
|
||||
nsresult rv;
|
||||
if (!m_ShowDialog || !m_registryUtils.getShowDialog()) return NS_OK;
|
||||
nsCOMPtr<nsIPromptService> promptService(do_GetService(
|
||||
"@mozilla.org/embedcomp/prompt-service;1", &rv));
|
||||
if (NS_SUCCEEDED(rv) && promptService)
|
||||
{
|
||||
nsCOMPtr<nsIStringBundle> bundle;
|
||||
rv = m_registryUtils.MakeMapiStringBundle (getter_AddRefs (bundle)) ;
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
|
||||
nsXPIDLString dialogTitle;
|
||||
const PRUnichar *brandStrings[] = { m_registryUtils.brandName() };
|
||||
NS_NAMED_LITERAL_STRING(dialogTitlePropertyTag, "dialogTitle");
|
||||
rv = bundle->FormatStringFromName(dialogTitlePropertyTag.get(),
|
||||
brandStrings, 1,
|
||||
getter_Copies(dialogTitle));
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
|
||||
nsXPIDLString dialogText;
|
||||
NS_NAMED_LITERAL_STRING(dialogTextPropertyTag, "dialogText");
|
||||
rv = bundle->FormatStringFromName(dialogTextPropertyTag.get(),
|
||||
brandStrings, 1,
|
||||
getter_Copies(dialogText));
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
|
||||
nsXPIDLString checkboxText;
|
||||
rv = bundle->GetStringFromName(
|
||||
NS_LITERAL_STRING("checkboxText").get(),
|
||||
getter_Copies(checkboxText));
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
|
||||
PRBool checkValue = PR_FALSE;
|
||||
PRInt32 buttonPressed = 0;
|
||||
rv = promptService->ConfirmEx(aParentWindow,
|
||||
dialogTitle,
|
||||
dialogText.get(),
|
||||
(nsIPromptService::BUTTON_TITLE_YES *
|
||||
nsIPromptService::BUTTON_POS_0) +
|
||||
(nsIPromptService::BUTTON_TITLE_NO *
|
||||
nsIPromptService::BUTTON_POS_1),
|
||||
nsnull,
|
||||
nsnull,
|
||||
nsnull,
|
||||
checkboxText,
|
||||
&checkValue,
|
||||
&buttonPressed);
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
rv = m_registryUtils.SetRegistryKey(HKEY_LOCAL_MACHINE, "Software\\Mozilla\\Desktop",
|
||||
"showMapiDialog", (checkValue) ? "0" : "1");
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
|
||||
m_ShowDialog = PR_FALSE;
|
||||
if (!buttonPressed)
|
||||
rv = SetIsDefaultMailClient(PR_TRUE) ; // SetDefaultMailClient();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
/*
|
||||
* prng.c
|
||||
*
|
||||
* Command-line pseudo-random number generator
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
@@ -16,14 +11,15 @@
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic library.
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael J. Fromberger.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2001
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Srilatha Moturi <srilatha@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@@ -38,53 +34,43 @@
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: prng.c,v 1.4 2004-04-27 23:04:37 gerv%gerv.net Exp $ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <time.h>
|
||||
#ifndef nsmapiregistry_h____
|
||||
#define nsmapiregistry_h____
|
||||
|
||||
#ifdef __OS2__
|
||||
#include <types.h>
|
||||
#include <process.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include "nsIMapiRegistry.h"
|
||||
|
||||
#ifndef MAX_BUF
|
||||
#define MAX_BUF 4096
|
||||
#endif
|
||||
|
||||
#include "bbs_rand.h"
|
||||
/* c5be14ba-4e0a-4eec-a1b8-04363761d63c */
|
||||
#define NS_IMAPIREGISTRY_CID \
|
||||
{ 0xc5be14ba, 0x4e0a, 0x4eec, {0xa1, 0xb8, 0x04, 0x36, 0x37, 0x61, 0xd6, 0x3c} }
|
||||
#define NS_IMAPIREGISTRY_CONTRACTID "@mozilla.org/mapiregistry;1"
|
||||
#define NS_IMAPIREGISTRY_CLASSNAME "Mozilla MAPI Registry"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
unsigned char *seed;
|
||||
unsigned int ix, num = 1;
|
||||
pid_t pid;
|
||||
|
||||
if(argc > 1) {
|
||||
num = atoi(argv[1]);
|
||||
if(num <= 0)
|
||||
num = 1;
|
||||
}
|
||||
#define MAILNEWS_ALLOW_DEFAULT_MAIL_CLIENT "mailnews.default_mail_client"
|
||||
|
||||
pid = getpid();
|
||||
srand(time(NULL) * (unsigned int)pid);
|
||||
class nsMapiRegistry : public nsIMapiRegistry {
|
||||
public:
|
||||
// ctor/dtor
|
||||
nsMapiRegistry();
|
||||
virtual ~nsMapiRegistry();
|
||||
|
||||
/* Not a perfect seed, but not bad */
|
||||
seed = malloc(bbs_seed_size);
|
||||
for(ix = 0; ix < bbs_seed_size; ix++) {
|
||||
seed[ix] = rand() % UCHAR_MAX;
|
||||
}
|
||||
// Declare all interface methods we must implement.
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIMAPIREGISTRY
|
||||
|
||||
bbs_srand(seed, bbs_seed_size);
|
||||
memset(seed, 0, bbs_seed_size);
|
||||
free(seed);
|
||||
protected:
|
||||
|
||||
PRBool m_DefaultMailClient;
|
||||
PRBool m_ShowDialog;
|
||||
nsMapiRegistryUtils m_registryUtils ;
|
||||
|
||||
while(num-- > 0) {
|
||||
ix = bbs_rand();
|
||||
private:
|
||||
// Special member to handle initialization.
|
||||
PRBool mHaveBeenSet;
|
||||
}; // nsMapiRegistry
|
||||
|
||||
printf("%u\n", ix);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
#endif // nsmapiregistry_h____
|
||||
743
mozilla/mailnews/mapi/mapihook/src/nsMapiRegistryUtils.cpp
Normal file
743
mozilla/mailnews/mapi/mapihook/src/nsMapiRegistryUtils.cpp
Normal file
@@ -0,0 +1,743 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2001
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Srilatha Moturi <srilatha@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#undef UNICODE
|
||||
#undef _UNICODE
|
||||
|
||||
#include "nsIServiceManager.h"
|
||||
#include "msgMapiImp.h"
|
||||
#include "msgMapiMain.h"
|
||||
#include "nsMapiRegistryUtils.h"
|
||||
#include "nsString.h"
|
||||
#include "nsIStringBundle.h"
|
||||
#include "nsIPromptService.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsSpecialSystemDirectory.h"
|
||||
#include "nsDirectoryService.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
#include "nsIPref.h"
|
||||
|
||||
static NS_DEFINE_CID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID);
|
||||
|
||||
#define EXE_EXTENSION ".exe"
|
||||
#define USERAGENT_VERSION_PREF "general.useragent.misc"
|
||||
#define USERAGENT_VERSION_NS_PREF "general.useragent.vendorSub"
|
||||
#define USERAGENT_PREF_PREFIX "rv:"
|
||||
|
||||
nsMapiRegistryUtils::nsMapiRegistryUtils()
|
||||
{
|
||||
m_mapiStringBundle = nsnull ;
|
||||
}
|
||||
|
||||
const char * nsMapiRegistryUtils::thisApplication()
|
||||
{
|
||||
if (m_thisApp.IsEmpty()) {
|
||||
char buffer[MAX_PATH] = {0};
|
||||
DWORD len = ::GetModuleFileName(NULL, buffer, MAX_PATH);
|
||||
if (!len) return nsnull ;
|
||||
char shortPathBuf[MAX_PATH] = {0};
|
||||
len = ::GetShortPathName(buffer, shortPathBuf, MAX_PATH);
|
||||
if (!len) return nsnull ;
|
||||
m_thisApp = buffer;
|
||||
m_thisApp.ToUpperCase();
|
||||
}
|
||||
|
||||
return m_thisApp.get() ;
|
||||
}
|
||||
|
||||
const PRUnichar * nsMapiRegistryUtils::brandName()
|
||||
{
|
||||
nsresult rv;
|
||||
if (m_brand.IsEmpty()) {
|
||||
nsCOMPtr<nsIStringBundleService> bundleService(do_GetService(
|
||||
kStringBundleServiceCID, &rv));
|
||||
if (NS_SUCCEEDED(rv) && bundleService) {
|
||||
nsCOMPtr<nsIStringBundle> brandBundle;
|
||||
rv = bundleService->CreateBundle(
|
||||
"chrome://global/locale/brand.properties",
|
||||
getter_AddRefs(brandBundle));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsXPIDLString brandName;
|
||||
rv = brandBundle->GetStringFromName(
|
||||
NS_LITERAL_STRING("brandShortName").get(),
|
||||
getter_Copies(brandName));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
m_brand = brandName ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return m_brand.get() ;
|
||||
}
|
||||
|
||||
const PRUnichar * nsMapiRegistryUtils::versionNo()
|
||||
{
|
||||
if (!m_versionNo.IsEmpty())
|
||||
return m_versionNo.get() ;
|
||||
|
||||
nsCOMPtr<nsIPref> prefs = do_GetService(NS_PREF_CONTRACTID);
|
||||
if (prefs) {
|
||||
nsXPIDLCString versionStr ;
|
||||
nsresult rv = prefs->GetCharPref(USERAGENT_VERSION_NS_PREF, getter_Copies(versionStr));
|
||||
if (NS_SUCCEEDED(rv) && versionStr)
|
||||
m_versionNo.AssignWithConversion (versionStr.get()) ;
|
||||
else {
|
||||
rv = prefs->GetCharPref(USERAGENT_VERSION_PREF, getter_Copies(versionStr));
|
||||
if (NS_SUCCEEDED(rv) && versionStr) {
|
||||
m_versionNo.AssignWithConversion (versionStr.get()) ;
|
||||
m_versionNo.StripChars (USERAGENT_PREF_PREFIX) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return m_versionNo.get() ;
|
||||
}
|
||||
|
||||
|
||||
PRBool nsMapiRegistryUtils::verifyRestrictedAccess() {
|
||||
char subKey[] = "Software\\Mozilla - Test Key";
|
||||
PRBool result = PR_FALSE;
|
||||
DWORD dwDisp = 0;
|
||||
HKEY key;
|
||||
// Try to create/open a subkey under HKLM.
|
||||
DWORD rc = ::RegCreateKeyEx(HKEY_LOCAL_MACHINE,
|
||||
subKey,
|
||||
0,
|
||||
NULL,
|
||||
REG_OPTION_NON_VOLATILE,
|
||||
KEY_WRITE,
|
||||
NULL,
|
||||
&key,
|
||||
&dwDisp);
|
||||
|
||||
if (rc == ERROR_SUCCESS) {
|
||||
// Key was opened; first close it.
|
||||
::RegCloseKey(key);
|
||||
// Delete it if we just created it.
|
||||
switch(dwDisp) {
|
||||
case REG_CREATED_NEW_KEY:
|
||||
::RegDeleteKey(HKEY_LOCAL_MACHINE, subKey);
|
||||
break;
|
||||
case REG_OPENED_EXISTING_KEY:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// Can't create/open it; we don't have access.
|
||||
result = PR_TRUE;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult nsMapiRegistryUtils::SetRegistryKey(HKEY baseKey, const char * keyName,
|
||||
const char * valueName, char * value)
|
||||
{
|
||||
nsresult result = NS_ERROR_FAILURE;
|
||||
HKEY key;
|
||||
LONG rc = ::RegCreateKey(baseKey, keyName, &key);
|
||||
|
||||
if (rc == ERROR_SUCCESS) {
|
||||
rc = ::RegSetValueEx(key, valueName, NULL, REG_SZ,
|
||||
(LPBYTE)(const char*)value, strlen(value));
|
||||
if (rc == ERROR_SUCCESS) {
|
||||
result = NS_OK;
|
||||
}
|
||||
::RegCloseKey(key);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult nsMapiRegistryUtils::DeleteRegistryValue(HKEY baseKey, const char * keyName,
|
||||
const char * valueName)
|
||||
{
|
||||
nsresult result = NS_ERROR_FAILURE;
|
||||
HKEY key;
|
||||
LONG rc = ::RegOpenKey(baseKey, keyName, &key);
|
||||
|
||||
if (rc == ERROR_SUCCESS) {
|
||||
rc = ::RegDeleteValue(key, valueName);
|
||||
if (rc == ERROR_SUCCESS)
|
||||
result = NS_OK;
|
||||
::RegCloseKey(key);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void nsMapiRegistryUtils::GetRegistryKey(HKEY baseKey, const char * keyName,
|
||||
const char * valueName, nsCAutoString & value)
|
||||
{
|
||||
HKEY key;
|
||||
LONG rc = ::RegOpenKey(baseKey, keyName, &key);
|
||||
if (rc == ERROR_SUCCESS) {
|
||||
char buffer[MAX_PATH] = {0};
|
||||
DWORD len = sizeof buffer;
|
||||
rc = ::RegQueryValueEx(key, valueName, NULL, NULL,
|
||||
(LPBYTE)buffer, &len);
|
||||
if (rc == ERROR_SUCCESS) {
|
||||
if (len)
|
||||
value = buffer;
|
||||
}
|
||||
::RegCloseKey(key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
PRBool nsMapiRegistryUtils::IsDefaultMailClient()
|
||||
{
|
||||
if (!isSmartDll() && !isMozDll())
|
||||
return PR_FALSE;
|
||||
nsCAutoString name;
|
||||
GetRegistryKey(HKEY_LOCAL_MACHINE, "Software\\Clients\\Mail", "", name);
|
||||
if (!name.IsEmpty()) {
|
||||
nsCAutoString keyName("Software\\Clients\\Mail\\");
|
||||
keyName += name.get();
|
||||
keyName += "\\protocols\\mailto\\shell\\open\\command";
|
||||
|
||||
nsCAutoString result;
|
||||
GetRegistryKey(HKEY_LOCAL_MACHINE, keyName.get(), "", result);
|
||||
if (!result.IsEmpty()) {
|
||||
nsCAutoString strExtension;
|
||||
strExtension.Assign(EXE_EXTENSION);
|
||||
result.ToUpperCase();
|
||||
strExtension.ToUpperCase();
|
||||
PRInt32 index = result.RFind(strExtension.get());
|
||||
if (index != kNotFound) {
|
||||
result.Truncate(index + strExtension.Length());
|
||||
}
|
||||
nsCAutoString thisApp (thisApplication()) ;
|
||||
return (result == thisApp);
|
||||
}
|
||||
}
|
||||
return PR_FALSE;
|
||||
|
||||
}
|
||||
|
||||
nsresult nsMapiRegistryUtils::saveDefaultMailClient()
|
||||
{
|
||||
nsresult rv;
|
||||
nsCAutoString name ;
|
||||
GetRegistryKey(HKEY_LOCAL_MACHINE,"Software\\Clients\\Mail", "", name);
|
||||
if (!name.IsEmpty()) {
|
||||
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
|
||||
"Software\\Mozilla\\Desktop",
|
||||
"HKEY_LOCAL_MACHINE\\Software\\Clients\\Mail",
|
||||
(char *)name.get());
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCAutoString keyName("Software\\Clients\\Mail\\");
|
||||
keyName += name.get();
|
||||
keyName += "\\protocols\\mailto\\shell\\open\\command";
|
||||
nsCAutoString appPath ;
|
||||
GetRegistryKey(HKEY_LOCAL_MACHINE, keyName.get(), "", appPath);
|
||||
if (!appPath.IsEmpty()) {
|
||||
nsCAutoString stringName("HKEY_LOCAL_MACHINE\\");
|
||||
stringName += keyName.get();
|
||||
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
|
||||
"Software\\Mozilla\\Desktop",
|
||||
stringName.get(), (char *)appPath.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
|
||||
"Software\\Mozilla\\Desktop",
|
||||
"HKEY_LOCAL_MACHINE\\Software\\Clients\\Mail",
|
||||
"");
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsMapiRegistryUtils::saveUserDefaultMailClient()
|
||||
{
|
||||
nsresult rv;
|
||||
nsCAutoString name ;
|
||||
GetRegistryKey(HKEY_CURRENT_USER,"Software\\Clients\\Mail", "", name);
|
||||
if (!name.IsEmpty()) {
|
||||
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
|
||||
"Software\\Mozilla\\Desktop",
|
||||
"HKEY_CURRENT_USER\\Software\\Clients\\Mail",
|
||||
(char *)name.get());
|
||||
}
|
||||
else {
|
||||
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
|
||||
"Software\\Mozilla\\Desktop",
|
||||
"HKEY_CURRENT_USER\\Software\\Clients\\Mail",
|
||||
"");
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether it is a smart dll or not. Smart dll is the one installed by
|
||||
* IE5 or Outlook Express which forwards the MAPI calls to the dll based on the
|
||||
* registry key setttings.
|
||||
* Returns TRUE if is a smart dll.
|
||||
*/
|
||||
|
||||
typedef HRESULT (FAR PASCAL GetOutlookVersionFunc)();
|
||||
PRBool nsMapiRegistryUtils::isSmartDll()
|
||||
{
|
||||
char buffer[MAX_PATH] = {0};
|
||||
if (GetSystemDirectory(buffer, sizeof(buffer)) == 0)
|
||||
return PR_FALSE;
|
||||
PL_strcatn(buffer, sizeof(buffer), "\\Mapi32.dll");
|
||||
|
||||
HINSTANCE hInst;
|
||||
GetOutlookVersionFunc *doesExist = nsnull;
|
||||
hInst = LoadLibrary(buffer);
|
||||
if (hInst == nsnull)
|
||||
return PR_FALSE;
|
||||
|
||||
doesExist = (GetOutlookVersionFunc *) GetProcAddress (hInst, "GetOutlookVersion");
|
||||
FreeLibrary(hInst);
|
||||
|
||||
return (doesExist != nsnull);
|
||||
}
|
||||
|
||||
typedef HRESULT (FAR PASCAL GetMapiDllVersion)();
|
||||
/**
|
||||
* Checks whether mapi32.dll is installed by this app.
|
||||
* Returns TRUE if it is.
|
||||
*/
|
||||
PRBool nsMapiRegistryUtils::isMozDll()
|
||||
{
|
||||
char buffer[MAX_PATH] = {0};
|
||||
if (GetSystemDirectory(buffer, sizeof(buffer)) == 0)
|
||||
return PR_FALSE;
|
||||
PL_strcatn(buffer, sizeof(buffer), "\\Mapi32.dll");
|
||||
|
||||
HINSTANCE hInst;
|
||||
GetMapiDllVersion *doesExist = nsnull;
|
||||
hInst = LoadLibrary(buffer);
|
||||
if (hInst == nsnull)
|
||||
return PR_FALSE;
|
||||
|
||||
doesExist = (GetMapiDllVersion *) GetProcAddress (hInst, "GetMapiDllVersion");
|
||||
FreeLibrary(hInst);
|
||||
|
||||
return (doesExist != nsnull);
|
||||
}
|
||||
|
||||
/** Renames Mapi32.dl in system directory to Mapi32_moz_bak.dll
|
||||
* copies the mozMapi32.dll from bin directory to the system directory
|
||||
*/
|
||||
nsresult nsMapiRegistryUtils::CopyMozMapiToWinSysDir()
|
||||
{
|
||||
nsresult rv;
|
||||
char buffer[MAX_PATH] = {0};
|
||||
if (GetSystemDirectory(buffer, sizeof(buffer)) == 0)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCAutoString filePath(buffer);
|
||||
filePath.Append("\\Mapi32_moz_bak.dll");
|
||||
|
||||
nsCOMPtr<nsILocalFile> pCurrentMapiFile = do_CreateInstance (NS_LOCAL_FILE_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv) || !pCurrentMapiFile) return rv;
|
||||
pCurrentMapiFile->InitWithPath(filePath.get());
|
||||
|
||||
nsCOMPtr<nsIFile> pMozMapiFile;
|
||||
nsCOMPtr<nsIProperties> directoryService =
|
||||
do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
|
||||
if (!directoryService) return NS_ERROR_FAILURE;
|
||||
rv = directoryService->Get(NS_OS_CURRENT_PROCESS_DIR,
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(pMozMapiFile));
|
||||
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
pMozMapiFile->Append("mozMapi32.dll");
|
||||
|
||||
PRBool bExist;
|
||||
rv = pMozMapiFile->Exists(&bExist);
|
||||
if (NS_FAILED(rv) || !bExist) return rv;
|
||||
|
||||
rv = pCurrentMapiFile->Exists(&bExist);
|
||||
if (NS_SUCCEEDED(rv) && bExist)
|
||||
{
|
||||
rv = pCurrentMapiFile->Remove(PR_FALSE);
|
||||
}
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
filePath.Assign(buffer);
|
||||
filePath.Append("\\Mapi32.dll");
|
||||
pCurrentMapiFile->InitWithPath(filePath.get());
|
||||
rv = pCurrentMapiFile->Exists(&bExist);
|
||||
if (NS_SUCCEEDED(rv) && bExist)
|
||||
{
|
||||
rv = pCurrentMapiFile->MoveTo(nsnull, "Mapi32_moz_bak.dll");
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
nsCAutoString fullFilePath(buffer);
|
||||
fullFilePath.Append("\\Mapi32_moz_bak.dll");
|
||||
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
|
||||
"Software\\Mozilla\\Desktop",
|
||||
"Mapi_backup_dll",
|
||||
(char *)fullFilePath.get());
|
||||
if (NS_FAILED(rv)) {
|
||||
RestoreBackedUpMapiDll();
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
NS_NAMED_LITERAL_STRING(fileName, "Mapi32.dll");
|
||||
filePath.Assign(buffer);
|
||||
pCurrentMapiFile->InitWithPath(filePath.get());
|
||||
rv = pMozMapiFile->CopyToUnicode(pCurrentMapiFile, fileName.get());
|
||||
if (NS_FAILED(rv))
|
||||
RestoreBackedUpMapiDll();
|
||||
return rv;
|
||||
}
|
||||
|
||||
/** deletes the Mapi32.dll in system directory and renames Mapi32_moz_bak.dll
|
||||
* to Mapi32.dll
|
||||
*/
|
||||
nsresult nsMapiRegistryUtils::RestoreBackedUpMapiDll()
|
||||
{
|
||||
nsresult rv;
|
||||
char buffer[MAX_PATH] = {0};
|
||||
if (GetSystemDirectory(buffer, sizeof(buffer)) == 0)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCAutoString filePath(buffer);
|
||||
nsCAutoString previousFileName(buffer);
|
||||
filePath.Append("\\Mapi32.dll");
|
||||
previousFileName.Append("\\Mapi32_moz_bak.dll");
|
||||
|
||||
nsCOMPtr <nsILocalFile> pCurrentMapiFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv) || !pCurrentMapiFile) return NS_ERROR_FAILURE;
|
||||
pCurrentMapiFile->InitWithPath(filePath.get());
|
||||
|
||||
nsCOMPtr<nsILocalFile> pPreviousMapiFile = do_CreateInstance (NS_LOCAL_FILE_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv) || !pPreviousMapiFile) return NS_ERROR_FAILURE;
|
||||
pPreviousMapiFile->InitWithPath(previousFileName.get());
|
||||
|
||||
PRBool bExist;
|
||||
rv = pCurrentMapiFile->Exists(&bExist);
|
||||
if (NS_SUCCEEDED(rv) && bExist) {
|
||||
rv = pCurrentMapiFile->Remove(PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
rv = pPreviousMapiFile->Exists(&bExist);
|
||||
if (NS_SUCCEEDED(rv) && bExist)
|
||||
rv = pPreviousMapiFile->MoveTo(nsnull, "Mapi32.dll");
|
||||
if (NS_SUCCEEDED(rv))
|
||||
DeleteRegistryValue(HKEY_LOCAL_MACHINE,
|
||||
"Software\\Mozilla\\Desktop",
|
||||
"Mapi_backup_dll");
|
||||
return rv;
|
||||
}
|
||||
|
||||
/** Sets Mozilla as default Mail Client
|
||||
*/
|
||||
nsresult nsMapiRegistryUtils::setDefaultMailClient()
|
||||
{
|
||||
nsresult rv;
|
||||
nsresult mailKeySet=NS_ERROR_FAILURE;
|
||||
if (verifyRestrictedAccess()) return NS_ERROR_FAILURE;
|
||||
if (!isSmartDll()) {
|
||||
if (NS_FAILED(CopyMozMapiToWinSysDir())) return NS_ERROR_FAILURE;
|
||||
}
|
||||
rv = saveDefaultMailClient();
|
||||
if (NS_FAILED(saveUserDefaultMailClient()) ||
|
||||
NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
nsCAutoString keyName("Software\\Clients\\Mail\\");
|
||||
|
||||
nsCAutoString appName (NS_ConvertUCS2toUTF8(brandName()).get());
|
||||
if (!appName.IsEmpty()) {
|
||||
keyName.Append(appName.get());
|
||||
|
||||
nsCOMPtr<nsIStringBundle> bundle;
|
||||
rv = MakeMapiStringBundle (getter_AddRefs (bundle)) ;
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
|
||||
nsXPIDLString defaultMailTitle;
|
||||
const PRUnichar *keyValuePrefixStr[] = { brandName(), versionNo() };
|
||||
NS_NAMED_LITERAL_STRING(defaultMailTitleTag, "defaultMailDisplayTitle");
|
||||
rv = bundle->FormatStringFromName(defaultMailTitleTag.get(),
|
||||
keyValuePrefixStr, 2,
|
||||
getter_Copies(defaultMailTitle));
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
|
||||
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
|
||||
keyName.get(),
|
||||
"", NS_CONST_CAST(char *, NS_ConvertUCS2toUTF8(defaultMailTitle).get()) ) ;
|
||||
}
|
||||
else
|
||||
rv = NS_ERROR_FAILURE;
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCAutoString thisApp (thisApplication()) ;
|
||||
if (NS_FAILED(rv)) return rv ;
|
||||
|
||||
nsCAutoString dllPath (thisApp) ;
|
||||
PRInt32 index = dllPath.RFind("\\");
|
||||
if (index != kNotFound)
|
||||
dllPath.Truncate(index + 1);
|
||||
dllPath += "mozMapi32.dll";
|
||||
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
|
||||
keyName.get(), "DLLPath",
|
||||
(char *)dllPath.get());
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
keyName.Append("\\protocols\\mailto");
|
||||
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
|
||||
keyName.get(),
|
||||
"", "URL:MailTo Protocol");
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCAutoString appPath (thisApp);
|
||||
appPath += " \"%1\"";
|
||||
keyName.Append("\\shell\\open\\command");
|
||||
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
|
||||
keyName.get(),
|
||||
"", (char *)appPath.get());
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
|
||||
"Software\\Clients\\Mail",
|
||||
"", (char *)appName.get());
|
||||
}
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCAutoString mailAppPath(thisApp);
|
||||
mailAppPath += " -mail";
|
||||
nsCAutoString appKeyName ("Software\\Clients\\Mail\\");
|
||||
appKeyName.Append(appName.get());
|
||||
appKeyName.Append("\\shell\\open\\command");
|
||||
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
|
||||
appKeyName.get(),
|
||||
"", (char *)mailAppPath.get());
|
||||
}
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCAutoString iconPath(thisApp);
|
||||
iconPath += ",0";
|
||||
nsCAutoString iconKeyName ("Software\\Clients\\Mail\\");
|
||||
iconKeyName.Append(appName.get());
|
||||
iconKeyName.Append("\\DefaultIcon");
|
||||
mailKeySet = SetRegistryKey(HKEY_LOCAL_MACHINE,
|
||||
iconKeyName.get(),
|
||||
"", (char *)iconPath.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(mailKeySet)) {
|
||||
nsresult desktopKeySet = SetRegistryKey(HKEY_CURRENT_USER,
|
||||
"Software\\Clients\\Mail",
|
||||
"", (char *)appName.get());
|
||||
if (NS_SUCCEEDED(desktopKeySet)) {
|
||||
desktopKeySet = SetRegistryKey(HKEY_LOCAL_MACHINE,
|
||||
"Software\\Mozilla\\Desktop",
|
||||
"defaultMailHasBeenSet", "1");
|
||||
}
|
||||
::SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0,
|
||||
(LPARAM)"Software\\Clients\\Mail");
|
||||
RegisterServer(CLSID_CMapiImp, "Mozilla MAPI", "mozMapi", "mozMapi.1");
|
||||
return desktopKeySet;
|
||||
}
|
||||
|
||||
return mailKeySet;
|
||||
}
|
||||
|
||||
/** Removes Mozilla as the default Mail client and restores the previous setting
|
||||
*/
|
||||
nsresult nsMapiRegistryUtils::unsetDefaultMailClient() {
|
||||
nsresult result = NS_OK;
|
||||
nsresult mailKeySet = NS_ERROR_FAILURE;
|
||||
if (verifyRestrictedAccess()) return NS_ERROR_FAILURE;
|
||||
if (!isSmartDll()) {
|
||||
if (NS_FAILED(RestoreBackedUpMapiDll())) return NS_ERROR_FAILURE;
|
||||
}
|
||||
nsCAutoString name ;
|
||||
GetRegistryKey(HKEY_LOCAL_MACHINE, "Software\\Mozilla\\Desktop",
|
||||
"HKEY_LOCAL_MACHINE\\Software\\Clients\\Mail", name);
|
||||
nsCAutoString appName (NS_ConvertUCS2toUTF8(brandName()).get());
|
||||
|
||||
if (!name.IsEmpty() && !appName.IsEmpty() && name.Equals(appName)) {
|
||||
nsCAutoString keyName("HKEY_LOCAL_MACHINE\\Software\\Clients\\Mail\\");
|
||||
keyName.Append(appName.get());
|
||||
keyName.Append("\\protocols\\mailto\\shell\\open\\command");
|
||||
nsCAutoString appPath ;
|
||||
GetRegistryKey(HKEY_LOCAL_MACHINE, "Software\\Mozilla\\Desktop",
|
||||
keyName.get(), appPath);
|
||||
if (!appPath.IsEmpty()) {
|
||||
keyName.Assign("Software\\Clients\\Mail\\");
|
||||
keyName.Append(appName.get());
|
||||
keyName.Append("\\protocols\\mailto\\shell\\open\\command");
|
||||
result = SetRegistryKey(HKEY_LOCAL_MACHINE,
|
||||
keyName.get(),
|
||||
"", (char *)appPath.get());
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
PRInt32 index = appPath.RFind("\\");
|
||||
if (index != kNotFound)
|
||||
appPath.Truncate(index + 1);
|
||||
appPath += "mozMapi32.dll";
|
||||
keyName.Assign("Software\\Clients\\Mail\\");
|
||||
keyName.Append(appName.get());
|
||||
result = SetRegistryKey(HKEY_LOCAL_MACHINE,
|
||||
keyName.get(),
|
||||
"DLLPath", (char *) appPath.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!name.IsEmpty()) {
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
mailKeySet = SetRegistryKey(HKEY_LOCAL_MACHINE,
|
||||
"Software\\Clients\\Mail",
|
||||
"", (char *)name.get());
|
||||
}
|
||||
}
|
||||
else
|
||||
mailKeySet = SetRegistryKey(HKEY_LOCAL_MACHINE,
|
||||
"Software\\Clients\\Mail",
|
||||
"", "");
|
||||
|
||||
if (NS_SUCCEEDED(mailKeySet)) {
|
||||
nsCAutoString userAppName ;
|
||||
GetRegistryKey(HKEY_LOCAL_MACHINE,
|
||||
"Software\\Mozilla\\Desktop",
|
||||
"HKEY_CURRENT_USER\\Software\\Clients\\Mail", userAppName);
|
||||
nsresult desktopKeySet = NS_OK;
|
||||
if (!userAppName.IsEmpty()) {
|
||||
desktopKeySet = SetRegistryKey(HKEY_CURRENT_USER,
|
||||
"Software\\Clients\\Mail",
|
||||
"", (char *)userAppName.get());
|
||||
}
|
||||
else {
|
||||
DeleteRegistryValue(HKEY_CURRENT_USER, "Software\\Clients\\Mail", "");
|
||||
}
|
||||
if (NS_SUCCEEDED(desktopKeySet)) {
|
||||
desktopKeySet = SetRegistryKey(HKEY_LOCAL_MACHINE,
|
||||
"Software\\Mozilla\\Desktop",
|
||||
"defaultMailHasBeenSet", "0");
|
||||
}
|
||||
::SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0,
|
||||
(LPARAM)"Software\\Clients\\Mail");
|
||||
UnregisterServer(CLSID_CMapiImp, "mozMapi", "mozMapi.1");
|
||||
return desktopKeySet;
|
||||
}
|
||||
return mailKeySet;
|
||||
}
|
||||
|
||||
/** Returns FALSE if showMapiDialog is set to 0.
|
||||
* Returns TRUE otherwise
|
||||
* Also returns TRUE if the Mozilla has been set as the default mail client
|
||||
* and some other application has changed that setting.
|
||||
* This function gets called only if the current app is not the default mail
|
||||
* client
|
||||
*/
|
||||
PRBool nsMapiRegistryUtils::getShowDialog() {
|
||||
PRBool rv = PR_FALSE;
|
||||
nsCAutoString showDialog ;
|
||||
GetRegistryKey(HKEY_LOCAL_MACHINE, "Software\\Mozilla\\Desktop",
|
||||
"showMapiDialog", showDialog);
|
||||
// if the user has not selected the checkbox, show dialog
|
||||
if (showDialog.IsEmpty() || showDialog.Equals("1"))
|
||||
rv = PR_TRUE;
|
||||
|
||||
if (!rv) {
|
||||
// even if the user has selected the checkbox
|
||||
// show it if some other application has changed the
|
||||
// default setting.
|
||||
nsCAutoString setMailDefault ;
|
||||
GetRegistryKey(HKEY_LOCAL_MACHINE,"Software\\Mozilla\\Desktop",
|
||||
"defaultMailHasBeenSet", setMailDefault);
|
||||
if (setMailDefault.Equals("1")) {
|
||||
// need to reset the defaultMailHasBeenSet to "0"
|
||||
// so that after the dialog is displayed once,
|
||||
// we do not keep displaying this dialog after the user has
|
||||
// selected the checkbox
|
||||
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
|
||||
"Software\\Mozilla\\Desktop",
|
||||
"defaultMailHasBeenSet", "0");
|
||||
rv = PR_TRUE;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsMapiRegistryUtils::MakeMapiStringBundle(nsIStringBundle ** aMapiStringBundle)
|
||||
{
|
||||
nsresult rv = NS_OK ;
|
||||
|
||||
if (m_mapiStringBundle)
|
||||
{
|
||||
*aMapiStringBundle = m_mapiStringBundle ;
|
||||
NS_ADDREF(*aMapiStringBundle);
|
||||
return rv ;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIStringBundleService> bundleService(do_GetService(
|
||||
kStringBundleServiceCID, &rv));
|
||||
if (NS_FAILED(rv) || !bundleService) return NS_ERROR_FAILURE;
|
||||
|
||||
rv = bundleService->CreateBundle(
|
||||
MAPI_PROPERTIES_CHROME,
|
||||
getter_AddRefs(m_mapiStringBundle));
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
|
||||
NS_ADDREF(*aMapiStringBundle = m_mapiStringBundle) ;
|
||||
|
||||
return rv ;
|
||||
}
|
||||
|
||||
nsresult nsMapiRegistryUtils::ShowMapiErrorDialog()
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIPromptService> promptService(do_GetService(
|
||||
"@mozilla.org/embedcomp/prompt-service;1", &rv));
|
||||
if (NS_SUCCEEDED(rv) && promptService)
|
||||
{
|
||||
nsCOMPtr<nsIStringBundle> bundle;
|
||||
rv = MakeMapiStringBundle (getter_AddRefs (bundle)) ;
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
|
||||
nsXPIDLString dialogTitle;
|
||||
const PRUnichar *brandStrings[] = { brandName() };
|
||||
NS_NAMED_LITERAL_STRING(dialogTitlePropertyTag, "errorMessageTitle");
|
||||
rv = bundle->FormatStringFromName(dialogTitlePropertyTag.get(),
|
||||
brandStrings, 1,
|
||||
getter_Copies(dialogTitle));
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
|
||||
nsXPIDLString dialogText;
|
||||
NS_NAMED_LITERAL_STRING(dialogTextPropertyTag, "errorMessage");
|
||||
rv = bundle->FormatStringFromName(dialogTextPropertyTag.get(),
|
||||
brandStrings, 1,
|
||||
getter_Copies(dialogText));
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
|
||||
rv = promptService->Alert(nsnull, dialogTitle,
|
||||
dialogText);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
112
mozilla/mailnews/mapi/mapihook/src/nsMapiRegistryUtils.h
Normal file
112
mozilla/mailnews/mapi/mapihook/src/nsMapiRegistryUtils.h
Normal file
@@ -0,0 +1,112 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2001
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Srilatha Moturi <srilatha@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef nsmapiregistryutils_h____
|
||||
#define nsmapiregistryutils_h____
|
||||
|
||||
#include <windows.h>
|
||||
#include <string.h>
|
||||
#include <winreg.h>
|
||||
|
||||
#include "Registry.h"
|
||||
#include "nsString.h"
|
||||
#include "nsIStringBundle.h"
|
||||
|
||||
class nsMapiRegistryUtils
|
||||
{
|
||||
private :
|
||||
nsCAutoString m_thisApp ;
|
||||
nsAutoString m_brand ;
|
||||
nsAutoString m_versionNo ;
|
||||
|
||||
nsCOMPtr<nsIStringBundle> m_mapiStringBundle ;
|
||||
public :
|
||||
nsMapiRegistryUtils() ;
|
||||
|
||||
// returns TRUE if the Mapi32.dll is smart dll.
|
||||
PRBool isSmartDll();
|
||||
// returns TRUE if the Mapi32.dll is a Mozilla dll.
|
||||
PRBool isMozDll();
|
||||
|
||||
// Returns the (fully-qualified) name of this executable.
|
||||
const char * thisApplication() ;
|
||||
// This returns the brand name for this application
|
||||
const PRUnichar * brandName() ;
|
||||
// This returns the version no for this application
|
||||
const PRUnichar * versionNo() ;
|
||||
// verifyRestrictedAccess - Returns PR_TRUE if this user only has restricted access
|
||||
// to the registry keys we need to modify.
|
||||
PRBool verifyRestrictedAccess() ;
|
||||
|
||||
// set the Windows registry key
|
||||
nsresult SetRegistryKey(HKEY baseKey, const char * keyName,
|
||||
const char * valueName, char * value);
|
||||
// delete a registry key
|
||||
nsresult DeleteRegistryValue(HKEY baseKey, const char * keyName,
|
||||
const char * valueName);
|
||||
// get a Windows registry key
|
||||
void GetRegistryKey(HKEY baseKey, const char * keyName,
|
||||
const char * valueName, nsCAutoString & value) ;
|
||||
|
||||
// Returns TRUE if the current application is default mail client.
|
||||
PRBool IsDefaultMailClient();
|
||||
// Sets Mozilla as default Mail Client
|
||||
nsresult setDefaultMailClient() ;
|
||||
// Removes Mozilla as the default Mail client and restores the previous setting
|
||||
nsresult unsetDefaultMailClient() ;
|
||||
|
||||
// Saves the current setting of the default Mail Client in
|
||||
// HKEY_LOCAL_MACHINE\\Software\\Mozilla\\Desktop
|
||||
nsresult saveDefaultMailClient();
|
||||
// Saves the current user setting of the default Mail Client in
|
||||
// HKEY_LOCAL_MACHINE\\Software\\Mozilla\\Desktop
|
||||
nsresult saveUserDefaultMailClient();
|
||||
|
||||
nsresult CopyMozMapiToWinSysDir();
|
||||
nsresult RestoreBackedUpMapiDll();
|
||||
|
||||
// Returns FALSE if showMapiDialog is set to 0.
|
||||
PRBool getShowDialog() ;
|
||||
|
||||
// create a string bundle for MAPI messages
|
||||
nsresult MakeMapiStringBundle(nsIStringBundle ** aMapiStringBundle) ;
|
||||
// display an error dialog for MAPI messages
|
||||
nsresult ShowMapiErrorDialog() ;
|
||||
|
||||
} ;
|
||||
|
||||
#endif
|
||||
30
mozilla/mailnews/mapi/resources/content/contents.rdf
Normal file
30
mozilla/mailnews/mapi/resources/content/contents.rdf
Normal file
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:chrome="http://www.mozilla.org/rdf/chrome#">
|
||||
|
||||
<!-- list all the packages being supplied by this jar -->
|
||||
<RDF:Seq about="urn:mozilla:package:root">
|
||||
<RDF:li resource="urn:mozilla:package:messenger-mapi"/>
|
||||
</RDF:Seq>
|
||||
|
||||
<!-- package information -->
|
||||
<RDF:Description about="urn:mozilla:package:messenger-mapi"
|
||||
chrome:displayName="Messenger"
|
||||
chrome:author="mozilla.org"
|
||||
chrome:name="messenger-mapi"
|
||||
chrome:localeVersion="0.9.7"
|
||||
chrome:skinVersion="0.9.4">
|
||||
</RDF:Description>
|
||||
|
||||
<!-- overlay information -->
|
||||
<RDF:Seq about="urn:mozilla:overlays">
|
||||
<RDF:li resource="chrome://messenger/content/pref-mailnews.xul"/>
|
||||
</RDF:Seq>
|
||||
|
||||
<!-- mapi items for Mail And Newsgroups preferences pane -->
|
||||
<RDF:Seq about="chrome://messenger/content/pref-mailnews.xul">
|
||||
<RDF:li>chrome://messenger-mapi/content/pref-mailnewsOverlay.xul</RDF:li>
|
||||
</RDF:Seq>
|
||||
|
||||
</RDF:RDF>
|
||||
3
mozilla/mailnews/mapi/resources/content/jar.mn
Normal file
3
mozilla/mailnews/mapi/resources/content/jar.mn
Normal file
@@ -0,0 +1,3 @@
|
||||
messenger.jar:
|
||||
content/messenger-mapi/pref-mailnewsOverlay.xul
|
||||
content/messenger-mapi/contents.rdf
|
||||
29
mozilla/mailnews/mapi/resources/content/makefile.win
Normal file
29
mozilla/mailnews/mapi/resources/content/makefile.win
Normal file
@@ -0,0 +1,29 @@
|
||||
#!nmake
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 2001 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Srilatha Moturi <srilatha@netscape.com>
|
||||
#
|
||||
|
||||
DEPTH=..\..\..\..
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
||||
chrome::
|
||||
$(REGCHROME) content messenger-mapi messenger.jar
|
||||
14
mozilla/mailnews/mapi/resources/content/overlays.rdf
Normal file
14
mozilla/mailnews/mapi/resources/content/overlays.rdf
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0"?>
|
||||
<RDF:RDF xmlns:chrome="http://www.mozilla.org/rdf/chrome#"
|
||||
xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
|
||||
<!-- mapi items for mailnews preferences -->
|
||||
<RDF:Seq about="urn:mozilla:overlays">
|
||||
<RDF:li resource="chrome://messenger/content/pref-mailnews.xul"/>
|
||||
</RDF:Seq>
|
||||
|
||||
<RDF:Seq about="chrome://messenger/content/pref-mailnews.xul">
|
||||
<RDF:li>chrome://messenger/content/pref-mailnewsOverlay.xul</RDF:li>
|
||||
</RDF:Seq>
|
||||
|
||||
</RDF:RDF>
|
||||
104
mozilla/mailnews/mapi/resources/content/pref-mailnewsOverlay.js
Normal file
104
mozilla/mailnews/mapi/resources/content/pref-mailnewsOverlay.js
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 2001 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Srilatha Moturi <srilatha@netscape.com>
|
||||
*/
|
||||
|
||||
function mailnewsOverlayStartup() {
|
||||
mailnewsOverlayInit();
|
||||
parent.hPrefWindow.registerOKCallbackFunc(onOK);
|
||||
if (!("mapiPref" in parent)) {
|
||||
parent.mapiPref = new Object;
|
||||
parent.mapiPref.isDefaultMailClient =
|
||||
document.getElementById("mailnewsEnableMapi").checked;
|
||||
}
|
||||
else {
|
||||
// when we switch between different panes
|
||||
// set the checkbox based on the saved state
|
||||
var mailnewsEnableMapi = document.getElementById("mailnewsEnableMapi");
|
||||
if (parent.mapiPref.isDefaultMailClient)
|
||||
mailnewsEnableMapi.setAttribute("checked", "true");
|
||||
else
|
||||
mailnewsEnableMapi.setAttribute("checked", "false");
|
||||
}
|
||||
}
|
||||
|
||||
function mailnewsOverlayInit() {
|
||||
try {
|
||||
var mapiRegistry = Components.classes[ "@mozilla.org/mapiregistry;1" ].
|
||||
getService( Components.interfaces.nsIMapiRegistry );
|
||||
}
|
||||
catch(ex){
|
||||
mapiRegistry = null;
|
||||
}
|
||||
|
||||
const prefbase = "system.windows.lock_ui.";
|
||||
var mailnewsEnableMapi = document.getElementById("mailnewsEnableMapi");
|
||||
if (mapiRegistry) {
|
||||
// initialise preference component.
|
||||
// While the data is coming from the system registry, we use a set
|
||||
// of parallel preferences to indicate if the ui should be locked.
|
||||
try {
|
||||
var prefService = Components.classes["@mozilla.org/preferences-service;1"]
|
||||
.getService()
|
||||
.QueryInterface(Components.interfaces.nsIPrefService);
|
||||
var prefBranch = prefService.getBranch(prefbase);
|
||||
if (prefBranch && prefBranch.prefIsLocked("default_mail_client")) {
|
||||
if (prefBranch.getBoolPref("default_mail_client"))
|
||||
mapiRegistry.setDefaultMailClient();
|
||||
else
|
||||
mapiRegistry.unsetDefaultMailClient();
|
||||
mailnewsEnableMapi.setAttribute("disabled", "true");
|
||||
}
|
||||
}
|
||||
catch(ex) {}
|
||||
if (mapiRegistry.isDefaultMailClient)
|
||||
mailnewsEnableMapi.setAttribute("checked", "true");
|
||||
else
|
||||
mailnewsEnableMapi.setAttribute("checked", "false");
|
||||
}
|
||||
else
|
||||
mailnewsEnableMapi.setAttribute("disabled", "true");
|
||||
}
|
||||
|
||||
function onEnableMapi() {
|
||||
// save the state of the checkbox
|
||||
if ("mapiPref" in parent)
|
||||
parent.mapiPref.isDefaultMailClient =
|
||||
document.getElementById("mailnewsEnableMapi").checked;
|
||||
}
|
||||
|
||||
function onOK()
|
||||
{
|
||||
try {
|
||||
var mapiRegistry = Components.classes[ "@mozilla.org/mapiregistry;1" ].
|
||||
getService( Components.interfaces.nsIMapiRegistry );
|
||||
}
|
||||
catch(ex){
|
||||
mapiRegistry = null;
|
||||
}
|
||||
if (mapiRegistry &&
|
||||
("mapiPref" in parent) &&
|
||||
(mapiRegistry.isDefaultMailClient != parent.mapiPref.isDefaultMailClient)) {
|
||||
if (parent.mapiPref.isDefaultMailClient)
|
||||
mapiRegistry.setDefaultMailClient();
|
||||
else
|
||||
mapiRegistry.unsetDefaultMailClient();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
The contents of this file are subject to the Mozilla Public
|
||||
License Version 1.1 (the "License"); you may not use this file
|
||||
except in compliance with the License. You may obtain a copy of
|
||||
the License at http://www.mozilla.org/MPL/
|
||||
|
||||
oftware distributed under the License is distributed on an "AS
|
||||
IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
rights and limitations under the License.
|
||||
|
||||
The Original Code is mozilla.org code.
|
||||
The Initial Developer of the Original Code is Netscape
|
||||
Communications Corporation. Portions created by Netscape are
|
||||
Copyright (C) 2001 Netscape Communications Corporation. All
|
||||
Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
Srilatha Moturi <srilatha@netscape.com>
|
||||
-->
|
||||
|
||||
<!DOCTYPE window [
|
||||
<!ENTITY % brandDTD SYSTEM "chrome://global/locale/brand.dtd" >
|
||||
%brandDTD;
|
||||
<!ENTITY % prefMailnewsOverlayDTD SYSTEM "chrome://messenger-mapi/locale/pref-mailnewsOverlay.dtd" >
|
||||
%prefMailnewsOverlayDTD;
|
||||
]>
|
||||
<overlay id="prefMailnewsOverlay"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<script type="application/x-javascript">
|
||||
<![CDATA[
|
||||
_elementIDs.push("mailnewsEnableMapi");
|
||||
]]>
|
||||
</script>
|
||||
<script type="application/x-javascript" src="chrome://messenger-mapi/content/pref-mailnewsOverlay.js"/>
|
||||
<hbox autostretch="never" id="mapi">
|
||||
<checkbox id="mailnewsEnableMapi" label="&enableMapi.label;"
|
||||
accesskey="&enableMapi.accesskey;"
|
||||
preftype="bool" prefstring="mailnews.default_mail_client" prefattribute="checked"/>
|
||||
|
||||
</hbox>
|
||||
</overlay>
|
||||
23
mozilla/mailnews/mapi/resources/locale/en-US/contents.rdf
Normal file
23
mozilla/mailnews/mapi/resources/locale/en-US/contents.rdf
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0"?>
|
||||
<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:chrome="http://www.mozilla.org/rdf/chrome#">
|
||||
|
||||
<!-- list all the skins being supplied by this package -->
|
||||
<RDF:Seq about="urn:mozilla:locale:root">
|
||||
<RDF:li resource="urn:mozilla:locale:en-US"/>
|
||||
</RDF:Seq>
|
||||
|
||||
<!-- locale information -->
|
||||
<RDF:Description about="urn:mozilla:locale:en-US">
|
||||
<chrome:packages>
|
||||
<RDF:Seq about="urn:mozilla:locale:en-US:packages">
|
||||
<RDF:li resource="urn:mozilla:locale:en-US:messenger-mapi"/>
|
||||
</RDF:Seq>
|
||||
</chrome:packages>
|
||||
</RDF:Description>
|
||||
|
||||
<!-- Version Information. State that we work only with major version of this
|
||||
package. -->
|
||||
<RDF:Description about="urn:mozilla:locale:en-US:messenger-mapi"
|
||||
chrome:localeVersion="0.9.7"/>
|
||||
</RDF:RDF>
|
||||
4
mozilla/mailnews/mapi/resources/locale/en-US/jar.mn
Normal file
4
mozilla/mailnews/mapi/resources/locale/en-US/jar.mn
Normal file
@@ -0,0 +1,4 @@
|
||||
en-US.jar:
|
||||
locale/en-US/messenger-mapi/pref-mailnewsOverlay.dtd
|
||||
locale/en-US/messenger-mapi/mapi.properties
|
||||
locale/en-US/messenger-mapi/contents.rdf
|
||||
40
mozilla/mailnews/mapi/resources/locale/en-US/makefile.win
Normal file
40
mozilla/mailnews/mapi/resources/locale/en-US/makefile.win
Normal file
@@ -0,0 +1,40 @@
|
||||
#!nmake
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 2001 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Srilatha Moturi <srilatha@netscape.com>
|
||||
#
|
||||
|
||||
DEPTH=..\..\..\..\..
|
||||
|
||||
|
||||
CHROME_DIR=locales\en-US
|
||||
CHROME_L10N_DIR=messenger\locale
|
||||
|
||||
CHROME_L10N = \
|
||||
.\pref-mailnewsOverlay.dtd \
|
||||
.\mapi.properties \
|
||||
.\contents.rdf \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
||||
chrome::
|
||||
$(REGCHROME) locale en-US/messenger-mapi en-US.jar
|
||||
|
||||
23
mozilla/mailnews/mapi/resources/locale/en-US/mapi.properties
Normal file
23
mozilla/mailnews/mapi/resources/locale/en-US/mapi.properties
Normal file
@@ -0,0 +1,23 @@
|
||||
# Mail Integration Dialog
|
||||
dialogTitle=%S Mail
|
||||
dialogText=Do you want to use %S as the default mail application?
|
||||
checkboxText=Do not display this dialog again
|
||||
|
||||
# MAPI Messages
|
||||
loginText=Please enter your password for %S:
|
||||
loginTextwithName=Please enter your username and password
|
||||
loginTitle=%S Mail
|
||||
PasswordTitle=%S Mail
|
||||
|
||||
# MAPI Error Messages
|
||||
errorMessage=%S Mail could not be set as the default mail application because a registry key could not be updated. Verify with your system administrator that you have write access to your system registry, and then try again.
|
||||
errorMessageTitle=%S Mail
|
||||
|
||||
# MAPI Security Messages
|
||||
mapiBlindSendWarning=Another application is attempting to send mail using your user profile. Are you sure you want to send mail?
|
||||
mapiBlindSendDontShowAgain=Warn me whenever other applications try to send mail from me
|
||||
|
||||
#Default Mail Display String
|
||||
# localization note, $1%S is the app name, $2%S is the version
|
||||
defaultMailDisplayTitle=%S %S Mail
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
<!ENTITY enableMapiTitle.label "When sending mail from other applications">
|
||||
<!ENTITY enableMapi.label "Use &vendorShortName; Mail as the default mail application.">
|
||||
<!ENTITY enableMapi.accesskey "u">
|
||||
28
mozilla/mailnews/mapi/resources/locale/makefile.win
Normal file
28
mozilla/mailnews/mapi/resources/locale/makefile.win
Normal file
@@ -0,0 +1,28 @@
|
||||
#!nmake
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 2001 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Srilatha Moturi <srilatha@netscape.com>
|
||||
#
|
||||
|
||||
DEPTH=..\..\..\..
|
||||
|
||||
DIRS=en-US
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
27
mozilla/mailnews/mapi/resources/makefile.win
Normal file
27
mozilla/mailnews/mapi/resources/makefile.win
Normal file
@@ -0,0 +1,27 @@
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 2001 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Srilatha Moturi <srilatha@netscape.com>
|
||||
#
|
||||
|
||||
DEPTH=..\..\..
|
||||
|
||||
DIRS=content locale
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
@@ -1,152 +0,0 @@
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Dr Vipul Gupta <vipul.gupta@sun.com> and
|
||||
# Douglas Stebila <douglas@stebila.ca>, Sun Microsystems
|
||||
# Laboratories
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
CORE_DEPTH = ../../..
|
||||
|
||||
MODULE = nss
|
||||
|
||||
ifndef FREEBL_RECURSIVE_BUILD
|
||||
LIBRARY_NAME = freebl
|
||||
else
|
||||
ifdef USE_PURE_32
|
||||
CORE_DEPTH = ../../../..
|
||||
LIBRARY_NAME = freebl_pure32
|
||||
else
|
||||
LIBRARY_NAME = freebl_hybrid
|
||||
endif
|
||||
endif
|
||||
|
||||
# same version as rest of freebl
|
||||
LIBRARY_VERSION = _3
|
||||
|
||||
DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\" -DSHLIB_PREFIX=\"$(DLL_PREFIX)\"
|
||||
|
||||
REQUIRES =
|
||||
|
||||
EXPORTS = \
|
||||
blapit.h \
|
||||
shsign.h \
|
||||
ecl-exp.h \
|
||||
$(NULL)
|
||||
|
||||
PRIVATE_EXPORTS = \
|
||||
blapi.h \
|
||||
secmpi.h \
|
||||
secrng.h \
|
||||
ec.h \
|
||||
ecl.h \
|
||||
ecl-curve.h \
|
||||
$(NULL)
|
||||
|
||||
MPI_HDRS = mpi-config.h mpi.h mpi-priv.h mplogic.h mpprime.h logtab.h mp_gf2m.h
|
||||
MPI_SRCS = mpprime.c mpmontg.c mplogic.c mpi.c mp_gf2m.c mpcpucache.c
|
||||
ECL_HDRS = ecl-exp.h ecl.h ec2.h ecp.h ecl-priv.h
|
||||
ifdef NSS_ENABLE_ECC
|
||||
ECL_SRCS = ecl.c ecl_curve.c ecl_mult.c ecl_gf.c \
|
||||
ec2_aff.c ec2_mont.c ec2_proj.c \
|
||||
ec2_163.c ec2_193.c ec2_233.c \
|
||||
ecp_aff.c ecp_jac.c ecp_mont.c \
|
||||
ecp_192.c ecp_224.c \
|
||||
ec_naf.c ecp_jm.c
|
||||
else
|
||||
ECL_SRCS = $(NULL)
|
||||
endif
|
||||
|
||||
CSRCS = \
|
||||
ldvector.c \
|
||||
prng_fips1861.c \
|
||||
sysrand.c \
|
||||
sha_fast.c \
|
||||
md2.c \
|
||||
md5.c \
|
||||
sha512.c \
|
||||
alg2268.c \
|
||||
arcfour.c \
|
||||
arcfive.c \
|
||||
desblapi.c \
|
||||
des.c \
|
||||
rijndael.c \
|
||||
aeskeywrap.c \
|
||||
dh.c \
|
||||
ec.c \
|
||||
pqg.c \
|
||||
dsa.c \
|
||||
rsa.c \
|
||||
shvfy.c \
|
||||
$(MPI_SRCS) \
|
||||
$(ECL_SRCS) \
|
||||
$(NULL)
|
||||
|
||||
ALL_CSRCS := $(CSRCS)
|
||||
|
||||
ALL_HDRS = \
|
||||
blapi.h \
|
||||
blapit.h \
|
||||
des.h \
|
||||
ec.h \
|
||||
loader.h \
|
||||
rijndael.h \
|
||||
secmpi.h \
|
||||
sha.h \
|
||||
sha_fast.h \
|
||||
shsign.h \
|
||||
vis_proto.h \
|
||||
$(NULL)
|
||||
|
||||
ifdef NSS_ENABLE_ECC
|
||||
DEFINES += -DNSS_ENABLE_ECC
|
||||
endif
|
||||
|
||||
ifdef AES_GEN_TBL
|
||||
DEFINES += -DRIJNDAEL_GENERATE_TABLES
|
||||
else
|
||||
ifdef AES_GEN_TBL_M
|
||||
DEFINES += -DRIJNDAEL_GENERATE_TABLES_MACRO
|
||||
else
|
||||
ifdef AES_GEN_VAL
|
||||
DEFINES += -DRIJNDAEL_GENERATE_VALUES
|
||||
else
|
||||
ifdef AES_GEN_VAL_M
|
||||
DEFINES += -DRIJNDAEL_GENERATE_VALUES_MACRO
|
||||
else
|
||||
DEFINES += -DRIJNDAEL_INCLUDE_TABLES
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
@@ -1,278 +0,0 @@
|
||||
#
|
||||
# Makefile for MPI library
|
||||
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the MPI Arbitrary Precision Integer Arithmetic library.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Michael J. Fromberger <sting@linguist.dartmouth.edu>.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Netscape Communications Corporation
|
||||
# Richard C. Swift (swift@netscape.com)
|
||||
# Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# $Id: Makefile,v 1.21 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
#
|
||||
|
||||
## Define CC to be the C compiler you wish to use. The GNU cc
|
||||
## compiler (gcc) should work, at the very least
|
||||
#CC=cc
|
||||
#CC=gcc
|
||||
|
||||
##
|
||||
## Define PERL to point to your local Perl interpreter. It
|
||||
## should be Perl 5.x, although it's conceivable that Perl 4
|
||||
## might work ... I haven't tested it.
|
||||
##
|
||||
#PERL=/usr/bin/perl
|
||||
PERL=perl
|
||||
|
||||
include target.mk
|
||||
|
||||
CFLAGS+= $(XCFLAGS)
|
||||
|
||||
##
|
||||
## Define LIBS to include any libraries you need to link against.
|
||||
## If NO_TABLE is define, LIBS should include '-lm' or whatever is
|
||||
## necessary to bring in the math library. Otherwise, it can be
|
||||
## left alone, unless your system has other peculiar requirements.
|
||||
##
|
||||
LIBS=#-lmalloc#-lefence#-lm
|
||||
|
||||
##
|
||||
## Define RANLIB to be the library header randomizer; you might not
|
||||
## need this on some systems (just set it to 'echo' on these systems,
|
||||
## such as IRIX)
|
||||
##
|
||||
RANLIB=echo
|
||||
|
||||
##
|
||||
## This is the version string used for the documentation and
|
||||
## building the distribution tarball. Don't mess with it unless
|
||||
## you are releasing a new version
|
||||
VERS=1.7p6
|
||||
|
||||
## ----------------------------------------------------------------------
|
||||
## You probably don't need to change anything below this line...
|
||||
##
|
||||
|
||||
##
|
||||
## This is the list of source files that need to be packed into
|
||||
## the distribution file
|
||||
SRCS= mpi.c mpprime.c mplogic.c mp_gf2m.c mpmontg.c mpi-test.c primes.c tests/ \
|
||||
utils/gcd.c utils/invmod.c utils/lap.c \
|
||||
utils/ptab.pl utils/sieve.c utils/isprime.c\
|
||||
utils/dec2hex.c utils/hex2dec.c utils/bbs_rand.c \
|
||||
utils/bbsrand.c utils/prng.c utils/primegen.c \
|
||||
utils/basecvt.c utils/makeprime.c\
|
||||
utils/fact.c utils/exptmod.c utils/pi.c utils/metime.c \
|
||||
utils/mpi.h utils/mpprime.h mulsqr.c \
|
||||
make-test-arrays test-arrays.txt all-tests make-logtab \
|
||||
types.pl stats timetest multest
|
||||
|
||||
## These are the header files that go into the distribution file
|
||||
HDRS=mpi.h mpi-config.h utils/mpi.h utils/mpi-config.h mpprime.h mplogic.h mp_gf2m.h \
|
||||
mp_gf2m-priv.h utils/bbs_rand.h tests/mpi.h tests/mpprime.h
|
||||
|
||||
## These are the documentation files that go into the distribution file
|
||||
DOCS=README doc utils/README utils/PRIMES
|
||||
|
||||
## This is the list of tools built by 'make tools'
|
||||
TOOLS=gcd invmod isprime lap dec2hex hex2dec primegen prng \
|
||||
basecvt fact exptmod pi makeprime identest
|
||||
|
||||
LIBOBJS = mpprime.o mpmontg.o mplogic.o mp_gf2m.o mpi.o $(AS_OBJS)
|
||||
LIBHDRS = mpi-config.h mpi-priv.h mpi.h
|
||||
APPHDRS = mpi-config.h mpi.h mplogic.h mp_gf2m.h mpprime.h
|
||||
|
||||
help:
|
||||
@ echo ""
|
||||
@ echo "The following targets can be built with this Makefile:"
|
||||
@ echo ""
|
||||
@ echo "libmpi.a - arithmetic and prime testing library"
|
||||
@ echo "mpi-test - test driver (requires MP_IOFUNC)"
|
||||
@ echo "tools - command line tools"
|
||||
@ echo "doc - manual pages for tools"
|
||||
@ echo "clean - clean up objects and such"
|
||||
@ echo "distclean - get ready for distribution"
|
||||
@ echo "dist - distribution tarball"
|
||||
@ echo ""
|
||||
|
||||
.SUFFIXES: .c .o .i
|
||||
|
||||
.c.i:
|
||||
$(CC) $(CFLAGS) -E $< > $@
|
||||
|
||||
#.c.o: $*.h $*.c
|
||||
# $(CC) $(CFLAGS) -c $<
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
$(LIBOBJS): $(LIBHDRS)
|
||||
|
||||
logtab.h: make-logtab
|
||||
$(PERL) make-logtab > logtab.h
|
||||
|
||||
mpi.o: mpi.c logtab.h $(LIBHDRS)
|
||||
|
||||
mplogic.o: mplogic.c mpi-priv.h mplogic.h $(LIBHDRS)
|
||||
|
||||
mp_gf2m.o: mp_gf2m.c mpi-priv.h mp_gf2m.h mp_gf2m-priv.h $(LIBHDRS)
|
||||
|
||||
mpmontg.o: mpmontg.c mpi-priv.h mplogic.h mpprime.h $(LIBHDRS)
|
||||
|
||||
mpprime.o: mpprime.c mpi-priv.h mpprime.h mplogic.h primes.c $(LIBHDRS)
|
||||
|
||||
mpi_mips.o: mpi_mips.s
|
||||
$(CC) -o $@ $(ASFLAGS) -c mpi_mips.s
|
||||
|
||||
mpi_sparc.o : montmulf.h
|
||||
|
||||
mpv_sparcv9.s: vis_64.il mpv_sparc.c
|
||||
$(CC) -o $@ $(SOLARIS_FPU_FLAGS) -S vis_64.il mpv_sparc.c
|
||||
|
||||
mpv_sparcv8.s: vis_64.il mpv_sparc.c
|
||||
$(CC) -o $@ $(SOLARIS_FPU_FLAGS) -S vis_32.il mpv_sparc.c
|
||||
|
||||
montmulfv8.o montmulfv9.o mpv_sparcv8.o mpv_sparcv9.o : %.o : %.s
|
||||
$(CC) -o $@ $(SOLARIS_ASM_FLAGS) -c $<
|
||||
|
||||
# This rule is used to build the .s sources, which are then hand optimized.
|
||||
#montmulfv8.s montmulfv9.s : montmulf%.s : montmulf%.il montmulf.c montmulf.h
|
||||
# $(CC) -o $@ $(SOLARIS_ASM_FLAGS) -S montmulf$*.il montmulf.c
|
||||
|
||||
|
||||
libmpi.a: $(LIBOBJS)
|
||||
ar -cvr libmpi.a $(LIBOBJS)
|
||||
$(RANLIB) libmpi.a
|
||||
|
||||
lib libs: libmpi.a
|
||||
|
||||
mpi.i: mpi.h
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
MPTESTOBJS = mptest1.o mptest2.o mptest3.o mptest3a.o mptest4.o mptest4a.o \
|
||||
mptest4b.o mptest6.o mptest7.o mptest8.o mptest9.o mptestb.o
|
||||
MPTESTS = $(MPTESTOBJS:.o=)
|
||||
|
||||
$(MPTESTOBJS): mptest%.o: tests/mptest-%.c $(LIBHDRS)
|
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
$(MPTESTS): mptest%: mptest%.o libmpi.a
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
tests: mptest1 mptest2 mptest3 mptest3a mptest4 mptest4a mptest4b mptest6 \
|
||||
mptestb bbsrand
|
||||
|
||||
utests: mptest7 mptest8 mptest9
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
EXTRAOBJS = bbsrand.o bbs_rand.o prng.o
|
||||
UTILOBJS = primegen.o metime.o identest.o basecvt.o fact.o exptmod.o pi.o \
|
||||
makeprime.o gcd.o invmod.o lap.o isprime.o \
|
||||
dec2hex.o hex2dec.o
|
||||
UTILS = $(UTILOBJS:.o=)
|
||||
|
||||
$(UTILS): % : %.o libmpi.a
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
$(UTILOBJS) $(EXTRAOBJS): %.o : utils/%.c $(LIBHDRS)
|
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
prng: prng.o bbs_rand.o libmpi.a
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
bbsrand: bbsrand.o bbs_rand.o libmpi.a
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
utils: $(UTILS) prng bbsrand
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
test-info.c: test-arrays.txt
|
||||
$(PERL) make-test-arrays test-arrays.txt > test-info.c
|
||||
|
||||
mpi-test.o: mpi-test.c test-info.c $(LIBHDRS)
|
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
mpi-test: mpi-test.o libmpi.a
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
mdxptest.o: mdxptest.c $(LIBHDRS) mpi-priv.h
|
||||
|
||||
mdxptest: mdxptest.o libmpi.a
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
mulsqr.o: mulsqr.c logtab.h mpi.h mpi-config.h mpprime.h
|
||||
$(CC) $(CFLAGS) -DMP_SQUARE=1 -o $@ -c mulsqr.c
|
||||
|
||||
mulsqr: mulsqr.o libmpi.a
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
alltests: tests utests mpi-test
|
||||
|
||||
tools: $(TOOLS)
|
||||
|
||||
doc:
|
||||
(cd doc; ./build)
|
||||
|
||||
clean:
|
||||
rm -f *.o *.a *.i
|
||||
rm -f core
|
||||
rm -f *~ .*~
|
||||
rm -f utils/*.o
|
||||
rm -f utils/core
|
||||
rm -f utils/*~ utils/.*~
|
||||
|
||||
clobber: clean
|
||||
rm -f $(TOOLS) $(UTILS)
|
||||
|
||||
distclean: clean
|
||||
rm -f mptest? mpi-test metime mulsqr karatsuba
|
||||
rm -f mptest?a mptest?b
|
||||
rm -f utils/mptest?
|
||||
rm -f test-info.c logtab.h
|
||||
rm -f libmpi.a
|
||||
rm -f $(TOOLS)
|
||||
|
||||
dist: Makefile $(HDRS) $(SRCS) $(DOCS)
|
||||
tar -cvf mpi-$(VERS).tar Makefile $(HDRS) $(SRCS) $(DOCS)
|
||||
pgps -ab mpi-$(VERS).tar
|
||||
chmod +r mpi-$(VERS).tar.asc
|
||||
gzip -9 mpi-$(VERS).tar
|
||||
|
||||
# END
|
||||
@@ -1,280 +0,0 @@
|
||||
#
|
||||
# Makefile.win - gmake Makefile for building MPI with VACPP on OS/2
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the MPI Arbitrary Precision Integer Arithmetic library.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Michael J. Fromberger <sting@linguist.dartmouth.edu>.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Netscape Communications Corporation
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# $Id: Makefile.os2,v 1.3 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
#
|
||||
|
||||
## Define CC to be the C compiler you wish to use. The GNU cc
|
||||
## compiler (gcc) should work, at the very least
|
||||
#CC=cc
|
||||
#CC=gcc
|
||||
CC=icc.exe
|
||||
AS=alp.exe
|
||||
|
||||
##
|
||||
## Define PERL to point to your local Perl interpreter. It
|
||||
## should be Perl 5.x, although it's conceivable that Perl 4
|
||||
## might work ... I haven't tested it.
|
||||
##
|
||||
#PERL=/usr/bin/perl
|
||||
PERL=perl
|
||||
|
||||
##
|
||||
## Define CFLAGS to contain any local options your compiler
|
||||
## setup requires.
|
||||
##
|
||||
## Conditional compilation options are no longer here; see
|
||||
## the file 'mpi-config.h' instead.
|
||||
##
|
||||
MPICMN = -I. -DMP_API_COMPATIBLE -DMP_IOFUNC -DMP_USE_UINT_DIGIT -DMP_NO_MP_WORD
|
||||
|
||||
#OS/2
|
||||
AS_SRCS = mpi_x86.asm
|
||||
MPICMN += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE -DMP_ASSEMBLY_DIV_2DX1D
|
||||
#CFLAGS= -Od -Z7 -MD -W3 -nologo -D_X86_ -DXP_PC \
|
||||
-DDEBUG -D_DEBUG -UNDEBUG -DWIN32 -D_WINDOWS -DWIN95 $(MPICMN)
|
||||
#CFLAGS = -O2 -MD -W3 -nologo -D_X86_ -DXP_PC -UDEBUG -U_DEBUG -DNDEBUG \
|
||||
-DWIN32 -D_WINDOWS -DWIN95 $(MPICMN)
|
||||
#CFLAGS = -Od -Z7 -MD -W3 -nologo -D_X86_ -DXP_PC -UDEBUG -U_DEBUG -DNDEBUG \
|
||||
-DWIN32 -D_WINDOWS -DWIN95 $(MPICMN)
|
||||
CFLAGS = /Ti+ -D_X86_ -DXP_PC -UDEBUG -U_DEBUG -DNDEBUG \
|
||||
$(MPICMN)
|
||||
ASFLAGS =
|
||||
|
||||
##
|
||||
## Define LIBS to include any libraries you need to link against.
|
||||
## If NO_TABLE is define, LIBS should include '-lm' or whatever is
|
||||
## necessary to bring in the math library. Otherwise, it can be
|
||||
## left alone, unless your system has other peculiar requirements.
|
||||
##
|
||||
LIBS=#-lmalloc#-lefence#-lm
|
||||
|
||||
##
|
||||
## Define RANLIB to be the library header randomizer; you might not
|
||||
## need this on some systems (just set it to 'echo' on these systems,
|
||||
## such as IRIX)
|
||||
##
|
||||
RANLIB=echo
|
||||
|
||||
##
|
||||
## This is the version string used for the documentation and
|
||||
## building the distribution tarball. Don't mess with it unless
|
||||
## you are releasing a new version
|
||||
VERS=1.7p6
|
||||
|
||||
## ----------------------------------------------------------------------
|
||||
## You probably don't need to change anything below this line...
|
||||
##
|
||||
|
||||
##
|
||||
## This is the list of source files that need to be packed into
|
||||
## the distribution file
|
||||
SRCS= mpi.c mpprime.c mplogic.c mpmontg.c mpi-test.c primes.c tests/ \
|
||||
utils/gcd.c utils/invmod.c utils/lap.c \
|
||||
utils/ptab.pl utils/sieve.c utils/isprime.c\
|
||||
utils/dec2hex.c utils/hex2dec.c utils/bbs_rand.c \
|
||||
utils/bbsrand.c utils/prng.c utils/primegen.c \
|
||||
utils/basecvt.c utils/makeprime.c\
|
||||
utils/fact.c utils/exptmod.c utils/pi.c utils/metime.c \
|
||||
utils/mpi.h utils/mpprime.h mulsqr.c \
|
||||
make-test-arrays test-arrays.txt all-tests make-logtab \
|
||||
types.pl stats timetest multest
|
||||
|
||||
## These are the header files that go into the distribution file
|
||||
HDRS=mpi.h mpi-config.h utils/mpi.h utils/mpi-config.h mpprime.h mplogic.h \
|
||||
utils/bbs_rand.h tests/mpi.h tests/mpprime.h
|
||||
|
||||
## These are the documentation files that go into the distribution file
|
||||
DOCS=README doc utils/README utils/PRIMES
|
||||
|
||||
## This is the list of tools built by 'make tools'
|
||||
TOOLS=gcd.exe invmod.exe isprime.exe lap.exe dec2hex.exe hex2dec.exe \
|
||||
primegen.exe prng.exe basecvt.exe fact.exe exptmod.exe pi.exe makeprime.exe
|
||||
|
||||
AS_OBJS = $(AS_SRCS:.asm=.obj)
|
||||
LIBOBJS = mpprime.obj mpmontg.obj mplogic.obj mpi.obj $(AS_OBJS)
|
||||
LIBHDRS = mpi-config.h mpi-priv.h mpi.h
|
||||
APPHDRS = mpi-config.h mpi.h mplogic.h mpprime.h
|
||||
|
||||
|
||||
help:
|
||||
@ echo ""
|
||||
@ echo "The following targets can be built with this Makefile:"
|
||||
@ echo ""
|
||||
@ echo "mpi.lib - arithmetic and prime testing library"
|
||||
@ echo "mpi-test.exe - test driver (requires MP_IOFUNC)"
|
||||
@ echo "tools - command line tools"
|
||||
@ echo "doc - manual pages for tools"
|
||||
@ echo "clean - clean up objects and such"
|
||||
@ echo "distclean - get ready for distribution"
|
||||
@ echo "dist - distribution tarball"
|
||||
@ echo ""
|
||||
|
||||
.SUFFIXES: .c .obj .i .lib .exe .asm
|
||||
|
||||
.c.i:
|
||||
$(CC) $(CFLAGS) -E $< > $@
|
||||
|
||||
.c.obj:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
||||
.asm.obj:
|
||||
$(AS) $(ASFLAGS) $<
|
||||
|
||||
.obj.exe:
|
||||
$(CC) $(CFLAGS) -Fo$@ $<
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
$(LIBOBJS): $(LIBHDRS)
|
||||
|
||||
logtab.h: make-logtab
|
||||
$(PERL) make-logtab > logtab.h
|
||||
|
||||
mpi.obj: mpi.c logtab.h $(LIBHDRS)
|
||||
|
||||
mplogic.obj: mplogic.c mpi-priv.h mplogic.h $(LIBHDRS)
|
||||
|
||||
mpmontg.obj: mpmontg.c mpi-priv.h mplogic.h mpprime.h $(LIBHDRS)
|
||||
|
||||
mpprime.obj: mpprime.c mpi-priv.h mpprime.h mplogic.h primes.c $(LIBHDRS)
|
||||
|
||||
mpi_mips.obj: mpi_mips.s
|
||||
$(CC) -Fo$@ $(ASFLAGS) -c mpi_mips.s
|
||||
|
||||
mpi.lib: $(LIBOBJS)
|
||||
ilib /out:mpi.lib $(LIBOBJS)
|
||||
$(RANLIB) mpi.lib
|
||||
|
||||
lib libs: mpi.lib
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
MPTESTOBJS = mptest1.obj mptest2.obj mptest3.obj mptest3a.obj mptest4.obj \
|
||||
mptest4a.obj mptest4b.obj mptest6.obj mptest7.obj mptest8.obj mptest9.obj
|
||||
MPTESTS = $(MPTESTOBJS:.obj=.exe)
|
||||
|
||||
$(MPTESTOBJS): mptest%.obj: tests/mptest-%.c $(LIBHDRS)
|
||||
$(CC) $(CFLAGS) -Fo$@ -c $<
|
||||
|
||||
$(MPTESTS): mptest%.exe: mptest%.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
tests: mptest1.exe mptest2.exe mptest3.exe mptest3a.exe mptest4.exe \
|
||||
mptest4a.exe mptest4b.exe mptest6.exe bbsrand.exe
|
||||
|
||||
utests: mptest7.exe mptest8.exe mptest9.exe
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
EXTRAOBJS = bbsrand.obj bbs_rand.obj prng.obj
|
||||
UTILOBJS = primegen.obj metime.obj identest.obj basecvt.obj fact.obj \
|
||||
exptmod.obj pi.obj makeprime.obj karatsuba.obj gcd.obj invmod.obj lap.obj \
|
||||
isprime.obj dec2hex.obj hex2dec.obj
|
||||
UTILS = $(UTILOBJS:.obj=.exe)
|
||||
|
||||
$(UTILS): %.exe : %.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
$(UTILOBJS) $(EXTRAOBJS): %.obj : utils/%.c $(LIBHDRS)
|
||||
$(CC) $(CFLAGS) -Fo$@ -c $<
|
||||
|
||||
prng.exe: prng.obj bbs_rand.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
bbsrand.exe: bbsrand.obj bbs_rand.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
utils: $(UTILS) prng.exe bbsrand.exe
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
test-info.c: test-arrays.txt
|
||||
$(PERL) make-test-arrays test-arrays.txt > test-info.c
|
||||
|
||||
mpi-test.obj: mpi-test.c test-info.c $(LIBHDRS)
|
||||
$(CC) $(CFLAGS) -Fo$@ -c $<
|
||||
|
||||
mpi-test.exe: mpi-test.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
mdxptest.obj: mdxptest.c $(LIBHDRS) mpi-priv.h
|
||||
|
||||
mdxptest.exe: mdxptest.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
mulsqr.obj: mulsqr.c logtab.h mpi.h mpi-config.h mpprime.h
|
||||
$(CC) $(CFLAGS) -DMP_SQUARE=1 -Fo$@ -c mulsqr.c
|
||||
|
||||
mulsqr.exe: mulsqr.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
alltests: tests utests mpi-test.exe
|
||||
|
||||
tools: $(TOOLS)
|
||||
|
||||
doc:
|
||||
(cd doc; ./build)
|
||||
|
||||
clean:
|
||||
rm -f *.obj *.lib *.pdb *.ilk
|
||||
cd utils; rm -f *.obj *.lib *.pdb *.ilk
|
||||
|
||||
distclean: clean
|
||||
rm -f mptest? mpi-test metime mulsqr karatsuba
|
||||
rm -f mptest?a mptest?b
|
||||
rm -f utils/mptest?
|
||||
rm -f test-info.c logtab.h
|
||||
rm -f mpi.lib
|
||||
rm -f $(TOOLS)
|
||||
|
||||
dist: Makefile $(HDRS) $(SRCS) $(DOCS)
|
||||
tar -cvf mpi-$(VERS).tar Makefile $(HDRS) $(SRCS) $(DOCS)
|
||||
pgps -ab mpi-$(VERS).tar
|
||||
chmod +r mpi-$(VERS).tar.asc
|
||||
gzip -9 mpi-$(VERS).tar
|
||||
|
||||
|
||||
print:
|
||||
@echo LIBOBJS = $(LIBOBJS)
|
||||
# END
|
||||
@@ -1,280 +0,0 @@
|
||||
#
|
||||
# Makefile.win - gmake Makefile for building MPI with MSVC on NT
|
||||
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the MPI Arbitrary Precision Integer Arithmetic library.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Michael J. Fromberger <sting@linguist.dartmouth.edu>.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Netscape Communications Corporation
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# $Id: Makefile.win,v 1.3 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
#
|
||||
|
||||
## Define CC to be the C compiler you wish to use. The GNU cc
|
||||
## compiler (gcc) should work, at the very least
|
||||
#CC=cc
|
||||
#CC=gcc
|
||||
CC=cl.exe
|
||||
AS=ml.exe
|
||||
|
||||
##
|
||||
## Define PERL to point to your local Perl interpreter. It
|
||||
## should be Perl 5.x, although it's conceivable that Perl 4
|
||||
## might work ... I haven't tested it.
|
||||
##
|
||||
#PERL=/usr/bin/perl
|
||||
PERL=perl
|
||||
|
||||
##
|
||||
## Define CFLAGS to contain any local options your compiler
|
||||
## setup requires.
|
||||
##
|
||||
## Conditional compilation options are no longer here; see
|
||||
## the file 'mpi-config.h' instead.
|
||||
##
|
||||
MPICMN = -I. -DMP_API_COMPATIBLE -DMP_IOFUNC
|
||||
|
||||
#NT
|
||||
AS_SRCS = mpi_x86.asm
|
||||
MPICMN += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE -DMP_ASSEMBLY_DIV_2DX1D
|
||||
#CFLAGS= -Od -Z7 -MD -W3 -nologo -D_X86_ -DXP_PC \
|
||||
-DDEBUG -D_DEBUG -UNDEBUG -DWIN32 -D_WINDOWS -DWIN95 $(MPICMN)
|
||||
#CFLAGS = -O2 -MD -W3 -nologo -D_X86_ -DXP_PC -UDEBUG -U_DEBUG -DNDEBUG \
|
||||
-DWIN32 -D_WINDOWS -DWIN95 $(MPICMN)
|
||||
#CFLAGS = -Od -Z7 -MD -W3 -nologo -D_X86_ -DXP_PC -UDEBUG -U_DEBUG -DNDEBUG \
|
||||
-DWIN32 -D_WINDOWS -DWIN95 $(MPICMN)
|
||||
CFLAGS = -O2 -Z7 -MD -W3 -nologo -D_X86_ -DXP_PC -UDEBUG -U_DEBUG -DNDEBUG \
|
||||
-DWIN32 -D_WINDOWS -DWIN95 $(MPICMN)
|
||||
ASFLAGS = -Cp -Sn -Zi -coff -I.
|
||||
|
||||
##
|
||||
## Define LIBS to include any libraries you need to link against.
|
||||
## If NO_TABLE is define, LIBS should include '-lm' or whatever is
|
||||
## necessary to bring in the math library. Otherwise, it can be
|
||||
## left alone, unless your system has other peculiar requirements.
|
||||
##
|
||||
LIBS=#-lmalloc#-lefence#-lm
|
||||
|
||||
##
|
||||
## Define RANLIB to be the library header randomizer; you might not
|
||||
## need this on some systems (just set it to 'echo' on these systems,
|
||||
## such as IRIX)
|
||||
##
|
||||
RANLIB=echo
|
||||
|
||||
##
|
||||
## This is the version string used for the documentation and
|
||||
## building the distribution tarball. Don't mess with it unless
|
||||
## you are releasing a new version
|
||||
VERS=1.7p6
|
||||
|
||||
## ----------------------------------------------------------------------
|
||||
## You probably don't need to change anything below this line...
|
||||
##
|
||||
|
||||
##
|
||||
## This is the list of source files that need to be packed into
|
||||
## the distribution file
|
||||
SRCS= mpi.c mpprime.c mplogic.c mpmontg.c mpi-test.c primes.c tests/ \
|
||||
utils/gcd.c utils/invmod.c utils/lap.c \
|
||||
utils/ptab.pl utils/sieve.c utils/isprime.c\
|
||||
utils/dec2hex.c utils/hex2dec.c utils/bbs_rand.c \
|
||||
utils/bbsrand.c utils/prng.c utils/primegen.c \
|
||||
utils/basecvt.c utils/makeprime.c\
|
||||
utils/fact.c utils/exptmod.c utils/pi.c utils/metime.c \
|
||||
utils/mpi.h utils/mpprime.h mulsqr.c \
|
||||
make-test-arrays test-arrays.txt all-tests make-logtab \
|
||||
types.pl stats timetest multest
|
||||
|
||||
## These are the header files that go into the distribution file
|
||||
HDRS=mpi.h mpi-config.h utils/mpi.h utils/mpi-config.h mpprime.h mplogic.h \
|
||||
utils/bbs_rand.h tests/mpi.h tests/mpprime.h
|
||||
|
||||
## These are the documentation files that go into the distribution file
|
||||
DOCS=README doc utils/README utils/PRIMES
|
||||
|
||||
## This is the list of tools built by 'make tools'
|
||||
TOOLS=gcd.exe invmod.exe isprime.exe lap.exe dec2hex.exe hex2dec.exe \
|
||||
primegen.exe prng.exe basecvt.exe fact.exe exptmod.exe pi.exe makeprime.exe
|
||||
|
||||
AS_OBJS = $(AS_SRCS:.asm=.obj)
|
||||
LIBOBJS = mpprime.obj mpmontg.obj mplogic.obj mpi.obj $(AS_OBJS)
|
||||
LIBHDRS = mpi-config.h mpi-priv.h mpi.h
|
||||
APPHDRS = mpi-config.h mpi.h mplogic.h mpprime.h
|
||||
|
||||
|
||||
help:
|
||||
@ echo ""
|
||||
@ echo "The following targets can be built with this Makefile:"
|
||||
@ echo ""
|
||||
@ echo "mpi.lib - arithmetic and prime testing library"
|
||||
@ echo "mpi-test - test driver (requires MP_IOFUNC)"
|
||||
@ echo "tools - command line tools"
|
||||
@ echo "doc - manual pages for tools"
|
||||
@ echo "clean - clean up objects and such"
|
||||
@ echo "distclean - get ready for distribution"
|
||||
@ echo "dist - distribution tarball"
|
||||
@ echo ""
|
||||
|
||||
.SUFFIXES: .c .obj .i .lib .exe .asm
|
||||
|
||||
.c.i:
|
||||
$(CC) $(CFLAGS) -E $< > $@
|
||||
|
||||
.c.obj:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
||||
.asm.obj:
|
||||
$(AS) $(ASFLAGS) -c $<
|
||||
|
||||
.obj.exe:
|
||||
$(CC) $(CFLAGS) -Fo$@ $<
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
$(LIBOBJS): $(LIBHDRS)
|
||||
|
||||
logtab.h: make-logtab
|
||||
$(PERL) make-logtab > logtab.h
|
||||
|
||||
mpi.obj: mpi.c logtab.h $(LIBHDRS)
|
||||
|
||||
mplogic.obj: mplogic.c mpi-priv.h mplogic.h $(LIBHDRS)
|
||||
|
||||
mpmontg.obj: mpmontg.c mpi-priv.h mplogic.h mpprime.h $(LIBHDRS)
|
||||
|
||||
mpprime.obj: mpprime.c mpi-priv.h mpprime.h mplogic.h primes.c $(LIBHDRS)
|
||||
|
||||
mpi_mips.obj: mpi_mips.s
|
||||
$(CC) -Fo$@ $(ASFLAGS) -c mpi_mips.s
|
||||
|
||||
mpi.lib: $(LIBOBJS)
|
||||
ar -cvr mpi.lib $(LIBOBJS)
|
||||
$(RANLIB) mpi.lib
|
||||
|
||||
lib libs: mpi.lib
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
MPTESTOBJS = mptest1.obj mptest2.obj mptest3.obj mptest3a.obj mptest4.obj \
|
||||
mptest4a.obj mptest4b.obj mptest6.obj mptest7.obj mptest8.obj mptest9.obj
|
||||
MPTESTS = $(MPTESTOBJS:.obj=.exe)
|
||||
|
||||
$(MPTESTOBJS): mptest%.obj: tests/mptest-%.c $(LIBHDRS)
|
||||
$(CC) $(CFLAGS) -Fo$@ -c $<
|
||||
|
||||
$(MPTESTS): mptest%.exe: mptest%.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
tests: mptest1.exe mptest2.exe mptest3.exe mptest3a.exe mptest4.exe \
|
||||
mptest4a.exe mptest4b.exe mptest6.exe bbsrand.exe
|
||||
|
||||
utests: mptest7.exe mptest8.exe mptest9.exe
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
EXTRAOBJS = bbsrand.obj bbs_rand.obj prng.obj
|
||||
UTILOBJS = primegen.obj metime.obj identest.obj basecvt.obj fact.obj \
|
||||
exptmod.obj pi.obj makeprime.obj karatsuba.obj gcd.obj invmod.obj lap.obj \
|
||||
isprime.obj dec2hex.obj hex2dec.obj
|
||||
UTILS = $(UTILOBJS:.obj=.exe)
|
||||
|
||||
$(UTILS): %.exe : %.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
$(UTILOBJS) $(EXTRAOBJS): %.obj : utils/%.c $(LIBHDRS)
|
||||
$(CC) $(CFLAGS) -Fo$@ -c $<
|
||||
|
||||
prng.exe: prng.obj bbs_rand.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
bbsrand.exe: bbsrand.obj bbs_rand.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
utils: $(UTILS) prng.exe bbsrand.exe
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
test-info.c: test-arrays.txt
|
||||
$(PERL) make-test-arrays test-arrays.txt > test-info.c
|
||||
|
||||
mpi-test.obj: mpi-test.c test-info.c $(LIBHDRS)
|
||||
$(CC) $(CFLAGS) -Fo$@ -c $<
|
||||
|
||||
mpi-test.exe: mpi-test.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
mdxptest.obj: mdxptest.c $(LIBHDRS) mpi-priv.h
|
||||
|
||||
mdxptest.exe: mdxptest.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
mulsqr.obj: mulsqr.c logtab.h mpi.h mpi-config.h mpprime.h
|
||||
$(CC) $(CFLAGS) -DMP_SQUARE=1 -Fo$@ -c mulsqr.c
|
||||
|
||||
mulsqr.exe: mulsqr.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
alltests: tests utests mpi-test.exe
|
||||
|
||||
tools: $(TOOLS)
|
||||
|
||||
doc:
|
||||
(cd doc; ./build)
|
||||
|
||||
clean:
|
||||
rm -f *.obj *.lib *.pdb *.ilk
|
||||
cd utils; rm -f *.obj *.lib *.pdb *.ilk
|
||||
|
||||
distclean: clean
|
||||
rm -f mptest? mpi-test metime mulsqr karatsuba
|
||||
rm -f mptest?a mptest?b
|
||||
rm -f utils/mptest?
|
||||
rm -f test-info.c logtab.h
|
||||
rm -f mpi.lib
|
||||
rm -f $(TOOLS)
|
||||
|
||||
dist: Makefile $(HDRS) $(SRCS) $(DOCS)
|
||||
tar -cvf mpi-$(VERS).tar Makefile $(HDRS) $(SRCS) $(DOCS)
|
||||
pgps -ab mpi-$(VERS).tar
|
||||
chmod +r mpi-$(VERS).tar.asc
|
||||
gzip -9 mpi-$(VERS).tar
|
||||
|
||||
|
||||
print:
|
||||
@echo LIBOBJS = $(LIBOBJS)
|
||||
# END
|
||||
@@ -1,799 +0,0 @@
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version
|
||||
1.1 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
http://www.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
for the specific language governing rights and limitations under the
|
||||
License.
|
||||
|
||||
The Original Code is the MPI Arbitrary Precision Integer Arithmetic
|
||||
library.
|
||||
|
||||
The Initial Developer of the Original Code is
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Portions created by the Initial Developer are Copyright (C) 1997-2000
|
||||
the Initial Developer. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
of those above. If you wish to allow use of your version of this file only
|
||||
under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
use your version of this file under the terms of the MPL, indicate your
|
||||
decision by deleting the provisions above and replace them with the notice
|
||||
and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file under
|
||||
the terms of any one of the MPL, the GPL or the LGPL.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
|
||||
About the MPI Library
|
||||
---------------------
|
||||
|
||||
The files 'mpi.h' and 'mpi.c' define a simple, arbitrary precision
|
||||
signed integer arithmetic package. The implementation is not the most
|
||||
efficient possible, but the code is small and should be fairly easily
|
||||
portable to just about any machine that supports an ANSI C compiler,
|
||||
as long as it is capable of at least 16-bit arithmetic (but also see
|
||||
below for more on this).
|
||||
|
||||
This library was written with an eye to cryptographic applications;
|
||||
thus, some care is taken to make sure that temporary values are not
|
||||
left lying around in memory when they are no longer in use. This adds
|
||||
some overhead for zeroing buffers before they are released back into
|
||||
the free pool; however, it gives you the assurance that there is only
|
||||
one copy of your important values residing in your process's address
|
||||
space at a time. Obviously, it is difficult to guarantee anything, in
|
||||
a pre-emptive multitasking environment, but this at least helps you
|
||||
keep a lid on the more obvious ways your data can get spread around in
|
||||
memory.
|
||||
|
||||
|
||||
Using the Library
|
||||
-----------------
|
||||
|
||||
To use the MPI library in your program, you must include the header:
|
||||
|
||||
#include "mpi.h"
|
||||
|
||||
This header provides all the type and function declarations you'll
|
||||
need to use the library. Almost all the names defined by the library
|
||||
begin with the prefix 'mp_', so it should be easy to keep them from
|
||||
clashing with your program's namespace (he says, glibly, knowing full
|
||||
well there are always pathological cases).
|
||||
|
||||
There are a few things you may want to configure about the library.
|
||||
By default, the MPI library uses an unsigned short for its digit type,
|
||||
and an unsigned int for its word type. The word type must be big
|
||||
enough to contain at least two digits, for the primitive arithmetic to
|
||||
work out. On my machine, a short is 2 bytes and an int is 4 bytes --
|
||||
but if you have 64-bit ints, you might want to use a 4-byte digit and
|
||||
an 8-byte word. I have tested the library using 1-byte digits and
|
||||
2-byte words, as well. Whatever you choose to do, the things you need
|
||||
to change are:
|
||||
|
||||
(1) The type definitions for mp_digit and mp_word.
|
||||
|
||||
(2) The macro DIGIT_FMT which tells mp_print() how to display a
|
||||
single digit. This is just a printf() format string, so you
|
||||
can adjust it appropriately.
|
||||
|
||||
(3) The macros DIGIT_MAX and MP_WORD_MAX, which specify the
|
||||
largest value expressible in an mp_digit and an mp_word,
|
||||
respectively.
|
||||
|
||||
Both the mp_digit and mp_word should be UNSIGNED integer types. The
|
||||
code relies on having the full positive precision of the type used for
|
||||
digits and words.
|
||||
|
||||
The remaining type definitions should be left alone, for the most
|
||||
part. The code in the library does not make any significant
|
||||
assumptions about the sizes of things, but there is little if any
|
||||
reason to change the other parameters, so I would recommend you leave
|
||||
them as you found them.
|
||||
|
||||
The library comes with a Perl script, 'types.pl', which will scan your
|
||||
current Makefile settings, and attempt to find good definitions for
|
||||
these types. It relies on a Unix sort of build environment, so it
|
||||
probably won't work under MacOS or Windows, but it can be convenient
|
||||
if you're porting to a new flavour of Unix. Just run 'types.pl' at
|
||||
the command line, and it will spit out its results to the standard
|
||||
output.
|
||||
|
||||
|
||||
Conventions
|
||||
-----------
|
||||
|
||||
Most functions in the library return a value of type mp_err. This
|
||||
permits the library to communicate success or various kinds of failure
|
||||
to the calling program. The return values currently defined are:
|
||||
|
||||
MP_OKAY - okay, operation succeeded, all's well
|
||||
MP_YES - okay, the answer is yes (same as MP_OKAY)
|
||||
MP_NO - okay, but answer is no (not MP_OKAY)
|
||||
MP_MEM - operation ran out of memory
|
||||
MP_RANGE - input parameter was out of range
|
||||
MP_BADARG - an invalid input parameter was provided
|
||||
MP_UNDEF - no output value is defined for this input
|
||||
|
||||
The only function which currently uses MP_UNDEF is mp_invmod().
|
||||
Division by zero is undefined, but the division functions will return
|
||||
MP_RANGE for a zero divisor. MP_BADARG usually means you passed a
|
||||
bogus mp_int structure to the function. MP_YES and MP_NO are not used
|
||||
by the library itself; they're defined so you can use them in your own
|
||||
extensions.
|
||||
|
||||
If you need a readable interpretation of these error codes in your
|
||||
program, you may also use the mp_strerror() function. This function
|
||||
takes an mp_err as input, and returns a pointer to a human-readable
|
||||
string describing the meaning of the error. These strings are stored
|
||||
as constants within the library, so the caller should not attempt to
|
||||
modify or free the memory associated with these strings.
|
||||
|
||||
The library represents values in signed-magnitude format. Values
|
||||
strictly less than zero are negative, all others are considered
|
||||
positive (zero is positive by fiat). You can access the 'sign' member
|
||||
of the mp_int structure directly, but better is to use the mp_cmp_z()
|
||||
function, to find out which side of zero the value lies on.
|
||||
|
||||
Most arithmetic functions have a single-digit variant, as well as the
|
||||
full arbitrary-precision. An mp_digit is an unsigned value between 0
|
||||
and DIGIT_MAX inclusive. The radix is available as RADIX. The number
|
||||
of bits in a given digit is given as DIGIT_BIT.
|
||||
|
||||
Generally, input parameters are given before output parameters.
|
||||
Unless otherwise specified, any input parameter can be re-used as an
|
||||
output parameter, without confusing anything.
|
||||
|
||||
The basic numeric type defined by the library is an mp_int. Virtually
|
||||
all the functions in the library take a pointer to an mp_int as one of
|
||||
their parameters. An explanation of how to create and use these
|
||||
<HR>
|
||||
<A NAME="p23">
|
||||
<H3>Problem 23:</H3>
|
||||
|
||||
structures follows. And so, without further ado...
|
||||
|
||||
|
||||
Initialization and Cleanup
|
||||
--------------------------
|
||||
|
||||
The basic numeric type defined by the library is an 'mp_int'.
|
||||
However, it is not sufficient to simply declare a variable of type
|
||||
mp_int in your program. These variables also need to be initialized
|
||||
before they can be used, to allocate the internal storage they require
|
||||
for computation.
|
||||
|
||||
This is done using one of the following functions:
|
||||
|
||||
mp_init(mp_int *mp);
|
||||
mp_init_copy(mp_int *mp, mp_int *from);
|
||||
mp_init_size(mp_int *mp, mp_size p);
|
||||
|
||||
Each of these requires a pointer to a structure of type mp_int. The
|
||||
basic mp_init() simply initializes the mp_int to a default size, and
|
||||
sets its value to zero. If you would like to initialize a copy of an
|
||||
existing mp_int, use mp_init_copy(), where the 'from' parameter is the
|
||||
mp_int you'd like to make a copy of. The third function,
|
||||
mp_init_size(), permits you to specify how many digits of precision
|
||||
should be preallocated for your mp_int. This can help the library
|
||||
avoid unnecessary re-allocations later on.
|
||||
|
||||
The default precision used by mp_init() can be retrieved using:
|
||||
|
||||
precision = mp_get_prec();
|
||||
|
||||
This returns the number of digits that will be allocated. You can
|
||||
change this value by using:
|
||||
|
||||
mp_set_prec(unsigned int prec);
|
||||
|
||||
Any positive value is acceptable -- if you pass zero, the default
|
||||
precision will be re-set to the compiled-in library default (this is
|
||||
specified in the header file 'mpi-config.h', and typically defaults to
|
||||
8 or 16).
|
||||
|
||||
Just as you must allocate an mp_int before you can use it, you must
|
||||
clean up the structure when you are done with it. This is performed
|
||||
using the mp_clear() function. Remember that any mp_int that you
|
||||
create as a local variable in a function must be mp_clear()'d before
|
||||
that function exits, or else the memory allocated to that mp_int will
|
||||
be orphaned and unrecoverable.
|
||||
|
||||
To set an mp_int to a given value, the following functions are given:
|
||||
|
||||
mp_set(mp_int *mp, mp_digit d);
|
||||
mp_set_int(mp_int *mp, long z);
|
||||
|
||||
The mp_set() function sets the mp_int to a single digit value, while
|
||||
mp_set_int() sets the mp_int to a signed long integer value.
|
||||
|
||||
To set an mp_int to zero, use:
|
||||
|
||||
mp_zero(mp_int *mp);
|
||||
|
||||
|
||||
Copying and Moving
|
||||
------------------
|
||||
|
||||
If you have two initialized mp_int's, and you want to copy the value
|
||||
of one into the other, use:
|
||||
|
||||
mp_copy(from, to)
|
||||
|
||||
This takes care of clearing the old value of 'to', and copies the new
|
||||
value into it. If 'to' is not yet initialized, use mp_init_copy()
|
||||
instead (see above).
|
||||
|
||||
Note: The library tries, whenever possible, to avoid allocating
|
||||
---- new memory. Thus, mp_copy() tries first to satisfy the needs
|
||||
of the copy by re-using the memory already allocated to 'to'.
|
||||
Only if this proves insufficient will mp_copy() actually
|
||||
allocate new memory.
|
||||
|
||||
For this reason, if you know a priori that 'to' has enough
|
||||
available space to hold 'from', you don't need to check the
|
||||
return value of mp_copy() for memory failure. The USED()
|
||||
macro tells you how many digits are used by an mp_int, and
|
||||
the ALLOC() macro tells you how many are allocated.
|
||||
|
||||
If you have two initialized mp_int's, and you want to exchange their
|
||||
values, use:
|
||||
|
||||
mp_exch(a, b)
|
||||
|
||||
This is better than using mp_copy() with a temporary, since it will
|
||||
not (ever) touch the memory allocator -- it just swaps the exact
|
||||
contents of the two structures. The mp_exch() function cannot fail;
|
||||
if you pass it an invalid structure, it just ignores it, and does
|
||||
nothing.
|
||||
|
||||
|
||||
Basic Arithmetic
|
||||
----------------
|
||||
|
||||
Once you have initialized your integers, you can operate on them. The
|
||||
basic arithmetic functions on full mp_int values are:
|
||||
|
||||
mp_add(a, b, c) - computes c = a + b
|
||||
mp_sub(a, b, c) - computes c = a - b
|
||||
mp_mul(a, b, c) - computes c = a * b
|
||||
mp_sqr(a, b) - computes b = a * a
|
||||
mp_div(a, b, q, r) - computes q, r such that a = bq + r
|
||||
mp_div_2d(a, d, q, r) - computes q = a / 2^d, r = a % 2^d
|
||||
mp_expt(a, b, c) - computes c = a ** b
|
||||
mp_2expt(a, k) - computes a = 2^k
|
||||
mp_sqrt(a, c) - computes c = floor(sqrt(a))
|
||||
|
||||
The mp_div_2d() function efficiently computes division by powers of
|
||||
two. Either the q or r parameter may be NULL, in which case that
|
||||
portion of the computation will be discarded.
|
||||
|
||||
The algorithms used for some of the computations here are described in
|
||||
the following files which are included with this distribution:
|
||||
|
||||
mul.txt Describes the multiplication algorithm
|
||||
div.txt Describes the division algorithm
|
||||
expt.txt Describes the exponentiation algorithm
|
||||
sqrt.txt Describes the square-root algorithm
|
||||
square.txt Describes the squaring algorithm
|
||||
|
||||
There are single-digit versions of most of these routines, as well.
|
||||
In the following prototypes, 'd' is a single mp_digit:
|
||||
|
||||
mp_add_d(a, d, c) - computes c = a + d
|
||||
mp_sub_d(a, d, c) - computes c = a - d
|
||||
mp_mul_d(a, d, c) - computes c = a * d
|
||||
mp_mul_2(a, c) - computes c = a * 2
|
||||
mp_div_d(a, d, q, r) - computes q, r such that a = bq + r
|
||||
mp_div_2(a, c) - computes c = a / 2
|
||||
mp_expt_d(a, d, c) - computes c = a ** d
|
||||
|
||||
The mp_mul_2() and mp_div_2() functions take advantage of the internal
|
||||
representation of an mp_int to do multiplication by two more quickly
|
||||
than mp_mul_d() would. Other basic functions of an arithmetic variety
|
||||
include:
|
||||
|
||||
mp_zero(a) - assign 0 to a
|
||||
mp_neg(a, c) - negate a: c = -a
|
||||
mp_abs(a, c) - absolute value: c = |a|
|
||||
|
||||
|
||||
Comparisons
|
||||
-----------
|
||||
|
||||
Several comparison functions are provided. Each of these, unless
|
||||
otherwise specified, returns zero if the comparands are equal, < 0 if
|
||||
the first is less than the second, and > 0 if the first is greater
|
||||
than the second:
|
||||
|
||||
mp_cmp_z(a) - compare a <=> 0
|
||||
mp_cmp_d(a, d) - compare a <=> d, d is a single digit
|
||||
mp_cmp(a, b) - compare a <=> b
|
||||
mp_cmp_mag(a, b) - compare |a| <=> |b|
|
||||
mp_cmp_int(a, z) - compare a <=> z, z is a signed long integer
|
||||
mp_isodd(a) - return nonzero if odd, zero otherwise
|
||||
mp_iseven(a) - return nonzero if even, zero otherwise
|
||||
|
||||
|
||||
Modular Arithmetic
|
||||
------------------
|
||||
|
||||
Modular variations of the basic arithmetic functions are also
|
||||
supported. These are available if the MP_MODARITH parameter in
|
||||
mpi-config.h is turned on (it is by default). The modular arithmetic
|
||||
functions are:
|
||||
|
||||
mp_mod(a, m, c) - compute c = a (mod m), 0 <= c < m
|
||||
mp_mod_d(a, d, c) - compute c = a (mod d), 0 <= c < d (see below)
|
||||
mp_addmod(a, b, m, c) - compute c = (a + b) mod m
|
||||
mp_submod(a, b, m, c) - compute c = (a - b) mod m
|
||||
mp_mulmod(a, b, m, c) - compute c = (a * b) mod m
|
||||
mp_sqrmod(a, m, c) - compute c = (a * a) mod m
|
||||
mp_exptmod(a, b, m, c) - compute c = (a ** b) mod m
|
||||
mp_exptmod_d(a, d, m, c)- compute c = (a ** d) mod m
|
||||
|
||||
The mp_sqr() function squares its input argument. A call to mp_sqr(a,
|
||||
c) is identical in meaning to mp_mul(a, a, c); however, if the
|
||||
MP_SQUARE variable is set true in mpi-config.h (see below), then it
|
||||
will be implemented with a different algorithm, that is supposed to
|
||||
take advantage of the redundant computation that takes place during
|
||||
squaring. Unfortunately, some compilers result in worse performance
|
||||
on this code, so you can change the behaviour at will. There is a
|
||||
utility program "mulsqr.c" that lets you test which does better on
|
||||
your system.
|
||||
|
||||
The mp_sqrmod() function is analogous to the mp_sqr() function; it
|
||||
uses the mp_sqr() function rather than mp_mul(), and then performs the
|
||||
modular reduction. This probably won't help much unless you are doing
|
||||
a lot of them.
|
||||
|
||||
See the file 'square.txt' for a synopsis of the algorithm used.
|
||||
|
||||
Note: The mp_mod_d() function computes a modular reduction around
|
||||
---- a single digit d. The result is a single digit c.
|
||||
|
||||
Because an inverse is defined for a (mod m) if and only if (a, m) = 1
|
||||
(that is, if a and m are relatively prime), mp_invmod() may not be
|
||||
able to compute an inverse for the arguments. In this case, it
|
||||
returns the value MP_UNDEF, and does not modify c. If an inverse is
|
||||
defined, however, it returns MP_OKAY, and sets c to the value of the
|
||||
inverse (mod m).
|
||||
|
||||
See the file 'redux.txt' for a description of the modular reduction
|
||||
algorithm used by mp_exptmod().
|
||||
|
||||
|
||||
Greatest Common Divisor
|
||||
-----------------------
|
||||
|
||||
If The greates common divisor of two values can be found using one of the
|
||||
following functions:
|
||||
|
||||
mp_gcd(a, b, c) - compute c = (a, b) using binary algorithm
|
||||
mp_lcm(a, b, c) - compute c = [a, b] = ab / (a, b)
|
||||
mp_xgcd(a, b, g, x, y) - compute g, x, y so that ax + by = g = (a, b)
|
||||
|
||||
Also provided is a function to compute modular inverses, if they
|
||||
exist:
|
||||
|
||||
mp_invmod(a, m, c) - compute c = a^-1 (mod m), if it exists
|
||||
|
||||
The function mp_xgcd() computes the greatest common divisor, and also
|
||||
returns values of x and y satisfying Bezout's identity. This is used
|
||||
by mp_invmod() to find modular inverses. However, if you do not need
|
||||
these values, you will find that mp_gcd() is MUCH more efficient,
|
||||
since it doesn't need all the intermediate values that mp_xgcd()
|
||||
requires in order to compute x and y.
|
||||
|
||||
The mp_gcd() (and mp_xgcd()) functions use the binary (extended) GCD
|
||||
algorithm due to Josef Stein.
|
||||
|
||||
|
||||
Input & Output Functions
|
||||
------------------------
|
||||
|
||||
The following basic I/O routines are provided. These are present at
|
||||
all times:
|
||||
|
||||
mp_read_radix(mp, str, r) - convert a string in radix r to an mp_int
|
||||
mp_read_raw(mp, s, len) - convert a string of bytes to an mp_int
|
||||
mp_radix_size(mp, r) - return length of buffer needed by mp_toradix()
|
||||
mp_raw_size(mp) - return length of buffer needed by mp_toraw()
|
||||
mp_toradix(mp, str, r) - convert an mp_int to a string of radix r
|
||||
digits
|
||||
mp_toraw(mp, str) - convert an mp_int to a string of bytes
|
||||
mp_tovalue(ch, r) - convert ch to its value when taken as
|
||||
a radix r digit, or -1 if invalid
|
||||
mp_strerror(err) - get a string describing mp_err value 'err'
|
||||
|
||||
If you compile the MPI library with MP_IOFUNC defined, you will also
|
||||
have access to the following additional I/O function:
|
||||
|
||||
mp_print(mp, ofp) - print an mp_int as text to output stream ofp
|
||||
|
||||
Note that mp_radix_size() returns a size in bytes guaranteed to be AT
|
||||
LEAST big enough for the digits output by mp_toradix(). Because it
|
||||
uses an approximation technique to figure out how many digits will be
|
||||
needed, it may return a figure which is larger than necessary. Thus,
|
||||
the caller should not rely on the value to determine how many bytes
|
||||
will actually be written by mp_toradix(). The string mp_toradix()
|
||||
creates will be NUL terminated, so the standard C library function
|
||||
strlen() should be able to ascertain this for you, if you need it.
|
||||
|
||||
The mp_read_radix() and mp_toradix() functions support bases from 2 to
|
||||
64 inclusive. If you require more general radix conversion facilities
|
||||
than this, you will need to write them yourself (that's why mp_div_d()
|
||||
is provided, after all).
|
||||
|
||||
Note: mp_read_radix() will accept as digits either capital or
|
||||
---- lower-case letters. However, the current implementation of
|
||||
mp_toradix() only outputs upper-case letters, when writing
|
||||
bases betwee 10 and 36. The underlying code supports using
|
||||
lower-case letters, but the interface stub does not have a
|
||||
selector for it. You can add one yourself if you think it
|
||||
is worthwhile -- I do not. Bases from 36 to 64 use lower-
|
||||
case letters as distinct from upper-case. Bases 63 and
|
||||
64 use the characters '+' and '/' as digits.
|
||||
|
||||
Note also that compiling with MP_IOFUNC defined will cause
|
||||
inclusion of <stdio.h>, so if you are trying to write code
|
||||
which does not depend on the standard C library, you will
|
||||
probably want to avoid this option. This is needed because
|
||||
the mp_print() function takes a standard library FILE * as
|
||||
one of its parameters, and uses the fprintf() function.
|
||||
|
||||
The mp_toraw() function converts the integer to a sequence of bytes,
|
||||
in big-endian ordering (most-significant byte first). Assuming your
|
||||
bytes are 8 bits wide, this corresponds to base 256. The sign is
|
||||
encoded as a single leading byte, whose value is 0 for zero or
|
||||
positive values, or 1 for negative values. The mp_read_raw() function
|
||||
reverses this process -- it takes a buffer of bytes, interprets the
|
||||
first as a sign indicator (0 = zero/positive, nonzero = negative), and
|
||||
the rest as a sequence of 1-byte digits in big-endian ordering.
|
||||
|
||||
The mp_raw_size() function returns the exact number of bytes required
|
||||
to store the given integer in "raw" format (as described in the
|
||||
previous paragraph). Zero is returned in case of error; a valid
|
||||
integer will require at least three bytes of storage.
|
||||
|
||||
In previous versions of the MPI library, an "external representation
|
||||
format" was supported. This was removed, however, because I found I
|
||||
was never using it, it was not as portable as I would have liked, and
|
||||
I decided it was a waste of space.
|
||||
|
||||
|
||||
Other Functions
|
||||
---------------
|
||||
|
||||
The files 'mpprime.h' and 'mpprime.c' define some routines which are
|
||||
useful for divisibility testing and probabilistic primality testing.
|
||||
The routines defined are:
|
||||
|
||||
mpp_divis(a, b) - is a divisible by b?
|
||||
mpp_divis_d(a, d) - is a divisible by digit d?
|
||||
mpp_random(a) - set a to random value at current precision
|
||||
mpp_random_size(a, prec) - set a to random value at given precision
|
||||
|
||||
Note: The mpp_random() and mpp_random_size() functions use the C
|
||||
---- library's rand() function to generate random values. It is
|
||||
up to the caller to seed this generator before it is called.
|
||||
These functions are not suitable for generating quantities
|
||||
requiring cryptographic-quality randomness; they are intended
|
||||
primarily for use in primality testing.
|
||||
|
||||
Note too that the MPI library does not call srand(), so your
|
||||
application should do this, if you ever want the sequence
|
||||
to change.
|
||||
|
||||
mpp_divis_vector(a, v, s, w) - is a divisible by any of the s digits
|
||||
in v? If so, let w be the index of
|
||||
that digit
|
||||
|
||||
mpp_divis_primes(a, np) - is a divisible by any of the first np
|
||||
primes? If so, set np to the prime
|
||||
which divided a.
|
||||
|
||||
mpp_fermat(a, d) - test if w^a = w (mod a). If so,
|
||||
returns MP_YES, otherwise MP_NO.
|
||||
|
||||
mpp_pprime(a, nt) - perform nt iterations of the Rabin-
|
||||
Miller probabilistic primality test
|
||||
on a. Returns MP_YES if all tests
|
||||
passed, or MP_NO if any test fails.
|
||||
|
||||
The mpp_fermat() function works based on Fermat's little theorem, a
|
||||
consequence of which is that if p is a prime, and (w, p) = 1, then:
|
||||
|
||||
w^p = w (mod p)
|
||||
|
||||
Put another way, if w^p != w (mod p), then p is not prime. The test
|
||||
is expensive to compute, but it helps to quickly eliminate an enormous
|
||||
class of composite numbers prior to Rabin-Miller testing.
|
||||
|
||||
Building the Library
|
||||
--------------------
|
||||
|
||||
The MPI library is designed to be as self-contained as possible. You
|
||||
should be able to compile it with your favourite ANSI C compiler, and
|
||||
link it into your program directly. If you are on a Unix system using
|
||||
the GNU C compiler (gcc), the following should work:
|
||||
|
||||
% gcc -ansi -pedantic -Wall -O2 -c mpi.c
|
||||
|
||||
The file 'mpi-config.h' defines several configurable parameters for
|
||||
the library, which you can adjust to suit your application. At the
|
||||
time of this writing, the available options are:
|
||||
|
||||
MP_IOFUNC - Define true to include the mp_print() function,
|
||||
which is moderately useful for debugging. This
|
||||
implicitly includes <stdio.h>.
|
||||
|
||||
MP_MODARITH - Define true to include the modular arithmetic
|
||||
functions. If you don't need modular arithmetic
|
||||
in your application, you can set this to zero to
|
||||
leave out all the modular routines.
|
||||
|
||||
MP_NUMTH - Define true to include number theoretic functions
|
||||
such as mp_gcd(), mp_lcm(), and mp_invmod().
|
||||
|
||||
MP_LOGTAB - If true, the file "logtab.h" is included, which
|
||||
is basically a static table of base 2 logarithms.
|
||||
These are used to compute how big the buffers for
|
||||
radix conversion need to be. If you set this false,
|
||||
the library includes <math.h> and uses log(). This
|
||||
typically forces you to link against math libraries.
|
||||
|
||||
MP_MEMSET - If true, use memset() to zero buffers. If you run
|
||||
into weird alignment related bugs, set this to zero
|
||||
and an explicit loop will be used.
|
||||
|
||||
MP_MEMCPY - If true, use memcpy() to copy buffers. If you run
|
||||
into weird alignment bugs, set this to zero and an
|
||||
explicit loop will be used.
|
||||
|
||||
MP_CRYPTO - If true, whenever arrays of digits are free'd, they
|
||||
are zeroed first. This is useful if you're using
|
||||
the library in a cryptographic environment; however,
|
||||
it does add overhead to each free operation. For
|
||||
performance, if you don't care about zeroing your
|
||||
buffers, set this to false.
|
||||
|
||||
MP_ARGCHK - Set to 0, 1, or 2. This defines how the argument
|
||||
checking macro, ARGCHK(), gets expanded. If this
|
||||
is set to zero, ARGCHK() expands to nothing; no
|
||||
argument checks are performed. If this is 1, the
|
||||
ARGCHK() macro expands to code that returns MP_BADARG
|
||||
or similar at runtime. If it is 2, ARGCHK() expands
|
||||
to an assert() call that aborts the program on a
|
||||
bad input.
|
||||
|
||||
MP_DEBUG - Turns on debugging output. This is probably not at
|
||||
all useful unless you are debugging the library. It
|
||||
tends to spit out a LOT of output.
|
||||
|
||||
MP_DEFPREC - The default precision of a newly-created mp_int, in
|
||||
digits. The precision can be changed at runtime by
|
||||
the mp_set_prec() function, but this is its initial
|
||||
value.
|
||||
|
||||
MP_SQUARE - If this is set to a nonzero value, the mp_sqr()
|
||||
function will use an alternate algorithm that takes
|
||||
advantage of the redundant inner product computation
|
||||
when both multiplicands are identical. Unfortunately,
|
||||
with some compilers this is actually SLOWER than just
|
||||
calling mp_mul() with the same argument twice. So
|
||||
if you set MP_SQUARE to zero, mp_sqr() will be expan-
|
||||
ded into a call to mp_mul(). This applies to all
|
||||
the uses of mp_sqr(), including mp_sqrmod() and the
|
||||
internal calls to s_mp_sqr() inside mpi.c
|
||||
|
||||
The program 'mulsqr' (mulsqr.c) can be used to test
|
||||
which works best for your configuration. Set up the
|
||||
CC and CFLAGS variables in the Makefile, then type:
|
||||
|
||||
make mulsqr
|
||||
|
||||
Invoke it with arguments similar to the following:
|
||||
|
||||
mulsqr 25000 1024
|
||||
|
||||
That is, 25000 products computed on 1024-bit values.
|
||||
The output will compare the two timings, and recommend
|
||||
a setting for MP_SQUARE. It is off by default.
|
||||
|
||||
If you would like to use the mp_print() function (see above), be sure
|
||||
to define MP_IOFUNC in mpi-config.h. Many of the test drivers in the
|
||||
'tests' subdirectory expect this to be defined (although the test
|
||||
driver 'mpi-test' doesn't need it)
|
||||
|
||||
The Makefile which comes with the library should take care of building
|
||||
the library for you, if you have set the CC and CFLAGS variables at
|
||||
the top of the file appropriately. By default, they are set up to
|
||||
use the GNU C compiler:
|
||||
|
||||
CC=gcc
|
||||
CFLAGS=-ansi -pedantic -Wall -O2
|
||||
|
||||
If all goes well, the library should compile without warnings using
|
||||
this combination. You should, of course, make whatever adjustments
|
||||
you find necessary.
|
||||
|
||||
The MPI library distribution comes with several additional programs
|
||||
which are intended to demonstrate the use of the library, and provide
|
||||
a framework for testing it. There are a handful of test driver
|
||||
programs, in the files named 'mptest-X.c', where X is a digit. Also,
|
||||
there are some simple command-line utilities (in the 'utils'
|
||||
directory) for manipulating large numbers. These include:
|
||||
|
||||
basecvt.c A radix-conversion program, supporting bases from
|
||||
2 to 64 inclusive.
|
||||
|
||||
bbsrand.c A BBS (quadratic residue) pseudo-random number
|
||||
generator. The file 'bbsrand.c' is just the driver
|
||||
for the program; the real code lives in the files
|
||||
'bbs_rand.h' and 'bbs_rand.c'
|
||||
|
||||
dec2hex.c Converts decimal to hexadecimal
|
||||
|
||||
gcd.c Computes the greatest common divisor of two values.
|
||||
If invoked as 'xgcd', also computes constants x and
|
||||
y such that (a, b) = ax + by, in accordance with
|
||||
Bezout's identity.
|
||||
|
||||
hex2dec.c Converts hexadecimal to decimal
|
||||
|
||||
invmod.c Computes modular inverses
|
||||
|
||||
isprime.c Performs the Rabin-Miller probabilistic primality
|
||||
test on a number. Values which fail this test are
|
||||
definitely composite, and those which pass are very
|
||||
likely to be prime (although there are no guarantees)
|
||||
|
||||
lap.c Computes the order (least annihilating power) of
|
||||
a value v modulo m. Very dumb algorithm.
|
||||
|
||||
primegen.c Generates large (probable) primes.
|
||||
|
||||
prng.c A pseudo-random number generator based on the
|
||||
BBS generator code in 'bbs_rand.c'
|
||||
|
||||
sieve.c Implements the Sieve of Eratosthenes, using a big
|
||||
bitmap, to generate a list of prime numbers.
|
||||
|
||||
fact.c Computes the factorial of an arbitrary precision
|
||||
integer (iterative).
|
||||
|
||||
exptmod.c Computes arbitrary precision modular exponentiation
|
||||
from the command line (exptmod a b m -> a^b (mod m))
|
||||
|
||||
Most of these can be built from the Makefile that comes with the
|
||||
library. Try 'make tools', if your environment supports it. (If you
|
||||
are compiling on a Macintosh, I'm afraid you'll have to build them by
|
||||
hand -- fortunately, this is not difficult -- the library itself
|
||||
should compile just fine under Metrowerks CodeWarrior).
|
||||
|
||||
|
||||
Testing the Library
|
||||
-------------------
|
||||
|
||||
Automatic test vectors are included, in the form of a program called
|
||||
'mpi-test'. To build this program and run all the tests, simply
|
||||
invoke the shell script 'all-tests'. If all the tests pass, you
|
||||
should see a message:
|
||||
|
||||
All tests passed
|
||||
|
||||
If something went wrong, you'll get:
|
||||
|
||||
One or more tests failed.
|
||||
|
||||
If this happens, scan back through the preceding lines, to see which
|
||||
test failed. Any failure indicates a bug in the library, which needs
|
||||
to be fixed before it will give accurate results. If you get any such
|
||||
thing, please let me know, and I'll try to fix it. Please let me know
|
||||
what platform and compiler you were using, as well as which test
|
||||
failed. If a reason for failure was given, please send me that text
|
||||
as well.
|
||||
|
||||
If you're on a system such as the Macintosh, where the standard Unix
|
||||
build tools don't work, you can build the 'mpi-test' program manually,
|
||||
and run it by hand. This is tedious and obnoxious, sorry.
|
||||
|
||||
Further manual testing can be performed by building the manual testing
|
||||
programs, whose source is found in the 'tests' subdirectory. Each
|
||||
test is in a source file called 'mptest-X.c'. The Makefile contains a
|
||||
target to build all of them at once:
|
||||
|
||||
make tests
|
||||
|
||||
Read the comments at the top of each source file to see what the
|
||||
driver is supposed to test. You probably don't need to do this; these
|
||||
programs were only written to help me as I was developing the library.
|
||||
|
||||
The relevant files are:
|
||||
|
||||
mpi-test.c The source for the test driver
|
||||
|
||||
make-test-arrays A Perl script to generate some of the internal
|
||||
data structures used by mpi-test.c
|
||||
|
||||
test-arrays.txt The source file for make-test-arrays
|
||||
|
||||
all-tests A Bourne shell script which runs all the
|
||||
tests in the mpi-test suite
|
||||
|
||||
Running 'make mpi-test' should build the mpi-test program. If you
|
||||
cannot use make, here is what needs to be done:
|
||||
|
||||
(1) Use 'make-test-arrays' to generate the file 'test-info.c' from
|
||||
the 'test-arrays.txt' file. Since Perl can be found everywhere,
|
||||
even on the Macintosh, this should be no trouble. Under Unix,
|
||||
this looks like:
|
||||
|
||||
make-test-arrays test-arrays.txt > test-info.c
|
||||
|
||||
(2) Build the MPI library:
|
||||
|
||||
gcc -ansi -pedantic -Wall -c mpi.c
|
||||
|
||||
(3) Build the mpi-test program:
|
||||
|
||||
gcc -ansi -pedantic -Wall -o mpi-test mpi.o mpi-test.c
|
||||
|
||||
When you've got mpi-test, you can use 'all-tests' to run all the tests
|
||||
made available by mpi-test. If any of them fail, there should be a
|
||||
diagnostic indicating what went wrong. These are fairly high-level
|
||||
diagnostics, and won't really help you debug the problem; they're
|
||||
simply intended to help you isolate which function caused the problem.
|
||||
If you encounter a problem of this sort, feel free to e-mail me, and I
|
||||
will certainly attempt to help you debug it.
|
||||
|
||||
Note: Several of the tests hard-wired into 'mpi-test' operate under
|
||||
---- the assumption that you are using at least a 16-bit mp_digit
|
||||
type. If that is not true, several tests might fail, because
|
||||
of range problems with the maximum digit value.
|
||||
|
||||
If you are using an 8-bit digit, you will also need to
|
||||
modify the code for mp_read_raw(), which assumes that
|
||||
multiplication by 256 can be done with mp_mul_d(), a
|
||||
fact that fails when DIGIT_MAX is 255. You can replace
|
||||
the call with s_mp_lshd(), which will give you the same
|
||||
effect, and without doing as much work. :)
|
||||
|
||||
Acknowledgements:
|
||||
----------------
|
||||
|
||||
The algorithms used in this library were drawn primarily from Volume
|
||||
2 of Donald Knuth's magnum opus, _The Art of Computer Programming_,
|
||||
"Semi-Numerical Methods". Barrett's algorithm for modular reduction
|
||||
came from Menezes, Oorschot, and Vanstone's _Handbook of Applied
|
||||
Cryptography_, Chapter 14.
|
||||
|
||||
Thanks are due to Tom St. Denis, for finding an obnoxious sign-related
|
||||
bug in mp_read_raw() that made things break on platforms which use
|
||||
signed chars.
|
||||
|
||||
About the Author
|
||||
----------------
|
||||
|
||||
This software was written by Michael J. Fromberger. You can contact
|
||||
the author as follows:
|
||||
|
||||
E-mail: <sting@linguist.dartmouth.edu>
|
||||
|
||||
Postal: 8000 Cummings Hall, Thayer School of Engineering
|
||||
Dartmouth College, Hanover, New Hampshire, USA
|
||||
|
||||
PGP key: http://linguist.dartmouth.edu/~sting/keys/mjf.html
|
||||
9736 188B 5AFA 23D6 D6AA BE0D 5856 4525 289D 9907
|
||||
|
||||
Last updated: 16-Jan-2000
|
||||
@@ -1,115 +0,0 @@
|
||||
#!/bin/sh
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the MPI Arbitrary Precision Integer Arithmetic library.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Michael J. Fromberger <sting@linguist.dartmouth.edu>.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1997
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
ECHO=/bin/echo
|
||||
MAKE=gmake
|
||||
|
||||
$ECHO "\n** Running unit tests for MPI library\n"
|
||||
|
||||
# Build the mpi-test program, which comprises all the unit tests for
|
||||
# the MPI library...
|
||||
|
||||
$ECHO "Bringing mpi-test up to date ... "
|
||||
if $MAKE mpi-test ; then
|
||||
:
|
||||
else
|
||||
$ECHO " "
|
||||
$ECHO "Make failed to build mpi-test."
|
||||
$ECHO " "
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -x mpi-test ] ; then
|
||||
$ECHO " "
|
||||
$ECHO "Cannot find 'mpi-test' program, testing cannot continue."
|
||||
$ECHO " "
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get the list of available test suites...
|
||||
tests=`mpi-test list | awk '{print $1}'`
|
||||
errs=0
|
||||
|
||||
# Run each test suite and check the result code of mpi-test
|
||||
for test in $tests ; do
|
||||
$ECHO "$test ... \c"
|
||||
if mpi-test $test ; then
|
||||
$ECHO "passed"
|
||||
else
|
||||
$ECHO "FAILED"
|
||||
errs=1
|
||||
fi
|
||||
done
|
||||
|
||||
# If any tests failed, we'll stop at this point
|
||||
if [ "$errs" = "0" ] ; then
|
||||
$ECHO "All unit tests passed"
|
||||
else
|
||||
$ECHO "One or more tests failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Now try to build the 'pi' program, and see if it can compute the
|
||||
# first thousand digits of pi correctly
|
||||
$ECHO "\n** Running other tests\n"
|
||||
|
||||
$ECHO "Bringing 'pi' up to date ... "
|
||||
if $MAKE pi ; then
|
||||
:
|
||||
else
|
||||
$ECHO "\nMake failed to build pi.\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -x pi ] ; then
|
||||
$ECHO "\nCannot find 'pi' program; testing cannot continue.\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
./pi 2000 > /tmp/pi.tmp.$$
|
||||
if cmp tests/pi2k.txt /tmp/pi.tmp.$$ ; then
|
||||
$ECHO "Okay! The pi test passes."
|
||||
else
|
||||
$ECHO "Oops! The pi test failed. :("
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -f /tmp/pi.tmp.$$
|
||||
|
||||
exit 0
|
||||
|
||||
# Here there be dragons
|
||||
@@ -1,11 +0,0 @@
|
||||
Within this directory, each of the file listed below is licensed under
|
||||
the terms given in the file LICENSE-MPL, also in this directory.
|
||||
|
||||
basecvt.pod
|
||||
gcd.pod
|
||||
invmod.pod
|
||||
isprime.pod
|
||||
lap.pod
|
||||
mpi-test.pod
|
||||
prime.txt
|
||||
prng.pod
|
||||
@@ -1,32 +0,0 @@
|
||||
The contents of this file are subject to the Mozilla Public
|
||||
License Version 1.1 (the "License"); you may not use this file
|
||||
except in compliance with the License. You may obtain a copy of
|
||||
the License at http://www.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS
|
||||
IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
rights and limitations under the License.
|
||||
|
||||
The Original Code is the Netscape security libraries.
|
||||
|
||||
The Initial Developer of the Original Code is Netscape
|
||||
Communications Corporation. Portions created by Netscape are
|
||||
Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
|
||||
Alternatively, the contents of this file may be used under the
|
||||
terms of the GNU General Public License Version 2 or later (the
|
||||
"GPL"), in which case the provisions of the GPL are applicable
|
||||
instead of those above. If you wish to allow use of your
|
||||
version of this file only under the terms of the GPL and not to
|
||||
allow others to use your version of this file under the MPL,
|
||||
indicate your decision by deleting the provisions above and
|
||||
replace them with the notice and other provisions required by
|
||||
the GPL. If you do not delete the provisions above, a recipient
|
||||
may use your version of this file under either the MPL or the
|
||||
GPL.
|
||||
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
=head1 NAME
|
||||
|
||||
basecvt - radix conversion for arbitrary precision integers
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
basecvt <ibase> <obase> [values]
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The B<basecvt> program is a command-line tool for converting integers
|
||||
of arbitrary precision from one radix to another. The current version
|
||||
supports radix values from 2 (binary) to 64, inclusive. The first two
|
||||
command line arguments specify the input and output radix, in base 10.
|
||||
Any further arguments are taken to be integers notated in the input
|
||||
radix, and these are converted to the output radix. The output is
|
||||
written, one integer per line, to standard output.
|
||||
|
||||
When reading integers, only digits considered "valid" for the input
|
||||
radix are considered. Processing of an integer terminates when an
|
||||
invalid input digit is encountered. So, for example, if you set the
|
||||
input radix to 10 and enter '10ACF', B<basecvt> would assume that you
|
||||
had entered '10' and ignore the rest of the string.
|
||||
|
||||
If no values are provided, no output is written, but the program
|
||||
simply terminates with a zero exit status. Error diagnostics are
|
||||
written to standard error in the event of out-of-range radix
|
||||
specifications. Regardless of the actual values of the input and
|
||||
output radix, the radix arguments are taken to be in base 10 (decimal)
|
||||
notation.
|
||||
|
||||
=head1 DIGITS
|
||||
|
||||
For radices from 2-10, standard ASCII decimal digits 0-9 are used for
|
||||
both input and output. For radices from 11-36, the ASCII letters A-Z
|
||||
are also included, following the convention used in hexadecimal. In
|
||||
this range, input is accepted in either upper or lower case, although
|
||||
on output only lower-case letters are used.
|
||||
|
||||
For radices from 37-62, the output includes both upper- and lower-case
|
||||
ASCII letters, and case matters. In this range, case is distinguished
|
||||
both for input and for output values.
|
||||
|
||||
For radices 63 and 64, the characters '+' (plus) and '/' (forward
|
||||
solidus) are also used. These are derived from the MIME base64
|
||||
encoding scheme. The overall encoding is not the same as base64,
|
||||
because the ASCII digits are used for the bottom of the range, and the
|
||||
letters are shifted upward; however, the output will consist of the
|
||||
same character set.
|
||||
|
||||
This input and output behaviour is inherited from the MPI library used
|
||||
by B<basecvt>, and so is not configurable at runtime.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
dec2hex(1), hex2dec(1)
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Thayer School of Engineering, Hanover, New Hampshire, USA
|
||||
|
||||
$Date: 2000-07-14 00:44:31 $
|
||||
@@ -1,101 +0,0 @@
|
||||
Division
|
||||
|
||||
This describes the division algorithm used by the MPI library.
|
||||
|
||||
Input: a, b; a > b
|
||||
Compute: Q, R; a = Qb + R
|
||||
|
||||
The input numbers are normalized so that the high-order digit of b is
|
||||
at least half the radix. This guarantees that we have a reasonable
|
||||
way to guess at the digits of the quotient (this method was taken from
|
||||
Knuth, vol. 2, with adaptations).
|
||||
|
||||
To normalize, test the high-order digit of b. If it is less than half
|
||||
the radix, multiply both a and b by d, where:
|
||||
|
||||
radix - 1
|
||||
d = -----------
|
||||
bmax + 1
|
||||
|
||||
...where bmax is the high-order digit of b. Otherwise, set d = 1.
|
||||
|
||||
Given normalize values for a and b, let the notation a[n] denote the
|
||||
nth digit of a. Let #a be the number of significant figures of a (not
|
||||
including any leading zeroes).
|
||||
|
||||
Let R = 0
|
||||
Let p = #a - 1
|
||||
|
||||
while(p >= 0)
|
||||
do
|
||||
R = (R * radix) + a[p]
|
||||
p = p - 1
|
||||
while(R < b and p >= 0)
|
||||
|
||||
if(R < b)
|
||||
break
|
||||
|
||||
q = (R[#R - 1] * radix) + R[#R - 2]
|
||||
q = q / b[#b - 1]
|
||||
|
||||
T = b * q
|
||||
|
||||
while(T > L)
|
||||
q = q - 1
|
||||
T = T - b
|
||||
endwhile
|
||||
|
||||
L = L - T
|
||||
|
||||
Q = (Q * radix) + q
|
||||
|
||||
endwhile
|
||||
|
||||
At this point, Q is the quotient, and R is the normalized remainder.
|
||||
To denormalize R, compute:
|
||||
|
||||
R = (R / d)
|
||||
|
||||
At this point, you are finished.
|
||||
|
||||
------------------------------------------------------------------
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version
|
||||
1.1 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
http://www.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
for the specific language governing rights and limitations under the
|
||||
License.
|
||||
|
||||
The Original Code is the MPI Arbitrary Precision Integer Arithmetic
|
||||
library.
|
||||
|
||||
The Initial Developer of the Original Code is
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Portions created by the Initial Developer are Copyright (C) 1998, 2000
|
||||
the Initial Developer. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
of those above. If you wish to allow use of your version of this file only
|
||||
under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
use your version of this file under the terms of the MPL, indicate your
|
||||
decision by deleting the provisions above and replace them with the notice
|
||||
and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file under
|
||||
the terms of any one of the MPL, the GPL or the LGPL.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
|
||||
$Id: div.txt,v 1.2 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
Exponentiation
|
||||
|
||||
For exponentiation, the MPI library uses a simple and fairly standard
|
||||
square-and-multiply method. The algorithm is this:
|
||||
|
||||
Input: a, b
|
||||
Output: a ** b
|
||||
|
||||
s = 1
|
||||
|
||||
while(b != 0)
|
||||
if(b is odd)
|
||||
s = s * a
|
||||
endif
|
||||
|
||||
b = b / 2
|
||||
|
||||
x = x * x
|
||||
endwhile
|
||||
|
||||
return s
|
||||
|
||||
The modular exponentiation is done the same way, except replacing:
|
||||
|
||||
s = s * a
|
||||
|
||||
with
|
||||
s = (s * a) mod m
|
||||
|
||||
and replacing
|
||||
|
||||
x = x * x
|
||||
|
||||
with
|
||||
|
||||
x = (x * x) mod m
|
||||
|
||||
Here is a sample exponentiation using the MPI library, as compared to
|
||||
the same problem solved by the Unix 'bc' program on my system:
|
||||
|
||||
Computation of 2,381,283 ** 235
|
||||
|
||||
'bc' says:
|
||||
|
||||
4385CA4A804D199FBEAD95FAD0796FAD0D0B51FC9C16743C45568C789666985DB719\
|
||||
4D90E393522F74C9601262C0514145A49F3B53D00983F95FDFCEA3D0043ECEF6227E\
|
||||
6FB59C924C3EE74447B359B5BF12A555D46CB819809EF423F004B55C587D6F0E8A55\
|
||||
4988036A42ACEF9F71459F97CEF6E574BD7373657111648626B1FF8EE15F663B2C0E\
|
||||
6BBE5082D4CDE8E14F263635AE8F35DB2C280819517BE388B5573B84C5A19C871685\
|
||||
FD408A6471F9D6AFAF5129A7548EAE926B40874B340285F44765BF5468CE20A13267\
|
||||
CD88CE6BC786ACED36EC7EA50F67FF27622575319068A332C3C0CB23E26FB55E26F4\
|
||||
5F732753A52B8E2FB4D4F42D894242613CA912A25486C3DEC9C66E5DB6182F6C1761\
|
||||
CF8CD0D255BE64B93836B27D452AE38F950EB98B517D4CF50D48F0165EF0CCCE1F5C\
|
||||
49BF18219FDBA0EEDD1A7E8B187B70C2BAED5EC5C6821EF27FAFB1CFF70111C52235\
|
||||
5E948B93A015AA1AE152B110BB5658CB14D3E45A48BFE7F082C1182672A455A695CD\
|
||||
A1855E8781E625F25B41B516E77F589FA420C3B058861EA138CF7A2C58DB3C7504FD\
|
||||
D29554D78237834CC5AE710D403CC4F6973D5012B7E117A8976B14A0B5AFA889BD47\
|
||||
92C461F0F96116F00A97AE9E83DC5203680CAF9A18A062566C145650AB86BE4F907F\
|
||||
A9F7AB4A700B29E1E5BACCD6DCBFA513E10832815F710807EED2E279081FEC61D619\
|
||||
AB270BEB3D3A1787B35A9DD41A8766CF21F3B5C693B3BAB1C2FA14A4ED202BC35743\
|
||||
E5CBE2391624D4F8C9BFBBC78D69764E7C6C5B11BF005677BFAD17D9278FFC1F158F\
|
||||
1B3683FF7960FA0608103792C4163DC0AF3E06287BB8624F8FE3A0FFBDF82ACECA2F\
|
||||
CFFF2E1AC93F3CA264A1B
|
||||
|
||||
MPI says:
|
||||
|
||||
4385CA4A804D199FBEAD95FAD0796FAD0D0B51FC9C16743C45568C789666985DB719\
|
||||
4D90E393522F74C9601262C0514145A49F3B53D00983F95FDFCEA3D0043ECEF6227E\
|
||||
6FB59C924C3EE74447B359B5BF12A555D46CB819809EF423F004B55C587D6F0E8A55\
|
||||
4988036A42ACEF9F71459F97CEF6E574BD7373657111648626B1FF8EE15F663B2C0E\
|
||||
6BBE5082D4CDE8E14F263635AE8F35DB2C280819517BE388B5573B84C5A19C871685\
|
||||
FD408A6471F9D6AFAF5129A7548EAE926B40874B340285F44765BF5468CE20A13267\
|
||||
CD88CE6BC786ACED36EC7EA50F67FF27622575319068A332C3C0CB23E26FB55E26F4\
|
||||
5F732753A52B8E2FB4D4F42D894242613CA912A25486C3DEC9C66E5DB6182F6C1761\
|
||||
CF8CD0D255BE64B93836B27D452AE38F950EB98B517D4CF50D48F0165EF0CCCE1F5C\
|
||||
49BF18219FDBA0EEDD1A7E8B187B70C2BAED5EC5C6821EF27FAFB1CFF70111C52235\
|
||||
5E948B93A015AA1AE152B110BB5658CB14D3E45A48BFE7F082C1182672A455A695CD\
|
||||
A1855E8781E625F25B41B516E77F589FA420C3B058861EA138CF7A2C58DB3C7504FD\
|
||||
D29554D78237834CC5AE710D403CC4F6973D5012B7E117A8976B14A0B5AFA889BD47\
|
||||
92C461F0F96116F00A97AE9E83DC5203680CAF9A18A062566C145650AB86BE4F907F\
|
||||
A9F7AB4A700B29E1E5BACCD6DCBFA513E10832815F710807EED2E279081FEC61D619\
|
||||
AB270BEB3D3A1787B35A9DD41A8766CF21F3B5C693B3BAB1C2FA14A4ED202BC35743\
|
||||
E5CBE2391624D4F8C9BFBBC78D69764E7C6C5B11BF005677BFAD17D9278FFC1F158F\
|
||||
1B3683FF7960FA0608103792C4163DC0AF3E06287BB8624F8FE3A0FFBDF82ACECA2F\
|
||||
CFFF2E1AC93F3CA264A1B
|
||||
|
||||
Diff says:
|
||||
% diff bc.txt mp.txt
|
||||
%
|
||||
|
||||
------------------------------------------------------------------
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version
|
||||
1.1 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
http://www.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
for the specific language governing rights and limitations under the
|
||||
License.
|
||||
|
||||
The Original Code is the MPI Arbitrary Precision Integer Arithmetic
|
||||
library.
|
||||
|
||||
The Initial Developer of the Original Code is
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Portions created by the Initial Developer are Copyright (C) 1998, 2000
|
||||
the Initial Developer. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
of those above. If you wish to allow use of your version of this file only
|
||||
under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
use your version of this file under the terms of the MPL, indicate your
|
||||
decision by deleting the provisions above and replace them with the notice
|
||||
and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file under
|
||||
the terms of any one of the MPL, the GPL or the LGPL.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
|
||||
$Id: expt.txt,v 1.2 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
=head1 NAME
|
||||
|
||||
gcd - compute greatest common divisor of two integers
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
gcd <a> <b>
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The B<gcd> program computes the greatest common divisor of two
|
||||
arbitrary-precision integers I<a> and I<b>. The result is written in
|
||||
standard decimal notation to the standard output.
|
||||
|
||||
If I<b> is zero, B<gcd> will print an error message and exit.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
invmod(1), isprime(1), lap(1)
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Thayer School of Engineering, Hanover, New Hampshire, USA
|
||||
|
||||
$Date: 2000-07-14 00:44:32 $
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
=head1 NAME
|
||||
|
||||
invmod - compute modular inverse of an integer
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
invmod <a> <m>
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The B<invmod> program computes the inverse of I<a>, modulo I<m>, if
|
||||
that inverse exists. Both I<a> and I<m> are arbitrary-precision
|
||||
integers in decimal notation. The result is written in standard
|
||||
decimal notation to the standard output.
|
||||
|
||||
If there is no inverse, the message:
|
||||
|
||||
No inverse
|
||||
|
||||
...will be printed to the standard output (an inverse exists if and
|
||||
only if the greatest common divisor of I<a> and I<m> is 1).
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
gcd(1), isprime(1), lap(1)
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Thayer School of Engineering, Hanover, New Hampshire, USA
|
||||
|
||||
$Date: 2000-07-14 00:44:33 $
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
=head1 NAME
|
||||
|
||||
isprime - probabilistic primality testing
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
isprime <a>
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The B<isprime> program attempts to determine whether the arbitrary
|
||||
precision integer I<a> is prime. It first tests I<a> for divisibility
|
||||
by the first 170 or so small primes, and assuming I<a> is not
|
||||
divisible by any of these, applies 15 iterations of the Rabin-Miller
|
||||
probabilistic primality test.
|
||||
|
||||
If the program discovers that the number is composite, it will print:
|
||||
|
||||
Not prime (reason)
|
||||
|
||||
Where I<reason> is either:
|
||||
|
||||
divisible by small prime x
|
||||
|
||||
Or:
|
||||
|
||||
failed nth pseudoprime test
|
||||
|
||||
In the first case, I<x> indicates the first small prime factor that
|
||||
was found. In the second case, I<n> indicates which of the
|
||||
pseudoprime tests failed (numbered from 1)
|
||||
|
||||
If this happens, the number is definitely not prime. However, if the
|
||||
number succeeds, this message results:
|
||||
|
||||
Probably prime, 1 in 4^15 chance of false positive
|
||||
|
||||
If this happens, the number is prime with very high probability, but
|
||||
its primality has not been absolutely proven, only demonstrated to a
|
||||
very convincing degree.
|
||||
|
||||
The value I<a> can be input in standard decimal notation, or, if it is
|
||||
prefixed with I<Ox>, it will be read as hexadecimal.
|
||||
|
||||
=head1 ENVIRONMENT
|
||||
|
||||
You can control how many iterations of Rabin-Miller are performed on
|
||||
the candidate number by setting the I<RM_TESTS> environment variable
|
||||
to an integer value before starting up B<isprime>. This will change
|
||||
the output slightly if the number passes all the tests.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
gcd(1), invmod(1), lap(1)
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Thayer School of Engineering, Hanover, New Hampshire, USA
|
||||
|
||||
$Date: 2000-07-14 00:44:33 $
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
=head1 NAME
|
||||
|
||||
lap - compute least annihilating power of a number
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
lap <a> <m>
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The B<lap> program computes the order of I<a> modulo I<m>, for
|
||||
arbitrary precision integers I<a> and I<m>. The B<order> of I<a>
|
||||
modulo I<m> is defined as the smallest positive value I<n> for which
|
||||
I<a> raised to the I<n>th power, modulo I<m>, is equal to 1. The
|
||||
order may not exist, if I<m> is composite.
|
||||
|
||||
=head1 RESTRICTIONS
|
||||
|
||||
This program is very slow, especially for large moduli. It is
|
||||
intended as a way to help find primitive elements in a modular field,
|
||||
but it does not do so in a particularly inefficient manner. It was
|
||||
written simply to help verify that a particular candidate does not
|
||||
have an obviously short cycle mod I<m>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
gcd(1), invmod(1), isprime(1)
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Thayer School of Engineering, Hanover, New Hampshire, USA
|
||||
|
||||
$Date: 2000-07-14 00:44:34 $
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
=head1 NAME
|
||||
|
||||
mpi-test - automated test program for MPI library
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
mpi-test <suite-name> [quiet]
|
||||
mpi-test list
|
||||
mpi-test help
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The B<mpi-test> program is a general unit test driver for the MPI
|
||||
library. It is used to verify that the library works as it is
|
||||
supposed to on your architecture. As with most such things, passing
|
||||
all the tests in B<mpi-test> does not guarantee the code is correct,
|
||||
but if any of them fail, there are certainly problems.
|
||||
|
||||
Each major function of the library can be tested individually. For a
|
||||
list of the test suites understood by B<mpi-test>, run it with the
|
||||
I<list> command line option:
|
||||
|
||||
mpi-test list
|
||||
|
||||
This will display a list of the available test suites and a brief
|
||||
synopsis of what each one does. For a brief overview of this
|
||||
document, run B<mpi-test> I<help>.
|
||||
|
||||
B<mpi-test> exits with a zero status if the selected test succeeds, or
|
||||
a nonzero status if it fails. If a I<suite-name> which is not
|
||||
understood by B<mpi-test> is given, a diagnostic is printed to the
|
||||
standard error, and the program exits with a result code of 2. If a
|
||||
test fails, the result code will be 1, and a diagnostic is ordinarily
|
||||
printed to the standard error. However, if the I<quiet> option is
|
||||
provided, these diagnostics will be suppressed.
|
||||
|
||||
=head1 RESTRICTIONS
|
||||
|
||||
Only a few canned test cases are provided. The solutions have been
|
||||
verified using the GNU bc(1) program, so bugs there may cause problems
|
||||
here; however, this is very unlikely, so if a test fails, it is almost
|
||||
certainly my fault, not bc(1)'s.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Thayer School of Engineering, Hanover, New Hampshire, USA
|
||||
|
||||
$Date: 2000-07-14 00:44:34 $
|
||||
@@ -1,114 +0,0 @@
|
||||
Multiplication
|
||||
|
||||
This describes the multiplication algorithm used by the MPI library.
|
||||
|
||||
This is basically a standard "schoolbook" algorithm. It is slow --
|
||||
O(mn) for m = #a, n = #b -- but easy to implement and verify.
|
||||
Basically, we run two nested loops, as illustrated here (R is the
|
||||
radix):
|
||||
|
||||
k = 0
|
||||
for j <- 0 to (#b - 1)
|
||||
for i <- 0 to (#a - 1)
|
||||
w = (a[j] * b[i]) + k + c[i+j]
|
||||
c[i+j] = w mod R
|
||||
k = w div R
|
||||
endfor
|
||||
c[i+j] = k;
|
||||
k = 0;
|
||||
endfor
|
||||
|
||||
It is necessary that 'w' have room for at least two radix R digits.
|
||||
The product of any two digits in radix R is at most:
|
||||
|
||||
(R - 1)(R - 1) = R^2 - 2R + 1
|
||||
|
||||
Since a two-digit radix-R number can hold R^2 - 1 distinct values,
|
||||
this insures that the product will fit into the two-digit register.
|
||||
|
||||
To insure that two digits is enough for w, we must also show that
|
||||
there is room for the carry-in from the previous multiplication, and
|
||||
the current value of the product digit that is being recomputed.
|
||||
Assuming each of these may be as big as R - 1 (and no larger,
|
||||
certainly), two digits will be enough if and only if:
|
||||
|
||||
(R^2 - 2R + 1) + 2(R - 1) <= R^2 - 1
|
||||
|
||||
Solving this equation shows that, indeed, this is the case:
|
||||
|
||||
R^2 - 2R + 1 + 2R - 2 <= R^2 - 1
|
||||
|
||||
R^2 - 1 <= R^2 - 1
|
||||
|
||||
This suggests that a good radix would be one more than the largest
|
||||
value that can be held in half a machine word -- so, for example, as
|
||||
in this implementation, where we used a radix of 65536 on a machine
|
||||
with 4-byte words. Another advantage of a radix of this sort is that
|
||||
binary-level operations are easy on numbers in this representation.
|
||||
|
||||
Here's an example multiplication worked out longhand in radix-10,
|
||||
using the above algorithm:
|
||||
|
||||
a = 999
|
||||
b = x 999
|
||||
-------------
|
||||
p = 98001
|
||||
|
||||
w = (a[jx] * b[ix]) + kin + c[ix + jx]
|
||||
c[ix+jx] = w % RADIX
|
||||
k = w / RADIX
|
||||
product
|
||||
ix jx a[jx] b[ix] kin w c[i+j] kout 000000
|
||||
0 0 9 9 0 81+0+0 1 8 000001
|
||||
0 1 9 9 8 81+8+0 9 8 000091
|
||||
0 2 9 9 8 81+8+0 9 8 000991
|
||||
8 0 008991
|
||||
1 0 9 9 0 81+0+9 0 9 008901
|
||||
1 1 9 9 9 81+9+9 9 9 008901
|
||||
1 2 9 9 9 81+9+8 8 9 008901
|
||||
9 0 098901
|
||||
2 0 9 9 0 81+0+9 0 9 098001
|
||||
2 1 9 9 9 81+9+8 8 9 098001
|
||||
2 2 9 9 9 81+9+9 9 9 098001
|
||||
|
||||
------------------------------------------------------------------
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version
|
||||
1.1 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
http://www.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
for the specific language governing rights and limitations under the
|
||||
License.
|
||||
|
||||
The Original Code is the MPI Arbitrary Precision Integer Arithmetic
|
||||
library.
|
||||
|
||||
The Initial Developer of the Original Code is
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Portions created by the Initial Developer are Copyright (C) 1998, 2000
|
||||
the Initial Developer. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
of those above. If you wish to allow use of your version of this file only
|
||||
under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
use your version of this file under the terms of the MPL, indicate your
|
||||
decision by deleting the provisions above and replace them with the notice
|
||||
and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file under
|
||||
the terms of any one of the MPL, the GPL or the LGPL.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
|
||||
$Id: mul.txt,v 1.2 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
This file describes how pi is computed by the program in 'pi.c' (see
|
||||
the utils subdirectory).
|
||||
|
||||
Basically, we use Machin's formula, which is what everyone in the
|
||||
world uses as a simple method for computing approximations to pi.
|
||||
This works for up to a few thousand digits without too much effort.
|
||||
Beyond that, though, it gets too slow.
|
||||
|
||||
Machin's formula states:
|
||||
|
||||
pi := 16 * arctan(1/5) - 4 * arctan(1/239)
|
||||
|
||||
We compute this in integer arithmetic by first multiplying everything
|
||||
through by 10^d, where 'd' is the number of digits of pi we wanted to
|
||||
compute. It turns out, the last few digits will be wrong, but the
|
||||
number that are wrong is usually very small (ordinarly only 2-3).
|
||||
Having done this, we compute the arctan() function using the formula:
|
||||
|
||||
1 1 1 1 1
|
||||
arctan(1/x) := --- - ----- + ----- - ----- + ----- - ...
|
||||
x 3 x^3 5 x^5 7 x^7 9 x^9
|
||||
|
||||
This is done iteratively by computing the first term manually, and
|
||||
then iteratively dividing x^2 and k, where k = 3, 5, 7, ... out of the
|
||||
current figure. This is then added to (or subtracted from) a running
|
||||
sum, as appropriate. The iteration continues until we overflow our
|
||||
available precision and the current figure goes to zero under integer
|
||||
division. At that point, we're finished.
|
||||
|
||||
Actually, we get a couple extra bits of precision out of the fact that
|
||||
we know we're computing y * arctan(1/x), by setting up the multiplier
|
||||
as:
|
||||
|
||||
y * 10^d
|
||||
|
||||
... instead of just 10^d. There is also a bit of cleverness in how
|
||||
the loop is constructed, to avoid special-casing the first term.
|
||||
Check out the code for arctan() in 'pi.c', if you are interested in
|
||||
seeing how it is set up.
|
||||
|
||||
Thanks to Jason P. for this algorithm, which I assembled from notes
|
||||
and programs found on his cool "Pile of Pi Programs" page, at:
|
||||
|
||||
http://www.isr.umd.edu/~jasonp/pipage.html
|
||||
|
||||
Thanks also to Henrik Johansson <Henrik.Johansson@Nexus.Comm.SE>, from
|
||||
whose pi program I borrowed the clever idea of pre-multiplying by x in
|
||||
order to avoid a special case on the loop iteration.
|
||||
|
||||
------------------------------------------------------------------
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version
|
||||
1.1 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
http://www.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
for the specific language governing rights and limitations under the
|
||||
License.
|
||||
|
||||
The Original Code is the MPI Arbitrary Precision Integer Arithmetic
|
||||
library.
|
||||
|
||||
The Initial Developer of the Original Code is
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Portions created by the Initial Developer are Copyright (C) 1998, 2000
|
||||
the Initial Developer. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
of those above. If you wish to allow use of your version of this file only
|
||||
under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
use your version of this file under the terms of the MPL, indicate your
|
||||
decision by deleting the provisions above and replace them with the notice
|
||||
and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file under
|
||||
the terms of any one of the MPL, the GPL or the LGPL.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
|
||||
$Id: pi.txt,v 1.2 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,41 +0,0 @@
|
||||
=head1 NAME
|
||||
|
||||
prng - pseudo-random number generator
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
prng [count]
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
B<Prng> generates 32-bit pseudo-random integers using the
|
||||
Blum-Blum-Shub (BBS) quadratic residue generator. It is seeded using
|
||||
the standard C library's rand() function, which itself seeded from the
|
||||
system clock and the process ID number. Thus, the values generated
|
||||
are not particularly useful for cryptographic applications, but they
|
||||
are in general much better than the typical output of the usual
|
||||
multiplicative congruency generator used by most runtime libraries.
|
||||
|
||||
You may optionally specify how many random values should be generated
|
||||
by giving a I<count> argument on the command line. If you do not
|
||||
specify a count, only one random value will be generated. The results
|
||||
are output to the standard output in decimal notation, one value per
|
||||
line.
|
||||
|
||||
=head1 RESTRICTIONS
|
||||
|
||||
As stated above, B<prng> uses the C library's rand() function to seed
|
||||
the generator, so it is not terribly suitable for cryptographic
|
||||
applications. Also note that each time you run the program, a new
|
||||
seed is generated, so it is better to run it once with a I<count>
|
||||
parameter than it is to run it multiple times to generate several
|
||||
values.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Copyright (C) 1998 Michael J. Fromberger, All Rights Reserved
|
||||
Thayer School of Engineering, Dartmouth College, Hanover, NH USA
|
||||
|
||||
$Date: 2000-07-14 00:44:36 $
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
Modular Reduction
|
||||
|
||||
Usually, modular reduction is accomplished by long division, using the
|
||||
mp_div() or mp_mod() functions. However, when performing modular
|
||||
exponentiation, you spend a lot of time reducing by the same modulus
|
||||
again and again. For this purpose, doing a full division for each
|
||||
multiplication is quite inefficient.
|
||||
|
||||
For this reason, the mp_exptmod() function does not perform modular
|
||||
reductions in the usual way, but instead takes advantage of an
|
||||
algorithm due to Barrett, as described by Menezes, Oorschot and
|
||||
VanStone in their book _Handbook of Applied Cryptography_, published
|
||||
by the CRC Press (see Chapter 14 for details). This method reduces
|
||||
most of the computation of reduction to efficient shifting and masking
|
||||
operations, and avoids the multiple-precision division entirely.
|
||||
|
||||
Here is a brief synopsis of Barrett reduction, as it is implemented in
|
||||
this library.
|
||||
|
||||
Let b denote the radix of the computation (one more than the maximum
|
||||
value that can be denoted by an mp_digit). Let m be the modulus, and
|
||||
let k be the number of significant digits of m. Let x be the value to
|
||||
be reduced modulo m. By the Division Theorem, there exist unique
|
||||
integers Q and R such that:
|
||||
|
||||
x = Qm + R, 0 <= R < m
|
||||
|
||||
Barrett reduction takes advantage of the fact that you can easily
|
||||
approximate Q to within two, given a value M such that:
|
||||
|
||||
2k
|
||||
b
|
||||
M = floor( ----- )
|
||||
m
|
||||
|
||||
Computation of M requires a full-precision division step, so if you
|
||||
are only doing a single reduction by m, you gain no advantage.
|
||||
However, when multiple reductions by the same m are required, this
|
||||
division need only be done once, beforehand. Using this, we can use
|
||||
the following equation to compute Q', an approximation of Q:
|
||||
|
||||
x
|
||||
floor( ------ ) M
|
||||
k-1
|
||||
b
|
||||
Q' = floor( ----------------- )
|
||||
k+1
|
||||
b
|
||||
|
||||
The divisions by b^(k-1) and b^(k+1) and the floor() functions can be
|
||||
efficiently implemented with shifts and masks, leaving only a single
|
||||
multiplication to be performed to get this approximation. It can be
|
||||
shown that Q - 2 <= Q' <= Q, so in the worst case, we can get out with
|
||||
two additional subtractions to bring the value into line with the
|
||||
actual value of Q.
|
||||
|
||||
Once we've got Q', we basically multiply that by m and subtract from
|
||||
x, yielding:
|
||||
|
||||
x - Q'm = Qm + R - Q'm
|
||||
|
||||
Since we know the constraint on Q', this is one of:
|
||||
|
||||
R
|
||||
m + R
|
||||
2m + R
|
||||
|
||||
Since R < m by the Division Theorem, we can simply subtract off m
|
||||
until we get a value in the correct range, which will happen with no
|
||||
more than 2 subtractions:
|
||||
|
||||
v = x - Q'm
|
||||
|
||||
while(v >= m)
|
||||
v = v - m
|
||||
endwhile
|
||||
|
||||
|
||||
In random performance trials, modular exponentiation using this method
|
||||
of reduction gave around a 40% speedup over using the division for
|
||||
reduction.
|
||||
|
||||
------------------------------------------------------------------
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version
|
||||
1.1 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
http://www.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
for the specific language governing rights and limitations under the
|
||||
License.
|
||||
|
||||
The Original Code is the MPI Arbitrary Precision Integer Arithmetic
|
||||
library.
|
||||
|
||||
The Initial Developer of the Original Code is
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Portions created by the Initial Developer are Copyright (C) 1998, 2000
|
||||
the Initial Developer. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
of those above. If you wish to allow use of your version of this file only
|
||||
under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
use your version of this file under the terms of the MPL, indicate your
|
||||
decision by deleting the provisions above and replace them with the notice
|
||||
and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file under
|
||||
the terms of any one of the MPL, the GPL or the LGPL.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
|
||||
$Id: redux.txt,v 1.2 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
@@ -1,87 +0,0 @@
|
||||
Square Root
|
||||
|
||||
A simple iterative algorithm is used to compute the greatest integer
|
||||
less than or equal to the square root. Essentially, this is Newton's
|
||||
linear approximation, computed by finding successive values of the
|
||||
equation:
|
||||
|
||||
x[k]^2 - V
|
||||
x[k+1] = x[k] - ------------
|
||||
2 x[k]
|
||||
|
||||
...where V is the value for which the square root is being sought. In
|
||||
essence, what is happening here is that we guess a value for the
|
||||
square root, then figure out how far off we were by squaring our guess
|
||||
and subtracting the target. Using this value, we compute a linear
|
||||
approximation for the error, and adjust the "guess". We keep doing
|
||||
this until the precision gets low enough that the above equation
|
||||
yields a quotient of zero. At this point, our last guess is one
|
||||
greater than the square root we're seeking.
|
||||
|
||||
The initial guess is computed by dividing V by 4, which is a heuristic
|
||||
I have found to be fairly good on average. This also has the
|
||||
advantage of being very easy to compute efficiently, even for large
|
||||
values.
|
||||
|
||||
So, the resulting algorithm works as follows:
|
||||
|
||||
x = V / 4 /* compute initial guess */
|
||||
|
||||
loop
|
||||
t = (x * x) - V /* Compute absolute error */
|
||||
u = 2 * x /* Adjust by tangent slope */
|
||||
t = t / u
|
||||
|
||||
/* Loop is done if error is zero */
|
||||
if(t == 0)
|
||||
break
|
||||
|
||||
/* Adjust guess by error term */
|
||||
x = x - t
|
||||
end
|
||||
|
||||
x = x - 1
|
||||
|
||||
The result of the computation is the value of x.
|
||||
|
||||
------------------------------------------------------------------
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version
|
||||
1.1 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
http://www.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
for the specific language governing rights and limitations under the
|
||||
License.
|
||||
|
||||
The Original Code is the MPI Arbitrary Precision Integer Arithmetic
|
||||
library.
|
||||
|
||||
The Initial Developer of the Original Code is
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Portions created by the Initial Developer are Copyright (C) 1998, 2000
|
||||
the Initial Developer. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
of those above. If you wish to allow use of your version of this file only
|
||||
under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
use your version of this file under the terms of the MPL, indicate your
|
||||
decision by deleting the provisions above and replace them with the notice
|
||||
and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file under
|
||||
the terms of any one of the MPL, the GPL or the LGPL.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
|
||||
$Id: sqrt.txt,v 1.2 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
Squaring Algorithm
|
||||
|
||||
When you are squaring a value, you can take advantage of the fact that
|
||||
half the multiplications performed by the more general multiplication
|
||||
algorithm (see 'mul.txt' for a description) are redundant when the
|
||||
multiplicand equals the multiplier.
|
||||
|
||||
In particular, the modified algorithm is:
|
||||
|
||||
k = 0
|
||||
for j <- 0 to (#a - 1)
|
||||
w = c[2*j] + (a[j] ^ 2);
|
||||
k = w div R
|
||||
|
||||
for i <- j+1 to (#a - 1)
|
||||
w = (2 * a[j] * a[i]) + k + c[i+j]
|
||||
c[i+j] = w mod R
|
||||
k = w div R
|
||||
endfor
|
||||
c[i+j] = k;
|
||||
k = 0;
|
||||
endfor
|
||||
|
||||
On the surface, this looks identical to the multiplication algorithm;
|
||||
however, note the following differences:
|
||||
|
||||
- precomputation of the leading term in the outer loop
|
||||
|
||||
- i runs from j+1 instead of from zero
|
||||
|
||||
- doubling of a[i] * a[j] in the inner product
|
||||
|
||||
Unfortunately, the construction of the inner product is such that we
|
||||
need more than two digits to represent the inner product, in some
|
||||
cases. In a C implementation, this means that some gymnastics must be
|
||||
performed in order to handle overflow, for which C has no direct
|
||||
abstraction. We do this by observing the following:
|
||||
|
||||
If we have multiplied a[i] and a[j], and the product is more than half
|
||||
the maximum value expressible in two digits, then doubling this result
|
||||
will overflow into a third digit. If this occurs, we take note of the
|
||||
overflow, and double it anyway -- C integer arithmetic ignores
|
||||
overflow, so the two digits we get back should still be valid, modulo
|
||||
the overflow.
|
||||
|
||||
Having doubled this value, we now have to add in the remainders and
|
||||
the digits already computed by earlier steps. If we did not overflow
|
||||
in the previous step, we might still cause an overflow here. That
|
||||
will happen whenever the maximum value expressible in two digits, less
|
||||
the amount we have to add, is greater than the result of the previous
|
||||
step. Thus, the overflow computation is:
|
||||
|
||||
|
||||
u = 0
|
||||
w = a[i] * a[j]
|
||||
|
||||
if(w > (R - 1)/ 2)
|
||||
u = 1;
|
||||
|
||||
w = w * 2
|
||||
v = c[i + j] + k
|
||||
|
||||
if(u == 0 && (R - 1 - v) < w)
|
||||
u = 1
|
||||
|
||||
If there is an overflow, u will be 1, otherwise u will be 0. The rest
|
||||
of the parameters are the same as they are in the above description.
|
||||
|
||||
------------------------------------------------------------------
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version
|
||||
1.1 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
http://www.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
for the specific language governing rights and limitations under the
|
||||
License.
|
||||
|
||||
The Original Code is the MPI Arbitrary Precision Integer Arithmetic
|
||||
library.
|
||||
|
||||
The Initial Developer of the Original Code is
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Portions created by the Initial Developer are Copyright (C) 1998, 2000
|
||||
the Initial Developer. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
of those above. If you wish to allow use of your version of this file only
|
||||
under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
use your version of this file under the terms of the MPL, indicate your
|
||||
decision by deleting the provisions above and replace them with the notice
|
||||
and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file under
|
||||
the terms of any one of the MPL, the GPL or the LGPL.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
|
||||
$Id: square.txt,v 1.2 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
|
||||
|
||||
@@ -1,250 +0,0 @@
|
||||
MPI Library Timing Tests
|
||||
|
||||
Hardware/OS
|
||||
(A) SGI O2 1 x MIPS R10000 250MHz IRIX 6.5.3
|
||||
(B) IBM RS/6000 43P-240 1 x PowerPC 603e 223MHz AIX 4.3
|
||||
(C) Dell GX1/L+ 1 x Pentium III 550MHz Linux 2.2.12-20
|
||||
(D) PowerBook G3 1 x PowerPC 750 266MHz LinuxPPC 2.2.6-15apmac
|
||||
(E) PowerBook G3 1 x PowerPC 750 266MHz MacOS 8.5.1
|
||||
(F) PowerBook G3 1 x PowerPC 750 400MHz MacOS 9.0.2
|
||||
|
||||
Compiler
|
||||
(1) MIPSpro C 7.2.1 -O3 optimizations
|
||||
(2) GCC 2.95.1 -O3 optimizations
|
||||
(3) IBM AIX xlc -O3 optimizations (version unknown)
|
||||
(4) EGCS 2.91.66 -O3 optimizations
|
||||
(5) Metrowerks CodeWarrior 5.0 C, all optimizations
|
||||
(6) MIPSpro C 7.30 -O3 optimizations
|
||||
(7) same as (6), with optimized libmalloc.so
|
||||
|
||||
Timings are given in seconds, computed using the C library's clock()
|
||||
function. The first column gives the hardware and compiler
|
||||
configuration used for the test. The second column indicates the
|
||||
number of tests that were aggregated to get the statistics for that
|
||||
size. These were compiled using 16 bit digits.
|
||||
|
||||
Source data were generated randomly using a fixed seed, so they should
|
||||
be internally consistent, but may vary on different systems depending
|
||||
on the C library. Also, since the resolution of the timer accessed by
|
||||
clock() varies, there may be some variance in the precision of these
|
||||
measurements.
|
||||
|
||||
Prime Generation (primegen)
|
||||
|
||||
128 bits:
|
||||
A1 200 min=0.03, avg=0.19, max=0.72, sum=38.46
|
||||
A2 200 min=0.02, avg=0.16, max=0.62, sum=32.55
|
||||
B3 200 min=0.01, avg=0.07, max=0.22, sum=13.29
|
||||
C4 200 min=0.00, avg=0.03, max=0.20, sum=6.14
|
||||
D4 200 min=0.00, avg=0.05, max=0.33, sum=9.70
|
||||
A6 200 min=0.01, avg=0.09, max=0.36, sum=17.48
|
||||
A7 200 min=0.00, avg=0.05, max=0.24, sum=10.07
|
||||
|
||||
192 bits:
|
||||
A1 200 min=0.05, avg=0.45, max=3.13, sum=89.96
|
||||
A2 200 min=0.04, avg=0.39, max=2.61, sum=77.55
|
||||
B3 200 min=0.02, avg=0.18, max=1.25, sum=36.97
|
||||
C4 200 min=0.01, avg=0.09, max=0.33, sum=18.24
|
||||
D4 200 min=0.02, avg=0.15, max=0.54, sum=29.63
|
||||
A6 200 min=0.02, avg=0.24, max=1.70, sum=47.84
|
||||
A7 200 min=0.01, avg=0.15, max=1.05, sum=30.88
|
||||
|
||||
256 bits:
|
||||
A1 200 min=0.08, avg=0.92, max=6.13, sum=184.79
|
||||
A2 200 min=0.06, avg=0.76, max=5.03, sum=151.11
|
||||
B3 200 min=0.04, avg=0.41, max=2.68, sum=82.35
|
||||
C4 200 min=0.02, avg=0.19, max=0.69, sum=37.91
|
||||
D4 200 min=0.03, avg=0.31, max=1.15, sum=63.00
|
||||
A6 200 min=0.04, avg=0.48, max=3.13, sum=95.46
|
||||
A7 200 min=0.03, avg=0.37, max=2.36, sum=73.60
|
||||
|
||||
320 bits:
|
||||
A1 200 min=0.11, avg=1.59, max=6.14, sum=318.81
|
||||
A2 200 min=0.09, avg=1.27, max=4.93, sum=254.03
|
||||
B3 200 min=0.07, avg=0.82, max=3.13, sum=163.80
|
||||
C4 200 min=0.04, avg=0.44, max=1.91, sum=87.59
|
||||
D4 200 min=0.06, avg=0.73, max=3.22, sum=146.73
|
||||
A6 200 min=0.07, avg=0.93, max=3.50, sum=185.01
|
||||
A7 200 min=0.05, avg=0.76, max=2.94, sum=151.78
|
||||
|
||||
384 bits:
|
||||
A1 200 min=0.16, avg=2.69, max=11.41, sum=537.89
|
||||
A2 200 min=0.13, avg=2.15, max=9.03, sum=429.14
|
||||
B3 200 min=0.11, avg=1.54, max=6.49, sum=307.78
|
||||
C4 200 min=0.06, avg=0.81, max=4.84, sum=161.13
|
||||
D4 200 min=0.10, avg=1.38, max=8.31, sum=276.81
|
||||
A6 200 min=0.11, avg=1.73, max=7.36, sum=345.55
|
||||
A7 200 min=0.09, avg=1.46, max=6.12, sum=292.02
|
||||
|
||||
448 bits:
|
||||
A1 200 min=0.23, avg=3.36, max=15.92, sum=672.63
|
||||
A2 200 min=0.17, avg=2.61, max=12.25, sum=522.86
|
||||
B3 200 min=0.16, avg=2.10, max=9.83, sum=420.86
|
||||
C4 200 min=0.09, avg=1.44, max=7.64, sum=288.36
|
||||
D4 200 min=0.16, avg=2.50, max=13.29, sum=500.17
|
||||
A6 200 min=0.15, avg=2.31, max=10.81, sum=461.58
|
||||
A7 200 min=0.14, avg=2.03, max=9.53, sum=405.16
|
||||
|
||||
512 bits:
|
||||
A1 200 min=0.30, avg=6.12, max=22.18, sum=1223.35
|
||||
A2 200 min=0.25, avg=4.67, max=16.90, sum=933.18
|
||||
B3 200 min=0.23, avg=4.13, max=14.94, sum=825.45
|
||||
C4 200 min=0.13, avg=2.08, max=9.75, sum=415.22
|
||||
D4 200 min=0.24, avg=4.04, max=20.18, sum=808.11
|
||||
A6 200 min=0.22, avg=4.47, max=16.19, sum=893.83
|
||||
A7 200 min=0.20, avg=4.03, max=14.65, sum=806.02
|
||||
|
||||
Modular Exponentation (metime)
|
||||
|
||||
The following results are aggregated from 200 pseudo-randomly
|
||||
generated tests, based on a fixed seed.
|
||||
|
||||
base, exponent, and modulus size (bits)
|
||||
P/C 128 192 256 320 384 448 512 640 768 896 1024
|
||||
------- -----------------------------------------------------------------
|
||||
A1 0.015 0.027 0.047 0.069 0.098 0.133 0.176 0.294 0.458 0.680 1.040
|
||||
A2 0.013 0.024 0.037 0.053 0.077 0.102 0.133 0.214 0.326 0.476 0.668
|
||||
B3 0.005 0.011 0.021 0.036 0.056 0.084 0.121 0.222 0.370 0.573 0.840
|
||||
C4 0.002 0.006 0.011 0.020 0.032 0.048 0.069 0.129 0.223 0.344 0.507
|
||||
D4 0.004 0.010 0.019 0.034 0.056 0.085 0.123 0.232 0.390 0.609 0.899
|
||||
E5 0.007 0.015 0.031 0.055 0.088 0.133 0.183 0.342 0.574 0.893 1.317
|
||||
A6 0.008 0.016 0.038 0.042 0.064 0.093 0.133 0.239 0.393 0.604 0.880
|
||||
A7 0.005 0.011 0.020 0.036 0.056 0.083 0.121 0.223 0.374 0.583 0.855
|
||||
|
||||
Multiplication and Squaring tests, (mulsqr)
|
||||
|
||||
The following results are aggregated from 500000 pseudo-randomly
|
||||
generated tests, based on a per-run wall-clock seed. Times are given
|
||||
in seconds, except where indicated in microseconds (us).
|
||||
|
||||
(A1)
|
||||
|
||||
bits multiply square ad percent time/mult time/square
|
||||
64 9.33 9.15 > 1.9 18.7us 18.3us
|
||||
128 10.88 10.44 > 4.0 21.8us 20.9us
|
||||
192 13.30 11.89 > 10.6 26.7us 23.8us
|
||||
256 14.88 12.64 > 15.1 29.8us 25.3us
|
||||
320 18.64 15.01 > 19.5 37.3us 30.0us
|
||||
384 23.11 17.70 > 23.4 46.2us 35.4us
|
||||
448 28.28 20.88 > 26.2 56.6us 41.8us
|
||||
512 34.09 24.51 > 28.1 68.2us 49.0us
|
||||
640 47.86 33.25 > 30.5 95.7us 66.5us
|
||||
768 64.91 43.54 > 32.9 129.8us 87.1us
|
||||
896 84.49 55.48 > 34.3 169.0us 111.0us
|
||||
1024 107.25 69.21 > 35.5 214.5us 138.4us
|
||||
1536 227.97 141.91 > 37.8 456.0us 283.8us
|
||||
2048 394.05 242.15 > 38.5 788.1us 484.3us
|
||||
|
||||
(A2)
|
||||
|
||||
bits multiply square ad percent time/mult time/square
|
||||
64 7.87 7.95 < 1.0 15.7us 15.9us
|
||||
128 9.40 9.19 > 2.2 18.8us 18.4us
|
||||
192 11.15 10.59 > 5.0 22.3us 21.2us
|
||||
256 12.02 11.16 > 7.2 24.0us 22.3us
|
||||
320 14.62 13.43 > 8.1 29.2us 26.9us
|
||||
384 17.72 15.80 > 10.8 35.4us 31.6us
|
||||
448 21.24 18.51 > 12.9 42.5us 37.0us
|
||||
512 25.36 21.78 > 14.1 50.7us 43.6us
|
||||
640 34.57 29.00 > 16.1 69.1us 58.0us
|
||||
768 46.10 37.60 > 18.4 92.2us 75.2us
|
||||
896 58.94 47.72 > 19.0 117.9us 95.4us
|
||||
1024 73.76 59.12 > 19.8 147.5us 118.2us
|
||||
1536 152.00 118.80 > 21.8 304.0us 237.6us
|
||||
2048 259.41 199.57 > 23.1 518.8us 399.1us
|
||||
|
||||
(B3)
|
||||
|
||||
bits multiply square ad percent time/mult time/square
|
||||
64 2.60 2.47 > 5.0 5.20us 4.94us
|
||||
128 4.43 4.06 > 8.4 8.86us 8.12us
|
||||
192 7.03 6.10 > 13.2 14.1us 12.2us
|
||||
256 10.44 8.59 > 17.7 20.9us 17.2us
|
||||
320 14.44 11.64 > 19.4 28.9us 23.3us
|
||||
384 19.12 15.08 > 21.1 38.2us 30.2us
|
||||
448 24.55 19.09 > 22.2 49.1us 38.2us
|
||||
512 31.03 23.53 > 24.2 62.1us 47.1us
|
||||
640 45.05 33.80 > 25.0 90.1us 67.6us
|
||||
768 63.02 46.05 > 26.9 126.0us 92.1us
|
||||
896 83.74 60.29 > 28.0 167.5us 120.6us
|
||||
1024 106.73 76.65 > 28.2 213.5us 153.3us
|
||||
1536 228.94 160.98 > 29.7 457.9us 322.0us
|
||||
2048 398.08 275.93 > 30.7 796.2us 551.9us
|
||||
|
||||
(C4)
|
||||
|
||||
bits multiply square ad percent time/mult time/square
|
||||
64 1.34 1.28 > 4.5 2.68us 2.56us
|
||||
128 2.76 2.59 > 6.2 5.52us 5.18us
|
||||
192 4.52 4.16 > 8.0 9.04us 8.32us
|
||||
256 6.64 5.99 > 9.8 13.3us 12.0us
|
||||
320 9.20 8.13 > 11.6 18.4us 16.3us
|
||||
384 12.01 10.58 > 11.9 24.0us 21.2us
|
||||
448 15.24 13.33 > 12.5 30.5us 26.7us
|
||||
512 19.02 16.46 > 13.5 38.0us 32.9us
|
||||
640 27.56 23.54 > 14.6 55.1us 47.1us
|
||||
768 37.89 31.78 > 16.1 75.8us 63.6us
|
||||
896 49.24 41.42 > 15.9 98.5us 82.8us
|
||||
1024 62.59 52.18 > 16.6 125.2us 104.3us
|
||||
1536 131.66 107.72 > 18.2 263.3us 215.4us
|
||||
2048 226.45 182.95 > 19.2 453.0us 365.9us
|
||||
|
||||
(A7)
|
||||
|
||||
bits multiply square ad percent time/mult time/square
|
||||
64 1.74 1.71 > 1.7 3.48us 3.42us
|
||||
128 3.48 2.96 > 14.9 6.96us 5.92us
|
||||
192 5.74 4.60 > 19.9 11.5us 9.20us
|
||||
256 8.75 6.61 > 24.5 17.5us 13.2us
|
||||
320 12.5 8.99 > 28.1 25.0us 18.0us
|
||||
384 16.9 11.9 > 29.6 33.8us 23.8us
|
||||
448 22.2 15.2 > 31.7 44.4us 30.4us
|
||||
512 28.3 19.0 > 32.7 56.6us 38.0us
|
||||
640 42.4 28.0 > 34.0 84.8us 56.0us
|
||||
768 59.4 38.5 > 35.2 118.8us 77.0us
|
||||
896 79.5 51.2 > 35.6 159.0us 102.4us
|
||||
1024 102.6 65.5 > 36.2 205.2us 131.0us
|
||||
1536 224.3 140.6 > 37.3 448.6us 281.2us
|
||||
2048 393.4 244.3 > 37.9 786.8us 488.6us
|
||||
|
||||
------------------------------------------------------------------
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version
|
||||
1.1 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
http://www.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
for the specific language governing rights and limitations under the
|
||||
License.
|
||||
|
||||
The Original Code is the MPI Arbitrary Precision Integer Arithmetic
|
||||
library.
|
||||
|
||||
The Initial Developer of the Original Code is
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Portions created by the Initial Developer are Copyright (C) 1998, 2000
|
||||
the Initial Developer. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
of those above. If you wish to allow use of your version of this file only
|
||||
under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
use your version of this file under the terms of the MPL, indicate your
|
||||
decision by deleting the provisions above and replace them with the notice
|
||||
and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file under
|
||||
the terms of any one of the MPL, the GPL or the LGPL.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
|
||||
$Id: timing.txt,v 1.2 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
|
||||
|
||||
@@ -1,640 +0,0 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is multacc512 multiple-precision integer arithmetic.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Hewlett-Packard Company.
|
||||
* Portions created by Hewlett-Packard Company are
|
||||
* Copyright (C) March 1999, Hewlett-Packard Company. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* coded by: Bill Worley, Hewlett-Packard labs
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*
|
||||
* This PA-RISC 2.0 function computes the product of two unsigned integers,
|
||||
* and adds the result to a previously computed integer. The multiplicand
|
||||
* is a 512-bit (64-byte, eight doubleword) unsigned integer, stored in
|
||||
* memory in little-double-wordian order. The multiplier is an unsigned
|
||||
* 64-bit integer. The previously computed integer to which the product is
|
||||
* added is located in the result ("res") area, and is assumed to be a
|
||||
* 576-bit (72-byte, nine doubleword) unsigned integer, stored in memory
|
||||
* in little-double-wordian order. This value normally will be the result
|
||||
* of a previously computed nine doubleword result. It is not necessary
|
||||
* to pad the multiplicand with an additional 64-bit zero doubleword.
|
||||
*
|
||||
* Multiplicand, multiplier, and addend ideally should be aligned at
|
||||
* 16-byte boundaries for best performance. The code will function
|
||||
* correctly for alignment at eight-byte boundaries which are not 16-byte
|
||||
* boundaries, but the execution may be slightly slower due to even/odd
|
||||
* bank conflicts on PA-RISC 8000 processors.
|
||||
*
|
||||
* This function is designed to accept the same calling sequence as Bill
|
||||
* Ackerman's "maxpy_little" function. The carry from the ninth doubleword
|
||||
* of the result is written to the tenth word of the result, as is done by
|
||||
* Bill Ackerman's function. The final carry also is returned as an
|
||||
* integer, which may be ignored. The function prototype may be either
|
||||
* of the following:
|
||||
*
|
||||
* void multacc512( int l, chunk* m, const chunk* a, chunk* res );
|
||||
* or
|
||||
* int multacc512( int l, chunk* m, const chunk* a, chunk* res );
|
||||
*
|
||||
* where: "l" originally denoted vector lengths. This parameter is
|
||||
* ignored. This function always assumes a multiplicand length of
|
||||
* 512 bits (eight doublewords), and addend and result lengths of
|
||||
* 576 bits (nine doublewords).
|
||||
*
|
||||
* "m" is a pointer to the doubleword multiplier, ideally aligned
|
||||
* on a 16-byte boundary.
|
||||
*
|
||||
* "a" is a pointer to the eight-doubleword multiplicand, stored
|
||||
* in little-double-wordian order, and ideally aligned on a 16-byte
|
||||
* boundary.
|
||||
*
|
||||
* "res" is a pointer to the nine doubleword addend, and to the
|
||||
* nine-doubleword product computed by this function. The result
|
||||
* also is stored in little-double-wordian order, and ideally is
|
||||
* aligned on a 16-byte boundary. It is expected that the alignment
|
||||
* of the "res" area may alternate between even/odd doubleword
|
||||
* boundaries for successive calls for 512-bit x 512-bit
|
||||
* multiplications.
|
||||
*
|
||||
* The code for this function has been scheduled to use the parallelism
|
||||
* of the PA-RISC 8000 series microprocessors as well as the author was
|
||||
* able. Comments and/or suggestions for improvement are welcomed.
|
||||
*
|
||||
* The code is "64-bit safe". This means it may be called in either
|
||||
* the 32ILP context or the 64LP context. All 64-bits of registers are
|
||||
* saved and restored.
|
||||
*
|
||||
* This code is self-contained. It requires no other header files in order
|
||||
* to compile and to be linkable on a PA-RISC 2.0 machine. Symbolic
|
||||
* definitions for registers and stack offsets are included within this
|
||||
* one source file.
|
||||
*
|
||||
* This is a leaf routine. As such, minimal use is made of the stack area.
|
||||
* Of the 192 bytes allocated, 64 bytes are used for saving/restoring eight
|
||||
* general registers, and 128 bytes are used to move intermediate products
|
||||
* from the floating-point registers to the general registers. Stack
|
||||
* protocols assure proper alignment of these areas.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* ====================================================================*/
|
||||
/* symbolic definitions for PA-RISC registers */
|
||||
/* in the MIPS style, avoids lots of case shifts */
|
||||
/* assigments (except t4) preserve register number parity */
|
||||
/* ====================================================================*/
|
||||
|
||||
#define zero %r0 /* permanent zero */
|
||||
#define t5 %r1 /* temp register, altered by addil */
|
||||
|
||||
#define rp %r2 /* return pointer */
|
||||
|
||||
#define s1 %r3 /* callee saves register*/
|
||||
#define s0 %r4 /* callee saves register*/
|
||||
#define s3 %r5 /* callee saves register*/
|
||||
#define s2 %r6 /* callee saves register*/
|
||||
#define s5 %r7 /* callee saves register*/
|
||||
#define s4 %r8 /* callee saves register*/
|
||||
#define s7 %r9 /* callee saves register*/
|
||||
#define s6 %r10 /* callee saves register*/
|
||||
|
||||
#define t1 %r19 /* caller saves register*/
|
||||
#define t0 %r20 /* caller saves register*/
|
||||
#define t3 %r21 /* caller saves register*/
|
||||
#define t2 %r22 /* caller saves register*/
|
||||
|
||||
#define a3 %r23 /* fourth argument register, high word */
|
||||
#define a2 %r24 /* third argument register, low word*/
|
||||
#define a1 %r25 /* second argument register, high word*/
|
||||
#define a0 %r26 /* first argument register, low word*/
|
||||
|
||||
#define v0 %r28 /* high order return value*/
|
||||
#define v1 %r29 /* low order return value*/
|
||||
|
||||
#define sp %r30 /* stack pointer*/
|
||||
#define t4 %r31 /* temporary register */
|
||||
|
||||
#define fa0 %fr4 /* first argument register*/
|
||||
#define fa1 %fr5 /* second argument register*/
|
||||
#define fa2 %fr6 /* third argument register*/
|
||||
#define fa3 %fr7 /* fourth argument register*/
|
||||
|
||||
#define fa0r %fr4R /* first argument register*/
|
||||
#define fa1r %fr5R /* second argument register*/
|
||||
#define fa2r %fr6R /* third argument register*/
|
||||
#define fa3r %fr7R /* fourth argument register*/
|
||||
|
||||
#define ft0 %fr8 /* caller saves register*/
|
||||
#define ft1 %fr9 /* caller saves register*/
|
||||
#define ft2 %fr10 /* caller saves register*/
|
||||
#define ft3 %fr11 /* caller saves register*/
|
||||
|
||||
#define ft0r %fr8R /* caller saves register*/
|
||||
#define ft1r %fr9R /* caller saves register*/
|
||||
#define ft2r %fr10R /* caller saves register*/
|
||||
#define ft3r %fr11R /* caller saves register*/
|
||||
|
||||
#define ft4 %fr22 /* caller saves register*/
|
||||
#define ft5 %fr23 /* caller saves register*/
|
||||
#define ft6 %fr24 /* caller saves register*/
|
||||
#define ft7 %fr25 /* caller saves register*/
|
||||
#define ft8 %fr26 /* caller saves register*/
|
||||
#define ft9 %fr27 /* caller saves register*/
|
||||
#define ft10 %fr28 /* caller saves register*/
|
||||
#define ft11 %fr29 /* caller saves register*/
|
||||
#define ft12 %fr30 /* caller saves register*/
|
||||
#define ft13 %fr31 /* caller saves register*/
|
||||
|
||||
#define ft4r %fr22R /* caller saves register*/
|
||||
#define ft5r %fr23R /* caller saves register*/
|
||||
#define ft6r %fr24R /* caller saves register*/
|
||||
#define ft7r %fr25R /* caller saves register*/
|
||||
#define ft8r %fr26R /* caller saves register*/
|
||||
#define ft9r %fr27R /* caller saves register*/
|
||||
#define ft10r %fr28R /* caller saves register*/
|
||||
#define ft11r %fr29R /* caller saves register*/
|
||||
#define ft12r %fr30R /* caller saves register*/
|
||||
#define ft13r %fr31R /* caller saves register*/
|
||||
|
||||
|
||||
|
||||
/* ================================================================== */
|
||||
/* functional definitions for PA-RISC registers */
|
||||
/* ================================================================== */
|
||||
|
||||
/* general registers */
|
||||
|
||||
#define T1 a0 /* temp, (length parameter ignored) */
|
||||
|
||||
#define pM a1 /* -> 64-bit multiplier */
|
||||
#define T2 a1 /* temp, (after fetching multiplier) */
|
||||
|
||||
#define pA a2 /* -> multiplicand vector (8 64-bit words) */
|
||||
#define T3 a2 /* temp, (after fetching multiplicand) */
|
||||
|
||||
#define pR a3 /* -> addend vector (8 64-bit doublewords,
|
||||
result vector (9 64-bit words) */
|
||||
|
||||
#define S0 s0 /* callee saves summand registers */
|
||||
#define S1 s1
|
||||
#define S2 s2
|
||||
#define S3 s3
|
||||
#define S4 s4
|
||||
#define S5 s5
|
||||
#define S6 s6
|
||||
#define S7 s7
|
||||
|
||||
#define S8 v0 /* caller saves summand registers */
|
||||
#define S9 v1
|
||||
#define S10 t0
|
||||
#define S11 t1
|
||||
#define S12 t2
|
||||
#define S13 t3
|
||||
#define S14 t4
|
||||
#define S15 t5
|
||||
|
||||
|
||||
|
||||
/* floating-point registers */
|
||||
|
||||
#define M fa0 /* multiplier double word */
|
||||
#define MR fa0r /* low order half of multiplier double word */
|
||||
#define ML fa0 /* high order half of multiplier double word */
|
||||
|
||||
#define A0 fa2 /* multiplicand double word 0 */
|
||||
#define A0R fa2r /* low order half of multiplicand double word */
|
||||
#define A0L fa2 /* high order half of multiplicand double word */
|
||||
|
||||
#define A1 fa3 /* multiplicand double word 1 */
|
||||
#define A1R fa3r /* low order half of multiplicand double word */
|
||||
#define A1L fa3 /* high order half of multiplicand double word */
|
||||
|
||||
#define A2 ft0 /* multiplicand double word 2 */
|
||||
#define A2R ft0r /* low order half of multiplicand double word */
|
||||
#define A2L ft0 /* high order half of multiplicand double word */
|
||||
|
||||
#define A3 ft1 /* multiplicand double word 3 */
|
||||
#define A3R ft1r /* low order half of multiplicand double word */
|
||||
#define A3L ft1 /* high order half of multiplicand double word */
|
||||
|
||||
#define A4 ft2 /* multiplicand double word 4 */
|
||||
#define A4R ft2r /* low order half of multiplicand double word */
|
||||
#define A4L ft2 /* high order half of multiplicand double word */
|
||||
|
||||
#define A5 ft3 /* multiplicand double word 5 */
|
||||
#define A5R ft3r /* low order half of multiplicand double word */
|
||||
#define A5L ft3 /* high order half of multiplicand double word */
|
||||
|
||||
#define A6 ft4 /* multiplicand double word 6 */
|
||||
#define A6R ft4r /* low order half of multiplicand double word */
|
||||
#define A6L ft4 /* high order half of multiplicand double word */
|
||||
|
||||
#define A7 ft5 /* multiplicand double word 7 */
|
||||
#define A7R ft5r /* low order half of multiplicand double word */
|
||||
#define A7L ft5 /* high order half of multiplicand double word */
|
||||
|
||||
#define P0 ft6 /* product word 0 */
|
||||
#define P1 ft7 /* product word 0 */
|
||||
#define P2 ft8 /* product word 0 */
|
||||
#define P3 ft9 /* product word 0 */
|
||||
#define P4 ft10 /* product word 0 */
|
||||
#define P5 ft11 /* product word 0 */
|
||||
#define P6 ft12 /* product word 0 */
|
||||
#define P7 ft13 /* product word 0 */
|
||||
|
||||
|
||||
|
||||
|
||||
/* ====================================================================== */
|
||||
/* symbolic definitions for HP-UX stack offsets */
|
||||
/* symbolic definitions for memory NOPs */
|
||||
/* ====================================================================== */
|
||||
|
||||
#define ST_SZ 192 /* stack area total size */
|
||||
|
||||
#define SV0 -192(sp) /* general register save area */
|
||||
#define SV1 -184(sp)
|
||||
#define SV2 -176(sp)
|
||||
#define SV3 -168(sp)
|
||||
#define SV4 -160(sp)
|
||||
#define SV5 -152(sp)
|
||||
#define SV6 -144(sp)
|
||||
#define SV7 -136(sp)
|
||||
|
||||
#define XF0 -128(sp) /* data transfer area */
|
||||
#define XF1 -120(sp) /* for floating-pt to integer regs */
|
||||
#define XF2 -112(sp)
|
||||
#define XF3 -104(sp)
|
||||
#define XF4 -96(sp)
|
||||
#define XF5 -88(sp)
|
||||
#define XF6 -80(sp)
|
||||
#define XF7 -72(sp)
|
||||
#define XF8 -64(sp)
|
||||
#define XF9 -56(sp)
|
||||
#define XF10 -48(sp)
|
||||
#define XF11 -40(sp)
|
||||
#define XF12 -32(sp)
|
||||
#define XF13 -24(sp)
|
||||
#define XF14 -16(sp)
|
||||
#define XF15 -8(sp)
|
||||
|
||||
#define mnop proberi (sp),3,zero /* memory NOP */
|
||||
|
||||
|
||||
|
||||
|
||||
/* ====================================================================== */
|
||||
/* assembler formalities */
|
||||
/* ====================================================================== */
|
||||
|
||||
#ifdef __LP64__
|
||||
.level 2.0W
|
||||
#else
|
||||
.level 2.0
|
||||
#endif
|
||||
.space $TEXT$
|
||||
.subspa $CODE$
|
||||
.align 16
|
||||
|
||||
/* ====================================================================== */
|
||||
/* here to compute 64-bit x 512-bit product + 512-bit addend */
|
||||
/* ====================================================================== */
|
||||
|
||||
multacc512
|
||||
.PROC
|
||||
.CALLINFO
|
||||
.ENTER
|
||||
fldd 0(pM),M ; multiplier double word
|
||||
ldo ST_SZ(sp),sp ; push stack
|
||||
|
||||
fldd 0(pA),A0 ; multiplicand double word 0
|
||||
std S1,SV1 ; save s1
|
||||
|
||||
fldd 16(pA),A2 ; multiplicand double word 2
|
||||
std S3,SV3 ; save s3
|
||||
|
||||
fldd 32(pA),A4 ; multiplicand double word 4
|
||||
std S5,SV5 ; save s5
|
||||
|
||||
fldd 48(pA),A6 ; multiplicand double word 6
|
||||
std S7,SV7 ; save s7
|
||||
|
||||
|
||||
std S0,SV0 ; save s0
|
||||
fldd 8(pA),A1 ; multiplicand double word 1
|
||||
xmpyu MR,A0L,P0 ; A0 cross 32-bit word products
|
||||
xmpyu ML,A0R,P2
|
||||
|
||||
std S2,SV2 ; save s2
|
||||
fldd 24(pA),A3 ; multiplicand double word 3
|
||||
xmpyu MR,A2L,P4 ; A2 cross 32-bit word products
|
||||
xmpyu ML,A2R,P6
|
||||
|
||||
std S4,SV4 ; save s4
|
||||
fldd 40(pA),A5 ; multiplicand double word 5
|
||||
|
||||
std S6,SV6 ; save s6
|
||||
fldd 56(pA),A7 ; multiplicand double word 7
|
||||
|
||||
|
||||
fstd P0,XF0 ; MR * A0L
|
||||
xmpyu MR,A0R,P0 ; A0 right 32-bit word product
|
||||
xmpyu MR,A1L,P1 ; A1 cross 32-bit word product
|
||||
|
||||
fstd P2,XF2 ; ML * A0R
|
||||
xmpyu ML,A0L,P2 ; A0 left 32-bit word product
|
||||
xmpyu ML,A1R,P3 ; A1 cross 32-bit word product
|
||||
|
||||
fstd P4,XF4 ; MR * A2L
|
||||
xmpyu MR,A2R,P4 ; A2 right 32-bit word product
|
||||
xmpyu MR,A3L,P5 ; A3 cross 32-bit word product
|
||||
|
||||
fstd P6,XF6 ; ML * A2R
|
||||
xmpyu ML,A2L,P6 ; A2 parallel 32-bit word product
|
||||
xmpyu ML,A3R,P7 ; A3 cross 32-bit word product
|
||||
|
||||
|
||||
ldd XF0,S0 ; MR * A0L
|
||||
fstd P1,XF1 ; MR * A1L
|
||||
|
||||
ldd XF2,S2 ; ML * A0R
|
||||
fstd P3,XF3 ; ML * A1R
|
||||
|
||||
ldd XF4,S4 ; MR * A2L
|
||||
fstd P5,XF5 ; MR * A3L
|
||||
xmpyu MR,A1R,P1 ; A1 parallel 32-bit word products
|
||||
xmpyu ML,A1L,P3
|
||||
|
||||
ldd XF6,S6 ; ML * A2R
|
||||
fstd P7,XF7 ; ML * A3R
|
||||
xmpyu MR,A3R,P5 ; A3 parallel 32-bit word products
|
||||
xmpyu ML,A3L,P7
|
||||
|
||||
|
||||
fstd P0,XF0 ; MR * A0R
|
||||
ldd XF1,S1 ; MR * A1L
|
||||
nop
|
||||
add S0,S2,T1 ; A0 cross product sum
|
||||
|
||||
fstd P2,XF2 ; ML * A0L
|
||||
ldd XF3,S3 ; ML * A1R
|
||||
add,dc zero,zero,S0 ; A0 cross product sum carry
|
||||
depd,z T1,31,32,S2 ; A0 cross product sum << 32
|
||||
|
||||
fstd P4,XF4 ; MR * A2R
|
||||
ldd XF5,S5 ; MR * A3L
|
||||
shrpd S0,T1,32,S0 ; A0 carry | cross product sum >> 32
|
||||
add S4,S6,T3 ; A2 cross product sum
|
||||
|
||||
fstd P6,XF6 ; ML * A2L
|
||||
ldd XF7,S7 ; ML * A3R
|
||||
add,dc zero,zero,S4 ; A2 cross product sum carry
|
||||
depd,z T3,31,32,S6 ; A2 cross product sum << 32
|
||||
|
||||
|
||||
ldd XF0,S8 ; MR * A0R
|
||||
fstd P1,XF1 ; MR * A1R
|
||||
xmpyu MR,A4L,P0 ; A4 cross 32-bit word product
|
||||
xmpyu MR,A5L,P1 ; A5 cross 32-bit word product
|
||||
|
||||
ldd XF2,S10 ; ML * A0L
|
||||
fstd P3,XF3 ; ML * A1L
|
||||
xmpyu ML,A4R,P2 ; A4 cross 32-bit word product
|
||||
xmpyu ML,A5R,P3 ; A5 cross 32-bit word product
|
||||
|
||||
ldd XF4,S12 ; MR * A2R
|
||||
fstd P5,XF5 ; MR * A3L
|
||||
xmpyu MR,A6L,P4 ; A6 cross 32-bit word product
|
||||
xmpyu MR,A7L,P5 ; A7 cross 32-bit word product
|
||||
|
||||
ldd XF6,S14 ; ML * A2L
|
||||
fstd P7,XF7 ; ML * A3L
|
||||
xmpyu ML,A6R,P6 ; A6 cross 32-bit word product
|
||||
xmpyu ML,A7R,P7 ; A7 cross 32-bit word product
|
||||
|
||||
|
||||
fstd P0,XF0 ; MR * A4L
|
||||
ldd XF1,S9 ; MR * A1R
|
||||
shrpd S4,T3,32,S4 ; A2 carry | cross product sum >> 32
|
||||
add S1,S3,T1 ; A1 cross product sum
|
||||
|
||||
fstd P2,XF2 ; ML * A4R
|
||||
ldd XF3,S11 ; ML * A1L
|
||||
add,dc zero,zero,S1 ; A1 cross product sum carry
|
||||
depd,z T1,31,32,S3 ; A1 cross product sum << 32
|
||||
|
||||
fstd P4,XF4 ; MR * A6L
|
||||
ldd XF5,S13 ; MR * A3R
|
||||
shrpd S1,T1,32,S1 ; A1 carry | cross product sum >> 32
|
||||
add S5,S7,T3 ; A3 cross product sum
|
||||
|
||||
fstd P6,XF6 ; ML * A6R
|
||||
ldd XF7,S15 ; ML * A3L
|
||||
add,dc zero,zero,S5 ; A3 cross product sum carry
|
||||
depd,z T3,31,32,S7 ; A3 cross product sum << 32
|
||||
|
||||
|
||||
shrpd S5,T3,32,S5 ; A3 carry | cross product sum >> 32
|
||||
add S2,S8,S8 ; M * A0 right doubleword, P0 doubleword
|
||||
|
||||
add,dc S0,S10,S10 ; M * A0 left doubleword
|
||||
add S3,S9,S9 ; M * A1 right doubleword
|
||||
|
||||
add,dc S1,S11,S11 ; M * A1 left doubleword
|
||||
add S6,S12,S12 ; M * A2 right doubleword
|
||||
|
||||
|
||||
ldd 24(pR),S3 ; Addend word 3
|
||||
fstd P1,XF1 ; MR * A5L
|
||||
add,dc S4,S14,S14 ; M * A2 left doubleword
|
||||
xmpyu MR,A5R,P1 ; A5 right 32-bit word product
|
||||
|
||||
ldd 8(pR),S1 ; Addend word 1
|
||||
fstd P3,XF3 ; ML * A5R
|
||||
add S7,S13,S13 ; M * A3 right doubleword
|
||||
xmpyu ML,A5L,P3 ; A5 left 32-bit word product
|
||||
|
||||
ldd 0(pR),S7 ; Addend word 0
|
||||
fstd P5,XF5 ; MR * A7L
|
||||
add,dc S5,S15,S15 ; M * A3 left doubleword
|
||||
xmpyu MR,A7R,P5 ; A7 right 32-bit word product
|
||||
|
||||
ldd 16(pR),S5 ; Addend word 2
|
||||
fstd P7,XF7 ; ML * A7R
|
||||
add S10,S9,S9 ; P1 doubleword
|
||||
xmpyu ML,A7L,P7 ; A7 left 32-bit word products
|
||||
|
||||
|
||||
ldd XF0,S0 ; MR * A4L
|
||||
fstd P1,XF9 ; MR * A5R
|
||||
add,dc S11,S12,S12 ; P2 doubleword
|
||||
xmpyu MR,A4R,P0 ; A4 right 32-bit word product
|
||||
|
||||
ldd XF2,S2 ; ML * A4R
|
||||
fstd P3,XF11 ; ML * A5L
|
||||
add,dc S14,S13,S13 ; P3 doubleword
|
||||
xmpyu ML,A4L,P2 ; A4 left 32-bit word product
|
||||
|
||||
ldd XF6,S6 ; ML * A6R
|
||||
fstd P5,XF13 ; MR * A7R
|
||||
add,dc zero,S15,T2 ; P4 partial doubleword
|
||||
xmpyu MR,A6R,P4 ; A6 right 32-bit word product
|
||||
|
||||
ldd XF4,S4 ; MR * A6L
|
||||
fstd P7,XF15 ; ML * A7L
|
||||
add S7,S8,S8 ; R0 + P0, new R0 doubleword
|
||||
xmpyu ML,A6L,P6 ; A6 left 32-bit word product
|
||||
|
||||
|
||||
fstd P0,XF0 ; MR * A4R
|
||||
ldd XF7,S7 ; ML * A7R
|
||||
add,dc S1,S9,S9 ; c + R1 + P1, new R1 doubleword
|
||||
|
||||
fstd P2,XF2 ; ML * A4L
|
||||
ldd XF1,S1 ; MR * A5L
|
||||
add,dc S5,S12,S12 ; c + R2 + P2, new R2 doubleword
|
||||
|
||||
fstd P4,XF4 ; MR * A6R
|
||||
ldd XF5,S5 ; MR * A7L
|
||||
add,dc S3,S13,S13 ; c + R3 + P3, new R3 doubleword
|
||||
|
||||
fstd P6,XF6 ; ML * A6L
|
||||
ldd XF3,S3 ; ML * A5R
|
||||
add,dc zero,T2,T2 ; c + partial P4
|
||||
add S0,S2,T1 ; A4 cross product sum
|
||||
|
||||
|
||||
std S8,0(pR) ; save R0
|
||||
add,dc zero,zero,S0 ; A4 cross product sum carry
|
||||
depd,z T1,31,32,S2 ; A4 cross product sum << 32
|
||||
|
||||
std S9,8(pR) ; save R1
|
||||
shrpd S0,T1,32,S0 ; A4 carry | cross product sum >> 32
|
||||
add S4,S6,T3 ; A6 cross product sum
|
||||
|
||||
std S12,16(pR) ; save R2
|
||||
add,dc zero,zero,S4 ; A6 cross product sum carry
|
||||
depd,z T3,31,32,S6 ; A6 cross product sum << 32
|
||||
|
||||
|
||||
std S13,24(pR) ; save R3
|
||||
shrpd S4,T3,32,S4 ; A6 carry | cross product sum >> 32
|
||||
add S1,S3,T1 ; A5 cross product sum
|
||||
|
||||
ldd XF0,S8 ; MR * A4R
|
||||
add,dc zero,zero,S1 ; A5 cross product sum carry
|
||||
depd,z T1,31,32,S3 ; A5 cross product sum << 32
|
||||
|
||||
ldd XF2,S10 ; ML * A4L
|
||||
ldd XF9,S9 ; MR * A5R
|
||||
shrpd S1,T1,32,S1 ; A5 carry | cross product sum >> 32
|
||||
add S5,S7,T3 ; A7 cross product sum
|
||||
|
||||
ldd XF4,S12 ; MR * A6R
|
||||
ldd XF11,S11 ; ML * A5L
|
||||
add,dc zero,zero,S5 ; A7 cross product sum carry
|
||||
depd,z T3,31,32,S7 ; A7 cross product sum << 32
|
||||
|
||||
ldd XF6,S14 ; ML * A6L
|
||||
ldd XF13,S13 ; MR * A7R
|
||||
shrpd S5,T3,32,S5 ; A7 carry | cross product sum >> 32
|
||||
add S2,S8,S8 ; M * A4 right doubleword
|
||||
|
||||
|
||||
ldd XF15,S15 ; ML * A7L
|
||||
add,dc S0,S10,S10 ; M * A4 left doubleword
|
||||
add S3,S9,S9 ; M * A5 right doubleword
|
||||
|
||||
add,dc S1,S11,S11 ; M * A5 left doubleword
|
||||
add S6,S12,S12 ; M * A6 right doubleword
|
||||
|
||||
ldd 32(pR),S0 ; Addend word 4
|
||||
ldd 40(pR),S1 ; Addend word 5
|
||||
add,dc S4,S14,S14 ; M * A6 left doubleword
|
||||
add S7,S13,S13 ; M * A7 right doubleword
|
||||
|
||||
ldd 48(pR),S2 ; Addend word 6
|
||||
ldd 56(pR),S3 ; Addend word 7
|
||||
add,dc S5,S15,S15 ; M * A7 left doubleword
|
||||
add S8,T2,S8 ; P4 doubleword
|
||||
|
||||
ldd 64(pR),S4 ; Addend word 8
|
||||
ldd SV5,s5 ; restore s5
|
||||
add,dc S10,S9,S9 ; P5 doubleword
|
||||
add,dc S11,S12,S12 ; P6 doubleword
|
||||
|
||||
|
||||
ldd SV6,s6 ; restore s6
|
||||
ldd SV7,s7 ; restore s7
|
||||
add,dc S14,S13,S13 ; P7 doubleword
|
||||
add,dc zero,S15,S15 ; P8 doubleword
|
||||
|
||||
add S0,S8,S8 ; new R4 doubleword
|
||||
|
||||
ldd SV0,s0 ; restore s0
|
||||
std S8,32(pR) ; save R4
|
||||
add,dc S1,S9,S9 ; new R5 doubleword
|
||||
|
||||
ldd SV1,s1 ; restore s1
|
||||
std S9,40(pR) ; save R5
|
||||
add,dc S2,S12,S12 ; new R6 doubleword
|
||||
|
||||
ldd SV2,s2 ; restore s2
|
||||
std S12,48(pR) ; save R6
|
||||
add,dc S3,S13,S13 ; new R7 doubleword
|
||||
|
||||
ldd SV3,s3 ; restore s3
|
||||
std S13,56(pR) ; save R7
|
||||
add,dc S4,S15,S15 ; new R8 doubleword
|
||||
|
||||
ldd SV4,s4 ; restore s4
|
||||
std S15,64(pR) ; save result[8]
|
||||
add,dc zero,zero,v0 ; return carry from R8
|
||||
|
||||
CMPIB,*= 0,v0,$L0 ; if no overflow, exit
|
||||
LDO 8(pR),pR
|
||||
|
||||
$FINAL1 ; Final carry propagation
|
||||
LDD 64(pR),v0
|
||||
LDO 8(pR),pR
|
||||
ADDI 1,v0,v0
|
||||
CMPIB,*= 0,v0,$FINAL1 ; Keep looping if there is a carry.
|
||||
STD v0,56(pR)
|
||||
$L0
|
||||
bv zero(rp) ; -> caller
|
||||
ldo -ST_SZ(sp),sp ; pop stack
|
||||
|
||||
/* ====================================================================== */
|
||||
/* end of module */
|
||||
/* ====================================================================== */
|
||||
|
||||
.LEAVE
|
||||
|
||||
.PROCEND
|
||||
.SPACE $TEXT$
|
||||
.SUBSPA $CODE$
|
||||
.EXPORT multacc512,ENTRY
|
||||
|
||||
.end
|
||||
@@ -1,929 +0,0 @@
|
||||
; The contents of this file are subject to the Mozilla Public
|
||||
; License Version 1.1 (the "License"); you may not use this file
|
||||
; except in compliance with the License. You may obtain a copy of
|
||||
; the License at http://www.mozilla.org/MPL/
|
||||
;
|
||||
; Software distributed under the License is distributed on an "AS
|
||||
; IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
; implied. See the License for the specific language governing
|
||||
; rights and limitations under the License.
|
||||
;
|
||||
; The Original Code is MAXPY multiple-precision integer arithmetic.
|
||||
;
|
||||
; The Initial Developer of the Original Code is the Hewlett-Packard Company.
|
||||
; Portions created by Hewlett-Packard Company are
|
||||
; Copyright (C) 1997 Hewlett-Packard Company. All Rights Reserved.
|
||||
;
|
||||
; Contributor(s):
|
||||
; coded by: William B. Ackerman
|
||||
;
|
||||
; Alternatively, the contents of this file may be used under the
|
||||
; terms of the GNU General Public License Version 2 or later (the
|
||||
; "GPL"), in which case the provisions of the GPL are applicable
|
||||
; instead of those above. If you wish to allow use of your
|
||||
; version of this file only under the terms of the GPL and not to
|
||||
; allow others to use your version of this file under the MPL,
|
||||
; indicate your decision by deleting the provisions above and
|
||||
; replace them with the notice and other provisions required by
|
||||
; the GPL. If you do not delete the provisions above, a recipient
|
||||
; may use your version of this file under either the MPL or the
|
||||
; GPL.
|
||||
|
||||
#ifdef __LP64__
|
||||
.LEVEL 2.0W
|
||||
#else
|
||||
; .LEVEL 1.1
|
||||
; .ALLOW 2.0N
|
||||
.LEVEL 2.0N
|
||||
#endif
|
||||
.SPACE $TEXT$,SORT=8
|
||||
.SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=0x2c,CODE_ONLY,SORT=24
|
||||
|
||||
; ***************************************************************
|
||||
;
|
||||
; maxpy_[little/big]
|
||||
;
|
||||
; ***************************************************************
|
||||
|
||||
; There is no default -- you must specify one or the other.
|
||||
#define LITTLE_WORDIAN 1
|
||||
|
||||
#ifdef LITTLE_WORDIAN
|
||||
#define EIGHT 8
|
||||
#define SIXTEEN 16
|
||||
#define THIRTY_TWO 32
|
||||
#define UN_EIGHT -8
|
||||
#define UN_SIXTEEN -16
|
||||
#define UN_TWENTY_FOUR -24
|
||||
#endif
|
||||
|
||||
#ifdef BIG_WORDIAN
|
||||
#define EIGHT -8
|
||||
#define SIXTEEN -16
|
||||
#define THIRTY_TWO -32
|
||||
#define UN_EIGHT 8
|
||||
#define UN_SIXTEEN 16
|
||||
#define UN_TWENTY_FOUR 24
|
||||
#endif
|
||||
|
||||
; This performs a multiple-precision integer version of "daxpy",
|
||||
; Using the selected addressing direction. "Little-wordian" means that
|
||||
; the least significant word of a number is stored at the lowest address.
|
||||
; "Big-wordian" means that the most significant word is at the lowest
|
||||
; address. Either way, the incoming address of the vector is that
|
||||
; of the least significant word. That means that, for little-wordian
|
||||
; addressing, we move the address upward as we propagate carries
|
||||
; from the least significant word to the most significant. For
|
||||
; big-wordian we move the address downward.
|
||||
|
||||
; We use the following registers:
|
||||
;
|
||||
; r2 return PC, of course
|
||||
; r26 = arg1 = length
|
||||
; r25 = arg2 = address of scalar
|
||||
; r24 = arg3 = multiplicand vector
|
||||
; r23 = arg4 = result vector
|
||||
;
|
||||
; fr9 = scalar loaded once only from r25
|
||||
|
||||
; The cycle counts shown in the bodies below are simply the result of a
|
||||
; scheduling by hand. The actual PCX-U hardware does it differently.
|
||||
; The intention is that the overall speed is the same.
|
||||
|
||||
; The pipeline startup and shutdown code is constructed in the usual way,
|
||||
; by taking the loop bodies and removing unnecessary instructions.
|
||||
; We have left the comments describing cycle numbers in the code.
|
||||
; These are intended for reference when comparing with the main loop,
|
||||
; and have no particular relationship to actual cycle numbers.
|
||||
|
||||
#ifdef LITTLE_WORDIAN
|
||||
maxpy_little
|
||||
#else
|
||||
maxpy_big
|
||||
#endif
|
||||
.PROC
|
||||
.CALLINFO FRAME=120,ENTRY_GR=%r4
|
||||
.ENTER
|
||||
|
||||
; Of course, real men don't use the sissy "enter" and "leave" commands.
|
||||
; They write their own stack manipulation stuff. Unfortunately,
|
||||
; that doesn't generate complete unwind info, whereas "enter" and
|
||||
; "leave" (if the documentation is to be believed) do so. Therefore,
|
||||
; we use the sissy commands. We have verified (by real-man methods)
|
||||
; that the above command generates what we want:
|
||||
; STW,MA %r3,128(%sp)
|
||||
; STW %r4,-124(%sp)
|
||||
|
||||
ADDIB,< -1,%r26,$L0 ; If N = 0, exit immediately.
|
||||
FLDD 0(%r25),%fr9 ; fr9 = scalar
|
||||
|
||||
; First startup
|
||||
|
||||
FLDD 0(%r24),%fr24 ; Cycle 1
|
||||
XMPYU %fr9R,%fr24R,%fr27 ; Cycle 3
|
||||
XMPYU %fr9R,%fr24L,%fr25 ; Cycle 4
|
||||
XMPYU %fr9L,%fr24L,%fr26 ; Cycle 5
|
||||
CMPIB,> 3,%r26,$N_IS_SMALL ; Pick out cases N = 1, 2, or 3
|
||||
XMPYU %fr9L,%fr24R,%fr24 ; Cycle 6
|
||||
FLDD EIGHT(%r24),%fr28 ; Cycle 8
|
||||
XMPYU %fr9L,%fr28R,%fr31 ; Cycle 10
|
||||
FSTD %fr24,-96(%sp)
|
||||
XMPYU %fr9R,%fr28L,%fr30 ; Cycle 11
|
||||
FSTD %fr25,-80(%sp)
|
||||
LDO SIXTEEN(%r24),%r24 ; Cycle 12
|
||||
FSTD %fr31,-64(%sp)
|
||||
XMPYU %fr9R,%fr28R,%fr29 ; Cycle 13
|
||||
FSTD %fr27,-48(%sp)
|
||||
|
||||
; Second startup
|
||||
|
||||
XMPYU %fr9L,%fr28L,%fr28 ; Cycle 1
|
||||
FSTD %fr30,-56(%sp)
|
||||
FLDD 0(%r24),%fr24
|
||||
|
||||
FSTD %fr26,-88(%sp) ; Cycle 2
|
||||
|
||||
XMPYU %fr9R,%fr24R,%fr27 ; Cycle 3
|
||||
FSTD %fr28,-104(%sp)
|
||||
|
||||
XMPYU %fr9R,%fr24L,%fr25 ; Cycle 4
|
||||
LDD -96(%sp),%r3
|
||||
FSTD %fr29,-72(%sp)
|
||||
|
||||
XMPYU %fr9L,%fr24L,%fr26 ; Cycle 5
|
||||
LDD -64(%sp),%r19
|
||||
LDD -80(%sp),%r21
|
||||
|
||||
XMPYU %fr9L,%fr24R,%fr24 ; Cycle 6
|
||||
LDD -56(%sp),%r20
|
||||
ADD %r21,%r3,%r3
|
||||
|
||||
ADD,DC %r20,%r19,%r19 ; Cycle 7
|
||||
LDD -88(%sp),%r4
|
||||
SHRPD %r3,%r0,32,%r21
|
||||
LDD -48(%sp),%r1
|
||||
|
||||
FLDD EIGHT(%r24),%fr28 ; Cycle 8
|
||||
LDD -104(%sp),%r31
|
||||
ADD,DC %r0,%r0,%r20
|
||||
SHRPD %r19,%r3,32,%r3
|
||||
|
||||
LDD -72(%sp),%r29 ; Cycle 9
|
||||
SHRPD %r20,%r19,32,%r20
|
||||
ADD %r21,%r1,%r1
|
||||
|
||||
XMPYU %fr9L,%fr28R,%fr31 ; Cycle 10
|
||||
ADD,DC %r3,%r4,%r4
|
||||
FSTD %fr24,-96(%sp)
|
||||
|
||||
XMPYU %fr9R,%fr28L,%fr30 ; Cycle 11
|
||||
ADD,DC %r0,%r20,%r20
|
||||
LDD 0(%r23),%r3
|
||||
FSTD %fr25,-80(%sp)
|
||||
|
||||
LDO SIXTEEN(%r24),%r24 ; Cycle 12
|
||||
FSTD %fr31,-64(%sp)
|
||||
|
||||
XMPYU %fr9R,%fr28R,%fr29 ; Cycle 13
|
||||
ADD %r0,%r0,%r0 ; clear the carry bit
|
||||
ADDIB,<= -4,%r26,$ENDLOOP ; actually happens in cycle 12
|
||||
FSTD %fr27,-48(%sp)
|
||||
; MFCTL %cr16,%r21 ; for timing
|
||||
; STD %r21,-112(%sp)
|
||||
|
||||
; Here is the loop.
|
||||
|
||||
$LOOP XMPYU %fr9L,%fr28L,%fr28 ; Cycle 1
|
||||
ADD,DC %r29,%r4,%r4
|
||||
FSTD %fr30,-56(%sp)
|
||||
FLDD 0(%r24),%fr24
|
||||
|
||||
LDO SIXTEEN(%r23),%r23 ; Cycle 2
|
||||
ADD,DC %r0,%r20,%r20
|
||||
FSTD %fr26,-88(%sp)
|
||||
|
||||
XMPYU %fr9R,%fr24R,%fr27 ; Cycle 3
|
||||
ADD %r3,%r1,%r1
|
||||
FSTD %fr28,-104(%sp)
|
||||
LDD UN_EIGHT(%r23),%r21
|
||||
|
||||
XMPYU %fr9R,%fr24L,%fr25 ; Cycle 4
|
||||
ADD,DC %r21,%r4,%r28
|
||||
FSTD %fr29,-72(%sp)
|
||||
LDD -96(%sp),%r3
|
||||
|
||||
XMPYU %fr9L,%fr24L,%fr26 ; Cycle 5
|
||||
ADD,DC %r20,%r31,%r22
|
||||
LDD -64(%sp),%r19
|
||||
LDD -80(%sp),%r21
|
||||
|
||||
XMPYU %fr9L,%fr24R,%fr24 ; Cycle 6
|
||||
ADD %r21,%r3,%r3
|
||||
LDD -56(%sp),%r20
|
||||
STD %r1,UN_SIXTEEN(%r23)
|
||||
|
||||
ADD,DC %r20,%r19,%r19 ; Cycle 7
|
||||
SHRPD %r3,%r0,32,%r21
|
||||
LDD -88(%sp),%r4
|
||||
LDD -48(%sp),%r1
|
||||
|
||||
ADD,DC %r0,%r0,%r20 ; Cycle 8
|
||||
SHRPD %r19,%r3,32,%r3
|
||||
FLDD EIGHT(%r24),%fr28
|
||||
LDD -104(%sp),%r31
|
||||
|
||||
SHRPD %r20,%r19,32,%r20 ; Cycle 9
|
||||
ADD %r21,%r1,%r1
|
||||
STD %r28,UN_EIGHT(%r23)
|
||||
LDD -72(%sp),%r29
|
||||
|
||||
XMPYU %fr9L,%fr28R,%fr31 ; Cycle 10
|
||||
ADD,DC %r3,%r4,%r4
|
||||
FSTD %fr24,-96(%sp)
|
||||
|
||||
XMPYU %fr9R,%fr28L,%fr30 ; Cycle 11
|
||||
ADD,DC %r0,%r20,%r20
|
||||
FSTD %fr25,-80(%sp)
|
||||
LDD 0(%r23),%r3
|
||||
|
||||
LDO SIXTEEN(%r24),%r24 ; Cycle 12
|
||||
FSTD %fr31,-64(%sp)
|
||||
|
||||
XMPYU %fr9R,%fr28R,%fr29 ; Cycle 13
|
||||
ADD %r22,%r1,%r1
|
||||
ADDIB,> -2,%r26,$LOOP ; actually happens in cycle 12
|
||||
FSTD %fr27,-48(%sp)
|
||||
|
||||
$ENDLOOP
|
||||
|
||||
; Shutdown code, first stage.
|
||||
|
||||
; MFCTL %cr16,%r21 ; for timing
|
||||
; STD %r21,UN_SIXTEEN(%r23)
|
||||
; LDD -112(%sp),%r21
|
||||
; STD %r21,UN_EIGHT(%r23)
|
||||
|
||||
XMPYU %fr9L,%fr28L,%fr28 ; Cycle 1
|
||||
ADD,DC %r29,%r4,%r4
|
||||
CMPIB,= 0,%r26,$ONEMORE
|
||||
FSTD %fr30,-56(%sp)
|
||||
|
||||
LDO SIXTEEN(%r23),%r23 ; Cycle 2
|
||||
ADD,DC %r0,%r20,%r20
|
||||
FSTD %fr26,-88(%sp)
|
||||
|
||||
ADD %r3,%r1,%r1 ; Cycle 3
|
||||
FSTD %fr28,-104(%sp)
|
||||
LDD UN_EIGHT(%r23),%r21
|
||||
|
||||
ADD,DC %r21,%r4,%r28 ; Cycle 4
|
||||
FSTD %fr29,-72(%sp)
|
||||
STD %r28,UN_EIGHT(%r23) ; moved up from cycle 9
|
||||
LDD -96(%sp),%r3
|
||||
|
||||
ADD,DC %r20,%r31,%r22 ; Cycle 5
|
||||
STD %r1,UN_SIXTEEN(%r23)
|
||||
$JOIN4
|
||||
LDD -64(%sp),%r19
|
||||
LDD -80(%sp),%r21
|
||||
|
||||
ADD %r21,%r3,%r3 ; Cycle 6
|
||||
LDD -56(%sp),%r20
|
||||
|
||||
ADD,DC %r20,%r19,%r19 ; Cycle 7
|
||||
SHRPD %r3,%r0,32,%r21
|
||||
LDD -88(%sp),%r4
|
||||
LDD -48(%sp),%r1
|
||||
|
||||
ADD,DC %r0,%r0,%r20 ; Cycle 8
|
||||
SHRPD %r19,%r3,32,%r3
|
||||
LDD -104(%sp),%r31
|
||||
|
||||
SHRPD %r20,%r19,32,%r20 ; Cycle 9
|
||||
ADD %r21,%r1,%r1
|
||||
LDD -72(%sp),%r29
|
||||
|
||||
ADD,DC %r3,%r4,%r4 ; Cycle 10
|
||||
|
||||
ADD,DC %r0,%r20,%r20 ; Cycle 11
|
||||
LDD 0(%r23),%r3
|
||||
|
||||
ADD %r22,%r1,%r1 ; Cycle 13
|
||||
|
||||
; Shutdown code, second stage.
|
||||
|
||||
ADD,DC %r29,%r4,%r4 ; Cycle 1
|
||||
|
||||
LDO SIXTEEN(%r23),%r23 ; Cycle 2
|
||||
ADD,DC %r0,%r20,%r20
|
||||
|
||||
LDD UN_EIGHT(%r23),%r21 ; Cycle 3
|
||||
ADD %r3,%r1,%r1
|
||||
|
||||
ADD,DC %r21,%r4,%r28 ; Cycle 4
|
||||
|
||||
ADD,DC %r20,%r31,%r22 ; Cycle 5
|
||||
|
||||
STD %r1,UN_SIXTEEN(%r23); Cycle 6
|
||||
|
||||
STD %r28,UN_EIGHT(%r23) ; Cycle 9
|
||||
|
||||
LDD 0(%r23),%r3 ; Cycle 11
|
||||
|
||||
; Shutdown code, third stage.
|
||||
|
||||
LDO SIXTEEN(%r23),%r23
|
||||
ADD %r3,%r22,%r1
|
||||
$JOIN1 ADD,DC %r0,%r0,%r21
|
||||
CMPIB,*= 0,%r21,$L0 ; if no overflow, exit
|
||||
STD %r1,UN_SIXTEEN(%r23)
|
||||
|
||||
; Final carry propagation
|
||||
|
||||
$FINAL1 LDO EIGHT(%r23),%r23
|
||||
LDD UN_SIXTEEN(%r23),%r21
|
||||
ADDI 1,%r21,%r21
|
||||
CMPIB,*= 0,%r21,$FINAL1 ; Keep looping if there is a carry.
|
||||
STD %r21,UN_SIXTEEN(%r23)
|
||||
B $L0
|
||||
NOP
|
||||
|
||||
; Here is the code that handles the difficult cases N=1, N=2, and N=3.
|
||||
; We do the usual trick -- branch out of the startup code at appropriate
|
||||
; points, and branch into the shutdown code.
|
||||
|
||||
$N_IS_SMALL
|
||||
CMPIB,= 0,%r26,$N_IS_ONE
|
||||
FSTD %fr24,-96(%sp) ; Cycle 10
|
||||
FLDD EIGHT(%r24),%fr28 ; Cycle 8
|
||||
XMPYU %fr9L,%fr28R,%fr31 ; Cycle 10
|
||||
XMPYU %fr9R,%fr28L,%fr30 ; Cycle 11
|
||||
FSTD %fr25,-80(%sp)
|
||||
FSTD %fr31,-64(%sp) ; Cycle 12
|
||||
XMPYU %fr9R,%fr28R,%fr29 ; Cycle 13
|
||||
FSTD %fr27,-48(%sp)
|
||||
XMPYU %fr9L,%fr28L,%fr28 ; Cycle 1
|
||||
CMPIB,= 2,%r26,$N_IS_THREE
|
||||
FSTD %fr30,-56(%sp)
|
||||
|
||||
; N = 2
|
||||
FSTD %fr26,-88(%sp) ; Cycle 2
|
||||
FSTD %fr28,-104(%sp) ; Cycle 3
|
||||
LDD -96(%sp),%r3 ; Cycle 4
|
||||
FSTD %fr29,-72(%sp)
|
||||
B $JOIN4
|
||||
ADD %r0,%r0,%r22
|
||||
|
||||
$N_IS_THREE
|
||||
FLDD SIXTEEN(%r24),%fr24
|
||||
FSTD %fr26,-88(%sp) ; Cycle 2
|
||||
XMPYU %fr9R,%fr24R,%fr27 ; Cycle 3
|
||||
FSTD %fr28,-104(%sp)
|
||||
XMPYU %fr9R,%fr24L,%fr25 ; Cycle 4
|
||||
LDD -96(%sp),%r3
|
||||
FSTD %fr29,-72(%sp)
|
||||
XMPYU %fr9L,%fr24L,%fr26 ; Cycle 5
|
||||
LDD -64(%sp),%r19
|
||||
LDD -80(%sp),%r21
|
||||
B $JOIN3
|
||||
ADD %r0,%r0,%r22
|
||||
|
||||
$N_IS_ONE
|
||||
FSTD %fr25,-80(%sp)
|
||||
FSTD %fr27,-48(%sp)
|
||||
FSTD %fr26,-88(%sp) ; Cycle 2
|
||||
B $JOIN5
|
||||
ADD %r0,%r0,%r22
|
||||
|
||||
; We came out of the unrolled loop with wrong parity. Do one more
|
||||
; single cycle. This is quite tricky, because of the way the
|
||||
; carry chains and SHRPD chains have been chopped up.
|
||||
|
||||
$ONEMORE
|
||||
|
||||
FLDD 0(%r24),%fr24
|
||||
|
||||
LDO SIXTEEN(%r23),%r23 ; Cycle 2
|
||||
ADD,DC %r0,%r20,%r20
|
||||
FSTD %fr26,-88(%sp)
|
||||
|
||||
XMPYU %fr9R,%fr24R,%fr27 ; Cycle 3
|
||||
FSTD %fr28,-104(%sp)
|
||||
LDD UN_EIGHT(%r23),%r21
|
||||
ADD %r3,%r1,%r1
|
||||
|
||||
XMPYU %fr9R,%fr24L,%fr25 ; Cycle 4
|
||||
ADD,DC %r21,%r4,%r28
|
||||
STD %r28,UN_EIGHT(%r23) ; moved from cycle 9
|
||||
LDD -96(%sp),%r3
|
||||
FSTD %fr29,-72(%sp)
|
||||
|
||||
XMPYU %fr9L,%fr24L,%fr26 ; Cycle 5
|
||||
ADD,DC %r20,%r31,%r22
|
||||
LDD -64(%sp),%r19
|
||||
LDD -80(%sp),%r21
|
||||
|
||||
STD %r1,UN_SIXTEEN(%r23); Cycle 6
|
||||
$JOIN3
|
||||
XMPYU %fr9L,%fr24R,%fr24
|
||||
LDD -56(%sp),%r20
|
||||
ADD %r21,%r3,%r3
|
||||
|
||||
ADD,DC %r20,%r19,%r19 ; Cycle 7
|
||||
LDD -88(%sp),%r4
|
||||
SHRPD %r3,%r0,32,%r21
|
||||
LDD -48(%sp),%r1
|
||||
|
||||
LDD -104(%sp),%r31 ; Cycle 8
|
||||
ADD,DC %r0,%r0,%r20
|
||||
SHRPD %r19,%r3,32,%r3
|
||||
|
||||
LDD -72(%sp),%r29 ; Cycle 9
|
||||
SHRPD %r20,%r19,32,%r20
|
||||
ADD %r21,%r1,%r1
|
||||
|
||||
ADD,DC %r3,%r4,%r4 ; Cycle 10
|
||||
FSTD %fr24,-96(%sp)
|
||||
|
||||
ADD,DC %r0,%r20,%r20 ; Cycle 11
|
||||
LDD 0(%r23),%r3
|
||||
FSTD %fr25,-80(%sp)
|
||||
|
||||
ADD %r22,%r1,%r1 ; Cycle 13
|
||||
FSTD %fr27,-48(%sp)
|
||||
|
||||
; Shutdown code, stage 1-1/2.
|
||||
|
||||
ADD,DC %r29,%r4,%r4 ; Cycle 1
|
||||
|
||||
LDO SIXTEEN(%r23),%r23 ; Cycle 2
|
||||
ADD,DC %r0,%r20,%r20
|
||||
FSTD %fr26,-88(%sp)
|
||||
|
||||
LDD UN_EIGHT(%r23),%r21 ; Cycle 3
|
||||
ADD %r3,%r1,%r1
|
||||
|
||||
ADD,DC %r21,%r4,%r28 ; Cycle 4
|
||||
STD %r28,UN_EIGHT(%r23) ; moved from cycle 9
|
||||
|
||||
ADD,DC %r20,%r31,%r22 ; Cycle 5
|
||||
STD %r1,UN_SIXTEEN(%r23)
|
||||
$JOIN5
|
||||
LDD -96(%sp),%r3 ; moved from cycle 4
|
||||
LDD -80(%sp),%r21
|
||||
ADD %r21,%r3,%r3 ; Cycle 6
|
||||
ADD,DC %r0,%r0,%r19 ; Cycle 7
|
||||
LDD -88(%sp),%r4
|
||||
SHRPD %r3,%r0,32,%r21
|
||||
LDD -48(%sp),%r1
|
||||
SHRPD %r19,%r3,32,%r3 ; Cycle 8
|
||||
ADD %r21,%r1,%r1 ; Cycle 9
|
||||
ADD,DC %r3,%r4,%r4 ; Cycle 10
|
||||
LDD 0(%r23),%r3 ; Cycle 11
|
||||
ADD %r22,%r1,%r1 ; Cycle 13
|
||||
|
||||
; Shutdown code, stage 2-1/2.
|
||||
|
||||
ADD,DC %r0,%r4,%r4 ; Cycle 1
|
||||
LDO SIXTEEN(%r23),%r23 ; Cycle 2
|
||||
LDD UN_EIGHT(%r23),%r21 ; Cycle 3
|
||||
ADD %r3,%r1,%r1
|
||||
STD %r1,UN_SIXTEEN(%r23)
|
||||
ADD,DC %r21,%r4,%r1
|
||||
B $JOIN1
|
||||
LDO EIGHT(%r23),%r23
|
||||
|
||||
; exit
|
||||
|
||||
$L0
|
||||
.LEAVE
|
||||
|
||||
; We have verified that the above command generates what we want:
|
||||
; LDW -124(%sp),%r4
|
||||
; BVE (%r2)
|
||||
; LDW,MB -128(%sp),%r3
|
||||
|
||||
.PROCEND
|
||||
|
||||
; ***************************************************************
|
||||
;
|
||||
; add_diag_[little/big]
|
||||
;
|
||||
; ***************************************************************
|
||||
|
||||
; The arguments are as follows:
|
||||
; r2 return PC, of course
|
||||
; r26 = arg1 = length
|
||||
; r25 = arg2 = vector to square
|
||||
; r24 = arg3 = result vector
|
||||
|
||||
#ifdef LITTLE_WORDIAN
|
||||
add_diag_little
|
||||
#else
|
||||
add_diag_big
|
||||
#endif
|
||||
.PROC
|
||||
.CALLINFO FRAME=120,ENTRY_GR=%r4
|
||||
.ENTER
|
||||
|
||||
ADDIB,< -1,%r26,$Z0 ; If N=0, exit immediately.
|
||||
NOP
|
||||
|
||||
; Startup code
|
||||
|
||||
FLDD 0(%r25),%fr7 ; Cycle 2 (alternate body)
|
||||
XMPYU %fr7R,%fr7R,%fr29 ; Cycle 4
|
||||
XMPYU %fr7L,%fr7R,%fr27 ; Cycle 5
|
||||
XMPYU %fr7L,%fr7L,%fr30
|
||||
LDO SIXTEEN(%r25),%r25 ; Cycle 6
|
||||
FSTD %fr29,-88(%sp)
|
||||
FSTD %fr27,-72(%sp) ; Cycle 7
|
||||
CMPIB,= 0,%r26,$DIAG_N_IS_ONE ; Cycle 1 (main body)
|
||||
FSTD %fr30,-96(%sp)
|
||||
FLDD UN_EIGHT(%r25),%fr7 ; Cycle 2
|
||||
LDD -88(%sp),%r22 ; Cycle 3
|
||||
LDD -72(%sp),%r31 ; Cycle 4
|
||||
XMPYU %fr7R,%fr7R,%fr28
|
||||
XMPYU %fr7L,%fr7R,%fr24 ; Cycle 5
|
||||
XMPYU %fr7L,%fr7L,%fr31
|
||||
LDD -96(%sp),%r20 ; Cycle 6
|
||||
FSTD %fr28,-80(%sp)
|
||||
ADD %r0,%r0,%r0 ; clear the carry bit
|
||||
ADDIB,<= -2,%r26,$ENDDIAGLOOP ; Cycle 7
|
||||
FSTD %fr24,-64(%sp)
|
||||
|
||||
; Here is the loop. It is unrolled twice, modelled after the "alternate body" and then the "main body".
|
||||
|
||||
$DIAGLOOP
|
||||
SHRPD %r31,%r0,31,%r3 ; Cycle 1 (alternate body)
|
||||
LDO SIXTEEN(%r25),%r25
|
||||
LDD 0(%r24),%r1
|
||||
FSTD %fr31,-104(%sp)
|
||||
SHRPD %r0,%r31,31,%r4 ; Cycle 2
|
||||
ADD,DC %r22,%r3,%r3
|
||||
FLDD UN_SIXTEEN(%r25),%fr7
|
||||
ADD,DC %r0,%r20,%r20 ; Cycle 3
|
||||
ADD %r1,%r3,%r3
|
||||
XMPYU %fr7R,%fr7R,%fr29 ; Cycle 4
|
||||
LDD -80(%sp),%r21
|
||||
STD %r3,0(%r24)
|
||||
XMPYU %fr7L,%fr7R,%fr27 ; Cycle 5
|
||||
XMPYU %fr7L,%fr7L,%fr30
|
||||
LDD -64(%sp),%r29
|
||||
LDD EIGHT(%r24),%r1
|
||||
ADD,DC %r4,%r20,%r20 ; Cycle 6
|
||||
LDD -104(%sp),%r19
|
||||
FSTD %fr29,-88(%sp)
|
||||
ADD %r20,%r1,%r1 ; Cycle 7
|
||||
FSTD %fr27,-72(%sp)
|
||||
SHRPD %r29,%r0,31,%r4 ; Cycle 1 (main body)
|
||||
LDO THIRTY_TWO(%r24),%r24
|
||||
LDD UN_SIXTEEN(%r24),%r28
|
||||
FSTD %fr30,-96(%sp)
|
||||
SHRPD %r0,%r29,31,%r3 ; Cycle 2
|
||||
ADD,DC %r21,%r4,%r4
|
||||
FLDD UN_EIGHT(%r25),%fr7
|
||||
STD %r1,UN_TWENTY_FOUR(%r24)
|
||||
ADD,DC %r0,%r19,%r19 ; Cycle 3
|
||||
ADD %r28,%r4,%r4
|
||||
XMPYU %fr7R,%fr7R,%fr28 ; Cycle 4
|
||||
LDD -88(%sp),%r22
|
||||
STD %r4,UN_SIXTEEN(%r24)
|
||||
XMPYU %fr7L,%fr7R,%fr24 ; Cycle 5
|
||||
XMPYU %fr7L,%fr7L,%fr31
|
||||
LDD -72(%sp),%r31
|
||||
LDD UN_EIGHT(%r24),%r28
|
||||
ADD,DC %r3,%r19,%r19 ; Cycle 6
|
||||
LDD -96(%sp),%r20
|
||||
FSTD %fr28,-80(%sp)
|
||||
ADD %r19,%r28,%r28 ; Cycle 7
|
||||
FSTD %fr24,-64(%sp)
|
||||
ADDIB,> -2,%r26,$DIAGLOOP ; Cycle 8
|
||||
STD %r28,UN_EIGHT(%r24)
|
||||
|
||||
$ENDDIAGLOOP
|
||||
|
||||
ADD,DC %r0,%r22,%r22
|
||||
CMPIB,= 0,%r26,$ONEMOREDIAG
|
||||
SHRPD %r31,%r0,31,%r3
|
||||
|
||||
; Shutdown code, first stage.
|
||||
|
||||
FSTD %fr31,-104(%sp) ; Cycle 1 (alternate body)
|
||||
LDD 0(%r24),%r28
|
||||
SHRPD %r0,%r31,31,%r4 ; Cycle 2
|
||||
ADD %r3,%r22,%r3
|
||||
ADD,DC %r0,%r20,%r20 ; Cycle 3
|
||||
LDD -80(%sp),%r21
|
||||
ADD %r3,%r28,%r3
|
||||
LDD -64(%sp),%r29 ; Cycle 4
|
||||
STD %r3,0(%r24)
|
||||
LDD EIGHT(%r24),%r1 ; Cycle 5
|
||||
LDO SIXTEEN(%r25),%r25 ; Cycle 6
|
||||
LDD -104(%sp),%r19
|
||||
ADD,DC %r4,%r20,%r20
|
||||
ADD %r20,%r1,%r1 ; Cycle 7
|
||||
ADD,DC %r0,%r21,%r21 ; Cycle 8
|
||||
STD %r1,EIGHT(%r24)
|
||||
|
||||
; Shutdown code, second stage.
|
||||
|
||||
SHRPD %r29,%r0,31,%r4 ; Cycle 1 (main body)
|
||||
LDO THIRTY_TWO(%r24),%r24
|
||||
LDD UN_SIXTEEN(%r24),%r1
|
||||
SHRPD %r0,%r29,31,%r3 ; Cycle 2
|
||||
ADD %r4,%r21,%r4
|
||||
ADD,DC %r0,%r19,%r19 ; Cycle 3
|
||||
ADD %r4,%r1,%r4
|
||||
STD %r4,UN_SIXTEEN(%r24); Cycle 4
|
||||
LDD UN_EIGHT(%r24),%r28 ; Cycle 5
|
||||
ADD,DC %r3,%r19,%r19 ; Cycle 6
|
||||
ADD %r19,%r28,%r28 ; Cycle 7
|
||||
ADD,DC %r0,%r0,%r22 ; Cycle 8
|
||||
CMPIB,*= 0,%r22,$Z0 ; if no overflow, exit
|
||||
STD %r28,UN_EIGHT(%r24)
|
||||
|
||||
; Final carry propagation
|
||||
|
||||
$FDIAG2
|
||||
LDO EIGHT(%r24),%r24
|
||||
LDD UN_EIGHT(%r24),%r26
|
||||
ADDI 1,%r26,%r26
|
||||
CMPIB,*= 0,%r26,$FDIAG2 ; Keep looping if there is a carry.
|
||||
STD %r26,UN_EIGHT(%r24)
|
||||
|
||||
B $Z0
|
||||
NOP
|
||||
|
||||
; Here is the code that handles the difficult case N=1.
|
||||
; We do the usual trick -- branch out of the startup code at appropriate
|
||||
; points, and branch into the shutdown code.
|
||||
|
||||
$DIAG_N_IS_ONE
|
||||
|
||||
LDD -88(%sp),%r22
|
||||
LDD -72(%sp),%r31
|
||||
B $JOINDIAG
|
||||
LDD -96(%sp),%r20
|
||||
|
||||
; We came out of the unrolled loop with wrong parity. Do one more
|
||||
; single cycle. This is the "alternate body". It will, of course,
|
||||
; give us opposite registers from the other case, so we need
|
||||
; completely different shutdown code.
|
||||
|
||||
$ONEMOREDIAG
|
||||
FSTD %fr31,-104(%sp) ; Cycle 1 (alternate body)
|
||||
LDD 0(%r24),%r28
|
||||
FLDD 0(%r25),%fr7 ; Cycle 2
|
||||
SHRPD %r0,%r31,31,%r4
|
||||
ADD %r3,%r22,%r3
|
||||
ADD,DC %r0,%r20,%r20 ; Cycle 3
|
||||
LDD -80(%sp),%r21
|
||||
ADD %r3,%r28,%r3
|
||||
LDD -64(%sp),%r29 ; Cycle 4
|
||||
STD %r3,0(%r24)
|
||||
XMPYU %fr7R,%fr7R,%fr29
|
||||
LDD EIGHT(%r24),%r1 ; Cycle 5
|
||||
XMPYU %fr7L,%fr7R,%fr27
|
||||
XMPYU %fr7L,%fr7L,%fr30
|
||||
LDD -104(%sp),%r19 ; Cycle 6
|
||||
FSTD %fr29,-88(%sp)
|
||||
ADD,DC %r4,%r20,%r20
|
||||
FSTD %fr27,-72(%sp) ; Cycle 7
|
||||
ADD %r20,%r1,%r1
|
||||
ADD,DC %r0,%r21,%r21 ; Cycle 8
|
||||
STD %r1,EIGHT(%r24)
|
||||
|
||||
; Shutdown code, first stage.
|
||||
|
||||
SHRPD %r29,%r0,31,%r4 ; Cycle 1 (main body)
|
||||
LDO THIRTY_TWO(%r24),%r24
|
||||
FSTD %fr30,-96(%sp)
|
||||
LDD UN_SIXTEEN(%r24),%r1
|
||||
SHRPD %r0,%r29,31,%r3 ; Cycle 2
|
||||
ADD %r4,%r21,%r4
|
||||
ADD,DC %r0,%r19,%r19 ; Cycle 3
|
||||
LDD -88(%sp),%r22
|
||||
ADD %r4,%r1,%r4
|
||||
LDD -72(%sp),%r31 ; Cycle 4
|
||||
STD %r4,UN_SIXTEEN(%r24)
|
||||
LDD UN_EIGHT(%r24),%r28 ; Cycle 5
|
||||
LDD -96(%sp),%r20 ; Cycle 6
|
||||
ADD,DC %r3,%r19,%r19
|
||||
ADD %r19,%r28,%r28 ; Cycle 7
|
||||
ADD,DC %r0,%r22,%r22 ; Cycle 8
|
||||
STD %r28,UN_EIGHT(%r24)
|
||||
|
||||
; Shutdown code, second stage.
|
||||
|
||||
$JOINDIAG
|
||||
SHRPD %r31,%r0,31,%r3 ; Cycle 1 (alternate body)
|
||||
LDD 0(%r24),%r28
|
||||
SHRPD %r0,%r31,31,%r4 ; Cycle 2
|
||||
ADD %r3,%r22,%r3
|
||||
ADD,DC %r0,%r20,%r20 ; Cycle 3
|
||||
ADD %r3,%r28,%r3
|
||||
STD %r3,0(%r24) ; Cycle 4
|
||||
LDD EIGHT(%r24),%r1 ; Cycle 5
|
||||
ADD,DC %r4,%r20,%r20
|
||||
ADD %r20,%r1,%r1 ; Cycle 7
|
||||
ADD,DC %r0,%r0,%r21 ; Cycle 8
|
||||
CMPIB,*= 0,%r21,$Z0 ; if no overflow, exit
|
||||
STD %r1,EIGHT(%r24)
|
||||
|
||||
; Final carry propagation
|
||||
|
||||
$FDIAG1
|
||||
LDO EIGHT(%r24),%r24
|
||||
LDD EIGHT(%r24),%r26
|
||||
ADDI 1,%r26,%r26
|
||||
CMPIB,*= 0,%r26,$FDIAG1 ; Keep looping if there is a carry.
|
||||
STD %r26,EIGHT(%r24)
|
||||
|
||||
$Z0
|
||||
.LEAVE
|
||||
.PROCEND
|
||||
; .ALLOW
|
||||
|
||||
.SPACE $TEXT$
|
||||
.SUBSPA $CODE$
|
||||
#ifdef LITTLE_WORDIAN
|
||||
.EXPORT maxpy_little,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,LONG_RETURN
|
||||
.EXPORT add_diag_little,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,LONG_RETURN
|
||||
#else
|
||||
.EXPORT maxpy_big,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,LONG_RETURN
|
||||
.EXPORT add_diag_big,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,LONG_RETURN
|
||||
#endif
|
||||
.END
|
||||
|
||||
|
||||
; How to use "maxpy_PA20_little" and "maxpy_PA20_big"
|
||||
;
|
||||
; The routine "maxpy_PA20_little" or "maxpy_PA20_big"
|
||||
; performs a 64-bit x any-size multiply, and adds the
|
||||
; result to an area of memory. That is, it performs
|
||||
; something like
|
||||
;
|
||||
; A B C D
|
||||
; * Z
|
||||
; __________
|
||||
; P Q R S T
|
||||
;
|
||||
; and then adds the "PQRST" vector into an area of memory,
|
||||
; handling all carries.
|
||||
;
|
||||
; Digression on nomenclature and endian-ness:
|
||||
;
|
||||
; Each of the capital letters in the above represents a 64-bit
|
||||
; quantity. That is, you could think of the discussion as
|
||||
; being in terms of radix-16-quintillion arithmetic. The data
|
||||
; type being manipulated is "unsigned long long int". This
|
||||
; requires the 64-bit extension of the HP-UX C compiler,
|
||||
; available at release 10. You need these compiler flags to
|
||||
; enable these extensions:
|
||||
;
|
||||
; -Aa +e +DA2.0 +DS2.0
|
||||
;
|
||||
; (The first specifies ANSI C, the second enables the
|
||||
; extensions, which are beyond ANSI C, and the third and
|
||||
; fourth tell the compiler to use whatever features of the
|
||||
; PA2.0 architecture it wishes, in order to made the code more
|
||||
; efficient. Since the presence of the assembly code will
|
||||
; make the program unable to run on anything less than PA2.0,
|
||||
; you might as well gain the performance enhancements in the C
|
||||
; code as well.)
|
||||
;
|
||||
; Questions of "endian-ness" often come up, usually in the
|
||||
; context of byte ordering in a word. These routines have a
|
||||
; similar issue, that could be called "wordian-ness".
|
||||
; Independent of byte ordering (PA is always big-endian), one
|
||||
; can make two choices when representing extremely large
|
||||
; numbers as arrays of 64-bit doublewords in memory.
|
||||
;
|
||||
; "Little-wordian" layout means that the least significant
|
||||
; word of a number is stored at the lowest address.
|
||||
;
|
||||
; MSW LSW
|
||||
; | |
|
||||
; V V
|
||||
;
|
||||
; A B C D E
|
||||
;
|
||||
; ^ ^ ^
|
||||
; | | |____ address 0
|
||||
; | |
|
||||
; | |_______address 8
|
||||
; |
|
||||
; address 32
|
||||
;
|
||||
; "Big-wordian" means that the most significant word is at the
|
||||
; lowest address.
|
||||
;
|
||||
; MSW LSW
|
||||
; | |
|
||||
; V V
|
||||
;
|
||||
; A B C D E
|
||||
;
|
||||
; ^ ^ ^
|
||||
; | | |____ address 32
|
||||
; | |
|
||||
; | |_______address 24
|
||||
; |
|
||||
; address 0
|
||||
;
|
||||
; When you compile the file, you must specify one or the other, with
|
||||
; a switch "-DLITTLE_WORDIAN" or "-DBIG_WORDIAN".
|
||||
;
|
||||
; Incidentally, you assemble this file as part of your
|
||||
; project with the same C compiler as the rest of the program.
|
||||
; My "makefile" for a superprecision arithmetic package has
|
||||
; the following stuff:
|
||||
;
|
||||
; # definitions:
|
||||
; CC = cc -Aa +e -z +DA2.0 +DS2.0 +w1
|
||||
; CFLAGS = +O3
|
||||
; LDFLAGS = -L /usr/lib -Wl,-aarchive
|
||||
;
|
||||
; # general build rule for ".s" files:
|
||||
; .s.o:
|
||||
; $(CC) $(CFLAGS) -c $< -DBIG_WORDIAN
|
||||
;
|
||||
; # Now any bind step that calls for pa20.o will assemble pa20.s
|
||||
;
|
||||
; End of digression, back to arithmetic:
|
||||
;
|
||||
; The way we multiply two huge numbers is, of course, to multiply
|
||||
; the "ABCD" vector by each of the "WXYZ" doublewords, adding
|
||||
; the result vectors with increasing offsets, the way we learned
|
||||
; in school, back before we all used calculators:
|
||||
;
|
||||
; A B C D
|
||||
; * W X Y Z
|
||||
; __________
|
||||
; P Q R S T
|
||||
; E F G H I
|
||||
; M N O P Q
|
||||
; + R S T U V
|
||||
; _______________
|
||||
; F I N A L S U M
|
||||
;
|
||||
; So we call maxpy_PA20_big (in my case; my package is
|
||||
; big-wordian) repeatedly, giving the W, X, Y, and Z arguments
|
||||
; in turn as the "scalar", and giving the "ABCD" vector each
|
||||
; time. We direct it to add its result into an area of memory
|
||||
; that we have cleared at the start. We skew the exact
|
||||
; location into that area with each call.
|
||||
;
|
||||
; The prototype for the function is
|
||||
;
|
||||
; extern void maxpy_PA20_big(
|
||||
; int length, /* Number of doublewords in the multiplicand vector. */
|
||||
; const long long int *scalaraddr, /* Address to fetch the scalar. */
|
||||
; const long long int *multiplicand, /* The multiplicand vector. */
|
||||
; long long int *result); /* Where to accumulate the result. */
|
||||
;
|
||||
; (You should place a copy of this prototype in an include file
|
||||
; or in your C file.)
|
||||
;
|
||||
; Now, IN ALL CASES, the given address for the multiplicand or
|
||||
; the result is that of the LEAST SIGNIFICANT DOUBLEWORD.
|
||||
; That word is, of course, the word at which the routine
|
||||
; starts processing. "maxpy_PA20_little" then increases the
|
||||
; addresses as it computes. "maxpy_PA20_big" decreases them.
|
||||
;
|
||||
; In our example above, "length" would be 4 in each case.
|
||||
; "multiplicand" would be the "ABCD" vector. Specifically,
|
||||
; the address of the element "D". "scalaraddr" would be the
|
||||
; address of "W", "X", "Y", or "Z" on the four calls that we
|
||||
; would make. (The order doesn't matter, of course.)
|
||||
; "result" would be the appropriate address in the result
|
||||
; area. When multiplying by "Z", that would be the least
|
||||
; significant word. When multiplying by "Y", it would be the
|
||||
; next higher word (8 bytes higher if little-wordian; 8 bytes
|
||||
; lower if big-wordian), and so on. The size of the result
|
||||
; area must be the the sum of the sizes of the multiplicand
|
||||
; and multiplier vectors, and must be initialized to zero
|
||||
; before we start.
|
||||
;
|
||||
; Whenever the routine adds its partial product into the result
|
||||
; vector, it follows carry chains as far as they need to go.
|
||||
;
|
||||
; Here is the super-precision multiply routine that I use for
|
||||
; my package. The package is big-wordian. I have taken out
|
||||
; handling of exponents (it's a floating point package):
|
||||
;
|
||||
; static void mul_PA20(
|
||||
; int size,
|
||||
; const long long int *arg1,
|
||||
; const long long int *arg2,
|
||||
; long long int *result)
|
||||
; {
|
||||
; int i;
|
||||
;
|
||||
; for (i=0 ; i<2*size ; i++) result[i] = 0ULL;
|
||||
;
|
||||
; for (i=0 ; i<size ; i++) {
|
||||
; maxpy_PA20_big(size, &arg2[i], &arg1[size-1], &result[size+i]);
|
||||
; }
|
||||
; }
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* logtab.h
|
||||
*
|
||||
* Arbitrary precision integer arithmetic library
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael J. Fromberger.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: logtab.h,v 1.5 2004-04-27 23:04:36 gerv%gerv.net Exp $ */
|
||||
|
||||
const float s_logv_2[] = {
|
||||
0.000000000f, 0.000000000f, 1.000000000f, 0.630929754f, /* 0 1 2 3 */
|
||||
0.500000000f, 0.430676558f, 0.386852807f, 0.356207187f, /* 4 5 6 7 */
|
||||
0.333333333f, 0.315464877f, 0.301029996f, 0.289064826f, /* 8 9 10 11 */
|
||||
0.278942946f, 0.270238154f, 0.262649535f, 0.255958025f, /* 12 13 14 15 */
|
||||
0.250000000f, 0.244650542f, 0.239812467f, 0.235408913f, /* 16 17 18 19 */
|
||||
0.231378213f, 0.227670249f, 0.224243824f, 0.221064729f, /* 20 21 22 23 */
|
||||
0.218104292f, 0.215338279f, 0.212746054f, 0.210309918f, /* 24 25 26 27 */
|
||||
0.208014598f, 0.205846832f, 0.203795047f, 0.201849087f, /* 28 29 30 31 */
|
||||
0.200000000f, 0.198239863f, 0.196561632f, 0.194959022f, /* 32 33 34 35 */
|
||||
0.193426404f, 0.191958720f, 0.190551412f, 0.189200360f, /* 36 37 38 39 */
|
||||
0.187901825f, 0.186652411f, 0.185449023f, 0.184288833f, /* 40 41 42 43 */
|
||||
0.183169251f, 0.182087900f, 0.181042597f, 0.180031327f, /* 44 45 46 47 */
|
||||
0.179052232f, 0.178103594f, 0.177183820f, 0.176291434f, /* 48 49 50 51 */
|
||||
0.175425064f, 0.174583430f, 0.173765343f, 0.172969690f, /* 52 53 54 55 */
|
||||
0.172195434f, 0.171441601f, 0.170707280f, 0.169991616f, /* 56 57 58 59 */
|
||||
0.169293808f, 0.168613099f, 0.167948779f, 0.167300179f, /* 60 61 62 63 */
|
||||
0.166666667f
|
||||
};
|
||||
|
||||
@@ -1,133 +0,0 @@
|
||||
#!/usr/linguist/bin/perl
|
||||
|
||||
#
|
||||
# make-test-arrays
|
||||
#
|
||||
# Given a test-arrays file, which specifies the test suite names, the
|
||||
# names of the functions which perform those test suites, and
|
||||
# descriptive comments, this script generates C structures for the
|
||||
# mpi-test program. The input consists of lines of the form:
|
||||
#
|
||||
# suite-name:function-name:comment
|
||||
#
|
||||
# The output is written to the standard output. Blank lines are
|
||||
# ignored, and comments beginning with '#' are stripped.
|
||||
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the MPI Arbitrary Precision Integer Arithmetic library.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Michael J. Fromberger <sting@linguist.dartmouth.edu>.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
# $Id: make-test-arrays,v 1.2 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
#
|
||||
|
||||
# Read parameters from the environment, if available
|
||||
$NAMEVAR = $ENV{'NAMEVAR'} || "g_names";
|
||||
$COUNTVAR = $ENV{'COUNTVAR'} || "g_count";
|
||||
$FUNCVAR = $ENV{'FUNCVAR'} || "g_tests";
|
||||
$DESCVAR = $ENV{'DESCVAR'} || "g_descs";
|
||||
$FUNCLEN = 13;
|
||||
$NAMELEN = 18;
|
||||
$DESCLEN = 45;
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
# Suck in input from the files on the command line, or standard input
|
||||
while(<>) {
|
||||
chomp;
|
||||
s/\#.*$//;
|
||||
next if /^\s*$/;
|
||||
|
||||
($suite, $func, $desc) = split(/:/, $_);
|
||||
|
||||
$tmp = { "suite" => $suite,
|
||||
"func" => $func,
|
||||
"desc" => $desc };
|
||||
|
||||
push(@item, $tmp);
|
||||
}
|
||||
$count = scalar(@item);
|
||||
$last = pop(@item);
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
# Output the table of names
|
||||
print "/* Table mapping test suite names to index numbers */\n";
|
||||
printf("const int %s = %d;\n", $COUNTVAR, $count);
|
||||
printf("const char *%s[] = {\n", $NAMEVAR);
|
||||
|
||||
foreach $elt (@item) {
|
||||
printf(" \"%s\",%s/* %s%s */\n", $elt->{"suite"},
|
||||
" " x ($NAMELEN - length($elt->{"suite"})),
|
||||
$elt->{"desc"},
|
||||
" " x ($DESCLEN - length($elt->{"desc"})));
|
||||
}
|
||||
printf(" \"%s\" %s/* %s%s */\n", $last->{"suite"},
|
||||
" " x ($NAMELEN - length($last->{"suite"})),
|
||||
$last->{"desc"},
|
||||
" " x ($DESCLEN - length($last->{"desc"})));
|
||||
print "};\n\n";
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
# Output the driver function prototypes
|
||||
print "/* Test function prototypes */\n";
|
||||
foreach $elt (@item, $last) {
|
||||
printf("int %s(void);\n", $elt->{"func"});
|
||||
}
|
||||
print "\n";
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
# Output the table of functions
|
||||
print "/* Table mapping index numbers to functions */\n";
|
||||
printf("int (*%s[])(void) = {\n ", $FUNCVAR);
|
||||
$brk = 0;
|
||||
|
||||
foreach $elt (@item) {
|
||||
print($elt->{"func"}, ", ",
|
||||
" " x ($FUNCLEN - length($elt->{"func"})));
|
||||
$brk = ($brk + 1) & 3;
|
||||
print "\n " unless($brk);
|
||||
}
|
||||
print $last->{"func"}, "\n};\n\n";
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
# Output the table of descriptions
|
||||
print "/* Table mapping index numbers to descriptions */\n";
|
||||
printf("const char *%s[] = {\n", $DESCVAR);
|
||||
|
||||
foreach $elt (@item) {
|
||||
printf(" \"%s\",\n", $elt->{"desc"});
|
||||
}
|
||||
printf(" \"%s\"\n};\n\n", $last->{"desc"});
|
||||
|
||||
exit 0;
|
||||
|
||||
@@ -1,342 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <time.h>
|
||||
#include "mpi.h"
|
||||
#include "mpi-priv.h"
|
||||
|
||||
/* #define OLD_WAY 1 */
|
||||
|
||||
/* This key is the 1024-bit test key used for speed testing of RSA private
|
||||
** key ops.
|
||||
*/
|
||||
|
||||
#define CONST const
|
||||
|
||||
static CONST unsigned char default_n[128] = {
|
||||
0xc2,0xae,0x96,0x89,0xaf,0xce,0xd0,0x7b,0x3b,0x35,0xfd,0x0f,0xb1,0xf4,0x7a,0xd1,
|
||||
0x3c,0x7d,0xb5,0x86,0xf2,0x68,0x36,0xc9,0x97,0xe6,0x82,0x94,0x86,0xaa,0x05,0x39,
|
||||
0xec,0x11,0x51,0xcc,0x5c,0xa1,0x59,0xba,0x29,0x18,0xf3,0x28,0xf1,0x9d,0xe3,0xae,
|
||||
0x96,0x5d,0x6d,0x87,0x73,0xf6,0xf6,0x1f,0xd0,0x2d,0xfb,0x2f,0x7a,0x13,0x7f,0xc8,
|
||||
0x0c,0x7a,0xe9,0x85,0xfb,0xce,0x74,0x86,0xf8,0xef,0x2f,0x85,0x37,0x73,0x0f,0x62,
|
||||
0x4e,0x93,0x17,0xb7,0x7e,0x84,0x9a,0x94,0x11,0x05,0xca,0x0d,0x31,0x4b,0x2a,0xc8,
|
||||
0xdf,0xfe,0xe9,0x0c,0x13,0xc7,0xf2,0xad,0x19,0x64,0x28,0x3c,0xb5,0x6a,0xc8,0x4b,
|
||||
0x79,0xea,0x7c,0xce,0x75,0x92,0x45,0x3e,0xa3,0x9d,0x64,0x6f,0x04,0x69,0x19,0x17
|
||||
};
|
||||
|
||||
static CONST unsigned char default_d[128] = {
|
||||
0x13,0xcb,0xbc,0xf2,0xf3,0x35,0x8c,0x6d,0x7b,0x6f,0xd9,0xf3,0xa6,0x9c,0xbd,0x80,
|
||||
0x59,0x2e,0x4f,0x2f,0x11,0xa7,0x17,0x2b,0x18,0x8f,0x0f,0xe8,0x1a,0x69,0x5f,0x6e,
|
||||
0xac,0x5a,0x76,0x7e,0xd9,0x4c,0x6e,0xdb,0x47,0x22,0x8a,0x57,0x37,0x7a,0x5e,0x94,
|
||||
0x7a,0x25,0xb5,0xe5,0x78,0x1d,0x3c,0x99,0xaf,0x89,0x7d,0x69,0x2e,0x78,0x9d,0x1d,
|
||||
0x84,0xc8,0xc1,0xd7,0x1a,0xb2,0x6d,0x2d,0x8a,0xd9,0xab,0x6b,0xce,0xae,0xb0,0xa0,
|
||||
0x58,0x55,0xad,0x5c,0x40,0x8a,0xd6,0x96,0x08,0x8a,0xe8,0x63,0xe6,0x3d,0x6c,0x20,
|
||||
0x49,0xc7,0xaf,0x0f,0x25,0x73,0xd3,0x69,0x43,0x3b,0xf2,0x32,0xf8,0x3d,0x5e,0xee,
|
||||
0x7a,0xca,0xd6,0x94,0x55,0xe5,0xbd,0x25,0x34,0x8d,0x63,0x40,0xb5,0x8a,0xc3,0x01
|
||||
};
|
||||
|
||||
|
||||
#define DEFAULT_ITERS 50
|
||||
|
||||
typedef clock_t timetype;
|
||||
#define gettime(x) *(x) = clock()
|
||||
#define subtime(a, b) a -= b
|
||||
#define msec(x) ((clock_t)((double)x * 1000.0 / CLOCKS_PER_SEC))
|
||||
#define sec(x) (x / CLOCKS_PER_SEC)
|
||||
|
||||
struct TimingContextStr {
|
||||
timetype start;
|
||||
timetype end;
|
||||
timetype interval;
|
||||
|
||||
int minutes;
|
||||
int seconds;
|
||||
int millisecs;
|
||||
};
|
||||
|
||||
typedef struct TimingContextStr TimingContext;
|
||||
|
||||
TimingContext *CreateTimingContext(void)
|
||||
{
|
||||
return (TimingContext *)malloc(sizeof(TimingContext));
|
||||
}
|
||||
|
||||
void DestroyTimingContext(TimingContext *ctx)
|
||||
{
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
void TimingBegin(TimingContext *ctx)
|
||||
{
|
||||
gettime(&ctx->start);
|
||||
}
|
||||
|
||||
static void timingUpdate(TimingContext *ctx)
|
||||
{
|
||||
|
||||
ctx->millisecs = msec(ctx->interval) % 1000;
|
||||
ctx->seconds = sec(ctx->interval);
|
||||
ctx->minutes = ctx->seconds / 60;
|
||||
ctx->seconds %= 60;
|
||||
|
||||
}
|
||||
|
||||
void TimingEnd(TimingContext *ctx)
|
||||
{
|
||||
gettime(&ctx->end);
|
||||
ctx->interval = ctx->end;
|
||||
subtime(ctx->interval, ctx->start);
|
||||
timingUpdate(ctx);
|
||||
}
|
||||
|
||||
char *TimingGenerateString(TimingContext *ctx)
|
||||
{
|
||||
static char sBuf[4096];
|
||||
|
||||
sprintf(sBuf, "%d minutes, %d.%03d seconds", ctx->minutes,
|
||||
ctx->seconds, ctx->millisecs);
|
||||
return sBuf;
|
||||
}
|
||||
|
||||
static void
|
||||
dumpBytes( unsigned char * b, int l)
|
||||
{
|
||||
int i;
|
||||
if (l <= 0)
|
||||
return;
|
||||
for (i = 0; i < l; ++i) {
|
||||
if (i % 16 == 0)
|
||||
printf("\t");
|
||||
printf(" %02x", b[i]);
|
||||
if (i % 16 == 15)
|
||||
printf("\n");
|
||||
}
|
||||
if ((i % 16) != 0)
|
||||
printf("\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static mp_err
|
||||
testNewFuncs(const unsigned char * modulusBytes, int modulus_len)
|
||||
{
|
||||
mp_err mperr = MP_OKAY;
|
||||
mp_int modulus;
|
||||
unsigned char buf[512];
|
||||
|
||||
mperr = mp_init(&modulus);
|
||||
mperr = mp_read_unsigned_octets(&modulus, modulusBytes, modulus_len );
|
||||
mperr = mp_to_fixlen_octets(&modulus, buf, modulus_len);
|
||||
mperr = mp_to_fixlen_octets(&modulus, buf, modulus_len+1);
|
||||
mperr = mp_to_fixlen_octets(&modulus, buf, modulus_len+4);
|
||||
mperr = mp_to_unsigned_octets(&modulus, buf, modulus_len);
|
||||
mperr = mp_to_signed_octets(&modulus, buf, modulus_len + 1);
|
||||
mp_clear(&modulus);
|
||||
return mperr;
|
||||
}
|
||||
|
||||
int
|
||||
testModExp( const unsigned char * modulusBytes,
|
||||
const unsigned int expo,
|
||||
const unsigned char * input,
|
||||
unsigned char * output,
|
||||
int modulus_len)
|
||||
{
|
||||
mp_err mperr = MP_OKAY;
|
||||
mp_int modulus;
|
||||
mp_int base;
|
||||
mp_int exponent;
|
||||
mp_int result;
|
||||
|
||||
mperr = mp_init(&modulus);
|
||||
mperr += mp_init(&base);
|
||||
mperr += mp_init(&exponent);
|
||||
mperr += mp_init(&result);
|
||||
/* we initialize all mp_ints unconditionally, even if some fail.
|
||||
** This guarantees that the DIGITS pointer is valid (even if null).
|
||||
** So, mp_clear will do the right thing below.
|
||||
*/
|
||||
if (mperr == MP_OKAY) {
|
||||
mperr = mp_read_unsigned_octets(&modulus,
|
||||
modulusBytes + (sizeof default_n - modulus_len), modulus_len );
|
||||
mperr += mp_read_unsigned_octets(&base, input, modulus_len );
|
||||
mp_set(&exponent, expo);
|
||||
if (mperr == MP_OKAY) {
|
||||
#if OLD_WAY
|
||||
mperr = s_mp_exptmod(&base, &exponent, &modulus, &result);
|
||||
#else
|
||||
mperr = mp_exptmod(&base, &exponent, &modulus, &result);
|
||||
#endif
|
||||
if (mperr == MP_OKAY) {
|
||||
mperr = mp_to_fixlen_octets(&result, output, modulus_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
mp_clear(&base);
|
||||
mp_clear(&result);
|
||||
|
||||
mp_clear(&modulus);
|
||||
mp_clear(&exponent);
|
||||
|
||||
return (int)mperr;
|
||||
}
|
||||
|
||||
int
|
||||
doModExp( const unsigned char * modulusBytes,
|
||||
const unsigned char * exponentBytes,
|
||||
const unsigned char * input,
|
||||
unsigned char * output,
|
||||
int modulus_len)
|
||||
{
|
||||
mp_err mperr = MP_OKAY;
|
||||
mp_int modulus;
|
||||
mp_int base;
|
||||
mp_int exponent;
|
||||
mp_int result;
|
||||
|
||||
mperr = mp_init(&modulus);
|
||||
mperr += mp_init(&base);
|
||||
mperr += mp_init(&exponent);
|
||||
mperr += mp_init(&result);
|
||||
/* we initialize all mp_ints unconditionally, even if some fail.
|
||||
** This guarantees that the DIGITS pointer is valid (even if null).
|
||||
** So, mp_clear will do the right thing below.
|
||||
*/
|
||||
if (mperr == MP_OKAY) {
|
||||
mperr = mp_read_unsigned_octets(&modulus,
|
||||
modulusBytes + (sizeof default_n - modulus_len), modulus_len );
|
||||
mperr += mp_read_unsigned_octets(&exponent, exponentBytes, modulus_len );
|
||||
mperr += mp_read_unsigned_octets(&base, input, modulus_len );
|
||||
if (mperr == MP_OKAY) {
|
||||
#if OLD_WAY
|
||||
mperr = s_mp_exptmod(&base, &exponent, &modulus, &result);
|
||||
#else
|
||||
mperr = mp_exptmod(&base, &exponent, &modulus, &result);
|
||||
#endif
|
||||
if (mperr == MP_OKAY) {
|
||||
mperr = mp_to_fixlen_octets(&result, output, modulus_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
mp_clear(&base);
|
||||
mp_clear(&result);
|
||||
|
||||
mp_clear(&modulus);
|
||||
mp_clear(&exponent);
|
||||
|
||||
return (int)mperr;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
TimingContext * timeCtx;
|
||||
char * progName;
|
||||
long iters = DEFAULT_ITERS;
|
||||
unsigned int modulus_len;
|
||||
int i;
|
||||
int rv;
|
||||
unsigned char buf [1024];
|
||||
unsigned char buf2[1024];
|
||||
|
||||
progName = strrchr(argv[0], '/');
|
||||
if (!progName)
|
||||
progName = strrchr(argv[0], '\\');
|
||||
progName = progName ? progName+1 : argv[0];
|
||||
|
||||
if (argc >= 2) {
|
||||
iters = atol(argv[1]);
|
||||
}
|
||||
|
||||
if (argc >= 3) {
|
||||
modulus_len = atol(argv[2]);
|
||||
} else
|
||||
modulus_len = sizeof default_n;
|
||||
|
||||
/* no library init function !? */
|
||||
|
||||
memset(buf, 0x41, sizeof buf);
|
||||
|
||||
if (iters < 2) {
|
||||
testNewFuncs( default_n, modulus_len);
|
||||
testNewFuncs( default_n+1, modulus_len - 1);
|
||||
testNewFuncs( default_n+2, modulus_len - 2);
|
||||
testNewFuncs( default_n+3, modulus_len - 3);
|
||||
|
||||
printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies);
|
||||
rv = testModExp(default_n, 0, buf, buf2, modulus_len);
|
||||
dumpBytes((unsigned char *)buf2, modulus_len);
|
||||
|
||||
printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies);
|
||||
rv = testModExp(default_n, 1, buf, buf2, modulus_len);
|
||||
dumpBytes((unsigned char *)buf2, modulus_len);
|
||||
|
||||
printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies);
|
||||
rv = testModExp(default_n, 2, buf, buf2, modulus_len);
|
||||
dumpBytes((unsigned char *)buf2, modulus_len);
|
||||
|
||||
printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies);
|
||||
rv = testModExp(default_n, 3, buf, buf2, modulus_len);
|
||||
dumpBytes((unsigned char *)buf2, modulus_len);
|
||||
}
|
||||
printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies);
|
||||
rv = doModExp(default_n, default_d, buf, buf2, modulus_len);
|
||||
if (rv != 0) {
|
||||
fprintf(stderr, "Error in modexp operation:\n");
|
||||
exit(1);
|
||||
}
|
||||
dumpBytes((unsigned char *)buf2, modulus_len);
|
||||
printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies);
|
||||
|
||||
timeCtx = CreateTimingContext();
|
||||
TimingBegin(timeCtx);
|
||||
i = iters;
|
||||
while (i--) {
|
||||
rv = doModExp(default_n, default_d, buf, buf2, modulus_len);
|
||||
if (rv != 0) {
|
||||
fprintf(stderr, "Error in modexp operation\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
TimingEnd(timeCtx);
|
||||
printf("%ld iterations in %s\n", iters, TimingGenerateString(timeCtx));
|
||||
printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,329 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is SPARC optimized Montgomery multiply functions.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1999-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Netscape Communications Corporation
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: montmulf.c,v 1.7 2004-04-27 23:04:36 gerv%gerv.net Exp $ */
|
||||
|
||||
#ifdef SOLARIS
|
||||
#define RF_INLINE_MACROS 1
|
||||
#endif
|
||||
|
||||
static const double TwoTo16=65536.0;
|
||||
static const double TwoToMinus16=1.0/65536.0;
|
||||
static const double Zero=0.0;
|
||||
static const double TwoTo32=65536.0*65536.0;
|
||||
static const double TwoToMinus32=1.0/(65536.0*65536.0);
|
||||
|
||||
#ifdef RF_INLINE_MACROS
|
||||
|
||||
double upper32(double);
|
||||
double lower32(double, double);
|
||||
double mod(double, double, double);
|
||||
|
||||
void i16_to_d16_and_d32x4(const double * /*1/(2^16)*/,
|
||||
const double * /* 2^16*/,
|
||||
const double * /* 0 */,
|
||||
double * /*result16*/,
|
||||
double * /* result32 */,
|
||||
float * /*source - should be unsigned int*
|
||||
converted to float* */);
|
||||
|
||||
#else
|
||||
#ifdef MP_USE_FLOOR
|
||||
#include <math.h>
|
||||
#else
|
||||
#define floor(d) ((double)((unsigned long long)(d)))
|
||||
#endif
|
||||
|
||||
static double upper32(double x)
|
||||
{
|
||||
return floor(x*TwoToMinus32);
|
||||
}
|
||||
|
||||
static double lower32(double x, double y)
|
||||
{
|
||||
return x-TwoTo32*floor(x*TwoToMinus32);
|
||||
}
|
||||
|
||||
static double mod(double x, double oneoverm, double m)
|
||||
{
|
||||
return x-m*floor(x*oneoverm);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static void cleanup(double *dt, int from, int tlen)
|
||||
{
|
||||
int i;
|
||||
double tmp,tmp1,x,x1;
|
||||
|
||||
tmp=tmp1=Zero;
|
||||
/* original code **
|
||||
for(i=2*from;i<2*tlen-2;i++)
|
||||
{
|
||||
x=dt[i];
|
||||
dt[i]=lower32(x,Zero)+tmp1;
|
||||
tmp1=tmp;
|
||||
tmp=upper32(x);
|
||||
}
|
||||
dt[tlen-2]+=tmp1;
|
||||
dt[tlen-1]+=tmp;
|
||||
**end original code ***/
|
||||
/* new code ***/
|
||||
for(i=2*from;i<2*tlen;i+=2)
|
||||
{
|
||||
x=dt[i];
|
||||
x1=dt[i+1];
|
||||
dt[i]=lower32(x,Zero)+tmp;
|
||||
dt[i+1]=lower32(x1,Zero)+tmp1;
|
||||
tmp=upper32(x);
|
||||
tmp1=upper32(x1);
|
||||
}
|
||||
/** end new code **/
|
||||
}
|
||||
|
||||
|
||||
void conv_d16_to_i32(unsigned int *i32, double *d16, long long *tmp, int ilen)
|
||||
{
|
||||
int i;
|
||||
long long t, t1, a, b, c, d;
|
||||
|
||||
t1=0;
|
||||
a=(long long)d16[0];
|
||||
b=(long long)d16[1];
|
||||
for(i=0; i<ilen-1; i++)
|
||||
{
|
||||
c=(long long)d16[2*i+2];
|
||||
t1+=(unsigned int)a;
|
||||
t=(a>>32);
|
||||
d=(long long)d16[2*i+3];
|
||||
t1+=(b&0xffff)<<16;
|
||||
t+=(b>>16)+(t1>>32);
|
||||
i32[i]=(unsigned int)t1;
|
||||
t1=t;
|
||||
a=c;
|
||||
b=d;
|
||||
}
|
||||
t1+=(unsigned int)a;
|
||||
t=(a>>32);
|
||||
t1+=(b&0xffff)<<16;
|
||||
i32[i]=(unsigned int)t1;
|
||||
}
|
||||
|
||||
void conv_i32_to_d32(double *d32, unsigned int *i32, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
#pragma pipeloop(0)
|
||||
for(i=0;i<len;i++) d32[i]=(double)(i32[i]);
|
||||
}
|
||||
|
||||
|
||||
void conv_i32_to_d16(double *d16, unsigned int *i32, int len)
|
||||
{
|
||||
int i;
|
||||
unsigned int a;
|
||||
|
||||
#pragma pipeloop(0)
|
||||
for(i=0;i<len;i++)
|
||||
{
|
||||
a=i32[i];
|
||||
d16[2*i]=(double)(a&0xffff);
|
||||
d16[2*i+1]=(double)(a>>16);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void conv_i32_to_d32_and_d16(double *d32, double *d16,
|
||||
unsigned int *i32, int len)
|
||||
{
|
||||
int i = 0;
|
||||
unsigned int a;
|
||||
|
||||
#pragma pipeloop(0)
|
||||
#ifdef RF_INLINE_MACROS
|
||||
for(;i<len-3;i+=4)
|
||||
{
|
||||
i16_to_d16_and_d32x4(&TwoToMinus16, &TwoTo16, &Zero,
|
||||
&(d16[2*i]), &(d32[i]), (float *)(&(i32[i])));
|
||||
}
|
||||
#endif
|
||||
for(;i<len;i++)
|
||||
{
|
||||
a=i32[i];
|
||||
d32[i]=(double)(i32[i]);
|
||||
d16[2*i]=(double)(a&0xffff);
|
||||
d16[2*i+1]=(double)(a>>16);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void adjust_montf_result(unsigned int *i32, unsigned int *nint, int len)
|
||||
{
|
||||
long long acc;
|
||||
int i;
|
||||
|
||||
if(i32[len]>0) i=-1;
|
||||
else
|
||||
{
|
||||
for(i=len-1; i>=0; i--)
|
||||
{
|
||||
if(i32[i]!=nint[i]) break;
|
||||
}
|
||||
}
|
||||
if((i<0)||(i32[i]>nint[i]))
|
||||
{
|
||||
acc=0;
|
||||
for(i=0;i<len;i++)
|
||||
{
|
||||
acc=acc+(unsigned long long)(i32[i])-(unsigned long long)(nint[i]);
|
||||
i32[i]=(unsigned int)acc;
|
||||
acc=acc>>32;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** the lengths of the input arrays should be at least the following:
|
||||
** result[nlen+1], dm1[nlen], dm2[2*nlen+1], dt[4*nlen+2], dn[nlen], nint[nlen]
|
||||
** all of them should be different from one another
|
||||
**
|
||||
*/
|
||||
void mont_mulf_noconv(unsigned int *result,
|
||||
double *dm1, double *dm2, double *dt,
|
||||
double *dn, unsigned int *nint,
|
||||
int nlen, double dn0)
|
||||
{
|
||||
int i, j, jj;
|
||||
int tmp;
|
||||
double digit, m2j, nextm2j, a, b;
|
||||
double *dptmp, *pdm1, *pdm2, *pdn, *pdtj, pdn_0, pdm1_0;
|
||||
|
||||
pdm1=&(dm1[0]);
|
||||
pdm2=&(dm2[0]);
|
||||
pdn=&(dn[0]);
|
||||
pdm2[2*nlen]=Zero;
|
||||
|
||||
if (nlen!=16)
|
||||
{
|
||||
for(i=0;i<4*nlen+2;i++) dt[i]=Zero;
|
||||
|
||||
a=dt[0]=pdm1[0]*pdm2[0];
|
||||
digit=mod(lower32(a,Zero)*dn0,TwoToMinus16,TwoTo16);
|
||||
|
||||
pdtj=&(dt[0]);
|
||||
for(j=jj=0;j<2*nlen;j++,jj++,pdtj++)
|
||||
{
|
||||
m2j=pdm2[j];
|
||||
a=pdtj[0]+pdn[0]*digit;
|
||||
b=pdtj[1]+pdm1[0]*pdm2[j+1]+a*TwoToMinus16;
|
||||
pdtj[1]=b;
|
||||
|
||||
#pragma pipeloop(0)
|
||||
for(i=1;i<nlen;i++)
|
||||
{
|
||||
pdtj[2*i]+=pdm1[i]*m2j+pdn[i]*digit;
|
||||
}
|
||||
if((jj==30)) {cleanup(dt,j/2+1,2*nlen+1); jj=0;}
|
||||
|
||||
digit=mod(lower32(b,Zero)*dn0,TwoToMinus16,TwoTo16);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
a=dt[0]=pdm1[0]*pdm2[0];
|
||||
|
||||
dt[65]= dt[64]= dt[63]= dt[62]= dt[61]= dt[60]=
|
||||
dt[59]= dt[58]= dt[57]= dt[56]= dt[55]= dt[54]=
|
||||
dt[53]= dt[52]= dt[51]= dt[50]= dt[49]= dt[48]=
|
||||
dt[47]= dt[46]= dt[45]= dt[44]= dt[43]= dt[42]=
|
||||
dt[41]= dt[40]= dt[39]= dt[38]= dt[37]= dt[36]=
|
||||
dt[35]= dt[34]= dt[33]= dt[32]= dt[31]= dt[30]=
|
||||
dt[29]= dt[28]= dt[27]= dt[26]= dt[25]= dt[24]=
|
||||
dt[23]= dt[22]= dt[21]= dt[20]= dt[19]= dt[18]=
|
||||
dt[17]= dt[16]= dt[15]= dt[14]= dt[13]= dt[12]=
|
||||
dt[11]= dt[10]= dt[ 9]= dt[ 8]= dt[ 7]= dt[ 6]=
|
||||
dt[ 5]= dt[ 4]= dt[ 3]= dt[ 2]= dt[ 1]=Zero;
|
||||
|
||||
pdn_0=pdn[0];
|
||||
pdm1_0=pdm1[0];
|
||||
|
||||
digit=mod(lower32(a,Zero)*dn0,TwoToMinus16,TwoTo16);
|
||||
pdtj=&(dt[0]);
|
||||
|
||||
for(j=0;j<32;j++,pdtj++)
|
||||
{
|
||||
|
||||
m2j=pdm2[j];
|
||||
a=pdtj[0]+pdn_0*digit;
|
||||
b=pdtj[1]+pdm1_0*pdm2[j+1]+a*TwoToMinus16;
|
||||
pdtj[1]=b;
|
||||
|
||||
/**** this loop will be fully unrolled:
|
||||
for(i=1;i<16;i++)
|
||||
{
|
||||
pdtj[2*i]+=pdm1[i]*m2j+pdn[i]*digit;
|
||||
}
|
||||
*************************************/
|
||||
pdtj[2]+=pdm1[1]*m2j+pdn[1]*digit;
|
||||
pdtj[4]+=pdm1[2]*m2j+pdn[2]*digit;
|
||||
pdtj[6]+=pdm1[3]*m2j+pdn[3]*digit;
|
||||
pdtj[8]+=pdm1[4]*m2j+pdn[4]*digit;
|
||||
pdtj[10]+=pdm1[5]*m2j+pdn[5]*digit;
|
||||
pdtj[12]+=pdm1[6]*m2j+pdn[6]*digit;
|
||||
pdtj[14]+=pdm1[7]*m2j+pdn[7]*digit;
|
||||
pdtj[16]+=pdm1[8]*m2j+pdn[8]*digit;
|
||||
pdtj[18]+=pdm1[9]*m2j+pdn[9]*digit;
|
||||
pdtj[20]+=pdm1[10]*m2j+pdn[10]*digit;
|
||||
pdtj[22]+=pdm1[11]*m2j+pdn[11]*digit;
|
||||
pdtj[24]+=pdm1[12]*m2j+pdn[12]*digit;
|
||||
pdtj[26]+=pdm1[13]*m2j+pdn[13]*digit;
|
||||
pdtj[28]+=pdm1[14]*m2j+pdn[14]*digit;
|
||||
pdtj[30]+=pdm1[15]*m2j+pdn[15]*digit;
|
||||
/* no need for cleenup, cannot overflow */
|
||||
digit=mod(lower32(b,Zero)*dn0,TwoToMinus16,TwoTo16);
|
||||
}
|
||||
}
|
||||
|
||||
conv_d16_to_i32(result,dt+2*nlen,(long long *)dt,nlen+1);
|
||||
|
||||
adjust_montf_result(result,nint,nlen);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is interface file for SPARC Montgomery multiply functions.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1999-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Netscape Communications Corporation
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: montmulf.h,v 1.4 2004-04-27 23:04:36 gerv%gerv.net Exp $ */
|
||||
|
||||
/* The functions that are to be called from outside of the .s file have the
|
||||
* following interfaces and array size requirements:
|
||||
*/
|
||||
|
||||
|
||||
void conv_i32_to_d32(double *d32, unsigned int *i32, int len);
|
||||
|
||||
/* Converts an array of int's to an array of doubles, so that each double
|
||||
* corresponds to an int. len is the number of items converted.
|
||||
* Does not allocate the output array.
|
||||
* The pointers d32 and i32 should point to arrays of size at least len
|
||||
* (doubles and unsigned ints, respectively)
|
||||
*/
|
||||
|
||||
|
||||
void conv_i32_to_d16(double *d16, unsigned int *i32, int len);
|
||||
|
||||
/* Converts an array of int's to an array of doubles so that each element
|
||||
* of the int array is converted to a pair of doubles, the first one
|
||||
* corresponding to the lower (least significant) 16 bits of the int and
|
||||
* the second one corresponding to the upper (most significant) 16 bits of
|
||||
* the 32-bit int. len is the number of ints converted.
|
||||
* Does not allocate the output array.
|
||||
* The pointer d16 should point to an array of doubles of size at least
|
||||
* 2*len and i32 should point an array of ints of size at least len
|
||||
*/
|
||||
|
||||
|
||||
void conv_i32_to_d32_and_d16(double *d32, double *d16,
|
||||
unsigned int *i32, int len);
|
||||
|
||||
/* Does the above two conversions together, it is much faster than doing
|
||||
* both of those in succession
|
||||
*/
|
||||
|
||||
|
||||
void mont_mulf_noconv(unsigned int *result,
|
||||
double *dm1, double *dm2, double *dt,
|
||||
double *dn, unsigned int *nint,
|
||||
int nlen, double dn0);
|
||||
|
||||
/* Does the Montgomery multiplication of the numbers stored in the arrays
|
||||
* pointed to by dm1 and dm2, writing the result to the array pointed to by
|
||||
* result. It uses the array pointed to by dt as a temporary work area.
|
||||
* nint should point to the modulus in the array-of-integers representation,
|
||||
* dn should point to its array-of-doubles as obtained as a result of the
|
||||
* function call conv_i32_to_d32(dn, nint, nlen);
|
||||
* nlen is the length of the array containing the modulus.
|
||||
* The representation used for dm1 is the one that is a result of the function
|
||||
* call conv_i32_to_d32(dm1, m1, nlen), the representation for dm2 is the
|
||||
* result of the function call conv_i32_to_d16(dm2, m2, nlen).
|
||||
* Note that m1 and m2 should both be of length nlen, so they should be
|
||||
* padded with 0's if necessary before the conversion. The result comes in
|
||||
* this form (int representation, padded with 0's).
|
||||
* dn0 is the value of the 16 least significant bits of n0'.
|
||||
* The function does not allocate memory for any of the arrays, so the
|
||||
* pointers should point to arrays with the following minimal sizes:
|
||||
* result - nlen+1
|
||||
* dm1 - nlen
|
||||
* dm2 - 2*nlen+1 ( the +1 is necessary for technical reasons )
|
||||
* dt - 4*nlen+2
|
||||
* dn - nlen
|
||||
* nint - nlen
|
||||
* No two arrays should point to overlapping areas of memory.
|
||||
*/
|
||||
@@ -1,141 +0,0 @@
|
||||
!
|
||||
! ***** BEGIN LICENSE BLOCK *****
|
||||
! Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
!
|
||||
! The contents of this file are subject to the Mozilla Public License Version
|
||||
! 1.1 (the "License"); you may not use this file except in compliance with
|
||||
! the License. You may obtain a copy of the License at
|
||||
! http://www.mozilla.org/MPL/
|
||||
!
|
||||
! Software distributed under the License is distributed on an "AS IS" basis,
|
||||
! WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
! for the specific language governing rights and limitations under the
|
||||
! License.
|
||||
!
|
||||
! The Original Code is inline macros for SPARC Montgomery multiply functions.
|
||||
!
|
||||
! The Initial Developer of the Original Code is
|
||||
! Sun Microsystems Inc.
|
||||
! Portions created by the Initial Developer are Copyright (C) 1999-2000
|
||||
! the Initial Developer. All Rights Reserved.
|
||||
!
|
||||
! Contributor(s):
|
||||
!
|
||||
! Alternatively, the contents of this file may be used under the terms of
|
||||
! either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
! the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
! in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
! of those above. If you wish to allow use of your version of this file only
|
||||
! under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
! use your version of this file under the terms of the MPL, indicate your
|
||||
! decision by deleting the provisions above and replace them with the notice
|
||||
! and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
! the provisions above, a recipient may use your version of this file under
|
||||
! the terms of any one of the MPL, the GPL or the LGPL.
|
||||
!
|
||||
! ***** END LICENSE BLOCK *****
|
||||
! $Id: montmulf.il,v 1.4 2004-04-27 23:04:36 gerv%gerv.net Exp $
|
||||
|
||||
!
|
||||
! double upper32(double /*frs1*/);
|
||||
!
|
||||
.inline upper32,8
|
||||
std %o0,[%sp+0x48]
|
||||
ldd [%sp+0x48],%f10
|
||||
|
||||
fdtox %f10,%f10
|
||||
fitod %f10,%f0
|
||||
.end
|
||||
|
||||
!
|
||||
! double lower32(double /*frs1*/, double /* Zero */);
|
||||
!
|
||||
.inline lower32,8
|
||||
std %o0,[%sp+0x48]
|
||||
ldd [%sp+0x48],%f10
|
||||
std %o2,[%sp+0x48]
|
||||
ldd [%sp+0x48],%f12
|
||||
|
||||
fdtox %f10,%f10
|
||||
fmovs %f12,%f10
|
||||
fxtod %f10,%f0
|
||||
.end
|
||||
|
||||
!
|
||||
! double mod(double /*x*/, double /*1/m*/, double /*m*/);
|
||||
!
|
||||
.inline mod,12
|
||||
std %o0,[%sp+0x48]
|
||||
ldd [%sp+0x48],%f2
|
||||
std %o2,[%sp+0x48]
|
||||
ldd [%sp+0x48],%f4
|
||||
std %o4,[%sp+0x48]
|
||||
ldd [%sp+0x48],%f6
|
||||
|
||||
fmuld %f2,%f4,%f4
|
||||
fdtox %f4,%f4
|
||||
fxtod %f4,%f4
|
||||
fmuld %f4,%f6,%f4
|
||||
fsubd %f2,%f4,%f0
|
||||
.end
|
||||
|
||||
|
||||
!
|
||||
! void i16_to_d16_and_d32x4(double * /*1/(2^16)*/, double * /* 2^16*/,
|
||||
! double * /* 0 */,
|
||||
! double * /*result16*/, double * /* result32 */
|
||||
! float * /*source - should be unsigned int*
|
||||
! converted to float* */);
|
||||
!
|
||||
.inline i16_to_d16_and_d32x4,24
|
||||
ldd [%o0],%f2 ! 1/(2^16)
|
||||
ldd [%o1],%f4 ! 2^16
|
||||
ldd [%o2],%f22
|
||||
|
||||
fmovd %f22,%f6
|
||||
ld [%o5],%f7
|
||||
fmovd %f22,%f10
|
||||
ld [%o5+4],%f11
|
||||
fmovd %f22,%f14
|
||||
ld [%o5+8],%f15
|
||||
fmovd %f22,%f18
|
||||
ld [%o5+12],%f19
|
||||
fxtod %f6,%f6
|
||||
std %f6,[%o4]
|
||||
fxtod %f10,%f10
|
||||
std %f10,[%o4+8]
|
||||
fxtod %f14,%f14
|
||||
std %f14,[%o4+16]
|
||||
fxtod %f18,%f18
|
||||
std %f18,[%o4+24]
|
||||
fmuld %f2,%f6,%f8
|
||||
fmuld %f2,%f10,%f12
|
||||
fmuld %f2,%f14,%f16
|
||||
fmuld %f2,%f18,%f20
|
||||
fdtox %f8,%f8
|
||||
fdtox %f12,%f12
|
||||
fdtox %f16,%f16
|
||||
fdtox %f20,%f20
|
||||
fxtod %f8,%f8
|
||||
std %f8,[%o3+8]
|
||||
fxtod %f12,%f12
|
||||
std %f12,[%o3+24]
|
||||
fxtod %f16,%f16
|
||||
std %f16,[%o3+40]
|
||||
fxtod %f20,%f20
|
||||
std %f20,[%o3+56]
|
||||
fmuld %f8,%f4,%f8
|
||||
fmuld %f12,%f4,%f12
|
||||
fmuld %f16,%f4,%f16
|
||||
fmuld %f20,%f4,%f20
|
||||
fsubd %f6,%f8,%f8
|
||||
std %f8,[%o3]
|
||||
fsubd %f10,%f12,%f12
|
||||
std %f12,[%o3+16]
|
||||
fsubd %f14,%f16,%f16
|
||||
std %f16,[%o3+32]
|
||||
fsubd %f18,%f20,%f20
|
||||
std %f20,[%o3+48]
|
||||
.end
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,141 +0,0 @@
|
||||
!
|
||||
! ***** BEGIN LICENSE BLOCK *****
|
||||
! Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
!
|
||||
! The contents of this file are subject to the Mozilla Public License Version
|
||||
! 1.1 (the "License"); you may not use this file except in compliance with
|
||||
! the License. You may obtain a copy of the License at
|
||||
! http://www.mozilla.org/MPL/
|
||||
!
|
||||
! Software distributed under the License is distributed on an "AS IS" basis,
|
||||
! WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
! for the specific language governing rights and limitations under the
|
||||
! License.
|
||||
!
|
||||
! The Original Code is inline macros for SPARC Montgomery multiply functions.
|
||||
!
|
||||
! The Initial Developer of the Original Code is
|
||||
! Sun Microsystems Inc.
|
||||
! Portions created by the Initial Developer are Copyright (C) 1999-2000
|
||||
! the Initial Developer. All Rights Reserved.
|
||||
!
|
||||
! Contributor(s):
|
||||
!
|
||||
! Alternatively, the contents of this file may be used under the terms of
|
||||
! either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
! the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
! in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
! of those above. If you wish to allow use of your version of this file only
|
||||
! under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
! use your version of this file under the terms of the MPL, indicate your
|
||||
! decision by deleting the provisions above and replace them with the notice
|
||||
! and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
! the provisions above, a recipient may use your version of this file under
|
||||
! the terms of any one of the MPL, the GPL or the LGPL.
|
||||
!
|
||||
! ***** END LICENSE BLOCK *****
|
||||
! $Id: montmulfv8.il,v 1.3 2004-04-27 23:04:36 gerv%gerv.net Exp $
|
||||
|
||||
!
|
||||
! double upper32(double /*frs1*/);
|
||||
!
|
||||
.inline upper32,8
|
||||
std %o0,[%sp+0x48]
|
||||
ldd [%sp+0x48],%f10
|
||||
|
||||
fdtox %f10,%f10
|
||||
fitod %f10,%f0
|
||||
.end
|
||||
|
||||
!
|
||||
! double lower32(double /*frs1*/, double /* Zero */);
|
||||
!
|
||||
.inline lower32,8
|
||||
std %o0,[%sp+0x48]
|
||||
ldd [%sp+0x48],%f10
|
||||
std %o2,[%sp+0x48]
|
||||
ldd [%sp+0x48],%f12
|
||||
|
||||
fdtox %f10,%f10
|
||||
fmovs %f12,%f10
|
||||
fxtod %f10,%f0
|
||||
.end
|
||||
|
||||
!
|
||||
! double mod(double /*x*/, double /*1/m*/, double /*m*/);
|
||||
!
|
||||
.inline mod,12
|
||||
std %o0,[%sp+0x48]
|
||||
ldd [%sp+0x48],%f2
|
||||
std %o2,[%sp+0x48]
|
||||
ldd [%sp+0x48],%f4
|
||||
std %o4,[%sp+0x48]
|
||||
ldd [%sp+0x48],%f6
|
||||
|
||||
fmuld %f2,%f4,%f4
|
||||
fdtox %f4,%f4
|
||||
fxtod %f4,%f4
|
||||
fmuld %f4,%f6,%f4
|
||||
fsubd %f2,%f4,%f0
|
||||
.end
|
||||
|
||||
|
||||
!
|
||||
! void i16_to_d16_and_d32x4(double * /*1/(2^16)*/, double * /* 2^16*/,
|
||||
! double * /* 0 */,
|
||||
! double * /*result16*/, double * /* result32 */
|
||||
! float * /*source - should be unsigned int*
|
||||
! converted to float* */);
|
||||
!
|
||||
.inline i16_to_d16_and_d32x4,24
|
||||
ldd [%o0],%f2 ! 1/(2^16)
|
||||
ldd [%o1],%f4 ! 2^16
|
||||
ldd [%o2],%f22
|
||||
|
||||
fmovd %f22,%f6
|
||||
ld [%o5],%f7
|
||||
fmovd %f22,%f10
|
||||
ld [%o5+4],%f11
|
||||
fmovd %f22,%f14
|
||||
ld [%o5+8],%f15
|
||||
fmovd %f22,%f18
|
||||
ld [%o5+12],%f19
|
||||
fxtod %f6,%f6
|
||||
std %f6,[%o4]
|
||||
fxtod %f10,%f10
|
||||
std %f10,[%o4+8]
|
||||
fxtod %f14,%f14
|
||||
std %f14,[%o4+16]
|
||||
fxtod %f18,%f18
|
||||
std %f18,[%o4+24]
|
||||
fmuld %f2,%f6,%f8
|
||||
fmuld %f2,%f10,%f12
|
||||
fmuld %f2,%f14,%f16
|
||||
fmuld %f2,%f18,%f20
|
||||
fdtox %f8,%f8
|
||||
fdtox %f12,%f12
|
||||
fdtox %f16,%f16
|
||||
fdtox %f20,%f20
|
||||
fxtod %f8,%f8
|
||||
std %f8,[%o3+8]
|
||||
fxtod %f12,%f12
|
||||
std %f12,[%o3+24]
|
||||
fxtod %f16,%f16
|
||||
std %f16,[%o3+40]
|
||||
fxtod %f20,%f20
|
||||
std %f20,[%o3+56]
|
||||
fmuld %f8,%f4,%f8
|
||||
fmuld %f12,%f4,%f12
|
||||
fmuld %f16,%f4,%f16
|
||||
fmuld %f20,%f4,%f20
|
||||
fsubd %f6,%f8,%f8
|
||||
std %f8,[%o3]
|
||||
fsubd %f10,%f12,%f12
|
||||
std %f12,[%o3+16]
|
||||
fsubd %f14,%f16,%f16
|
||||
std %f16,[%o3+32]
|
||||
fsubd %f18,%f20,%f20
|
||||
std %f20,[%o3+48]
|
||||
.end
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,126 +0,0 @@
|
||||
!
|
||||
! ***** BEGIN LICENSE BLOCK *****
|
||||
! Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
!
|
||||
! The contents of this file are subject to the Mozilla Public License Version
|
||||
! 1.1 (the "License"); you may not use this file except in compliance with
|
||||
! the License. You may obtain a copy of the License at
|
||||
! http://www.mozilla.org/MPL/
|
||||
!
|
||||
! Software distributed under the License is distributed on an "AS IS" basis,
|
||||
! WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
! for the specific language governing rights and limitations under the
|
||||
! License.
|
||||
!
|
||||
! The Original Code is inline macros for SPARC Montgomery multiply functions.
|
||||
!
|
||||
! The Initial Developer of the Original Code is
|
||||
! Sun Microsystems Inc.
|
||||
! Portions created by the Initial Developer are Copyright (C) 1999-2000
|
||||
! the Initial Developer. All Rights Reserved.
|
||||
!
|
||||
! Contributor(s):
|
||||
!
|
||||
! Alternatively, the contents of this file may be used under the terms of
|
||||
! either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
! the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
! in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
! of those above. If you wish to allow use of your version of this file only
|
||||
! under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
! use your version of this file under the terms of the MPL, indicate your
|
||||
! decision by deleting the provisions above and replace them with the notice
|
||||
! and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
! the provisions above, a recipient may use your version of this file under
|
||||
! the terms of any one of the MPL, the GPL or the LGPL.
|
||||
!
|
||||
! ***** END LICENSE BLOCK *****
|
||||
! $Id: montmulfv9.il,v 1.3 2004-04-27 23:04:36 gerv%gerv.net Exp $
|
||||
|
||||
!
|
||||
! double upper32(double /*frs1*/);
|
||||
!
|
||||
.inline upper32,8
|
||||
fdtox %f0,%f10
|
||||
fitod %f10,%f0
|
||||
.end
|
||||
|
||||
!
|
||||
! double lower32(double /*frs1*/, double /* Zero */);
|
||||
!
|
||||
.inline lower32,8
|
||||
fdtox %f0,%f10
|
||||
fmovs %f2,%f10
|
||||
fxtod %f10,%f0
|
||||
.end
|
||||
|
||||
!
|
||||
! double mod(double /*x*/, double /*1/m*/, double /*m*/);
|
||||
!
|
||||
.inline mod,12
|
||||
fmuld %f0,%f2,%f2
|
||||
fdtox %f2,%f2
|
||||
fxtod %f2,%f2
|
||||
fmuld %f2,%f4,%f2
|
||||
fsubd %f0,%f2,%f0
|
||||
.end
|
||||
|
||||
|
||||
!
|
||||
! void i16_to_d16_and_d32x4(double * /*1/(2^16)*/, double * /* 2^16*/,
|
||||
! double * /* 0 */,
|
||||
! double * /*result16*/, double * /* result32 */
|
||||
! float * /*source - should be unsigned int*
|
||||
! converted to float* */);
|
||||
!
|
||||
.inline i16_to_d16_and_d32x4,24
|
||||
ldd [%o0],%f2 ! 1/(2^16)
|
||||
ldd [%o1],%f4 ! 2^16
|
||||
ldd [%o2],%f22
|
||||
|
||||
fmovd %f22,%f6
|
||||
ld [%o5],%f7
|
||||
fmovd %f22,%f10
|
||||
ld [%o5+4],%f11
|
||||
fmovd %f22,%f14
|
||||
ld [%o5+8],%f15
|
||||
fmovd %f22,%f18
|
||||
ld [%o5+12],%f19
|
||||
fxtod %f6,%f6
|
||||
std %f6,[%o4]
|
||||
fxtod %f10,%f10
|
||||
std %f10,[%o4+8]
|
||||
fxtod %f14,%f14
|
||||
std %f14,[%o4+16]
|
||||
fxtod %f18,%f18
|
||||
std %f18,[%o4+24]
|
||||
fmuld %f2,%f6,%f8
|
||||
fmuld %f2,%f10,%f12
|
||||
fmuld %f2,%f14,%f16
|
||||
fmuld %f2,%f18,%f20
|
||||
fdtox %f8,%f8
|
||||
fdtox %f12,%f12
|
||||
fdtox %f16,%f16
|
||||
fdtox %f20,%f20
|
||||
fxtod %f8,%f8
|
||||
std %f8,[%o3+8]
|
||||
fxtod %f12,%f12
|
||||
std %f12,[%o3+24]
|
||||
fxtod %f16,%f16
|
||||
std %f16,[%o3+40]
|
||||
fxtod %f20,%f20
|
||||
std %f20,[%o3+56]
|
||||
fmuld %f8,%f4,%f8
|
||||
fmuld %f12,%f4,%f12
|
||||
fmuld %f16,%f4,%f16
|
||||
fmuld %f20,%f4,%f20
|
||||
fsubd %f6,%f8,%f8
|
||||
std %f8,[%o3]
|
||||
fsubd %f10,%f12,%f12
|
||||
std %f12,[%o3+16]
|
||||
fsubd %f14,%f16,%f16
|
||||
std %f16,[%o3+32]
|
||||
fsubd %f18,%f20,%f20
|
||||
std %f20,[%o3+48]
|
||||
.end
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,102 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Multi-precision Binary Polynomial Arithmetic Library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sheueling Chang Shantz <sheueling.chang@sun.com> and
|
||||
* Douglas Stebila <douglas@stebila.ca> of Sun Laboratories.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _MP_GF2M_PRIV_H_
|
||||
#define _MP_GF2M_PRIV_H_
|
||||
|
||||
#include "mpi-priv.h"
|
||||
|
||||
extern const mp_digit mp_gf2m_sqr_tb[16];
|
||||
|
||||
#if defined(MP_USE_UINT_DIGIT)
|
||||
#define MP_DIGIT_BITS 32
|
||||
#else
|
||||
#define MP_DIGIT_BITS 64
|
||||
#endif
|
||||
|
||||
/* Platform-specific macros for fast binary polynomial squaring. */
|
||||
#if MP_DIGIT_BITS == 32
|
||||
#define gf2m_SQR1(w) \
|
||||
mp_gf2m_sqr_tb[(w) >> 28 & 0xF] << 24 | mp_gf2m_sqr_tb[(w) >> 24 & 0xF] << 16 | \
|
||||
mp_gf2m_sqr_tb[(w) >> 20 & 0xF] << 8 | mp_gf2m_sqr_tb[(w) >> 16 & 0xF]
|
||||
#define gf2m_SQR0(w) \
|
||||
mp_gf2m_sqr_tb[(w) >> 12 & 0xF] << 24 | mp_gf2m_sqr_tb[(w) >> 8 & 0xF] << 16 | \
|
||||
mp_gf2m_sqr_tb[(w) >> 4 & 0xF] << 8 | mp_gf2m_sqr_tb[(w) & 0xF]
|
||||
#else
|
||||
#define gf2m_SQR1(w) \
|
||||
mp_gf2m_sqr_tb[(w) >> 60 & 0xF] << 56 | mp_gf2m_sqr_tb[(w) >> 56 & 0xF] << 48 | \
|
||||
mp_gf2m_sqr_tb[(w) >> 52 & 0xF] << 40 | mp_gf2m_sqr_tb[(w) >> 48 & 0xF] << 32 | \
|
||||
mp_gf2m_sqr_tb[(w) >> 44 & 0xF] << 24 | mp_gf2m_sqr_tb[(w) >> 40 & 0xF] << 16 | \
|
||||
mp_gf2m_sqr_tb[(w) >> 36 & 0xF] << 8 | mp_gf2m_sqr_tb[(w) >> 32 & 0xF]
|
||||
#define gf2m_SQR0(w) \
|
||||
mp_gf2m_sqr_tb[(w) >> 28 & 0xF] << 56 | mp_gf2m_sqr_tb[(w) >> 24 & 0xF] << 48 | \
|
||||
mp_gf2m_sqr_tb[(w) >> 20 & 0xF] << 40 | mp_gf2m_sqr_tb[(w) >> 16 & 0xF] << 32 | \
|
||||
mp_gf2m_sqr_tb[(w) >> 12 & 0xF] << 24 | mp_gf2m_sqr_tb[(w) >> 8 & 0xF] << 16 | \
|
||||
mp_gf2m_sqr_tb[(w) >> 4 & 0xF] << 8 | mp_gf2m_sqr_tb[(w) & 0xF]
|
||||
#endif
|
||||
|
||||
/* Multiply two binary polynomials mp_digits a, b.
|
||||
* Result is a polynomial with degree < 2 * MP_DIGIT_BITS - 1.
|
||||
* Output in two mp_digits rh, rl.
|
||||
*/
|
||||
void s_bmul_1x1(mp_digit *rh, mp_digit *rl, const mp_digit a, const mp_digit b);
|
||||
|
||||
/* Compute xor-multiply of two binary polynomials (a1, a0) x (b1, b0)
|
||||
* result is a binary polynomial in 4 mp_digits r[4].
|
||||
* The caller MUST ensure that r has the right amount of space allocated.
|
||||
*/
|
||||
void s_bmul_2x2(mp_digit *r, const mp_digit a1, const mp_digit a0, const mp_digit b1,
|
||||
const mp_digit b0);
|
||||
|
||||
/* Compute xor-multiply of two binary polynomials (a2, a1, a0) x (b2, b1, b0)
|
||||
* result is a binary polynomial in 6 mp_digits r[6].
|
||||
* The caller MUST ensure that r has the right amount of space allocated.
|
||||
*/
|
||||
void s_bmul_3x3(mp_digit *r, const mp_digit a2, const mp_digit a1, const mp_digit a0,
|
||||
const mp_digit b2, const mp_digit b1, const mp_digit b0);
|
||||
|
||||
/* Compute xor-multiply of two binary polynomials (a3, a2, a1, a0) x (b3, b2, b1, b0)
|
||||
* result is a binary polynomial in 8 mp_digits r[8].
|
||||
* The caller MUST ensure that r has the right amount of space allocated.
|
||||
*/
|
||||
void s_bmul_4x4(mp_digit *r, const mp_digit a3, const mp_digit a2, const mp_digit a1,
|
||||
const mp_digit a0, const mp_digit b3, const mp_digit b2, const mp_digit b1,
|
||||
const mp_digit b0);
|
||||
|
||||
#endif /* _MP_GF2M_PRIV_H_ */
|
||||
@@ -1,600 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Multi-precision Binary Polynomial Arithmetic Library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sheueling Chang Shantz <sheueling.chang@sun.com> and
|
||||
* Douglas Stebila <douglas@stebila.ca> of Sun Laboratories.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "mp_gf2m.h"
|
||||
#include "mp_gf2m-priv.h"
|
||||
#include "mplogic.h"
|
||||
#include "mpi-priv.h"
|
||||
|
||||
const mp_digit mp_gf2m_sqr_tb[16] =
|
||||
{
|
||||
0, 1, 4, 5, 16, 17, 20, 21,
|
||||
64, 65, 68, 69, 80, 81, 84, 85
|
||||
};
|
||||
|
||||
/* Multiply two binary polynomials mp_digits a, b.
|
||||
* Result is a polynomial with degree < 2 * MP_DIGIT_BITS - 1.
|
||||
* Output in two mp_digits rh, rl.
|
||||
*/
|
||||
#if MP_DIGIT_BITS == 32
|
||||
void
|
||||
s_bmul_1x1(mp_digit *rh, mp_digit *rl, const mp_digit a, const mp_digit b)
|
||||
{
|
||||
register mp_digit h, l, s;
|
||||
mp_digit tab[8], top2b = a >> 30;
|
||||
register mp_digit a1, a2, a4;
|
||||
|
||||
a1 = a & (0x3FFFFFFF); a2 = a1 << 1; a4 = a2 << 1;
|
||||
|
||||
tab[0] = 0; tab[1] = a1; tab[2] = a2; tab[3] = a1^a2;
|
||||
tab[4] = a4; tab[5] = a1^a4; tab[6] = a2^a4; tab[7] = a1^a2^a4;
|
||||
|
||||
s = tab[b & 0x7]; l = s;
|
||||
s = tab[b >> 3 & 0x7]; l ^= s << 3; h = s >> 29;
|
||||
s = tab[b >> 6 & 0x7]; l ^= s << 6; h ^= s >> 26;
|
||||
s = tab[b >> 9 & 0x7]; l ^= s << 9; h ^= s >> 23;
|
||||
s = tab[b >> 12 & 0x7]; l ^= s << 12; h ^= s >> 20;
|
||||
s = tab[b >> 15 & 0x7]; l ^= s << 15; h ^= s >> 17;
|
||||
s = tab[b >> 18 & 0x7]; l ^= s << 18; h ^= s >> 14;
|
||||
s = tab[b >> 21 & 0x7]; l ^= s << 21; h ^= s >> 11;
|
||||
s = tab[b >> 24 & 0x7]; l ^= s << 24; h ^= s >> 8;
|
||||
s = tab[b >> 27 & 0x7]; l ^= s << 27; h ^= s >> 5;
|
||||
s = tab[b >> 30 ]; l ^= s << 30; h ^= s >> 2;
|
||||
|
||||
/* compensate for the top two bits of a */
|
||||
|
||||
if (top2b & 01) { l ^= b << 30; h ^= b >> 2; }
|
||||
if (top2b & 02) { l ^= b << 31; h ^= b >> 1; }
|
||||
|
||||
*rh = h; *rl = l;
|
||||
}
|
||||
#else
|
||||
void
|
||||
s_bmul_1x1(mp_digit *rh, mp_digit *rl, const mp_digit a, const mp_digit b)
|
||||
{
|
||||
register mp_digit h, l, s;
|
||||
mp_digit tab[16], top3b = a >> 61;
|
||||
register mp_digit a1, a2, a4, a8;
|
||||
|
||||
a1 = a & (0x1FFFFFFFFFFFFFFF); a2 = a1 << 1;
|
||||
a4 = a2 << 1; a8 = a4 << 1;
|
||||
tab[ 0] = 0; tab[ 1] = a1; tab[ 2] = a2; tab[ 3] = a1^a2;
|
||||
tab[ 4] = a4; tab[ 5] = a1^a4; tab[ 6] = a2^a4; tab[ 7] = a1^a2^a4;
|
||||
tab[ 8] = a8; tab[ 9] = a1^a8; tab[10] = a2^a8; tab[11] = a1^a2^a8;
|
||||
tab[12] = a4^a8; tab[13] = a1^a4^a8; tab[14] = a2^a4^a8; tab[15] = a1^a2^a4^a8;
|
||||
|
||||
s = tab[b & 0xF]; l = s;
|
||||
s = tab[b >> 4 & 0xF]; l ^= s << 4; h = s >> 60;
|
||||
s = tab[b >> 8 & 0xF]; l ^= s << 8; h ^= s >> 56;
|
||||
s = tab[b >> 12 & 0xF]; l ^= s << 12; h ^= s >> 52;
|
||||
s = tab[b >> 16 & 0xF]; l ^= s << 16; h ^= s >> 48;
|
||||
s = tab[b >> 20 & 0xF]; l ^= s << 20; h ^= s >> 44;
|
||||
s = tab[b >> 24 & 0xF]; l ^= s << 24; h ^= s >> 40;
|
||||
s = tab[b >> 28 & 0xF]; l ^= s << 28; h ^= s >> 36;
|
||||
s = tab[b >> 32 & 0xF]; l ^= s << 32; h ^= s >> 32;
|
||||
s = tab[b >> 36 & 0xF]; l ^= s << 36; h ^= s >> 28;
|
||||
s = tab[b >> 40 & 0xF]; l ^= s << 40; h ^= s >> 24;
|
||||
s = tab[b >> 44 & 0xF]; l ^= s << 44; h ^= s >> 20;
|
||||
s = tab[b >> 48 & 0xF]; l ^= s << 48; h ^= s >> 16;
|
||||
s = tab[b >> 52 & 0xF]; l ^= s << 52; h ^= s >> 12;
|
||||
s = tab[b >> 56 & 0xF]; l ^= s << 56; h ^= s >> 8;
|
||||
s = tab[b >> 60 ]; l ^= s << 60; h ^= s >> 4;
|
||||
|
||||
/* compensate for the top three bits of a */
|
||||
|
||||
if (top3b & 01) { l ^= b << 61; h ^= b >> 3; }
|
||||
if (top3b & 02) { l ^= b << 62; h ^= b >> 2; }
|
||||
if (top3b & 04) { l ^= b << 63; h ^= b >> 1; }
|
||||
|
||||
*rh = h; *rl = l;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Compute xor-multiply of two binary polynomials (a1, a0) x (b1, b0)
|
||||
* result is a binary polynomial in 4 mp_digits r[4].
|
||||
* The caller MUST ensure that r has the right amount of space allocated.
|
||||
*/
|
||||
void
|
||||
s_bmul_2x2(mp_digit *r, const mp_digit a1, const mp_digit a0, const mp_digit b1,
|
||||
const mp_digit b0)
|
||||
{
|
||||
mp_digit m1, m0;
|
||||
/* r[3] = h1, r[2] = h0; r[1] = l1; r[0] = l0 */
|
||||
s_bmul_1x1(r+3, r+2, a1, b1);
|
||||
s_bmul_1x1(r+1, r, a0, b0);
|
||||
s_bmul_1x1(&m1, &m0, a0 ^ a1, b0 ^ b1);
|
||||
/* Correction on m1 ^= l1 ^ h1; m0 ^= l0 ^ h0; */
|
||||
r[2] ^= m1 ^ r[1] ^ r[3]; /* h0 ^= m1 ^ l1 ^ h1; */
|
||||
r[1] = r[3] ^ r[2] ^ r[0] ^ m1 ^ m0; /* l1 ^= l0 ^ h0 ^ m0; */
|
||||
}
|
||||
|
||||
/* Compute xor-multiply of two binary polynomials (a2, a1, a0) x (b2, b1, b0)
|
||||
* result is a binary polynomial in 6 mp_digits r[6].
|
||||
* The caller MUST ensure that r has the right amount of space allocated.
|
||||
*/
|
||||
void
|
||||
s_bmul_3x3(mp_digit *r, const mp_digit a2, const mp_digit a1, const mp_digit a0,
|
||||
const mp_digit b2, const mp_digit b1, const mp_digit b0)
|
||||
{
|
||||
mp_digit zm[4];
|
||||
|
||||
s_bmul_1x1(r+5, r+4, a2, b2); /* fill top 2 words */
|
||||
s_bmul_2x2(zm, a1, a2^a0, b1, b2^b0); /* fill middle 4 words */
|
||||
s_bmul_2x2(r, a1, a0, b1, b0); /* fill bottom 4 words */
|
||||
|
||||
zm[3] ^= r[3];
|
||||
zm[2] ^= r[2];
|
||||
zm[1] ^= r[1] ^ r[5];
|
||||
zm[0] ^= r[0] ^ r[4];
|
||||
|
||||
r[5] ^= zm[3];
|
||||
r[4] ^= zm[2];
|
||||
r[3] ^= zm[1];
|
||||
r[2] ^= zm[0];
|
||||
}
|
||||
|
||||
/* Compute xor-multiply of two binary polynomials (a3, a2, a1, a0) x (b3, b2, b1, b0)
|
||||
* result is a binary polynomial in 8 mp_digits r[8].
|
||||
* The caller MUST ensure that r has the right amount of space allocated.
|
||||
*/
|
||||
void s_bmul_4x4(mp_digit *r, const mp_digit a3, const mp_digit a2, const mp_digit a1,
|
||||
const mp_digit a0, const mp_digit b3, const mp_digit b2, const mp_digit b1,
|
||||
const mp_digit b0)
|
||||
{
|
||||
mp_digit zm[4];
|
||||
|
||||
s_bmul_2x2(r+4, a3, a2, b3, b2); /* fill top 4 words */
|
||||
s_bmul_2x2(zm, a3^a1, a2^a0, b3^b1, b2^b0); /* fill middle 4 words */
|
||||
s_bmul_2x2(r, a1, a0, b1, b0); /* fill bottom 4 words */
|
||||
|
||||
zm[3] ^= r[3] ^ r[7];
|
||||
zm[2] ^= r[2] ^ r[6];
|
||||
zm[1] ^= r[1] ^ r[5];
|
||||
zm[0] ^= r[0] ^ r[4];
|
||||
|
||||
r[5] ^= zm[3];
|
||||
r[4] ^= zm[2];
|
||||
r[3] ^= zm[1];
|
||||
r[2] ^= zm[0];
|
||||
}
|
||||
|
||||
/* Compute addition of two binary polynomials a and b,
|
||||
* store result in c; c could be a or b, a and b could be equal;
|
||||
* c is the bitwise XOR of a and b.
|
||||
*/
|
||||
mp_err
|
||||
mp_badd(const mp_int *a, const mp_int *b, mp_int *c)
|
||||
{
|
||||
mp_digit *pa, *pb, *pc;
|
||||
mp_size ix;
|
||||
mp_size used_pa, used_pb;
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
/* Add all digits up to the precision of b. If b had more
|
||||
* precision than a initially, swap a, b first
|
||||
*/
|
||||
if (MP_USED(a) >= MP_USED(b)) {
|
||||
pa = MP_DIGITS(a);
|
||||
pb = MP_DIGITS(b);
|
||||
used_pa = MP_USED(a);
|
||||
used_pb = MP_USED(b);
|
||||
} else {
|
||||
pa = MP_DIGITS(b);
|
||||
pb = MP_DIGITS(a);
|
||||
used_pa = MP_USED(b);
|
||||
used_pb = MP_USED(a);
|
||||
}
|
||||
|
||||
/* Make sure c has enough precision for the output value */
|
||||
MP_CHECKOK( s_mp_pad(c, used_pa) );
|
||||
|
||||
/* Do word-by-word xor */
|
||||
pc = MP_DIGITS(c);
|
||||
for (ix = 0; ix < used_pb; ix++) {
|
||||
(*pc++) = (*pa++) ^ (*pb++);
|
||||
}
|
||||
|
||||
/* Finish the rest of digits until we're actually done */
|
||||
for (; ix < used_pa; ++ix) {
|
||||
*pc++ = *pa++;
|
||||
}
|
||||
|
||||
MP_USED(c) = used_pa;
|
||||
MP_SIGN(c) = ZPOS;
|
||||
s_mp_clamp(c);
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
#define s_mp_div2(a) MP_CHECKOK( mpl_rsh((a), (a), 1) );
|
||||
|
||||
/* Compute binary polynomial multiply d = a * b */
|
||||
static void
|
||||
s_bmul_d(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *d)
|
||||
{
|
||||
mp_digit a_i, a0b0, a1b1, carry = 0;
|
||||
while (a_len--) {
|
||||
a_i = *a++;
|
||||
s_bmul_1x1(&a1b1, &a0b0, a_i, b);
|
||||
*d++ = a0b0 ^ carry;
|
||||
carry = a1b1;
|
||||
}
|
||||
*d = carry;
|
||||
}
|
||||
|
||||
/* Compute binary polynomial xor multiply accumulate d ^= a * b */
|
||||
static void
|
||||
s_bmul_d_add(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *d)
|
||||
{
|
||||
mp_digit a_i, a0b0, a1b1, carry = 0;
|
||||
while (a_len--) {
|
||||
a_i = *a++;
|
||||
s_bmul_1x1(&a1b1, &a0b0, a_i, b);
|
||||
*d++ ^= a0b0 ^ carry;
|
||||
carry = a1b1;
|
||||
}
|
||||
*d ^= carry;
|
||||
}
|
||||
|
||||
/* Compute binary polynomial xor multiply c = a * b.
|
||||
* All parameters may be identical.
|
||||
*/
|
||||
mp_err
|
||||
mp_bmul(const mp_int *a, const mp_int *b, mp_int *c)
|
||||
{
|
||||
mp_digit *pb, b_i;
|
||||
mp_int tmp;
|
||||
mp_size ib, a_used, b_used;
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_DIGITS(&tmp) = 0;
|
||||
|
||||
ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
|
||||
|
||||
if (a == c) {
|
||||
MP_CHECKOK( mp_init_copy(&tmp, a) );
|
||||
if (a == b)
|
||||
b = &tmp;
|
||||
a = &tmp;
|
||||
} else if (b == c) {
|
||||
MP_CHECKOK( mp_init_copy(&tmp, b) );
|
||||
b = &tmp;
|
||||
}
|
||||
|
||||
if (MP_USED(a) < MP_USED(b)) {
|
||||
const mp_int *xch = b; /* switch a and b if b longer */
|
||||
b = a;
|
||||
a = xch;
|
||||
}
|
||||
|
||||
MP_USED(c) = 1; MP_DIGIT(c, 0) = 0;
|
||||
MP_CHECKOK( s_mp_pad(c, USED(a) + USED(b)) );
|
||||
|
||||
pb = MP_DIGITS(b);
|
||||
s_bmul_d(MP_DIGITS(a), MP_USED(a), *pb++, MP_DIGITS(c));
|
||||
|
||||
/* Outer loop: Digits of b */
|
||||
a_used = MP_USED(a);
|
||||
b_used = MP_USED(b);
|
||||
MP_USED(c) = a_used + b_used;
|
||||
for (ib = 1; ib < b_used; ib++) {
|
||||
b_i = *pb++;
|
||||
|
||||
/* Inner product: Digits of a */
|
||||
if (b_i)
|
||||
s_bmul_d_add(MP_DIGITS(a), a_used, b_i, MP_DIGITS(c) + ib);
|
||||
else
|
||||
MP_DIGIT(c, ib + a_used) = b_i;
|
||||
}
|
||||
|
||||
s_mp_clamp(c);
|
||||
|
||||
SIGN(c) = ZPOS;
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&tmp);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* Compute modular reduction of a and store result in r.
|
||||
* r could be a.
|
||||
* For modular arithmetic, the irreducible polynomial f(t) is represented
|
||||
* as an array of int[], where f(t) is of the form:
|
||||
* f(t) = t^p[0] + t^p[1] + ... + t^p[k]
|
||||
* where m = p[0] > p[1] > ... > p[k] = 0.
|
||||
*/
|
||||
mp_err
|
||||
mp_bmod(const mp_int *a, const unsigned int p[], mp_int *r)
|
||||
{
|
||||
int j, k;
|
||||
int n, dN, d0, d1;
|
||||
mp_digit zz, *z, tmp;
|
||||
mp_size used;
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
/* The algorithm does the reduction in place in r,
|
||||
* if a != r, copy a into r first so reduction can be done in r
|
||||
*/
|
||||
if (a != r) {
|
||||
MP_CHECKOK( mp_copy(a, r) );
|
||||
}
|
||||
z = MP_DIGITS(r);
|
||||
|
||||
/* start reduction */
|
||||
dN = p[0] / MP_DIGIT_BITS;
|
||||
used = MP_USED(r);
|
||||
|
||||
for (j = used - 1; j > dN;) {
|
||||
|
||||
zz = z[j];
|
||||
if (zz == 0) {
|
||||
j--; continue;
|
||||
}
|
||||
z[j] = 0;
|
||||
|
||||
for (k = 1; p[k] > 0; k++) {
|
||||
/* reducing component t^p[k] */
|
||||
n = p[0] - p[k];
|
||||
d0 = n % MP_DIGIT_BITS;
|
||||
d1 = MP_DIGIT_BITS - d0;
|
||||
n /= MP_DIGIT_BITS;
|
||||
z[j-n] ^= (zz>>d0);
|
||||
if (d0)
|
||||
z[j-n-1] ^= (zz<<d1);
|
||||
}
|
||||
|
||||
/* reducing component t^0 */
|
||||
n = dN;
|
||||
d0 = p[0] % MP_DIGIT_BITS;
|
||||
d1 = MP_DIGIT_BITS - d0;
|
||||
z[j-n] ^= (zz >> d0);
|
||||
if (d0)
|
||||
z[j-n-1] ^= (zz << d1);
|
||||
|
||||
}
|
||||
|
||||
/* final round of reduction */
|
||||
while (j == dN) {
|
||||
|
||||
d0 = p[0] % MP_DIGIT_BITS;
|
||||
zz = z[dN] >> d0;
|
||||
if (zz == 0) break;
|
||||
d1 = MP_DIGIT_BITS - d0;
|
||||
|
||||
/* clear up the top d1 bits */
|
||||
if (d0) z[dN] = (z[dN] << d1) >> d1;
|
||||
*z ^= zz; /* reduction t^0 component */
|
||||
|
||||
for (k = 1; p[k] > 0; k++) {
|
||||
/* reducing component t^p[k]*/
|
||||
n = p[k] / MP_DIGIT_BITS;
|
||||
d0 = p[k] % MP_DIGIT_BITS;
|
||||
d1 = MP_DIGIT_BITS - d0;
|
||||
z[n] ^= (zz << d0);
|
||||
tmp = zz >> d1;
|
||||
if (d0 && tmp)
|
||||
z[n+1] ^= tmp;
|
||||
}
|
||||
}
|
||||
|
||||
s_mp_clamp(r);
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the product of two polynomials a and b, reduce modulo p,
|
||||
* Store the result in r. r could be a or b; a could be b.
|
||||
*/
|
||||
mp_err
|
||||
mp_bmulmod(const mp_int *a, const mp_int *b, const unsigned int p[], mp_int *r)
|
||||
{
|
||||
mp_err res;
|
||||
|
||||
if (a == b) return mp_bsqrmod(a, p, r);
|
||||
if ((res = mp_bmul(a, b, r) ) != MP_OKAY)
|
||||
return res;
|
||||
return mp_bmod(r, p, r);
|
||||
}
|
||||
|
||||
/* Compute binary polynomial squaring c = a*a mod p .
|
||||
* Parameter r and a can be identical.
|
||||
*/
|
||||
|
||||
mp_err
|
||||
mp_bsqrmod(const mp_int *a, const unsigned int p[], mp_int *r)
|
||||
{
|
||||
mp_digit *pa, *pr, a_i;
|
||||
mp_int tmp;
|
||||
mp_size ia, a_used;
|
||||
mp_err res;
|
||||
|
||||
ARGCHK(a != NULL && r != NULL, MP_BADARG);
|
||||
MP_DIGITS(&tmp) = 0;
|
||||
|
||||
if (a == r) {
|
||||
MP_CHECKOK( mp_init_copy(&tmp, a) );
|
||||
a = &tmp;
|
||||
}
|
||||
|
||||
MP_USED(r) = 1; MP_DIGIT(r, 0) = 0;
|
||||
MP_CHECKOK( s_mp_pad(r, 2*USED(a)) );
|
||||
|
||||
pa = MP_DIGITS(a);
|
||||
pr = MP_DIGITS(r);
|
||||
a_used = MP_USED(a);
|
||||
MP_USED(r) = 2 * a_used;
|
||||
|
||||
for (ia = 0; ia < a_used; ia++) {
|
||||
a_i = *pa++;
|
||||
*pr++ = gf2m_SQR0(a_i);
|
||||
*pr++ = gf2m_SQR1(a_i);
|
||||
}
|
||||
|
||||
MP_CHECKOK( mp_bmod(r, p, r) );
|
||||
s_mp_clamp(r);
|
||||
SIGN(r) = ZPOS;
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&tmp);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute binary polynomial y/x mod p, y divided by x, reduce modulo p.
|
||||
* Store the result in r. r could be x or y, and x could equal y.
|
||||
* Uses algorithm Modular_Division_GF(2^m) from
|
||||
* Chang-Shantz, S. "From Euclid's GCD to Montgomery Multiplication to
|
||||
* the Great Divide".
|
||||
*/
|
||||
int
|
||||
mp_bdivmod(const mp_int *y, const mp_int *x, const mp_int *pp,
|
||||
const unsigned int p[], mp_int *r)
|
||||
{
|
||||
mp_int aa, bb, uu;
|
||||
mp_int *a, *b, *u, *v;
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_DIGITS(&aa) = 0;
|
||||
MP_DIGITS(&bb) = 0;
|
||||
MP_DIGITS(&uu) = 0;
|
||||
|
||||
MP_CHECKOK( mp_init_copy(&aa, x) );
|
||||
MP_CHECKOK( mp_init_copy(&uu, y) );
|
||||
MP_CHECKOK( mp_init_copy(&bb, pp) );
|
||||
MP_CHECKOK( s_mp_pad(r, USED(pp)) );
|
||||
MP_USED(r) = 1; MP_DIGIT(r, 0) = 0;
|
||||
|
||||
a = &aa; b= &bb; u=&uu; v=r;
|
||||
/* reduce x and y mod p */
|
||||
MP_CHECKOK( mp_bmod(a, p, a) );
|
||||
MP_CHECKOK( mp_bmod(u, p, u) );
|
||||
|
||||
while (!mp_isodd(a)) {
|
||||
s_mp_div2(a);
|
||||
if (mp_isodd(u)) {
|
||||
MP_CHECKOK( mp_badd(u, pp, u) );
|
||||
}
|
||||
s_mp_div2(u);
|
||||
}
|
||||
|
||||
do {
|
||||
if (mp_cmp_mag(b, a) > 0) {
|
||||
MP_CHECKOK( mp_badd(b, a, b) );
|
||||
MP_CHECKOK( mp_badd(v, u, v) );
|
||||
do {
|
||||
s_mp_div2(b);
|
||||
if (mp_isodd(v)) {
|
||||
MP_CHECKOK( mp_badd(v, pp, v) );
|
||||
}
|
||||
s_mp_div2(v);
|
||||
} while (!mp_isodd(b));
|
||||
}
|
||||
else if ((MP_DIGIT(a,0) == 1) && (MP_USED(a) == 1))
|
||||
break;
|
||||
else {
|
||||
MP_CHECKOK( mp_badd(a, b, a) );
|
||||
MP_CHECKOK( mp_badd(u, v, u) );
|
||||
do {
|
||||
s_mp_div2(a);
|
||||
if (mp_isodd(u)) {
|
||||
MP_CHECKOK( mp_badd(u, pp, u) );
|
||||
}
|
||||
s_mp_div2(u);
|
||||
} while (!mp_isodd(a));
|
||||
}
|
||||
} while (1);
|
||||
|
||||
MP_CHECKOK( mp_copy(u, r) );
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
/* Convert the bit-string representation of a polynomial a into an array
|
||||
* of integers corresponding to the bits with non-zero coefficient.
|
||||
* Up to max elements of the array will be filled. Return value is total
|
||||
* number of coefficients that would be extracted if array was large enough.
|
||||
*/
|
||||
int
|
||||
mp_bpoly2arr(const mp_int *a, unsigned int p[], int max)
|
||||
{
|
||||
int i, j, k;
|
||||
mp_digit top_bit, mask;
|
||||
|
||||
top_bit = 1;
|
||||
top_bit <<= MP_DIGIT_BIT - 1;
|
||||
|
||||
for (k = 0; k < max; k++) p[k] = 0;
|
||||
k = 0;
|
||||
|
||||
for (i = MP_USED(a) - 1; i >= 0; i--) {
|
||||
mask = top_bit;
|
||||
for (j = MP_DIGIT_BIT - 1; j >= 0; j--) {
|
||||
if (MP_DIGITS(a)[i] & mask) {
|
||||
if (k < max) p[k] = MP_DIGIT_BIT * i + j;
|
||||
k++;
|
||||
}
|
||||
mask >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
/* Convert the coefficient array representation of a polynomial to a
|
||||
* bit-string. The array must be terminated by 0.
|
||||
*/
|
||||
mp_err
|
||||
mp_barr2poly(const unsigned int p[], mp_int *a)
|
||||
{
|
||||
|
||||
mp_err res = MP_OKAY;
|
||||
int i;
|
||||
|
||||
mp_zero(a);
|
||||
for (i = 0; p[i] > 0; i++) {
|
||||
MP_CHECKOK( mpl_set_bit(a, p[i], 1) );
|
||||
}
|
||||
MP_CHECKOK( mpl_set_bit(a, 0, 1) );
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
@@ -1,760 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Red Hat, Inc
|
||||
* Portions created by the Initial Developer are Copyright (C) 2005
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Robert Relyea <rrelyea@redhat.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "mpi.h"
|
||||
|
||||
/*
|
||||
* This file implements a single function: mpi_getProcessorLineSize();
|
||||
* mpi_getProcessorLineSize() returns the size in bytes of the cache line
|
||||
* if a cache exists, or zero if there is no cache. If more than one
|
||||
* cache line exists, it should return the smallest line size (which is
|
||||
* usually the L1 cache).
|
||||
*
|
||||
* mp_modexp uses this information to make sure that private key information
|
||||
* isn't being leaked through the cache.
|
||||
*
|
||||
* Currently the file returns good data for most modern x86 processors, and
|
||||
* reasonable data on 64-bit ppc processors. All other processors are assumed
|
||||
* to have a cache line size of 32 bytes unless modified by target.mk.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(i386) || defined(__i386) || defined(__X86__) || defined (_M_IX86)
|
||||
/* X86 processors have special instructions that tell us about the cache */
|
||||
#include "string.h"
|
||||
|
||||
/* Generic CPUID function */
|
||||
#ifndef _WIN32
|
||||
static void cpuid(unsigned long op, unsigned long *eax,
|
||||
unsigned long *ebx, unsigned long *ecx,
|
||||
unsigned long *edx)
|
||||
{
|
||||
/* sigh GCC isn't smart enough to save the ebx PIC register on it's own
|
||||
* in this case, so do it by hand. */
|
||||
__asm__("pushl %%ebx\n\t"
|
||||
"cpuid\n\t"
|
||||
"mov %%ebx,%1\n\t"
|
||||
"popl %%ebx\n\t"
|
||||
: "=a" (*eax),
|
||||
"=r" (*ebx),
|
||||
"=c" (*ecx),
|
||||
"=d" (*edx)
|
||||
: "0" (op));
|
||||
}
|
||||
|
||||
/*
|
||||
* try flipping a processor flag to determine CPU type
|
||||
*/
|
||||
static unsigned long changeFlag(unsigned long flag)
|
||||
{
|
||||
unsigned long changedFlags, originalFlags;
|
||||
__asm__("pushfl\n\t" /* get the flags */
|
||||
"popl %0\n\t"
|
||||
"movl %0,%1\n\t" /* save the original flags */
|
||||
"xor %0,%2\n\t" /* flip the but */
|
||||
"pushl %0\n\t" /* set the flags */
|
||||
"popfl\n\t"
|
||||
"pushfl\n\t" /* get the flags again (for return) */
|
||||
"popl %0\n\t"
|
||||
"pushl %1\n\t" /* restore the original flags */
|
||||
"popfl\n\t"
|
||||
: "=r" (changedFlags),
|
||||
"=r" (originalFlags)
|
||||
: "r" (flag));
|
||||
return changedFlags ^ originalFlags;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* windows versions of the above assembler
|
||||
*/
|
||||
#define wcpuid __asm __emit 0fh __asm __emit 0a2h
|
||||
static void cpuid(unsigned long op, unsigned long *Reax, unsigned long *Rebx,
|
||||
unsigned long *Recx, unsigned long *Redx)
|
||||
{
|
||||
unsigned long Leax, Lebx, Lecx, Ledx;
|
||||
__asm {
|
||||
pushad
|
||||
mov eax,op
|
||||
wcpuid
|
||||
mov Leax,eax
|
||||
mov Lebx,ebx
|
||||
mov Lecx,ecx
|
||||
mov Ledx,edx
|
||||
popad
|
||||
}
|
||||
*Reax = Leax;
|
||||
*Rebx = Lebx;
|
||||
*Recx = Lecx;
|
||||
*Redx = Ledx;
|
||||
}
|
||||
|
||||
static unsigned long changeFlag(unsigned long flag)
|
||||
{
|
||||
unsigned long changedFlags, originalFlags;
|
||||
__asm {
|
||||
pushad
|
||||
pushfd /* get the flags */
|
||||
pop eax
|
||||
mov ecx,eax /* save the original flags */
|
||||
mov originalFlags,ecx /* save the original flags */
|
||||
mov ebx,flag
|
||||
xor eax,ebx /* flip the but */
|
||||
push eax /* set the flags */
|
||||
popfd
|
||||
pushfd /* get the flags again (for return) */
|
||||
pop eax
|
||||
push ecx /* restore the original flags */
|
||||
popfd
|
||||
mov changedFlags,eax
|
||||
popad
|
||||
}
|
||||
return changedFlags ^ originalFlags;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define AC_FLAG 0x40000
|
||||
#define ID_FLAG 0x200000
|
||||
|
||||
/* 386 processors can't flip the AC_FLAG, intel AP Note AP-485 */
|
||||
static int is386()
|
||||
{
|
||||
return changeFlag(AC_FLAG) == 0;
|
||||
}
|
||||
|
||||
/* 486 processors can't flip the ID_FLAG, intel AP Note AP-485 */
|
||||
static int is486()
|
||||
{
|
||||
return changeFlag(ID_FLAG) == 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* table for Intel Cache.
|
||||
* See Intel Application Note AP-485 for more information
|
||||
*/
|
||||
typedef enum {
|
||||
Cache_NONE = 0,
|
||||
Cache_UNKNOWN = 1,
|
||||
Cache_TLB = 2,
|
||||
Cache_Trace = 3,
|
||||
Cache_L1 = 4,
|
||||
Cache_L2 = 5 ,
|
||||
Cache_L3 = 6
|
||||
} CacheType;
|
||||
|
||||
#define DATA_INSTR 1
|
||||
#define DATA_DATA 2
|
||||
#define DATA_BOTH 3
|
||||
#define DATA_TRACE 4
|
||||
#define DATA_NONE 0
|
||||
|
||||
#define TLB_4k 0x01
|
||||
#define TLB_2M 0x08
|
||||
#define TLB_4M 0x10
|
||||
#define TLB_4Mk 0x11
|
||||
#define TLB_ALL 0x19
|
||||
|
||||
#define k * 1024
|
||||
#define M * (1024*1024)
|
||||
#define G * (1024*1024*1024)
|
||||
|
||||
struct _cache {
|
||||
CacheType type;
|
||||
unsigned long data;
|
||||
#define pageSize size
|
||||
#define trcuops size
|
||||
unsigned long size;
|
||||
unsigned long association;
|
||||
#define tlbEntries lineSize
|
||||
unsigned long lineSize;
|
||||
} CacheMap[] = {
|
||||
/* 00 */ {Cache_NONE, DATA_NONE, 0, 0, 0 },
|
||||
/* 01 */ {Cache_TLB, DATA_INSTR, TLB_4k, 4, 32 },
|
||||
/* 02 */ {Cache_TLB, DATA_INSTR, TLB_4M, 0, 2 },
|
||||
/* 03 */ {Cache_TLB, DATA_DATA, TLB_4k, 4, 64 },
|
||||
/* 04 */ {Cache_TLB, DATA_DATA, TLB_4M, 4, 8 },
|
||||
/* 05 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 06 */ {Cache_L1, DATA_INSTR, 8 k, 4, 32 },
|
||||
/* 07 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 08 */ {Cache_L1, DATA_INSTR, 16 k, 4, 32 },
|
||||
/* 09 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 0a */ {Cache_L1, DATA_DATA, 8 k, 4, 32 },
|
||||
/* 0b */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 0c */ {Cache_L1, DATA_DATA, 16 k, 4, 32 },
|
||||
/* 0d */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 0e */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 0f */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 10 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 11 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 12 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 13 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 14 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 15 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 16 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 17 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 18 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 19 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 1a */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 1b */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 1c */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 1d */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 1e */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 1f */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 20 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 21 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 22 */ {Cache_L3, DATA_BOTH, 512 k, 8, 64 },
|
||||
/* 23 */ {Cache_L3, DATA_BOTH, 1 M, 8, 64 },
|
||||
/* 24 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 25 */ {Cache_L3, DATA_BOTH, 2 M, 8, 64 },
|
||||
/* 26 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 27 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 28 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 29 */ {Cache_L3, DATA_BOTH, 4 M, 8, 64 },
|
||||
/* 2a */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 2b */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 2c */ {Cache_L1, DATA_DATA, 32 k, 8, 64 },
|
||||
/* 2d */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 2e */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 2f */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 30 */ {Cache_L1, DATA_INSTR, 32 k, 8, 64 },
|
||||
/* 31 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 32 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 33 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 34 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 35 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 36 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 37 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 38 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 39 */ {Cache_L2, DATA_BOTH, 128 k, 4, 64 },
|
||||
/* 3a */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 3b */ {Cache_L2, DATA_BOTH, 128 k, 2, 64 },
|
||||
/* 3c */ {Cache_L2, DATA_BOTH, 256 k, 4, 64 },
|
||||
/* 3d */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 3e */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 3f */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 40 */ {Cache_L2, DATA_NONE, 0, 0, 0 },
|
||||
/* 41 */ {Cache_L2, DATA_BOTH, 128 k, 4, 32 },
|
||||
/* 42 */ {Cache_L2, DATA_BOTH, 256 k, 4, 32 },
|
||||
/* 43 */ {Cache_L2, DATA_BOTH, 512 k, 4, 32 },
|
||||
/* 44 */ {Cache_L2, DATA_BOTH, 1 M, 4, 32 },
|
||||
/* 45 */ {Cache_L2, DATA_BOTH, 2 M, 4, 32 },
|
||||
/* 46 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 47 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 48 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 49 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 4a */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 4b */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 4c */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 4d */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 4e */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 4f */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 50 */ {Cache_TLB, DATA_INSTR, TLB_ALL, 0, 64 },
|
||||
/* 51 */ {Cache_TLB, DATA_INSTR, TLB_ALL, 0, 128 },
|
||||
/* 52 */ {Cache_TLB, DATA_INSTR, TLB_ALL, 0, 256 },
|
||||
/* 53 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 54 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 55 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 56 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 57 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 58 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 59 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 5a */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 5b */ {Cache_TLB, DATA_DATA, TLB_4Mk, 0, 64 },
|
||||
/* 5c */ {Cache_TLB, DATA_DATA, TLB_4Mk, 0, 128 },
|
||||
/* 5d */ {Cache_TLB, DATA_DATA, TLB_4Mk, 0, 256 },
|
||||
/* 5e */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 5f */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 60 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 61 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 62 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 63 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 64 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 65 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 66 */ {Cache_L1, DATA_DATA, 8 k, 4, 64 },
|
||||
/* 67 */ {Cache_L1, DATA_DATA, 16 k, 4, 64 },
|
||||
/* 68 */ {Cache_L1, DATA_DATA, 32 k, 4, 64 },
|
||||
/* 69 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 6a */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 6b */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 6c */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 6d */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 6e */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 6f */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 70 */ {Cache_Trace, DATA_TRACE, 12 k, 8, 1 },
|
||||
/* 71 */ {Cache_Trace, DATA_TRACE, 16 k, 8, 1 },
|
||||
/* 72 */ {Cache_Trace, DATA_TRACE, 32 k, 8, 1 },
|
||||
/* 73 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 74 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 75 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 76 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 77 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 78 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 79 */ {Cache_L2, DATA_BOTH, 128 k, 8, 64 },
|
||||
/* 7a */ {Cache_L2, DATA_BOTH, 256 k, 8, 64 },
|
||||
/* 7b */ {Cache_L2, DATA_BOTH, 512 k, 8, 64 },
|
||||
/* 7c */ {Cache_L2, DATA_BOTH, 1 M, 8, 64 },
|
||||
/* 7d */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 7e */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 7f */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 80 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 81 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 82 */ {Cache_L2, DATA_BOTH, 256 k, 8, 32 },
|
||||
/* 83 */ {Cache_L2, DATA_BOTH, 512 k, 8, 32 },
|
||||
/* 84 */ {Cache_L2, DATA_BOTH, 1 M, 8, 32 },
|
||||
/* 85 */ {Cache_L2, DATA_BOTH, 2 M, 8, 32 },
|
||||
/* 86 */ {Cache_L2, DATA_BOTH, 512 k, 4, 64 },
|
||||
/* 87 */ {Cache_L2, DATA_BOTH, 1 M, 8, 64 },
|
||||
/* 88 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 89 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 8a */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 8b */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 8c */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 8d */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 8e */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 8f */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 90 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 91 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 92 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 93 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 94 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 95 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 96 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 97 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 98 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 99 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 9a */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 9b */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 9c */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 9d */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 9e */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 9f */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* a0 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* a1 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* a2 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* a3 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* a4 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* a5 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* a6 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* a7 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* a8 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* a9 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* aa */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* ab */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* ac */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* ad */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* ae */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* af */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* b0 */ {Cache_TLB, DATA_INSTR, TLB_4k, 4, 128 },
|
||||
/* b1 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* b2 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* b3 */ {Cache_TLB, DATA_DATA, TLB_4k, 4, 128 },
|
||||
/* b4 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* b5 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* b6 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* b7 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* b8 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* b9 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* ba */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* bb */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* bc */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* bd */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* be */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* bf */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* c0 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* c1 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* c2 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* c3 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* c4 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* c5 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* c6 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* c7 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* c8 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* c9 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* ca */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* cb */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* cc */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* cd */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* ce */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* cf */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* d0 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* d1 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* d2 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* d3 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* d4 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* d5 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* d6 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* d7 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* d8 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* d9 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* da */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* db */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* dc */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* dd */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* de */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* df */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* e0 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* e1 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* e2 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* e3 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* e4 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* e5 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* e6 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* e7 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* e8 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* e9 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* ea */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* eb */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* ec */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* ed */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* ee */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* ef */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* f0 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* f1 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* f2 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* f3 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* f4 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* f5 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* f6 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* f7 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* f8 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* f9 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* fa */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* fb */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* fc */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* fd */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* fe */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* ff */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* use the above table to determine the CacheEntryLineSize.
|
||||
*/
|
||||
static void
|
||||
getIntelCacheEntryLineSize(unsigned long val, int *level,
|
||||
unsigned long *lineSize)
|
||||
{
|
||||
CacheType type;
|
||||
|
||||
type = CacheMap[val].type;
|
||||
/* only interested in data caches */
|
||||
/* NOTE val = 0x40 is a special value that means no L2 or L3 cache.
|
||||
* this data check has the side effect of rejecting that entry. If
|
||||
* that wasn't the case, we could have to reject it explicitly */
|
||||
if ((CacheMap[val].data & DATA_DATA) != DATA_DATA) {
|
||||
return;
|
||||
}
|
||||
/* look at the caches, skip types we aren't interested in.
|
||||
* if we already have a value for a lower level cache, skip the
|
||||
* current entry */
|
||||
if (type == Cache_L1) {
|
||||
*level = 1;
|
||||
*lineSize = CacheMap[val].lineSize;
|
||||
} else if ((*level >= 2) && type == Cache_L2) {
|
||||
*level = 2;
|
||||
*lineSize = CacheMap[val].lineSize;
|
||||
} else if ((*level >= 3) && type == Cache_L3) {
|
||||
*level = 3;
|
||||
*lineSize = CacheMap[val].lineSize;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
getIntelRegisterCacheLineSize(unsigned long val,
|
||||
int *level, unsigned long *lineSize)
|
||||
{
|
||||
getIntelCacheEntryLineSize(val >> 24 & 0xff, level, lineSize);
|
||||
getIntelCacheEntryLineSize(val >> 16 & 0xff, level, lineSize);
|
||||
getIntelCacheEntryLineSize(val >> 8 & 0xff, level, lineSize);
|
||||
getIntelCacheEntryLineSize(val & 0xff, level, lineSize);
|
||||
}
|
||||
|
||||
/*
|
||||
* returns '0' if no recognized cache is found, or if the cache
|
||||
* information is supported by this processor
|
||||
*/
|
||||
static unsigned long
|
||||
getIntelCacheLineSize(int cpuidLevel)
|
||||
{
|
||||
int level = 4;
|
||||
unsigned long lineSize = 0;
|
||||
unsigned long eax, ebx, ecx, edx;
|
||||
int repeat, count;
|
||||
|
||||
if (cpuidLevel < 2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* command '2' of the cpuid is intel's cache info call. Each byte of the
|
||||
* 4 registers contain a potential descriptor for the cache. The CacheMap
|
||||
* table maps the cache entry with the processor cache. Register 'al'
|
||||
* contains a count value that cpuid '2' needs to be called in order to
|
||||
* find all the cache descriptors. Only registers with the high bit set
|
||||
* to 'zero' have valid descriptors. This code loops through all the
|
||||
* required calls to cpuid '2' and passes any valid descriptors it finds
|
||||
* to the getIntelRegisterCacheLineSize code, which breaks the registers
|
||||
* down into their component descriptors. In the end the lineSize of the
|
||||
* lowest level cache data cache is returned. */
|
||||
cpuid(2, &eax, &ebx, &ecx, &edx);
|
||||
repeat = eax & 0xf;
|
||||
for (count = 0; count < repeat; count++) {
|
||||
if ((eax & 0x80000000) == 0) {
|
||||
getIntelRegisterCacheLineSize(eax & 0xffffff00, &level, &lineSize);
|
||||
}
|
||||
if ((ebx & 0x80000000) == 0) {
|
||||
getIntelRegisterCacheLineSize(ebx, &level, &lineSize);
|
||||
}
|
||||
if ((ecx & 0x80000000) == 0) {
|
||||
getIntelRegisterCacheLineSize(ecx, &level, &lineSize);
|
||||
}
|
||||
if ((edx & 0x80000000) == 0) {
|
||||
getIntelRegisterCacheLineSize(edx, &level, &lineSize);
|
||||
}
|
||||
if (count+1 != repeat) {
|
||||
cpuid(2, &eax, &ebx, &ecx, &edx);
|
||||
}
|
||||
}
|
||||
return lineSize;
|
||||
}
|
||||
|
||||
/*
|
||||
* returns '0' if the cache info is not supported by this processor.
|
||||
* This is based on the AMD extended cache commands for cpuid.
|
||||
* (see "AMD Processor Recognition Application Note" Publication 20734).
|
||||
* Some other processors use the identical scheme.
|
||||
* (see "Processor Recognition, Transmeta Corporation").
|
||||
*/
|
||||
static unsigned long
|
||||
getOtherCacheLineSize(unsigned long cpuidLevel)
|
||||
{
|
||||
unsigned long lineSize = 0;
|
||||
unsigned long eax, ebx, ecx, edx;
|
||||
|
||||
/* get the Extended CPUID level */
|
||||
cpuid(0x80000000, &eax, &ebx, &ecx, &edx);
|
||||
cpuidLevel = eax;
|
||||
|
||||
if (cpuidLevel >= 0x80000005) {
|
||||
cpuid(0x80000005, &eax, &ebx, &ecx, &edx);
|
||||
lineSize = ecx & 0xff; /* line Size, L1 Data Cache */
|
||||
}
|
||||
return lineSize;
|
||||
}
|
||||
|
||||
char *manMap[] = {
|
||||
#define INTEL 0
|
||||
"GenuineIntel",
|
||||
#define AMD 1
|
||||
"AuthenticAMD",
|
||||
#define CYRIX 2
|
||||
"CyrixInstead",
|
||||
#define CENTAUR 2
|
||||
"CentaurHauls",
|
||||
#define NEXGEN 3
|
||||
"NexGenDriven",
|
||||
#define TRANSMETA 4
|
||||
"GenuineTMx86",
|
||||
#define RISE 5
|
||||
"RiseRiseRise",
|
||||
#define UMC 6
|
||||
"UMC UMC UMC ",
|
||||
#define SIS 7
|
||||
"Sis Sis Sis ",
|
||||
#define NATIONAL 8
|
||||
"Geode by NSC",
|
||||
};
|
||||
|
||||
int n_manufacturers = sizeof(manMap)/sizeof(manMap[0]);
|
||||
|
||||
#define MAN_UNKNOWN 9
|
||||
|
||||
|
||||
unsigned long
|
||||
mpi_getProcessorLineSize()
|
||||
{
|
||||
unsigned long eax, ebx, ecx, edx;
|
||||
unsigned long cpuidLevel;
|
||||
unsigned long cacheLineSize = 0;
|
||||
int manufacturer = MAN_UNKNOWN;
|
||||
int i;
|
||||
char string[65];
|
||||
|
||||
if (is386()) {
|
||||
return 0; /* 386 had no cache */
|
||||
} if (is486()) {
|
||||
return 32; /* really? need more info */
|
||||
}
|
||||
|
||||
/* Pentium, cpuid command is available */
|
||||
cpuid(0, &eax, &ebx, &ecx, &edx);
|
||||
cpuidLevel = eax;
|
||||
*(int *)string = ebx;
|
||||
*(int *)&string[4] = edx;
|
||||
*(int *)&string[8] = ecx;
|
||||
string[12] = 0;
|
||||
|
||||
manufacturer = MAN_UNKNOWN;
|
||||
for (i=0; i < n_manufacturers; i++) {
|
||||
if ( strcmp(manMap[i],string) == 0) {
|
||||
manufacturer = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (manufacturer == INTEL) {
|
||||
cacheLineSize = getIntelCacheLineSize(cpuidLevel);
|
||||
} else {
|
||||
cacheLineSize = getOtherCacheLineSize(cpuidLevel);
|
||||
}
|
||||
/* doesn't support cache info based on cpuid. This means
|
||||
* an old pentium class processor, which have cache lines of
|
||||
* 32. If we learn differently, we can use a switch based on
|
||||
* the Manufacturer id */
|
||||
if (cacheLineSize == 0) {
|
||||
cacheLineSize = 32;
|
||||
}
|
||||
return cacheLineSize;
|
||||
}
|
||||
#define MPI_GET_PROCESSER_LINE_SIZE_DEFINED 1
|
||||
#endif
|
||||
|
||||
#if defined(__ppc64__)
|
||||
/*
|
||||
* Sigh, The PPC has some really nice features to help us determine cache
|
||||
* size, since it had lots of direct control functions to do so. The POWER
|
||||
* processor even has an instruction to do this, but it was dropped in
|
||||
* PowerPC. Unfortunately most of them are not available in user mode.
|
||||
*
|
||||
* The dcbz function would be a great way to determine cache line size except
|
||||
* 1) it only works on write-back memory (it throws an exception otherwise),
|
||||
* and 2) because so many mac programs 'knew' the processor cache size was
|
||||
* 32 bytes, they used this instruction as a fast 'zero 32 bytes'. Now the new
|
||||
* G5 processor has 128 byte cache, but dcbz only clears 32 bytes to keep
|
||||
* these programs happy. dcbzl work if 64 bit instructions are supported.
|
||||
* If you know 64 bit instructions are supported, and that stack is
|
||||
* write-back, you can use this code.
|
||||
*/
|
||||
#include "memory.h"
|
||||
|
||||
/* clear the cache line that contains 'array' */
|
||||
static inline void dcbzl(char *array)
|
||||
{
|
||||
register char *a asm("r2") = array;
|
||||
__asm__ __volatile__( "dcbzl %0,r0" : "=r" (a): "0"(a) );
|
||||
}
|
||||
|
||||
|
||||
#define PPC_DO_ALIGN(x,y) ((char *)\
|
||||
((((long long) (x))+((y)-1))&~((y)-1)))
|
||||
|
||||
#define PPC_MAX_LINE_SIZE 256
|
||||
unsigned long
|
||||
mpi_getProcessorLineSize()
|
||||
{
|
||||
char testArray[2*PPC_MAX_LINE_SIZE+1];
|
||||
char *test;
|
||||
int i;
|
||||
|
||||
/* align the array on a maximum line size boundary, so we
|
||||
* know we are starting to clear from the first address */
|
||||
test = PPC_DO_ALIGN(testArray, PPC_MAX_LINE_SIZE);
|
||||
/* set all the values to 1's */
|
||||
memset(test, 0xff, PPC_MAX_LINE_SIZE);
|
||||
/* clear one cache block starting at 'test' */
|
||||
dcbzl(test);
|
||||
|
||||
/* find the size of the cleared area, that's our block size */
|
||||
for (i=PPC_MAX_LINE_SIZE; i != 0; i = i/2) {
|
||||
if (test[i-1] == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define MPI_GET_PROCESSER_LINE_SIZE_DEFINED 1
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* put other processor and platform specific cache code here
|
||||
* return the smallest cache line size in bytes on the processor
|
||||
* (usually the L1 cache). If the OS has a call, this would be
|
||||
* a greate place to put it.
|
||||
*
|
||||
* If there is no cache, return 0;
|
||||
*
|
||||
* define MPI_GET_PROCESSOR_LINE_SIZE_DEFINED so the generic functions
|
||||
* below aren't compiled.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* target.mk can define LINE_SIZE if it's common for the family or OS */
|
||||
#if defined(LINE_SIZE) && !defined(MPI_GET_PROCESSOR_LINE_SIZE_DEFINED)
|
||||
|
||||
unsigned long
|
||||
mpi_getProcessorLineSize()
|
||||
{
|
||||
return LINE_SIZE;
|
||||
}
|
||||
#define MPI_GET_PROCESSER_LINE_SIZE_DEFINED 1
|
||||
#endif
|
||||
|
||||
|
||||
/* If no way to get the processor cache line size has been defined, assume
|
||||
* it's 32 bytes (most common value, does not significantly impact performance
|
||||
*/
|
||||
#ifndef MPI_GET_PROCESSER_LINE_SIZE_DEFINED
|
||||
unsigned long
|
||||
mpi_getProcessorLineSize()
|
||||
{
|
||||
return 32;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TEST_IT
|
||||
#include <stdio.h>
|
||||
|
||||
main()
|
||||
{
|
||||
printf("line size = %d\n", mpi_getProcessorLineSize());
|
||||
}
|
||||
#endif
|
||||
@@ -1,112 +0,0 @@
|
||||
/* Default configuration for MPI library
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael J. Fromberger.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1997
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Netscape Communications Corporation
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: mpi-config.h,v 1.5 2004-04-25 15:03:10 gerv%gerv.net Exp $ */
|
||||
|
||||
#ifndef MPI_CONFIG_H_
|
||||
#define MPI_CONFIG_H_
|
||||
|
||||
/*
|
||||
For boolean options,
|
||||
0 = no
|
||||
1 = yes
|
||||
|
||||
Other options are documented individually.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef MP_IOFUNC
|
||||
#define MP_IOFUNC 0 /* include mp_print() ? */
|
||||
#endif
|
||||
|
||||
#ifndef MP_MODARITH
|
||||
#define MP_MODARITH 1 /* include modular arithmetic ? */
|
||||
#endif
|
||||
|
||||
#ifndef MP_NUMTH
|
||||
#define MP_NUMTH 1 /* include number theoretic functions? */
|
||||
#endif
|
||||
|
||||
#ifndef MP_LOGTAB
|
||||
#define MP_LOGTAB 1 /* use table of logs instead of log()? */
|
||||
#endif
|
||||
|
||||
#ifndef MP_MEMSET
|
||||
#define MP_MEMSET 1 /* use memset() to zero buffers? */
|
||||
#endif
|
||||
|
||||
#ifndef MP_MEMCPY
|
||||
#define MP_MEMCPY 1 /* use memcpy() to copy buffers? */
|
||||
#endif
|
||||
|
||||
#ifndef MP_CRYPTO
|
||||
#define MP_CRYPTO 1 /* erase memory on free? */
|
||||
#endif
|
||||
|
||||
#ifndef MP_ARGCHK
|
||||
/*
|
||||
0 = no parameter checks
|
||||
1 = runtime checks, continue execution and return an error to caller
|
||||
2 = assertions; dump core on parameter errors
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
#define MP_ARGCHK 2 /* how to check input arguments */
|
||||
#else
|
||||
#define MP_ARGCHK 1 /* how to check input arguments */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef MP_DEBUG
|
||||
#define MP_DEBUG 0 /* print diagnostic output? */
|
||||
#endif
|
||||
|
||||
#ifndef MP_DEFPREC
|
||||
#define MP_DEFPREC 64 /* default precision, in digits */
|
||||
#endif
|
||||
|
||||
#ifndef MP_MACRO
|
||||
#define MP_MACRO 0 /* use macros for frequent calls? */
|
||||
#endif
|
||||
|
||||
#ifndef MP_SQUARE
|
||||
#define MP_SQUARE 1 /* use separate squaring code? */
|
||||
#endif
|
||||
|
||||
#endif /* ifndef MPI_CONFIG_H_ */
|
||||
|
||||
|
||||
@@ -1,289 +0,0 @@
|
||||
/*
|
||||
* mpi-priv.h - Private header file for MPI
|
||||
* Arbitrary precision integer arithmetic library
|
||||
*
|
||||
* NOTE WELL: the content of this header file is NOT part of the "public"
|
||||
* API for the MPI library, and may change at any time.
|
||||
* Application programs that use libmpi should NOT include this header file.
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael J. Fromberger.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Netscape Communications Corporation
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: mpi-priv.h,v 1.18 2005-02-25 04:30:11 julien.pierre.bugs%sun.com Exp $ */
|
||||
#ifndef _MPI_PRIV_H_
|
||||
#define _MPI_PRIV_H_ 1
|
||||
|
||||
#include "mpi.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#if MP_DEBUG
|
||||
#include <stdio.h>
|
||||
|
||||
#define DIAG(T,V) {fprintf(stderr,T);mp_print(V,stderr);fputc('\n',stderr);}
|
||||
#else
|
||||
#define DIAG(T,V)
|
||||
#endif
|
||||
|
||||
/* If we aren't using a wired-in logarithm table, we need to include
|
||||
the math library to get the log() function
|
||||
*/
|
||||
|
||||
/* {{{ s_logv_2[] - log table for 2 in various bases */
|
||||
|
||||
#if MP_LOGTAB
|
||||
/*
|
||||
A table of the logs of 2 for various bases (the 0 and 1 entries of
|
||||
this table are meaningless and should not be referenced).
|
||||
|
||||
This table is used to compute output lengths for the mp_toradix()
|
||||
function. Since a number n in radix r takes up about log_r(n)
|
||||
digits, we estimate the output size by taking the least integer
|
||||
greater than log_r(n), where:
|
||||
|
||||
log_r(n) = log_2(n) * log_r(2)
|
||||
|
||||
This table, therefore, is a table of log_r(2) for 2 <= r <= 36,
|
||||
which are the output bases supported.
|
||||
*/
|
||||
|
||||
extern const float s_logv_2[];
|
||||
#define LOG_V_2(R) s_logv_2[(R)]
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
If MP_LOGTAB is not defined, use the math library to compute the
|
||||
logarithms on the fly. Otherwise, use the table.
|
||||
Pick which works best for your system.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#define LOG_V_2(R) (log(2.0)/log(R))
|
||||
|
||||
#endif /* if MP_LOGTAB */
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Digit arithmetic macros */
|
||||
|
||||
/*
|
||||
When adding and multiplying digits, the results can be larger than
|
||||
can be contained in an mp_digit. Thus, an mp_word is used. These
|
||||
macros mask off the upper and lower digits of the mp_word (the
|
||||
mp_word may be more than 2 mp_digits wide, but we only concern
|
||||
ourselves with the low-order 2 mp_digits)
|
||||
*/
|
||||
|
||||
#define CARRYOUT(W) (mp_digit)((W)>>DIGIT_BIT)
|
||||
#define ACCUM(W) (mp_digit)(W)
|
||||
|
||||
#define MP_MIN(a,b) (((a) < (b)) ? (a) : (b))
|
||||
#define MP_MAX(a,b) (((a) > (b)) ? (a) : (b))
|
||||
#define MP_HOWMANY(a,b) (((a) + (b) - 1)/(b))
|
||||
#define MP_ROUNDUP(a,b) (MP_HOWMANY(a,b) * (b))
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Comparison constants */
|
||||
|
||||
#define MP_LT -1
|
||||
#define MP_EQ 0
|
||||
#define MP_GT 1
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ private function declarations */
|
||||
|
||||
/*
|
||||
If MP_MACRO is false, these will be defined as actual functions;
|
||||
otherwise, suitable macro definitions will be used. This works
|
||||
around the fact that ANSI C89 doesn't support an 'inline' keyword
|
||||
(although I hear C9x will ... about bloody time). At present, the
|
||||
macro definitions are identical to the function bodies, but they'll
|
||||
expand in place, instead of generating a function call.
|
||||
|
||||
I chose these particular functions to be made into macros because
|
||||
some profiling showed they are called a lot on a typical workload,
|
||||
and yet they are primarily housekeeping.
|
||||
*/
|
||||
#if MP_MACRO == 0
|
||||
void s_mp_setz(mp_digit *dp, mp_size count); /* zero digits */
|
||||
void s_mp_copy(const mp_digit *sp, mp_digit *dp, mp_size count); /* copy */
|
||||
void *s_mp_alloc(size_t nb, size_t ni); /* general allocator */
|
||||
void s_mp_free(void *ptr); /* general free function */
|
||||
extern unsigned long mp_allocs;
|
||||
extern unsigned long mp_frees;
|
||||
extern unsigned long mp_copies;
|
||||
#else
|
||||
|
||||
/* Even if these are defined as macros, we need to respect the settings
|
||||
of the MP_MEMSET and MP_MEMCPY configuration options...
|
||||
*/
|
||||
#if MP_MEMSET == 0
|
||||
#define s_mp_setz(dp, count) \
|
||||
{int ix;for(ix=0;ix<(count);ix++)(dp)[ix]=0;}
|
||||
#else
|
||||
#define s_mp_setz(dp, count) memset(dp, 0, (count) * sizeof(mp_digit))
|
||||
#endif /* MP_MEMSET */
|
||||
|
||||
#if MP_MEMCPY == 0
|
||||
#define s_mp_copy(sp, dp, count) \
|
||||
{int ix;for(ix=0;ix<(count);ix++)(dp)[ix]=(sp)[ix];}
|
||||
#else
|
||||
#define s_mp_copy(sp, dp, count) memcpy(dp, sp, (count) * sizeof(mp_digit))
|
||||
#endif /* MP_MEMCPY */
|
||||
|
||||
#define s_mp_alloc(nb, ni) calloc(nb, ni)
|
||||
#define s_mp_free(ptr) {if(ptr) free(ptr);}
|
||||
#endif /* MP_MACRO */
|
||||
|
||||
mp_err s_mp_grow(mp_int *mp, mp_size min); /* increase allocated size */
|
||||
mp_err s_mp_pad(mp_int *mp, mp_size min); /* left pad with zeroes */
|
||||
|
||||
#if MP_MACRO == 0
|
||||
void s_mp_clamp(mp_int *mp); /* clip leading zeroes */
|
||||
#else
|
||||
#define s_mp_clamp(mp)\
|
||||
{ mp_size used = MP_USED(mp); \
|
||||
while (used > 1 && DIGIT(mp, used - 1) == 0) --used; \
|
||||
MP_USED(mp) = used; \
|
||||
}
|
||||
#endif /* MP_MACRO */
|
||||
|
||||
void s_mp_exch(mp_int *a, mp_int *b); /* swap a and b in place */
|
||||
|
||||
mp_err s_mp_lshd(mp_int *mp, mp_size p); /* left-shift by p digits */
|
||||
void s_mp_rshd(mp_int *mp, mp_size p); /* right-shift by p digits */
|
||||
mp_err s_mp_mul_2d(mp_int *mp, mp_digit d); /* multiply by 2^d in place */
|
||||
void s_mp_div_2d(mp_int *mp, mp_digit d); /* divide by 2^d in place */
|
||||
void s_mp_mod_2d(mp_int *mp, mp_digit d); /* modulo 2^d in place */
|
||||
void s_mp_div_2(mp_int *mp); /* divide by 2 in place */
|
||||
mp_err s_mp_mul_2(mp_int *mp); /* multiply by 2 in place */
|
||||
mp_err s_mp_norm(mp_int *a, mp_int *b, mp_digit *pd);
|
||||
/* normalize for division */
|
||||
mp_err s_mp_add_d(mp_int *mp, mp_digit d); /* unsigned digit addition */
|
||||
mp_err s_mp_sub_d(mp_int *mp, mp_digit d); /* unsigned digit subtract */
|
||||
mp_err s_mp_mul_d(mp_int *mp, mp_digit d); /* unsigned digit multiply */
|
||||
mp_err s_mp_div_d(mp_int *mp, mp_digit d, mp_digit *r);
|
||||
/* unsigned digit divide */
|
||||
mp_err s_mp_reduce(mp_int *x, const mp_int *m, const mp_int *mu);
|
||||
/* Barrett reduction */
|
||||
mp_err s_mp_add(mp_int *a, const mp_int *b); /* magnitude addition */
|
||||
mp_err s_mp_add_3arg(const mp_int *a, const mp_int *b, mp_int *c);
|
||||
mp_err s_mp_sub(mp_int *a, const mp_int *b); /* magnitude subtract */
|
||||
mp_err s_mp_sub_3arg(const mp_int *a, const mp_int *b, mp_int *c);
|
||||
mp_err s_mp_add_offset(mp_int *a, mp_int *b, mp_size offset);
|
||||
/* a += b * RADIX^offset */
|
||||
mp_err s_mp_mul(mp_int *a, const mp_int *b); /* magnitude multiply */
|
||||
#if MP_SQUARE
|
||||
mp_err s_mp_sqr(mp_int *a); /* magnitude square */
|
||||
#else
|
||||
#define s_mp_sqr(a) s_mp_mul(a, a)
|
||||
#endif
|
||||
mp_err s_mp_div(mp_int *rem, mp_int *div, mp_int *quot); /* magnitude div */
|
||||
mp_err s_mp_exptmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c);
|
||||
mp_err s_mp_2expt(mp_int *a, mp_digit k); /* a = 2^k */
|
||||
int s_mp_cmp(const mp_int *a, const mp_int *b); /* magnitude comparison */
|
||||
int s_mp_cmp_d(const mp_int *a, mp_digit d); /* magnitude digit compare */
|
||||
int s_mp_ispow2(const mp_int *v); /* is v a power of 2? */
|
||||
int s_mp_ispow2d(mp_digit d); /* is d a power of 2? */
|
||||
|
||||
int s_mp_tovalue(char ch, int r); /* convert ch to value */
|
||||
char s_mp_todigit(mp_digit val, int r, int low); /* convert val to digit */
|
||||
int s_mp_outlen(int bits, int r); /* output length in bytes */
|
||||
mp_digit s_mp_invmod_radix(mp_digit P); /* returns (P ** -1) mod RADIX */
|
||||
mp_err s_mp_invmod_odd_m( const mp_int *a, const mp_int *m, mp_int *c);
|
||||
mp_err s_mp_invmod_2d( const mp_int *a, mp_size k, mp_int *c);
|
||||
mp_err s_mp_invmod_even_m(const mp_int *a, const mp_int *m, mp_int *c);
|
||||
|
||||
/* ------ mpv functions, operate on arrays of digits, not on mp_int's ------ */
|
||||
#if defined (__OS2__) && defined (__IBMC__)
|
||||
#define MPI_ASM_DECL __cdecl
|
||||
#else
|
||||
#define MPI_ASM_DECL
|
||||
#endif
|
||||
|
||||
#ifdef MPI_AMD64
|
||||
|
||||
mp_digit MPI_ASM_DECL s_mpv_mul_set_vec64(mp_digit*, mp_digit *, mp_size, mp_digit);
|
||||
mp_digit MPI_ASM_DECL s_mpv_mul_add_vec64(mp_digit*, const mp_digit*, mp_size, mp_digit);
|
||||
|
||||
/* c = a * b */
|
||||
#define s_mpv_mul_d(a, a_len, b, c) \
|
||||
((unsigned long*)c)[a_len] = s_mpv_mul_set_vec64(c, a, a_len, b)
|
||||
|
||||
/* c += a * b */
|
||||
#define s_mpv_mul_d_add(a, a_len, b, c) \
|
||||
((unsigned long*)c)[a_len] = s_mpv_mul_add_vec64(c, a, a_len, b)
|
||||
|
||||
#else
|
||||
|
||||
void MPI_ASM_DECL s_mpv_mul_d(const mp_digit *a, mp_size a_len,
|
||||
mp_digit b, mp_digit *c);
|
||||
void MPI_ASM_DECL s_mpv_mul_d_add(const mp_digit *a, mp_size a_len,
|
||||
mp_digit b, mp_digit *c);
|
||||
|
||||
#endif
|
||||
|
||||
void MPI_ASM_DECL s_mpv_mul_d_add_prop(const mp_digit *a,
|
||||
mp_size a_len, mp_digit b,
|
||||
mp_digit *c);
|
||||
void MPI_ASM_DECL s_mpv_sqr_add_prop(const mp_digit *a,
|
||||
mp_size a_len,
|
||||
mp_digit *sqrs);
|
||||
|
||||
mp_err MPI_ASM_DECL s_mpv_div_2dx1d(mp_digit Nhi, mp_digit Nlo,
|
||||
mp_digit divisor, mp_digit *quot, mp_digit *rem);
|
||||
|
||||
/* c += a * b * (MP_RADIX ** offset); */
|
||||
#define s_mp_mul_d_add_offset(a, b, c, off) \
|
||||
(s_mpv_mul_d_add_prop(MP_DIGITS(a), MP_USED(a), b, MP_DIGITS(c) + off), MP_OKAY)
|
||||
|
||||
typedef struct {
|
||||
mp_int N; /* modulus N */
|
||||
mp_digit n0prime; /* n0' = - (n0 ** -1) mod MP_RADIX */
|
||||
mp_size b; /* R == 2 ** b, also b = # significant bits in N */
|
||||
} mp_mont_modulus;
|
||||
|
||||
mp_err s_mp_mul_mont(const mp_int *a, const mp_int *b, mp_int *c,
|
||||
mp_mont_modulus *mmm);
|
||||
mp_err s_mp_redc(mp_int *T, mp_mont_modulus *mmm);
|
||||
|
||||
/* }}} */
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,349 +0,0 @@
|
||||
/*
|
||||
* mpi.h
|
||||
*
|
||||
* Arbitrary precision integer arithmetic library
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael J. Fromberger.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Netscape Communications Corporation
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: mpi.h,v 1.22.8.1 2005-06-09 20:44:58 relyea%netscape.com Exp $ */
|
||||
|
||||
#ifndef _H_MPI_
|
||||
#define _H_MPI_
|
||||
|
||||
#include "mpi-config.h"
|
||||
|
||||
#if MP_DEBUG
|
||||
#undef MP_IOFUNC
|
||||
#define MP_IOFUNC 1
|
||||
#endif
|
||||
|
||||
#if MP_IOFUNC
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#if defined(BSDI)
|
||||
#undef ULLONG_MAX
|
||||
#endif
|
||||
|
||||
#if defined( macintosh )
|
||||
#include <Types.h>
|
||||
#elif defined( _WIN32_WCE)
|
||||
/* #include <sys/types.h> What do we need here ?? */
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#define MP_NEG 1
|
||||
#define MP_ZPOS 0
|
||||
|
||||
#define MP_OKAY 0 /* no error, all is well */
|
||||
#define MP_YES 0 /* yes (boolean result) */
|
||||
#define MP_NO -1 /* no (boolean result) */
|
||||
#define MP_MEM -2 /* out of memory */
|
||||
#define MP_RANGE -3 /* argument out of range */
|
||||
#define MP_BADARG -4 /* invalid parameter */
|
||||
#define MP_UNDEF -5 /* answer is undefined */
|
||||
#define MP_LAST_CODE MP_UNDEF
|
||||
|
||||
typedef unsigned int mp_sign;
|
||||
typedef unsigned int mp_size;
|
||||
typedef int mp_err;
|
||||
|
||||
#define MP_32BIT_MAX 4294967295U
|
||||
|
||||
#if !defined(ULONG_MAX)
|
||||
#error "ULONG_MAX not defined"
|
||||
#elif !defined(UINT_MAX)
|
||||
#error "UINT_MAX not defined"
|
||||
#elif !defined(USHRT_MAX)
|
||||
#error "USHRT_MAX not defined"
|
||||
#endif
|
||||
|
||||
#if defined(ULONG_LONG_MAX) /* GCC, HPUX */
|
||||
#define MP_ULONG_LONG_MAX ULONG_LONG_MAX
|
||||
#elif defined(ULLONG_MAX) /* Solaris */
|
||||
#define MP_ULONG_LONG_MAX ULLONG_MAX
|
||||
/* MP_ULONG_LONG_MAX was defined to be ULLONG_MAX */
|
||||
#elif defined(ULONGLONG_MAX) /* IRIX, AIX */
|
||||
#define MP_ULONG_LONG_MAX ULONGLONG_MAX
|
||||
#endif
|
||||
|
||||
/* We only use unsigned long for mp_digit iff long is more than 32 bits. */
|
||||
#if !defined(MP_USE_UINT_DIGIT) && ULONG_MAX > MP_32BIT_MAX
|
||||
typedef unsigned long mp_digit;
|
||||
#define MP_DIGIT_MAX ULONG_MAX
|
||||
#define MP_DIGIT_FMT "%016lX" /* printf() format for 1 digit */
|
||||
#define MP_HALF_DIGIT_MAX UINT_MAX
|
||||
#undef MP_NO_MP_WORD
|
||||
#define MP_NO_MP_WORD 1
|
||||
#undef MP_USE_LONG_DIGIT
|
||||
#define MP_USE_LONG_DIGIT 1
|
||||
#undef MP_USE_LONG_LONG_DIGIT
|
||||
|
||||
#elif !defined(MP_USE_UINT_DIGIT) && defined(MP_ULONG_LONG_MAX)
|
||||
typedef unsigned long long mp_digit;
|
||||
#define MP_DIGIT_MAX MP_ULONG_LONG_MAX
|
||||
#define MP_DIGIT_FMT "%016llX" /* printf() format for 1 digit */
|
||||
#define MP_HALF_DIGIT_MAX UINT_MAX
|
||||
#undef MP_NO_MP_WORD
|
||||
#define MP_NO_MP_WORD 1
|
||||
#undef MP_USE_LONG_LONG_DIGIT
|
||||
#define MP_USE_LONG_LONG_DIGIT 1
|
||||
#undef MP_USE_LONG_DIGIT
|
||||
|
||||
#else
|
||||
typedef unsigned int mp_digit;
|
||||
#define MP_DIGIT_MAX UINT_MAX
|
||||
#define MP_DIGIT_FMT "%08X" /* printf() format for 1 digit */
|
||||
#define MP_HALF_DIGIT_MAX USHRT_MAX
|
||||
#undef MP_USE_UINT_DIGIT
|
||||
#define MP_USE_UINT_DIGIT 1
|
||||
#undef MP_USE_LONG_LONG_DIGIT
|
||||
#undef MP_USE_LONG_DIGIT
|
||||
#endif
|
||||
|
||||
#if !defined(MP_NO_MP_WORD)
|
||||
#if defined(MP_USE_UINT_DIGIT) && \
|
||||
(defined(MP_ULONG_LONG_MAX) || (ULONG_MAX > UINT_MAX))
|
||||
|
||||
#if (ULONG_MAX > UINT_MAX)
|
||||
typedef unsigned long mp_word;
|
||||
typedef long mp_sword;
|
||||
#define MP_WORD_MAX ULONG_MAX
|
||||
|
||||
#else
|
||||
typedef unsigned long long mp_word;
|
||||
typedef long long mp_sword;
|
||||
#define MP_WORD_MAX MP_ULONG_LONG_MAX
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define MP_NO_MP_WORD 1
|
||||
#endif
|
||||
#endif /* !defined(MP_NO_MP_WORD) */
|
||||
|
||||
#if !defined(MP_WORD_MAX) && defined(MP_DEFINE_SMALL_WORD)
|
||||
typedef unsigned int mp_word;
|
||||
typedef int mp_sword;
|
||||
#define MP_WORD_MAX UINT_MAX
|
||||
#endif
|
||||
|
||||
#define MP_DIGIT_BIT (CHAR_BIT*sizeof(mp_digit))
|
||||
#define MP_WORD_BIT (CHAR_BIT*sizeof(mp_word))
|
||||
#define MP_RADIX (1+(mp_word)MP_DIGIT_MAX)
|
||||
|
||||
#define MP_HALF_DIGIT_BIT (MP_DIGIT_BIT/2)
|
||||
#define MP_HALF_RADIX (1+(mp_digit)MP_HALF_DIGIT_MAX)
|
||||
/* MP_HALF_RADIX really ought to be called MP_SQRT_RADIX, but it's named
|
||||
** MP_HALF_RADIX because it's the radix for MP_HALF_DIGITs, and it's
|
||||
** consistent with the other _HALF_ names.
|
||||
*/
|
||||
|
||||
|
||||
/* Macros for accessing the mp_int internals */
|
||||
#define MP_SIGN(MP) ((MP)->sign)
|
||||
#define MP_USED(MP) ((MP)->used)
|
||||
#define MP_ALLOC(MP) ((MP)->alloc)
|
||||
#define MP_DIGITS(MP) ((MP)->dp)
|
||||
#define MP_DIGIT(MP,N) (MP)->dp[(N)]
|
||||
|
||||
/* This defines the maximum I/O base (minimum is 2) */
|
||||
#define MP_MAX_RADIX 64
|
||||
|
||||
typedef struct {
|
||||
mp_sign sign; /* sign of this quantity */
|
||||
mp_size alloc; /* how many digits allocated */
|
||||
mp_size used; /* how many digits used */
|
||||
mp_digit *dp; /* the digits themselves */
|
||||
} mp_int;
|
||||
|
||||
/* Default precision */
|
||||
mp_size mp_get_prec(void);
|
||||
void mp_set_prec(mp_size prec);
|
||||
|
||||
/* Memory management */
|
||||
mp_err mp_init(mp_int *mp);
|
||||
mp_err mp_init_size(mp_int *mp, mp_size prec);
|
||||
mp_err mp_init_copy(mp_int *mp, const mp_int *from);
|
||||
mp_err mp_copy(const mp_int *from, mp_int *to);
|
||||
void mp_exch(mp_int *mp1, mp_int *mp2);
|
||||
void mp_clear(mp_int *mp);
|
||||
void mp_zero(mp_int *mp);
|
||||
void mp_set(mp_int *mp, mp_digit d);
|
||||
mp_err mp_set_int(mp_int *mp, long z);
|
||||
#define mp_set_long(mp,z) mp_set_int(mp,z)
|
||||
mp_err mp_set_ulong(mp_int *mp, unsigned long z);
|
||||
|
||||
/* Single digit arithmetic */
|
||||
mp_err mp_add_d(const mp_int *a, mp_digit d, mp_int *b);
|
||||
mp_err mp_sub_d(const mp_int *a, mp_digit d, mp_int *b);
|
||||
mp_err mp_mul_d(const mp_int *a, mp_digit d, mp_int *b);
|
||||
mp_err mp_mul_2(const mp_int *a, mp_int *c);
|
||||
mp_err mp_div_d(const mp_int *a, mp_digit d, mp_int *q, mp_digit *r);
|
||||
mp_err mp_div_2(const mp_int *a, mp_int *c);
|
||||
mp_err mp_expt_d(const mp_int *a, mp_digit d, mp_int *c);
|
||||
|
||||
/* Sign manipulations */
|
||||
mp_err mp_abs(const mp_int *a, mp_int *b);
|
||||
mp_err mp_neg(const mp_int *a, mp_int *b);
|
||||
|
||||
/* Full arithmetic */
|
||||
mp_err mp_add(const mp_int *a, const mp_int *b, mp_int *c);
|
||||
mp_err mp_sub(const mp_int *a, const mp_int *b, mp_int *c);
|
||||
mp_err mp_mul(const mp_int *a, const mp_int *b, mp_int *c);
|
||||
#if MP_SQUARE
|
||||
mp_err mp_sqr(const mp_int *a, mp_int *b);
|
||||
#else
|
||||
#define mp_sqr(a, b) mp_mul(a, a, b)
|
||||
#endif
|
||||
mp_err mp_div(const mp_int *a, const mp_int *b, mp_int *q, mp_int *r);
|
||||
mp_err mp_div_2d(const mp_int *a, mp_digit d, mp_int *q, mp_int *r);
|
||||
mp_err mp_expt(mp_int *a, mp_int *b, mp_int *c);
|
||||
mp_err mp_2expt(mp_int *a, mp_digit k);
|
||||
mp_err mp_sqrt(const mp_int *a, mp_int *b);
|
||||
|
||||
/* Modular arithmetic */
|
||||
#if MP_MODARITH
|
||||
mp_err mp_mod(const mp_int *a, const mp_int *m, mp_int *c);
|
||||
mp_err mp_mod_d(const mp_int *a, mp_digit d, mp_digit *c);
|
||||
mp_err mp_addmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c);
|
||||
mp_err mp_submod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c);
|
||||
mp_err mp_mulmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c);
|
||||
#if MP_SQUARE
|
||||
mp_err mp_sqrmod(const mp_int *a, const mp_int *m, mp_int *c);
|
||||
#else
|
||||
#define mp_sqrmod(a, m, c) mp_mulmod(a, a, m, c)
|
||||
#endif
|
||||
mp_err mp_exptmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c);
|
||||
mp_err mp_exptmod_d(const mp_int *a, mp_digit d, const mp_int *m, mp_int *c);
|
||||
#endif /* MP_MODARITH */
|
||||
|
||||
/* Comparisons */
|
||||
int mp_cmp_z(const mp_int *a);
|
||||
int mp_cmp_d(const mp_int *a, mp_digit d);
|
||||
int mp_cmp(const mp_int *a, const mp_int *b);
|
||||
int mp_cmp_mag(mp_int *a, mp_int *b);
|
||||
int mp_cmp_int(const mp_int *a, long z);
|
||||
int mp_isodd(const mp_int *a);
|
||||
int mp_iseven(const mp_int *a);
|
||||
|
||||
/* Number theoretic */
|
||||
#if MP_NUMTH
|
||||
mp_err mp_gcd(mp_int *a, mp_int *b, mp_int *c);
|
||||
mp_err mp_lcm(mp_int *a, mp_int *b, mp_int *c);
|
||||
mp_err mp_xgcd(const mp_int *a, const mp_int *b, mp_int *g, mp_int *x, mp_int *y);
|
||||
mp_err mp_invmod(const mp_int *a, const mp_int *m, mp_int *c);
|
||||
mp_err mp_invmod_xgcd(const mp_int *a, const mp_int *m, mp_int *c);
|
||||
#endif /* end MP_NUMTH */
|
||||
|
||||
/* Input and output */
|
||||
#if MP_IOFUNC
|
||||
void mp_print(mp_int *mp, FILE *ofp);
|
||||
#endif /* end MP_IOFUNC */
|
||||
|
||||
/* Base conversion */
|
||||
mp_err mp_read_raw(mp_int *mp, char *str, int len);
|
||||
int mp_raw_size(mp_int *mp);
|
||||
mp_err mp_toraw(mp_int *mp, char *str);
|
||||
mp_err mp_read_radix(mp_int *mp, const char *str, int radix);
|
||||
mp_err mp_read_variable_radix(mp_int *a, const char * str, int default_radix);
|
||||
int mp_radix_size(mp_int *mp, int radix);
|
||||
mp_err mp_toradix(mp_int *mp, char *str, int radix);
|
||||
int mp_tovalue(char ch, int r);
|
||||
|
||||
#define mp_tobinary(M, S) mp_toradix((M), (S), 2)
|
||||
#define mp_tooctal(M, S) mp_toradix((M), (S), 8)
|
||||
#define mp_todecimal(M, S) mp_toradix((M), (S), 10)
|
||||
#define mp_tohex(M, S) mp_toradix((M), (S), 16)
|
||||
|
||||
/* Error strings */
|
||||
const char *mp_strerror(mp_err ec);
|
||||
|
||||
/* Octet string conversion functions */
|
||||
mp_err mp_read_unsigned_octets(mp_int *mp, const unsigned char *str, mp_size len);
|
||||
int mp_unsigned_octet_size(const mp_int *mp);
|
||||
mp_err mp_to_unsigned_octets(const mp_int *mp, unsigned char *str, mp_size maxlen);
|
||||
mp_err mp_to_signed_octets(const mp_int *mp, unsigned char *str, mp_size maxlen);
|
||||
mp_err mp_to_fixlen_octets(const mp_int *mp, unsigned char *str, mp_size len);
|
||||
|
||||
/* Miscellaneous */
|
||||
mp_size mp_trailing_zeros(const mp_int *mp);
|
||||
|
||||
#define MP_CHECKOK(x) if (MP_OKAY > (res = (x))) goto CLEANUP
|
||||
#define MP_CHECKERR(x) if (MP_OKAY > (res = (x))) goto CLEANUP
|
||||
|
||||
#if defined(MP_API_COMPATIBLE)
|
||||
#define NEG MP_NEG
|
||||
#define ZPOS MP_ZPOS
|
||||
#define DIGIT_MAX MP_DIGIT_MAX
|
||||
#define DIGIT_BIT MP_DIGIT_BIT
|
||||
#define DIGIT_FMT MP_DIGIT_FMT
|
||||
#define RADIX MP_RADIX
|
||||
#define MAX_RADIX MP_MAX_RADIX
|
||||
#define SIGN(MP) MP_SIGN(MP)
|
||||
#define USED(MP) MP_USED(MP)
|
||||
#define ALLOC(MP) MP_ALLOC(MP)
|
||||
#define DIGITS(MP) MP_DIGITS(MP)
|
||||
#define DIGIT(MP,N) MP_DIGIT(MP,N)
|
||||
|
||||
#if MP_ARGCHK == 1
|
||||
#define ARGCHK(X,Y) {if(!(X)){return (Y);}}
|
||||
#elif MP_ARGCHK == 2
|
||||
#include <assert.h>
|
||||
#define ARGCHK(X,Y) assert(X)
|
||||
#else
|
||||
#define ARGCHK(X,Y) /* */
|
||||
#endif
|
||||
#endif /* defined MP_API_COMPATIBLE */
|
||||
|
||||
/*
|
||||
* mpi_getProcessorLineSize() returns the size in bytes of the cache line
|
||||
* if a cache exists, or zero if there is no cache. If more than one
|
||||
* cache line exists, it should return the smallest line size (which is
|
||||
* usually the L1 cache).
|
||||
*
|
||||
* mp_modexp uses this information to make sure that private key information
|
||||
* isn't being leaked through the cache.
|
||||
*
|
||||
* see mpcpucache.c for the implementation.
|
||||
*/
|
||||
unsigned long mpi_getProcessorLineSize();
|
||||
|
||||
#endif /* end _H_MPI_ */
|
||||
@@ -1,418 +0,0 @@
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Solaris software cryptographic token.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Sun Microsystems, Inc.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2005
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Sun Microsystems, Inc.
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------
|
||||
#
|
||||
# Implementation of s_mpv_mul_set_vec which exploits
|
||||
# the 64X64->128 bit unsigned multiply instruction.
|
||||
#
|
||||
# ------------------------------------------------------------------------
|
||||
|
||||
# r = a * digit, r and a are vectors of length len
|
||||
# returns the carry digit
|
||||
# r and a are 64 bit aligned.
|
||||
#
|
||||
# uint64_t
|
||||
# s_mpv_mul_set_vec64(uint64_t *r, uint64_t *a, int len, uint64_t digit)
|
||||
#
|
||||
|
||||
.text; .align 16; .globl s_mpv_mul_set_vec64; .type s_mpv_mul_set_vec64, @function; s_mpv_mul_set_vec64:
|
||||
|
||||
xorq %rax, %rax # if (len == 0) return (0)
|
||||
testq %rdx, %rdx
|
||||
jz .L17
|
||||
|
||||
movq %rdx, %r8 # Use r8 for len; %rdx is used by mul
|
||||
xorq %r9, %r9 # cy = 0
|
||||
|
||||
.L15:
|
||||
cmpq $8, %r8 # 8 - len
|
||||
jb .L16
|
||||
movq 0(%rsi), %rax # rax = a[0]
|
||||
movq 8(%rsi), %r11 # prefetch a[1]
|
||||
mulq %rcx # p = a[0] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 0(%rdi) # r[0] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 16(%rsi), %r11 # prefetch a[2]
|
||||
mulq %rcx # p = a[1] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 8(%rdi) # r[1] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 24(%rsi), %r11 # prefetch a[3]
|
||||
mulq %rcx # p = a[2] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 16(%rdi) # r[2] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 32(%rsi), %r11 # prefetch a[4]
|
||||
mulq %rcx # p = a[3] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 24(%rdi) # r[3] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 40(%rsi), %r11 # prefetch a[5]
|
||||
mulq %rcx # p = a[4] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 32(%rdi) # r[4] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 48(%rsi), %r11 # prefetch a[6]
|
||||
mulq %rcx # p = a[5] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 40(%rdi) # r[5] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 56(%rsi), %r11 # prefetch a[7]
|
||||
mulq %rcx # p = a[6] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 48(%rdi) # r[6] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
mulq %rcx # p = a[7] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 56(%rdi) # r[7] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
|
||||
addq $64, %rsi
|
||||
addq $64, %rdi
|
||||
subq $8, %r8
|
||||
|
||||
jz .L17
|
||||
jmp .L15
|
||||
|
||||
.L16:
|
||||
movq 0(%rsi), %rax
|
||||
mulq %rcx # p = a[0] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 0(%rdi) # r[0] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
decq %r8
|
||||
jz .L17
|
||||
|
||||
movq 8(%rsi), %rax
|
||||
mulq %rcx # p = a[1] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 8(%rdi) # r[1] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
decq %r8
|
||||
jz .L17
|
||||
|
||||
movq 16(%rsi), %rax
|
||||
mulq %rcx # p = a[2] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 16(%rdi) # r[2] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
decq %r8
|
||||
jz .L17
|
||||
|
||||
movq 24(%rsi), %rax
|
||||
mulq %rcx # p = a[3] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 24(%rdi) # r[3] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
decq %r8
|
||||
jz .L17
|
||||
|
||||
movq 32(%rsi), %rax
|
||||
mulq %rcx # p = a[4] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 32(%rdi) # r[4] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
decq %r8
|
||||
jz .L17
|
||||
|
||||
movq 40(%rsi), %rax
|
||||
mulq %rcx # p = a[5] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 40(%rdi) # r[5] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
decq %r8
|
||||
jz .L17
|
||||
|
||||
movq 48(%rsi), %rax
|
||||
mulq %rcx # p = a[6] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 48(%rdi) # r[6] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
decq %r8
|
||||
jz .L17
|
||||
|
||||
|
||||
.L17:
|
||||
movq %r9, %rax
|
||||
ret
|
||||
|
||||
.size s_mpv_mul_set_vec64, [.-s_mpv_mul_set_vec64]
|
||||
|
||||
# ------------------------------------------------------------------------
|
||||
#
|
||||
# Implementation of s_mpv_mul_add_vec which exploits
|
||||
# the 64X64->128 bit unsigned multiply instruction.
|
||||
#
|
||||
# ------------------------------------------------------------------------
|
||||
|
||||
# r += a * digit, r and a are vectors of length len
|
||||
# returns the carry digit
|
||||
# r and a are 64 bit aligned.
|
||||
#
|
||||
# uint64_t
|
||||
# s_mpv_mul_add_vec64(uint64_t *r, uint64_t *a, int len, uint64_t digit)
|
||||
#
|
||||
|
||||
.text; .align 16; .globl s_mpv_mul_add_vec64; .type s_mpv_mul_add_vec64, @function; s_mpv_mul_add_vec64:
|
||||
|
||||
xorq %rax, %rax # if (len == 0) return (0)
|
||||
testq %rdx, %rdx
|
||||
jz .L27
|
||||
|
||||
movq %rdx, %r8 # Use r8 for len; %rdx is used by mul
|
||||
xorq %r9, %r9 # cy = 0
|
||||
|
||||
.L25:
|
||||
cmpq $8, %r8 # 8 - len
|
||||
jb .L26
|
||||
movq 0(%rsi), %rax # rax = a[0]
|
||||
movq 0(%rdi), %r10 # r10 = r[0]
|
||||
movq 8(%rsi), %r11 # prefetch a[1]
|
||||
mulq %rcx # p = a[0] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx # p += r[0]
|
||||
movq 8(%rdi), %r10 # prefetch r[1]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 0(%rdi) # r[0] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 16(%rsi), %r11 # prefetch a[2]
|
||||
mulq %rcx # p = a[1] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx # p += r[1]
|
||||
movq 16(%rdi), %r10 # prefetch r[2]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 8(%rdi) # r[1] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 24(%rsi), %r11 # prefetch a[3]
|
||||
mulq %rcx # p = a[2] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx # p += r[2]
|
||||
movq 24(%rdi), %r10 # prefetch r[3]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 16(%rdi) # r[2] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 32(%rsi), %r11 # prefetch a[4]
|
||||
mulq %rcx # p = a[3] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx # p += r[3]
|
||||
movq 32(%rdi), %r10 # prefetch r[4]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 24(%rdi) # r[3] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 40(%rsi), %r11 # prefetch a[5]
|
||||
mulq %rcx # p = a[4] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx # p += r[4]
|
||||
movq 40(%rdi), %r10 # prefetch r[5]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 32(%rdi) # r[4] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 48(%rsi), %r11 # prefetch a[6]
|
||||
mulq %rcx # p = a[5] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx # p += r[5]
|
||||
movq 48(%rdi), %r10 # prefetch r[6]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 40(%rdi) # r[5] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 56(%rsi), %r11 # prefetch a[7]
|
||||
mulq %rcx # p = a[6] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx # p += r[6]
|
||||
movq 56(%rdi), %r10 # prefetch r[7]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 48(%rdi) # r[6] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
mulq %rcx # p = a[7] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx # p += r[7]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 56(%rdi) # r[7] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
|
||||
addq $64, %rsi
|
||||
addq $64, %rdi
|
||||
subq $8, %r8
|
||||
|
||||
jz .L27
|
||||
jmp .L25
|
||||
|
||||
.L26:
|
||||
movq 0(%rsi), %rax
|
||||
movq 0(%rdi), %r10
|
||||
mulq %rcx # p = a[0] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx # p += r[0]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 0(%rdi) # r[0] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
decq %r8
|
||||
jz .L27
|
||||
|
||||
movq 8(%rsi), %rax
|
||||
movq 8(%rdi), %r10
|
||||
mulq %rcx # p = a[1] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx # p += r[1]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 8(%rdi) # r[1] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
decq %r8
|
||||
jz .L27
|
||||
|
||||
movq 16(%rsi), %rax
|
||||
movq 16(%rdi), %r10
|
||||
mulq %rcx # p = a[2] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx # p += r[2]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 16(%rdi) # r[2] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
decq %r8
|
||||
jz .L27
|
||||
|
||||
movq 24(%rsi), %rax
|
||||
movq 24(%rdi), %r10
|
||||
mulq %rcx # p = a[3] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx # p += r[3]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 24(%rdi) # r[3] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
decq %r8
|
||||
jz .L27
|
||||
|
||||
movq 32(%rsi), %rax
|
||||
movq 32(%rdi), %r10
|
||||
mulq %rcx # p = a[4] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx # p += r[4]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 32(%rdi) # r[4] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
decq %r8
|
||||
jz .L27
|
||||
|
||||
movq 40(%rsi), %rax
|
||||
movq 40(%rdi), %r10
|
||||
mulq %rcx # p = a[5] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx # p += r[5]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 40(%rdi) # r[5] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
decq %r8
|
||||
jz .L27
|
||||
|
||||
movq 48(%rsi), %rax
|
||||
movq 48(%rdi), %r10
|
||||
mulq %rcx # p = a[6] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx # p += r[6]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 48(%rdi) # r[6] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
decq %r8
|
||||
jz .L27
|
||||
|
||||
|
||||
.L27:
|
||||
movq %r9, %rax
|
||||
ret
|
||||
|
||||
.size s_mpv_mul_add_vec64, [.-s_mpv_mul_add_vec64]
|
||||
@@ -1,418 +0,0 @@
|
||||
/ ***** BEGIN LICENSE BLOCK *****
|
||||
/ Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
/
|
||||
/ The contents of this file are subject to the Mozilla Public License Version
|
||||
/ 1.1 (the "License"); you may not use this file except in compliance with
|
||||
/ the License. You may obtain a copy of the License at
|
||||
/ http://www.mozilla.org/MPL/
|
||||
/
|
||||
/ Software distributed under the License is distributed on an "AS IS" basis,
|
||||
/ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
/ for the specific language governing rights and limitations under the
|
||||
/ License.
|
||||
/
|
||||
/ The Original Code is the Solaris software cryptographic token.
|
||||
/
|
||||
/ The Initial Developer of the Original Code is
|
||||
/ Sun Microsystems, Inc.
|
||||
/ Portions created by the Initial Developer are Copyright (C) 2005
|
||||
/ the Initial Developer. All Rights Reserved.
|
||||
/
|
||||
/ Contributor(s):
|
||||
/ Sun Microsystems, Inc.
|
||||
/
|
||||
/ Alternatively, the contents of this file may be used under the terms of
|
||||
/ either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
/ the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
/ in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
/ of those above. If you wish to allow use of your version of this file only
|
||||
/ under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
/ use your version of this file under the terms of the MPL, indicate your
|
||||
/ decision by deleting the provisions above and replace them with the notice
|
||||
/ and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
/ the provisions above, a recipient may use your version of this file under
|
||||
/ the terms of any one of the MPL, the GPL or the LGPL.
|
||||
/
|
||||
/ ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
/ ------------------------------------------------------------------------
|
||||
/
|
||||
/ Implementation of s_mpv_mul_set_vec which exploits
|
||||
/ the 64X64->128 bit unsigned multiply instruction.
|
||||
/
|
||||
/ ------------------------------------------------------------------------
|
||||
|
||||
/ r = a * digit, r and a are vectors of length len
|
||||
/ returns the carry digit
|
||||
/ r and a are 64 bit aligned.
|
||||
/
|
||||
/ uint64_t
|
||||
/ s_mpv_mul_set_vec64(uint64_t *r, uint64_t *a, int len, uint64_t digit)
|
||||
/
|
||||
|
||||
.text; .align 16; .globl s_mpv_mul_set_vec64; .type s_mpv_mul_set_vec64, @function; s_mpv_mul_set_vec64:
|
||||
|
||||
xorq %rax, %rax / if (len == 0) return (0)
|
||||
testq %rdx, %rdx
|
||||
jz .L17
|
||||
|
||||
movq %rdx, %r8 / Use r8 for len; %rdx is used by mul
|
||||
xorq %r9, %r9 / cy = 0
|
||||
|
||||
.L15:
|
||||
cmpq $8, %r8 / 8 - len
|
||||
jb .L16
|
||||
movq 0(%rsi), %rax / rax = a[0]
|
||||
movq 8(%rsi), %r11 / prefetch a[1]
|
||||
mulq %rcx / p = a[0] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 0(%rdi) / r[0] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 16(%rsi), %r11 / prefetch a[2]
|
||||
mulq %rcx / p = a[1] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 8(%rdi) / r[1] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 24(%rsi), %r11 / prefetch a[3]
|
||||
mulq %rcx / p = a[2] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 16(%rdi) / r[2] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 32(%rsi), %r11 / prefetch a[4]
|
||||
mulq %rcx / p = a[3] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 24(%rdi) / r[3] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 40(%rsi), %r11 / prefetch a[5]
|
||||
mulq %rcx / p = a[4] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 32(%rdi) / r[4] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 48(%rsi), %r11 / prefetch a[6]
|
||||
mulq %rcx / p = a[5] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 40(%rdi) / r[5] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 56(%rsi), %r11 / prefetch a[7]
|
||||
mulq %rcx / p = a[6] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 48(%rdi) / r[6] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
mulq %rcx / p = a[7] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 56(%rdi) / r[7] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
|
||||
addq $64, %rsi
|
||||
addq $64, %rdi
|
||||
subq $8, %r8
|
||||
|
||||
jz .L17
|
||||
jmp .L15
|
||||
|
||||
.L16:
|
||||
movq 0(%rsi), %rax
|
||||
mulq %rcx / p = a[0] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 0(%rdi) / r[0] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
decq %r8
|
||||
jz .L17
|
||||
|
||||
movq 8(%rsi), %rax
|
||||
mulq %rcx / p = a[1] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 8(%rdi) / r[1] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
decq %r8
|
||||
jz .L17
|
||||
|
||||
movq 16(%rsi), %rax
|
||||
mulq %rcx / p = a[2] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 16(%rdi) / r[2] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
decq %r8
|
||||
jz .L17
|
||||
|
||||
movq 24(%rsi), %rax
|
||||
mulq %rcx / p = a[3] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 24(%rdi) / r[3] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
decq %r8
|
||||
jz .L17
|
||||
|
||||
movq 32(%rsi), %rax
|
||||
mulq %rcx / p = a[4] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 32(%rdi) / r[4] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
decq %r8
|
||||
jz .L17
|
||||
|
||||
movq 40(%rsi), %rax
|
||||
mulq %rcx / p = a[5] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 40(%rdi) / r[5] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
decq %r8
|
||||
jz .L17
|
||||
|
||||
movq 48(%rsi), %rax
|
||||
mulq %rcx / p = a[6] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 48(%rdi) / r[6] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
decq %r8
|
||||
jz .L17
|
||||
|
||||
|
||||
.L17:
|
||||
movq %r9, %rax
|
||||
ret
|
||||
|
||||
.size s_mpv_mul_set_vec64, [.-s_mpv_mul_set_vec64]
|
||||
|
||||
/ ------------------------------------------------------------------------
|
||||
/
|
||||
/ Implementation of s_mpv_mul_add_vec which exploits
|
||||
/ the 64X64->128 bit unsigned multiply instruction.
|
||||
/
|
||||
/ ------------------------------------------------------------------------
|
||||
|
||||
/ r += a * digit, r and a are vectors of length len
|
||||
/ returns the carry digit
|
||||
/ r and a are 64 bit aligned.
|
||||
/
|
||||
/ uint64_t
|
||||
/ s_mpv_mul_add_vec64(uint64_t *r, uint64_t *a, int len, uint64_t digit)
|
||||
/
|
||||
|
||||
.text; .align 16; .globl s_mpv_mul_add_vec64; .type s_mpv_mul_add_vec64, @function; s_mpv_mul_add_vec64:
|
||||
|
||||
xorq %rax, %rax / if (len == 0) return (0)
|
||||
testq %rdx, %rdx
|
||||
jz .L27
|
||||
|
||||
movq %rdx, %r8 / Use r8 for len; %rdx is used by mul
|
||||
xorq %r9, %r9 / cy = 0
|
||||
|
||||
.L25:
|
||||
cmpq $8, %r8 / 8 - len
|
||||
jb .L26
|
||||
movq 0(%rsi), %rax / rax = a[0]
|
||||
movq 0(%rdi), %r10 / r10 = r[0]
|
||||
movq 8(%rsi), %r11 / prefetch a[1]
|
||||
mulq %rcx / p = a[0] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx / p += r[0]
|
||||
movq 8(%rdi), %r10 / prefetch r[1]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 0(%rdi) / r[0] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 16(%rsi), %r11 / prefetch a[2]
|
||||
mulq %rcx / p = a[1] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx / p += r[1]
|
||||
movq 16(%rdi), %r10 / prefetch r[2]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 8(%rdi) / r[1] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 24(%rsi), %r11 / prefetch a[3]
|
||||
mulq %rcx / p = a[2] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx / p += r[2]
|
||||
movq 24(%rdi), %r10 / prefetch r[3]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 16(%rdi) / r[2] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 32(%rsi), %r11 / prefetch a[4]
|
||||
mulq %rcx / p = a[3] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx / p += r[3]
|
||||
movq 32(%rdi), %r10 / prefetch r[4]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 24(%rdi) / r[3] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 40(%rsi), %r11 / prefetch a[5]
|
||||
mulq %rcx / p = a[4] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx / p += r[4]
|
||||
movq 40(%rdi), %r10 / prefetch r[5]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 32(%rdi) / r[4] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 48(%rsi), %r11 / prefetch a[6]
|
||||
mulq %rcx / p = a[5] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx / p += r[5]
|
||||
movq 48(%rdi), %r10 / prefetch r[6]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 40(%rdi) / r[5] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 56(%rsi), %r11 / prefetch a[7]
|
||||
mulq %rcx / p = a[6] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx / p += r[6]
|
||||
movq 56(%rdi), %r10 / prefetch r[7]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 48(%rdi) / r[6] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
mulq %rcx / p = a[7] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx / p += r[7]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 56(%rdi) / r[7] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
|
||||
addq $64, %rsi
|
||||
addq $64, %rdi
|
||||
subq $8, %r8
|
||||
|
||||
jz .L27
|
||||
jmp .L25
|
||||
|
||||
.L26:
|
||||
movq 0(%rsi), %rax
|
||||
movq 0(%rdi), %r10
|
||||
mulq %rcx / p = a[0] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx / p += r[0]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 0(%rdi) / r[0] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
decq %r8
|
||||
jz .L27
|
||||
|
||||
movq 8(%rsi), %rax
|
||||
movq 8(%rdi), %r10
|
||||
mulq %rcx / p = a[1] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx / p += r[1]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 8(%rdi) / r[1] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
decq %r8
|
||||
jz .L27
|
||||
|
||||
movq 16(%rsi), %rax
|
||||
movq 16(%rdi), %r10
|
||||
mulq %rcx / p = a[2] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx / p += r[2]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 16(%rdi) / r[2] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
decq %r8
|
||||
jz .L27
|
||||
|
||||
movq 24(%rsi), %rax
|
||||
movq 24(%rdi), %r10
|
||||
mulq %rcx / p = a[3] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx / p += r[3]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 24(%rdi) / r[3] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
decq %r8
|
||||
jz .L27
|
||||
|
||||
movq 32(%rsi), %rax
|
||||
movq 32(%rdi), %r10
|
||||
mulq %rcx / p = a[4] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx / p += r[4]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 32(%rdi) / r[4] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
decq %r8
|
||||
jz .L27
|
||||
|
||||
movq 40(%rsi), %rax
|
||||
movq 40(%rdi), %r10
|
||||
mulq %rcx / p = a[5] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx / p += r[5]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 40(%rdi) / r[5] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
decq %r8
|
||||
jz .L27
|
||||
|
||||
movq 48(%rsi), %rax
|
||||
movq 48(%rdi), %r10
|
||||
mulq %rcx / p = a[6] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx / p += r[6]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 48(%rdi) / r[6] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
decq %r8
|
||||
jz .L27
|
||||
|
||||
|
||||
.L27:
|
||||
movq %r9, %rax
|
||||
ret
|
||||
|
||||
.size s_mpv_mul_add_vec64, [.-s_mpv_mul_add_vec64]
|
||||
@@ -1,115 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: mpi_hp.c,v 1.5 2004-04-27 23:04:36 gerv%gerv.net Exp $ */
|
||||
|
||||
/* This file contains routines that perform vector multiplication. */
|
||||
|
||||
#include "mpi-priv.h"
|
||||
#include <unistd.h>
|
||||
|
||||
#include <stddef.h>
|
||||
/* #include <sys/systeminfo.h> */
|
||||
#include <strings.h>
|
||||
|
||||
extern void multacc512(
|
||||
int length, /* doublewords in multiplicand vector. */
|
||||
const mp_digit *scalaraddr, /* Address of scalar. */
|
||||
const mp_digit *multiplicand, /* The multiplicand vector. */
|
||||
mp_digit * result); /* Where to accumulate the result. */
|
||||
|
||||
extern void maxpy_little(
|
||||
int length, /* doublewords in multiplicand vector. */
|
||||
const mp_digit *scalaraddr, /* Address of scalar. */
|
||||
const mp_digit *multiplicand, /* The multiplicand vector. */
|
||||
mp_digit * result); /* Where to accumulate the result. */
|
||||
|
||||
extern void add_diag_little(
|
||||
int length, /* doublewords in input vector. */
|
||||
const mp_digit *root, /* The vector to square. */
|
||||
mp_digit * result); /* Where to accumulate the result. */
|
||||
|
||||
void
|
||||
s_mpv_sqr_add_prop(const mp_digit *pa, mp_size a_len, mp_digit *ps)
|
||||
{
|
||||
add_diag_little(a_len, pa, ps);
|
||||
}
|
||||
|
||||
#define MAX_STACK_DIGITS 258
|
||||
#define MULTACC512_LEN (512 / MP_DIGIT_BIT)
|
||||
#define HP_MPY_ADD_FN (a_len == MULTACC512_LEN ? multacc512 : maxpy_little)
|
||||
|
||||
/* c = a * b */
|
||||
void
|
||||
s_mpv_mul_d(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
|
||||
{
|
||||
mp_digit x[MAX_STACK_DIGITS];
|
||||
mp_digit *px = x;
|
||||
size_t xSize = 0;
|
||||
|
||||
if (a == c) {
|
||||
if (a_len > MAX_STACK_DIGITS) {
|
||||
xSize = sizeof(mp_digit) * (a_len + 2);
|
||||
px = malloc(xSize);
|
||||
if (!px)
|
||||
return;
|
||||
}
|
||||
memcpy(px, a, a_len * sizeof(*a));
|
||||
a = px;
|
||||
}
|
||||
s_mp_setz(c, a_len + 1);
|
||||
HP_MPY_ADD_FN(a_len, &b, a, c);
|
||||
if (px != x && px) {
|
||||
memset(px, 0, xSize);
|
||||
free(px);
|
||||
}
|
||||
}
|
||||
|
||||
/* c += a * b, where a is a_len words long. */
|
||||
void
|
||||
s_mpv_mul_d_add(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
|
||||
{
|
||||
c[a_len] = 0; /* so carry propagation stops here. */
|
||||
HP_MPY_ADD_FN(a_len, &b, a, c);
|
||||
}
|
||||
|
||||
/* c += a * b, where a is y words long. */
|
||||
void
|
||||
s_mpv_mul_d_add_prop(const mp_digit *a, mp_size a_len, mp_digit b,
|
||||
mp_digit *c)
|
||||
{
|
||||
HP_MPY_ADD_FN(a_len, &b, a, c);
|
||||
}
|
||||
|
||||
@@ -1,342 +0,0 @@
|
||||
/
|
||||
/ The contents of this file are subject to the Mozilla Public
|
||||
/ License Version 1.1 (the "License"); you may not use this file
|
||||
/ except in compliance with the License. You may obtain a copy of
|
||||
/ the License at http://www.mozilla.org/MPL/
|
||||
/
|
||||
/ Software distributed under the License is distributed on an "AS
|
||||
/ IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
/ implied. See the License for the specific language governing
|
||||
/ rights and limitations under the License.
|
||||
/
|
||||
/ The Original Code is the Netscape security libraries.
|
||||
/
|
||||
/ The Initial Developer of the Original Code is Netscape
|
||||
/ Communications Corporation. Portions created by Netscape are
|
||||
/ Copyright (C) 2001 Netscape Communications Corporation. All
|
||||
/ Rights Reserved.
|
||||
/
|
||||
/ Contributor(s):
|
||||
/
|
||||
/ Alternatively, the contents of this file may be used under the
|
||||
/ terms of the GNU General Public License Version 2 or later (the
|
||||
/ "GPL"), in which case the provisions of the GPL are applicable
|
||||
/ instead of those above. If you wish to allow use of your
|
||||
/ version of this file only under the terms of the GPL and not to
|
||||
/ allow others to use your version of this file under the MPL,
|
||||
/ indicate your decision by deleting the provisions above and
|
||||
/ replace them with the notice and other provisions required by
|
||||
/ the GPL. If you do not delete the provisions above, a recipient
|
||||
/ may use your version of this file under either the MPL or the
|
||||
/ GPL.
|
||||
/ $Id: mpi_i86pc.s,v 1.1 2001-04-27 20:47:39 nelsonb%netscape.com Exp $
|
||||
/
|
||||
|
||||
.text
|
||||
|
||||
/ ebp - 36: caller's esi
|
||||
/ ebp - 32: caller's edi
|
||||
/ ebp - 28:
|
||||
/ ebp - 24:
|
||||
/ ebp - 20:
|
||||
/ ebp - 16:
|
||||
/ ebp - 12:
|
||||
/ ebp - 8:
|
||||
/ ebp - 4:
|
||||
/ ebp + 0: caller's ebp
|
||||
/ ebp + 4: return address
|
||||
/ ebp + 8: a argument
|
||||
/ ebp + 12: a_len argument
|
||||
/ ebp + 16: b argument
|
||||
/ ebp + 20: c argument
|
||||
/ registers:
|
||||
/ eax:
|
||||
/ ebx: carry
|
||||
/ ecx: a_len
|
||||
/ edx:
|
||||
/ esi: a ptr
|
||||
/ edi: c ptr
|
||||
.globl s_mpv_mul_d
|
||||
.type s_mpv_mul_d,@function
|
||||
s_mpv_mul_d:
|
||||
push %ebp
|
||||
mov %esp,%ebp
|
||||
sub $28,%esp
|
||||
push %edi
|
||||
push %esi
|
||||
push %ebx
|
||||
movl $0,%ebx / carry = 0
|
||||
mov 12(%ebp),%ecx / ecx = a_len
|
||||
mov 20(%ebp),%edi
|
||||
cmp $0,%ecx
|
||||
je L2 / jmp if a_len == 0
|
||||
mov 8(%ebp),%esi / esi = a
|
||||
cld
|
||||
L1:
|
||||
lodsl / eax = [ds:esi]; esi += 4
|
||||
mov 16(%ebp),%edx / edx = b
|
||||
mull %edx / edx:eax = Phi:Plo = a_i * b
|
||||
|
||||
add %ebx,%eax / add carry (%ebx) to edx:eax
|
||||
adc $0,%edx
|
||||
mov %edx,%ebx / high half of product becomes next carry
|
||||
|
||||
stosl / [es:edi] = ax; edi += 4;
|
||||
dec %ecx / --a_len
|
||||
jnz L1 / jmp if a_len != 0
|
||||
L2:
|
||||
mov %ebx,0(%edi) / *c = carry
|
||||
pop %ebx
|
||||
pop %esi
|
||||
pop %edi
|
||||
leave
|
||||
ret
|
||||
nop
|
||||
|
||||
/ ebp - 36: caller's esi
|
||||
/ ebp - 32: caller's edi
|
||||
/ ebp - 28:
|
||||
/ ebp - 24:
|
||||
/ ebp - 20:
|
||||
/ ebp - 16:
|
||||
/ ebp - 12:
|
||||
/ ebp - 8:
|
||||
/ ebp - 4:
|
||||
/ ebp + 0: caller's ebp
|
||||
/ ebp + 4: return address
|
||||
/ ebp + 8: a argument
|
||||
/ ebp + 12: a_len argument
|
||||
/ ebp + 16: b argument
|
||||
/ ebp + 20: c argument
|
||||
/ registers:
|
||||
/ eax:
|
||||
/ ebx: carry
|
||||
/ ecx: a_len
|
||||
/ edx:
|
||||
/ esi: a ptr
|
||||
/ edi: c ptr
|
||||
.globl s_mpv_mul_d_add
|
||||
.type s_mpv_mul_d_add,@function
|
||||
s_mpv_mul_d_add:
|
||||
push %ebp
|
||||
mov %esp,%ebp
|
||||
sub $28,%esp
|
||||
push %edi
|
||||
push %esi
|
||||
push %ebx
|
||||
movl $0,%ebx / carry = 0
|
||||
mov 12(%ebp),%ecx / ecx = a_len
|
||||
mov 20(%ebp),%edi
|
||||
cmp $0,%ecx
|
||||
je L4 / jmp if a_len == 0
|
||||
mov 8(%ebp),%esi / esi = a
|
||||
cld
|
||||
L3:
|
||||
lodsl / eax = [ds:esi]; esi += 4
|
||||
mov 16(%ebp),%edx / edx = b
|
||||
mull %edx / edx:eax = Phi:Plo = a_i * b
|
||||
|
||||
add %ebx,%eax / add carry (%ebx) to edx:eax
|
||||
adc $0,%edx
|
||||
mov 0(%edi),%ebx / add in current word from *c
|
||||
add %ebx,%eax
|
||||
adc $0,%edx
|
||||
mov %edx,%ebx / high half of product becomes next carry
|
||||
|
||||
stosl / [es:edi] = ax; edi += 4;
|
||||
dec %ecx / --a_len
|
||||
jnz L3 / jmp if a_len != 0
|
||||
L4:
|
||||
mov %ebx,0(%edi) / *c = carry
|
||||
pop %ebx
|
||||
pop %esi
|
||||
pop %edi
|
||||
leave
|
||||
ret
|
||||
nop
|
||||
|
||||
/ ebp - 36: caller's esi
|
||||
/ ebp - 32: caller's edi
|
||||
/ ebp - 28:
|
||||
/ ebp - 24:
|
||||
/ ebp - 20:
|
||||
/ ebp - 16:
|
||||
/ ebp - 12:
|
||||
/ ebp - 8:
|
||||
/ ebp - 4:
|
||||
/ ebp + 0: caller's ebp
|
||||
/ ebp + 4: return address
|
||||
/ ebp + 8: a argument
|
||||
/ ebp + 12: a_len argument
|
||||
/ ebp + 16: b argument
|
||||
/ ebp + 20: c argument
|
||||
/ registers:
|
||||
/ eax:
|
||||
/ ebx: carry
|
||||
/ ecx: a_len
|
||||
/ edx:
|
||||
/ esi: a ptr
|
||||
/ edi: c ptr
|
||||
.globl s_mpv_mul_d_add_prop
|
||||
.type s_mpv_mul_d_add_prop,@function
|
||||
s_mpv_mul_d_add_prop:
|
||||
push %ebp
|
||||
mov %esp,%ebp
|
||||
sub $28,%esp
|
||||
push %edi
|
||||
push %esi
|
||||
push %ebx
|
||||
movl $0,%ebx / carry = 0
|
||||
mov 12(%ebp),%ecx / ecx = a_len
|
||||
mov 20(%ebp),%edi
|
||||
cmp $0,%ecx
|
||||
je L6 / jmp if a_len == 0
|
||||
cld
|
||||
mov 8(%ebp),%esi / esi = a
|
||||
L5:
|
||||
lodsl / eax = [ds:esi]; esi += 4
|
||||
mov 16(%ebp),%edx / edx = b
|
||||
mull %edx / edx:eax = Phi:Plo = a_i * b
|
||||
|
||||
add %ebx,%eax / add carry (%ebx) to edx:eax
|
||||
adc $0,%edx
|
||||
mov 0(%edi),%ebx / add in current word from *c
|
||||
add %ebx,%eax
|
||||
adc $0,%edx
|
||||
mov %edx,%ebx / high half of product becomes next carry
|
||||
|
||||
stosl / [es:edi] = ax; edi += 4;
|
||||
dec %ecx / --a_len
|
||||
jnz L5 / jmp if a_len != 0
|
||||
L6:
|
||||
cmp $0,%ebx / is carry zero?
|
||||
jz L8
|
||||
mov 0(%edi),%eax / add in current word from *c
|
||||
add %ebx,%eax
|
||||
stosl / [es:edi] = ax; edi += 4;
|
||||
jnc L8
|
||||
L7:
|
||||
mov 0(%edi),%eax / add in current word from *c
|
||||
adc $0,%eax
|
||||
stosl / [es:edi] = ax; edi += 4;
|
||||
jc L7
|
||||
L8:
|
||||
pop %ebx
|
||||
pop %esi
|
||||
pop %edi
|
||||
leave
|
||||
ret
|
||||
nop
|
||||
|
||||
/ ebp - 20: caller's esi
|
||||
/ ebp - 16: caller's edi
|
||||
/ ebp - 12:
|
||||
/ ebp - 8: carry
|
||||
/ ebp - 4: a_len local
|
||||
/ ebp + 0: caller's ebp
|
||||
/ ebp + 4: return address
|
||||
/ ebp + 8: pa argument
|
||||
/ ebp + 12: a_len argument
|
||||
/ ebp + 16: ps argument
|
||||
/ ebp + 20:
|
||||
/ registers:
|
||||
/ eax:
|
||||
/ ebx: carry
|
||||
/ ecx: a_len
|
||||
/ edx:
|
||||
/ esi: a ptr
|
||||
/ edi: c ptr
|
||||
|
||||
.globl s_mpv_sqr_add_prop
|
||||
.type s_mpv_sqr_add_prop,@function
|
||||
s_mpv_sqr_add_prop:
|
||||
push %ebp
|
||||
mov %esp,%ebp
|
||||
sub $12,%esp
|
||||
push %edi
|
||||
push %esi
|
||||
push %ebx
|
||||
movl $0,%ebx / carry = 0
|
||||
mov 12(%ebp),%ecx / a_len
|
||||
mov 16(%ebp),%edi / edi = ps
|
||||
cmp $0,%ecx
|
||||
je L11 / jump if a_len == 0
|
||||
cld
|
||||
mov 8(%ebp),%esi / esi = pa
|
||||
L10:
|
||||
lodsl / %eax = [ds:si]; si += 4;
|
||||
mull %eax
|
||||
|
||||
add %ebx,%eax / add "carry"
|
||||
adc $0,%edx
|
||||
mov 0(%edi),%ebx
|
||||
add %ebx,%eax / add low word from result
|
||||
mov 4(%edi),%ebx
|
||||
stosl / [es:di] = %eax; di += 4;
|
||||
adc %ebx,%edx / add high word from result
|
||||
movl $0,%ebx
|
||||
mov %edx,%eax
|
||||
adc $0,%ebx
|
||||
stosl / [es:di] = %eax; di += 4;
|
||||
dec %ecx / --a_len
|
||||
jnz L10 / jmp if a_len != 0
|
||||
L11:
|
||||
cmp $0,%ebx / is carry zero?
|
||||
jz L14
|
||||
mov 0(%edi),%eax / add in current word from *c
|
||||
add %ebx,%eax
|
||||
stosl / [es:edi] = ax; edi += 4;
|
||||
jnc L14
|
||||
L12:
|
||||
mov 0(%edi),%eax / add in current word from *c
|
||||
adc $0,%eax
|
||||
stosl / [es:edi] = ax; edi += 4;
|
||||
jc L12
|
||||
L14:
|
||||
pop %ebx
|
||||
pop %esi
|
||||
pop %edi
|
||||
leave
|
||||
ret
|
||||
nop
|
||||
|
||||
/
|
||||
/ Divide 64-bit (Nhi,Nlo) by 32-bit divisor, which must be normalized
|
||||
/ so its high bit is 1. This code is from NSPR.
|
||||
/
|
||||
/ mp_err s_mpv_div_2dx1d(mp_digit Nhi, mp_digit Nlo, mp_digit divisor,
|
||||
/ mp_digit *qp, mp_digit *rp)
|
||||
|
||||
/ esp + 0: Caller's ebx
|
||||
/ esp + 4: return address
|
||||
/ esp + 8: Nhi argument
|
||||
/ esp + 12: Nlo argument
|
||||
/ esp + 16: divisor argument
|
||||
/ esp + 20: qp argument
|
||||
/ esp + 24: rp argument
|
||||
/ registers:
|
||||
/ eax:
|
||||
/ ebx: carry
|
||||
/ ecx: a_len
|
||||
/ edx:
|
||||
/ esi: a ptr
|
||||
/ edi: c ptr
|
||||
/
|
||||
|
||||
.globl s_mpv_div_2dx1d
|
||||
.type s_mpv_div_2dx1d,@function
|
||||
s_mpv_div_2dx1d:
|
||||
push %ebx
|
||||
mov 8(%esp),%edx
|
||||
mov 12(%esp),%eax
|
||||
mov 16(%esp),%ebx
|
||||
div %ebx
|
||||
mov 20(%esp),%ebx
|
||||
mov %eax,0(%ebx)
|
||||
mov 24(%esp),%ebx
|
||||
mov %edx,0(%ebx)
|
||||
xor %eax,%eax / return zero
|
||||
pop %ebx
|
||||
ret
|
||||
nop
|
||||
|
||||
@@ -1,502 +0,0 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
* $Id: mpi_mips.s,v 1.2 2000-08-31 02:40:32 nelsonb%netscape.com Exp $
|
||||
*/
|
||||
#include <regdef.h>
|
||||
.set noreorder
|
||||
.set noat
|
||||
|
||||
.section .text, 1, 0x00000006, 4, 4
|
||||
.text:
|
||||
.section .text
|
||||
|
||||
.ent s_mpv_mul_d_add
|
||||
.globl s_mpv_mul_d_add
|
||||
|
||||
s_mpv_mul_d_add:
|
||||
#/* c += a * b */
|
||||
#void s_mpv_mul_d_add(const mp_digit *a, mp_size a_len, mp_digit b,
|
||||
# mp_digit *c)
|
||||
#{
|
||||
# mp_digit a0, a1; regs a4, a5
|
||||
# mp_digit c0, c1; regs a6, a7
|
||||
# mp_digit cy = 0; reg t2
|
||||
# mp_word w0, w1; regs t0, t1
|
||||
#
|
||||
# if (a_len) {
|
||||
beq a1,zero,.L.1
|
||||
move t2,zero # cy = 0
|
||||
dsll32 a2,a2,0 # "b" is sometimes negative (?!?!)
|
||||
dsrl32 a2,a2,0 # This clears the upper 32 bits.
|
||||
# a0 = a[0];
|
||||
lwu a4,0(a0)
|
||||
# w0 = ((mp_word)b * a0);
|
||||
dmultu a2,a4
|
||||
# if (--a_len) {
|
||||
addiu a1,a1,-1
|
||||
beq a1,zero,.L.2
|
||||
# while (a_len >= 2) {
|
||||
sltiu t3,a1,2
|
||||
bne t3,zero,.L.3
|
||||
# a1 = a[1];
|
||||
lwu a5,4(a0)
|
||||
.L.4:
|
||||
# a_len -= 2;
|
||||
addiu a1,a1,-2
|
||||
# c0 = c[0];
|
||||
lwu a6,0(a3)
|
||||
# w0 += cy;
|
||||
mflo t0
|
||||
daddu t0,t0,t2
|
||||
# w0 += c0;
|
||||
daddu t0,t0,a6
|
||||
# w1 = (mp_word)b * a1;
|
||||
dmultu a2,a5 #
|
||||
# cy = CARRYOUT(w0);
|
||||
dsrl32 t2,t0,0
|
||||
# c[0] = ACCUM(w0);
|
||||
sw t0,0(a3)
|
||||
# a0 = a[2];
|
||||
lwu a4,8(a0)
|
||||
# a += 2;
|
||||
addiu a0,a0,8
|
||||
# c1 = c[1];
|
||||
lwu a7,4(a3)
|
||||
# w1 += cy;
|
||||
mflo t1
|
||||
daddu t1,t1,t2
|
||||
# w1 += c1;
|
||||
daddu t1,t1,a7
|
||||
# w0 = (mp_word)b * a0;
|
||||
dmultu a2,a4 #
|
||||
# cy = CARRYOUT(w1);
|
||||
dsrl32 t2,t1,0
|
||||
# c[1] = ACCUM(w1);
|
||||
sw t1,4(a3)
|
||||
# c += 2;
|
||||
addiu a3,a3,8
|
||||
sltiu t3,a1,2
|
||||
beq t3,zero,.L.4
|
||||
# a1 = a[1];
|
||||
lwu a5,4(a0)
|
||||
# }
|
||||
.L.3:
|
||||
# c0 = c[0];
|
||||
lwu a6,0(a3)
|
||||
# w0 += cy;
|
||||
# if (a_len) {
|
||||
mflo t0
|
||||
beq a1,zero,.L.5
|
||||
daddu t0,t0,t2
|
||||
# w1 = (mp_word)b * a1;
|
||||
dmultu a2,a5
|
||||
# w0 += c0;
|
||||
daddu t0,t0,a6 #
|
||||
# cy = CARRYOUT(w0);
|
||||
dsrl32 t2,t0,0
|
||||
# c[0] = ACCUM(w0);
|
||||
sw t0,0(a3)
|
||||
# c1 = c[1];
|
||||
lwu a7,4(a3)
|
||||
# w1 += cy;
|
||||
mflo t1
|
||||
daddu t1,t1,t2
|
||||
# w1 += c1;
|
||||
daddu t1,t1,a7
|
||||
# c[1] = ACCUM(w1);
|
||||
sw t1,4(a3)
|
||||
# cy = CARRYOUT(w1);
|
||||
dsrl32 t2,t1,0
|
||||
# c += 1;
|
||||
b .L.6
|
||||
addiu a3,a3,4
|
||||
# } else {
|
||||
.L.5:
|
||||
# w0 += c0;
|
||||
daddu t0,t0,a6
|
||||
# c[0] = ACCUM(w0);
|
||||
sw t0,0(a3)
|
||||
# cy = CARRYOUT(w0);
|
||||
b .L.6
|
||||
dsrl32 t2,t0,0
|
||||
# }
|
||||
# } else {
|
||||
.L.2:
|
||||
# c0 = c[0];
|
||||
lwu a6,0(a3)
|
||||
# w0 += c0;
|
||||
mflo t0
|
||||
daddu t0,t0,a6
|
||||
# c[0] = ACCUM(w0);
|
||||
sw t0,0(a3)
|
||||
# cy = CARRYOUT(w0);
|
||||
dsrl32 t2,t0,0
|
||||
# }
|
||||
.L.6:
|
||||
# c[1] = cy;
|
||||
jr ra
|
||||
sw t2,4(a3)
|
||||
# }
|
||||
.L.1:
|
||||
jr ra
|
||||
nop
|
||||
#}
|
||||
#
|
||||
.end s_mpv_mul_d_add
|
||||
|
||||
.ent s_mpv_mul_d_add_prop
|
||||
.globl s_mpv_mul_d_add_prop
|
||||
|
||||
s_mpv_mul_d_add_prop:
|
||||
#/* c += a * b */
|
||||
#void s_mpv_mul_d_add_prop(const mp_digit *a, mp_size a_len, mp_digit b,
|
||||
# mp_digit *c)
|
||||
#{
|
||||
# mp_digit a0, a1; regs a4, a5
|
||||
# mp_digit c0, c1; regs a6, a7
|
||||
# mp_digit cy = 0; reg t2
|
||||
# mp_word w0, w1; regs t0, t1
|
||||
#
|
||||
# if (a_len) {
|
||||
beq a1,zero,.M.1
|
||||
move t2,zero # cy = 0
|
||||
dsll32 a2,a2,0 # "b" is sometimes negative (?!?!)
|
||||
dsrl32 a2,a2,0 # This clears the upper 32 bits.
|
||||
# a0 = a[0];
|
||||
lwu a4,0(a0)
|
||||
# w0 = ((mp_word)b * a0);
|
||||
dmultu a2,a4
|
||||
# if (--a_len) {
|
||||
addiu a1,a1,-1
|
||||
beq a1,zero,.M.2
|
||||
# while (a_len >= 2) {
|
||||
sltiu t3,a1,2
|
||||
bne t3,zero,.M.3
|
||||
# a1 = a[1];
|
||||
lwu a5,4(a0)
|
||||
.M.4:
|
||||
# a_len -= 2;
|
||||
addiu a1,a1,-2
|
||||
# c0 = c[0];
|
||||
lwu a6,0(a3)
|
||||
# w0 += cy;
|
||||
mflo t0
|
||||
daddu t0,t0,t2
|
||||
# w0 += c0;
|
||||
daddu t0,t0,a6
|
||||
# w1 = (mp_word)b * a1;
|
||||
dmultu a2,a5 #
|
||||
# cy = CARRYOUT(w0);
|
||||
dsrl32 t2,t0,0
|
||||
# c[0] = ACCUM(w0);
|
||||
sw t0,0(a3)
|
||||
# a0 = a[2];
|
||||
lwu a4,8(a0)
|
||||
# a += 2;
|
||||
addiu a0,a0,8
|
||||
# c1 = c[1];
|
||||
lwu a7,4(a3)
|
||||
# w1 += cy;
|
||||
mflo t1
|
||||
daddu t1,t1,t2
|
||||
# w1 += c1;
|
||||
daddu t1,t1,a7
|
||||
# w0 = (mp_word)b * a0;
|
||||
dmultu a2,a4 #
|
||||
# cy = CARRYOUT(w1);
|
||||
dsrl32 t2,t1,0
|
||||
# c[1] = ACCUM(w1);
|
||||
sw t1,4(a3)
|
||||
# c += 2;
|
||||
addiu a3,a3,8
|
||||
sltiu t3,a1,2
|
||||
beq t3,zero,.M.4
|
||||
# a1 = a[1];
|
||||
lwu a5,4(a0)
|
||||
# }
|
||||
.M.3:
|
||||
# c0 = c[0];
|
||||
lwu a6,0(a3)
|
||||
# w0 += cy;
|
||||
# if (a_len) {
|
||||
mflo t0
|
||||
beq a1,zero,.M.5
|
||||
daddu t0,t0,t2
|
||||
# w1 = (mp_word)b * a1;
|
||||
dmultu a2,a5
|
||||
# w0 += c0;
|
||||
daddu t0,t0,a6 #
|
||||
# cy = CARRYOUT(w0);
|
||||
dsrl32 t2,t0,0
|
||||
# c[0] = ACCUM(w0);
|
||||
sw t0,0(a3)
|
||||
# c1 = c[1];
|
||||
lwu a7,4(a3)
|
||||
# w1 += cy;
|
||||
mflo t1
|
||||
daddu t1,t1,t2
|
||||
# w1 += c1;
|
||||
daddu t1,t1,a7
|
||||
# c[1] = ACCUM(w1);
|
||||
sw t1,4(a3)
|
||||
# cy = CARRYOUT(w1);
|
||||
dsrl32 t2,t1,0
|
||||
# c += 1;
|
||||
b .M.6
|
||||
addiu a3,a3,8
|
||||
# } else {
|
||||
.M.5:
|
||||
# w0 += c0;
|
||||
daddu t0,t0,a6
|
||||
# c[0] = ACCUM(w0);
|
||||
sw t0,0(a3)
|
||||
# cy = CARRYOUT(w0);
|
||||
dsrl32 t2,t0,0
|
||||
b .M.6
|
||||
addiu a3,a3,4
|
||||
# }
|
||||
# } else {
|
||||
.M.2:
|
||||
# c0 = c[0];
|
||||
lwu a6,0(a3)
|
||||
# w0 += c0;
|
||||
mflo t0
|
||||
daddu t0,t0,a6
|
||||
# c[0] = ACCUM(w0);
|
||||
sw t0,0(a3)
|
||||
# cy = CARRYOUT(w0);
|
||||
dsrl32 t2,t0,0
|
||||
addiu a3,a3,4
|
||||
# }
|
||||
.M.6:
|
||||
|
||||
# while (cy) {
|
||||
beq t2,zero,.M.1
|
||||
nop
|
||||
.M.7:
|
||||
# mp_word w = (mp_word)*c + cy;
|
||||
lwu a6,0(a3)
|
||||
daddu t2,t2,a6
|
||||
# *c++ = ACCUM(w);
|
||||
sw t2,0(a3)
|
||||
# cy = CARRYOUT(w);
|
||||
dsrl32 t2,t2,0
|
||||
bne t2,zero,.M.7
|
||||
addiu a3,a3,4
|
||||
|
||||
# }
|
||||
.M.1:
|
||||
jr ra
|
||||
nop
|
||||
#}
|
||||
#
|
||||
.end s_mpv_mul_d_add_prop
|
||||
|
||||
.ent s_mpv_mul_d
|
||||
.globl s_mpv_mul_d
|
||||
|
||||
s_mpv_mul_d:
|
||||
#/* c = a * b */
|
||||
#void s_mpv_mul_d(const mp_digit *a, mp_size a_len, mp_digit b,
|
||||
# mp_digit *c)
|
||||
#{
|
||||
# mp_digit a0, a1; regs a4, a5
|
||||
# mp_digit cy = 0; reg t2
|
||||
# mp_word w0, w1; regs t0, t1
|
||||
#
|
||||
# if (a_len) {
|
||||
beq a1,zero,.N.1
|
||||
move t2,zero # cy = 0
|
||||
dsll32 a2,a2,0 # "b" is sometimes negative (?!?!)
|
||||
dsrl32 a2,a2,0 # This clears the upper 32 bits.
|
||||
# a0 = a[0];
|
||||
lwu a4,0(a0)
|
||||
# w0 = ((mp_word)b * a0);
|
||||
dmultu a2,a4
|
||||
# if (--a_len) {
|
||||
addiu a1,a1,-1
|
||||
beq a1,zero,.N.2
|
||||
# while (a_len >= 2) {
|
||||
sltiu t3,a1,2
|
||||
bne t3,zero,.N.3
|
||||
# a1 = a[1];
|
||||
lwu a5,4(a0)
|
||||
.N.4:
|
||||
# a_len -= 2;
|
||||
addiu a1,a1,-2
|
||||
# w0 += cy;
|
||||
mflo t0
|
||||
daddu t0,t0,t2
|
||||
# cy = CARRYOUT(w0);
|
||||
dsrl32 t2,t0,0
|
||||
# w1 = (mp_word)b * a1;
|
||||
dmultu a2,a5
|
||||
# c[0] = ACCUM(w0);
|
||||
sw t0,0(a3)
|
||||
# a0 = a[2];
|
||||
lwu a4,8(a0)
|
||||
# a += 2;
|
||||
addiu a0,a0,8
|
||||
# w1 += cy;
|
||||
mflo t1
|
||||
daddu t1,t1,t2
|
||||
# cy = CARRYOUT(w1);
|
||||
dsrl32 t2,t1,0
|
||||
# w0 = (mp_word)b * a0;
|
||||
dmultu a2,a4
|
||||
# c[1] = ACCUM(w1);
|
||||
sw t1,4(a3)
|
||||
# c += 2;
|
||||
addiu a3,a3,8
|
||||
sltiu t3,a1,2
|
||||
beq t3,zero,.N.4
|
||||
# a1 = a[1];
|
||||
lwu a5,4(a0)
|
||||
# }
|
||||
.N.3:
|
||||
# w0 += cy;
|
||||
# if (a_len) {
|
||||
mflo t0
|
||||
beq a1,zero,.N.5
|
||||
daddu t0,t0,t2
|
||||
# w1 = (mp_word)b * a1;
|
||||
dmultu a2,a5 #
|
||||
# cy = CARRYOUT(w0);
|
||||
dsrl32 t2,t0,0
|
||||
# c[0] = ACCUM(w0);
|
||||
sw t0,0(a3)
|
||||
# w1 += cy;
|
||||
mflo t1
|
||||
daddu t1,t1,t2
|
||||
# c[1] = ACCUM(w1);
|
||||
sw t1,4(a3)
|
||||
# cy = CARRYOUT(w1);
|
||||
dsrl32 t2,t1,0
|
||||
# c += 1;
|
||||
b .N.6
|
||||
addiu a3,a3,4
|
||||
# } else {
|
||||
.N.5:
|
||||
# c[0] = ACCUM(w0);
|
||||
sw t0,0(a3)
|
||||
# cy = CARRYOUT(w0);
|
||||
b .N.6
|
||||
dsrl32 t2,t0,0
|
||||
# }
|
||||
# } else {
|
||||
.N.2:
|
||||
mflo t0
|
||||
# c[0] = ACCUM(w0);
|
||||
sw t0,0(a3)
|
||||
# cy = CARRYOUT(w0);
|
||||
dsrl32 t2,t0,0
|
||||
# }
|
||||
.N.6:
|
||||
# c[1] = cy;
|
||||
jr ra
|
||||
sw t2,4(a3)
|
||||
# }
|
||||
.N.1:
|
||||
jr ra
|
||||
nop
|
||||
#}
|
||||
#
|
||||
.end s_mpv_mul_d
|
||||
|
||||
|
||||
.ent s_mpv_sqr_add_prop
|
||||
.globl s_mpv_sqr_add_prop
|
||||
#void s_mpv_sqr_add_prop(const mp_digit *a, mp_size a_len, mp_digit *sqrs);
|
||||
# registers
|
||||
# a0 *a
|
||||
# a1 a_len
|
||||
# a2 *sqr
|
||||
# a3 digit from *a, a_i
|
||||
# a4 square of digit from a
|
||||
# a5,a6 next 2 digits in sqr
|
||||
# a7,t0 carry
|
||||
s_mpv_sqr_add_prop:
|
||||
move a7,zero
|
||||
move t0,zero
|
||||
lwu a3,0(a0)
|
||||
addiu a1,a1,-1 # --a_len
|
||||
dmultu a3,a3
|
||||
beq a1,zero,.P.3 # jump if we've already done the only sqr
|
||||
addiu a0,a0,4 # ++a
|
||||
.P.2:
|
||||
lwu a5,0(a2)
|
||||
lwu a6,4(a2)
|
||||
addiu a2,a2,8 # sqrs += 2;
|
||||
dsll32 a6,a6,0
|
||||
daddu a5,a5,a6
|
||||
lwu a3,0(a0)
|
||||
addiu a0,a0,4 # ++a
|
||||
mflo a4
|
||||
daddu a6,a5,a4
|
||||
sltu a7,a6,a5 # a7 = a6 < a5 detect overflow
|
||||
dmultu a3,a3
|
||||
daddu a4,a6,t0
|
||||
sltu t0,a4,a6
|
||||
add t0,t0,a7
|
||||
sw a4,-8(a2)
|
||||
addiu a1,a1,-1 # --a_len
|
||||
dsrl32 a4,a4,0
|
||||
bne a1,zero,.P.2 # loop if a_len > 0
|
||||
sw a4,-4(a2)
|
||||
.P.3:
|
||||
lwu a5,0(a2)
|
||||
lwu a6,4(a2)
|
||||
addiu a2,a2,8 # sqrs += 2;
|
||||
dsll32 a6,a6,0
|
||||
daddu a5,a5,a6
|
||||
mflo a4
|
||||
daddu a6,a5,a4
|
||||
sltu a7,a6,a5 # a7 = a6 < a5 detect overflow
|
||||
daddu a4,a6,t0
|
||||
sltu t0,a4,a6
|
||||
add t0,t0,a7
|
||||
sw a4,-8(a2)
|
||||
beq t0,zero,.P.9 # jump if no carry
|
||||
dsrl32 a4,a4,0
|
||||
.P.8:
|
||||
sw a4,-4(a2)
|
||||
/* propagate final carry */
|
||||
lwu a5,0(a2)
|
||||
daddu a6,a5,t0
|
||||
sltu t0,a6,a5
|
||||
bne t0,zero,.P.8 # loop if carry persists
|
||||
addiu a2,a2,4 # sqrs++
|
||||
.P.9:
|
||||
jr ra
|
||||
sw a4,-4(a2)
|
||||
|
||||
.end s_mpv_sqr_add_prop
|
||||
@@ -1,361 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: mpi_sparc.c,v 1.6 2004-04-27 23:04:36 gerv%gerv.net Exp $ */
|
||||
|
||||
/* Multiplication performance enhancements for sparc v8+vis CPUs. */
|
||||
|
||||
#include "mpi-priv.h"
|
||||
#include <stddef.h>
|
||||
#include <sys/systeminfo.h>
|
||||
#include <strings.h>
|
||||
|
||||
/* In the functions below, */
|
||||
/* vector y must be 8-byte aligned, and n must be even */
|
||||
/* returns carry out of high order word of result */
|
||||
/* maximum n is 256 */
|
||||
|
||||
/* vector x += vector y * scaler a; where y is of length n words. */
|
||||
extern mp_digit mul_add_inp(mp_digit *x, const mp_digit *y, int n, mp_digit a);
|
||||
|
||||
/* vector z = vector x + vector y * scaler a; where y is of length n words. */
|
||||
extern mp_digit mul_add(mp_digit *z, const mp_digit *x, const mp_digit *y,
|
||||
int n, mp_digit a);
|
||||
|
||||
/* v8 versions of these functions run on any Sparc v8 CPU. */
|
||||
|
||||
/* This trick works on Sparc V8 CPUs with the Workshop compilers. */
|
||||
#define MP_MUL_DxD(a, b, Phi, Plo) \
|
||||
{ unsigned long long product = (unsigned long long)a * b; \
|
||||
Plo = (mp_digit)product; \
|
||||
Phi = (mp_digit)(product >> MP_DIGIT_BIT); }
|
||||
|
||||
/* c = a * b */
|
||||
static void
|
||||
v8_mpv_mul_d(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
|
||||
{
|
||||
#if !defined(MP_NO_MP_WORD)
|
||||
mp_digit d = 0;
|
||||
|
||||
/* Inner product: Digits of a */
|
||||
while (a_len--) {
|
||||
mp_word w = ((mp_word)b * *a++) + d;
|
||||
*c++ = ACCUM(w);
|
||||
d = CARRYOUT(w);
|
||||
}
|
||||
*c = d;
|
||||
#else
|
||||
mp_digit carry = 0;
|
||||
while (a_len--) {
|
||||
mp_digit a_i = *a++;
|
||||
mp_digit a0b0, a1b1;
|
||||
|
||||
MP_MUL_DxD(a_i, b, a1b1, a0b0);
|
||||
|
||||
a0b0 += carry;
|
||||
if (a0b0 < carry)
|
||||
++a1b1;
|
||||
*c++ = a0b0;
|
||||
carry = a1b1;
|
||||
}
|
||||
*c = carry;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* c += a * b */
|
||||
static void
|
||||
v8_mpv_mul_d_add(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
|
||||
{
|
||||
#if !defined(MP_NO_MP_WORD)
|
||||
mp_digit d = 0;
|
||||
|
||||
/* Inner product: Digits of a */
|
||||
while (a_len--) {
|
||||
mp_word w = ((mp_word)b * *a++) + *c + d;
|
||||
*c++ = ACCUM(w);
|
||||
d = CARRYOUT(w);
|
||||
}
|
||||
*c = d;
|
||||
#else
|
||||
mp_digit carry = 0;
|
||||
while (a_len--) {
|
||||
mp_digit a_i = *a++;
|
||||
mp_digit a0b0, a1b1;
|
||||
|
||||
MP_MUL_DxD(a_i, b, a1b1, a0b0);
|
||||
|
||||
a0b0 += carry;
|
||||
if (a0b0 < carry)
|
||||
++a1b1;
|
||||
a0b0 += a_i = *c;
|
||||
if (a0b0 < a_i)
|
||||
++a1b1;
|
||||
*c++ = a0b0;
|
||||
carry = a1b1;
|
||||
}
|
||||
*c = carry;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Presently, this is only used by the Montgomery arithmetic code. */
|
||||
/* c += a * b */
|
||||
static void
|
||||
v8_mpv_mul_d_add_prop(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
|
||||
{
|
||||
#if !defined(MP_NO_MP_WORD)
|
||||
mp_digit d = 0;
|
||||
|
||||
/* Inner product: Digits of a */
|
||||
while (a_len--) {
|
||||
mp_word w = ((mp_word)b * *a++) + *c + d;
|
||||
*c++ = ACCUM(w);
|
||||
d = CARRYOUT(w);
|
||||
}
|
||||
|
||||
while (d) {
|
||||
mp_word w = (mp_word)*c + d;
|
||||
*c++ = ACCUM(w);
|
||||
d = CARRYOUT(w);
|
||||
}
|
||||
#else
|
||||
mp_digit carry = 0;
|
||||
while (a_len--) {
|
||||
mp_digit a_i = *a++;
|
||||
mp_digit a0b0, a1b1;
|
||||
|
||||
MP_MUL_DxD(a_i, b, a1b1, a0b0);
|
||||
|
||||
a0b0 += carry;
|
||||
if (a0b0 < carry)
|
||||
++a1b1;
|
||||
|
||||
a0b0 += a_i = *c;
|
||||
if (a0b0 < a_i)
|
||||
++a1b1;
|
||||
|
||||
*c++ = a0b0;
|
||||
carry = a1b1;
|
||||
}
|
||||
while (carry) {
|
||||
mp_digit c_i = *c;
|
||||
carry += c_i;
|
||||
*c++ = carry;
|
||||
carry = carry < c_i;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* vis versions of these functions run only on v8+vis or v9+vis CPUs. */
|
||||
|
||||
/* c = a * b */
|
||||
static void
|
||||
vis_mpv_mul_d(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
|
||||
{
|
||||
mp_digit d;
|
||||
mp_digit x[258];
|
||||
if (a_len <= 256) {
|
||||
if (a == c || ((ptrdiff_t)a & 0x7) != 0 || (a_len & 1) != 0) {
|
||||
mp_digit * px;
|
||||
px = (((ptrdiff_t)x & 0x7) != 0) ? x + 1 : x;
|
||||
memcpy(px, a, a_len * sizeof(*a));
|
||||
a = px;
|
||||
if (a_len & 1) {
|
||||
px[a_len] = 0;
|
||||
}
|
||||
}
|
||||
s_mp_setz(c, a_len + 1);
|
||||
d = mul_add_inp(c, a, a_len, b);
|
||||
c[a_len] = d;
|
||||
} else {
|
||||
v8_mpv_mul_d(a, a_len, b, c);
|
||||
}
|
||||
}
|
||||
|
||||
/* c += a * b, where a is a_len words long. */
|
||||
static void
|
||||
vis_mpv_mul_d_add(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
|
||||
{
|
||||
mp_digit d;
|
||||
mp_digit x[258];
|
||||
if (a_len <= 256) {
|
||||
if (((ptrdiff_t)a & 0x7) != 0 || (a_len & 1) != 0) {
|
||||
mp_digit * px;
|
||||
px = (((ptrdiff_t)x & 0x7) != 0) ? x + 1 : x;
|
||||
memcpy(px, a, a_len * sizeof(*a));
|
||||
a = px;
|
||||
if (a_len & 1) {
|
||||
px[a_len] = 0;
|
||||
}
|
||||
}
|
||||
d = mul_add_inp(c, a, a_len, b);
|
||||
c[a_len] = d;
|
||||
} else {
|
||||
v8_mpv_mul_d_add(a, a_len, b, c);
|
||||
}
|
||||
}
|
||||
|
||||
/* c += a * b, where a is y words long. */
|
||||
static void
|
||||
vis_mpv_mul_d_add_prop(const mp_digit *a, mp_size a_len, mp_digit b,
|
||||
mp_digit *c)
|
||||
{
|
||||
mp_digit d;
|
||||
mp_digit x[258];
|
||||
if (a_len <= 256) {
|
||||
if (((ptrdiff_t)a & 0x7) != 0 || (a_len & 1) != 0) {
|
||||
mp_digit * px;
|
||||
px = (((ptrdiff_t)x & 0x7) != 0) ? x + 1 : x;
|
||||
memcpy(px, a, a_len * sizeof(*a));
|
||||
a = px;
|
||||
if (a_len & 1) {
|
||||
px[a_len] = 0;
|
||||
}
|
||||
}
|
||||
d = mul_add_inp(c, a, a_len, b);
|
||||
if (d) {
|
||||
c += a_len;
|
||||
do {
|
||||
mp_digit sum = d + *c;
|
||||
*c++ = sum;
|
||||
d = sum < d;
|
||||
} while (d);
|
||||
}
|
||||
} else {
|
||||
v8_mpv_mul_d_add_prop(a, a_len, b, c);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(SOLARIS2_5)
|
||||
static int
|
||||
isSparcV8PlusVis(void)
|
||||
{
|
||||
long buflen;
|
||||
int rv = 0; /* false */
|
||||
char buf[256];
|
||||
buflen = sysinfo(SI_MACHINE, buf, sizeof buf);
|
||||
if (buflen > 0) {
|
||||
rv = (!strcmp(buf, "sun4u") || !strcmp(buf, "sun4u1"));
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
#else /* SunOS2.6or higher has SI_ISALIST */
|
||||
|
||||
static int
|
||||
isSparcV8PlusVis(void)
|
||||
{
|
||||
long buflen;
|
||||
int rv = 0; /* false */
|
||||
char buf[256];
|
||||
buflen = sysinfo(SI_ISALIST, buf, sizeof buf);
|
||||
if (buflen > 0) {
|
||||
#if defined(MP_USE_LONG_DIGIT)
|
||||
char * found = strstr(buf, "sparcv9+vis");
|
||||
#else
|
||||
char * found = strstr(buf, "sparcv8plus+vis");
|
||||
#endif
|
||||
rv = (found != 0);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef void MPVmpy(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c);
|
||||
|
||||
/* forward static function declarations */
|
||||
static MPVmpy sp_mpv_mul_d;
|
||||
static MPVmpy sp_mpv_mul_d_add;
|
||||
static MPVmpy sp_mpv_mul_d_add_prop;
|
||||
|
||||
static MPVmpy *p_mpv_mul_d = &sp_mpv_mul_d;
|
||||
static MPVmpy *p_mpv_mul_d_add = &sp_mpv_mul_d_add;
|
||||
static MPVmpy *p_mpv_mul_d_add_prop = &sp_mpv_mul_d_add_prop;
|
||||
|
||||
static void
|
||||
initPtrs(void)
|
||||
{
|
||||
if (isSparcV8PlusVis()) {
|
||||
p_mpv_mul_d = &vis_mpv_mul_d;
|
||||
p_mpv_mul_d_add = &vis_mpv_mul_d_add;
|
||||
p_mpv_mul_d_add_prop = &vis_mpv_mul_d_add_prop;
|
||||
} else {
|
||||
p_mpv_mul_d = &v8_mpv_mul_d;
|
||||
p_mpv_mul_d_add = &v8_mpv_mul_d_add;
|
||||
p_mpv_mul_d_add_prop = &v8_mpv_mul_d_add_prop;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sp_mpv_mul_d(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
|
||||
{
|
||||
initPtrs();
|
||||
(* p_mpv_mul_d)(a, a_len, b, c);
|
||||
}
|
||||
|
||||
static void
|
||||
sp_mpv_mul_d_add(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
|
||||
{
|
||||
initPtrs();
|
||||
(* p_mpv_mul_d_add)(a, a_len, b, c);
|
||||
}
|
||||
|
||||
static void
|
||||
sp_mpv_mul_d_add_prop(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
|
||||
{
|
||||
initPtrs();
|
||||
(* p_mpv_mul_d_add_prop)(a, a_len, b, c);
|
||||
}
|
||||
|
||||
|
||||
/* This is the external interface */
|
||||
|
||||
void
|
||||
s_mpv_mul_d(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
|
||||
{
|
||||
(* p_mpv_mul_d)(a, a_len, b, c);
|
||||
}
|
||||
|
||||
void
|
||||
s_mpv_mul_d_add(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
|
||||
{
|
||||
(* p_mpv_mul_d_add)(a, a_len, b, c);
|
||||
}
|
||||
|
||||
void
|
||||
s_mpv_mul_d_add_prop(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
|
||||
{
|
||||
(* p_mpv_mul_d_add_prop)(a, a_len, b, c);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,356 +0,0 @@
|
||||
;
|
||||
; mpi_x86.asm - assembly language implementation of s_mpv_ functions.
|
||||
;
|
||||
; ***** BEGIN LICENSE BLOCK *****
|
||||
; Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
;
|
||||
; The contents of this file are subject to the Mozilla Public License Version
|
||||
; 1.1 (the "License"); you may not use this file except in compliance with
|
||||
; the License. You may obtain a copy of the License at
|
||||
; http://www.mozilla.org/MPL/
|
||||
;
|
||||
; Software distributed under the License is distributed on an "AS IS" basis,
|
||||
; WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
; for the specific language governing rights and limitations under the
|
||||
; License.
|
||||
;
|
||||
; The Original Code is the Netscape security libraries.
|
||||
;
|
||||
; The Initial Developer of the Original Code is
|
||||
; Netscape Communications Corporation.
|
||||
; Portions created by the Initial Developer are Copyright (C) 2000
|
||||
; the Initial Developer. All Rights Reserved.
|
||||
;
|
||||
; Contributor(s):
|
||||
;
|
||||
; Alternatively, the contents of this file may be used under the terms of
|
||||
; either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
; the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
; in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
; of those above. If you wish to allow use of your version of this file only
|
||||
; under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
; use your version of this file under the terms of the MPL, indicate your
|
||||
; decision by deleting the provisions above and replace them with the notice
|
||||
; and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
; the provisions above, a recipient may use your version of this file under
|
||||
; the terms of any one of the MPL, the GPL or the LGPL.
|
||||
;
|
||||
; ***** END LICENSE BLOCK *****
|
||||
|
||||
; $Id: mpi_x86.asm,v 1.2 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
|
||||
.386p
|
||||
.MODEL FLAT
|
||||
ASSUME CS: FLAT, DS: FLAT, SS: FLAT
|
||||
_TEXT SEGMENT
|
||||
|
||||
; ebp - 36: caller's esi
|
||||
; ebp - 32: caller's edi
|
||||
; ebp - 28:
|
||||
; ebp - 24:
|
||||
; ebp - 20:
|
||||
; ebp - 16:
|
||||
; ebp - 12:
|
||||
; ebp - 8:
|
||||
; ebp - 4:
|
||||
; ebp + 0: caller's ebp
|
||||
; ebp + 4: return address
|
||||
; ebp + 8: a argument
|
||||
; ebp + 12: a_len argument
|
||||
; ebp + 16: b argument
|
||||
; ebp + 20: c argument
|
||||
; registers:
|
||||
; eax:
|
||||
; ebx: carry
|
||||
; ecx: a_len
|
||||
; edx:
|
||||
; esi: a ptr
|
||||
; edi: c ptr
|
||||
|
||||
public _s_mpv_mul_d
|
||||
_s_mpv_mul_d PROC NEAR
|
||||
push ebp
|
||||
mov ebp,esp
|
||||
sub esp,28
|
||||
push edi
|
||||
push esi
|
||||
push ebx
|
||||
mov ebx,0 ; carry = 0
|
||||
mov ecx,[ebp+12] ; ecx = a_len
|
||||
mov edi,[ebp+20]
|
||||
cmp ecx,0
|
||||
je L_2 ; jmp if a_len == 0
|
||||
mov esi,[ebp+8] ; esi = a
|
||||
cld
|
||||
L_1:
|
||||
lodsd ; eax = [ds:esi]; esi += 4
|
||||
mov edx,[ebp+16] ; edx = b
|
||||
mul edx ; edx:eax = Phi:Plo = a_i * b
|
||||
|
||||
add eax,ebx ; add carry (ebx) to edx:eax
|
||||
adc edx,0
|
||||
mov ebx,edx ; high half of product becomes next carry
|
||||
|
||||
stosd ; [es:edi] = ax; edi += 4;
|
||||
dec ecx ; --a_len
|
||||
jnz L_1 ; jmp if a_len != 0
|
||||
L_2:
|
||||
mov [edi],ebx ; *c = carry
|
||||
pop ebx
|
||||
pop esi
|
||||
pop edi
|
||||
leave
|
||||
ret
|
||||
nop
|
||||
_s_mpv_mul_d ENDP
|
||||
|
||||
; ebp - 36: caller's esi
|
||||
; ebp - 32: caller's edi
|
||||
; ebp - 28:
|
||||
; ebp - 24:
|
||||
; ebp - 20:
|
||||
; ebp - 16:
|
||||
; ebp - 12:
|
||||
; ebp - 8:
|
||||
; ebp - 4:
|
||||
; ebp + 0: caller's ebp
|
||||
; ebp + 4: return address
|
||||
; ebp + 8: a argument
|
||||
; ebp + 12: a_len argument
|
||||
; ebp + 16: b argument
|
||||
; ebp + 20: c argument
|
||||
; registers:
|
||||
; eax:
|
||||
; ebx: carry
|
||||
; ecx: a_len
|
||||
; edx:
|
||||
; esi: a ptr
|
||||
; edi: c ptr
|
||||
public _s_mpv_mul_d_add
|
||||
_s_mpv_mul_d_add PROC NEAR
|
||||
push ebp
|
||||
mov ebp,esp
|
||||
sub esp,28
|
||||
push edi
|
||||
push esi
|
||||
push ebx
|
||||
mov ebx,0 ; carry = 0
|
||||
mov ecx,[ebp+12] ; ecx = a_len
|
||||
mov edi,[ebp+20]
|
||||
cmp ecx,0
|
||||
je L_4 ; jmp if a_len == 0
|
||||
mov esi,[ebp+8] ; esi = a
|
||||
cld
|
||||
L_3:
|
||||
lodsd ; eax = [ds:esi]; esi += 4
|
||||
mov edx,[ebp+16] ; edx = b
|
||||
mul edx ; edx:eax = Phi:Plo = a_i * b
|
||||
|
||||
add eax,ebx ; add carry (ebx) to edx:eax
|
||||
adc edx,0
|
||||
mov ebx,[edi] ; add in current word from *c
|
||||
add eax,ebx
|
||||
adc edx,0
|
||||
mov ebx,edx ; high half of product becomes next carry
|
||||
|
||||
stosd ; [es:edi] = ax; edi += 4;
|
||||
dec ecx ; --a_len
|
||||
jnz L_3 ; jmp if a_len != 0
|
||||
L_4:
|
||||
mov [edi],ebx ; *c = carry
|
||||
pop ebx
|
||||
pop esi
|
||||
pop edi
|
||||
leave
|
||||
ret
|
||||
nop
|
||||
_s_mpv_mul_d_add ENDP
|
||||
|
||||
; ebp - 36: caller's esi
|
||||
; ebp - 32: caller's edi
|
||||
; ebp - 28:
|
||||
; ebp - 24:
|
||||
; ebp - 20:
|
||||
; ebp - 16:
|
||||
; ebp - 12:
|
||||
; ebp - 8:
|
||||
; ebp - 4:
|
||||
; ebp + 0: caller's ebp
|
||||
; ebp + 4: return address
|
||||
; ebp + 8: a argument
|
||||
; ebp + 12: a_len argument
|
||||
; ebp + 16: b argument
|
||||
; ebp + 20: c argument
|
||||
; registers:
|
||||
; eax:
|
||||
; ebx: carry
|
||||
; ecx: a_len
|
||||
; edx:
|
||||
; esi: a ptr
|
||||
; edi: c ptr
|
||||
public _s_mpv_mul_d_add_prop
|
||||
_s_mpv_mul_d_add_prop PROC NEAR
|
||||
push ebp
|
||||
mov ebp,esp
|
||||
sub esp,28
|
||||
push edi
|
||||
push esi
|
||||
push ebx
|
||||
mov ebx,0 ; carry = 0
|
||||
mov ecx,[ebp+12] ; ecx = a_len
|
||||
mov edi,[ebp+20]
|
||||
cmp ecx,0
|
||||
je L_6 ; jmp if a_len == 0
|
||||
cld
|
||||
mov esi,[ebp+8] ; esi = a
|
||||
L_5:
|
||||
lodsd ; eax = [ds:esi]; esi += 4
|
||||
mov edx,[ebp+16] ; edx = b
|
||||
mul edx ; edx:eax = Phi:Plo = a_i * b
|
||||
|
||||
add eax,ebx ; add carry (ebx) to edx:eax
|
||||
adc edx,0
|
||||
mov ebx,[edi] ; add in current word from *c
|
||||
add eax,ebx
|
||||
adc edx,0
|
||||
mov ebx,edx ; high half of product becomes next carry
|
||||
|
||||
stosd ; [es:edi] = ax; edi += 4;
|
||||
dec ecx ; --a_len
|
||||
jnz L_5 ; jmp if a_len != 0
|
||||
L_6:
|
||||
cmp ebx,0 ; is carry zero?
|
||||
jz L_8
|
||||
mov eax,[edi] ; add in current word from *c
|
||||
add eax,ebx
|
||||
stosd ; [es:edi] = ax; edi += 4;
|
||||
jnc L_8
|
||||
L_7:
|
||||
mov eax,[edi] ; add in current word from *c
|
||||
adc eax,0
|
||||
stosd ; [es:edi] = ax; edi += 4;
|
||||
jc L_7
|
||||
L_8:
|
||||
pop ebx
|
||||
pop esi
|
||||
pop edi
|
||||
leave
|
||||
ret
|
||||
nop
|
||||
_s_mpv_mul_d_add_prop ENDP
|
||||
|
||||
; ebp - 20: caller's esi
|
||||
; ebp - 16: caller's edi
|
||||
; ebp - 12:
|
||||
; ebp - 8: carry
|
||||
; ebp - 4: a_len local
|
||||
; ebp + 0: caller's ebp
|
||||
; ebp + 4: return address
|
||||
; ebp + 8: pa argument
|
||||
; ebp + 12: a_len argument
|
||||
; ebp + 16: ps argument
|
||||
; ebp + 20:
|
||||
; registers:
|
||||
; eax:
|
||||
; ebx: carry
|
||||
; ecx: a_len
|
||||
; edx:
|
||||
; esi: a ptr
|
||||
; edi: c ptr
|
||||
|
||||
public _s_mpv_sqr_add_prop
|
||||
_s_mpv_sqr_add_prop PROC NEAR
|
||||
push ebp
|
||||
mov ebp,esp
|
||||
sub esp,12
|
||||
push edi
|
||||
push esi
|
||||
push ebx
|
||||
mov ebx,0 ; carry = 0
|
||||
mov ecx,[ebp+12] ; a_len
|
||||
mov edi,[ebp+16] ; edi = ps
|
||||
cmp ecx,0
|
||||
je L_11 ; jump if a_len == 0
|
||||
cld
|
||||
mov esi,[ebp+8] ; esi = pa
|
||||
L_10:
|
||||
lodsd ; eax = [ds:si]; si += 4;
|
||||
mul eax
|
||||
|
||||
add eax,ebx ; add "carry"
|
||||
adc edx,0
|
||||
mov ebx,[edi]
|
||||
add eax,ebx ; add low word from result
|
||||
mov ebx,[edi+4]
|
||||
stosd ; [es:di] = eax; di += 4;
|
||||
adc edx,ebx ; add high word from result
|
||||
mov ebx,0
|
||||
mov eax,edx
|
||||
adc ebx,0
|
||||
stosd ; [es:di] = eax; di += 4;
|
||||
dec ecx ; --a_len
|
||||
jnz L_10 ; jmp if a_len != 0
|
||||
L_11:
|
||||
cmp ebx,0 ; is carry zero?
|
||||
jz L_14
|
||||
mov eax,[edi] ; add in current word from *c
|
||||
add eax,ebx
|
||||
stosd ; [es:edi] = ax; edi += 4;
|
||||
jnc L_14
|
||||
L_12:
|
||||
mov eax,[edi] ; add in current word from *c
|
||||
adc eax,0
|
||||
stosd ; [es:edi] = ax; edi += 4;
|
||||
jc L_12
|
||||
L_14:
|
||||
pop ebx
|
||||
pop esi
|
||||
pop edi
|
||||
leave
|
||||
ret
|
||||
nop
|
||||
_s_mpv_sqr_add_prop ENDP
|
||||
|
||||
;
|
||||
; Divide 64-bit (Nhi,Nlo) by 32-bit divisor, which must be normalized
|
||||
; so its high bit is 1. This code is from NSPR.
|
||||
;
|
||||
; mp_err s_mpv_div_2dx1d(mp_digit Nhi, mp_digit Nlo, mp_digit divisor,
|
||||
; mp_digit *qp, mp_digit *rp)
|
||||
|
||||
; Dump of assembler code for function s_mpv_div_2dx1d:
|
||||
;
|
||||
; esp + 0: Caller's ebx
|
||||
; esp + 4: return address
|
||||
; esp + 8: Nhi argument
|
||||
; esp + 12: Nlo argument
|
||||
; esp + 16: divisor argument
|
||||
; esp + 20: qp argument
|
||||
; esp + 24: rp argument
|
||||
; registers:
|
||||
; eax:
|
||||
; ebx: carry
|
||||
; ecx: a_len
|
||||
; edx:
|
||||
; esi: a ptr
|
||||
; edi: c ptr
|
||||
;
|
||||
public _s_mpv_div_2dx1d
|
||||
_s_mpv_div_2dx1d PROC NEAR
|
||||
push ebx
|
||||
mov edx,[esp+8]
|
||||
mov eax,[esp+12]
|
||||
mov ebx,[esp+16]
|
||||
div ebx
|
||||
mov ebx,[esp+20]
|
||||
mov [ebx],eax
|
||||
mov ebx,[esp+24]
|
||||
mov [ebx],edx
|
||||
xor eax,eax ; return zero
|
||||
pop ebx
|
||||
ret
|
||||
nop
|
||||
_s_mpv_div_2dx1d ENDP
|
||||
|
||||
_TEXT ENDS
|
||||
END
|
||||
@@ -1,345 +0,0 @@
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 2000 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU General Public License Version 2 or later (the
|
||||
# "GPL"), in which case the provisions of the GPL are applicable
|
||||
# instead of those above. If you wish to allow use of your
|
||||
# version of this file only under the terms of the GPL and not to
|
||||
# allow others to use your version of this file under the MPL,
|
||||
# indicate your decision by deleting the provisions above and
|
||||
# replace them with the notice and other provisions required by
|
||||
# the GPL. If you do not delete the provisions above, a recipient
|
||||
# may use your version of this file under either the MPL or the
|
||||
# GPL.
|
||||
# $Id: mpi_x86.s,v 1.4 2003-10-24 04:47:23 wchang0222%aol.com Exp $
|
||||
#
|
||||
|
||||
.text
|
||||
|
||||
# ebp - 36: caller's esi
|
||||
# ebp - 32: caller's edi
|
||||
# ebp - 28:
|
||||
# ebp - 24:
|
||||
# ebp - 20:
|
||||
# ebp - 16:
|
||||
# ebp - 12:
|
||||
# ebp - 8:
|
||||
# ebp - 4:
|
||||
# ebp + 0: caller's ebp
|
||||
# ebp + 4: return address
|
||||
# ebp + 8: a argument
|
||||
# ebp + 12: a_len argument
|
||||
# ebp + 16: b argument
|
||||
# ebp + 20: c argument
|
||||
# registers:
|
||||
# eax:
|
||||
# ebx: carry
|
||||
# ecx: a_len
|
||||
# edx:
|
||||
# esi: a ptr
|
||||
# edi: c ptr
|
||||
.globl s_mpv_mul_d
|
||||
.type s_mpv_mul_d,@function
|
||||
s_mpv_mul_d:
|
||||
push %ebp
|
||||
mov %esp,%ebp
|
||||
sub $28,%esp
|
||||
push %edi
|
||||
push %esi
|
||||
push %ebx
|
||||
movl $0,%ebx # carry = 0
|
||||
mov 12(%ebp),%ecx # ecx = a_len
|
||||
mov 20(%ebp),%edi
|
||||
cmp $0,%ecx
|
||||
je 2f # jmp if a_len == 0
|
||||
mov 8(%ebp),%esi # esi = a
|
||||
cld
|
||||
1:
|
||||
lodsl # eax = [ds:esi]; esi += 4
|
||||
mov 16(%ebp),%edx # edx = b
|
||||
mull %edx # edx:eax = Phi:Plo = a_i * b
|
||||
|
||||
add %ebx,%eax # add carry (%ebx) to edx:eax
|
||||
adc $0,%edx
|
||||
mov %edx,%ebx # high half of product becomes next carry
|
||||
|
||||
stosl # [es:edi] = ax; edi += 4;
|
||||
dec %ecx # --a_len
|
||||
jnz 1b # jmp if a_len != 0
|
||||
2:
|
||||
mov %ebx,0(%edi) # *c = carry
|
||||
pop %ebx
|
||||
pop %esi
|
||||
pop %edi
|
||||
leave
|
||||
ret
|
||||
nop
|
||||
|
||||
# ebp - 36: caller's esi
|
||||
# ebp - 32: caller's edi
|
||||
# ebp - 28:
|
||||
# ebp - 24:
|
||||
# ebp - 20:
|
||||
# ebp - 16:
|
||||
# ebp - 12:
|
||||
# ebp - 8:
|
||||
# ebp - 4:
|
||||
# ebp + 0: caller's ebp
|
||||
# ebp + 4: return address
|
||||
# ebp + 8: a argument
|
||||
# ebp + 12: a_len argument
|
||||
# ebp + 16: b argument
|
||||
# ebp + 20: c argument
|
||||
# registers:
|
||||
# eax:
|
||||
# ebx: carry
|
||||
# ecx: a_len
|
||||
# edx:
|
||||
# esi: a ptr
|
||||
# edi: c ptr
|
||||
.globl s_mpv_mul_d_add
|
||||
.type s_mpv_mul_d_add,@function
|
||||
s_mpv_mul_d_add:
|
||||
push %ebp
|
||||
mov %esp,%ebp
|
||||
sub $28,%esp
|
||||
push %edi
|
||||
push %esi
|
||||
push %ebx
|
||||
movl $0,%ebx # carry = 0
|
||||
mov 12(%ebp),%ecx # ecx = a_len
|
||||
mov 20(%ebp),%edi
|
||||
cmp $0,%ecx
|
||||
je 4f # jmp if a_len == 0
|
||||
mov 8(%ebp),%esi # esi = a
|
||||
cld
|
||||
3:
|
||||
lodsl # eax = [ds:esi]; esi += 4
|
||||
mov 16(%ebp),%edx # edx = b
|
||||
mull %edx # edx:eax = Phi:Plo = a_i * b
|
||||
|
||||
add %ebx,%eax # add carry (%ebx) to edx:eax
|
||||
adc $0,%edx
|
||||
mov 0(%edi),%ebx # add in current word from *c
|
||||
add %ebx,%eax
|
||||
adc $0,%edx
|
||||
mov %edx,%ebx # high half of product becomes next carry
|
||||
|
||||
stosl # [es:edi] = ax; edi += 4;
|
||||
dec %ecx # --a_len
|
||||
jnz 3b # jmp if a_len != 0
|
||||
4:
|
||||
mov %ebx,0(%edi) # *c = carry
|
||||
pop %ebx
|
||||
pop %esi
|
||||
pop %edi
|
||||
leave
|
||||
ret
|
||||
nop
|
||||
|
||||
# ebp - 36: caller's esi
|
||||
# ebp - 32: caller's edi
|
||||
# ebp - 28:
|
||||
# ebp - 24:
|
||||
# ebp - 20:
|
||||
# ebp - 16:
|
||||
# ebp - 12:
|
||||
# ebp - 8:
|
||||
# ebp - 4:
|
||||
# ebp + 0: caller's ebp
|
||||
# ebp + 4: return address
|
||||
# ebp + 8: a argument
|
||||
# ebp + 12: a_len argument
|
||||
# ebp + 16: b argument
|
||||
# ebp + 20: c argument
|
||||
# registers:
|
||||
# eax:
|
||||
# ebx: carry
|
||||
# ecx: a_len
|
||||
# edx:
|
||||
# esi: a ptr
|
||||
# edi: c ptr
|
||||
.globl s_mpv_mul_d_add_prop
|
||||
.type s_mpv_mul_d_add_prop,@function
|
||||
s_mpv_mul_d_add_prop:
|
||||
push %ebp
|
||||
mov %esp,%ebp
|
||||
sub $28,%esp
|
||||
push %edi
|
||||
push %esi
|
||||
push %ebx
|
||||
movl $0,%ebx # carry = 0
|
||||
mov 12(%ebp),%ecx # ecx = a_len
|
||||
mov 20(%ebp),%edi
|
||||
cmp $0,%ecx
|
||||
je 6f # jmp if a_len == 0
|
||||
cld
|
||||
mov 8(%ebp),%esi # esi = a
|
||||
5:
|
||||
lodsl # eax = [ds:esi]; esi += 4
|
||||
mov 16(%ebp),%edx # edx = b
|
||||
mull %edx # edx:eax = Phi:Plo = a_i * b
|
||||
|
||||
add %ebx,%eax # add carry (%ebx) to edx:eax
|
||||
adc $0,%edx
|
||||
mov 0(%edi),%ebx # add in current word from *c
|
||||
add %ebx,%eax
|
||||
adc $0,%edx
|
||||
mov %edx,%ebx # high half of product becomes next carry
|
||||
|
||||
stosl # [es:edi] = ax; edi += 4;
|
||||
dec %ecx # --a_len
|
||||
jnz 5b # jmp if a_len != 0
|
||||
6:
|
||||
cmp $0,%ebx # is carry zero?
|
||||
jz 8f
|
||||
mov 0(%edi),%eax # add in current word from *c
|
||||
add %ebx,%eax
|
||||
stosl # [es:edi] = ax; edi += 4;
|
||||
jnc 8f
|
||||
7:
|
||||
mov 0(%edi),%eax # add in current word from *c
|
||||
adc $0,%eax
|
||||
stosl # [es:edi] = ax; edi += 4;
|
||||
jc 7b
|
||||
8:
|
||||
pop %ebx
|
||||
pop %esi
|
||||
pop %edi
|
||||
leave
|
||||
ret
|
||||
nop
|
||||
|
||||
# ebp - 20: caller's esi
|
||||
# ebp - 16: caller's edi
|
||||
# ebp - 12:
|
||||
# ebp - 8: carry
|
||||
# ebp - 4: a_len local
|
||||
# ebp + 0: caller's ebp
|
||||
# ebp + 4: return address
|
||||
# ebp + 8: pa argument
|
||||
# ebp + 12: a_len argument
|
||||
# ebp + 16: ps argument
|
||||
# ebp + 20:
|
||||
# registers:
|
||||
# eax:
|
||||
# ebx: carry
|
||||
# ecx: a_len
|
||||
# edx:
|
||||
# esi: a ptr
|
||||
# edi: c ptr
|
||||
|
||||
.globl s_mpv_sqr_add_prop
|
||||
.type s_mpv_sqr_add_prop,@function
|
||||
s_mpv_sqr_add_prop:
|
||||
push %ebp
|
||||
mov %esp,%ebp
|
||||
sub $12,%esp
|
||||
push %edi
|
||||
push %esi
|
||||
push %ebx
|
||||
movl $0,%ebx # carry = 0
|
||||
mov 12(%ebp),%ecx # a_len
|
||||
mov 16(%ebp),%edi # edi = ps
|
||||
cmp $0,%ecx
|
||||
je 11f # jump if a_len == 0
|
||||
cld
|
||||
mov 8(%ebp),%esi # esi = pa
|
||||
10:
|
||||
lodsl # %eax = [ds:si]; si += 4;
|
||||
mull %eax
|
||||
|
||||
add %ebx,%eax # add "carry"
|
||||
adc $0,%edx
|
||||
mov 0(%edi),%ebx
|
||||
add %ebx,%eax # add low word from result
|
||||
mov 4(%edi),%ebx
|
||||
stosl # [es:di] = %eax; di += 4;
|
||||
adc %ebx,%edx # add high word from result
|
||||
movl $0,%ebx
|
||||
mov %edx,%eax
|
||||
adc $0,%ebx
|
||||
stosl # [es:di] = %eax; di += 4;
|
||||
dec %ecx # --a_len
|
||||
jnz 10b # jmp if a_len != 0
|
||||
11:
|
||||
cmp $0,%ebx # is carry zero?
|
||||
jz 14f
|
||||
mov 0(%edi),%eax # add in current word from *c
|
||||
add %ebx,%eax
|
||||
stosl # [es:edi] = ax; edi += 4;
|
||||
jnc 14f
|
||||
12:
|
||||
mov 0(%edi),%eax # add in current word from *c
|
||||
adc $0,%eax
|
||||
stosl # [es:edi] = ax; edi += 4;
|
||||
jc 12b
|
||||
14:
|
||||
pop %ebx
|
||||
pop %esi
|
||||
pop %edi
|
||||
leave
|
||||
ret
|
||||
nop
|
||||
|
||||
#
|
||||
# Divide 64-bit (Nhi,Nlo) by 32-bit divisor, which must be normalized
|
||||
# so its high bit is 1. This code is from NSPR.
|
||||
#
|
||||
# mp_err s_mpv_div_2dx1d(mp_digit Nhi, mp_digit Nlo, mp_digit divisor,
|
||||
# mp_digit *qp, mp_digit *rp)
|
||||
|
||||
# esp + 0: Caller's ebx
|
||||
# esp + 4: return address
|
||||
# esp + 8: Nhi argument
|
||||
# esp + 12: Nlo argument
|
||||
# esp + 16: divisor argument
|
||||
# esp + 20: qp argument
|
||||
# esp + 24: rp argument
|
||||
# registers:
|
||||
# eax:
|
||||
# ebx: carry
|
||||
# ecx: a_len
|
||||
# edx:
|
||||
# esi: a ptr
|
||||
# edi: c ptr
|
||||
#
|
||||
|
||||
.globl s_mpv_div_2dx1d
|
||||
.type s_mpv_div_2dx1d,@function
|
||||
s_mpv_div_2dx1d:
|
||||
push %ebx
|
||||
mov 8(%esp),%edx
|
||||
mov 12(%esp),%eax
|
||||
mov 16(%esp),%ebx
|
||||
div %ebx
|
||||
mov 20(%esp),%ebx
|
||||
mov %eax,0(%ebx)
|
||||
mov 24(%esp),%ebx
|
||||
mov %edx,0(%ebx)
|
||||
xor %eax,%eax # return zero
|
||||
pop %ebx
|
||||
ret
|
||||
nop
|
||||
|
||||
# Magic indicating no need for an executable stack
|
||||
.section .note.GNU-stack, "", @progbits
|
||||
.previous
|
||||
@@ -1,465 +0,0 @@
|
||||
/*
|
||||
* mplogic.c
|
||||
*
|
||||
* Bitwise logical operations on MPI values
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael J. Fromberger.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: mplogic.c,v 1.15 2004-04-27 23:04:36 gerv%gerv.net Exp $ */
|
||||
|
||||
#include "mpi-priv.h"
|
||||
#include "mplogic.h"
|
||||
|
||||
/* {{{ Lookup table for population count */
|
||||
|
||||
static unsigned char bitc[] = {
|
||||
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
|
||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
||||
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
||||
4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
|
||||
};
|
||||
|
||||
/* }}} */
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/*
|
||||
mpl_not(a, b) - compute b = ~a
|
||||
mpl_and(a, b, c) - compute c = a & b
|
||||
mpl_or(a, b, c) - compute c = a | b
|
||||
mpl_xor(a, b, c) - compute c = a ^ b
|
||||
*/
|
||||
|
||||
/* {{{ mpl_not(a, b) */
|
||||
|
||||
mp_err mpl_not(mp_int *a, mp_int *b)
|
||||
{
|
||||
mp_err res;
|
||||
unsigned int ix;
|
||||
|
||||
ARGCHK(a != NULL && b != NULL, MP_BADARG);
|
||||
|
||||
if((res = mp_copy(a, b)) != MP_OKAY)
|
||||
return res;
|
||||
|
||||
/* This relies on the fact that the digit type is unsigned */
|
||||
for(ix = 0; ix < USED(b); ix++)
|
||||
DIGIT(b, ix) = ~DIGIT(b, ix);
|
||||
|
||||
s_mp_clamp(b);
|
||||
|
||||
return MP_OKAY;
|
||||
|
||||
} /* end mpl_not() */
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ mpl_and(a, b, c) */
|
||||
|
||||
mp_err mpl_and(mp_int *a, mp_int *b, mp_int *c)
|
||||
{
|
||||
mp_int *which, *other;
|
||||
mp_err res;
|
||||
unsigned int ix;
|
||||
|
||||
ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
|
||||
|
||||
if(USED(a) <= USED(b)) {
|
||||
which = a;
|
||||
other = b;
|
||||
} else {
|
||||
which = b;
|
||||
other = a;
|
||||
}
|
||||
|
||||
if((res = mp_copy(which, c)) != MP_OKAY)
|
||||
return res;
|
||||
|
||||
for(ix = 0; ix < USED(which); ix++)
|
||||
DIGIT(c, ix) &= DIGIT(other, ix);
|
||||
|
||||
s_mp_clamp(c);
|
||||
|
||||
return MP_OKAY;
|
||||
|
||||
} /* end mpl_and() */
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ mpl_or(a, b, c) */
|
||||
|
||||
mp_err mpl_or(mp_int *a, mp_int *b, mp_int *c)
|
||||
{
|
||||
mp_int *which, *other;
|
||||
mp_err res;
|
||||
unsigned int ix;
|
||||
|
||||
ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
|
||||
|
||||
if(USED(a) >= USED(b)) {
|
||||
which = a;
|
||||
other = b;
|
||||
} else {
|
||||
which = b;
|
||||
other = a;
|
||||
}
|
||||
|
||||
if((res = mp_copy(which, c)) != MP_OKAY)
|
||||
return res;
|
||||
|
||||
for(ix = 0; ix < USED(which); ix++)
|
||||
DIGIT(c, ix) |= DIGIT(other, ix);
|
||||
|
||||
return MP_OKAY;
|
||||
|
||||
} /* end mpl_or() */
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ mpl_xor(a, b, c) */
|
||||
|
||||
mp_err mpl_xor(mp_int *a, mp_int *b, mp_int *c)
|
||||
{
|
||||
mp_int *which, *other;
|
||||
mp_err res;
|
||||
unsigned int ix;
|
||||
|
||||
ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
|
||||
|
||||
if(USED(a) >= USED(b)) {
|
||||
which = a;
|
||||
other = b;
|
||||
} else {
|
||||
which = b;
|
||||
other = a;
|
||||
}
|
||||
|
||||
if((res = mp_copy(which, c)) != MP_OKAY)
|
||||
return res;
|
||||
|
||||
for(ix = 0; ix < USED(which); ix++)
|
||||
DIGIT(c, ix) ^= DIGIT(other, ix);
|
||||
|
||||
s_mp_clamp(c);
|
||||
|
||||
return MP_OKAY;
|
||||
|
||||
} /* end mpl_xor() */
|
||||
|
||||
/* }}} */
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/*
|
||||
mpl_rsh(a, b, d) - b = a >> d
|
||||
mpl_lsh(a, b, d) - b = a << d
|
||||
*/
|
||||
|
||||
/* {{{ mpl_rsh(a, b, d) */
|
||||
|
||||
mp_err mpl_rsh(const mp_int *a, mp_int *b, mp_digit d)
|
||||
{
|
||||
mp_err res;
|
||||
|
||||
ARGCHK(a != NULL && b != NULL, MP_BADARG);
|
||||
|
||||
if((res = mp_copy(a, b)) != MP_OKAY)
|
||||
return res;
|
||||
|
||||
s_mp_div_2d(b, d);
|
||||
|
||||
return MP_OKAY;
|
||||
|
||||
} /* end mpl_rsh() */
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ mpl_lsh(a, b, d) */
|
||||
|
||||
mp_err mpl_lsh(const mp_int *a, mp_int *b, mp_digit d)
|
||||
{
|
||||
mp_err res;
|
||||
|
||||
ARGCHK(a != NULL && b != NULL, MP_BADARG);
|
||||
|
||||
if((res = mp_copy(a, b)) != MP_OKAY)
|
||||
return res;
|
||||
|
||||
return s_mp_mul_2d(b, d);
|
||||
|
||||
} /* end mpl_lsh() */
|
||||
|
||||
/* }}} */
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/*
|
||||
mpl_num_set(a, num)
|
||||
|
||||
Count the number of set bits in the binary representation of a.
|
||||
Returns MP_OKAY and sets 'num' to be the number of such bits, if
|
||||
possible. If num is NULL, the result is thrown away, but it is
|
||||
not considered an error.
|
||||
|
||||
mpl_num_clear() does basically the same thing for clear bits.
|
||||
*/
|
||||
|
||||
/* {{{ mpl_num_set(a, num) */
|
||||
|
||||
mp_err mpl_num_set(mp_int *a, int *num)
|
||||
{
|
||||
unsigned int ix;
|
||||
int db, nset = 0;
|
||||
mp_digit cur;
|
||||
unsigned char reg;
|
||||
|
||||
ARGCHK(a != NULL, MP_BADARG);
|
||||
|
||||
for(ix = 0; ix < USED(a); ix++) {
|
||||
cur = DIGIT(a, ix);
|
||||
|
||||
for(db = 0; db < sizeof(mp_digit); db++) {
|
||||
reg = (unsigned char)(cur >> (CHAR_BIT * db));
|
||||
|
||||
nset += bitc[reg];
|
||||
}
|
||||
}
|
||||
|
||||
if(num)
|
||||
*num = nset;
|
||||
|
||||
return MP_OKAY;
|
||||
|
||||
} /* end mpl_num_set() */
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ mpl_num_clear(a, num) */
|
||||
|
||||
mp_err mpl_num_clear(mp_int *a, int *num)
|
||||
{
|
||||
unsigned int ix;
|
||||
int db, nset = 0;
|
||||
mp_digit cur;
|
||||
unsigned char reg;
|
||||
|
||||
ARGCHK(a != NULL, MP_BADARG);
|
||||
|
||||
for(ix = 0; ix < USED(a); ix++) {
|
||||
cur = DIGIT(a, ix);
|
||||
|
||||
for(db = 0; db < sizeof(mp_digit); db++) {
|
||||
reg = (unsigned char)(cur >> (CHAR_BIT * db));
|
||||
|
||||
nset += bitc[UCHAR_MAX - reg];
|
||||
}
|
||||
}
|
||||
|
||||
if(num)
|
||||
*num = nset;
|
||||
|
||||
return MP_OKAY;
|
||||
|
||||
|
||||
} /* end mpl_num_clear() */
|
||||
|
||||
/* }}} */
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/*
|
||||
mpl_parity(a)
|
||||
|
||||
Determines the bitwise parity of the value given. Returns MP_EVEN
|
||||
if an even number of digits are set, MP_ODD if an odd number are
|
||||
set.
|
||||
*/
|
||||
|
||||
/* {{{ mpl_parity(a) */
|
||||
|
||||
mp_err mpl_parity(mp_int *a)
|
||||
{
|
||||
unsigned int ix;
|
||||
int par = 0;
|
||||
mp_digit cur;
|
||||
|
||||
ARGCHK(a != NULL, MP_BADARG);
|
||||
|
||||
for(ix = 0; ix < USED(a); ix++) {
|
||||
int shft = (sizeof(mp_digit) * CHAR_BIT) / 2;
|
||||
|
||||
cur = DIGIT(a, ix);
|
||||
|
||||
/* Compute parity for current digit */
|
||||
while(shft != 0) {
|
||||
cur ^= (cur >> shft);
|
||||
shft >>= 1;
|
||||
}
|
||||
cur &= 1;
|
||||
|
||||
/* XOR with running parity so far */
|
||||
par ^= cur;
|
||||
}
|
||||
|
||||
if(par)
|
||||
return MP_ODD;
|
||||
else
|
||||
return MP_EVEN;
|
||||
|
||||
} /* end mpl_parity() */
|
||||
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
mpl_set_bit
|
||||
|
||||
Returns MP_OKAY or some error code.
|
||||
Grows a if needed to set a bit to 1.
|
||||
*/
|
||||
mp_err mpl_set_bit(mp_int *a, mp_size bitNum, mp_size value)
|
||||
{
|
||||
mp_size ix;
|
||||
mp_err rv;
|
||||
mp_digit mask;
|
||||
|
||||
ARGCHK(a != NULL, MP_BADARG);
|
||||
|
||||
ix = bitNum / MP_DIGIT_BIT;
|
||||
if (ix + 1 > MP_USED(a)) {
|
||||
rv = s_mp_pad(a, ix + 1);
|
||||
if (rv != MP_OKAY)
|
||||
return rv;
|
||||
}
|
||||
|
||||
bitNum = bitNum % MP_DIGIT_BIT;
|
||||
mask = (mp_digit)1 << bitNum;
|
||||
if (value)
|
||||
MP_DIGIT(a,ix) |= mask;
|
||||
else
|
||||
MP_DIGIT(a,ix) &= ~mask;
|
||||
s_mp_clamp(a);
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
/*
|
||||
mpl_get_bit
|
||||
|
||||
returns 0 or 1 or some (negative) error code.
|
||||
*/
|
||||
mp_err mpl_get_bit(const mp_int *a, mp_size bitNum)
|
||||
{
|
||||
mp_size bit, ix;
|
||||
mp_err rv;
|
||||
|
||||
ARGCHK(a != NULL, MP_BADARG);
|
||||
|
||||
ix = bitNum / MP_DIGIT_BIT;
|
||||
ARGCHK(ix <= MP_USED(a) - 1, MP_RANGE);
|
||||
|
||||
bit = bitNum % MP_DIGIT_BIT;
|
||||
rv = (mp_err)(MP_DIGIT(a, ix) >> bit) & 1;
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
mpl_get_bits
|
||||
- Extracts numBits bits from a, where the least significant extracted bit
|
||||
is bit lsbNum. Returns a negative value if error occurs.
|
||||
- Because sign bit is used to indicate error, maximum number of bits to
|
||||
be returned is the lesser of (a) the number of bits in an mp_digit, or
|
||||
(b) one less than the number of bits in an mp_err.
|
||||
- lsbNum + numbits can be greater than the number of significant bits in
|
||||
integer a, as long as bit lsbNum is in the high order digit of a.
|
||||
*/
|
||||
mp_err mpl_get_bits(const mp_int *a, mp_size lsbNum, mp_size numBits)
|
||||
{
|
||||
mp_size rshift = (lsbNum % MP_DIGIT_BIT);
|
||||
mp_size lsWndx = (lsbNum / MP_DIGIT_BIT);
|
||||
mp_digit * digit = MP_DIGITS(a) + lsWndx;
|
||||
mp_digit mask = ((1 << numBits) - 1);
|
||||
|
||||
ARGCHK(numBits < CHAR_BIT * sizeof mask, MP_BADARG);
|
||||
ARGCHK(MP_HOWMANY(lsbNum, MP_DIGIT_BIT) <= MP_USED(a), MP_RANGE);
|
||||
|
||||
if ((numBits + lsbNum % MP_DIGIT_BIT <= MP_DIGIT_BIT) ||
|
||||
(lsWndx + 1 >= MP_USED(a))) {
|
||||
mask &= (digit[0] >> rshift);
|
||||
} else {
|
||||
mask &= ((digit[0] >> rshift) | (digit[1] << (MP_DIGIT_BIT - rshift)));
|
||||
}
|
||||
return (mp_err)mask;
|
||||
}
|
||||
|
||||
/*
|
||||
mpl_significant_bits
|
||||
returns number of significnant bits in abs(a).
|
||||
returns 1 if value is zero.
|
||||
*/
|
||||
mp_err mpl_significant_bits(const mp_int *a)
|
||||
{
|
||||
mp_err bits = 0;
|
||||
int ix;
|
||||
|
||||
ARGCHK(a != NULL, MP_BADARG);
|
||||
|
||||
ix = MP_USED(a);
|
||||
for (ix = MP_USED(a); ix > 0; ) {
|
||||
mp_digit d;
|
||||
d = MP_DIGIT(a, --ix);
|
||||
if (d) {
|
||||
while (d) {
|
||||
++bits;
|
||||
d >>= 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
bits += ix * MP_DIGIT_BIT;
|
||||
if (!bits)
|
||||
bits = 1;
|
||||
return bits;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* HERE THERE BE DRAGONS */
|
||||
@@ -1,85 +0,0 @@
|
||||
/*
|
||||
* mplogic.h
|
||||
*
|
||||
* Bitwise logical operations on MPI values
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael J. Fromberger.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: mplogic.h,v 1.7 2004-04-27 23:04:36 gerv%gerv.net Exp $ */
|
||||
|
||||
#ifndef _H_MPLOGIC_
|
||||
#define _H_MPLOGIC_
|
||||
|
||||
#include "mpi.h"
|
||||
|
||||
/*
|
||||
The logical operations treat an mp_int as if it were a bit vector,
|
||||
without regard to its sign (an mp_int is represented in a signed
|
||||
magnitude format). Values are treated as if they had an infinite
|
||||
string of zeros left of the most-significant bit.
|
||||
*/
|
||||
|
||||
/* Parity results */
|
||||
|
||||
#define MP_EVEN MP_YES
|
||||
#define MP_ODD MP_NO
|
||||
|
||||
/* Bitwise functions */
|
||||
|
||||
mp_err mpl_not(mp_int *a, mp_int *b); /* one's complement */
|
||||
mp_err mpl_and(mp_int *a, mp_int *b, mp_int *c); /* bitwise AND */
|
||||
mp_err mpl_or(mp_int *a, mp_int *b, mp_int *c); /* bitwise OR */
|
||||
mp_err mpl_xor(mp_int *a, mp_int *b, mp_int *c); /* bitwise XOR */
|
||||
|
||||
/* Shift functions */
|
||||
|
||||
mp_err mpl_rsh(const mp_int *a, mp_int *b, mp_digit d); /* right shift */
|
||||
mp_err mpl_lsh(const mp_int *a, mp_int *b, mp_digit d); /* left shift */
|
||||
|
||||
/* Bit count and parity */
|
||||
|
||||
mp_err mpl_num_set(mp_int *a, int *num); /* count set bits */
|
||||
mp_err mpl_num_clear(mp_int *a, int *num); /* count clear bits */
|
||||
mp_err mpl_parity(mp_int *a); /* determine parity */
|
||||
|
||||
/* Get & Set the value of a bit */
|
||||
|
||||
mp_err mpl_set_bit(mp_int *a, mp_size bitNum, mp_size value);
|
||||
mp_err mpl_get_bit(const mp_int *a, mp_size bitNum);
|
||||
mp_err mpl_get_bits(const mp_int *a, mp_size lsbNum, mp_size numBits);
|
||||
mp_err mpl_significant_bits(const mp_int *a);
|
||||
|
||||
#endif /* end _H_MPLOGIC_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,626 +0,0 @@
|
||||
/*
|
||||
* mpprime.c
|
||||
*
|
||||
* Utilities for finding and working with prime and pseudo-prime
|
||||
* integers
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael J. Fromberger.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1997
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Netscape Communications Corporation
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "mpi-priv.h"
|
||||
#include "mpprime.h"
|
||||
#include "mplogic.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define SMALL_TABLE 0 /* determines size of hard-wired prime table */
|
||||
|
||||
#define RANDOM() rand()
|
||||
|
||||
#include "primes.c" /* pull in the prime digit table */
|
||||
|
||||
/*
|
||||
Test if any of a given vector of digits divides a. If not, MP_NO
|
||||
is returned; otherwise, MP_YES is returned and 'which' is set to
|
||||
the index of the integer in the vector which divided a.
|
||||
*/
|
||||
mp_err s_mpp_divp(mp_int *a, const mp_digit *vec, int size, int *which);
|
||||
|
||||
/* {{{ mpp_divis(a, b) */
|
||||
|
||||
/*
|
||||
mpp_divis(a, b)
|
||||
|
||||
Returns MP_YES if a is divisible by b, or MP_NO if it is not.
|
||||
*/
|
||||
|
||||
mp_err mpp_divis(mp_int *a, mp_int *b)
|
||||
{
|
||||
mp_err res;
|
||||
mp_int rem;
|
||||
|
||||
if((res = mp_init(&rem)) != MP_OKAY)
|
||||
return res;
|
||||
|
||||
if((res = mp_mod(a, b, &rem)) != MP_OKAY)
|
||||
goto CLEANUP;
|
||||
|
||||
if(mp_cmp_z(&rem) == 0)
|
||||
res = MP_YES;
|
||||
else
|
||||
res = MP_NO;
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&rem);
|
||||
return res;
|
||||
|
||||
} /* end mpp_divis() */
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ mpp_divis_d(a, d) */
|
||||
|
||||
/*
|
||||
mpp_divis_d(a, d)
|
||||
|
||||
Return MP_YES if a is divisible by d, or MP_NO if it is not.
|
||||
*/
|
||||
|
||||
mp_err mpp_divis_d(mp_int *a, mp_digit d)
|
||||
{
|
||||
mp_err res;
|
||||
mp_digit rem;
|
||||
|
||||
ARGCHK(a != NULL, MP_BADARG);
|
||||
|
||||
if(d == 0)
|
||||
return MP_NO;
|
||||
|
||||
if((res = mp_mod_d(a, d, &rem)) != MP_OKAY)
|
||||
return res;
|
||||
|
||||
if(rem == 0)
|
||||
return MP_YES;
|
||||
else
|
||||
return MP_NO;
|
||||
|
||||
} /* end mpp_divis_d() */
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ mpp_random(a) */
|
||||
|
||||
/*
|
||||
mpp_random(a)
|
||||
|
||||
Assigns a random value to a. This value is generated using the
|
||||
standard C library's rand() function, so it should not be used for
|
||||
cryptographic purposes, but it should be fine for primality testing,
|
||||
since all we really care about there is good statistical properties.
|
||||
|
||||
As many digits as a currently has are filled with random digits.
|
||||
*/
|
||||
|
||||
mp_err mpp_random(mp_int *a)
|
||||
|
||||
{
|
||||
mp_digit next = 0;
|
||||
unsigned int ix, jx;
|
||||
|
||||
ARGCHK(a != NULL, MP_BADARG);
|
||||
|
||||
for(ix = 0; ix < USED(a); ix++) {
|
||||
for(jx = 0; jx < sizeof(mp_digit); jx++) {
|
||||
next = (next << CHAR_BIT) | (RANDOM() & UCHAR_MAX);
|
||||
}
|
||||
DIGIT(a, ix) = next;
|
||||
}
|
||||
|
||||
return MP_OKAY;
|
||||
|
||||
} /* end mpp_random() */
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ mpp_random_size(a, prec) */
|
||||
|
||||
mp_err mpp_random_size(mp_int *a, mp_size prec)
|
||||
{
|
||||
mp_err res;
|
||||
|
||||
ARGCHK(a != NULL && prec > 0, MP_BADARG);
|
||||
|
||||
if((res = s_mp_pad(a, prec)) != MP_OKAY)
|
||||
return res;
|
||||
|
||||
return mpp_random(a);
|
||||
|
||||
} /* end mpp_random_size() */
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ mpp_divis_vector(a, vec, size, which) */
|
||||
|
||||
/*
|
||||
mpp_divis_vector(a, vec, size, which)
|
||||
|
||||
Determines if a is divisible by any of the 'size' digits in vec.
|
||||
Returns MP_YES and sets 'which' to the index of the offending digit,
|
||||
if it is; returns MP_NO if it is not.
|
||||
*/
|
||||
|
||||
mp_err mpp_divis_vector(mp_int *a, const mp_digit *vec, int size, int *which)
|
||||
{
|
||||
ARGCHK(a != NULL && vec != NULL && size > 0, MP_BADARG);
|
||||
|
||||
return s_mpp_divp(a, vec, size, which);
|
||||
|
||||
} /* end mpp_divis_vector() */
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ mpp_divis_primes(a, np) */
|
||||
|
||||
/*
|
||||
mpp_divis_primes(a, np)
|
||||
|
||||
Test whether a is divisible by any of the first 'np' primes. If it
|
||||
is, returns MP_YES and sets *np to the value of the digit that did
|
||||
it. If not, returns MP_NO.
|
||||
*/
|
||||
mp_err mpp_divis_primes(mp_int *a, mp_digit *np)
|
||||
{
|
||||
int size, which;
|
||||
mp_err res;
|
||||
|
||||
ARGCHK(a != NULL && np != NULL, MP_BADARG);
|
||||
|
||||
size = (int)*np;
|
||||
if(size > prime_tab_size)
|
||||
size = prime_tab_size;
|
||||
|
||||
res = mpp_divis_vector(a, prime_tab, size, &which);
|
||||
if(res == MP_YES)
|
||||
*np = prime_tab[which];
|
||||
|
||||
return res;
|
||||
|
||||
} /* end mpp_divis_primes() */
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ mpp_fermat(a, w) */
|
||||
|
||||
/*
|
||||
Using w as a witness, try pseudo-primality testing based on Fermat's
|
||||
little theorem. If a is prime, and (w, a) = 1, then w^a == w (mod
|
||||
a). So, we compute z = w^a (mod a) and compare z to w; if they are
|
||||
equal, the test passes and we return MP_YES. Otherwise, we return
|
||||
MP_NO.
|
||||
*/
|
||||
mp_err mpp_fermat(mp_int *a, mp_digit w)
|
||||
{
|
||||
mp_int base, test;
|
||||
mp_err res;
|
||||
|
||||
if((res = mp_init(&base)) != MP_OKAY)
|
||||
return res;
|
||||
|
||||
mp_set(&base, w);
|
||||
|
||||
if((res = mp_init(&test)) != MP_OKAY)
|
||||
goto TEST;
|
||||
|
||||
/* Compute test = base^a (mod a) */
|
||||
if((res = mp_exptmod(&base, a, a, &test)) != MP_OKAY)
|
||||
goto CLEANUP;
|
||||
|
||||
|
||||
if(mp_cmp(&base, &test) == 0)
|
||||
res = MP_YES;
|
||||
else
|
||||
res = MP_NO;
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&test);
|
||||
TEST:
|
||||
mp_clear(&base);
|
||||
|
||||
return res;
|
||||
|
||||
} /* end mpp_fermat() */
|
||||
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
Perform the fermat test on each of the primes in a list until
|
||||
a) one of them shows a is not prime, or
|
||||
b) the list is exhausted.
|
||||
Returns: MP_YES if it passes tests.
|
||||
MP_NO if fermat test reveals it is composite
|
||||
Some MP error code if some other error occurs.
|
||||
*/
|
||||
mp_err mpp_fermat_list(mp_int *a, const mp_digit *primes, mp_size nPrimes)
|
||||
{
|
||||
mp_err rv = MP_YES;
|
||||
|
||||
while (nPrimes-- > 0 && rv == MP_YES) {
|
||||
rv = mpp_fermat(a, *primes++);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* {{{ mpp_pprime(a, nt) */
|
||||
|
||||
/*
|
||||
mpp_pprime(a, nt)
|
||||
|
||||
Performs nt iteration of the Miller-Rabin probabilistic primality
|
||||
test on a. Returns MP_YES if the tests pass, MP_NO if one fails.
|
||||
If MP_NO is returned, the number is definitely composite. If MP_YES
|
||||
is returned, it is probably prime (but that is not guaranteed).
|
||||
*/
|
||||
|
||||
mp_err mpp_pprime(mp_int *a, int nt)
|
||||
{
|
||||
mp_err res;
|
||||
mp_int x, amo, m, z; /* "amo" = "a minus one" */
|
||||
int iter;
|
||||
unsigned int jx;
|
||||
mp_size b;
|
||||
|
||||
ARGCHK(a != NULL, MP_BADARG);
|
||||
|
||||
MP_DIGITS(&x) = 0;
|
||||
MP_DIGITS(&amo) = 0;
|
||||
MP_DIGITS(&m) = 0;
|
||||
MP_DIGITS(&z) = 0;
|
||||
|
||||
/* Initialize temporaries... */
|
||||
MP_CHECKOK( mp_init(&amo));
|
||||
/* Compute amo = a - 1 for what follows... */
|
||||
MP_CHECKOK( mp_sub_d(a, 1, &amo) );
|
||||
|
||||
b = mp_trailing_zeros(&amo);
|
||||
if (!b) { /* a was even ? */
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
MP_CHECKOK( mp_init_size(&x, MP_USED(a)) );
|
||||
MP_CHECKOK( mp_init(&z) );
|
||||
MP_CHECKOK( mp_init(&m) );
|
||||
MP_CHECKOK( mp_div_2d(&amo, b, &m, 0) );
|
||||
|
||||
/* Do the test nt times... */
|
||||
for(iter = 0; iter < nt; iter++) {
|
||||
|
||||
/* Choose a random value for x < a */
|
||||
s_mp_pad(&x, USED(a));
|
||||
mpp_random(&x);
|
||||
MP_CHECKOK( mp_mod(&x, a, &x) );
|
||||
|
||||
/* Compute z = (x ** m) mod a */
|
||||
MP_CHECKOK( mp_exptmod(&x, &m, a, &z) );
|
||||
|
||||
if(mp_cmp_d(&z, 1) == 0 || mp_cmp(&z, &amo) == 0) {
|
||||
res = MP_YES;
|
||||
continue;
|
||||
}
|
||||
|
||||
res = MP_NO; /* just in case the following for loop never executes. */
|
||||
for (jx = 1; jx < b; jx++) {
|
||||
/* z = z^2 (mod a) */
|
||||
MP_CHECKOK( mp_sqrmod(&z, a, &z) );
|
||||
res = MP_NO; /* previous line set res to MP_YES */
|
||||
|
||||
if(mp_cmp_d(&z, 1) == 0) {
|
||||
break;
|
||||
}
|
||||
if(mp_cmp(&z, &amo) == 0) {
|
||||
res = MP_YES;
|
||||
break;
|
||||
}
|
||||
} /* end testing loop */
|
||||
|
||||
/* If the test passes, we will continue iterating, but a failed
|
||||
test means the candidate is definitely NOT prime, so we will
|
||||
immediately break out of this loop
|
||||
*/
|
||||
if(res == MP_NO)
|
||||
break;
|
||||
|
||||
} /* end iterations loop */
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&m);
|
||||
mp_clear(&z);
|
||||
mp_clear(&x);
|
||||
mp_clear(&amo);
|
||||
return res;
|
||||
|
||||
} /* end mpp_pprime() */
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* Produce table of composites from list of primes and trial value.
|
||||
** trial must be odd. List of primes must not include 2.
|
||||
** sieve should have dimension >= MAXPRIME/2, where MAXPRIME is largest
|
||||
** prime in list of primes. After this function is finished,
|
||||
** if sieve[i] is non-zero, then (trial + 2*i) is composite.
|
||||
** Each prime used in the sieve costs one division of trial, and eliminates
|
||||
** one or more values from the search space. (3 eliminates 1/3 of the values
|
||||
** alone!) Each value left in the search space costs 1 or more modular
|
||||
** exponentations. So, these divisions are a bargain!
|
||||
*/
|
||||
mp_err mpp_sieve(mp_int *trial, const mp_digit *primes, mp_size nPrimes,
|
||||
unsigned char *sieve, mp_size nSieve)
|
||||
{
|
||||
mp_err res;
|
||||
mp_digit rem;
|
||||
mp_size ix;
|
||||
unsigned long offset;
|
||||
|
||||
memset(sieve, 0, nSieve);
|
||||
|
||||
for(ix = 0; ix < nPrimes; ix++) {
|
||||
mp_digit prime = primes[ix];
|
||||
mp_size i;
|
||||
if((res = mp_mod_d(trial, prime, &rem)) != MP_OKAY)
|
||||
return res;
|
||||
|
||||
if (rem == 0) {
|
||||
offset = 0;
|
||||
} else {
|
||||
offset = prime - (rem / 2);
|
||||
}
|
||||
for (i = offset; i < nSieve ; i += prime) {
|
||||
sieve[i] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
#define SIEVE_SIZE 32*1024
|
||||
|
||||
mp_err mpp_make_prime(mp_int *start, mp_size nBits, mp_size strong,
|
||||
unsigned long * nTries)
|
||||
{
|
||||
mp_digit np;
|
||||
mp_err res;
|
||||
int i = 0;
|
||||
mp_int trial;
|
||||
mp_int q;
|
||||
mp_size num_tests;
|
||||
/*
|
||||
* Always make sieve the last variabale allocated so that
|
||||
* Mac builds don't break by adding an extra variable
|
||||
* on the stack. -javi
|
||||
*/
|
||||
#if defined(macintosh) || defined (XP_OS2) \
|
||||
|| (defined(HPUX) && defined(__ia64))
|
||||
unsigned char *sieve;
|
||||
|
||||
sieve = malloc(SIEVE_SIZE);
|
||||
ARGCHK(sieve != NULL, MP_MEM);
|
||||
#else
|
||||
unsigned char sieve[SIEVE_SIZE];
|
||||
#endif
|
||||
|
||||
ARGCHK(start != 0, MP_BADARG);
|
||||
ARGCHK(nBits > 16, MP_RANGE);
|
||||
|
||||
MP_DIGITS(&trial) = 0;
|
||||
MP_DIGITS(&q) = 0;
|
||||
MP_CHECKOK( mp_init(&trial) );
|
||||
MP_CHECKOK( mp_init(&q) );
|
||||
/* values taken from table 4.4, HandBook of Applied Cryptography */
|
||||
if (nBits >= 1300) {
|
||||
num_tests = 2;
|
||||
} else if (nBits >= 850) {
|
||||
num_tests = 3;
|
||||
} else if (nBits >= 650) {
|
||||
num_tests = 4;
|
||||
} else if (nBits >= 550) {
|
||||
num_tests = 5;
|
||||
} else if (nBits >= 450) {
|
||||
num_tests = 6;
|
||||
} else if (nBits >= 400) {
|
||||
num_tests = 7;
|
||||
} else if (nBits >= 350) {
|
||||
num_tests = 8;
|
||||
} else if (nBits >= 300) {
|
||||
num_tests = 9;
|
||||
} else if (nBits >= 250) {
|
||||
num_tests = 12;
|
||||
} else if (nBits >= 200) {
|
||||
num_tests = 15;
|
||||
} else if (nBits >= 150) {
|
||||
num_tests = 18;
|
||||
} else if (nBits >= 100) {
|
||||
num_tests = 27;
|
||||
} else
|
||||
num_tests = 50;
|
||||
|
||||
if (strong)
|
||||
--nBits;
|
||||
MP_CHECKOK( mpl_set_bit(start, nBits - 1, 1) );
|
||||
MP_CHECKOK( mpl_set_bit(start, 0, 1) );
|
||||
for (i = mpl_significant_bits(start) - 1; i >= nBits; --i) {
|
||||
MP_CHECKOK( mpl_set_bit(start, i, 0) );
|
||||
}
|
||||
/* start sieveing with prime value of 3. */
|
||||
MP_CHECKOK(mpp_sieve(start, prime_tab + 1, prime_tab_size - 1,
|
||||
sieve, SIEVE_SIZE) );
|
||||
|
||||
#ifdef DEBUG_SIEVE
|
||||
res = 0;
|
||||
for (i = 0; i < SIEVE_SIZE; ++i) {
|
||||
if (!sieve[i])
|
||||
++res;
|
||||
}
|
||||
fprintf(stderr,"sieve found %d potential primes.\n", res);
|
||||
#define FPUTC(x,y) fputc(x,y)
|
||||
#else
|
||||
#define FPUTC(x,y)
|
||||
#endif
|
||||
|
||||
res = MP_NO;
|
||||
for(i = 0; i < SIEVE_SIZE; ++i) {
|
||||
if (sieve[i]) /* this number is composite */
|
||||
continue;
|
||||
MP_CHECKOK( mp_add_d(start, 2 * i, &trial) );
|
||||
FPUTC('.', stderr);
|
||||
/* run a Fermat test */
|
||||
res = mpp_fermat(&trial, 2);
|
||||
if (res != MP_OKAY) {
|
||||
if (res == MP_NO)
|
||||
continue; /* was composite */
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
FPUTC('+', stderr);
|
||||
/* If that passed, run some Miller-Rabin tests */
|
||||
res = mpp_pprime(&trial, num_tests);
|
||||
if (res != MP_OKAY) {
|
||||
if (res == MP_NO)
|
||||
continue; /* was composite */
|
||||
goto CLEANUP;
|
||||
}
|
||||
FPUTC('!', stderr);
|
||||
|
||||
if (!strong)
|
||||
break; /* success !! */
|
||||
|
||||
/* At this point, we have strong evidence that our candidate
|
||||
is itself prime. If we want a strong prime, we need now
|
||||
to test q = 2p + 1 for primality...
|
||||
*/
|
||||
MP_CHECKOK( mp_mul_2(&trial, &q) );
|
||||
MP_CHECKOK( mp_add_d(&q, 1, &q) );
|
||||
|
||||
/* Test q for small prime divisors ... */
|
||||
np = prime_tab_size;
|
||||
res = mpp_divis_primes(&q, &np);
|
||||
if (res == MP_YES) { /* is composite */
|
||||
mp_clear(&q);
|
||||
continue;
|
||||
}
|
||||
if (res != MP_NO)
|
||||
goto CLEANUP;
|
||||
|
||||
/* And test with Fermat, as with its parent ... */
|
||||
res = mpp_fermat(&q, 2);
|
||||
if (res != MP_YES) {
|
||||
mp_clear(&q);
|
||||
if (res == MP_NO)
|
||||
continue; /* was composite */
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* And test with Miller-Rabin, as with its parent ... */
|
||||
res = mpp_pprime(&q, num_tests);
|
||||
if (res != MP_YES) {
|
||||
mp_clear(&q);
|
||||
if (res == MP_NO)
|
||||
continue; /* was composite */
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* If it passed, we've got a winner */
|
||||
mp_exch(&q, &trial);
|
||||
mp_clear(&q);
|
||||
break;
|
||||
|
||||
} /* end of loop through sieved values */
|
||||
if (res == MP_YES)
|
||||
mp_exch(&trial, start);
|
||||
CLEANUP:
|
||||
mp_clear(&trial);
|
||||
mp_clear(&q);
|
||||
if (nTries)
|
||||
*nTries += i;
|
||||
#if defined(macintosh) || defined(XP_OS2) \
|
||||
|| (defined(HPUX) && defined(__ia64))
|
||||
if (sieve != NULL) {
|
||||
memset(sieve, 0, SIEVE_SIZE);
|
||||
free (sieve);
|
||||
}
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
/*========================================================================*/
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Static functions visible only to the library internally */
|
||||
|
||||
/* {{{ s_mpp_divp(a, vec, size, which) */
|
||||
|
||||
/*
|
||||
Test for divisibility by members of a vector of digits. Returns
|
||||
MP_NO if a is not divisible by any of them; returns MP_YES and sets
|
||||
'which' to the index of the offender, if it is. Will stop on the
|
||||
first digit against which a is divisible.
|
||||
*/
|
||||
|
||||
mp_err s_mpp_divp(mp_int *a, const mp_digit *vec, int size, int *which)
|
||||
{
|
||||
mp_err res;
|
||||
mp_digit rem;
|
||||
|
||||
int ix;
|
||||
|
||||
for(ix = 0; ix < size; ix++) {
|
||||
if((res = mp_mod_d(a, vec[ix], &rem)) != MP_OKAY)
|
||||
return res;
|
||||
|
||||
if(rem == 0) {
|
||||
if(which)
|
||||
*which = ix;
|
||||
return MP_YES;
|
||||
}
|
||||
}
|
||||
|
||||
return MP_NO;
|
||||
|
||||
} /* end s_mpp_divp() */
|
||||
|
||||
/* }}} */
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* HERE THERE BE DRAGONS */
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* mpprime.h
|
||||
*
|
||||
* Utilities for finding and working with prime and pseudo-prime
|
||||
* integers
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael J. Fromberger.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1997
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _H_MP_PRIME_
|
||||
#define _H_MP_PRIME_
|
||||
|
||||
#include "mpi.h"
|
||||
|
||||
extern const int prime_tab_size; /* number of primes available */
|
||||
extern const mp_digit prime_tab[];
|
||||
|
||||
/* Tests for divisibility */
|
||||
mp_err mpp_divis(mp_int *a, mp_int *b);
|
||||
mp_err mpp_divis_d(mp_int *a, mp_digit d);
|
||||
|
||||
/* Random selection */
|
||||
mp_err mpp_random(mp_int *a);
|
||||
mp_err mpp_random_size(mp_int *a, mp_size prec);
|
||||
|
||||
/* Pseudo-primality testing */
|
||||
mp_err mpp_divis_vector(mp_int *a, const mp_digit *vec, int size, int *which);
|
||||
mp_err mpp_divis_primes(mp_int *a, mp_digit *np);
|
||||
mp_err mpp_fermat(mp_int *a, mp_digit w);
|
||||
mp_err mpp_fermat_list(mp_int *a, const mp_digit *primes, mp_size nPrimes);
|
||||
mp_err mpp_pprime(mp_int *a, int nt);
|
||||
mp_err mpp_sieve(mp_int *trial, const mp_digit *primes, mp_size nPrimes,
|
||||
unsigned char *sieve, mp_size nSieve);
|
||||
mp_err mpp_make_prime(mp_int *start, mp_size nBits, mp_size strong,
|
||||
unsigned long * nTries);
|
||||
|
||||
#endif /* end _H_MP_PRIME_ */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user