├── LICENSE
├── README.md
├── lib
├── .DS_Store
├── .gitignore
├── makefile
├── objects.mk
├── sources.mk
└── src
│ ├── .gitignore
│ ├── Ciphertext.d
│ ├── Ciphertext.o
│ ├── Context.d
│ ├── Context.o
│ ├── EvaluatorUtils.d
│ ├── EvaluatorUtils.o
│ ├── Key.d
│ ├── Key.o
│ ├── Numb.d
│ ├── Numb.o
│ ├── Plaintext.d
│ ├── Plaintext.o
│ ├── Scheme.d
│ ├── Scheme.o
│ ├── SchemeAlgo.d
│ ├── SchemeAlgo.o
│ ├── SecretKey.d
│ ├── SecretKey.o
│ ├── StringUtils.d
│ ├── StringUtils.o
│ ├── TestScheme.d
│ ├── TestScheme.o
│ ├── TimeUtils.d
│ ├── TimeUtils.o
│ └── subdir.mk
├── run
├── .DS_Store
├── FRNSHEAAN
├── main.cpp
└── makefile
└── src
├── .DS_Store
├── Ciphertext.cpp
├── Ciphertext.h
├── Common.h
├── Context.cpp
├── Context.h
├── EvaluatorUtils.cpp
├── EvaluatorUtils.h
├── Key.cpp
├── Key.h
├── Numb.cpp
├── Numb.h
├── Plaintext.cpp
├── Plaintext.h
├── Scheme.cpp
├── Scheme.h
├── SchemeAlgo.cpp
├── SchemeAlgo.h
├── SecretKey.cpp
├── SecretKey.h
├── StringUtils.cpp
├── StringUtils.h
├── TestScheme.cpp
├── TestScheme.h
├── TimeUtils.cpp
├── TimeUtils.h
└── main.cpp
/LICENSE:
--------------------------------------------------------------------------------
1 | Creative Commons Legal Code
2 |
3 | Attribution-NonCommercial 3.0 Unported
4 |
5 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
6 | LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN
7 | ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
8 | INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
9 | REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR
10 | DAMAGES RESULTING FROM ITS USE.
11 |
12 | License
13 |
14 | THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE
15 | COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY
16 | COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS
17 | AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
18 |
19 | BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE
20 | TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY
21 | BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS
22 | CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND
23 | CONDITIONS.
24 |
25 | 1. Definitions
26 |
27 | a. "Adaptation" means a work based upon the Work, or upon the Work and
28 | other pre-existing works, such as a translation, adaptation,
29 | derivative work, arrangement of music or other alterations of a
30 | literary or artistic work, or phonogram or performance and includes
31 | cinematographic adaptations or any other form in which the Work may be
32 | recast, transformed, or adapted including in any form recognizably
33 | derived from the original, except that a work that constitutes a
34 | Collection will not be considered an Adaptation for the purpose of
35 | this License. For the avoidance of doubt, where the Work is a musical
36 | work, performance or phonogram, the synchronization of the Work in
37 | timed-relation with a moving image ("synching") will be considered an
38 | Adaptation for the purpose of this License.
39 | b. "Collection" means a collection of literary or artistic works, such as
40 | encyclopedias and anthologies, or performances, phonograms or
41 | broadcasts, or other works or subject matter other than works listed
42 | in Section 1(f) below, which, by reason of the selection and
43 | arrangement of their contents, constitute intellectual creations, in
44 | which the Work is included in its entirety in unmodified form along
45 | with one or more other contributions, each constituting separate and
46 | independent works in themselves, which together are assembled into a
47 | collective whole. A work that constitutes a Collection will not be
48 | considered an Adaptation (as defined above) for the purposes of this
49 | License.
50 | c. "Distribute" means to make available to the public the original and
51 | copies of the Work or Adaptation, as appropriate, through sale or
52 | other transfer of ownership.
53 | d. "Licensor" means the individual, individuals, entity or entities that
54 | offer(s) the Work under the terms of this License.
55 | e. "Original Author" means, in the case of a literary or artistic work,
56 | the individual, individuals, entity or entities who created the Work
57 | or if no individual or entity can be identified, the publisher; and in
58 | addition (i) in the case of a performance the actors, singers,
59 | musicians, dancers, and other persons who act, sing, deliver, declaim,
60 | play in, interpret or otherwise perform literary or artistic works or
61 | expressions of folklore; (ii) in the case of a phonogram the producer
62 | being the person or legal entity who first fixes the sounds of a
63 | performance or other sounds; and, (iii) in the case of broadcasts, the
64 | organization that transmits the broadcast.
65 | f. "Work" means the literary and/or artistic work offered under the terms
66 | of this License including without limitation any production in the
67 | literary, scientific and artistic domain, whatever may be the mode or
68 | form of its expression including digital form, such as a book,
69 | pamphlet and other writing; a lecture, address, sermon or other work
70 | of the same nature; a dramatic or dramatico-musical work; a
71 | choreographic work or entertainment in dumb show; a musical
72 | composition with or without words; a cinematographic work to which are
73 | assimilated works expressed by a process analogous to cinematography;
74 | a work of drawing, painting, architecture, sculpture, engraving or
75 | lithography; a photographic work to which are assimilated works
76 | expressed by a process analogous to photography; a work of applied
77 | art; an illustration, map, plan, sketch or three-dimensional work
78 | relative to geography, topography, architecture or science; a
79 | performance; a broadcast; a phonogram; a compilation of data to the
80 | extent it is protected as a copyrightable work; or a work performed by
81 | a variety or circus performer to the extent it is not otherwise
82 | considered a literary or artistic work.
83 | g. "You" means an individual or entity exercising rights under this
84 | License who has not previously violated the terms of this License with
85 | respect to the Work, or who has received express permission from the
86 | Licensor to exercise rights under this License despite a previous
87 | violation.
88 | h. "Publicly Perform" means to perform public recitations of the Work and
89 | to communicate to the public those public recitations, by any means or
90 | process, including by wire or wireless means or public digital
91 | performances; to make available to the public Works in such a way that
92 | members of the public may access these Works from a place and at a
93 | place individually chosen by them; to perform the Work to the public
94 | by any means or process and the communication to the public of the
95 | performances of the Work, including by public digital performance; to
96 | broadcast and rebroadcast the Work by any means including signs,
97 | sounds or images.
98 | i. "Reproduce" means to make copies of the Work by any means including
99 | without limitation by sound or visual recordings and the right of
100 | fixation and reproducing fixations of the Work, including storage of a
101 | protected performance or phonogram in digital form or other electronic
102 | medium.
103 |
104 | 2. Fair Dealing Rights. Nothing in this License is intended to reduce,
105 | limit, or restrict any uses free from copyright or rights arising from
106 | limitations or exceptions that are provided for in connection with the
107 | copyright protection under copyright law or other applicable laws.
108 |
109 | 3. License Grant. Subject to the terms and conditions of this License,
110 | Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
111 | perpetual (for the duration of the applicable copyright) license to
112 | exercise the rights in the Work as stated below:
113 |
114 | a. to Reproduce the Work, to incorporate the Work into one or more
115 | Collections, and to Reproduce the Work as incorporated in the
116 | Collections;
117 | b. to create and Reproduce Adaptations provided that any such Adaptation,
118 | including any translation in any medium, takes reasonable steps to
119 | clearly label, demarcate or otherwise identify that changes were made
120 | to the original Work. For example, a translation could be marked "The
121 | original work was translated from English to Spanish," or a
122 | modification could indicate "The original work has been modified.";
123 | c. to Distribute and Publicly Perform the Work including as incorporated
124 | in Collections; and,
125 | d. to Distribute and Publicly Perform Adaptations.
126 |
127 | The above rights may be exercised in all media and formats whether now
128 | known or hereafter devised. The above rights include the right to make
129 | such modifications as are technically necessary to exercise the rights in
130 | other media and formats. Subject to Section 8(f), all rights not expressly
131 | granted by Licensor are hereby reserved, including but not limited to the
132 | rights set forth in Section 4(d).
133 |
134 | 4. Restrictions. The license granted in Section 3 above is expressly made
135 | subject to and limited by the following restrictions:
136 |
137 | a. You may Distribute or Publicly Perform the Work only under the terms
138 | of this License. You must include a copy of, or the Uniform Resource
139 | Identifier (URI) for, this License with every copy of the Work You
140 | Distribute or Publicly Perform. You may not offer or impose any terms
141 | on the Work that restrict the terms of this License or the ability of
142 | the recipient of the Work to exercise the rights granted to that
143 | recipient under the terms of the License. You may not sublicense the
144 | Work. You must keep intact all notices that refer to this License and
145 | to the disclaimer of warranties with every copy of the Work You
146 | Distribute or Publicly Perform. When You Distribute or Publicly
147 | Perform the Work, You may not impose any effective technological
148 | measures on the Work that restrict the ability of a recipient of the
149 | Work from You to exercise the rights granted to that recipient under
150 | the terms of the License. This Section 4(a) applies to the Work as
151 | incorporated in a Collection, but this does not require the Collection
152 | apart from the Work itself to be made subject to the terms of this
153 | License. If You create a Collection, upon notice from any Licensor You
154 | must, to the extent practicable, remove from the Collection any credit
155 | as required by Section 4(c), as requested. If You create an
156 | Adaptation, upon notice from any Licensor You must, to the extent
157 | practicable, remove from the Adaptation any credit as required by
158 | Section 4(c), as requested.
159 | b. You may not exercise any of the rights granted to You in Section 3
160 | above in any manner that is primarily intended for or directed toward
161 | commercial advantage or private monetary compensation. The exchange of
162 | the Work for other copyrighted works by means of digital file-sharing
163 | or otherwise shall not be considered to be intended for or directed
164 | toward commercial advantage or private monetary compensation, provided
165 | there is no payment of any monetary compensation in connection with
166 | the exchange of copyrighted works.
167 | c. If You Distribute, or Publicly Perform the Work or any Adaptations or
168 | Collections, You must, unless a request has been made pursuant to
169 | Section 4(a), keep intact all copyright notices for the Work and
170 | provide, reasonable to the medium or means You are utilizing: (i) the
171 | name of the Original Author (or pseudonym, if applicable) if supplied,
172 | and/or if the Original Author and/or Licensor designate another party
173 | or parties (e.g., a sponsor institute, publishing entity, journal) for
174 | attribution ("Attribution Parties") in Licensor's copyright notice,
175 | terms of service or by other reasonable means, the name of such party
176 | or parties; (ii) the title of the Work if supplied; (iii) to the
177 | extent reasonably practicable, the URI, if any, that Licensor
178 | specifies to be associated with the Work, unless such URI does not
179 | refer to the copyright notice or licensing information for the Work;
180 | and, (iv) consistent with Section 3(b), in the case of an Adaptation,
181 | a credit identifying the use of the Work in the Adaptation (e.g.,
182 | "French translation of the Work by Original Author," or "Screenplay
183 | based on original Work by Original Author"). The credit required by
184 | this Section 4(c) may be implemented in any reasonable manner;
185 | provided, however, that in the case of a Adaptation or Collection, at
186 | a minimum such credit will appear, if a credit for all contributing
187 | authors of the Adaptation or Collection appears, then as part of these
188 | credits and in a manner at least as prominent as the credits for the
189 | other contributing authors. For the avoidance of doubt, You may only
190 | use the credit required by this Section for the purpose of attribution
191 | in the manner set out above and, by exercising Your rights under this
192 | License, You may not implicitly or explicitly assert or imply any
193 | connection with, sponsorship or endorsement by the Original Author,
194 | Licensor and/or Attribution Parties, as appropriate, of You or Your
195 | use of the Work, without the separate, express prior written
196 | permission of the Original Author, Licensor and/or Attribution
197 | Parties.
198 | d. For the avoidance of doubt:
199 |
200 | i. Non-waivable Compulsory License Schemes. In those jurisdictions in
201 | which the right to collect royalties through any statutory or
202 | compulsory licensing scheme cannot be waived, the Licensor
203 | reserves the exclusive right to collect such royalties for any
204 | exercise by You of the rights granted under this License;
205 | ii. Waivable Compulsory License Schemes. In those jurisdictions in
206 | which the right to collect royalties through any statutory or
207 | compulsory licensing scheme can be waived, the Licensor reserves
208 | the exclusive right to collect such royalties for any exercise by
209 | You of the rights granted under this License if Your exercise of
210 | such rights is for a purpose or use which is otherwise than
211 | noncommercial as permitted under Section 4(b) and otherwise waives
212 | the right to collect royalties through any statutory or compulsory
213 | licensing scheme; and,
214 | iii. Voluntary License Schemes. The Licensor reserves the right to
215 | collect royalties, whether individually or, in the event that the
216 | Licensor is a member of a collecting society that administers
217 | voluntary licensing schemes, via that society, from any exercise
218 | by You of the rights granted under this License that is for a
219 | purpose or use which is otherwise than noncommercial as permitted
220 | under Section 4(c).
221 | e. Except as otherwise agreed in writing by the Licensor or as may be
222 | otherwise permitted by applicable law, if You Reproduce, Distribute or
223 | Publicly Perform the Work either by itself or as part of any
224 | Adaptations or Collections, You must not distort, mutilate, modify or
225 | take other derogatory action in relation to the Work which would be
226 | prejudicial to the Original Author's honor or reputation. Licensor
227 | agrees that in those jurisdictions (e.g. Japan), in which any exercise
228 | of the right granted in Section 3(b) of this License (the right to
229 | make Adaptations) would be deemed to be a distortion, mutilation,
230 | modification or other derogatory action prejudicial to the Original
231 | Author's honor and reputation, the Licensor will waive or not assert,
232 | as appropriate, this Section, to the fullest extent permitted by the
233 | applicable national law, to enable You to reasonably exercise Your
234 | right under Section 3(b) of this License (right to make Adaptations)
235 | but not otherwise.
236 |
237 | 5. Representations, Warranties and Disclaimer
238 |
239 | UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR
240 | OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY
241 | KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE,
242 | INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY,
243 | FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF
244 | LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS,
245 | WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION
246 | OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.
247 |
248 | 6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE
249 | LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR
250 | ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES
251 | ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS
252 | BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
253 |
254 | 7. Termination
255 |
256 | a. This License and the rights granted hereunder will terminate
257 | automatically upon any breach by You of the terms of this License.
258 | Individuals or entities who have received Adaptations or Collections
259 | from You under this License, however, will not have their licenses
260 | terminated provided such individuals or entities remain in full
261 | compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will
262 | survive any termination of this License.
263 | b. Subject to the above terms and conditions, the license granted here is
264 | perpetual (for the duration of the applicable copyright in the Work).
265 | Notwithstanding the above, Licensor reserves the right to release the
266 | Work under different license terms or to stop distributing the Work at
267 | any time; provided, however that any such election will not serve to
268 | withdraw this License (or any other license that has been, or is
269 | required to be, granted under the terms of this License), and this
270 | License will continue in full force and effect unless terminated as
271 | stated above.
272 |
273 | 8. Miscellaneous
274 |
275 | a. Each time You Distribute or Publicly Perform the Work or a Collection,
276 | the Licensor offers to the recipient a license to the Work on the same
277 | terms and conditions as the license granted to You under this License.
278 | b. Each time You Distribute or Publicly Perform an Adaptation, Licensor
279 | offers to the recipient a license to the original Work on the same
280 | terms and conditions as the license granted to You under this License.
281 | c. If any provision of this License is invalid or unenforceable under
282 | applicable law, it shall not affect the validity or enforceability of
283 | the remainder of the terms of this License, and without further action
284 | by the parties to this agreement, such provision shall be reformed to
285 | the minimum extent necessary to make such provision valid and
286 | enforceable.
287 | d. No term or provision of this License shall be deemed waived and no
288 | breach consented to unless such waiver or consent shall be in writing
289 | and signed by the party to be charged with such waiver or consent.
290 | e. This License constitutes the entire agreement between the parties with
291 | respect to the Work licensed here. There are no understandings,
292 | agreements or representations with respect to the Work not specified
293 | here. Licensor shall not be bound by any additional provisions that
294 | may appear in any communication from You. This License may not be
295 | modified without the mutual written agreement of the Licensor and You.
296 | f. The rights granted under, and the subject matter referenced, in this
297 | License were drafted utilizing the terminology of the Berne Convention
298 | for the Protection of Literary and Artistic Works (as amended on
299 | September 28, 1979), the Rome Convention of 1961, the WIPO Copyright
300 | Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996
301 | and the Universal Copyright Convention (as revised on July 24, 1971).
302 | These rights and subject matter take effect in the relevant
303 | jurisdiction in which the License terms are sought to be enforced
304 | according to the corresponding provisions of the implementation of
305 | those treaty provisions in the applicable national law. If the
306 | standard suite of rights granted under applicable copyright law
307 | includes additional rights not granted under this License, such
308 | additional rights are deemed to be included in the License; this
309 | License is not intended to restrict the license of any rights under
310 | applicable law.
311 |
312 |
313 | Creative Commons Notice
314 |
315 | Creative Commons is not a party to this License, and makes no warranty
316 | whatsoever in connection with the Work. Creative Commons will not be
317 | liable to You or any party on any legal theory for any damages
318 | whatsoever, including without limitation any general, special,
319 | incidental or consequential damages arising in connection to this
320 | license. Notwithstanding the foregoing two (2) sentences, if Creative
321 | Commons has expressly identified itself as the Licensor hereunder, it
322 | shall have all rights and obligations of Licensor.
323 |
324 | Except for the limited purpose of indicating to the public that the
325 | Work is licensed under the CCPL, Creative Commons does not authorize
326 | the use by either party of the trademark "Creative Commons" or any
327 | related trademark or logo of Creative Commons without the prior
328 | written consent of Creative Commons. Any permitted use will be in
329 | compliance with Creative Commons' then-current trademark usage
330 | guidelines, as may be published on its website or otherwise made
331 | available upon request from time to time. For the avoidance of doubt,
332 | this trademark restriction does not form part of the License.
333 |
334 | Creative Commons may be contacted at https://creativecommons.org/.
335 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # FullRNS-HEAAN
2 |
3 | ## This code is implementation of the paper "A Full RNS variant of Approximate Homomorphic Encryption" which will appear in SAC 2018.
4 |
5 | ## To install the HE library, you need to type in the "lib" folder as follows:
6 | 1. make clean
7 | 2. make all
8 |
9 | ## To run and test this code, you need to type in the "run" folder as follows:
10 | 1. make clean
11 | 2. make
12 | 3. ./FRNSHEAAN
13 |
14 | - Notice that this code will run only at gcc (this code uses unsigned __int128 variable)
15 |
16 | ## License
17 | Copyright (c) by CryptoLab inc.
18 | This program is licensed under a
19 | Creative Commons Attribution-NonCommercial 3.0 Unported License.
20 | You should have received a copy of the license along with this
21 | work. If not, see .
22 |
--------------------------------------------------------------------------------
/lib/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KyoohyungHan/FullRNS-HEAAN/515f6414076ca387996cb12e0798b4e3fcee653e/lib/.DS_Store
--------------------------------------------------------------------------------
/lib/.gitignore:
--------------------------------------------------------------------------------
1 | /*.a
2 |
--------------------------------------------------------------------------------
/lib/makefile:
--------------------------------------------------------------------------------
1 | ################################################################################
2 | # Automatically-generated file. Do not edit!
3 | ################################################################################
4 |
5 | -include ../makefile.init
6 |
7 | RM := rm -rf
8 |
9 | # All of the sources participating in the build are defined here
10 | -include sources.mk
11 | -include src/subdir.mk
12 | -include subdir.mk
13 | -include objects.mk
14 |
15 | ifneq ($(MAKECMDGOALS),clean)
16 | ifneq ($(strip $(CC_DEPS)),)
17 | -include $(CC_DEPS)
18 | endif
19 | ifneq ($(strip $(C++_DEPS)),)
20 | -include $(C++_DEPS)
21 | endif
22 | ifneq ($(strip $(C_UPPER_DEPS)),)
23 | -include $(C_UPPER_DEPS)
24 | endif
25 | ifneq ($(strip $(CXX_DEPS)),)
26 | -include $(CXX_DEPS)
27 | endif
28 | ifneq ($(strip $(CPP_DEPS)),)
29 | -include $(CPP_DEPS)
30 | endif
31 | ifneq ($(strip $(C_DEPS)),)
32 | -include $(C_DEPS)
33 | endif
34 | endif
35 |
36 | -include ../makefile.defs
37 |
38 | # Add inputs and outputs from these tool invocations to the build variables
39 |
40 | # All Target
41 | all: libFRNSHEAAN.a
42 |
43 | # Tool invocations
44 | libFRNSHEAAN.a: $(OBJS) $(USER_OBJS)
45 | @echo 'Building target: $@'
46 | @echo 'Invoking: GCC Archiver'
47 | ar -r "libFRNSHEAAN.a" $(OBJS) $(USER_OBJS) $(LIBS)
48 | @echo 'Finished building target: $@'
49 | @echo ' '
50 |
51 | # Other Targets
52 | clean:
53 | -$(RM) $(CC_DEPS)$(C++_DEPS)$(ARCHIVES)$(C_UPPER_DEPS)$(CXX_DEPS)$(OBJS)$(CPP_DEPS)$(C_DEPS) libHEAAN.a
54 | -@echo ' '
55 |
56 | .PHONY: all clean dependents
57 |
58 | -include ../makefile.targets
59 |
--------------------------------------------------------------------------------
/lib/objects.mk:
--------------------------------------------------------------------------------
1 | ################################################################################
2 | # Automatically-generated file. Do not edit!
3 | ################################################################################
4 |
5 | USER_OBJS :=
6 |
7 | LIBS :=
8 |
9 |
--------------------------------------------------------------------------------
/lib/sources.mk:
--------------------------------------------------------------------------------
1 | ################################################################################
2 | # Automatically-generated file. Do not edit!
3 | ################################################################################
4 |
5 | C_UPPER_SRCS :=
6 | CXX_SRCS :=
7 | C++_SRCS :=
8 | OBJ_SRCS :=
9 | CC_SRCS :=
10 | ASM_SRCS :=
11 | CPP_SRCS :=
12 | C_SRCS :=
13 | O_SRCS :=
14 | S_UPPER_SRCS :=
15 | CC_DEPS :=
16 | C++_DEPS :=
17 | EXECUTABLES :=
18 | C_UPPER_DEPS :=
19 | CXX_DEPS :=
20 | OBJS :=
21 | CPP_DEPS :=
22 | C_DEPS :=
23 |
24 | # Every subdirectory with source files must be described here
25 | SUBDIRS := \
26 | src \
27 |
28 |
--------------------------------------------------------------------------------
/lib/src/.gitignore:
--------------------------------------------------------------------------------
1 | /BootKey.d
2 |
--------------------------------------------------------------------------------
/lib/src/Ciphertext.d:
--------------------------------------------------------------------------------
1 | src/Ciphertext.o: ../src/Ciphertext.cpp ../src/Ciphertext.h \
2 | ../src/Common.h
3 |
4 | ../src/Ciphertext.h:
5 |
6 | ../src/Common.h:
7 |
--------------------------------------------------------------------------------
/lib/src/Ciphertext.o:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KyoohyungHan/FullRNS-HEAAN/515f6414076ca387996cb12e0798b4e3fcee653e/lib/src/Ciphertext.o
--------------------------------------------------------------------------------
/lib/src/Context.d:
--------------------------------------------------------------------------------
1 | src/Context.o: ../src/Context.cpp ../src/Context.h ../src/Common.h \
2 | ../src/Numb.h ../src/EvaluatorUtils.h
3 |
4 | ../src/Context.h:
5 |
6 | ../src/Common.h:
7 |
8 | ../src/Numb.h:
9 |
10 | ../src/EvaluatorUtils.h:
11 |
--------------------------------------------------------------------------------
/lib/src/Context.o:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KyoohyungHan/FullRNS-HEAAN/515f6414076ca387996cb12e0798b4e3fcee653e/lib/src/Context.o
--------------------------------------------------------------------------------
/lib/src/EvaluatorUtils.d:
--------------------------------------------------------------------------------
1 | src/EvaluatorUtils.o: ../src/EvaluatorUtils.cpp ../src/EvaluatorUtils.h \
2 | ../src/Context.h ../src/Common.h ../src/Numb.h
3 |
4 | ../src/EvaluatorUtils.h:
5 |
6 | ../src/Context.h:
7 |
8 | ../src/Common.h:
9 |
10 | ../src/Numb.h:
11 |
--------------------------------------------------------------------------------
/lib/src/EvaluatorUtils.o:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KyoohyungHan/FullRNS-HEAAN/515f6414076ca387996cb12e0798b4e3fcee653e/lib/src/EvaluatorUtils.o
--------------------------------------------------------------------------------
/lib/src/Key.d:
--------------------------------------------------------------------------------
1 | src/Key.o: ../src/Key.cpp ../src/Key.h
2 |
3 | ../src/Key.h:
4 |
--------------------------------------------------------------------------------
/lib/src/Key.o:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KyoohyungHan/FullRNS-HEAAN/515f6414076ca387996cb12e0798b4e3fcee653e/lib/src/Key.o
--------------------------------------------------------------------------------
/lib/src/Numb.d:
--------------------------------------------------------------------------------
1 | src/Numb.o: ../src/Numb.cpp ../src/Numb.h ../src/Common.h
2 |
3 | ../src/Numb.h:
4 |
5 | ../src/Common.h:
6 |
--------------------------------------------------------------------------------
/lib/src/Numb.o:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KyoohyungHan/FullRNS-HEAAN/515f6414076ca387996cb12e0798b4e3fcee653e/lib/src/Numb.o
--------------------------------------------------------------------------------
/lib/src/Plaintext.d:
--------------------------------------------------------------------------------
1 | src/Plaintext.o: ../src/Plaintext.cpp ../src/Plaintext.h ../src/Common.h
2 |
3 | ../src/Plaintext.h:
4 |
5 | ../src/Common.h:
6 |
--------------------------------------------------------------------------------
/lib/src/Plaintext.o:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KyoohyungHan/FullRNS-HEAAN/515f6414076ca387996cb12e0798b4e3fcee653e/lib/src/Plaintext.o
--------------------------------------------------------------------------------
/lib/src/Scheme.d:
--------------------------------------------------------------------------------
1 | src/Scheme.o: ../src/Scheme.cpp ../src/Scheme.h ../src/Common.h \
2 | ../src/Ciphertext.h ../src/Context.h ../src/Numb.h ../src/Plaintext.h \
3 | ../src/SecretKey.h ../src/Key.h
4 |
5 | ../src/Scheme.h:
6 |
7 | ../src/Common.h:
8 |
9 | ../src/Ciphertext.h:
10 |
11 | ../src/Context.h:
12 |
13 | ../src/Numb.h:
14 |
15 | ../src/Plaintext.h:
16 |
17 | ../src/SecretKey.h:
18 |
19 | ../src/Key.h:
20 |
--------------------------------------------------------------------------------
/lib/src/Scheme.o:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KyoohyungHan/FullRNS-HEAAN/515f6414076ca387996cb12e0798b4e3fcee653e/lib/src/Scheme.o
--------------------------------------------------------------------------------
/lib/src/SchemeAlgo.d:
--------------------------------------------------------------------------------
1 | src/SchemeAlgo.o: ../src/SchemeAlgo.cpp ../src/SchemeAlgo.h \
2 | ../src/Common.h ../src/EvaluatorUtils.h ../src/Context.h ../src/Numb.h \
3 | ../src/Plaintext.h ../src/SecretKey.h ../src/Ciphertext.h \
4 | ../src/Scheme.h ../src/Key.h
5 |
6 | ../src/SchemeAlgo.h:
7 |
8 | ../src/Common.h:
9 |
10 | ../src/EvaluatorUtils.h:
11 |
12 | ../src/Context.h:
13 |
14 | ../src/Numb.h:
15 |
16 | ../src/Plaintext.h:
17 |
18 | ../src/SecretKey.h:
19 |
20 | ../src/Ciphertext.h:
21 |
22 | ../src/Scheme.h:
23 |
24 | ../src/Key.h:
25 |
--------------------------------------------------------------------------------
/lib/src/SchemeAlgo.o:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KyoohyungHan/FullRNS-HEAAN/515f6414076ca387996cb12e0798b4e3fcee653e/lib/src/SchemeAlgo.o
--------------------------------------------------------------------------------
/lib/src/SecretKey.d:
--------------------------------------------------------------------------------
1 | src/SecretKey.o: ../src/SecretKey.cpp ../src/SecretKey.h ../src/Common.h \
2 | ../src/Context.h ../src/Numb.h
3 |
4 | ../src/SecretKey.h:
5 |
6 | ../src/Common.h:
7 |
8 | ../src/Context.h:
9 |
10 | ../src/Numb.h:
11 |
--------------------------------------------------------------------------------
/lib/src/SecretKey.o:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KyoohyungHan/FullRNS-HEAAN/515f6414076ca387996cb12e0798b4e3fcee653e/lib/src/SecretKey.o
--------------------------------------------------------------------------------
/lib/src/StringUtils.d:
--------------------------------------------------------------------------------
1 | src/StringUtils.o: ../src/StringUtils.cpp ../src/StringUtils.h \
2 | ../src/Common.h
3 |
4 | ../src/StringUtils.h:
5 |
6 | ../src/Common.h:
7 |
--------------------------------------------------------------------------------
/lib/src/StringUtils.o:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KyoohyungHan/FullRNS-HEAAN/515f6414076ca387996cb12e0798b4e3fcee653e/lib/src/StringUtils.o
--------------------------------------------------------------------------------
/lib/src/TestScheme.d:
--------------------------------------------------------------------------------
1 | src/TestScheme.o: ../src/TestScheme.cpp ../src/TestScheme.h ../src/Numb.h \
2 | ../src/Common.h ../src/Context.h ../src/SecretKey.h ../src/Scheme.h \
3 | ../src/Ciphertext.h ../src/Plaintext.h ../src/Key.h \
4 | ../src/EvaluatorUtils.h ../src/StringUtils.h ../src/TimeUtils.h \
5 | ../src/SchemeAlgo.h
6 |
7 | ../src/TestScheme.h:
8 |
9 | ../src/Numb.h:
10 |
11 | ../src/Common.h:
12 |
13 | ../src/Context.h:
14 |
15 | ../src/SecretKey.h:
16 |
17 | ../src/Scheme.h:
18 |
19 | ../src/Ciphertext.h:
20 |
21 | ../src/Plaintext.h:
22 |
23 | ../src/Key.h:
24 |
25 | ../src/EvaluatorUtils.h:
26 |
27 | ../src/StringUtils.h:
28 |
29 | ../src/TimeUtils.h:
30 |
31 | ../src/SchemeAlgo.h:
32 |
--------------------------------------------------------------------------------
/lib/src/TestScheme.o:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KyoohyungHan/FullRNS-HEAAN/515f6414076ca387996cb12e0798b4e3fcee653e/lib/src/TestScheme.o
--------------------------------------------------------------------------------
/lib/src/TimeUtils.d:
--------------------------------------------------------------------------------
1 | src/TimeUtils.o: ../src/TimeUtils.cpp ../src/TimeUtils.h ../src/Common.h
2 |
3 | ../src/TimeUtils.h:
4 |
5 | ../src/Common.h:
6 |
--------------------------------------------------------------------------------
/lib/src/TimeUtils.o:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KyoohyungHan/FullRNS-HEAAN/515f6414076ca387996cb12e0798b4e3fcee653e/lib/src/TimeUtils.o
--------------------------------------------------------------------------------
/lib/src/subdir.mk:
--------------------------------------------------------------------------------
1 | ################################################################################
2 | # Automatically-generated file. Do not edit!
3 | ################################################################################
4 |
5 | # Add inputs and outputs from these tool invocations to the build variables
6 | CPP_SRCS += \
7 | ../src/Ciphertext.cpp \
8 | ../src/Context.cpp \
9 | ../src/EvaluatorUtils.cpp \
10 | ../src/Key.cpp \
11 | ../src/Numb.cpp \
12 | ../src/Plaintext.cpp \
13 | ../src/Scheme.cpp \
14 | ../src/SchemeAlgo.cpp \
15 | ../src/SecretKey.cpp \
16 | ../src/StringUtils.cpp \
17 | ../src/TestScheme.cpp \
18 | ../src/TimeUtils.cpp
19 |
20 | OBJS += \
21 | ./src/Ciphertext.o \
22 | ./src/Context.o \
23 | ./src/EvaluatorUtils.o \
24 | ./src/Key.o \
25 | ./src/Numb.o \
26 | ./src/Plaintext.o \
27 | ./src/Scheme.o \
28 | ./src/SchemeAlgo.o \
29 | ./src/SecretKey.o \
30 | ./src/StringUtils.o \
31 | ./src/TestScheme.o \
32 | ./src/TimeUtils.o
33 |
34 | CPP_DEPS += \
35 | ./src/Ciphertext.d \
36 | ./src/Context.d \
37 | ./src/EvaluatorUtils.d \
38 | ./src/Key.d \
39 | ./src/Numb.d \
40 | ./src/Plaintext.d \
41 | ./src/Scheme.d \
42 | ./src/SchemeAlgo.d \
43 | ./src/SecretKey.d \
44 | ./src/StringUtils.d \
45 | ./src/TestScheme.d \
46 | ./src/TimeUtils.d
47 |
48 |
49 | # Each subdirectory must supply rules for building sources it contributes
50 | src/%.o: ../src/%.cpp
51 | @echo 'Building file: $<'
52 | @echo 'Invoking: GCC C++ Compiler'
53 | g++ -I/usr/local/include -O3 -c -std=c++11 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
54 | @echo 'Finished building: $<'
55 | @echo ' '
56 |
57 |
58 |
--------------------------------------------------------------------------------
/run/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KyoohyungHan/FullRNS-HEAAN/515f6414076ca387996cb12e0798b4e3fcee653e/run/.DS_Store
--------------------------------------------------------------------------------
/run/FRNSHEAAN:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KyoohyungHan/FullRNS-HEAAN/515f6414076ca387996cb12e0798b4e3fcee653e/run/FRNSHEAAN
--------------------------------------------------------------------------------
/run/main.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) by CryptoLab inc.
3 | * This program is licensed under a
4 | * Creative Commons Attribution-NonCommercial 3.0 Unported License.
5 | * You should have received a copy of the license along with this
6 | * work. If not, see .
7 | */
8 |
9 | #include "../src/TestScheme.h"
10 |
11 | int main() {
12 |
13 | TestScheme::testEncodeSingle(14, 1, 55);
14 |
15 | TestScheme::testEncodeBatch(15, 6, 55, 3);
16 |
17 | TestScheme::testBasic(15, 11, 55, 3);
18 |
19 | // TestScheme::testConjugateBatch(15, 6, 55, 1);
20 |
21 | // TestScheme::testRotateByPo2Batch(16, 26, 40, 1, 4, false);
22 |
23 | // TestScheme::testRotateBatch(15, 6, 55, 3, 4, true);
24 |
25 | // TestScheme::testimultBatch(16, 16, 55, 2);
26 |
27 | // TestScheme::testPowerOf2Batch(16, 15, 50, 2, 3);
28 |
29 | TestScheme::testInverseBatch(14, 5, 55, 4, 3);
30 |
31 | TestScheme::testExponentBatch(14, 5, 55, 7, 3);
32 |
33 | TestScheme::testSigmoidBatch(16, 15, 55, 3, 3);
34 |
35 | // TestScheme::testSlotsSum(16, 15, 40, 3);
36 |
37 | // TestScheme::testMeanVariance(14, 3, 55, 13);
38 |
39 | // TestScheme::testHEML("data/uis.txt", 0, 5);
40 |
41 | return 0;
42 | }
43 |
--------------------------------------------------------------------------------
/run/makefile:
--------------------------------------------------------------------------------
1 | ################################################################################
2 | # Automatically-generated file. Do not edit!
3 | ################################################################################
4 |
5 | # All Target
6 | all: FRNSHEAAN
7 |
8 | # Tool invocations
9 | FRNSHEAAN:
10 | @echo 'Building target: $@'
11 | @echo 'Invoking: MacOS X C++ Linker'
12 | g++ -std=c++11 -pthread -o "FRNSHEAAN" main.cpp ../lib/libFRNSHEAAN.a -I/../src/
13 | @echo 'Finished building target: $@'
14 | @echo ' '
15 |
16 | # Other Targets
17 | clean:
18 | rm -rf FRNSHEAAN
19 |
--------------------------------------------------------------------------------
/src/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KyoohyungHan/FullRNS-HEAAN/515f6414076ca387996cb12e0798b4e3fcee653e/src/.DS_Store
--------------------------------------------------------------------------------
/src/Ciphertext.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) by CryptoLab inc.
3 | * This program is licensed under a
4 | * Creative Commons Attribution-NonCommercial 3.0 Unported License.
5 | * You should have received a copy of the license along with this
6 | * work. If not, see .
7 | */
8 |
9 | #include "Ciphertext.h"
10 |
11 | Ciphertext::Ciphertext() : ax(nullptr), bx(nullptr), N(0), slots(0), l(0) {}
12 |
13 | Ciphertext::Ciphertext(uint64_t* ax, uint64_t* bx, long N, long slots, long l) : ax(ax), bx(bx), N(N), slots(slots), l(l){}
14 |
15 | Ciphertext::Ciphertext(const Ciphertext& cipher) : N(cipher.N), slots(cipher.slots), l(cipher.l) {
16 | ax = new uint64_t[N * l];
17 | bx = new uint64_t[N * l];
18 | for (long i = 0; i < N * l; ++i) {
19 | ax[i] = cipher.ax[i];
20 | bx[i] = cipher.bx[i];
21 | }
22 | }
23 |
24 | Ciphertext& Ciphertext::operator=(const Ciphertext& o) {
25 | if(this == &o) return *this; // handling of self assignment, thanks for your advice, arul.
26 | delete[] ax;
27 | delete[] bx;
28 | N = o.N;
29 | l = o.l;
30 | slots = o.slots;
31 | ax = new uint64_t[N * l];
32 | bx = new uint64_t[N * l];
33 | for (long i = 0; i < N * l; ++i) {
34 | ax[i] = o.ax[i];
35 | bx[i] = o.bx[i];
36 | }
37 | return *this;
38 | }
39 |
--------------------------------------------------------------------------------
/src/Ciphertext.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) by CryptoLab inc.
3 | * This program is licensed under a
4 | * Creative Commons Attribution-NonCommercial 3.0 Unported License.
5 | * You should have received a copy of the license along with this
6 | * work. If not, see .
7 | */
8 |
9 | #ifndef HEAANNTT_CIPHERTEXT_H_
10 | #define HEAANNTT_CIPHERTEXT_H_
11 |
12 | #include "Common.h"
13 |
14 | class Ciphertext {
15 |
16 | public:
17 |
18 | uint64_t* bx;
19 | uint64_t* ax;
20 |
21 | long N; ///< Dimension of Ring
22 |
23 | long slots; ///< The length of plaintext vector
24 |
25 | long l; ///< The level of this ciphertext
26 |
27 | // Default constructor
28 | Ciphertext();
29 |
30 | // Constructor
31 | Ciphertext(uint64_t* ax, uint64_t* bx, long N, long slots, long l);
32 |
33 | // Copy constructor
34 | Ciphertext(const Ciphertext& cipher);
35 | Ciphertext& operator=(const Ciphertext &o);
36 |
37 | };
38 |
39 | #endif
40 |
--------------------------------------------------------------------------------
/src/Common.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) by CryptoLab inc.
3 | * This program is licensed under a
4 | * Creative Commons Attribution-NonCommercial 3.0 Unported License.
5 | * You should have received a copy of the license along with this
6 | * work. If not, see .
7 | */
8 |
9 | #ifndef HEAANNTT_COMMON_H_
10 | #define HEAANNTT_COMMON_H_
11 |
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 |
21 | #endif
22 |
--------------------------------------------------------------------------------
/src/Context.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) by CryptoLab inc.
3 | * This program is licensed under a
4 | * Creative Commons Attribution-NonCommercial 3.0 Unported License.
5 | * You should have received a copy of the license along with this
6 | * work. If not, see .
7 | */
8 |
9 | #include
10 |
11 | #include "Context.h"
12 | #include "EvaluatorUtils.h"
13 |
14 | Context::Context(long logN, long logp, long L, long K, long h, double sigma) :
15 | logN(logN), logp(logp), L(L), K(K), h(h), sigma(sigma) {
16 |
17 | N = 1L << logN;
18 | M = N << 1;
19 | logNh = logN - 1;
20 | Nh = N >> 1;
21 | p = 1L << logp;
22 |
23 | qVec = new uint64_t[L]();
24 | qrVec = new uint64_t[L]();
25 | qTwok = new long[L]();
26 | qkVec = new uint64_t[L]();
27 | qdVec = new uint64_t[L]();
28 | qInvVec = new uint64_t[L]();
29 | qRoots = new uint64_t[L]();
30 | qRootsInv = new uint64_t[L]();
31 | qRootPows = new uint64_t*[L];
32 | qRootScalePows = new uint64_t*[L];
33 | qRootScalePowsOverq = new uint64_t*[L];
34 | qRootScalePowsInv = new uint64_t*[L];
35 | qRootPowsInv = new uint64_t*[L];
36 | NInvModq = new uint64_t[L]();
37 | NScaleInvModq = new uint64_t[L]();
38 |
39 | // Generate Primes //
40 | long bnd = 1;
41 | long cnt = 1;
42 |
43 | bnd = 1;
44 | while(1) {
45 | uint64_t prime = (1ULL << Q0_BIT_SIZE) + bnd * M + 1;
46 | if(primeTest(prime)) {
47 | qVec[0] = prime;
48 | break;
49 | }
50 | bnd++;
51 | }
52 |
53 | bnd = 1;
54 | while(cnt < L) {
55 | uint64_t prime1 = (1ULL << logp) + bnd * M + 1;
56 | if(primeTest(prime1)) {
57 | qVec[cnt] = prime1;
58 | cnt++;
59 | }
60 | uint64_t prime2 = (1ULL << logp) - bnd * M + 1;
61 | if(primeTest(prime2)) {
62 | qVec[cnt] = prime2;
63 | cnt++;
64 | }
65 | bnd++;
66 | }
67 |
68 | if(logp - logN - 1 - ceil(log2(bnd)) < 10) {
69 | cerr << "ERROR: too small number of precision" << endl;
70 | cerr << "TRY to use larger logp or smaller depth" << endl;
71 | }
72 |
73 | for (long i = 0; i < L; ++i) {
74 | qTwok[i] = (2 * ((long)log2(qVec[i]) + 1));
75 | qrVec[i] = (static_cast(1) << qTwok[i]) / qVec[i];
76 | qkVec[i] = static_cast(((static_cast(invMod(((uint64_t)(1) << 62), qVec[i])) << 62) - 1) / qVec[i]);
77 | qdVec[i] = qVec[i] << 1;
78 | qRoots[i] = findMthRootOfUnity(M, qVec[i]);
79 | qRootsInv[i] = invMod(qRoots[i], qVec[i]);
80 | NInvModq[i] = invMod(N, qVec[i]);
81 | mulMod(NScaleInvModq[i], NInvModq[i], (static_cast(1) << 32), qVec[i]);
82 | mulMod(NScaleInvModq[i], NScaleInvModq[i], (static_cast(1) << 32), qVec[i]);
83 | qInvVec[i] = inv(qVec[i]);
84 | qRootPows[i] = new uint64_t[N]();
85 | qRootPowsInv[i] = new uint64_t[N]();
86 | qRootScalePows[i] = new uint64_t[N]();
87 | qRootScalePowsOverq[i] = new uint64_t[N]();
88 | qRootScalePowsInv[i] = new uint64_t[N]();
89 | uint64_t power = static_cast(1);
90 | uint64_t powerInv = static_cast(1);
91 |
92 | for (long j = 0; j < N; ++j) {
93 | uint64_t jprime = bitReverse(static_cast(j)) >> (32 - logN);
94 | qRootPows[i][jprime] = power;
95 | unsigned __int128 tmp = (static_cast(power) << 64);
96 | qRootScalePowsOverq[i][jprime] = static_cast(tmp / qVec[i]);
97 | mulMod(qRootScalePows[i][jprime], qRootPows[i][jprime], (static_cast(1) << 32), qVec[i]);
98 | mulMod(qRootScalePows[i][jprime], qRootScalePows[i][jprime], (static_cast(1) << 32), qVec[i]);
99 | qRootPowsInv[i][jprime] = powerInv;
100 | mulMod(qRootScalePowsInv[i][jprime], qRootPowsInv[i][jprime], (static_cast(1) << 32), qVec[i]);
101 | mulMod(qRootScalePowsInv[i][jprime], qRootScalePowsInv[i][jprime], (static_cast(1) << 32), qVec[i]);
102 |
103 | if (j < N - 1) {
104 | mulMod(power, power, qRoots[i], qVec[i]);
105 | mulMod(powerInv, powerInv, qRootsInv[i], qVec[i]);
106 | }
107 | }
108 | }
109 |
110 | pVec = new uint64_t[K]();
111 | prVec = new uint64_t[K]();
112 | pTwok = new long[K]();
113 | pkVec = new uint64_t[K]();
114 | pdVec = new uint64_t[K]();
115 | pInvVec = new uint64_t[K]();
116 | pRoots = new uint64_t[K]();
117 | pRootsInv = new uint64_t[K]();
118 | pRootPows = new uint64_t*[K];
119 | pRootPowsInv = new uint64_t*[K];
120 | pRootScalePows = new uint64_t*[K];
121 | pRootScalePowsOverp = new uint64_t*[K];
122 | pRootScalePowsInv = new uint64_t*[K];
123 | NInvModp = new uint64_t[K]();
124 | NScaleInvModp = new uint64_t[K]();
125 |
126 | // Generate Special Primes //
127 | cnt = 0;
128 | while(cnt < K) {
129 | uint64_t prime1 = (1ULL << logp) + bnd * M + 1;
130 | if(primeTest(prime1)) {
131 | pVec[cnt] = prime1;
132 | cnt++;
133 | }
134 | if(cnt == K) break;
135 | uint64_t prime2 = (1ULL << logp) - bnd * M + 1;
136 | if(primeTest(prime2)) {
137 | pVec[cnt] = prime2;
138 | cnt++;
139 | }
140 | bnd++;
141 | }
142 |
143 | for (long i = 0; i < K; ++i) {
144 | pTwok[i] = (2 * ((long)log2(pVec[i]) + 1));
145 | prVec[i] = (static_cast(1) << pTwok[i]) / pVec[i];
146 | pkVec[i] = static_cast(((static_cast(invMod(((uint64_t)(1) << 62), pVec[i])) << 62) - 1) / pVec[i]);
147 | pdVec[i] = pVec[i] << 1;
148 | pRoots[i] = findMthRootOfUnity(M, pVec[i]);
149 | pRootsInv[i] = invMod(pRoots[i], pVec[i]);
150 | NInvModp[i] = invMod(N, pVec[i]);
151 | mulMod(NScaleInvModp[i], NInvModp[i], (static_cast(1) << 32), pVec[i]);
152 | mulMod(NScaleInvModp[i], NScaleInvModp[i], (static_cast(1) << 32), pVec[i]);
153 | pRootPows[i] = new uint64_t[N]();
154 | pRootScalePows[i] = new uint64_t[N]();
155 | pRootScalePowsOverp[i] = new uint64_t[N]();
156 | pRootScalePowsInv[i] = new uint64_t[N]();
157 | pRootPowsInv[i] = new uint64_t[N]();
158 | pInvVec[i] = inv(pVec[i]);
159 | uint64_t power = static_cast(1);
160 | uint64_t powerInv = static_cast(1);
161 | for (long j = 0; j < N; ++j) {
162 | uint64_t jprime = bitReverse(static_cast(j)) >> (32 - logN);
163 | pRootPows[i][jprime] = power;
164 | unsigned __int128 tmp = (static_cast(power) << 64);
165 | mulMod(pRootScalePows[i][jprime], pRootPows[i][jprime], (static_cast(1) << 32), pVec[i]);
166 | mulMod(pRootScalePows[i][jprime], pRootScalePows[i][jprime], (static_cast(1) << 32), pVec[i]);
167 | pRootPowsInv[i][jprime] = powerInv;
168 | mulMod(pRootScalePowsInv[i][jprime], pRootPowsInv[i][jprime], (static_cast(1) << 32), pVec[i]);
169 | mulMod(pRootScalePowsInv[i][jprime], pRootScalePowsInv[i][jprime], (static_cast(1) << 32), pVec[i]);
170 | if (j < N - 1) {
171 | mulMod(power, power, pRoots[i], pVec[i]);
172 | mulMod(powerInv, powerInv, pRootsInv[i], pVec[i]);
173 | }
174 | }
175 | }
176 |
177 | qHatModq = new uint64_t*[L]; // [l][i] (phat_i)_l mod p_i
178 | for (long l = 0; l < L; ++l) {
179 | qHatModq[l] = new uint64_t[l + 1]();
180 | for (long i = 0; i < l + 1; ++i) {
181 | qHatModq[l][i] = 1;
182 | for (long j = 0; j < i; ++j) {
183 | uint64_t temp = qVec[j] % qVec[i];
184 | mulMod(qHatModq[l][i], qHatModq[l][i], temp, qVec[i]);
185 | }
186 | for (long j = i + 1; j < l + 1; ++j) {
187 | uint64_t temp = qVec[j] % qVec[i];
188 | mulMod(qHatModq[l][i], qHatModq[l][i], temp, qVec[i]);
189 | }
190 | }
191 | }
192 |
193 | qHatInvModq = new uint64_t*[L]; // [l][i] (phat_i)_l^-1 mod p_i
194 | for (long l = 0; l < L; ++l) {
195 | qHatInvModq[l] = new uint64_t[l + 1]();
196 | for (long i = 0; i < l + 1; ++i) {
197 | qHatInvModq[l][i] = invMod(qHatModq[l][i], qVec[i]);
198 | }
199 | }
200 |
201 | pHatModp = new uint64_t[K](); // [k] qhat_k mod q_k
202 |
203 | for (long k = 0; k < K; ++k) {
204 | pHatModp[k] = 1;
205 | for (long j = 0; j < k; ++j) {
206 | uint64_t temp = pVec[j] % pVec[k];
207 | mulMod(pHatModp[k], pHatModp[k], temp, pVec[k]);
208 | }
209 | for (long j = k + 1; j < K; ++j) {
210 | uint64_t temp = pVec[j] % pVec[k];
211 | mulMod(pHatModp[k], pHatModp[k], temp, pVec[k]);
212 | }
213 | }
214 |
215 | pHatInvModp = new uint64_t[K](); // [k] qhat_k^-1 mod q_k
216 | for (long k = 0; k < K; ++k) {
217 | pHatInvModp[k] = invMod(pHatModp[k], pVec[k]);
218 | }
219 |
220 | qHatModp = new uint64_t**[L]; // [l] [i] [k] (phat_i)_l mod q_k
221 | for (long l = 0; l < L; ++l) {
222 | qHatModp[l] = new uint64_t*[l + 1];
223 | for (long i = 0; i < l + 1; ++i) {
224 | qHatModp[l][i] = new uint64_t[K]();
225 | for (long k = 0; k < K; ++k) {
226 | qHatModp[l][i][k] = 1;
227 | for (long j = 0; j < i; ++j) {
228 | uint64_t temp = qVec[j] % pVec[k];
229 | mulMod(qHatModp[l][i][k], qHatModp[l][i][k], temp, pVec[k]);
230 | }
231 | for (long j = i + 1; j < l + 1; ++j) {
232 | uint64_t temp = qVec[j] % pVec[k];
233 | mulMod(qHatModp[l][i][k], qHatModp[l][i][k], temp, pVec[k]);
234 | }
235 | }
236 | }
237 | }
238 |
239 | pHatModq = new uint64_t*[K]; // [k][i] qhat_k mod p_i
240 | for (long k = 0; k < K; ++k) {
241 | pHatModq[k] = new uint64_t[L]();
242 | for (long i = 0; i < L; ++i) {
243 | pHatModq[k][i] = 1;
244 | for (long s = 0; s < k; ++s) {
245 | uint64_t temp = pVec[s] % qVec[i];
246 | mulMod(pHatModq[k][i], pHatModq[k][i], temp, qVec[i]);
247 | }
248 | for (long s = k + 1; s < K; ++s) {
249 | uint64_t temp = pVec[s] % qVec[i];
250 | mulMod(pHatModq[k][i], pHatModq[k][i], temp, qVec[i]);
251 | }
252 | }
253 | }
254 |
255 | PModq = new uint64_t[L](); // [i] qprod mod p_i
256 | for (long i = 0; i < L; ++i) {
257 | PModq[i] = 1;
258 | for (long k = 0; k < K; ++k) {
259 | uint64_t temp = pVec[k] % qVec[i];
260 | mulMod(PModq[i], PModq[i], temp, qVec[i]);
261 | }
262 | }
263 |
264 | PInvModq = new uint64_t[L](); // [i] qprod^-1 mod p_i
265 | for (long i = 0; i < L; ++i) {
266 | PInvModq[i] = invMod(PModq[i], qVec[i]);
267 | }
268 |
269 | QModp = new uint64_t*[L];
270 | for (long i = 0; i < L; ++i) {
271 | QModp[i] = new uint64_t[K]();
272 | for (long k = 0; k < K; ++k) {
273 | QModp[i][k] = 1;
274 | for (long j = 0; j < i + 1; ++j) {
275 | uint64_t temp = qVec[j] % pVec[k];
276 | mulMod(QModp[i][k], QModp[i][k], temp, pVec[k]);
277 | }
278 | }
279 | }
280 | QInvModp = new uint64_t*[L];
281 | for (long i = 0; i < L; ++i) {
282 | QInvModp[i] = new uint64_t[K]();
283 | for (long k = 0; k < K; ++k) {
284 | QInvModp[i][k] = invMod(QModp[i][k], pVec[k]);
285 | }
286 | }
287 |
288 | qInvModq = new uint64_t*[L]; // [i][j] p_i^-1 mod p_j
289 | for (long i = 0; i < L; ++i) {
290 | qInvModq[i] = new uint64_t[L]();
291 | for (long j = 0; j < i; ++j) {
292 | qInvModq[i][j] = invMod(qVec[i], qVec[j]);
293 | }
294 | for (long j = i + 1; j < L; ++j) {
295 | qInvModq[i][j] = invMod(qVec[i], qVec[j]);
296 | }
297 | }
298 |
299 | rotGroup = new long[Nh]();
300 | long fivePows = 1;
301 | for (long i = 0; i < Nh; ++i) {
302 | rotGroup[i] = fivePows;
303 | fivePows *= 5;
304 | fivePows %= M;
305 | }
306 |
307 | ksiPows = new complex[M + 1];
308 | for (long j = 0; j < M; ++j) {
309 | double angle = 2.0 * M_PI * j / M;
310 | ksiPows[j].real(cos(angle));
311 | ksiPows[j].imag(sin(angle));
312 | }
313 |
314 | ksiPows[M] = ksiPows[0];
315 |
316 | p2coeff = new uint64_t[L << logN];
317 |
318 | for (long i = 0; i < L; ++i) {
319 | for (long n = 0; n < N; ++n) {
320 | mulModBarrett(p2coeff[n + (i << logN)], p, p, qVec[i], qrVec[i], qTwok[i]);
321 | }
322 | }
323 | p2hcoeff = new uint64_t[L << logN];
324 |
325 | for (long i = 0; i < L; ++i) {
326 | for (long n = 0; n < N; ++n) {
327 | mulModBarrett(p2hcoeff[n + (i << logN)], (p >> 1), p, qVec[i], qrVec[i], qTwok[i]);
328 | }
329 | }
330 |
331 | pccoeff = new uint64_t[L << logN]();
332 | for (long i = 0; i < L; ++i) {
333 | for (long n = 0; n < N; ++n) {
334 | mulModBarrett(pccoeff[n + (i << logN)], (94.2372881) * (p >> 20), (1L << 20), qVec[i], qrVec[i], qTwok[i]);
335 | }
336 | }
337 | negateAndEqual(pccoeff, L);
338 |
339 |
340 | taylorCoeffsMap.insert(pair(LOGARITHM, new double[11]{0,1,-0.5,1./3,-1./4,1./5,-1./6,1./7,-1./8,1./9,-1./10}));
341 | taylorCoeffsMap.insert(pair(EXPONENT, new double[11]{1,1,0.5,1./6,1./24,1./120,1./720,1./5040, 1./40320,1./362880,1./3628800}));
342 | taylorCoeffsMap.insert(pair(SIGMOID, new double[11]{1./2,1./4,0,-1./48,0,1./480,0,-17./80640,0,31./1451520,0}));
343 |
344 | }
345 |
346 | void Context::arrayBitReverse(complex* vals, const long size) {
347 | for (long i = 1, j = 0; i < size; ++i) {
348 | long bit = size >> 1;
349 | for (; j >= bit; bit >>= 1) {
350 | j -= bit;
351 | }
352 | j += bit;
353 | if (i < j) {
354 | swap(vals[i], vals[j]);
355 | }
356 | }
357 | }
358 |
359 | void Context::arrayBitReverse(uint64_t* vals, const long size) {
360 | for (long i = 1, j = 0; i < size; ++i) {
361 | long bit = size >> 1;
362 | for (; j >= bit; bit >>= 1) {
363 | j -= bit;
364 | }
365 | j += bit;
366 | if (i < j) {
367 | swap(vals[i], vals[j]);
368 | }
369 | }
370 | }
371 |
372 | void Context::fft(complex* vals, const long size) {
373 | arrayBitReverse(vals, size);
374 | for (long len = 2; len <= size; len <<= 1) {
375 | long MoverLen = M / len;
376 | long lenh = len >> 1;
377 | for (long i = 0; i < size; i += len) {
378 | for (long j = 0; j < lenh; ++j) {
379 | long idx = j * MoverLen;
380 | complex u = vals[i + j];
381 | complex v = vals[i + j + lenh];
382 | v *= ksiPows[idx];
383 | vals[i + j] = u + v;
384 | vals[i + j + lenh] = u - v;
385 | }
386 | }
387 | }
388 | }
389 |
390 | void Context::fftInvLazy(complex* vals, const long size) {
391 | arrayBitReverse(vals, size);
392 | for (long len = 2; len <= size; len <<= 1) {
393 | long MoverLen = M / len;
394 | long lenh = len >> 1;
395 | for (long i = 0; i < size; i += len) {
396 | for (long j = 0; j < lenh; ++j) {
397 | long idx = (len - j) * MoverLen;
398 | complex u = vals[i + j];
399 | complex v = vals[i + j + lenh];
400 | v *= ksiPows[idx];
401 | vals[i + j] = u + v;
402 | vals[i + j + lenh] = u - v;
403 | }
404 | }
405 | }
406 | }
407 |
408 | void Context::fftInv(complex* vals, const long size) {
409 | fftInvLazy(vals, size);
410 | for (long i = 0; i < size; ++i) {
411 | vals[i] /= size;
412 | }
413 | }
414 |
415 | void Context::fftSpecial(complex* vals, const long size) {
416 | arrayBitReverse(vals, size);
417 | for (long len = 2; len <= size; len <<= 1) {
418 | for (long i = 0; i < size; i += len) {
419 | long lenh = len >> 1;
420 | long lenq = len << 2;
421 | for (long j = 0; j < lenh; ++j) {
422 | long idx = ((rotGroup[j] % lenq)) * M / lenq;
423 | complex u = vals[i + j];
424 | complex v = vals[i + j + lenh];
425 | v *= ksiPows[idx];
426 | vals[i + j] = u + v;
427 | vals[i + j + lenh] = u - v;
428 | }
429 | }
430 | }
431 | }
432 |
433 | void Context::fftSpecialInvLazy(complex* vals, const long size) {
434 | for (long len = size; len >= 1; len >>= 1) {
435 | for (long i = 0; i < size; i += len) {
436 | long lenh = len >> 1;
437 | long lenq = len << 2;
438 | for (long j = 0; j < lenh; ++j) {
439 | long idx = (lenq - (rotGroup[j] % lenq)) * M / lenq;
440 | complex u = vals[i + j] + vals[i + j + lenh];
441 | complex v = vals[i + j] - vals[i + j + lenh];
442 | v *= ksiPows[idx];
443 | vals[i + j] = u;
444 | vals[i + j + lenh] = v;
445 | }
446 | }
447 | }
448 | arrayBitReverse(vals, size);
449 | }
450 |
451 | void Context::fftSpecialInv(complex* vals, const long size) {
452 | fftSpecialInvLazy(vals, size);
453 | for (long i = 0; i < size; ++i) {
454 | vals[i] /= size;
455 | }
456 | }
457 |
458 | void Context::encode(uint64_t* a, complex* v, long slots, long l) {
459 | complex* uvals = new complex [slots]();
460 | copy(v, v + slots, uvals);
461 |
462 | long gap = Nh / slots;
463 |
464 | fftSpecialInv(uvals, slots);
465 |
466 | for (long j = 0; j < slots; ++j) {
467 | uvals[j] *= p;
468 | }
469 |
470 | for (long i = 0; i < l; ++i) {
471 | uint64_t* mi = a + i * N;
472 | for (long j = 0, jdx = Nh, idx = 0; j < slots; ++j, jdx += gap, idx += gap) {
473 | long mir = uvals[j].real();
474 | long mii = uvals[j].imag();
475 | mi[idx] = mir >= 0 ? (uint64_t) mir : (uint64_t) (qVec[i] + mir);
476 | mi[jdx] = mii >= 0 ? (uint64_t) mii : (uint64_t) (qVec[i] + mii);
477 | }
478 | qiNTTAndEqual(mi, i);
479 | }
480 | delete[] uvals;
481 | }
482 |
483 | void Context::encode(uint64_t* ax, double* vals, long slots, long l) {
484 |
485 | }
486 |
487 | void Context::encodeSingle(uint64_t* ax, complex& val, long l) {
488 | long vr = val.real() * p;
489 | long vi = val.imag() * p;
490 |
491 | for (long i = 0; i < l; ++i) {
492 | uint64_t* ai = ax + i * N;
493 | ai[0] = vr >= 0 ? vr : qVec[i] + vr;
494 | ai[Nh] = vi >= 0 ? vi : qVec[i] + vi;
495 | qiNTTAndEqual(ai, i);
496 | }
497 | }
498 |
499 | void Context::encodeSingle(uint64_t* ax, double val, long l) {
500 |
501 | }
502 |
503 | void Context::decode(uint64_t* a, complex* v, long slots, long l) {
504 | uint64_t* tmp = new uint64_t[N]();
505 | copy(a, a + N, tmp);
506 | long gap = Nh / slots;
507 | qiINTTAndEqual(tmp, 0);
508 |
509 | uint64_t pr = qVec[0];
510 | uint64_t pr_2 = qVec[0] / 2;
511 |
512 | for (long j = 0, jdx = Nh, idx = 0; j < slots; ++j, jdx += gap, idx += gap) {
513 | double mir = tmp[idx] <= pr_2 ? ((double) (tmp[idx]) / p) : (((double) (tmp[idx]) - (double) (pr)) / p);
514 | double mii = tmp[jdx] <= pr_2 ? ((double) (tmp[jdx]) / p) : (((double) (tmp[jdx]) - (double) (pr)) / p);
515 | v[j].real(mir);
516 | v[j].imag(mii);
517 | }
518 | fftSpecial(v, slots);
519 | }
520 |
521 | void Context::decodeSingle(uint64_t* ax, complex& val, long l) {
522 | uint64_t* tmp = new uint64_t[N]();
523 | copy(ax, ax + N, tmp);
524 | qiINTTAndEqual(tmp, 0);
525 |
526 | uint64_t pr = qVec[0];
527 | uint64_t pr_2 = qVec[0] / 2;
528 |
529 | double vr = tmp[0] <= pr_2 ? ((double) tmp[0]) / p : (((double) tmp[0]) - ((double) pr)) / (double) p;
530 | double vi = tmp[Nh] <= pr_2 ? ((double) tmp[Nh]) / p : (((double) tmp[Nh]) - ((double) pr)) / (double) p;
531 |
532 | val.real(vr);
533 | val.imag(vi);
534 | }
535 |
536 | void Context::decodeSingle(uint64_t* ax, double val, long l) {
537 | //TODO implement method
538 |
539 | }
540 |
541 | void Context::qiNTT(uint64_t* res, uint64_t* a, long index) {
542 | copy(a, a + N, res);
543 | qiNTTAndEqual(res, index);
544 | }
545 |
546 | void Context::piNTT(uint64_t* res, uint64_t* a, long index) {
547 | copy(a, a + N, res);
548 | piNTTAndEqual(res, index);
549 | }
550 |
551 | void Context::NTT(uint64_t* res, uint64_t* a, long l, long k) {
552 | for (long index = 0; index < l; ++index) {
553 | uint64_t* ai = a + (index << logN);
554 | uint64_t* resi = a + (index << logN);
555 | qiNTT(resi, ai, index);
556 | }
557 |
558 | for (long index = l; index < l + k; ++index) {
559 | uint64_t* ai = a + (index << logN);
560 | uint64_t* resi = a + (index << logN);
561 | piNTT(resi, ai, index - l);
562 | }
563 | }
564 |
565 | void Context::qiNTTAndEqual(uint64_t* a, long index) {
566 | long t = N;
567 | long logt1 = logN + 1;
568 | uint64_t q = qVec[index];
569 | // uint64_t qd = qdVec[index];
570 | uint64_t qInv = qInvVec[index];
571 | for (long m = 1; m < N; m <<= 1) {
572 | t >>= 1;
573 | logt1 -= 1;
574 | for (long i = 0; i < m; i++) {
575 | long j1 = i << logt1;
576 | long j2 = j1 + t - 1;
577 | uint64_t W = qRootScalePows[index][m + i];
578 | // uint64_t W = qRootScalePowsOverq[index][m + i];
579 | // uint64_t w = qRootPows[index][m + i];
580 | for (long j = j1; j <= j2; j++) {
581 |
582 | uint64_t T = a[j + t];
583 | unsigned __int128 U = static_cast(T) * W;
584 | uint64_t U0 = static_cast(U);
585 | uint64_t U1 = static_cast(U >> 64);
586 | uint64_t Q = U0 * qInv;
587 | unsigned __int128 Hx = static_cast(Q) * q;
588 | uint64_t H = static_cast(Hx >> 64);
589 | uint64_t V = U1 < H ? U1 + q - H : U1 - H;
590 | a[j + t] = a[j] < V ? a[j] + q - V: a[j] - V;
591 | a[j] += V;
592 | if(a[j] > q) a[j] -= q;
593 |
594 | // if(a[j] >= qd) a[j] -= qd;
595 | // uint64_t T = a[j + t];
596 | // unsigned __int128 U = static_cast(T) * W;
597 | // uint64_t Q = static_cast(U >> 64);
598 | // T *= w;
599 | // uint64_t T1 = Q * q;
600 | // T -= T1;
601 | // a[j + t] = a[j] + qd - T;
602 | // a[j] += T;
603 | }
604 | }
605 | }
606 | // for(long i = 0; i < N; i++) {
607 | // if(a[i] >= qd) a[i] -= qd;
608 | // if(a[i] >= q) a[i] -= q;
609 | // }
610 | }
611 |
612 | void Context::piNTTAndEqual(uint64_t* a, long index) {
613 | long t = N;
614 | long logt1 = logN + 1;
615 | uint64_t pi = pVec[index];
616 | // uint64_t pd = pdVec[index];
617 | uint64_t pInv = pInvVec[index];
618 | for (long m = 1; m < N; m <<= 1) {
619 | t >>= 1;
620 | logt1 -= 1;
621 | for (long i = 0; i < m; i++) {
622 | long j1 = i << logt1;
623 | long j2 = j1 + t - 1;
624 | uint64_t W = pRootScalePows[index][m + i];
625 | // uint64_t W = pRootScalePowsOverp[index][m + i];
626 | // uint64_t w = pRootPows[index][m + i];
627 | for (long j = j1; j <= j2; j++) {
628 |
629 | uint64_t T = a[j + t];
630 | unsigned __int128 U = static_cast(T) * W;
631 | uint64_t U0 = static_cast(U);
632 | uint64_t U1 = static_cast(U >> 64);
633 | uint64_t Q = U0 * pInv;
634 | unsigned __int128 Hx = static_cast(Q) * pi;
635 | uint64_t H = static_cast(Hx >> 64);
636 | uint64_t V = U1 < H ? U1 + pi - H : U1 - H;
637 | a[j + t] = a[j] < V ? a[j] + pi - V: a[j] - V;
638 | a[j] += V;
639 | if(a[j] > pi) a[j] -= pi;
640 |
641 | // if(a[j] >= pd) a[j] -= pd;
642 | // uint64_t T = a[j + t];
643 | // unsigned __int128 U = static_cast(T) * W;
644 | // uint64_t Q = static_cast(U >> 64);
645 | // T *= w;
646 | // uint64_t T1 = Q * pi;
647 | // T -= T1;
648 | // a[j + t] = a[j] + pd - T;
649 | // a[j] += T;
650 | }
651 | }
652 | }
653 | // for(long i = 0; i < N; i++) {
654 | // if(a[i] >= pd) a[i] -= pd;
655 | // if(a[i] >= p) a[i] -= pi;
656 | // }
657 | }
658 |
659 | void Context::NTTAndEqual(uint64_t* a, long l, long k) {
660 | for (long index = 0; index < l; ++index) {
661 | uint64_t* ai = a + (index << logN);
662 | qiNTTAndEqual(ai, index);
663 | }
664 |
665 | for (long index = l; index < l + k; ++index) {
666 | uint64_t* ai = a + (index << logN);
667 | piNTTAndEqual(ai, index - l);
668 | }
669 | }
670 |
671 | void Context::qiINTT(uint64_t* res, uint64_t* a, long index) {
672 | copy(a, a + N, res);
673 | qiINTTAndEqual(res, index);
674 | }
675 |
676 | void Context::qiINTTAndEqual(uint64_t* a, long index) {
677 | uint64_t q = qVec[index];
678 | uint64_t qd = qdVec[index];
679 | uint64_t qInv = qInvVec[index];
680 | long t = 1;
681 | for (long m = N; m > 1; m >>= 1) {
682 | long j1 = 0;
683 | long h = m >> 1;
684 | for (long i = 0; i < h; i++) {
685 | long j2 = j1 + t - 1;
686 | uint64_t W = qRootScalePowsInv[index][h + i];
687 | for (long j = j1; j <= j2; j++) {
688 | uint64_t T = a[j] + qd;
689 | T -= a[j + t];
690 | a[j] += a[j + t];
691 | if(a[j] >= qd) a[j] -= qd;
692 | unsigned __int128 UU = static_cast(T) * W;
693 | uint64_t U0 = static_cast(UU);
694 | uint64_t U1 = static_cast(UU >> 64);
695 | uint64_t Q = U0 * qInv;
696 | unsigned __int128 Hx = static_cast(Q) * q;
697 | uint64_t H = static_cast(Hx >> 64);
698 | a[j + t] = U1 + q;
699 | a[j + t] -= H;
700 | }
701 | j1 += (t << 1);
702 | }
703 | t <<= 1;
704 | }
705 |
706 | uint64_t NScale = NScaleInvModq[index];
707 | for (long i = 0; i < N; i++) {
708 | uint64_t T = (a[i] < q) ? a[i] : a[i] - q;
709 | unsigned __int128 U = static_cast(T) * NScale;
710 | uint64_t U0 = static_cast(U);
711 | uint64_t U1 = static_cast(U >> 64);
712 | uint64_t Q = U0 * qInv;
713 | unsigned __int128 Hx = static_cast(Q) * q;
714 | uint64_t H = static_cast(Hx >> 64);
715 | a[i] = (U1 < H) ? U1 + q - H : U1 - H;
716 | }
717 | }
718 |
719 | void Context::piINTTAndEqual(uint64_t* a, long index) {
720 | uint64_t pi = pVec[index];
721 | uint64_t pd = pdVec[index];
722 | uint64_t pInv = pInvVec[index];
723 | long t = 1;
724 | for (long m = N; m > 1; m >>= 1) {
725 | long j1 = 0;
726 | long h = m >> 1;
727 | for (long i = 0; i < h; i++) {
728 | long j2 = j1 + t - 1;
729 | uint64_t W = pRootScalePowsInv[index][h + i];
730 | for (long j = j1; j <= j2; j++) {
731 | uint64_t T = a[j] + pd;
732 | T -= a[j + t];
733 | a[j] += a[j + t];
734 | if(a[j] >= pd) a[j] -= pd;
735 | unsigned __int128 UU = static_cast(T) * W;
736 | uint64_t U0 = static_cast(UU);
737 | uint64_t U1 = static_cast(UU >> 64);
738 | uint64_t Q = U0 * pInv;
739 | unsigned __int128 Hx = static_cast(Q) * pi;
740 | uint64_t H = static_cast(Hx >> 64);
741 | a[j + t] = U1 + pi;
742 | a[j + t] -= H;
743 | }
744 | j1 += (t << 1);
745 | }
746 | t <<= 1;
747 | }
748 |
749 | uint64_t NScale = NScaleInvModp[index];
750 | for (long i = 0; i < N; i++) {
751 | uint64_t T = (a[i] < pi) ? a[i] : a[i] - pi;
752 | unsigned __int128 U = static_cast(T) * NScale;
753 | uint64_t U0 = static_cast(U);
754 | uint64_t U1 = static_cast(U >> 64);
755 | uint64_t Q = U0 * pInv;
756 | unsigned __int128 Hx = static_cast(Q) * pi;
757 | uint64_t H = static_cast(Hx >> 64);
758 | a[i] = (U1 < H) ? U1 + pi - H : U1 - H;
759 | }
760 | }
761 |
762 | void Context::INTTAndEqual(uint64_t* a, long l, long k) {
763 | for (long index = 0; index < l; ++index) {
764 | uint64_t* ai = a + (index << logN);
765 | qiINTTAndEqual(ai, index);
766 | }
767 |
768 | for (long index = l; index < l + k; ++index) {
769 | uint64_t* ai = a + (index << logN);
770 | piINTTAndEqual(ai, index - l);
771 | }
772 | }
773 |
774 | void Context::qiNegate(uint64_t* res, uint64_t* a, long index) {
775 | for (long i = 0; i < N; ++i) {
776 | res[i] = (a[i] == 0) ? 0 : qVec[index] - a[i];
777 | }
778 | }
779 |
780 | void Context::piNegate(uint64_t* res, uint64_t* a, long index) {
781 | for (long i = 0; i < N; ++i) {
782 | res[i] = (a[i] == 0) ? 0 : pVec[index] - a[i];
783 | }
784 | }
785 |
786 | void Context::negate(uint64_t* res, uint64_t* a, long l, long k) {
787 | for (long i = 0; i < l; ++i) {
788 | uint64_t* ai = a + (i << logN);
789 | uint64_t* resi = res + (i << logN);
790 | qiNegate(resi, ai, i);
791 | }
792 |
793 | for (long i = l; i < l + k; ++i) {
794 | uint64_t* ai = a + (i << logN);
795 | uint64_t* resi = res + (i << logN);
796 | piNegate(resi, ai, i - l);
797 | }
798 | }
799 |
800 | void Context::qiNegateAndEqual(uint64_t* a, long index) {
801 | for (long i = 0; i < N; ++i) {
802 | a[i] = (a[i] == 0) ? 0 : qVec[index] - a[i];
803 | }
804 | }
805 |
806 | void Context::piNegateAndEqual(uint64_t* a, long index) {
807 | for (long i = 0; i < N; ++i) {
808 | a[i] = (a[i] == 0) ? 0 : pVec[index] - a[i];
809 | }
810 | }
811 |
812 | void Context::negateAndEqual(uint64_t* a, long l, long k) {
813 | for (long i = 0; i < l; ++i) {
814 | uint64_t* ai = a + (i << logN);
815 | qiNegateAndEqual(ai, i);
816 | }
817 |
818 | for (long i = l; i < l + k; ++i) {
819 | uint64_t* ai = a + (i << logN);
820 | piNegateAndEqual(ai, i - l);
821 | }
822 | }
823 |
824 | void Context::qiAddConst(uint64_t* res, uint64_t* a, uint64_t c, long index) {
825 | for (long i = 0; i < N; ++i) {
826 | addMod(res[i], a[i], c, qVec[index]);
827 | }
828 | }
829 |
830 | void Context::piAddConst(uint64_t* res, uint64_t* a, uint64_t c, long index) {
831 | for (long i = 0; i < N; ++i) {
832 | addMod(res[i], a[i], c, pVec[index]);
833 | }
834 | }
835 |
836 | void Context::addConst(uint64_t* res, uint64_t* a, uint64_t c, long l, long k) {
837 | for (long i = 0; i < l; ++i) {
838 | uint64_t* ai = a + (i << logN);
839 | uint64_t* resi = res + (i << logN);
840 | qiAddConst(resi, ai, c, i);
841 | }
842 |
843 | for (long i = l; i < l + k; ++i) {
844 | uint64_t* ai = a + (i << logN);
845 | uint64_t* resi = res + (i << logN);
846 | piAddConst(resi, ai, c, i - l);
847 | }
848 | }
849 |
850 | void Context::qiAddConstAndEqual(uint64_t* a, uint64_t c, long index) {
851 | for (long i = 0; i < N; ++i) {
852 | addMod(a[i], a[i], c, qVec[index]);
853 | }
854 | }
855 |
856 | void Context::piAddConstAndEqual(uint64_t* a, uint64_t c, long index) {
857 | for (long i = 0; i < N; ++i) {
858 | addMod(a[i], a[i], c, pVec[index]);
859 | }
860 | }
861 |
862 | void Context::addConstAndEqual(uint64_t* a, uint64_t c, long l, long k) {
863 | for (long i = 0; i < l; ++i) {
864 | uint64_t* ai = a + (i << logN);
865 | qiAddConstAndEqual(ai, c, i);
866 | }
867 |
868 | for (long i = l; i < l + k; ++i) {
869 | uint64_t* ai = a + (i << logN);
870 | piAddConstAndEqual(ai, c, i - l);
871 | }
872 | }
873 |
874 | void Context::qiSubConst(uint64_t* res, uint64_t* a, uint64_t c, long index) {
875 | for (long i = 0; i < N; ++i) {
876 | subMod(res[i], a[i], c, qVec[index]);
877 | }
878 | }
879 |
880 | void Context::piSubConst(uint64_t* res, uint64_t* a, uint64_t c, long index) {
881 | for (long i = 0; i < N; ++i) {
882 | subMod(res[i], a[i], c, pVec[index]);
883 | }
884 | }
885 |
886 | void Context::subConst(uint64_t* res, uint64_t* a, uint64_t c, long l, long k) {
887 | for (long i = 0; i < l; ++i) {
888 | uint64_t* ai = a + (i << logN);
889 | uint64_t* resi = res + (i << logN);
890 | qiSubConst(resi, ai, c, i);
891 | }
892 |
893 | for (long i = l; i < l + k; ++i) {
894 | uint64_t* ai = a + (i << logN);
895 | uint64_t* resi = res + (i << logN);
896 | piSubConst(resi, ai, c, i - l);
897 | }
898 | }
899 |
900 | void Context::qiSubConstAndEqual(uint64_t* a, uint64_t c, long index) {
901 | for (long i = 0; i < N; ++i) {
902 | subMod(a[i], a[i], c, qVec[index]);
903 | }
904 | }
905 |
906 | void Context::piSubConstAndEqual(uint64_t* a, uint64_t c, long index) {
907 | for (long i = 0; i < N; ++i) {
908 | subMod(a[i], a[i], c, pVec[index]);
909 | }
910 | }
911 |
912 | void Context::subConstAndEqual(uint64_t* a, uint64_t c, long l, long k) {
913 | for (long i = 0; i < l; ++i) {
914 | uint64_t* ai = a + (i << logN);
915 | qiSubConstAndEqual(ai, c, i);
916 | }
917 |
918 | for (long i = l; i < l + k; ++i) {
919 | uint64_t* ai = a + (i << logN);
920 | piSubConstAndEqual(ai, c, i - l);
921 | }
922 | }
923 |
924 | void Context::qiAdd(uint64_t* res, uint64_t* a, uint64_t* b, long index) {
925 | for (long i = 0; i < N; ++i) {
926 | addMod(res[i], a[i], b[i], qVec[index]);
927 | }
928 | }
929 |
930 | void Context::piAdd(uint64_t* res, uint64_t* a, uint64_t* b, long index) {
931 | for (long i = 0; i < N; ++i) {
932 | addMod(res[i], a[i], b[i], pVec[index]);
933 | }
934 | }
935 |
936 | void Context::add(uint64_t* res, uint64_t* a, uint64_t* b, long l, long k) {
937 | for (long i = 0; i < l; ++i) {
938 | uint64_t* ai = a + (i << logN);
939 | uint64_t* bi = b + (i << logN);
940 | uint64_t* resi = res + (i << logN);
941 | qiAdd(resi, ai, bi, i);
942 | }
943 |
944 | for (long i = l; i < l + k; ++i) {
945 | uint64_t* ai = a + (i << logN);
946 | uint64_t* bi = b + (i << logN);
947 | uint64_t* resi = res + (i << logN);
948 | piAdd(resi, ai, bi, i - l);
949 | }
950 | }
951 |
952 | void Context::qiAddAndEqual(uint64_t* a, uint64_t* b, long index) {
953 | for (long i = 0; i < N; ++i) {
954 | addMod(a[i], a[i], b[i], qVec[index]);
955 | }
956 | }
957 |
958 | void Context::piAddAndEqual(uint64_t* a, uint64_t* b, long index) {
959 | for (long i = 0; i < N; ++i) {
960 | addMod(a[i], a[i], b[i], pVec[index]);
961 | }
962 | }
963 |
964 | void Context::addAndEqual(uint64_t* a, uint64_t* b, long l, long k) {
965 | for (long i = 0; i < l; ++i) {
966 | uint64_t* ai = a + (i << logN);
967 | uint64_t* bi = b + (i << logN);
968 | qiAddAndEqual(ai, bi, i);
969 | }
970 |
971 | for (long i = l; i < l + k; ++i) {
972 | uint64_t* ai = a + (i << logN);
973 | uint64_t* bi = b + (i << logN);
974 | piAddAndEqual(ai, bi, i - l);
975 | }
976 | }
977 |
978 | void Context::qiSub(uint64_t* res, uint64_t* a, uint64_t* b, long index) {
979 | for (long i = 0; i < N; ++i) {
980 | subMod(res[i], a[i], b[i], qVec[index]);
981 | }
982 | }
983 |
984 | void Context::piSub(uint64_t* res, uint64_t* a, uint64_t* b, long index) {
985 | for (long i = 0; i < N; ++i) {
986 | subMod(res[i], a[i], b[i], pVec[index]);
987 | }
988 | }
989 |
990 | void Context::sub(uint64_t* res, uint64_t* a, uint64_t* b, long l, long k) {
991 | for (long i = 0; i < l; ++i) {
992 | uint64_t* ai = a + (i << logN);
993 | uint64_t* bi = b + (i << logN);
994 | uint64_t* resi = res + (i << logN);
995 | qiSub(resi, ai, bi, i);
996 | }
997 |
998 | for (long i = l; i < l + k; ++i) {
999 | uint64_t* ai = a + (i << logN);
1000 | uint64_t* bi = b + (i << logN);
1001 | uint64_t* resi = res + (i << logN);
1002 | piSub(resi, ai, bi, i - l);
1003 | }
1004 | }
1005 |
1006 | void Context::qiSubAndEqual(uint64_t* a, uint64_t* b, long index) {
1007 | for (long i = 0; i < N; ++i) {
1008 | subMod(a[i], a[i], b[i], qVec[index]);
1009 | }
1010 | }
1011 |
1012 | void Context::piSubAndEqual(uint64_t* a, uint64_t* b, long index) {
1013 | for (long i = 0; i < N; ++i) {
1014 | subMod(a[i], a[i], b[i], pVec[index]);
1015 | }
1016 | }
1017 |
1018 | void Context::subAndEqual(uint64_t* a, uint64_t* b, long l, long k) {
1019 | for (long i = 0; i < l; ++i) {
1020 | uint64_t* ai = a + (i << logN);
1021 | uint64_t* bi = b + (i << logN);
1022 | qiSubAndEqual(ai, bi, i);
1023 | }
1024 |
1025 | for (long i = l; i < l + k; ++i) {
1026 | uint64_t* ai = a + (i << logN);
1027 | uint64_t* bi = b + (i << logN);
1028 | piSubAndEqual(ai, bi, i - l);
1029 | }
1030 | }
1031 |
1032 | void Context::qiSub2AndEqual(uint64_t* a, uint64_t* b, long index) {
1033 | for (long i = 0; i < N; ++i) {
1034 | subMod(b[i], a[i], b[i], qVec[index]);
1035 | }
1036 | }
1037 |
1038 | void Context::piSub2AndEqual(uint64_t* a, uint64_t* b, long index) {
1039 | for (long i = 0; i < N; ++i) {
1040 | subMod(b[i], a[i], b[i], pVec[index]);
1041 | }
1042 | }
1043 |
1044 | void Context::sub2AndEqual(uint64_t* a, uint64_t* b, long l, long k) {
1045 | for (long i = 0; i < l; ++i) {
1046 | uint64_t* ai = a + (i << logN);
1047 | uint64_t* bi = b + (i << logN);
1048 | qiSub2AndEqual(ai, bi, i);
1049 | }
1050 |
1051 | for (long i = l; i < l + k; ++i) {
1052 | uint64_t* ai = a + (i << logN);
1053 | uint64_t* bi = b + (i << logN);
1054 | piSub2AndEqual(ai, bi, i - l);
1055 | }
1056 | }
1057 |
1058 | void Context::qiMulConst(uint64_t* res, uint64_t* a, uint64_t cnst, long index) {
1059 | for (long i = 0; i < N; ++i) {
1060 | mulModBarrett(res[i], a[i], cnst, qVec[index], qrVec[index], qTwok[index]);
1061 | }
1062 | }
1063 |
1064 | void Context::piMulConst(uint64_t* res, uint64_t* a, uint64_t cnst, long index) {
1065 | for (long i = 0; i < N; ++i) {
1066 | mulModBarrett(res[i], a[i], cnst, pVec[index], prVec[index], pTwok[index]);
1067 | }
1068 | }
1069 |
1070 | void Context::mulConst(uint64_t* res, uint64_t* a, uint64_t cnst, long l, long k) {
1071 | for (long i = 0; i < l; ++i) {
1072 | uint64_t* ai = a + (i << logN);
1073 | uint64_t* resi = res + (i << logN);
1074 | qiMulConst(resi, ai, cnst, i);
1075 | }
1076 |
1077 | for (long i = l; i < l + k; ++i) {
1078 | uint64_t* ai = a + (i << logN);
1079 | uint64_t* resi = res + (i << logN);
1080 | piMulConst(resi, ai, cnst, i - l);
1081 | }
1082 | }
1083 |
1084 | void Context::qiMulConstAndEqual(uint64_t* res, uint64_t cnst, long index) {
1085 | for (long i = 0; i < N; ++i) {
1086 | mulModBarrett(res[i], res[i], cnst, qVec[index], qrVec[index], qTwok[index]);
1087 | }
1088 | }
1089 |
1090 | void Context::piMulConstAndEqual(uint64_t* res, uint64_t cnst, long index) {
1091 | for (long i = 0; i < N; ++i) {
1092 | mulModBarrett(res[i], res[i], cnst, pVec[index], prVec[index], pTwok[index]);
1093 | }
1094 | }
1095 |
1096 | void Context::mulConstAndEqual(uint64_t* a, uint64_t cnst, long l, long k) {
1097 | for (long i = 0; i < l; ++i) {
1098 | uint64_t* ai = a + (i << logN);
1099 | qiMulConstAndEqual(ai, cnst, i);
1100 | }
1101 |
1102 | for (long i = l; i < l + k; ++i) {
1103 | uint64_t* ai = a + (i << logN);
1104 | piMulConstAndEqual(ai, cnst, i - l);
1105 | }
1106 | }
1107 |
1108 | void Context::qiMul(uint64_t* res, uint64_t* a, uint64_t* b, long index) {
1109 | for (long i = 0; i < N; ++i) {
1110 | mulModBarrett(res[i], a[i], b[i], qVec[index], qrVec[index], qTwok[index]);
1111 | }
1112 | }
1113 |
1114 | void Context::piMul(uint64_t* res, uint64_t* a, uint64_t* b, long index) {
1115 | for (long i = 0; i < N; ++i) {
1116 | mulModBarrett(res[i], a[i], b[i], pVec[index], prVec[index], pTwok[index]);
1117 | }
1118 | }
1119 |
1120 | void Context::mul(uint64_t* res, uint64_t* a, uint64_t* b, long l, long k) {
1121 | for (long i = 0; i < l; ++i) {
1122 | uint64_t* ai = a + (i << logN);
1123 | uint64_t* bi = b + (i << logN);
1124 | uint64_t* resi = res + (i << logN);
1125 | qiMul(resi, ai, bi, i);
1126 | }
1127 |
1128 | for (long i = l; i < l + k; ++i) {
1129 | uint64_t* ai = a + (i << logN);
1130 | uint64_t* bi = b + (i << logN);
1131 | uint64_t* resi = res + (i << logN);
1132 | piMul(resi, ai, bi, i - l);
1133 | }
1134 | }
1135 |
1136 | void Context::mulKey(uint64_t* res, uint64_t* a, uint64_t* key, long l) {
1137 | for (long i = 0; i < l; ++i) {
1138 | uint64_t* ai = a + (i << logN);
1139 | uint64_t* keyi = key + (i << logN);
1140 | uint64_t* resi = res + (i << logN);
1141 | qiMul(resi, ai, keyi, i);
1142 | }
1143 |
1144 | for (long i = l; i < l + K; ++i) {
1145 | uint64_t* ai = a + (i << logN);
1146 | uint64_t* keyi = key + ((i - l + L) << logN);
1147 | uint64_t* resi = res + (i << logN);
1148 | piMul(resi, ai, keyi, i - l);
1149 | }
1150 | }
1151 |
1152 | void Context::qiMulAndEqual(uint64_t* a, uint64_t* b, long index) {
1153 | for (long i = 0; i < N; ++i) {
1154 | mulModBarrett(a[i], a[i], b[i], qVec[index], qrVec[index], qTwok[index]);
1155 | }
1156 | }
1157 |
1158 | void Context::piMulAndEqual(uint64_t* a, uint64_t* b, long index) {
1159 | for (long i = 0; i < N; ++i) {
1160 | mulModBarrett(a[i], a[i], b[i], pVec[index], prVec[index], pTwok[index]);
1161 | }
1162 | }
1163 |
1164 | void Context::mulAndEqual(uint64_t* a, uint64_t* b, long l, long k) {
1165 | for (long i = 0; i < l; ++i) {
1166 | uint64_t* ai = a + (i << logN);
1167 | uint64_t* bi = b + (i << logN);
1168 | qiMulAndEqual(ai, bi, i);
1169 | }
1170 |
1171 | for (long i = l; i < l + k; ++i) {
1172 | uint64_t* ai = a + (i << logN);
1173 | uint64_t* bi = b + (i << logN);
1174 | piMulAndEqual(ai, bi, i - l);
1175 | }
1176 | }
1177 |
1178 | void Context::qiSquare(uint64_t* res, uint64_t* a, long index) {
1179 | for (long i = 0; i < N; ++i) {
1180 | mulModBarrett(res[i], a[i], a[i], qVec[index], qrVec[index], qTwok[index]);
1181 | }
1182 | }
1183 |
1184 | void Context::piSquare(uint64_t* res, uint64_t* a, long index) {
1185 | for (long i = 0; i < N; ++i) {
1186 | mulModBarrett(res[i], a[i], a[i], pVec[index], prVec[index], pTwok[index]);
1187 | }
1188 | }
1189 |
1190 | void Context::square(uint64_t* res, uint64_t* a, long l, long k) {
1191 | for (long i = 0; i < l; ++i) {
1192 | uint64_t* ai = a + (i << logN);
1193 | uint64_t* resi = res + (i << logN);
1194 | qiSquare(resi, ai, i);
1195 | }
1196 |
1197 | for (long i = l; i < l + k; ++i) {
1198 | uint64_t* ai = a + (i << logN);
1199 | uint64_t* resi = res + (i << logN);
1200 | piSquare(resi, ai, i - l);
1201 | }
1202 | }
1203 |
1204 | void Context::qiSquareAndEqual(uint64_t* a, long index) {
1205 | for (long i = 0; i < N; ++i) {
1206 | mulModBarrett(a[i], a[i], a[i], qVec[index], qrVec[index], qTwok[index]);
1207 | }
1208 | }
1209 |
1210 | void Context::piSquareAndEqual(uint64_t* a, long index) {
1211 | for (long i = 0; i < N; ++i) {
1212 | mulModBarrett(a[i], a[i], a[i], pVec[index], prVec[index], pTwok[index]);
1213 | }
1214 | }
1215 |
1216 | void Context::squareAndEqual(uint64_t* a, long l, long k) {
1217 | for (long i = 0; i < l; ++i) {
1218 | uint64_t* ai = a + (i << logN);
1219 | qiSquare(ai, ai, i);
1220 | }
1221 |
1222 | for (long i = l; i < l + k; ++i) {
1223 | uint64_t* ai = a + (i << logN);
1224 | piSquare(ai, ai, i - l);
1225 | }
1226 | }
1227 |
1228 | void Context::evalAndEqual(uint64_t* a, long l) {
1229 | INTTAndEqual(a, l);
1230 | for (long i = 0; i < l; ++i) {
1231 | uint64_t* ai = a + (i << logN);
1232 | for (long n = 0; n < N; ++n) {
1233 | mulModBarrett(ai[n], ai[n], PModq[i], qVec[i], qrVec[i], qTwok[i]);
1234 | }
1235 | }
1236 | NTTAndEqual(a, l);
1237 | }
1238 |
1239 | void Context::raise(uint64_t* res, uint64_t* a, long l) {
1240 | //TODO implement method
1241 |
1242 | }
1243 |
1244 | void Context::raiseAndEqual(uint64_t*& a, long l) {
1245 | uint64_t* ra = new uint64_t[(l + K) << logN]();
1246 | copy(a, a + (l << logN), ra);
1247 |
1248 | INTTAndEqual(a, l);
1249 |
1250 | uint64_t* tmp3 = new uint64_t[l << logN];
1251 | for(long i = 0; i < l; ++i) {
1252 | uint64_t* tmp3i = tmp3 + (i << logN);
1253 | uint64_t* ai = a + (i << logN);
1254 | for(long n = 0; n < N; ++n) {
1255 | mulModBarrett(tmp3i[n], ai[n], qHatInvModq[l - 1][i], qVec[i], qrVec[i], qTwok[i]);
1256 | }
1257 | }
1258 | for (long k = 0; k < K; ++k) {
1259 | uint64_t* rak = ra + ((l + k) << logN);
1260 | for (long n = 0; n < N; ++n) {
1261 | uint64_t tt = tmp3[n];
1262 | unsigned __int128 sum = static_cast(tt) * qHatModp[l - 1][0][k];
1263 | for (long i = 1; i < l; ++i) {
1264 | tt = tmp3[n + (i << logN)];
1265 | sum += static_cast(tt) * qHatModp[l - 1][i][k];
1266 | }
1267 | modBarrett(rak[n], sum, pVec[k], prVec[k], pTwok[k]);
1268 | }
1269 | }
1270 | NTTAndEqual(ra + (l << logN), 0, K);
1271 |
1272 | delete[] a;
1273 | a = ra;
1274 |
1275 | }
1276 |
1277 | void Context::back(uint64_t* res, uint64_t* a, long l) {
1278 | uint64_t* tmp = new uint64_t[(l + K) << logN];
1279 | copy(a, a + ((l + K) << logN), tmp);
1280 | INTTAndEqual(tmp, l, K);
1281 | uint64_t* tmp3 = new uint64_t[K << logN];
1282 | for(long k = 0; k < K; k++) {
1283 | uint64_t* tmpk = tmp + ((k + l) << logN);
1284 | uint64_t* tmp3k = tmp3 + (k << logN);
1285 | for(long n = 0; n < N; ++n) {
1286 | mulModBarrett(tmp3k[n], tmpk[n], pHatInvModp[k], pVec[k], prVec[k], pTwok[k]);
1287 | }
1288 | }
1289 | for (long i = 0; i < l; ++i) {
1290 | uint64_t* resi = res + (i << logN);
1291 | uint64_t* tmpi = tmp + (i << logN);
1292 |
1293 | for (long n = 0; n < N; ++n) {
1294 | uint64_t tt = tmp3[n];
1295 | unsigned __int128 sum = static_cast(tt) * pHatModq[0][i];
1296 | for (long k = 1; k < K; ++k) {
1297 | tt = tmp3[n + (k << logN)];
1298 | sum += static_cast(tt) * pHatModq[k][i];
1299 | }
1300 | modBarrett(resi[n], sum, qVec[i], qrVec[i], qTwok[i]);
1301 | subMod(resi[n], tmpi[n], resi[n], qVec[i]);
1302 | mulModBarrett(resi[n], resi[n], PInvModq[i], qVec[i], qrVec[i], qTwok[i]);
1303 | }
1304 | }
1305 |
1306 | delete[] tmp;
1307 |
1308 | NTTAndEqual(res, l);
1309 | }
1310 |
1311 | void Context::backAndEqual(uint64_t*& a, long l) {
1312 |
1313 | INTTAndEqual(a, l, K);
1314 |
1315 | uint64_t* ra = new uint64_t[l << logN]();
1316 | uint64_t* tmp3 = new uint64_t[K << logN];
1317 |
1318 | for(long k = 0; k < K; k++) {
1319 | uint64_t* tmp3k = tmp3 + (k << logN);
1320 | uint64_t* ak = a + ((k + l) << logN);
1321 | for(long n = 0; n < N; ++n) {
1322 | mulModBarrett(tmp3k[n], ak[n], pHatInvModp[k], pVec[k], prVec[k], pTwok[k]);
1323 | }
1324 | }
1325 |
1326 | for (long i = 0; i < l; ++i) {
1327 | uint64_t* rai = ra + (i << logN);
1328 | uint64_t* ai = a + (i << logN);
1329 | for (long n = 0; n < N; ++n) {
1330 | uint64_t tt = tmp3[n];
1331 | unsigned __int128 sum = static_cast(tt) * pHatModq[0][i];
1332 | for (long k = 1; k < K; ++k) {
1333 | tt = tmp3[n + (k << logN)];
1334 | sum += static_cast(tt) * pHatModq[k][i];
1335 | }
1336 | modBarrett(rai[n], sum, qVec[i], qrVec[i], qTwok[i]);
1337 | subMod(rai[n], ai[n], rai[n], qVec[i]);
1338 | mulModBarrett(rai[n], rai[n], PInvModq[i], qVec[i], qrVec[i], qTwok[i]);
1339 | }
1340 | }
1341 | NTTAndEqual(ra, l);
1342 | delete[] a;
1343 | a = ra;
1344 | }
1345 |
1346 | void Context::reScale(uint64_t* res, uint64_t* a, long l) {
1347 | //TODO implement method
1348 | }
1349 |
1350 | void Context::reScaleAndEqual(uint64_t*& a, long l) {
1351 | uint64_t* ra = new uint64_t[(l - 1) << logN]();
1352 | uint64_t* al = a + ((l - 1) << logN);
1353 | qiINTTAndEqual(al, l - 1);
1354 | for (long i = 0; i < l - 1; ++i) {
1355 | uint64_t* rai = ra + (i << logN);
1356 | uint64_t* ai = a + (i << logN);
1357 |
1358 | copy(al, al + N, rai);
1359 | for (long n = 0; n < N; ++n) {
1360 | modBarrett(rai[n], al[n], qVec[i], qrVec[i], qTwok[i]);
1361 | }
1362 | qiNTTAndEqual(rai, i);
1363 |
1364 |
1365 | for (long n = 0; n < N; ++n) {
1366 | subMod(rai[n], ai[n], rai[n], qVec[i]);
1367 | mulModBarrett(rai[n], rai[n], qInvModq[l - 1][i], qVec[i], qrVec[i], qTwok[i]);
1368 | }
1369 | }
1370 | delete[] a;
1371 | a = ra;
1372 | }
1373 |
1374 | void Context::modDownAndEqual(uint64_t*& a, long l, long dl) {
1375 | uint64_t* ra = new uint64_t[(l - dl) << logN]();
1376 | copy(a, a + ((l - dl) << logN), ra);
1377 | delete[] a;
1378 | a = ra;
1379 | }
1380 |
1381 | uint64_t* Context::modDown(uint64_t* a, long l, long dl) {
1382 | uint64_t* ra = new uint64_t[(l - dl) << logN]();
1383 | copy(a, a + ((l - dl) << logN), ra);
1384 | return ra;
1385 | }
1386 |
1387 | void Context::leftRot(uint64_t* res, uint64_t* a, long l, long rotSlots) {
1388 | // long idx = rotSlots % Nh;
1389 | // for (long n = 0; n < N; ++n) {
1390 | // uint32_t reversed = bitReverse(static_cast(n)) >> (32 - logN);
1391 | // uint64_t index_raw = rotGroup[idx] * (2 * reversed + 1);
1392 | // index_raw &= (M - 1);
1393 | // long index = bitReverse((static_cast(index_raw) - 1) >> 1) >> (32 - logN);
1394 | // for (long i = 0; i < l; ++i) {
1395 | // res[n + (i << logN)] = a[index + (i << logN)];
1396 | // }
1397 | // }
1398 |
1399 | uint64_t* tmp = new uint64_t[l << logN]();
1400 | copy(a, a + (l << logN), tmp);
1401 | INTTAndEqual(tmp, l);
1402 | long pow = rotGroup[rotSlots];
1403 | for (long i = 0; i < l; ++i) {
1404 | uint64_t* resi = res + (i << logN);
1405 | uint64_t* tmpi = tmp + (i << logN);
1406 | for (long n = 0; n < N; ++n) {
1407 | long npow = n * pow;
1408 | long shift = npow % M;
1409 | if(shift < N) {
1410 | resi[shift] = tmpi[n];
1411 | } else {
1412 | resi[shift - N] = qVec[i] - tmpi[n];
1413 | }
1414 | }
1415 | }
1416 | NTTAndEqual(res, l);
1417 | }
1418 |
1419 | void Context::leftRotAndEqual(uint64_t* a, long l, long rotSlots) {
1420 | uint64_t* tmp = new uint64_t[l << logN];
1421 | copy(a, a + (l << logN), tmp);
1422 | long idx = rotSlots % Nh;
1423 | for (long n = 0; n < N; ++n) {
1424 | uint32_t reversed = bitReverse(static_cast(n)) >> (32 - logN);
1425 | uint64_t index_raw = rotGroup[idx] * (2 * reversed + 1);
1426 | index_raw &= M - 1;
1427 | uint32_t index = bitReverse((static_cast(index_raw) - 1) >> 1) >> (32 - logN);
1428 | for (long i = 0; i < l; ++i) {
1429 | a[n + (i << logN)] = tmp[index + (i << logN)];
1430 | }
1431 | }
1432 | // INTTAndEqual(tmp, l);
1433 | // long pow = rotGroup[rotSlots];
1434 | // for (long i = 0; i < l; ++i) {
1435 | // uint64_t* ai = a + (i << logN);
1436 | // uint64_t* tmpi = tmp + (i << logN);
1437 | // for (long n = 0; n < N; ++n) {
1438 | // long jpow = n * pow;
1439 | // long shift = jpow % M;
1440 | // if(shift < N) {
1441 | // ai[shift] = tmpi[n];
1442 | // } else {
1443 | // ai[shift - N] = qVec[i] - tmpi[n];
1444 | // }
1445 | // }
1446 | // }
1447 | // NTTAndEqual(a, l);
1448 | }
1449 |
1450 | void Context::conjugate(uint64_t* res, uint64_t* a, long l) {
1451 | for (long i = 0; i < l; ++i) {
1452 | uint64_t* resi = res + (i << logN);
1453 | uint64_t* ai = a + (i << logN);
1454 | for (int n = 0; n < N; ++n) {
1455 | resi[n] = ai[N - 1 - n];
1456 | }
1457 | }
1458 | }
1459 |
1460 | void Context::conjugateAndEqual(uint64_t* a, long l) {
1461 | for (long i = 0; i < l; ++i) {
1462 | uint64_t* ai = a + (i << logN);
1463 | for (int n = 0; n < N; ++n) {
1464 | swap(ai[n], ai[N - 1 - n]);
1465 | }
1466 | }
1467 | }
1468 |
1469 | void Context::mulByMonomial(uint64_t* res, uint64_t* a, long l, long mdeg) {
1470 | for (long i = 0; i < l; ++i) {
1471 | uint64_t* resi = res + (i << logN);
1472 | uint64_t* ai = a + (i << logN);
1473 | for (long n = 0; n < N; ++n) {
1474 | mulModBarrett(resi[n], ai[n], qRootPows[i][n], qVec[i], qrVec[i], qTwok[i]);
1475 | }
1476 | }
1477 | }
1478 |
1479 | void Context::mulByMonomialAndEqual(uint64_t* a, long l, long mdeg) {
1480 |
1481 | }
1482 |
1483 | void Context::sampleGauss(uint64_t* res, long l, long k) {
1484 | static long const bignum = 0xfffffff;
1485 | for (long i = 0; i < N; i += 2) {
1486 | double r1 = (1 + (uint64_t)rand() % bignum) / ((double) bignum + 1);
1487 | double r2 = (1 + (uint64_t)rand() % bignum) / ((double) bignum + 1);
1488 | double theta = 2 * M_PI * r1;
1489 | double rr = sqrt(-2.0 * log(r2)) * sigma;
1490 |
1491 | long g1 = floor(rr * cos(theta) + 0.5);
1492 | long g2 = floor(rr * sin(theta) + 0.5);
1493 |
1494 | for (long j = 0; j < l; ++j) {
1495 | uint64_t* resj = res + (j << logN);
1496 | resj[i] = g1 >= 0 ? g1 : qVec[j] + g1;
1497 | resj[i + 1] = g2 >= 0 ? g2 : qVec[j] + g2;
1498 | }
1499 | for (long j = 0; j < k; ++j) {
1500 | uint64_t* resj = res + ((j + l) << logN);
1501 | resj[i] = g1 >= 0 ? g1 : pVec[j] + g1;
1502 | resj[i + 1] = g2 >= 0 ? g2 : pVec[j] + g2;
1503 | }
1504 | }
1505 | }
1506 |
1507 | void Context::sampleZO(uint64_t* res, long s, long l, long k) {
1508 | for (long i = 0; i < N; ++i) {
1509 | long zo = (rand() % 2) == 0 ? 0 : (rand() % 2) ? 1 : -1;
1510 | for (long j = 0; j < l; ++j) {
1511 | uint64_t* resj = res + (j << logN);
1512 | resj[i] = zo >= 0 ? zo : qVec[j] + zo;
1513 | }
1514 | for (long j = 0; j < k; ++j) {
1515 | uint64_t* resj = res + ((j + l) << logN);
1516 | resj[i] = zo >= 0 ? zo : pVec[j] + zo;
1517 | }
1518 | }
1519 | }
1520 |
1521 | void Context::sampleUniform(uint64_t* res, long l, long k) {
1522 | for (long j = 0; j < l; ++j) {
1523 | uint64_t* resj = res + (j << logN);
1524 | for (long n = 0; n < N; ++n) {
1525 | resj[n] = floor(((double) rand() / (RAND_MAX)) * qVec[j]);
1526 | }
1527 | }
1528 | for (long j = 0; j < k; ++j) {
1529 | uint64_t* resj = res + ((j + l) << logN);
1530 | for (long n = 0; n < N; ++n) {
1531 | resj[n] = floor(((double) rand() / (RAND_MAX)) * pVec[j]);
1532 | }
1533 | }
1534 | }
1535 |
1536 | void Context::sampleHWT(uint64_t* res, long l, long k) {
1537 | long idx = 0;
1538 | while (idx < h) {
1539 | long i = ((double) rand() / (RAND_MAX)) * N;
1540 | if (res[i] == 0) {
1541 | long hwt = (rand() % 2) ? 1 : -1;
1542 | for (long j = 0; j < l; ++j) {
1543 | uint64_t* resj = res + (j << logN);
1544 | resj[i] = hwt >= 0 ? hwt : qVec[j] + hwt;
1545 | }
1546 | for (long j = 0; j < k; ++j) {
1547 | uint64_t* resj = res + ((j + l) << logN);
1548 | resj[i] = hwt >= 0 ? hwt : pVec[j] + hwt;
1549 | }
1550 | idx++;
1551 | }
1552 | }
1553 | }
1554 |
1555 |
--------------------------------------------------------------------------------
/src/Context.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) by CryptoLab inc.
3 | * This program is licensed under a
4 | * Creative Commons Attribution-NonCommercial 3.0 Unported License.
5 | * You should have received a copy of the license along with this
6 | * work. If not, see .
7 | */
8 |
9 | #ifndef HEAANNTT_CONTEXT_H_
10 | #define HEAANNTT_CONTEXT_H_
11 |
12 | #include
13 | #include
14 | #include